diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index 0b9dc3348fe..0ece122fe0e 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -2900,6 +2900,39 @@ class TestWorkOrder(FrappeTestCase): self.assertLessEqual(row.qty, 20) self.assertGreaterEqual(row.qty, 0) + def test_overproduction_allowed_qty(self): + """Test overproduction allowed qty in work order""" + allow_overproduction("overproduction_percentage_for_work_order", 50) + + wo_order = make_wo_order_test_record(planned_start_date=now(), qty=10) + + test_stock_entry.make_stock_entry( + item_code="_Test Item", target="Stores - _TC", qty=100, basic_rate=100 + ) + test_stock_entry.make_stock_entry( + item_code="_Test Item Home Desktop 100", + target="_Test Warehouse - _TC", + qty=100, + basic_rate=1000.0, + ) + + mt_stock_entry = frappe.get_doc( + make_stock_entry(wo_order.name, "Material Transfer for Manufacture", 10) + ) + mt_stock_entry.submit() + + fg_stock_entry = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 10)) + fg_stock_entry.items[2].qty = 15 + fg_stock_entry.fg_completed_qty = 15 + fg_stock_entry.submit() + + wo_order.reload() + + self.assertEqual(wo_order.produced_qty, 15) + self.assertEqual(wo_order.status, "Completed") + + allow_overproduction("overproduction_percentage_for_work_order", 0) + def make_stock_in_entries_and_get_batches(rm_item, source_warehouse, wip_warehouse): from erpnext.stock.doctype.stock_entry.test_stock_entry import ( diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index 0989d610b4a..4b28f6094c1 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -823,9 +823,28 @@ frappe.ui.form.on("Stock Entry", { refresh_field("process_loss_qty"); } }, + + set_fg_completed_qty(frm) { + let fg_completed_qty = 0; + + frm.doc.items.forEach((item) => { + if (item.is_finished_item) { + fg_completed_qty += flt(item.qty); + } + }); + + frm.doc.fg_completed_qty = fg_completed_qty; + frm.refresh_field("fg_completed_qty"); + }, }); frappe.ui.form.on("Stock Entry Detail", { + items_add(frm, cdt, cdn) { + let item = frappe.get_doc(cdt, cdn); + if (item.is_finished_item) { + frm.events.set_fg_completed_qty(frm); + } + }, set_basic_rate_manually(frm, cdt, cdn) { let row = locals[cdt][cdn]; frm.fields_dict.items.grid.update_docfield_property( @@ -837,6 +856,10 @@ frappe.ui.form.on("Stock Entry Detail", { qty(frm, cdt, cdn) { frm.events.set_basic_rate(frm, cdt, cdn); + let item = frappe.get_doc(cdt, cdn); + if (item.is_finished_item) { + frm.events.set_fg_completed_qty(frm); + } }, conversion_factor(frm, cdt, cdn) { diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 7ad2b9f3cd1..f8a9160aca8 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -1356,12 +1356,6 @@ class StockEntry(StockController): d.item_code, self.work_order ) ) - elif flt(d.transfer_qty) > flt(self.fg_completed_qty): - frappe.throw( - _("Quantity in row {0} ({1}) must be same as manufactured quantity {2}").format( - d.idx, d.transfer_qty, self.fg_completed_qty - ) - ) finished_items.append(d.item_code)