helpdesk_rating_five_stars/hooks.py
2025-11-26 10:39:26 +07:00

129 lines
4.3 KiB
Python

# -*- coding: utf-8 -*-
import logging
from odoo import api, SUPERUSER_ID
_logger = logging.getLogger(__name__)
def post_init_hook(env):
"""
Post-installation hook to migrate existing ratings from 0-3 scale to 0-5 scale.
Migration mapping:
- 0 → 0 (no rating)
- 1 → 3 (poor becomes 3 stars)
- 2 → 4 (okay becomes 4 stars)
- 3 → 5 (good becomes 5 stars)
Args:
env: Odoo environment
"""
_logger.info("Starting rating migration from 0-3 scale to 0-5 scale...")
cr = env.cr
# Check if we're running in test mode by checking if commit is forbidden
test_mode = False
try:
# Try to check if we're in test mode by looking at the cursor
test_mode = hasattr(cr, '__class__') and 'TestCursor' in cr.__class__.__name__
except:
test_mode = False
try:
# Define the migration mapping
migration_mapping = {
0: 0, # No rating stays 0
1: 3, # Poor (1) becomes 3 stars
2: 4, # Okay (2) becomes 4 stars
3: 5, # Good (3) becomes 5 stars
}
# Get all ratings that need migration (values 0-3)
# We need to use SQL to avoid triggering constraints during migration
cr.execute("""
SELECT id, rating
FROM rating_rating
WHERE rating IN (0, 1, 2, 3)
""")
ratings_to_migrate = cr.fetchall()
total_count = len(ratings_to_migrate)
if total_count == 0:
_logger.info("No ratings found to migrate. Migration complete.")
return
_logger.info(f"Found {total_count} ratings to migrate.")
# Migrate ratings in batches for better performance
batch_size = 1000
migrated_count = 0
error_count = 0
for i in range(0, total_count, batch_size):
batch = ratings_to_migrate[i:i + batch_size]
try:
# Use SQL UPDATE for better performance and to avoid constraint issues
for rating_id, old_value in batch:
# Only migrate if the value is in the old scale (0-3)
if old_value in migration_mapping:
new_value = migration_mapping[old_value]
# Update using SQL to bypass ORM constraints temporarily
cr.execute("""
UPDATE rating_rating
SET rating = %s
WHERE id = %s AND rating = %s
""", (new_value, rating_id, old_value))
migrated_count += 1
# Only commit if not in test mode
if not test_mode:
cr.commit()
_logger.info(f"Migrated batch: {migrated_count}/{total_count} ratings")
except Exception as batch_error:
_logger.error(f"Error migrating batch: {batch_error}")
error_count += len(batch)
# Only rollback if not in test mode
if not test_mode:
cr.rollback()
continue
# Final commit (only if not in test mode)
if not test_mode:
cr.commit()
# Log final results
_logger.info(f"Rating migration complete!")
_logger.info(f"Successfully migrated: {migrated_count} ratings")
if error_count > 0:
_logger.warning(f"Failed to migrate: {error_count} ratings")
# Verify migration results
cr.execute("""
SELECT COUNT(*)
FROM rating_rating
WHERE rating > 0 AND rating < 1
""")
invalid_count = cr.fetchone()[0]
if invalid_count > 0:
_logger.warning(f"Found {invalid_count} ratings with invalid values after migration")
_logger.info("Rating migration process finished.")
except Exception as e:
_logger.error(f"Critical error during rating migration: {e}")
# Only rollback if not in test mode
if not test_mode:
cr.rollback()
_logger.error("Migration rolled back due to critical error.")
raise