From 7ce97ce0c2fdc2f6308e5b9266b1db198984061b Mon Sep 17 00:00:00 2001 From: Kavin <78342682+kavin0411@users.noreply.github.com> Date: Tue, 30 Sep 2025 16:10:38 +0530 Subject: [PATCH 1/3] fix: validate transfer_qty based on overproduction wo percentage (cherry picked from commit 4024d8846b59387d69ead723c93d29da72c4dc30) --- erpnext/stock/doctype/stock_entry/stock_entry.py | 6 ------ 1 file changed, 6 deletions(-) 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) From b6d57ff8a5d66c09dbd4098f2747c9f8c692b3ad Mon Sep 17 00:00:00 2001 From: Kavin <78342682+kavin0411@users.noreply.github.com> Date: Tue, 30 Sep 2025 17:38:45 +0530 Subject: [PATCH 2/3] fix: set fg_completed_qty based upon fg item qty (cherry picked from commit 526b850e61f507f0fd571d09dbf2b048ce8dce9c) --- .../stock/doctype/stock_entry/stock_entry.js | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) 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) { From 0fec34e886179838a2bf89d26bca332385ae0d2d Mon Sep 17 00:00:00 2001 From: Kavin <78342682+kavin0411@users.noreply.github.com> Date: Tue, 30 Sep 2025 18:27:45 +0530 Subject: [PATCH 3/3] test: test overproduction allowed qty in wo (cherry picked from commit b527d38bfafd5843deaa4732e8df2e1ed244cddc) --- .../doctype/work_order/test_work_order.py | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) 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 (