fix: don't allow to deliver/transfer reserved stock
This commit is contained in:
parent
56097807b4
commit
f0acb2049b
@ -179,18 +179,13 @@ def get_stock_reservation_entries_for_voucher(
|
||||
|
||||
|
||||
def get_sre_reserved_qty_details_for_item_and_warehouse(
|
||||
item_code: str | list, warehouse: str | list
|
||||
item_code_list: list, warehouse_list: list
|
||||
) -> dict:
|
||||
"""Returns a dict like {("item_code", "warehouse"): "reserved_qty", ... }."""
|
||||
|
||||
sre_details = {}
|
||||
|
||||
if item_code and warehouse:
|
||||
if isinstance(item_code, str):
|
||||
item_code = [item_code]
|
||||
if isinstance(warehouse, str):
|
||||
warehouse = [warehouse]
|
||||
|
||||
if item_code_list and warehouse_list:
|
||||
sre = frappe.qb.DocType("Stock Reservation Entry")
|
||||
sre_data = (
|
||||
frappe.qb.from_(sre)
|
||||
@ -201,8 +196,8 @@ def get_sre_reserved_qty_details_for_item_and_warehouse(
|
||||
)
|
||||
.where(
|
||||
(sre.docstatus == 1)
|
||||
& (sre.item_code.isin(item_code))
|
||||
& (sre.warehouse.isin(warehouse))
|
||||
& (sre.item_code.isin(item_code_list))
|
||||
& (sre.warehouse.isin(warehouse_list))
|
||||
& (sre.status.notin(["Delivered", "Cancelled"]))
|
||||
)
|
||||
.groupby(sre.item_code, sre.warehouse)
|
||||
@ -214,6 +209,27 @@ def get_sre_reserved_qty_details_for_item_and_warehouse(
|
||||
return sre_details
|
||||
|
||||
|
||||
def get_sre_reserved_qty_for_item_and_warehouse(item_code: str, warehouse: str) -> float:
|
||||
"""Returns `Reserved Qty` for Item and Warehouse combination."""
|
||||
|
||||
reserved_qty = 0.0
|
||||
|
||||
if item_code and warehouse:
|
||||
sre = frappe.qb.DocType("Stock Reservation Entry")
|
||||
return (
|
||||
frappe.qb.from_(sre)
|
||||
.select(Sum(sre.reserved_qty - sre.delivered_qty))
|
||||
.where(
|
||||
(sre.docstatus == 1)
|
||||
& (sre.item_code == item_code)
|
||||
& (sre.warehouse == warehouse)
|
||||
& (sre.status.notin(["Delivered", "Cancelled"]))
|
||||
)
|
||||
).run(as_list=True)[0][0] or 0.0
|
||||
|
||||
return reserved_qty
|
||||
|
||||
|
||||
def get_sre_reserved_qty_details_for_voucher(
|
||||
voucher_type: str, voucher_no: str, voucher_detail_no: str = None
|
||||
) -> dict:
|
||||
|
@ -13,6 +13,9 @@ from frappe.utils import cint, cstr, flt, get_link_to_form, getdate, now, nowdat
|
||||
|
||||
import erpnext
|
||||
from erpnext.stock.doctype.bin.bin import update_qty as update_bin_qty
|
||||
from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import (
|
||||
get_sre_reserved_qty_for_item_and_warehouse as get_reserved_stock,
|
||||
)
|
||||
from erpnext.stock.utils import (
|
||||
get_incoming_outgoing_rate_for_cancel,
|
||||
get_or_make_bin,
|
||||
@ -380,6 +383,7 @@ class update_entries_after(object):
|
||||
self.new_items_found = False
|
||||
self.distinct_item_warehouses = args.get("distinct_item_warehouses", frappe._dict())
|
||||
self.affected_transactions: Set[Tuple[str, str]] = set()
|
||||
self.reserved_stock = get_reserved_stock(self.args.item_code, self.args.warehouse)
|
||||
|
||||
self.data = frappe._dict()
|
||||
self.initialize_previous_data(self.args)
|
||||
@ -610,7 +614,7 @@ class update_entries_after(object):
|
||||
validate negative stock for entries current datetime onwards
|
||||
will not consider cancelled entries
|
||||
"""
|
||||
diff = self.wh_data.qty_after_transaction + flt(sle.actual_qty)
|
||||
diff = self.wh_data.qty_after_transaction + flt(sle.actual_qty) - flt(self.reserved_stock)
|
||||
diff = flt(diff, self.flt_precision) # respect system precision
|
||||
|
||||
if diff < 0 and abs(diff) > 0.0001:
|
||||
@ -1006,6 +1010,7 @@ class update_entries_after(object):
|
||||
msg_list = []
|
||||
for warehouse, exceptions in self.exceptions.items():
|
||||
deficiency = min(e["diff"] for e in exceptions)
|
||||
msg_prefix = _("As {} units are reserved, ").format(frappe.bold(self.reserved_stock))
|
||||
|
||||
if (
|
||||
exceptions[0]["voucher_type"],
|
||||
@ -1013,7 +1018,7 @@ class update_entries_after(object):
|
||||
) in frappe.local.flags.currently_saving:
|
||||
|
||||
msg = _("{0} units of {1} needed in {2} to complete this transaction.").format(
|
||||
abs(deficiency),
|
||||
frappe.bold(abs(deficiency)),
|
||||
frappe.get_desk_link("Item", exceptions[0]["item_code"]),
|
||||
frappe.get_desk_link("Warehouse", warehouse),
|
||||
)
|
||||
@ -1021,7 +1026,7 @@ class update_entries_after(object):
|
||||
msg = _(
|
||||
"{0} units of {1} needed in {2} on {3} {4} for {5} to complete this transaction."
|
||||
).format(
|
||||
abs(deficiency),
|
||||
frappe.bold(abs(deficiency)),
|
||||
frappe.get_desk_link("Item", exceptions[0]["item_code"]),
|
||||
frappe.get_desk_link("Warehouse", warehouse),
|
||||
exceptions[0]["posting_date"],
|
||||
@ -1030,6 +1035,9 @@ class update_entries_after(object):
|
||||
)
|
||||
|
||||
if msg:
|
||||
if self.reserved_stock:
|
||||
msg = msg_prefix + msg
|
||||
|
||||
msg_list.append(msg)
|
||||
|
||||
if msg_list:
|
||||
|
Loading…
x
Reference in New Issue
Block a user