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
187 lines
6.7 KiB
# Copyright 2013-2017 Therp BV <http://therp.nl>
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
|
# pylint: disable=api-one-deprecated
|
|
"""Store relations (connections) between partners."""
|
|
from odoo import _, api, fields, models
|
|
from odoo.exceptions import ValidationError
|
|
|
|
|
|
class ResPartnerRelation(models.Model):
|
|
"""Model res.partner.relation is used to describe all links or relations
|
|
between partners in the database.
|
|
|
|
This model is actually only used to store the data. The model
|
|
res.partner.relation.all, based on a view that contains each record
|
|
two times, once for the normal relation, once for the inverse relation,
|
|
will be used to maintain the data.
|
|
"""
|
|
_name = 'res.partner.relation'
|
|
_description = 'Partner relation'
|
|
|
|
left_partner_id = fields.Many2one(
|
|
comodel_name='res.partner',
|
|
string='Source Partner',
|
|
required=True,
|
|
auto_join=True,
|
|
ondelete='cascade',
|
|
)
|
|
right_partner_id = fields.Many2one(
|
|
comodel_name='res.partner',
|
|
string='Destination Partner',
|
|
required=True,
|
|
auto_join=True,
|
|
ondelete='cascade',
|
|
)
|
|
type_id = fields.Many2one(
|
|
comodel_name='res.partner.relation.type',
|
|
string='Type',
|
|
required=True,
|
|
auto_join=True,
|
|
)
|
|
date_start = fields.Date('Starting date')
|
|
date_end = fields.Date('Ending date')
|
|
|
|
@api.model
|
|
def create(self, vals):
|
|
"""Override create to correct values, before being stored.
|
|
Check to make sure each unique relation stays unique"""
|
|
context = self.env.context
|
|
if 'left_partner_id' not in vals and context.get('active_id'):
|
|
vals['left_partner_id'] = context.get('active_id')
|
|
if not self.check_is_unique(vals):
|
|
raise ValidationError(_('Relation already exists!'))
|
|
return super(ResPartnerRelation, self).create(vals)
|
|
|
|
@api.model
|
|
def write(self, vals):
|
|
"""Check to make sure each unique relation stays unique"""
|
|
if not self.check_is_unique(vals):
|
|
raise ValidationError(_('Relation already exists!'))
|
|
return super(ResPartnerRelation, self).write(vals)
|
|
|
|
@api.constrains('date_start', 'date_end')
|
|
def _check_dates(self):
|
|
"""End date should not be before start date, if not filled
|
|
|
|
:raises ValidationError: When constraint is violated
|
|
"""
|
|
for record in self:
|
|
if (record.date_start and record.date_end and
|
|
record.date_start > record.date_end):
|
|
raise ValidationError(
|
|
_('The starting date cannot be after the ending date.')
|
|
)
|
|
|
|
@api.constrains('left_partner_id', 'type_id')
|
|
def _check_partner_left(self):
|
|
"""Check left partner for required company or person
|
|
|
|
:raises ValidationError: When constraint is violated
|
|
"""
|
|
self._check_partner("left")
|
|
|
|
@api.constrains('right_partner_id', 'type_id')
|
|
def _check_partner_right(self):
|
|
"""Check right partner for required company or person
|
|
|
|
:raises ValidationError: When constraint is violated
|
|
"""
|
|
self._check_partner("right")
|
|
|
|
@api.multi
|
|
def _check_partner(self, side):
|
|
"""Check partner for required company or person, and for category
|
|
|
|
:param str side: left or right
|
|
:raises ValidationError: When constraint is violated
|
|
"""
|
|
for record in self:
|
|
assert side in ['left', 'right']
|
|
ptype = getattr(record.type_id, "contact_type_%s" % side)
|
|
partner = getattr(record, '%s_partner_id' % side)
|
|
if ((ptype == 'c' and not partner.is_company) or
|
|
(ptype == 'p' and partner.is_company)):
|
|
raise ValidationError(
|
|
_('The %s partner is not applicable for this '
|
|
'relation type.') % side
|
|
)
|
|
category = getattr(record.type_id, "partner_category_%s" % side)
|
|
if category and category.id not in partner.category_id.ids:
|
|
raise ValidationError(
|
|
_('The %s partner does not have category %s.') %
|
|
(side, category.name)
|
|
)
|
|
|
|
@api.constrains('left_partner_id', 'right_partner_id')
|
|
def _check_not_with_self(self):
|
|
"""Not allowed to link partner to same partner
|
|
|
|
:raises ValidationError: When constraint is violated
|
|
"""
|
|
for record in self:
|
|
if record.left_partner_id == record.right_partner_id:
|
|
if not (record.type_id and record.type_id.allow_self):
|
|
raise ValidationError(
|
|
_('Partners cannot have a relation with themselves.')
|
|
)
|
|
|
|
@api.constrains(
|
|
'left_partner_id',
|
|
'type_id',
|
|
'right_partner_id',
|
|
'date_start',
|
|
'date_end',
|
|
)
|
|
def _check_relation_uniqueness(self):
|
|
"""Forbid multiple active relations of the same type between the same
|
|
partners
|
|
|
|
:raises ValidationError: When constraint is violated
|
|
"""
|
|
# pylint: disable=no-member
|
|
# pylint: disable=no-value-for-parameter
|
|
for record in self:
|
|
domain = [
|
|
('type_id', '=', record.type_id.id),
|
|
('id', '!=', record.id),
|
|
('left_partner_id', '=', record.left_partner_id.id),
|
|
('right_partner_id', '=', record.right_partner_id.id),
|
|
]
|
|
if record.date_start:
|
|
domain += [
|
|
'|',
|
|
('date_end', '=', False),
|
|
('date_end', '>=', record.date_start),
|
|
]
|
|
if record.date_end:
|
|
domain += [
|
|
'|',
|
|
('date_start', '=', False),
|
|
('date_start', '<=', record.date_end),
|
|
]
|
|
if record.search(domain):
|
|
raise ValidationError(
|
|
_('There is already a similar relation with '
|
|
'overlapping dates')
|
|
)
|
|
|
|
@api.multi
|
|
def check_is_unique(self, vals):
|
|
if 'type_id' in vals:
|
|
type_id = vals['type_id']
|
|
else:
|
|
type_id = self.type_id.id
|
|
type_rec = self.env['res.partner.relation.type'].\
|
|
search([('id', '=', type_id)])
|
|
if 'right_partner_id' in vals:
|
|
right = vals['right_partner_id']
|
|
else:
|
|
right = self.right_partner_id.id
|
|
res = self.search([('type_id', '=', type_id),
|
|
('right_partner_id', '=', right)])
|
|
if (type_rec.is_unique and len(res) > 0):
|
|
return False
|
|
for rec in res:
|
|
if rec.type_id.is_unique:
|
|
return False
|
|
return True
|