From db82782ece01d7d4125b89d4fc70761376ac4dc5 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 18 Dec 2023 14:11:36 +0530 Subject: [PATCH 1/5] fix: not able to cancel SCR with Batch (#38817) (cherry picked from commit fb5090fd3f23ada507fe8abc5a899f4b06e48d7e) # Conflicts: # erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py --- .../subcontracting_receipt.py | 2 +- .../test_subcontracting_receipt.py | 74 +++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index 1a5deb68df68..52bf13c78d92 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -167,13 +167,13 @@ def on_cancel(self): ) self.update_status_updater_args() self.update_prevdoc_status() - self.delete_auto_created_batches() self.set_consumed_qty_in_subcontract_order() self.set_subcontracting_order_status() self.update_stock_ledger() self.make_gl_entries_on_cancel() self.repost_future_sle_and_gle() self.update_status() + self.delete_auto_created_batches() def validate_items_qty(self): for item in self.items: diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py index f4af21d7c4b0..753c9509f928 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py @@ -817,6 +817,7 @@ def test_subcontracting_receipt_raw_material_rate(self): self.assertEqual(rm_item.rate, 100) self.assertEqual(rm_item.amount, rm_item.consumed_qty * rm_item.rate) +<<<<<<< HEAD def test_quality_inspection_for_subcontracting_receipt(self): from erpnext.stock.doctype.quality_inspection.test_quality_inspection import ( create_quality_inspection, @@ -929,10 +930,58 @@ def test_scrap_items_for_subcontracting_receipt(self): # Transfer RM's to Subcontractor make_stock_transfer_entry( +======= + def test_subcontracting_receipt_cancel_with_batch(self): + from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom + + # Step - 1: Set Backflush Based On as "BOM" + set_backflush_based_on("BOM") + + # Step - 2: Create FG and RM Items + fg_item = make_item( + properties={"is_stock_item": 1, "is_sub_contracted_item": 1, "has_batch_no": 1} + ).name + rm_item1 = make_item(properties={"is_stock_item": 1}).name + rm_item2 = make_item(properties={"is_stock_item": 1}).name + make_item("Subcontracted Service Item Test For Batch 1", {"is_stock_item": 0}) + + # Step - 3: Create BOM for FG Item + bom = make_bom(item=fg_item, raw_materials=[rm_item1, rm_item2]) + for rm_item in bom.items: + self.assertEqual(rm_item.rate, 0) + self.assertEqual(rm_item.amount, 0) + bom = bom.name + + # Step - 4: Create PO and SCO + service_items = [ + { + "warehouse": "_Test Warehouse - _TC", + "item_code": "Subcontracted Service Item Test For Batch 1", + "qty": 100, + "rate": 100, + "fg_item": fg_item, + "fg_item_qty": 100, + }, + ] + sco = get_subcontracting_order(service_items=service_items) + for rm_item in sco.supplied_items: + self.assertEqual(rm_item.rate, 0) + self.assertEqual(rm_item.amount, 0) + + # Step - 5: Inward Raw Materials + rm_items = get_rm_items(sco.supplied_items) + for rm_item in rm_items: + rm_item["rate"] = 100 + itemwise_details = make_stock_in_entry(rm_items=rm_items) + + # Step - 6: Transfer RM's to Subcontractor + se = make_stock_transfer_entry( +>>>>>>> fb5090fd3f (fix: not able to cancel SCR with Batch (#38817)) sco_no=sco.name, rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details), ) +<<<<<<< HEAD # Create Subcontracting Receipt scr = make_subcontracting_receipt(sco.name) @@ -972,6 +1021,31 @@ def test_auto_create_purchase_receipt(self): scr.submit() self.assertTrue(frappe.db.get_value("Purchase Receipt", {"subcontracting_receipt": scr.name})) +======= + for item in se.items: + self.assertEqual(item.qty, 100) + self.assertEqual(item.basic_rate, 100) + self.assertEqual(item.amount, item.qty * item.basic_rate) + + batch_doc = frappe.get_doc( + { + "doctype": "Batch", + "item": fg_item, + "batch_id": frappe.generate_hash(length=10), + } + ).insert(ignore_permissions=True) + + # Step - 7: Create Subcontracting Receipt + scr = make_subcontracting_receipt(sco.name) + scr.items[0].batch_no = batch_doc.batch_id + scr.save() + scr.submit() + scr.load_from_db() + + # Step - 8: Cancel Subcontracting Receipt + scr.cancel() + self.assertTrue(scr.docstatus == 2) +>>>>>>> fb5090fd3f (fix: not able to cancel SCR with Batch (#38817)) def make_return_subcontracting_receipt(**args): From d15895dd6e7c1e82831ddba9ef684299616b9475 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 18 Dec 2023 14:28:36 +0530 Subject: [PATCH 2/5] chore: fix test case --- .../test_subcontracting_receipt.py | 73 +++++++++---------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py index 753c9509f928..1382ae868742 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py @@ -817,7 +817,6 @@ def test_subcontracting_receipt_raw_material_rate(self): self.assertEqual(rm_item.rate, 100) self.assertEqual(rm_item.amount, rm_item.consumed_qty * rm_item.rate) -<<<<<<< HEAD def test_quality_inspection_for_subcontracting_receipt(self): from erpnext.stock.doctype.quality_inspection.test_quality_inspection import ( create_quality_inspection, @@ -930,7 +929,23 @@ def test_scrap_items_for_subcontracting_receipt(self): # Transfer RM's to Subcontractor make_stock_transfer_entry( -======= + sco_no=sco.name, + rm_items=rm_items, + itemwise_details=copy.deepcopy(itemwise_details), + ) + + # Create Subcontracting Receipt + scr = make_subcontracting_receipt(sco.name) + scr.save() + scr.get_scrap_items() + + # Test - 1: Scrap Items should be fetched from BOM in items table with `is_scrap_item` = 1 + scr_scrap_items = set([item.item_code for item in scr.items if item.is_scrap_item]) + self.assertEqual(len(scr.items), 3) # 1 FG Item + 2 Scrap Items + self.assertEqual(scr_scrap_items, set(scrap_items)) + + scr.submit() + def test_subcontracting_receipt_cancel_with_batch(self): from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom @@ -976,24 +991,33 @@ def test_subcontracting_receipt_cancel_with_batch(self): # Step - 6: Transfer RM's to Subcontractor se = make_stock_transfer_entry( ->>>>>>> fb5090fd3f (fix: not able to cancel SCR with Batch (#38817)) sco_no=sco.name, rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details), ) -<<<<<<< HEAD + for item in se.items: + self.assertEqual(item.qty, 100) + self.assertEqual(item.basic_rate, 100) + self.assertEqual(item.amount, item.qty * item.basic_rate) - # Create Subcontracting Receipt + batch_doc = frappe.get_doc( + { + "doctype": "Batch", + "item": fg_item, + "batch_id": frappe.generate_hash(length=10), + } + ).insert(ignore_permissions=True) + + # Step - 7: Create Subcontracting Receipt scr = make_subcontracting_receipt(sco.name) + scr.items[0].batch_no = batch_doc.batch_id scr.save() - scr.get_scrap_items() - - # Test - 1: Scrap Items should be fetched from BOM in items table with `is_scrap_item` = 1 - scr_scrap_items = set([item.item_code for item in scr.items if item.is_scrap_item]) - self.assertEqual(len(scr.items), 3) # 1 FG Item + 2 Scrap Items - self.assertEqual(scr_scrap_items, set(scrap_items)) - scr.submit() + scr.load_from_db() + + # Step - 8: Cancel Subcontracting Receipt + scr.cancel() + self.assertTrue(scr.docstatus == 2) @change_settings("Buying Settings", {"auto_create_purchase_receipt": 1}) def test_auto_create_purchase_receipt(self): @@ -1021,31 +1045,6 @@ def test_auto_create_purchase_receipt(self): scr.submit() self.assertTrue(frappe.db.get_value("Purchase Receipt", {"subcontracting_receipt": scr.name})) -======= - for item in se.items: - self.assertEqual(item.qty, 100) - self.assertEqual(item.basic_rate, 100) - self.assertEqual(item.amount, item.qty * item.basic_rate) - - batch_doc = frappe.get_doc( - { - "doctype": "Batch", - "item": fg_item, - "batch_id": frappe.generate_hash(length=10), - } - ).insert(ignore_permissions=True) - - # Step - 7: Create Subcontracting Receipt - scr = make_subcontracting_receipt(sco.name) - scr.items[0].batch_no = batch_doc.batch_id - scr.save() - scr.submit() - scr.load_from_db() - - # Step - 8: Cancel Subcontracting Receipt - scr.cancel() - self.assertTrue(scr.docstatus == 2) ->>>>>>> fb5090fd3f (fix: not able to cancel SCR with Batch (#38817)) def make_return_subcontracting_receipt(**args): From 27780f87e8e23e0e7638d616d026e9fffe8fbd72 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 18 Dec 2023 15:21:28 +0530 Subject: [PATCH 3/5] chore: fix test case --- .../test_subcontracting_receipt.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py index 1382ae868742..8a51f5ca07e6 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py @@ -1008,9 +1008,24 @@ def test_subcontracting_receipt_cancel_with_batch(self): } ).insert(ignore_permissions=True) + serial_batch_bundle = frappe.get_doc( + { + "doctype": "Serial and Batch Bundle", + "item_code": fg_item, + "warehouse": sco.items[0].warehouse, + "has_batch_no": 1, + "entries": [ + { + "batch_no": frappe.generate_hash(length=10), + "qty": sco.items[0].qty + } + ] + } + ).insert(ignore_permissions=True) + # Step - 7: Create Subcontracting Receipt scr = make_subcontracting_receipt(sco.name) - scr.items[0].batch_no = batch_doc.batch_id + scr.items[0].serial_and_batch_bundle = serial_batch_bundle.name scr.save() scr.submit() scr.load_from_db() From ce21542b8c6529b1a100a408e0d1a9f8eaad6819 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 18 Dec 2023 15:47:08 +0530 Subject: [PATCH 4/5] chore: fix test case --- .../subcontracting_receipt/test_subcontracting_receipt.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py index 8a51f5ca07e6..a4188407d801 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py @@ -1014,12 +1014,7 @@ def test_subcontracting_receipt_cancel_with_batch(self): "item_code": fg_item, "warehouse": sco.items[0].warehouse, "has_batch_no": 1, - "entries": [ - { - "batch_no": frappe.generate_hash(length=10), - "qty": sco.items[0].qty - } - ] + "entries": [{"batch_no": batch_doc.name, "qty": sco.items[0].qty}], } ).insert(ignore_permissions=True) From 2769ed9bdbe3c0783a0b085b0414d8eae67deefd Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 18 Dec 2023 16:18:42 +0530 Subject: [PATCH 5/5] chore: fix test case --- .../serial_and_batch_bundle/serial_and_batch_bundle.py | 2 +- .../subcontracting_receipt/test_subcontracting_receipt.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) 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 52ef26e641a2..37916e21c892 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 @@ -459,7 +459,7 @@ def validate_quantity(self, row, qty_field=None): qty_field = "qty" precision = row.precision - if self.voucher_type in ["Subcontracting Receipt"]: + if row.get("doctype") in ["Subcontracting Receipt Supplied Item"]: qty_field = "consumed_qty" if abs(abs(flt(self.total_qty, precision)) - abs(flt(row.get(qty_field), precision))) > 0.01: diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py index a4188407d801..9d7be36adbcc 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py @@ -1014,7 +1014,9 @@ def test_subcontracting_receipt_cancel_with_batch(self): "item_code": fg_item, "warehouse": sco.items[0].warehouse, "has_batch_no": 1, - "entries": [{"batch_no": batch_doc.name, "qty": sco.items[0].qty}], + "type_of_transaction": "Inward", + "voucher_type": "Subcontracting Receipt", + "entries": [{"batch_no": batch_doc.name, "qty": 100}], } ).insert(ignore_permissions=True)