From 49e3830e7ffe293aaed1b4ec73313b9aff000293 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Tue, 23 Jun 2026 23:07:54 +0530 Subject: [PATCH 1/3] Revert "fix(selling): make POS item-price NULL ordering match across engines (Postgres)" This reverts commit 20e6a6e149362b579ae4b9f76d588d4b7fd3f61e. --- erpnext/selling/page/point_of_sale/point_of_sale.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py index fff8c5ab6a3..83e7bac3fef 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.py +++ b/erpnext/selling/page/point_of_sale/point_of_sale.py @@ -6,7 +6,6 @@ import json import frappe from frappe.query_builder import Criterion, DocType, Order -from frappe.query_builder.functions import Coalesce from frappe.utils import cint, get_datetime from frappe.utils.nestedset import get_root_of @@ -232,10 +231,7 @@ def get_items( .where(ItemPrice.selling == 1) .where((ItemPrice.valid_from <= current_date) | (ItemPrice.valid_from.isnull())) .where((ItemPrice.valid_upto >= current_date) | (ItemPrice.valid_upto.isnull())) - # Coalesce so a NULL valid_from (open-ended base price) sorts last under DESC on both - # engines: MariaDB already sorts NULL last for DESC, Postgres defaults to NULLS FIRST, which - # would otherwise make the base price win the positional pick over a dated override. - .orderby(Coalesce(ItemPrice.valid_from, "1900-01-01"), order=Order.desc) + .orderby(ItemPrice.valid_from, order=Order.desc) ).run(as_dict=True) stock_uom_price = next((d for d in item_prices if d.get("uom") == item.stock_uom), {}) From c989e424f01686c91b59eb34a6ba44d96d3c5293 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Tue, 23 Jun 2026 23:07:54 +0530 Subject: [PATCH 2/3] Revert "fix(stock): guard traceability qty division against a zero divisor (Postgres)" This reverts commit 3859919263bc3ca23a40b5f2e4af0ea568c44e3b. --- .../serial_no_and_batch_traceability.py | 10 +++------- 1 file changed, 3 insertions(+), 7 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 69c34f25cd9..493313ed9e6 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,7 +4,6 @@ import frappe from frappe import _ from frappe.query_builder import Case -from frappe.query_builder.functions import NullIf def execute(filters: dict | None = None): @@ -301,12 +300,9 @@ class ReportData: ( ( stock_entry_detail.qty - / NullIf( - Case() - .when(stock_entry.fg_completed_qty > 0, stock_entry.fg_completed_qty) - .else_(sabb_data.qty), - 0, - ) + / Case() + .when(stock_entry.fg_completed_qty > 0, stock_entry.fg_completed_qty) + .else_(sabb_data.qty) ) * sabb_data.qty ).as_("qty"), From 1f86b57f942089067539fae67a5c4ac3062f9512 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Tue, 23 Jun 2026 23:07:54 +0530 Subject: [PATCH 3/3] Revert "fix(manufacturing): case-sensitive variant BOM lookup on Postgres" This reverts commit 2e5310f8a01a424fe8e42755726dbe9e2354c295. --- erpnext/manufacturing/doctype/bom/bom.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 061fbbf43e7..42a3c7c2737 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -1403,18 +1403,16 @@ def validate_bom_no(item, bom_no): def _bom_contains_item(bom, item): - item_lower = item.lower() + item = item.lower() for d in bom.items: - if d.item_code.lower() == item_lower: + if d.item_code.lower() == item: return True for d in bom.secondary_items: - if d.item_code.lower() == item_lower: + if d.item_code.lower() == item: return True - # Use the original-cased `item` for the Item lookup: names are case-sensitive on Postgres, - # so a lowercased name would miss the record and drop the variant->template BOM match. return ( - bom.item.lower() == item_lower + bom.item.lower() == item or bom.item.lower() == cstr(frappe.db.get_value("Item", item, "variant_of")).lower() )