Merge pull request #39251 from ruthra-kumar/continues_pr_39196
fix: update status on manual allocation
diff --git a/erpnext/manufacturing/doctype/bom_update_log/bom_updation_utils.py b/erpnext/manufacturing/doctype/bom_update_log/bom_updation_utils.py
index a2919b7..f013b88 100644
--- a/erpnext/manufacturing/doctype/bom_update_log/bom_updation_utils.py
+++ b/erpnext/manufacturing/doctype/bom_update_log/bom_updation_utils.py
@@ -86,10 +86,12 @@
if new_bom == d.parent:
frappe.throw(_("BOM recursion: {0} cannot be child of {1}").format(new_bom, d.parent))
- bom_list.append(d.parent)
+ if d.parent not in tuple(bom_list):
+ bom_list.append(d.parent)
+
get_ancestor_boms(d.parent, bom_list)
- return list(set(bom_list))
+ return bom_list
def update_new_bom_in_bom_items(unit_cost: float, current_bom: str, new_bom: str) -> None:
diff --git a/erpnext/manufacturing/doctype/bom_update_log/test_bom_update_log.py b/erpnext/manufacturing/doctype/bom_update_log/test_bom_update_log.py
index b38fc89..30e6f5e 100644
--- a/erpnext/manufacturing/doctype/bom_update_log/test_bom_update_log.py
+++ b/erpnext/manufacturing/doctype/bom_update_log/test_bom_update_log.py
@@ -57,6 +57,68 @@
log.reload()
self.assertEqual(log.status, "Completed")
+ def test_bom_replace_for_root_bom(self):
+ """
+ - B-Item A (Root Item)
+ - B-Item B
+ - B-Item C
+ - B-Item D
+ - B-Item E
+ - B-Item F
+
+ Create New BOM for B-Item E with B-Item G and replace it in the above BOM.
+ """
+
+ from erpnext.manufacturing.doctype.bom.test_bom import create_nested_bom
+ from erpnext.stock.doctype.item.test_item import make_item
+
+ items = ["B-Item A", "B-Item B", "B-Item C", "B-Item D", "B-Item E", "B-Item F", "B-Item G"]
+
+ for item_code in items:
+ if not frappe.db.exists("Item", item_code):
+ make_item(item_code)
+
+ for item_code in items:
+ remove_bom(item_code)
+
+ bom_tree = {
+ "B-Item A": {"B-Item B": {"B-Item C": {}}, "B-Item D": {"B-Item E": {"B-Item F": {}}}}
+ }
+
+ root_bom = create_nested_bom(bom_tree, prefix="")
+
+ exploded_items = frappe.get_all(
+ "BOM Explosion Item", filters={"parent": root_bom.name}, fields=["item_code"]
+ )
+
+ exploded_items = [item.item_code for item in exploded_items]
+ expected_exploded_items = ["B-Item C", "B-Item F"]
+ self.assertEqual(sorted(exploded_items), sorted(expected_exploded_items))
+
+ old_bom = frappe.db.get_value("BOM", {"item": "B-Item E"}, "name")
+ bom_tree = {"B-Item E": {"B-Item G": {}}}
+
+ new_bom = create_nested_bom(bom_tree, prefix="")
+ enqueue_replace_bom(boms=frappe._dict(current_bom=old_bom, new_bom=new_bom.name))
+
+ exploded_items = frappe.get_all(
+ "BOM Explosion Item", filters={"parent": root_bom.name}, fields=["item_code"]
+ )
+
+ exploded_items = [item.item_code for item in exploded_items]
+ expected_exploded_items = ["B-Item C", "B-Item G"]
+ self.assertEqual(sorted(exploded_items), sorted(expected_exploded_items))
+
+
+def remove_bom(item_code):
+ boms = frappe.get_all("BOM", fields=["docstatus", "name"], filters={"item": item_code})
+
+ for row in boms:
+ if row.docstatus == 1:
+ frappe.get_doc("BOM", row.name).cancel()
+
+ frappe.delete_doc("BOM", row.name)
+
def update_cost_in_all_boms_in_test():
"""
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index 09941ea..9542361 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -582,17 +582,17 @@
def set_indicator(self):
"""Set indicator for portal"""
- if self.per_billed < 100 and self.per_delivered < 100:
- self.indicator_color = "orange"
- self.indicator_title = _("Not Paid and Not Delivered")
+ self.indicator_color = {
+ "Draft": "red",
+ "On Hold": "orange",
+ "To Deliver and Bill": "orange",
+ "To Bill": "orange",
+ "To Deliver": "orange",
+ "Completed": "green",
+ "Cancelled": "red",
+ }.get(self.status, "blue")
- elif self.per_billed == 100 and self.per_delivered < 100:
- self.indicator_color = "orange"
- self.indicator_title = _("Paid and Not Delivered")
-
- else:
- self.indicator_color = "green"
- self.indicator_title = _("Paid")
+ self.indicator_title = _(self.status)
def on_recurring(self, reference_doc, auto_repeat_doc):
def _get_delivery_date(ref_doc_delivery_date, red_doc_transaction_date, transaction_date):