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.

246 lines
9.4 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_select(self, cr, uid, ids, field_name, arg,
  29. context=None):
  30. '''return the partners' relations as tuple
  31. (id, left_partner_id, right_partner_id)'''
  32. cr.execute(
  33. '''select id, left_partner_id, right_partner_id
  34. from res_partner_relation
  35. where (left_partner_id in %s or right_partner_id in %s)''' +
  36. ' order by ' + self.pool['res.partner.relation']._order,
  37. (tuple(ids), tuple(ids))
  38. )
  39. return cr.fetchall()
  40. def _get_relation_ids(
  41. self, cr, uid, ids, field_name, arg, context=None):
  42. '''getter for relation_ids'''
  43. if context is None:
  44. context = {}
  45. result = dict([(i, []) for i in ids])
  46. # TODO: do a permission test on returned ids
  47. for row in self._get_relation_ids_select(
  48. cr, uid, ids, field_name, arg, context=context):
  49. if row[1] in result:
  50. result[row[1]].append(row[0])
  51. if row[2] in result:
  52. result[row[2]].append(row[0])
  53. return result
  54. def _set_relation_ids(
  55. self, cr, uid, ids, dummy_name, field_value, dummy_arg,
  56. context=None):
  57. '''setter for relation_ids'''
  58. if context is None:
  59. context = {}
  60. relation_obj = self.pool.get('res.partner.relation')
  61. context2 = self._update_context(context, ids)
  62. for value in field_value:
  63. if value[0] == 0:
  64. relation_obj.create(cr, uid, value[2], context=context2)
  65. if value[0] == 1:
  66. relation_obj.write(
  67. cr, uid, value[1], value[2], context=context2)
  68. if value[0] == 2:
  69. relation_obj.unlink(cr, uid, value[1], context=context2)
  70. def _search_relation_id(
  71. self, cr, uid, dummy_obj, name, args, context=None):
  72. result = []
  73. for arg in args:
  74. if isinstance(arg, tuple) and arg[0] == name:
  75. if arg[1] != '=':
  76. continue
  77. type_id, is_inverse = self\
  78. .pool['res.partner.relation.type.selection']\
  79. .get_type_from_selection_id(cr, uid, arg[2])
  80. result.extend([
  81. '&',
  82. ('relation_all_ids.type_id', '=', type_id),
  83. ('relation_all_ids.record_type', '=',
  84. 'b' if is_inverse else 'a')
  85. ])
  86. return result
  87. def _search_relation_date(self, cr, uid, obj, name, args, context=None):
  88. result = []
  89. for arg in args:
  90. if isinstance(arg, tuple) and arg[0] == name:
  91. # TODO: handle {<,>}{,=}
  92. if arg[1] != '=':
  93. continue
  94. result.extend([
  95. '&',
  96. '|',
  97. ('relation_all_ids.date_start', '=', False),
  98. ('relation_all_ids.date_start', '<=', arg[2]),
  99. '|',
  100. ('relation_all_ids.date_end', '=', False),
  101. ('relation_all_ids.date_end', '>=', arg[2]),
  102. ])
  103. return result
  104. def _search_related_partner_id(
  105. self, cr, uid, dummy_obj, name, args, context=None):
  106. result = []
  107. for arg in args:
  108. if isinstance(arg, tuple) and arg[0] == name:
  109. result.append(
  110. (
  111. 'relation_all_ids.other_partner_id',
  112. arg[1],
  113. arg[2],
  114. ))
  115. return result
  116. def _search_related_partner_category_id(
  117. self, cr, uid, dummy_obj, name, args, context=None):
  118. result = []
  119. for arg in args:
  120. if isinstance(arg, tuple) and arg[0] == name:
  121. result.append(
  122. (
  123. 'relation_all_ids.other_partner_id.category_id',
  124. arg[1],
  125. arg[2],
  126. ))
  127. return result
  128. _columns = {
  129. 'relation_ids': fields.function(
  130. lambda self, *args, **kwargs: self._get_relation_ids(
  131. *args, **kwargs),
  132. fnct_inv=_set_relation_ids,
  133. type='one2many', obj='res.partner.relation',
  134. string='Relations',
  135. selectable=False,
  136. ),
  137. 'relation_all_ids': fields.one2many(
  138. 'res.partner.relation.all', 'this_partner_id',
  139. string='All relations with current partner',
  140. auto_join=True,
  141. selectable=False,
  142. ),
  143. 'search_relation_id': fields.function(
  144. lambda self, cr, uid, ids, *args: dict([
  145. (i, False) for i in ids]),
  146. fnct_search=_search_relation_id,
  147. string='Has relation of type',
  148. type='many2one', obj='res.partner.relation.type.selection'
  149. ),
  150. 'search_relation_partner_id': fields.function(
  151. lambda self, cr, uid, ids, *args: dict([
  152. (i, False) for i in ids]),
  153. fnct_search=_search_related_partner_id,
  154. string='Has relation with',
  155. type='many2one', obj='res.partner'
  156. ),
  157. 'search_relation_date': fields.function(
  158. lambda self, cr, uid, ids, *args: dict([
  159. (i, False) for i in ids]),
  160. fnct_search=_search_relation_date,
  161. string='Relation valid', type='date'
  162. ),
  163. 'search_relation_partner_category_id': fields.function(
  164. lambda self, cr, uid, ids, *args: dict([
  165. (i, False) for i in ids]),
  166. fnct_search=_search_related_partner_category_id,
  167. string='Has relation with a partner in category',
  168. type='many2one', obj='res.partner.category'
  169. ),
  170. }
  171. def copy_data(self, cr, uid, id, default=None, context=None):
  172. if default is None:
  173. default = {}
  174. default.setdefault('relation_ids', [])
  175. default.setdefault('relation_all_ids', [])
  176. return super(ResPartner, self).copy_data(cr, uid, id, default=default,
  177. context=context)
  178. def search(self, cr, uid, args, offset=0, limit=None, order=None,
  179. context=None, count=False):
  180. if context is None:
  181. context = {}
  182. # inject searching for current relation date if we search for relation
  183. # properties and no explicit date was given
  184. date_args = []
  185. for arg in args:
  186. if is_leaf(arg) and arg[0].startswith('search_relation'):
  187. if arg[0] == 'search_relation_date':
  188. date_args = []
  189. break
  190. if not date_args:
  191. date_args = [
  192. ('search_relation_date', '=', time.strftime(
  193. DEFAULT_SERVER_DATE_FORMAT))]
  194. # because of auto_join, we have to do the active test by hand
  195. active_args = []
  196. if context.get('active_test', True):
  197. for arg in args:
  198. if is_leaf(arg) and\
  199. arg[0].startswith('search_relation'):
  200. active_args = [('relation_all_ids.active', '=', True)]
  201. break
  202. return super(ResPartner, self).search(
  203. cr, uid, args + date_args + active_args, offset=offset,
  204. limit=limit, order=order, context=context, count=count)
  205. def read(
  206. self, cr, uid, ids, fields=None, context=None,
  207. load='_classic_read'):
  208. return super(ResPartner, self).read(
  209. cr, uid, ids, fields=fields,
  210. context=self._update_context(context, ids))
  211. def write(self, cr, uid, ids, vals, context=None):
  212. return super(ResPartner, self).write(
  213. cr, uid, ids, vals, context=self._update_context(context, ids))
  214. def _update_context(self, context, ids):
  215. if context is None:
  216. context = {}
  217. ids = ids if isinstance(ids, list) else [ids] if ids else []
  218. result = context.copy()
  219. result.setdefault('active_id', ids[0] if ids else None)
  220. result.setdefault('active_ids', ids)
  221. result.setdefault('active_model', self._name)
  222. return result