From dc448c2f51210e4b7481ad229cf9c339e81ffd69 Mon Sep 17 00:00:00 2001 From: Anupam Date: Thu, 17 Jun 2021 00:28:03 +0530 Subject: [PATCH 01/12] refactor: lead --- erpnext/crm/doctype/lead/lead.js | 5 - erpnext/crm/doctype/lead/lead.json | 186 ++++++++++++++++------------- erpnext/crm/doctype/lead/lead.py | 84 +------------ 3 files changed, 107 insertions(+), 168 deletions(-) diff --git a/erpnext/crm/doctype/lead/lead.js b/erpnext/crm/doctype/lead/lead.js index ebe85241d2..815bb41a76 100644 --- a/erpnext/crm/doctype/lead/lead.js +++ b/erpnext/crm/doctype/lead/lead.js @@ -68,11 +68,6 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller }) } - organization_lead () { - this.frm.toggle_reqd("lead_name", !this.frm.doc.organization_lead); - this.frm.toggle_reqd("company_name", this.frm.doc.organization_lead); - } - company_name () { if (this.frm.doc.organization_lead && !this.frm.doc.lead_name) { this.frm.set_value("lead_name", this.frm.doc.company_name); diff --git a/erpnext/crm/doctype/lead/lead.json b/erpnext/crm/doctype/lead/lead.json index 1b33fd73ac..ed33d896f8 100644 --- a/erpnext/crm/doctype/lead/lead.json +++ b/erpnext/crm/doctype/lead/lead.json @@ -9,30 +9,32 @@ "email_append_to": 1, "engine": "InnoDB", "field_order": [ - "organization_lead", "lead_details", "naming_series", - "lead_name", - "company_name", - "email_id", - "col_break123", - "lead_owner", - "status", "salutation", + "first_name", + "middle_name", + "last_name", + "lead_name", + "email_id", + "mobile_no", + "phone", + "col_break123", + "status", + "company_name", "designation", "gender", - "source", - "customer", - "campaign_name", - "image", - "section_break_12", - "contact_by", - "column_break_14", - "contact_date", - "ends_on", - "notes_section", - "notes", - "address_info", + "additional_information_section", + "no_of_employees", + "industry", + "market_segment", + "type", + "request_type", + "column_break_22", + "whatsapp_no", + "fax", + "website", + "address_section", "address_html", "address_type", "address_title", @@ -45,35 +47,33 @@ "state", "country", "pincode", - "contact_section", - "phone", - "mobile_no", - "fax", - "website", - "more_info", - "type", - "market_segment", - "industry", - "request_type", - "column_break3", + "section_break_12", + "lead_owner", + "ends_on", + "column_break_14", + "contact_by", + "contact_date", + "lead_source_details_section", "company", "territory", "language", + "column_break_50", + "source", + "campaign_name", "unsubscribed", "blog_subscriber", + "notes_section", + "notes", + "other_information_section", + "customer", + "image", "title" ], "fields": [ - { - "default": "0", - "fieldname": "organization_lead", - "fieldtype": "Check", - "label": "Lead is an Organization", - "set_only_once": 1 - }, { "fieldname": "lead_details", "fieldtype": "Section Break", + "label": "Lead Details", "options": "fa fa-user" }, { @@ -90,7 +90,8 @@ "fieldname": "lead_name", "fieldtype": "Data", "in_global_search": 1, - "label": "Person Name", + "label": "Full Name", + "mandatory_depends_on": "eval: !(doc.company_name)", "oldfieldname": "lead_name", "oldfieldtype": "Data", "search_index": 1 @@ -99,7 +100,9 @@ "fieldname": "company_name", "fieldtype": "Data", "in_list_view": 1, + "in_standard_filter": 1, "label": "Organization Name", + "mandatory_depends_on": "eval: !(doc.lead_name)", "oldfieldname": "company_name", "oldfieldtype": "Data" }, @@ -121,7 +124,6 @@ "default": "__user", "fieldname": "lead_owner", "fieldtype": "Link", - "in_list_view": 1, "label": "Lead Owner", "oldfieldname": "lead_owner", "oldfieldtype": "Link", @@ -241,46 +243,39 @@ "read_only": 1 }, { - "depends_on": "eval: doc.__islocal", "description": "Home, Work, etc.", "fieldname": "address_title", "fieldtype": "Data", "label": "Address Title" }, { - "depends_on": "eval: doc.__islocal", "fieldname": "address_line1", "fieldtype": "Data", "label": "Address Line 1", "mandatory_depends_on": "eval: doc.address_title && doc.address_type" }, { - "depends_on": "eval: doc.__islocal", "fieldname": "address_line2", "fieldtype": "Data", "label": "Address Line 2" }, { - "depends_on": "eval: doc.__islocal", "fieldname": "city", "fieldtype": "Data", "label": "City/Town", "mandatory_depends_on": "eval: doc.address_title && doc.address_type" }, { - "depends_on": "eval: doc.__islocal", "fieldname": "county", "fieldtype": "Data", "label": "County" }, { - "depends_on": "eval: doc.__islocal", "fieldname": "state", "fieldtype": "Data", "label": "State" }, { - "depends_on": "eval: doc.__islocal", "fieldname": "country", "fieldtype": "Link", "label": "Country", @@ -288,7 +283,7 @@ "options": "Country" }, { - "depends_on": "eval: doc.__islocal", + "collapsible_depends_on": "eval: doc.__islocal", "fieldname": "pincode", "fieldtype": "Data", "label": "Postal Code" @@ -329,14 +324,6 @@ "oldfieldname": "fax", "oldfieldtype": "Data" }, - { - "collapsible": 1, - "fieldname": "more_info", - "fieldtype": "Section Break", - "label": "More Information", - "oldfieldtype": "Section Break", - "options": "fa fa-file-text" - }, { "fieldname": "type", "fieldtype": "Select", @@ -369,12 +356,6 @@ "oldfieldtype": "Select", "options": "\nProduct Enquiry\nRequest for Information\nSuggestions\nOther" }, - { - "fieldname": "column_break3", - "fieldtype": "Column Break", - "oldfieldtype": "Column Break", - "width": "50%" - }, { "fieldname": "company", "fieldtype": "Link", @@ -389,11 +370,14 @@ "fieldtype": "Data", "label": "Website", "oldfieldname": "website", - "oldfieldtype": "Data" + "oldfieldtype": "Data", + "options": "URL" }, { "fieldname": "territory", "fieldtype": "Link", + "in_list_view": 1, + "in_standard_filter": 1, "label": "Territory", "oldfieldname": "territory", "oldfieldtype": "Link", @@ -422,28 +406,13 @@ { "fieldname": "designation", "fieldtype": "Link", + "in_list_view": 1, + "in_standard_filter": 1, "label": "Designation", "options": "Designation" }, - { - "collapsible": 1, - "collapsible_depends_on": "eval: doc.__islocal", - "fieldname": "address_info", - "fieldtype": "Section Break", - "label": "Address & Contact", - "oldfieldtype": "Column Break", - "options": "fa fa-map-marker" - }, - { - "collapsible": 1, - "collapsible_depends_on": "eval: doc.__islocal", - "fieldname": "contact_section", - "fieldtype": "Section Break", - "label": "Contact" - }, { "default": "Billing", - "depends_on": "eval: doc.__islocal", "fieldname": "address_type", "fieldtype": "Select", "label": "Address Type", @@ -454,13 +423,70 @@ "fieldtype": "Link", "label": "Print Language", "options": "Language" + }, + { + "fieldname": "first_name", + "fieldtype": "Data", + "label": "First Name" + }, + { + "fieldname": "middle_name", + "fieldtype": "Data", + "label": "Middle Name" + }, + { + "fieldname": "last_name", + "fieldtype": "Data", + "label": "Last Name" + }, + { + "collapsible": 1, + "fieldname": "additional_information_section", + "fieldtype": "Section Break", + "label": "Additional Information" + }, + { + "fieldname": "no_of_employees", + "fieldtype": "Int", + "label": "No. of Employees" + }, + { + "fieldname": "column_break_22", + "fieldtype": "Column Break" + }, + { + "fieldname": "whatsapp_no", + "fieldtype": "Data", + "label": "WhatsApp No.", + "options": "Phone" + }, + { + "collapsible": 1, + "depends_on": "eval:!doc.__islocal", + "fieldname": "address_section", + "fieldtype": "Section Break", + "label": "Address" + }, + { + "fieldname": "lead_source_details_section", + "fieldtype": "Section Break", + "label": "Lead Source Details" + }, + { + "fieldname": "column_break_50", + "fieldtype": "Column Break" + }, + { + "fieldname": "other_information_section", + "fieldtype": "Section Break", + "label": "Other Information" } ], "icon": "fa fa-user", "idx": 5, "image_field": "image", "links": [], - "modified": "2021-01-06 19:39:58.748978", + "modified": "2021-06-17 00:20:37.768449", "modified_by": "Administrator", "module": "CRM", "name": "Lead", diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py index d1d096843b..b18129b14f 100644 --- a/erpnext/crm/doctype/lead/lead.py +++ b/erpnext/crm/doctype/lead/lead.py @@ -21,14 +21,6 @@ class Lead(SellingController): self.get("__onload").is_customer = customer load_address_and_contact(self) - def before_insert(self): - if self.address_title and self.address_type: - self.address_doc = self.create_address() - self.contact_doc = self.create_contact() - - def after_insert(self): - self.update_links() - def validate(self): self.set_lead_name() self.set_title() @@ -120,85 +112,11 @@ class Lead(SellingController): self.lead_name = self.email_id.split("@")[0] def set_title(self): - if self.organization_lead: + if self.company_name: self.title = self.company_name else: self.title = self.lead_name - def create_address(self): - address_fields = ["address_type", "address_title", "address_line1", "address_line2", - "city", "county", "state", "country", "pincode"] - info_fields = ["email_id", "phone", "fax"] - - # do not create an address if no fields are available, - # skipping country since the system auto-sets it from system defaults - address = frappe.new_doc("Address") - - address.update({addr_field: self.get(addr_field) for addr_field in address_fields}) - address.update({info_field: self.get(info_field) for info_field in info_fields}) - address.insert() - - return address - - def create_contact(self): - if not self.lead_name: - self.set_lead_name() - - names = self.lead_name.strip().split(" ") - if len(names) > 1: - first_name, last_name = names[0], " ".join(names[1:]) - else: - first_name, last_name = self.lead_name, None - - contact = frappe.new_doc("Contact") - contact.update({ - "first_name": first_name, - "last_name": last_name, - "salutation": self.salutation, - "gender": self.gender, - "designation": self.designation, - }) - - if self.email_id: - contact.append("email_ids", { - "email_id": self.email_id, - "is_primary": 1 - }) - - if self.phone: - contact.append("phone_nos", { - "phone": self.phone, - "is_primary": 1 - }) - - if self.mobile_no: - contact.append("phone_nos", { - "phone": self.mobile_no - }) - - contact.insert(ignore_permissions=True) - - return contact - - def update_links(self): - # update address links - if hasattr(self, 'address_doc'): - self.address_doc.append("links", { - "link_doctype": "Lead", - "link_name": self.name, - "link_title": self.lead_name - }) - self.address_doc.save() - - # update contact links - if self.contact_doc: - self.contact_doc.append("links", { - "link_doctype": "Lead", - "link_name": self.name, - "link_title": self.lead_name - }) - self.contact_doc.save() - @frappe.whitelist() def make_customer(source_name, target_doc=None): return _make_customer(source_name, target_doc) From 49cfac0ef0eb2333e5ff6291a60550d26faf3930 Mon Sep 17 00:00:00 2001 From: Anupam Date: Wed, 28 Jul 2021 17:51:35 +0530 Subject: [PATCH 02/12] feat: added basic info. of lead in header part --- erpnext/crm/doctype/lead/lead.js | 40 ++++++++++++++++++++++++++++++ erpnext/crm/doctype/lead/lead.json | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/erpnext/crm/doctype/lead/lead.js b/erpnext/crm/doctype/lead/lead.js index 815bb41a76..bd1639bb12 100644 --- a/erpnext/crm/doctype/lead/lead.js +++ b/erpnext/crm/doctype/lead/lead.js @@ -42,6 +42,7 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller if (!this.frm.is_new()) { frappe.contacts.render_address_and_contact(this.frm); + cur_frm.trigger('render_basic_info_html'); } else { frappe.contacts.clear_address_and_contact(this.frm); } @@ -81,6 +82,45 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller this.frm.set_value("ends_on", d.format(frappe.defaultDatetimeFormat)); } } + + render_basic_info_html() { + let html=''; + if (cur_frm.doc.lead_owner){ + html += `
+ Lead Owner +
+
+ ${cur_frm.doc.lead_owner} +
` ; + } + + if (cur_frm.doc.email_id){ + html += `
+ Email +
+
+ ${cur_frm.doc.email_id} +
` ; + } + + if (cur_frm.doc.mobile_no){ + html += `
+ Mobile +
+
+ ${cur_frm.doc.mobile_no} +
` ; + } + + html += `
+ Status +
+
+ ${cur_frm.doc.status} +
` ; + html = `
${html}
`; + cur_frm.dashboard.set_headline_alert(html); + } }; extend_cscript(cur_frm.cscript, new erpnext.LeadController({ frm: cur_frm })); diff --git a/erpnext/crm/doctype/lead/lead.json b/erpnext/crm/doctype/lead/lead.json index ed33d896f8..dc030fe819 100644 --- a/erpnext/crm/doctype/lead/lead.json +++ b/erpnext/crm/doctype/lead/lead.json @@ -486,7 +486,7 @@ "idx": 5, "image_field": "image", "links": [], - "modified": "2021-06-17 00:20:37.768449", + "modified": "2021-07-28 00:20:37.768449", "modified_by": "Administrator", "module": "CRM", "name": "Lead", From 47a651a80fe5be8ec9100b68f33097f2e349a086 Mon Sep 17 00:00:00 2001 From: Anupam Date: Wed, 28 Jul 2021 18:21:19 +0530 Subject: [PATCH 03/12] fix: removing depends_on for contact fields --- erpnext/crm/doctype/lead/lead.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/erpnext/crm/doctype/lead/lead.json b/erpnext/crm/doctype/lead/lead.json index dc030fe819..f9a500fa97 100644 --- a/erpnext/crm/doctype/lead/lead.json +++ b/erpnext/crm/doctype/lead/lead.json @@ -145,7 +145,6 @@ "search_index": 1 }, { - "depends_on": "eval: doc.__islocal", "fieldname": "salutation", "fieldtype": "Link", "label": "Salutation", @@ -283,7 +282,6 @@ "options": "Country" }, { - "collapsible_depends_on": "eval: doc.__islocal", "fieldname": "pincode", "fieldtype": "Data", "label": "Postal Code" @@ -299,7 +297,6 @@ "read_only": 1 }, { - "depends_on": "eval: doc.__islocal", "fieldname": "phone", "fieldtype": "Data", "label": "Phone", @@ -308,7 +305,6 @@ "options": "Phone" }, { - "depends_on": "eval: doc.__islocal", "fieldname": "mobile_no", "fieldtype": "Data", "label": "Mobile No.", @@ -317,7 +313,6 @@ "options": "Phone" }, { - "depends_on": "eval: doc.__islocal", "fieldname": "fax", "fieldtype": "Data", "label": "Fax", From a6ce1244a07279d601702ece31243d9d6e857557 Mon Sep 17 00:00:00 2001 From: Anupam Date: Thu, 29 Jul 2021 10:43:21 +0530 Subject: [PATCH 04/12] fix: sider issues --- erpnext/crm/doctype/lead/lead.js | 6 +++--- erpnext/crm/doctype/lead/lead.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/crm/doctype/lead/lead.js b/erpnext/crm/doctype/lead/lead.js index bd1639bb12..ad24a6e222 100644 --- a/erpnext/crm/doctype/lead/lead.js +++ b/erpnext/crm/doctype/lead/lead.js @@ -85,7 +85,7 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller render_basic_info_html() { let html=''; - if (cur_frm.doc.lead_owner){ + if (cur_frm.doc.lead_owner) { html += `
Lead Owner
@@ -94,7 +94,7 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller ` ; } - if (cur_frm.doc.email_id){ + if (cur_frm.doc.email_id) { html += `
Email
@@ -103,7 +103,7 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller ` ; } - if (cur_frm.doc.mobile_no){ + if (cur_frm.doc.mobile_no) { html += `
Mobile
diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py index ce36069052..f09a814540 100644 --- a/erpnext/crm/doctype/lead/lead.py +++ b/erpnext/crm/doctype/lead/lead.py @@ -95,7 +95,7 @@ class Lead(SellingController): if d.link_doctype == self.doctype and d.link_name == self.name: to_remove = d if to_remove: - link_doctype.remove(to_remove) + linked_doc.remove(to_remove) def has_customer(self): return frappe.db.get_value("Customer", {"lead_name": self.name}) From 2732490cbefd0e8af56ae4e473e6a2fb9c72b1a3 Mon Sep 17 00:00:00 2001 From: Anupam Date: Thu, 5 Aug 2021 00:30:01 +0530 Subject: [PATCH 05/12] fix: review changes --- erpnext/crm/doctype/lead/lead.js | 47 +++++--------------- erpnext/crm/doctype/lead/lead.json | 70 +++++++++++++----------------- erpnext/crm/doctype/lead/lead.py | 18 +++++--- 3 files changed, 54 insertions(+), 81 deletions(-) diff --git a/erpnext/crm/doctype/lead/lead.js b/erpnext/crm/doctype/lead/lead.js index ad24a6e222..10e3f7da6b 100644 --- a/erpnext/crm/doctype/lead/lead.js +++ b/erpnext/crm/doctype/lead/lead.js @@ -12,7 +12,8 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller 'Opportunity': this.make_opportunity }; - this.frm.toggle_reqd("lead_name", !this.frm.doc.organization_lead); + // For avoiding integration issues. + this.frm.set_df_property('first_name', 'reqd', true); } onload () { @@ -84,42 +85,16 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller } render_basic_info_html() { - let html=''; - if (cur_frm.doc.lead_owner) { - html += `
- Lead Owner -
-
- ${cur_frm.doc.lead_owner} -
` ; + if (cur_frm.doc.contact_date) { + let contact_date = frappe.datetime.obj_to_str(cur_frm.doc.contact_date) + let diff_days = frappe.datetime.get_day_diff(contact_date, frappe.datetime.get_today()); + let color = diff_days > 0 ? "orange" : "green"; + let message = diff_days > 0 ? __("Next Contact Date") : __("Last Contact Date"); + let html = `
+ ${message} : ${contact_date} +
` ; + cur_frm.dashboard.set_headline_alert(html); } - - if (cur_frm.doc.email_id) { - html += `
- Email -
-
- ${cur_frm.doc.email_id} -
` ; - } - - if (cur_frm.doc.mobile_no) { - html += `
- Mobile -
-
- ${cur_frm.doc.mobile_no} -
` ; - } - - html += `
- Status -
-
- ${cur_frm.doc.status} -
` ; - html = `
${html}
`; - cur_frm.dashboard.set_headline_alert(html); } }; diff --git a/erpnext/crm/doctype/lead/lead.json b/erpnext/crm/doctype/lead/lead.json index f9a500fa97..542977e689 100644 --- a/erpnext/crm/doctype/lead/lead.json +++ b/erpnext/crm/doctype/lead/lead.json @@ -16,37 +16,36 @@ "middle_name", "last_name", "lead_name", - "email_id", - "mobile_no", - "phone", "col_break123", "status", "company_name", "designation", "gender", + "contact_details_section", + "email_id", + "mobile_no", + "whatsapp_no", + "column_break_16", + "phone", + "phone_ext", "additional_information_section", "no_of_employees", "industry", "market_segment", - "type", - "request_type", "column_break_22", - "whatsapp_no", "fax", "website", + "type", + "request_type", "address_section", "address_html", - "address_type", - "address_title", - "address_line1", - "address_line2", "city", + "pincode", "county", "column_break2", "contact_html", "state", "country", - "pincode", "section_break_12", "lead_owner", "ends_on", @@ -91,9 +90,9 @@ "fieldtype": "Data", "in_global_search": 1, "label": "Full Name", - "mandatory_depends_on": "eval: !(doc.company_name)", "oldfieldname": "lead_name", "oldfieldtype": "Data", + "read_only": 1, "search_index": 1 }, { @@ -102,7 +101,7 @@ "in_list_view": 1, "in_standard_filter": 1, "label": "Organization Name", - "mandatory_depends_on": "eval: !(doc.lead_name)", + "mandatory_depends_on": "eval: !(doc.first_name)", "oldfieldname": "company_name", "oldfieldtype": "Data" }, @@ -241,23 +240,6 @@ "label": "Address HTML", "read_only": 1 }, - { - "description": "Home, Work, etc.", - "fieldname": "address_title", - "fieldtype": "Data", - "label": "Address Title" - }, - { - "fieldname": "address_line1", - "fieldtype": "Data", - "label": "Address Line 1", - "mandatory_depends_on": "eval: doc.address_title && doc.address_type" - }, - { - "fieldname": "address_line2", - "fieldtype": "Data", - "label": "Address Line 2" - }, { "fieldname": "city", "fieldtype": "Data", @@ -406,13 +388,6 @@ "label": "Designation", "options": "Designation" }, - { - "default": "Billing", - "fieldname": "address_type", - "fieldtype": "Select", - "label": "Address Type", - "options": "Billing\nShipping\nOffice\nPersonal\nPlant\nPostal\nShop\nSubsidiary\nWarehouse\nCurrent\nPermanent\nOther" - }, { "fieldname": "language", "fieldtype": "Link", @@ -422,7 +397,8 @@ { "fieldname": "first_name", "fieldtype": "Data", - "label": "First Name" + "label": "First Name", + "mandatory_depends_on": "eval: !(doc.company_name)" }, { "fieldname": "middle_name", @@ -457,7 +433,7 @@ }, { "collapsible": 1, - "depends_on": "eval:!doc.__islocal", + "depends_on": "eval: !doc.__islocal", "fieldname": "address_section", "fieldtype": "Section Break", "label": "Address" @@ -475,13 +451,27 @@ "fieldname": "other_information_section", "fieldtype": "Section Break", "label": "Other Information" + }, + { + "fieldname": "contact_details_section", + "fieldtype": "Section Break", + "label": "Contact Details" + }, + { + "fieldname": "column_break_16", + "fieldtype": "Column Break" + }, + { + "fieldname": "phone_ext", + "fieldtype": "Data", + "label": "Phone Ext." } ], "icon": "fa fa-user", "idx": 5, "image_field": "image", "links": [], - "modified": "2021-07-28 00:20:37.768449", + "modified": "2021-08-04 00:24:57.208590", "modified_by": "Administrator", "module": "CRM", "name": "Lead", diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py index f09a814540..33fda89f28 100644 --- a/erpnext/crm/doctype/lead/lead.py +++ b/erpnext/crm/doctype/lead/lead.py @@ -21,18 +21,24 @@ class Lead(SellingController): self.get("__onload").is_customer = customer load_address_and_contact(self) + def set_full_name(self): + self.lead_name = " ".join(filter(None, [self.first_name, self.middle_name, self.last_name])) + def validate(self): + self.set_full_name() self.set_lead_name() self.set_title() + self.set_status() + self.check_email_id_is_unique() + self.validate_email_id() + self.validate_contact_date() self._prev = frappe._dict({ "contact_date": frappe.db.get_value("Lead", self.name, "contact_date") if (not cint(self.is_new())) else None, "ends_on": frappe.db.get_value("Lead", self.name, "ends_on") if (not cint(self.is_new())) else None, "contact_by": frappe.db.get_value("Lead", self.name, "contact_by") if (not cint(self.is_new())) else None, }) - - self.set_status() - self.check_email_id_is_unique() - + + def validate_email_id(self): if self.email_id: if not self.flags.ignore_email_validation: validate_email_address(self.email_id, throw=True) @@ -46,6 +52,7 @@ class Lead(SellingController): if self.is_new() or not self.image: self.image = has_gravatar(self.email_id) + def validate_contact_date(self): if self.contact_date and getdate(self.contact_date) < getdate(nowdate()): frappe.throw(_("Next Contact Date cannot be in the past")) @@ -88,7 +95,7 @@ class Lead(SellingController): linked_doc = frappe.get_doc(link['parenttype'], link['parent']) if len(linked_doc.get('links')) == 1: - linked_doc.delete() + linked_doc.delete(ignore_permissions=True) else: to_remove = None for d in linked_doc.get('links'): @@ -96,6 +103,7 @@ class Lead(SellingController): to_remove = d if to_remove: linked_doc.remove(to_remove) + linked_doc.save(ignore_permissions=True) def has_customer(self): return frappe.db.get_value("Customer", {"lead_name": self.name}) From c35a526dd826e91e764194ad45a1b6ac52b98b2a Mon Sep 17 00:00:00 2001 From: Anupam Date: Thu, 5 Aug 2021 14:42:15 +0530 Subject: [PATCH 06/12] fix: adding test cases --- erpnext/crm/doctype/lead/lead.js | 6 ++-- erpnext/crm/doctype/lead/lead.py | 6 ++-- erpnext/crm/doctype/lead/test_lead.py | 49 +++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/erpnext/crm/doctype/lead/lead.js b/erpnext/crm/doctype/lead/lead.js index 10e3f7da6b..3363d8c023 100644 --- a/erpnext/crm/doctype/lead/lead.js +++ b/erpnext/crm/doctype/lead/lead.js @@ -43,7 +43,7 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller if (!this.frm.is_new()) { frappe.contacts.render_address_and_contact(this.frm); - cur_frm.trigger('render_basic_info_html'); + cur_frm.trigger('render_contact_day_html'); } else { frappe.contacts.clear_address_and_contact(this.frm); } @@ -84,14 +84,14 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller } } - render_basic_info_html() { + render_contact_day_html() { if (cur_frm.doc.contact_date) { let contact_date = frappe.datetime.obj_to_str(cur_frm.doc.contact_date) let diff_days = frappe.datetime.get_day_diff(contact_date, frappe.datetime.get_today()); let color = diff_days > 0 ? "orange" : "green"; let message = diff_days > 0 ? __("Next Contact Date") : __("Last Contact Date"); let html = `
- ${message} : ${contact_date} + ${message} : ${frappe.datetime.global_date_format(contact_date)}
` ; cur_frm.dashboard.set_headline_alert(html); } diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py index 33fda89f28..49b682c12f 100644 --- a/erpnext/crm/doctype/lead/lead.py +++ b/erpnext/crm/doctype/lead/lead.py @@ -21,9 +21,6 @@ class Lead(SellingController): self.get("__onload").is_customer = customer load_address_and_contact(self) - def set_full_name(self): - self.lead_name = " ".join(filter(None, [self.first_name, self.middle_name, self.last_name])) - def validate(self): self.set_full_name() self.set_lead_name() @@ -38,6 +35,9 @@ class Lead(SellingController): "contact_by": frappe.db.get_value("Lead", self.name, "contact_by") if (not cint(self.is_new())) else None, }) + def set_full_name(self): + self.lead_name = " ".join(filter(None, [self.first_name, self.middle_name, self.last_name])) + def validate_email_id(self): if self.email_id: if not self.flags.ignore_email_validation: diff --git a/erpnext/crm/doctype/lead/test_lead.py b/erpnext/crm/doctype/lead/test_lead.py index d428a453f9..174b1c98bd 100644 --- a/erpnext/crm/doctype/lead/test_lead.py +++ b/erpnext/crm/doctype/lead/test_lead.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import frappe +from frappe.utils import random_string import unittest test_records = frappe.get_test_records('Lead') @@ -32,3 +33,51 @@ class TestLead(unittest.TestCase): customer.company = "_Test Company" customer.customer_group = "_Test Customer Group" customer.insert() + + def test_create_lead_and_unlinking_dynamic_links(self): + lead_doc = make_lead(first_name = "Lorem", last_name="Ipsum") + lead_doc_1 = make_lead() + address = frappe.get_doc({ + "doctype": "Address", + "address_type": "Billing", + "city": "Mumbai", + "address_line1": "Vidya Vihar West", + "country": "India", + "links": [{ + "link_doctype": "Lead", + "link_name": lead_doc.name + }] + }).insert() + + address_1 = frappe.get_doc({ + "doctype": "Address", + "address_type": "Billing", + "address_line1": "Baner", + "city": "Pune", + "country": "India", + "links": [{ + "link_doctype": "Lead", + "link_name": lead_doc.name + }, + { + "link_doctype": "Lead", + "link_name": lead_doc_1.name + }] + }).insert() + + lead_doc.delete() + address_1.reload() + self.assertEqual(frappe.db.exists("Lead",lead_doc.name), None) + self.assertEqual(len(address_1.get('links')), 1) + +def make_lead(**args): + args = frappe._dict(args) + + lead_doc = frappe.get_doc({ + "doctype": "Lead", + "first_name": args.first_name or "Test", + "last_name": args.last_name or "Lead", + "email_id": args.email_id or "new_lead{}@example.com".format(random_string(5)), + }).insert() + + return lead_doc \ No newline at end of file From 4723e18f9e3dec0846fd13240dd7594095b7cbc4 Mon Sep 17 00:00:00 2001 From: Anupam Date: Thu, 5 Aug 2021 19:44:00 +0530 Subject: [PATCH 07/12] fix: sider issue --- erpnext/crm/doctype/lead/lead.js | 2 +- erpnext/crm/doctype/lead/test_lead.py | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/erpnext/crm/doctype/lead/lead.js b/erpnext/crm/doctype/lead/lead.js index 3363d8c023..97e6315eff 100644 --- a/erpnext/crm/doctype/lead/lead.js +++ b/erpnext/crm/doctype/lead/lead.js @@ -86,7 +86,7 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller render_contact_day_html() { if (cur_frm.doc.contact_date) { - let contact_date = frappe.datetime.obj_to_str(cur_frm.doc.contact_date) + let contact_date = frappe.datetime.obj_to_str(cur_frm.doc.contact_date); let diff_days = frappe.datetime.get_day_diff(contact_date, frappe.datetime.get_today()); let color = diff_days > 0 ? "orange" : "green"; let message = diff_days > 0 ? __("Next Contact Date") : __("Last Contact Date"); diff --git a/erpnext/crm/doctype/lead/test_lead.py b/erpnext/crm/doctype/lead/test_lead.py index 174b1c98bd..18e0692c5e 100644 --- a/erpnext/crm/doctype/lead/test_lead.py +++ b/erpnext/crm/doctype/lead/test_lead.py @@ -37,7 +37,7 @@ class TestLead(unittest.TestCase): def test_create_lead_and_unlinking_dynamic_links(self): lead_doc = make_lead(first_name = "Lorem", last_name="Ipsum") lead_doc_1 = make_lead() - address = frappe.get_doc({ + frappe.get_doc({ "doctype": "Address", "address_type": "Billing", "city": "Mumbai", @@ -55,14 +55,16 @@ class TestLead(unittest.TestCase): "address_line1": "Baner", "city": "Pune", "country": "India", - "links": [{ - "link_doctype": "Lead", - "link_name": lead_doc.name - }, - { - "link_doctype": "Lead", - "link_name": lead_doc_1.name - }] + "links": [ + { + "link_doctype": "Lead", + "link_name": lead_doc.name + }, + { + "link_doctype": "Lead", + "link_name": lead_doc_1.name + } + ] }).insert() lead_doc.delete() From 01a0585ba0bbfe68b650a1090edb20f6071bfaf0 Mon Sep 17 00:00:00 2001 From: Anupam Date: Fri, 6 Aug 2021 11:47:07 +0530 Subject: [PATCH 08/12] fix: removing organization_lead traceback --- erpnext/crm/doctype/lead/lead.js | 2 +- erpnext/crm/doctype/lead/test_lead.py | 4 ++-- erpnext/crm/doctype/lead/test_records.json | 1 - erpnext/crm/doctype/lead/tests/test_lead_organization.js | 1 - erpnext/selling/doctype/customer/customer.py | 4 ++-- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/erpnext/crm/doctype/lead/lead.js b/erpnext/crm/doctype/lead/lead.js index 97e6315eff..75af937990 100644 --- a/erpnext/crm/doctype/lead/lead.js +++ b/erpnext/crm/doctype/lead/lead.js @@ -71,7 +71,7 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller } company_name () { - if (this.frm.doc.organization_lead && !this.frm.doc.lead_name) { + if (!this.frm.doc.lead_name) { this.frm.set_value("lead_name", this.frm.doc.company_name); } } diff --git a/erpnext/crm/doctype/lead/test_lead.py b/erpnext/crm/doctype/lead/test_lead.py index 18e0692c5e..cadc1a28a0 100644 --- a/erpnext/crm/doctype/lead/test_lead.py +++ b/erpnext/crm/doctype/lead/test_lead.py @@ -35,7 +35,7 @@ class TestLead(unittest.TestCase): customer.insert() def test_create_lead_and_unlinking_dynamic_links(self): - lead_doc = make_lead(first_name = "Lorem", last_name="Ipsum") + lead_doc = make_lead(first_name = "Lorem", last_name="Ipsum", email_id="lorem_ipsum@example.com") lead_doc_1 = make_lead() frappe.get_doc({ "doctype": "Address", @@ -79,7 +79,7 @@ def make_lead(**args): "doctype": "Lead", "first_name": args.first_name or "Test", "last_name": args.last_name or "Lead", - "email_id": args.email_id or "new_lead{}@example.com".format(random_string(5)), + "email_id": args.email_id or "new_lead_{}@example.com".format(random_string(5)), }).insert() return lead_doc \ No newline at end of file diff --git a/erpnext/crm/doctype/lead/test_records.json b/erpnext/crm/doctype/lead/test_records.json index 39864e2e3e..3158add0f2 100644 --- a/erpnext/crm/doctype/lead/test_records.json +++ b/erpnext/crm/doctype/lead/test_records.json @@ -27,7 +27,6 @@ { "doctype": "Lead", "email_id": "test_lead4@example.com", - "organization_lead": 1, "lead_name": "_Test Lead 4", "company_name": "_Test Lead 4", "status": "Open" diff --git a/erpnext/crm/doctype/lead/tests/test_lead_organization.js b/erpnext/crm/doctype/lead/tests/test_lead_organization.js index 43959356b1..7fb957370b 100644 --- a/erpnext/crm/doctype/lead/tests/test_lead_organization.js +++ b/erpnext/crm/doctype/lead/tests/test_lead_organization.js @@ -9,7 +9,6 @@ QUnit.test("test: lead", function (assert) { () => frappe.set_route("List", "Lead"), () => frappe.new_doc("Lead"), () => frappe.timeout(1), - () => cur_frm.set_value("organization_lead", "1"), () => cur_frm.set_value("company_name", lead_name), () => cur_frm.save(), () => frappe.timeout(1), diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index 3b62081e24..66edcd0188 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -176,12 +176,12 @@ class Customer(TransactionBase): address.append('links', dict(link_doctype='Customer', link_name=self.name)) address.save(ignore_permissions=self.flags.ignore_permissions) - lead = frappe.db.get_value("Lead", self.lead_name, ["organization_lead", "lead_name", "email_id", "phone", "mobile_no", "gender", "salutation"], as_dict=True) + lead = frappe.db.get_value("Lead", self.lead_name, ["company_name", "lead_name", "email_id", "phone", "mobile_no", "gender", "salutation"], as_dict=True) if not lead.lead_name: frappe.throw(_("Please mention the Lead Name in Lead {0}").format(self.lead_name)) - if lead.organization_lead: + if lead.company_name: contact_names = frappe.get_all('Dynamic Link', filters={ "parenttype":"Contact", "link_doctype":"Lead", From 59c971015abf1e90452da2e8752d47b34ed76ee4 Mon Sep 17 00:00:00 2001 From: Anupam Date: Fri, 6 Aug 2021 14:02:57 +0530 Subject: [PATCH 09/12] fix: test case --- erpnext/crm/doctype/lead/test_lead.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/crm/doctype/lead/test_lead.py b/erpnext/crm/doctype/lead/test_lead.py index cadc1a28a0..d4886d3506 100644 --- a/erpnext/crm/doctype/lead/test_lead.py +++ b/erpnext/crm/doctype/lead/test_lead.py @@ -77,7 +77,7 @@ def make_lead(**args): lead_doc = frappe.get_doc({ "doctype": "Lead", - "first_name": args.first_name or "Test", + "first_name": args.first_name or "_Test", "last_name": args.last_name or "Lead", "email_id": args.email_id or "new_lead_{}@example.com".format(random_string(5)), }).insert() From b4e720f8ecd8ad5966fb8c7f399c1347f11a84d2 Mon Sep 17 00:00:00 2001 From: Anupam Date: Fri, 6 Aug 2021 14:39:13 +0530 Subject: [PATCH 10/12] fix: test case --- erpnext/crm/doctype/appointment/test_appointment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/crm/doctype/appointment/test_appointment.py b/erpnext/crm/doctype/appointment/test_appointment.py index 50c98c59de..bcab7bd708 100644 --- a/erpnext/crm/doctype/appointment/test_appointment.py +++ b/erpnext/crm/doctype/appointment/test_appointment.py @@ -9,7 +9,7 @@ import datetime def create_test_lead(): - test_lead = frappe.db.exists({'doctype': 'Lead', 'lead_name': 'Test Lead'}) + test_lead = frappe.db.exists({'doctype': 'Lead', 'email':'test@example.com'}) if test_lead: return frappe.get_doc('Lead', test_lead[0][0]) test_lead = frappe.get_doc({ From 42bb77bf80a494e6ed4fae35e1e283dbadf2c581 Mon Sep 17 00:00:00 2001 From: Anupam Date: Mon, 9 Aug 2021 15:11:13 +0530 Subject: [PATCH 11/12] fix: creating contact on creation of lead --- erpnext/crm/doctype/lead/lead.py | 58 +++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py index 49b682c12f..7f028cb316 100644 --- a/erpnext/crm/doctype/lead/lead.py +++ b/erpnext/crm/doctype/lead/lead.py @@ -63,6 +63,22 @@ class Lead(SellingController): def on_update(self): self.add_calendar_event() + def before_insert(self): + self.contact_doc = self.create_contact() + + def after_insert(self): + self.update_links() + + def update_links(self): + # update contact links + if self.contact_doc: + self.contact_doc.append("links", { + "link_doctype": "Lead", + "link_name": self.name, + "link_title": self.lead_name + }) + self.contact_doc.save() + def add_calendar_event(self, opts=None, force=False): super(Lead, self).add_calendar_event({ "owner": self.lead_owner, @@ -116,7 +132,6 @@ class Lead(SellingController): "party_name": self.name, "docstatus": 1, "status": ["!=", "Lost"] - }) def has_lost_quotation(self): @@ -137,10 +152,43 @@ class Lead(SellingController): self.lead_name = self.email_id.split("@")[0] def set_title(self): - if self.company_name: - self.title = self.company_name - else: - self.title = self.lead_name + self.title = self.company_name or self.lead_name + + def create_contact(self): + if not self.lead_name: + self.set_full_name() + self.set_lead_name() + + contact = frappe.new_doc("Contact") + contact.update({ + "first_name": self.first_name or self.lead_name, + "last_name": self.last_name, + "salutation": self.salutation, + "gender": self.gender, + "designation": self.designation, + }) + + if self.email_id: + contact.append("email_ids", { + "email_id": self.email_id, + "is_primary": 1 + }) + + if self.phone: + contact.append("phone_nos", { + "phone": self.phone, + "is_primary_phone": 1 + }) + + if self.mobile_no: + contact.append("phone_nos", { + "phone": self.mobile_no, + "is_primary_mobile_no":1 + }) + + contact.insert(ignore_permissions=True) + + return contact @frappe.whitelist() def make_customer(source_name, target_doc=None): From db3ee314138ee40653c562d89d5aff0764a03ad7 Mon Sep 17 00:00:00 2001 From: Anupam Date: Mon, 9 Aug 2021 15:34:50 +0530 Subject: [PATCH 12/12] fix: test case --- erpnext/crm/doctype/appointment/test_appointment.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/crm/doctype/appointment/test_appointment.py b/erpnext/crm/doctype/appointment/test_appointment.py index bcab7bd708..c7563e9d15 100644 --- a/erpnext/crm/doctype/appointment/test_appointment.py +++ b/erpnext/crm/doctype/appointment/test_appointment.py @@ -9,7 +9,7 @@ import datetime def create_test_lead(): - test_lead = frappe.db.exists({'doctype': 'Lead', 'email':'test@example.com'}) + test_lead = frappe.db.exists({'doctype': 'Lead', 'email_id':'test@example.com'}) if test_lead: return frappe.get_doc('Lead', test_lead[0][0]) test_lead = frappe.get_doc({