mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-05 21:29:11 +00:00
fix: persist main item code for MR plan items (#55623)
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
"min_order_qty",
|
||||
"section_break_8",
|
||||
"sales_order",
|
||||
"main_item_code",
|
||||
"bin_qty_section",
|
||||
"actual_qty",
|
||||
"requested_qty",
|
||||
@@ -114,6 +115,14 @@
|
||||
"options": "Sales Order",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "main_item_code",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"label": "Main Item Code",
|
||||
"no_copy": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "requested_qty",
|
||||
"fieldtype": "Float",
|
||||
@@ -213,4 +222,4 @@
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ class MaterialRequestPlanItem(Document):
|
||||
from_warehouse: DF.Link | None
|
||||
item_code: DF.Link
|
||||
item_name: DF.Data | None
|
||||
main_item_code: DF.Data | None
|
||||
material_request_type: DF.Literal[
|
||||
"", "Purchase", "Material Transfer", "Material Issue", "Manufacture", "Customer Provided"
|
||||
]
|
||||
|
||||
@@ -1397,7 +1397,7 @@ def get_material_request_items(
|
||||
"sales_order": sales_order,
|
||||
"description": row.get("description"),
|
||||
"uom": row.get("purchase_uom") or row.get("stock_uom"),
|
||||
"main_bom_item": row.get("main_bom_item"),
|
||||
"main_item_code": row.get("main_bom_item"),
|
||||
}
|
||||
|
||||
|
||||
@@ -1557,6 +1557,8 @@ def get_items_for_material_requests(doc, warehouses=None, get_parent_warehouse_d
|
||||
"item_code": sa_row.production_item,
|
||||
"required_qty": sa_row.qty,
|
||||
"include_exploded_items": 0,
|
||||
"sales_order": sa_row.sales_order,
|
||||
"main_bom_item": sa_row.parent_item_code,
|
||||
}
|
||||
)
|
||||
)
|
||||
@@ -1660,6 +1662,7 @@ def get_items_for_material_requests(doc, warehouses=None, get_parent_warehouse_d
|
||||
"stock_uom": item_master.stock_uom,
|
||||
"conversion_factor": conversion_factor,
|
||||
"safety_stock": item_master.safety_stock,
|
||||
"main_bom_item": data.get("main_bom_item"),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -1254,8 +1254,10 @@ class TestProductionPlan(FrappeTestCase):
|
||||
plan.get_sub_assembly_items()
|
||||
|
||||
mr_items = []
|
||||
expected_main_item_by_mr_item = {"ChildPart1 For MR": "SubAssembly1-1 For MR"}
|
||||
for row in plan.sub_assembly_items:
|
||||
mr_items.append(row.production_item)
|
||||
expected_main_item_by_mr_item[row.production_item] = row.parent_item_code
|
||||
row.type_of_manufacturing = "Material Request"
|
||||
|
||||
plan.save()
|
||||
@@ -1265,6 +1267,10 @@ class TestProductionPlan(FrappeTestCase):
|
||||
for item_code in mr_items:
|
||||
self.assertTrue(item_code in validate_mr_items)
|
||||
|
||||
main_item_by_mr_item = {item.get("item_code"): item.get("main_item_code") for item in items}
|
||||
for item_code, main_item_code in expected_main_item_by_mr_item.items():
|
||||
self.assertEqual(main_item_by_mr_item[item_code], main_item_code)
|
||||
|
||||
def test_resered_qty_for_production_plan_for_material_requests(self):
|
||||
from erpnext.stock.utils import get_or_make_bin
|
||||
|
||||
|
||||
@@ -435,3 +435,4 @@ erpnext.patches.v16_0.update_order_qty_and_requested_qty_based_on_mr_and_po
|
||||
erpnext.patches.v16_0.depends_on_inv_dimensions
|
||||
erpnext.patches.v16_0.clear_procedures_from_receivable_report
|
||||
erpnext.patches.v16_0.migrate_address_contact_custom_fields
|
||||
erpnext.patches.v15_0.set_main_item_code_in_material_request_plan_item
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
import frappe
|
||||
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc("manufacturing", "doctype", "material_request_plan_item")
|
||||
|
||||
if not frappe.db.has_column("Material Request Plan Item", "main_item_code"):
|
||||
return
|
||||
|
||||
for row in get_material_request_plan_items():
|
||||
if row.main_item_code:
|
||||
continue
|
||||
|
||||
main_item_code = get_main_item_code(row)
|
||||
if main_item_code:
|
||||
frappe.db.set_value(
|
||||
"Material Request Plan Item",
|
||||
row.name,
|
||||
"main_item_code",
|
||||
main_item_code,
|
||||
update_modified=False,
|
||||
)
|
||||
|
||||
|
||||
def get_material_request_plan_items():
|
||||
return frappe.get_all(
|
||||
"Material Request Plan Item",
|
||||
fields=["name", "parent", "item_code", "sales_order", "main_item_code"],
|
||||
)
|
||||
|
||||
|
||||
def get_main_item_code(row):
|
||||
return (
|
||||
get_main_item_code_from_sub_assembly(row)
|
||||
or get_main_item_code_from_sub_assembly_bom(row)
|
||||
or get_main_item_code_from_production_plan_bom(row)
|
||||
)
|
||||
|
||||
|
||||
def get_main_item_code_from_sub_assembly(row):
|
||||
sub_assembly = frappe.db.get_value(
|
||||
"Production Plan Sub Assembly Item",
|
||||
get_filters(
|
||||
row,
|
||||
{
|
||||
"parent": row.parent,
|
||||
"production_item": row.item_code,
|
||||
},
|
||||
),
|
||||
"parent_item_code",
|
||||
)
|
||||
|
||||
return sub_assembly
|
||||
|
||||
|
||||
def get_main_item_code_from_sub_assembly_bom(row):
|
||||
for sub_assembly in get_sub_assembly_items(row):
|
||||
if item_exists_in_bom(row.item_code, sub_assembly.bom_no):
|
||||
return frappe.db.get_value("BOM", sub_assembly.bom_no, "item")
|
||||
|
||||
|
||||
def get_main_item_code_from_production_plan_bom(row):
|
||||
for production_plan_item in get_production_plan_items(row):
|
||||
if item_exists_in_bom(row.item_code, production_plan_item.bom_no):
|
||||
return frappe.db.get_value("BOM", production_plan_item.bom_no, "item")
|
||||
|
||||
|
||||
def get_sub_assembly_items(row):
|
||||
return frappe.get_all(
|
||||
"Production Plan Sub Assembly Item",
|
||||
filters=get_filters(row, {"parent": row.parent}),
|
||||
fields=["bom_no"],
|
||||
)
|
||||
|
||||
|
||||
def get_production_plan_items(row):
|
||||
return frappe.get_all(
|
||||
"Production Plan Item",
|
||||
filters=get_filters(row, {"parent": row.parent}),
|
||||
fields=["bom_no"],
|
||||
)
|
||||
|
||||
|
||||
def get_filters(row, filters):
|
||||
if row.sales_order:
|
||||
filters["sales_order"] = row.sales_order
|
||||
|
||||
return filters
|
||||
|
||||
|
||||
def item_exists_in_bom(item_code, bom_no):
|
||||
if not bom_no:
|
||||
return False
|
||||
|
||||
return frappe.db.exists("BOM Item", {"parent": bom_no, "item_code": item_code}) or frappe.db.exists(
|
||||
"BOM Explosion Item", {"parent": bom_no, "item_code": item_code}
|
||||
)
|
||||
Reference in New Issue
Block a user