From 7674536713aaa3721ddb55e43ddf50585a4f20a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9rome=20Maes?= Date: Wed, 2 Sep 2015 14:57:30 +0200 Subject: [PATCH] [IMP] mail : message_post_with_template helper Create `message_post_with_template` helper method to factorize the simulation of a mail.compose.message wizard. Also, fix the generated attachments of mail.compose.message wizard by returning ORM command (6, 0, ids) instead of the list of attachments ids. In order to standardize the behavior of the wizard, and since the ORM support command assignation in onchange api.v8, all the x2many fields of the wizard return a command. FYI, that was tde's idea ! --- .../hr_recruitment/models/hr_recruitment.py | 15 +---------- addons/mail/models/mail_thread.py | 27 +++++++++++++++++++ addons/mail/tests/test_mail_template.py | 13 +++------ addons/mail/wizard/mail_compose_message.py | 25 ++++++++--------- .../product_email_template/models/invoice.py | 14 +--------- addons/sale/sale.py | 18 ++----------- 6 files changed, 48 insertions(+), 64 deletions(-) diff --git a/addons/hr_recruitment/models/hr_recruitment.py b/addons/hr_recruitment/models/hr_recruitment.py index 91214728f65..be3787bc651 100644 --- a/addons/hr_recruitment/models/hr_recruitment.py +++ b/addons/hr_recruitment/models/hr_recruitment.py @@ -290,20 +290,7 @@ class Applicant(models.Model): # post processing: if stage changed, post a message in the chatter if vals.get('stage_id'): if self.stage_id.template_id: - # TDENOTE: probably factorize me in a message_post_with_template generic method FIXME - composer = self.env['mail.compose.message'].with_context(active_ids=self.ids).create( - { - 'model': self._name, - 'composition_mode': 'mass_mail', - 'template_id': self.stage_id.template_id.id, - 'notify': True, - }) - values = composer.onchange_template_id( - self.stage_id.template_id.id, 'mass_mail', self._name, False)['value'] - if values.get('attachment_ids'): - values['attachment_ids'] = [(6, 0, values['attachment_ids'])] - composer.write(values) - composer.send_mail() + self.message_post_with_template(self.stage_id.template_id.id, notify=True, composition_mode='mass_mail') return res @api.model diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 52f3dc6346a..f2c829886d0 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -1663,6 +1663,33 @@ class MailThread(models.AbstractModel): self.message_subscribe([new_message.author_id.id]) return new_message + @api.multi + def message_post_with_template(self, template_id, **kwargs): + """ Helper method to send a mail with a template + :param template_id : the id of the template to render to create the body of the message + :param **kwargs : parameter to create a mail.compose.message woaerd (which inherit from mail.message) + """ + # Get composition mode, or force it according to the number of record in self + composition_mode = kwargs.get('composition_mode') + if not composition_mode: + composition_mode = 'comment' if len(self.ids) == 1 else 'mass_mail' + res_id = self.ids[0] or 0 + # Create the composer + composer = self.env['mail.compose.message'].with_context( + active_ids=self.ids, + active_model=self._name, + default_composition_mode=composition_mode, + default_model=self._name, + default_res_id=self.ids[0] or 0, + default_template_id=template_id, + ).create(kwargs) + # Simulate the onchange (like trigger in form the view) only + # when having a template in single-email mode + if template_id: + update_values = composer.onchange_template_id(template_id, composition_mode, self._name, res_id)['value'] + composer.write(update_values) + return composer.send_mail() + # ------------------------------------------------------ # Followers API # ------------------------------------------------------ diff --git a/addons/mail/tests/test_mail_template.py b/addons/mail/tests/test_mail_template.py index 1c21b1693ee..72b17ee9403 100644 --- a/addons/mail/tests/test_mail_template.py +++ b/addons/mail/tests/test_mail_template.py @@ -50,8 +50,9 @@ class TestMailTemplate(TestMail): }).create({'subject': 'Forget me subject', 'body': 'Dummy body'}) values = composer.onchange_template_id(self.email_template.id, 'comment', 'mail.channel', self.group_pigs.id)['value'] - recipients = self.env['res.partner'].browse(values['partner_ids']) - attachments = self.env['ir.attachment'].browse(values['attachment_ids']) + # this onchange return command [(6, 0, ids)] for x2many fields + recipients = self.env['res.partner'].browse(values['partner_ids'][0][2]) + attachments = self.env['ir.attachment'].browse(values['attachment_ids'][0][2]) test_recipients = self.env['res.partner'].search([('email', 'in', ['test1@example.com', 'test2@example.com'])]) | self.partner_1 | self.partner_2 | self.user_employee.partner_id test_attachments = self.env['ir.attachment'].search([('name', 'in', ['_Test_First', '_Test_Second'])]) self.assertEqual(values['subject'], self.group_pigs.name) @@ -64,13 +65,7 @@ class TestMailTemplate(TestMail): @mute_logger('openerp.addons.mail.models.mail_mail') def test_composer_template_send(self): - composer = self.env['mail.compose.message'].with_context({ - 'default_composition_mode': 'comment', - 'default_model': 'mail.channel', - 'default_res_id': self.group_pigs.id, - 'default_use_template': False, - 'default_template_id': self.email_template.id, - }).create({}).send_mail() + self.group_pigs.with_context(use_template=False).message_post_with_template(self.email_template.id, composition_mode='comment') message = self.group_pigs.message_ids[0] test_recipients = self.env['res.partner'].search([('email', 'in', ['test1@example.com', 'test2@example.com'])]) | self.partner_1 | self.partner_2 | self.user_employee.partner_id diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index 2c7c5b7894d..ac6953af348 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -94,18 +94,8 @@ class MailComposer(models.TransientModel): result['model'] = 'res.partner' result['res_id'] = self.env.user.partner_id.id - # Override to pre-fill the data when having a template in single-email mode - # and not going through the view: the on_change is not called in that case. - if result.get('composition_mode') != 'mass_mail' and self._context.get('default_template_id') and result.get('model') and result.get('res_id'): - result.update( - self.onchange_template_id( - self._context['default_template_id'], result.get('composition_mode'), - result.get('model'), result.get('res_id') - )['value'] - ) if fields is not None: [result.pop(field, None) for field in result.keys() if field not in fields] - return result @api.model @@ -330,7 +320,7 @@ class MailComposer(models.TransientModel): #------------------------------------------------------ @api.multi - @api.onchange('template_id', 'composition_mode', 'model', 'res_id') + @api.onchange('template_id') def onchange_template_id_wrapper(self): self.ensure_one() values = self.onchange_template_id(self.template_id.id, self.composition_mode, self.model, self.res_id)['value'] @@ -340,7 +330,9 @@ class MailComposer(models.TransientModel): @api.multi def onchange_template_id(self, template_id, composition_mode, model, res_id): """ - mass_mailing: we cannot render, so return the template values - - normal mode: return rendered values """ + - normal mode: return rendered values + /!\ for x2many field, this onchange return command instead of ids + """ if template_id and composition_mode == 'mass_mail': template = self.env['mail.template'].browse(template_id) fields = ['subject', 'body_html', 'email_from', 'reply_to', 'mail_server_id'] @@ -373,6 +365,15 @@ class MailComposer(models.TransientModel): if values.get('body_html'): values['body'] = values.pop('body_html') + + # This onchange should return command instead of ids for x2many field. + # ORM handle the assignation of command list on new onchange (api.v8), + # this force the complete replacement of x2many field with the (6, 0, ids) + # command and is compatible with onchange api.v7 + for field_name in values.keys(): + if self._fields[field_name].type == 'many2many' or self._fields[field_name].type == 'one2many': + values[field_name] = [(6, 0, values[field_name])] + return {'value': values} @api.multi diff --git a/addons/product_email_template/models/invoice.py b/addons/product_email_template/models/invoice.py index 74eb173607d..c93b3901fc0 100644 --- a/addons/product_email_template/models/invoice.py +++ b/addons/product_email_template/models/invoice.py @@ -17,19 +17,7 @@ class account_invoice(osv.Model): self.message_subscribe(cr, uid, [invoice.id], [invoice.partner_id.id], context=context) for line in invoice.invoice_line_ids: if line.product_id.email_template_id: - # CLEANME: should define and use a clean API: message_post with a template - composer_id = Composer.create(cr, uid, { - 'model': 'account.invoice', - 'res_id': invoice.id, - 'template_id': line.product_id.email_template_id.id, - 'composition_mode': 'comment', - }, context=context) - template_values = Composer.onchange_template_id( - cr, uid, composer_id, line.product_id.email_template_id.id, 'comment', 'account.invoice', invoice.id - )['value'] - template_values['attachment_ids'] = [(4, id) for id in template_values.get('attachment_ids', [])] - Composer.write(cr, uid, [composer_id], template_values, context=context) - Composer.send_mail(cr, uid, [composer_id], context=context) + invoice.message_post_with_template(line.product_id.email_template_id.id, composition_mode='comment') return True def invoice_validate(self, cr, uid, ids, context=None): diff --git a/addons/sale/sale.py b/addons/sale/sale.py index c39a411bf3e..515cdb393b9 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -325,22 +325,9 @@ class SaleOrder(models.Model): for order in self: email_act = order.action_quotation_send() if email_act and email_act.get('context'): - composer_obj = self.env['mail.compose.message'] email_ctx = email_act['context'] - template_values = [ - email_ctx.get('default_template_id'), - email_ctx.get('default_composition_mode'), - email_ctx.get('default_model'), - email_ctx.get('default_res_id'), - ] - composer_values = composer_obj.onchange_template_id(*template_values).get('value', {}) - if not composer_values.get('email_from'): - composer_values['email_from'] = order.company_id.email - for key in ['attachment_ids', 'partner_ids']: - if composer_values.get(key): - composer_values[key] = [(6, 0, composer_values[key])] - composer_id = composer_obj.with_context(email_ctx).create(composer_values) - composer_id.with_context(email_ctx).send_mail() + email_ctx.update(default_email_from=order.company_id.email) + order.with_context(email_ctx).message_post_with_template(email_ctx.get('default_template_id')) return True @api.multi @@ -784,4 +771,3 @@ class ProductTemplate(models.Model): ('delivery', 'Delivered quantities'), ('cost', 'Invoice based on time and material')], string='Invoicing Policy', default='order') -