From e286d0590471a29346c35ba55c5eb21122b1b212 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 30 Mar 2023 16:00:04 +0530 Subject: [PATCH] fix: SRE `Available Qty to Reserve` for Group Warehouse --- erpnext/controllers/stock_controller.py | 31 +++--------------- .../doctype/sales_order/sales_order.py | 12 +++++-- .../stock_reservation_entry.py | 32 +++++++++++++++++++ 3 files changed, 45 insertions(+), 30 deletions(-) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 6e2fb2eae4..507deae42c 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -784,6 +784,10 @@ class StockController(AccountsController): gl_entries.append(self.get_gl_dict(gl_entry, item=item)) def make_sr_entries(self): + from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import ( + get_available_qty_to_reserve, + ) + if not self.get("reserve_stock"): return @@ -1021,33 +1025,6 @@ def get_conditions_to_validate_future_sle(sl_entries): return or_conditions -@frappe.whitelist() -def get_available_qty_to_reserve(item_code, warehouse): - from frappe.query_builder.functions import Sum - - from erpnext.stock.utils import get_stock_balance - - available_qty = get_stock_balance(item_code, warehouse) - - if available_qty: - sre = frappe.qb.DocType("Stock Reservation Entry") - reserved_qty = ( - 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()[0][0] or 0.0 - - if reserved_qty: - return available_qty - reserved_qty - - return available_qty - - def create_repost_item_valuation_entry(args): args = frappe._dict(args) repost_entry = frappe.new_doc("Repost Item Valuation") diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 5accaf61a9..403477b375 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -634,9 +634,12 @@ def make_delivery_note(source_name, target_doc=None, skip_item_mapping=False): for item in source.get("items"): if item.name in sre_dict: - qty_to_deliver = ( - sre_dict[item.name]["reserved_qty"] - sre_dict[item.name]["delivered_qty"] - ) / item.conversion_factor + reserved_qty, delivered_qty, warehouse = ( + sre_dict[item.name]["reserved_qty"], + sre_dict[item.name]["delivered_qty"], + sre_dict[item.name]["warehouse"], + ) + qty_to_deliver = (reserved_qty - delivered_qty) / item.conversion_factor row = frappe.new_doc("Delivery Note Item") row.against_sales_order = source.name @@ -650,6 +653,9 @@ def make_delivery_note(source_name, target_doc=None, skip_item_mapping=False): row.uom = item.uom row.conversion_factor = item.conversion_factor + if not frappe.get_cached_value("Warehouse", warehouse, "is_group"): + row.warehouse = warehouse + target.append("items", row) target.run_method("set_missing_values") diff --git a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py index efe99799b1..c47049319d 100644 --- a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py +++ b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py @@ -85,6 +85,38 @@ class StockReservationEntry(Document): ) +@frappe.whitelist() +def get_available_qty_to_reserve(item_code, warehouse): + from frappe.query_builder.functions import Sum + + from erpnext.stock.get_item_details import get_bin_details + + available_qty = get_bin_details(item_code, warehouse, include_child_warehouses=True).get( + "actual_qty" + ) + + if available_qty: + from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses + + warehouses = get_child_warehouses(warehouse) + sre = frappe.qb.DocType("Stock Reservation Entry") + reserved_qty = ( + frappe.qb.from_(sre) + .select(Sum(sre.reserved_qty - sre.delivered_qty)) + .where( + (sre.docstatus == 1) + & (sre.item_code == item_code) + & (sre.warehouse.isin(warehouses)) + & (sre.status.notin(["Delivered", "Cancelled"])) + ) + ).run()[0][0] or 0.0 + + if reserved_qty: + return available_qty - reserved_qty + + return available_qty + + def get_stock_reservation_entries_for_voucher( voucher_type: str, voucher_no: str, voucher_detail_no: str = None, fields: list[str] = None ) -> list[dict]: