124 lines
4.7 KiB
Python
124 lines
4.7 KiB
Python
"""Reassign ir_model_data ownership from fusion_accounting to fusion_accounting_ai.
|
|
|
|
Pre-Phase-0, all fusion code lived in module='fusion_accounting'. Post-Phase-0,
|
|
fusion_accounting is the meta-module and the AI code lives in
|
|
'fusion_accounting_ai'. Odoo loads the Python from the new location, but
|
|
existing ir_model_data rows still record the old module name. This script
|
|
rewrites them.
|
|
|
|
Special case: if the data-load phase of this very upgrade already created a
|
|
new row in module='fusion_accounting_ai' with the same `name` as an old
|
|
orphan (because the orphan lived under the old module name when data-load
|
|
looked for it, missed it, and re-created the record), the UPDATE below would
|
|
violate the unique constraint on (module, name). For those conflicts we
|
|
delete the old orphan — the newly-created row is the one that records and
|
|
the runtime will actually use going forward.
|
|
|
|
Idempotent: running it a second time does nothing because the WHERE clauses
|
|
find no matches.
|
|
"""
|
|
|
|
import logging
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
# Exact xml-id names (model_ prefix, one per fusion.* model) that belonged to
|
|
# the AI module. Each corresponds to a <record id="model_..."/> auto-created
|
|
# by Odoo when the model class loads.
|
|
AI_MODEL_PREFIXES = (
|
|
'model_fusion_accounting_session',
|
|
'model_fusion_accounting_match_history',
|
|
'model_fusion_accounting_rule',
|
|
'model_fusion_accounting_tool',
|
|
'model_fusion_accounting_dashboard',
|
|
'model_fusion_accounting_recurring_pattern',
|
|
'model_fusion_accounting_vendor_tax_profile',
|
|
'model_fusion_accounting_rule_wizard',
|
|
)
|
|
|
|
# XML-id name patterns for views/data/security/wizard/etc. that belong to
|
|
# the AI sub-module. These cover every xml-id the AI module declares in its
|
|
# data files (cron.xml, default_rules.xml, tool_definitions.xml, views/*.xml,
|
|
# wizards/*.xml, report/*.xml) plus the ACL entries in ir.model.access.csv.
|
|
#
|
|
# Patterns use SQL LIKE syntax; '%' matches anything. These are broad on
|
|
# purpose: we want to catch every past and present xml-id declared by the AI
|
|
# data files, including Odoo-auto-generated companions (e.g. ir.cron auto-
|
|
# creates an ir.actions.server with xml-id '<cron_name>_ir_actions_server').
|
|
AI_NAME_LIKE = (
|
|
'view_fusion_%',
|
|
'action_fusion_%',
|
|
'menu_fusion_%',
|
|
'fusion_tool_%',
|
|
'fusion_rule_%',
|
|
'cron_fusion_%',
|
|
'seq_fusion_%',
|
|
'access_fusion_%',
|
|
'rule_fusion_%',
|
|
'paperformat_fusion_%',
|
|
'report_fusion_%',
|
|
'audit_report_template',
|
|
)
|
|
|
|
|
|
# Group/category/privilege xml-ids that moved from 'fusion_accounting' to
|
|
# 'fusion_accounting_core' in Phase 0 (Task 16). Both _core and _ai
|
|
# post-migrations run this same UPDATE — whichever runs first wins, the other
|
|
# is a no-op. We reassign these here too so that if _ai happens to upgrade
|
|
# first (before _core's own post-migration has had a chance to run) the groups
|
|
# are still rehomed correctly.
|
|
CORE_SECURITY_NAMES = (
|
|
'module_category_fusion_accounting',
|
|
'res_groups_privilege_fusion_accounting',
|
|
'group_fusion_accounting_user',
|
|
'group_fusion_accounting_manager',
|
|
'group_fusion_accounting_admin',
|
|
)
|
|
|
|
|
|
def migrate(cr, version):
|
|
# Step 0: Reassign security groups/category/privilege to fusion_accounting_core.
|
|
cr.execute("""
|
|
UPDATE ir_model_data
|
|
SET module = 'fusion_accounting_core'
|
|
WHERE module = 'fusion_accounting'
|
|
AND name = ANY(%s)
|
|
""", (list(CORE_SECURITY_NAMES),))
|
|
moved_to_core = cr.rowcount
|
|
|
|
# Step 1: Delete orphan rows that conflict with an already-existing row in
|
|
# fusion_accounting_ai (data-load artifact). The new row is the survivor.
|
|
cr.execute("""
|
|
DELETE FROM ir_model_data AS old
|
|
WHERE old.module = 'fusion_accounting'
|
|
AND (old.name = ANY(%s) OR old.name LIKE ANY(%s))
|
|
AND EXISTS (
|
|
SELECT 1 FROM ir_model_data AS new
|
|
WHERE new.module = 'fusion_accounting_ai'
|
|
AND new.name = old.name
|
|
)
|
|
""", (list(AI_MODEL_PREFIXES), list(AI_NAME_LIKE)))
|
|
deleted_conflicts = cr.rowcount
|
|
|
|
# Step 2: Reassign the non-conflicting orphans to fusion_accounting_ai.
|
|
cr.execute("""
|
|
UPDATE ir_model_data
|
|
SET module = 'fusion_accounting_ai'
|
|
WHERE module = 'fusion_accounting'
|
|
AND (
|
|
name = ANY(%s)
|
|
OR name LIKE ANY(%s)
|
|
)
|
|
""", (list(AI_MODEL_PREFIXES), list(AI_NAME_LIKE)))
|
|
moved_to_ai = cr.rowcount
|
|
|
|
_logger.info(
|
|
"fusion_accounting_ai post-migration: reassigned %d security rows to "
|
|
"fusion_accounting_core, deleted %d conflicting AI orphans, reassigned "
|
|
"%d ir_model_data rows from module='fusion_accounting' to "
|
|
"module='fusion_accounting_ai'",
|
|
moved_to_core,
|
|
deleted_conflicts,
|
|
moved_to_ai,
|
|
)
|