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.

172 lines
6.0 KiB

  1. # -*- coding: utf-8 -*-
  2. # © 2013-2016 Therp BV <http://therp.nl>
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  4. """Support connections between partners."""
  5. import numbers
  6. from openerp import _, api, exceptions, fields, models
  7. from openerp.osv.expression import is_leaf, OR, FALSE_LEAF
  8. class ResPartner(models.Model):
  9. """Extend partner with relations and allow to search for relations
  10. in various ways.
  11. """
  12. # pylint: disable=invalid-name
  13. # pylint: disable=no-member
  14. _inherit = 'res.partner'
  15. relation_count = fields.Integer(
  16. string='Relation Count',
  17. compute="_compute_relation_count"
  18. )
  19. relation_all_ids = fields.One2many(
  20. comodel_name='res.partner.relation.all',
  21. inverse_name='this_partner_id',
  22. string='All relations with current partner',
  23. auto_join=True,
  24. selectable=False,
  25. copy=False,
  26. )
  27. search_relation_type_id = fields.Many2one(
  28. comodel_name='res.partner.relation.type.selection',
  29. compute=lambda self: None,
  30. search='_search_relation_type_id',
  31. string='Has relation of type',
  32. )
  33. search_relation_partner_id = fields.Many2one(
  34. comodel_name='res.partner',
  35. compute=lambda self: None,
  36. search='_search_related_partner_id',
  37. string='Has relation with',
  38. )
  39. search_relation_date = fields.Date(
  40. compute=lambda self: None,
  41. search='_search_relation_date',
  42. string='Relation valid',
  43. )
  44. search_relation_partner_category_id = fields.Many2one(
  45. comodel_name='res.partner.category',
  46. compute=lambda self: None,
  47. search='_search_related_partner_category_id',
  48. string='Has relation with a partner in category',
  49. )
  50. @api.depends("relation_all_ids")
  51. def _compute_relation_count(self):
  52. """Count the number of relations this partner has for Smart Button
  53. Don't count inactive relations.
  54. """
  55. for rec in self:
  56. rec.relation_count = len(rec.relation_all_ids.filtered('active'))
  57. @api.model
  58. def _search_relation_type_id(self, operator, value):
  59. """Search partners based on their type of relations."""
  60. result = []
  61. SUPPORTED_OPERATORS = (
  62. '=',
  63. '!=',
  64. 'like',
  65. 'not like',
  66. 'ilike',
  67. 'not ilike',
  68. 'in',
  69. 'not in',
  70. )
  71. if operator not in SUPPORTED_OPERATORS:
  72. raise exceptions.ValidationError(
  73. _('Unsupported search operator "%s"') % operator)
  74. type_selection_model = self.env['res.partner.relation.type.selection']
  75. relation_type_selection = []
  76. if operator == '=' and isinstance(value, numbers.Integral):
  77. relation_type_selection += type_selection_model.browse(value)
  78. elif operator == '!=' and isinstance(value, numbers.Integral):
  79. relation_type_selection = type_selection_model.search([
  80. ('id', operator, value),
  81. ])
  82. else:
  83. relation_type_selection = type_selection_model.search([
  84. '|',
  85. ('type_id.name', operator, value),
  86. ('type_id.name_inverse', operator, value),
  87. ])
  88. if not relation_type_selection:
  89. result = [FALSE_LEAF]
  90. for relation_type in relation_type_selection:
  91. result = OR([
  92. result,
  93. [
  94. ('relation_all_ids.type_selection_id.id', '=',
  95. relation_type.id),
  96. ],
  97. ])
  98. return result
  99. @api.model
  100. def _search_related_partner_id(self, operator, value):
  101. """Find partner based on relation with other partner."""
  102. # pylint: disable=no-self-use
  103. return [
  104. ('relation_all_ids.other_partner_id', operator, value),
  105. ]
  106. @api.model
  107. def _search_relation_date(self, operator, value):
  108. """Look only for relations valid at date of search."""
  109. # pylint: disable=no-self-use
  110. return [
  111. '&',
  112. '|',
  113. ('relation_all_ids.date_start', '=', False),
  114. ('relation_all_ids.date_start', '<=', value),
  115. '|',
  116. ('relation_all_ids.date_end', '=', False),
  117. ('relation_all_ids.date_end', '>=', value),
  118. ]
  119. @api.model
  120. def _search_related_partner_category_id(self, operator, value):
  121. """Search for partner related to a partner with search category."""
  122. # pylint: disable=no-self-use
  123. return [
  124. ('relation_all_ids.other_partner_id.category_id', operator, value),
  125. ]
  126. @api.model
  127. def search(self, args, offset=0, limit=None, order=None, count=False):
  128. """Inject searching for current relation date if we search for
  129. relation properties and no explicit date was given.
  130. """
  131. # pylint: disable=arguments-differ
  132. # pylint: disable=no-value-for-parameter
  133. date_args = []
  134. for arg in args:
  135. if is_leaf(arg) and arg[0].startswith('search_relation'):
  136. if arg[0] == 'search_relation_date':
  137. date_args = []
  138. break
  139. if not date_args:
  140. date_args = [
  141. ('search_relation_date', '=', fields.Date.today()),
  142. ]
  143. # because of auto_join, we have to do the active test by hand
  144. active_args = []
  145. if self.env.context.get('active_test', True):
  146. for arg in args:
  147. if is_leaf(arg) and arg[0].startswith('search_relation'):
  148. active_args = [('relation_all_ids.active', '=', True)]
  149. break
  150. return super(ResPartner, self).search(
  151. args + date_args + active_args, offset=offset, limit=limit,
  152. order=order, count=count)
  153. @api.multi
  154. def get_partner_type(self):
  155. """Get partner type for relation.
  156. :return: 'c' for company or 'p' for person
  157. :rtype: str
  158. """
  159. self.ensure_one()
  160. return 'c' if self.is_company else 'p'