From b1be6bb8a75cfe9e3dd09e5508b60e5e39e99a7e Mon Sep 17 00:00:00 2001 From: Thierry Ducrest Date: Mon, 26 Sep 2022 11:02:12 +0200 Subject: [PATCH 01/18] [MIG] rename account_invoice_mode_monthly --- partner_invoicing_mode_monthly/README.rst | 0 partner_invoicing_mode_monthly/__init__.py | 2 + .../__manifest__.py | 22 + .../data/ir_cron.xml | 18 + .../data/queue_job_data.xml | 15 + .../migrations/15.0.1.0.0/pre-migrate.py | 11 + .../models/__init__.py | 4 + .../models/res_company.py | 21 + .../models/res_config_settings.py | 14 + .../models/res_partner.py | 13 + .../models/sale_order.py | 102 ++++ .../readme/CONTRIBUTORS.rst | 5 + .../readme/CREDITS.rst | 3 + .../readme/DESCRIPTION.rst | 4 + .../readme/INSTALL.rst | 0 .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 447 ++++++++++++++++++ .../tests/__init__.py | 2 + .../tests/test_invoice_mode_monthly.py | 139 ++++++ .../test_invoice_mode_monthly_is_it_today.py | 63 +++ .../views/res_config_settings_views.xml | 43 ++ 21 files changed, 928 insertions(+) create mode 100644 partner_invoicing_mode_monthly/README.rst create mode 100644 partner_invoicing_mode_monthly/__init__.py create mode 100644 partner_invoicing_mode_monthly/__manifest__.py create mode 100644 partner_invoicing_mode_monthly/data/ir_cron.xml create mode 100644 partner_invoicing_mode_monthly/data/queue_job_data.xml create mode 100644 partner_invoicing_mode_monthly/migrations/15.0.1.0.0/pre-migrate.py create mode 100644 partner_invoicing_mode_monthly/models/__init__.py create mode 100644 partner_invoicing_mode_monthly/models/res_company.py create mode 100644 partner_invoicing_mode_monthly/models/res_config_settings.py create mode 100644 partner_invoicing_mode_monthly/models/res_partner.py create mode 100644 partner_invoicing_mode_monthly/models/sale_order.py create mode 100644 partner_invoicing_mode_monthly/readme/CONTRIBUTORS.rst create mode 100644 partner_invoicing_mode_monthly/readme/CREDITS.rst create mode 100644 partner_invoicing_mode_monthly/readme/DESCRIPTION.rst create mode 100644 partner_invoicing_mode_monthly/readme/INSTALL.rst create mode 100644 partner_invoicing_mode_monthly/static/description/icon.png create mode 100644 partner_invoicing_mode_monthly/static/description/index.html create mode 100644 partner_invoicing_mode_monthly/tests/__init__.py create mode 100644 partner_invoicing_mode_monthly/tests/test_invoice_mode_monthly.py create mode 100644 partner_invoicing_mode_monthly/tests/test_invoice_mode_monthly_is_it_today.py create mode 100644 partner_invoicing_mode_monthly/views/res_config_settings_views.xml diff --git a/partner_invoicing_mode_monthly/README.rst b/partner_invoicing_mode_monthly/README.rst new file mode 100644 index 00000000000..e69de29bb2d diff --git a/partner_invoicing_mode_monthly/__init__.py b/partner_invoicing_mode_monthly/__init__.py new file mode 100644 index 00000000000..0ee8b5073e2 --- /dev/null +++ b/partner_invoicing_mode_monthly/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import tests diff --git a/partner_invoicing_mode_monthly/__manifest__.py b/partner_invoicing_mode_monthly/__manifest__.py new file mode 100644 index 00000000000..341fbf434d0 --- /dev/null +++ b/partner_invoicing_mode_monthly/__manifest__.py @@ -0,0 +1,22 @@ +# Copyright 2020 Camptocamp +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +{ + "name": "Partner Invoicing Mode Monthly", + "version": "15.0.1.0.0", + "summary": "Create invoices automatically on a monthly basis.", + "author": "Camptocamp, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/account-invoicing", + "license": "AGPL-3", + "category": "Accounting & Finance", + "depends": [ + "account", + "partner_invoicing_mode", + "queue_job", + "sale_stock", + ], + "data": [ + "data/ir_cron.xml", + "data/queue_job_data.xml", + "views/res_config_settings_views.xml", + ], +} diff --git a/partner_invoicing_mode_monthly/data/ir_cron.xml b/partner_invoicing_mode_monthly/data/ir_cron.xml new file mode 100644 index 00000000000..0410250612f --- /dev/null +++ b/partner_invoicing_mode_monthly/data/ir_cron.xml @@ -0,0 +1,18 @@ + + + + Generate Monthly Invoices + + + 1 + days + -1 + + + model.cron_generate_monthly_invoices() + + + diff --git a/partner_invoicing_mode_monthly/data/queue_job_data.xml b/partner_invoicing_mode_monthly/data/queue_job_data.xml new file mode 100644 index 00000000000..67ab12aa9c3 --- /dev/null +++ b/partner_invoicing_mode_monthly/data/queue_job_data.xml @@ -0,0 +1,15 @@ + + + + + invoice_monthly + + + + + + + _generate_invoices_by_partner + + + diff --git a/partner_invoicing_mode_monthly/migrations/15.0.1.0.0/pre-migrate.py b/partner_invoicing_mode_monthly/migrations/15.0.1.0.0/pre-migrate.py new file mode 100644 index 00000000000..1dcfedcb0bc --- /dev/null +++ b/partner_invoicing_mode_monthly/migrations/15.0.1.0.0/pre-migrate.py @@ -0,0 +1,11 @@ +# Copyright 2022 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from openupgradelib import openupgrade + + +@openupgrade.migrate(use_env=True) +def migrate(env, version): + openupgrade.update_module_names( + env.cr, [("account_invoice_mode_monthly", "partner_invoicing_mode_monthly")] + ) diff --git a/partner_invoicing_mode_monthly/models/__init__.py b/partner_invoicing_mode_monthly/models/__init__.py new file mode 100644 index 00000000000..ea64a69d2e0 --- /dev/null +++ b/partner_invoicing_mode_monthly/models/__init__.py @@ -0,0 +1,4 @@ +from . import res_company +from . import res_config_settings +from . import res_partner +from . import sale_order diff --git a/partner_invoicing_mode_monthly/models/res_company.py b/partner_invoicing_mode_monthly/models/res_company.py new file mode 100644 index 00000000000..614a77c7cc3 --- /dev/null +++ b/partner_invoicing_mode_monthly/models/res_company.py @@ -0,0 +1,21 @@ +# Copyright 2020 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from odoo import fields, models + + +class ResCompany(models.Model): + _inherit = "res.company" + + invoicing_mode_monthly_day_todo = fields.Integer( + "Invoicing Day", + default="31", + help="Day of the month to execute the invoicing. For a number higher" + "than the number of days in a month, the invoicing will be" + "executed on the last day of the month.", + ) + invoicing_mode_monthly_last_execution = fields.Datetime( + string="Last execution", + help="Last execution of monthly invoicing.", + readonly=True, + ) diff --git a/partner_invoicing_mode_monthly/models/res_config_settings.py b/partner_invoicing_mode_monthly/models/res_config_settings.py new file mode 100644 index 00000000000..a2c560c73c9 --- /dev/null +++ b/partner_invoicing_mode_monthly/models/res_config_settings.py @@ -0,0 +1,14 @@ +# Copyright 2020 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + res_invoicing_mode_monthly_day_todo = fields.Integer( + related="company_id.invoicing_mode_monthly_day_todo", readonly=False + ) + invoicing_mode_monthly_last_execution = fields.Datetime( + related="company_id.invoicing_mode_monthly_last_execution", readonly=True + ) diff --git a/partner_invoicing_mode_monthly/models/res_partner.py b/partner_invoicing_mode_monthly/models/res_partner.py new file mode 100644 index 00000000000..630a2584b32 --- /dev/null +++ b/partner_invoicing_mode_monthly/models/res_partner.py @@ -0,0 +1,13 @@ +# Copyright 2020 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from odoo import fields, models + + +class ResPartner(models.Model): + _inherit = "res.partner" + + invoicing_mode = fields.Selection( + selection_add=[("monthly", "Monthly")], + ondelete={"monthly": "set default"}, + ) diff --git a/partner_invoicing_mode_monthly/models/sale_order.py b/partner_invoicing_mode_monthly/models/sale_order.py new file mode 100644 index 00000000000..84e064729e3 --- /dev/null +++ b/partner_invoicing_mode_monthly/models/sale_order.py @@ -0,0 +1,102 @@ +# Copyright 2020 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from datetime import datetime + +from dateutil.relativedelta import relativedelta + +from odoo import api, models +from odoo.osv.expression import OR + + +class SaleOrder(models.Model): + _inherit = "sale.order" + + @api.model + def cron_generate_monthly_invoices(self): + """Cron called daily to check if monthly invoicing needs to be done.""" + company_ids = self._company_monthly_invoicing_today() + if company_ids: + self.generate_monthly_invoices(company_ids) + + @api.model + def generate_monthly_invoices(self, companies=None): + """Generate monthly invoices for customers who require that mode. + + Invoices will be generated by other jobs split for different customer + and different payment term. + """ + if not companies: + companies = self.company_id + saleorder_groups = self.read_group( + [ + ("invoicing_mode", "=", "monthly"), + ("invoice_status", "=", "to invoice"), + ("company_id", "in", companies.ids), + ], + ["partner_invoice_id"], + groupby=self._get_groupby_fields_for_monthly_invoicing(), + lazy=False, + ) + for saleorder_group in saleorder_groups: + saleorder_ids = self.search(saleorder_group["__domain"]).ids + self.with_delay()._generate_invoices_by_partner(saleorder_ids) + companies.write({"invoicing_mode_monthly_last_execution": datetime.now()}) + return saleorder_groups + + @api.model + def _get_groupby_fields_for_monthly_invoicing(self): + """Returns the sale order fields used to group them into jobs.""" + return ["partner_invoice_id", "payment_term_id"] + + def _generate_invoices_by_partner(self, saleorder_ids, invoicing_mode="monthly"): + """Generate invoices for a group of sale order belonging to a customer.""" + sales = ( + self.browse(saleorder_ids) + .exists() + .filtered(lambda r: r.invoice_status == "to invoice") + ) + if not sales: + return "No sale order found to invoice ?" + invoices = sales._create_invoices( + grouped=sales[0].partner_invoice_id.one_invoice_per_order, final=True + ) + for invoice in invoices: + invoice.with_delay()._validate_invoice() + return invoices + + @api.model + def _company_monthly_invoicing_today(self): + """Get company ids for which today is monthly invoicing day.""" + today = datetime.now() + first_day_this_month = today.replace( + day=1, hour=0, minute=0, second=0, microsecond=0 + ) + first_day_last_month = first_day_this_month - relativedelta(months=1) + last_day_of_this_month = (today + relativedelta(day=31)).day + # Last month still not executed, it needs to be done + domain_last_month = [ + ("invoicing_mode_monthly_last_execution", "<", first_day_last_month), + ] + # Invoicing day is today or in the past and invoicing not yet done + domain_this_month = [ + "|", + ("invoicing_mode_monthly_last_execution", "<", first_day_this_month), + ("invoicing_mode_monthly_last_execution", "=", False), + ("invoicing_mode_monthly_day_todo", "<=", today.day), + ] + # Make sure non exisiting days are done at the end of the month + domain_last_day_of_month = [ + "|", + ("invoicing_mode_monthly_last_execution", "<", first_day_this_month), + ("invoicing_mode_monthly_last_execution", "=", False), + ("invoicing_mode_monthly_day_todo", ">", today.day), + ] + if today.day == last_day_of_this_month: + domain = OR( + [domain_last_month, domain_this_month, domain_last_day_of_month] + ) + else: + domain = OR([domain_last_month, domain_this_month]) + + return self.env["res.company"].search(domain) diff --git a/partner_invoicing_mode_monthly/readme/CONTRIBUTORS.rst b/partner_invoicing_mode_monthly/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000000..ecddfcde7f4 --- /dev/null +++ b/partner_invoicing_mode_monthly/readme/CONTRIBUTORS.rst @@ -0,0 +1,5 @@ +* `Camptocamp `_: + + * Thierry Ducrest + +* Phuc (Tran Thanh) diff --git a/partner_invoicing_mode_monthly/readme/CREDITS.rst b/partner_invoicing_mode_monthly/readme/CREDITS.rst new file mode 100644 index 00000000000..f5cc070c78e --- /dev/null +++ b/partner_invoicing_mode_monthly/readme/CREDITS.rst @@ -0,0 +1,3 @@ +The development of this module has been financially supported by: + +* Camptocamp diff --git a/partner_invoicing_mode_monthly/readme/DESCRIPTION.rst b/partner_invoicing_mode_monthly/readme/DESCRIPTION.rst new file mode 100644 index 00000000000..acfe0b72b13 --- /dev/null +++ b/partner_invoicing_mode_monthly/readme/DESCRIPTION.rst @@ -0,0 +1,4 @@ +This module allows to select a monthly invoicing mode for a customer. +It is based on `partner_invoicing_mode`. +When this mode is selected for a customer, the customer will be automatically +invoiced diff --git a/partner_invoicing_mode_monthly/readme/INSTALL.rst b/partner_invoicing_mode_monthly/readme/INSTALL.rst new file mode 100644 index 00000000000..e69de29bb2d diff --git a/partner_invoicing_mode_monthly/static/description/icon.png b/partner_invoicing_mode_monthly/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/partner_invoicing_mode_monthly/static/description/index.html b/partner_invoicing_mode_monthly/static/description/index.html new file mode 100644 index 00000000000..58627afbb08 --- /dev/null +++ b/partner_invoicing_mode_monthly/static/description/index.html @@ -0,0 +1,447 @@ + + + + + + +Account Invoice Mode Monthly + + + +
+

Account Invoice Mode Monthly

+ + +

Beta License: AGPL-3 OCA/account-invoicing Translate me on Weblate Try me on Runbot

+

This module allows to select a monthly invoicing mode for a customer. +It is based on account_invoice_base_invoicing_mode. +When this mode is selected for a customer, the customer will be automatically +invoiced

+

Table of contents

+ +
+

Known issues / Roadmap

+

On the version 13.0 PR there is some discussion about changing how the +_company_monthly_invoicing_today works by storing the next invoicing day +to simplify the computation. +Would it be an improvment or not ? +I answered with this comment

+
+
+

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 smashing it by providing a detailed and welcomed +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • Camptocamp
  • +
+
+
+

Contributors

+ +
+
+

Other credits

+

The development of this module has been financially supported by:

+
    +
  • Camptocamp
  • +
+
+
+

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/account-invoicing project on GitHub.

+

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

+
+
+
+ + diff --git a/partner_invoicing_mode_monthly/tests/__init__.py b/partner_invoicing_mode_monthly/tests/__init__.py new file mode 100644 index 00000000000..bae1b469a28 --- /dev/null +++ b/partner_invoicing_mode_monthly/tests/__init__.py @@ -0,0 +1,2 @@ +from . import test_invoice_mode_monthly +from . import test_invoice_mode_monthly_is_it_today diff --git a/partner_invoicing_mode_monthly/tests/test_invoice_mode_monthly.py b/partner_invoicing_mode_monthly/tests/test_invoice_mode_monthly.py new file mode 100644 index 00000000000..2a9c33ef4e7 --- /dev/null +++ b/partner_invoicing_mode_monthly/tests/test_invoice_mode_monthly.py @@ -0,0 +1,139 @@ +# Copyright 2020 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from odoo import tools +from odoo.tests.common import TransactionCase + + +class TestInvoiceModeMonthly(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) + cls.SaleOrder = cls.env["sale.order"] + cls.partner = cls.env.ref("base.res_partner_1") + cls.partner.invoicing_mode = "monthly" + cls.partner2 = cls.env.ref("base.res_partner_2") + cls.partner2.invoicing_mode = "monthly" + cls.product = cls.env.ref("product.product_delivery_01") + cls.pt1 = cls.env["account.payment.term"].create({"name": "Term Two"}) + cls.pt2 = cls.env["account.payment.term"].create({"name": "Term One"}) + cls.so1 = cls.env["sale.order"].create( + { + "partner_id": cls.partner.id, + "partner_invoice_id": cls.partner.id, + "partner_shipping_id": cls.partner.id, + "payment_term_id": cls.pt1.id, + "order_line": [ + ( + 0, + 0, + { + "name": "Line one", + "product_id": cls.product.id, + "product_uom_qty": 4, + "product_uom": cls.product.uom_id.id, + "price_unit": 123, + }, + ) + ], + "pricelist_id": cls.env.ref("product.list0").id, + } + ) + # Lets give the saleorder the same partner and payment terms + cls.so2 = cls.env["sale.order"].create( + { + "partner_id": cls.partner.id, + "partner_invoice_id": cls.partner.id, + "partner_shipping_id": cls.partner.id, + "payment_term_id": cls.pt1.id, + "order_line": [ + ( + 0, + 0, + { + "name": "Line one", + "product_id": cls.product.id, + "product_uom_qty": 4, + "product_uom": cls.product.uom_id.id, + "price_unit": 123, + }, + ) + ], + "pricelist_id": cls.env.ref("product.list0").id, + } + ) + cls.company = cls.so1.company_id + + def deliver_invoice(self, sale_order): + sale_order.action_confirm() + for picking in sale_order.picking_ids: + for line in picking.move_lines: + line.quantity_done = line.product_uom_qty + picking.action_assign() + picking.button_validate() + + def test_saleorder_with_different_mode_term(self): + """Check multiple sale order one partner diverse terms.""" + self.so1.payment_term_id = self.pt1.id + self.deliver_invoice(self.so1) + self.so2.payment_term_id = self.pt2.id + self.deliver_invoice(self.so2) + with tools.mute_logger("odoo.addons.queue_job.models.base"): + self.SaleOrder.with_context( + test_queue_job_no_delay=True + ).generate_monthly_invoices(self.company) + self.assertEqual(len(self.so1.invoice_ids), 1) + self.assertEqual(len(self.so2.invoice_ids), 1) + # Two invoices because the term are different + self.assertNotEqual(self.so1.invoice_ids, self.so2.invoice_ids) + self.assertEqual(self.so1.invoice_ids.state, "posted") + + def test_saleorder_grouped_in_invoice(self): + """Check multiple sale order grouped in one invoice""" + self.deliver_invoice(self.so1) + self.deliver_invoice(self.so2) + with tools.mute_logger("odoo.addons.queue_job.models.base"): + self.SaleOrder.with_context( + test_queue_job_no_delay=True + ).generate_monthly_invoices(self.company) + self.assertEqual(len(self.so1.invoice_ids), 1) + self.assertEqual(len(self.so2.invoice_ids), 1) + # Same invoice for both order + self.assertEqual(self.so1.invoice_ids, self.so2.invoice_ids) + self.assertEqual(self.so1.invoice_ids.state, "posted") + + def test_split_invoice_by_sale_order(self): + """For same customer invoice 2 sales order separately.""" + self.partner.invoicing_mode = "monthly" + self.partner.one_invoice_per_order = True + self.deliver_invoice(self.so1) + self.deliver_invoice(self.so2) + with tools.mute_logger("odoo.addons.queue_job.models.base"): + self.SaleOrder.with_context( + test_queue_job_no_delay=True + ).generate_monthly_invoices(self.company) + self.assertEqual(len(self.so1.invoice_ids), 1) + self.assertEqual(len(self.so2.invoice_ids), 1) + # Two invoices as they must be split + self.assertNotEqual(self.so1.invoice_ids, self.so2.invoice_ids) + self.assertEqual(self.so1.invoice_ids.state, "posted") + self.assertEqual(self.so2.invoice_ids.state, "posted") + + def test_invoice_for_multiple_customer(self): + """Check two sale order for different customers.""" + self.partner.invoicing_mode = "monthly" + self.so2.partner_id = self.partner2 + self.so2.partner_invoice_id = self.partner2 + self.so2.partner_shipping_id = self.partner2 + self.deliver_invoice(self.so1) + self.deliver_invoice(self.so2) + with tools.mute_logger("odoo.addons.queue_job.models.base"): + self.SaleOrder.with_context( + test_queue_job_no_delay=True + ).generate_monthly_invoices(self.company) + self.assertEqual(len(self.so1.invoice_ids), 1) + self.assertEqual(len(self.so2.invoice_ids), 1) + self.assertNotEqual(self.so1.invoice_ids, self.so2.invoice_ids) + self.assertEqual(self.so1.invoice_ids.state, "posted") + self.assertEqual(self.so2.invoice_ids.state, "posted") diff --git a/partner_invoicing_mode_monthly/tests/test_invoice_mode_monthly_is_it_today.py b/partner_invoicing_mode_monthly/tests/test_invoice_mode_monthly_is_it_today.py new file mode 100644 index 00000000000..f3cee6fb210 --- /dev/null +++ b/partner_invoicing_mode_monthly/tests/test_invoice_mode_monthly_is_it_today.py @@ -0,0 +1,63 @@ +# Copyright 2020 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from freezegun import freeze_time + +from odoo.tests.common import TransactionCase + + +class TestInvoiceModeMonthly(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.company = cls.env.company + cls.SaleOrder = cls.env["sale.order"] + + def test_late_invoicing_for_last_month(self): + """Check that last month invoicing will be done if missed.""" + company = self.env.company + company.invoicing_mode_monthly_day_todo = 31 + company.invoicing_mode_monthly_last_execution = "2020-05-31" + self.assertTrue(self.env.company) + with freeze_time("2020-07-03"): + res = self.SaleOrder._company_monthly_invoicing_today() + self.assertTrue(res) + company.invoicing_mode_monthly_last_execution = "2020-06-30" + with freeze_time("2020-07-03"): + res = self.SaleOrder._company_monthly_invoicing_today() + self.assertFalse(res) + + def test_selected_day_not_exist_in_month(self): + """Check on last day of the month invoicing is done. + + The day of invoicing selected could not exist in the current + month, but invoicing should still be executed on the last + day of the month. + """ + company = self.env.company + company.invoicing_mode_monthly_day_todo = 31 + company.invoicing_mode_monthly_last_execution = "2020-05-29" + self.assertTrue(self.env.company) + with freeze_time("2020-06-29"): + res = self.SaleOrder._company_monthly_invoicing_today() + self.assertFalse(res) + with freeze_time("2020-06-30"): + res = self.SaleOrder._company_monthly_invoicing_today() + self.assertTrue(res) + + def test_no_invoicing_done_yet(self): + """Check when is the first monthly invoicing done. + + When monthly invoicing has never been done, it will not be run + for the previous month. + """ + company = self.env.company + company.invoicing_mode_monthly_day_todo = 15 + company.invoicing_mode_monthly_last_execution = None + self.assertTrue(self.env.company) + with freeze_time("2020-06-11"): + res = self.SaleOrder._company_monthly_invoicing_today() + self.assertFalse(res) + with freeze_time("2020-06-30"): + res = self.SaleOrder._company_monthly_invoicing_today() + self.assertTrue(res) diff --git a/partner_invoicing_mode_monthly/views/res_config_settings_views.xml b/partner_invoicing_mode_monthly/views/res_config_settings_views.xml new file mode 100644 index 00000000000..dbe09556648 --- /dev/null +++ b/partner_invoicing_mode_monthly/views/res_config_settings_views.xml @@ -0,0 +1,43 @@ + + + + + res.config.settings + +
+

Invoicing Mode

+
+
+
+
+ Monthly Invoicing Options +
+
+
+
+
+
+
+
+
+
+ + + From b51aa67b7bc5b2f9fb080d89dca476899fcfb338 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Wed, 30 Nov 2022 19:57:27 +0100 Subject: [PATCH 02/18] [IMP] partner_invoicing_mode_monthly: pre-commit stuff --- partner_invoicing_mode_monthly/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/partner_invoicing_mode_monthly/__init__.py b/partner_invoicing_mode_monthly/__init__.py index 0ee8b5073e2..0650744f6bc 100644 --- a/partner_invoicing_mode_monthly/__init__.py +++ b/partner_invoicing_mode_monthly/__init__.py @@ -1,2 +1 @@ from . import models -from . import tests From 2870cf2a95e84a9abfc4dd7712a871b53085cfdd Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Wed, 30 Nov 2022 21:12:50 +0100 Subject: [PATCH 03/18] [MIG] partner_invoicing_mode_monthly: Migration to 16.0 --- partner_invoicing_mode_monthly/README.rst | 87 +++++++++++++++++ .../__manifest__.py | 4 +- .../data/ir_cron.xml | 2 +- .../i18n/partner_invoicing_mode_monthly.pot | 94 +++++++++++++++++++ .../migrations/15.0.1.0.0/pre-migrate.py | 11 --- .../models/sale_order.py | 4 +- .../static/description/index.html | 47 ++++------ .../tests/test_invoice_mode_monthly.py | 50 ++++++++-- 8 files changed, 246 insertions(+), 53 deletions(-) create mode 100644 partner_invoicing_mode_monthly/i18n/partner_invoicing_mode_monthly.pot delete mode 100644 partner_invoicing_mode_monthly/migrations/15.0.1.0.0/pre-migrate.py diff --git a/partner_invoicing_mode_monthly/README.rst b/partner_invoicing_mode_monthly/README.rst index e69de29bb2d..c9aca7698c1 100644 --- a/partner_invoicing_mode_monthly/README.rst +++ b/partner_invoicing_mode_monthly/README.rst @@ -0,0 +1,87 @@ +============================== +Partner Invoicing Mode Monthly +============================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Faccount--invoicing-lightgray.png?logo=github + :target: https://github.com/OCA/account-invoicing/tree/16.0/partner_invoicing_mode_monthly + :alt: OCA/account-invoicing +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/account-invoicing-16-0/account-invoicing-16-0-partner_invoicing_mode_monthly + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/95/16.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows to select a monthly invoicing mode for a customer. +It is based on `partner_invoicing_mode`. +When this mode is selected for a customer, the customer will be automatically +invoiced + +**Table of contents** + +.. contents:: + :local: + +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 smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Camptocamp + +Contributors +~~~~~~~~~~~~ + +* `Camptocamp `_: + + * Thierry Ducrest + +* Phuc (Tran Thanh) + +Other credits +~~~~~~~~~~~~~ + +The development of this module has been financially supported by: + +* Camptocamp + +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/account-invoicing `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/partner_invoicing_mode_monthly/__manifest__.py b/partner_invoicing_mode_monthly/__manifest__.py index 341fbf434d0..82524b72f1c 100644 --- a/partner_invoicing_mode_monthly/__manifest__.py +++ b/partner_invoicing_mode_monthly/__manifest__.py @@ -2,16 +2,14 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { "name": "Partner Invoicing Mode Monthly", - "version": "15.0.1.0.0", + "version": "16.0.1.0.0", "summary": "Create invoices automatically on a monthly basis.", "author": "Camptocamp, Odoo Community Association (OCA)", "website": "https://github.com/OCA/account-invoicing", "license": "AGPL-3", "category": "Accounting & Finance", "depends": [ - "account", "partner_invoicing_mode", - "queue_job", "sale_stock", ], "data": [ diff --git a/partner_invoicing_mode_monthly/data/ir_cron.xml b/partner_invoicing_mode_monthly/data/ir_cron.xml index 0410250612f..b723a9369f9 100644 --- a/partner_invoicing_mode_monthly/data/ir_cron.xml +++ b/partner_invoicing_mode_monthly/data/ir_cron.xml @@ -1,6 +1,6 @@ - + Generate Monthly Invoices diff --git a/partner_invoicing_mode_monthly/i18n/partner_invoicing_mode_monthly.pot b/partner_invoicing_mode_monthly/i18n/partner_invoicing_mode_monthly.pot new file mode 100644 index 00000000000..154fd67d488 --- /dev/null +++ b/partner_invoicing_mode_monthly/i18n/partner_invoicing_mode_monthly.pot @@ -0,0 +1,94 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * partner_invoicing_mode_monthly +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.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: partner_invoicing_mode_monthly +#: model_terms:ir.ui.view,arch_db:partner_invoicing_mode_monthly.res_config_settings_view_form +msgid "Monthly Invoicing Options" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.model,name:partner_invoicing_mode_monthly.model_res_company +msgid "Companies" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.model,name:partner_invoicing_mode_monthly.model_res_config_settings +msgid "Config Settings" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.model,name:partner_invoicing_mode_monthly.model_res_partner +msgid "Contact" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.model.fields,help:partner_invoicing_mode_monthly.field_res_company__invoicing_mode_monthly_day_todo +#: model:ir.model.fields,help:partner_invoicing_mode_monthly.field_res_config_settings__res_invoicing_mode_monthly_day_todo +msgid "" +"Day of the month to execute the invoicing. For a number higherthan the " +"number of days in a month, the invoicing will beexecuted on the last day of " +"the month." +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.actions.server,name:partner_invoicing_mode_monthly.ir_cron_generate_monthly_invoice_ir_actions_server +#: model:ir.cron,cron_name:partner_invoicing_mode_monthly.ir_cron_generate_monthly_invoice +msgid "Generate Monthly Invoices" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.model.fields,field_description:partner_invoicing_mode_monthly.field_res_company__invoicing_mode_monthly_day_todo +#: model:ir.model.fields,field_description:partner_invoicing_mode_monthly.field_res_config_settings__res_invoicing_mode_monthly_day_todo +msgid "Invoicing Day" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.model.fields,field_description:partner_invoicing_mode_monthly.field_res_partner__invoicing_mode +#: model:ir.model.fields,field_description:partner_invoicing_mode_monthly.field_res_users__invoicing_mode +#: model_terms:ir.ui.view,arch_db:partner_invoicing_mode_monthly.res_config_settings_view_form +msgid "Invoicing Mode" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model_terms:ir.ui.view,arch_db:partner_invoicing_mode_monthly.res_config_settings_view_form +msgid "Invoicing day" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model_terms:ir.ui.view,arch_db:partner_invoicing_mode_monthly.res_config_settings_view_form +msgid "Last executed on" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.model.fields,field_description:partner_invoicing_mode_monthly.field_res_company__invoicing_mode_monthly_last_execution +#: model:ir.model.fields,field_description:partner_invoicing_mode_monthly.field_res_config_settings__invoicing_mode_monthly_last_execution +msgid "Last execution" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.model.fields,help:partner_invoicing_mode_monthly.field_res_company__invoicing_mode_monthly_last_execution +#: model:ir.model.fields,help:partner_invoicing_mode_monthly.field_res_config_settings__invoicing_mode_monthly_last_execution +msgid "Last execution of monthly invoicing." +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.model.fields.selection,name:partner_invoicing_mode_monthly.selection__res_partner__invoicing_mode__monthly +msgid "Monthly" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.model,name:partner_invoicing_mode_monthly.model_sale_order +msgid "Sales Order" +msgstr "" diff --git a/partner_invoicing_mode_monthly/migrations/15.0.1.0.0/pre-migrate.py b/partner_invoicing_mode_monthly/migrations/15.0.1.0.0/pre-migrate.py deleted file mode 100644 index 1dcfedcb0bc..00000000000 --- a/partner_invoicing_mode_monthly/migrations/15.0.1.0.0/pre-migrate.py +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright 2022 Camptocamp SA -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) - -from openupgradelib import openupgrade - - -@openupgrade.migrate(use_env=True) -def migrate(env, version): - openupgrade.update_module_names( - env.cr, [("account_invoice_mode_monthly", "partner_invoicing_mode_monthly")] - ) diff --git a/partner_invoicing_mode_monthly/models/sale_order.py b/partner_invoicing_mode_monthly/models/sale_order.py index 84e064729e3..486c0f0d832 100644 --- a/partner_invoicing_mode_monthly/models/sale_order.py +++ b/partner_invoicing_mode_monthly/models/sale_order.py @@ -26,8 +26,8 @@ def generate_monthly_invoices(self, companies=None): Invoices will be generated by other jobs split for different customer and different payment term. """ - if not companies: - companies = self.company_id + if companies is None: + companies = self.env.company saleorder_groups = self.read_group( [ ("invoicing_mode", "=", "monthly"), diff --git a/partner_invoicing_mode_monthly/static/description/index.html b/partner_invoicing_mode_monthly/static/description/index.html index 58627afbb08..feb8a9bdb35 100644 --- a/partner_invoicing_mode_monthly/static/description/index.html +++ b/partner_invoicing_mode_monthly/static/description/index.html @@ -4,7 +4,7 @@ -Account Invoice Mode Monthly +Partner Invoicing Mode Monthly -
-

Account Invoice Mode Monthly

+
+

Partner Invoicing Mode Monthly

-

Beta License: AGPL-3 OCA/account-invoicing Translate me on Weblate Try me on Runbot

+

Beta License: AGPL-3 OCA/account-invoicing Translate me on Weblate Try me on Runbot

This module allows to select a monthly invoicing mode for a customer. -It is based on account_invoice_base_invoicing_mode. +It is based on partner_invoicing_mode. When this mode is selected for a customer, the customer will be automatically invoiced

Table of contents

-
-

Known issues / Roadmap

-

On the version 13.0 PR there is some discussion about changing how the -_company_monthly_invoicing_today works by storing the next invoicing day -to simplify the computation. -Would it be an improvment or not ? -I answered with this comment

-
-

Bug Tracker

+

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 smashing it by providing a detailed and welcomed -feedback.

+feedback.

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

-

Credits

+

Credits

-

Authors

+

Authors

  • Camptocamp
-

Other credits

+

Other credits

The development of this module has been financially supported by:

  • Camptocamp
-

Maintainers

+

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/account-invoicing project on GitHub.

+

This module is part of the OCA/account-invoicing project on GitHub.

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

diff --git a/partner_invoicing_mode_monthly/tests/test_invoice_mode_monthly.py b/partner_invoicing_mode_monthly/tests/test_invoice_mode_monthly.py index 2a9c33ef4e7..f98d5a02c51 100644 --- a/partner_invoicing_mode_monthly/tests/test_invoice_mode_monthly.py +++ b/partner_invoicing_mode_monthly/tests/test_invoice_mode_monthly.py @@ -1,8 +1,12 @@ # Copyright 2020 Camptocamp SA # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) -from odoo import tools +from unittest import mock + from odoo.tests.common import TransactionCase +from odoo.tools import mute_logger + +from odoo.addons.partner_invoicing_mode_monthly.models.sale_order import SaleOrder class TestInvoiceModeMonthly(TransactionCase): @@ -68,10 +72,40 @@ def setUpClass(cls): def deliver_invoice(self, sale_order): sale_order.action_confirm() for picking in sale_order.picking_ids: - for line in picking.move_lines: - line.quantity_done = line.product_uom_qty + for move in picking.move_ids: + move.quantity_done = move.product_uom_qty picking.action_assign() - picking.button_validate() + picking.with_context(test_queue_job_no_delay=True).button_validate() + + def test_invoice_mode_monthly(self): + self.so1.payment_term_id = self.pt1.id + self.deliver_invoice(self.so1) + self.assertFalse(self.so1.invoice_ids) + with mute_logger("odoo.addons.queue_job.delay"): + self.SaleOrder.with_context( + test_queue_job_no_delay=True + ).generate_monthly_invoices() + self.assertTrue(self.so1.invoice_ids) + # No errors are raised when called without anything to invoice + with mute_logger("odoo.addons.queue_job.delay"): + self.SaleOrder.with_context( + test_queue_job_no_delay=True + ).generate_monthly_invoices() + + def test_invoice_mode_monthly_cron(self): + cron = self.env.ref( + "partner_invoicing_mode_monthly.ir_cron_generate_monthly_invoice" + ) + self.so1.payment_term_id = self.pt1.id + self.deliver_invoice(self.so1) + self.assertFalse(self.so1.invoice_ids) + with mute_logger("odoo.addons.queue_job.delay"), mock.patch.object( + SaleOrder, + "_company_monthly_invoicing_today", + return_value=self.so1.company_id, + ): + cron.with_context(test_queue_job_no_delay=True).ir_actions_server_id.run() + self.assertTrue(self.so1.invoice_ids) def test_saleorder_with_different_mode_term(self): """Check multiple sale order one partner diverse terms.""" @@ -79,7 +113,7 @@ def test_saleorder_with_different_mode_term(self): self.deliver_invoice(self.so1) self.so2.payment_term_id = self.pt2.id self.deliver_invoice(self.so2) - with tools.mute_logger("odoo.addons.queue_job.models.base"): + with mute_logger("odoo.addons.queue_job.delay"): self.SaleOrder.with_context( test_queue_job_no_delay=True ).generate_monthly_invoices(self.company) @@ -93,7 +127,7 @@ def test_saleorder_grouped_in_invoice(self): """Check multiple sale order grouped in one invoice""" self.deliver_invoice(self.so1) self.deliver_invoice(self.so2) - with tools.mute_logger("odoo.addons.queue_job.models.base"): + with mute_logger("odoo.addons.queue_job.delay"): self.SaleOrder.with_context( test_queue_job_no_delay=True ).generate_monthly_invoices(self.company) @@ -109,7 +143,7 @@ def test_split_invoice_by_sale_order(self): self.partner.one_invoice_per_order = True self.deliver_invoice(self.so1) self.deliver_invoice(self.so2) - with tools.mute_logger("odoo.addons.queue_job.models.base"): + with mute_logger("odoo.addons.queue_job.delay"): self.SaleOrder.with_context( test_queue_job_no_delay=True ).generate_monthly_invoices(self.company) @@ -128,7 +162,7 @@ def test_invoice_for_multiple_customer(self): self.so2.partner_shipping_id = self.partner2 self.deliver_invoice(self.so1) self.deliver_invoice(self.so2) - with tools.mute_logger("odoo.addons.queue_job.models.base"): + with mute_logger("odoo.addons.queue_job.delay"): self.SaleOrder.with_context( test_queue_job_no_delay=True ).generate_monthly_invoices(self.company) From 80ab1e18b6bb03ab728425729a8738c65673cb54 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Fri, 21 Apr 2023 00:48:39 +0000 Subject: [PATCH 04/18] partner_invoicing_mode_monthly 16.0.1.0.1 --- partner_invoicing_mode_monthly/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/partner_invoicing_mode_monthly/__manifest__.py b/partner_invoicing_mode_monthly/__manifest__.py index 82524b72f1c..e8fdfc22868 100644 --- a/partner_invoicing_mode_monthly/__manifest__.py +++ b/partner_invoicing_mode_monthly/__manifest__.py @@ -2,7 +2,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { "name": "Partner Invoicing Mode Monthly", - "version": "16.0.1.0.0", + "version": "16.0.1.0.1", "summary": "Create invoices automatically on a monthly basis.", "author": "Camptocamp, Odoo Community Association (OCA)", "website": "https://github.com/OCA/account-invoicing", From f0364b5191fb519217b68d830e518d7c585a6f3a Mon Sep 17 00:00:00 2001 From: Ivorra78 Date: Sat, 29 Jul 2023 09:09:45 +0000 Subject: [PATCH 05/18] Added translation using Weblate (Spanish) --- partner_invoicing_mode_monthly/i18n/es.po | 95 +++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 partner_invoicing_mode_monthly/i18n/es.po diff --git a/partner_invoicing_mode_monthly/i18n/es.po b/partner_invoicing_mode_monthly/i18n/es.po new file mode 100644 index 00000000000..289f3ca5601 --- /dev/null +++ b/partner_invoicing_mode_monthly/i18n/es.po @@ -0,0 +1,95 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * partner_invoicing_mode_monthly +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#. module: partner_invoicing_mode_monthly +#: model_terms:ir.ui.view,arch_db:partner_invoicing_mode_monthly.res_config_settings_view_form +msgid "Monthly Invoicing Options" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.model,name:partner_invoicing_mode_monthly.model_res_company +msgid "Companies" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.model,name:partner_invoicing_mode_monthly.model_res_config_settings +msgid "Config Settings" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.model,name:partner_invoicing_mode_monthly.model_res_partner +msgid "Contact" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.model.fields,help:partner_invoicing_mode_monthly.field_res_company__invoicing_mode_monthly_day_todo +#: model:ir.model.fields,help:partner_invoicing_mode_monthly.field_res_config_settings__res_invoicing_mode_monthly_day_todo +msgid "" +"Day of the month to execute the invoicing. For a number higherthan the " +"number of days in a month, the invoicing will beexecuted on the last day of " +"the month." +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.actions.server,name:partner_invoicing_mode_monthly.ir_cron_generate_monthly_invoice_ir_actions_server +#: model:ir.cron,cron_name:partner_invoicing_mode_monthly.ir_cron_generate_monthly_invoice +msgid "Generate Monthly Invoices" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.model.fields,field_description:partner_invoicing_mode_monthly.field_res_company__invoicing_mode_monthly_day_todo +#: model:ir.model.fields,field_description:partner_invoicing_mode_monthly.field_res_config_settings__res_invoicing_mode_monthly_day_todo +msgid "Invoicing Day" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.model.fields,field_description:partner_invoicing_mode_monthly.field_res_partner__invoicing_mode +#: model:ir.model.fields,field_description:partner_invoicing_mode_monthly.field_res_users__invoicing_mode +#: model_terms:ir.ui.view,arch_db:partner_invoicing_mode_monthly.res_config_settings_view_form +msgid "Invoicing Mode" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model_terms:ir.ui.view,arch_db:partner_invoicing_mode_monthly.res_config_settings_view_form +msgid "Invoicing day" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model_terms:ir.ui.view,arch_db:partner_invoicing_mode_monthly.res_config_settings_view_form +msgid "Last executed on" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.model.fields,field_description:partner_invoicing_mode_monthly.field_res_company__invoicing_mode_monthly_last_execution +#: model:ir.model.fields,field_description:partner_invoicing_mode_monthly.field_res_config_settings__invoicing_mode_monthly_last_execution +msgid "Last execution" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.model.fields,help:partner_invoicing_mode_monthly.field_res_company__invoicing_mode_monthly_last_execution +#: model:ir.model.fields,help:partner_invoicing_mode_monthly.field_res_config_settings__invoicing_mode_monthly_last_execution +msgid "Last execution of monthly invoicing." +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.model.fields.selection,name:partner_invoicing_mode_monthly.selection__res_partner__invoicing_mode__monthly +msgid "Monthly" +msgstr "" + +#. module: partner_invoicing_mode_monthly +#: model:ir.model,name:partner_invoicing_mode_monthly.model_sale_order +msgid "Sales Order" +msgstr "" From b652718f567b5247c159374fc6563b00b8793e32 Mon Sep 17 00:00:00 2001 From: Ivorra78 Date: Sat, 29 Jul 2023 09:13:58 +0000 Subject: [PATCH 06/18] Translated using Weblate (Spanish) Currently translated at 100.0% (14 of 14 strings) Translation: account-invoicing-16.0/account-invoicing-16.0-partner_invoicing_mode_monthly Translate-URL: https://translation.odoo-community.org/projects/account-invoicing-16-0/account-invoicing-16-0-partner_invoicing_mode_monthly/es/ --- partner_invoicing_mode_monthly/README.rst | 15 +++++--- partner_invoicing_mode_monthly/i18n/es.po | 32 +++++++++------- .../static/description/index.html | 38 ++++++++++--------- 3 files changed, 47 insertions(+), 38 deletions(-) diff --git a/partner_invoicing_mode_monthly/README.rst b/partner_invoicing_mode_monthly/README.rst index c9aca7698c1..85618e4d014 100644 --- a/partner_invoicing_mode_monthly/README.rst +++ b/partner_invoicing_mode_monthly/README.rst @@ -2,10 +2,13 @@ Partner Invoicing Mode Monthly ============================== -.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:797ada8f66de67a289ed2dd1824bdbb2662a06b115a0106f689e51fcf0c77e09 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status @@ -19,11 +22,11 @@ Partner Invoicing Mode Monthly .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png :target: https://translation.odoo-community.org/projects/account-invoicing-16-0/account-invoicing-16-0-partner_invoicing_mode_monthly :alt: Translate me on Weblate -.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/95/16.0 - :alt: Try me on Runbot +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/account-invoicing&target_branch=16.0 + :alt: Try me on Runboat -|badge1| |badge2| |badge3| |badge4| |badge5| +|badge1| |badge2| |badge3| |badge4| |badge5| This module allows to select a monthly invoicing mode for a customer. It is based on `partner_invoicing_mode`. @@ -40,7 +43,7 @@ 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 smashing it by providing a detailed and welcomed +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. diff --git a/partner_invoicing_mode_monthly/i18n/es.po b/partner_invoicing_mode_monthly/i18n/es.po index 289f3ca5601..4bcd2aebc2a 100644 --- a/partner_invoicing_mode_monthly/i18n/es.po +++ b/partner_invoicing_mode_monthly/i18n/es.po @@ -6,33 +6,35 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 16.0\n" "Report-Msgid-Bugs-To: \n" -"Last-Translator: Automatically generated\n" +"PO-Revision-Date: 2023-07-29 10:09+0000\n" +"Last-Translator: Ivorra78 \n" "Language-Team: none\n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" #. module: partner_invoicing_mode_monthly #: model_terms:ir.ui.view,arch_db:partner_invoicing_mode_monthly.res_config_settings_view_form msgid "Monthly Invoicing Options" -msgstr "" +msgstr "Opciones de facturación mensual" #. module: partner_invoicing_mode_monthly #: model:ir.model,name:partner_invoicing_mode_monthly.model_res_company msgid "Companies" -msgstr "" +msgstr "Compañías" #. module: partner_invoicing_mode_monthly #: model:ir.model,name:partner_invoicing_mode_monthly.model_res_config_settings msgid "Config Settings" -msgstr "" +msgstr "Ajustes de Configuración" #. module: partner_invoicing_mode_monthly #: model:ir.model,name:partner_invoicing_mode_monthly.model_res_partner msgid "Contact" -msgstr "" +msgstr "Contacto" #. module: partner_invoicing_mode_monthly #: model:ir.model.fields,help:partner_invoicing_mode_monthly.field_res_company__invoicing_mode_monthly_day_todo @@ -42,54 +44,56 @@ msgid "" "number of days in a month, the invoicing will beexecuted on the last day of " "the month." msgstr "" +"Día del mes para ejecutar la facturación. Si el número es mayor al numero de " +"días del mes, la facturación será ejecutada el último día del mes." #. module: partner_invoicing_mode_monthly #: model:ir.actions.server,name:partner_invoicing_mode_monthly.ir_cron_generate_monthly_invoice_ir_actions_server #: model:ir.cron,cron_name:partner_invoicing_mode_monthly.ir_cron_generate_monthly_invoice msgid "Generate Monthly Invoices" -msgstr "" +msgstr "Generar facturas mensuales" #. module: partner_invoicing_mode_monthly #: model:ir.model.fields,field_description:partner_invoicing_mode_monthly.field_res_company__invoicing_mode_monthly_day_todo #: model:ir.model.fields,field_description:partner_invoicing_mode_monthly.field_res_config_settings__res_invoicing_mode_monthly_day_todo msgid "Invoicing Day" -msgstr "" +msgstr "Día de facturación" #. module: partner_invoicing_mode_monthly #: model:ir.model.fields,field_description:partner_invoicing_mode_monthly.field_res_partner__invoicing_mode #: model:ir.model.fields,field_description:partner_invoicing_mode_monthly.field_res_users__invoicing_mode #: model_terms:ir.ui.view,arch_db:partner_invoicing_mode_monthly.res_config_settings_view_form msgid "Invoicing Mode" -msgstr "" +msgstr "Modo de facturación" #. module: partner_invoicing_mode_monthly #: model_terms:ir.ui.view,arch_db:partner_invoicing_mode_monthly.res_config_settings_view_form msgid "Invoicing day" -msgstr "" +msgstr "Día de facturación" #. module: partner_invoicing_mode_monthly #: model_terms:ir.ui.view,arch_db:partner_invoicing_mode_monthly.res_config_settings_view_form msgid "Last executed on" -msgstr "" +msgstr "Última ejecución el" #. module: partner_invoicing_mode_monthly #: model:ir.model.fields,field_description:partner_invoicing_mode_monthly.field_res_company__invoicing_mode_monthly_last_execution #: model:ir.model.fields,field_description:partner_invoicing_mode_monthly.field_res_config_settings__invoicing_mode_monthly_last_execution msgid "Last execution" -msgstr "" +msgstr "Última ejecución" #. module: partner_invoicing_mode_monthly #: model:ir.model.fields,help:partner_invoicing_mode_monthly.field_res_company__invoicing_mode_monthly_last_execution #: model:ir.model.fields,help:partner_invoicing_mode_monthly.field_res_config_settings__invoicing_mode_monthly_last_execution msgid "Last execution of monthly invoicing." -msgstr "" +msgstr "Última ejecución de la facturación mensual." #. module: partner_invoicing_mode_monthly #: model:ir.model.fields.selection,name:partner_invoicing_mode_monthly.selection__res_partner__invoicing_mode__monthly msgid "Monthly" -msgstr "" +msgstr "Mensualmente" #. module: partner_invoicing_mode_monthly #: model:ir.model,name:partner_invoicing_mode_monthly.model_sale_order msgid "Sales Order" -msgstr "" +msgstr "Órdenes de venta" diff --git a/partner_invoicing_mode_monthly/static/description/index.html b/partner_invoicing_mode_monthly/static/description/index.html index feb8a9bdb35..5310f08c3ee 100644 --- a/partner_invoicing_mode_monthly/static/description/index.html +++ b/partner_invoicing_mode_monthly/static/description/index.html @@ -1,20 +1,20 @@ - + - + Partner Invoicing Mode Monthly