test: add bom tests for process loss val, add se test for qty calc
diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py
index c89f7d6..e61bb52 100644
--- a/erpnext/manufacturing/doctype/bom/test_bom.py
+++ b/erpnext/manufacturing/doctype/bom/test_bom.py
@@ -280,6 +280,38 @@
self.assertEqual(reqd_item.qty, created_item.qty)
self.assertEqual(reqd_item.exploded_qty, created_item.exploded_qty)
+ def test_bom_with_process_loss_item(self):
+ fg_item_non_whole, fg_item_whole, bom_item = create_process_loss_bom_items()
+
+ if frappe.db.exists("BOM", f"BOM-{fg_item_non_whole.item_code}-001") is None:
+ bom_doc = create_bom_with_process_loss_item(
+ fg_item_non_whole, bom_item, 0.25, 0, 1
+ )
+ bom_doc.submit()
+
+ bom_doc = create_bom_with_process_loss_item(
+ fg_item_non_whole, bom_item, 2, 0
+ )
+ # PL Item qty can't be >= FG Item qty
+ self.assertRaises(frappe.ValidationError, bom_doc.submit)
+
+ bom_doc = create_bom_with_process_loss_item(
+ fg_item_non_whole, bom_item, 1, 100
+ )
+ # PL Item rate has to be 0
+ self.assertRaises(frappe.ValidationError, bom_doc.submit)
+
+ bom_doc = create_bom_with_process_loss_item(
+ fg_item_whole, bom_item, 0.25, 0
+ )
+ # Items with whole UOMs can't be PL Items
+ self.assertRaises(frappe.ValidationError, bom_doc.submit)
+
+ bom_doc = create_bom_with_process_loss_item(
+ fg_item_non_whole, bom_item, 0.25, 0, is_process_loss=0
+ )
+ # FG Items in Scrap/Loss Table should have Is Process Loss set
+ self.assertRaises(frappe.ValidationError, bom_doc.submit)
def get_default_bom(item_code="_Test FG Item 2"):
return frappe.db.get_value("BOM", {"item": item_code, "is_active": 1, "is_default": 1})
@@ -353,3 +385,44 @@
for warehouse in warehouse_list:
create_stock_reconciliation(item_code=item_code, warehouse=warehouse, qty=qty, rate=rate)
+
+def create_bom_with_process_loss_item(
+ fg_item, bom_item, scrap_qty, scrap_rate, fg_qty=2, is_process_loss=1):
+ bom_doc = frappe.new_doc("BOM")
+ bom_doc.item = fg_item.item_code
+ bom_doc.quantity = fg_qty
+ bom_doc.append("items", {
+ "item_code": bom_item.item_code,
+ "qty": 1,
+ "uom": bom_item.stock_uom,
+ "stock_uom": bom_item.stock_uom,
+ "rate": 100.0
+ })
+ bom_doc.append("scrap_items", {
+ "item_code": fg_item.item_code,
+ "qty": scrap_qty,
+ "stock_qty": scrap_qty,
+ "uom": fg_item.stock_uom,
+ "stock_uom": fg_item.stock_uom,
+ "rate": scrap_rate,
+ "is_process_loss": is_process_loss
+ })
+ return bom_doc
+
+def create_process_loss_bom_items():
+ item_list = [
+ ("_Test Item - Non Whole UOM", "Kg"),
+ ("_Test Item - Whole UOM", "Unit"),
+ ( "_Test PL BOM Item", "Unit")
+ ]
+ return [create_process_loss_bom_item(it) for it in item_list]
+
+def create_process_loss_bom_item(item_tuple):
+ item_code, stock_uom = item_tuple
+ if frappe.db.exists("Item", item_code) is None:
+ return make_item(
+ item_code,
+ {'stock_uom':stock_uom, 'valuation_rate':100}
+ )
+ else:
+ return frappe.get_doc("Item", item_code)
diff --git a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_manufacture.js b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_manufacture.js
new file mode 100644
index 0000000..d74f316
--- /dev/null
+++ b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_manufacture.js
@@ -0,0 +1,27 @@
+QUnit.module('Stock');
+
+QUnit.test("test manufacture from bom", function(assert) {
+ assert.expect(2);
+ let done = assert.async();
+ frappe.run_serially([
+ () => {
+ return frappe.tests.make("Stock Entry", [
+ {purpose:"Manufacture"},
+ {from_bom:1},
+ {bom_no:"BOM-_Test Item - Non Whole UOM-001"},
+ {fg_completed_qty:2}
+ ]);
+ },
+ () => cur_frm.save(),
+ () => frappe.click_button("Update Rate and Availability"),
+ () => {
+ assert.ok(cur_frm.doc.items[1] === 0.75, " Finished Item Qty correct");
+ assert.ok(cur_frm.doc.items[2] === 0.25, " Process Loss Item Qty correct");
+ },
+ () => frappe.tests.click_button('Submit'),
+ () => frappe.tests.click_button('Yes'),
+ () => frappe.timeout(0.3),
+ () => done()
+ ]);
+});
+