|
| 1 | +import logging |
| 2 | + |
| 3 | +from openupgradelib import openupgrade_merge_records |
| 4 | + |
| 5 | +from odoo import SUPERUSER_ID, api |
| 6 | + |
| 7 | +logger = logging.getLogger(__name__) |
| 8 | + |
| 9 | + |
| 10 | +def _cleanup_orphan_references(cr, model_table): |
| 11 | + """Nullify references to activities that no longer exist after merging.""" |
| 12 | + logger.info("Cleaning up orphan references to %s", model_table) |
| 13 | + column = "l10n_ar_arca_activity_id" |
| 14 | + for table in ["res_company", "account_account"]: |
| 15 | + cr.execute( |
| 16 | + f""" |
| 17 | + UPDATE {table} |
| 18 | + SET {column} = NULL |
| 19 | + WHERE NOT EXISTS ( |
| 20 | + SELECT 1 FROM {model_table} WHERE id = {table}.{column} |
| 21 | + ) |
| 22 | + """ |
| 23 | + ) |
| 24 | + if cr.rowcount: |
| 25 | + logger.info( |
| 26 | + "Cleaned %d orphan references in table '%s'", cr.rowcount, table |
| 27 | + ) |
| 28 | + |
| 29 | + |
| 30 | +def migrate(cr, version): |
| 31 | + """Merge duplicate records in l10n_ar.arca.activity based on the 'code' field. |
| 32 | +
|
| 33 | + This handles the case where activities were user-created in the old model (afip.padron) |
| 34 | + but are now created as data in the new model (l10n_ar.arca.activity), which can lead |
| 35 | + to duplicates after migration. |
| 36 | + """ |
| 37 | + model_name = "l10n_ar.arca.activity" |
| 38 | + model_table = "l10n_ar_arca_activity" |
| 39 | + |
| 40 | + # Find duplicate codes |
| 41 | + cr.execute( |
| 42 | + f""" |
| 43 | + SELECT code, array_agg(id ORDER BY id) as ids |
| 44 | + FROM {model_table} |
| 45 | + WHERE code IS NOT NULL |
| 46 | + GROUP BY code |
| 47 | + HAVING COUNT(*) > 1 |
| 48 | + """ |
| 49 | + ) |
| 50 | + |
| 51 | + duplicates = cr.fetchall() |
| 52 | + if not duplicates: |
| 53 | + logger.info("No duplicate activities found based on 'code' field") |
| 54 | + return |
| 55 | + |
| 56 | + logger.info("Found %s groups of duplicate activities to merge", len(duplicates)) |
| 57 | + env = api.Environment(cr, SUPERUSER_ID, {}) |
| 58 | + |
| 59 | + for code, record_ids in duplicates: |
| 60 | + if len(record_ids) < 2: |
| 61 | + continue |
| 62 | + |
| 63 | + # Use the last record (highest ID) as target, which is the original user-created record |
| 64 | + # The lower IDs are typically the new data records that were loaded |
| 65 | + target_record_id = record_ids[-1] |
| 66 | + records_to_merge = record_ids[:-1] |
| 67 | + |
| 68 | + logger.info( |
| 69 | + "Merging duplicate activities with code '%s': merging %s into %s", |
| 70 | + code, |
| 71 | + records_to_merge, |
| 72 | + target_record_id, |
| 73 | + ) |
| 74 | + |
| 75 | + try: |
| 76 | + openupgrade_merge_records.merge_records( |
| 77 | + env=env, |
| 78 | + model_name=model_name, |
| 79 | + record_ids=records_to_merge, |
| 80 | + target_record_id=target_record_id, |
| 81 | + method="sql", |
| 82 | + delete=True, |
| 83 | + model_table=model_table, |
| 84 | + ) |
| 85 | + logger.info( |
| 86 | + "Successfully merged %s duplicate records into record %s", |
| 87 | + len(records_to_merge), |
| 88 | + target_record_id, |
| 89 | + ) |
| 90 | + except Exception as e: |
| 91 | + logger.error( |
| 92 | + "Error merging duplicate activities with code '%s': %s", code, str(e) |
| 93 | + ) |
| 94 | + # Continue with next group even if one fails |
| 95 | + continue |
| 96 | + |
| 97 | + # Clean up any references that might have been broken after the merge |
| 98 | + _cleanup_orphan_references(cr, model_table) |
0 commit comments