mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-11 13:41:47 +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>
54 lines
1.8 KiB
Python
54 lines
1.8 KiB
Python
import frappe
|
|
from frappe.model.naming import get_default_naming_series
|
|
|
|
|
|
class NamingSeriesNotSetError(frappe.ValidationError):
|
|
pass
|
|
|
|
|
|
def set_by_naming_series(doctype, fieldname, naming_series, hide_name_field=True, make_mandatory=1):
|
|
"""Change a doctype's naming to user naming series"""
|
|
from frappe.custom.doctype.property_setter.property_setter import make_property_setter
|
|
|
|
if naming_series:
|
|
make_property_setter(
|
|
doctype, "naming_series", "hidden", 0, "Check", validate_fields_for_doctype=False
|
|
)
|
|
make_property_setter(
|
|
doctype, "naming_series", "reqd", make_mandatory, "Check", validate_fields_for_doctype=False
|
|
)
|
|
|
|
# set values for mandatory
|
|
try:
|
|
dt = frappe.qb.DocType(doctype)
|
|
(
|
|
frappe.qb.update(dt)
|
|
.set(dt.naming_series, get_default_naming_series(doctype))
|
|
.where(dt.naming_series.isnull() | (dt.naming_series == ""))
|
|
.run()
|
|
)
|
|
except NamingSeriesNotSetError:
|
|
pass
|
|
|
|
if hide_name_field:
|
|
make_property_setter(doctype, fieldname, "reqd", 0, "Check", validate_fields_for_doctype=False)
|
|
make_property_setter(doctype, fieldname, "hidden", 1, "Check", validate_fields_for_doctype=False)
|
|
else:
|
|
make_property_setter(doctype, "naming_series", "reqd", 0, "Check", validate_fields_for_doctype=False)
|
|
make_property_setter(
|
|
doctype, "naming_series", "hidden", 1, "Check", validate_fields_for_doctype=False
|
|
)
|
|
|
|
if hide_name_field:
|
|
make_property_setter(doctype, fieldname, "hidden", 0, "Check", validate_fields_for_doctype=False)
|
|
make_property_setter(doctype, fieldname, "reqd", 1, "Check", validate_fields_for_doctype=False)
|
|
|
|
# set values for mandatory
|
|
dt = frappe.qb.DocType(doctype)
|
|
(
|
|
frappe.qb.update(dt)
|
|
.set(dt[fieldname], dt.name)
|
|
.where(dt[fieldname].isnull() | (dt[fieldname] == ""))
|
|
.run()
|
|
)
|