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",
reqd: 1,
},
{
label: __("Is Phantom BOM"),
fieldtype: "Check",
fieldname: "is_phantom",
default: 0,
change: toggle_filter,
},
{ fieldtype: "Column Break" },
{
label: __("Quantity"),
@@ -72,7 +79,7 @@ frappe.ui.form.on("BOM Creator", {
reqd: 1,
default: 1.0,
},
{ fieldtype: "Section Break" },
{ fieldtype: "Section Break", depends_on: "eval:!doc.is_phantom" },
{
label: __("Currency"),
fieldtype: "Link",
@@ -89,7 +96,7 @@ frappe.ui.form.on("BOM Creator", {
reqd: 1,
default: 1.0,
},
{ fieldtype: "Section Break" },
{ fieldtype: "Section Break", depends_on: "eval:!doc.is_phantom" },
{
label: __("Routing"),
fieldtype: "Link",
@@ -99,14 +106,39 @@ frappe.ui.form.on("BOM Creator", {
],
primary_action_label: __("Create"),
primary_action: (values) => {
values.doctype = frm.doc.doctype;
frappe.db.insert(values).then((doc) => {
frappe.set_route("Form", doc.doctype, doc.name);
frappe.db.get_value("Item", values.item_code, "is_stock_item").then((r) => {
if (r.message) {
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();
},

View File

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

View File

@@ -52,6 +52,7 @@ class BOMCreator(Document):
currency: DF.Link
default_warehouse: DF.Link | None
error_log: DF.Text | None
is_phantom: DF.Check
item_code: DF.Link
item_group: DF.Link | None
item_name: DF.Data | None
@@ -77,6 +78,7 @@ class BOMCreator(Document):
self.set_rate_for_items()
def validate(self):
self.validate_finished_good()
self.validate_items()
self.validate_duplicate_item()
@@ -102,6 +104,15 @@ class BOMCreator(Document):
else:
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):
for row in self.items:
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()):
bom.routing = self.routing
bom.with_operations = 1
bom.transfer_material_against = "Work Order"
if row.item_code == self.item_code:
bom.is_phantom_bom = self.is_phantom
if not self.is_phantom and (self.routing or self.has_operations()):
bom.routing = self.routing
bom.with_operations = 1
bom.transfer_material_against = "Work Order"
for field in BOM_FIELDS:
if self.get(field):