# -*- coding: utf-8 -*- # Copyright 2026 Nexa Systems Inc. # License OPL-1 """Migrate the single Default CoC Contact (Many2one) to the multi-contact Many2many. The field x_fc_default_coc_contact_id (Many2one column on res_partner) was renamed to x_fc_default_coc_contact_ids (self-referential Many2many, rel table fp_default_coc_contact_rel). Odoo creates the new rel table during the schema-update phase but leaves the old column orphaned. Copy each partner's single contact into the new M2m so existing per-customer CoC routing carries over, then drop the dead column. Idempotent + guarded on column existence. """ import logging _logger = logging.getLogger(__name__) def migrate(cr, version): # Old column still present (Odoo doesn't drop removed-field columns)? cr.execute(""" SELECT 1 FROM information_schema.columns WHERE table_name = 'res_partner' AND column_name = 'x_fc_default_coc_contact_id' """) if not cr.fetchone(): return # New M2m rel table created by the schema update before this runs. cr.execute(""" SELECT 1 FROM information_schema.tables WHERE table_name = 'fp_default_coc_contact_rel' """) if not cr.fetchone(): _logger.warning( 'fp_default_coc_contact_rel missing — skipping CoC contact ' 'migration (rel table not created yet).') return # Copy the single value into the M2m (skip rows already present so a # re-run is harmless). cr.execute(""" INSERT INTO fp_default_coc_contact_rel (partner_id, contact_id) SELECT p.id, p.x_fc_default_coc_contact_id FROM res_partner p WHERE p.x_fc_default_coc_contact_id IS NOT NULL AND NOT EXISTS ( SELECT 1 FROM fp_default_coc_contact_rel r WHERE r.partner_id = p.id AND r.contact_id = p.x_fc_default_coc_contact_id) """) moved = cr.rowcount cr.execute( "ALTER TABLE res_partner DROP COLUMN IF EXISTS " "x_fc_default_coc_contact_id") _logger.info( 'CoC contact migration: copied %s single Default-CoC-Contact value(s) ' 'into the new x_fc_default_coc_contact_ids M2m, dropped old column.', moved)