From bb4e1b6e744927ce1860302ab9ba1ff1d6ce9f2c Mon Sep 17 00:00:00 2001 From: Thierry Ducrest Date: Thu, 16 Feb 2023 15:24:21 +0100 Subject: [PATCH] Add account_invoice_auto_send_by_email --- .../__init__.py | 1 + .../__manifest__.py | 17 +++ .../data/ir_cron.xml | 18 +++ .../models/__init__.py | 2 + .../models/account_invoice_send.py | 15 +++ .../models/account_move.py | 36 ++++++ .../readme/CONTRIBUTORS.rst | 0 .../readme/DESCRIPTION.rst | 2 + .../tests/__init__.py | 1 + ...test_account_invoice_auto_send_by_email.py | 112 ++++++++++++++++++ .../addons/account_invoice_auto_send_by_email | 1 + .../setup.py | 6 + 12 files changed, 211 insertions(+) create mode 100644 account_invoice_auto_send_by_email/__init__.py create mode 100644 account_invoice_auto_send_by_email/__manifest__.py create mode 100644 account_invoice_auto_send_by_email/data/ir_cron.xml create mode 100644 account_invoice_auto_send_by_email/models/__init__.py create mode 100644 account_invoice_auto_send_by_email/models/account_invoice_send.py create mode 100644 account_invoice_auto_send_by_email/models/account_move.py create mode 100644 account_invoice_auto_send_by_email/readme/CONTRIBUTORS.rst create mode 100644 account_invoice_auto_send_by_email/readme/DESCRIPTION.rst create mode 100644 account_invoice_auto_send_by_email/tests/__init__.py create mode 100644 account_invoice_auto_send_by_email/tests/test_account_invoice_auto_send_by_email.py create mode 120000 setup/account_invoice_auto_send_by_email/odoo/addons/account_invoice_auto_send_by_email create mode 100644 setup/account_invoice_auto_send_by_email/setup.py diff --git a/account_invoice_auto_send_by_email/__init__.py b/account_invoice_auto_send_by_email/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/account_invoice_auto_send_by_email/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/account_invoice_auto_send_by_email/__manifest__.py b/account_invoice_auto_send_by_email/__manifest__.py new file mode 100644 index 00000000000..232740808a6 --- /dev/null +++ b/account_invoice_auto_send_by_email/__manifest__.py @@ -0,0 +1,17 @@ +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +{ + "name": "Account Invoice Auto Send By Email", + "summary": "Invoice with the email transmit method are send automatically.", + "version": "14.0.1.0.0", + "category": "Accounting", + "author": "Camptocamp, Odoo Community Association (OCA)", + "license": "AGPL-3", + "depends": ["account", "account_invoice_transmit_method", "queue_job"], + "website": "https://github.com/OCA/account-invoicing", + "data": [ + "data/ir_cron.xml", + ], + "installable": True, +} diff --git a/account_invoice_auto_send_by_email/data/ir_cron.xml b/account_invoice_auto_send_by_email/data/ir_cron.xml new file mode 100644 index 00000000000..8f0465678f5 --- /dev/null +++ b/account_invoice_auto_send_by_email/data/ir_cron.xml @@ -0,0 +1,18 @@ + + + + + + Account Invoice: Send email invoice + 1 + days + -1 + + + + code + model.cron_send_email_invoice() + + + diff --git a/account_invoice_auto_send_by_email/models/__init__.py b/account_invoice_auto_send_by_email/models/__init__.py new file mode 100644 index 00000000000..acc8de77390 --- /dev/null +++ b/account_invoice_auto_send_by_email/models/__init__.py @@ -0,0 +1,2 @@ +from . import account_move +from . import account_invoice_send diff --git a/account_invoice_auto_send_by_email/models/account_invoice_send.py b/account_invoice_auto_send_by_email/models/account_invoice_send.py new file mode 100644 index 00000000000..e1c511e435c --- /dev/null +++ b/account_invoice_auto_send_by_email/models/account_invoice_send.py @@ -0,0 +1,15 @@ +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) +from odoo import models + + +class AccountInvoiceSend(models.TransientModel): + _inherit = "account.invoice.send" + + def _get_ui_options(self): + return { + "is_print": self.is_print, + "is_email": self.is_email, + "template_id": self.template_id.id, + "composition_mode": "mass_mail", + } diff --git a/account_invoice_auto_send_by_email/models/account_move.py b/account_invoice_auto_send_by_email/models/account_move.py new file mode 100644 index 00000000000..3e4a86b877b --- /dev/null +++ b/account_invoice_auto_send_by_email/models/account_move.py @@ -0,0 +1,36 @@ +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from odoo import _, api, models + + +class AccountMove(models.Model): + _inherit = "account.move" + + def cron_send_email_invoice(self): + invoices = self.search(self._email_invoice_to_send_domain()) + for invoice in invoices: + description = "Send invoice {} by email".format(invoice.name) + invoice.with_delay(description=description)._execute_invoice_sent_wizard() + + def _execute_invoice_sent_wizard(self, options=None): + self.ensure_one() + if self.is_move_sent: + return _("This invoice has already been sent.") + res = self.action_invoice_sent() + wiz_ctx = res["context"] or {} + wiz_ctx["active_model"] = self._name + wiz_ctx["active_ids"] = self.ids + wiz = self.env["account.invoice.send"].with_context(**wiz_ctx).create({}) + wiz.write(wiz._get_ui_options()) + return wiz.send_and_print_action() + + @api.model + def _email_invoice_to_send_domain(self): + return [ + ("move_type", "in", ("out_invoice", "out_refund")), + ("state", "=", "posted"), + ("is_move_sent", "=", False), + ("transmit_method_code", "=", "mail"), + ("payment_state", "=", "not_paid"), + ] diff --git a/account_invoice_auto_send_by_email/readme/CONTRIBUTORS.rst b/account_invoice_auto_send_by_email/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000000..e69de29bb2d diff --git a/account_invoice_auto_send_by_email/readme/DESCRIPTION.rst b/account_invoice_auto_send_by_email/readme/DESCRIPTION.rst new file mode 100644 index 00000000000..aaa74ca3d2d --- /dev/null +++ b/account_invoice_auto_send_by_email/readme/DESCRIPTION.rst @@ -0,0 +1,2 @@ +This module will on a daily basis send all invoices with `email` as transmit method. +That are posted and not yet send. The email is send with the use of queue job. diff --git a/account_invoice_auto_send_by_email/tests/__init__.py b/account_invoice_auto_send_by_email/tests/__init__.py new file mode 100644 index 00000000000..c067d900285 --- /dev/null +++ b/account_invoice_auto_send_by_email/tests/__init__.py @@ -0,0 +1 @@ +from . import test_account_invoice_auto_send_by_email diff --git a/account_invoice_auto_send_by_email/tests/test_account_invoice_auto_send_by_email.py b/account_invoice_auto_send_by_email/tests/test_account_invoice_auto_send_by_email.py new file mode 100644 index 00000000000..c14a19df79a --- /dev/null +++ b/account_invoice_auto_send_by_email/tests/test_account_invoice_auto_send_by_email.py @@ -0,0 +1,112 @@ +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) +import mock + +from odoo.tests.common import SavepointCase + + +class TestAccountInvoiceAutoSendByEmail(SavepointCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env( + context=dict( + cls.env.context, tracking_disable=True, test_queue_job_no_delay=True + ) + ) + + cls.AccountMove = cls.env["account.move"] + cls.AccountMove.search([]).write({"transmit_method_code": ""}) + cls.company = cls.env.user.company_id + cls.transmit_method = cls.env.ref("account_invoice_transmit_method.mail") + cls.env["account.journal"].create( + {"name": "Test sale journal", "type": "sale", "code": "tsj"} + ) + cls.customer = cls.env.ref("base.res_partner_1") + cls.receivable_account = cls.env["account.account"].search( + [ + ( + "user_type_id", + "=", + cls.env.ref("account.data_account_type_receivable").id, + ), + ("company_id", "=", cls.env.company.id), + ], + limit=1, + ) + cls.income_account = cls.env["account.account"].search( + [ + ( + "user_type_id", + "=", + cls.env.ref("account.data_account_type_current_liabilities").id, + ), + ("company_id", "=", cls.env.company.id), + ], + limit=1, + ) + cls.bank = cls.env.ref("base.res_bank_1") + cls.partner_bank = cls.env["res.partner.bank"].create( + { + "bank_id": cls.bank.id, + "acc_number": "300.300.300", + "acc_holder_name": "AccountHolderName", + "partner_id": cls.company.partner_id.id, + } + ) + cls.invoice = cls.AccountMove.create( + { + "move_type": "out_invoice", + "partner_id": cls.customer.id, + "partner_bank_id": cls.partner_bank.id, + "transmit_method_id": cls.transmit_method.id, + "line_ids": [ + ( + 0, + 0, + { + "quantity": 3, + "price_unit": 4.0, + "debit": 12, + "credit": 0, + "name": "Some service", + "account_id": cls.receivable_account.id, + }, + ), + ( + 0, + 0, + { + "debit": 0, + "credit": 12, + "name": "inv", + "account_id": cls.income_account.id, + }, + ), + ], + } + ) + cls.invoice.action_post() + cls.invoice.write({"payment_state": "not_paid"}) + + @mock.patch( + "odoo.addons.base.models.ir_actions_report.IrActionsReport._render_qweb_pdf" + ) + def test_send_email_invoice_cron(self, mocked): + # We don't care about the content of the invoice report + mocked.return_value = (b"Whatever gets printed", "pdf") + moves = self.AccountMove.search( + self.AccountMove._email_invoice_to_send_domain() + ) + self.assertEqual(len(moves), 1) + self.AccountMove.cron_send_email_invoice() + moves = self.AccountMove.search( + self.AccountMove._email_invoice_to_send_domain() + ) + self.assertEqual(len(moves), 0) + self.assertTrue(self.invoice.is_move_sent) + + def test_invoice_not_send_multiple_time(self): + self.invoice.is_move_sent = True + res = self.invoice._execute_invoice_sent_wizard() + self.assertEqual(res, "This invoice has already been sent.") diff --git a/setup/account_invoice_auto_send_by_email/odoo/addons/account_invoice_auto_send_by_email b/setup/account_invoice_auto_send_by_email/odoo/addons/account_invoice_auto_send_by_email new file mode 120000 index 00000000000..4994c8ec4b3 --- /dev/null +++ b/setup/account_invoice_auto_send_by_email/odoo/addons/account_invoice_auto_send_by_email @@ -0,0 +1 @@ +../../../../account_invoice_auto_send_by_email \ No newline at end of file diff --git a/setup/account_invoice_auto_send_by_email/setup.py b/setup/account_invoice_auto_send_by_email/setup.py new file mode 100644 index 00000000000..28c57bb6403 --- /dev/null +++ b/setup/account_invoice_auto_send_by_email/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)