fix(controllers): guard return-rate division against a zero stock qty (Postgres)

get_rate_for_return builds Abs(stock_value_difference / actual_qty) for Sales/Delivery returns and passes it to get_value with no actual_qty filter. A matched Stock Ledger Entry with actual_qty=0 (a zero-qty repost / serial-batch row) makes Postgres raise 'division by zero' while MariaDB returns NULL. Wrap the divisor in NullIf(actual_qty, 0) so both engines return NULL. MariaDB output unchanged. Sibling of the already-fixed /actual_qty sites in stock_ledger.py and incorrect_serial_no_valuation.py.
This commit is contained in:
Mihir Kandoi
2026-06-29 22:25:19 +05:30
parent c26ad9fc36
commit 8c03029f28

View File

@@ -7,7 +7,7 @@ import frappe
from frappe import _, bold
from frappe.model.meta import get_field_precision
from frappe.query_builder import DocType
from frappe.query_builder.functions import Abs, Sum
from frappe.query_builder.functions import Abs, NullIf, Sum
from frappe.utils import cint, flt, format_datetime, get_datetime
import erpnext
@@ -766,7 +766,7 @@ def get_rate_for_return(
select_field = "incoming_rate"
else:
StockLedgerEntry = frappe.qb.DocType("Stock Ledger Entry")
select_field = Abs(StockLedgerEntry.stock_value_difference / StockLedgerEntry.actual_qty)
select_field = Abs(StockLedgerEntry.stock_value_difference / NullIf(StockLedgerEntry.actual_qty, 0))
item_details = frappe.get_cached_value("Item", item_code, ["has_batch_no", "has_expiry_date"], as_dict=1)
set_zero_rate_for_expired_batch = frappe.db.get_single_value(