From 94cacb60de00bda141537eb59d3d775004576a3d Mon Sep 17 00:00:00 2001 From: marination Date: Mon, 30 Jan 2023 13:54:30 +0530 Subject: [PATCH] feat: Filter rows to be mapped on server side mapping function - Pass dialog selections to `make_sales_order` - Map either original item or its alternative depending on mapping - Only qty check for simple rows (without alternatives and not an alternative itself) --- .../selling/doctype/quotation/quotation.js | 20 +++++++------ .../selling/doctype/quotation/quotation.py | 29 ++++++++++++++++++- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/erpnext/selling/doctype/quotation/quotation.js b/erpnext/selling/doctype/quotation/quotation.js index 6f75673a8e5..0ea424f1b43 100644 --- a/erpnext/selling/doctype/quotation/quotation.js +++ b/erpnext/selling/doctype/quotation/quotation.js @@ -233,7 +233,9 @@ erpnext.selling.QuotationController = class QuotationController extends erpnext. show_alternative_item_dialog() { // Create a `{original item: [alternate items]}` map - const item_alt_map = {}; + var me = this; + let item_alt_map = {}; + this.frm.doc.items.filter( (item) => item.is_alternative ).forEach((item) => @@ -286,7 +288,14 @@ erpnext.selling.QuotationController = class QuotationController extends erpnext. }, ], primary_action: function() { - this.hide(); + frappe.model.open_mapped_doc({ + method: "erpnext.selling.doctype.quotation.quotation.make_sales_order", + frm: me.frm, + args: { + mapping: dialog.get_value("alternative_items") + } + }); + dialog.hide(); }, primary_action_label: __('Continue') }); @@ -297,13 +306,6 @@ erpnext.selling.QuotationController = class QuotationController extends erpnext. cur_frm.script_manager.make(erpnext.selling.QuotationController); -cur_frm.cscript['Make Sales Order'] = function() { - frappe.model.open_mapped_doc({ - method: "erpnext.selling.doctype.quotation.quotation.make_sales_order", - frm: cur_frm - }) -} - frappe.ui.form.on("Quotation Item", "items_on_form_rendered", "packed_items_on_form_rendered", function(frm, cdt, cdn) { // enable tax_amount field if Actual }) diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index 6836d56647f..d4ae66e53b9 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -210,6 +210,10 @@ def _make_sales_order(source_name, target_doc=None, ignore_permissions=False): ) ) + alternative_map = { + x.get("original_item") : x.get("alternative_item") for x in frappe.flags.get("args", {}).get("mapping", []) + } + def set_missing_values(source, target): if customer: target.customer = customer.name @@ -233,6 +237,29 @@ def _make_sales_order(source_name, target_doc=None, ignore_permissions=False): target.blanket_order = obj.blanket_order target.blanket_order_rate = obj.blanket_order_rate + def can_map_row(item) -> bool: + """ + Row mapping from Quotation to Sales order: + 1. Simple row: Map if adequate qty + 2. Has Alternative Item: Map if no alternative was selected against original item and #1 + 3. Is Alternative Item: Map if alternative was selected against original item and #1 + """ + has_qty = item.qty > 0 + + has_alternative = item.item_code in alternative_map + is_alternative = item.is_alternative + + if not alternative_map or not (is_alternative or has_alternative): + # No alternative items in doc or current row is a simple item (without alternatives) + return has_qty + + if is_alternative: + is_selected = alternative_map.get(item.alternative_to) == item.item_code + else: + is_selected = alternative_map.get(item.item_code) is None + return is_selected and has_qty + + doclist = get_mapped_doc( "Quotation", source_name, @@ -242,7 +269,7 @@ def _make_sales_order(source_name, target_doc=None, ignore_permissions=False): "doctype": "Sales Order Item", "field_map": {"parent": "prevdoc_docname", "name": "quotation_item"}, "postprocess": update_item, - "condition": lambda doc: doc.qty > 0, + "condition": can_map_row, }, "Sales Taxes and Charges": {"doctype": "Sales Taxes and Charges", "add_if_empty": True}, "Sales Team": {"doctype": "Sales Team", "add_if_empty": True},