From a5a03da964a81bf7b6183ae68359ab80c5db1467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Taymans?= Date: Wed, 31 Jan 2024 16:50:01 +0100 Subject: [PATCH] [OU-ADD] project: migration script --- docsource/modules150-160.rst | 2 +- .../hr/16.0.1.1/upgrade_analysis_work.txt | 43 ++++++ .../project/16.0.1.2/post-migration.py | 11 ++ .../scripts/project/16.0.1.2/pre-migration.py | 139 ++++++++++++++++++ .../16.0.1.2/upgrade_analysis_work.txt | 99 +++++++++++++ 5 files changed, 293 insertions(+), 1 deletion(-) create mode 100644 openupgrade_scripts/scripts/hr/16.0.1.1/upgrade_analysis_work.txt create mode 100644 openupgrade_scripts/scripts/project/16.0.1.2/post-migration.py create mode 100644 openupgrade_scripts/scripts/project/16.0.1.2/pre-migration.py create mode 100644 openupgrade_scripts/scripts/project/16.0.1.2/upgrade_analysis_work.txt diff --git a/docsource/modules150-160.rst b/docsource/modules150-160.rst index b0f5266d47e8..bb54156f8193 100644 --- a/docsource/modules150-160.rst +++ b/docsource/modules150-160.rst @@ -640,7 +640,7 @@ Module coverage 15.0 -> 16.0 +-------------------------------------------------+----------------------+-------------------------------------------------+ | product_matrix | | | +-------------------------------------------------+----------------------+-------------------------------------------------+ -| project | | | +| project | Done | | +-------------------------------------------------+----------------------+-------------------------------------------------+ | |del| project_account | | | +-------------------------------------------------+----------------------+-------------------------------------------------+ diff --git a/openupgrade_scripts/scripts/hr/16.0.1.1/upgrade_analysis_work.txt b/openupgrade_scripts/scripts/hr/16.0.1.1/upgrade_analysis_work.txt new file mode 100644 index 000000000000..e51fb4d9f9ac --- /dev/null +++ b/openupgrade_scripts/scripts/hr/16.0.1.1/upgrade_analysis_work.txt @@ -0,0 +1,43 @@ +---Models in module 'hr'--- +model hr.contract.type (moved from hr_contract) +---Fields in module 'hr'--- +hr / hr.contract.type / __last_update (datetime) : previously in module hr_contract +hr / hr.contract.type / _order : previously in module hr_contract +hr / hr.contract.type / display_name (char) : previously in module hr_contract +hr / hr.contract.type / name (char) : previously in module hr_contract +hr / hr.contract.type / sequence (integer) : NEW +hr / hr.department / master_department_id (many2one): NEW relation: hr.department, isfunction: function, stored +hr / hr.department / parent_path (char) : NEW +hr / hr.department / plan_ids (one2many) : NEW relation: hr.plan +hr / hr.employee / currency_id (many2one) : previously in module hr_timesheet +hr / hr.employee / mobile_phone (char) : now a function +hr / hr.employee / work_contact_id (many2one) : NEW relation: res.partner +hr / hr.employee / work_email (char) : now a function +hr / hr.job / active (boolean) : NEW hasdefault: default +hr / hr.job / contract_type_id (many2one) : NEW relation: hr.contract.type +hr / hr.job / state (selection) : DEL required, selection_keys: ['open', 'recruit'] +hr / hr.plan / company_id (many2one) : NEW relation: res.company, hasdefault: default +hr / hr.plan / department_id (many2one) : NEW relation: hr.department +hr / hr.plan / plan_activity_type_ids (many2many): table is now 'False' ('hr_plan_hr_plan_activity_type_rel') +hr / hr.plan / plan_activity_type_ids (many2many): type is now 'one2many' ('many2many') +hr / hr.plan.activity.type / company_id (many2one) : NEW relation: res.company, hasdefault: default +hr / hr.plan.activity.type / plan_id (many2one) : NEW relation: hr.plan +hr / res.users / create_employee (boolean) : NEW hasdefault: default +hr / res.users / create_employee_id (many2one) : NEW relation: hr.employee +hr / resource.resource / employee_id (one2many) : NEW relation: hr.employee +---XML records in module 'hr'--- +NEW ir.actions.act_window: hr.hr_contract_type_action +NEW ir.actions.server: hr.action_hr_employee_create_user +NEW ir.model.access: hr.access_hr_contract_type_manager [renamed from hr_contract module] +NEW ir.rule: hr.hr_plan_activity_type_company_rule (noupdate) +NEW ir.rule: hr.hr_plan_company_rule (noupdate) +NEW ir.ui.menu: hr.menu_config_employee +NEW ir.ui.menu: hr.menu_config_recruitment +NEW ir.ui.menu: hr.menu_view_hr_contract_type +DEL ir.ui.menu: hr.menu_config_plan_types +DEL ir.ui.menu: hr.menu_human_resources_configuration_employee +NEW ir.ui.view: hr.hr_contract_type_view_form +NEW ir.ui.view: hr.hr_contract_type_view_tree +NEW ir.ui.view: hr.view_employee_form_smartbutton +NEW ir.ui.view: hr.view_users_simple_form +NEW ir.ui.view: hr.view_users_simple_form_inherit_hr diff --git a/openupgrade_scripts/scripts/project/16.0.1.2/post-migration.py b/openupgrade_scripts/scripts/project/16.0.1.2/post-migration.py new file mode 100644 index 000000000000..e334ef6b9d5e --- /dev/null +++ b/openupgrade_scripts/scripts/project/16.0.1.2/post-migration.py @@ -0,0 +1,11 @@ +# Copyright 2023 Trần Trường Sơn +# Copyright 2023 Rémy Taymans +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openupgradelib import openupgrade + + +@openupgrade.migrate() +def migrate(env, version): + # TODO: check to load only needed update + openupgrade.load_data(env.cr, "project", "16.0.1.2/noupdate_changes.xml") diff --git a/openupgrade_scripts/scripts/project/16.0.1.2/pre-migration.py b/openupgrade_scripts/scripts/project/16.0.1.2/pre-migration.py new file mode 100644 index 000000000000..8e926bc0aa42 --- /dev/null +++ b/openupgrade_scripts/scripts/project/16.0.1.2/pre-migration.py @@ -0,0 +1,139 @@ +# Copyright 2023 Trần Trường Sơn +# Copyright 2023 Rémy Taymans +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import openupgradelib as openupgrade + + +def _set_task_type_fold_if_is_closed(env): + """Field `is_closed` on project.task.type is removed. The field + `fold` can be used instead. + """ + openupgrade.logged_query( + env.cr, + """ + UPDATE project_task_type + SET fold = TRUE + WHERE is_closed = TRUE; + """, + ) + + +def _fill_project_task_is_closed(env): + """Field `is_closed` on project.task is now a stored field.""" + openupgrade.add_fields( + env, + [ + ( + "is_closed", # Field name + "project.task", # Model name + "project_task", # Table name + "boolean", # Odoo Field type (in lower case) + False, # [Optional] SQL type (if custom fields) + "project", # Module name + False, # [Optional] Default value + ) + ], + ) + openupgrade.logged_query( + env.cr, + """ + UPDATE project_task task + SET is_closed = CASE + WHEN stage.fold = TRUE THEN TRUE + ELSE FALSE + END + FROM project_task_type stage + WHERE task.stage_id = stage.id; + """, + ) + + +def _fill_project_last_update_status_if_null(env): + """In some cases, the user can go to the DB and reset the + `last_update_status` field to NULL. In version 16.0 it is necessary + to reset it to `to_define` because it has a `required` attribute. + """ + openupgrade.logged_query( + env.cr, + """ + UPDATE project_project project + SET last_update_status = 'to_define' + WHERE last_update_status IS NULL; + """, + ) + + +def _compute_project_task_ancestor_id(env): + """ + New column at version 16.0. valid as the ancestor of the current task + """ + openupgrade.logged_query( + env.cr, + """ + WITH RECURSIVE task_ancestors AS ( + SELECT id, parent_id, id AS ancestor_id + FROM project_task + WHERE parent_id IS NULL + + UNION ALL + + SELECT pt.id, pt.parent_id, ta.ancestor_id + FROM project_task pt + INNER JOIN task_ancestors ta ON pt.parent_id = ta.id + ) + UPDATE project_task pt + SET ancestor_id = ta.ancestor_id + FROM task_ancestors ta + WHERE pt.id = ta.id; + + UPDATE project_task pt + SET ancestor_id = NULL + WHERE id = ancestor_id; + """, + ) + + +def _compute_project_task_is_analytic_account_id_changed(env): + """ + `is_analytic_account_id_changed` is a new field at version 16.0. + It has a value of False if you have the same admin account as the project, + otherwise it will have a value of True + """ + openupgrade.add_fields( + env, + [ + ( + "is_analytic_account_id_changed", # Field name + "project.task", # Model name + "project_task", # Table name + "boolean", # Odoo Field type (in lower case) + False, # [Optional] SQL type (if custom fields) + "project", # Module name + False, # [Optional] Default value + ) + ], + ) + openupgrade.logged_query( + env.cr, + """ + UPDATE project_task task + SET is_analytic_account_id_changed = CASE + WHEN project_id IS NOT NULL + AND task.project_id = project.id + AND task.analytic_account_id != project.analytic_account_id + THEN TRUE + ELSE FALSE + END + FROM project_project as project; + """, + ) + + +@openupgrade.migrate() +def migrate(env, version): + _set_task_type_fold_if_is_closed(env) + _fill_project_task_is_closed(env) + _fill_project_last_update_status_if_null(env) + _compute_project_task_ancestor_id(env) + _compute_project_task_is_analytic_account_id_changed(env) diff --git a/openupgrade_scripts/scripts/project/16.0.1.2/upgrade_analysis_work.txt b/openupgrade_scripts/scripts/project/16.0.1.2/upgrade_analysis_work.txt new file mode 100644 index 000000000000..e03c8b7118b6 --- /dev/null +++ b/openupgrade_scripts/scripts/project/16.0.1.2/upgrade_analysis_work.txt @@ -0,0 +1,99 @@ +---Models in module 'project'--- +obsolete model project.delete.wizard [transient] +# NOTHING TO DO: wizard removed + +---Fields in module 'project'--- +project / account.analytic.tag / task_ids (many2many) : DEL relation: project.task +project / project.task / analytic_tag_ids (many2many) : DEL relation: account.analytic.tag +# NOTHING TO DO: lost feature + +project / project.milestone / task_ids (one2many) : NEW relation: project.task +project / project.project / allow_milestones (boolean) : NEW hasdefault: default +project / project.project / task_properties_definition (properties_definition): NEW +project / project.task / task_properties (properties) : NEW hasdefault: compute +project / res.company / analytic_plan_id (many2one) : NEW relation: account.analytic.plan, hasdefault: compute +# NOTHING TO DO: new features + +project / project.tags / project_ids (many2many) : NEW relation: project.project +project / project.tags / task_ids (many2many) : NEW relation: project.task +# NOTHING TO DO: reverse relation that already exists on project.project and project.task + +pad_project / project.project / description_pad (char) : DEL +pad_project / project.project / use_pads (boolean) : DEL +pad_project / project.task / description_pad (char) : DEL +# TODO: Module pad_project has been removed + +project / project.project / last_update_status (selection): not a function anymore +project / project.project / last_update_status (selection): now required +project / project.project / last_update_status (selection): selection_keys is now '['at_risk', 'off_track', 'on_hold', 'on_track', 'to_define']' ('['at_risk', 'off_track', 'on_hold', 'on_track']') +# DONE: pre-migration: Set value of last_update_status to 'to_define' where field is empty + +project / project.task.type / is_closed (boolean) : DEL +# DONE: pre-migration: Field removed, field 'fold' should be used instead. Moving values from 'is_closed' to 'fold'. + +project / project.task / is_closed (boolean) : is now stored +# DONE: pre-migration: Add new column & set value for it + +project / project.task / ancestor_id (many2one) : NEW relation: project.task, isfunction: function, stored +project / project.task / is_analytic_account_id_changed (boolean): NEW isfunction: function, stored +# DONE: pre-migration: pre-compute value for new computed fields + +project / project.task / is_blocked (boolean) : NEW isfunction: function, stored +project / project.task / milestone_id (many2one) : NEW relation: project.milestone, hasdefault: compute +# TODO (speed improvement): pre-migration: pre-compute value for new computed fields + + +---XML records in module 'project'--- +NEW digest.tip: project.digest_tip_project_1 +NEW ir.actions.act_window: project.action_send_mail_project_project +NEW ir.actions.act_window: project.action_send_mail_project_task +NEW ir.actions.act_window: project.action_view_task_from_milestone +NEW ir.actions.act_window: project.open_view_project_all_config_group_stage +NEW ir.actions.act_window: project.project_sharing_project_task_action_sub_task +NEW ir.actions.act_window: project.project_task_action_sub_task +DEL ir.actions.act_window: project.project_milestone_all +NEW ir.actions.act_window.view: project.open_view_all_task_list_calendar +NEW ir.actions.act_window.view: project.open_view_all_task_list_kanban +NEW ir.actions.act_window.view: project.open_view_all_task_list_tree +NEW ir.actions.act_window.view: project.open_view_project_all_config_group_stage_kanban_action_view +NEW ir.actions.act_window.view: project.open_view_project_all_config_group_stage_tree_action_view +NEW ir.actions.act_window.view: project.project_all_task_activity_action_view +NEW ir.actions.act_window.view: project.project_all_task_calendar_action_view +NEW ir.actions.act_window.view: project.project_all_task_graph_action_view +NEW ir.actions.act_window.view: project.project_all_task_pivot_action_view +NEW ir.actions.act_window.view: project.project_sharing_subtasks_form_action_view +NEW ir.actions.act_window.view: project.project_sharing_subtasks_kanban_action_view +NEW ir.actions.act_window.view: project.project_sharing_subtasks_tree_action_view +NEW ir.actions.act_window.view: project.project_task_form_action_view +NEW ir.actions.act_window.view: project.project_task_kanban_action_view +NEW ir.actions.act_window.view: project.project_task_tree_action_view +NEW ir.actions.act_window.view: project.rating_rating_action_task_kanban +NEW ir.actions.act_window.view: project.rating_rating_action_view_project_rating_kanban +DEL ir.actions.server: project.unlink_project_action +NEW ir.model.access: project.access_project_task_burndown_chart_report_user +NEW ir.model.access: project.access_report_project_task_user_project_user +DEL ir.model.access: project.access_project_delete_wizard +NEW ir.rule: project.burndown_chart_project_manager_rule (noupdate) +NEW ir.rule: project.burndown_chart_project_user_rule (noupdate) +NEW ir.rule: project.report_project_task_manager_rule (noupdate) +NEW ir.rule: project.report_project_task_user_rule (noupdate) +NEW ir.ui.menu: project.menu_projects_config_group_stage +NEW ir.ui.view: project.rating_rating_project_view_kanban +NEW ir.ui.view: project.task_type_tree_inherited +NEW ir.ui.view: project.view_project_calendar +NEW ir.ui.view: project.view_project_config_kanban +NEW ir.ui.view: project.view_project_task_pivot_inherit +NEW ir.ui.view: project.view_project_task_type_unarchive_wizard +NEW ir.ui.view: project.view_task_all_calendar +NEW ir.ui.view: project.view_task_kanban_inherit_my_task +DEL ir.ui.view: pad_project.project_project_view_form +DEL ir.ui.view: pad_project.res_config_settings_view_form +DEL ir.ui.view: pad_project.view_task_form2_inherit_pad_project +DEL ir.ui.view: project.project_collaborator_view_form +DEL ir.ui.view: project.project_delete_wizard_form +DEL ir.ui.view: project.project_task_burndown_chart_report_view_pivot +NEW mail.message.subtype: project.mt_project_update_create (noupdate) +NEW mail.message.subtype: project.mt_task_progress (noupdate) +NEW mail.message.subtype: project.mt_update_create (noupdate) +NEW res.groups: project.group_project_milestone +# NOTHING TO DO