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
213 lines
7.1 KiB
# -*- coding: utf-8 -*-
|
|
# © 2013-2016 Therp BV <http://therp.nl>
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
|
import numbers
|
|
from openerp import _, models, fields, exceptions, api
|
|
from openerp.osv.expression import is_leaf, OR, FALSE_LEAF
|
|
|
|
PADDING = 10
|
|
|
|
|
|
class ResPartner(models.Model):
|
|
_inherit = 'res.partner'
|
|
|
|
relation_count = fields.Integer(
|
|
'Relation Count',
|
|
compute="_compute_relation_count"
|
|
)
|
|
|
|
relation_ids = fields.One2many(
|
|
'res.partner.relation', string='Relations',
|
|
compute='_compute_relation_ids',
|
|
selectable=False,
|
|
)
|
|
|
|
relation_all_ids = fields.One2many(
|
|
'res.partner.relation.all', 'this_partner_id',
|
|
string='All relations with current partner',
|
|
auto_join=True, selectable=False, copy=False,
|
|
)
|
|
|
|
search_relation_id = fields.Many2one(
|
|
'res.partner.relation.type.selection', compute=lambda self: None,
|
|
search='_search_relation_id', string='Has relation of type',
|
|
)
|
|
|
|
search_relation_partner_id = fields.Many2one(
|
|
'res.partner', compute=lambda self: None,
|
|
search='_search_related_partner_id', string='Has relation with',
|
|
)
|
|
|
|
search_relation_date = fields.Date(
|
|
compute=lambda self: None, search='_search_relation_date',
|
|
string='Relation valid',
|
|
)
|
|
|
|
search_relation_partner_category_id = fields.Many2one(
|
|
'res.partner.category', compute=lambda self: None,
|
|
search='_search_related_partner_category_id',
|
|
string='Has relation with a partner in category',
|
|
)
|
|
|
|
@api.one
|
|
@api.depends("relation_ids")
|
|
def _compute_relation_count(self):
|
|
"""Count the number of relations this partner has for Smart Button
|
|
|
|
Don't count inactive relations.
|
|
"""
|
|
self.relation_count = len([r for r in self.relation_ids if r.active])
|
|
|
|
@api.multi
|
|
def _compute_relation_ids(self):
|
|
'''getter for relation_ids'''
|
|
self.env.cr.execute(
|
|
"select p.id, array_agg(r.id) "
|
|
"from res_partner p join res_partner_relation r "
|
|
"on r.left_partner_id=p.id or r.right_partner_id=p.id "
|
|
"where p.id in %s "
|
|
"group by p.id",
|
|
(tuple(self.ids),)
|
|
)
|
|
partner2relation = dict(self.env.cr.fetchall())
|
|
for this in self:
|
|
this.relation_ids += self.env['res.partner.relation'].browse(
|
|
partner2relation.get(this.id, []),
|
|
)
|
|
|
|
@api.model
|
|
def _search_relation_id(self, operator, value):
|
|
result = []
|
|
|
|
if operator not in [
|
|
'=', '!=', 'like', 'not like', 'ilike', 'not ilike', 'in', 'not in'
|
|
]:
|
|
raise exceptions.ValidationError(
|
|
_('Unsupported search operator "%s"') % operator)
|
|
|
|
relation_type_selection = []
|
|
|
|
if operator == '=' and isinstance(value, numbers.Integral):
|
|
relation_type_selection += self\
|
|
.env['res.partner.relation.type.selection']\
|
|
.browse(value)
|
|
elif operator == '!=' and isinstance(value, numbers.Integral):
|
|
relation_type_selection = self\
|
|
.env['res.partner.relation.type.selection']\
|
|
.search([
|
|
('id', operator, value),
|
|
])
|
|
else:
|
|
relation_type_selection = self\
|
|
.env['res.partner.relation.type.selection']\
|
|
.search([
|
|
('type_id.name', operator, value),
|
|
])
|
|
|
|
if not relation_type_selection:
|
|
result = [FALSE_LEAF]
|
|
|
|
for relation_type in relation_type_selection:
|
|
type_id, is_inverse = relation_type.get_type_from_selection_id()
|
|
|
|
result = OR([
|
|
result,
|
|
[
|
|
'&',
|
|
('relation_all_ids.type_id', '=', type_id),
|
|
(
|
|
'relation_all_ids.record_type', 'in',
|
|
['a', 'b']
|
|
if relation_type.type_id.symmetric
|
|
else
|
|
(['b'] if is_inverse else ['a'])
|
|
)
|
|
],
|
|
])
|
|
|
|
return result
|
|
|
|
@api.model
|
|
def _search_related_partner_id(self, operator, value):
|
|
return [
|
|
('relation_all_ids.other_partner_id', operator, value),
|
|
]
|
|
|
|
@api.model
|
|
def _search_relation_date(self, operator, value):
|
|
if operator != '=':
|
|
raise exceptions.ValidationError(
|
|
_('Unsupported search operator "%s"') % operator)
|
|
|
|
return [
|
|
'&',
|
|
'|',
|
|
('relation_all_ids.date_start', '=', False),
|
|
('relation_all_ids.date_start', '<=', value),
|
|
'|',
|
|
('relation_all_ids.date_end', '=', False),
|
|
('relation_all_ids.date_end', '>=', value),
|
|
]
|
|
|
|
@api.model
|
|
def _search_related_partner_category_id(self, operator, value):
|
|
return [
|
|
('relation_all_ids.other_partner_id.category_id', operator, value),
|
|
]
|
|
|
|
@api.model
|
|
def search(self, args, offset=0, limit=None, order=None, count=False):
|
|
# inject searching for current relation date if we search for relation
|
|
# properties and no explicit date was given
|
|
date_args = []
|
|
for arg in args:
|
|
if is_leaf(arg) and arg[0].startswith('search_relation'):
|
|
if arg[0] == 'search_relation_date':
|
|
date_args = []
|
|
break
|
|
if not date_args:
|
|
date_args = [
|
|
('search_relation_date', '=', fields.Date.today()),
|
|
]
|
|
|
|
# because of auto_join, we have to do the active test by hand
|
|
active_args = []
|
|
if self.env.context.get('active_test', True):
|
|
for arg in args:
|
|
if is_leaf(arg) and arg[0].startswith('search_relation'):
|
|
active_args = [('relation_all_ids.active', '=', True)]
|
|
break
|
|
|
|
return super(ResPartner, self).search(
|
|
args + date_args + active_args, offset=offset, limit=limit,
|
|
order=order, count=count)
|
|
|
|
@api.multi
|
|
def read(self, fields=None, load='_classic_read'):
|
|
return super(ResPartner, self.with_partner_relations_context())\
|
|
.read(fields=fields, load=load)
|
|
|
|
@api.multi
|
|
def write(self, vals):
|
|
return super(ResPartner, self.with_partner_relations_context())\
|
|
.write(vals)
|
|
|
|
@api.multi
|
|
def with_partner_relations_context(self):
|
|
context = dict(self.env.context)
|
|
if context.get('active_model', self._name) == self._name:
|
|
existing = self.exists()
|
|
context.setdefault(
|
|
'active_id', existing.ids[0] if existing.ids else None)
|
|
context.setdefault('active_ids', existing.ids)
|
|
context.setdefault('active_model', self._name)
|
|
return self.with_context(context)
|
|
|
|
@api.multi
|
|
def get_partner_type(self):
|
|
"""Get partner type for relation.
|
|
:return: 'c' for company or 'p' for person
|
|
:rtype: str
|
|
"""
|
|
self.ensure_one()
|
|
return 'c' if self.is_company else 'p'
|