mirror of
https://github.com/frappe/erpnext.git
synced 2026-04-21 07:38:29 +00:00
Co-authored-by: Mihir Kandoi <kandoimihir@gmail.com>
This commit is contained in:
@@ -829,7 +829,7 @@ erpnext.work_order = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (counter > 0) {
|
if (counter > 0) {
|
||||||
var consumption_btn = frm.add_custom_button(
|
frm.add_custom_button(
|
||||||
__("Material Consumption"),
|
__("Material Consumption"),
|
||||||
function () {
|
function () {
|
||||||
const backflush_raw_materials_based_on =
|
const backflush_raw_materials_based_on =
|
||||||
|
|||||||
@@ -938,7 +938,9 @@ class StockEntry(StockController, SubcontractingInwardController):
|
|||||||
if matched_item := self.get_matched_items(item_code):
|
if matched_item := self.get_matched_items(item_code):
|
||||||
if flt(details.get("qty"), precision) != flt(matched_item.qty, precision):
|
if flt(details.get("qty"), precision) != flt(matched_item.qty, precision):
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("For the item {0}, the quantity should be {1} according to the BOM {2}.").format(
|
_(
|
||||||
|
"For the item {0}, the consumed quantity should be {1} according to the BOM {2}."
|
||||||
|
).format(
|
||||||
frappe.bold(item_code),
|
frappe.bold(item_code),
|
||||||
flt(details.get("qty")),
|
flt(details.get("qty")),
|
||||||
get_link_to_form("BOM", self.bom_no),
|
get_link_to_form("BOM", self.bom_no),
|
||||||
@@ -1003,12 +1005,37 @@ class StockEntry(StockController, SubcontractingInwardController):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def get_matched_items(self, item_code):
|
def get_matched_items(self, item_code):
|
||||||
for row in self.items:
|
items = [item for item in self.items if item.s_warehouse]
|
||||||
|
for row in items or self.get_consumed_items():
|
||||||
if row.item_code == item_code or row.original_item == item_code:
|
if row.item_code == item_code or row.original_item == item_code:
|
||||||
return row
|
return row
|
||||||
|
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
def get_consumed_items(self):
|
||||||
|
"""Get all raw materials consumed through consumption entries"""
|
||||||
|
parent = frappe.qb.DocType("Stock Entry")
|
||||||
|
child = frappe.qb.DocType("Stock Entry Detail")
|
||||||
|
|
||||||
|
query = (
|
||||||
|
frappe.qb.from_(parent)
|
||||||
|
.join(child)
|
||||||
|
.on(parent.name == child.parent)
|
||||||
|
.select(
|
||||||
|
child.item_code,
|
||||||
|
Sum(child.qty).as_("qty"),
|
||||||
|
child.original_item,
|
||||||
|
)
|
||||||
|
.where(
|
||||||
|
(parent.docstatus == 1)
|
||||||
|
& (parent.purpose == "Material Consumption for Manufacture")
|
||||||
|
& (parent.work_order == self.work_order)
|
||||||
|
)
|
||||||
|
.groupby(child.item_code, child.original_item)
|
||||||
|
)
|
||||||
|
|
||||||
|
return query.run(as_dict=True)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_stock_and_rate(self):
|
def get_stock_and_rate(self):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -2362,6 +2362,33 @@ class TestStockEntry(IntegrationTestCase):
|
|||||||
self.assertEqual(target_sabb.entries[0].batch_no, batch)
|
self.assertEqual(target_sabb.entries[0].batch_no, batch)
|
||||||
self.assertEqual([entry.serial_no for entry in target_sabb.entries], serial_nos[:2])
|
self.assertEqual([entry.serial_no for entry in target_sabb.entries], serial_nos[:2])
|
||||||
|
|
||||||
|
@IntegrationTestCase.change_settings(
|
||||||
|
"Manufacturing Settings",
|
||||||
|
{
|
||||||
|
"material_consumption": 1,
|
||||||
|
"backflush_raw_materials_based_on": "BOM",
|
||||||
|
"validate_components_quantities_per_bom": 1,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
def test_validation_as_per_bom_with_continuous_raw_material_consumption(self):
|
||||||
|
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
|
||||||
|
from erpnext.manufacturing.doctype.work_order.work_order import make_stock_entry as _make_stock_entry
|
||||||
|
from erpnext.manufacturing.doctype.work_order.work_order import make_work_order
|
||||||
|
|
||||||
|
fg_item = make_item("_Mobiles", properties={"is_stock_item": 1}).name
|
||||||
|
rm_item1 = make_item("_Battery", properties={"is_stock_item": 1}).name
|
||||||
|
warehouse = "Stores - WP"
|
||||||
|
bom_no = make_bom(item=fg_item, raw_materials=[rm_item1]).name
|
||||||
|
make_stock_entry(item_code=rm_item1, target=warehouse, qty=5, rate=10, purpose="Material Receipt")
|
||||||
|
|
||||||
|
work_order = make_work_order(bom_no, fg_item, 5)
|
||||||
|
work_order.skip_transfer = 1
|
||||||
|
work_order.fg_warehouse = warehouse
|
||||||
|
work_order.submit()
|
||||||
|
|
||||||
|
frappe.get_doc(_make_stock_entry(work_order.name, "Material Consumption for Manufacture", 5)).submit()
|
||||||
|
frappe.get_doc(_make_stock_entry(work_order.name, "Manufacture", 5)).submit()
|
||||||
|
|
||||||
|
|
||||||
def make_serialized_item(self, **args):
|
def make_serialized_item(self, **args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
|
|||||||
Reference in New Issue
Block a user