From f121b33e291915f3a445de75380cefacb82041de Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 13:57:40 +0530 Subject: [PATCH] fix: valuation rate for legacy serial nos (backport #41543) (#41545) fix: valuation rate for legacy serial nos (#41543) fix: valuation rate for serial nos (cherry picked from commit 214b38f7c88cd31b0caa42f3122355fb19d1d044) Co-authored-by: rohitwaghchaure --- erpnext/stock/deprecated_serial_batch.py | 19 +-- .../delivery_note/test_delivery_note.py | 126 ++++++++++++++++++ erpnext/stock/serial_batch_bundle.py | 4 +- 3 files changed, 139 insertions(+), 10 deletions(-) diff --git a/erpnext/stock/deprecated_serial_batch.py b/erpnext/stock/deprecated_serial_batch.py index 81daa924b75..5b826455d4c 100644 --- a/erpnext/stock/deprecated_serial_batch.py +++ b/erpnext/stock/deprecated_serial_batch.py @@ -17,15 +17,11 @@ class DeprecatedSerialNoValuation: if not serial_nos: return - actual_qty = flt(self.sle.actual_qty) - stock_value_change = 0 - if actual_qty < 0: - if not self.sle.is_cancelled: - outgoing_value = self.get_incoming_value_for_serial_nos(serial_nos) - stock_value_change = -1 * outgoing_value + if not self.sle.is_cancelled: + stock_value_change = self.get_incoming_value_for_serial_nos(serial_nos) - self.stock_value_change += stock_value_change + self.stock_value_change += flt(stock_value_change) def get_filterd_serial_nos(self): serial_nos = [] @@ -141,7 +137,14 @@ class DeprecatedBatchNoValuation: if not self.non_batchwise_balance_qty: continue - self.batch_avg_rate[batch_no] = self.non_batchwise_balance_value / self.non_batchwise_balance_qty + if self.non_batchwise_balance_value == 0: + self.batch_avg_rate[batch_no] = 0.0 + self.stock_value_differece[batch_no] = 0.0 + else: + self.batch_avg_rate[batch_no] = ( + self.non_batchwise_balance_value / self.non_batchwise_balance_qty + ) + self.stock_value_differece[batch_no] = self.non_batchwise_balance_value stock_value_change = self.batch_avg_rate[batch_no] * ledger.qty self.stock_value_change += stock_value_change diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index 791a9730b50..192d828d843 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -1697,6 +1697,132 @@ class TestDeliveryNote(FrappeTestCase): if row.serial_no: self.assertEqual(row.serial_no, serial_no) + def test_delivery_note_legacy_serial_no_valuation(self): + from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_return + from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos + + frappe.flags.ignore_serial_batch_bundle_validation = True + sn_item = "Old Serial NO Item Valuation Test - 2" + make_item( + sn_item, + { + "has_serial_no": 1, + "serial_no_series": "SN-SOVOSN-.####", + "is_stock_item": 1, + }, + ) + + serial_nos = [ + "SN-SOVOSN-1234", + "SN-SOVOSN-2234", + ] + + for sn in serial_nos: + if not frappe.db.exists("Serial No", sn): + sn_doc = frappe.get_doc( + { + "doctype": "Serial No", + "item_code": sn_item, + "serial_no": sn, + } + ) + sn_doc.insert() + + warehouse = "_Test Warehouse - _TC" + company = frappe.db.get_value("Warehouse", warehouse, "company") + se_doc = make_stock_entry( + item_code=sn_item, + company=company, + target="_Test Warehouse - _TC", + qty=2, + basic_rate=150, + do_not_submit=1, + use_serial_batch_fields=0, + ) + se_doc.submit() + + se_doc.items[0].db_set("serial_no", "\n".join(serial_nos)) + + sle_data = frappe.get_all( + "Stock Ledger Entry", + filters={"voucher_no": se_doc.name, "voucher_type": "Stock Entry"}, + )[0] + + sle_doc = frappe.get_doc("Stock Ledger Entry", sle_data.name) + self.assertFalse(sle_doc.serial_no) + sle_doc.db_set("serial_no", "\n".join(serial_nos)) + sle_doc.reload() + self.assertTrue(sle_doc.serial_no) + self.assertFalse(sle_doc.is_cancelled) + + for sn in serial_nos: + sn_doc = frappe.get_doc("Serial No", sn) + sn_doc.db_set( + { + "status": "Active", + "warehouse": warehouse, + } + ) + + self.assertEqual(sorted(get_serial_nos(se_doc.items[0].serial_no)), sorted(serial_nos)) + frappe.flags.ignore_serial_batch_bundle_validation = False + + se_doc = make_stock_entry( + item_code=sn_item, + company=company, + target="_Test Warehouse - _TC", + qty=2, + basic_rate=200, + ) + + serial_nos.extend(get_serial_nos_from_bundle(se_doc.items[0].serial_and_batch_bundle)) + + dn = create_delivery_note( + item_code=sn_item, + qty=3, + rate=500, + warehouse=warehouse, + company=company, + expense_account="Cost of Goods Sold - _TC", + cost_center="Main - _TC", + use_serial_batch_fields=1, + serial_no="\n".join(serial_nos[0:3]), + ) + + dn.reload() + + sle_data = frappe.get_all( + "Stock Ledger Entry", + filters={"voucher_no": dn.name, "voucher_type": "Delivery Note"}, + fields=["stock_value_difference", "actual_qty"], + )[0] + + self.assertEqual(sle_data.actual_qty, 3 * -1) + self.assertEqual(sle_data.stock_value_difference, 500.0 * -1) + + dn = create_delivery_note( + item_code=sn_item, + qty=1, + rate=500, + warehouse=warehouse, + company=company, + expense_account="Cost of Goods Sold - _TC", + cost_center="Main - _TC", + use_serial_batch_fields=1, + serial_no=serial_nos[-1], + ) + + dn.reload() + + sle_data = frappe.get_all( + "Stock Ledger Entry", + filters={"voucher_no": dn.name, "voucher_type": "Delivery Note"}, + fields=["stock_value_difference", "actual_qty"], + )[0] + + self.assertEqual(sle_data.actual_qty, 1 * -1) + self.assertEqual(sle_data.stock_value_difference, 200.0 * -1) + def create_delivery_note(**args): dn = frappe.new_doc("Delivery Note") diff --git a/erpnext/stock/serial_batch_bundle.py b/erpnext/stock/serial_batch_bundle.py index 21a96c41cb4..50a7707d4a9 100644 --- a/erpnext/stock/serial_batch_bundle.py +++ b/erpnext/stock/serial_batch_bundle.py @@ -553,7 +553,7 @@ class BatchNoValuation(DeprecatedBatchNoValuation): self.set_stock_value_difference() def get_batch_no_ledgers(self) -> list[dict]: - if not self.batches: + if not self.batchwise_valuation_batches: return [] parent = frappe.qb.DocType("Serial and Batch Bundle") @@ -575,7 +575,7 @@ class BatchNoValuation(DeprecatedBatchNoValuation): Sum(child.qty).as_("qty"), ) .where( - (child.batch_no.isin(self.batches)) + (child.batch_no.isin(self.batchwise_valuation_batches)) & (parent.warehouse == self.sle.warehouse) & (parent.item_code == self.sle.item_code) & (parent.docstatus == 1)