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.

303 lines
12 KiB

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