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.

285 lines
11 KiB

10 years ago
10 years ago
  1. # -*- coding: utf-8 -*-
  2. # © 2013-2017 Therp BV <http://therp.nl>.
  3. # License AGPL-3.0 or later <http://www.gnu.org/licenses/agpl.html>.
  4. import time
  5. from openerp.osv import orm, fields
  6. from openerp.osv.expression import is_leaf, AND, OR, FALSE_LEAF
  7. from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
  8. from openerp.tools.translate import _
  9. class ResPartner(orm.Model):
  10. _inherit = 'res.partner'
  11. def _get_relation_ids_select(self, cr, uid, ids, field_name, arg,
  12. context=None):
  13. """return the partners' relations as tuple
  14. (id, left_partner_id, right_partner_id)"""
  15. cr.execute(
  16. """select id, left_partner_id, right_partner_id
  17. from res_partner_relation
  18. where (left_partner_id in %s or right_partner_id in %s)""" +
  19. ' order by ' + self.pool['res.partner.relation']._order,
  20. (tuple(ids), tuple(ids))
  21. )
  22. return cr.fetchall()
  23. def _get_relation_ids(
  24. self, cr, uid, ids, field_name, arg, context=None):
  25. """getter for relation_ids"""
  26. if context is None:
  27. context = {}
  28. result = dict([(i, []) for i in ids])
  29. # TODO: do a permission test on returned ids
  30. for row in self._get_relation_ids_select(
  31. cr, uid, ids, field_name, arg, context=context):
  32. if row[1] in result:
  33. result[row[1]].append(row[0])
  34. if row[2] in result:
  35. result[row[2]].append(row[0])
  36. return result
  37. def _set_relation_ids(
  38. self, cr, uid, ids, dummy_name, field_value, dummy_arg,
  39. context=None):
  40. """setter for relation_ids"""
  41. if context is None:
  42. context = {}
  43. relation_obj = self.pool.get('res.partner.relation')
  44. context2 = self._update_context(context, ids)
  45. for value in field_value:
  46. if value[0] == 0:
  47. relation_obj.create(cr, uid, value[2], context=context2)
  48. if value[0] == 1:
  49. # if we write partner_id_display, we also need to pass
  50. # type_selection_id in order to have this write end up on
  51. # the correct field
  52. if 'partner_id_display' in value[2] and 'type_selection_id'\
  53. not in value[2]:
  54. relation_data = relation_obj.read(
  55. cr, uid, [value[1]], ['type_selection_id'],
  56. context=context)[0]
  57. value[2]['type_selection_id'] =\
  58. relation_data['type_selection_id']
  59. relation_obj.write(
  60. cr, uid, value[1], value[2], context=context2)
  61. if value[0] == 2:
  62. relation_obj.unlink(cr, uid, value[1], context=context2)
  63. def _search_relation_id(
  64. self, cr, uid, dummy_obj, name, args, context=None):
  65. result = []
  66. for arg in args:
  67. if isinstance(arg, tuple) and arg[0] == name:
  68. if arg[1] not in ['=', '!=', 'like', 'not like', 'ilike',
  69. 'not ilike', 'in', 'not in']:
  70. raise orm.except_orm(
  71. _('Error'),
  72. _('Unsupported search operand "%s"') % arg[1])
  73. relation_type_selection_ids = []
  74. relation_type_selection = self\
  75. .pool['res.partner.relation.type.selection']
  76. if arg[1] == '=' and isinstance(arg[2], (long, int)):
  77. relation_type_selection_ids.append(arg[2])
  78. elif arg[1] == '!=' and isinstance(arg[2], (long, int)):
  79. type_id, is_inverse = relation_type_selection\
  80. .get_type_from_selection_id(
  81. cr, uid, arg[2])
  82. result = OR([
  83. result,
  84. [
  85. ('relation_all_ids.type_id', '!=', type_id),
  86. ]
  87. ])
  88. continue
  89. else:
  90. relation_type_selection_ids = relation_type_selection\
  91. .search(
  92. cr, uid,
  93. [
  94. ('type_id.name', arg[1], arg[2]),
  95. ('record_type', '=', 'a'),
  96. ],
  97. context=context)
  98. relation_type_selection_ids.extend(
  99. relation_type_selection.search(
  100. cr, uid,
  101. [
  102. ('type_id.name_inverse', arg[1], arg[2]),
  103. ('record_type', '=', 'b'),
  104. ],
  105. context=context))
  106. if not relation_type_selection_ids:
  107. result = AND([result, [FALSE_LEAF]])
  108. for relation_type_selection_id in relation_type_selection_ids:
  109. type_id, is_inverse = relation_type_selection\
  110. .get_type_from_selection_id(
  111. cr, uid, relation_type_selection_id)
  112. result = OR([
  113. result,
  114. [
  115. '&',
  116. ('relation_all_ids.type_id', '=', type_id),
  117. ('relation_all_ids.record_type', '=',
  118. 'b' if is_inverse else 'a')
  119. ],
  120. ])
  121. return result
  122. def _search_relation_date(self, cr, uid, obj, name, args, context=None):
  123. result = []
  124. for arg in args:
  125. if isinstance(arg, tuple) and arg[0] == name:
  126. # TODO: handle {<,>}{,=}
  127. if arg[1] != '=':
  128. continue
  129. result.extend([
  130. '&',
  131. '|',
  132. ('relation_all_ids.date_start', '=', False),
  133. ('relation_all_ids.date_start', '<=', arg[2]),
  134. '|',
  135. ('relation_all_ids.date_end', '=', False),
  136. ('relation_all_ids.date_end', '>=', arg[2]),
  137. ])
  138. return result
  139. def _search_related_partner_id(
  140. self, cr, uid, dummy_obj, name, args, context=None):
  141. result = []
  142. for arg in args:
  143. if isinstance(arg, tuple) and arg[0] == name:
  144. result.append(
  145. (
  146. 'relation_all_ids.other_partner_id',
  147. arg[1],
  148. arg[2],
  149. ))
  150. return result
  151. def _search_related_partner_category_id(
  152. self, cr, uid, dummy_obj, name, args, context=None):
  153. result = []
  154. for arg in args:
  155. if isinstance(arg, tuple) and arg[0] == name:
  156. result.append(
  157. (
  158. 'relation_all_ids.other_partner_id.category_id',
  159. arg[1],
  160. arg[2],
  161. ))
  162. return result
  163. _columns = {
  164. 'relation_ids': fields.function(
  165. lambda self, *args, **kwargs: self._get_relation_ids(
  166. *args, **kwargs),
  167. fnct_inv=_set_relation_ids,
  168. type='one2many', obj='res.partner.relation',
  169. string='Relations',
  170. selectable=False,
  171. ),
  172. 'relation_all_ids': fields.one2many(
  173. 'res.partner.relation.all', 'this_partner_id',
  174. string='All relations with current partner',
  175. auto_join=True,
  176. selectable=False,
  177. ),
  178. 'search_relation_id': fields.function(
  179. lambda self, cr, uid, ids, *args: dict([
  180. (i, False) for i in ids]),
  181. fnct_search=_search_relation_id,
  182. string='Has relation of type',
  183. type='many2one', obj='res.partner.relation.type.selection'
  184. ),
  185. 'search_relation_partner_id': fields.function(
  186. lambda self, cr, uid, ids, *args: dict([
  187. (i, False) for i in ids]),
  188. fnct_search=_search_related_partner_id,
  189. string='Has relation with',
  190. type='many2one', obj='res.partner'
  191. ),
  192. 'search_relation_date': fields.function(
  193. lambda self, cr, uid, ids, *args: dict([
  194. (i, False) for i in ids]),
  195. fnct_search=_search_relation_date,
  196. string='Relation valid', type='date'
  197. ),
  198. 'search_relation_partner_category_id': fields.function(
  199. lambda self, cr, uid, ids, *args: dict([
  200. (i, False) for i in ids]),
  201. fnct_search=_search_related_partner_category_id,
  202. string='Has relation with a partner in category',
  203. type='many2one', obj='res.partner.category'
  204. ),
  205. }
  206. def copy_data(self, cr, uid, id, default=None, context=None):
  207. if default is None:
  208. default = {}
  209. default.setdefault('relation_ids', [])
  210. default.setdefault('relation_all_ids', [])
  211. return super(ResPartner, self).copy_data(cr, uid, id, default=default,
  212. context=context)
  213. def search(self, cr, uid, args, offset=0, limit=None, order=None,
  214. context=None, count=False):
  215. if context is None:
  216. context = {}
  217. # inject searching for current relation date if we search for relation
  218. # properties and no explicit date was given
  219. date_args = []
  220. for arg in args:
  221. if is_leaf(arg) and arg[0].startswith('search_relation'):
  222. if arg[0] == 'search_relation_date':
  223. date_args = []
  224. break
  225. if not date_args:
  226. date_args = [
  227. ('search_relation_date', '=', time.strftime(
  228. DEFAULT_SERVER_DATE_FORMAT))]
  229. # because of auto_join, we have to do the active test by hand
  230. active_args = []
  231. if context.get('active_test', True):
  232. for arg in args:
  233. if is_leaf(arg) and\
  234. arg[0].startswith('search_relation'):
  235. active_args = [('relation_all_ids.active', '=', True)]
  236. break
  237. return super(ResPartner, self).search(
  238. cr, uid, args + date_args + active_args, offset=offset,
  239. limit=limit, order=order, context=context, count=count)
  240. def read(
  241. self, cr, uid, ids, fields=None, context=None,
  242. load='_classic_read'):
  243. return super(ResPartner, self).read(
  244. cr, uid, ids, fields=fields,
  245. context=self._update_context(context, ids), load=load)
  246. def write(self, cr, uid, ids, vals, context=None):
  247. return super(ResPartner, self).write(
  248. cr, uid, ids, vals, context=self._update_context(context, ids))
  249. def _update_context(self, context, ids):
  250. if context is None:
  251. context = {}
  252. ids = ids if isinstance(ids, list) else [ids] if ids else []
  253. result = context.copy()
  254. result.setdefault('active_id', ids[0] if ids else None)
  255. result.setdefault('active_ids', ids)
  256. result.setdefault('active_model', self._name)
  257. return result