From 8960e3ff4a9f54a3d3c877c737f0d2a8dad83bb5 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Tue, 23 Jun 2026 19:38:27 +0530 Subject: [PATCH] fix(accounts): cast non-text Account fields for LIKE filters (Postgres) Financial Report Template calculation_formula filters are user-authored and only validated for field existence + operator membership, not that a like/ilike operator targets a text field. A filter such as ["is_group", "like", "1"] builds `is_group ILIKE '%1%'`; PostgreSQL has no LIKE/ILIKE operator for a smallint/int/numeric column (`operator does not exist: smallint ~~* unknown`) and aborts the report, while MariaDB implicitly casts the numeric column to text and matches. For like-family operators, cast a numeric/Check Account field to varchar (`Cast_(field, "varchar")`), reproducing MariaDB's implicit numeric->text coercion on both engines. Text-field filters (the normal account_name/ account_number case) are left untouched, so MariaDB output is unchanged. --- .../financial_report_engine.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py b/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py index 47c7e2e6366..6d44796fb1c 100644 --- a/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py +++ b/erpnext/accounts/doctype/financial_report_template/financial_report_engine.py @@ -12,8 +12,9 @@ from typing import Any, Union import frappe from frappe import _ from frappe.database.operator_map import OPERATOR_MAP +from frappe.model import numeric_fieldtypes from frappe.query_builder import Case -from frappe.query_builder.functions import Sum +from frappe.query_builder.functions import Cast_, Sum from frappe.utils import cstr, date_diff, flt, getdate from frappe.utils.xlsxutils import XLSXMetadata, XLSXStyleBuilder from pypika.terms import Bracket, LiteralValue @@ -864,8 +865,15 @@ class FilterExpressionParser: field = getattr(table, field_name, None) operator_fn = OPERATOR_MAP.get(operator.casefold()) - if "like" in operator.casefold() and "%" not in value: - value = f"%{value}%" + if "like" in operator.casefold(): + if "%" not in value: + value = f"%{value}%" + # Postgres has no LIKE/ILIKE operator for non-text columns; MariaDB implicitly casts + # the numeric column to text. Cast a numeric/Check Account field to varchar so the + # match runs on both engines and reproduces MariaDB's result. + meta_field = frappe.get_meta("Account").get_field(field_name) + if meta_field and meta_field.fieldtype in numeric_fieldtypes: + field = Cast_(field, "varchar") return operator_fn(field, value)