diff --git a/crm/api/contact.py b/crm/api/contact.py index 2f52f433..8ef93e43 100644 --- a/crm/api/contact.py +++ b/crm/api/contact.py @@ -73,6 +73,7 @@ def get_linked_deals(contact): fields=[ "name", "organization", + "currency", "annual_revenue", "status", "email", diff --git a/crm/api/doc.py b/crm/api/doc.py index 0159c663..a1a7bb40 100644 --- a/crm/api/doc.py +++ b/crm/api/doc.py @@ -257,17 +257,18 @@ def get_list_data( "user": frappe.session.user, } + _list = get_controller(doctype) + if not custom_view and frappe.db.exists("CRM View Settings", default_view_filters): list_view_settings = frappe.get_doc("CRM View Settings", default_view_filters) columns = frappe.parse_json(list_view_settings.columns) rows = frappe.parse_json(list_view_settings.rows) is_default = False - elif not custom_view or is_default: - _list = get_controller(doctype) + elif not custom_view or is_default and hasattr(_list, "default_list_data"): + columns = _list.default_list_data().get("columns") - if hasattr(_list, "default_list_data"): - columns = _list.default_list_data().get("columns") - rows = _list.default_list_data().get("rows") + if hasattr(_list, "default_list_data"): + rows = _list.default_list_data().get("rows") # check if rows has all keys from columns if not add them for column in columns: diff --git a/crm/fcrm/doctype/crm_deal/crm_deal.json b/crm/fcrm/doctype/crm_deal/crm_deal.json index 8b91b3db..e5c973d8 100644 --- a/crm/fcrm/doctype/crm_deal/crm_deal.json +++ b/crm/fcrm/doctype/crm_deal/crm_deal.json @@ -8,31 +8,41 @@ "engine": "InnoDB", "field_order": [ "organization_tab", + "naming_series", "organization", - "website", - "territory", - "annual_revenue", - "close_date", - "probability", "next_step", + "probability", + "column_break_ijan", + "status", + "close_date", "deal_owner", "contacts_tab", + "contacts", + "contact", + "lead_details_tab", + "lead", + "source", + "column_break_wsde", "lead_name", + "organization_details_section", + "organization_name", + "website", + "no_of_employees", + "job_title", + "column_break_xbyf", + "territory", + "currency", + "annual_revenue", + "industry", + "person_section", + "salutation", + "first_name", + "last_name", + "column_break_xjmy", "email", "mobile_no", "phone", - "contacts", - "others_tab", - "naming_series", - "status", - "section_break_sygz", - "no_of_employees", - "column_break_nwob", - "job_title", - "section_break_eepu", - "lead", - "column_break_bqvs", - "source", + "gender", "sla_tab", "sla", "sla_creation", @@ -63,7 +73,8 @@ "fetch_from": ".annual_revenue", "fieldname": "annual_revenue", "fieldtype": "Currency", - "label": "Amount" + "label": "Amount", + "options": "currency" }, { "fetch_from": ".website", @@ -88,14 +99,6 @@ "label": "Lead", "options": "CRM Lead" }, - { - "fieldname": "section_break_eepu", - "fieldtype": "Section Break" - }, - { - "fieldname": "column_break_bqvs", - "fieldtype": "Column Break" - }, { "fieldname": "deal_owner", "fieldtype": "Link", @@ -142,12 +145,6 @@ "label": "Contacts", "options": "CRM Contacts" }, - { - "fieldname": "others_tab", - "fieldtype": "Tab Break", - "label": "Others", - "read_only": 1 - }, { "fieldname": "organization_tab", "fieldtype": "Tab Break", @@ -235,14 +232,6 @@ "label": "No. of Employees", "options": "1-10\n11-50\n51-200\n201-500\n501-1000\n1000+" }, - { - "fieldname": "section_break_sygz", - "fieldtype": "Section Break" - }, - { - "fieldname": "column_break_nwob", - "fieldtype": "Column Break" - }, { "fieldname": "job_title", "fieldtype": "Data", @@ -270,11 +259,87 @@ "fieldname": "lead_name", "fieldtype": "Data", "label": "Lead Name" + }, + { + "fieldname": "column_break_ijan", + "fieldtype": "Column Break" + }, + { + "fieldname": "lead_details_tab", + "fieldtype": "Tab Break", + "label": "Lead Details" + }, + { + "fieldname": "column_break_wsde", + "fieldtype": "Column Break" + }, + { + "fieldname": "organization_details_section", + "fieldtype": "Section Break", + "label": "Organization Details" + }, + { + "fieldname": "organization_name", + "fieldtype": "Data", + "label": "Organization Name" + }, + { + "fieldname": "column_break_xbyf", + "fieldtype": "Column Break" + }, + { + "fieldname": "industry", + "fieldtype": "Link", + "label": "Industry", + "options": "CRM Industry" + }, + { + "fieldname": "person_section", + "fieldtype": "Section Break", + "label": "Person" + }, + { + "fieldname": "salutation", + "fieldtype": "Link", + "label": "Salutation", + "options": "Salutation" + }, + { + "fieldname": "first_name", + "fieldtype": "Data", + "label": "First Name" + }, + { + "fieldname": "last_name", + "fieldtype": "Data", + "label": "Last Name" + }, + { + "fieldname": "column_break_xjmy", + "fieldtype": "Column Break" + }, + { + "fieldname": "gender", + "fieldtype": "Link", + "label": "Gender", + "options": "Gender" + }, + { + "fieldname": "contact", + "fieldtype": "Link", + "label": "Contact", + "options": "Contact" + }, + { + "fieldname": "currency", + "fieldtype": "Link", + "label": "Currency", + "options": "Currency" } ], "index_web_pages_for_search": 1, "links": [], - "modified": "2024-01-25 21:00:08.216020", + "modified": "2024-06-20 12:55:41.602364", "modified_by": "Administrator", "module": "FCRM", "name": "CRM Deal", diff --git a/crm/fcrm/doctype/crm_deal/crm_deal.py b/crm/fcrm/doctype/crm_deal/crm_deal.py index 901f2179..83615ab0 100644 --- a/crm/fcrm/doctype/crm_deal/crm_deal.py +++ b/crm/fcrm/doctype/crm_deal/crm_deal.py @@ -178,6 +178,7 @@ class CRMDeal(Document): "annual_revenue", "status", "email", + "currency", "mobile_no", "deal_owner", "sla_status", diff --git a/crm/fcrm/doctype/crm_organization/crm_organization.json b/crm/fcrm/doctype/crm_organization/crm_organization.json index bc1a042c..ce424763 100644 --- a/crm/fcrm/doctype/crm_organization/crm_organization.json +++ b/crm/fcrm/doctype/crm_organization/crm_organization.json @@ -9,6 +9,7 @@ "field_order": [ "organization_name", "no_of_employees", + "currency", "annual_revenue", "organization_logo", "column_break_pnpp", @@ -47,7 +48,8 @@ { "fieldname": "annual_revenue", "fieldtype": "Currency", - "label": "Annual Revenue" + "label": "Annual Revenue", + "options": "currency" }, { "fieldname": "industry", @@ -60,12 +62,18 @@ "fieldtype": "Link", "label": "Territory", "options": "CRM Territory" + }, + { + "fieldname": "currency", + "fieldtype": "Link", + "label": "Currency", + "options": "Currency" } ], "image_field": "organization_logo", "index_web_pages_for_search": 1, "links": [], - "modified": "2024-01-19 21:53:14.945857", + "modified": "2024-06-20 12:59:55.297752", "modified_by": "Administrator", "module": "FCRM", "name": "CRM Organization", diff --git a/crm/fcrm/doctype/crm_organization/crm_organization.py b/crm/fcrm/doctype/crm_organization/crm_organization.py index 6d9a2a14..471d0f51 100644 --- a/crm/fcrm/doctype/crm_organization/crm_organization.py +++ b/crm/fcrm/doctype/crm_organization/crm_organization.py @@ -47,6 +47,7 @@ class CRMOrganization(Document): "organization_logo", "website", "industry", + "currency", "annual_revenue", "modified", ] diff --git a/crm/install.py b/crm/install.py index 923cbd4e..92d8a2ef 100644 --- a/crm/install.py +++ b/crm/install.py @@ -113,19 +113,19 @@ def add_default_fields_layout(): layouts = { "CRM Lead-Quick Entry": { "doctype": "CRM Lead", - "layout": '[\n{\n"label": "Person",\n\t"fields": ["salutation", "first_name", "last_name", "email", "mobile_no", "gender"]\n},\n{\n"label": "Organization",\n\t"fields": ["organization", "website", "no_of_employees", "territory", "annual_revenue", "industry"]\n},\n{\n"label": "Other",\n"columns": 2,\n\t"fields": ["status", "lead_owner"]\n}\n]' + "layout": '[{"label":"Person","fields":["salutation","first_name","last_name","email","mobile_no", "gender"],"hideLabel":true},{"label":"Organization","fields":["organization","website","no_of_employees","territory","annual_revenue","industry"],"hideLabel":true,"hideBorder":false},{"label":"Other","columns":2,"fields":["status","lead_owner"],"hideLabel":true,"hideBorder":false}]' }, "CRM Deal-Quick Entry": { "doctype": "CRM Deal", - "layout": '[\n{\n"label": "Select Organization",\n\t"fields": ["organization"]\n},\n{\n"label": "Organization Details",\n\t"fields": [{"label": "Organization Name", "name": "organization_name", "type": "Data"}, "website", "no_of_employees", "territory", "annual_revenue", {"label": "Industry", "name": "industry", "type": "Link", "options": "CRM Industry"}]\n},\n{\n"label": "Select Contact",\n\t"fields": [{"label": "Contact", "name": "contact", "type": "Link", "options": "Contact"}]\n},\n{\n"label": "Contact Details",\n\t"fields": [{"label": "Salutation", "name": "salutation", "type": "Link", "options": "Salutation"}, {"label": "First Name", "name": "first_name", "type": "Data"}, {"label": "Last Name", "name": "last_name", "type": "Data"}, "email", "mobile_no", {"label": "Gender", "name": "gender", "type": "Link", "options": "Gender"}]\n},\n{\n"label": "Other",\n"columns": 2,\n\t"fields": ["status", "deal_owner"]\n}\n]' + "layout": '[{"label": "Select Organization", "fields": ["organization"], "hideLabel": true, "editable": true}, {"label": "Organization Details", "fields": ["organization_name", "website", "no_of_employees", "territory", "annual_revenue", "industry"], "hideLabel": true, "editable": true}, {"label": "Select Contact", "fields": ["contact"], "hideLabel": true, "editable": true}, {"label": "Contact Details", "fields": ["salutation", "first_name", "last_name", "email", "mobile_no", "gender"], "hideLabel": true, "editable": true}, {"label": "Other", "columns": 2, "fields": ["status", "deal_owner"], "hideLabel": true}]' }, "Contact-Quick Entry": { "doctype": "Contact", - "layout": '[\n{\n"label": "Salutation",\n"columns": 1,\n"fields": ["salutation"]\n},\n{\n"label": "Full Name",\n"columns": 2,\n"hideBorder": true,\n"fields": ["first_name", "last_name"]\n},\n{\n"label": "Email",\n"columns": 1,\n"hideBorder": true,\n"fields": ["email_id"]\n},\n{\n"label": "Mobile No. & Gender",\n"columns": 2,\n"hideBorder": true,\n"fields": ["mobile_no", "gender"]\n},\n{\n"label": "Organization",\n"columns": 1,\n"hideBorder": true,\n"fields": ["company_name"]\n},\n{\n"label": "Designation",\n"columns": 1,\n"hideBorder": true,\n"fields": ["designation"]\n}\n]' + "layout": '[{"label":"Salutation","columns":1,"fields":["salutation"],"hideLabel":true},{"label":"Full Name","columns":2,"hideBorder":true,"fields":["first_name","last_name"],"hideLabel":true},{"label":"Email","columns":1,"hideBorder":true,"fields":["email_id"],"hideLabel":true},{"label":"Mobile No. & Gender","columns":2,"hideBorder":true,"fields":["mobile_no","gender"],"hideLabel":true},{"label":"Organization","columns":1,"hideBorder":true,"fields":["company_name"],"hideLabel":true},{"label":"Designation","columns":1,"hideBorder":true,"fields":["designation"],"hideLabel":true}]' }, "Organization-Quick Entry": { "doctype": "CRM Organization", - "layout": '[\n{\n"label": "Organization Name",\n"columns": 1,\n"fields": ["organization_name"]\n},\n{\n"label": "Website & Revenue",\n"columns": 2,\n"hideBorder": true,\n"fields": ["website", "annual_revenue"]\n},\n{\n"label": "Territory",\n"columns": 1,\n"hideBorder": true,\n"fields": ["territory"]\n},\n{\n"label": "No of Employees & Industry",\n"columns": 2,\n"hideBorder": true,\n"fields": ["no_of_employees", "industry"]\n}\n]' + "layout": '[{"label":"Organization Name","columns":1,"fields":["organization_name"],"hideLabel":true},{"label":"Website & Revenue","columns":2,"hideBorder":true,"fields":["website","annual_revenue"],"hideLabel":true},{"label":"Territory","columns":1,"hideBorder":true,"fields":["territory"],"hideLabel":true},{"label":"No of Employees & Industry","columns":2,"hideBorder":true,"fields":["no_of_employees","industry"],"hideLabel":true}]' }, } diff --git a/crm/patches.txt b/crm/patches.txt index 32c4485a..b4c07a8e 100644 --- a/crm/patches.txt +++ b/crm/patches.txt @@ -7,4 +7,5 @@ crm.patches.v1_0.move_crm_note_data_to_fcrm_note # Patches added in this section will be executed after doctypes are migrated crm.patches.v1_0.create_email_template_custom_fields crm.patches.v1_0.create_default_fields_layout -crm.patches.v1_0.create_default_sidebar_fields_layout \ No newline at end of file +crm.patches.v1_0.create_default_sidebar_fields_layout +crm.patches.v1_0.update_deal_quick_entry_layout \ No newline at end of file diff --git a/crm/patches/v1_0/update_deal_quick_entry_layout.py b/crm/patches/v1_0/update_deal_quick_entry_layout.py new file mode 100644 index 00000000..fc52e2ac --- /dev/null +++ b/crm/patches/v1_0/update_deal_quick_entry_layout.py @@ -0,0 +1,15 @@ +import json +import frappe + +def execute(): + if not frappe.db.exists("CRM Fields Layout", "CRM Deal-Quick Entry"): + return + + deal = frappe.db.get_value("CRM Fields Layout", "CRM Deal-Quick Entry", "layout") + + layout = json.loads(deal) + for section in layout: + if section.get("label") in ["Select Organization", "Organization Details", "Select Contact", "Contact Details"]: + section["editable"] = False + + frappe.db.set_value("CRM Fields Layout", "CRM Deal-Quick Entry", "layout", json.dumps(layout)) \ No newline at end of file diff --git a/frontend/src/components/Fields.vue b/frontend/src/components/Fields.vue index 6bfdc09f..238b3ada 100644 --- a/frontend/src/components/Fields.vue +++ b/frontend/src/components/Fields.vue @@ -6,6 +6,12 @@ class="first:border-t-0 first:pt-0" :class="section.hideBorder ? '' : 'border-t pt-4'" > +
+ {{ section.label }} +
+ + + + + diff --git a/frontend/src/components/Icons/RightSideLayoutIcon.vue b/frontend/src/components/Icons/RightSideLayoutIcon.vue new file mode 100644 index 00000000..d9074f3b --- /dev/null +++ b/frontend/src/components/Icons/RightSideLayoutIcon.vue @@ -0,0 +1,18 @@ + diff --git a/frontend/src/components/Modals/DealModal.vue b/frontend/src/components/Modals/DealModal.vue index 08260ef0..15147f69 100644 --- a/frontend/src/components/Modals/DealModal.vue +++ b/frontend/src/components/Modals/DealModal.vue @@ -147,15 +147,15 @@ const dealStatuses = computed(() => { }) function createDeal() { + if (deal.website && !deal.website.startsWith('http')) { + deal.website = 'https://' + deal.website + } createResource({ url: 'crm.fcrm.doctype.crm_deal.crm_deal.create_deal', params: { args: deal }, auto: true, validate() { error.value = null - if (deal.website && !deal.website.startsWith('http')) { - deal.website = 'https://' + deal.website - } if (deal.annual_revenue) { deal.annual_revenue = deal.annual_revenue.replace(/,/g, '') if (isNaN(deal.annual_revenue)) { @@ -182,6 +182,14 @@ function createDeal() { show.value = false router.push({ name: 'Deal', params: { dealId: name } }) }, + onError(err) { + isDealCreating.value = false + if (!err.messages) { + error.value = err.message + return + } + error.value = err.messages.join('\n') + }, }) } diff --git a/frontend/src/components/Modals/LeadModal.vue b/frontend/src/components/Modals/LeadModal.vue index d288196d..6a3d35fd 100644 --- a/frontend/src/components/Modals/LeadModal.vue +++ b/frontend/src/components/Modals/LeadModal.vue @@ -97,6 +97,10 @@ const leadStatuses = computed(() => { }) function createNewLead() { + if (lead.website && !lead.website.startsWith('http')) { + lead.website = 'https://' + lead.website + } + createLead.submit(lead, { validate() { error.value = null @@ -104,9 +108,6 @@ function createNewLead() { error.value = __('First Name is mandatory') return error.value } - if (lead.website && !lead.website.startsWith('http')) { - lead.website = 'https://' + lead.website - } if (lead.annual_revenue) { lead.annual_revenue = lead.annual_revenue.replace(/,/g, '') if (isNaN(lead.annual_revenue)) { @@ -133,6 +134,14 @@ function createNewLead() { show.value = false router.push({ name: 'Lead', params: { leadId: data.name } }) }, + onError(err) { + isLeadCreating.value = false + if (!err.messages) { + error.value = err.message + return + } + error.value = err.messages.join('\n') + }, }) } diff --git a/frontend/src/components/Modals/OrganizationModal.vue b/frontend/src/components/Modals/OrganizationModal.vue index a051166c..9e94ff6d 100644 --- a/frontend/src/components/Modals/OrganizationModal.vue +++ b/frontend/src/components/Modals/OrganizationModal.vue @@ -61,9 +61,11 @@ diff --git a/frontend/src/components/SectionFields.vue b/frontend/src/components/SectionFields.vue index d80868b5..80a07229 100644 --- a/frontend/src/components/SectionFields.vue +++ b/frontend/src/components/SectionFields.vue @@ -36,7 +36,7 @@ { props.fields?.forEach((field) => { let df = field.all_properties if (df?.depends_on) evaluate_depends_on(df.depends_on, field) - all_fields.push(field) + all_fields.push({ + ...field, + placeholder: field.placeholder || field.label, + }) }) return all_fields }) diff --git a/frontend/src/components/Settings/FieldsLayout.vue b/frontend/src/components/Settings/FieldsLayout.vue deleted file mode 100644 index 9f6879c7..00000000 --- a/frontend/src/components/Settings/FieldsLayout.vue +++ /dev/null @@ -1,94 +0,0 @@ - - diff --git a/frontend/src/components/Settings/QuickEntryLayout.vue b/frontend/src/components/Settings/QuickEntryLayout.vue new file mode 100644 index 00000000..a043dbe9 --- /dev/null +++ b/frontend/src/components/Settings/QuickEntryLayout.vue @@ -0,0 +1,113 @@ + + diff --git a/frontend/src/components/Settings/QuickEntryLayoutBuilder.vue b/frontend/src/components/Settings/QuickEntryLayoutBuilder.vue new file mode 100644 index 00000000..c285db8a --- /dev/null +++ b/frontend/src/components/Settings/QuickEntryLayoutBuilder.vue @@ -0,0 +1,220 @@ + + diff --git a/frontend/src/components/Settings/SettingsModal.vue b/frontend/src/components/Settings/SettingsModal.vue index af45481f..623621c7 100644 --- a/frontend/src/components/Settings/SettingsModal.vue +++ b/frontend/src/components/Settings/SettingsModal.vue @@ -3,42 +3,31 @@ diff --git a/frontend/src/components/UserDropdown.vue b/frontend/src/components/UserDropdown.vue index 969cbbfd..8ec7ca2f 100644 --- a/frontend/src/components/UserDropdown.vue +++ b/frontend/src/components/UserDropdown.vue @@ -7,8 +7,8 @@ isCollapsed ? 'w-auto px-0' : open - ? 'w-52 bg-white px-2 shadow-sm' - : 'w-52 px-2 hover:bg-gray-200' + ? 'w-52 bg-white px-2 shadow-sm' + : 'w-52 px-2 hover:bg-gray-200' " > @@ -44,7 +44,7 @@ - +