feat: Only update exploded items rate and amount
- Generate RM-Rate map from Items table (will include subassembly items with rate) - Function to reset exploded item rate from above map - `db_update` exploded item rate only if rate is changed - Via Update Cost, only update exploded items rate, do not regenerate table again - Exploded Items are regenerated on Save and Replace BOM job - `calculate_exploded_cost` is run only via non doc events (Update Cost button, Update BOMs Cost Job)
This commit is contained in:
parent
9f5f18e94d
commit
eabd8290d4
@ -5,7 +5,7 @@ import functools
|
||||
import re
|
||||
from collections import deque
|
||||
from operator import itemgetter
|
||||
from typing import List
|
||||
from typing import Dict, List
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
@ -185,6 +185,7 @@ class BOM(WebsiteGenerator):
|
||||
self.validate_transfer_against()
|
||||
self.set_routing_operations()
|
||||
self.validate_operations()
|
||||
self.update_exploded_items(save=False)
|
||||
self.calculate_cost()
|
||||
self.update_stock_qty()
|
||||
self.update_cost(update_parent=False, from_child_bom=True, update_hour_rate=False, save=False)
|
||||
@ -391,8 +392,6 @@ class BOM(WebsiteGenerator):
|
||||
if save:
|
||||
self.db_update()
|
||||
|
||||
self.update_exploded_items(save=save)
|
||||
|
||||
# update parent BOMs
|
||||
if self.total_cost != existing_bom_cost and update_parent:
|
||||
parent_boms = frappe.db.sql_list(
|
||||
@ -594,6 +593,10 @@ class BOM(WebsiteGenerator):
|
||||
self.calculate_op_cost(update_hour_rate)
|
||||
self.calculate_rm_cost(save=save_updates)
|
||||
self.calculate_sm_cost(save=save_updates)
|
||||
if save_updates:
|
||||
# not via doc event, table is not regenerated and needs updation
|
||||
self.calculate_exploded_cost()
|
||||
|
||||
self.total_cost = self.operating_cost + self.raw_material_cost - self.scrap_material_cost
|
||||
self.base_total_cost = (
|
||||
self.base_operating_cost + self.base_raw_material_cost - self.base_scrap_material_cost
|
||||
@ -689,6 +692,36 @@ class BOM(WebsiteGenerator):
|
||||
self.scrap_material_cost = total_sm_cost
|
||||
self.base_scrap_material_cost = base_total_sm_cost
|
||||
|
||||
def calculate_exploded_cost(self):
|
||||
"Set exploded row cost from it's parent BOM."
|
||||
rm_rate_map = self.get_rm_rate_map()
|
||||
|
||||
for row in self.get("exploded_items"):
|
||||
old_rate = flt(row.rate)
|
||||
row.rate = rm_rate_map.get(row.item_code)
|
||||
row.amount = flt(row.stock_qty) * row.rate
|
||||
|
||||
if old_rate != row.rate:
|
||||
# Only db_update if unchanged
|
||||
row.db_update()
|
||||
|
||||
def get_rm_rate_map(self) -> Dict[str, float]:
|
||||
"Create Raw Material-Rate map for Exploded Items. Fetch rate from Items table or Subassembly BOM."
|
||||
rm_rate_map = {}
|
||||
|
||||
for item in self.get("items"):
|
||||
if item.bom_no:
|
||||
# Get Item-Rate from Subassembly BOM
|
||||
explosion_items = frappe.db.get_all(
|
||||
"BOM Explosion Item", filters={"parent": item.bom_no}, fields=["item_code", "rate"]
|
||||
)
|
||||
explosion_item_rate = {item.item_code: flt(item.rate) for item in explosion_items}
|
||||
rm_rate_map.update(explosion_item_rate)
|
||||
else:
|
||||
rm_rate_map[item.item_code] = flt(item.base_rate) / flt(item.conversion_factor or 1.0)
|
||||
|
||||
return rm_rate_map
|
||||
|
||||
def update_exploded_items(self, save=True):
|
||||
"""Update Flat BOM, following will be correct data"""
|
||||
self.get_exploded_items()
|
||||
|
@ -169,13 +169,15 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-10-08 16:21:29.386212",
|
||||
"modified": "2022-05-27 13:42:23.305455",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM Explosion Item",
|
||||
"naming_rule": "Random",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
@ -120,7 +120,6 @@ def update_cost_in_boms(bom_list: List[str], docname: str) -> Dict[str, Dict]:
|
||||
for bom in bom_list:
|
||||
bom_doc = frappe.get_cached_doc("BOM", bom)
|
||||
bom_doc.calculate_cost(save_updates=True, update_hour_rate=True)
|
||||
# bom_doc.update_exploded_items(save=True) #TODO: edit exploded items rate
|
||||
bom_doc.db_update()
|
||||
updated_boms[bom] = True
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user