From 116ef44ddbe7930195d7cf038f4160451027ef43 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Tue, 23 Jun 2026 20:25:44 +0530 Subject: [PATCH] fix(stock): make get_item_price NULL ordering match across engines (Postgres) (#56380) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit get_item_price orders Item Price rows by valid_from DESC and takes LIMIT 1 to pick the most-recent applicable price. NULL-valid_from rows are kept (the transaction-date guard uses IfNull(valid_from, '2000-01-01')), and MariaDB sorts NULL last for DESC while PostgreSQL defaults to NULLS FIRST — so when an item/price_list/uom has both a dated price and a NULL-valid_from price, PostgreSQL returns the NULL one and MariaDB the most-recent dated one, a silent price divergence. Wrap the sort key in IfNull(valid_from, '1900-01-01') so the NULL row sorts last on both engines. MariaDB already placed it last for DESC, so its pick is unchanged. Same NULL-ordering class fixed in point_of_sale.get_items (#56378). --- erpnext/stock/get_item_details.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index b11868347ea..d774ba83c2e 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -1234,7 +1234,10 @@ def get_item_price( & (ip.price_list == pctx.price_list) & (IfNull(ip.uom, "").isin(["", pctx.uom])) ) - .orderby(ip.valid_from, order=frappe.qb.desc) + # IfNull so a NULL valid_from sorts last under DESC on both engines: MariaDB sorts NULL last + # for DESC, but Postgres defaults to NULLS FIRST, which would otherwise make a NULL-valid_from + # price win the LIMIT 1 over the most-recent dated price. + .orderby(IfNull(ip.valid_from, "1900-01-01"), order=frappe.qb.desc) .orderby(IfNull(ip.batch_no, ""), order=frappe.qb.desc) .orderby(ip.uom, order=frappe.qb.desc) .limit(1)