From f547befeb9f366311f2d9c874498193745d825c3 Mon Sep 17 00:00:00 2001 From: Nihantra Patel Date: Thu, 18 Jul 2024 12:14:53 +0530 Subject: [PATCH 1/5] fix: Create Sales Order from Quotation for Prospect (cherry picked from commit 2f63fae31da75425f01f5c7c8d57d72514b3eb9f) # Conflicts: # erpnext/selling/doctype/quotation/quotation.py --- erpnext/crm/doctype/prospect/test_prospect.py | 20 ++++++ .../selling/doctype/customer/customer.json | 9 +++ erpnext/selling/doctype/customer/customer.py | 1 + .../selling/doctype/quotation/quotation.py | 61 +++++++++++++++++++ 4 files changed, 91 insertions(+) diff --git a/erpnext/crm/doctype/prospect/test_prospect.py b/erpnext/crm/doctype/prospect/test_prospect.py index c3930ee6c93..286b91e2086 100644 --- a/erpnext/crm/doctype/prospect/test_prospect.py +++ b/erpnext/crm/doctype/prospect/test_prospect.py @@ -27,6 +27,26 @@ class TestProspect(unittest.TestCase): address_doc.reload() self.assertEqual(address_doc.has_link("Prospect", prospect_doc.name), True) + def test_make_customer_from_prospect(self): + from erpnext.crm.doctype.prospect.prospect import make_customer as make_customer_from_prospect + + frappe.delete_doc_if_exists("Customer", "_Test Prospect") + + prospect = frappe.get_doc({ + "doctype": "Prospect", + "company_name": "_Test Prospect", + "customer_group": "_Test Customer Group", + }) + prospect.insert() + + customer = make_customer_from_prospect("_Test Prospect") + + self.assertEqual(customer.doctype, "Customer") + self.assertEqual(customer.company_name, "_Test Prospect") + self.assertEqual(customer.customer_group, "_Test Customer Group") + + customer.company = "_Test Company" + customer.insert() def make_prospect(**args): args = frappe._dict(args) diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json index af32f4ecf84..59f082431b8 100644 --- a/erpnext/selling/doctype/customer/customer.json +++ b/erpnext/selling/doctype/customer/customer.json @@ -21,6 +21,7 @@ "gender", "lead_name", "opportunity_name", + "prospect_name", "account_manager", "image", "defaults_tab", @@ -570,6 +571,14 @@ { "fieldname": "column_break_nwor", "fieldtype": "Column Break" + }, + { + "fieldname": "prospect_name", + "fieldtype": "Link", + "label": "From Prospect", + "no_copy": 1, + "options": "Prospect", + "print_hide": 1 } ], "icon": "fa fa-user", diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index 71f0022df14..9bd9b5e760a 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -77,6 +77,7 @@ class Customer(TransactionBase): payment_terms: DF.Link | None portal_users: DF.Table[PortalUser] primary_address: DF.Text | None + prospect_name: DF.Link | None represents_company: DF.Link | None sales_team: DF.Table[SalesTeam] salutation: DF.Link | None diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index f9442204df1..f48f8a88712 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -516,6 +516,7 @@ def _make_customer(source_name, ignore_permissions=False, customer_group=None): if not customer_name: from erpnext.crm.doctype.lead.lead import _make_customer +<<<<<<< HEAD customer_doclist = _make_customer(lead_name, ignore_permissions=ignore_permissions) customer = frappe.get_doc(customer_doclist) customer.flags.ignore_permissions = ignore_permissions @@ -535,6 +536,25 @@ def _make_customer(source_name, ignore_permissions=False, customer_group=None): except frappe.MandatoryError as e: mandatory_fields = e.args[0].split(":")[1].split(",") mandatory_fields = [customer.meta.get_label(field.strip()) for field in mandatory_fields] +======= + # Check if a Customer already exists for the Lead or Prospect. + existing_customer = None + if quotation.quotation_to == "Lead": + existing_customer = frappe.db.get_value("Customer", {"lead_name": quotation.party_name}) + elif quotation.quotation_to == "Prospect": + existing_customer = frappe.db.get_value("Customer", {"prospect_name": quotation.party_name}) + + if existing_customer: + return frappe.get_doc("Customer", existing_customer) + + # If no Customer exists, create a new Customer or Prospect. + if quotation.quotation_to == "Lead": + return create_customer_from_lead(quotation.party_name, ignore_permissions=ignore_permissions) + elif quotation.quotation_to == "Prospect": + return create_customer_from_prospect(quotation.party_name, ignore_permissions=ignore_permissions) + + return None +>>>>>>> 2f63fae31d (fix: Create Sales Order from Quotation for Prospect) frappe.local.message_log = [] lead_link = frappe.utils.get_link_to_form("Lead", lead_name) @@ -545,8 +565,49 @@ def _make_customer(source_name, ignore_permissions=False, customer_group=None): message += "
" message += _("Please create Customer from Lead {0}.").format(lead_link) +<<<<<<< HEAD frappe.throw(message, title=_("Mandatory Missing")) else: return customer_name else: return frappe.get_doc("Customer", quotation.get("party_name")) +======= +def create_customer_from_lead(lead_name, ignore_permissions=False): + from erpnext.crm.doctype.lead.lead import _make_customer + + customer = _make_customer(lead_name, ignore_permissions=ignore_permissions) + customer.flags.ignore_permissions = ignore_permissions + + try: + customer.insert() + return customer + except frappe.MandatoryError as e: + handle_mandatory_error(e, customer, lead_name) + + +def create_customer_from_prospect(prospect_name, ignore_permissions=False): + from erpnext.crm.doctype.prospect.prospect import make_customer as make_customer_from_prospect + + customer = make_customer_from_prospect(prospect_name) + customer.flags.ignore_permissions = ignore_permissions + + try: + customer.insert() + return customer + except frappe.MandatoryError as e: + handle_mandatory_error(e, customer, prospect_name) + + +def handle_mandatory_error(e, customer, lead_name): + from frappe.utils import get_link_to_form + + mandatory_fields = e.args[0].split(":")[1].split(",") + mandatory_fields = [customer.meta.get_label(field.strip()) for field in mandatory_fields] + + frappe.local.message_log = [] + message = _("Could not auto create Customer due to the following missing mandatory field(s):") + "
" + message += "
" + message += _("Please create Customer from Lead {0}.").format(get_link_to_form("Lead", lead_name)) + + frappe.throw(message, title=_("Mandatory Missing")) +>>>>>>> 2f63fae31d (fix: Create Sales Order from Quotation for Prospect) From 549dc286d03a7ae267b5e2742704dd9f023ee363 Mon Sep 17 00:00:00 2001 From: Nihantra Patel Date: Thu, 18 Jul 2024 12:24:52 +0530 Subject: [PATCH 2/5] fix: update the testcase format (cherry picked from commit 29d50b770e3d8de745a75cecbf18c0d745c4de6f) --- erpnext/crm/doctype/prospect/test_prospect.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/erpnext/crm/doctype/prospect/test_prospect.py b/erpnext/crm/doctype/prospect/test_prospect.py index 286b91e2086..e89bade19a1 100644 --- a/erpnext/crm/doctype/prospect/test_prospect.py +++ b/erpnext/crm/doctype/prospect/test_prospect.py @@ -32,11 +32,13 @@ class TestProspect(unittest.TestCase): frappe.delete_doc_if_exists("Customer", "_Test Prospect") - prospect = frappe.get_doc({ - "doctype": "Prospect", - "company_name": "_Test Prospect", - "customer_group": "_Test Customer Group", - }) + prospect = frappe.get_doc( + { + "doctype": "Prospect", + "company_name": "_Test Prospect", + "customer_group": "_Test Customer Group", + } + ) prospect.insert() customer = make_customer_from_prospect("_Test Prospect") From 33542cb9097751492204d6ec3b0fe3573dbddf36 Mon Sep 17 00:00:00 2001 From: Nihantra Patel Date: Thu, 18 Jul 2024 12:26:23 +0530 Subject: [PATCH 3/5] fix: update the testcase format (cherry picked from commit ee44022249c39bc17d9cbf29c854c64c41f9a911) --- erpnext/crm/doctype/prospect/test_prospect.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/crm/doctype/prospect/test_prospect.py b/erpnext/crm/doctype/prospect/test_prospect.py index e89bade19a1..47e38515cac 100644 --- a/erpnext/crm/doctype/prospect/test_prospect.py +++ b/erpnext/crm/doctype/prospect/test_prospect.py @@ -50,6 +50,7 @@ class TestProspect(unittest.TestCase): customer.company = "_Test Company" customer.insert() + def make_prospect(**args): args = frappe._dict(args) From 5d7fb1d9457c276d6bd91c66546f001f56fdb728 Mon Sep 17 00:00:00 2001 From: "Nihantra C. Patel" <141945075+Nihantra-Patel@users.noreply.github.com> Date: Tue, 20 Aug 2024 11:31:49 +0530 Subject: [PATCH 4/5] fix: create SO from Quot for Prospect --conflicts --- .../selling/doctype/quotation/quotation.py | 63 ++++--------------- 1 file changed, 12 insertions(+), 51 deletions(-) diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index f48f8a88712..bf2c166069f 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -347,8 +347,8 @@ def make_sales_order(source_name: str, target_doc=None): return _make_sales_order(source_name, target_doc) -def _make_sales_order(source_name, target_doc=None, customer_group=None, ignore_permissions=False): - customer = _make_customer(source_name, ignore_permissions, customer_group) +def _make_sales_order(source_name, target_doc=None, ignore_permissions=False): + customer = _make_customer(source_name, ignore_permissions) ordered_items = frappe._dict( frappe.db.get_all( "Sales Order Item", @@ -502,41 +502,17 @@ def _make_sales_invoice(source_name, target_doc=None, ignore_permissions=False): return doclist -def _make_customer(source_name, ignore_permissions=False, customer_group=None): +def _make_customer(source_name, ignore_permissions=False): quotation = frappe.db.get_value( - "Quotation", source_name, ["order_type", "party_name", "customer_name"], as_dict=1 + "Quotation", + source_name, + ["order_type", "quotation_to", "party_name", "customer_name"], + as_dict=1, ) - if quotation and quotation.get("party_name"): - if not frappe.db.exists("Customer", quotation.get("party_name")): - lead_name = quotation.get("party_name") - customer_name = frappe.db.get_value( - "Customer", {"lead_name": lead_name}, ["name", "customer_name"], as_dict=True - ) - if not customer_name: - from erpnext.crm.doctype.lead.lead import _make_customer + if quotation.quotation_to == "Customer": + return frappe.get_doc("Customer", quotation.party_name) -<<<<<<< HEAD - customer_doclist = _make_customer(lead_name, ignore_permissions=ignore_permissions) - customer = frappe.get_doc(customer_doclist) - customer.flags.ignore_permissions = ignore_permissions - customer.customer_group = customer_group - - try: - customer.insert() - return customer - except frappe.NameError: - if frappe.defaults.get_global_default("cust_master_name") == "Customer Name": - customer.run_method("autoname") - customer.name += "-" + lead_name - customer.insert() - return customer - else: - raise - except frappe.MandatoryError as e: - mandatory_fields = e.args[0].split(":")[1].split(",") - mandatory_fields = [customer.meta.get_label(field.strip()) for field in mandatory_fields] -======= # Check if a Customer already exists for the Lead or Prospect. existing_customer = None if quotation.quotation_to == "Lead": @@ -554,24 +530,8 @@ def _make_customer(source_name, ignore_permissions=False, customer_group=None): return create_customer_from_prospect(quotation.party_name, ignore_permissions=ignore_permissions) return None ->>>>>>> 2f63fae31d (fix: Create Sales Order from Quotation for Prospect) - frappe.local.message_log = [] - lead_link = frappe.utils.get_link_to_form("Lead", lead_name) - message = ( - _("Could not auto create Customer due to the following missing mandatory field(s):") - + "
" - ) - message += "
  • " + "
  • ".join(mandatory_fields) + "
" - message += _("Please create Customer from Lead {0}.").format(lead_link) -<<<<<<< HEAD - frappe.throw(message, title=_("Mandatory Missing")) - else: - return customer_name - else: - return frappe.get_doc("Customer", quotation.get("party_name")) -======= def create_customer_from_lead(lead_name, ignore_permissions=False): from erpnext.crm.doctype.lead.lead import _make_customer @@ -605,9 +565,10 @@ def handle_mandatory_error(e, customer, lead_name): mandatory_fields = [customer.meta.get_label(field.strip()) for field in mandatory_fields] frappe.local.message_log = [] - message = _("Could not auto create Customer due to the following missing mandatory field(s):") + "
" + message = ( + _("Could not auto create Customer due to the following missing mandatory field(s):") + "
" + ) message += "
  • " + "
  • ".join(mandatory_fields) + "
" message += _("Please create Customer from Lead {0}.").format(get_link_to_form("Lead", lead_name)) frappe.throw(message, title=_("Mandatory Missing")) ->>>>>>> 2f63fae31d (fix: Create Sales Order from Quotation for Prospect) From ec0201cb85f0c46a92993c6082b51507091dffd9 Mon Sep 17 00:00:00 2001 From: "Nihantra C. Patel" <141945075+Nihantra-Patel@users.noreply.github.com> Date: Tue, 20 Aug 2024 11:34:27 +0530 Subject: [PATCH 5/5] fix: create SO from Quot for Prospect --conflicts --- erpnext/selling/doctype/quotation/quotation.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index bf2c166069f..2a4b04b9db5 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -565,9 +565,7 @@ def handle_mandatory_error(e, customer, lead_name): mandatory_fields = [customer.meta.get_label(field.strip()) for field in mandatory_fields] frappe.local.message_log = [] - message = ( - _("Could not auto create Customer due to the following missing mandatory field(s):") + "
" - ) + message = _("Could not auto create Customer due to the following missing mandatory field(s):") + "
" message += "
  • " + "
  • ".join(mandatory_fields) + "
" message += _("Please create Customer from Lead {0}.").format(get_link_to_form("Lead", lead_name))