"""Pre-migration: 19.0.12.0.0 → 19.0.13.0.0 Removes three models that are being retired in this version: - laundry.product.wizard (replaced by native sale.order.line product selection) - laundry.product.wizard.line (child of above) - laundry.whatsapp.wizard (replaced by one-click wa.me URL action) If these ir.model records are left in the DB while the Python classes no longer exist, Odoo will log warnings or fail on field-level checks during upgrade. We clean them here, before the ORM loads. """ import logging _logger = logging.getLogger(__name__) _REMOVED_MODELS = [ 'laundry.product.wizard', 'laundry.product.wizard.line', 'laundry.whatsapp.wizard', ] _REMOVED_TABLES = [ 'laundry_product_wizard', 'laundry_product_wizard_line', 'laundry_whatsapp_wizard', ] def migrate(cr, version): if not version: return _logger.info('pre_migrate 19.0.13.0.0: cleaning retired wizard models %s', _REMOVED_MODELS) # 1. Drop physical tables (TransientModels do have real tables in Odoo) for tbl in _REMOVED_TABLES: cr.execute(f'DROP TABLE IF EXISTS "{tbl}" CASCADE') _logger.info(' dropped table: %s', tbl) # 2. Remove ir.model.access entries for these models cr.execute(""" DELETE FROM ir_model_access WHERE model_id IN ( SELECT id FROM ir_model WHERE model = ANY(%s) ) """, (_REMOVED_MODELS,)) _logger.info(' deleted %d ir.model.access rows', cr.rowcount) # 3. Remove ir.rule entries cr.execute(""" DELETE FROM ir_rule WHERE model_id IN ( SELECT id FROM ir_model WHERE model = ANY(%s) ) """, (_REMOVED_MODELS,)) # 4. Remove ir.model.fields for these models cr.execute(""" DELETE FROM ir_model_fields WHERE model_id IN ( SELECT id FROM ir_model WHERE model = ANY(%s) ) """, (_REMOVED_MODELS,)) _logger.info(' deleted ir.model.fields rows') # 5. Remove ir.model.constraint cr.execute(""" DELETE FROM ir_model_constraint WHERE model_id IN ( SELECT id FROM ir_model WHERE model = ANY(%s) ) """, (_REMOVED_MODELS,)) # 6. Remove ir.model.relation cr.execute(""" DELETE FROM ir_model_relation WHERE model_id IN ( SELECT id FROM ir_model WHERE model = ANY(%s) ) """, (_REMOVED_MODELS,)) # 7. Remove ir.model.data (XML IDs) for these models cr.execute(""" DELETE FROM ir_model_data WHERE model = 'ir.model' AND name IN ( SELECT REPLACE(model, '.', '_') || '_' || id::text FROM ir_model WHERE model = ANY(%s) ) """, (_REMOVED_MODELS,)) # Also delete by res_id cr.execute(""" DELETE FROM ir_model_data WHERE model = 'ir.model' AND res_id IN (SELECT id FROM ir_model WHERE model = ANY(%s)) """, (_REMOVED_MODELS,)) # 8. Finally remove ir.model entries themselves cr.execute(""" DELETE FROM ir_model WHERE model = ANY(%s) """, (_REMOVED_MODELS,)) _logger.info(' deleted ir.model entries for retired wizards') _logger.info('pre_migrate 19.0.13.0.0: complete')