fix(manufacturing): guard average bin valuation-rate division against a zero divisor (Postgres)

_get_avg_valuation_rate_from_bins divides Sum(stock_value) by Sum(actual_qty).
The `Count(name) > 0` guard only proves a Bin row exists; Sum(actual_qty) can
still be 0 (stock depleted, or per-warehouse quantities cancelling out), and
the outer IfNull catches only NULL, not a 0 divisor.

MariaDB returns NULL for x/0 (then IfNull -> 0.0); PostgreSQL raises
`division by zero` and aborts BOM costing. Wrapping the divisor in
NullIf(Sum(actual_qty), 0) keeps the identical 0.0 result on MariaDB and
avoids the error on PostgreSQL.
This commit is contained in:
Mihir Kandoi
2026-06-23 17:49:26 +05:30
parent 297153264b
commit affd2fd95d

View File

@@ -9,7 +9,7 @@ import frappe
from frappe import _, bold
from frappe.model.document import Document
from frappe.query_builder import Field
from frappe.query_builder.functions import Count, IfNull, Max, Min, Sum
from frappe.query_builder.functions import Count, IfNull, Max, Min, NullIf, Sum
from frappe.utils import cint, cstr, flt, get_link_to_form, parse_json
from frappe.website.website_generator import WebsiteGenerator
@@ -1124,7 +1124,8 @@ def _get_avg_valuation_rate_from_bins(item_code, company, data):
.select(
Case()
.when(
Count(bin_table.name) > 0, IfNull(Sum(bin_table.stock_value) / Sum(bin_table.actual_qty), 0.0)
Count(bin_table.name) > 0,
IfNull(Sum(bin_table.stock_value) / NullIf(Sum(bin_table.actual_qty), 0), 0.0),
)
.else_(None)
.as_("valuation_rate")