From db002708958dc88b09b05c1d7deea16687a1b345 Mon Sep 17 00:00:00 2001 From: Marica Date: Mon, 17 Feb 2020 15:58:08 +0530 Subject: [PATCH] feat: Added popup to 'Get Items from Open Material Requests' in Purchase Order (#20371) * feat: Added popup to 'Get Items from Open Material Requests' in Purchase Order * fix: Query with filters, UX enhancements and cleanup --- .../doctype/purchase_order/purchase_order.js | 12 ++- .../purchase_order/purchase_order.json | 3 +- erpnext/public/js/utils.js | 17 +++- .../material_request/material_request.py | 81 +++++++++++-------- 4 files changed, 75 insertions(+), 38 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js index 7b1f1354d79..a3264a4c0f8 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order.js @@ -180,10 +180,20 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend( get_items_from_open_material_requests: function() { erpnext.utils.map_current_doc({ method: "erpnext.stock.doctype.material_request.material_request.make_purchase_order_based_on_supplier", + args: { + supplier: this.frm.doc.supplier + }, + source_doctype: "Material Request", source_name: this.frm.doc.supplier, + target: this.frm, + setters: { + company: me.frm.doc.company + }, get_query_filters: { docstatus: ["!=", 2], - } + supplier: this.frm.doc.supplier + }, + get_query_method: "erpnext.stock.doctype.material_request.material_request.get_material_requests_based_on_supplier" }); }, diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json index d82e128735e..4d836903911 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.json +++ b/erpnext/buying/doctype/purchase_order/purchase_order.json @@ -12,8 +12,8 @@ "supplier", "get_items_from_open_material_requests", "supplier_name", - "company", "column_break1", + "company", "transaction_date", "schedule_date", "order_confirmation_no", @@ -170,6 +170,7 @@ "search_index": 1 }, { + "description": "Fetch items based on Default Supplier.", "depends_on": "eval:doc.supplier && doc.docstatus===0 && (!(doc.items && doc.items.length) || (doc.items.length==1 && !doc.items[0].item_code))", "fieldname": "get_items_from_open_material_requests", "fieldtype": "Button", diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 3f444f83879..35dc8427aa9 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -514,9 +514,18 @@ erpnext.utils.update_child_items = function(opts) { } erpnext.utils.map_current_doc = function(opts) { - if(opts.get_query_filters) { - opts.get_query = function() { - return {filters: opts.get_query_filters}; + let query_args = {}; + if (opts.get_query_filters) { + query_args.filters = opts.get_query_filters; + } + + if (opts.get_query_method) { + query_args.query = opts.get_query_method; + } + + if (query_args.filters || query_args.query) { + opts.get_query = () => { + return query_args; } } var _map = function() { @@ -582,7 +591,7 @@ erpnext.utils.map_current_doc = function(opts) { "method": opts.method, "source_names": opts.source_name, "target_doc": cur_frm.doc, - 'args': opts.args + "args": opts.args }, callback: function(r) { if(!r.exc) { diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index 941f9041023..45428470167 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -6,6 +6,7 @@ from __future__ import unicode_literals import frappe +import json from frappe.utils import cstr, flt, getdate, new_line_sep, nowdate, add_days from frappe import msgprint, _ @@ -329,17 +330,13 @@ def make_request_for_quotation(source_name, target_doc=None): return doclist @frappe.whitelist() -def make_purchase_order_based_on_supplier(source_name, target_doc=None): - if target_doc: - if isinstance(target_doc, string_types): - import json - target_doc = frappe.get_doc(json.loads(target_doc)) - target_doc.set("items", []) +def make_purchase_order_based_on_supplier(source_name, target_doc=None, args=None): + mr = source_name - material_requests, supplier_items = get_material_requests_based_on_supplier(source_name) + supplier_items = get_items_based_on_default_supplier(args.get("supplier")) def postprocess(source, target_doc): - target_doc.supplier = source_name + target_doc.supplier = args.get("supplier") if getdate(target_doc.schedule_date) < getdate(nowdate()): target_doc.schedule_date = None target_doc.set("items", [d for d in target_doc.get("items") @@ -347,44 +344,64 @@ def make_purchase_order_based_on_supplier(source_name, target_doc=None): set_missing_values(source, target_doc) - for mr in material_requests: - target_doc = get_mapped_doc("Material Request", mr, { - "Material Request": { - "doctype": "Purchase Order", - }, - "Material Request Item": { - "doctype": "Purchase Order Item", - "field_map": [ - ["name", "material_request_item"], - ["parent", "material_request"], - ["uom", "stock_uom"], - ["uom", "uom"] - ], - "postprocess": update_item, - "condition": lambda doc: doc.ordered_qty < doc.qty - } - }, target_doc, postprocess) + target_doc = get_mapped_doc("Material Request", mr, { + "Material Request": { + "doctype": "Purchase Order", + }, + "Material Request Item": { + "doctype": "Purchase Order Item", + "field_map": [ + ["name", "material_request_item"], + ["parent", "material_request"], + ["uom", "stock_uom"], + ["uom", "uom"] + ], + "postprocess": update_item, + "condition": lambda doc: doc.ordered_qty < doc.qty + } + }, target_doc, postprocess) return target_doc -def get_material_requests_based_on_supplier(supplier): +@frappe.whitelist() +def get_items_based_on_default_supplier(supplier): supplier_items = [d.parent for d in frappe.db.get_all("Item Default", - {"default_supplier": supplier}, 'parent')] + {"default_supplier": supplier, "parenttype": "Item"}, 'parent')] + + return supplier_items + +@frappe.whitelist() +def get_material_requests_based_on_supplier(doctype, txt, searchfield, start, page_len, filters): + conditions = "" + if txt: + conditions += "and mr.name like '%%"+txt+"%%' " + + if filters.get("transaction_date"): + date = filters.get("transaction_date")[1] + conditions += "and mr.transaction_date between '{0}' and '{1}' ".format(date[0], date[1]) + + supplier = filters.get("supplier") + supplier_items = get_items_based_on_default_supplier(supplier) + if not supplier_items: frappe.throw(_("{0} is not the default supplier for any items.").format(supplier)) - material_requests = frappe.db.sql_list("""select distinct mr.name + material_requests = frappe.db.sql("""select distinct mr.name, transaction_date,company from `tabMaterial Request` mr, `tabMaterial Request Item` mr_item where mr.name = mr_item.parent - and mr_item.item_code in (%s) + and mr_item.item_code in ({0}) and mr.material_request_type = 'Purchase' and mr.per_ordered < 99.99 and mr.docstatus = 1 and mr.status != 'Stopped' - order by mr_item.item_code ASC""" % ', '.join(['%s']*len(supplier_items)), - tuple(supplier_items)) + and mr.company = '{1}' + {2} + order by mr_item.item_code ASC + limit {3} offset {4} """ \ + .format(', '.join(['%s']*len(supplier_items)), filters.get("company"), conditions, page_len, start), + tuple(supplier_items), as_dict=1) - return material_requests, supplier_items + return material_requests def get_default_supplier_query(doctype, txt, searchfield, start, page_len, filters): doc = frappe.get_doc("Material Request", filters.get("doc"))