mirror of
https://github.com/frappe/erpnext.git
synced 2026-04-27 02:28:30 +00:00
committed by
Mergify
parent
3bee79b90d
commit
2c73e37f80
@@ -7,31 +7,18 @@
|
|||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"production_item_tab",
|
"production_item_tab",
|
||||||
|
"final_product_section",
|
||||||
"company",
|
"company",
|
||||||
"item",
|
"item",
|
||||||
|
"column_break_ztxc",
|
||||||
"quantity",
|
"quantity",
|
||||||
"cb0",
|
"uom",
|
||||||
"is_active",
|
"cost_allocation__process_loss_section",
|
||||||
"is_default",
|
|
||||||
"allow_alternative_item",
|
|
||||||
"set_rate_of_sub_assembly_item_based_on_bom",
|
|
||||||
"is_phantom_bom",
|
|
||||||
"cost_allocation_section",
|
|
||||||
"cost_allocation_per",
|
"cost_allocation_per",
|
||||||
"column_break_srby",
|
|
||||||
"cost_allocation",
|
"cost_allocation",
|
||||||
"process_loss_section",
|
"column_break_tgkb",
|
||||||
"process_loss_percentage",
|
"process_loss_percentage",
|
||||||
"column_break_ssj2",
|
|
||||||
"process_loss_qty",
|
"process_loss_qty",
|
||||||
"currency_detail",
|
|
||||||
"rm_cost_as_per",
|
|
||||||
"buying_price_list",
|
|
||||||
"price_list_currency",
|
|
||||||
"plc_conversion_rate",
|
|
||||||
"column_break_ivyw",
|
|
||||||
"currency",
|
|
||||||
"conversion_rate",
|
|
||||||
"operations_section_section",
|
"operations_section_section",
|
||||||
"with_operations",
|
"with_operations",
|
||||||
"track_semi_finished_goods",
|
"track_semi_finished_goods",
|
||||||
@@ -46,8 +33,27 @@
|
|||||||
"operations",
|
"operations",
|
||||||
"materials_section",
|
"materials_section",
|
||||||
"items",
|
"items",
|
||||||
"secondary_items_tab",
|
"section_break_hygk",
|
||||||
"secondary_items",
|
"secondary_items",
|
||||||
|
"bom_conf_tab",
|
||||||
|
"bom_configuration_section",
|
||||||
|
"column_break_zbzp",
|
||||||
|
"is_active",
|
||||||
|
"is_default",
|
||||||
|
"set_rate_of_sub_assembly_item_based_on_bom",
|
||||||
|
"cb0",
|
||||||
|
"is_phantom_bom",
|
||||||
|
"allow_alternative_item",
|
||||||
|
"quality_inspection_section_break",
|
||||||
|
"inspection_required",
|
||||||
|
"column_break_dxp7",
|
||||||
|
"quality_inspection_template",
|
||||||
|
"default_warehouse_section",
|
||||||
|
"default_source_warehouse",
|
||||||
|
"column_break_inep",
|
||||||
|
"default_target_warehouse",
|
||||||
|
"consume_components_section",
|
||||||
|
"backflush_based_on",
|
||||||
"costing",
|
"costing",
|
||||||
"operating_cost",
|
"operating_cost",
|
||||||
"raw_material_cost",
|
"raw_material_cost",
|
||||||
@@ -59,23 +65,21 @@
|
|||||||
"column_break_26",
|
"column_break_26",
|
||||||
"total_cost",
|
"total_cost",
|
||||||
"base_total_cost",
|
"base_total_cost",
|
||||||
"quality_inspection_tab",
|
|
||||||
"quality_inspection_section_break",
|
|
||||||
"inspection_required",
|
|
||||||
"column_break_dxp7",
|
|
||||||
"quality_inspection_template",
|
|
||||||
"more_info_tab",
|
"more_info_tab",
|
||||||
|
"currency_detail",
|
||||||
|
"rm_cost_as_per",
|
||||||
|
"buying_price_list",
|
||||||
|
"price_list_currency",
|
||||||
|
"plc_conversion_rate",
|
||||||
|
"column_break_ivyw",
|
||||||
|
"currency",
|
||||||
|
"conversion_rate",
|
||||||
"production_item_info_section",
|
"production_item_info_section",
|
||||||
"item_name",
|
"item_name",
|
||||||
"uom",
|
|
||||||
"image",
|
"image",
|
||||||
"column_break_27",
|
"column_break_27",
|
||||||
"description",
|
"description",
|
||||||
"has_variants",
|
"has_variants",
|
||||||
"default_warehouse_section",
|
|
||||||
"default_source_warehouse",
|
|
||||||
"column_break_inep",
|
|
||||||
"default_target_warehouse",
|
|
||||||
"section_break_ouuf",
|
"section_break_ouuf",
|
||||||
"project",
|
"project",
|
||||||
"section_break0",
|
"section_break0",
|
||||||
@@ -99,17 +103,18 @@
|
|||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"description": "Item to be manufactured or repacked",
|
"description": "The final item that will be produced using this BOM.",
|
||||||
"fieldname": "item",
|
"fieldname": "item",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Item",
|
"label": "Item to Manufacture",
|
||||||
"oldfieldname": "item",
|
"oldfieldname": "item",
|
||||||
"oldfieldtype": "Link",
|
"oldfieldtype": "Link",
|
||||||
"options": "Item",
|
"options": "Item",
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 1
|
"search_index": 1,
|
||||||
|
"show_description_on_click": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fetch_from": "item.item_name",
|
"fetch_from": "item.item_name",
|
||||||
@@ -130,23 +135,26 @@
|
|||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"depends_on": "item",
|
||||||
"fetch_from": "item.stock_uom",
|
"fetch_from": "item.stock_uom",
|
||||||
"fieldname": "uom",
|
"fieldname": "uom",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Item UOM",
|
"label": "Unit Of Measure",
|
||||||
"options": "UOM",
|
"options": "UOM",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "1",
|
"default": "1",
|
||||||
"description": "Quantity of item obtained after manufacturing / repacking from given quantities of raw materials",
|
"depends_on": "item",
|
||||||
|
"description": "How many units of the final product this BOM makes.",
|
||||||
"fieldname": "quantity",
|
"fieldname": "quantity",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"label": "Quantity",
|
"label": "Quantity (Output Qty)",
|
||||||
"non_negative": 1,
|
"non_negative": 1,
|
||||||
"oldfieldname": "quantity",
|
"oldfieldname": "quantity",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"reqd": 1
|
"reqd": 1,
|
||||||
|
"show_description_on_click": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "cb0",
|
"fieldname": "cb0",
|
||||||
@@ -288,14 +296,13 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "materials_section",
|
"fieldname": "materials_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Raw Materials",
|
|
||||||
"oldfieldtype": "Section Break"
|
"oldfieldtype": "Section Break"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 1,
|
"allow_bulk_edit": 1,
|
||||||
"fieldname": "items",
|
"fieldname": "items",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"label": "Items",
|
"label": "Components",
|
||||||
"oldfieldname": "bom_materials",
|
"oldfieldname": "bom_materials",
|
||||||
"oldfieldtype": "Table",
|
"oldfieldtype": "Table",
|
||||||
"options": "BOM Item",
|
"options": "BOM Item",
|
||||||
@@ -415,6 +422,7 @@
|
|||||||
"depends_on": "eval:!doc.is_phantom_bom",
|
"depends_on": "eval:!doc.is_phantom_bom",
|
||||||
"fieldname": "website_section",
|
"fieldname": "website_section",
|
||||||
"fieldtype": "Tab Break",
|
"fieldtype": "Tab Break",
|
||||||
|
"hidden": 1,
|
||||||
"label": "Website"
|
"label": "Website"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -528,11 +536,6 @@
|
|||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Operations"
|
"label": "Operations"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "process_loss_section",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"label": "Process Loss"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "process_loss_percentage",
|
"fieldname": "process_loss_percentage",
|
||||||
"fieldtype": "Percent",
|
"fieldtype": "Percent",
|
||||||
@@ -546,10 +549,6 @@
|
|||||||
"non_negative": 1,
|
"non_negative": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "column_break_ssj2",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "more_info_tab",
|
"fieldname": "more_info_tab",
|
||||||
"fieldtype": "Tab Break",
|
"fieldtype": "Tab Break",
|
||||||
@@ -668,11 +667,6 @@
|
|||||||
"fieldname": "section_break_ouuf",
|
"fieldname": "section_break_ouuf",
|
||||||
"fieldtype": "Section Break"
|
"fieldtype": "Section Break"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "quality_inspection_tab",
|
|
||||||
"fieldtype": "Tab Break",
|
|
||||||
"label": "Quality Inspection"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "secondary_items",
|
"fieldname": "secondary_items",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
@@ -697,20 +691,6 @@
|
|||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "secondary_items_tab",
|
|
||||||
"fieldtype": "Tab Break",
|
|
||||||
"label": "Secondary Items"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "cost_allocation_section",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"label": "Cost Allocation"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_srby",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "cost_allocation",
|
"fieldname": "cost_allocation",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
@@ -725,6 +705,55 @@
|
|||||||
"fieldtype": "Percent",
|
"fieldtype": "Percent",
|
||||||
"label": "% Cost Allocation",
|
"label": "% Cost Allocation",
|
||||||
"non_negative": 1
|
"non_negative": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsible": 1,
|
||||||
|
"fieldname": "bom_configuration_section",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_zbzp",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_ztxc",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsible": 1,
|
||||||
|
"fieldname": "cost_allocation__process_loss_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Cost Allocation / Process Loss"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_tgkb",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_hygk",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "final_product_section",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "bom_conf_tab",
|
||||||
|
"fieldtype": "Tab Break",
|
||||||
|
"label": "BOM Configuration"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "consume_components_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Consume Components"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Controls how raw materials are consumed during the \u2018Manufacture\u2019 stock entry.",
|
||||||
|
"fieldname": "backflush_based_on",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"label": "Based On",
|
||||||
|
"options": "\nBOM\nMaterial Transferred for Manufacture",
|
||||||
|
"show_description_on_click": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-sitemap",
|
"icon": "fa fa-sitemap",
|
||||||
@@ -732,7 +761,7 @@
|
|||||||
"image_field": "image",
|
"image_field": "image",
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2026-02-26 14:13:34.040181",
|
"modified": "2026-04-17 15:22:33.598938",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "BOM",
|
"name": "BOM",
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ class BOM(WebsiteGenerator):
|
|||||||
|
|
||||||
allow_alternative_item: DF.Check
|
allow_alternative_item: DF.Check
|
||||||
amended_from: DF.Link | None
|
amended_from: DF.Link | None
|
||||||
|
backflush_based_on: DF.Literal["", "BOM", "Material Transferred for Manufacture"]
|
||||||
base_operating_cost: DF.Currency
|
base_operating_cost: DF.Currency
|
||||||
base_raw_material_cost: DF.Currency
|
base_raw_material_cost: DF.Currency
|
||||||
base_secondary_items_cost: DF.Currency
|
base_secondary_items_cost: DF.Currency
|
||||||
@@ -1982,3 +1983,16 @@ def get_secondary_items_from_sub_assemblies(bom_no, company, qty, secondary_item
|
|||||||
get_secondary_items_from_sub_assemblies(row.bom_no, company, qty, secondary_items)
|
get_secondary_items_from_sub_assemblies(row.bom_no, company, qty, secondary_items)
|
||||||
|
|
||||||
return secondary_items
|
return secondary_items
|
||||||
|
|
||||||
|
|
||||||
|
def get_backflush_based_on(bom_no):
|
||||||
|
backflush_based_on = None
|
||||||
|
if bom_no:
|
||||||
|
backflush_based_on = frappe.get_cached_value("BOM", bom_no, "backflush_based_on")
|
||||||
|
|
||||||
|
if not backflush_based_on:
|
||||||
|
backflush_based_on = frappe.db.get_single_value(
|
||||||
|
"Manufacturing Settings", "backflush_raw_materials_based_on"
|
||||||
|
)
|
||||||
|
|
||||||
|
return backflush_based_on
|
||||||
|
|||||||
@@ -2879,6 +2879,9 @@ def make_bom(**args):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if args.backflush_based_on:
|
||||||
|
bom.backflush_based_on = args.backflush_based_on
|
||||||
|
|
||||||
if args.operating_cost_per_bom_quantity:
|
if args.operating_cost_per_bom_quantity:
|
||||||
bom.fg_based_operating_cost = 1
|
bom.fg_based_operating_cost = 1
|
||||||
bom.operating_cost_per_bom_quantity = args.operating_cost_per_bom_quantity
|
bom.operating_cost_per_bom_quantity = args.operating_cost_per_bom_quantity
|
||||||
|
|||||||
@@ -4240,6 +4240,66 @@ class TestWorkOrder(ERPNextTestSuite):
|
|||||||
self.assertEqual(wo_order.operations[0].time_in_mins, 72)
|
self.assertEqual(wo_order.operations[0].time_in_mins, 72)
|
||||||
self.assertEqual(wo_order.operations[1].time_in_mins, 240)
|
self.assertEqual(wo_order.operations[1].time_in_mins, 240)
|
||||||
|
|
||||||
|
def test_backflush_based_on_in_bom(self):
|
||||||
|
raw_material_1 = make_item(item_code="BOM RM 1", properties={"is_stock_item": 1}).name
|
||||||
|
raw_material_2 = make_item(item_code="BOM RM 2", properties={"is_stock_item": 1}).name
|
||||||
|
fg_item = make_item(item_code="BOM FG 1", properties={"is_stock_item": 1}).name
|
||||||
|
|
||||||
|
frappe.db.set_single_value("Manufacturing Settings", "backflush_raw_materials_based_on", "BOM")
|
||||||
|
|
||||||
|
backflush_based_on = frappe.db.get_single_value(
|
||||||
|
"Manufacturing Settings", "backflush_raw_materials_based_on"
|
||||||
|
)
|
||||||
|
self.assertEqual(backflush_based_on, "BOM")
|
||||||
|
|
||||||
|
for item_code in [raw_material_1, raw_material_2]:
|
||||||
|
test_stock_entry.make_stock_entry(
|
||||||
|
item_code=item_code, target="Stores - _TC", qty=1, basic_rate=100
|
||||||
|
)
|
||||||
|
|
||||||
|
bom = make_bom(
|
||||||
|
item=fg_item,
|
||||||
|
quantity=1,
|
||||||
|
raw_materials=[raw_material_1],
|
||||||
|
backflush_based_on="Material Transferred for Manufacture",
|
||||||
|
)
|
||||||
|
|
||||||
|
wo_order = make_wo_order_test_record(item=fg_item, qty=1, source_warehouse="Stores - _TC")
|
||||||
|
|
||||||
|
self.assertEqual(bom.name, wo_order.bom_no)
|
||||||
|
backflush_based_on = frappe.db.get_value("BOM", wo_order.bom_no, "backflush_based_on")
|
||||||
|
self.assertEqual(backflush_based_on, "Material Transferred for Manufacture")
|
||||||
|
|
||||||
|
material_transfer_entry = frappe.get_doc(
|
||||||
|
make_stock_entry(wo_order.name, "Material Transfer for Manufacture", 1)
|
||||||
|
)
|
||||||
|
material_transfer_entry.save()
|
||||||
|
|
||||||
|
# Add second raw material in the material transfer entry which is not in the BOM to simulate backflush based on material transfer scenario
|
||||||
|
material_transfer_entry.append(
|
||||||
|
"items",
|
||||||
|
{
|
||||||
|
"item_code": raw_material_2,
|
||||||
|
"item_name": raw_material_2,
|
||||||
|
"item_group": frappe.get_value("Item", raw_material_2, "item_group"),
|
||||||
|
"uom": frappe.get_value("Item", raw_material_2, "stock_uom"),
|
||||||
|
"conversion_factor": 1,
|
||||||
|
"s_warehouse": "Stores - _TC",
|
||||||
|
"t_warehouse": material_transfer_entry.items[0].t_warehouse,
|
||||||
|
"qty": 1,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
material_transfer_entry.submit()
|
||||||
|
|
||||||
|
manufacture_entry = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 1))
|
||||||
|
manufacture_entry.save()
|
||||||
|
|
||||||
|
self.assertEqual(len(manufacture_entry.items), 3)
|
||||||
|
for row in manufacture_entry.items:
|
||||||
|
if row.s_warehouse:
|
||||||
|
self.assertIn(row.item_code, [raw_material_1, raw_material_2])
|
||||||
|
|
||||||
|
|
||||||
def get_reserved_entries(voucher_no, warehouse=None):
|
def get_reserved_entries(voucher_no, warehouse=None):
|
||||||
doctype = frappe.qb.DocType("Stock Reservation Entry")
|
doctype = frappe.qb.DocType("Stock Reservation Entry")
|
||||||
|
|||||||
@@ -242,6 +242,11 @@ frappe.ui.form.on("Work Order", {
|
|||||||
frm.trigger("hide_reserve_stock_button");
|
frm.trigger("hide_reserve_stock_button");
|
||||||
frm.trigger("toggle_items_editable");
|
frm.trigger("toggle_items_editable");
|
||||||
frm.trigger("set_fg_warehouse_mandatory");
|
frm.trigger("set_fg_warehouse_mandatory");
|
||||||
|
frm.trigger("toggle_hide_fields");
|
||||||
|
},
|
||||||
|
|
||||||
|
toggle_hide_fields(frm) {
|
||||||
|
frm.toggle_display("operations", frm.doc?.operations && frm.doc.operations.length > 0);
|
||||||
},
|
},
|
||||||
|
|
||||||
skip_transfer(frm) {
|
skip_transfer(frm) {
|
||||||
@@ -638,6 +643,8 @@ frappe.ui.form.on("Work Order", {
|
|||||||
if (r.message["set_scrap_wh_mandatory"]) {
|
if (r.message["set_scrap_wh_mandatory"]) {
|
||||||
frm.toggle_reqd("scrap_warehouse", true);
|
frm.toggle_reqd("scrap_warehouse", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frm.trigger("toggle_hide_fields");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
"column_break1",
|
"column_break1",
|
||||||
"qty",
|
"qty",
|
||||||
"sales_order",
|
"sales_order",
|
||||||
"track_semi_finished_goods",
|
|
||||||
"reserve_stock",
|
"reserve_stock",
|
||||||
"section_break_vrpa",
|
"section_break_vrpa",
|
||||||
"max_producible_qty",
|
"max_producible_qty",
|
||||||
@@ -86,6 +85,7 @@
|
|||||||
"product_bundle_item",
|
"product_bundle_item",
|
||||||
"section_break_ynih",
|
"section_break_ynih",
|
||||||
"status",
|
"status",
|
||||||
|
"track_semi_finished_goods",
|
||||||
"column_break_cvuw",
|
"column_break_cvuw",
|
||||||
"amended_from",
|
"amended_from",
|
||||||
"connections_tab"
|
"connections_tab"
|
||||||
@@ -608,6 +608,7 @@
|
|||||||
"fetch_from": "bom_no.track_semi_finished_goods",
|
"fetch_from": "bom_no.track_semi_finished_goods",
|
||||||
"fieldname": "track_semi_finished_goods",
|
"fieldname": "track_semi_finished_goods",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
|
"hidden": 1,
|
||||||
"label": "Track Semi Finished Goods",
|
"label": "Track Semi Finished Goods",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
@@ -705,7 +706,7 @@
|
|||||||
"image_field": "image",
|
"image_field": "image",
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2026-03-16 10:15:28.708688",
|
"modified": "2026-04-17 13:42:12.374055",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Work Order",
|
"name": "Work Order",
|
||||||
|
|||||||
@@ -162,6 +162,10 @@ class WorkOrder(Document):
|
|||||||
frappe.db.get_single_value("Stock Settings", "enable_stock_reservation"),
|
frappe.db.get_single_value("Stock Settings", "enable_stock_reservation"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if self.bom_no:
|
||||||
|
if based_on := frappe.get_cached_value("BOM", self.bom_no, "backflush_based_on"):
|
||||||
|
self.set_onload("backflush_raw_materials_based_on", based_on)
|
||||||
|
|
||||||
def show_create_job_card_button(self):
|
def show_create_job_card_button(self):
|
||||||
operation_details = frappe._dict(
|
operation_details = frappe._dict(
|
||||||
frappe.get_all(
|
frappe.get_all(
|
||||||
|
|||||||
@@ -2537,14 +2537,12 @@ class StockEntry(StockController, SubcontractingInwardController):
|
|||||||
frappe.throw(_("Posting date and posting time is mandatory"))
|
frappe.throw(_("Posting date and posting time is mandatory"))
|
||||||
|
|
||||||
self.set_work_order_details()
|
self.set_work_order_details()
|
||||||
self.flags.backflush_based_on = frappe.db.get_single_value(
|
backflush_based_on = frappe.db.get_single_value(
|
||||||
"Manufacturing Settings", "backflush_raw_materials_based_on"
|
"Manufacturing Settings", "backflush_raw_materials_based_on"
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.bom_no:
|
if self.bom_no:
|
||||||
backflush_based_on = frappe.db.get_single_value(
|
backflush_based_on = self.get_backflush_based_on()
|
||||||
"Manufacturing Settings", "backflush_raw_materials_based_on"
|
|
||||||
)
|
|
||||||
|
|
||||||
if self.purpose in [
|
if self.purpose in [
|
||||||
"Material Issue",
|
"Material Issue",
|
||||||
@@ -2569,7 +2567,7 @@ class StockEntry(StockController, SubcontractingInwardController):
|
|||||||
or self.purpose == "Material Consumption for Manufacture"
|
or self.purpose == "Material Consumption for Manufacture"
|
||||||
)
|
)
|
||||||
and not self.pro_doc.skip_transfer
|
and not self.pro_doc.skip_transfer
|
||||||
and self.flags.backflush_based_on == "Material Transferred for Manufacture"
|
and backflush_based_on == "Material Transferred for Manufacture"
|
||||||
):
|
):
|
||||||
self.add_transfered_raw_materials_in_items()
|
self.add_transfered_raw_materials_in_items()
|
||||||
|
|
||||||
@@ -2579,7 +2577,7 @@ class StockEntry(StockController, SubcontractingInwardController):
|
|||||||
self.purpose == "Manufacture"
|
self.purpose == "Manufacture"
|
||||||
or self.purpose == "Material Consumption for Manufacture"
|
or self.purpose == "Material Consumption for Manufacture"
|
||||||
)
|
)
|
||||||
and self.flags.backflush_based_on == "BOM"
|
and backflush_based_on == "BOM"
|
||||||
and frappe.db.get_single_value("Manufacturing Settings", "material_consumption") == 1
|
and frappe.db.get_single_value("Manufacturing Settings", "material_consumption") == 1
|
||||||
):
|
):
|
||||||
self.get_unconsumed_raw_materials()
|
self.get_unconsumed_raw_materials()
|
||||||
@@ -2649,8 +2647,7 @@ class StockEntry(StockController, SubcontractingInwardController):
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
self.purpose not in ["Material Transfer for Manufacture"]
|
self.purpose not in ["Material Transfer for Manufacture"]
|
||||||
and frappe.db.get_single_value("Manufacturing Settings", "backflush_raw_materials_based_on")
|
and self.get_backflush_based_on() != "BOM"
|
||||||
!= "BOM"
|
|
||||||
and not skip_transfer
|
and not skip_transfer
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
@@ -2727,6 +2724,11 @@ class StockEntry(StockController, SubcontractingInwardController):
|
|||||||
row.idx = idx
|
row.idx = idx
|
||||||
self.set("items", sorted_items)
|
self.set("items", sorted_items)
|
||||||
|
|
||||||
|
def get_backflush_based_on(self):
|
||||||
|
from erpnext.manufacturing.doctype.bom.bom import get_backflush_based_on
|
||||||
|
|
||||||
|
return get_backflush_based_on(self.bom_no)
|
||||||
|
|
||||||
def get_available_reserved_materials(self):
|
def get_available_reserved_materials(self):
|
||||||
reserved_entries = self.get_reserved_materials()
|
reserved_entries = self.get_reserved_materials()
|
||||||
if not reserved_entries:
|
if not reserved_entries:
|
||||||
|
|||||||
@@ -115,6 +115,10 @@ class ManufactureEntry:
|
|||||||
"Manufacturing Settings", "backflush_raw_materials_based_on"
|
"Manufacturing Settings", "backflush_raw_materials_based_on"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if self.bom_no:
|
||||||
|
if based_on := frappe.get_cached_value("BOM", self.bom_no, "backflush_based_on"):
|
||||||
|
backflush_based_on = based_on
|
||||||
|
|
||||||
available_serial_batches = frappe._dict({})
|
available_serial_batches = frappe._dict({})
|
||||||
if backflush_based_on != "BOM":
|
if backflush_based_on != "BOM":
|
||||||
available_serial_batches = self.get_transferred_serial_batches()
|
available_serial_batches = self.get_transferred_serial_batches()
|
||||||
|
|||||||
Reference in New Issue
Block a user