From 3859919263bc3ca23a40b5f2e4af0ea568c44e3b Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Tue, 23 Jun 2026 19:38:27 +0530 Subject: [PATCH] fix(stock): guard traceability qty division against a zero divisor (Postgres) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit get_materials divides stock_entry_detail.qty by a CASE that returns fg_completed_qty when it is > 0 and otherwise the injected sabb_data.qty. The code explicitly anticipates fg_completed_qty <= 0 (the else branch), and neither fg_completed_qty nor sabb_data.qty is constrained non-zero, so the divisor can be 0. MariaDB returns NULL for x/0; PostgreSQL raises `division by zero` and aborts the report. Wrapping the CASE in NullIf(..., 0) makes the divisor NULL instead of 0 — unchanged on MariaDB, valid on Postgres. --- .../serial_no_and_batch_traceability.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/report/serial_no_and_batch_traceability/serial_no_and_batch_traceability.py b/erpnext/stock/report/serial_no_and_batch_traceability/serial_no_and_batch_traceability.py index 493313ed9e6..69c34f25cd9 100644 --- a/erpnext/stock/report/serial_no_and_batch_traceability/serial_no_and_batch_traceability.py +++ b/erpnext/stock/report/serial_no_and_batch_traceability/serial_no_and_batch_traceability.py @@ -4,6 +4,7 @@ import frappe from frappe import _ from frappe.query_builder import Case +from frappe.query_builder.functions import NullIf def execute(filters: dict | None = None): @@ -300,9 +301,12 @@ class ReportData: ( ( stock_entry_detail.qty - / Case() - .when(stock_entry.fg_completed_qty > 0, stock_entry.fg_completed_qty) - .else_(sabb_data.qty) + / NullIf( + Case() + .when(stock_entry.fg_completed_qty > 0, stock_entry.fg_completed_qty) + .else_(sabb_data.qty), + 0, + ) ) * sabb_data.qty ).as_("qty"),