mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-11 13:41:47 +00:00
feat: warn when ordered qty exceeds min order qty only by UOM rounding
A minimum order qty defined in stock UOM often has no exact representation in the purchase UOM, so the smallest valid order slightly exceeds the minimum. Surface that overage on the Purchase Order with a toast on first save when an item's ordered stock qty is above its minimum by less than one purchase-UOM step, so the buyer sees the marginal increase before sending the order. Sub-precision dust stays silent.
This commit is contained in:
@@ -319,6 +319,38 @@ class PurchaseOrder(BuyingController):
|
||||
).format(item_code, flt(qty, precision), itemwise_min_order_qty.get(item_code))
|
||||
)
|
||||
|
||||
self.warn_marginal_min_order_qty(itemwise_qty, itemwise_min_order_qty)
|
||||
|
||||
def warn_marginal_min_order_qty(self, itemwise_qty, itemwise_min_order_qty):
|
||||
"""Toast when an item's ordered qty exceeds its minimum only by purchase UOM rounding."""
|
||||
if not self.is_new():
|
||||
return
|
||||
|
||||
precision = self.items[0].precision("stock_qty")
|
||||
itemwise_step = frappe._dict()
|
||||
itemwise_stock_uom = frappe._dict()
|
||||
for d in self.get("items"):
|
||||
step = 10 ** -d.precision("qty") * flt(d.conversion_factor)
|
||||
itemwise_step[d.item_code] = max(itemwise_step.get(d.item_code, 0), step)
|
||||
itemwise_stock_uom[d.item_code] = d.stock_uom
|
||||
|
||||
for item_code, qty in itemwise_qty.items():
|
||||
min_order_qty = flt(itemwise_min_order_qty.get(item_code))
|
||||
overage = flt(qty) - min_order_qty
|
||||
if min_order_qty and flt(overage, precision) > 0 and overage < itemwise_step[item_code]:
|
||||
frappe.toast(
|
||||
_(
|
||||
"Item {0}: Ordered qty {1} {2} exceeds the minimum order qty {3} {2} by {4} {2} due to purchase UOM rounding."
|
||||
).format(
|
||||
item_code,
|
||||
flt(qty, precision),
|
||||
itemwise_stock_uom[item_code],
|
||||
min_order_qty,
|
||||
flt(overage, precision),
|
||||
),
|
||||
indicator="orange",
|
||||
)
|
||||
|
||||
def get_schedule_dates(self):
|
||||
for d in self.get("items"):
|
||||
if d.material_request_item and not d.schedule_date:
|
||||
|
||||
Reference in New Issue
Block a user