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.

235 lines
8.9 KiB

  1. # -*- coding: utf-8 -*-
  2. '''Extend res.partner model'''
  3. ##############################################################################
  4. #
  5. # OpenERP, Open Source Management Solution
  6. # This module copyright (C) 2013 Therp BV (<http://therp.nl>).
  7. #
  8. # This program is free software: you can redistribute it and/or modify
  9. # it under the terms of the GNU Affero General Public License as
  10. # published by the Free Software Foundation, either version 3 of the
  11. # License, or (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU Affero General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU Affero General Public License
  19. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. #
  21. ##############################################################################
  22. import time
  23. from openerp.osv import orm, fields
  24. from openerp.osv.expression import is_leaf
  25. from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
  26. class ResPartner(orm.Model):
  27. _inherit = 'res.partner'
  28. def _get_relation_ids(
  29. self, cr, uid, ids, dummy_name, dummy_arg, context=None):
  30. # TODO: do a permission test on returned ids
  31. cr.execute(
  32. '''select id, left_partner_id, right_partner_id
  33. from res_partner_relation
  34. where (left_partner_id in %s or right_partner_id in %s)''' +
  35. ' order by ' + self.pool['res.partner.relation']._order,
  36. (tuple(ids), tuple(ids))
  37. )
  38. result = dict([(i, []) for i in ids])
  39. for row in cr.fetchall():
  40. if row[1] in result:
  41. result[row[1]].append(row[0])
  42. if row[2] in result:
  43. result[row[2]].append(row[0])
  44. return result
  45. def _set_relation_ids(
  46. self, cr, uid, ids, dummy_name, field_value, dummy_arg,
  47. context=None):
  48. if context is None:
  49. context = {}
  50. relation_obj = self.pool.get('res.partner.relation')
  51. context2 = self._update_context(context, ids)
  52. for value in field_value:
  53. if value[0] == 0:
  54. relation_obj.create(cr, uid, value[2], context=context2)
  55. if value[0] == 1:
  56. relation_obj.write(
  57. cr, uid, value[1], value[2], context=context2)
  58. if value[0] == 2:
  59. relation_obj.unlink(cr, uid, value[1], context=context2)
  60. def _search_relation_id(
  61. self, cr, uid, dummy_obj, name, args, context=None):
  62. result = []
  63. for arg in args:
  64. if isinstance(arg, tuple) and arg[0] == name:
  65. if arg[1] != '=':
  66. continue
  67. type_id, is_inverse = self\
  68. .pool['res.partner.relation.type.selection']\
  69. .get_type_from_selection_id(cr, uid, arg[2])
  70. result.extend([
  71. '&',
  72. ('relation_all_ids.type_id', '=', type_id),
  73. ('relation_all_ids.record_type', '=',
  74. 'b' if is_inverse else 'a')
  75. ])
  76. return result
  77. def _search_relation_date(self, cr, uid, obj, name, args, context=None):
  78. result = []
  79. for arg in args:
  80. if isinstance(arg, tuple) and arg[0] == name:
  81. # TODO: handle {<,>}{,=}
  82. if arg[1] != '=':
  83. continue
  84. result.extend([
  85. '&',
  86. '|',
  87. ('relation_all_ids.date_start', '=', False),
  88. ('relation_all_ids.date_start', '<=', arg[2]),
  89. '|',
  90. ('relation_all_ids.date_end', '=', False),
  91. ('relation_all_ids.date_end', '>=', arg[2]),
  92. ])
  93. return result
  94. def _search_related_partner_id(
  95. self, cr, uid, dummy_obj, name, args, context=None):
  96. result = []
  97. for arg in args:
  98. if isinstance(arg, tuple) and arg[0] == name:
  99. result.append(
  100. (
  101. 'relation_all_ids.other_partner_id',
  102. arg[1],
  103. arg[2],
  104. ))
  105. return result
  106. def _search_related_partner_category_id(
  107. self, cr, uid, dummy_obj, name, args, context=None):
  108. result = []
  109. for arg in args:
  110. if isinstance(arg, tuple) and arg[0] == name:
  111. result.append(
  112. (
  113. 'relation_all_ids.other_partner_id.category_id',
  114. arg[1],
  115. arg[2],
  116. ))
  117. return result
  118. _columns = {
  119. 'relation_ids': fields.function(
  120. lambda self, *args, **kwargs: self._get_relation_ids(
  121. *args, **kwargs),
  122. fnct_inv=_set_relation_ids,
  123. type='one2many', obj='res.partner.relation',
  124. string='Relations',
  125. selectable=False,
  126. ),
  127. 'relation_all_ids': fields.one2many(
  128. 'res.partner.relation.all', 'this_partner_id',
  129. string='All relations with current partner',
  130. auto_join=True,
  131. selectable=False,
  132. ),
  133. 'search_relation_id': fields.function(
  134. lambda self, cr, uid, ids, *args: dict([
  135. (i, False) for i in ids]),
  136. fnct_search=_search_relation_id,
  137. string='Has relation of type',
  138. type='many2one', obj='res.partner.relation.type.selection'
  139. ),
  140. 'search_relation_partner_id': fields.function(
  141. lambda self, cr, uid, ids, *args: dict([
  142. (i, False) for i in ids]),
  143. fnct_search=_search_related_partner_id,
  144. string='Has relation with',
  145. type='many2one', obj='res.partner'
  146. ),
  147. 'search_relation_date': fields.function(
  148. lambda self, cr, uid, ids, *args: dict([
  149. (i, False) for i in ids]),
  150. fnct_search=_search_relation_date,
  151. string='Relation valid', type='date'
  152. ),
  153. 'search_relation_partner_category_id': fields.function(
  154. lambda self, cr, uid, ids, *args: dict([
  155. (i, False) for i in ids]),
  156. fnct_search=_search_related_partner_category_id,
  157. string='Has relation with a partner in category',
  158. type='many2one', obj='res.partner.category'
  159. ),
  160. }
  161. def copy_data(self, cr, uid, id, default=None, context=None):
  162. if default is None:
  163. default = {}
  164. default.setdefault('relation_ids', [])
  165. default.setdefault('relation_all_ids', [])
  166. return super(ResPartner, self).copy_data(cr, uid, id, default=default,
  167. context=context)
  168. def search(self, cr, uid, args, offset=0, limit=None, order=None,
  169. context=None, count=False):
  170. if context is None:
  171. context = {}
  172. # inject searching for current relation date if we search for relation
  173. # properties and no explicit date was given
  174. date_args = []
  175. for arg in args:
  176. if is_leaf(arg) and arg[0].startswith('search_relation'):
  177. if arg[0] == 'search_relation_date':
  178. date_args = []
  179. break
  180. if not date_args:
  181. date_args = [
  182. ('search_relation_date', '=', time.strftime(
  183. DEFAULT_SERVER_DATE_FORMAT))]
  184. # because of auto_join, we have to do the active test by hand
  185. active_args = []
  186. if context.get('active_test', True):
  187. for arg in args:
  188. if is_leaf(arg) and\
  189. arg[0].startswith('search_relation'):
  190. active_args = [('relation_all_ids.active', '=', True)]
  191. break
  192. return super(ResPartner, self).search(
  193. cr, uid, args + date_args + active_args, offset=offset,
  194. limit=limit, order=order, context=context, count=count)
  195. def read(
  196. self, cr, uid, ids, fields=None, context=None,
  197. load='_classic_read'):
  198. return super(ResPartner, self).read(
  199. cr, uid, ids, fields=fields,
  200. context=self._update_context(context, ids))
  201. def write(self, cr, uid, ids, vals, context=None):
  202. return super(ResPartner, self).write(
  203. cr, uid, ids, vals, context=self._update_context(context, ids))
  204. def _update_context(self, context, ids):
  205. if context is None:
  206. context = {}
  207. ids = ids if isinstance(ids, list) else [ids] if ids else []
  208. result = context.copy()
  209. result.setdefault('active_id', ids[0] if ids else None)
  210. result.setdefault('active_ids', ids)
  211. result.setdefault('active_model', self._name)
  212. return result