diff --git a/odoo/addons/base/__manifest__.py b/odoo/addons/base/__manifest__.py index 99f634350e2..27844454c0c 100644 --- a/odoo/addons/base/__manifest__.py +++ b/odoo/addons/base/__manifest__.py @@ -57,6 +57,7 @@ The kernel of Odoo, needed for all installation. 'wizard/base_update_translations_views.xml', 'wizard/base_partner_merge_views.xml', 'data/ir_actions_data.xml', + 'data/ir_demo_failure_data.xml', 'views/res_company_views.xml', 'views/res_lang_views.xml', 'views/res_partner_views.xml', diff --git a/odoo/addons/base/data/ir_demo_failure_data.xml b/odoo/addons/base/data/ir_demo_failure_data.xml new file mode 100644 index 00000000000..c3afb3f1f9a --- /dev/null +++ b/odoo/addons/base/data/ir_demo_failure_data.xml @@ -0,0 +1,51 @@ + + + Failed to install demo data for some modules, demo disabled + + code + +failures = env['ir.demo_failure'].search([ + ('wizard_id', '=', False), +]) +record = model.create({ + 'failure_ids': [(6, 0, failures.ids)], +}) +action = { + 'type': 'ir.actions.act_window', + 'res_id': record.id, + 'res_model': 'ir.demo_failure.wizard', + 'target': 'new', + 'views': [(env.ref('base.demo_failures_dialog').id, 'form')], +} + + + + + Demo Failure Dialog + ir.demo_failure.wizard + +
+

+ The demonstration data of + module(s) failed to install and were disabled +

+ + + + + + +
+
+
+
+
+ + + Demo Failure Notification + 1 + done + + +
diff --git a/odoo/addons/base/models/__init__.py b/odoo/addons/base/models/__init__.py index 4506929a5c5..e29a0938007 100644 --- a/odoo/addons/base/models/__init__.py +++ b/odoo/addons/base/models/__init__.py @@ -28,6 +28,7 @@ from . import ir_logging from . import ir_property from . import ir_module from . import ir_demo +from . import ir_demo_failure from . import report_paperformat from . import res_country from . import res_lang diff --git a/odoo/addons/base/models/ir_actions.py b/odoo/addons/base/models/ir_actions.py index f770b667c27..5403990ea24 100644 --- a/odoo/addons/base/models/ir_actions.py +++ b/odoo/addons/base/models/ir_actions.py @@ -661,17 +661,18 @@ class IrActionsTodo(models.Model): return super(IrActionsTodo, self)._name_search(name, args=args, operator=operator, limit=limit, name_get_uid=name_get_uid) @api.multi - def action_launch(self, context=None): + def action_launch(self): """ Launch Action of Wizard""" self.ensure_one() self.write({'state': 'done'}) # Load action - action = self.env[self.action_id.type].browse(self.action_id.id) + action_type = self.action_id.type + action = self.env[action_type].browse(self.action_id.id) result = action.read()[0] - if action._name != 'ir.actions.act_window': + if action_type != 'ir.actions.act_window': return result result.setdefault('context', '{}') diff --git a/odoo/addons/base/models/ir_demo_failure.py b/odoo/addons/base/models/ir_demo_failure.py new file mode 100644 index 00000000000..8a7396fa99d --- /dev/null +++ b/odoo/addons/base/models/ir_demo_failure.py @@ -0,0 +1,29 @@ +from odoo import api, fields, models + + +class DemoFailure(models.TransientModel): + """ Stores modules for which we could not install demo data + """ + _name = 'ir.demo_failure' + + module_id = fields.Many2one('ir.module.module', required=True, string="Module") + error = fields.Char(string="Error") + wizard_id = fields.Many2one('ir.demo_failure.wizard') + +class DemoFailureWizard(models.TransientModel): + _name = 'ir.demo_failure.wizard' + + failure_ids = fields.One2many( + 'ir.demo_failure', 'wizard_id', readonly=True, + string="Demo Installation Failures" + ) + failures_count = fields.Integer(compute='_compute_failures_count') + + @api.depends('failure_ids') + def _compute_failures_count(self): + for r in self: + r.failures_count = len(r.failure_ids) + + def done(self): + # pylint: disable=next-method-called + return self.env['ir.module.module'].next() diff --git a/odoo/addons/base/models/ir_module.py b/odoo/addons/base/models/ir_module.py index d61d7321912..4c2afe54876 100644 --- a/odoo/addons/base/models/ir_module.py +++ b/odoo/addons/base/models/ir_module.py @@ -516,7 +516,7 @@ class Module(models.Model): _logger.info('getting next %s', Todos) active_todo = Todos.search([('state', '=', 'open')], limit=1) if active_todo: - _logger.info('next action is %s', active_todo) + _logger.info('next action is "%s"', active_todo.name) return active_todo.action_launch() return { 'type': 'ir.actions.act_url', diff --git a/odoo/modules/graph.py b/odoo/modules/graph.py index 0f2e329fab9..33846fbd1ec 100644 --- a/odoo/modules/graph.py +++ b/odoo/modules/graph.py @@ -176,3 +176,17 @@ class Node(object): for c in self.children: s += '%s`-> %s' % (' ' * depth, c._pprint(depth+1)) return s + + def should_have_demo(self): + return (hasattr(self, 'demo') or (self.dbdemo and self.state != 'installed')) and all(p.dbdemo for p in self.parents) + + @property + def parents(self): + if self.depth == 0: + return [] + + return ( + node for node in self.graph.values() + if node.depth < self.depth + if self in node.children + ) diff --git a/odoo/modules/loading.py b/odoo/modules/loading.py index f9a41c9161b..af4ed28ca59 100644 --- a/odoo/modules/loading.py +++ b/odoo/modules/loading.py @@ -75,10 +75,27 @@ def load_demo(cr, package, idref, mode, report=None): """ Loads demo data for the specified package. """ - has_demo = hasattr(package, 'demo') or (package.dbdemo and package.state != 'installed') - if has_demo: - load_data(cr, idref, mode, kind='demo', package=package, report=report) - return has_demo + if not package.should_have_demo(): + return False + + try: + _logger.info("Module %s: loading demo", package.name) + with cr.savepoint(): + load_data(cr, idref, mode, kind='demo', package=package, report=report) + return True + except Exception as e: + # If we could not install demo data for this module + _logger.warning( + "Module %s demo data failed to install, installed without demo data", + package.name, exc_info=True) + + env = api.Environment(cr, SUPERUSER_ID, {}) + todo = env.ref('base.demo_failure_todo', raise_if_not_found=False) + Failure = env.get('ir.demo_failure') + if todo and Failure is not None: + todo.state = 'open' + Failure.create({'module_id': package.id, 'error': str(e)}) + return False def force_demo(cr): @@ -205,10 +222,9 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, # upgrading the module information module.write(module.get_values_from_terp(package.data)) load_data(cr, idref, mode, kind='data', package=package, report=report) - demo_loaded = load_demo(cr, package, idref, mode, report) - if demo_loaded: - cr.execute('update ir_module_module set demo=%s where id=%s', (True, module_id)) - module.invalidate_cache(['demo']) + demo_loaded = package.dbdemo = load_demo(cr, package, idref, mode, report) + cr.execute('update ir_module_module set demo=%s where id=%s', (demo_loaded, module_id)) + module.invalidate_cache(['demo']) migrations.migrate_module(package, 'post')