Merge pull request #52544 from one-highflyer/fix/improve-reserved-serial-no-error-message

fix(stock): improve error message when serial no is reserved via SRE

(cherry picked from commit 71248ff40b)
This commit is contained in:
Imesha Sudasingha
2026-02-23 20:42:08 +05:30
committed by Mergify
parent a0c8ac524b
commit ae3453c84b

View File

@@ -299,10 +299,20 @@ class SerialandBatchBundle(Document):
for serial_no in serial_nos:
if not serial_no_warehouse.get(serial_no) or serial_no_warehouse.get(serial_no) != self.warehouse:
self.throw_error_message(
f"Serial No {bold(serial_no)} is not present in the warehouse {bold(self.warehouse)}.",
SerialNoWarehouseError,
)
reservation = get_serial_no_reservation(self.item_code, serial_no, self.warehouse)
if reservation:
self.throw_error_message(
f"Serial No {bold(serial_no)} is in warehouse {bold(self.warehouse)}"
f" but is reserved for {reservation.voucher_type} {bold(reservation.voucher_no)}"
f" via {get_link_to_form('Stock Reservation Entry', reservation.name)}."
f" Please use an unreserved serial number or cancel the reservation.",
SerialNoWarehouseError,
)
else:
self.throw_error_message(
f"Serial No {bold(serial_no)} is not present in the warehouse {bold(self.warehouse)}.",
SerialNoWarehouseError,
)
def validate_serial_nos_duplicate(self):
# Don't inward same serial number multiple times
@@ -2585,6 +2595,32 @@ def get_reserved_serial_nos_for_sre(kwargs) -> list:
return query.run(as_dict=True)
def get_serial_no_reservation(item_code: str, serial_no: str, warehouse: str) -> _dict | None:
"""Returns the Stock Reservation Entry that has reserved the given serial number, if any."""
sre = frappe.qb.DocType("Stock Reservation Entry")
sb_entry = frappe.qb.DocType("Serial and Batch Entry")
result = (
frappe.qb.from_(sre)
.inner_join(sb_entry)
.on(sre.name == sb_entry.parent)
.select(sre.name, sre.voucher_type, sre.voucher_no)
.where(
(sre.docstatus == 1)
& (sre.item_code == item_code)
& (sre.warehouse == warehouse)
& (sre.status.notin(["Delivered", "Cancelled", "Closed"]))
& (sre.reservation_based_on == "Serial and Batch")
& (sb_entry.serial_no == serial_no)
& (sb_entry.qty != sb_entry.delivered_qty)
)
.limit(1)
.run(as_dict=True)
)
return result[0] if result else None
def get_reserved_batches_for_pos(kwargs) -> dict:
"""Returns a dict of `Batch No` followed by the `Qty` reserved in POS Invoices."""