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.

197 lines
7.2 KiB

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