From 96dc408484ee846c2a6bbb0ac545a47455545685 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Fri, 17 Jul 2026 16:52:13 +0530 Subject: [PATCH 1/4] fix: validate buying price list on material request and update item rates on change --- .../material_request/material_request.js | 9 +++-- .../material_request/material_request.py | 38 ++++++++++++++++++- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js index 7642133fe3e..1a868dc546a 100644 --- a/erpnext/stock/doctype/material_request/material_request.js +++ b/erpnext/stock/doctype/material_request/material_request.js @@ -92,7 +92,10 @@ frappe.ui.form.on("Material Request", { erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype); if (!frm.doc.buying_price_list) { - frm.doc.buying_price_list = frappe.defaults.get_default("buying_price_list"); + const buying_price_list = frappe.defaults.get_default("buying_price_list"); + if (frappe.has_permission("Price List", "read", buying_price_list)) { + frm.set_value("buying_price_list", buying_price_list); + } } }, @@ -271,9 +274,7 @@ frappe.ui.form.on("Material Request", { from_warehouse: item.from_warehouse, warehouse: item.warehouse, doctype: frm.doc.doctype, - buying_price_list: frm.doc.buying_price_list - ? frm.doc.buying_price_list - : frappe.defaults.get_default("buying_price_list"), + buying_price_list: frm.doc.buying_price_list, currency: frappe.defaults.get_default("Currency"), name: frm.doc.name, qty: item.qty || 1, diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index ffd37d91df4..ea4ccb20a36 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -19,6 +19,7 @@ from erpnext.buying.utils import check_on_hold_or_closed_status, validate_for_it from erpnext.controllers.buying_controller import BuyingController from erpnext.manufacturing.doctype.work_order.work_order import get_item_details from erpnext.stock.doctype.item.item import get_item_defaults +from erpnext.stock.get_item_details import get_price_list_rate_for from erpnext.stock.stock_balance import get_indented_qty, update_bin_qty form_grid_templates = {"items": "templates/form_grid/material_request_grid.html"} @@ -169,8 +170,43 @@ class MaterialRequest(BuyingController): self.reset_default_field_value("set_warehouse", "items", "warehouse") self.reset_default_field_value("set_from_warehouse", "items", "from_warehouse") + if self.buying_price_list and not frappe.get_value("Price List", self.buying_price_list, "buying"): + self.buying_price_list = None + if not self.buying_price_list: - self.buying_price_list = frappe.defaults.get_defaults().buying_price_list + buying_price_list = frappe.defaults.get_defaults().buying_price_list + if frappe.has_permission("Price List", "read", buying_price_list): + self.buying_price_list = buying_price_list + + def on_update(self): + if self.buying_price_list and self.has_value_changed("buying_price_list"): + self.update_item_rates() + + def update_item_rates(self): + price_not_uom_dependent = frappe.get_value( + "Price List", self.buying_price_list, "price_not_uom_dependent" + ) + for item in self.items: + rate = get_price_list_rate_for( + frappe._dict( + { + "price_list": self.buying_price_list, + "uom": item.uom, + "transaction_date": self.transaction_date, + "qty": item.qty, + "stock_uom": item.stock_uom, + "price_not_uom_dependent": price_not_uom_dependent, + } + ), + item.item_code, + ) + item.db_set({"rate": flt(rate), "amount": flt(flt(rate) * item.qty, item.precision("amount"))}) + frappe.msgprint( + _("Item rates have been updated based on the selected Buying Price List {0}").format( + self.buying_price_list + ), + alert=True, + ) def before_update_after_submit(self): self.validate_schedule_date() From 302cbbe5d864f72e4e1556b59b877fbb219739f4 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Fri, 17 Jul 2026 18:24:15 +0530 Subject: [PATCH 2/4] fix: pass ctx keys get_price_list_rate_for reads, skip rate update on insert update_item_rates passed price_not_uom_dependent, a key get_price_list_rate_for never reads, and omitted conversion_factor, so a stock-UOM price was never converted to the row UOM. The function's (historically misnamed) price_list_uom_dependant ctx key carries the Price List's price_not_uom_dependent value: truthy returns the found rate as-is, falsy multiplies by conversion_factor. Also guard on_update with is_new(): has_value_changed returns True when there is no doc_before_save, so every first save re-wrote item rates. --- erpnext/stock/doctype/material_request/material_request.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index ea4ccb20a36..550c562da4a 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -179,7 +179,7 @@ class MaterialRequest(BuyingController): self.buying_price_list = buying_price_list def on_update(self): - if self.buying_price_list and self.has_value_changed("buying_price_list"): + if not self.is_new() and self.buying_price_list and self.has_value_changed("buying_price_list"): self.update_item_rates() def update_item_rates(self): @@ -195,7 +195,8 @@ class MaterialRequest(BuyingController): "transaction_date": self.transaction_date, "qty": item.qty, "stock_uom": item.stock_uom, - "price_not_uom_dependent": price_not_uom_dependent, + "conversion_factor": item.conversion_factor, + "price_list_uom_dependant": price_not_uom_dependent, } ), item.item_code, From 74e9718871dcd34f8abbccafc5f22e30d50b235e Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Fri, 17 Jul 2026 21:23:49 +0530 Subject: [PATCH 3/4] fix: dont overwrite rate with 0 if not found --- erpnext/stock/doctype/material_request/material_request.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index 550c562da4a..7ba8dd27571 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -201,7 +201,9 @@ class MaterialRequest(BuyingController): ), item.item_code, ) - item.db_set({"rate": flt(rate), "amount": flt(flt(rate) * item.qty, item.precision("amount"))}) + if rate is not None: + item.db_set({"rate": flt(rate), "amount": flt(flt(rate) * item.qty, item.precision("amount"))}) + frappe.msgprint( _("Item rates have been updated based on the selected Buying Price List {0}").format( self.buying_price_list From 1fabf78dea0bc68ded4347bd783e5bb20235c649 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Fri, 17 Jul 2026 21:24:40 +0530 Subject: [PATCH 4/4] chore: remove unneccessary flt --- erpnext/stock/doctype/material_request/material_request.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index 7ba8dd27571..ceae67114f9 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -202,7 +202,7 @@ class MaterialRequest(BuyingController): item.item_code, ) if rate is not None: - item.db_set({"rate": flt(rate), "amount": flt(flt(rate) * item.qty, item.precision("amount"))}) + item.db_set({"rate": rate, "amount": flt(rate * item.qty, item.precision("amount"))}) frappe.msgprint( _("Item rates have been updated based on the selected Buying Price List {0}").format(