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
    • 337
    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.

     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)

     

 0 Comment(s)

Sign In
                           OR                           
                           OR                           
Register

Sign up using

                           OR                           
Forgot Password
Fill out the form below and instructions to reset your password will be emailed to you:
Reset Password
Fill out the form below and reset your password: