Join the social network of Tech Nerds, increase skill rank, get work, manage projects...
 
  • How to perform a super with count as False, to have the ids, not a counter in Odoo?

    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 400
    Comment on it

    If you want to perform a super with count as False, to have the ids, not a counter in Odoo then follow the following code in your .py file.

    1. ids = super(mail_message, self)._search(cr, uid, args, offset=offset, limit=limit, order=order,
    2. context=context, count=False, access_rights_uid=access_rights_uid)
    3. if not ids and count:
    4. return 0
    5. elif not ids:
    6. return ids
    7.  
    8. pid = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=context).partner_id.id
    9. author_ids, partner_ids, allowed_ids = set([]), set([]), set([])
    10. model_ids = {}
    11.  
    12. messages = super(mail_message, self).read(cr, uid, ids, ['author_id', 'model', 'res_id', 'notified_partner_ids'], context=context)
    13. for message in messages:
    14. if message.get('author_id') and message.get('author_id')[0] == pid:
    15. author_ids.add(message.get('id'))
    16. elif pid in message.get('notified_partner_ids'):
    17. partner_ids.add(message.get('id'))
    18. elif message.get('model') and message.get('res_id'):
    19. model_ids.setdefault(message.get('model'), {}).setdefault(message.get('res_id'), set()).add(message.get('id'))
    20.  
    21. allowed_ids = self._find_allowed_doc_ids(cr, uid, model_ids, context=context)
    22. final_ids = author_ids | partner_ids | allowed_ids
    23.  
    24. if count:
    25. return len(final_ids)
    26. else:
    27. # re-construct a list based on ids, because set did not keep the original order
    28. id_list = [id for id in ids if id in final_ids]
    29. return id_list
    30.  
    31. def check_access_rule(self, cr, uid, ids, operation, context=None):
    32. """ Access rules of mail.message:
    33. - read: if
    34. - author_id == pid, uid is the author, OR
    35. - mail_notification (id, pid) exists, uid has been notified, OR
    36. - uid have read access to the related document if model, res_id
    37. - otherwise: raise
    38. - create: if
    39. - no model, no res_id, I create a private message OR
    40. - pid in message_follower_ids if model, res_id OR
    41. - mail_notification (parent_id.id, pid) exists, uid has been notified of the parent, OR
    42. - uid have write or create access on the related document if model, res_id, OR
    43. - otherwise: raise
    44. - write: if
    45. - author_id == pid, uid is the author, OR
    46. - uid has write or create access on the related document if model, res_id
    47. - otherwise: raise
    48. - unlink: if
    49. - uid has write or create access on the related document if model, res_id
    50. - otherwise: raise
    51. """
    52. def _generate_model_record_ids(msg_val, msg_ids=[]):
    53. """ :param model_record_ids: {'model': {'res_id': (msg_id, msg_id)}, ... }
    54. :param message_values: {'msg_id': {'model': .., 'res_id': .., 'author_id': ..}}
    55. """
    56. model_record_ids = {}
    57. for id in msg_ids:
    58. vals = msg_val.get(id, {})
    59. if vals.get('model') and vals.get('res_id'):
    60. model_record_ids.setdefault(vals['model'], set()).add(vals['res_id'])
    61. return model_record_ids
    62.  
    63. if uid == SUPERUSER_ID:
    64. return
    65. if isinstance(ids, (int, long)):
    66. ids = [ids]
    67. not_obj = self.pool.get('mail.notification')
    68. fol_obj = self.pool.get('mail.followers')
    69. partner_id = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=None).partner_id.id
    70.  
    71. # Read mail_message.ids to have their values
    72. message_values = dict.fromkeys(ids, {})
    73. cr.execute('SELECT DISTINCT id, model, res_id, author_id, parent_id FROM "%s" WHERE id = ANY (%%s)' % self._table, (ids,))
    74. for id, rmod, rid, author_id, parent_id in cr.fetchall():
    75. message_values[id] = {'model': rmod, 'res_id': rid, 'author_id': author_id, 'parent_id': parent_id}
    76.  
    77. # Author condition (READ, WRITE, CREATE (private)) -> could become an ir.rule ?
    78. author_ids = []
    79. if operation == 'read' or operation == 'write':
    80. author_ids = [mid for mid, message in message_values.iteritems()
    81. if message.get('author_id') and message.get('author_id') == partner_id]
    82. elif operation == 'create':
    83. author_ids = [mid for mid, message in message_values.iteritems()
    84. if not message.get('model') and not message.get('res_id')]
    85.  
    86. # Parent condition, for create (check for received notifications for the created message parent)
    87. notified_ids = []
    88. if operation == 'create':
    89. parent_ids = [message.get('parent_id') for mid, message in message_values.iteritems()
    90. if message.get('parent_id')]
    91. not_ids = not_obj.search(cr, SUPERUSER_ID, [('message_id.id', 'in', parent_ids), ('partner_id', '=', partner_id)], context=context)
    92. not_parent_ids = [notif.message_id.id for notif in not_obj.browse(cr, SUPERUSER_ID, not_ids, context=context)]
    93. notified_ids += [mid for mid, message in message_values.iteritems()
    94. if message.get('parent_id') in not_parent_ids]
    95.  
    96. # Notification condition, for read (check for received notifications and create (in message_follower_ids)) -> could become an ir.rule, but not till we do not have a many2one variable field
    97. other_ids = set(ids).difference(set(author_ids), set(notified_ids))
    98. model_record_ids = _generate_model_record_ids(message_values, other_ids)
    99. if operation == 'read':
    100. not_ids = not_obj.search(cr, SUPERUSER_ID, [
    101. ('partner_id', '=', partner_id),
    102. ('message_id', 'in', ids),
    103. ], context=context)
    104. notified_ids = [notification.message_id.id for notification in not_obj.browse(cr, SUPERUSER_ID, not_ids, context=context)]
    105. elif operation == 'create':
    106. for doc_model, doc_ids in model_record_ids.items():
    107. fol_ids = fol_obj.search(cr, SUPERUSER_ID, [
    108. ('res_model', '=', doc_model),
    109. ('res_id', 'in', list(doc_ids)),
    110. ('partner_id', '=', partner_id),
    111. ], context=context)
    112. fol_mids = [follower.res_id for follower in fol_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context)]
    113. notified_ids += [mid for mid, message in message_values.iteritems()
    114. if message.get('model') == doc_model and message.get('res_id') in fol_mids]
    115.  
    116. # CRUD: Access rights related to the document
    117. other_ids = other_ids.difference(set(notified_ids))
    118. model_record_ids = _generate_model_record_ids(message_values, other_ids)
    119. document_related_ids = []
    120. for model, doc_ids in model_record_ids.items():
    121. model_obj = self.pool[model]
    122. mids = model_obj.exists(cr, uid, list(doc_ids))
    123. if hasattr(model_obj, 'check_mail_message_access'):
    124. model_obj.check_mail_message_access(cr, uid, mids, operation, context=context)
    125. else:
    126. self.pool['mail.thread'].check_mail_message_access(cr, uid, mids, operation, model_obj=model_obj, context=context)
    127. document_related_ids += [mid for mid, message in message_values.iteritems()
    128. if message.get('model') == model and message.get('res_id') in mids]
    129.  
    130. # Calculate remaining ids: if not void, raise an error
    131. other_ids = other_ids.difference(set(document_related_ids))
    132. if not other_ids:
    133. return
    134. raise orm.except_orm(_('Access Denied'),
    135. _('The requested operation cannot be completed due to security restrictions. Please contact your system administrator.\n\n(Document type: %s, Operation: %s)') % \
    136. (self._description, operation))
    137.  
    138. def _get_record_name(self, cr, uid, values, context=None):
    139. """ Return the related document name, using name_get. It is done using
    140. SUPERUSER_ID, to be sure to have the record name correctly stored. """
    141. if not values.get('model') or not values.get('res_id') or values['model'] not in self.pool:
    142. return False
    143. return self.pool[values['model']].name_get(cr, SUPERUSER_ID, [values['res_id']], context=context)[0][1]
    144.  
    145. def _get_reply_to(self, cr, uid, values, context=None):
    146. """ Return a specific reply_to: alias of the document through message_get_reply_to
    147. or take the email_from
    148. """
    149. email_reply_to = None
    150.  
    151. ir_config_parameter = self.pool.get("ir.config_parameter")
    152. catchall_domain = ir_config_parameter.get_param(cr, uid, "mail.catchall.domain", context=context)
    153.  
    154. # model, res_id, email_from: comes from values OR related message
    155. model, res_id, email_from = values.get('model'), values.get('res_id'), values.get('email_from')
    156.  
    157. # if model and res_id: try to use ``message_get_reply_to`` that returns the document alias
    158. if not email_reply_to and model and res_id and catchall_domain and hasattr(self.pool[model], 'message_get_reply_to'):
    159. email_reply_to = self.pool[model].message_get_reply_to(cr, uid, [res_id], context=context)[0]
    160. # no alias reply_to -> catchall alias
    161. if not email_reply_to and catchall_domain:
    162. catchall_alias = ir_config_parameter.get_param(cr, uid, "mail.catchall.alias", context=context)
    163. if catchall_alias:
    164. email_reply_to = '%s@%s' % (catchall_alias, catchall_domain)
    165. # still no reply_to -> reply_to will be the email_from
    166. if not email_reply_to and email_from:
    167. email_reply_to = email_from
    168.  
    169. # format 'Document name <email_address>'
    170. if email_reply_to and model and res_id:
    171. emails = tools.email_split(email_reply_to)
    172. if emails:
    173. email_reply_to = emails[0]
    174. document_name = self.pool[model].name_get(cr, SUPERUSER_ID, [res_id], context=context)[0]
    175. if document_name:
    176. # sanitize document name
    177. sanitized_doc_name = re.sub(r'[^\w+.]+', '-', document_name[1])
    178. # generate reply to
    179. email_reply_to = _('"Followers of %s" <%s>') % (sanitized_doc_name, email_reply_to)
    180.  
    181. return email_reply_to
    182.  
    183. def _get_message_id(self, cr, uid, values, context=None):
    184. if values.get('reply_to'):
    185. message_id = tools.generate_tracking_message_id('reply_to')
    186. elif values.get('res_id') and values.get('model'):
    187. message_id = tools.generate_tracking_message_id('%(res_id)s-%(model)s' % values)
    188. else:
    189. message_id = tools.generate_tracking_message_id('private')
    190. return message_id
    191.  
    192. def create(self, cr, uid, values, context=None):
    193. if context is None:
    194. context = {}
    195. default_starred = context.pop('default_starred', False)
    196.  
    197. if 'email_from' not in values: # needed to compute reply_to
    198. values['email_from'] = self._get_default_from(cr, uid, context=context)
    199. if 'message_id' not in values:
    200. values['message_id'] = self._get_message_id(cr, uid, values, context=context)
    201. if 'reply_to' not in values:
    202. values['reply_to'] = self._get_reply_to(cr, uid, values, context=context)
    203. if 'record_name' not in values and 'default_record_name' not in context:
    204. values['record_name'] = self._get_record_name(cr, uid, values, context=context)
    205.  
    206. newid = super(mail_message, self).create(cr, uid, values, context)
    207.  
    208. self._notify(cr, uid, newid, context=context,
    209. force_send=context.get('mail_notify_force_send', True),
    210. user_signature=context.get('mail_notify_user_signature', True))
    211. # TDE FIXME: handle default_starred. Why not setting an inv on starred ?
    212. # Because starred will call set_message_starred, that looks for notifications.
    213. # When creating a new mail_message, it will create a notification to a message
    214. # that does not exist, leading to an error (key not existing). Also this
    215. # this means unread notifications will be created, yet we can not assure
    216. # this is what we want.
    217. if default_starred:
    218. self.set_message_starred(cr, uid, [newid], True, context=context)
    219. return newid
    220.  
    221. def read(self, cr, uid, ids, fields=None, context=None, load='_classic_read'):
    222. """ Override to explicitely call check_access_rule, that is not called
    223. by the ORM. It instead directly fetches ir.rules and apply them. """
    224. self.check_access_rule(cr, uid, ids, 'read', context=context)
    225. res = super(mail_message, self).read(cr, uid, ids, fields=fields, context=context, load=load)
    226. return res
    227.  
    228. def unlink(self, cr, uid, ids, context=None):
    229. # cascade-delete attachments that are directly attached to the message (should only happen
    230. # for mail.messages that act as parent for a standalone mail.mail record).
    231. self.check_access_rule(cr, uid, ids, 'unlink', context=context)
    232. attachments_to_delete = []
    233. for message in self.browse(cr, uid, ids, context=context):
    234. for attach in message.attachment_ids:
    235. if attach.res_model == self._name and (attach.res_id == message.id or attach.res_id == 0):
    236. attachments_to_delete.append(attach.id)
    237. if attachments_to_delete:
    238. self.pool.get('ir.attachment').unlink(cr, uid, attachments_to_delete, context=context)
    239. return super(mail_message, self).unlink(cr, uid, ids, context=context)
    240.  
    241. def copy(self, cr, uid, id, default=None, context=None):
    242. """ Overridden to avoid duplicating fields that are unique to each email """
    243. if default is None:
    244. default = {}
    245. default.update(message_id=False, headers=False)
    246. return super(mail_message, self).copy(cr, uid, id, default=default, context=context)
    247.  
    248. #------------------------------------------------------
    249. # Messaging API
    250. #------------------------------------------------------
    251.  
    252. def _notify(self, cr, uid, newid, context=None, force_send=False, user_signature=True):
    253. """ Add the related record followers to the destination partner_ids if is not a private message.
    254. Call mail_notification.notify to manage the email sending
    255. """
    256. notification_obj = self.pool.get('mail.notification')
    257. message = self.browse(cr, uid, newid, context=context)
    258. partners_to_notify = set([])
    259.  
    260. # all followers of the mail.message document have to be added as partners and notified if a subtype is defined (otherwise: log message)
    261. if message.subtype_id and message.model and message.res_id:
    262. fol_obj = self.pool.get("mail.followers")
    263. # browse as SUPERUSER because rules could restrict the search results
    264. fol_ids = fol_obj.search(
    265. cr, SUPERUSER_ID, [
    266. ('res_model', '=', message.model),
    267. ('res_id', '=', message.res_id),
    268. ], context=context)
    269. partners_to_notify |= set(
    270. fo.partner_id.id for fo in fol_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context)
    271. if message.subtype_id.id in [st.id for st in fo.subtype_ids]
    272. )
    273. # remove me from notified partners, unless the message is written on my own wall
    274. if message.subtype_id and message.author_id and message.model == "res.partner" and message.res_id == message.author_id.id:
    275. partners_to_notify |= set([message.author_id.id])
    276. elif message.author_id:
    277. partners_to_notify -= set([message.author_id.id])
    278.  
    279. # all partner_ids of the mail.message have to be notified regardless of the above (even the author if explicitly added!)
    280. if message.partner_ids:
    281. partners_to_notify |= set([p.id for p in message.partner_ids])
    282.  
    283. # notify
    284. notification_obj._notify(
    285. cr, uid, newid, partners_to_notify=list(partners_to_notify), context=context,
    286. force_send=force_send, user_signature=user_signature
    287. )
    288. message.refresh()
    289.  
    290. # An error appear when a user receive a notification without notifying
    291. # the parent message -> add a read notification for the parent
    292. if message.parent_id:
    293. # all notified_partner_ids of the mail.message have to be notified for the parented messages
    294. partners_to_parent_notify = set(message.notified_partner_ids).difference(message.parent_id.notified_partner_ids)
    295. for partner in partners_to_parent_notify:
    296. notification_obj.create(cr, uid, {
    297. 'message_id': message.parent_id.id,
    298. 'partner_id': partner.id,
    299. 'read': True,
    300. }, context=context)

     

 0 Comment(s)

Sign In
                           OR                           
                           OR                           
Register

Sign up using

                           OR                           
Forgot Password
Reset Password
Fill out the form below and reset your password: