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.

187 lines
6.7 KiB

  1. # Copyright 2013-2017 Therp BV <http://therp.nl>
  2. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  3. # pylint: disable=api-one-deprecated
  4. """Store relations (connections) between partners."""
  5. from odoo import _, api, fields, models
  6. from odoo.exceptions import ValidationError
  7. class ResPartnerRelation(models.Model):
  8. """Model res.partner.relation is used to describe all links or relations
  9. between partners in the database.
  10. This model is actually only used to store the data. The model
  11. res.partner.relation.all, based on a view that contains each record
  12. two times, once for the normal relation, once for the inverse relation,
  13. will be used to maintain the data.
  14. """
  15. _name = 'res.partner.relation'
  16. _description = 'Partner relation'
  17. left_partner_id = fields.Many2one(
  18. comodel_name='res.partner',
  19. string='Source Partner',
  20. required=True,
  21. auto_join=True,
  22. ondelete='cascade',
  23. )
  24. right_partner_id = fields.Many2one(
  25. comodel_name='res.partner',
  26. string='Destination Partner',
  27. required=True,
  28. auto_join=True,
  29. ondelete='cascade',
  30. )
  31. type_id = fields.Many2one(
  32. comodel_name='res.partner.relation.type',
  33. string='Type',
  34. required=True,
  35. auto_join=True,
  36. )
  37. date_start = fields.Date('Starting date')
  38. date_end = fields.Date('Ending date')
  39. @api.model
  40. def create(self, vals):
  41. """Override create to correct values, before being stored.
  42. Check to make sure each unique relation stays unique"""
  43. context = self.env.context
  44. if 'left_partner_id' not in vals and context.get('active_id'):
  45. vals['left_partner_id'] = context.get('active_id')
  46. if not self.check_is_unique(vals):
  47. raise ValidationError(_('Relation already exists!'))
  48. return super(ResPartnerRelation, self).create(vals)
  49. @api.model
  50. def write(self, vals):
  51. """Check to make sure each unique relation stays unique"""
  52. if not self.check_is_unique(vals):
  53. raise ValidationError(_('Relation already exists!'))
  54. return super(ResPartnerRelation, self).write(vals)
  55. @api.constrains('date_start', 'date_end')
  56. def _check_dates(self):
  57. """End date should not be before start date, if not filled
  58. :raises ValidationError: When constraint is violated
  59. """
  60. for record in self:
  61. if (record.date_start and record.date_end and
  62. record.date_start > record.date_end):
  63. raise ValidationError(
  64. _('The starting date cannot be after the ending date.')
  65. )
  66. @api.constrains('left_partner_id', 'type_id')
  67. def _check_partner_left(self):
  68. """Check left partner for required company or person
  69. :raises ValidationError: When constraint is violated
  70. """
  71. self._check_partner("left")
  72. @api.constrains('right_partner_id', 'type_id')
  73. def _check_partner_right(self):
  74. """Check right partner for required company or person
  75. :raises ValidationError: When constraint is violated
  76. """
  77. self._check_partner("right")
  78. @api.multi
  79. def _check_partner(self, side):
  80. """Check partner for required company or person, and for category
  81. :param str side: left or right
  82. :raises ValidationError: When constraint is violated
  83. """
  84. for record in self:
  85. assert side in ['left', 'right']
  86. ptype = getattr(record.type_id, "contact_type_%s" % side)
  87. partner = getattr(record, '%s_partner_id' % side)
  88. if ((ptype == 'c' and not partner.is_company) or
  89. (ptype == 'p' and partner.is_company)):
  90. raise ValidationError(
  91. _('The %s partner is not applicable for this '
  92. 'relation type.') % side
  93. )
  94. category = getattr(record.type_id, "partner_category_%s" % side)
  95. if category and category.id not in partner.category_id.ids:
  96. raise ValidationError(
  97. _('The %s partner does not have category %s.') %
  98. (side, category.name)
  99. )
  100. @api.constrains('left_partner_id', 'right_partner_id')
  101. def _check_not_with_self(self):
  102. """Not allowed to link partner to same partner
  103. :raises ValidationError: When constraint is violated
  104. """
  105. for record in self:
  106. if record.left_partner_id == record.right_partner_id:
  107. if not (record.type_id and record.type_id.allow_self):
  108. raise ValidationError(
  109. _('Partners cannot have a relation with themselves.')
  110. )
  111. @api.constrains(
  112. 'left_partner_id',
  113. 'type_id',
  114. 'right_partner_id',
  115. 'date_start',
  116. 'date_end',
  117. )
  118. def _check_relation_uniqueness(self):
  119. """Forbid multiple active relations of the same type between the same
  120. partners
  121. :raises ValidationError: When constraint is violated
  122. """
  123. # pylint: disable=no-member
  124. # pylint: disable=no-value-for-parameter
  125. for record in self:
  126. domain = [
  127. ('type_id', '=', record.type_id.id),
  128. ('id', '!=', record.id),
  129. ('left_partner_id', '=', record.left_partner_id.id),
  130. ('right_partner_id', '=', record.right_partner_id.id),
  131. ]
  132. if record.date_start:
  133. domain += [
  134. '|',
  135. ('date_end', '=', False),
  136. ('date_end', '>=', record.date_start),
  137. ]
  138. if record.date_end:
  139. domain += [
  140. '|',
  141. ('date_start', '=', False),
  142. ('date_start', '<=', record.date_end),
  143. ]
  144. if record.search(domain):
  145. raise ValidationError(
  146. _('There is already a similar relation with '
  147. 'overlapping dates')
  148. )
  149. @api.multi
  150. def check_is_unique(self, vals):
  151. if 'type_id' in vals:
  152. type_id = vals['type_id']
  153. else:
  154. type_id = self.type_id.id
  155. type_rec = self.env['res.partner.relation.type'].\
  156. search([('id', '=', type_id)])
  157. if 'right_partner_id' in vals:
  158. right = vals['right_partner_id']
  159. else:
  160. right = self.right_partner_id.id
  161. res = self.search([('type_id', '=', type_id),
  162. ('right_partner_id', '=', right)])
  163. if (type_rec.is_unique and len(res) > 0):
  164. return False
  165. for rec in res:
  166. if rec.type_id.is_unique:
  167. return False
  168. return True