diff --git a/upgrade_analysis/__init__.py b/upgrade_analysis/__init__.py index abe0f8c3c..338ffe995 100644 --- a/upgrade_analysis/__init__.py +++ b/upgrade_analysis/__init__.py @@ -1,3 +1,4 @@ +from . import odoo_patch from . import models from . import wizards from . import blacklist diff --git a/upgrade_analysis/blacklist.py b/upgrade_analysis/blacklist.py index 814396ad6..41943d6fb 100644 --- a/upgrade_analysis/blacklist.py +++ b/upgrade_analysis/blacklist.py @@ -1,7 +1,10 @@ -BLACKLIST_MODULES = [ - # the hw_* modules are not affected by a migration as they don't - # contain any ORM functionality, but they do start up threads that - # delay the process and spit out annoying log messages continously. - "hw_escpos", - "hw_proxy", -] +BLACKLIST_MODULES = [] + +# the hw_* modules are not affected by a migration as they don't +# contain any ORM functionality, but they do start up threads that +# delay the process and spit out annoying log messages continously. + +# We also don't want to analyze tests modules +BLACKLIST_MODULES_STARTS_WITH = ["hw_", "test_"] + +BLACKLIST_MODULES_ENDS_WITH = ["_test"] diff --git a/upgrade_analysis/models/__init__.py b/upgrade_analysis/models/__init__.py index 748d5aee0..e0245a184 100644 --- a/upgrade_analysis/models/__init__.py +++ b/upgrade_analysis/models/__init__.py @@ -1,3 +1,4 @@ +from . import ir_module_module from . import upgrade_comparison_config from . import upgrade_attribute from . import upgrade_record diff --git a/upgrade_analysis/models/ir_module_module.py b/upgrade_analysis/models/ir_module_module.py new file mode 100644 index 000000000..9456af708 --- /dev/null +++ b/upgrade_analysis/models/ir_module_module.py @@ -0,0 +1,35 @@ +# Copyright 2011-2015 Therp BV +# Copyright 2016 Opener B.V. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import os + +from odoo import fields, models +from odoo.modules import get_module_path + + +class UpgradeAttribute(models.Model): + _inherit = "ir.module.module" + + is_odoo_module = fields.Boolean( + compute="_compute_is_odoo_module", + ) + + is_oca_module = fields.Boolean(compute="_compute_is_oca_module") + + def _compute_is_oca_module(self): + for module in self: + if "/OCA/" in module.website: + module.is_oca_module = True + else: + module.is_oca_module = False + + def _compute_is_odoo_module(self): + for module in self: + module_path = get_module_path(module.name) + absolute_repo_path = os.path.split(module_path)[0] + x, relative_repo_path = os.path.split(absolute_repo_path) + if relative_repo_path == "addons": + module.is_odoo_module = True + else: + module.is_odoo_module = False diff --git a/upgrade_analysis/tests/__init__.py b/upgrade_analysis/tests/__init__.py new file mode 100644 index 000000000..d9b96c4fa --- /dev/null +++ b/upgrade_analysis/tests/__init__.py @@ -0,0 +1 @@ +from . import test_module diff --git a/upgrade_analysis/tests/test_module.py b/upgrade_analysis/tests/test_module.py new file mode 100644 index 000000000..85a66d9b7 --- /dev/null +++ b/upgrade_analysis/tests/test_module.py @@ -0,0 +1,46 @@ +from odoo.tests import common, tagged + + +@tagged("post_install", "-at_install") +class TestUpgradeAnalysis(common.TransactionCase): + def setUp(self): + super().setUp() + self.IrModuleModule = self.env["ir.module.module"] + self.product_module = self.IrModuleModule.search([("name", "=", "product")]) + self.sale_module = self.IrModuleModule.search([("name", "=", "sale")]) + self.upgrade_analysis = self.IrModuleModule.search( + [("name", "=", "upgrade_analysis")] + ) + + def test_upgrade_install_wizard(self): + InstallWizard = self.env["upgrade.install.wizard"] + wizard = InstallWizard.create({}) + + wizard.select_odoo_modules() + self.assertTrue( + self.product_module.id in wizard.module_ids.ids, + "Select Odoo module should select 'product' module", + ) + + wizard.select_oca_modules() + self.assertTrue( + self.upgrade_analysis.id in wizard.module_ids.ids, + "Select OCA module should select 'upgrade_analysis' module", + ) + + wizard.select_other_modules() + self.assertTrue( + self.product_module.id not in wizard.module_ids.ids, + "Select Other module should not select 'product' module", + ) + + wizard.unselect_modules() + self.assertEqual( + wizard.module_ids.ids, [], "Unselect module should clear the selection" + ) + # For the time being, tests doens't call install_modules() function + # because installing module in a test context will execute the test + # of the installed modules, raising finally an error: + + # TypeError: Many2many fields ir.actions.server.partner_ids and + # ir.actions.server.partner_ids use the same table and columns diff --git a/upgrade_analysis/views/menu.xml b/upgrade_analysis/views/menu.xml index 12d44779d..e12c75236 100644 --- a/upgrade_analysis/views/menu.xml +++ b/upgrade_analysis/views/menu.xml @@ -1,10 +1,9 @@ - diff --git a/upgrade_analysis/wizards/upgrade_generate_record_wizard.py b/upgrade_analysis/wizards/upgrade_generate_record_wizard.py index fc7f6c02f..439f6b2c2 100644 --- a/upgrade_analysis/wizards/upgrade_generate_record_wizard.py +++ b/upgrade_analysis/wizards/upgrade_generate_record_wizard.py @@ -95,7 +95,7 @@ class GenerateWizard(models.TransientModel): ) self.env.cache.invalidate( [ - (self.env["openupgrade.record"]._fields["noupdate"], None), + (self.env["upgrade.record"]._fields["noupdate"], None), ] ) diff --git a/upgrade_analysis/wizards/upgrade_install_wizard.py b/upgrade_analysis/wizards/upgrade_install_wizard.py index 4ea1d36b9..d91232867 100644 --- a/upgrade_analysis/wizards/upgrade_install_wizard.py +++ b/upgrade_analysis/wizards/upgrade_install_wizard.py @@ -6,7 +6,11 @@ from odoo import api, fields, models from odoo.modules.registry import Registry from odoo.osv.expression import AND -from ..blacklist import BLACKLIST_MODULES +from ..blacklist import ( + BLACKLIST_MODULES, + BLACKLIST_MODULES_ENDS_WITH, + BLACKLIST_MODULES_STARTS_WITH, +) class UpgradeInstallWizard(models.TransientModel): @@ -14,38 +18,87 @@ class UpgradeInstallWizard(models.TransientModel): _description = "Upgrade Install Wizard" state = fields.Selection( - [("init", "init"), ("ready", "ready")], readonly=True, default="init" + [("draft", "Draft"), ("done", "Done")], readonly=True, default="draft" + ) + + module_ids = fields.Many2many( + comodel_name="ir.module.module", + domain=lambda x: x._module_ids_domain(), + ) + + module_qty = fields.Integer( + string="Modules Quantity", compute="_compute_module_qty" ) - to_install = fields.Integer("Number of modules to install", readonly=True) @api.model - def default_get(self, fields): - """Update module list and retrieve the number - of installable modules""" - res = super().default_get(fields) - update, add = self.env["ir.module.module"].update_list() - modules = self.env["ir.module.module"].search( - [("state", "not in", ["uninstallable", "unknown"])] - ) - res["to_install"] = len(modules) - return res - - def install_all(self, extra_domain=None): - """Main wizard step. Set all installable modules to install - and actually install them. Exclude testing modules.""" + def _module_ids_domain(self, extra_domain=None): domain = [ - "&", "&", ("state", "not in", ["uninstallable", "unknown"]), - ("category_id.name", "!=", "Tests"), ("name", "not in", BLACKLIST_MODULES), ] if extra_domain: domain = AND([domain, extra_domain]) modules = self.env["ir.module.module"].search(domain) - if modules: - modules.write({"state": "to install"}) - self.env.cr.commit() # pylint: disable=invalid-commit - Registry.new(self.env.cr.dbname, update_module=True) - self.write({"state": "ready"}) - return True + + for start_pattern in BLACKLIST_MODULES_STARTS_WITH: + modules = modules.filtered(lambda x: not x.name.startswith(start_pattern)) + for end_pattern in BLACKLIST_MODULES_ENDS_WITH: + modules = modules.filtered(lambda x: not x.name.endswith(end_pattern)) + return [("id", "in", modules.ids)] + + @api.depends("module_ids") + def _compute_module_qty(self): + for wizard in self: + wizard.module_qty = len(wizard.module_ids) + + def select_odoo_modules(self): + self.ensure_one() + modules = self.env["ir.module.module"].search(self._module_ids_domain()) + modules = modules.filtered(lambda x: x.is_odoo_module) + self.module_ids = modules + return self.return_same_form_view() + + def select_oca_modules(self): + self.ensure_one() + modules = self.env["ir.module.module"].search(self._module_ids_domain()) + modules = modules.filtered(lambda x: x.is_oca_module) + self.module_ids = modules + return self.return_same_form_view() + + def select_other_modules(self): + self.ensure_one() + modules = self.env["ir.module.module"].search(self._module_ids_domain()) + modules = modules.filtered(lambda x: not (x.is_oca_module or x.is_odoo_module)) + self.module_ids = modules + return self.return_same_form_view() + + def select_installable_modules(self): + self.ensure_one() + self.module_ids = self.env["ir.module.module"].search(self._module_ids_domain()) + return self.return_same_form_view() + + def unselect_modules(self): + self.ensure_one() + self.module_ids = False + return self.return_same_form_view() + + def install_modules(self): + """Set all selected modules and actually install them.""" + self.ensure_one() + self.module_ids.write({"state": "to install"}) + self.env.cr.commit() # pylint: disable=invalid-commit + Registry.new(self.env.cr.dbname, update_module=True) + self.write({"state": "done"}) + return self.return_same_form_view() + + def return_same_form_view(self): + return { + "type": "ir.actions.act_window", + "res_model": "upgrade.install.wizard", + "view_mode": "form", + "view_type": "form", + "res_id": self.id, + "views": [(False, "form")], + "target": "new", + } diff --git a/upgrade_analysis/wizards/view_upgrade_generate_record_wizard.xml b/upgrade_analysis/wizards/view_upgrade_generate_record_wizard.xml index 86c620179..a0a310e74 100644 --- a/upgrade_analysis/wizards/view_upgrade_generate_record_wizard.xml +++ b/upgrade_analysis/wizards/view_upgrade_generate_record_wizard.xml @@ -28,7 +28,7 @@ - Generate Records + Generate Records Wizard ir.actions.act_window upgrade.generate.record.wizard form,tree @@ -36,7 +36,7 @@ upgrade.install.wizard
- - + +

This will install all modules on the database. Do not continue if you use this database in production.

- + class="alert alert-warning" + role="alert" + >This will install the selected modules on the database. Do not continue if you use this database in production.

- -

Modules installed

+ + + + +