From d48396cb117c999511755178709782ab7bdc2e64 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Tue, 23 Jun 2026 17:49:27 +0530 Subject: [PATCH] fix(selling): guard lost-value ratio against a zero total (Postgres) The Lost Quotations report's lost-value ratio divides Sum(base_net_total) by total_value, a scalar Sum(base_net_total) subquery over the same lost quotations. If every lost quotation in the period is zero-amount, total_value is 0 while the grouped query still returns rows. MariaDB returns NULL for x/0; PostgreSQL raises `division by zero` and aborts the report. Wrapping the divisor in NullIf(total_value, 0) yields the same NULL column on MariaDB and no error on PostgreSQL. (The sibling count ratio divides by Count >= 1 in any returned row and is unaffected.) --- erpnext/selling/report/lost_quotations/lost_quotations.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/selling/report/lost_quotations/lost_quotations.py b/erpnext/selling/report/lost_quotations/lost_quotations.py index c3bcd54cfd3..799dbec5878 100644 --- a/erpnext/selling/report/lost_quotations/lost_quotations.py +++ b/erpnext/selling/report/lost_quotations/lost_quotations.py @@ -6,7 +6,7 @@ from typing import Literal import frappe from frappe import _ from frappe.model.docstatus import DocStatus -from frappe.query_builder.functions import Coalesce, Count, Round, Sum +from frappe.query_builder.functions import Coalesce, Count, NullIf, Round, Sum from frappe.utils.data import get_timespan_date_range @@ -86,7 +86,7 @@ def get_data(company: str, from_date: str, to_date: str, group_by: Literal["Lost # `* 100.0` before dividing: count/count is integer division on Postgres (truncates to 0) Round((Count(q.name).distinct() * 100.0 / total_quotations), 2), Sum(q.base_net_total), - Round((Sum(q.base_net_total) / total_value * 100), 2), + Round((Sum(q.base_net_total) / NullIf(total_value, 0) * 100), 2), ) .left_join(dimension) .on(dimension.parent == q.name)