################################################################################### # # Copyright (C) 2017 MuK IT GmbH # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # ################################################################################### import json import operator import functools import collections from odoo import models, fields, api class Hierarchy(models.AbstractModel): _name = 'muk_utils.mixins.hierarchy' _description = 'Hierarchy Mixin' _parent_store = True _parent_path_sudo = False #---------------------------------------------------------- # Database #---------------------------------------------------------- parent_path = fields.Char( string="Parent Path", index=True) @api.model def _add_magic_fields(self): super(Hierarchy, self)._add_magic_fields() def add(name, field): if name not in self._fields: self._add_field(name, field) add('parent_path_names', fields.Char( _module=self._module, compute='_compute_parent_path', compute_sudo=self._parent_path_sudo, string="Path Names", readonly=True, store=True, automatic=True)) add('parent_path_json', fields.Text( _module=self._module, compute='_compute_parent_path', compute_sudo=self._parent_path_sudo, string="Path Json", readonly=True, store=True, automatic=True)) #---------------------------------------------------------- # Read, View #---------------------------------------------------------- @api.depends('parent_path') def _compute_parent_path(self): paths = [list(map(int, rec.parent_path.split('/')[:-1])) for rec in self] ids = set(functools.reduce(operator.concat, paths)) data = dict(self.browse(ids)._filter_access('read').name_get()) for record in self: path_names = [""] path_json = [] for id in reversed(list(map(int, record.parent_path.split('/')[:-1]))): if id not in data: break path_names.append(data[id]) path_json.append({ 'model': record._name, 'name': data[id], 'id': record.id, }) path_names.reverse() path_json.reverse() record.update({ 'parent_path_names': '/'.join(path_names), 'parent_path_json': json.dumps(path_json), }) #---------------------------------------------------------- # Create, Update, Delete #---------------------------------------------------------- @api.multi def write(self, vals): if self._rec_name_fallback() in vals: with self.env.norecompute(): res = super(Hierarchy, self).write(vals) domain = [('id', 'child_of', self.ids)] records = self.sudo().search(domain) records.modified(['parent_path']) if self.env.recompute and self.env.context.get('recompute', True): records.recompute() return res return super(Hierarchy, self).write(vals)