"""Followup-specific migration step. Backfills fusion.followup.level from Enterprise's account_followup.followup.line records (if Enterprise account_followup is installed).""" import logging from odoo import api, fields, models _logger = logging.getLogger(__name__) class FusionMigrationWizard(models.TransientModel): _inherit = "fusion.migration.wizard" def _followup_bootstrap_step(self): """Backfill fusion.followup.level from account_followup.followup.line.""" result = { 'step': 'followup_bootstrap', 'enterprise_module_present': False, 'created': 0, 'skipped': 0, 'errors': [], } # Enterprise's followup model — name varies by version EnterpriseLine = self.env.get('account_followup.followup.line') if EnterpriseLine is None: EnterpriseLine = self.env.get('account.followup.line') if EnterpriseLine is None: result['enterprise_module_present'] = False return result result['enterprise_module_present'] = True FusionLevel = self.env['fusion.followup.level'].sudo() try: ee_records = EnterpriseLine.sudo().search([]) except Exception as e: result['errors'].append(f"Enterprise search failed: {e}") return result # Map Enterprise tone-ish fields to ours for ee in ee_records: try: # Idempotency: skip if a level with same sequence + name already exists seq = getattr(ee, 'sequence', None) or 50 name = getattr(ee, 'name', None) or f"Migrated Level {seq}" existing = FusionLevel.search([ ('sequence', '=', seq), ('name', '=', name), ], limit=1) if existing: result['skipped'] += 1 continue delay = getattr(ee, 'delay', None) or getattr(ee, 'delay_days', 7) # Enterprise tone heuristic: scale by sequence tone = 'gentle' if seq <= 1 else 'firm' if seq <= 2 else 'legal' FusionLevel.create({ 'name': name, 'sequence': seq + 100, # offset so we don't clash with seeded defaults 'delay_days': delay, 'tone': tone, 'active': True, }) result['created'] += 1 except Exception as e: result['errors'].append(f"Line {ee.id}: {e}") _logger.info( "fusion_accounting_followup migration: %d created, %d skipped, %d errors", result['created'], result['skipped'], len(result['errors'])) return result def action_run_migration(self): result = super().action_run_migration() if hasattr(super(), 'action_run_migration') else None try: self._followup_bootstrap_step() except Exception as e: _logger.warning("followup_bootstrap_step failed: %s", e) return result