mirror of
https://github.com/frappe/erpnext.git
synced 2026-02-15 23:54:59 +00:00
Merge pull request #49123 from rohitwaghchaure/fixed-sub-assembl-in-pp
fix: do not fetch sub-assembly in PP
This commit is contained in:
@@ -76,6 +76,8 @@ frappe.ui.form.on("BOM", {
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
frm.trigger("toggle_fields_for_semi_finished_goods");
|
||||
},
|
||||
|
||||
validate: function (frm) {
|
||||
@@ -87,8 +89,27 @@ frappe.ui.form.on("BOM", {
|
||||
}
|
||||
},
|
||||
|
||||
track_semi_finished_goods(frm) {
|
||||
frm.trigger("toggle_fields_for_semi_finished_goods");
|
||||
},
|
||||
|
||||
toggle_fields_for_semi_finished_goods(frm) {
|
||||
let fields = ["finished_good", "finished_good_qty", "bom_no"];
|
||||
|
||||
fields.forEach((field) => {
|
||||
frm.fields_dict["operations"].grid.update_docfield_property(
|
||||
field,
|
||||
"read_only",
|
||||
!frm.doc.track_semi_finished_goods
|
||||
);
|
||||
});
|
||||
|
||||
refresh_field("operations");
|
||||
},
|
||||
|
||||
with_operations: function (frm) {
|
||||
frm.set_df_property("fg_based_operating_cost", "hidden", frm.doc.with_operations ? 1 : 0);
|
||||
frm.trigger("toggle_fields_for_semi_finished_goods");
|
||||
},
|
||||
|
||||
fg_based_operating_cost: function (frm) {
|
||||
@@ -929,6 +950,19 @@ frappe.ui.form.on("BOM", {
|
||||
},
|
||||
});
|
||||
|
||||
let items = frm.doc.items.filter((item) => cint(item.operation_row_id) === cint(row.idx));
|
||||
if (items?.length) {
|
||||
items.forEach((item) => {
|
||||
frm._bom_rm_dialog.fields_dict.items.df.data.push({
|
||||
item_code: item.item_code,
|
||||
qty: item.qty,
|
||||
name: item.name,
|
||||
});
|
||||
});
|
||||
|
||||
frm._bom_rm_dialog.fields_dict.items.grid.refresh();
|
||||
}
|
||||
|
||||
frm._bom_rm_dialog.show();
|
||||
},
|
||||
|
||||
@@ -938,6 +972,7 @@ frappe.ui.form.on("BOM", {
|
||||
label: __("Raw Materials"),
|
||||
fieldname: "items",
|
||||
fieldtype: "Table",
|
||||
data: [],
|
||||
reqd: 1,
|
||||
fields: [
|
||||
{
|
||||
|
||||
@@ -722,12 +722,43 @@ class BOM(WebsiteGenerator):
|
||||
|
||||
row.update(get_item_details(row.get("item_code")))
|
||||
row.operation_row_id = operation_row_id
|
||||
row.idx = None
|
||||
row.name = None
|
||||
self.append("items", row)
|
||||
|
||||
item_row = None
|
||||
if row.name:
|
||||
item_row = self.get_item_data(row.name)
|
||||
|
||||
if item_row:
|
||||
item_row.update(
|
||||
{
|
||||
"item_code": row.get("item_code"),
|
||||
"qty": row.get("qty"),
|
||||
}
|
||||
)
|
||||
else:
|
||||
row.idx = None
|
||||
row.name = None
|
||||
row.do_not_explode = 1
|
||||
row.is_sub_assembly_item = self.is_sub_assembly_item(row.item_code)
|
||||
|
||||
self.append("items", row)
|
||||
|
||||
self.save()
|
||||
|
||||
def is_sub_assembly_item(self, item_code):
|
||||
if not self.operations:
|
||||
return False
|
||||
|
||||
for row in self.operations:
|
||||
if row.finished_good == item_code:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def get_item_data(self, name):
|
||||
for row in self.items:
|
||||
if row.item_code == name:
|
||||
return row
|
||||
|
||||
@frappe.whitelist()
|
||||
def add_materials_from_bom(self, finished_good, bom_no, operation_row_id, qty=None):
|
||||
if not frappe.db.exists("BOM", {"item": finished_good, "name": bom_no, "docstatus": 1}):
|
||||
@@ -745,6 +776,9 @@ class BOM(WebsiteGenerator):
|
||||
row.uom = row.stock_uom
|
||||
row.operation_row_id = operation_row_id
|
||||
row.idx = None
|
||||
row.do_not_explode = 1
|
||||
row.is_sub_assembly_item = self.is_sub_assembly_item(row.item_code)
|
||||
|
||||
self.append("items", row)
|
||||
|
||||
def traverse_tree(self, bom_list=None):
|
||||
@@ -946,6 +980,7 @@ class BOM(WebsiteGenerator):
|
||||
"item_code": d.item_code,
|
||||
"item_name": d.item_name,
|
||||
"operation": d.operation,
|
||||
"is_sub_assembly_item": d.is_sub_assembly_item,
|
||||
"source_warehouse": d.source_warehouse,
|
||||
"description": d.description,
|
||||
"image": d.image,
|
||||
@@ -978,6 +1013,7 @@ class BOM(WebsiteGenerator):
|
||||
bom_item.description,
|
||||
bom_item.source_warehouse,
|
||||
bom_item.operation,
|
||||
bom_item.is_sub_assembly_item,
|
||||
bom_item.stock_uom,
|
||||
bom_item.stock_qty,
|
||||
bom_item.rate,
|
||||
@@ -1008,6 +1044,7 @@ class BOM(WebsiteGenerator):
|
||||
"rate": flt(d["rate"]),
|
||||
"include_item_in_manufacturing": d.get("include_item_in_manufacturing", 0),
|
||||
"sourced_by_supplier": d.get("sourced_by_supplier", 0),
|
||||
"is_sub_assembly_item": d.get("is_sub_assembly_item", 0),
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
"stock_uom",
|
||||
"amount",
|
||||
"include_item_in_manufacturing",
|
||||
"sourced_by_supplier"
|
||||
"sourced_by_supplier",
|
||||
"is_sub_assembly_item"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@@ -165,21 +166,30 @@
|
||||
"fieldtype": "Check",
|
||||
"label": "Sourced by Supplier",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "is_sub_assembly_item",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Sub Assembly Item",
|
||||
"no_copy": 1,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:06:40.935882",
|
||||
"modified": "2025-08-12 20:02:32.694836",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM Explosion Item",
|
||||
"naming_rule": "Random",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"row_format": "Dynamic",
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ class BOMExplosionItem(Document):
|
||||
description: DF.TextEditor | None
|
||||
image: DF.Attach | None
|
||||
include_item_in_manufacturing: DF.Check
|
||||
is_sub_assembly_item: DF.Check
|
||||
item_code: DF.Link | None
|
||||
item_name: DF.Data | None
|
||||
operation: DF.Link | None
|
||||
|
||||
@@ -41,7 +41,8 @@
|
||||
"include_item_in_manufacturing",
|
||||
"original_item",
|
||||
"column_break_33",
|
||||
"sourced_by_supplier"
|
||||
"sourced_by_supplier",
|
||||
"is_sub_assembly_item"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@@ -300,19 +301,28 @@
|
||||
"fieldname": "operation_row_id",
|
||||
"fieldtype": "Int",
|
||||
"label": "Operation ID"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "is_sub_assembly_item",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Sub Assembly Item",
|
||||
"no_copy": 1,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:08:41.079752",
|
||||
"modified": "2025-08-12 20:01:59.532613",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM Item",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"row_format": "Dynamic",
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ class BOMItem(Document):
|
||||
image: DF.Attach | None
|
||||
include_item_in_manufacturing: DF.Check
|
||||
is_stock_item: DF.Check
|
||||
is_sub_assembly_item: DF.Check
|
||||
item_code: DF.Link
|
||||
item_name: DF.Data | None
|
||||
operation: DF.Link | None
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"columns": 2,
|
||||
"fieldname": "operation",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
@@ -53,9 +54,11 @@
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"depends_on": "eval:!doc.workstation_type",
|
||||
"fieldname": "workstation",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Workstation",
|
||||
"oldfieldname": "workstation",
|
||||
"oldfieldtype": "Link",
|
||||
@@ -83,7 +86,7 @@
|
||||
"precision": "2"
|
||||
},
|
||||
{
|
||||
"columns": 1,
|
||||
"columns": 3,
|
||||
"description": "In minutes",
|
||||
"fetch_from": "operation.total_operation_time",
|
||||
"fetch_if_empty": 1,
|
||||
@@ -191,7 +194,7 @@
|
||||
"label": "Set Operating Cost Based On BOM Quantity"
|
||||
},
|
||||
{
|
||||
"columns": 1,
|
||||
"columns": 3,
|
||||
"fieldname": "workstation_type",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
@@ -199,26 +202,31 @@
|
||||
"options": "Workstation Type"
|
||||
},
|
||||
{
|
||||
"columns": 3,
|
||||
"depends_on": "eval:parent.track_semi_finished_goods === 1",
|
||||
"fieldname": "finished_good",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Finished Goods / Semi Finished Goods Item",
|
||||
"label": "FG / Semi FG Item",
|
||||
"options": "Item"
|
||||
},
|
||||
{
|
||||
"columns": 1,
|
||||
"columns": 2,
|
||||
"depends_on": "eval:parent.track_semi_finished_goods === 1",
|
||||
"fieldname": "bom_no",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "BOM No",
|
||||
"options": "BOM"
|
||||
},
|
||||
{
|
||||
"columns": 1,
|
||||
"columns": 2,
|
||||
"default": "1",
|
||||
"depends_on": "eval:parent.track_semi_finished_goods === 1",
|
||||
"fieldname": "finished_good_qty",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Finished Goods Qty"
|
||||
"label": "Qty to Produce"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
@@ -264,7 +272,7 @@
|
||||
"label": "Is Subcontracted"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:!doc.bom_no",
|
||||
"depends_on": "eval:!doc.bom_no && parent.track_semi_finished_goods === 1",
|
||||
"fieldname": "add_raw_materials",
|
||||
"fieldtype": "Button",
|
||||
"label": "Add Raw Materials"
|
||||
@@ -287,7 +295,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-07-31 16:17:47.287117",
|
||||
"modified": "2025-08-12 19:27:20.682797",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM Operation",
|
||||
|
||||
@@ -425,7 +425,6 @@
|
||||
"fieldname": "sub_assembly_warehouse",
|
||||
"fieldtype": "Link",
|
||||
"label": "Sub Assembly Warehouse",
|
||||
"mandatory_depends_on": "eval:doc.skip_available_sub_assembly_item === 1",
|
||||
"options": "Warehouse"
|
||||
},
|
||||
{
|
||||
@@ -446,7 +445,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-05-09 18:55:45.500257",
|
||||
"modified": "2025-08-12 19:48:09.302503",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Production Plan",
|
||||
|
||||
@@ -1001,6 +1001,7 @@ class ProductionPlan(Document):
|
||||
sub_assembly_items_store = [] # temporary store to process all subassembly items
|
||||
bin_details = frappe._dict()
|
||||
|
||||
track_semi_finished_goods = True
|
||||
for row in self.po_items:
|
||||
if self.skip_available_sub_assembly_item and not self.sub_assembly_warehouse:
|
||||
frappe.throw(_("Row #{0}: Please select the Sub Assembly Warehouse").format(row.idx))
|
||||
@@ -1011,8 +1012,18 @@ class ProductionPlan(Document):
|
||||
if not row.bom_no:
|
||||
frappe.throw(_("Row #{0}: Please select the BOM No in Assembly Items").format(row.idx))
|
||||
|
||||
if frappe.db.get_value("BOM", row.bom_no, "track_semi_finished_goods"):
|
||||
frappe.msgprint(
|
||||
_(
|
||||
"Row #{0}: Since 'Track Semi Finished Goods' is enabled, the BOM {1} cannot be used for Sub Assembly Items"
|
||||
).format(row.idx, row.bom_no)
|
||||
)
|
||||
continue
|
||||
|
||||
bom_data = []
|
||||
|
||||
track_semi_finished_goods = False
|
||||
|
||||
get_sub_assembly_items(
|
||||
[item.production_item for item in sub_assembly_items_store],
|
||||
bin_details,
|
||||
@@ -1026,7 +1037,11 @@ class ProductionPlan(Document):
|
||||
self.set_sub_assembly_items_based_on_level(row, bom_data, manufacturing_type)
|
||||
sub_assembly_items_store.extend(bom_data)
|
||||
|
||||
if not sub_assembly_items_store and self.skip_available_sub_assembly_item:
|
||||
if (
|
||||
not track_semi_finished_goods
|
||||
and not sub_assembly_items_store
|
||||
and self.skip_available_sub_assembly_item
|
||||
):
|
||||
message = (
|
||||
_(
|
||||
"As there are sufficient Sub Assembly Items, Work Order is not required for Warehouse {0}."
|
||||
@@ -1253,6 +1268,7 @@ def get_exploded_items(item_details, company, bom_no, include_non_stock_items, p
|
||||
)
|
||||
.where(
|
||||
(bei.docstatus < 2)
|
||||
& (bei.is_sub_assembly_item == 0)
|
||||
& (bom.name == bom_no)
|
||||
& (item.is_stock_item.isin([0, 1]) if include_non_stock_items else item.is_stock_item == 1)
|
||||
)
|
||||
@@ -1321,6 +1337,7 @@ def get_subitems(
|
||||
)
|
||||
.where(
|
||||
(bom.name == bom_no)
|
||||
& (bom_item.is_sub_assembly_item == 0)
|
||||
& (bom_item.docstatus < 2)
|
||||
& (item.is_stock_item.isin([0, 1]) if include_non_stock_items else item.is_stock_item == 1)
|
||||
)
|
||||
@@ -2003,6 +2020,7 @@ def get_raw_materials_of_sub_assembly_items(
|
||||
)
|
||||
.where(
|
||||
(bei.docstatus == 1)
|
||||
& (bei.is_sub_assembly_item == 0)
|
||||
& (bom.name == bom_no)
|
||||
& (item.is_stock_item.isin([0, 1]) if include_non_stock_items else item.is_stock_item == 1)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user