From 4b6097914abfe5f602723dd83faeb1f0082f7e15 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Sat, 3 Jan 2026 14:56:12 +0530 Subject: [PATCH 1/2] fix: not able to submit backdated stock reco (cherry picked from commit cccd34b06a28e52e6c9635e3478eecf3e6ade280) # Conflicts: # erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py --- .../repost_item_valuation.py | 9 ++ .../serial_and_batch_bundle.py | 15 ++-- .../test_stock_reconciliation.py | 88 +++++++++++++++++++ 3 files changed, 106 insertions(+), 6 deletions(-) diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py index 49ba0bf8358..96660288eff 100644 --- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py @@ -69,6 +69,15 @@ class RepostItemValuation(Document): ), ) +<<<<<<< HEAD +======= + def on_discard(self): + self.db_set("status", "Cancelled") + + def repost_now(self): + repost(self) + +>>>>>>> cccd34b06a (fix: not able to submit backdated stock reco) def validate(self): self.set_company() self.validate_period_closing_voucher() diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index aa22e6b8bde..ffd0a0a137d 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -554,7 +554,7 @@ class SerialandBatchBundle(Document): available_qty += flt(d.qty, precision) if not allow_negative_stock: - self.validate_negative_batch(d.batch_no, available_qty) + self.validate_negative_batch(d.batch_no, available_qty, field) d.stock_value_difference = flt(d.qty) * flt(d.incoming_rate) @@ -567,8 +567,8 @@ class SerialandBatchBundle(Document): } ) - def validate_negative_batch(self, batch_no, available_qty): - if available_qty < 0 and not self.is_stock_reco_for_valuation_adjustment(available_qty): + def validate_negative_batch(self, batch_no, available_qty, field=None): + if available_qty < 0 and not self.is_stock_reco_for_valuation_adjustment(available_qty, field=field): msg = f"""Batch No {bold(batch_no)} of an Item {bold(self.item_code)} has negative stock of quantity {bold(available_qty)} in the @@ -576,13 +576,16 @@ class SerialandBatchBundle(Document): frappe.throw(_(msg), BatchNegativeStockError) - def is_stock_reco_for_valuation_adjustment(self, available_qty): + def is_stock_reco_for_valuation_adjustment(self, available_qty, field=None): if ( self.voucher_type == "Stock Reconciliation" and self.type_of_transaction == "Outward" and self.voucher_detail_no - and abs(frappe.db.get_value("Stock Reconciliation Item", self.voucher_detail_no, "qty")) - == abs(available_qty) + and ( + abs(frappe.db.get_value("Stock Reconciliation Item", self.voucher_detail_no, "qty")) + == abs(available_qty) + or field == "total_qty" + ) ): return True diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py index 61c32d09467..b45934ffebd 100644 --- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py @@ -1557,6 +1557,94 @@ class TestStockReconciliation(FrappeTestCase, StockTestMixin): self.assertFalse(status == "Active") + def test_change_valuation_of_batch_using_backdated_stock_reco(self): + from erpnext.stock.doctype.batch.batch import get_batch_qty + from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry + + item_code = self.make_item( + "Test Item Change Valuation of Batch", + { + "is_stock_item": 1, + "has_batch_no": 1, + "create_new_batch": 1, + "batch_number_series": "TEST-BATCH-CVB-.###", + }, + ).name + + warehouse = "_Test Warehouse - _TC" + + reco = create_stock_reconciliation( + item_code=item_code, + posting_date=add_days(nowdate(), -6), + warehouse=warehouse, + qty=10, + rate=80, + use_serial_batch_fields=1, + ) + + batch_no = get_batch_from_bundle(reco.items[0].serial_and_batch_bundle) + + make_stock_entry( + item_code=item_code, + source=warehouse, + qty=2, + posting_date=add_days(nowdate(), -4), + use_serial_batch_fields=1, + batch_no=batch_no, + ) + + make_stock_entry( + item_code=item_code, + source=warehouse, + qty=2, + posting_date=add_days(nowdate(), -3), + use_serial_batch_fields=1, + batch_no=batch_no, + ) + + se4 = make_stock_entry( + item_code=item_code, + source=warehouse, + qty=2, + posting_date=add_days(nowdate(), -2), + use_serial_batch_fields=1, + batch_no=batch_no, + ) + + sle = frappe.db.get_value( + "Stock Ledger Entry", + {"voucher_no": se4.name, "is_cancelled": 0}, + ["actual_qty", "stock_value_difference"], + as_dict=1, + ) + + valuation_rate = sle.stock_value_difference / sle.actual_qty + self.assertEqual(valuation_rate, 80) + + create_stock_reconciliation( + item_code=item_code, + posting_date=add_days(nowdate(), -5), + warehouse=warehouse, + qty=10, + rate=100, + use_serial_batch_fields=1, + batch_no=batch_no, + ) + + sle = frappe.db.get_value( + "Stock Ledger Entry", + {"voucher_no": se4.name, "is_cancelled": 0}, + ["actual_qty", "stock_value_difference"], + as_dict=1, + ) + + valuation_rate = sle.stock_value_difference / sle.actual_qty + + self.assertEqual(valuation_rate, 100) + + batch_qty = get_batch_qty(batch_no, warehouse, item_code) + self.assertEqual(batch_qty, 4) + def create_batch_item_with_batch(item_name, batch_id): batch_item_doc = create_item(item_name, is_stock_item=1) From 46f3ab1c39be37930a2c7561eeba4ab807872c26 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Sat, 3 Jan 2026 15:23:29 +0530 Subject: [PATCH 2/2] chore: fix conflicts Removed unused on_discard method and cleaned up code. --- .../doctype/repost_item_valuation/repost_item_valuation.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py index 96660288eff..e3b1b330fad 100644 --- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py @@ -69,15 +69,9 @@ class RepostItemValuation(Document): ), ) -<<<<<<< HEAD -======= - def on_discard(self): - self.db_set("status", "Cancelled") - def repost_now(self): repost(self) ->>>>>>> cccd34b06a (fix: not able to submit backdated stock reco) def validate(self): self.set_company() self.validate_period_closing_voucher()