fix(fusion_accounting_core): add pre-migration for security group rename
Task 16's security group rehoming (fusion_accounting → fusion_accounting_core) only existed in post-migration. That flow fails on fresh pre-Phase-0 upgrades: data-load runs before post-migration and looks up group xml-ids by (module, name); if the row still has module='fusion_accounting', Odoo creates a duplicate res.groups record under module='fusion_accounting_core'. The subsequent post-migration UPDATE...SET module='fusion_accounting_core' then trips the (module, name) unique constraint on ir_model_data, rolling back the whole transaction. Pre-migration runs BEFORE data-load, renames the five security xml-ids (module_category, privilege, three groups) to the new module, so data-load finds the existing rows and UPDATEs them in place. Existing user-group links via res_groups_users_rel are preserved. The post-migration is kept as an idempotent safety net (docstring updated to reflect the new division of labour). Verified on westin-v19 by simulating the pre-Phase-0 state (UPDATE ir_model_data SET module='fusion_accounting' ...) and re-running the upgrade: 5 rows renamed cleanly, zero duplicates, no errors. Made-with: Cursor
This commit is contained in:
@@ -1,17 +1,15 @@
|
||||
"""Reassign security group/category/privilege xml-ids from the old module name.
|
||||
"""Safety-net reassignment of security xml-ids to fusion_accounting_core.
|
||||
|
||||
Pre-Phase-0, the three fusion security groups (user, manager, admin), the
|
||||
module category and the privilege all lived in module='fusion_accounting'.
|
||||
Post-Phase-0 (Task 16) they moved into module='fusion_accounting_core'.
|
||||
The actual rename lives in pre-migration.py — it MUST run before data-load
|
||||
to avoid creating duplicate res.groups records and hitting the (module,
|
||||
name) unique constraint on ir_model_data. This post-migration is a
|
||||
belt-and-suspenders no-op for the common case: if pre-migration already
|
||||
ran, this UPDATE matches zero rows.
|
||||
|
||||
Odoo loads the XML from the new location on upgrade, but the existing
|
||||
ir_model_data rows still reference the old module. This script rewrites them.
|
||||
|
||||
Both fusion_accounting_core and fusion_accounting_ai ship an equivalent
|
||||
UPDATE — whichever post-migration runs first wins the rehoming, the other
|
||||
is a no-op. This redundancy protects the common case where the two modules
|
||||
are upgraded in either order (as well as the case where only one is
|
||||
installed in a given database).
|
||||
It also catches a rare edge case: fusion_accounting_ai.post-migration.py
|
||||
runs an identical UPDATE to cover cross-module upgrade ordering, so both
|
||||
modules redundantly ensure the rows land in the right module regardless
|
||||
of which upgrade runs first.
|
||||
|
||||
Idempotent: running it a second time matches zero rows.
|
||||
"""
|
||||
@@ -21,7 +19,7 @@ import logging
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
CORE_SECURITY_NAMES = (
|
||||
SECURITY_NAMES = (
|
||||
'module_category_fusion_accounting',
|
||||
'res_groups_privilege_fusion_accounting',
|
||||
'group_fusion_accounting_user',
|
||||
@@ -38,11 +36,12 @@ def migrate(cr, version):
|
||||
WHERE module = 'fusion_accounting'
|
||||
AND name = ANY(%s)
|
||||
""",
|
||||
(list(CORE_SECURITY_NAMES),),
|
||||
(list(SECURITY_NAMES),),
|
||||
)
|
||||
moved = cr.rowcount
|
||||
_logger.info(
|
||||
"fusion_accounting_core post-migration: reassigned %d security rows "
|
||||
"from module='fusion_accounting' to module='fusion_accounting_core'",
|
||||
"from module='fusion_accounting' to module='fusion_accounting_core' "
|
||||
"(usually zero; pre-migration already handled the rename)",
|
||||
moved,
|
||||
)
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
"""Rehome the fusion security xml-ids to fusion_accounting_core BEFORE data-load.
|
||||
|
||||
Pre-Phase-0, the three fusion security groups (user, manager, admin), the
|
||||
module category and the privilege all lived in module='fusion_accounting'.
|
||||
Post-Phase-0 (Task 16) they moved into module='fusion_accounting_core'.
|
||||
|
||||
Running this rename in pre-migration (rather than post-migration) is
|
||||
essential: Odoo's XML data-load looks up records by (module, name) in
|
||||
ir_model_data. If the old row still has module='fusion_accounting' when
|
||||
data-load runs, Odoo will not find a match for
|
||||
'fusion_accounting_core.group_fusion_accounting_user' and will CREATE a
|
||||
brand-new res.groups record plus a new ir_model_data row. That leaves the
|
||||
database with two groups per name:
|
||||
|
||||
1. The ORIGINAL group (still tagged module='fusion_accounting') that every
|
||||
existing user is linked to via res_groups_users_rel.
|
||||
2. A FRESH empty group (newly tagged module='fusion_accounting_core').
|
||||
|
||||
The subsequent post-migration UPDATE...SET module='fusion_accounting_core'
|
||||
would then violate the (module, name) unique constraint on ir_model_data
|
||||
and the upgrade transaction would roll back.
|
||||
|
||||
By renaming ir_model_data rows BEFORE data-load, Odoo finds the existing
|
||||
row (now tagged fusion_accounting_core.*), UPDATEs the res.groups record
|
||||
in place with the XML-defined values, and the user-group links are
|
||||
preserved untouched.
|
||||
|
||||
Idempotent: running this a second time matches zero rows.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
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):
|
||||
cr.execute(
|
||||
"""
|
||||
UPDATE ir_model_data
|
||||
SET module = 'fusion_accounting_core'
|
||||
WHERE module = 'fusion_accounting'
|
||||
AND name = ANY(%s)
|
||||
""",
|
||||
(list(SECURITY_NAMES),),
|
||||
)
|
||||
moved = cr.rowcount
|
||||
_logger.info(
|
||||
"fusion_accounting_core pre-migration: renamed %d security rows "
|
||||
"from module='fusion_accounting' to module='fusion_accounting_core' "
|
||||
"before data-load (idempotent; non-zero only on first upgrade from "
|
||||
"pre-Phase-0)",
|
||||
moved,
|
||||
)
|
||||
Reference in New Issue
Block a user