From 35438b6fc0bcb5752dfd8e572f4b06fc42f8ff0c Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Thu, 10 Aug 2017 11:15:50 +0530 Subject: [PATCH] [Fix] Opportunity status has not changed after making of quotation against it if items has not added in the opportunity (#10351) --- .../crm/doctype/opportunity/opportunity.py | 20 ++++++--- .../doctype/opportunity/test_opportunity.py | 43 ++++++++++++++++++- .../selling/doctype/quotation/quotation.json | 33 +++++++++++++- .../selling/doctype/quotation/quotation.py | 15 +++++-- 4 files changed, 101 insertions(+), 10 deletions(-) diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py index 93a294174d..8bc7ad8461 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.py +++ b/erpnext/crm/doctype/opportunity/opportunity.py @@ -84,11 +84,19 @@ class Opportunity(TransactionBase): self.delete_events() def has_active_quotation(self): - return frappe.db.sql(""" - select q.name - from `tabQuotation` q, `tabQuotation Item` qi - where q.name = qi.parent and q.docstatus=1 and qi.prevdoc_docname =%s - and q.status not in ('Lost', 'Closed')""", self.name) + if not self.with_items: + return frappe.get_all('Quotation', + { + 'opportunity': self.name, + 'status': ("not in", ['Lost', 'Closed']), + 'docstatus': 1 + }, 'name') + else: + return frappe.db.sql(""" + select q.name + from `tabQuotation` q, `tabQuotation Item` qi + where q.name = qi.parent and q.docstatus=1 and qi.prevdoc_docname =%s + and q.status not in ('Lost', 'Closed')""", self.name) def has_ordered_quotation(self): return frappe.db.sql(""" @@ -212,6 +220,8 @@ def make_quotation(source_name, target_doc=None): quotation.run_method("set_missing_values") quotation.run_method("calculate_taxes_and_totals") + if not source.with_items: + quotation.opportunity = source.name doclist = get_mapped_doc("Opportunity", source_name, { "Opportunity": { diff --git a/erpnext/crm/doctype/opportunity/test_opportunity.py b/erpnext/crm/doctype/opportunity/test_opportunity.py index 0957afe697..4cd20ea72d 100644 --- a/erpnext/crm/doctype/opportunity/test_opportunity.py +++ b/erpnext/crm/doctype/opportunity/test_opportunity.py @@ -3,9 +3,50 @@ from __future__ import unicode_literals import frappe +from frappe.utils import today +from erpnext.crm.doctype.opportunity.opportunity import make_quotation import unittest test_records = frappe.get_test_records('Opportunity') class TestOpportunity(unittest.TestCase): - pass + def test_opportunity_status(self): + doc = make_opportunity(with_items=0) + quotation = make_quotation(doc.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() + + doc = frappe.get_doc('Opportunity', doc.name) + self.assertEquals(doc.status, "Quotation") + +def make_opportunity(**args): + args = frappe._dict(args) + + opp_doc = frappe.get_doc({ + "doctype": "Opportunity", + "enquiry_from": "Customer" or args.enquiry_from, + "enquiry_type": "Sales", + "with_items": args.with_items or 0, + "transaction_date": today() + }) + + if opp_doc.enquiry_from == 'Customer': + opp_doc.customer = args.customer or "_Test Customer" + + if opp_doc.enquiry_from == 'Lead': + opp_doc.customer = args.lead or "_T-Lead-00001" + + if args.with_items: + opp_doc.append('items', { + "item_code": args.item_code or "_Test Item", + "qty": args.qty or 1 + }) + + opp_doc.insert() + return opp_doc \ No newline at end of file diff --git a/erpnext/selling/doctype/quotation/quotation.json b/erpnext/selling/doctype/quotation/quotation.json index ab3e8c9c21..0afc5ca3d0 100644 --- a/erpnext/selling/doctype/quotation/quotation.json +++ b/erpnext/selling/doctype/quotation/quotation.json @@ -2588,6 +2588,37 @@ "search_index": 0, "set_only_once": 0, "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "opportunity", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Opportunity", + "length": 0, + "no_copy": 0, + "options": "Opportunity", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 } ], "has_web_view": 0, @@ -2602,7 +2633,7 @@ "istable": 0, "max_attachments": 1, "menu_index": 0, - "modified": "2017-08-09 01:16:21.104135", + "modified": "2017-08-09 06:35:48.691648", "modified_by": "Administrator", "module": "Selling", "name": "Quotation", diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index 5eb8b06ed8..ce5fb49c52 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -49,9 +49,18 @@ class Quotation(SellingController): def update_opportunity(self): for opportunity in list(set([d.prevdoc_docname for d in self.get("items")])): if opportunity: - opp = frappe.get_doc("Opportunity", opportunity) - opp.status = None - opp.set_status(update=True) + self.update_opportunity_status(opportunity) + + if self.opportunity: + self.update_opportunity_status() + + def update_opportunity_status(self, opportunity=None): + if not opportunity: + opportunity = self.opportunity + + opp = frappe.get_doc("Opportunity", opportunity) + opp.status = None + opp.set_status(update=True) def declare_order_lost(self, arg): if not self.has_sales_order():