diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index e7eb9c6149..a399edda70 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -911,6 +911,54 @@ class TestWorkOrder(ERPNextTestCase): self.assertEqual(wo1.operations[0].time_in_mins, wo2.operations[0].time_in_mins) + def test_partial_manufacture_entries(self): + cancel_stock_entry = [] + + frappe.db.set_value("Manufacturing Settings", None, + "backflush_raw_materials_based_on", "Material Transferred for Manufacture") + + wo_order = make_wo_order_test_record(planned_start_date=now(), qty=100) + ste1 = test_stock_entry.make_stock_entry(item_code="_Test Item", + target="_Test Warehouse - _TC", qty=120, basic_rate=5000.0) + ste2 = test_stock_entry.make_stock_entry(item_code="_Test Item Home Desktop 100", + target="_Test Warehouse - _TC", qty=240, basic_rate=1000.0) + + cancel_stock_entry.extend([ste1.name, ste2.name]) + + sm = frappe.get_doc(make_stock_entry(wo_order.name, "Material Transfer for Manufacture", 100)) + for row in sm.get('items'): + if row.get('item_code') == '_Test Item': + row.qty = 110 + + sm.submit() + cancel_stock_entry.append(sm.name) + + s = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 90)) + for row in s.get('items'): + if row.get('item_code') == '_Test Item': + self.assertEqual(row.get('qty'), 100) + s.submit() + cancel_stock_entry.append(s.name) + + s1 = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 5)) + for row in s1.get('items'): + if row.get('item_code') == '_Test Item': + self.assertEqual(row.get('qty'), 5) + s1.submit() + cancel_stock_entry.append(s1.name) + + s2 = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 5)) + for row in s2.get('items'): + if row.get('item_code') == '_Test Item': + self.assertEqual(row.get('qty'), 5) + + cancel_stock_entry.reverse() + for ste in cancel_stock_entry: + doc = frappe.get_doc("Stock Entry", ste) + doc.cancel() + + frappe.db.set_value("Manufacturing Settings", None, + "backflush_raw_materials_based_on", "BOM") def update_job_card(job_card, jc_qty=None): employee = frappe.db.get_value('Employee', {'status': 'Active'}, 'name') diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index a61b3199c0..60154afa15 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -1445,14 +1445,15 @@ class StockEntry(StockController): qty = req_qty_each * flt(self.fg_completed_qty) elif backflushed_materials.get(item.item_code): + precision = frappe.get_precision("Stock Entry Detail", "qty") for d in backflushed_materials.get(item.item_code): - if d.get(item.warehouse): + if d.get(item.warehouse) > 0: if (qty > req_qty): - qty = (qty/trans_qty) * flt(self.fg_completed_qty) + qty = ((flt(qty, precision) - flt(d.get(item.warehouse), precision)) + / (flt(trans_qty, precision) - flt(produced_qty, precision)) + ) * flt(self.fg_completed_qty) - if consumed_qty and frappe.db.get_single_value("Manufacturing Settings", - "material_consumption"): - qty -= consumed_qty + d[item.warehouse] -= qty if cint(frappe.get_cached_value('UOM', item.stock_uom, 'must_be_whole_number')): qty = frappe.utils.ceil(qty)