diff --git a/crm/api/doc.py b/crm/api/doc.py index 6ff2788e..9a2299ed 100644 --- a/crm/api/doc.py +++ b/crm/api/doc.py @@ -45,3 +45,122 @@ def get_filterable_fields(doctype: str): res = [] res.extend(from_doc_fields) return res + +@frappe.whitelist() +def get_doctype_fields(doctype): + DocField = frappe.qb.DocType("DocField") + CustomField = frappe.qb.DocType("Custom Field") + not_allowed_fieldtypes = [ + "Section Break", + "Column Break", + ] + + fields = ( + frappe.qb.from_(DocField) + .select( + DocField.fieldname, + DocField.fieldtype, + DocField.label, + DocField.name, + DocField.options, + DocField.read_only, + DocField.idx, + ) + .where(DocField.parent == doctype) + .where(DocField.hidden == False) + .where(Criterion.notin(DocField.fieldtype, not_allowed_fieldtypes)) + .orderby(DocField.idx) + .run(as_dict=True) + ) + + custom_fields = ( + frappe.qb.from_(CustomField) + .select( + CustomField.fieldname, + CustomField.fieldtype, + CustomField.label, + CustomField.name, + CustomField.options, + CustomField.read_only, + CustomField.idx, + CustomField.insert_after, + ) + .where(CustomField.dt == doctype) + .where(CustomField.hidden == False) + .where(Criterion.notin(CustomField.fieldtype, not_allowed_fieldtypes)) + .orderby(CustomField.idx) + .run(as_dict=True) + ) + + all_fields = [] + all_fields.extend(fields) + + # Add custom fields based on insert_after + for custom_field in custom_fields: + if custom_field.insert_after: + for i, field in enumerate(all_fields): + if field.fieldname == custom_field.insert_after: + all_fields.insert(i + 1, custom_field) + break + else: + all_fields.prepend(custom_field) + + sections = {} + section_fields = [] + last_section = None + + for field in all_fields: + if field.fieldtype == "Tab Break" and last_section: + sections[last_section]["fields"] = section_fields + last_section = None + if field.read_only: + section_fields = [] + continue + if field.fieldtype == "Tab Break": + if field.read_only: + section_fields = [] + continue + section_fields = [] + last_section = field.fieldname + sections[field.fieldname] = { + "label": field.label, + "opened": True, + "fields": [], + } + else: + section_fields.append(get_field_obj(field)) + + deal_fields = [] + for section in sections: + deal_fields.append(sections[section]) + + return deal_fields + +def get_field_obj(field): + obj = { + "label": field.label, + "type": get_type(field), + "name": field.fieldname, + } + + obj["placeholder"] = "Add " + field.label.lower() + "..." + + if field.fieldtype == "Link": + obj["placeholder"] = "Select " + field.label.lower() + "..." + obj["doctype"] = field.options + elif field.fieldtype == "Select": + obj["options"] = [{"label": option, "value": option} for option in field.options.split("\n")] + + if field.read_only: + obj["tooltip"] = "This field is read only and cannot be edited." + + return obj + +def get_type(field): + if field.fieldtype == "Data" and field.options == "Phone": + return "phone" + elif field.fieldtype == "Data" and field.options == "Email": + return "email" + elif field.read_only: + return "read_only" + return field.fieldtype.lower() \ No newline at end of file diff --git a/crm/fcrm/doctype/crm_lead/api.py b/crm/fcrm/doctype/crm_lead/api.py index 0407d890..f51be6fa 100644 --- a/crm/fcrm/doctype/crm_lead/api.py +++ b/crm/fcrm/doctype/crm_lead/api.py @@ -1,6 +1,5 @@ import frappe from frappe import _ -from pypika import Criterion @frappe.whitelist() @@ -14,128 +13,4 @@ def get_lead(name): frappe.throw(_("Lead not found"), frappe.DoesNotExistError) lead = lead.pop() - return lead - -@frappe.whitelist() -def get_lead_fields(): - DocField = frappe.qb.DocType("DocField") - CustomField = frappe.qb.DocType("Custom Field") - not_allowed_fieldtypes = [ - "Section Break", - "Column Break", - ] - restricted_fieldnames = [ - "converted", - "lead_owner", - "status", - "image", - "naming_series" - ] - - fields = ( - frappe.qb.from_(DocField) - .select( - DocField.fieldname, - DocField.fieldtype, - DocField.label, - DocField.name, - DocField.options, - DocField.read_only, - DocField.idx, - ) - .where(DocField.parent == "CRM Lead") - .where(DocField.hidden == False) - .where(Criterion.notin(DocField.fieldtype, not_allowed_fieldtypes)) - .where(Criterion.notin(DocField.fieldname, restricted_fieldnames)) - .orderby(DocField.idx) - .run(as_dict=True) - ) - - custom_fields = ( - frappe.qb.from_(CustomField) - .select( - CustomField.fieldname, - CustomField.fieldtype, - CustomField.label, - CustomField.name, - CustomField.options, - CustomField.read_only, - CustomField.idx, - CustomField.insert_after, - ) - .where(CustomField.dt == "CRM Lead") - .where(CustomField.hidden == False) - .where(Criterion.notin(CustomField.fieldtype, not_allowed_fieldtypes)) - .orderby(CustomField.idx) - .run(as_dict=True) - ) - - all_fields = [] - all_fields.extend(fields) - - # Add custom fields based on insert_after - for custom_field in custom_fields: - if custom_field.insert_after: - for i, field in enumerate(all_fields): - if field.fieldname == custom_field.insert_after: - all_fields.insert(i + 1, custom_field) - break - else: - all_fields.prepend(custom_field) - - sections = {} - section_fields = [] - last_section = None - - for field in all_fields: - if field.fieldtype == "Tab Break" and last_section: - sections[last_section]["fields"] = section_fields - last_section = None - if field.read_only: - section_fields = [] - continue - if field.fieldtype == "Tab Break": - section_fields = [] - last_section = field.fieldname - sections[field.fieldname] = { - "label": field.label, - "opened": True, - "fields": [], - } - else: - section_fields.append(get_field_obj(field)) - - lead_fields = [] - for section in sections: - lead_fields.append(sections[section]) - - return lead_fields - -def get_field_obj(field): - obj = { - "label": field.label, - "type": get_type(field), - "name": field.fieldname, - } - - obj["placeholder"] = "Add " + field.label.lower() + "..." - - if field.fieldtype == "Link": - obj["placeholder"] = "Select " + field.label.lower() + "..." - obj["doctype"] = field.options - elif field.fieldtype == "Select": - obj["options"] = [{"label": option, "value": option} for option in field.options.split("\n")] - - if field.read_only: - obj["tooltip"] = "This field is read only and cannot be edited." - - return obj - -def get_type(field): - if field.fieldtype == "Data" and field.options == "Phone": - return "phone" - elif field.fieldtype == "Data" and field.options == "Email": - return "email" - elif field.read_only: - return "read_only" - return field.fieldtype.lower() \ No newline at end of file + return lead \ No newline at end of file diff --git a/crm/fcrm/doctype/crm_lead/crm_lead.json b/crm/fcrm/doctype/crm_lead/crm_lead.json index d75ba940..c885e4a7 100644 --- a/crm/fcrm/doctype/crm_lead/crm_lead.json +++ b/crm/fcrm/doctype/crm_lead/crm_lead.json @@ -13,7 +13,6 @@ "website", "industry", "job_title", - "naming_series", "source", "person_tab", "salutation", @@ -23,6 +22,7 @@ "mobile_no", "organization_tab", "section_break_uixv", + "naming_series", "lead_name", "middle_name", "gender", @@ -199,7 +199,7 @@ "image_field": "image", "index_web_pages_for_search": 1, "links": [], - "modified": "2023-11-21 13:02:11.680600", + "modified": "2023-11-22 13:03:02.261001", "modified_by": "Administrator", "module": "FCRM", "name": "CRM Lead", diff --git a/frontend/src/pages/Lead.vue b/frontend/src/pages/Lead.vue index c6c0fe76..743fe8b2 100644 --- a/frontend/src/pages/Lead.vue +++ b/frontend/src/pages/Lead.vue @@ -423,7 +423,8 @@ function validateFile(file) { } const detailSections = createResource({ - url: 'crm.fcrm.doctype.crm_lead.api.get_lead_fields', + url: 'crm.api.doc.get_doctype_fields', + params: { doctype: 'CRM Lead' }, cache: 'leadFields', auto: true, transform: (data) => { @@ -436,6 +437,8 @@ function getParsedFields(sections) { section.fields.forEach((field) => { if (['website', 'industry'].includes(field.name)) { field.value = organization.value?.[field.name] + field.tooltip = + 'This field is read-only and is fetched from the organization' } else if (field.name == 'organization') { field.create = (value, close) => { _organization.value.organization_name = value