# -*- coding: utf-8 -*- # Copyright 2026 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) # # Defensive pre-migration: re-link orphaned fusion_clock config-parameter # external IDs. # # Booleans/floats saved through the Settings UI go in via set_param(), which # creates the ir_config_parameter row WITHOUT an ir_model_data external id. If a # param later also appears in the noupdate data/ir_config_parameter_data.xml, # a plain `-u` can't match it by external id, treats it as new, and the INSERT # trips the UNIQUE(key) constraint -> "Failed to load registry". # # This runs BEFORE the data files load: for every config record in the XML whose # param already exists but whose external id is missing, we create the external # id pointing at the existing param. The noupdate load then matches + skips it, # so the existing (possibly customised) value is preserved. import logging import os from lxml import etree from odoo.modules.module import get_module_path _logger = logging.getLogger(__name__) def migrate(cr, version): module_path = get_module_path('fusion_clock') if not module_path: return xml_path = os.path.join(module_path, 'data', 'ir_config_parameter_data.xml') if not os.path.exists(xml_path): return tree = etree.parse(xml_path) fixed = 0 for rec in tree.findall('.//record[@model="ir.config_parameter"]'): xmlid = rec.get('id') key_node = rec.find('./field[@name="key"]') if not xmlid or key_node is None or not (key_node.text or '').strip(): continue key = key_node.text.strip() cr.execute("SELECT id FROM ir_config_parameter WHERE key = %s", (key,)) param = cr.fetchone() if not param: continue # not set yet -> the noupdate load will create it cleanly cr.execute( "SELECT id FROM ir_model_data WHERE module = 'fusion_clock' AND name = %s", (xmlid,)) if cr.fetchone(): continue # already linked cr.execute(""" INSERT INTO ir_model_data (module, name, model, res_id, noupdate, create_date, write_date) VALUES ('fusion_clock', %s, 'ir.config_parameter', %s, true, now(), now()) """, (xmlid, param[0])) fixed += 1 if fixed: _logger.info( "Fusion Clock: re-linked %s orphaned config-parameter external id(s).", fixed)