diff --git a/sale_invoice_plan_report/README.rst b/sale_invoice_plan_report/README.rst new file mode 100644 index 000000000..bb8bd398c --- /dev/null +++ b/sale_invoice_plan_report/README.rst @@ -0,0 +1,141 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +========================= +Sales Invoice Plan Report +========================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:ae26797bd52187bd2c92fe1e0762d2eac388228726a6cc16c26587e3d97303e6 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png + :target: https://odoo-community.org/page/development-status + :alt: Alpha +.. |badge2| image:: https://img.shields.io/badge/license-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%2Fsale--reporting-lightgray.png?logo=github + :target: https://github.com/OCA/sale-reporting/tree/16.0/sale_invoice_plan_report + :alt: OCA/sale-reporting +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/sale-reporting-16-0/sale-reporting-16-0-sale_invoice_plan_report + :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/sale-reporting&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module extends the sales order/quotation PDF report to include invoice plan information when the order is configured to use invoice plans. + +When a sales order has an invoice plan configured, the PDF report will automatically display: + +* Invoice plan section with detailed installment information +* Installment sequence number +* Due dates for each payment +* Percentage of total amount for each installment +* Calculated amounts in the order currency + +The invoice plan section is only displayed when the sales order has "Use Invoice Plan" enabled and contains invoice plan lines. + +.. IMPORTANT:: + This is an alpha version, the data model and design can change at any time without warning. + Only for development or testing purpose, do not use in production. + `More details on development status `_ + +**Table of contents** + +.. contents:: + :local: + +Installation +============ + +This module depends on `sale_invoice_plan` from OCA sale-workflow. + +1. First, ensure that `sale_invoice_plan` is installed +2. Install this module (`sale_invoice_plan_report`) +3. No additional configuration is required - the module works automatically + +Usage +===== + +This module works automatically once installed. To see the invoice plan in PDF reports: + +1. Create a sales order/quotation +2. Enable "Use Invoice Plan" checkbox +3. Add invoice plan lines (installments) with: + * Installment sequence number + * Due date + * Percentage of total amount +4. Print the quotation or sales order PDF +5. The report will automatically include an "Invoice Plan" section showing all installment details + +The invoice plan section appears between the order lines and the totals summary, and includes: + +* **No.**: Sequence number of each installment +* **Date**: When each payment is due +* **Percentage**: What percentage of total each installment represents +* **Amount**: Calculated monetary value for each installment + +The section is only visible when the order has invoice plans configured. + +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 +~~~~~~~ + +* Escodoo + +Contributors +~~~~~~~~~~~~ + +* `Escodoo `_: + + * Kaynnan Lemes + * Marcel Savegnago + +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. + +.. |maintainer-kaynnan| image:: https://github.com/kaynnan.png?size=40px + :target: https://github.com/kaynnan + :alt: kaynnan +.. |maintainer-marcelsavegnago| image:: https://github.com/marcelsavegnago.png?size=40px + :target: https://github.com/marcelsavegnago + :alt: marcelsavegnago + +Current `maintainers `__: + +|maintainer-kaynnan| |maintainer-marcelsavegnago| + +This module is part of the `OCA/sale-reporting `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/sale_invoice_plan_report/__init__.py b/sale_invoice_plan_report/__init__.py new file mode 100644 index 000000000..0819474d7 --- /dev/null +++ b/sale_invoice_plan_report/__init__.py @@ -0,0 +1 @@ +# This addon customizes the sale order report template only. diff --git a/sale_invoice_plan_report/__manifest__.py b/sale_invoice_plan_report/__manifest__.py new file mode 100644 index 000000000..89972de0c --- /dev/null +++ b/sale_invoice_plan_report/__manifest__.py @@ -0,0 +1,22 @@ +# Copyright 2025 Escodoo (http://escodoo.com.br/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) + +{ + "name": "Sales Invoice Plan Report", + "summary": "Add invoice plan to sales order/quotation PDF report", + "version": "16.0.1.0.0", + "author": "Escodoo, Odoo Community Association (OCA)", + "license": "AGPL-3", + "website": "https://github.com/OCA/sale-reporting", + "category": "Sales", + "depends": [ + "sale_invoice_plan", + ], + "data": [ + "views/report_saleorder.xml", + ], + "development_status": "Alpha", + "maintainers": ["kaynnan", "marcelsavegnago"], + "installable": True, + "auto_install": False, +} diff --git a/sale_invoice_plan_report/readme/CONTRIBUTORS.rst b/sale_invoice_plan_report/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..2b7acce96 --- /dev/null +++ b/sale_invoice_plan_report/readme/CONTRIBUTORS.rst @@ -0,0 +1,4 @@ +* `Escodoo `_: + + * Kaynnan Lemes + * Marcel Savegnago diff --git a/sale_invoice_plan_report/readme/DESCRIPTION.rst b/sale_invoice_plan_report/readme/DESCRIPTION.rst new file mode 100644 index 000000000..c390763aa --- /dev/null +++ b/sale_invoice_plan_report/readme/DESCRIPTION.rst @@ -0,0 +1,11 @@ +This module extends the sales order/quotation PDF report to include invoice plan information when the order is configured to use invoice plans. + +When a sales order has an invoice plan configured, the PDF report will automatically display: + +* Invoice plan section with detailed installment information +* Installment sequence number +* Due dates for each payment +* Percentage of total amount for each installment +* Calculated amounts in the order currency + +The invoice plan section is only displayed when the sales order has "Use Invoice Plan" enabled and contains invoice plan lines. diff --git a/sale_invoice_plan_report/readme/INSTALL.rst b/sale_invoice_plan_report/readme/INSTALL.rst new file mode 100644 index 000000000..8059f330e --- /dev/null +++ b/sale_invoice_plan_report/readme/INSTALL.rst @@ -0,0 +1,5 @@ +This module depends on `sale_invoice_plan` from OCA sale-workflow. + +1. First, ensure that `sale_invoice_plan` is installed +2. Install this module (`sale_invoice_plan_report`) +3. No additional configuration is required - the module works automatically diff --git a/sale_invoice_plan_report/readme/USAGE.rst b/sale_invoice_plan_report/readme/USAGE.rst new file mode 100644 index 000000000..a553e0fe5 --- /dev/null +++ b/sale_invoice_plan_report/readme/USAGE.rst @@ -0,0 +1,19 @@ +This module works automatically once installed. To see the invoice plan in PDF reports: + +1. Create a sales order/quotation +2. Enable "Use Invoice Plan" checkbox +3. Add invoice plan lines (installments) with: + * Installment sequence number + * Due date + * Percentage of total amount +4. Print the quotation or sales order PDF +5. The report will automatically include an "Invoice Plan" section showing all installment details + +The invoice plan section appears between the order lines and the totals summary, and includes: + +* **No.**: Sequence number of each installment +* **Date**: When each payment is due +* **Percentage**: What percentage of total each installment represents +* **Amount**: Calculated monetary value for each installment + +The section is only visible when the order has invoice plans configured. diff --git a/sale_invoice_plan_report/static/description/icon.png b/sale_invoice_plan_report/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/sale_invoice_plan_report/static/description/icon.png differ diff --git a/sale_invoice_plan_report/static/description/index.html b/sale_invoice_plan_report/static/description/index.html new file mode 100644 index 000000000..07efee3b9 --- /dev/null +++ b/sale_invoice_plan_report/static/description/index.html @@ -0,0 +1,486 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

Sales Invoice Plan Report

+ +

Alpha License: AGPL-3 OCA/sale-reporting Translate me on Weblate Try me on Runboat

+

This module extends the sales order/quotation PDF report to include invoice plan information when the order is configured to use invoice plans.

+

When a sales order has an invoice plan configured, the PDF report will automatically display:

+
    +
  • Invoice plan section with detailed installment information
  • +
  • Installment sequence number
  • +
  • Due dates for each payment
  • +
  • Percentage of total amount for each installment
  • +
  • Calculated amounts in the order currency
  • +
+

The invoice plan section is only displayed when the sales order has “Use Invoice Plan” enabled and contains invoice plan lines.

+
+

Important

+

This is an alpha version, the data model and design can change at any time without warning. +Only for development or testing purpose, do not use in production. +More details on development status

+
+

Table of contents

+ +
+

Installation

+

This module depends on sale_invoice_plan from OCA sale-workflow.

+
    +
  1. First, ensure that sale_invoice_plan is installed
  2. +
  3. Install this module (sale_invoice_plan_report)
  4. +
  5. No additional configuration is required - the module works automatically
  6. +
+
+
+

Usage

+

This module works automatically once installed. To see the invoice plan in PDF reports:

+
    +
  1. Create a sales order/quotation
  2. +
  3. Enable “Use Invoice Plan” checkbox
  4. +
  5. Add invoice plan lines (installments) with: +* Installment sequence number +* Due date +* Percentage of total amount
  6. +
  7. Print the quotation or sales order PDF
  8. +
  9. The report will automatically include an “Invoice Plan” section showing all installment details
  10. +
+

The invoice plan section appears between the order lines and the totals summary, and includes:

+
    +
  • No.: Sequence number of each installment
  • +
  • Date: When each payment is due
  • +
  • Percentage: What percentage of total each installment represents
  • +
  • Amount: Calculated monetary value for each installment
  • +
+

The section is only visible when the order has invoice plans configured.

+
+
+

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

+
    +
  • Escodoo
  • +
+
+
+

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.

+

Current maintainers:

+

kaynnan marcelsavegnago

+

This module is part of the OCA/sale-reporting project on GitHub.

+

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

+
+
+
+
+ + diff --git a/sale_invoice_plan_report/tests/__init__.py b/sale_invoice_plan_report/tests/__init__.py new file mode 100644 index 000000000..02415651f --- /dev/null +++ b/sale_invoice_plan_report/tests/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import test_report diff --git a/sale_invoice_plan_report/tests/test_report.py b/sale_invoice_plan_report/tests/test_report.py new file mode 100644 index 000000000..1e8d86574 --- /dev/null +++ b/sale_invoice_plan_report/tests/test_report.py @@ -0,0 +1,174 @@ +# Copyright 2026 - TODAY, Escodoo +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo.tests import tagged + +from odoo.addons.sale.tests import common + + +@tagged("post_install", "-at_install") +class TestSaleInvoicePlanReport(common.TestSaleCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.sale_order = cls.env["sale.order"].create( + { + "partner_id": cls.partner_a.id, + "pricelist_id": cls.env.ref("product.list0").id, + "use_invoice_plan": True, + "order_line": [ + ( + 0, + 0, + { + "product_id": cls.product_a.id, + "name": cls.product_a.name, + "product_uom_qty": 2.0, + "price_unit": 100.0, + }, + ), + ], + "invoice_plan_ids": [ + ( + 0, + 0, + { + "installment": 1, + "plan_date": "2026-02-23", + "invoice_type": "installment", + "percent": 50.0, + }, + ), + ( + 0, + 0, + { + "installment": 2, + "plan_date": "2026-03-23", + "invoice_type": "installment", + "percent": 50.0, + }, + ), + ], + } + ) + + def _render_report(self, order): + """Helper to render the sale order report as HTML.""" + report_model = self.env["ir.actions.report"].with_context( + discard_logo_check=True + ) + html, _ = report_model._render_qweb_html( + "sale.action_report_saleorder", order.ids + ) + if isinstance(html, list): + html = b"".join(html) + return html.decode("utf-8") + + def test_sale_order_report_render_smoke(self): + """Test that the report renders without errors.""" + html = self._render_report(self.sale_order) + self.assertTrue(html) + + def test_report_contains_invoice_plan_section(self): + """Test that the invoice plan section appears in the report.""" + html = self._render_report(self.sale_order) + self.assertIn("Invoice Plan", html) + self.assertIn("invoice_plan_section", html) + + def test_report_contains_installment_details(self): + """Test that installment details are displayed correctly.""" + html = self._render_report(self.sale_order) + self.assertIn("2026", html) + self.assertIn("50", html) + self.assertIn("Installment", html) + + def test_report_contains_type_badge(self): + """Test that installment type badges are rendered.""" + html = self._render_report(self.sale_order) + self.assertIn("Installment", html) + + def test_report_no_invoice_plan_when_disabled(self): + """Test that invoice plan section is hidden when not configured.""" + order_no_plan = self.env["sale.order"].create( + { + "partner_id": self.partner_a.id, + "pricelist_id": self.env.ref("product.list0").id, + "order_line": [ + ( + 0, + 0, + { + "product_id": self.product_a.id, + "name": "Test Product", + "product_uom_qty": 1.0, + "price_unit": 50.0, + }, + ), + ], + } + ) + html = self._render_report(order_no_plan) + self.assertNotIn("invoice_plan_section", html) + self.assertNotIn("Invoice Plan", html) + + def test_report_with_advance_and_installments(self): + """Test report with advance payment and installments.""" + order_with_advance = self.env["sale.order"].create( + { + "partner_id": self.partner_a.id, + "pricelist_id": self.env.ref("product.list0").id, + "use_invoice_plan": True, + "order_line": [ + ( + 0, + 0, + { + "product_id": self.product_a.id, + "name": "Test Product", + "product_uom_qty": 1.0, + "price_unit": 1000.0, + }, + ), + ], + "invoice_plan_ids": [ + ( + 0, + 0, + { + "installment": 0, + "plan_date": "2026-01-15", + "invoice_type": "advance", + "percent": 50.0, + }, + ), + ( + 0, + 0, + { + "installment": 1, + "plan_date": "2026-06-03", + "invoice_type": "installment", + "percent": 41.0, + }, + ), + ( + 0, + 0, + { + "installment": 2, + "plan_date": "2026-07-24", + "invoice_type": "installment", + }, + ), + ], + } + ) + html = self._render_report(order_with_advance) + self.assertIn("Invoice Plan", html) + self.assertIn("Total", html) + + def test_report_currency_display(self): + """Test that currency values are displayed in the report.""" + html = self._render_report(self.sale_order) + self.assertIn("oe_currency_value", html.lower()) diff --git a/sale_invoice_plan_report/views/report_saleorder.xml b/sale_invoice_plan_report/views/report_saleorder.xml new file mode 100644 index 000000000..02d3e1a6f --- /dev/null +++ b/sale_invoice_plan_report/views/report_saleorder.xml @@ -0,0 +1,429 @@ + + + + + diff --git a/setup/sale_invoice_plan_report/odoo/addons/sale_invoice_plan_report b/setup/sale_invoice_plan_report/odoo/addons/sale_invoice_plan_report new file mode 120000 index 000000000..c8582b931 --- /dev/null +++ b/setup/sale_invoice_plan_report/odoo/addons/sale_invoice_plan_report @@ -0,0 +1 @@ +../../../../sale_invoice_plan_report \ No newline at end of file diff --git a/setup/sale_invoice_plan_report/setup.py b/setup/sale_invoice_plan_report/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/sale_invoice_plan_report/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)