diff options
| -rw-r--r-- | addons/mail/wizard/__init__.py | 1 | ||||
| -rw-r--r-- | addons/mail/wizard/base_module_uninstall.py | 13 | ||||
| -rw-r--r-- | odoo/addons/base/__manifest__.py | 1 | ||||
| -rw-r--r-- | odoo/addons/base/ir/ir_model.py | 11 | ||||
| -rw-r--r-- | odoo/addons/base/module/module.py | 12 | ||||
| -rw-r--r-- | odoo/addons/base/module/module_view.xml | 2 | ||||
| -rw-r--r-- | odoo/addons/base/module/wizard/__init__.py | 1 | ||||
| -rw-r--r-- | odoo/addons/base/module/wizard/base_module_uninstall.py | 55 | ||||
| -rw-r--r-- | odoo/addons/base/module/wizard/base_module_uninstall_view.xml | 52 |
9 files changed, 147 insertions, 1 deletions
diff --git a/addons/mail/wizard/__init__.py b/addons/mail/wizard/__init__.py index 2181ffa8266..2523a3593b0 100644 --- a/addons/mail/wizard/__init__.py +++ b/addons/mail/wizard/__init__.py @@ -4,3 +4,4 @@ from . import invite from . import mail_compose_message from . import email_template_preview +from . import base_module_uninstall diff --git a/addons/mail/wizard/base_module_uninstall.py b/addons/mail/wizard/base_module_uninstall.py new file mode 100644 index 00000000000..43e029ba851 --- /dev/null +++ b/addons/mail/wizard/base_module_uninstall.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import models + + +class BaseModuleUninstall(models.TransientModel): + _inherit = "base.module.uninstall" + + def _get_models(self): + # consider mail-thread models only + models = super(BaseModuleUninstall, self)._get_models() + return models.filtered('is_mail_thread') diff --git a/odoo/addons/base/__manifest__.py b/odoo/addons/base/__manifest__.py index 8f8f585473c..be3a4b6af25 100644 --- a/odoo/addons/base/__manifest__.py +++ b/odoo/addons/base/__manifest__.py @@ -46,6 +46,7 @@ The kernel of Odoo, needed for all installation. 'module/wizard/base_language_install_view.xml', 'module/wizard/base_import_language_view.xml', 'module/wizard/base_module_upgrade_view.xml', + 'module/wizard/base_module_uninstall_view.xml', 'module/wizard/base_export_language_view.xml', 'module/wizard/base_update_translations_view.xml', 'module/wizard/base_module_immediate_install.xml', diff --git a/odoo/addons/base/ir/ir_model.py b/odoo/addons/base/ir/ir_model.py index 4ce65a210c2..31828750dfe 100644 --- a/odoo/addons/base/ir/ir_model.py +++ b/odoo/addons/base/ir/ir_model.py @@ -97,6 +97,8 @@ class IrModel(models.Model): transient = fields.Boolean(string="Transient Model") modules = fields.Char(compute='_in_modules', string='In Apps', help='List of modules in which the object is defined or inherited') view_ids = fields.One2many('ir.ui.view', compute='_view_ids', string='Views') + count = fields.Integer(compute='_compute_count', string="Count (incl. archived)", + help="Total number of records in this model") @api.depends() def _inherited_models(self): @@ -119,6 +121,15 @@ class IrModel(models.Model): for model in self: model.view_ids = self.env['ir.ui.view'].search([('model', '=', model.model)]) + @api.depends() + def _compute_count(self): + cr = self.env.cr + for model in self: + records = self.env[model.model] + if not records._abstract: + cr.execute('SELECT COUNT(*) FROM "%s"' % records._table) + model.count = cr.fetchone()[0] + @api.constrains('model') def _check_model_name(self): for model in self: diff --git a/odoo/addons/base/module/module.py b/odoo/addons/base/module/module.py index bfc018f247f..3ded39fb128 100644 --- a/odoo/addons/base/module/module.py +++ b/odoo/addons/base/module/module.py @@ -535,6 +535,18 @@ class Module(models.Model): return dict(ACTION_DICT, name=_('Uninstall')) @api.multi + def button_uninstall_wizard(self): + """ Launch the wizard to uninstall the given module. """ + return { + 'type': 'ir.actions.act_window', + 'target': 'new', + 'name': _('Uninstall module'), + 'view_mode': 'form', + 'res_model': 'base.module.uninstall', + 'context': {'default_module_id': self.id}, + } + + @api.multi def button_uninstall_cancel(self): self.write({'state': 'installed'}) return True diff --git a/odoo/addons/base/module/module_view.xml b/odoo/addons/base/module/module_view.xml index 338cb723980..d0e842b5e3e 100644 --- a/odoo/addons/base/module/module_view.xml +++ b/odoo/addons/base/module/module_view.xml @@ -82,7 +82,7 @@ <div> <button name="button_immediate_install" states="uninstalled" string="Install" type="object" class="btn btn-primary"/> <button name="button_immediate_upgrade" states="installed" string="Upgrade" type="object" class="btn btn-primary"/> - <button name="button_uninstall" states="installed" string="Uninstall" type="object" class="btn btn-default"/> + <button name="button_uninstall_wizard" states="installed" string="Uninstall" type="object" class="btn btn-default"/> <button name="button_uninstall_cancel" states="to remove" string="Cancel Uninstall" type="object" class="btn btn-default"/> <button name="button_upgrade_cancel" states="to upgrade" string="Cancel Upgrade" type="object" class="btn btn-default"/> <button name="button_install_cancel" states="to install" string="Cancel Install" type="object" class="btn btn-default"/> diff --git a/odoo/addons/base/module/wizard/__init__.py b/odoo/addons/base/module/wizard/__init__.py index 72162359952..ece1521da87 100644 --- a/odoo/addons/base/module/wizard/__init__.py +++ b/odoo/addons/base/module/wizard/__init__.py @@ -5,5 +5,6 @@ from . import base_module_update from . import base_language_install from . import base_import_language from . import base_module_upgrade +from . import base_module_uninstall from . import base_export_language from . import base_update_translations diff --git a/odoo/addons/base/module/wizard/base_module_uninstall.py b/odoo/addons/base/module/wizard/base_module_uninstall.py new file mode 100644 index 00000000000..1168e57341c --- /dev/null +++ b/odoo/addons/base/module/wizard/base_module_uninstall.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import api, fields, models + + +class BaseModuleUninstall(models.TransientModel): + _name = "base.module.uninstall" + _description = "Module Uninstallation" + + show_all = fields.Boolean() + module_id = fields.Many2one('ir.module.module', string="Module", required=True, + domain=[('state', 'in', ['installed', 'to upgrade', 'to install'])]) + module_ids = fields.Many2many('ir.module.module', string="Impacted modules", + compute='_compute_module_ids') + model_ids = fields.Many2many('ir.model', string="Impacted data models", + compute='_compute_model_ids') + + def _get_modules(self): + """ Return all the modules impacted by self. """ + return self.module_id.downstream_dependencies(self.module_id) + + @api.depends('module_id', 'show_all') + def _compute_module_ids(self): + for wizard in self: + modules = wizard._get_modules() + wizard.module_ids = modules if wizard.show_all else modules.filtered('application') + + def _get_models(self): + """ Return the models (ir.model) to consider for the impact. """ + return self.env['ir.model'].search([('transient', '=', False)]) + + @api.depends('module_ids') + def _compute_model_ids(self): + ir_models = self._get_models() + ir_models_xids = ir_models._get_external_ids() + for wizard in self: + if wizard.module_id: + module_names = set(wizard._get_modules().mapped('name')) + # find the models that have all their XIDs in the given modules + def lost(model): + return all(xid.split('.')[0] in module_names + for xid in ir_models_xids.get(model.id, ())) + self.model_ids = ir_models.filtered(lost).sorted('name') + + @api.onchange('module_id') + def _onchange_module_id(self): + # if we select a technical module, show technical modules by default + if not self.module_id.application: + self.show_all = True + + @api.multi + def action_uninstall(self): + modules = self.mapped('module_id') + return modules.button_immediate_uninstall() diff --git a/odoo/addons/base/module/wizard/base_module_uninstall_view.xml b/odoo/addons/base/module/wizard/base_module_uninstall_view.xml new file mode 100644 index 00000000000..43da6a2bcde --- /dev/null +++ b/odoo/addons/base/module/wizard/base_module_uninstall_view.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <data> + + <record id="view_base_module_uninstall" model="ir.ui.view"> + <field name="name">Uninstall module</field> + <field name="model">base.module.uninstall</field> + <field name="arch" type="xml"> + <form string="Uninstall module"> + <field name="module_id" groups="base.group_no_one"/> + <h3>The following apps will be uninstalled</h3> + <field name="show_all"/> Show technical modules + <field name="module_ids" mode="kanban"> + <kanban create="false"> + <field name="icon"/> + <field name="name"/> + <field name="shortdesc"/> + <field name="summary"/> + <templates> + <t t-name="kanban-box"> + <div class="oe_module_vignette"> + <img t-attf-src="#{record.icon.value}" + class="oe_module_icon" style="width: 60px; height: 60px"/> + <div class="oe_module_desc" style="padding-left: 70px"> + <h4><field name="shortdesc"/></h4> + <p class="oe_module_name"> + <t t-if="record.summary.raw_value"><field name="summary"/><br/></t> + <i><field name="name" groups="base.group_no_one"/></i> + </p> + </div> + </div> + </t> + </templates> + </kanban> + </field> + <h3>The following documents will be permanently lost</h3> + <field name="model_ids"> + <tree string="Models"> + <field name="name" string="Document"/> + <field name="count"/> + </tree> + </field> + <footer> + <button string="Confirm" class="btn-primary" type="object" name="action_uninstall"/> + <button string="Cancel" class="btn-default" special="cancel"/> + </footer> + </form> + </field> + </record> + + </data> +</odoo> |
