diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 4da1e76c2dc..3576cd426d6 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -49,18 +49,6 @@ class PurchaseOrder(BuyingController): } ] - def can_update_items(self) -> bool: - result = True - - if self.is_subcontracted and not self.is_old_subcontracting_flow: - # Check - 1: NOT ALLOWED if non-cancelled Subcontracting Order exists for this Purchase Order - if frappe.db.exists( - "Subcontracting Order", {"purchase_order": self.name, "docstatus": ["!=", 2]} - ): - return False - - return result - def onload(self): supplier_tds = frappe.db.get_value("Supplier", self.supplier, "tax_withholding_category") self.set_onload("supplier_tds", supplier_tds) @@ -463,6 +451,17 @@ class PurchaseOrder(BuyingController): else: self.db_set("per_received", 0, update_modified=False) + def can_update_items(self) -> bool: + result = True + + if self.is_subcontracted and not self.is_old_subcontracting_flow: + if frappe.db.exists( + "Subcontracting Order", {"purchase_order": self.name, "docstatus": ["!=", 2]} + ): + result = False + + return result + def item_last_purchase_rate(name, conversion_rate, item_code, conversion_factor=1.0): """get last purchase rate for an item""" diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 340ec01bee7..081abe12104 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -2855,6 +2855,27 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil return update_supplied_items + def validate_fg_item_for_subcontracting(new_data, is_new): + if is_new: + if not new_data.get("fg_item"): + frappe.throw( + _("Finished Good Item is not specified for service item {0}").format(new_data["item_code"]) + ) + else: + is_sub_contracted_item, default_bom = frappe.db.get_value( + "Item", new_data["fg_item"], ["is_sub_contracted_item", "default_bom"] + ) + + if not is_sub_contracted_item: + frappe.throw( + _("Finished Good Item {0} must be a sub-contracted item").format(new_data["fg_item"]) + ) + elif not default_bom: + frappe.throw(_("Default BOM not found for FG Item {0}").format(new_data["fg_item"])) + + if not new_data.get("fg_item_qty"): + frappe.throw(_("Finished Good Item {0} Qty can not be zero").format(new_data["fg_item"])) + data = json.loads(trans_items) any_qty_changed = False # updated to true if any item's qty changes @@ -2886,6 +2907,7 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil prev_rate, new_rate = flt(child_item.get("rate")), flt(d.get("rate")) prev_qty, new_qty = flt(child_item.get("qty")), flt(d.get("qty")) + prev_fg_qty, new_fg_qty = flt(child_item.get("fg_item_qty")), flt(d.get("fg_item_qty")) prev_con_fac, new_con_fac = flt(child_item.get("conversion_factor")), flt( d.get("conversion_factor") ) @@ -2898,6 +2920,7 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil rate_unchanged = prev_rate == new_rate qty_unchanged = prev_qty == new_qty + fg_qty_unchanged = prev_fg_qty == new_fg_qty uom_unchanged = prev_uom == new_uom conversion_factor_unchanged = prev_con_fac == new_con_fac any_conversion_factor_changed |= not conversion_factor_unchanged @@ -2907,6 +2930,7 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil if ( rate_unchanged and qty_unchanged + and fg_qty_unchanged and conversion_factor_unchanged and uom_unchanged and date_unchanged @@ -2917,6 +2941,17 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil if flt(child_item.get("qty")) != flt(d.get("qty")): any_qty_changed = True + if ( + parent.doctype == "Purchase Order" + and parent.is_subcontracted + and not parent.is_old_subcontracting_flow + ): + validate_fg_item_for_subcontracting(d, new_child_flag) + child_item.fg_item_qty = flt(d["fg_item_qty"]) + + if new_child_flag: + child_item.fg_item = d["fg_item"] + child_item.qty = flt(d.get("qty")) rate_precision = child_item.precision("rate") or 2 conv_fac_precision = child_item.precision("conversion_factor") or 2 diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 9116fd1f036..c11d123982f 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -579,7 +579,9 @@ erpnext.utils.update_child_items = function(opts) { "conversion_factor": d.conversion_factor, "qty": d.qty, "rate": d.rate, - "uom": d.uom + "uom": d.uom, + "fg_item": d.fg_item, + "fg_item_qty": d.fg_item_qty, } });