mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-19 09:28:46 +00:00
Convert raw `frappe.db.sql` in the Setup, Utilities, Templates and Regional areas to `frappe.qb` / the ORM so the same code runs on MariaDB and Postgres. Behaviour is preserved on MariaDB; the conversions also make these paths valid under Postgres' stricter SQL (GROUP BY, case-sensitivity, reserved words). Conversions of note (behaviour kept identical to the MariaDB original): - email_digest: ToDo ordering replicated with a CASE that mirrors MySQL `field(priority,'High','Medium','Low')` (unknown/NULL -> 0, sorts first), NULL-date-first and a `name` tie-break for a deterministic LIMIT. - company.get_all_transactions_annual_history: the cross-DocType UNION + GROUP BY is replaced by one grouped query per DocType merged with a Counter, so two different DocTypes sharing a transaction_date still collapse into one bucket. - templates/utils.send_message: contact lookup wraps both sides in LOWER() to keep MariaDB's case-insensitive email match on case-sensitive Postgres. - regional/irs_1099 & uae_vat_201: address ranking and emirate aggregation rebuilt with CASE/aggregate selects that satisfy Postgres GROUP BY, with a deterministic tie-break on the LIMIT-1 address lookups. - utilities/product.get_item_codes_by_attributes: numeric attribute values are cast with cstr() so Postgres doesn't reject `varchar = numeric`. Tests (run on both MariaDB and Postgres, --lightmode): - New: company merge test, authorization_rule duplicate-check, youtube report, templates/utils, and utilities/templates page reports (partners, rfq, material_request_info, product, utilities __init__). - Existing suites kept green: company, email_digest, transaction_deletion_record, irs_1099, uae_vat_201. Deferred (tracked separately): - setup/doctype/authorization_control.py still has raw `.format()` SELECTs; left for its own PR. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
42 lines
1.7 KiB
Python
42 lines
1.7 KiB
Python
# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and Contributors
|
|
# License: GNU General Public License v3. See license.txt
|
|
|
|
import frappe
|
|
|
|
from erpnext.templates.utils import get_customer_from_contact_email
|
|
from erpnext.tests.utils import ERPNextTestSuite
|
|
|
|
|
|
class TestTemplateUtils(ERPNextTestSuite):
|
|
def test_contact_email_lookup_is_case_insensitive(self):
|
|
"""send_message resolves the Opportunity party by matching Contact.email_id with `==`.
|
|
Equality is case-SENSITIVE on Postgres (the query-builder ILIKE patch only rewrites LIKE),
|
|
while MariaDB's default collation is case-insensitive. A Contact email stored as
|
|
'Case.Test@Example.com' with a lowercase sender therefore matches on MariaDB but not on
|
|
Postgres -- so the Contact-Us form links a Lead instead of the Customer. The original raw SQL
|
|
used the same `c.email_id = %s`, so MariaDB output is unchanged: this is a Postgres-only break."""
|
|
customer_name = "_Test Contact Case Customer"
|
|
if not frappe.db.exists("Customer", customer_name):
|
|
frappe.get_doc(
|
|
{
|
|
"doctype": "Customer",
|
|
"customer_name": customer_name,
|
|
"customer_group": "_Test Customer Group",
|
|
"territory": "_Test Territory",
|
|
}
|
|
).insert(ignore_permissions=True)
|
|
|
|
frappe.get_doc(
|
|
{
|
|
"doctype": "Contact",
|
|
"first_name": "Case Test Contact",
|
|
"email_ids": [{"email_id": "Case.Test@Example.com", "is_primary": 1}],
|
|
"links": [{"link_doctype": "Customer", "link_name": customer_name}],
|
|
}
|
|
).insert(ignore_permissions=True)
|
|
|
|
# lowercase sender vs the stored mixed-case Contact email
|
|
matched = get_customer_from_contact_email("case.test@example.com")
|
|
self.assertTrue(matched, "Contact email lookup found no Customer for a case-differing sender")
|
|
self.assertEqual(matched[0][0], customer_name)
|