|
@ -1,31 +1,13 @@ |
|
|
# -*- coding: utf-8 -*- |
|
|
# -*- coding: utf-8 -*- |
|
|
'''Define model res.partner.relation''' |
|
|
|
|
|
############################################################################## |
|
|
|
|
|
# |
|
|
|
|
|
# OpenERP, Open Source Management Solution |
|
|
|
|
|
# This module copyright (C) 2013 Therp BV (<http://therp.nl>). |
|
|
|
|
|
# |
|
|
|
|
|
# This program is free software: you can redistribute it and/or modify |
|
|
|
|
|
# it under the terms of the GNU Affero General Public License as |
|
|
|
|
|
# published by the Free Software Foundation, either version 3 of the |
|
|
|
|
|
# License, or (at your option) any later version. |
|
|
|
|
|
# |
|
|
|
|
|
# This program is distributed in the hope that it will be useful, |
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
|
|
|
# GNU Affero General Public License for more details. |
|
|
|
|
|
# |
|
|
|
|
|
# You should have received a copy of the GNU Affero General Public License |
|
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
|
|
|
|
# |
|
|
|
|
|
############################################################################## |
|
|
|
|
|
|
|
|
# © 2013-2017 Therp BV <http://therp.nl>. |
|
|
|
|
|
# License AGPL-3.0 or later <http://www.gnu.org/licenses/agpl.html>. |
|
|
from openerp.osv.orm import Model, except_orm |
|
|
from openerp.osv.orm import Model, except_orm |
|
|
from openerp.osv import fields |
|
|
from openerp.osv import fields |
|
|
from openerp.tools.translate import _ |
|
|
from openerp.tools.translate import _ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ResPartnerRelation(Model): |
|
|
class ResPartnerRelation(Model): |
|
|
'''Model res.partner.relation is used to describe all links or relations |
|
|
|
|
|
|
|
|
"""Model res.partner.relation is used to describe all links or relations |
|
|
between partners in the database. |
|
|
between partners in the database. |
|
|
|
|
|
|
|
|
In many parts of the code we have to know whether the active partner is |
|
|
In many parts of the code we have to know whether the active partner is |
|
@ -35,23 +17,14 @@ class ResPartnerRelation(Model): |
|
|
Because the active partner is crucial for the working of partner |
|
|
Because the active partner is crucial for the working of partner |
|
|
relationships, we make sure on the res.partner model that the partner id |
|
|
relationships, we make sure on the res.partner model that the partner id |
|
|
is set in the context where needed. |
|
|
is set in the context where needed. |
|
|
''' |
|
|
|
|
|
|
|
|
""" |
|
|
_name = 'res.partner.relation' |
|
|
_name = 'res.partner.relation' |
|
|
_description = 'Partner relation' |
|
|
_description = 'Partner relation' |
|
|
_order = 'active desc, date_start desc, date_end desc' |
|
|
_order = 'active desc, date_start desc, date_end desc' |
|
|
|
|
|
|
|
|
def _on_right_partner(self, cr, uid, right_partner_id, context=None): |
|
|
|
|
|
'''Determine wether functions are called in a situation where the |
|
|
|
|
|
active partner is the right partner. Default False! |
|
|
|
|
|
''' |
|
|
|
|
|
if (context and 'active_ids' in context and |
|
|
|
|
|
right_partner_id in context.get('active_ids', [])): |
|
|
|
|
|
return True |
|
|
|
|
|
return False |
|
|
|
|
|
|
|
|
|
|
|
def _correct_vals(self, cr, uid, vals, context=None): |
|
|
def _correct_vals(self, cr, uid, vals, context=None): |
|
|
'''Fill type and left and right partner id, according to wether |
|
|
|
|
|
we have a normal relation type or an inverse relation type''' |
|
|
|
|
|
|
|
|
"""Fill type and left and right partner id, according to wether |
|
|
|
|
|
we have a normal relation type or an inverse relation type""" |
|
|
vals = vals.copy() |
|
|
vals = vals.copy() |
|
|
# If type_selection_id ends in 1, it is a reverse relation type |
|
|
# If type_selection_id ends in 1, it is a reverse relation type |
|
|
if 'type_selection_id' in vals: |
|
|
if 'type_selection_id' in vals: |
|
@ -75,13 +48,16 @@ class ResPartnerRelation(Model): |
|
|
|
|
|
|
|
|
def _get_computed_fields( |
|
|
def _get_computed_fields( |
|
|
self, cr, uid, ids, field_names, arg, context=None): |
|
|
self, cr, uid, ids, field_names, arg, context=None): |
|
|
'''Return a dictionary of dictionaries, with for every partner for |
|
|
|
|
|
ids, the computed values.''' |
|
|
|
|
|
|
|
|
"""Return a dictionary of dictionaries, with for every partner for |
|
|
|
|
|
ids, the computed values.""" |
|
|
def get_values(self, dummy_field_names, dummy_arg, context=None): |
|
|
def get_values(self, dummy_field_names, dummy_arg, context=None): |
|
|
'''Get computed values for record''' |
|
|
|
|
|
|
|
|
"""Get computed values for record""" |
|
|
values = {} |
|
|
values = {} |
|
|
on_right_partner = self._on_right_partner( |
|
|
|
|
|
cr, uid, self.right_partner_id.id, context=context) |
|
|
|
|
|
|
|
|
on_right_partner = ( |
|
|
|
|
|
'active_ids' in context and |
|
|
|
|
|
self.right_partner_id.id in context.get('active_ids', []) or |
|
|
|
|
|
False |
|
|
|
|
|
) |
|
|
# type_selection_id |
|
|
# type_selection_id |
|
|
values['type_selection_id'] = ( |
|
|
values['type_selection_id'] = ( |
|
|
((self.type_id.id) * 10) + (on_right_partner and 1 or 0)) |
|
|
((self.type_id.id) * 10) + (on_right_partner and 1 or 0)) |
|
@ -99,26 +75,27 @@ class ResPartnerRelation(Model): |
|
|
values['is_relation_future'] = self.date_start > today |
|
|
values['is_relation_future'] = self.date_start > today |
|
|
return values |
|
|
return values |
|
|
|
|
|
|
|
|
|
|
|
context = context or {} |
|
|
return dict([ |
|
|
return dict([ |
|
|
(i.id, get_values(i, field_names, arg, context=context)) |
|
|
(i.id, get_values(i, field_names, arg, context=context)) |
|
|
for i in self.browse(cr, uid, ids, context=context) |
|
|
for i in self.browse(cr, uid, ids, context=context) |
|
|
]) |
|
|
]) |
|
|
|
|
|
|
|
|
def write(self, cr, uid, ids, vals, context=None): |
|
|
def write(self, cr, uid, ids, vals, context=None): |
|
|
'''Override write to correct values, before being stored.''' |
|
|
|
|
|
|
|
|
"""Override write to correct values, before being stored.""" |
|
|
vals = self._correct_vals(cr, uid, vals, context=context) |
|
|
vals = self._correct_vals(cr, uid, vals, context=context) |
|
|
return super(ResPartnerRelation, self).write( |
|
|
return super(ResPartnerRelation, self).write( |
|
|
cr, uid, ids, vals, context=context) |
|
|
cr, uid, ids, vals, context=context) |
|
|
|
|
|
|
|
|
def create(self, cr, uid, vals, context=None): |
|
|
def create(self, cr, uid, vals, context=None): |
|
|
'''Override create to correct values, before being stored.''' |
|
|
|
|
|
|
|
|
"""Override create to correct values, before being stored.""" |
|
|
vals = self._correct_vals(cr, uid, vals, context=context) |
|
|
vals = self._correct_vals(cr, uid, vals, context=context) |
|
|
return super(ResPartnerRelation, self).create( |
|
|
return super(ResPartnerRelation, self).create( |
|
|
cr, uid, vals, context=context) |
|
|
cr, uid, vals, context=context) |
|
|
|
|
|
|
|
|
def on_change_type_selection_id( |
|
|
def on_change_type_selection_id( |
|
|
self, cr, uid, dummy_ids, type_selection_id, context=None): |
|
|
self, cr, uid, dummy_ids, type_selection_id, context=None): |
|
|
'''Set domain on partner_id_display, when selection a relation type''' |
|
|
|
|
|
|
|
|
"""Set domain on partner_id_display, when selection a relation type""" |
|
|
result = { |
|
|
result = { |
|
|
'domain': {'partner_id_display': []}, |
|
|
'domain': {'partner_id_display': []}, |
|
|
'value': {'type_id': False} |
|
|
'value': {'type_id': False} |
|
@ -198,13 +175,12 @@ class ResPartnerRelation(Model): |
|
|
), |
|
|
), |
|
|
'active': fields.boolean('Active'), |
|
|
'active': fields.boolean('Active'), |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
_defaults = { |
|
|
_defaults = { |
|
|
'active': True, |
|
|
'active': True, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
def _check_dates(self, cr, uid, ids, context=None): |
|
|
def _check_dates(self, cr, uid, ids, context=None): |
|
|
'''End date should not be before start date, if noth filled''' |
|
|
|
|
|
|
|
|
"""End date should not be before start date, if noth filled""" |
|
|
for line in self.browse(cr, uid, ids, context=context): |
|
|
for line in self.browse(cr, uid, ids, context=context): |
|
|
if line.date_start and line.date_end: |
|
|
if line.date_start and line.date_end: |
|
|
if line.date_start > line.date_end: |
|
|
if line.date_start > line.date_end: |
|
@ -212,7 +188,7 @@ class ResPartnerRelation(Model): |
|
|
return True |
|
|
return True |
|
|
|
|
|
|
|
|
def _check_partner_type_left(self, cr, uid, ids, context=None): |
|
|
def _check_partner_type_left(self, cr, uid, ids, context=None): |
|
|
'''Check left partner for required company or person''' |
|
|
|
|
|
|
|
|
"""Check left partner for required company or person""" |
|
|
for this in self.browse(cr, uid, ids, context=context): |
|
|
for this in self.browse(cr, uid, ids, context=context): |
|
|
ptype = this.type_id.contact_type_left |
|
|
ptype = this.type_id.contact_type_left |
|
|
company = this.left_partner_id.is_company |
|
|
company = this.left_partner_id.is_company |
|
@ -221,7 +197,7 @@ class ResPartnerRelation(Model): |
|
|
return True |
|
|
return True |
|
|
|
|
|
|
|
|
def _check_partner_type_right(self, cr, uid, ids, context=None): |
|
|
def _check_partner_type_right(self, cr, uid, ids, context=None): |
|
|
'''Check right partner for required company or person''' |
|
|
|
|
|
|
|
|
"""Check right partner for required company or person""" |
|
|
for this in self.browse(cr, uid, ids, context=context): |
|
|
for this in self.browse(cr, uid, ids, context=context): |
|
|
ptype = this.type_id.contact_type_right |
|
|
ptype = this.type_id.contact_type_right |
|
|
company = this.right_partner_id.is_company |
|
|
company = this.right_partner_id.is_company |
|
@ -230,15 +206,15 @@ class ResPartnerRelation(Model): |
|
|
return True |
|
|
return True |
|
|
|
|
|
|
|
|
def _check_not_with_self(self, cr, uid, ids, context=None): |
|
|
def _check_not_with_self(self, cr, uid, ids, context=None): |
|
|
'''Not allowed to link partner to same partner''' |
|
|
|
|
|
|
|
|
"""Not allowed to link partner to same partner""" |
|
|
for this in self.browse(cr, uid, ids, context=context): |
|
|
for this in self.browse(cr, uid, ids, context=context): |
|
|
if this.left_partner_id == this.right_partner_id: |
|
|
if this.left_partner_id == this.right_partner_id: |
|
|
return False |
|
|
return False |
|
|
return True |
|
|
return True |
|
|
|
|
|
|
|
|
def _check_relation_uniqueness(self, cr, uid, ids, context=None): |
|
|
def _check_relation_uniqueness(self, cr, uid, ids, context=None): |
|
|
'''Forbid multiple active relations of the same type between the same |
|
|
|
|
|
partners''' |
|
|
|
|
|
|
|
|
"""Forbid multiple active relations of the same type between the same |
|
|
|
|
|
partners""" |
|
|
for this in self.browse(cr, uid, ids, context=context): |
|
|
for this in self.browse(cr, uid, ids, context=context): |
|
|
if not this.active: |
|
|
if not this.active: |
|
|
continue |
|
|
continue |
|
@ -250,17 +226,21 @@ class ResPartnerRelation(Model): |
|
|
('right_partner_id', '=', this.right_partner_id.id), |
|
|
('right_partner_id', '=', this.right_partner_id.id), |
|
|
] |
|
|
] |
|
|
if this.date_start: |
|
|
if this.date_start: |
|
|
domain += ['|', ('date_end', '=', False), |
|
|
|
|
|
('date_end', '>=', this.date_start)] |
|
|
|
|
|
|
|
|
domain += [ |
|
|
|
|
|
'|', ('date_end', '=', False), |
|
|
|
|
|
('date_end', '>=', this.date_start), |
|
|
|
|
|
] |
|
|
if this.date_end: |
|
|
if this.date_end: |
|
|
domain += ['|', ('date_start', '=', False), |
|
|
|
|
|
('date_start', '<=', this.date_end)] |
|
|
|
|
|
|
|
|
domain += [ |
|
|
|
|
|
'|', ('date_start', '=', False), |
|
|
|
|
|
('date_start', '<=', this.date_end), |
|
|
|
|
|
] |
|
|
if self.search(cr, uid, domain, context=context): |
|
|
if self.search(cr, uid, domain, context=context): |
|
|
raise except_orm( |
|
|
raise except_orm( |
|
|
_('Overlapping relation'), |
|
|
_('Overlapping relation'), |
|
|
_('There is already a similar relation ' |
|
|
_('There is already a similar relation ' |
|
|
'with overlapping dates')) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
'with overlapping dates') |
|
|
|
|
|
) |
|
|
return True |
|
|
return True |
|
|
|
|
|
|
|
|
_constraints = [ |
|
|
_constraints = [ |
|
@ -292,12 +272,13 @@ class ResPartnerRelation(Model): |
|
|
] |
|
|
] |
|
|
|
|
|
|
|
|
def get_action_related_partners(self, cr, uid, ids, context=None): |
|
|
def get_action_related_partners(self, cr, uid, ids, context=None): |
|
|
'''return a window action showing a list of partners taking part in the |
|
|
|
|
|
|
|
|
"""return a window action showing a list of partners taking part in the |
|
|
relations names by ids. Context key 'partner_relations_show_side' |
|
|
relations names by ids. Context key 'partner_relations_show_side' |
|
|
determines if we show 'left' side, 'right' side or 'all' (default) |
|
|
determines if we show 'left' side, 'right' side or 'all' (default) |
|
|
partners. |
|
|
partners. |
|
|
If active_model is res.partner.relation.all, left=this and |
|
|
If active_model is res.partner.relation.all, left=this and |
|
|
right=other''' |
|
|
|
|
|
|
|
|
right=other |
|
|
|
|
|
""" |
|
|
if context is None: |
|
|
if context is None: |
|
|
context = {} |
|
|
context = {} |
|
|
|
|
|
|
|
|