fix: don't allow to deliver/transfer reserved stock

This commit is contained in:
s-aga-r 2023-04-12 14:13:54 +05:30
parent 56097807b4
commit f0acb2049b
2 changed files with 36 additions and 12 deletions

View File

@ -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:

View File

@ -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: