diff --git a/erpnext/manufacturing/doctype/bom_creator/bom_creator.js b/erpnext/manufacturing/doctype/bom_creator/bom_creator.js index 2c4b786ef428b..01dc89b080268 100644 --- a/erpnext/manufacturing/doctype/bom_creator/bom_creator.js +++ b/erpnext/manufacturing/doctype/bom_creator/bom_creator.js @@ -13,23 +13,30 @@ frappe.ui.form.on("BOM Creator", { if (!frm.is_new()) { if ((!frappe.bom_configurator || frappe.bom_configurator.bom_configurator !== frm.doc.name)) { - let $parent = $(frm.fields_dict["bom_creator"].wrapper); - $parent.empty(); - - frappe.require('bom_configurator.bundle.js').then(() => { - frappe.bom_configurator = new frappe.ui.BOMConfigurator({ - wrapper: $parent, - page: $parent, - frm: frm, - bom_configurator: frm.doc.name, - }); - }); + frm.trigger("build_tree"); } } else { + let $parent = $(frm.fields_dict["bom_creator"].wrapper); + $parent.empty(); frm.trigger("make_new_entry"); } }, + build_tree(frm) { + let $parent = $(frm.fields_dict["bom_creator"].wrapper); + $parent.empty(); + frm.toggle_enable("item_code", false); + + frappe.require('bom_configurator.bundle.js').then(() => { + frappe.bom_configurator = new frappe.ui.BOMConfigurator({ + wrapper: $parent, + page: $parent, + frm: frm, + bom_configurator: frm.doc.name, + }); + }); + }, + make_new_entry(frm) { let dialog = new frappe.ui.Dialog({ title: __("Multi-level BOM Creator"), @@ -122,7 +129,11 @@ frappe.ui.form.on("BOM Creator", { }, add_custom_buttons(frm) { - // + if (!frm.is_new()) { + frm.add_custom_button(__("Rebuild Tree"), () => { + frm.trigger("build_tree"); + }); + } } }); diff --git a/erpnext/manufacturing/doctype/bom_creator/bom_creator.py b/erpnext/manufacturing/doctype/bom_creator/bom_creator.py index 1791f8ba3a638..999d610dfae5f 100644 --- a/erpnext/manufacturing/doctype/bom_creator/bom_creator.py +++ b/erpnext/manufacturing/doctype/bom_creator/bom_creator.py @@ -34,11 +34,19 @@ class BOMCreator(Document): def before_save(self): self.set_status() + self.set_is_expandable() self.set_conversion_factor() self.set_reference_id() - self.set_is_expandable() self.set_rate_for_items() + def validate(self): + self.validate_items() + + def validate_items(self): + for row in self.items: + if row.is_expandable and row.item_code == self.item_code: + frappe.throw(_("Item {0} cannot be added as a sub-assembly of itself").format(row.item_code)) + def set_status(self, save=False): self.status = { 0: "Draft", @@ -135,7 +143,7 @@ def get_raw_material_cost(self, fg_reference_id=None, amount=0): return amount def set_is_expandable(self): - fg_items = [row.fg_item for row in self.items] + fg_items = [row.fg_item for row in self.items if row.fg_item != self.item_code] for row in self.items: row.is_expandable = 0 if row.item_code in fg_items: @@ -231,6 +239,7 @@ def create_bom(self, row, production_item_wise_rm): for item in production_item_wise_rm[(row.item_code, row.name)]["items"]: bom_no = "" + item.do_not_explode = 1 if (item.item_code, item.name) in production_item_wise_rm: bom_no = production_item_wise_rm.get((item.item_code, item.name)).bom_no item.do_not_explode = 0 @@ -343,6 +352,7 @@ def add_sub_assembly(**kwargs): "stock_qty": bom_item.qty, "fg_reference_id": name, "do_not_explode": 1, + "is_expandable": 1, "stock_uom": item_info.stock_uom, }, ) @@ -405,5 +415,10 @@ def delete_node(**kwargs): @frappe.whitelist() -def edit_qty(doctype, docname, qty): +def edit_qty(doctype, docname, qty, parent): frappe.db.set_value(doctype, docname, "qty", qty) + doc = frappe.get_doc("BOM Creator", parent) + doc.set_rate_for_items() + doc.save() + + return doc diff --git a/erpnext/public/js/bom_configurator/bom_configurator.bundle.js b/erpnext/public/js/bom_configurator/bom_configurator.bundle.js index 6b0181a38ff19..b3b2e9f9b86fd 100644 --- a/erpnext/public/js/bom_configurator/bom_configurator.bundle.js +++ b/erpnext/public/js/bom_configurator/bom_configurator.bundle.js @@ -30,14 +30,15 @@ class BOMConfigurator { bind_events() { frappe.views.trees["BOM Configurator"].events = { + frm: this.frm, add_item: this.add_item, add_sub_assembly: this.add_sub_assembly, get_sub_assembly_modal_fields: this.get_sub_assembly_modal_fields, convert_to_sub_assembly: this.convert_to_sub_assembly, delete_node: this.delete_node, edit_qty: this.edit_qty, - frm: this.frm, load_tree: this.load_tree, + set_default_qty: this.set_default_qty, } } @@ -93,9 +94,8 @@ class BOMConfigurator { display: inline-flex; min-width: 128px; border: 1px solid var(--bg-gray); - " - data-bom-qty-docname="${docname}"> -