mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-06 21:59:13 +00:00
fix: item none not found (#44324)
This commit is contained in:
@@ -29,7 +29,6 @@ frappe.ui.form.on("BOM", {
|
|||||||
item: row.finished_good,
|
item: row.finished_good,
|
||||||
is_active: 1,
|
is_active: 1,
|
||||||
docstatus: 1,
|
docstatus: 1,
|
||||||
track_semi_finished_goods: 0,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -886,7 +886,7 @@ class BOM(WebsiteGenerator):
|
|||||||
self.cur_exploded_items = {}
|
self.cur_exploded_items = {}
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
if d.bom_no:
|
if d.bom_no:
|
||||||
self.get_child_exploded_items(d.bom_no, d.stock_qty)
|
self.get_child_exploded_items(d.bom_no, d.stock_qty, d.operation)
|
||||||
elif d.item_code:
|
elif d.item_code:
|
||||||
self.add_to_cur_exploded_items(
|
self.add_to_cur_exploded_items(
|
||||||
frappe._dict(
|
frappe._dict(
|
||||||
@@ -915,7 +915,7 @@ class BOM(WebsiteGenerator):
|
|||||||
else:
|
else:
|
||||||
self.cur_exploded_items[args.item_code] = args
|
self.cur_exploded_items[args.item_code] = args
|
||||||
|
|
||||||
def get_child_exploded_items(self, bom_no, stock_qty):
|
def get_child_exploded_items(self, bom_no, stock_qty, operation=None):
|
||||||
"""Add all items from Flat BOM of child BOM"""
|
"""Add all items from Flat BOM of child BOM"""
|
||||||
# Did not use qty_consumed_per_unit in the query, as it leads to rounding loss
|
# Did not use qty_consumed_per_unit in the query, as it leads to rounding loss
|
||||||
child_fb_items = frappe.db.sql(
|
child_fb_items = frappe.db.sql(
|
||||||
@@ -949,7 +949,7 @@ class BOM(WebsiteGenerator):
|
|||||||
"item_code": d["item_code"],
|
"item_code": d["item_code"],
|
||||||
"item_name": d["item_name"],
|
"item_name": d["item_name"],
|
||||||
"source_warehouse": d["source_warehouse"],
|
"source_warehouse": d["source_warehouse"],
|
||||||
"operation": d["operation"],
|
"operation": d["operation"] or operation,
|
||||||
"description": d["description"],
|
"description": d["description"],
|
||||||
"stock_uom": d["stock_uom"],
|
"stock_uom": d["stock_uom"],
|
||||||
"stock_qty": d["qty_consumed_per_unit"] * stock_qty,
|
"stock_qty": d["qty_consumed_per_unit"] * stock_qty,
|
||||||
|
|||||||
@@ -98,8 +98,6 @@ frappe.ui.form.on("BOM Creator", {
|
|||||||
],
|
],
|
||||||
primary_action_label: __("Create"),
|
primary_action_label: __("Create"),
|
||||||
primary_action: (values) => {
|
primary_action: (values) => {
|
||||||
frm.events.validate_dialog_values(frm, values);
|
|
||||||
|
|
||||||
values.doctype = frm.doc.doctype;
|
values.doctype = frm.doc.doctype;
|
||||||
frappe.db.insert(values).then((doc) => {
|
frappe.db.insert(values).then((doc) => {
|
||||||
frappe.set_route("Form", doc.doctype, doc.name);
|
frappe.set_route("Form", doc.doctype, doc.name);
|
||||||
@@ -111,18 +109,6 @@ frappe.ui.form.on("BOM Creator", {
|
|||||||
dialog.show();
|
dialog.show();
|
||||||
},
|
},
|
||||||
|
|
||||||
validate_dialog_values(frm, values) {
|
|
||||||
if (values.track_semi_finished_goods) {
|
|
||||||
if (values.final_operation_time <= 0) {
|
|
||||||
frappe.throw(__("Operation Time must be greater than 0"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!values.workstation && !values.workstation_type) {
|
|
||||||
frappe.throw(__("Either Workstation or Workstation Type is mandatory"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
set_queries(frm) {
|
set_queries(frm) {
|
||||||
frm.set_query("bom_no", "items", function (doc, cdt, cdn) {
|
frm.set_query("bom_no", "items", function (doc, cdt, cdn) {
|
||||||
let item = frappe.get_doc(cdt, cdn);
|
let item = frappe.get_doc(cdt, cdn);
|
||||||
|
|||||||
@@ -39,23 +39,6 @@
|
|||||||
"items",
|
"items",
|
||||||
"costing_detail",
|
"costing_detail",
|
||||||
"raw_material_cost",
|
"raw_material_cost",
|
||||||
"configuration_section",
|
|
||||||
"track_operations",
|
|
||||||
"column_break_obzr",
|
|
||||||
"track_semi_finished_goods",
|
|
||||||
"final_product_operation_section",
|
|
||||||
"operation",
|
|
||||||
"operation_time",
|
|
||||||
"column_break_xnlu",
|
|
||||||
"workstation_type",
|
|
||||||
"workstation",
|
|
||||||
"final_product_warehouse_section",
|
|
||||||
"skip_material_transfer",
|
|
||||||
"backflush_from_wip_warehouse",
|
|
||||||
"source_warehouse",
|
|
||||||
"column_break_buha",
|
|
||||||
"wip_warehouse",
|
|
||||||
"fg_warehouse",
|
|
||||||
"remarks_tab",
|
"remarks_tab",
|
||||||
"remarks",
|
"remarks",
|
||||||
"section_break_yixm",
|
"section_break_yixm",
|
||||||
@@ -298,104 +281,6 @@
|
|||||||
"label": "Error Log",
|
"label": "Error Log",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "configuration_section",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"label": "Operation"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"depends_on": "track_operations",
|
|
||||||
"fieldname": "track_semi_finished_goods",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"label": "Track Semi Finished Goods"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_obzr",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"fieldname": "track_operations",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"label": "Track Operations"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval:doc.track_semi_finished_goods === 1",
|
|
||||||
"fieldname": "final_product_operation_section",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"label": "Final Product Operation & Workstation"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_xnlu",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "operation",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Operation",
|
|
||||||
"options": "Operation"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "operation_time",
|
|
||||||
"fieldtype": "Float",
|
|
||||||
"label": "Operation Time (in mins)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "workstation",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Workstation",
|
|
||||||
"options": "Workstation"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "workstation_type",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Workstation Type",
|
|
||||||
"options": "Workstation Type"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval:!doc.backflush_from_wip_warehouse",
|
|
||||||
"fieldname": "source_warehouse",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Source Warehouse",
|
|
||||||
"options": "Warehouse"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval:!doc.skip_material_transfer || doc.backflush_from_wip_warehouse",
|
|
||||||
"fieldname": "wip_warehouse",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Work In Progress Warehouse",
|
|
||||||
"options": "Warehouse"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "fg_warehouse",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Finished Good Warehouse",
|
|
||||||
"options": "Warehouse"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval:doc.track_semi_finished_goods === 1",
|
|
||||||
"fieldname": "final_product_warehouse_section",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"label": "Final Product Warehouse"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"fieldname": "skip_material_transfer",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"label": "Skip Material Transfer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"depends_on": "eval:doc.skip_material_transfer",
|
|
||||||
"fieldname": "backflush_from_wip_warehouse",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"label": "Backflush Materials From WIP Warehouse"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_buha",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "section_break_xvld",
|
"fieldname": "section_break_xvld",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
@@ -417,7 +302,7 @@
|
|||||||
"link_fieldname": "bom_creator"
|
"link_fieldname": "bom_creator"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2024-09-26 17:07:32.111198",
|
"modified": "2024-11-25 16:41:03.047835",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "BOM Creator",
|
"name": "BOM Creator",
|
||||||
|
|||||||
@@ -44,20 +44,16 @@ class BOMCreator(Document):
|
|||||||
from erpnext.manufacturing.doctype.bom_creator_item.bom_creator_item import BOMCreatorItem
|
from erpnext.manufacturing.doctype.bom_creator_item.bom_creator_item import BOMCreatorItem
|
||||||
|
|
||||||
amended_from: DF.Link | None
|
amended_from: DF.Link | None
|
||||||
backflush_from_wip_warehouse: DF.Check
|
|
||||||
buying_price_list: DF.Link | None
|
buying_price_list: DF.Link | None
|
||||||
company: DF.Link
|
company: DF.Link
|
||||||
conversion_rate: DF.Float
|
conversion_rate: DF.Float
|
||||||
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
|
||||||
fg_warehouse: DF.Link | None
|
|
||||||
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
|
||||||
items: DF.Table[BOMCreatorItem]
|
items: DF.Table[BOMCreatorItem]
|
||||||
operation: DF.Link | None
|
|
||||||
operation_time: DF.Float
|
|
||||||
plc_conversion_rate: DF.Float
|
plc_conversion_rate: DF.Float
|
||||||
price_list_currency: DF.Link | None
|
price_list_currency: DF.Link | None
|
||||||
project: DF.Link | None
|
project: DF.Link | None
|
||||||
@@ -67,15 +63,8 @@ class BOMCreator(Document):
|
|||||||
rm_cost_as_per: DF.Literal["Valuation Rate", "Last Purchase Rate", "Price List"]
|
rm_cost_as_per: DF.Literal["Valuation Rate", "Last Purchase Rate", "Price List"]
|
||||||
routing: DF.Link | None
|
routing: DF.Link | None
|
||||||
set_rate_based_on_warehouse: DF.Check
|
set_rate_based_on_warehouse: DF.Check
|
||||||
skip_material_transfer: DF.Check
|
|
||||||
source_warehouse: DF.Link | None
|
|
||||||
status: DF.Literal["Draft", "Submitted", "In Progress", "Completed", "Failed", "Cancelled"]
|
status: DF.Literal["Draft", "Submitted", "In Progress", "Completed", "Failed", "Cancelled"]
|
||||||
track_operations: DF.Check
|
|
||||||
track_semi_finished_goods: DF.Check
|
|
||||||
uom: DF.Link | None
|
uom: DF.Link | None
|
||||||
wip_warehouse: DF.Link | None
|
|
||||||
workstation: DF.Link | None
|
|
||||||
workstation_type: DF.Link | None
|
|
||||||
# end: auto-generated types
|
# end: auto-generated types
|
||||||
|
|
||||||
def before_save(self):
|
def before_save(self):
|
||||||
@@ -272,15 +261,9 @@ class BOMCreator(Document):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
for d in reverse_tree:
|
for d in reverse_tree:
|
||||||
if self.track_operations and self.track_semi_finished_goods and final_product == d:
|
|
||||||
continue
|
|
||||||
|
|
||||||
fg_item_data = production_item_wise_rm.get(d).fg_item_data
|
fg_item_data = production_item_wise_rm.get(d).fg_item_data
|
||||||
self.create_bom(fg_item_data, production_item_wise_rm)
|
self.create_bom(fg_item_data, production_item_wise_rm)
|
||||||
|
|
||||||
if self.track_operations and self.track_semi_finished_goods:
|
|
||||||
self.make_bom_for_final_product(production_item_wise_rm)
|
|
||||||
|
|
||||||
frappe.msgprint(_("BOMs created successfully"))
|
frappe.msgprint(_("BOMs created successfully"))
|
||||||
except Exception:
|
except Exception:
|
||||||
traceback = frappe.get_traceback(with_context=True)
|
traceback = frappe.get_traceback(with_context=True)
|
||||||
@@ -293,81 +276,6 @@ class BOMCreator(Document):
|
|||||||
|
|
||||||
frappe.msgprint(_("BOMs creation failed"))
|
frappe.msgprint(_("BOMs creation failed"))
|
||||||
|
|
||||||
def make_bom_for_final_product(self, production_item_wise_rm):
|
|
||||||
bom = frappe.new_doc("BOM")
|
|
||||||
bom.update(
|
|
||||||
{
|
|
||||||
"item": self.item_code,
|
|
||||||
"bom_type": "Production",
|
|
||||||
"quantity": self.qty,
|
|
||||||
"allow_alternative_item": 1,
|
|
||||||
"bom_creator": self.name,
|
|
||||||
"bom_creator_item": self.name,
|
|
||||||
"rm_cost_as_per": "Manual",
|
|
||||||
"with_operations": 1,
|
|
||||||
"track_semi_finished_goods": 1,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
for field in BOM_FIELDS:
|
|
||||||
if self.get(field):
|
|
||||||
bom.set(field, self.get(field))
|
|
||||||
|
|
||||||
for item in self.items:
|
|
||||||
if not item.is_expandable or not item.operation:
|
|
||||||
continue
|
|
||||||
|
|
||||||
bom.append(
|
|
||||||
"operations",
|
|
||||||
{
|
|
||||||
"operation": item.operation,
|
|
||||||
"workstation": item.workstation,
|
|
||||||
"source_warehouse": item.source_warehouse,
|
|
||||||
"wip_warehouse": item.wip_warehouse,
|
|
||||||
"fg_warehouse": item.fg_warehouse,
|
|
||||||
"finished_good": item.item_code,
|
|
||||||
"finished_good_qty": item.qty,
|
|
||||||
"bom_no": production_item_wise_rm[(item.item_code, item.name)].bom_no,
|
|
||||||
"workstation_type": item.workstation_type,
|
|
||||||
"time_in_mins": item.operation_time,
|
|
||||||
"is_subcontracted": item.is_subcontracted,
|
|
||||||
"skip_material_transfer": item.skip_material_transfer,
|
|
||||||
"backflush_from_wip_warehouse": item.backflush_from_wip_warehouse,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
operation_row = bom.append(
|
|
||||||
"operations",
|
|
||||||
{
|
|
||||||
"operation": self.operation,
|
|
||||||
"time_in_mins": self.operation_time,
|
|
||||||
"workstation": self.workstation,
|
|
||||||
"workstation_type": self.workstation_type,
|
|
||||||
"finished_good": self.item_code,
|
|
||||||
"finished_good_qty": self.qty,
|
|
||||||
"source_warehouse": self.source_warehouse,
|
|
||||||
"wip_warehouse": self.wip_warehouse,
|
|
||||||
"fg_warehouse": self.fg_warehouse,
|
|
||||||
"skip_material_transfer": self.skip_material_transfer,
|
|
||||||
"backflush_from_wip_warehouse": self.backflush_from_wip_warehouse,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
final_product = (self.item_code, self.name)
|
|
||||||
items = production_item_wise_rm.get(final_product).get("items")
|
|
||||||
|
|
||||||
bom.set_materials_based_on_operation_bom()
|
|
||||||
|
|
||||||
for item in items:
|
|
||||||
item_args = {"operation_row_id": operation_row.idx}
|
|
||||||
for field in BOM_ITEM_FIELDS:
|
|
||||||
item_args[field] = item.get(field)
|
|
||||||
|
|
||||||
bom.append("items", item_args)
|
|
||||||
|
|
||||||
bom.save(ignore_permissions=True)
|
|
||||||
bom.submit()
|
|
||||||
|
|
||||||
def create_bom(self, row, production_item_wise_rm):
|
def create_bom(self, row, production_item_wise_rm):
|
||||||
bom_creator_item = row.name if row.name != self.name else ""
|
bom_creator_item = row.name if row.name != self.name else ""
|
||||||
if frappe.db.exists(
|
if frappe.db.exists(
|
||||||
@@ -393,25 +301,7 @@ class BOMCreator(Document):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.track_operations and not self.track_semi_finished_goods:
|
if row.item_code == self.item_code and (self.routing or self.has_operations()):
|
||||||
if row.item_code == self.item_code:
|
|
||||||
bom.with_operations = 1
|
|
||||||
bom.transfer_material_against = "Work Order"
|
|
||||||
for item in self.items:
|
|
||||||
if not item.operation:
|
|
||||||
continue
|
|
||||||
|
|
||||||
bom.append(
|
|
||||||
"operations",
|
|
||||||
{
|
|
||||||
"operation": item.operation,
|
|
||||||
"workstation_type": item.workstation_type,
|
|
||||||
"workstation": item.workstation,
|
|
||||||
"time_in_mins": item.operation_time,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
elif row.item_code == self.item_code and self.routing:
|
|
||||||
bom.routing = self.routing
|
bom.routing = self.routing
|
||||||
bom.with_operations = 1
|
bom.with_operations = 1
|
||||||
bom.transfer_material_against = "Work Order"
|
bom.transfer_material_against = "Work Order"
|
||||||
@@ -447,6 +337,13 @@ class BOMCreator(Document):
|
|||||||
|
|
||||||
production_item_wise_rm[(row.item_code, row.name)].bom_no = bom.name
|
production_item_wise_rm[(row.item_code, row.name)].bom_no = bom.name
|
||||||
|
|
||||||
|
def has_operations(self):
|
||||||
|
for row in self.items:
|
||||||
|
if row.operation:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_default_bom(self, item_code) -> str:
|
def get_default_bom(self, item_code) -> str:
|
||||||
return frappe.get_cached_value("Item", item_code, "default_bom")
|
return frappe.get_cached_value("Item", item_code, "default_bom")
|
||||||
@@ -562,14 +459,6 @@ def add_sub_assembly(**kwargs):
|
|||||||
"is_expandable": 1,
|
"is_expandable": 1,
|
||||||
"stock_uom": item_info.stock_uom,
|
"stock_uom": item_info.stock_uom,
|
||||||
"operation": bom_item.operation,
|
"operation": bom_item.operation,
|
||||||
"workstation_type": bom_item.workstation_type,
|
|
||||||
"operation_time": bom_item.operation_time,
|
|
||||||
"is_subcontracted": bom_item.is_subcontracted,
|
|
||||||
"workstation": bom_item.workstation,
|
|
||||||
"source_warehouse": bom_item.source_warehouse,
|
|
||||||
"wip_warehouse": bom_item.wip_warehouse,
|
|
||||||
"fg_warehouse": bom_item.fg_warehouse,
|
|
||||||
"skip_material_transfer": bom_item.skip_material_transfer,
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -579,20 +468,6 @@ def add_sub_assembly(**kwargs):
|
|||||||
parent_row_no = [row.idx for row in doc.items if row.name == kwargs.fg_reference_id]
|
parent_row_no = [row.idx for row in doc.items if row.name == kwargs.fg_reference_id]
|
||||||
if parent_row_no:
|
if parent_row_no:
|
||||||
parent_row_no = parent_row_no[0]
|
parent_row_no = parent_row_no[0]
|
||||||
doc.items[parent_row_no - 1].update(
|
|
||||||
{
|
|
||||||
"operation": bom_item.operation,
|
|
||||||
"workstation_type": bom_item.workstation_type,
|
|
||||||
"operation_time": bom_item.operation_time,
|
|
||||||
"is_subcontracted": bom_item.is_subcontracted,
|
|
||||||
"workstation": bom_item.workstation,
|
|
||||||
"source_warehouse": bom_item.source_warehouse,
|
|
||||||
"wip_warehouse": bom_item.wip_warehouse,
|
|
||||||
"fg_warehouse": bom_item.fg_warehouse,
|
|
||||||
"skip_material_transfer": bom_item.skip_material_transfer,
|
|
||||||
"backflush_from_wip_warehouse": bom_item.backflush_from_wip_warehouse,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
for row in bom_item.get("items"):
|
for row in bom_item.get("items"):
|
||||||
row = frappe._dict(row)
|
row = frappe._dict(row)
|
||||||
|
|||||||
@@ -17,17 +17,7 @@
|
|||||||
"is_subcontracted",
|
"is_subcontracted",
|
||||||
"operation_section",
|
"operation_section",
|
||||||
"operation",
|
"operation",
|
||||||
"operation_time",
|
|
||||||
"column_break_cbnk",
|
"column_break_cbnk",
|
||||||
"workstation_type",
|
|
||||||
"workstation",
|
|
||||||
"warehouse_section",
|
|
||||||
"skip_material_transfer",
|
|
||||||
"backflush_from_wip_warehouse",
|
|
||||||
"source_warehouse",
|
|
||||||
"column_break_xutc",
|
|
||||||
"wip_warehouse",
|
|
||||||
"fg_warehouse",
|
|
||||||
"description_section",
|
"description_section",
|
||||||
"description",
|
"description",
|
||||||
"quantity_and_rate_section",
|
"quantity_and_rate_section",
|
||||||
@@ -87,13 +77,6 @@
|
|||||||
"options": "Item",
|
"options": "Item",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"depends_on": "eval:doc.skip_material_transfer && !doc.backflush_from_wip_warehouse",
|
|
||||||
"fieldname": "source_warehouse",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Source Warehouse",
|
|
||||||
"options": "Warehouse"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"columns": 1,
|
"columns": 1,
|
||||||
"default": "0",
|
"default": "0",
|
||||||
@@ -256,59 +239,6 @@
|
|||||||
"fieldname": "column_break_cbnk",
|
"fieldname": "column_break_cbnk",
|
||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "workstation_type",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Workstation Type",
|
|
||||||
"options": "Workstation Type"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"description": "In Mins",
|
|
||||||
"fieldname": "operation_time",
|
|
||||||
"fieldtype": "Int",
|
|
||||||
"label": "Operation Time"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "workstation",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Workstation",
|
|
||||||
"options": "Workstation"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "warehouse_section",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"label": "Warehouse"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval:!doc.skip_material_transfer || doc.backflush_from_wip_warehouse",
|
|
||||||
"fieldname": "wip_warehouse",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Work In Progress Warehouse",
|
|
||||||
"options": "Warehouse"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_xutc",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "fg_warehouse",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Finished Good Warehouse",
|
|
||||||
"options": "Warehouse"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"fieldname": "skip_material_transfer",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"label": "Skip Material Transfer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"depends_on": "eval:doc.skip_material_transfer",
|
|
||||||
"fieldname": "backflush_from_wip_warehouse",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"label": "Backflush Materials From WIP Warehouse"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
"fieldname": "is_subcontracted",
|
"fieldname": "is_subcontracted",
|
||||||
@@ -320,7 +250,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-06-03 18:45:24.339532",
|
"modified": "2024-11-25 18:13:34.542391",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "BOM Creator Item",
|
"name": "BOM Creator Item",
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ class BOMCreatorItem(Document):
|
|||||||
from frappe.types import DF
|
from frappe.types import DF
|
||||||
|
|
||||||
amount: DF.Currency
|
amount: DF.Currency
|
||||||
backflush_from_wip_warehouse: DF.Check
|
|
||||||
base_amount: DF.Currency
|
base_amount: DF.Currency
|
||||||
base_rate: DF.Currency
|
base_rate: DF.Currency
|
||||||
bom_created: DF.Check
|
bom_created: DF.Check
|
||||||
@@ -24,7 +23,6 @@ class BOMCreatorItem(Document):
|
|||||||
do_not_explode: DF.Check
|
do_not_explode: DF.Check
|
||||||
fg_item: DF.Link
|
fg_item: DF.Link
|
||||||
fg_reference_id: DF.Data | None
|
fg_reference_id: DF.Data | None
|
||||||
fg_warehouse: DF.Link | None
|
|
||||||
instruction: DF.SmallText | None
|
instruction: DF.SmallText | None
|
||||||
is_expandable: DF.Check
|
is_expandable: DF.Check
|
||||||
is_subcontracted: DF.Check
|
is_subcontracted: DF.Check
|
||||||
@@ -32,22 +30,16 @@ class BOMCreatorItem(Document):
|
|||||||
item_group: DF.Link | None
|
item_group: DF.Link | None
|
||||||
item_name: DF.Data | None
|
item_name: DF.Data | None
|
||||||
operation: DF.Link | None
|
operation: DF.Link | None
|
||||||
operation_time: DF.Int
|
|
||||||
parent: DF.Data
|
parent: DF.Data
|
||||||
parent_row_no: DF.Data | None
|
parent_row_no: DF.Data | None
|
||||||
parentfield: DF.Data
|
parentfield: DF.Data
|
||||||
parenttype: DF.Data
|
parenttype: DF.Data
|
||||||
qty: DF.Float
|
qty: DF.Float
|
||||||
rate: DF.Currency
|
rate: DF.Currency
|
||||||
skip_material_transfer: DF.Check
|
|
||||||
source_warehouse: DF.Link | None
|
|
||||||
sourced_by_supplier: DF.Check
|
sourced_by_supplier: DF.Check
|
||||||
stock_qty: DF.Float
|
stock_qty: DF.Float
|
||||||
stock_uom: DF.Link | None
|
stock_uom: DF.Link | None
|
||||||
uom: DF.Link | None
|
uom: DF.Link | None
|
||||||
wip_warehouse: DF.Link | None
|
|
||||||
workstation: DF.Link | None
|
|
||||||
workstation_type: DF.Link | None
|
|
||||||
# end: auto-generated types
|
# end: auto-generated types
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -1157,6 +1157,9 @@ class JobCard(Document):
|
|||||||
for employee in kwargs.employees:
|
for employee in kwargs.employees:
|
||||||
kwargs.employee = employee.get("employee")
|
kwargs.employee = employee.get("employee")
|
||||||
if kwargs.from_time and not kwargs.to_time:
|
if kwargs.from_time and not kwargs.to_time:
|
||||||
|
if kwargs.qty:
|
||||||
|
kwargs.completed_qty = kwargs.qty
|
||||||
|
|
||||||
row = self.append("time_logs", kwargs)
|
row = self.append("time_logs", kwargs)
|
||||||
row.db_update()
|
row.db_update()
|
||||||
self.db_set("status", "Work In Progress")
|
self.db_set("status", "Work In Progress")
|
||||||
@@ -1223,6 +1226,10 @@ class JobCard(Document):
|
|||||||
|
|
||||||
if kwargs.auto_submit:
|
if kwargs.auto_submit:
|
||||||
self.submit()
|
self.submit()
|
||||||
|
|
||||||
|
if not self.finished_good:
|
||||||
|
return
|
||||||
|
|
||||||
self.make_stock_entry_for_semi_fg_item(kwargs.auto_submit)
|
self.make_stock_entry_for_semi_fg_item(kwargs.auto_submit)
|
||||||
frappe.msgprint(
|
frappe.msgprint(
|
||||||
_("Job Card {0} has been completed").format(get_link_to_form("Job Card", self.name))
|
_("Job Card {0} has been completed").format(get_link_to_form("Job Card", self.name))
|
||||||
|
|||||||
@@ -53,3 +53,24 @@ class Routing(Document):
|
|||||||
)
|
)
|
||||||
|
|
||||||
sequence_id = row.sequence_id
|
sequence_id = row.sequence_id
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
@frappe.validate_and_sanitize_search_inputs
|
||||||
|
def get_operations(doctype, txt, searchfield, start, page_len, filters):
|
||||||
|
query_filters = {}
|
||||||
|
|
||||||
|
if txt:
|
||||||
|
query_filters = {"operation": ["like", f"%{txt}%"]}
|
||||||
|
|
||||||
|
if filters.get("routing"):
|
||||||
|
query_filters["parent"] = filters.get("routing")
|
||||||
|
|
||||||
|
return frappe.get_all(
|
||||||
|
"BOM Operation",
|
||||||
|
fields=["operation"],
|
||||||
|
filters=query_filters,
|
||||||
|
start=start,
|
||||||
|
page_length=page_len,
|
||||||
|
as_list=1,
|
||||||
|
)
|
||||||
|
|||||||
@@ -1645,6 +1645,7 @@ def create_job_card(work_order, row, enable_capacity_planning=False, auto_create
|
|||||||
"sequence_id": row.get("sequence_id"),
|
"sequence_id": row.get("sequence_id"),
|
||||||
"hour_rate": row.get("hour_rate"),
|
"hour_rate": row.get("hour_rate"),
|
||||||
"serial_no": row.get("serial_no"),
|
"serial_no": row.get("serial_no"),
|
||||||
|
"time_required": row.get("time_in_mins"),
|
||||||
"source_warehouse": row.get("source_warehouse"),
|
"source_warehouse": row.get("source_warehouse"),
|
||||||
"target_warehouse": row.get("fg_warehouse"),
|
"target_warehouse": row.get("fg_warehouse"),
|
||||||
"wip_warehouse": work_order.wip_warehouse or row.get("wip_warehouse"),
|
"wip_warehouse": work_order.wip_warehouse or row.get("wip_warehouse"),
|
||||||
|
|||||||
@@ -509,6 +509,7 @@ def update_job_card(job_card, method, **kwargs):
|
|||||||
if kwargs.qty and isinstance(kwargs.qty, str):
|
if kwargs.qty and isinstance(kwargs.qty, str):
|
||||||
kwargs.qty = flt(kwargs.qty)
|
kwargs.qty = flt(kwargs.qty)
|
||||||
|
|
||||||
|
print(method)
|
||||||
doc = frappe.get_doc("Job Card", job_card)
|
doc = frappe.get_doc("Job Card", job_card)
|
||||||
doc.run_method(method, **kwargs)
|
doc.run_method(method, **kwargs)
|
||||||
|
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ class BOMConfigurator {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get_sub_assembly_modal_fields(view, is_root = false, read_only = false, show_operations_fields = false) {
|
get_sub_assembly_modal_fields(view, is_root = false, read_only = false) {
|
||||||
let fields = [
|
let fields = [
|
||||||
{
|
{
|
||||||
label: __("Sub Assembly Item"),
|
label: __("Sub Assembly Item"),
|
||||||
@@ -320,7 +320,7 @@ class BOMConfigurator {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
if (this.frm.doc.track_operations && (is_root || show_operations_fields)) {
|
if (is_root) {
|
||||||
fields.push(
|
fields.push(
|
||||||
...[
|
...[
|
||||||
{ fieldtype: "Section Break" },
|
{ fieldtype: "Section Break" },
|
||||||
@@ -329,105 +329,18 @@ class BOMConfigurator {
|
|||||||
fieldname: "operation",
|
fieldname: "operation",
|
||||||
fieldtype: "Link",
|
fieldtype: "Link",
|
||||||
options: "Operation",
|
options: "Operation",
|
||||||
reqd: 1,
|
get_query() {
|
||||||
},
|
let doc = view.events.frm.doc;
|
||||||
{
|
|
||||||
label: __("Operation Time"),
|
|
||||||
fieldname: "operation_time",
|
|
||||||
fieldtype: "Int",
|
|
||||||
reqd: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: __("Is Subcontracted"),
|
|
||||||
fieldname: "is_subcontracted",
|
|
||||||
fieldtype: "Check",
|
|
||||||
},
|
|
||||||
{ fieldtype: "Column Break" },
|
|
||||||
{
|
|
||||||
label: __("Workstation Type"),
|
|
||||||
fieldname: "workstation_type",
|
|
||||||
fieldtype: "Link",
|
|
||||||
options: "Workstation Type",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: __("Workstation"),
|
|
||||||
fieldname: "workstation",
|
|
||||||
fieldtype: "Link",
|
|
||||||
options: "Workstation",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this.frm.doc.track_semi_finished_goods) {
|
if (doc.routing) {
|
||||||
fields.push(
|
|
||||||
...[
|
|
||||||
{ label: __("Default Warehouse"), fieldtype: "Section Break", collapsible: 1 },
|
|
||||||
{
|
|
||||||
label: __("Skip Material Transfer"),
|
|
||||||
fieldname: "skip_material_transfer",
|
|
||||||
fieldtype: "Check",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: __("Backflush Materials From WIP"),
|
|
||||||
fieldname: "backflush_from_wip_warehouse",
|
|
||||||
fieldtype: "Check",
|
|
||||||
depends_on: "eval:doc.skip_material_transfer",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: __("Source Warehouse"),
|
|
||||||
fieldname: "source_warehouse",
|
|
||||||
fieldtype: "Link",
|
|
||||||
options: "Warehouse",
|
|
||||||
depends_on: "eval:!doc.backflush_from_wip_warehouse",
|
|
||||||
get_query() {
|
|
||||||
return {
|
return {
|
||||||
|
query: "erpnext.manufacturing.doctype.routing.routing.get_operations",
|
||||||
filters: {
|
filters: {
|
||||||
company: view.events.frm.doc.company,
|
routing: doc.routing,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
{ fieldtype: "Column Break" },
|
|
||||||
{
|
|
||||||
label: __("Work In Progress Warehouse"),
|
|
||||||
fieldname: "wip_warehouse",
|
|
||||||
fieldtype: "Link",
|
|
||||||
options: "Warehouse",
|
|
||||||
depends_on:
|
|
||||||
"eval:!doc.skip_material_transfer || doc.backflush_from_wip_warehouse",
|
|
||||||
get_query() {
|
|
||||||
return {
|
|
||||||
filters: {
|
|
||||||
company: view.events.frm.doc.company,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: __("Finished Good Warehouse"),
|
|
||||||
fieldname: "fg_warehouse",
|
|
||||||
fieldtype: "Link",
|
|
||||||
options: "Warehouse",
|
|
||||||
get_query() {
|
|
||||||
return {
|
|
||||||
filters: {
|
|
||||||
company: view.events.frm.doc.company,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (this.frm.doc.routing && is_root) {
|
|
||||||
fields.push(
|
|
||||||
...[
|
|
||||||
{ fieldtype: "Section Break" },
|
|
||||||
{
|
|
||||||
label: __("Operation"),
|
|
||||||
fieldname: "operation",
|
|
||||||
fieldtype: "Link",
|
|
||||||
options: "Operation",
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
@@ -473,7 +386,7 @@ class BOMConfigurator {
|
|||||||
|
|
||||||
convert_to_sub_assembly(node, view) {
|
convert_to_sub_assembly(node, view) {
|
||||||
let dialog = new frappe.ui.Dialog({
|
let dialog = new frappe.ui.Dialog({
|
||||||
fields: view.events.get_sub_assembly_modal_fields(view, node.is_root, true, true),
|
fields: view.events.get_sub_assembly_modal_fields(view, node.is_root, true),
|
||||||
title: __("Add Sub Assembly"),
|
title: __("Add Sub Assembly"),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -556,123 +469,6 @@ class BOMConfigurator {
|
|||||||
let qty = node.data.qty || this.frm.doc.qty;
|
let qty = node.data.qty || this.frm.doc.qty;
|
||||||
let fields = [{ label: __("Qty"), fieldname: "qty", default: qty, fieldtype: "Float", reqd: 1 }];
|
let fields = [{ label: __("Qty"), fieldname: "qty", default: qty, fieldtype: "Float", reqd: 1 }];
|
||||||
|
|
||||||
if (node.expandable && this.frm.doc.track_operations) {
|
|
||||||
let data = node.data.operation ? node.data : this.frm.doc;
|
|
||||||
|
|
||||||
fields = [
|
|
||||||
...fields,
|
|
||||||
...[
|
|
||||||
{ fieldtype: "Section Break" },
|
|
||||||
{
|
|
||||||
label: __("Operation"),
|
|
||||||
fieldname: "operation",
|
|
||||||
fieldtype: "Link",
|
|
||||||
options: "Operation",
|
|
||||||
default: data.operation,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: __("Operation Time"),
|
|
||||||
fieldname: "operation_time",
|
|
||||||
fieldtype: "Float",
|
|
||||||
default: data.operation_time,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: __("Is Subcontracted"),
|
|
||||||
fieldname: "is_subcontracted",
|
|
||||||
fieldtype: "Check",
|
|
||||||
hidden: node?.is_root || 0,
|
|
||||||
default: data.is_subcontracted,
|
|
||||||
},
|
|
||||||
{ fieldtype: "Column Break" },
|
|
||||||
{
|
|
||||||
label: __("Workstation Type"),
|
|
||||||
fieldname: "workstation_type",
|
|
||||||
fieldtype: "Link",
|
|
||||||
options: "Workstation Type",
|
|
||||||
default: data.workstation_type,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: __("Workstation"),
|
|
||||||
fieldname: "workstation",
|
|
||||||
fieldtype: "Link",
|
|
||||||
options: "Workstation",
|
|
||||||
default: data.workstation,
|
|
||||||
get_query() {
|
|
||||||
let dialog = me.frm.edit_bom_dialog;
|
|
||||||
let workstation_type = dialog.get_value("workstation_type");
|
|
||||||
|
|
||||||
if (workstation_type) {
|
|
||||||
return {
|
|
||||||
filters: {
|
|
||||||
workstation_type: dialog.get_value("workstation_type"),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ fieldtype: "Section Break" },
|
|
||||||
{
|
|
||||||
label: __("Skip Material Transfer"),
|
|
||||||
fieldname: "skip_material_transfer",
|
|
||||||
fieldtype: "Check",
|
|
||||||
default: data.skip_material_transfer,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: __("Backflush Materials From WIP"),
|
|
||||||
fieldname: "backflush_from_wip_warehouse",
|
|
||||||
fieldtype: "Check",
|
|
||||||
depends_on: "eval:doc.skip_material_transfer",
|
|
||||||
default: data.backflush_from_wip_warehouse,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: __("Source Warehouse"),
|
|
||||||
fieldname: "source_warehouse",
|
|
||||||
fieldtype: "Link",
|
|
||||||
options: "Warehouse",
|
|
||||||
default: data.source_warehouse,
|
|
||||||
depends_on: "eval:!doc.backflush_from_wip_warehouse",
|
|
||||||
get_query() {
|
|
||||||
return {
|
|
||||||
filters: {
|
|
||||||
company: me.frm.doc.company,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ fieldtype: "Column Break" },
|
|
||||||
{
|
|
||||||
label: __("Work In Progress Warehouse"),
|
|
||||||
fieldname: "wip_warehouse",
|
|
||||||
fieldtype: "Link",
|
|
||||||
options: "Warehouse",
|
|
||||||
default: data.wip_warehouse,
|
|
||||||
depends_on: "eval:!doc.skip_material_transfer || doc.backflush_from_wip_warehouse",
|
|
||||||
get_query() {
|
|
||||||
return {
|
|
||||||
filters: {
|
|
||||||
company: me.frm.doc.company,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: __("Finished Good Warehouse"),
|
|
||||||
fieldname: "fg_warehouse",
|
|
||||||
fieldtype: "Link",
|
|
||||||
options: "Warehouse",
|
|
||||||
default: data.fg_warehouse,
|
|
||||||
get_query() {
|
|
||||||
return {
|
|
||||||
filters: {
|
|
||||||
company: me.frm.doc.company,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.frm.edit_bom_dialog = frappe.prompt(
|
this.frm.edit_bom_dialog = frappe.prompt(
|
||||||
fields,
|
fields,
|
||||||
(data) => {
|
(data) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user