From 418439b58f2793344dbc30ea858070147f3afa7e Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Thu, 23 May 2024 14:51:54 +0530 Subject: [PATCH] fix: SCR batch qty issue (#41595) --- .../controllers/subcontracting_controller.py | 4 +- erpnext/stock/stock_ledger.py | 6 +- .../test_subcontracting_receipt.py | 110 ++++++++++++++++++ 3 files changed, 117 insertions(+), 3 deletions(-) diff --git a/erpnext/controllers/subcontracting_controller.py b/erpnext/controllers/subcontracting_controller.py index fc66345aeee..e0f1ed77140 100644 --- a/erpnext/controllers/subcontracting_controller.py +++ b/erpnext/controllers/subcontracting_controller.py @@ -327,13 +327,13 @@ class SubcontractingController(StockController): consumed_bundles.batch_nos[batch_no] += abs(qty) # Will be deprecated in v16 - if row.serial_no: + if row.serial_no and not consumed_bundles.serial_nos: self.available_materials[key]["serial_no"] = list( set(self.available_materials[key]["serial_no"]) - set(get_serial_nos(row.serial_no)) ) # Will be deprecated in v16 - if row.batch_no: + if row.batch_no and not consumed_bundles.batch_nos: self.available_materials[key]["batch_no"][row.batch_no] -= row.consumed_qty def get_available_materials(self): diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index c823c55e03c..ac513f2d380 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -308,7 +308,11 @@ def get_reposting_data(file_path) -> dict: attached_file = frappe.get_doc("File", file_name) - data = gzip.decompress(attached_file.get_content()) + content = attached_file.get_content() + if isinstance(content, str): + content = content.encode("utf-8") + + data = gzip.decompress(content) if data := json.loads(data.decode("utf-8")): data = data diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py index 996a99065bb..81662a6257b 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py @@ -1235,6 +1235,116 @@ class TestSubcontractingReceipt(FrappeTestCase): self.assertTrue(scr.items[0].serial_and_batch_bundle) self.assertTrue(scr.items[0].rejected_serial_and_batch_bundle) + def test_subcontracting_receipt_for_batch_materials_without_use_serial_batch_fields(self): + from erpnext.controllers.subcontracting_controller import make_rm_stock_entry + + set_backflush_based_on("Material Transferred for Subcontract") + + fg_item = make_item( + "Test Subcontracted FG Item With Batch No and Without Use Serial Batch Fields", + properties={"is_stock_item": 1, "is_sub_contracted_item": 1}, + ).name + + rm_item1 = make_item( + "Test Subcontracted RM Item With Batch No and Without Use Serial Batch Fields", + properties={ + "is_stock_item": 1, + "has_batch_no": 1, + "create_new_batch": 1, + "batch_number_series": "BATCH-RM-BNGS-.####", + }, + ).name + + make_item( + "Subcontracted Service Item 21", + properties={ + "is_stock_item": 0, + }, + ) + + bom = make_bom(item=fg_item, raw_materials=[rm_item1]) + + rm_batch_no = None + for row in bom.items: + se = make_stock_entry( + item_code=row.item_code, + qty=10, + target="_Test Warehouse - _TC", + rate=300, + ) + + se.reload() + rm_batch_no = get_batch_from_bundle(se.items[0].serial_and_batch_bundle) + + service_items = [ + { + "warehouse": "_Test Warehouse - _TC", + "item_code": "Subcontracted Service Item 21", + "qty": 10, + "rate": 100, + "fg_item": fg_item, + "fg_item_qty": 10, + }, + ] + sco = get_subcontracting_order(service_items=service_items) + self.assertTrue(sco.docstatus) + rm_items = [ + { + "name": sco.supplied_items[0].name, + "item_code": rm_item1, + "rm_item_code": rm_item1, + "item_name": rm_item1, + "qty": 10, + "warehouse": "_Test Warehouse - _TC", + "rate": 100, + "stock_uom": frappe.get_cached_value("Item", rm_item1, "stock_uom"), + "use_serial_batch_fields": 1, + }, + ] + se = frappe.get_doc(make_rm_stock_entry(sco.name, rm_items)) + se.items[0].subcontracted_item = fg_item + se.items[0].s_warehouse = "_Test Warehouse - _TC" + se.items[0].t_warehouse = "_Test Warehouse 1 - _TC" + se.items[0].use_serial_batch_fields = 1 + se.items[0].batch_no = rm_batch_no + se.submit() + + self.assertEqual(se.items[0].batch_no, rm_batch_no) + self.assertEqual(se.items[0].use_serial_batch_fields, 1) + + frappe.db.set_single_value("Stock Settings", "use_serial_batch_fields", 0) + scr = make_subcontracting_receipt(sco.name) + scr.items[0].qty = 2 + scr.save() + scr.submit() + + self.assertEqual(scr.supplied_items[0].consumed_qty, 2) + self.assertEqual(scr.supplied_items[0].batch_no, rm_batch_no) + self.assertEqual(get_batch_from_bundle(scr.supplied_items[0].serial_and_batch_bundle), rm_batch_no) + + scr = make_subcontracting_receipt(sco.name) + scr.items[0].qty = 2 + scr.save() + scr.submit() + + self.assertEqual(scr.supplied_items[0].consumed_qty, 2) + self.assertEqual(scr.supplied_items[0].batch_no, rm_batch_no) + self.assertEqual(get_batch_from_bundle(scr.supplied_items[0].serial_and_batch_bundle), rm_batch_no) + + scr = make_subcontracting_receipt(sco.name) + scr.items[0].qty = 6 + scr.save() + scr.submit() + + self.assertEqual(scr.supplied_items[0].consumed_qty, 6) + self.assertEqual(scr.supplied_items[0].batch_no, rm_batch_no) + self.assertEqual(get_batch_from_bundle(scr.supplied_items[0].serial_and_batch_bundle), rm_batch_no) + + sco.reload() + self.assertEqual(sco.status, "Completed") + + frappe.db.set_single_value("Stock Settings", "use_serial_batch_fields", 1) + def make_return_subcontracting_receipt(**args): args = frappe._dict(args)