chore: Limit Update Cost jobs & `db_update` only if changed values
- If `Update Cost` job is ongoing, then block creation of new ones since all BOMs are updated
- `db_update` in `calculate_rm_cost` only if changed values to reduce redundant row updates
- Misc: Use variable for batch size
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 7055efa..d4e0d4b 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -644,6 +644,7 @@
base_total_rm_cost = 0
for d in self.get("items"):
+ old_rate = d.rate
d.rate = self.get_rm_rate(
{
"company": self.company,
@@ -656,6 +657,7 @@
"sourced_by_supplier": d.sourced_by_supplier,
}
)
+
d.base_rate = flt(d.rate) * flt(self.conversion_rate)
d.amount = flt(d.rate, d.precision("rate")) * flt(d.qty, d.precision("qty"))
d.base_amount = d.amount * flt(self.conversion_rate)
@@ -665,7 +667,7 @@
total_rm_cost += d.amount
base_total_rm_cost += d.base_amount
- if save:
+ if save and (old_rate != d.rate):
d.db_update()
self.raw_material_cost = total_rm_cost
diff --git a/erpnext/manufacturing/doctype/bom_update_log/bom_update_log.py b/erpnext/manufacturing/doctype/bom_update_log/bom_update_log.py
index 639628a..f61f863 100644
--- a/erpnext/manufacturing/doctype/bom_update_log/bom_update_log.py
+++ b/erpnext/manufacturing/doctype/bom_update_log/bom_update_log.py
@@ -26,6 +26,8 @@
self.validate_boms_are_specified()
self.validate_same_bom()
self.validate_bom_items()
+ else:
+ self.validate_bom_cost_update_in_progress()
self.status = "Queued"
@@ -48,6 +50,21 @@
if current_bom_item != new_bom_item:
frappe.throw(_("The selected BOMs are not for the same item"))
+ def validate_bom_cost_update_in_progress(self):
+ "If another Cost Updation Log is still in progress, dont make new ones."
+
+ wip_log = frappe.get_all(
+ "BOM Update Log",
+ {"update_type": "Update Cost", "status": ["in", ["Queued", "In Progress", "Paused"]]},
+ limit_page_length=1,
+ )
+ if wip_log:
+ log_link = frappe.utils.get_link_to_form("BOM Update Log", wip_log[0].name)
+ frappe.throw(
+ _("BOM Updation already in progress. Please wait until {0} is complete.").format(log_link),
+ title=_("Note"),
+ )
+
def on_submit(self):
if frappe.flags.in_test:
return
@@ -124,10 +141,11 @@
current_boms_list = [bom for bom in current_boms]
while current_boms_list:
- boms_to_process = current_boms_list[:20000] # slice out batch of 20k BOMs
+ batch_size = 20_000
+ boms_to_process = current_boms_list[:batch_size] # slice out batch of 20k BOMs
# update list to exclude 20K (queued) BOMs
- current_boms_list = current_boms_list[20000:] if len(current_boms_list) > 20000 else []
+ current_boms_list = current_boms_list[batch_size:] if len(current_boms_list) > batch_size else []
frappe.enqueue(
method="erpnext.manufacturing.doctype.bom_update_log.bom_updation_utils.update_cost_in_level",
doc=update_doc,
diff --git a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
index 4a2e03f..758d8ed 100644
--- a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
+++ b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
@@ -38,7 +38,13 @@
def auto_update_latest_price_in_all_boms() -> None:
"""Called via hooks.py."""
if frappe.db.get_single_value("Manufacturing Settings", "update_bom_costs_automatically"):
- create_bom_update_log(update_type="Update Cost")
+ wip_log = frappe.get_all(
+ "BOM Update Log",
+ {"update_type": "Update Cost", "status": ["in", ["Queued", "In Progress", "Paused"]]},
+ limit_page_length=1,
+ )
+ if not wip_log:
+ create_bom_update_log(update_type="Update Cost")
def create_bom_update_log(