From 6dd54ebb79e529f373162e603b424f49bfab5dde Mon Sep 17 00:00:00 2001 From: Laurent Smet Date: Fri, 9 Jun 2023 11:04:30 +0000 Subject: [PATCH] [FIX] account: Create new attachments for mail message in send & print When creating the attachments for the mail.message, copy the attachments instead of linking the existing ones. That way, even if the user deletes the PDF or another business documents, the history remains the same and can be retrieved easily. X-original-commit: 7434cbe47ec58695a2dde40bcf4bd3bdaf6f1964 Part-of: odoo/odoo#125302 --- .../account/tests/test_account_move_send.py | 61 +++++++++++++++---- addons/account/wizard/account_move_send.py | 31 +++++++--- 2 files changed, 71 insertions(+), 21 deletions(-) diff --git a/addons/account/tests/test_account_move_send.py b/addons/account/tests/test_account_move_send.py index 7b3f7493b0a..9174deb39c3 100644 --- a/addons/account/tests/test_account_move_send.py +++ b/addons/account/tests/test_account_move_send.py @@ -527,6 +527,15 @@ class TestAccountMoveSend(TestAccountMoveSendCommon): ]) self.assertEqual(len(invoice_attachments), 1) + # Only one PDF linked to the invoice. + invoice_attachments = self.env['ir.attachment'].search([ + ('name', '=', pdf_report.name), + ('res_model', '=', invoice._name), + ('res_id', '=', invoice.id), + ('res_field', '=', False), + ]) + self.assertFalse(invoice_attachments) + def test_invoice_multi(self): invoice1 = self.init_invoice("out_invoice", partner=self.partner_a, amounts=[1000], post=True) invoice2 = self.init_invoice("out_invoice", partner=self.partner_b, amounts=[1000], post=True) @@ -653,13 +662,20 @@ class TestAccountMoveSend(TestAccountMoveSendCommon): # Send. wizard.action_send_and_print() message = self._get_mail_message(invoice) - self.assertRecordValues(message, [{ - 'attachment_ids': [ - manual_attachment.id, - invoice.invoice_pdf_report_id.id, - extra_attachment2.id, - ], - }]) + self.assertRecordValues(message.attachment_ids.sorted('name'), [ + { + 'name': invoice.invoice_pdf_report_id.name, + 'datas': invoice.invoice_pdf_report_id.datas, + }, + { + 'name': extra_attachment2.name, + 'datas': extra_attachment2.datas, + }, + { + 'name': manual_attachment.name, + 'datas': manual_attachment.datas, + }, + ]) # Resend. wizard = self.create_send_and_print(invoice) @@ -679,12 +695,31 @@ class TestAccountMoveSend(TestAccountMoveSendCommon): # Send. wizard.action_send_and_print() message = self._get_mail_message(invoice) - self.assertRecordValues(message, [{ - 'attachment_ids': [ - invoice.invoice_pdf_report_id.id, - extra_attachment2.id, - ], - }]) + self.assertRecordValues(message.attachment_ids.sorted('name'), [ + { + 'name': invoice.invoice_pdf_report_id.name, + 'datas': invoice.invoice_pdf_report_id.datas, + }, + { + 'name': extra_attachment2.name, + 'datas': extra_attachment2.datas, + }, + ]) + + # Manually remove the attachment and check the mail's attachments are not removed. + invoice_pdf_report_name = invoice.invoice_pdf_report_id.name + invoice_pdf_report_datas = invoice.invoice_pdf_report_id.datas + invoice.invoice_pdf_report_id.unlink() + self.assertRecordValues(message.attachment_ids.sorted('name'), [ + { + 'name': invoice_pdf_report_name, + 'datas': invoice_pdf_report_datas, + }, + { + 'name': extra_attachment2.name, + 'datas': extra_attachment2.datas, + }, + ]) def test_proforma_pdf(self): invoice = self.init_invoice("out_invoice", amounts=[1000], post=True) diff --git a/addons/account/wizard/account_move_send.py b/addons/account/wizard/account_move_send.py index f980135edf6..cdfa66e9bf6 100644 --- a/addons/account/wizard/account_move_send.py +++ b/addons/account/wizard/account_move_send.py @@ -404,7 +404,7 @@ class AccountMoveSend(models.Model): partner_ids = kwargs.get('partner_ids', []) mail_template = self.mail_template_id - move\ + new_message = move\ .with_context( no_new_invoice=True, mail_notify_author=self.env.user.partner_id.id in partner_ids, @@ -421,6 +421,12 @@ class AccountMoveSend(models.Model): }, ) + # Prevent duplicated attachments linked to the invoice. + new_message.attachment_ids.write({ + 'res_model': new_message._name, + 'res_id': new_message.id, + }) + def _get_mail_params(self, move): self.ensure_one() @@ -429,17 +435,25 @@ class AccountMoveSend(models.Model): # We must ensure the newly created PDF are added. At this point, the PDF has been generated but not added # to 'mail_attachments_widget'. - attachment_ids = list(set([ - x['id'] - for x in self.mail_attachments_widget + self._get_invoice_extra_attachments_data(self.move_ids) - if not x.get('placeholder') - ])) + seen_attachment_ids = set() + for attachment_data in self._get_invoice_extra_attachments_data(self.move_ids) + self.mail_attachments_widget: + try: + attachment_id = int(attachment_data['id']) + except ValueError: + continue + + seen_attachment_ids.add(attachment_id) + + mail_attachments = [ + (attachment.name, attachment.raw) + for attachment in self.env['ir.attachment'].browse(list(seen_attachment_ids)) + ] return { 'body': self.mail_body, 'subject': self.mail_subject, 'partner_ids': self.mail_partner_ids.ids, - 'attachment_ids': attachment_ids, + 'attachments': mail_attachments, } def _send_mails(self, moves_data): @@ -454,7 +468,8 @@ class AccountMoveSend(models.Model): continue if move_data.get('proforma_pdf_attachment'): - mail_params['attachment_ids'].append(move_data['proforma_pdf_attachment'].id) + attachment = move_data['proforma_pdf_attachment'] + mail_params['attachments'].append((attachment.name, attachment.raw)) mail_lang = form.mail_lang email_from = form._get_mail_default_field_value_from_template(mail_template, mail_lang, move, 'email_from')