From 68bac20198bea634c4aca55e554b89d3c834da87 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 07:33:02 +0000 Subject: [PATCH] Merge pull request #53095 from frappe/mergify/bp/version-15-hotfix/pr-52838 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: correct fields being updated on material request and purchase or… (backport #52838) --- erpnext/patches.txt | 1 + ...ty_and_requested_qty_based_on_mr_and_po.py | 33 +++++++++++++ .../sales_order_item/sales_order_item.json | 47 ++++++++++++++++++- .../sales_order_item/sales_order_item.py | 1 + .../material_request/material_request.py | 4 +- 5 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 erpnext/patches/v16_0/update_order_qty_and_requested_qty_based_on_mr_and_po.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 9e36329daa4..afb1201087a 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -432,3 +432,4 @@ erpnext.patches.v15_0.create_accounting_dimensions_in_advance_taxes_and_charges erpnext.patches.v16_0.set_ordered_qty_in_quotation_item erpnext.patches.v15_0.replace_http_with_https_in_sales_partner erpnext.patches.v16_0.add_portal_redirects +erpnext.patches.v16_0.update_order_qty_and_requested_qty_based_on_mr_and_po diff --git a/erpnext/patches/v16_0/update_order_qty_and_requested_qty_based_on_mr_and_po.py b/erpnext/patches/v16_0/update_order_qty_and_requested_qty_based_on_mr_and_po.py new file mode 100644 index 00000000000..59a84ec11d0 --- /dev/null +++ b/erpnext/patches/v16_0/update_order_qty_and_requested_qty_based_on_mr_and_po.py @@ -0,0 +1,33 @@ +import frappe +from frappe.query_builder import DocType +from frappe.query_builder.functions import Sum + + +def execute(): + PurchaseOrderItem = DocType("Purchase Order Item") + MaterialRequestItem = DocType("Material Request Item") + + poi_query = ( + frappe.qb.from_(PurchaseOrderItem) + .select(PurchaseOrderItem.sales_order_item, Sum(PurchaseOrderItem.stock_qty)) + .where(PurchaseOrderItem.sales_order_item.isnotnull() & PurchaseOrderItem.docstatus == 1) + .groupby(PurchaseOrderItem.sales_order_item) + ) + + mri_query = ( + frappe.qb.from_(MaterialRequestItem) + .select(MaterialRequestItem.sales_order_item, Sum(MaterialRequestItem.stock_qty)) + .where(MaterialRequestItem.sales_order_item.isnotnull() & MaterialRequestItem.docstatus == 1) + .groupby(MaterialRequestItem.sales_order_item) + ) + + poi_data = poi_query.run() + mri_data = mri_query.run() + + updates_against_poi = {data[0]: {"ordered_qty": data[1]} for data in poi_data} + updates_against_mri = {data[0]: {"requested_qty": data[1], "ordered_qty": 0} for data in mri_data} + + frappe.db.auto_commit_on_many_writes = 1 + frappe.db.bulk_update("Sales Order Item", updates_against_mri) + frappe.db.bulk_update("Sales Order Item", updates_against_poi) + frappe.db.auto_commit_on_many_writes = 0 diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.json b/erpnext/selling/doctype/sales_order_item/sales_order_item.json index 7edb81de48b..b8ca7343a4d 100644 --- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json +++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json @@ -90,6 +90,7 @@ "ordered_qty", "planned_qty", "production_plan_qty", + "requested_qty", "column_break_69", "work_order_qty", "delivered_qty", @@ -966,12 +967,56 @@ "label": "Project", "options": "Project", "search_index": 1 + }, + { + "fieldname": "sales_order_schedule_section", + "fieldtype": "Section Break", + "label": "Sales Order Schedule" + }, + { + "fieldname": "add_schedule", + "fieldtype": "Button", + "label": "Add Schedule" + }, + { + "allow_on_submit": 1, + "default": "0", + "depends_on": "eval:parent.is_subcontracted", + "fieldname": "subcontracted_qty", + "fieldtype": "Float", + "label": "Subcontracted Quantity", + "no_copy": 1, + "non_negative": 1, + "read_only": 1 + }, + { + "depends_on": "eval:parent.is_subcontracted", + "fieldname": "fg_item", + "fieldtype": "Link", + "label": "Finished Good", + "mandatory_depends_on": "eval:parent.is_subcontracted", + "options": "Item" + }, + { + "depends_on": "eval:parent.is_subcontracted", + "fieldname": "fg_item_qty", + "fieldtype": "Float", + "label": "Finished Good Qty", + "mandatory_depends_on": "eval:parent.is_subcontracted" + }, + { + "fieldname": "requested_qty", + "fieldtype": "Float", + "label": "Requested Qty", + "no_copy": 1, + "print_hide": 1, + "read_only": 1 } ], "idx": 1, "istable": 1, "links": [], - "modified": "2026-02-20 16:39:00.200328", + "modified": "2026-02-21 16:39:00.200328", "modified_by": "Administrator", "module": "Selling", "name": "Sales Order Item", diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.py b/erpnext/selling/doctype/sales_order_item/sales_order_item.py index 731cff665da..07a81c81f02 100644 --- a/erpnext/selling/doctype/sales_order_item/sales_order_item.py +++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.py @@ -78,6 +78,7 @@ class SalesOrderItem(Document): quotation_item: DF.Data | None rate: DF.Currency rate_with_margin: DF.Currency + requested_qty: DF.Float reserve_stock: DF.Check returned_qty: DF.Float stock_qty: DF.Float diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index b9aa7065c5d..068daeae4f1 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -81,7 +81,7 @@ class MaterialRequest(BuyingController): { "source_dt": "Material Request Item", "target_dt": "Sales Order Item", - "target_field": "ordered_qty", + "target_field": "requested_qty", "target_parent_dt": "Sales Order", "target_parent_field": "", "join_field": "sales_order_item", @@ -248,6 +248,8 @@ class MaterialRequest(BuyingController): def on_cancel(self): self.update_requested_qty_in_production_plan() self.update_requested_qty() + if self.material_request_type == "Purchase": + self.update_prevdoc_status() def get_mr_items_ordered_qty(self, mr_items): mr_items_ordered_qty = {}