fix: field validation and perm checks on get_stock_reservation_entries_for_voucher (backport #57968) (#57986)

Co-authored-by: Diptanil Saha <diptanil@frappe.io>
This commit is contained in:
mergify[bot]
2026-08-10 22:04:42 +05:30
committed by GitHub
parent 713af31eda
commit a0d156120b
2 changed files with 29 additions and 14 deletions

View File

@@ -882,7 +882,7 @@ def get_ssb_bundle_for_voucher(sre: dict) -> object:
def has_reserved_stock(voucher_type: str, voucher_no: str, voucher_detail_no: str | None = None) -> bool: def has_reserved_stock(voucher_type: str, voucher_no: str, voucher_detail_no: str | None = None) -> bool:
"""Returns True if there is any Stock Reservation Entry for the given voucher.""" """Returns True if there is any Stock Reservation Entry for the given voucher."""
if get_stock_reservation_entries_for_voucher( if _get_stock_reservation_entries_for_voucher(
voucher_type, voucher_no, voucher_detail_no, fields=["name"], ignore_status=True voucher_type, voucher_no, voucher_detail_no, fields=["name"], ignore_status=True
): ):
return True return True
@@ -1113,7 +1113,7 @@ def cancel_stock_reservation_entries(
sre_list = {} sre_list = {}
if voucher_type and voucher_no: if voucher_type and voucher_no:
sre_list = get_stock_reservation_entries_for_voucher( sre_list = _get_stock_reservation_entries_for_voucher(
voucher_type, voucher_no, voucher_detail_no, fields=["name"] voucher_type, voucher_no, voucher_detail_no, fields=["name"]
) )
elif from_voucher_type and from_voucher_no: elif from_voucher_type and from_voucher_no:
@@ -1156,6 +1156,24 @@ def get_stock_reservation_entries_for_voucher(
) -> list[dict]: ) -> list[dict]:
"""Returns list of Stock Reservation Entries against a Voucher.""" """Returns list of Stock Reservation Entries against a Voucher."""
return _get_stock_reservation_entries_for_voucher(
voucher_type, voucher_no, voucher_detail_no, fields, ignore_status, ignore_permissions=False
)
def _get_stock_reservation_entries_for_voucher(
voucher_type: str,
voucher_no: str,
voucher_detail_no: str | None = None,
fields: list[str] | None = None,
ignore_status: bool = False,
ignore_permissions: bool = True,
) -> list[dict]:
"""Returns list of Stock Reservation Entries against a Voucher."""
if not ignore_permissions:
frappe.has_permission(voucher_type, doc=voucher_no, throw=True)
if not fields or not isinstance(fields, list): if not fields or not isinstance(fields, list):
fields = [ fields = [
"name", "name",
@@ -1169,14 +1187,11 @@ def get_stock_reservation_entries_for_voucher(
sre = frappe.qb.DocType("Stock Reservation Entry") sre = frappe.qb.DocType("Stock Reservation Entry")
query = ( query = (
frappe.qb.from_(sre) frappe.get_query(sre, fields=fields)
.where((sre.docstatus == 1) & (sre.voucher_type == voucher_type) & (sre.voucher_no == voucher_no)) .where((sre.docstatus == 1) & (sre.voucher_type == voucher_type) & (sre.voucher_no == voucher_no))
.orderby(sre.creation) .orderby(sre.creation)
) )
for field in fields:
query = query.select(sre[field])
if voucher_detail_no: if voucher_detail_no:
query = query.where(sre.voucher_detail_no == voucher_detail_no) query = query.where(sre.voucher_detail_no == voucher_detail_no)

View File

@@ -13,9 +13,9 @@ from erpnext.stock.doctype.item.test_item import make_item
from erpnext.stock.doctype.stock_entry.stock_entry import StockEntry from erpnext.stock.doctype.stock_entry.stock_entry import StockEntry
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import ( from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import (
_get_stock_reservation_entries_for_voucher,
cancel_stock_reservation_entries, cancel_stock_reservation_entries,
get_sre_reserved_qty_details_for_voucher, get_sre_reserved_qty_details_for_voucher,
get_stock_reservation_entries_for_voucher,
has_reserved_stock, has_reserved_stock,
) )
from erpnext.stock.utils import get_stock_balance from erpnext.stock.utils import get_stock_balance
@@ -278,7 +278,7 @@ class TestStockReservationEntry(FrappeTestCase):
self.assertTrue(has_reserved_stock("Sales Order", so.name)) self.assertTrue(has_reserved_stock("Sales Order", so.name))
for item in so.items: for item in so.items:
sre_details = get_stock_reservation_entries_for_voucher( sre_details = _get_stock_reservation_entries_for_voucher(
"Sales Order", so.name, item.name, fields=["reserved_qty", "status"] "Sales Order", so.name, item.name, fields=["reserved_qty", "status"]
)[0] )[0]
self.assertEqual(item.stock_reserved_qty, sre_details.reserved_qty) self.assertEqual(item.stock_reserved_qty, sre_details.reserved_qty)
@@ -335,7 +335,7 @@ class TestStockReservationEntry(FrappeTestCase):
dn1.submit() dn1.submit()
for item in so.items: for item in so.items:
sre_details = get_stock_reservation_entries_for_voucher( sre_details = _get_stock_reservation_entries_for_voucher(
"Sales Order", so.name, item.name, fields=["delivered_qty", "status"] "Sales Order", so.name, item.name, fields=["delivered_qty", "status"]
)[0] )[0]
self.assertGreater(sre_details.delivered_qty, 0) self.assertGreater(sre_details.delivered_qty, 0)
@@ -352,7 +352,7 @@ class TestStockReservationEntry(FrappeTestCase):
dn2.submit() dn2.submit()
for item in so.items: for item in so.items:
sre_details = get_stock_reservation_entries_for_voucher( sre_details = _get_stock_reservation_entries_for_voucher(
"Sales Order", "Sales Order",
so.name, so.name,
item.name, item.name,
@@ -396,7 +396,7 @@ class TestStockReservationEntry(FrappeTestCase):
so.load_from_db() so.load_from_db()
for item in so.items: for item in so.items:
sre_details = get_stock_reservation_entries_for_voucher( sre_details = _get_stock_reservation_entries_for_voucher(
"Sales Order", so.name, item.name, fields=["status", "reserved_qty"] "Sales Order", so.name, item.name, fields=["status", "reserved_qty"]
)[0] )[0]
@@ -411,7 +411,7 @@ class TestStockReservationEntry(FrappeTestCase):
dn.submit() dn.submit()
for item in so.items: for item in so.items:
sre_details = get_stock_reservation_entries_for_voucher( sre_details = _get_stock_reservation_entries_for_voucher(
"Sales Order", so.name, item.name, fields=["status", "delivered_qty", "reserved_qty"] "Sales Order", so.name, item.name, fields=["status", "delivered_qty", "reserved_qty"]
)[0] )[0]
@@ -459,7 +459,7 @@ class TestStockReservationEntry(FrappeTestCase):
so.load_from_db() so.load_from_db()
for item in so.items: for item in so.items:
sre_details = get_stock_reservation_entries_for_voucher( sre_details = _get_stock_reservation_entries_for_voucher(
"Sales Order", "Sales Order",
so.name, so.name,
item.name, item.name,
@@ -520,7 +520,7 @@ class TestStockReservationEntry(FrappeTestCase):
so.load_from_db() so.load_from_db()
for item in so.items: for item in so.items:
sre_details = get_stock_reservation_entries_for_voucher( sre_details = _get_stock_reservation_entries_for_voucher(
"Sales Order", so.name, item.name, fields=["reserved_qty"] "Sales Order", so.name, item.name, fields=["reserved_qty"]
)[0] )[0]