Skip to content

Commit

Permalink
feat: consider over_order_allowance while validating sales order qty
Browse files Browse the repository at this point in the history
(cherry picked from commit 53701c3)
  • Loading branch information
s-aga-r authored and mergify[bot] committed Mar 17, 2023
1 parent 46b5ba9 commit 09b577a
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 28 deletions.
32 changes: 4 additions & 28 deletions erpnext/buying/doctype/purchase_order/purchase_order.py
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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:
Expand Down
35 changes: 35 additions & 0 deletions erpnext/manufacturing/doctype/blanket_order/blanket_order.py
Expand Up @@ -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
)
)
4 changes: 4 additions & 0 deletions erpnext/selling/doctype/sales_order/sales_order.py
Expand Up @@ -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,
)
Expand Down Expand Up @@ -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
)
Expand Down

0 comments on commit 09b577a

Please sign in to comment.