diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index d9ff98132252..06b9d29e69c7 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -21,6 +21,9 @@ from erpnext.accounts.party import get_party_account, get_party_account_currency from erpnext.buying.utils import check_on_hold_or_closed_status, validate_for_items from erpnext.controllers.buying_controller import BuyingController +from erpnext.manufacturing.doctype.blanket_order.blanket_order import ( + validate_against_blanket_order, +) from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults from erpnext.stock.doctype.item.item import get_item_defaults, get_last_purchase_details from erpnext.stock.stock_balance import get_ordered_qty, update_bin_qty @@ -69,7 +72,7 @@ def validate(self): self.validate_with_previous_doc() self.validate_for_subcontracting() self.validate_minimum_order_qty() - self.validate_against_blanket_order() + validate_against_blanket_order(self) if self.is_old_subcontracting_flow: self.validate_bom_for_subcontracting_items() @@ -198,33 +201,6 @@ def validate_minimum_order_qty(self): ).format(item_code, qty, itemwise_min_order_qty.get(item_code)) ) - def validate_against_blanket_order(self): - po_data = {} - for item in self.get("items"): - if item.against_blanket_order and item.blanket_order: - if item.blanket_order in po_data: - if item.item_code in po_data[item.blanket_order]: - po_data[item.blanket_order][item.item_code] += item.qty - else: - po_data[item.blanket_order][item.item_code] = item.qty - else: - po_data[item.blanket_order] = {item.item_code: item.qty} - - if po_data: - allowance = flt(frappe.db.get_single_value("Buying Settings", "over_order_allowance")) - for bo_name, item_data in po_data.items(): - bo_doc = frappe.get_doc("Blanket Order", bo_name) - for item in bo_doc.get("items"): - if item.item_code in item_data: - remaining_qty = item.qty - item.ordered_qty - allowed_qty = remaining_qty + (remaining_qty * (allowance / 100)) - if allowed_qty < item_data[item.item_code]: - frappe.throw( - _( - f"Item {item.item_code} cannot be ordered more than {allowed_qty} against Blanket Order {bo_name}." - ) - ) - def validate_bom_for_subcontracting_items(self): for item in self.items: if not item.bom: diff --git a/erpnext/manufacturing/doctype/blanket_order/blanket_order.py b/erpnext/manufacturing/doctype/blanket_order/blanket_order.py index d03f019b0847..32f1c365adef 100644 --- a/erpnext/manufacturing/doctype/blanket_order/blanket_order.py +++ b/erpnext/manufacturing/doctype/blanket_order/blanket_order.py @@ -87,3 +87,38 @@ def update_item(source, target, source_parent): }, ) return target_doc + + +def validate_against_blanket_order(order_doc): + if order_doc.doctype in ("Sales Order", "Purchase Order"): + order_data = {} + + for item in order_doc.get("items"): + if item.against_blanket_order and item.blanket_order: + if item.blanket_order in order_data: + if item.item_code in order_data[item.blanket_order]: + order_data[item.blanket_order][item.item_code] += item.qty + else: + order_data[item.blanket_order][item.item_code] = item.qty + else: + order_data[item.blanket_order] = {item.item_code: item.qty} + + if order_data: + allowance = flt( + frappe.db.get_single_value( + "Selling Settings" if order_doc.doctype == "Sales Order" else "Buying Settings", + "over_order_allowance", + ) + ) + for bo_name, item_data in order_data.items(): + bo_doc = frappe.get_doc("Blanket Order", bo_name) + for item in bo_doc.get("items"): + if item.item_code in item_data: + remaining_qty = item.qty - item.ordered_qty + allowed_qty = remaining_qty + (remaining_qty * (allowance / 100)) + if allowed_qty < item_data[item.item_code]: + frappe.throw( + _("Item {0} cannot be ordered more than {1} against Blanket Order {2}.").format( + item.item_code, allowed_qty, bo_name + ) + ) diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 385d0f3a5856..ee9161bee48e 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -21,6 +21,9 @@ ) from erpnext.accounts.party import get_party_account from erpnext.controllers.selling_controller import SellingController +from erpnext.manufacturing.doctype.blanket_order.blanket_order import ( + validate_against_blanket_order, +) from erpnext.manufacturing.doctype.production_plan.production_plan import ( get_items_for_material_requests, ) @@ -52,6 +55,7 @@ def validate(self): self.validate_warehouse() self.validate_drop_ship() self.validate_serial_no_based_delivery() + validate_against_blanket_order(self) validate_inter_company_party( self.doctype, self.customer, self.company, self.inter_company_order_reference )