From 10094829e8f0cc6649bcb2bcfa98fbd1942c5017 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 3 Nov 2025 15:19:24 +0530 Subject: [PATCH] fix: stock reservation cancellation for transfer case --- .../production_plan/production_plan.py | 7 ++++- .../stock_reservation_entry.py | 31 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index fe3c294e471..8a7133490c9 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -1928,7 +1928,12 @@ def get_reserved_qty_for_production_plan(item_code, warehouse): frappe.qb.from_(table) .inner_join(child) .on(table.name == child.parent) - .select(Sum(child.quantity * child.conversion_factor)) + .select( + Sum( + Case().when(child.quantity == 0, child.required_bom_qty).else_(child.quantity) + * child.conversion_factor + ) + ) .where( (table.docstatus == 1) & (child.item_code == item_code) 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 018d0b20dc0..d6ec32aeff8 100644 --- a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py +++ b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py @@ -109,6 +109,37 @@ class StockReservationEntry(Document): self.update_status() self.update_reserved_stock_in_bin() + def before_cancel(self) -> None: + self.validate_reserved_entries() + + def validate_reserved_entries(self): + entries = frappe.get_all( + "Stock Reservation Entry", + fields=["voucher_no as name"], + filters={ + "status": "Closed", + "docstatus": 1, + "from_voucher_type": "Purchase Receipt", + "from_voucher_no": self.from_voucher_no, + }, + ) + + if entries: + work_orders = frappe.get_all( + "Work Order", + fields=["name"], + filters={"production_plan": ("in", [entry.name for entry in entries])}, + ) + + frappe.throw( + _( + "Cannot cancel Stock Reservation Entry {0}, as it has used in the work order {1}. Please cancel the work order first or unreserved the stock" + ).format( + ", ".join([frappe.bold(entry.name) for entry in entries]), + ", ".join([frappe.bold(wo.name) for wo in work_orders]), + ) + ) + def update_unreserved_qty_in_sre(self): if self.voucher_type == "Delivery Note": return