diff --git a/erpnext/crm/doctype/opportunity/test_opportunity.py b/erpnext/crm/doctype/opportunity/test_opportunity.py index 62fad25a574..815ab992412 100644 --- a/erpnext/crm/doctype/opportunity/test_opportunity.py +++ b/erpnext/crm/doctype/opportunity/test_opportunity.py @@ -100,6 +100,42 @@ class TestOpportunity(ERPNextTestSuite): opp.opportunity_owner = None self.assertIsNone(opp.get_notification_email()) + def test_declare_enquiry_lost(self): + lost_reason = _ensure_master("Opportunity Lost Reason", "lost_reason", "_Test Lost - Too Expensive") + competitor = _ensure_master("Competitor", "competitor_name", "_Test Competitor") + + opp = make_opportunity(with_items=0) + opp.declare_enquiry_lost( + lost_reasons_list=[{"lost_reason": lost_reason}], + competitors=[{"competitor": competitor}], + detailed_reason="Budget too high", + ) + + opp.reload() + self.assertEqual(opp.status, "Lost") + self.assertEqual(opp.order_lost_reason, "Budget too high") + self.assertEqual([d.lost_reason for d in opp.lost_reasons], [lost_reason]) + self.assertEqual([d.competitor for d in opp.competitors], [competitor]) + + def test_declare_lost_blocked_when_quotation_active(self): + opp = make_opportunity(with_items=0) + quotation = make_quotation(opp.name) + quotation.append("items", {"item_code": "_Test Item", "qty": 1}) + quotation.run_method("set_missing_values") + quotation.run_method("calculate_taxes_and_totals") + quotation.submit() + + # A submitted, still-active quotation exists, so the opportunity can't be marked lost + opp.reload() + self.assertRaises(frappe.ValidationError, opp.declare_enquiry_lost, [], [], "x") + self.assertNotEqual(opp.status, "Lost") + + +def _ensure_master(doctype, fieldname, value): + if not frappe.db.exists(doctype, value): + frappe.get_doc({"doctype": doctype, fieldname: value}).insert(ignore_permissions=True) + return value + def make_opportunity_from_lead(company): new_lead_email_id = f"new{random_string(5)}@example.com"