diff --git a/erpnext/controllers/trends.py b/erpnext/controllers/trends.py index 4ced0129bda..5631441bbe1 100644 --- a/erpnext/controllers/trends.py +++ b/erpnext/controllers/trends.py @@ -400,13 +400,15 @@ def quotation_party_name_expr(): def quotation_territory_expr(): - """Only Customer and Lead carry a territory; other party types have none.""" + """Territory from the party master. CRM Deal has none here: it ships with the CRM app.""" return ( "case " "when t1.quotation_to = 'Customer' then " "(select c.territory from `tabCustomer` c where c.name = t1.party_name) " "when t1.quotation_to = 'Lead' then " "(select l.territory from `tabLead` l where l.name = t1.party_name) " + "when t1.quotation_to = 'Prospect' then " + "(select p.territory from `tabProspect` p where p.name = t1.party_name) " "end" ) diff --git a/erpnext/selling/report/quotation_trends/test_quotation_trends.py b/erpnext/selling/report/quotation_trends/test_quotation_trends.py index 8128195f7ab..28c5447711e 100644 --- a/erpnext/selling/report/quotation_trends/test_quotation_trends.py +++ b/erpnext/selling/report/quotation_trends/test_quotation_trends.py @@ -119,6 +119,54 @@ class TestQuotationTrends(ERPNextTestSuite): self.assertEqual(len(lead_rows), 1) self.assertEqual(lead_rows[0][name_idx], lead.company_name or lead_name) + def test_prospect_quotation_reports_its_master_territory(self): + """Prospect stores a territory, so its quotations must report it, not a blank cell. + + The CASE resolved territory for Customer and Lead only, so a Prospect quotation fell through + to NULL even though the master carries the field. + """ + territory = "_Test Trends Prospect Territory" + if not frappe.db.exists("Territory", territory): + frappe.get_doc( + { + "doctype": "Territory", + "territory_name": territory, + "parent_territory": "All Territories", + "is_group": 0, + } + ).insert() + + prospect_name = "_Test Trends Prospect Party" + if not frappe.db.exists("Prospect", prospect_name): + frappe.get_doc( + { + "doctype": "Prospect", + "company_name": prospect_name, + "company": "_Test Company", + "territory": territory, + } + ).insert() + + quotation = frappe.new_doc("Quotation") + quotation.company = "_Test Company" + quotation.transaction_date = TXN_DATE + quotation.currency = "INR" + quotation.quotation_to = "Prospect" + quotation.party_name = prospect_name + quotation.append( + "items", + {"item_code": "_Test Item", "qty": 1, "rate": 100, "warehouse": "_Test Warehouse - _TC"}, + ) + quotation.insert() + quotation.submit() + + labels, rows = self.run_report(based_on="Customer") + party_idx, territory_idx = labels.index("Party"), labels.index("Territory") + prospect_rows = [row for row in rows if row[party_idx] == prospect_name] + + self.assertEqual(len(prospect_rows), 1) + self.assertEqual(prospect_rows[0][territory_idx], territory) + def test_group_by_chart_matches_table_total_with_mixed_group_sizes(self): # _Test Item is quoted to two customers -> two detail rows under one header row. # _Test Item 2 is quoted to only one customer -> exactly one detail row under its