################################################################################### # # Copyright (c) 2017-2019 MuK IT GmbH. # # This file is part of MuK Search Panel # (see https://mukit.at). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser 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 Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # ################################################################################### import logging from odoo import _, api, fields, models from odoo.exceptions import UserError from odoo.osv import expression from odoo.tools import lazy _logger = logging.getLogger(__name__) class Base(models.AbstractModel): _inherit = 'base' #---------------------------------------------------------- # Functions #---------------------------------------------------------- @api.model def search_panel_select_range(self, field_name, **kwargs): """ Return possible values of the field field_name (case select="one") and the parent field (if any) used to hierarchize them. :param field_name: the name of a many2one category field :return: { 'parent_field': parent field on the comodel of field, or False 'values': array of dictionaries containing some info on the records available on the comodel of the field 'field_name'. The display name (and possibly parent_field) are fetched. } """ field = self._fields[field_name] supported_types = ['many2one'] if field.type not in supported_types: raise UserError(_('Only types %(supported_types)s are supported for category (found type %(field_type)s)') % ({ 'supported_types': supported_types, 'field_type': field.type})) Comodel = self.env[field.comodel_name] fields = ['display_name'] parent_name = Comodel._parent_name if Comodel._parent_name in Comodel._fields else False if parent_name: fields.append(parent_name) model_domain = expression.AND([ kwargs.get('search_domain', []), kwargs.get('category_domain', []), kwargs.get('filter_domain', []), ]) return { 'parent_field': parent_name, 'values': Comodel.with_context(hierarchical_naming=False).search_read(model_domain, fields), } @api.model def search_panel_select_multi_range(self, field_name, **kwargs): """ Return possible values of the field field_name (case select="multi"), possibly with counters and groups. :param field_name: the name of a filter field; possible types are many2one, many2many, selection. :param search_domain: base domain of search :param category_domain: domain generated by categories :param filter_domain: domain generated by filters :param comodel_domain: domain of field values (if relational) :param group_by: extra field to read on comodel, to group comodel records :param disable_counters: whether to count records by value :return: a list of possible values, each being a dict with keys 'id' (value), 'name' (value label), 'count' (how many records with that value), 'group_id' (value of group), 'group_name' (label of group). """ field = self._fields[field_name] supported_types = ['many2one', 'many2many', 'selection'] if field.type not in supported_types: raise UserError(_('Only types %(supported_types)s are supported for filter (found type %(field_type)s)') % ({ 'supported_types': supported_types, 'field_type': field.type})) Comodel = self.env.get(field.comodel_name) model_domain = expression.AND([ kwargs.get('search_domain', []), kwargs.get('category_domain', []), kwargs.get('filter_domain', []), [(field_name, '!=', False)], ]) comodel_domain = kwargs.get('comodel_domain', []) disable_counters = kwargs.get('disable_counters', False) group_by = kwargs.get('group_by', False) if group_by: # determine the labeling of values returned by the group_by field group_by_field = Comodel._fields[group_by] if group_by_field.type == 'many2one': def group_id_name(value): return value or (False, _("Not Set")) elif group_by_field.type == 'selection': desc = Comodel.fields_get([group_by])[group_by] group_by_selection = dict(desc['selection']) group_by_selection[False] = _("Not Set") def group_id_name(value): return value, group_by_selection[value] else: def group_id_name(value): return (value, value) if value else (False, _("Not Set")) # get filter_values filter_values = [] if field.type == 'many2one': counters = {} if not disable_counters: groups = self.read_group(model_domain, [field_name], [field_name]) counters = { group[field_name][0]: group[field_name + '_count'] for group in groups } # retrieve all possible values, and return them with their label and counter field_names = ['display_name', group_by] if group_by else ['display_name'] records = Comodel.search_read(comodel_domain, field_names) for record in records: record_id = record['id'] values = { 'id': record_id, 'name': record['display_name'], 'count': counters.get(record_id, 0), } if group_by: values['group_id'], values['group_name'] = group_id_name(record[group_by]) filter_values.append(values) elif field.type == 'many2many': # retrieve all possible values, and return them with their label and counter field_names = ['display_name', group_by] if group_by else ['display_name'] records = Comodel.search_read(comodel_domain, field_names) for record in records: record_id = record['id'] values = { 'id': record_id, 'name': record['display_name'], 'count': 0, } if not disable_counters: count_domain = expression.AND([model_domain, [(field_name, 'in', record_id)]]) values['count'] = self.search_count(count_domain) if group_by: values['group_id'], values['group_name'] = group_id_name(record[group_by]) filter_values.append(values) elif field.type == 'selection': counters = {} if not disable_counters: groups = self.read_group(model_domain, [field_name], [field_name]) counters = { group[field_name]: group[field_name + '_count'] for group in groups } # retrieve all possible values, and return them with their label and counter selection = self.fields_get([field_name])[field_name] for value, label in selection: filter_values.append({ 'id': value, 'name': label, 'count': counters.get(value, 0), }) return filter_values