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 <noreply@anthropic.com>
This commit is contained in:
metatroncubeswdev 2026-08-17 22:22:23 -04:00
parent 4449582d76
commit f6886c1b20

View File

@ -1,9 +1,10 @@
from odoo import fields, models from odoo import api, fields, models
DEFAULT_PRIMARY_COLOR = '#2C3E50' DEFAULT_PRIMARY_COLOR = '#2C3E50'
DEFAULT_SECONDARY_COLOR = '#7F8C8D' DEFAULT_SECONDARY_COLOR = '#7F8C8D'
DEFAULT_ACCENT_COLOR = '#3498DB' DEFAULT_ACCENT_COLOR = '#3498DB'
DEFAULT_FONT = 'Inter, sans-serif' DEFAULT_FONT = 'Inter, sans-serif'
LOGO_PARAM = 'community_theme_base.logo'
class ResConfigSettings(models.TransientModel): class ResConfigSettings(models.TransientModel):
@ -21,8 +22,12 @@ class ResConfigSettings(models.TransientModel):
string='Accent Colour', config_parameter='community_theme_base.accent_color', string='Accent Colour', config_parameter='community_theme_base.accent_color',
default=DEFAULT_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( 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. " help="Shown in the website navbar and on generated PDF reports/cards. "
"Falls back to the company logo if not set.", "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', string='Body Font', config_parameter='community_theme_base.body_font',
default=DEFAULT_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 '')