From 3327799524e8239843c44842b6fb4251de69528d Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Wed, 19 Nov 2025 15:57:15 +0530 Subject: [PATCH] test: add test case --- .../doctype/job_card/test_job_card.py | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/erpnext/manufacturing/doctype/job_card/test_job_card.py b/erpnext/manufacturing/doctype/job_card/test_job_card.py index 4ab07321bd2..425367c519d 100644 --- a/erpnext/manufacturing/doctype/job_card/test_job_card.py +++ b/erpnext/manufacturing/doctype/job_card/test_job_card.py @@ -708,6 +708,119 @@ class TestJobCard(ERPNextTestSuite): self.assertEqual(wo_doc.process_loss_qty, 2) self.assertEqual(wo_doc.status, "Completed") + def test_op_cost_calculation(self): + from erpnext.manufacturing.doctype.routing.test_routing import ( + create_routing, + setup_bom, + setup_operations, + ) + from erpnext.manufacturing.doctype.work_order.work_order import make_job_card + from erpnext.manufacturing.doctype.work_order.work_order import ( + make_stock_entry as make_stock_entry_for_wo, + ) + from erpnext.stock.doctype.item.test_item import make_item + from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse + + make_workstation(workstation_name="Test Workstation Z", hour_rate_rent=240) + operations = [ + {"operation": "Test Operation A1", "workstation": "Test Workstation Z", "time_in_mins": 30}, + ] + + warehouse = create_warehouse("Test Warehouse 123 for Job Card") + setup_operations(operations) + + item_code = "Test Job Card Process Qty Item" + for item in [item_code, item_code + "RM 1", item_code + "RM 2"]: + if not frappe.db.exists("Item", item): + make_item( + item, + { + "item_name": item, + "stock_uom": "Nos", + "is_stock_item": 1, + }, + ) + + routing_doc = create_routing(routing_name="Testing Route", operations=operations) + bom_doc = setup_bom( + item_code=item_code, + routing=routing_doc.name, + raw_materials=[item_code + "RM 1", item_code + "RM 2"], + source_warehouse=warehouse, + ) + + for row in bom_doc.items: + make_stock_entry( + item_code=row.item_code, + target=row.source_warehouse, + qty=10, + basic_rate=100, + ) + + wo_doc = make_wo_order_test_record( + production_item=item_code, + bom_no=bom_doc.name, + qty=10, + skip_transfer=1, + wip_warehouse=warehouse, + source_warehouse=warehouse, + ) + + first_job_card = frappe.get_all( + "Job Card", + filters={"work_order": wo_doc.name, "sequence_id": 1}, + fields=["name"], + order_by="sequence_id", + limit=1, + )[0].name + + jc = frappe.get_doc("Job Card", first_job_card) + for _ in jc.scheduled_time_logs: + jc.append( + "time_logs", + { + "from_time": now(), + "to_time": add_to_date(now(), minutes=1), + "completed_qty": 4, + }, + ) + jc.for_quantity = 4 + jc.save() + jc.submit() + + s = frappe.get_doc(make_stock_entry_for_wo(wo_doc.name, "Manufacture", 4)) + s.submit() + + self.assertEqual(s.additional_costs[0].amount, 4) + + make_job_card( + wo_doc.name, + [ + { + "name": wo_doc.operations[0].name, + "operation": "Test Operation A1", + "qty": 6, + "pending_qty": 6, + } + ], + ) + + job_card = frappe.get_last_doc("Job Card", {"work_order": wo_doc.name}) + job_card.append( + "time_logs", + { + "from_time": add_to_date(now(), hours=1), + "to_time": add_to_date(now(), hours=1, minutes=2), + "completed_qty": 6, + }, + ) + job_card.for_quantity = 6 + job_card.save() + job_card.submit() + + s = frappe.get_doc(make_stock_entry_for_wo(wo_doc.name, "Manufacture", 6)) + self.assertEqual(s.additional_costs[0].amount, 8) + def create_bom_with_multiple_operations(): "Create a BOM with multiple operations and Material Transfer against Job Card"