From 502a2626375462eb48f6dd9d73ff22e762d44923 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 20 Jan 2026 16:11:53 +0000 Subject: [PATCH] Merge pull request #51935 from frappe/mergify/bp/version-15-hotfix/pr-51934 fix: validation message in stock reco row idx (backport #51934) --- .../stock_reconciliation.py | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index 629a50e1c28..5359995ea9c 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -74,6 +74,7 @@ class StockReconciliation(StockController): self.validate_duplicate_serial_and_batch_bundle("items") self.remove_items_with_no_change() self.validate_data() + self.change_row_indexes() self.validate_expense_account() self.validate_customer_provided_item() self.set_zero_value_for_customer_provided_items() @@ -557,8 +558,7 @@ class StockReconciliation(StockController): elif len(items) != len(self.items): self.items = items - for i, item in enumerate(self.items): - item.idx = i + 1 + self.change_idx = True frappe.msgprint(_("Removed items with no change in quantity or value.")) def calculate_difference_amount(self, item, item_dict): @@ -575,14 +575,14 @@ class StockReconciliation(StockController): def validate_data(self): def _get_msg(row_num, msg): - return _("Row # {0}:").format(row_num + 1) + " " + msg + return _("Row #{0}:").format(row_num) + " " + msg self.validation_messages = [] item_warehouse_combinations = [] default_currency = frappe.db.get_default("currency") - for row_num, row in enumerate(self.items): + for row in self.items: # find duplicates key = [row.item_code, row.warehouse] for field in ["serial_no", "batch_no"]: @@ -595,7 +595,7 @@ class StockReconciliation(StockController): if key in item_warehouse_combinations: self.validation_messages.append( - _get_msg(row_num, _("Same item and warehouse combination already entered.")) + _get_msg(row.idx, _("Same item and warehouse combination already entered.")) ) else: item_warehouse_combinations.append(key) @@ -605,29 +605,29 @@ class StockReconciliation(StockController): if row.serial_no and not row.qty: self.validation_messages.append( _get_msg( - row_num, + row.idx, f"Quantity should not be zero for the {bold(row.item_code)} since serial nos are specified", ) ) # validate warehouse if not frappe.db.get_value("Warehouse", row.warehouse): - self.validation_messages.append(_get_msg(row_num, _("Warehouse not found in the system"))) + self.validation_messages.append(_get_msg(row.idx, _("Warehouse not found in the system"))) # if both not specified if row.qty in ["", None] and row.valuation_rate in ["", None]: self.validation_messages.append( - _get_msg(row_num, _("Please specify either Quantity or Valuation Rate or both")) + _get_msg(row.idx, _("Please specify either Quantity or Valuation Rate or both")) ) # do not allow negative quantity if flt(row.qty) < 0: - self.validation_messages.append(_get_msg(row_num, _("Negative Quantity is not allowed"))) + self.validation_messages.append(_get_msg(row.idx, _("Negative Quantity is not allowed"))) # do not allow negative valuation if flt(row.valuation_rate) < 0: self.validation_messages.append( - _get_msg(row_num, _("Negative Valuation Rate is not allowed")) + _get_msg(row.idx, _("Negative Valuation Rate is not allowed")) ) if row.qty and row.valuation_rate in ["", None]: @@ -659,6 +659,11 @@ class StockReconciliation(StockController): raise frappe.ValidationError(self.validation_messages) + def change_row_indexes(self): + if getattr(self, "change_idx", False): + for i, item in enumerate(self.items): + item.idx = i + 1 + def validate_item(self, item_code, row): from erpnext.stock.doctype.item.item import ( validate_cancelled_item,