From 6544a85f1e7c97ef3edc95ccaef2bb2e452653d4 Mon Sep 17 00:00:00 2001 From: AravindPranera Date: Thu, 24 Aug 2017 18:32:40 +0530 Subject: [PATCH 1/8] Opportunity Items fetching into Request for quotation --- .../crm/doctype/opportunity/opportunity.py | 48 ++++++++++++------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py index 8bc7ad8461..da0ade7043 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.py +++ b/erpnext/crm/doctype/opportunity/opportunity.py @@ -84,19 +84,11 @@ class Opportunity(TransactionBase): self.delete_events() def has_active_quotation(self): - 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) + 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(""" @@ -193,6 +185,27 @@ def get_item_details(item_code): 'brand': item and item[0]['brand'] or '' } +@frappe.whitelist() +def make_request_for_quotation(source_name, target_doc=None): + doclist = get_mapped_doc("Opportunity", source_name, { + "Opportunity": { + "doctype": "Request for Quotation", + "validation": { + "enquiry_type": ["=", "Sales"] + } + }, + "Opportunity Item": { + "doctype": "Request for Quotation Item", + "field_map": [ + ["name", "opportunity_item"], + ["parent", "opportunity"], + ["uom", "uom"] + ] + } + }, target_doc) + + return doclist + @frappe.whitelist() def make_quotation(source_name, target_doc=None): def set_missing_values(source, target): @@ -220,8 +233,6 @@ 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": { @@ -247,6 +258,7 @@ def make_quotation(source_name, target_doc=None): @frappe.whitelist() def make_supplier_quotation(source_name, target_doc=None): + frappe.msgprint("python"); doclist = get_mapped_doc("Opportunity", source_name, { "Opportunity": { "doctype": "Supplier Quotation", @@ -261,9 +273,11 @@ def make_supplier_quotation(source_name, target_doc=None): } } }, target_doc) - + return doclist + + @frappe.whitelist() def set_multiple_status(names, status): names = json.loads(names) @@ -284,4 +298,4 @@ def auto_close_opportunity(): doc.status = "Closed" doc.flags.ignore_permissions = True doc.flags.ignore_mandatory = True - doc.save() \ No newline at end of file + doc.save() From 764bb30d2da4e09b4313029d467e990f4777517e Mon Sep 17 00:00:00 2001 From: AravindPranera Date: Thu, 24 Aug 2017 18:34:45 +0530 Subject: [PATCH 2/8] Fetching Opportunity items into Request for Quotation --- .../request_for_quotation.js | 135 +++--------------- 1 file changed, 23 insertions(+), 112 deletions(-) diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js index 8509d77e20..ef8f7cb3b8 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js @@ -44,100 +44,13 @@ frappe.ui.form.on("Request for Quotation",{ freeze: true, args: { rfq_name: frm.doc.name - }, - callback: function(r){ - frm.reload_doc(); } }); }); - } + } }, - get_suppliers_button: function (frm) { - var doc = frm.doc; - var dialog = new frappe.ui.Dialog({ - title: __("Get Suppliers"), - fields: [ - { "fieldtype": "Select", "label": __("Get Suppliers By"), - "fieldname": "search_type", - "options": "Tag\nSupplier Type", "reqd": 1 }, - { "fieldtype": "Link", "label": __("Supplier Type"), - "fieldname": "supplier_type", - "options": "Supplier Type", "reqd": 0, - "depends_on": "eval:doc.search_type == 'Supplier Type'"}, - { "fieldtype": "Data", "label": __("Tag"), - "fieldname": "tag", "reqd": 0, - "depends_on": "eval:doc.search_type == 'Tag'" }, - { "fieldtype": "Button", "label": __("Add All Suppliers"), - "fieldname": "add_suppliers", "cssClass": "btn-primary"}, - ] - }); - - dialog.fields_dict.add_suppliers.$input.click(function() { - var args = dialog.get_values(); - if(!args) return; - dialog.hide(); - - //Remove blanks - for (var j = 0; j < frm.doc.suppliers.length; j++) { - if(!frm.doc.suppliers[j].hasOwnProperty("supplier")) { - frm.get_field("suppliers").grid.grid_rows[j].remove(); - } - } - - function load_suppliers(r) { - if(r.message) { - for (var i = 0; i < r.message.length; i++) { - var exists = false; - if (r.message[i].constructor === Array){ - var supplier = r.message[i][0]; - } else { - var supplier = r.message[i].name; - } - - for (var j = 0; j < doc.suppliers.length;j++) { - if (supplier === doc.suppliers[j].supplier) { - exists = true; - } - } - if(!exists) { - var d = frm.add_child('suppliers'); - d.supplier = supplier; - frm.script_manager.trigger("supplier", d.doctype, d.name); - } - } - } - frm.refresh_field("suppliers"); - } - - if (args.search_type === "Tag" && args.tag) { - return frappe.call({ - type: "GET", - method: "frappe.desk.tags.get_tagged_docs", - args: { - "doctype": "Supplier", - "tag": args.tag - }, - callback: load_suppliers - }); - } else if (args.supplier_type) { - return frappe.call({ - method: "frappe.client.get_list", - args: { - doctype: "Supplier", - order_by: "name", - fields: ["name"], - filters: [["Supplier", "supplier_type", "=", args.supplier_type]] - - }, - callback: load_suppliers - }); - } - }); - dialog.show(); - - }, make_suppplier_quotation: function(frm) { var doc = frm.doc; var dialog = new frappe.ui.Dialog({ @@ -206,29 +119,6 @@ frappe.ui.form.on("Request for Quotation Supplier",{ if(!w) { frappe.msgprint(__("Please enable pop-ups")); return; } - }, - no_quote: function(frm, cdt, cdn) { - var d = locals[cdt][cdn]; - if (d.no_quote) { - if (d.quote_status != __('Received')) { - frappe.model.set_value(cdt, cdn, 'quote_status', 'No Quote'); - } else { - frappe.msgprint(__("Cannot set a received RFQ to No Quote")); - frappe.model.set_value(cdt, cdn, 'no_quote', 0); - } - } else { - d.quote_status = __('Pending'); - frm.call({ - method:"update_rfq_supplier_status", - doc: frm.doc, - args: { - sup_name: d.supplier - }, - callback: function(r) { - frm.refresh_field("suppliers"); - } - }); - } } }) @@ -254,6 +144,27 @@ erpnext.buying.RequestforQuotationController = erpnext.buying.BuyingController.e } }) }, __("Get items from")); + + // Get items from Opportunity + this.frm.add_custom_button(__('Opportunity'), + function() { + erpnext.utils.map_current_doc({ + method: "erpnext.crm.doctype.opportunity.opportunity.make_request_for_quotation", + source_doctype: "Opportunity", + target: me.frm, + setters: { + company: me.frm.doc.company + }, + get_query_filters: { + enquiry_type: "Sales" + } + }) + }, __("Get items from")); + + + + + // Get items from open Material Requests based on supplier this.frm.add_custom_button(__('Possible Supplier'), function() { // Create a dialog window for the user to pick their supplier @@ -294,7 +205,7 @@ erpnext.buying.RequestforQuotationController = erpnext.buying.BuyingController.e }, __("Get items from")); } - }, + }, calculate_taxes_and_totals: function() { return; From c73383c34c4843746abf02505af73481c3ae1bc3 Mon Sep 17 00:00:00 2001 From: AravindPranera Date: Fri, 15 Sep 2017 10:34:21 +0530 Subject: [PATCH 3/8] Trailing whitespace in Line 207 and 276 --- erpnext/crm/doctype/opportunity/opportunity.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py index da0ade7043..7b052a6759 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.py +++ b/erpnext/crm/doctype/opportunity/opportunity.py @@ -187,7 +187,7 @@ def get_item_details(item_code): @frappe.whitelist() def make_request_for_quotation(source_name, target_doc=None): - doclist = get_mapped_doc("Opportunity", source_name, { + doclist = get_mapped_doc("Opportunity", source_name, { "Opportunity": { "doctype": "Request for Quotation", "validation": { @@ -204,7 +204,7 @@ def make_request_for_quotation(source_name, target_doc=None): } }, target_doc) - return doclist + return doclist @frappe.whitelist() def make_quotation(source_name, target_doc=None): @@ -258,7 +258,6 @@ def make_quotation(source_name, target_doc=None): @frappe.whitelist() def make_supplier_quotation(source_name, target_doc=None): - frappe.msgprint("python"); doclist = get_mapped_doc("Opportunity", source_name, { "Opportunity": { "doctype": "Supplier Quotation", @@ -276,8 +275,6 @@ def make_supplier_quotation(source_name, target_doc=None): return doclist - - @frappe.whitelist() def set_multiple_status(names, status): names = json.loads(names) From 2c1f44ecfa22890c2449ffc9ac2a2fc609d0a6ea Mon Sep 17 00:00:00 2001 From: AravindPranera Date: Fri, 15 Sep 2017 10:57:23 +0530 Subject: [PATCH 4/8] Trailing space removed in line 275 --- erpnext/crm/doctype/opportunity/opportunity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py index 7b052a6759..944eb56900 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.py +++ b/erpnext/crm/doctype/opportunity/opportunity.py @@ -273,7 +273,7 @@ def make_supplier_quotation(source_name, target_doc=None): } }, target_doc) - return doclist + return doclist @frappe.whitelist() def set_multiple_status(names, status): From 27bbb561d28a379ee7f4e9beb16446a25cb55e41 Mon Sep 17 00:00:00 2001 From: AravindPranera Date: Fri, 15 Sep 2017 11:04:14 +0530 Subject: [PATCH 5/8] removed whitespace --- erpnext/crm/doctype/opportunity/opportunity.py | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py index 944eb56900..4e6047760c 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.py +++ b/erpnext/crm/doctype/opportunity/opportunity.py @@ -272,7 +272,6 @@ def make_supplier_quotation(source_name, target_doc=None): } } }, target_doc) - return doclist @frappe.whitelist() From 1276893550b80420e2bc49e64e090d7aa2c5cc25 Mon Sep 17 00:00:00 2001 From: AravindPranera Date: Mon, 18 Sep 2017 17:30:20 +0530 Subject: [PATCH 6/8] Files added with all functions --- .../request_for_quotation.js | 126 ++++++++++++++++-- 1 file changed, 115 insertions(+), 11 deletions(-) diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js index ef8f7cb3b8..3801141fb9 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js @@ -12,11 +12,11 @@ frappe.ui.form.on("Request for Quotation",{ 'Supplier Quotation': 'Supplier Quotation' } - frm.fields_dict["suppliers"].grid.get_field("contact").get_query = function(doc, cdt, cdn){ - var d =locals[cdt][cdn]; + frm.fields_dict["suppliers"].grid.get_field("contact").get_query = function(doc, cdt, cdn) { + let d = locals[cdt][cdn]; return { query: "erpnext.buying.doctype.request_for_quotation.request_for_quotation.get_supplier_contacts", - filters: {'supplier': doc.supplier} + filters: {'supplier': d.supplier} } } }, @@ -44,13 +44,100 @@ frappe.ui.form.on("Request for Quotation",{ freeze: true, args: { rfq_name: frm.doc.name + }, + callback: function(r){ + frm.reload_doc(); } }); }); - } + } }, + get_suppliers_button: function (frm) { + var doc = frm.doc; + var dialog = new frappe.ui.Dialog({ + title: __("Get Suppliers"), + fields: [ + { "fieldtype": "Select", "label": __("Get Suppliers By"), + "fieldname": "search_type", + "options": "Tag\nSupplier Type", "reqd": 1 }, + { "fieldtype": "Link", "label": __("Supplier Type"), + "fieldname": "supplier_type", + "options": "Supplier Type", "reqd": 0, + "depends_on": "eval:doc.search_type == 'Supplier Type'"}, + { "fieldtype": "Data", "label": __("Tag"), + "fieldname": "tag", "reqd": 0, + "depends_on": "eval:doc.search_type == 'Tag'" }, + { "fieldtype": "Button", "label": __("Add All Suppliers"), + "fieldname": "add_suppliers", "cssClass": "btn-primary"}, + ] + }); + + dialog.fields_dict.add_suppliers.$input.click(function() { + var args = dialog.get_values(); + if(!args) return; + dialog.hide(); + + //Remove blanks + for (var j = 0; j < frm.doc.suppliers.length; j++) { + if(!frm.doc.suppliers[j].hasOwnProperty("supplier")) { + frm.get_field("suppliers").grid.grid_rows[j].remove(); + } + } + + function load_suppliers(r) { + if(r.message) { + for (var i = 0; i < r.message.length; i++) { + var exists = false; + if (r.message[i].constructor === Array){ + var supplier = r.message[i][0]; + } else { + var supplier = r.message[i].name; + } + + for (var j = 0; j < doc.suppliers.length;j++) { + if (supplier === doc.suppliers[j].supplier) { + exists = true; + } + } + if(!exists) { + var d = frm.add_child('suppliers'); + d.supplier = supplier; + frm.script_manager.trigger("supplier", d.doctype, d.name); + } + } + } + frm.refresh_field("suppliers"); + } + + if (args.search_type === "Tag" && args.tag) { + return frappe.call({ + type: "GET", + method: "frappe.desk.tags.get_tagged_docs", + args: { + "doctype": "Supplier", + "tag": args.tag + }, + callback: load_suppliers + }); + } else if (args.supplier_type) { + return frappe.call({ + method: "frappe.client.get_list", + args: { + doctype: "Supplier", + order_by: "name", + fields: ["name"], + filters: [["Supplier", "supplier_type", "=", args.supplier_type]] + + }, + callback: load_suppliers + }); + } + }); + dialog.show(); + + }, make_suppplier_quotation: function(frm) { var doc = frm.doc; var dialog = new frappe.ui.Dialog({ @@ -119,6 +206,29 @@ frappe.ui.form.on("Request for Quotation Supplier",{ if(!w) { frappe.msgprint(__("Please enable pop-ups")); return; } + }, + no_quote: function(frm, cdt, cdn) { + var d = locals[cdt][cdn]; + if (d.no_quote) { + if (d.quote_status != __('Received')) { + frappe.model.set_value(cdt, cdn, 'quote_status', 'No Quote'); + } else { + frappe.msgprint(__("Cannot set a received RFQ to No Quote")); + frappe.model.set_value(cdt, cdn, 'no_quote', 0); + } + } else { + d.quote_status = __('Pending'); + frm.call({ + method:"update_rfq_supplier_status", + doc: frm.doc, + args: { + sup_name: d.supplier + }, + callback: function(r) { + frm.refresh_field("suppliers"); + } + }); + } } }) @@ -144,7 +254,6 @@ erpnext.buying.RequestforQuotationController = erpnext.buying.BuyingController.e } }) }, __("Get items from")); - // Get items from Opportunity this.frm.add_custom_button(__('Opportunity'), function() { @@ -160,11 +269,6 @@ erpnext.buying.RequestforQuotationController = erpnext.buying.BuyingController.e } }) }, __("Get items from")); - - - - - // Get items from open Material Requests based on supplier this.frm.add_custom_button(__('Possible Supplier'), function() { // Create a dialog window for the user to pick their supplier @@ -205,7 +309,7 @@ erpnext.buying.RequestforQuotationController = erpnext.buying.BuyingController.e }, __("Get items from")); } - }, + }, calculate_taxes_and_totals: function() { return; From cb6774e373c2951c6a6a7fd1e6012ec8edecd222 Mon Sep 17 00:00:00 2001 From: AravindPranera Date: Mon, 18 Sep 2017 17:37:37 +0530 Subject: [PATCH 7/8] Files added with all functions --- .../crm/doctype/opportunity/opportunity.py | 65 +++++++++++-------- 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py index 4e6047760c..31f74a6941 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(""" @@ -185,27 +193,6 @@ def get_item_details(item_code): 'brand': item and item[0]['brand'] or '' } -@frappe.whitelist() -def make_request_for_quotation(source_name, target_doc=None): - doclist = get_mapped_doc("Opportunity", source_name, { - "Opportunity": { - "doctype": "Request for Quotation", - "validation": { - "enquiry_type": ["=", "Sales"] - } - }, - "Opportunity Item": { - "doctype": "Request for Quotation Item", - "field_map": [ - ["name", "opportunity_item"], - ["parent", "opportunity"], - ["uom", "uom"] - ] - } - }, target_doc) - - return doclist - @frappe.whitelist() def make_quotation(source_name, target_doc=None): def set_missing_values(source, target): @@ -233,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": { @@ -256,6 +245,27 @@ def make_quotation(source_name, target_doc=None): return doclist + @frappe.whitelist() + def make_request_for_quotation(source_name, target_doc=None): + doclist = get_mapped_doc("Opportunity", source_name, { + "Opportunity": { + "doctype": "Request for Quotation", + "validation": { + "enquiry_type": ["=", "Sales"] + } + }, + "Opportunity Item": { + "doctype": "Request for Quotation Item", + "field_map": [ + ["name", "opportunity_item"], + ["parent", "opportunity"], + ["uom", "uom"] + ] + } + }, target_doc) + + return doclist + @frappe.whitelist() def make_supplier_quotation(source_name, target_doc=None): doclist = get_mapped_doc("Opportunity", source_name, { @@ -272,7 +282,8 @@ def make_supplier_quotation(source_name, target_doc=None): } } }, target_doc) - return doclist + + return doclist @frappe.whitelist() def set_multiple_status(names, status): From 6d78f7b862cb018571835f2ffbbc9e124ec82a10 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 21 Sep 2017 15:51:42 +0530 Subject: [PATCH 8/8] Fixed indentation --- .../crm/doctype/opportunity/opportunity.py | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py index 31f74a6941..4251cae954 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.py +++ b/erpnext/crm/doctype/opportunity/opportunity.py @@ -245,26 +245,26 @@ def make_quotation(source_name, target_doc=None): return doclist - @frappe.whitelist() - def make_request_for_quotation(source_name, target_doc=None): - doclist = get_mapped_doc("Opportunity", source_name, { - "Opportunity": { - "doctype": "Request for Quotation", - "validation": { - "enquiry_type": ["=", "Sales"] - } - }, - "Opportunity Item": { - "doctype": "Request for Quotation Item", - "field_map": [ - ["name", "opportunity_item"], - ["parent", "opportunity"], - ["uom", "uom"] - ] - } - }, target_doc) - - return doclist +@frappe.whitelist() +def make_request_for_quotation(source_name, target_doc=None): + doclist = get_mapped_doc("Opportunity", source_name, { + "Opportunity": { + "doctype": "Request for Quotation", + "validation": { + "enquiry_type": ["=", "Sales"] + } + }, + "Opportunity Item": { + "doctype": "Request for Quotation Item", + "field_map": [ + ["name", "opportunity_item"], + ["parent", "opportunity"], + ["uom", "uom"] + ] + } + }, target_doc) + + return doclist @frappe.whitelist() def make_supplier_quotation(source_name, target_doc=None):