Skip to content

Commit

Permalink
feat: Only update exploded items rate and amount
Browse files Browse the repository at this point in the history
- 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)
  • Loading branch information
marination committed May 27, 2022
1 parent 9f5f18e commit eabd829
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 5 deletions.
39 changes: 36 additions & 3 deletions erpnext/manufacturing/doctype/bom/bom.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import re
from collections import deque
from operator import itemgetter
from typing import List
from typing import Dict, List

import frappe
from frappe import _
Expand Down Expand Up @@ -185,6 +185,7 @@ def validate(self):
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)
Expand Down Expand Up @@ -391,8 +392,6 @@ def update_cost(self, update_parent=True, from_child_bom=False, update_hour_rate
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(
Expand Down Expand Up @@ -594,6 +593,10 @@ def calculate_cost(self, save_updates=False, update_hour_rate=False):
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
Expand Down Expand Up @@ -689,6 +692,36 @@ def calculate_sm_cost(self, save=False):
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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit eabd829

Please sign in to comment.