test: added test case for disassembly order
This commit is contained in:
@@ -2364,6 +2364,105 @@ class TestWorkOrder(IntegrationTestCase):
|
|||||||
|
|
||||||
stock_entry.submit()
|
stock_entry.submit()
|
||||||
|
|
||||||
|
def test_disassembly_order_with_qty_behavior(self):
|
||||||
|
# Create raw material and FG item
|
||||||
|
raw_item = make_item("Test Raw for Disassembly", {"is_stock_item": 1}).name
|
||||||
|
fg_item = make_item("Test FG for Disassembly", {"is_stock_item": 1}).name
|
||||||
|
bom = make_bom(item=fg_item, quantity=10, raw_materials=[raw_item], rm_qty=5)
|
||||||
|
|
||||||
|
# Create and submit a Work Order for 10 qty
|
||||||
|
wo = make_wo_order_test_record(production_item=fg_item, qty=10, bom_no=bom.name, status="Not Started")
|
||||||
|
|
||||||
|
# create material receipt stock entry for raw material
|
||||||
|
from erpnext.stock.doctype.stock_entry.test_stock_entry import (
|
||||||
|
make_stock_entry as make_stock_entry_test_record,
|
||||||
|
)
|
||||||
|
|
||||||
|
make_stock_entry_test_record(
|
||||||
|
item_code=raw_item,
|
||||||
|
purpose="Material Receipt",
|
||||||
|
target=wo.wip_warehouse,
|
||||||
|
qty=10,
|
||||||
|
basic_rate=100,
|
||||||
|
)
|
||||||
|
make_stock_entry_test_record(
|
||||||
|
item_code=raw_item,
|
||||||
|
purpose="Material Receipt",
|
||||||
|
target=wo.fg_warehouse,
|
||||||
|
qty=10,
|
||||||
|
basic_rate=100,
|
||||||
|
)
|
||||||
|
|
||||||
|
# create material transfer for manufacture stock entry
|
||||||
|
se_for_material_tranfer_mfr = frappe.get_doc(
|
||||||
|
make_stock_entry(wo.name, "Material Transfer for Manufacture", wo.qty)
|
||||||
|
)
|
||||||
|
se_for_material_tranfer_mfr.items[0].s_warehouse = wo.wip_warehouse
|
||||||
|
se_for_material_tranfer_mfr.save()
|
||||||
|
se_for_material_tranfer_mfr.submit()
|
||||||
|
|
||||||
|
se_for_manufacture = frappe.get_doc(make_stock_entry(wo.name, "Manufacture", wo.qty))
|
||||||
|
se_for_manufacture.submit()
|
||||||
|
|
||||||
|
# Simulate a disassembly stock entry
|
||||||
|
disassemble_qty = 4
|
||||||
|
stock_entry = frappe.get_doc(make_stock_entry(wo.name, "Disassemble", disassemble_qty))
|
||||||
|
stock_entry.append(
|
||||||
|
"items",
|
||||||
|
{
|
||||||
|
"item_code": fg_item,
|
||||||
|
"qty": disassemble_qty,
|
||||||
|
"s_warehouse": wo.fg_warehouse,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
for bom_item in bom.items:
|
||||||
|
stock_entry.append(
|
||||||
|
"items",
|
||||||
|
{
|
||||||
|
"item_code": bom_item.item_code,
|
||||||
|
"qty": (bom_item.qty / bom.quantity) * disassemble_qty,
|
||||||
|
"t_warehouse": wo.source_warehouse,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
wo.reload()
|
||||||
|
stock_entry.save()
|
||||||
|
stock_entry.submit()
|
||||||
|
|
||||||
|
# Assert FG item is present with correct qty
|
||||||
|
finished_good_entry = next((item for item in stock_entry.items if item.item_code == fg_item), None)
|
||||||
|
self.assertIsNotNone(finished_good_entry, "Finished good item missing from stock entry")
|
||||||
|
self.assertEqual(
|
||||||
|
finished_good_entry.qty,
|
||||||
|
disassemble_qty,
|
||||||
|
f"Expected FG qty {disassemble_qty}, found {finished_good_entry.qty}",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Assert raw materials
|
||||||
|
for item in stock_entry.items:
|
||||||
|
if item.item_code == fg_item:
|
||||||
|
continue
|
||||||
|
bom_item = next((i for i in bom.items if i.item_code == item.item_code), None)
|
||||||
|
if bom_item:
|
||||||
|
expected_qty = (bom_item.qty / bom.quantity) * disassemble_qty
|
||||||
|
self.assertAlmostEqual(
|
||||||
|
item.qty,
|
||||||
|
expected_qty,
|
||||||
|
places=3,
|
||||||
|
msg=f"Raw item {item.item_code} qty mismatch: expected {expected_qty}, got {item.qty}",
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.fail(f"Unexpected item {item.item_code} found in stock entry")
|
||||||
|
|
||||||
|
wo.reload()
|
||||||
|
# Assert disassembled_qty field updated in Work Order
|
||||||
|
self.assertEqual(
|
||||||
|
wo.disassembled_qty,
|
||||||
|
disassemble_qty,
|
||||||
|
f"Work Order disassembled_qty mismatch: expected {disassemble_qty}, got {wo.disassembled_qty}",
|
||||||
|
)
|
||||||
|
|
||||||
def test_components_alternate_item_for_bom_based_manufacture_entry(self):
|
def test_components_alternate_item_for_bom_based_manufacture_entry(self):
|
||||||
frappe.db.set_single_value("Manufacturing Settings", "backflush_raw_materials_based_on", "BOM")
|
frappe.db.set_single_value("Manufacturing Settings", "backflush_raw_materials_based_on", "BOM")
|
||||||
frappe.db.set_single_value("Manufacturing Settings", "validate_components_quantities_per_bom", 1)
|
frappe.db.set_single_value("Manufacturing Settings", "validate_components_quantities_per_bom", 1)
|
||||||
@@ -3296,6 +3395,7 @@ def make_wo_order_test_record(**args):
|
|||||||
wo_order.transfer_material_against = args.transfer_material_against or "Work Order"
|
wo_order.transfer_material_against = args.transfer_material_against or "Work Order"
|
||||||
wo_order.from_wip_warehouse = args.from_wip_warehouse or 0
|
wo_order.from_wip_warehouse = args.from_wip_warehouse or 0
|
||||||
wo_order.batch_size = args.batch_size or 0
|
wo_order.batch_size = args.batch_size or 0
|
||||||
|
wo_order.status = args.status or "Draft"
|
||||||
|
|
||||||
if args.source_warehouse:
|
if args.source_warehouse:
|
||||||
wo_order.source_warehouse = args.source_warehouse
|
wo_order.source_warehouse = args.source_warehouse
|
||||||
|
|||||||
Reference in New Issue
Block a user