diff --git a/muk_utils/__manifest__.py b/muk_utils/__manifest__.py index 3d30ee0..3ce9ea6 100644 --- a/muk_utils/__manifest__.py +++ b/muk_utils/__manifest__.py @@ -1,51 +1,51 @@ -################################################################################### -# -# Copyright (C) 2018 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 . -# -################################################################################### -{ - "name": "MuK Utils", - "summary": """Utility Features""", - "version": '12.0.1.4.11', - "category": 'Extra Tools', - "license": "AGPL-3", - "author": "MuK IT", - "website": "https://www.mukit.at", - 'live_test_url': 'https://mukit.at/r/SgN', - "contributors": [ - "Mathias Markl ", - ], - "depends": [ - "base_setup", - ], - "data": [ - "views/mixins_groups.xml", - "views/res_config_settings_view.xml", - ], - "qweb": [ - "static/src/xml/*.xml", - ], - "images": [ - 'static/description/banner.png' - ], - "external_dependencies": { - "python": [], - "bin": [], - }, - "application": False, - "installable": True, - "auto_install": False, -} +################################################################################### +# +# Copyright (C) 2018 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 . +# +################################################################################### +{ + "name": "MuK Utils", + "summary": """Utility Features""", + "version": '12.0.1.4.12', + "category": 'Extra Tools', + "license": "AGPL-3", + "author": "MuK IT", + "website": "https://www.mukit.at", + 'live_test_url': 'https://mukit.at/r/SgN', + "contributors": [ + "Mathias Markl ", + ], + "depends": [ + "base_setup", + ], + "data": [ + "views/mixins_groups.xml", + "views/res_config_settings_view.xml", + ], + "qweb": [ + "static/src/xml/*.xml", + ], + "images": [ + 'static/description/banner.png' + ], + "external_dependencies": { + "python": [], + "bin": [], + }, + "application": False, + "installable": True, + "auto_install": False, +} diff --git a/muk_utils/models/base.py b/muk_utils/models/base.py index ffadc18..07f5751 100644 --- a/muk_utils/models/base.py +++ b/muk_utils/models/base.py @@ -42,7 +42,7 @@ class Base(models.AbstractModel): def _build_search_childs_domain(self, parent_id, domain=[]): self._check_parent_field() parent_domain = [[self._parent_name, '=', parent_id]] - return expression.AND(parent_domain, domain) if domain else parent_domain + return expression.AND([parent_domain, domain]) if domain else parent_domain #---------------------------------------------------------- # Security diff --git a/muk_utils/models/mixins_hierarchy.py b/muk_utils/models/mixins_hierarchy.py index b3e68c0..b2b723b 100644 --- a/muk_utils/models/mixins_hierarchy.py +++ b/muk_utils/models/mixins_hierarchy.py @@ -1,128 +1,143 @@ -################################################################################### -# -# 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 - _parent_path_store = 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) - path_names_search = None - if not self._parent_path_store: - path_names_search = '_search_parent_path_names', - add('parent_path_names', fields.Char( - _module=self._module, - compute='_compute_parent_path', - compute_sudo=self._parent_path_sudo, - store=self._parent_path_store, - search=path_names_search, - string="Path Names", - readonly=True, - automatic=True)) - add('parent_path_json', fields.Text( - _module=self._module, - compute='_compute_parent_path', - compute_sudo=self._parent_path_sudo, - store=self._parent_path_store, - string="Path Json", - readonly=True, - automatic=True)) - - #---------------------------------------------------------- - # Search - #---------------------------------------------------------- - - @api.model - def _search_parent_path_names(self, operator, operand): - domain = [] - for value in operand.split('/'): - args = [(self._rec_name_fallback(), operator, value)] - domain = expression.OR(args, domain) if domain else args - return domain - - #---------------------------------------------------------- - # Read, View - #---------------------------------------------------------- - - @api.depends('parent_path') - def _compute_parent_path(self): - records = self.filtered(lambda record: record.parent_path) - paths = [list(map(int, rec.parent_path.split('/')[:-1])) for rec in records] - ids = paths and set(functools.reduce(operator.concat, paths)) or [] - data = dict(self.browse(ids)._filter_access('read').name_get()) - for record in records: - 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': 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._parent_path_store and 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) +################################################################################### +# +# 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 +from odoo.osv import expression + +class Hierarchy(models.AbstractModel): + + _name = 'muk_utils.mixins.hierarchy' + _description = 'Hierarchy Mixin' + + _parent_store = True + _parent_path_sudo = False + _parent_path_store = 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) + path_names_search = None + if not self._parent_path_store: + path_names_search = '_search_parent_path_names' + add('parent_path_names', fields.Char( + _module=self._module, + compute='_compute_parent_paths', + compute_sudo=self._parent_path_sudo, + store=self._parent_path_store, + search=path_names_search, + string="Path Names", + readonly=True, + automatic=True)) + add('parent_path_json', fields.Text( + _module=self._module, + compute='_compute_parent_paths', + compute_sudo=self._parent_path_sudo, + store=self._parent_path_store, + string="Path Json", + readonly=True, + automatic=True)) + + #---------------------------------------------------------- + # Helper + #---------------------------------------------------------- + + def _get_depends_parent_paths(self): + depends = ['parent_path'] + if self._rec_name: + depends += [self._rec_name] + elif 'name' in self._fields: + depends += ['name'] + elif 'x_name' in self._fields: + depends += ['x_name'] + return depends + + #---------------------------------------------------------- + # Search + #---------------------------------------------------------- + + @api.model + def _search_parent_path_names(self, operator, operand): + domain = [] + for value in operand.split('/'): + args = [(self._rec_name_fallback(), operator, value)] + domain = expression.OR([args, domain]) if domain else args + return domain if domain else [(self._rec_name_fallback(), operator, "")] + + #---------------------------------------------------------- + # Read, View + #---------------------------------------------------------- + + @api.depends(lambda self: self._get_depends_parent_paths()) + def _compute_parent_paths(self): + records = self.filtered(lambda record: record.parent_path) + paths = [list(map(int, rec.parent_path.split('/')[:-1])) for rec in records] + ids = paths and set(functools.reduce(operator.concat, paths)) or [] + data = dict(self.browse(ids)._filter_access('read').name_get()) + for record in records: + 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': 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._parent_path_store and 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) \ No newline at end of file