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') -