You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

196 lines
8.2 KiB

  1. ###################################################################################
  2. #
  3. # Copyright (c) 2017-2019 MuK IT GmbH.
  4. #
  5. # This file is part of MuK Search Panel
  6. # (see https://mukit.at).
  7. #
  8. # This program is free software: you can redistribute it and/or modify
  9. # it under the terms of the GNU Lesser General Public License as published by
  10. # the Free Software Foundation, either version 3 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU Lesser General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU Lesser General Public License
  19. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. #
  21. ###################################################################################
  22. import logging
  23. from odoo import _, api, fields, models
  24. from odoo.exceptions import UserError
  25. from odoo.osv import expression
  26. from odoo.tools import lazy
  27. _logger = logging.getLogger(__name__)
  28. class Base(models.AbstractModel):
  29. _inherit = 'base'
  30. #----------------------------------------------------------
  31. # Functions
  32. #----------------------------------------------------------
  33. @api.model
  34. def search_panel_select_range(self, field_name, **kwargs):
  35. """
  36. Return possible values of the field field_name (case select="one")
  37. and the parent field (if any) used to hierarchize them.
  38. :param field_name: the name of a many2one category field
  39. :return: {
  40. 'parent_field': parent field on the comodel of field, or False
  41. 'values': array of dictionaries containing some info on the records
  42. available on the comodel of the field 'field_name'.
  43. The display name (and possibly parent_field) are fetched.
  44. }
  45. """
  46. field = self._fields[field_name]
  47. supported_types = ['many2one']
  48. if field.type not in supported_types:
  49. raise UserError(_('Only types %(supported_types)s are supported for category (found type %(field_type)s)') % ({
  50. 'supported_types': supported_types, 'field_type': field.type}))
  51. Comodel = self.env[field.comodel_name]
  52. fields = ['display_name']
  53. parent_name = Comodel._parent_name if Comodel._parent_name in Comodel._fields else False
  54. if parent_name:
  55. fields.append(parent_name)
  56. model_domain = expression.AND([
  57. kwargs.get('search_domain', []),
  58. kwargs.get('category_domain', []),
  59. kwargs.get('filter_domain', []),
  60. ])
  61. return {
  62. 'parent_field': parent_name,
  63. 'values': Comodel.with_context(hierarchical_naming=False).search_read(model_domain, fields),
  64. }
  65. @api.model
  66. def search_panel_select_multi_range(self, field_name, **kwargs):
  67. """
  68. Return possible values of the field field_name (case select="multi"),
  69. possibly with counters and groups.
  70. :param field_name: the name of a filter field;
  71. possible types are many2one, many2many, selection.
  72. :param search_domain: base domain of search
  73. :param category_domain: domain generated by categories
  74. :param filter_domain: domain generated by filters
  75. :param comodel_domain: domain of field values (if relational)
  76. :param group_by: extra field to read on comodel, to group comodel records
  77. :param disable_counters: whether to count records by value
  78. :return: a list of possible values, each being a dict with keys
  79. 'id' (value),
  80. 'name' (value label),
  81. 'count' (how many records with that value),
  82. 'group_id' (value of group),
  83. 'group_name' (label of group).
  84. """
  85. field = self._fields[field_name]
  86. supported_types = ['many2one', 'many2many', 'selection']
  87. if field.type not in supported_types:
  88. raise UserError(_('Only types %(supported_types)s are supported for filter (found type %(field_type)s)') % ({
  89. 'supported_types': supported_types, 'field_type': field.type}))
  90. Comodel = self.env.get(field.comodel_name)
  91. model_domain = expression.AND([
  92. kwargs.get('search_domain', []),
  93. kwargs.get('category_domain', []),
  94. kwargs.get('filter_domain', []),
  95. [(field_name, '!=', False)],
  96. ])
  97. comodel_domain = kwargs.get('comodel_domain', [])
  98. disable_counters = kwargs.get('disable_counters', False)
  99. group_by = kwargs.get('group_by', False)
  100. if group_by:
  101. # determine the labeling of values returned by the group_by field
  102. group_by_field = Comodel._fields[group_by]
  103. if group_by_field.type == 'many2one':
  104. def group_id_name(value):
  105. return value or (False, _("Not Set"))
  106. elif group_by_field.type == 'selection':
  107. desc = Comodel.fields_get([group_by])[group_by]
  108. group_by_selection = dict(desc['selection'])
  109. group_by_selection[False] = _("Not Set")
  110. def group_id_name(value):
  111. return value, group_by_selection[value]
  112. else:
  113. def group_id_name(value):
  114. return (value, value) if value else (False, _("Not Set"))
  115. # get filter_values
  116. filter_values = []
  117. if field.type == 'many2one':
  118. counters = {}
  119. if not disable_counters:
  120. groups = self.read_group(model_domain, [field_name], [field_name])
  121. counters = {
  122. group[field_name][0]: group[field_name + '_count']
  123. for group in groups
  124. }
  125. # retrieve all possible values, and return them with their label and counter
  126. field_names = ['display_name', group_by] if group_by else ['display_name']
  127. records = Comodel.search_read(comodel_domain, field_names)
  128. for record in records:
  129. record_id = record['id']
  130. values = {
  131. 'id': record_id,
  132. 'name': record['display_name'],
  133. 'count': counters.get(record_id, 0),
  134. }
  135. if group_by:
  136. values['group_id'], values['group_name'] = group_id_name(record[group_by])
  137. filter_values.append(values)
  138. elif field.type == 'many2many':
  139. # retrieve all possible values, and return them with their label and counter
  140. field_names = ['display_name', group_by] if group_by else ['display_name']
  141. records = Comodel.search_read(comodel_domain, field_names)
  142. for record in records:
  143. record_id = record['id']
  144. values = {
  145. 'id': record_id,
  146. 'name': record['display_name'],
  147. 'count': 0,
  148. }
  149. if not disable_counters:
  150. count_domain = expression.AND([model_domain, [(field_name, 'in', record_id)]])
  151. values['count'] = self.search_count(count_domain)
  152. if group_by:
  153. values['group_id'], values['group_name'] = group_id_name(record[group_by])
  154. filter_values.append(values)
  155. elif field.type == 'selection':
  156. counters = {}
  157. if not disable_counters:
  158. groups = self.read_group(model_domain, [field_name], [field_name])
  159. counters = {
  160. group[field_name]: group[field_name + '_count']
  161. for group in groups
  162. }
  163. # retrieve all possible values, and return them with their label and counter
  164. selection = self.fields_get([field_name])[field_name]
  165. for value, label in selection:
  166. filter_values.append({
  167. 'id': value,
  168. 'name': label,
  169. 'count': counters.get(value, 0),
  170. })
  171. return filter_values