Skip to content

Commit

Permalink
Merge pull request #396 from hbrunn/master-v18-specifics
Browse files Browse the repository at this point in the history
[ADD] openupgrade_180.convert_company_dependent
  • Loading branch information
pedrobaeza authored Jan 28, 2025
2 parents 1f84d5c + a1f4202 commit 1c8d2d8
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 0 deletions.
11 changes: 11 additions & 0 deletions openupgradelib/openupgrade.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,17 @@ def __exit__(self, exc_type, exc_value, traceback):
else:
import release

try:
# since 18.0, Odoo checks for the signature of migration functions
# and raises if the parameter names are not contained here
from odoo.modules.migration import VALID_MIGRATE_PARAMS

# allow (env, version) signatures in migration methods
if ("env", "version") not in VALID_MIGRATE_PARAMS:
VALID_MIGRATE_PARAMS.append(("env", "version"))
except ImportError: # pylint: disable=except-pass
pass

Many2many = False
One2many = False
one2many = False
Expand Down
72 changes: 72 additions & 0 deletions openupgradelib/openupgrade_180.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Copyright 2025 Hunki Enterprises BV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from .openupgrade import logged_query


def convert_company_dependent(
env, model_name, field_name, value_expression=None, old_field_id=None
):
"""
Company dependent fields used to live in ir.property, in v18 they are jsonb
dictionaries with company id as key and the company specific value as value.
Default values are set in ir.default
:param model_name: the name of the model
:param field_name: the name of the field
:param value_expression: an SQL expression extracting the value to be used
from a row of ir_property
:param old_field_id: in case a field has been renamed during the migration,
pass the field id of the previous field here
"""
Model = env[model_name]
Field = (
env["ir.model.fields"]._get(model_name, field_name)
if not old_field_id
else env["ir.model.fields"].browse(old_field_id)
)
value_expression = value_expression or (
"value_%s"
% {
"float": "float",
"boolean": "integer",
"integer": "integer",
"date": "datetime",
"datetime": "datetime",
}.get(Field.ttype, "text")
if Field.ttype != "many2one"
else "SPLIT_PART(value_reference, ',', 2)::integer"
)

logged_query(
env.cr,
f"ALTER TABLE {Model._table} ADD COLUMN IF NOT EXISTS {field_name} jsonb",
)

logged_query(
env.cr,
f"""
UPDATE {Model._table} SET {field_name}=ir_property_by_company.value
FROM (
SELECT
SPLIT_PART(res_id, ',', 2)::integer res_id,
JSON_OBJECT_AGG(company_id, {value_expression}) value
FROM ir_property
WHERE
fields_id={old_field_id or Field.id} AND res_id IS NOT NULL
AND company_id IS NOT NULL
GROUP BY res_id
) ir_property_by_company
WHERE {Model._table}.id=ir_property_by_company.res_id
""",
)

env.cr.execute(
f"""
SELECT company_id, {value_expression} FROM ir_property
WHERE
fields_id={old_field_id or Field.id} AND res_id IS NULL
"""
)
for company_id, value in env.cr.fetchall():
env["ir.default"].set(model_name, field_name, value, company_id=company_id)

0 comments on commit 1c8d2d8

Please sign in to comment.