diff --git a/addons/account/data/mail_template_data.xml b/addons/account/data/mail_template_data.xml index 81eb47ad08e..13f5c49d452 100644 --- a/addons/account/data/mail_template_data.xml +++ b/addons/account/data/mail_template_data.xml @@ -54,8 +54,7 @@

- - Invoice_{{ (object.name or '').replace('/','_') }}{{ object.state == 'draft' and '_draft' or '' }} + {{ object.partner_id.lang }} @@ -84,8 +83,7 @@

- - {{ (object.name or '').replace('/','-') }} + {{ object.partner_id.lang }} @@ -129,8 +127,7 @@

- - Credit_note_{{ (object.name or '').replace('/','_') }}{{ object.state == 'draft' and '_draft' or '' }} + {{ object.partner_id.lang }} diff --git a/addons/event/data/mail_template_data.xml b/addons/event/data/mail_template_data.xml index 1d5de71bdec..03d541a588d 100644 --- a/addons/event/data/mail_template_data.xml +++ b/addons/event/data/mail_template_data.xml @@ -22,8 +22,7 @@ --
Mitchell Admin
- - Foldable Badge - {{ (object.event_id.name or 'Event').replace('/','_') }} + {{ object.partner_id.lang }} @@ -254,8 +253,7 @@ - - Full Page Ticket - {{ (object.event_id.name or 'Event').replace('/','') }} + {{ object.partner_id.lang }} diff --git a/addons/loyalty/data/mail_template_data.xml b/addons/loyalty/data/mail_template_data.xml index 4c4a8597811..bba70470e01 100644 --- a/addons/loyalty/data/mail_template_data.xml +++ b/addons/loyalty/data/mail_template_data.xml @@ -34,8 +34,7 @@ - - Your Gift Card + @@ -96,8 +95,7 @@ - - Your Coupon Code + diff --git a/addons/mail/models/mail_template.py b/addons/mail/models/mail_template.py index 25c734bbac0..bccd11d813c 100644 --- a/addons/mail/models/mail_template.py +++ b/addons/mail/models/mail_template.py @@ -7,6 +7,7 @@ import logging from odoo import _, api, fields, models, tools, Command from odoo.exceptions import UserError from odoo.tools import is_html_empty +from odoo.tools.safe_eval import safe_eval, time _logger = logging.getLogger(__name__) @@ -63,10 +64,12 @@ class MailTemplate(models.Model): 'attachment_id', 'Attachments', help="You may attach files to this template, to be added to all " "emails created from this template") - report_name = fields.Char('Report Filename', translate=True, prefetch=True, - help="Name to use for the generated report file (may contain placeholders)\n" - "The extension can be omitted and will then come from the report type.") - report_template = fields.Many2one('ir.actions.report', 'Optional report to print and attach') + report_template_ids = fields.Many2many( + 'ir.actions.report', relation='mail_template_ir_actions_report_rel', + column1='mail_template_id', + column2='ir_actions_report_id', + string='Reports to print and attach', + domain="[('model', '=', model)]") # options mail_server_id = fields.Many2one('ir.mail_server', 'Outgoing Mail Server', readonly=False, help="Optional preferred server for outgoing mails. If not set, the highest " @@ -198,14 +201,14 @@ class MailTemplate(models.Model): def _generate_template_attachments(self, res_ids, render_fields, render_results=None): """ Render attachments of template 'self', returning values for records - given by 'res_ids'. Note that ``report_template`` returns values for + given by 'res_ids'. Note that ``report_template_ids`` returns values for 'attachments', as we have a list of tuple (report_name, base64 value) for those reports. It is considered as being the job of callers to transform those attachments into valid ``ir.attachment`` records. :param list res_ids: list of record IDs on which template is rendered; :param list render_fields: list of fields to render on template which - are specific to attachments, e.g. attachment_ids or report_template; + are specific to attachments, e.g. attachment_ids or report_template_ids; :param dict render_results: res_ids-based dictionary of render values. For each res_id, a dict of values based on render_fields is given @@ -215,6 +218,11 @@ class MailTemplate(models.Model): if render_results is None: render_results = {} + # generating reports is done on a per-record basis, better ensure cache + # is filled up to avoid rendering and browsing in a loop + if res_ids and 'report_template_ids' in render_fields and self.report_template_ids: + self.env[self.model].browse(res_ids) + for res_id in res_ids: values = render_results.setdefault(res_id, {}) @@ -223,27 +231,33 @@ class MailTemplate(models.Model): values['attachment_ids'] = self.attachment_ids.ids # generate attachments (reports) - if 'report_template' in render_fields and self.report_template: - report = self.report_template - - if report.report_type in ['qweb-html', 'qweb-pdf']: - report_content, report_format = self.env['ir.actions.report']._render_qweb_pdf(report, [res_id]) - else: - render_res = self.env['ir.actions.report']._render(report, [res_id]) - if not render_res: - raise UserError(_('Unsupported report type %s found.', report.report_type)) - report_content, report_format = render_res - report_content = base64.b64encode(report_content) - - report_name = self._render_field('report_name', [res_id])[res_id] - if not report_name: - report_name = 'report.' + report.report_name - ext = "." + report_format - if not report_name.endswith(ext): - report_name += ext - - values['attachments'] = [(report_name, report_content)] - elif 'report_template' in render_fields: + if 'report_template_ids' in render_fields and self.report_template_ids: + for report in self.report_template_ids: + # generate content + if report.report_type in ['qweb-html', 'qweb-pdf']: + report_content, report_format = self.env['ir.actions.report']._render_qweb_pdf(report, [res_id]) + else: + render_res = self.env['ir.actions.report']._render(report, [res_id]) + if not render_res: + raise UserError(_('Unsupported report type %s found.', report.report_type)) + report_content, report_format = render_res + report_content = base64.b64encode(report_content) + # generate name + if report.print_report_name: + report_name = safe_eval( + report.print_report_name, + { + 'object': self.env[self.model].browse(res_id), + 'time': time, + } + ) + else: + report_name = _('Report') + extension = "." + report_format + if not report_name.endswith(extension): + report_name += extension + values.setdefault('attachments', []).append((report_name, report_content)) + elif 'report_template_ids' in render_fields: values['attachments'] = [] # hook for attachments-specific computation, used currently only for accounting @@ -436,7 +450,7 @@ class MailTemplate(models.Model): 'email_cc', # recipients 'email_to', # recipients 'partner_to', # recipients - 'report_template', # attachments + 'report_template_ids', # attachments 'scheduled_date', # specific # not rendered (static) 'auto_delete', @@ -482,7 +496,7 @@ class MailTemplate(models.Model): ) # generate attachments if requested - if render_fields_set & {'attachment_ids', 'report_template'}: + if render_fields_set & {'attachment_ids', 'report_template_ids'}: template._generate_template_attachments( template_res_ids, render_fields_set, @@ -533,7 +547,7 @@ class MailTemplate(models.Model): 'model', 'partner_to', 'reply_to', - 'report_template', + 'report_template_ids', 'res_id', 'scheduled_date', 'subject', diff --git a/addons/mail/views/mail_template_views.xml b/addons/mail/views/mail_template_views.xml index 021e0dde091..0be8580fb0d 100644 --- a/addons/mail/views/mail_template_views.xml +++ b/addons/mail/views/mail_template_views.xml @@ -79,8 +79,9 @@ - - + @@ -102,7 +103,6 @@ - @@ -112,7 +112,7 @@ mail.template - + diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index b92fdb65867..3914e6be9d2 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -284,7 +284,7 @@ class MailComposer(models.TransientModel): 'mail_server_id', 'partner_ids', 'reply_to', - 'report_template', + 'report_template_ids', 'scheduled_date', 'subject', ) @@ -709,7 +709,7 @@ class MailComposer(models.TransientModel): 'email_cc', 'mail_server_id', 'partner_ids', - 'report_template', + 'report_template_ids', 'scheduled_date', ) ) @@ -906,7 +906,7 @@ class MailComposer(models.TransientModel): # some fields behave / are named differently on template model mapping = { - 'attachments': 'report_template', + 'attachments': 'report_template_ids', 'body': 'body_html', 'partner_ids': 'partner_to', } diff --git a/addons/mail/wizard/mail_template_preview.py b/addons/mail/wizard/mail_template_preview.py index 14367e1e250..6eb21551de0 100644 --- a/addons/mail/wizard/mail_template_preview.py +++ b/addons/mail/wizard/mail_template_preview.py @@ -15,7 +15,7 @@ class MailTemplatePreview(models.TransientModel): 'email_from', 'email_to', 'partner_to', - 'report_template', + 'report_template_ids', 'reply_to', 'scheduled_date', ] @@ -94,9 +94,9 @@ class MailTemplatePreview(models.TransientModel): def _set_mail_attributes(self, values=None): for field in self._MAIL_TEMPLATE_FIELDS: - if field in ('partner_to', 'report_template'): + if field in ('partner_to', 'report_template_ids'): # partner_to is used to generate partner_ids, handled here below - # report_template generates attachments, no usage here + # report_template_ids generates attachments, no usage here continue field_value = values.get(field, False) if values else self.mail_template_id[field] self[field] = field_value diff --git a/addons/purchase/data/mail_template_data.xml b/addons/purchase/data/mail_template_data.xml index 0b348044df9..3dffc957249 100644 --- a/addons/purchase/data/mail_template_data.xml +++ b/addons/purchase/data/mail_template_data.xml @@ -30,8 +30,7 @@

- - RFQ_{{ (object.name or '').replace('/','_') }} + {{ object.partner_id.lang }} @@ -69,8 +68,7 @@

- - PO_{{ (object.name or '').replace('/','_') }} + {{ object.partner_id.lang }} @@ -109,8 +107,7 @@

- - PO_{{ (object.name or '').replace('/','_') }} + {{ object.partner_id.lang }} diff --git a/addons/repair/data/mail_template_data.xml b/addons/repair/data/mail_template_data.xml index c2eb4f33f4e..cb05cf86397 100644 --- a/addons/repair/data/mail_template_data.xml +++ b/addons/repair/data/mail_template_data.xml @@ -28,8 +28,7 @@

- - {{ (object.name or '').replace('/','_') }} + {{ object.partner_id.lang }} diff --git a/addons/sale/data/mail_template_data.xml b/addons/sale/data/mail_template_data.xml index 545490d9179..be542b12212 100644 --- a/addons/sale/data/mail_template_data.xml +++ b/addons/sale/data/mail_template_data.xml @@ -39,8 +39,7 @@

- - {{ (object.name or '').replace('/','_') }} + {{ object.partner_id.lang }} @@ -234,8 +233,7 @@ - - {{ (object.name or '').replace('/','_') }} + {{ object.partner_id.lang }} diff --git a/addons/stock/data/mail_template_data.xml b/addons/stock/data/mail_template_data.xml index 778fa6ac710..e55142b507c 100644 --- a/addons/stock/data/mail_template_data.xml +++ b/addons/stock/data/mail_template_data.xml @@ -40,8 +40,7 @@

- - {{ (object.name or '').replace('/','_') }} + {{ object.partner_id.lang }} diff --git a/addons/survey/data/mail_template_data.xml b/addons/survey/data/mail_template_data.xml index 2bc37df0917..49ed3995a48 100644 --- a/addons/survey/data/mail_template_data.xml +++ b/addons/survey/data/mail_template_data.xml @@ -79,8 +79,7 @@ - - Certification Document + {{ object.partner_id.lang }} diff --git a/addons/survey/tests/test_certification_flow.py b/addons/survey/tests/test_certification_flow.py index b3fddf2d1b2..65205a5a531 100644 --- a/addons/survey/tests/test_certification_flow.py +++ b/addons/survey/tests/test_certification_flow.py @@ -128,7 +128,8 @@ class TestCertificationFlow(common.TestSurveyCommon, HttpCase): self.assertIn("User Certification for SO lines", certification_email.subject) self.assertIn("employee@example.com", certification_email.email_to) self.assertEqual(len(certification_email.attachment_ids), 1) - self.assertEqual(certification_email.attachment_ids[0].name, 'Certification Document.html') + self.assertEqual(certification_email.attachment_ids[0].name, f'Certification - {certification.title}.html', + 'Default certification report print_report_name is "Certification - %s" % (object.survey_id.display_name)') def test_randomized_certification(self): # Step: survey user creates the randomized certification diff --git a/addons/test_event_full/tests/common.py b/addons/test_event_full/tests/common.py index 7231d002406..3b748164c19 100644 --- a/addons/test_event_full/tests/common.py +++ b/addons/test_event_full/tests/common.py @@ -120,7 +120,7 @@ class TestEventFullCommon(EventCrmCase, TestSalesCommon, MockVisitor): # ------------------------------------------------------------ test_registration_report = cls.env.ref('test_event_full.event_registration_report_test') subscription_template = cls.env.ref('event.event_subscription') - subscription_template.write({'report_template': test_registration_report.id}) + subscription_template.write({'report_template_ids': [(6, 0, test_registration_report.ids)]}) cls.test_event_type = cls.env['event.type'].create({ 'auto_confirm': True, 'default_timezone': 'Europe/Paris', diff --git a/addons/test_mail/data/mail_template_data.xml b/addons/test_mail/data/mail_template_data.xml index 944a1b7a95f..f5970d9e211 100644 --- a/addons/test_mail/data/mail_template_data.xml +++ b/addons/test_mail/data/mail_template_data.xml @@ -33,6 +33,17 @@ + + diff --git a/addons/test_mail/tests/test_mail_composer.py b/addons/test_mail/tests/test_mail_composer.py index 0f47784412c..71f40256f1a 100644 --- a/addons/test_mail/tests/test_mail_composer.py +++ b/addons/test_mail/tests/test_mail_composer.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +import base64 + from ast import literal_eval from datetime import timedelta from freezegun import freeze_time @@ -61,13 +63,21 @@ class TestMailComposer(TestMailCommon, TestRecipients): additional_values={'user_id': cls.user_employee_2.id}, ) - cls.test_report = cls.env['ir.actions.report'].create({ - 'name': 'Test Report on mail test ticket', - 'model': 'mail.test.ticket', - 'report_type': 'qweb-pdf', - 'report_name': 'test_mail.mail_test_ticket_test_template', - }) - cls.test_record_report = cls.env['ir.actions.report']._render_qweb_pdf(cls.test_report, cls.test_record.ids) + cls.test_report, cls.test_report_2 = cls.env['ir.actions.report'].create([ + { + 'name': 'Test Report on Mail Test Ticket', + 'model': 'mail.test.ticket', + 'print_report_name': "'TestReport for %s' % object.name", + 'report_type': 'qweb-pdf', + 'report_name': 'test_mail.mail_test_ticket_test_template', + }, { + 'name': 'Test Report 2 on Mail Test Ticket', + 'model': 'mail.test.ticket', + 'print_report_name': "'TestReport2 for %s' % object.name", + 'report_type': 'qweb-pdf', + 'report_name': 'test_mail.mail_test_ticket_test_template_2', + } + ]) cls.test_from = '"John Doe" ' @@ -145,14 +155,13 @@ class TestComposerForm(TestMailComposer): attachment_data = self._generate_attachments_data(2, self.template._name, self.template.id) template_1 = self.template.copy({ 'attachment_ids': [(0, 0, a) for a in attachment_data], - 'report_name': 'TestReport for {{ object.name }}.html', # test cursor forces html - 'report_template': self.test_report.id, + 'report_template_ids': [(6, 0, (self.test_report + self.test_report_2).ids)], }) template_1_attachments = template_1.attachment_ids self.assertEqual(len(template_1_attachments), 2) template_2 = self.template.copy({ 'attachment_ids': False, - 'report_template': self.test_report.id, + 'report_template_ids': [(6, 0, self.test_report.ids)], }) # begins without attachments @@ -161,12 +170,12 @@ class TestComposerForm(TestMailComposer): )) self.assertEqual(len(composer_form.attachment_ids), 0) - # change template: 2 static (attachment_ids) and 1 dynamic (report) + # change template: 2 static (attachment_ids) and 2 dynamic (reports) composer_form.template_id = template_1 - self.assertEqual(len(composer_form.attachment_ids), 3) + self.assertEqual(len(composer_form.attachment_ids), 4) report_attachments = [att for att in composer_form.attachment_ids if att not in template_1_attachments] - self.assertEqual(len(report_attachments), 1) - tpl_attachments = composer_form.attachment_ids[:] - report_attachments[0] + self.assertEqual(len(report_attachments), 2) + tpl_attachments = composer_form.attachment_ids[:] - self.env['ir.attachment'].concat(*report_attachments) self.assertEqual(tpl_attachments, template_1_attachments) # change template: 0 static (attachment_ids) and 1 dynamic (report) @@ -174,15 +183,15 @@ class TestComposerForm(TestMailComposer): self.assertEqual(len(composer_form.attachment_ids), 1) report_attachments = [att for att in composer_form.attachment_ids if att not in template_1_attachments] self.assertEqual(len(report_attachments), 1) - tpl_attachments = composer_form.attachment_ids[:] - report_attachments[0] + tpl_attachments = composer_form.attachment_ids[:] - self.env['ir.attachment'].concat(*report_attachments) self.assertFalse(tpl_attachments) # change back to template 1 composer_form.template_id = template_1 - self.assertEqual(len(composer_form.attachment_ids), 3) + self.assertEqual(len(composer_form.attachment_ids), 4) report_attachments = [att for att in composer_form.attachment_ids if att not in template_1_attachments] - self.assertEqual(len(report_attachments), 1) - tpl_attachments = composer_form.attachment_ids[:] - report_attachments[0] + self.assertEqual(len(report_attachments), 2) + tpl_attachments = composer_form.attachment_ids[:] - self.env['ir.attachment'].concat(*report_attachments) self.assertEqual(tpl_attachments, template_1_attachments) # reset template @@ -362,16 +371,21 @@ class TestComposerInternals(TestMailComposer): attachment_data = self._generate_attachments_data(3, self.template._name, self.template.id) self.template.write({ 'attachment_ids': [(0, 0, a) for a in attachment_data], - 'report_name': 'TestReport for {{ object.name }}.html', # test cursor forces html - 'report_template': self.test_report.id, + 'report_template_ids': [(6, 0, (self.test_report + self.test_report_2).ids)], }) template_void = self.template.copy(default={ 'attachment_ids': False, - 'report_name': False, - 'report_template': False, + 'report_template_ids': False, }) attachs = self.env['ir.attachment'].search([('name', 'in', [a['name'] for a in attachment_data])]) self.assertEqual(len(attachs), 3) + extra_attach = self.env['ir.attachment'].create({ + 'datas': base64.b64encode(b'ExtraData'), + 'mimetype': 'text/plain', + 'name': 'ExtraAttFileName.txt', + 'res_model': False, + 'res_id': False, + }) for composition_mode, batch in (('comment', False), ('comment', True), ('mass_mail', False), ('mass_mail', True)): @@ -391,14 +405,16 @@ class TestComposerInternals(TestMailComposer): # values coming from template: attachment_ids + report in comment if composition_mode == 'comment' and not batch: - self.assertEqual(len(composer.attachment_ids), 4) + self.assertEqual(len(composer.attachment_ids), 5) for attach in attachs: self.assertIn(attach, composer.attachment_ids) generated = composer.attachment_ids - attachs - self.assertEqual(len(generated), 1, 'MailComposer: should have 1 additional attachment for report') - self.assertEqual(generated.name, f'TestReport for {self.test_record.name}.html') - self.assertEqual(generated.res_model, 'mail.compose.message') - self.assertEqual(generated.res_id, 0) + self.assertEqual(len(generated), 2, 'MailComposer: should have 2 additional attachments for reports') + self.assertEqual( + sorted(generated.mapped('name')), + sorted([f'TestReport for {self.test_record.name}.html', f'TestReport2 for {self.test_record.name}.html'])) + self.assertEqual(generated.mapped('res_model'), ['mail.compose.message'] * 2) + self.assertEqual(generated.mapped('res_id'), [0] * 2) # values coming from template: attachment_ids only (report is dynamic) else: self.assertEqual( @@ -406,16 +422,25 @@ class TestComposerInternals(TestMailComposer): sorted(attachs.ids) ) + # manual update + composer.write({ + 'attachment_ids': [(4, extra_attach.id)], + }) + if composition_mode == 'comment' and not batch: + self.assertEqual(composer.attachment_ids, attachs + extra_attach + generated) + else: + self.assertEqual(composer.attachment_ids, attachs + extra_attach) + # update with template with void values: values are kept composer.write({'template_id': template_void.id}) # currently onchange necessary composer._onchange_template_id_wrapper() if composition_mode == 'comment' and not batch: - self.assertEqual(composer.attachment_ids, attachs + generated, + self.assertEqual(composer.attachment_ids, attachs + extra_attach + generated, 'TODO: Values are kept (should be reset ?)') else: - self.assertEqual(composer.attachment_ids, attachs, + self.assertEqual(composer.attachment_ids, attachs + extra_attach, 'TODO: Values are kept (should be reset ?)') # reset template: values are kept @@ -424,10 +449,10 @@ class TestComposerInternals(TestMailComposer): composer._onchange_template_id_wrapper() if composition_mode == 'comment' and not batch: - self.assertEqual(composer.attachment_ids, attachs + generated, + self.assertEqual(composer.attachment_ids, attachs + extra_attach + generated, 'TODO: Values are kept (should be reset ?)') else: - self.assertEqual(composer.attachment_ids, attachs, + self.assertEqual(composer.attachment_ids, attachs + extra_attach, 'TODO: Values are kept (should be reset ?)') @users('employee') @@ -973,8 +998,7 @@ class TestComposerInternals(TestMailComposer): def test_mail_composer_rights_attachments(self): """ Ensure a user without write access to a template can send an email""" template_1 = self.template.copy({ - 'report_name': 'TestReport for {{ object.name }} (thanks TDE).html', # test cursor forces html - 'report_template': self.test_report.id, + 'report_template_ids': [(6, 0, self.test_report.ids)], }) attachment_data = self._generate_attachments_data(2, self.template._name, self.template.id) template_1.write({ @@ -986,7 +1010,7 @@ class TestComposerInternals(TestMailComposer): template_1_attachments = template_1.attachment_ids self.assertEqual(len(template_1_attachments), 2) - template_1_attachment_name = list(template_1_attachments.mapped('name')) + ["TestReport for TestRecord (thanks TDE).html"] + template_1_attachment_name = list(template_1_attachments.mapped('name')) + [f"TestReport for {self.test_record.name}.html"] composer = self.env['mail.compose.message'].with_context( self._get_web_context(self.test_record) @@ -1243,8 +1267,7 @@ class TestComposerResultsComment(TestMailComposer, CronMixinCase): 'email_to': '%s, %s, %s' % (email_to_1, email_to_2, email_to_3), 'email_cc': email_cc_1, 'partner_to': '%s, {{ object.customer_id.id if object.customer_id else "" }}' % self.partner_admin.id, - 'report_name': 'TestReport for {{ object.name }}', # test cursor forces html - 'report_template': self.test_report.id, + 'report_template_ids': [(6, 0, (self.test_report + self.test_report_2).ids)], }) attachs = self.env['ir.attachment'].search([('name', 'in', [a['name'] for a in attachment_data])]) self.assertEqual(len(attachs), 2) @@ -1346,6 +1369,7 @@ class TestComposerResultsComment(TestMailComposer, CronMixinCase): {'name': 'AttFileName_00.txt', 'raw': b'AttContent_00', 'type': 'text/plain'}, {'name': 'AttFileName_01.txt', 'raw': b'AttContent_01', 'type': 'text/plain'}, {'name': f'TestReport for {test_record.name}.html', 'type': 'text/plain'}, + {'name': f'TestReport2 for {test_record.name}.html', 'type': 'text/plain'}, ] }, fields_values={ @@ -1363,6 +1387,7 @@ class TestComposerResultsComment(TestMailComposer, CronMixinCase): {'name': 'AttFileName_00.txt', 'raw': b'AttContent_00', 'type': 'text/plain'}, {'name': 'AttFileName_01.txt', 'raw': b'AttContent_01', 'type': 'text/plain'}, {'name': f'TestReport for {test_record.name}.html', 'type': 'text/plain'}, + {'name': f'TestReport2 for {test_record.name}.html', 'type': 'text/plain'}, ] }, fields_values={ @@ -1376,7 +1401,9 @@ class TestComposerResultsComment(TestMailComposer, CronMixinCase): # attachments are copied on message and linked to document self.assertEqual( set(message.attachment_ids.mapped('name')), - set(['AttFileName_00.txt', 'AttFileName_01.txt', f'TestReport for {test_record.name}.html']) + set(['AttFileName_00.txt', 'AttFileName_01.txt', + f'TestReport for {test_record.name}.html', + f'TestReport2 for {test_record.name}.html']) ) self.assertEqual(set(message.attachment_ids.mapped('res_model')), set([test_record._name])) self.assertEqual(set(message.attachment_ids.mapped('res_id')), set(test_record.ids)) @@ -1611,8 +1638,7 @@ class TestComposerResultsMass(TestMailComposer): 'email_to': '%s, %s, %s' % (email_to_1, email_to_2, email_to_3), 'email_cc': email_cc_1, 'partner_to': '%s, {{ object.customer_id.id if object.customer_id else "" }}' % self.partner_admin.id, - 'report_name': 'TestReport for {{ object.name }}', # test cursor forces html - 'report_template': self.test_report.id, + 'report_template_ids': [(6, 0, self.test_report.ids)], }) attachs = self.env['ir.attachment'].search([('name', 'in', [a['name'] for a in attachment_data])]) self.assertEqual(len(attachs), 2) diff --git a/addons/website_slides/models/slide_channel.py b/addons/website_slides/models/slide_channel.py index 1399299fbdb..f86f527a9b0 100644 --- a/addons/website_slides/models/slide_channel.py +++ b/addons/website_slides/models/slide_channel.py @@ -145,7 +145,7 @@ class ChannelUsersRelation(models.Model): 'model', 'partner_to', 'reply_to', - 'report_template', + 'report_template_ids', 'res_id', 'scheduled_date', 'subject',