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.

213 lines
7.1 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. import numbers
  5. from openerp import _, models, fields, exceptions, api
  6. from openerp.osv.expression import is_leaf, OR, FALSE_LEAF
  7. PADDING = 10
  8. class ResPartner(models.Model):
  9. _inherit = 'res.partner'
  10. relation_count = fields.Integer(
  11. 'Relation Count',
  12. compute="_compute_relation_count"
  13. )
  14. relation_ids = fields.One2many(
  15. 'res.partner.relation', string='Relations',
  16. compute='_compute_relation_ids',
  17. selectable=False,
  18. )
  19. relation_all_ids = fields.One2many(
  20. 'res.partner.relation.all', 'this_partner_id',
  21. string='All relations with current partner',
  22. auto_join=True, selectable=False, copy=False,
  23. )
  24. search_relation_id = fields.Many2one(
  25. 'res.partner.relation.type.selection', compute=lambda self: None,
  26. search='_search_relation_id', string='Has relation of type',
  27. )
  28. search_relation_partner_id = fields.Many2one(
  29. 'res.partner', compute=lambda self: None,
  30. search='_search_related_partner_id', string='Has relation with',
  31. )
  32. search_relation_date = fields.Date(
  33. compute=lambda self: None, search='_search_relation_date',
  34. string='Relation valid',
  35. )
  36. search_relation_partner_category_id = fields.Many2one(
  37. 'res.partner.category', compute=lambda self: None,
  38. search='_search_related_partner_category_id',
  39. string='Has relation with a partner in category',
  40. )
  41. @api.one
  42. @api.depends("relation_ids")
  43. def _compute_relation_count(self):
  44. """Count the number of relations this partner has for Smart Button
  45. Don't count inactive relations.
  46. """
  47. self.relation_count = len([r for r in self.relation_ids if r.active])
  48. @api.multi
  49. def _compute_relation_ids(self):
  50. '''getter for relation_ids'''
  51. self.env.cr.execute(
  52. "select p.id, array_agg(r.id) "
  53. "from res_partner p join res_partner_relation r "
  54. "on r.left_partner_id=p.id or r.right_partner_id=p.id "
  55. "where p.id in %s "
  56. "group by p.id",
  57. (tuple(self.ids),)
  58. )
  59. partner2relation = dict(self.env.cr.fetchall())
  60. for this in self:
  61. this.relation_ids += self.env['res.partner.relation'].browse(
  62. partner2relation.get(this.id, []),
  63. )
  64. @api.model
  65. def _search_relation_id(self, operator, value):
  66. result = []
  67. if operator not in [
  68. '=', '!=', 'like', 'not like', 'ilike', 'not ilike', 'in', 'not in'
  69. ]:
  70. raise exceptions.ValidationError(
  71. _('Unsupported search operator "%s"') % operator)
  72. relation_type_selection = []
  73. if operator == '=' and isinstance(value, numbers.Integral):
  74. relation_type_selection += self\
  75. .env['res.partner.relation.type.selection']\
  76. .browse(value)
  77. elif operator == '!=' and isinstance(value, numbers.Integral):
  78. relation_type_selection = self\
  79. .env['res.partner.relation.type.selection']\
  80. .search([
  81. ('id', operator, value),
  82. ])
  83. else:
  84. relation_type_selection = self\
  85. .env['res.partner.relation.type.selection']\
  86. .search([
  87. ('type_id.name', operator, value),
  88. ])
  89. if not relation_type_selection:
  90. result = [FALSE_LEAF]
  91. for relation_type in relation_type_selection:
  92. type_id, is_inverse = relation_type.get_type_from_selection_id()
  93. result = OR([
  94. result,
  95. [
  96. '&',
  97. ('relation_all_ids.type_id', '=', type_id),
  98. (
  99. 'relation_all_ids.record_type', 'in',
  100. ['a', 'b']
  101. if relation_type.type_id.symmetric
  102. else
  103. (['b'] if is_inverse else ['a'])
  104. )
  105. ],
  106. ])
  107. return result
  108. @api.model
  109. def _search_related_partner_id(self, operator, value):
  110. return [
  111. ('relation_all_ids.other_partner_id', operator, value),
  112. ]
  113. @api.model
  114. def _search_relation_date(self, operator, value):
  115. if operator != '=':
  116. raise exceptions.ValidationError(
  117. _('Unsupported search operator "%s"') % operator)
  118. return [
  119. '&',
  120. '|',
  121. ('relation_all_ids.date_start', '=', False),
  122. ('relation_all_ids.date_start', '<=', value),
  123. '|',
  124. ('relation_all_ids.date_end', '=', False),
  125. ('relation_all_ids.date_end', '>=', value),
  126. ]
  127. @api.model
  128. def _search_related_partner_category_id(self, operator, value):
  129. return [
  130. ('relation_all_ids.other_partner_id.category_id', operator, value),
  131. ]
  132. @api.model
  133. def search(self, args, offset=0, limit=None, order=None, count=False):
  134. # inject searching for current relation date if we search for relation
  135. # properties and no explicit date was given
  136. date_args = []
  137. for arg in args:
  138. if is_leaf(arg) and arg[0].startswith('search_relation'):
  139. if arg[0] == 'search_relation_date':
  140. date_args = []
  141. break
  142. if not date_args:
  143. date_args = [
  144. ('search_relation_date', '=', fields.Date.today()),
  145. ]
  146. # because of auto_join, we have to do the active test by hand
  147. active_args = []
  148. if self.env.context.get('active_test', True):
  149. for arg in args:
  150. if is_leaf(arg) and arg[0].startswith('search_relation'):
  151. active_args = [('relation_all_ids.active', '=', True)]
  152. break
  153. return super(ResPartner, self).search(
  154. args + date_args + active_args, offset=offset, limit=limit,
  155. order=order, count=count)
  156. @api.multi
  157. def read(self, fields=None, load='_classic_read'):
  158. return super(ResPartner, self.with_partner_relations_context())\
  159. .read(fields=fields, load=load)
  160. @api.multi
  161. def write(self, vals):
  162. return super(ResPartner, self.with_partner_relations_context())\
  163. .write(vals)
  164. @api.multi
  165. def with_partner_relations_context(self):
  166. context = dict(self.env.context)
  167. if context.get('active_model', self._name) == self._name:
  168. existing = self.exists()
  169. context.setdefault(
  170. 'active_id', existing.ids[0] if existing.ids else None)
  171. context.setdefault('active_ids', existing.ids)
  172. context.setdefault('active_model', self._name)
  173. return self.with_context(context)
  174. @api.multi
  175. def get_partner_type(self):
  176. """Get partner type for relation.
  177. :return: 'c' for company or 'p' for person
  178. :rtype: str
  179. """
  180. self.ensure_one()
  181. return 'c' if self.is_company else 'p'