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.
320 lines
13 KiB
320 lines
13 KiB
# -*- coding: utf-8 -*-
|
|
'''Extend res.partner model'''
|
|
##############################################################################
|
|
#
|
|
# 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/>.
|
|
#
|
|
##############################################################################
|
|
import time
|
|
from openerp import osv, models, fields, exceptions, api
|
|
from openerp.osv.expression import is_leaf, AND, OR, FALSE_LEAF
|
|
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
|
|
from openerp.tools.translate import _
|
|
|
|
|
|
class ResPartner(models.Model):
|
|
_inherit = 'res.partner'
|
|
|
|
relation_count = fields.Integer(
|
|
'Relation Count',
|
|
compute="_count_relations"
|
|
)
|
|
|
|
@api.one
|
|
@api.depends("relation_ids")
|
|
def _count_relations(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])
|
|
|
|
def _get_relation_ids_select(self, cr, uid, ids, field_name, arg,
|
|
context=None):
|
|
'''return the partners' relations as tuple
|
|
(id, left_partner_id, right_partner_id)'''
|
|
cr.execute(
|
|
'''select id, left_partner_id, right_partner_id
|
|
from res_partner_relation
|
|
where (left_partner_id in %s or right_partner_id in %s)''' +
|
|
' order by ' + self.pool['res.partner.relation']._order,
|
|
(tuple(ids), tuple(ids))
|
|
)
|
|
return cr.fetchall()
|
|
|
|
def _get_relation_ids(
|
|
self, cr, uid, ids, field_name, arg, context=None):
|
|
'''getter for relation_ids'''
|
|
if context is None:
|
|
context = {}
|
|
result = dict([(i, []) for i in ids])
|
|
# TODO: do a permission test on returned ids
|
|
for row in self._get_relation_ids_select(
|
|
cr, uid, ids, field_name, arg, context=context):
|
|
if row[1] in result:
|
|
result[row[1]].append(row[0])
|
|
if row[2] in result:
|
|
result[row[2]].append(row[0])
|
|
return result
|
|
|
|
def _set_relation_ids(
|
|
self, cr, uid, ids, dummy_name, field_value, dummy_arg,
|
|
context=None):
|
|
'''setter for relation_ids'''
|
|
if context is None:
|
|
context = {}
|
|
relation_obj = self.pool.get('res.partner.relation')
|
|
context2 = self._update_context(context, ids)
|
|
for value in field_value:
|
|
if value[0] == 0:
|
|
relation_obj.create(cr, uid, value[2], context=context2)
|
|
if value[0] == 1:
|
|
# if we write partner_id_display, we also need to pass
|
|
# type_selection_id in order to have this write end up on
|
|
# the correct field
|
|
if 'partner_id_display' in value[2] and 'type_selection_id'\
|
|
not in value[2]:
|
|
relation_data = relation_obj.read(
|
|
cr, uid, [value[1]], ['type_selection_id'],
|
|
context=context)[0]
|
|
value[2]['type_selection_id'] =\
|
|
relation_data['type_selection_id']
|
|
relation_obj.write(
|
|
cr, uid, value[1], value[2], context=context2)
|
|
if value[0] == 2:
|
|
relation_obj.unlink(cr, uid, value[1], context=context2)
|
|
|
|
def _search_relation_id(
|
|
self, cr, uid, dummy_obj, name, args, context=None):
|
|
result = []
|
|
for arg in args:
|
|
if isinstance(arg, tuple) and arg[0] == name:
|
|
if arg[1] not in ['=', '!=', 'like', 'not like', 'ilike',
|
|
'not ilike', 'in', 'not in']:
|
|
raise exceptions.ValidationError(
|
|
_('Unsupported search operand "%s"') % arg[1])
|
|
|
|
relation_type_selection_ids = []
|
|
relation_type_selection = self\
|
|
.pool['res.partner.relation.type.selection']
|
|
|
|
if arg[1] == '=' and isinstance(arg[2], (long, int)):
|
|
relation_type_selection_ids.append(arg[2])
|
|
elif arg[1] == '!=' and isinstance(arg[2], (long, int)):
|
|
type_id, is_inverse = (
|
|
relation_type_selection.browse(cr, uid, arg[2],
|
|
context=context)
|
|
.get_type_from_selection_id()
|
|
)
|
|
result = OR([
|
|
result,
|
|
[
|
|
('relation_all_ids.type_id', '!=', type_id),
|
|
]
|
|
])
|
|
continue
|
|
else:
|
|
relation_type_selection_ids = relation_type_selection\
|
|
.search(
|
|
cr, uid,
|
|
[
|
|
('type_id.name', arg[1], arg[2]),
|
|
('record_type', '=', 'a'),
|
|
],
|
|
context=context)
|
|
relation_type_selection_ids.extend(
|
|
relation_type_selection.search(
|
|
cr, uid,
|
|
[
|
|
('type_id.name_inverse', arg[1], arg[2]),
|
|
('record_type', '=', 'b'),
|
|
],
|
|
context=context))
|
|
|
|
if not relation_type_selection_ids:
|
|
result = AND([result, [FALSE_LEAF]])
|
|
|
|
for relation_type_selection_id in relation_type_selection_ids:
|
|
type_id, is_inverse = (
|
|
relation_type_selection.browse(
|
|
cr, uid, relation_type_selection_id,
|
|
context=context
|
|
).get_type_from_selection_id()
|
|
)
|
|
|
|
result = OR([
|
|
result,
|
|
[
|
|
'&',
|
|
('relation_all_ids.type_id', '=', type_id),
|
|
('relation_all_ids.record_type', '=',
|
|
'b' if is_inverse else 'a')
|
|
],
|
|
])
|
|
|
|
return result
|
|
|
|
def _search_relation_date(self, cr, uid, obj, name, args, context=None):
|
|
result = []
|
|
for arg in args:
|
|
if isinstance(arg, tuple) and arg[0] == name:
|
|
# TODO: handle {<,>}{,=}
|
|
if arg[1] != '=':
|
|
continue
|
|
|
|
result.extend([
|
|
'&',
|
|
'|',
|
|
('relation_all_ids.date_start', '=', False),
|
|
('relation_all_ids.date_start', '<=', arg[2]),
|
|
'|',
|
|
('relation_all_ids.date_end', '=', False),
|
|
('relation_all_ids.date_end', '>=', arg[2]),
|
|
])
|
|
|
|
return result
|
|
|
|
def _search_related_partner_id(
|
|
self, cr, uid, dummy_obj, name, args, context=None):
|
|
result = []
|
|
for arg in args:
|
|
if isinstance(arg, tuple) and arg[0] == name:
|
|
result.append(
|
|
(
|
|
'relation_all_ids.other_partner_id',
|
|
arg[1],
|
|
arg[2],
|
|
))
|
|
|
|
return result
|
|
|
|
def _search_related_partner_category_id(
|
|
self, cr, uid, dummy_obj, name, args, context=None):
|
|
result = []
|
|
for arg in args:
|
|
if isinstance(arg, tuple) and arg[0] == name:
|
|
result.append(
|
|
(
|
|
'relation_all_ids.other_partner_id.category_id',
|
|
arg[1],
|
|
arg[2],
|
|
))
|
|
|
|
return result
|
|
|
|
_columns = {
|
|
'relation_ids': osv.fields.function(
|
|
lambda self, *args, **kwargs: self._get_relation_ids(
|
|
*args, **kwargs),
|
|
fnct_inv=_set_relation_ids,
|
|
type='one2many', obj='res.partner.relation',
|
|
string='Relations',
|
|
selectable=False,
|
|
),
|
|
'relation_all_ids': osv.fields.one2many(
|
|
'res.partner.relation.all', 'this_partner_id',
|
|
string='All relations with current partner',
|
|
auto_join=True,
|
|
selectable=False,
|
|
),
|
|
'search_relation_id': osv.fields.function(
|
|
lambda self, cr, uid, ids, *args: dict([
|
|
(i, False) for i in ids]),
|
|
fnct_search=_search_relation_id,
|
|
string='Has relation of type',
|
|
type='many2one', obj='res.partner.relation.type.selection'
|
|
),
|
|
'search_relation_partner_id': osv.fields.function(
|
|
lambda self, cr, uid, ids, *args: dict([
|
|
(i, False) for i in ids]),
|
|
fnct_search=_search_related_partner_id,
|
|
string='Has relation with',
|
|
type='many2one', obj='res.partner'
|
|
),
|
|
'search_relation_date': osv.fields.function(
|
|
lambda self, cr, uid, ids, *args: dict([
|
|
(i, False) for i in ids]),
|
|
fnct_search=_search_relation_date,
|
|
string='Relation valid', type='date'
|
|
),
|
|
'search_relation_partner_category_id': osv.fields.function(
|
|
lambda self, cr, uid, ids, *args: dict([
|
|
(i, False) for i in ids]),
|
|
fnct_search=_search_related_partner_category_id,
|
|
string='Has relation with a partner in category',
|
|
type='many2one', obj='res.partner.category'
|
|
),
|
|
}
|
|
|
|
def copy_data(self, cr, uid, id, default=None, context=None):
|
|
if default is None:
|
|
default = {}
|
|
default.setdefault('relation_ids', [])
|
|
default.setdefault('relation_all_ids', [])
|
|
return super(ResPartner, self).copy_data(cr, uid, id, default=default,
|
|
context=context)
|
|
|
|
def search(self, cr, uid, args, offset=0, limit=None, order=None,
|
|
context=None, count=False):
|
|
if context is None:
|
|
context = {}
|
|
# 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', '=', time.strftime(
|
|
DEFAULT_SERVER_DATE_FORMAT))]
|
|
|
|
# because of auto_join, we have to do the active test by hand
|
|
active_args = []
|
|
if 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(
|
|
cr, uid, args + date_args + active_args, offset=offset,
|
|
limit=limit, order=order, context=context, count=count)
|
|
|
|
def read(
|
|
self, cr, uid, ids, fields=None, context=None,
|
|
load='_classic_read'):
|
|
return super(ResPartner, self).read(
|
|
cr, uid, ids, fields=fields,
|
|
context=self._update_context(context, ids), load=load)
|
|
|
|
def write(self, cr, uid, ids, vals, context=None):
|
|
return super(ResPartner, self).write(
|
|
cr, uid, ids, vals, context=self._update_context(context, ids))
|
|
|
|
def _update_context(self, context, ids):
|
|
if context is None:
|
|
context = {}
|
|
ids = ids if isinstance(ids, list) else [ids] if ids else []
|
|
result = context.copy()
|
|
result.setdefault('active_id', ids[0] if ids else None)
|
|
result.setdefault('active_ids', ids)
|
|
result.setdefault('active_model', self._name)
|
|
return result
|