Merge pull request #25026 from ruchamahabal/production-raw-material-enhancements-v13
feat(Production Plan): Enhancements in Material Request Plan Item
This commit is contained in:
commit
2c191c105f
@ -11,10 +11,14 @@
|
|||||||
"from_warehouse",
|
"from_warehouse",
|
||||||
"warehouse",
|
"warehouse",
|
||||||
"column_break_4",
|
"column_break_4",
|
||||||
|
"required_bom_qty",
|
||||||
"quantity",
|
"quantity",
|
||||||
"uom",
|
"uom",
|
||||||
"projected_qty",
|
"projected_qty",
|
||||||
"actual_qty",
|
"actual_qty",
|
||||||
|
"ordered_qty",
|
||||||
|
"reserved_qty_for_production",
|
||||||
|
"safety_stock",
|
||||||
"item_details",
|
"item_details",
|
||||||
"description",
|
"description",
|
||||||
"min_order_qty",
|
"min_order_qty",
|
||||||
@ -129,11 +133,40 @@
|
|||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "From Warehouse",
|
"label": "From Warehouse",
|
||||||
"options": "Warehouse"
|
"options": "Warehouse"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "item_code.safety_stock",
|
||||||
|
"fieldname": "safety_stock",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Safety Stock",
|
||||||
|
"no_copy": 1,
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "ordered_qty",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Ordered Qty",
|
||||||
|
"no_copy": 1,
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "reserved_qty_for_production",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Reserved Qty for Production",
|
||||||
|
"no_copy": 1,
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "required_bom_qty",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Required Qty as per BOM",
|
||||||
|
"no_copy": 1,
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-02-03 12:22:29.913302",
|
"modified": "2021-03-26 12:41:13.013149",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Material Request Plan Item",
|
"name": "Material Request Plan Item",
|
||||||
|
|||||||
@ -251,7 +251,8 @@ frappe.ui.form.on('Production Plan', {
|
|||||||
|
|
||||||
get_items_for_material_requests: function(frm, warehouses) {
|
get_items_for_material_requests: function(frm, warehouses) {
|
||||||
const set_fields = ['actual_qty', 'item_code','item_name', 'description', 'uom', 'from_warehouse',
|
const set_fields = ['actual_qty', 'item_code','item_name', 'description', 'uom', 'from_warehouse',
|
||||||
'min_order_qty', 'quantity', 'sales_order', 'warehouse', 'projected_qty', 'material_request_type'];
|
'min_order_qty', 'required_bom_qty', 'quantity', 'sales_order', 'warehouse', 'projected_qty', 'ordered_qty',
|
||||||
|
'reserved_qty_for_production', 'material_request_type'];
|
||||||
|
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.manufacturing.doctype.production_plan.production_plan.get_items_for_material_requests",
|
method: "erpnext.manufacturing.doctype.production_plan.production_plan.get_items_for_material_requests",
|
||||||
|
|||||||
@ -32,6 +32,7 @@
|
|||||||
"material_request_planning",
|
"material_request_planning",
|
||||||
"include_non_stock_items",
|
"include_non_stock_items",
|
||||||
"include_subcontracted_items",
|
"include_subcontracted_items",
|
||||||
|
"include_safety_stock",
|
||||||
"ignore_existing_ordered_qty",
|
"ignore_existing_ordered_qty",
|
||||||
"column_break_25",
|
"column_break_25",
|
||||||
"for_warehouse",
|
"for_warehouse",
|
||||||
@ -309,13 +310,19 @@
|
|||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"label": "Sales Order Status",
|
"label": "Sales Order Status",
|
||||||
"options": "\nTo Deliver and Bill\nTo Bill\nTo Deliver"
|
"options": "\nTo Deliver and Bill\nTo Bill\nTo Deliver"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "include_safety_stock",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Include Safety Stock in Required Qty Calculation"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-calendar",
|
"icon": "fa fa-calendar",
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-11-10 18:01:54.991970",
|
"modified": "2021-03-08 11:17:25.470147",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Production Plan",
|
"name": "Production Plan",
|
||||||
|
|||||||
@ -434,12 +434,14 @@ def download_raw_materials(doc):
|
|||||||
if isinstance(doc, string_types):
|
if isinstance(doc, string_types):
|
||||||
doc = frappe._dict(json.loads(doc))
|
doc = frappe._dict(json.loads(doc))
|
||||||
|
|
||||||
item_list = [['Item Code', 'Description', 'Stock UOM', 'Required Qty', 'Warehouse',
|
item_list = [['Item Code', 'Description', 'Stock UOM', 'Warehouse', 'Required Qty as per BOM',
|
||||||
'projected Qty', 'Actual Qty']]
|
'Projected Qty', 'Actual Qty', 'Ordered Qty', 'Reserved Qty for Production',
|
||||||
|
'Safety Stock', 'Required Qty']]
|
||||||
|
|
||||||
for d in get_items_for_material_requests(doc):
|
for d in get_items_for_material_requests(doc):
|
||||||
item_list.append([d.get('item_code'), d.get('description'), d.get('stock_uom'), d.get('quantity'),
|
item_list.append([d.get('item_code'), d.get('description'), d.get('stock_uom'), d.get('warehouse'),
|
||||||
d.get('warehouse'), d.get('projected_qty'), d.get('actual_qty')])
|
d.get('required_bom_qty'), d.get('projected_qty'), d.get('actual_qty'), d.get('ordered_qty'),
|
||||||
|
d.get('reserved_qty_for_production'), d.get('safety_stock'), d.get('quantity')])
|
||||||
|
|
||||||
if not doc.get('for_warehouse'):
|
if not doc.get('for_warehouse'):
|
||||||
row = {'item_code': d.get('item_code')}
|
row = {'item_code': d.get('item_code')}
|
||||||
@ -447,8 +449,9 @@ def download_raw_materials(doc):
|
|||||||
if d.get("warehouse") == bin_dict.get('warehouse'):
|
if d.get("warehouse") == bin_dict.get('warehouse'):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
item_list.append(['', '', '', '', bin_dict.get('warehouse'),
|
item_list.append(['', '', '', bin_dict.get('warehouse'), '',
|
||||||
bin_dict.get('projected_qty', 0), bin_dict.get('actual_qty', 0)])
|
bin_dict.get('projected_qty', 0), bin_dict.get('actual_qty', 0),
|
||||||
|
bin_dict.get('ordered_qty', 0), bin_dict.get('reserved_qty_for_production', 0)])
|
||||||
|
|
||||||
build_csv_response(item_list, doc.name)
|
build_csv_response(item_list, doc.name)
|
||||||
|
|
||||||
@ -482,7 +485,7 @@ def get_subitems(doc, data, item_details, bom_no, company, include_non_stock_ite
|
|||||||
ifnull(%(parent_qty)s * sum(bom_item.stock_qty/ifnull(bom.quantity, 1)) * %(planned_qty)s, 0) as qty,
|
ifnull(%(parent_qty)s * sum(bom_item.stock_qty/ifnull(bom.quantity, 1)) * %(planned_qty)s, 0) as qty,
|
||||||
item.is_sub_contracted_item as is_sub_contracted, bom_item.source_warehouse,
|
item.is_sub_contracted_item as is_sub_contracted, bom_item.source_warehouse,
|
||||||
item.default_bom as default_bom, bom_item.description as description,
|
item.default_bom as default_bom, bom_item.description as description,
|
||||||
bom_item.stock_uom as stock_uom, item.min_order_qty as min_order_qty,
|
bom_item.stock_uom as stock_uom, item.min_order_qty as min_order_qty, item.safety_stock as safety_stock,
|
||||||
item_default.default_warehouse, item.purchase_uom, item_uom.conversion_factor
|
item_default.default_warehouse, item.purchase_uom, item_uom.conversion_factor
|
||||||
FROM
|
FROM
|
||||||
`tabBOM Item` bom_item
|
`tabBOM Item` bom_item
|
||||||
@ -518,8 +521,8 @@ def get_subitems(doc, data, item_details, bom_no, company, include_non_stock_ite
|
|||||||
include_non_stock_items, include_subcontracted_items, d.qty)
|
include_non_stock_items, include_subcontracted_items, d.qty)
|
||||||
return item_details
|
return item_details
|
||||||
|
|
||||||
def get_material_request_items(row, sales_order,
|
def get_material_request_items(row, sales_order, company,
|
||||||
company, ignore_existing_ordered_qty, warehouse, bin_dict):
|
ignore_existing_ordered_qty, include_safety_stock, warehouse, bin_dict):
|
||||||
total_qty = row['qty']
|
total_qty = row['qty']
|
||||||
|
|
||||||
required_qty = 0
|
required_qty = 0
|
||||||
@ -543,17 +546,24 @@ def get_material_request_items(row, sales_order,
|
|||||||
if frappe.db.get_value("UOM", row['purchase_uom'], "must_be_whole_number"):
|
if frappe.db.get_value("UOM", row['purchase_uom'], "must_be_whole_number"):
|
||||||
required_qty = ceil(required_qty)
|
required_qty = ceil(required_qty)
|
||||||
|
|
||||||
|
if include_safety_stock:
|
||||||
|
required_qty += flt(row['safety_stock'])
|
||||||
|
|
||||||
if required_qty > 0:
|
if required_qty > 0:
|
||||||
return {
|
return {
|
||||||
'item_code': row.item_code,
|
'item_code': row.item_code,
|
||||||
'item_name': row.item_name,
|
'item_name': row.item_name,
|
||||||
'quantity': required_qty,
|
'quantity': required_qty,
|
||||||
|
'required_bom_qty': total_qty,
|
||||||
'description': row.description,
|
'description': row.description,
|
||||||
'stock_uom': row.get("stock_uom"),
|
'stock_uom': row.get("stock_uom"),
|
||||||
'warehouse': warehouse or row.get('source_warehouse') \
|
'warehouse': warehouse or row.get('source_warehouse') \
|
||||||
or row.get('default_warehouse') or item_group_defaults.get("default_warehouse"),
|
or row.get('default_warehouse') or item_group_defaults.get("default_warehouse"),
|
||||||
|
'safety_stock': row.safety_stock,
|
||||||
'actual_qty': bin_dict.get("actual_qty", 0),
|
'actual_qty': bin_dict.get("actual_qty", 0),
|
||||||
'projected_qty': bin_dict.get("projected_qty", 0),
|
'projected_qty': bin_dict.get("projected_qty", 0),
|
||||||
|
'ordered_qty': bin_dict.get("ordered_qty", 0),
|
||||||
|
'reserved_qty_for_production': bin_dict.get("reserved_qty_for_production", 0),
|
||||||
'min_order_qty': row['min_order_qty'],
|
'min_order_qty': row['min_order_qty'],
|
||||||
'material_request_type': row.get("default_material_request_type"),
|
'material_request_type': row.get("default_material_request_type"),
|
||||||
'sales_order': sales_order,
|
'sales_order': sales_order,
|
||||||
@ -620,7 +630,8 @@ def get_bin_details(row, company, for_warehouse=None, all_warehouse=False):
|
|||||||
""".format(lft, rgt, company)
|
""".format(lft, rgt, company)
|
||||||
|
|
||||||
return frappe.db.sql(""" select ifnull(sum(projected_qty),0) as projected_qty,
|
return frappe.db.sql(""" select ifnull(sum(projected_qty),0) as projected_qty,
|
||||||
ifnull(sum(actual_qty),0) as actual_qty, warehouse from `tabBin`
|
ifnull(sum(actual_qty),0) as actual_qty, ifnull(sum(ordered_qty),0) as ordered_qty,
|
||||||
|
ifnull(sum(reserved_qty_for_production),0) as reserved_qty_for_production, warehouse from `tabBin`
|
||||||
where item_code = %(item_code)s {conditions}
|
where item_code = %(item_code)s {conditions}
|
||||||
group by item_code, warehouse
|
group by item_code, warehouse
|
||||||
""".format(conditions=conditions), { "item_code": row['item_code'] }, as_dict=1)
|
""".format(conditions=conditions), { "item_code": row['item_code'] }, as_dict=1)
|
||||||
@ -660,6 +671,7 @@ def get_items_for_material_requests(doc, warehouses=None):
|
|||||||
|
|
||||||
company = doc.get('company')
|
company = doc.get('company')
|
||||||
ignore_existing_ordered_qty = doc.get('ignore_existing_ordered_qty')
|
ignore_existing_ordered_qty = doc.get('ignore_existing_ordered_qty')
|
||||||
|
include_safety_stock = doc.get('include_safety_stock')
|
||||||
|
|
||||||
so_item_details = frappe._dict()
|
so_item_details = frappe._dict()
|
||||||
for data in po_items:
|
for data in po_items:
|
||||||
@ -711,6 +723,7 @@ def get_items_for_material_requests(doc, warehouses=None):
|
|||||||
'description' : item_master.description,
|
'description' : item_master.description,
|
||||||
'stock_uom' : item_master.stock_uom,
|
'stock_uom' : item_master.stock_uom,
|
||||||
'conversion_factor' : conversion_factor,
|
'conversion_factor' : conversion_factor,
|
||||||
|
'safety_stock': item_master.safety_stock
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -732,7 +745,7 @@ def get_items_for_material_requests(doc, warehouses=None):
|
|||||||
|
|
||||||
if details.qty > 0:
|
if details.qty > 0:
|
||||||
items = get_material_request_items(details, sales_order, company,
|
items = get_material_request_items(details, sales_order, company,
|
||||||
ignore_existing_ordered_qty, warehouse, bin_dict)
|
ignore_existing_ordered_qty, include_safety_stock, warehouse, bin_dict)
|
||||||
if items:
|
if items:
|
||||||
mr_items.append(items)
|
mr_items.append(items)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user