- Home
- >> Nerd Digest
- >> OpenERP
Your account has been flagged due to frequent spamming, you are not permitted to post comments. Contact admin@findnerd.com.
-
How to perform a super with count as False, to have the ids, not a counter in Odoo?
over 8 years ago
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.
ids = super(mail_message, self)._search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=False, access_rights_uid=access_rights_uid) if not ids and count: return 0 elif not ids: return ids pid = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=context).partner_id.id author_ids, partner_ids, allowed_ids = set([]), set([]), set([]) model_ids = {} messages = super(mail_message, self).read(cr, uid, ids, ['author_id', 'model', 'res_id', 'notified_partner_ids'], context=context) for message in messages: if message.get('author_id') and message.get('author_id')[0] == pid: author_ids.add(message.get('id')) elif pid in message.get('notified_partner_ids'): partner_ids.add(message.get('id')) elif message.get('model') and message.get('res_id'): model_ids.setdefault(message.get('model'), {}).setdefault(message.get('res_id'), set()).add(message.get('id')) allowed_ids = self._find_allowed_doc_ids(cr, uid, model_ids, context=context) final_ids = author_ids | partner_ids | allowed_ids if count: return len(final_ids) else: # re-construct a list based on ids, because set did not keep the original order id_list = [id for id in ids if id in final_ids] return id_list def check_access_rule(self, cr, uid, ids, operation, context=None): """ Access rules of mail.message: - read: if - author_id == pid, uid is the author, OR - mail_notification (id, pid) exists, uid has been notified, OR - uid have read access to the related document if model, res_id - otherwise: raise - create: if - no model, no res_id, I create a private message OR - pid in message_follower_ids if model, res_id OR - mail_notification (parent_id.id, pid) exists, uid has been notified of the parent, OR - uid have write or create access on the related document if model, res_id, OR - otherwise: raise - write: if - author_id == pid, uid is the author, OR - uid has write or create access on the related document if model, res_id - otherwise: raise - unlink: if - uid has write or create access on the related document if model, res_id - otherwise: raise """ def _generate_model_record_ids(msg_val, msg_ids=[]): """ :param model_record_ids: {'model': {'res_id': (msg_id, msg_id)}, ... } :param message_values: {'msg_id': {'model': .., 'res_id': .., 'author_id': ..}} """ model_record_ids = {} for id in msg_ids: vals = msg_val.get(id, {}) if vals.get('model') and vals.get('res_id'): model_record_ids.setdefault(vals['model'], set()).add(vals['res_id']) return model_record_ids if uid == SUPERUSER_ID: return if isinstance(ids, (int, long)): ids = [ids] not_obj = self.pool.get('mail.notification') fol_obj = self.pool.get('mail.followers') partner_id = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=None).partner_id.id # Read mail_message.ids to have their values message_values = dict.fromkeys(ids, {}) cr.execute('SELECT DISTINCT id, model, res_id, author_id, parent_id FROM "%s" WHERE id = ANY (%%s)' % self._table, (ids,)) for id, rmod, rid, author_id, parent_id in cr.fetchall(): message_values[id] = {'model': rmod, 'res_id': rid, 'author_id': author_id, 'parent_id': parent_id} # Author condition (READ, WRITE, CREATE (private)) -> could become an ir.rule ? author_ids = [] if operation == 'read' or operation == 'write': author_ids = [mid for mid, message in message_values.iteritems() if message.get('author_id') and message.get('author_id') == partner_id] elif operation == 'create': author_ids = [mid for mid, message in message_values.iteritems() if not message.get('model') and not message.get('res_id')] # Parent condition, for create (check for received notifications for the created message parent) notified_ids = [] if operation == 'create': parent_ids = [message.get('parent_id') for mid, message in message_values.iteritems() if message.get('parent_id')] not_ids = not_obj.search(cr, SUPERUSER_ID, [('message_id.id', 'in', parent_ids), ('partner_id', '=', partner_id)], context=context) not_parent_ids = [notif.message_id.id for notif in not_obj.browse(cr, SUPERUSER_ID, not_ids, context=context)] notified_ids += [mid for mid, message in message_values.iteritems() if message.get('parent_id') in not_parent_ids] # 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 other_ids = set(ids).difference(set(author_ids), set(notified_ids)) model_record_ids = _generate_model_record_ids(message_values, other_ids) if operation == 'read': not_ids = not_obj.search(cr, SUPERUSER_ID, [ ('partner_id', '=', partner_id), ('message_id', 'in', ids), ], context=context) notified_ids = [notification.message_id.id for notification in not_obj.browse(cr, SUPERUSER_ID, not_ids, context=context)] elif operation == 'create': for doc_model, doc_ids in model_record_ids.items(): fol_ids = fol_obj.search(cr, SUPERUSER_ID, [ ('res_model', '=', doc_model), ('res_id', 'in', list(doc_ids)), ('partner_id', '=', partner_id), ], context=context) fol_mids = [follower.res_id for follower in fol_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context)] notified_ids += [mid for mid, message in message_values.iteritems() if message.get('model') == doc_model and message.get('res_id') in fol_mids] # CRUD: Access rights related to the document other_ids = other_ids.difference(set(notified_ids)) model_record_ids = _generate_model_record_ids(message_values, other_ids) document_related_ids = [] for model, doc_ids in model_record_ids.items(): model_obj = self.pool[model] mids = model_obj.exists(cr, uid, list(doc_ids)) if hasattr(model_obj, 'check_mail_message_access'): model_obj.check_mail_message_access(cr, uid, mids, operation, context=context) else: self.pool['mail.thread'].check_mail_message_access(cr, uid, mids, operation, model_obj=model_obj, context=context) document_related_ids += [mid for mid, message in message_values.iteritems() if message.get('model') == model and message.get('res_id') in mids] # Calculate remaining ids: if not void, raise an error other_ids = other_ids.difference(set(document_related_ids)) if not other_ids: return raise orm.except_orm(_('Access Denied'), _('The requested operation cannot be completed due to security restrictions. Please contact your system administrator.\n\n(Document type: %s, Operation: %s)') % \ (self._description, operation)) def _get_record_name(self, cr, uid, values, context=None): """ Return the related document name, using name_get. It is done using SUPERUSER_ID, to be sure to have the record name correctly stored. """ if not values.get('model') or not values.get('res_id') or values['model'] not in self.pool: return False return self.pool[values['model']].name_get(cr, SUPERUSER_ID, [values['res_id']], context=context)[0][1] def _get_reply_to(self, cr, uid, values, context=None): """ Return a specific reply_to: alias of the document through message_get_reply_to or take the email_from """ email_reply_to = None ir_config_parameter = self.pool.get("ir.config_parameter") catchall_domain = ir_config_parameter.get_param(cr, uid, "mail.catchall.domain", context=context) # model, res_id, email_from: comes from values OR related message model, res_id, email_from = values.get('model'), values.get('res_id'), values.get('email_from') # if model and res_id: try to use ``message_get_reply_to`` that returns the document alias if not email_reply_to and model and res_id and catchall_domain and hasattr(self.pool[model], 'message_get_reply_to'): email_reply_to = self.pool[model].message_get_reply_to(cr, uid, [res_id], context=context)[0] # no alias reply_to -> catchall alias if not email_reply_to and catchall_domain: catchall_alias = ir_config_parameter.get_param(cr, uid, "mail.catchall.alias", context=context) if catchall_alias: email_reply_to = '%s@%s' % (catchall_alias, catchall_domain) # still no reply_to -> reply_to will be the email_from if not email_reply_to and email_from: email_reply_to = email_from # format 'Document name <email_address>' if email_reply_to and model and res_id: emails = tools.email_split(email_reply_to) if emails: email_reply_to = emails[0] document_name = self.pool[model].name_get(cr, SUPERUSER_ID, [res_id], context=context)[0] if document_name: # sanitize document name sanitized_doc_name = re.sub(r'[^\w+.]+', '-', document_name[1]) # generate reply to email_reply_to = _('"Followers of %s" <%s>') % (sanitized_doc_name, email_reply_to) return email_reply_to def _get_message_id(self, cr, uid, values, context=None): if values.get('reply_to'): message_id = tools.generate_tracking_message_id('reply_to') elif values.get('res_id') and values.get('model'): message_id = tools.generate_tracking_message_id('%(res_id)s-%(model)s' % values) else: message_id = tools.generate_tracking_message_id('private') return message_id def create(self, cr, uid, values, context=None): if context is None: context = {} default_starred = context.pop('default_starred', False) if 'email_from' not in values: # needed to compute reply_to values['email_from'] = self._get_default_from(cr, uid, context=context) if 'message_id' not in values: values['message_id'] = self._get_message_id(cr, uid, values, context=context) if 'reply_to' not in values: values['reply_to'] = self._get_reply_to(cr, uid, values, context=context) if 'record_name' not in values and 'default_record_name' not in context: values['record_name'] = self._get_record_name(cr, uid, values, context=context) newid = super(mail_message, self).create(cr, uid, values, context) self._notify(cr, uid, newid, context=context, force_send=context.get('mail_notify_force_send', True), user_signature=context.get('mail_notify_user_signature', True)) # TDE FIXME: handle default_starred. Why not setting an inv on starred ? # Because starred will call set_message_starred, that looks for notifications. # When creating a new mail_message, it will create a notification to a message # that does not exist, leading to an error (key not existing). Also this # this means unread notifications will be created, yet we can not assure # this is what we want. if default_starred: self.set_message_starred(cr, uid, [newid], True, context=context) return newid def read(self, cr, uid, ids, fields=None, context=None, load='_classic_read'): """ Override to explicitely call check_access_rule, that is not called by the ORM. It instead directly fetches ir.rules and apply them. """ self.check_access_rule(cr, uid, ids, 'read', context=context) res = super(mail_message, self).read(cr, uid, ids, fields=fields, context=context, load=load) return res def unlink(self, cr, uid, ids, context=None): # cascade-delete attachments that are directly attached to the message (should only happen # for mail.messages that act as parent for a standalone mail.mail record). self.check_access_rule(cr, uid, ids, 'unlink', context=context) attachments_to_delete = [] for message in self.browse(cr, uid, ids, context=context): for attach in message.attachment_ids: if attach.res_model == self._name and (attach.res_id == message.id or attach.res_id == 0): attachments_to_delete.append(attach.id) if attachments_to_delete: self.pool.get('ir.attachment').unlink(cr, uid, attachments_to_delete, context=context) return super(mail_message, self).unlink(cr, uid, ids, context=context) def copy(self, cr, uid, id, default=None, context=None): """ Overridden to avoid duplicating fields that are unique to each email """ if default is None: default = {} default.update(message_id=False, headers=False) return super(mail_message, self).copy(cr, uid, id, default=default, context=context) #------------------------------------------------------ # Messaging API #------------------------------------------------------ def _notify(self, cr, uid, newid, context=None, force_send=False, user_signature=True): """ Add the related record followers to the destination partner_ids if is not a private message. Call mail_notification.notify to manage the email sending """ notification_obj = self.pool.get('mail.notification') message = self.browse(cr, uid, newid, context=context) partners_to_notify = set([]) # all followers of the mail.message document have to be added as partners and notified if a subtype is defined (otherwise: log message) if message.subtype_id and message.model and message.res_id: fol_obj = self.pool.get("mail.followers") # browse as SUPERUSER because rules could restrict the search results fol_ids = fol_obj.search( cr, SUPERUSER_ID, [ ('res_model', '=', message.model), ('res_id', '=', message.res_id), ], context=context) partners_to_notify |= set( fo.partner_id.id for fo in fol_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context) if message.subtype_id.id in [st.id for st in fo.subtype_ids] ) # remove me from notified partners, unless the message is written on my own wall if message.subtype_id and message.author_id and message.model == "res.partner" and message.res_id == message.author_id.id: partners_to_notify |= set([message.author_id.id]) elif message.author_id: partners_to_notify -= set([message.author_id.id]) # all partner_ids of the mail.message have to be notified regardless of the above (even the author if explicitly added!) if message.partner_ids: partners_to_notify |= set([p.id for p in message.partner_ids]) # notify notification_obj._notify( cr, uid, newid, partners_to_notify=list(partners_to_notify), context=context, force_send=force_send, user_signature=user_signature ) message.refresh() # An error appear when a user receive a notification without notifying # the parent message -> add a read notification for the parent if message.parent_id: # all notified_partner_ids of the mail.message have to be notified for the parented messages partners_to_parent_notify = set(message.notified_partner_ids).difference(message.parent_id.notified_partner_ids) for partner in partners_to_parent_notify: notification_obj.create(cr, uid, { 'message_id': message.parent_id.id, 'partner_id': partner.id, 'read': True, }, context=context)
Comment on it
Insert an Image
To select an image, click on it.
Image path:
Example : https://wmd-editor.com/images/cloud1.jpg
0 Comment(s)