diff --git a/mail_template_attach_existing_attachment/README.rst b/mail_template_attach_existing_attachment/README.rst new file mode 100644 index 0000000000..abb1a40344 --- /dev/null +++ b/mail_template_attach_existing_attachment/README.rst @@ -0,0 +1,115 @@ +======================================== +Mail Template Attach Existing Attachment +======================================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:357b69bbbb54f796331009fc359e4aa8162a9efb1d806396d930e1ef3f23659e + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fsocial-lightgray.png?logo=github + :target: https://github.com/OCA/social/tree/17.0/mail_template_attach_existing_attachment + :alt: OCA/social +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/social-17-0/social-17-0-mail_template_attach_existing_attachment + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/social&target_branch=17.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module, based on mail_attach_existing_attachment allow to define +`REGular EXpression `__ to +pre-select existing attachment that matched with file name to send in +compose mail. + +This module is designed to work in mass mailing to select proper files +to attached from mail template configuration. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +- Configure attachment name pattern (regex) on email template advanced + setting (menu: Settings > Technical > Emails > Templates) + +|image1| + +.. |image1| image:: https://raw.githubusercontent.com/OCA/social/17.0/mail_template_attach_existing_attachment/static/description/email-template.png + +Usage +===== + +To use this module, you need to: + +- Adding some attachments on an object + +|image1| + +- Then, by sending the object via email, you can see existing attachment + matching the regex are selected by default from chosen configured + template + +|image2| + +-------------- + +Using in mass mailing existing attachements matching configured regex +will be part of the mail. + +.. |image1| image:: https://raw.githubusercontent.com/OCA/social/17.0/mail_template_attach_existing_attachment/static/description/attachment.png +.. |image2| image:: https://raw.githubusercontent.com/OCA/social/17.0/mail_template_attach_existing_attachment/static/description/mail_compose_message.png + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Pierre Verkest + +Contributors +------------ + +- Pierre Verkest + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/social `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/mail_template_attach_existing_attachment/__init__.py b/mail_template_attach_existing_attachment/__init__.py new file mode 100644 index 0000000000..9b4296142f --- /dev/null +++ b/mail_template_attach_existing_attachment/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizard diff --git a/mail_template_attach_existing_attachment/__manifest__.py b/mail_template_attach_existing_attachment/__manifest__.py new file mode 100644 index 0000000000..1ca513060a --- /dev/null +++ b/mail_template_attach_existing_attachment/__manifest__.py @@ -0,0 +1,15 @@ +# Copyright 2022 Foodles (http://www.foodles.co). +# @author Pierre Verkest +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "Mail Template Attach Existing Attachment", + "summary": "Select default attachement to send with regex set on mail template", + "author": "Pierre Verkest, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/social", + "category": "Social Network", + "version": "17.0.1.0.0", + "license": "AGPL-3", + "depends": ["mail_attach_existing_attachment"], + "data": ["views/mail_template.xml"], + "installable": True, +} diff --git a/mail_template_attach_existing_attachment/i18n/fr.po b/mail_template_attach_existing_attachment/i18n/fr.po new file mode 100644 index 0000000000..ac9c5e204a --- /dev/null +++ b/mail_template_attach_existing_attachment/i18n/fr.po @@ -0,0 +1,66 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mail_template_attach_existing_attachment +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: mail_template_attach_existing_attachment +#: model:ir.model.fields,field_description:mail_template_attach_existing_attachment.field_mail_template__attach_exist_document_regex +msgid "Attachment name pattern (regex)" +msgstr "Regex: ajout docs existants" + +#. module: mail_template_attach_existing_attachment +#: model:ir.model.fields,field_description:mail_template_attach_existing_attachment.field_mail_compose_message__display_name +#: model:ir.model.fields,field_description:mail_template_attach_existing_attachment.field_mail_template__display_name +msgid "Display Name" +msgstr "Nom affiché" + +#. module: mail_template_attach_existing_attachment +#: model:ir.model,name:mail_template_attach_existing_attachment.model_mail_template +msgid "Email Templates" +msgstr "Modèles d'emails" + +#. module: mail_template_attach_existing_attachment +#: model:ir.model,name:mail_template_attach_existing_attachment.model_mail_compose_message +msgid "Email composition wizard" +msgstr "Assistant de composition d'emails" + +#. module: mail_template_attach_existing_attachment +#: model:ir.model.fields,field_description:mail_template_attach_existing_attachment.field_mail_compose_message__id +#: model:ir.model.fields,field_description:mail_template_attach_existing_attachment.field_mail_template__id +msgid "ID" +msgstr "ID" + +#. module: mail_template_attach_existing_attachment +#: model:ir.model.fields,field_description:mail_template_attach_existing_attachment.field_mail_compose_message____last_update +#: model:ir.model.fields,field_description:mail_template_attach_existing_attachment.field_mail_template____last_update +msgid "Last Modified on" +msgstr "Dernière modification le" + +#. module: mail_template_attach_existing_attachment +#: model:ir.model.fields,help:mail_template_attach_existing_attachment.field_mail_template__attach_exist_document_regex +msgid "" +"REGular EXpression to find existing document (base on file name) to attach " +"in mass mailing or by default in mail composer" +msgstr "" +"Expression régulière (regex) utilisé pour joindre les documents liés " +"existants a ajouter aux pièces jointes. L'expression est testé sur le nom de " +"fichier (name)." + +#. module: mail_template_attach_existing_attachment +#: code:addons/.src/social/mail_template_attach_existing_attachment/models/mail_template.py:0 +#: code:addons/mail_template_attach_existing_attachment/models/mail_template.py:0 +#, python-format +msgid "The following regular expression is invalid to select attachment: %s" +msgstr "" +"L'expression régulière est invalide pour trouver les noms de fichiers: %s" diff --git a/mail_template_attach_existing_attachment/i18n/mail_template_attach_existing_attachment.pot b/mail_template_attach_existing_attachment/i18n/mail_template_attach_existing_attachment.pot new file mode 100644 index 0000000000..8670cbddb2 --- /dev/null +++ b/mail_template_attach_existing_attachment/i18n/mail_template_attach_existing_attachment.pot @@ -0,0 +1,61 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * mail_template_attach_existing_attachment +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: mail_template_attach_existing_attachment +#: model:ir.model.fields,field_description:mail_template_attach_existing_attachment.field_mail_template__attach_exist_document_regex +msgid "Attachment name pattern (regex)" +msgstr "" + +#. module: mail_template_attach_existing_attachment +#: model:ir.model.fields,field_description:mail_template_attach_existing_attachment.field_mail_compose_message__display_name +#: model:ir.model.fields,field_description:mail_template_attach_existing_attachment.field_mail_template__display_name +msgid "Display Name" +msgstr "" + +#. module: mail_template_attach_existing_attachment +#: model:ir.model,name:mail_template_attach_existing_attachment.model_mail_template +msgid "Email Templates" +msgstr "" + +#. module: mail_template_attach_existing_attachment +#: model:ir.model,name:mail_template_attach_existing_attachment.model_mail_compose_message +msgid "Email composition wizard" +msgstr "" + +#. module: mail_template_attach_existing_attachment +#: model:ir.model.fields,field_description:mail_template_attach_existing_attachment.field_mail_compose_message__id +#: model:ir.model.fields,field_description:mail_template_attach_existing_attachment.field_mail_template__id +msgid "ID" +msgstr "" + +#. module: mail_template_attach_existing_attachment +#: model:ir.model.fields,field_description:mail_template_attach_existing_attachment.field_mail_compose_message____last_update +#: model:ir.model.fields,field_description:mail_template_attach_existing_attachment.field_mail_template____last_update +msgid "Last Modified on" +msgstr "" + +#. module: mail_template_attach_existing_attachment +#: model:ir.model.fields,help:mail_template_attach_existing_attachment.field_mail_template__attach_exist_document_regex +msgid "" +"REGular EXpression to find existing document (base on file name) to attach " +"in mass mailing or by default in mail composer" +msgstr "" + +#. module: mail_template_attach_existing_attachment +#: code:addons/.src/social/mail_template_attach_existing_attachment/models/mail_template.py:0 +#: code:addons/mail_template_attach_existing_attachment/models/mail_template.py:0 +#, python-format +msgid "The following regular expression is invalid to select attachment: %s" +msgstr "" diff --git a/mail_template_attach_existing_attachment/models/__init__.py b/mail_template_attach_existing_attachment/models/__init__.py new file mode 100644 index 0000000000..44e83956eb --- /dev/null +++ b/mail_template_attach_existing_attachment/models/__init__.py @@ -0,0 +1 @@ +from . import mail_template diff --git a/mail_template_attach_existing_attachment/models/mail_template.py b/mail_template_attach_existing_attachment/models/mail_template.py new file mode 100644 index 0000000000..73b156147d --- /dev/null +++ b/mail_template_attach_existing_attachment/models/mail_template.py @@ -0,0 +1,36 @@ +# Copyright 2022 Foodles (http://www.foodles.co). +# @author Pierre Verkest +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +import re + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError + + +class MailTemplate(models.Model): + "Templates for sending email" + + _inherit = "mail.template" + + attach_exist_document_regex = fields.Char( + string="Attachment name pattern (regex)", + help=( + "REGular EXpression to find existing document (base on file name) " + "to attach in mass mailing or by default in mail composer" + ), + ) + + @api.constrains("attach_exist_document_regex") + def validate_regex(self): + for record in self: + try: + if record.attach_exist_document_regex: + re.compile(record.attach_exist_document_regex) + except re.error as re_error: + raise ValidationError( + _( + "The following regular expression is invalid to " + "select attachment: %s" + ) + % record.attach_exist_document_regex + ) from re_error diff --git a/mail_template_attach_existing_attachment/pyproject.toml b/mail_template_attach_existing_attachment/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/mail_template_attach_existing_attachment/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/mail_template_attach_existing_attachment/readme/CONFIGURE.md b/mail_template_attach_existing_attachment/readme/CONFIGURE.md new file mode 100644 index 0000000000..a69b841b24 --- /dev/null +++ b/mail_template_attach_existing_attachment/readme/CONFIGURE.md @@ -0,0 +1,4 @@ +- Configure attachment name pattern (regex) on email template advanced + setting (menu: Settings \> Technical \> Emails \> Templates) + +![](../static/description/email-template.png) diff --git a/mail_template_attach_existing_attachment/readme/CONTRIBUTORS.md b/mail_template_attach_existing_attachment/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..5396196590 --- /dev/null +++ b/mail_template_attach_existing_attachment/readme/CONTRIBUTORS.md @@ -0,0 +1 @@ +- Pierre Verkest \ diff --git a/mail_template_attach_existing_attachment/readme/DESCRIPTION.md b/mail_template_attach_existing_attachment/readme/DESCRIPTION.md new file mode 100644 index 0000000000..3d7040320f --- /dev/null +++ b/mail_template_attach_existing_attachment/readme/DESCRIPTION.md @@ -0,0 +1,7 @@ +This module, based on mail_attach_existing_attachment allow to define +[REGular EXpression](https://docs.python.org/3/library/re.html) to +pre-select existing attachment that matched with file name to send in +compose mail. + +This module is designed to work in mass mailing to select proper files +to attached from mail template configuration. diff --git a/mail_template_attach_existing_attachment/readme/USAGE.md b/mail_template_attach_existing_attachment/readme/USAGE.md new file mode 100644 index 0000000000..d8454fc6d4 --- /dev/null +++ b/mail_template_attach_existing_attachment/readme/USAGE.md @@ -0,0 +1,16 @@ +To use this module, you need to: + +- Adding some attachments on an object + +![](../static/description/attachment.png) + +- Then, by sending the object via email, you can see existing attachment + matching the regex are selected by default from chosen configured + template + +![](../static/description/mail_compose_message.png) + +--- + +Using in mass mailing existing attachements matching configured regex +will be part of the mail. diff --git a/mail_template_attach_existing_attachment/static/description/attachment.png b/mail_template_attach_existing_attachment/static/description/attachment.png new file mode 100644 index 0000000000..a74d6e3b82 Binary files /dev/null and b/mail_template_attach_existing_attachment/static/description/attachment.png differ diff --git a/mail_template_attach_existing_attachment/static/description/email-template.png b/mail_template_attach_existing_attachment/static/description/email-template.png new file mode 100644 index 0000000000..d09d042f2c Binary files /dev/null and b/mail_template_attach_existing_attachment/static/description/email-template.png differ diff --git a/mail_template_attach_existing_attachment/static/description/index.html b/mail_template_attach_existing_attachment/static/description/index.html new file mode 100644 index 0000000000..a00b94c679 --- /dev/null +++ b/mail_template_attach_existing_attachment/static/description/index.html @@ -0,0 +1,457 @@ + + + + + +Mail Template Attach Existing Attachment + + + +
+

Mail Template Attach Existing Attachment

+ + +

Beta License: AGPL-3 OCA/social Translate me on Weblate Try me on Runboat

+

This module, based on mail_attach_existing_attachment allow to define +REGular EXpression +to pre-select existing attachment that matched with file name to send in +compose mail.

+

This module is designed to work in mass mailing to select proper +files to attached from mail template configuration.

+

Table of contents

+ +
+

Configuration

+
    +
  • Configure attachment name pattern (regex) on email template advanced setting +(menu: Settings > Technical > Emails > Templates)
  • +
+
+Configured res partner email template +
+
+
+

Usage

+

To use this module, you need to:

+
    +
  • Adding some attachments on an object
  • +
+
+Attachment on res partner +
+
    +
  • Then, by sending the object via email, you can see existing attachment +matching the regex are selected by default from chosen configured template
  • +
+
+Sends the partner message +
+

+

Using in mass mailing existing attachements matching configured regex +will be part of the mail.

+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Pierre Verkest
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/social project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/mail_template_attach_existing_attachment/static/description/mail_compose_message.png b/mail_template_attach_existing_attachment/static/description/mail_compose_message.png new file mode 100644 index 0000000000..e2669e0650 Binary files /dev/null and b/mail_template_attach_existing_attachment/static/description/mail_compose_message.png differ diff --git a/mail_template_attach_existing_attachment/tests/__init__.py b/mail_template_attach_existing_attachment/tests/__init__.py new file mode 100644 index 0000000000..8d8fe1ccd4 --- /dev/null +++ b/mail_template_attach_existing_attachment/tests/__init__.py @@ -0,0 +1 @@ +from . import test_template_mail_attach_existing_attachment diff --git a/mail_template_attach_existing_attachment/tests/test_template_mail_attach_existing_attachment.py b/mail_template_attach_existing_attachment/tests/test_template_mail_attach_existing_attachment.py new file mode 100644 index 0000000000..db46dc59f7 --- /dev/null +++ b/mail_template_attach_existing_attachment/tests/test_template_mail_attach_existing_attachment.py @@ -0,0 +1,254 @@ +# Copyright 2022 Foodles (http://www.foodles.co). +# @author Pierre Verkest +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo.exceptions import ValidationError +from odoo.tests.common import Form, TransactionCase + +from odoo.addons.mail.tests.common import MockEmail + + +class TestTemplateAttachExistingAttachment(TransactionCase, MockEmail): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.template = cls.env["mail.template"].create( + { + "name": "Test template", + "subject": "TEST", + "body_html": '', + "lang": "{{ object.lang }}", + "auto_delete": True, + "model_id": cls.env.ref("base.model_res_partner").id, + } + ) + cls.template.subject = "TEST" + cls.partner_01 = cls.env["res.partner"].create( + { + "name": "Partner 1", + "email": "partner1@example.org", + } + ) + cls.partner_02 = cls.env["res.partner"].create( + { + "name": "Partner 2", + "email": "partner2@example.org", + } + ) + cls.partner_03_no_attachment = cls.env["res.partner"].create( + { + "name": "Partner 3 without attachment", + "email": "partner3@example.org", + } + ) + cls.attach_p1_csv1 = cls.env["ir.attachment"].create( + { + "name": "attach1.csv", + "datas": "bWlncmF0aW9uIHRlc3Q=", + "res_model": "res.partner", + "res_id": cls.partner_01.id, + } + ) + cls.attach_p1_jpg = cls.env["ir.attachment"].create( + { + "name": "attach.jpg", + "datas": "bWlncmF0aW9uIHRlc3Q=", + "res_model": "res.partner", + "res_id": cls.partner_01.id, + } + ) + cls.attach_p1_csv2 = cls.env["ir.attachment"].create( + { + "name": "attach2.csv", + "datas": "bWlncmF0aW9uIHRlc3Q=", + "res_model": "res.partner", + "res_id": cls.partner_01.id, + } + ) + cls.attach_p1_png = cls.env["ir.attachment"].create( + { + "name": "attach.png", + "datas": "bWlncmF0aW9uIHRlc3Q=", + "res_model": "res.partner", + "res_id": cls.partner_01.id, + } + ) + cls.attach_p2_csv = cls.env["ir.attachment"].create( + { + "name": "attach.csv", + "datas": "bWlncmF0aW9uIHRlc3Q=", + "res_model": "res.partner", + "res_id": cls.partner_02.id, + } + ) + cls.attach_p2_png = cls.env["ir.attachment"].create( + { + "name": "attach.png", + "datas": "bWlncmF0aW9uIHRlc3Q=", + "res_model": "res.partner", + "res_id": cls.partner_02.id, + } + ) + + def _get_composer_context(self, records, mass_mail=False, overwrite=None): + """Inspired from + addons.test_mail.tests.test_mail_composer:TestMailComposer._get_web_context + """ + if not overwrite: + overwrite = {} + ctx = dict( + default_model=records._name, + active_model=records._name, + active_id=records[0].id, + default_composition_mode="mass_mail" if mass_mail else "comment", + mail_auto_delete=False, + default_template_id=self.template.id, + ) + if mass_mail: + ctx["active_ids"] = records.ids + else: + ctx["default_res_ids"] = self.partner_01.ids + ctx.update(overwrite) + return ctx + + def test_wrong_pattern_raises(self): + with self.assertRaisesRegex( + ValidationError, + r"The following regular expression is invalid to select attachment: *", + ): + self.template.attach_exist_document_regex = "*" + + def test_default_images_attachments_from_template(self): + self.template.attach_exist_document_regex = ".*.[png|jpg]" + with Form( + self.env["mail.compose.message"].with_context( + **self._get_composer_context( + self.partner_01, overwrite={"default_template_id": None} + ) + ) + ) as composer: + self.assertEqual(len(composer.object_attachment_ids), 0) + composer.template_id = self.template + self.assertEqual(len(composer.object_attachment_ids), 2) + composed_mail = composer.save() + self.assertEqual( + composed_mail.object_attachment_ids, + (self.attach_p1_jpg | self.attach_p1_png), + ) + + def test_clear_default_images_attachments_changing_template(self): + self.template.attach_exist_document_regex = ".*.[png|jpg]" + with Form( + self.env["mail.compose.message"].with_context( + **self._get_composer_context(self.partner_01) + ) + ) as composer: + self.assertEqual(len(composer.object_attachment_ids), 2) + composer.template_id = self.env["mail.template"].browse() + self.assertEqual(len(composer.object_attachment_ids), 0) + + def test_send_email_with_default_and_manual_extra_attachment(self): + self.template.attach_exist_document_regex = ".*.[png|jpg]" + with Form( + self.env["mail.compose.message"].with_context( + **self._get_composer_context(self.partner_01) + ) + ) as composer: + composer.object_attachment_ids.add(self.attach_p1_csv1) + self.assertEqual(len(composer.object_attachment_ids), 3) + composed_mail = composer.save() + + self.assertEqual(len(composed_mail.object_attachment_ids), 3) + self.assertEqual( + composed_mail.object_attachment_ids, + (self.attach_p1_png | self.attach_p1_jpg | self.attach_p1_csv1), + ) + + with self.mock_mail_gateway(): + composed_mail.action_send_mail() + + self.assertEqual( + self.partner_01.message_ids[0].attachment_ids, + (self.attach_p1_png | self.attach_p1_jpg | self.attach_p1_csv1), + ) + + def test_no_pattern(self): + self.template.attach_exist_document_regex = False + with Form( + self.env["mail.compose.message"].with_context( + **self._get_composer_context(self.partner_01) + ) + ) as composer: + self.assertEqual(len(composer.object_attachment_ids), 0) + composed_mail = composer.save() + self.assertEqual(len(composed_mail.object_attachment_ids), 0) + + def test_send_mass_mail_with_default_extra_attachment(self): + self.template.attach_exist_document_regex = ".*.csv" + records = self.partner_01 | self.partner_02 | self.partner_03_no_attachment + composed_mail = Form( + self.env["mail.compose.message"].with_context( + **self._get_composer_context(records, mass_mail=True) + ) + ).save() + + with self.mock_mail_gateway(): + composed_mail.action_send_mail() + + self.assertEqual( + self.partner_01.message_ids[0].attachment_ids, + (self.attach_p1_csv1 | self.attach_p1_csv2), + ) + self.assertEqual( + self.partner_02.message_ids[0].attachment_ids, (self.attach_p2_csv) + ) + self.assertEqual( + len(self.partner_03_no_attachment.message_ids[0].attachment_ids), 0 + ) + + def test_mass_mailing_no_pattern(self): + self.template.attach_exist_document_regex = False + records = self.partner_01 | self.partner_02 | self.partner_03_no_attachment + composed_mail = Form( + self.env["mail.compose.message"].with_context( + **self._get_composer_context(records, mass_mail=True) + ) + ).save() + self.assertEqual(len(composed_mail.object_attachment_ids), 0) + + with self.mock_mail_gateway(): + composed_mail.action_send_mail() + + self.assertEqual(len(self.partner_01.message_ids[0].attachment_ids), 0) + self.assertEqual(len(self.partner_02.message_ids[0].attachment_ids), 0) + self.assertEqual( + len(self.partner_03_no_attachment.message_ids[0].attachment_ids), 0 + ) + + def test_switch_template_with_different_templates(self): + jpg_template = self.template + png_template = self.template.copy() + jpg_template.attach_exist_document_regex = ".*.jpg" + png_template.attach_exist_document_regex = ".*.png" + with Form( + self.env["mail.compose.message"].with_context( + **self._get_composer_context( + self.partner_01, overwrite={"default_template_id": None} + ) + ) + ) as composer: + self.assertEqual(len(composer.object_attachment_ids), 0) + composer.template_id = jpg_template + self.assertEqual(len(composer.object_attachment_ids), 1) + composed_mail = composer.save() + self.assertEqual( + composed_mail.object_attachment_ids, + self.attach_p1_jpg, + ) + composer.template_id = png_template + composed_mail = composer.save() + self.assertEqual(len(composer.object_attachment_ids), 1) + self.assertEqual( + composed_mail.object_attachment_ids, + self.attach_p1_png, + ) diff --git a/mail_template_attach_existing_attachment/views/mail_template.xml b/mail_template_attach_existing_attachment/views/mail_template.xml new file mode 100644 index 0000000000..5698d99b22 --- /dev/null +++ b/mail_template_attach_existing_attachment/views/mail_template.xml @@ -0,0 +1,16 @@ + + + + + email.template.form + mail.template + + + + + + + + + + diff --git a/mail_template_attach_existing_attachment/wizard/__init__.py b/mail_template_attach_existing_attachment/wizard/__init__.py new file mode 100644 index 0000000000..b528d997d1 --- /dev/null +++ b/mail_template_attach_existing_attachment/wizard/__init__.py @@ -0,0 +1 @@ +from . import mail_compose_message diff --git a/mail_template_attach_existing_attachment/wizard/mail_compose_message.py b/mail_template_attach_existing_attachment/wizard/mail_compose_message.py new file mode 100644 index 0000000000..8db1dc1352 --- /dev/null +++ b/mail_template_attach_existing_attachment/wizard/mail_compose_message.py @@ -0,0 +1,64 @@ +# Copyright 2022 Foodles (http://www.foodles.co). +# @author Pierre Verkest +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +import re + +from odoo import api, models, tools + +from odoo.addons.mail.tools.parser import parse_res_ids + + +class MailComposeMessage(models.TransientModel): + _inherit = "mail.compose.message" + + @api.model + def _match_attachment(self, re_pattern, model, res_ids): + """Could be nice to perform regex in sql side using PGSQL `~` operator""" + return ( + self.env["ir.attachment"] + .sudo() + .search( + [ + ("res_model", "=", model), + ("res_id", "in", res_ids), + ], + order="res_id", + ) + .filtered( + lambda attachement, pattern=re_pattern: pattern.match(attachement.name) + is not None + ) + ) + + @api.depends("composition_mode", "model", "res_domain", "res_ids", "template_id") + def _compute_attachment_ids(self): + for composer in self: + composer.object_attachment_ids = self.env["ir.attachment"].browse() + if ( + composer.template_id + and composer.template_id.attach_exist_document_regex + ): + pattern = re.compile(composer.template_id.attach_exist_document_regex) + composer.object_attachment_ids |= composer._match_attachment( + pattern, composer.model, parse_res_ids(composer.res_ids) + ) + + def _prepare_mail_values_dynamic(self, res_ids): + res = super()._prepare_mail_values_dynamic(res_ids) + self.ensure_one() + if ( + self.template_id + and self.template_id.attach_exist_document_regex + and len(res_ids) > 1 + ): + # Mass mailing case only + pattern = re.compile(self.template_id.attach_exist_document_regex) + attachment_per_res_id = tools.groupby( + self._match_attachment(pattern, self.model, res_ids), + lambda att: att.res_id, + ) + for res_id, attachments in attachment_per_res_id: + res[res_id].setdefault("attachment_ids", []).extend( + [(4, attachment.id) for attachment in attachments] + ) + return res