def rating_apply(self, rate, token=None, feedback=None, subtype=None): """ Apply a rating given a token. If the current model inherits from mail.thread mixing, a message is posted on its chatter. :param rate : the rating value to apply :type rate : float :param token : access token :param feedback : additional feedback :type feedback : string :param subtype : subtype for mail :type subtype : string :returns rating.rating record """ Rating, rating = self.env['rating.rating'], None if token: rating = self.env['rating.rating'].search([('access_token', '=', token)], limit=1) else: rating = Rating.search([('res_model', '=', self._name), ('res_id', '=', self.ids[0])], limit=1) if rating: rating.write({'rating': rate, 'feedback': feedback, 'consumed': True}) if hasattr(self, 'message_post'): feedback = tools.plaintext2html(feedback or '') self.message_post( body="<img src='/rating/static/src/img/rating_%s.png' alt=':%s/10' style='width:18px;height:18px;float:left;margin-right: 5px;'/>%s" % (rate, rate, feedback), subtype=subtype or "mail.mt_comment", author_id=rating.partner_id and rating.partner_id.id or None # None will set the default author in mail_thread.py ) if hasattr(self, 'stage_id') and self.stage_id and hasattr(self.stage_id, 'auto_validation_kanban_state') and self.stage_id.auto_validation_kanban_state: if rating.rating > 5: self.write({'kanban_state': 'done'}) if rating.rating < 5: self.write({'kanban_state': 'blocked'}) return rating
def portal_chatter_post(self, res_model, res_id, message, redirect=None, attachment_ids='', attachment_tokens='', **kw): """Create a new `mail.message` with the given `message` and/or `attachment_ids` and redirect the user to the newly created message. The message will be associated to the record `res_id` of the model `res_model`. The user must have access rights on this target document or must provide valid identifiers through `kw`. See `_message_post_helper`. """ url = redirect or (request.httprequest.referrer and request.httprequest.referrer + "#discussion") or '/my' res_id = int(res_id) attachment_ids = [int(attachment_id) for attachment_id in attachment_ids.split(',') if attachment_id] attachment_tokens = [attachment_token for attachment_token in attachment_tokens.split(',') if attachment_token] self._portal_post_check_attachments(attachment_ids, attachment_tokens) if message or attachment_ids: # message is received in plaintext and saved in html if message: message = plaintext2html(message) post_values = { 'res_model': res_model, 'res_id': res_id, 'message': message, 'send_after_commit': False, 'attachment_ids': attachment_ids, } post_values.update((fname, kw.get(fname)) for fname in self._portal_post_filter_params()) message = _message_post_helper(**post_values) return request.redirect(url)
def mail_chat_post(self, uuid, message_content, **kwargs): mail_channel = request.env["mail.channel"].sudo().search( [('uuid', '=', uuid)], limit=1) if not mail_channel: return False # find the author from the user session if request.session.uid: author = request.env['res.users'].sudo().browse( request.session.uid).partner_id author_id = author.id email_from = author.email_formatted else: # If Public User, use catchall email from company author_id = False email_from = mail_channel.anonymous_name or mail_channel.create_uid.company_id.catchall # post a message without adding followers to the channel. email_from=False avoid to get author from email data body = tools.plaintext2html(message_content) message = mail_channel.with_context( mail_create_nosubscribe=True).message_post( author_id=author_id, email_from=email_from, body=body, message_type='comment', subtype='mail.mt_comment') return message and message.id or False
def test_plaintext2html(self): cases = [ ("First \nSecond \nThird\n \nParagraph\n\r--\nSignature paragraph", 'div', "<div><p>First <br/>Second <br/>Third</p><p>Paragraph</p><p>--<br/>Signature paragraph</p></div>" ), ("First<p>It should be escaped</p>\nSignature", False, "<p>First<p>It should be escaped</p><br/>Signature</p>" ) ] for content, container_tag, expected in cases: html = plaintext2html(content, container_tag) self.assertEqual(html, expected, 'plaintext2html is broken')
def _message_sms(self, body, subtype_id=False, partner_ids=False, number_field=False, sms_numbers=None, sms_pid_to_number=None, **kwargs): """ Main method to post a message on a record using SMS-based notification method. :param body: content of SMS; :param subtype_id: mail.message.subtype used in mail.message associated to the sms notification process; :param partner_ids: if set is a record set of partners to notify; :param number_field: if set is a name of field to use on current record to compute a number to notify; :param sms_numbers: see ``_notify_record_by_sms``; :param sms_pid_to_number: see ``_notify_record_by_sms``; """ self.ensure_one() sms_pid_to_number = sms_pid_to_number if sms_pid_to_number is not None else {} if number_field or (partner_ids is False and sms_numbers is None): info = self._sms_get_recipients_info(force_field=number_field)[self.id] info_partner_ids = info['partner'].ids if info['partner'] else False info_number = info['sanitized'] if info['sanitized'] else info['number'] if info_partner_ids and info_number: sms_pid_to_number[info_partner_ids[0]] = info_number if info_partner_ids: partner_ids = info_partner_ids + (partner_ids or []) if info_number and not info_partner_ids: sms_numbers = [info_number] + (sms_numbers or []) if subtype_id is False: subtype_id = self.env['ir.model.data'].xmlid_to_res_id('mail.mt_note') return self.message_post( body=plaintext2html(html2plaintext(body)), partner_ids=partner_ids or [], # TDE FIXME: temp fix otherwise crash mail_thread.py message_type='sms', subtype_id=subtype_id, sms_numbers=sms_numbers, sms_pid_to_number=sms_pid_to_number, **kwargs )
def mail_update_message(self, res_model, res_id, message, message_id, redirect=None, attachment_ids='', attachment_tokens='', **post): # keep this mecanism intern to slide currently (saas 12.5) as it is # considered experimental if res_model != 'slide.channel': raise Forbidden() res_id = int(res_id) attachment_ids = [ int(attachment_id) for attachment_id in attachment_ids.split(',') if attachment_id ] attachment_tokens = [ attachment_token for attachment_token in attachment_tokens.split(',') if attachment_token ] self._portal_post_check_attachments(attachment_ids, attachment_tokens) pid = int(post['pid']) if post.get('pid') else False if not _check_special_access(res_model, res_id, token=post.get('token'), _hash=post.get('hash'), pid=pid): raise Forbidden() # fetch and update mail.message message_id = int(message_id) message_body = plaintext2html(message) domain = [('model', '=', res_model), ('res_id', '=', res_id), ('website_published', '=', True), ('author_id', '=', request.env.user.partner_id.id), ('message_type', '=', 'comment'), ('id', '=', message_id)] # restrict to the given message_id message = request.env['mail.message'].search(domain, limit=1) if not message: raise NotFound() message.write({ 'body': message_body, 'attachment_ids': [(4, aid) for aid in attachment_ids], }) # update rating if post.get('rating_value'): domain = [('res_model', '=', res_model), ('res_id', '=', res_id), ('website_published', '=', True), ('message_id', '=', message.id)] rating = request.env['rating.rating'].search( domain, order='write_date DESC', limit=1) rating.write({ 'rating': float(post['rating_value']), 'feedback': html2plaintext(message.body), }) # redirect to specified or referrer or simply channel page as fallback redirect_url = redirect or (request.httprequest.referrer and request.httprequest.referrer + '#review') or '/slides/%s' % res_id return werkzeug.utils.redirect(redirect_url, 302)