feat: make fg phantom-able in bom creator (backport #54332) (#54333)

This commit is contained in:
mergify[bot]
2026-04-16 19:17:51 +05:30
committed by GitHub
parent 07bcaab33b
commit 10dbfd310f
3 changed files with 66 additions and 12 deletions

View File

@@ -64,6 +64,13 @@ frappe.ui.form.on("BOM Creator", {
options: "Item", options: "Item",
reqd: 1, reqd: 1,
}, },
{
label: __("Is Phantom BOM"),
fieldtype: "Check",
fieldname: "is_phantom",
default: 0,
change: toggle_filter,
},
{ fieldtype: "Column Break" }, { fieldtype: "Column Break" },
{ {
label: __("Quantity"), label: __("Quantity"),
@@ -72,7 +79,7 @@ frappe.ui.form.on("BOM Creator", {
reqd: 1, reqd: 1,
default: 1.0, default: 1.0,
}, },
{ fieldtype: "Section Break" }, { fieldtype: "Section Break", depends_on: "eval:!doc.is_phantom" },
{ {
label: __("Currency"), label: __("Currency"),
fieldtype: "Link", fieldtype: "Link",
@@ -89,7 +96,7 @@ frappe.ui.form.on("BOM Creator", {
reqd: 1, reqd: 1,
default: 1.0, default: 1.0,
}, },
{ fieldtype: "Section Break" }, { fieldtype: "Section Break", depends_on: "eval:!doc.is_phantom" },
{ {
label: __("Routing"), label: __("Routing"),
fieldtype: "Link", fieldtype: "Link",
@@ -99,14 +106,39 @@ frappe.ui.form.on("BOM Creator", {
], ],
primary_action_label: __("Create"), primary_action_label: __("Create"),
primary_action: (values) => { primary_action: (values) => {
values.doctype = frm.doc.doctype; frappe.db.get_value("Item", values.item_code, "is_stock_item").then((r) => {
frappe.db.insert(values).then((doc) => { if (r.message) {
frappe.set_route("Form", doc.doctype, doc.name); if (r.message.is_stock_item && values.is_phantom) {
frappe.throw(
__("Phantom BOM cannot be created for stock item {0}.", [values.item_code])
);
} else if (!r.message.is_stock_item && !values.is_phantom) {
frappe.throw(
__("Non-phantom BOM cannot be created for non-stock item {0}.", [
values.item_code,
])
);
} else {
values.doctype = frm.doc.doctype;
frappe.db.insert(values).then((doc) => {
frappe.set_route("Form", doc.doctype, doc.name);
});
}
}
}); });
}, },
}); });
dialog.fields_dict.item_code.get_query = "erpnext.controllers.queries.item_query"; function toggle_filter() {
dialog.fields_dict.item_code.get_query = {
query: "erpnext.controllers.queries.item_query",
filters: {
is_stock_item: !dialog.fields_dict.is_phantom.value,
},
};
}
toggle_filter();
dialog.show(); dialog.show();
}, },

View File

@@ -13,6 +13,7 @@
"details_tab", "details_tab",
"section_break_ylsl", "section_break_ylsl",
"item_code", "item_code",
"is_phantom",
"item_name", "item_name",
"item_group", "item_group",
"column_break_ikj7", "column_break_ikj7",
@@ -291,6 +292,13 @@
"fieldtype": "Link", "fieldtype": "Link",
"label": "Routing", "label": "Routing",
"options": "Routing" "options": "Routing"
},
{
"default": "0",
"fieldname": "is_phantom",
"fieldtype": "Check",
"label": "Is Phantom Item",
"read_only": 1
} }
], ],
"hide_toolbar": 1, "hide_toolbar": 1,
@@ -302,7 +310,7 @@
"link_fieldname": "bom_creator" "link_fieldname": "bom_creator"
} }
], ],
"modified": "2024-11-25 16:41:03.047835", "modified": "2026-04-16 17:39:38.232864",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Manufacturing", "module": "Manufacturing",
"name": "BOM Creator", "name": "BOM Creator",
@@ -336,6 +344,7 @@
"write": 1 "write": 1
} }
], ],
"row_format": "Dynamic",
"show_name_in_global_search": 1, "show_name_in_global_search": 1,
"sort_field": "creation", "sort_field": "creation",
"sort_order": "DESC", "sort_order": "DESC",

View File

@@ -52,6 +52,7 @@ class BOMCreator(Document):
currency: DF.Link currency: DF.Link
default_warehouse: DF.Link | None default_warehouse: DF.Link | None
error_log: DF.Text | None error_log: DF.Text | None
is_phantom: DF.Check
item_code: DF.Link item_code: DF.Link
item_group: DF.Link | None item_group: DF.Link | None
item_name: DF.Data | None item_name: DF.Data | None
@@ -77,6 +78,7 @@ class BOMCreator(Document):
self.set_rate_for_items() self.set_rate_for_items()
def validate(self): def validate(self):
self.validate_finished_good()
self.validate_items() self.validate_items()
self.validate_duplicate_item() self.validate_duplicate_item()
@@ -102,6 +104,15 @@ class BOMCreator(Document):
else: else:
item_map[key] = row.idx item_map[key] = row.idx
def validate_finished_good(self):
is_stock_item = frappe.get_cached_value("Item", self.item_code, "is_stock_item")
if is_stock_item and self.is_phantom:
frappe.throw(_("Phantom BOM cannot be created for stock item {0}.").format(self.item_code))
elif not is_stock_item and not self.is_phantom:
frappe.throw(
_("Non-phantom BOM cannot be created for non-stock item {0}.").format(self.item_code)
)
def validate_items(self): def validate_items(self):
for row in self.items: for row in self.items:
if row.is_expandable and row.item_code == self.item_code: if row.is_expandable and row.item_code == self.item_code:
@@ -334,10 +345,12 @@ class BOMCreator(Document):
} }
) )
if row.item_code == self.item_code and (self.routing or self.has_operations()): if row.item_code == self.item_code:
bom.routing = self.routing bom.is_phantom_bom = self.is_phantom
bom.with_operations = 1 if not self.is_phantom and (self.routing or self.has_operations()):
bom.transfer_material_against = "Work Order" bom.routing = self.routing
bom.with_operations = 1
bom.transfer_material_against = "Work Order"
for field in BOM_FIELDS: for field in BOM_FIELDS:
if self.get(field): if self.get(field):