From f6886c1b200499b65305c5327ddad023289a2c36 Mon Sep 17 00:00:00 2001 From: metatroncubeswdev Date: Mon, 17 Aug 2026 22:22:23 -0400 Subject: [PATCH] fix(community_theme_base): Binary fields can't use config_parameter= directly Odoo's res.config.settings framework only supports auto-persisting fields of type boolean/integer/float/char/selection/many2one/datetime via config_parameter=. theme_logo (Binary) doesn't qualify, and because it was injected into the *shared* res.config.settings form, it broke every Settings tab across the whole install (including unrelated ones like Website/eLearning) - any settings load triggered default_get, which scans all fields on the model and raised. Caught via live testing in the browser, not by the automated suite, since the failure only surfaces on create()/default_get() of a resx.config.settings record, which the existing tests didn't exercise for other apps' tabs. Fixed by removing config_parameter from the field and persisting it manually through get_values()/set_values() overrides, base64-encoded into the same ir.config_parameter key the QWeb template already reads from - so the storage format is unchanged, just how it gets there. Audited every other config_parameter= field across all modules (grep) to confirm none of the others have the same problem - all are Char/Integer/ Boolean, which are on the whitelist. Verified against the live container: settings load and save cleanly for every module's tab, the logo round-trips through upload -> config parameter -> template read, and a full test run across all 9 modules (56 tests) plus a sweep of every custom button (call_button, matching the exact browser click path) and every public/portal page passes clean. Co-Authored-By: Claude Sonnet 5 --- .../models/res_config_settings.py | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/addons/community_theme_base/models/res_config_settings.py b/addons/community_theme_base/models/res_config_settings.py index 02f77b5..fe2a484 100644 --- a/addons/community_theme_base/models/res_config_settings.py +++ b/addons/community_theme_base/models/res_config_settings.py @@ -1,9 +1,10 @@ -from odoo import fields, models +from odoo import api, fields, models DEFAULT_PRIMARY_COLOR = '#2C3E50' DEFAULT_SECONDARY_COLOR = '#7F8C8D' DEFAULT_ACCENT_COLOR = '#3498DB' DEFAULT_FONT = 'Inter, sans-serif' +LOGO_PARAM = 'community_theme_base.logo' class ResConfigSettings(models.TransientModel): @@ -21,8 +22,12 @@ class ResConfigSettings(models.TransientModel): string='Accent Colour', config_parameter='community_theme_base.accent_color', default=DEFAULT_ACCENT_COLOR, ) + # Binary fields cannot use config_parameter= directly (Odoo's settings + # framework only supports boolean/integer/float/char/selection/many2one/ + # datetime that way), so this one is persisted manually via get_values/ + # set_values, base64-encoded into an ir.config_parameter like the others. theme_logo = fields.Binary( - string='Logo', config_parameter='community_theme_base.logo', + string='Logo', help="Shown in the website navbar and on generated PDF reports/cards. " "Falls back to the company logo if not set.", ) @@ -34,3 +39,16 @@ class ResConfigSettings(models.TransientModel): string='Body Font', config_parameter='community_theme_base.body_font', default=DEFAULT_FONT, ) + + @api.model + def get_values(self): + res = super().get_values() + res['theme_logo'] = self.env['ir.config_parameter'].sudo().get_param(LOGO_PARAM) or False + return res + + def set_values(self): + super().set_values() + value = self.theme_logo + if isinstance(value, bytes): + value = value.decode() + self.env['ir.config_parameter'].sudo().set_param(LOGO_PARAM, value or '')