From 263e9184f9e2a9ab616aedf6a960f1f993f95a36 Mon Sep 17 00:00:00 2001 From: Don Kendall Date: Thu, 21 May 2026 19:46:27 -0400 Subject: [PATCH 1/3] [OU-FIX] loyalty: pre-migrate stale `_get_mail_partner` in stored mail.template.lang MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 18.0 loyalty `mail_template_gift_card` and `mail_template_loyalty_card` both store `lang` as `{{ object._get_mail_partner().lang }}`. The method was renamed to `_get_mail_author` in 19.0 — when the 19.0 module update re-renders `lang` during data load, it raises AttributeError and aborts the migration at `loyalty/data/mail_template_data.xml:3` before the existing post-migration (which nulls `lang`) ever runs. Pre-migration is the only safe place to fix this; rename in place via REPLACE so the rendering check passes and the existing post-migration (or any user customization of `lang`) keeps working. --- docsource/modules180-190.rst | 2 +- .../scripts/loyalty/19.0.1.0/pre-migration.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 openupgrade_scripts/scripts/loyalty/19.0.1.0/pre-migration.py diff --git a/docsource/modules180-190.rst b/docsource/modules180-190.rst index fd4b86e2175e..f5f098bf583a 100644 --- a/docsource/modules180-190.rst +++ b/docsource/modules180-190.rst @@ -698,7 +698,7 @@ Module coverage 18.0 -> 19.0 +---------------------------------------------------+----------------------+-------------------------------------------------+ | link_tracker |Nothing to do |No DB layout changes. | +---------------------------------------------------+----------------------+-------------------------------------------------+ -| loyalty | | | +| loyalty |Done | | +---------------------------------------------------+----------------------+-------------------------------------------------+ | lunch | | | +---------------------------------------------------+----------------------+-------------------------------------------------+ diff --git a/openupgrade_scripts/scripts/loyalty/19.0.1.0/pre-migration.py b/openupgrade_scripts/scripts/loyalty/19.0.1.0/pre-migration.py new file mode 100644 index 000000000000..3c5e6439bf18 --- /dev/null +++ b/openupgrade_scripts/scripts/loyalty/19.0.1.0/pre-migration.py @@ -0,0 +1,18 @@ +from openupgradelib import openupgrade + + +@openupgrade.migrate() +def migrate(env, version): + """Rename the removed ``_get_mail_partner`` helper to ``_get_mail_author`` + in the stored ``lang`` of these templates, as the 19.0 data-load render + aborts before the existing post-migration could clear the field. + """ + openupgrade.logged_query( + env.cr, + """ + UPDATE mail_template + SET lang = REPLACE(lang, '_get_mail_partner', '_get_mail_author') + WHERE model = 'loyalty.card' + AND lang LIKE '%%_get_mail_partner%%' + """, + ) From bd06b4f6b14718623a55055848686d47ecd60570 Mon Sep 17 00:00:00 2001 From: Don Kendall Date: Thu, 11 Jun 2026 07:53:59 -0400 Subject: [PATCH 2/3] [FIX] loyalty: rewrite _get_mail_partner to its real 18.0 equivalent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The helper returned partner_id (the recipient); mapping it to _get_mail_author swapped the company/internal user into custom templates' lang (customer emails switch to company language) — and only core templates get reset by the module update. Rewrite to object.partner_id across the stored template columns that can carry the call. --- .../scripts/loyalty/19.0.1.0/pre-migration.py | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/openupgrade_scripts/scripts/loyalty/19.0.1.0/pre-migration.py b/openupgrade_scripts/scripts/loyalty/19.0.1.0/pre-migration.py index 3c5e6439bf18..90896ffaf2da 100644 --- a/openupgrade_scripts/scripts/loyalty/19.0.1.0/pre-migration.py +++ b/openupgrade_scripts/scripts/loyalty/19.0.1.0/pre-migration.py @@ -3,16 +3,26 @@ @openupgrade.migrate() def migrate(env, version): - """Rename the removed ``_get_mail_partner`` helper to ``_get_mail_author`` - in the stored ``lang`` of these templates, as the 19.0 data-load render - aborts before the existing post-migration could clear the field. + """Rewrite the removed ``_get_mail_partner`` helper (which returned + ``partner_id``, the recipient) to its exact 18.0 equivalent in stored + template fields, as the 19.0 data-load render aborts before the existing + post-migration could clear the field. ``_get_mail_author`` would swap in + the company/internal user instead — wrong partner for custom templates + that are never reset by the module update. """ - openupgrade.logged_query( - env.cr, - """ - UPDATE mail_template - SET lang = REPLACE(lang, '_get_mail_partner', '_get_mail_author') - WHERE model = 'loyalty.card' - AND lang LIKE '%%_get_mail_partner%%' - """, - ) + for column in ("lang", "partner_to", "email_to", "body_html"): + if not openupgrade.column_exists(env.cr, "mail_template", column): + continue + openupgrade.logged_query( + env.cr, + f""" + UPDATE mail_template + SET {column} = REPLACE( + {column}::text, + 'object._get_mail_partner()', + 'object.partner_id' + ) + WHERE model = 'loyalty.card' + AND {column}::text LIKE '%%_get_mail_partner%%' + """, + ) From e1c237287300a99e6ccce99155f2f958b6f64a43 Mon Sep 17 00:00:00 2001 From: Don Kendall Date: Thu, 11 Jun 2026 07:54:42 -0400 Subject: [PATCH 3/3] [FIX] loyalty: cast the body_html rewrite back to jsonb --- .../scripts/loyalty/19.0.1.0/pre-migration.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/openupgrade_scripts/scripts/loyalty/19.0.1.0/pre-migration.py b/openupgrade_scripts/scripts/loyalty/19.0.1.0/pre-migration.py index 90896ffaf2da..b29087957954 100644 --- a/openupgrade_scripts/scripts/loyalty/19.0.1.0/pre-migration.py +++ b/openupgrade_scripts/scripts/loyalty/19.0.1.0/pre-migration.py @@ -13,6 +13,15 @@ def migrate(env, version): for column in ("lang", "partner_to", "email_to", "body_html"): if not openupgrade.column_exists(env.cr, "mail_template", column): continue + env.cr.execute( + """ + SELECT data_type FROM information_schema.columns + WHERE table_name = 'mail_template' AND column_name = %s + """, + (column,), + ) + # translated columns (body_html) are jsonb; cast the rewrite back + cast = "::jsonb" if env.cr.fetchone()[0] == "jsonb" else "" openupgrade.logged_query( env.cr, f""" @@ -21,7 +30,7 @@ def migrate(env, version): {column}::text, 'object._get_mail_partner()', 'object.partner_id' - ) + ){cast} WHERE model = 'loyalty.card' AND {column}::text LIKE '%%_get_mail_partner%%' """,