Skip to content

Commit

Permalink
fix: Reserved Stock report (backport #38922) (#38924)
Browse files Browse the repository at this point in the history
* chore: improve `Allowed Qty` error msg

(cherry picked from commit 1a16291)

* fix: `Reserved Stock` report

(cherry picked from commit a5d5223)

---------

Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com>
  • Loading branch information
mergify[bot] and s-aga-r authored Dec 22, 2023
1 parent 8c2c90f commit 8f643f0
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from frappe.query_builder.functions import Sum
from frappe.utils import cint, flt

from erpnext.stock.utils import get_or_make_bin
from erpnext.stock.utils import get_or_make_bin, get_stock_balance


class StockReservationEntry(Document):
Expand Down Expand Up @@ -151,7 +151,7 @@ def validate_reservation_based_on_qty(self) -> None:
"""Validates `Reserved Qty` when `Reservation Based On` is `Qty`."""

if self.reservation_based_on == "Qty":
self.validate_with_max_reserved_qty(self.reserved_qty)
self.validate_with_allowed_qty(self.reserved_qty)

def auto_reserve_serial_and_batch(self, based_on: str = None) -> None:
"""Auto pick Serial and Batch Nos to reserve when `Reservation Based On` is `Serial and Batch`."""
Expand Down Expand Up @@ -324,7 +324,7 @@ def validate_reservation_based_on_serial_and_batch(self) -> None:
frappe.throw(msg)

# Should be called after validating Serial and Batch Nos.
self.validate_with_max_reserved_qty(qty_to_be_reserved)
self.validate_with_allowed_qty(qty_to_be_reserved)
self.db_set("reserved_qty", qty_to_be_reserved)

def update_reserved_qty_in_voucher(
Expand Down Expand Up @@ -429,7 +429,7 @@ def can_be_updated(self) -> None:
msg = _("Stock Reservation Entry cannot be updated as it has been delivered.")
frappe.throw(msg)

def validate_with_max_reserved_qty(self, qty_to_be_reserved: float) -> None:
def validate_with_allowed_qty(self, qty_to_be_reserved: float) -> None:
"""Validates `Reserved Qty` with `Max Reserved Qty`."""

self.db_set(
Expand All @@ -448,12 +448,12 @@ def validate_with_max_reserved_qty(self, qty_to_be_reserved: float) -> None:
)
voucher_delivered_qty = flt(delivered_qty) * flt(conversion_factor)

max_reserved_qty = min(
allowed_qty = min(
self.available_qty, (self.voucher_qty - voucher_delivered_qty - total_reserved_qty)
)

if max_reserved_qty <= 0 and self.voucher_type == "Sales Order":
msg = _("Item {0} is already delivered for Sales Order {1}.").format(
if self.get("_action") != "submit" and self.voucher_type == "Sales Order" and allowed_qty <= 0:
msg = _("Item {0} is already reserved/delivered against Sales Order {1}.").format(
frappe.bold(self.item_code), frappe.bold(self.voucher_no)
)

Expand All @@ -463,19 +463,33 @@ def validate_with_max_reserved_qty(self, qty_to_be_reserved: float) -> None:
else:
frappe.throw(msg)

if qty_to_be_reserved > max_reserved_qty:
if qty_to_be_reserved > allowed_qty:
actual_qty = get_stock_balance(self.item_code, self.warehouse)
msg = """
Cannot reserve more than Max Reserved Qty {0} {1}.<br /><br />
The <b>Max Reserved Qty</b> is calculated as follows:<br />
Cannot reserve more than Allowed Qty {0} {1} for Item {2} against {3} {4}.<br /><br />
The <b>Allowed Qty</b> is calculated as follows:<br />
<ul>
<li><b>Available Qty To Reserve</b> = (Actual Stock Qty - Reserved Stock Qty)</li>
<li><b>Voucher Qty</b> = Voucher Item Qty</li>
<li><b>Delivered Qty</b> = Qty delivered against the Voucher Item</li>
<li><b>Total Reserved Qty</b> = Qty reserved against the Voucher Item</li>
<li><b>Max Reserved Qty</b> = Minimum of (Available Qty To Reserve, (Voucher Qty - Delivered Qty - Total Reserved Qty))</li>
<li>Actual Qty [Available Qty at Warehouse] = {5}</li>
<li>Reserved Stock [Ignore current SRE] = {6}</li>
<li>Available Qty To Reserve [Actual Qty - Reserved Stock] = {7}</li>
<li>Voucher Qty [Voucher Item Qty] = {8}</li>
<li>Delivered Qty [Qty delivered against the Voucher Item] = {9}</li>
<li>Total Reserved Qty [Qty reserved against the Voucher Item] = {10}</li>
<li>Allowed Qty [Minimum of (Available Qty To Reserve, (Voucher Qty - Delivered Qty - Total Reserved Qty))] = {11}</li>
</ul>
""".format(
frappe.bold(max_reserved_qty), self.stock_uom
frappe.bold(allowed_qty),
self.stock_uom,
frappe.bold(self.item_code),
self.voucher_type,
frappe.bold(self.voucher_no),
actual_qty,
actual_qty - self.available_qty,
self.available_qty,
self.voucher_qty,
voucher_delivered_qty,
total_reserved_qty,
allowed_qty,
)
frappe.throw(msg)

Expand Down Expand Up @@ -509,7 +523,6 @@ def get_available_qty_to_reserve(
"""Returns `Available Qty to Reserve (Actual Qty - Reserved Qty)` for Item, Warehouse and Batch combination."""

from erpnext.stock.doctype.batch.batch import get_batch_qty
from erpnext.stock.utils import get_stock_balance

if batch_no:
return get_batch_qty(
Expand Down
48 changes: 25 additions & 23 deletions erpnext/stock/report/reserved_stock/reserved_stock.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,34 +149,36 @@ frappe.query_reports["Reserved Stock"] = {
formatter: (value, row, column, data, default_formatter) => {
value = default_formatter(value, row, column, data);

if (column.fieldname == "status") {
switch (data.status) {
case "Partially Reserved":
value = "<span style='color:orange'>" + value + "</span>";
break;
case "Reserved":
value = "<span style='color:blue'>" + value + "</span>";
break;
case "Partially Delivered":
value = "<span style='color:purple'>" + value + "</span>";
break;
case "Delivered":
value = "<span style='color:green'>" + value + "</span>";
break;
if (data) {
if (column.fieldname == "status") {
switch (data.status) {
case "Partially Reserved":
value = "<span style='color:orange'>" + value + "</span>";
break;
case "Reserved":
value = "<span style='color:blue'>" + value + "</span>";
break;
case "Partially Delivered":
value = "<span style='color:purple'>" + value + "</span>";
break;
case "Delivered":
value = "<span style='color:green'>" + value + "</span>";
break;
}
}
}
else if (column.fieldname == "delivered_qty") {
if (data.delivered_qty > 0) {
if (data.reserved_qty > data.delivered_qty) {
value = "<span style='color:blue'>" + value + "</span>";
else if (column.fieldname == "delivered_qty") {
if (data.delivered_qty > 0) {
if (data.reserved_qty > data.delivered_qty) {
value = "<span style='color:blue'>" + value + "</span>";
}
else {
value = "<span style='color:green'>" + value + "</span>";
}
}
else {
value = "<span style='color:green'>" + value + "</span>";
value = "<span style='color:red'>" + value + "</span>";
}
}
else {
value = "<span style='color:red'>" + value + "</span>";
}
}

return value;
Expand Down

0 comments on commit 8f643f0

Please sign in to comment.