Просмотр исходного кода

fix(helpdesk_extras): Corregir migraciones para evitar errores en producción

- Agregar manejo robusto de errores en migración 18.0.1.0.9
- Usar SQL directo como fallback si ir.translation no está disponible
- Agregar manejo de errores en migración 18.0.1.0.10
- Prevenir que errores en migraciones bloqueen la actualización del módulo
- Actualizar versión a 18.0.1.0.11
odoo 2 месяцев назад
Родитель
Сommit
e16a59d066

+ 1 - 1
helpdesk_extras/__manifest__.py

@@ -1,6 +1,6 @@
 {
 {
     "name": "Helpdesk Extras",
     "name": "Helpdesk Extras",
-    "version": "18.0.1.0.10",
+    "version": "18.0.1.0.11",
     "category": "Services/Helpdesk",
     "category": "Services/Helpdesk",
     "summary": "Funcionalidades extras para Helpdesk - Compartir equipos y widget de horas",
     "summary": "Funcionalidades extras para Helpdesk - Compartir equipos y widget de horas",
     "description": """
     "description": """

+ 55 - 42
helpdesk_extras/migrations/18.0.1.0.10/post-migration.py

@@ -7,49 +7,62 @@ _logger = logging.getLogger(__name__)
 
 
 def migrate(cr, version):
 def migrate(cr, version):
     """Cargar traducciones de selection fields en ir.model.fields.selection"""
     """Cargar traducciones de selection fields en ir.model.fields.selection"""
-    env = api.Environment(cr, SUPERUSER_ID, {})
-    
-    # Traducciones de business_impact
-    translations = {
-        'business_impact': {
-            '0': 'Crítico',
-            '1': 'Alto',
-            '2': 'Normal',
+    try:
+        env = api.Environment(cr, SUPERUSER_ID, {})
+        
+        # Traducciones de business_impact
+        translations = {
+            'business_impact': {
+                '0': 'Crítico',
+                '1': 'Alto',
+                '2': 'Normal',
+            }
+        }
+        
+        # Traducciones de approval_status
+        translations['approval_status'] = {
+            'draft': 'N/A',
+            'waiting': 'Esperando Aprobación',
+            'approved': 'Aprobado',
+            'rejected': 'Rechazado',
         }
         }
-    }
-    
-    # Traducciones de approval_status
-    translations['approval_status'] = {
-        'draft': 'N/A',
-        'waiting': 'Esperando Aprobación',
-        'approved': 'Aprobado',
-        'rejected': 'Rechazado',
-    }
-    
-    _logger.info("Cargando traducciones de selection fields...")
-    
-    for field_name, field_translations in translations.items():
-        # Buscar el campo en ir.model.fields
-        field_record = env['ir.model.fields'].search([
-            ('model', '=', 'helpdesk.ticket'),
-            ('name', '=', field_name)
-        ], limit=1)
         
         
-        if not field_record:
-            _logger.warning(f"Campo {field_name} no encontrado en ir.model.fields")
-            continue
+        _logger.info("Cargando traducciones de selection fields...")
         
         
-        # Actualizar cada opción de selection
-        updated_count = 0
-        for sel in field_record.selection_ids:
-            if sel.value in field_translations:
-                translated_name = field_translations[sel.value]
-                # Actualizar en español
-                sel.with_context(lang='es_MX').write({'name': translated_name})
-                updated_count += 1
-                _logger.info(f"  {field_name}.{sel.value}: '{sel.name}' → '{translated_name}'")
+        for field_name, field_translations in translations.items():
+            try:
+                # Buscar el campo en ir.model.fields
+                field_record = env['ir.model.fields'].search([
+                    ('model', '=', 'helpdesk.ticket'),
+                    ('name', '=', field_name)
+                ], limit=1)
+                
+                if not field_record:
+                    _logger.warning(f"Campo {field_name} no encontrado en ir.model.fields")
+                    continue
+                
+                # Actualizar cada opción de selection
+                updated_count = 0
+                for sel in field_record.selection_ids:
+                    try:
+                        if sel.value in field_translations:
+                            translated_name = field_translations[sel.value]
+                            # Actualizar en español
+                            sel.with_context(lang='es_MX').write({'name': translated_name})
+                            updated_count += 1
+                            _logger.info(f"  {field_name}.{sel.value}: '{sel.name}' → '{translated_name}'")
+                    except Exception as e:
+                        _logger.warning(f"Error al actualizar selection {sel.id} para {field_name}: {e}")
+                        continue
+                
+                _logger.info(f"✅ {updated_count} opciones actualizadas para {field_name}")
+            except Exception as e:
+                _logger.warning(f"Error al procesar campo {field_name}: {e}")
+                continue
         
         
-        _logger.info(f"✅ {updated_count} opciones actualizadas para {field_name}")
-    
-    cr.commit()
-    _logger.info("✅ Traducciones de selection fields cargadas exitosamente")
+        cr.commit()
+        _logger.info("✅ Traducciones de selection fields cargadas exitosamente")
+    except Exception as e:
+        _logger.error(f"Error en migración 18.0.1.0.10: {e}", exc_info=True)
+        cr.rollback()
+        # No lanzar la excepción para no bloquear la actualización del módulo

+ 84 - 40
helpdesk_extras/migrations/18.0.1.0.9/post-migration.py

@@ -1,52 +1,96 @@
 # -*- coding: utf-8 -*-
 # -*- coding: utf-8 -*-
 import logging
 import logging
 from odoo import api, SUPERUSER_ID
 from odoo import api, SUPERUSER_ID
+from odoo.tools import sql
 
 
 _logger = logging.getLogger(__name__)
 _logger = logging.getLogger(__name__)
 
 
 
 
 def migrate(cr, version):
 def migrate(cr, version):
     """Actualizar traducciones para quitar 'Enterprise' de los nombres de módulos"""
     """Actualizar traducciones para quitar 'Enterprise' de los nombres de módulos"""
-    env = api.Environment(cr, SUPERUSER_ID, {})
-    
-    # Actualizar traducciones en ir.translation
-    Translation = env['ir.translation']
-    
-    # Buscar traducciones problemáticas
-    translations = Translation.search([
-        ('name', '=', 'helpdesk.affected.module,name'),
-        ('lang', '=', 'es_MX'),
-        ('value', 'ilike', 'Enterprise'),
-    ])
-    
-    _logger.info(f"Encontradas {len(translations)} traducciones con 'Enterprise' para actualizar")
-    
-    updates = {
-        'Web de Enterprise': 'Web',
-        'Web Enterprise': 'Web',
-        'Contabilidad Analítica Enterprise': 'Contabilidad Analítica',
-        'Analytic Accounting Enterprise': 'Contabilidad Analítica',
-        'Facturación (Enterprise)': 'Facturación',
-        'Facturación Enterprise': 'Facturación',
-        'Invoicing (Enterprise)': 'Facturación',
-    }
-    
-    updated_count = 0
-    for trans in translations:
-        old_value = trans.value
-        new_value = updates.get(old_value)
+    try:
+        env = api.Environment(cr, SUPERUSER_ID, {})
         
         
-        if not new_value:
-            # Limpieza genérica
-            new_value = old_value.replace('Enterprise', '').replace('enterprise', '')
-            new_value = new_value.replace(' de ', ' ').replace(' (', '').replace(')', '')
-            new_value = ' '.join(new_value.split()).strip()
+        # Verificar si el modelo ir.translation está disponible
+        if 'ir.translation' not in env.registry:
+            _logger.warning("Modelo ir.translation no disponible, usando SQL directo")
+            # Usar SQL directo si el modelo no está disponible
+            if sql.table_exists(cr, '_ir_translation'):
+                cr.execute("""
+                    UPDATE _ir_translation
+                    SET value = CASE
+                        WHEN value = 'Web de Enterprise' THEN 'Web'
+                        WHEN value = 'Web Enterprise' THEN 'Web'
+                        WHEN value = 'Contabilidad Analítica Enterprise' THEN 'Contabilidad Analítica'
+                        WHEN value = 'Analytic Accounting Enterprise' THEN 'Contabilidad Analítica'
+                        WHEN value = 'Facturación (Enterprise)' THEN 'Facturación'
+                        WHEN value = 'Facturación Enterprise' THEN 'Facturación'
+                        WHEN value = 'Invoicing (Enterprise)' THEN 'Facturación'
+                        ELSE regexp_replace(
+                            regexp_replace(
+                                regexp_replace(value, 'Enterprise', '', 'gi'),
+                                'enterprise', '', 'gi'
+                            ),
+                            '\\s+', ' ', 'g'
+                        )
+                    END
+                    WHERE name = 'helpdesk.affected.module,name'
+                      AND lang = 'es_MX'
+                      AND (value ILIKE '%Enterprise%' OR value ILIKE '%enterprise%')
+                """)
+                updated_count = cr.rowcount
+                cr.commit()
+                _logger.info(f"✅ {updated_count} traducciones actualizadas exitosamente (vía SQL)")
+            else:
+                _logger.warning("Tabla _ir_translation no existe, saltando actualización")
+            return
         
         
-        if old_value != new_value:
-            trans.write({'value': new_value})
-            updated_count += 1
-            _logger.info(f"Actualizado: '{old_value}' → '{new_value}'")
-    
-    cr.commit()
-    _logger.info(f"✅ {updated_count} traducciones actualizadas exitosamente")
+        # Actualizar traducciones en ir.translation
+        Translation = env['ir.translation']
+        
+        # Buscar traducciones problemáticas
+        translations = Translation.search([
+            ('name', '=', 'helpdesk.affected.module,name'),
+            ('lang', '=', 'es_MX'),
+            ('value', 'ilike', 'Enterprise'),
+        ])
+        
+        _logger.info(f"Encontradas {len(translations)} traducciones con 'Enterprise' para actualizar")
+        
+        updates = {
+            'Web de Enterprise': 'Web',
+            'Web Enterprise': 'Web',
+            'Contabilidad Analítica Enterprise': 'Contabilidad Analítica',
+            'Analytic Accounting Enterprise': 'Contabilidad Analítica',
+            'Facturación (Enterprise)': 'Facturación',
+            'Facturación Enterprise': 'Facturación',
+            'Invoicing (Enterprise)': 'Facturación',
+        }
+        
+        updated_count = 0
+        for trans in translations:
+            try:
+                old_value = trans.value
+                new_value = updates.get(old_value)
+                
+                if not new_value:
+                    # Limpieza genérica
+                    new_value = old_value.replace('Enterprise', '').replace('enterprise', '')
+                    new_value = new_value.replace(' de ', ' ').replace(' (', '').replace(')', '')
+                    new_value = ' '.join(new_value.split()).strip()
+                
+                if old_value != new_value:
+                    trans.write({'value': new_value})
+                    updated_count += 1
+                    _logger.info(f"Actualizado: '{old_value}' → '{new_value}'")
+            except Exception as e:
+                _logger.warning(f"Error al actualizar traducción {trans.id}: {e}")
+                continue
+        
+        cr.commit()
+        _logger.info(f"✅ {updated_count} traducciones actualizadas exitosamente")
+    except Exception as e:
+        _logger.error(f"Error en migración 18.0.1.0.9: {e}", exc_info=True)
+        cr.rollback()
+        # No lanzar la excepción para no bloquear la actualización del módulo