From 5e9016ffab34df9609a75a7cbbaabbb37e7159d6 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 1 Dec 2023 21:42:22 +0530 Subject: [PATCH] fix: validation error has not throw for the batch (#38494) * fix: validation error has not throw for the batch * chore: fix test cases --- .../sales_invoice/test_sales_invoice.py | 1 + erpnext/controllers/buying_controller.py | 2 ++ erpnext/controllers/selling_controller.py | 1 + .../controllers/subcontracting_controller.py | 1 + .../serial_and_batch_bundle.py | 1 + .../stock/doctype/stock_entry/stock_entry.py | 1 + .../doctype/stock_entry/test_stock_entry.py | 36 +++++++++++++++++++ .../test_stock_ledger_entry.py | 4 +-- erpnext/stock/serial_batch_bundle.py | 8 +++-- 9 files changed, 50 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 840a31942a..e9b71ddffd 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -2629,6 +2629,7 @@ class TestSalesInvoice(FrappeTestCase): "voucher_type": "Sales Invoice", "voucher_no": si.name, "allow_zero_valuation": d.get("allow_zero_valuation"), + "voucher_detail_no": d.name, }, raise_error_if_no_rate=False, ) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 54c97b4208..3d863e9b87 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -118,6 +118,7 @@ class BuyingController(SubcontractingController): "company": self.company, "voucher_type": self.doctype, "voucher_no": self.name, + "voucher_detail_no": row.name, }, raise_error_if_no_rate=False, ) @@ -373,6 +374,7 @@ class BuyingController(SubcontractingController): "voucher_type": self.doctype, "voucher_no": self.name, "allow_zero_valuation": d.get("allow_zero_valuation"), + "voucher_detail_no": d.name, }, raise_error_if_no_rate=False, ) diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 5575a24b35..fdadb30e93 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -444,6 +444,7 @@ class SellingController(StockController): "company": self.company, "voucher_type": self.doctype, "voucher_no": self.name, + "voucher_detail_no": d.name, "allow_zero_valuation": d.get("allow_zero_valuation"), }, raise_error_if_no_rate=False, diff --git a/erpnext/controllers/subcontracting_controller.py b/erpnext/controllers/subcontracting_controller.py index b52fbad1f0..9555902a74 100644 --- a/erpnext/controllers/subcontracting_controller.py +++ b/erpnext/controllers/subcontracting_controller.py @@ -880,6 +880,7 @@ class SubcontractingController(StockController): "posting_date": self.posting_date, "posting_time": self.posting_time, "qty": -1 * item.consumed_qty, + "voucher_detail_no": item.name, "serial_and_batch_bundle": item.serial_and_batch_bundle, } ) 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 f0cff21a42..88929eaaa0 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 @@ -252,6 +252,7 @@ class SerialandBatchBundle(Document): "serial_nos": [row.serial_no for row in self.entries if row.serial_no], "batch_nos": {row.batch_no: row for row in self.entries if row.batch_no}, "voucher_type": self.voucher_type, + "voucher_detail_no": self.voucher_detail_no, } ) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 8158b99f93..3baafd77ba 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -883,6 +883,7 @@ class StockEntry(StockController): "company": self.company, "allow_zero_valuation": item.allow_zero_valuation_rate, "serial_and_batch_bundle": item.serial_and_batch_bundle, + "voucher_detail_no": item.name, } ) diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index b640983a09..eb1c7a85eb 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -936,6 +936,42 @@ class TestStockEntry(FrappeTestCase): stock_entry.insert() self.assertTrue("_Test Variant Item-S" in [d.item_code for d in stock_entry.items]) + def test_nagative_stock_for_batch(self): + item = make_item( + "_Test Batch Negative Item", + { + "has_batch_no": 1, + "create_new_batch": 1, + "batch_number_series": "B-BATCH-.##", + "is_stock_item": 1, + }, + ) + + make_stock_entry(item_code=item.name, target="_Test Warehouse - _TC", qty=50, basic_rate=100) + + ste = frappe.new_doc("Stock Entry") + ste.purpose = "Material Issue" + ste.company = "_Test Company" + for qty in [50, 20, 30]: + ste.append( + "items", + { + "item_code": item.name, + "s_warehouse": "_Test Warehouse - _TC", + "qty": qty, + "uom": item.stock_uom, + "stock_uom": item.stock_uom, + "conversion_factor": 1, + "transfer_qty": qty, + }, + ) + + ste.set_stock_entry_type() + ste.insert() + make_stock_entry(item_code=item.name, target="_Test Warehouse - _TC", qty=50, basic_rate=100) + + self.assertRaises(frappe.ValidationError, ste.submit) + def test_same_serial_nos_in_repack_or_manufacture_entries(self): s1 = make_serialized_item(target_warehouse="_Test Warehouse - _TC") serial_nos = get_serial_nos_from_bundle(s1.get("items")[0].serial_and_batch_bundle) diff --git a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py index f7c6ffece8..d8a3f2e33c 100644 --- a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py +++ b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py @@ -485,9 +485,9 @@ class TestStockLedgerEntry(FrappeTestCase, StockTestMixin): dns = create_delivery_note_entries_for_batchwise_item_valuation_test(dn_entry_list) sle_details = fetch_sle_details_for_doc_list(dns, ["stock_value_difference"]) svd_list = [-1 * d["stock_value_difference"] for d in sle_details] - expected_incoming_rates = expected_abs_svd = sorted([75.0, 125.0, 75.0, 125.0]) + expected_incoming_rates = expected_abs_svd = [75.0, 125.0, 75.0, 125.0] - self.assertEqual(expected_abs_svd, sorted(svd_list), "Incorrect 'Stock Value Difference' values") + self.assertEqual(expected_abs_svd, svd_list, "Incorrect 'Stock Value Difference' values") for dn, incoming_rate in zip(dns, expected_incoming_rates): self.assertTrue( dn.items[0].incoming_rate in expected_abs_svd, diff --git a/erpnext/stock/serial_batch_bundle.py b/erpnext/stock/serial_batch_bundle.py index de28be1c35..0c187923e3 100644 --- a/erpnext/stock/serial_batch_bundle.py +++ b/erpnext/stock/serial_batch_bundle.py @@ -406,7 +406,7 @@ class SerialNoValuation(DeprecatedSerialNoValuation): .orderby(bundle.posting_date, bundle.posting_time, bundle.creation) ) - # Important to exclude the current voucher + # Important to exclude the current voucher to calculate correct the stock value difference if self.sle.voucher_no: query = query.where(bundle.voucher_no != self.sle.voucher_no) @@ -539,8 +539,10 @@ class BatchNoValuation(DeprecatedBatchNoValuation): .groupby(child.batch_no) ) - # Important to exclude the current voucher - if self.sle.voucher_no: + # Important to exclude the current voucher detail no / voucher no to calculate the correct stock value difference + if self.sle.voucher_detail_no: + query = query.where(parent.voucher_detail_no != self.sle.voucher_detail_no) + elif self.sle.voucher_no: query = query.where(parent.voucher_no != self.sle.voucher_no) if timestamp_condition: