From 8bc3f4ab3db83f09230d6f9d7390955d8f4658d4 Mon Sep 17 00:00:00 2001 From: Florian da Costa Date: Wed, 13 Nov 2024 18:51:48 +0100 Subject: [PATCH] [16][REF] split account_ecotax into account_ecotax and account_ecotax_tax The goal is to be able to choose between the implementation with and without using the odoo tax mechanism. The advantages of the implementation based on Odoo tax mechanims are : - Possibility to choose if product price include or exclude the ecotax amounts - Isolate the ecotax amounts into a specifc accounting account The disadvantage is that it adds a small layer of complexity and you have to manage the tax configuration and see all those ecotax taxes on your invoices And a major difference which can be good or not depending on your use cases, the ecotax amounts are not in the turnover when using Odoo tax mechanism --- account_ecotax/README.rst | 47 +- account_ecotax/__manifest__.py | 4 +- .../models/account_ecotax_classification.py | 16 - account_ecotax/models/account_move_line.py | 71 +-- account_ecotax/readme/CONTRIBUTORS.rst | 1 + account_ecotax/readme/DESCRIPTION.rst | 8 + account_ecotax/readme/USAGE.rst | 31 +- account_ecotax/static/description/index.html | 48 +- account_ecotax/tests/test_ecotax.py | 150 +----- .../account_ecotax_classification_view.xml | 17 +- account_ecotax_tax/README.rst | 132 +++++ account_ecotax_tax/__init__.py | 1 + account_ecotax_tax/__manifest__.py | 22 + account_ecotax_tax/models/__init__.py | 3 + .../models/account_ecotax_classification.py | 26 + .../models/account_move_line.py | 77 +++ account_ecotax_tax/models/account_tax.py | 32 ++ account_ecotax_tax/readme/CONTRIBUTORS.rst | 2 + account_ecotax_tax/readme/DESCRIPTION.rst | 6 + account_ecotax_tax/readme/USAGE.rst | 35 ++ .../static/description/icon.png | Bin 0 -> 3731 bytes .../static/description/index.html | 477 ++++++++++++++++++ account_ecotax_tax/tests/__init__.py | 1 + account_ecotax_tax/tests/test_ecotax.py | 150 ++++++ .../account_ecotax_classification_view.xml | 30 ++ .../views/account_tax_view.xml | 0 .../odoo/addons/account_ecotax_tax | 1 + setup/account_ecotax_tax/setup.py | 6 + 28 files changed, 1082 insertions(+), 312 deletions(-) create mode 100644 account_ecotax_tax/README.rst create mode 100644 account_ecotax_tax/__init__.py create mode 100644 account_ecotax_tax/__manifest__.py create mode 100644 account_ecotax_tax/models/__init__.py create mode 100644 account_ecotax_tax/models/account_ecotax_classification.py create mode 100644 account_ecotax_tax/models/account_move_line.py create mode 100644 account_ecotax_tax/models/account_tax.py create mode 100644 account_ecotax_tax/readme/CONTRIBUTORS.rst create mode 100644 account_ecotax_tax/readme/DESCRIPTION.rst create mode 100644 account_ecotax_tax/readme/USAGE.rst create mode 100644 account_ecotax_tax/static/description/icon.png create mode 100644 account_ecotax_tax/static/description/index.html create mode 100644 account_ecotax_tax/tests/__init__.py create mode 100644 account_ecotax_tax/tests/test_ecotax.py create mode 100644 account_ecotax_tax/views/account_ecotax_classification_view.xml rename {account_ecotax => account_ecotax_tax}/views/account_tax_view.xml (100%) create mode 120000 setup/account_ecotax_tax/odoo/addons/account_ecotax_tax create mode 100644 setup/account_ecotax_tax/setup.py diff --git a/account_ecotax/README.rst b/account_ecotax/README.rst index 005d93a84..9a2d3ad83 100644 --- a/account_ecotax/README.rst +++ b/account_ecotax/README.rst @@ -41,6 +41,14 @@ ECOTAXE classification can either a fixed or weight based ecotaxe. A product can have one or serveral ecotaxe classifications. For exemple wooden window blinds equipped with electric motor can have ecotaxe for wood and ecotaxe for electric motor. +This module has some limits : +- The ecotax amount is always included in the price of the product. +- The ecotax amount is not isolated in an specific accounting account but is included in the product income account. + +If one of these limits is an issue, you could install the submodule account_ecotax_tax. +This second module lets you manage the ecotax as a tax, so you can configure if you want it to be included or excluded of product price and also configuring an accounting account to isolate it. +The main consequence of this approach is that the ecotax won't be considered in the turnover, since it is considered as a tax. + This module version add the possibility to manage several ecotaxe classification by product. A migration script is necessary to update from previous versions. @@ -68,42 +76,19 @@ product.template ecotaxe_line_product_ids Usage ===== -1. Create a tax group named **"Ecotaxes"**. The sequence must be lower than other tax groups. - - Set the **Preceding Subtotal** field to **"Without Ecotax"**. - -2. Create two taxes named **"Fixed Ecotax"** and **"Weight-Based Ecotax"**. - - Check the **Ecotax** checkbox. - - Set the correct Python code: - - - For the fixed ecotax: - - .. code-block:: python - - result = quantity and product.fixed_ecotax * quantity or 0.0 - - - For the weight-based ecotax: - - .. code-block:: python - - result = quantity and product.weight_based_ecotax * quantity or 0.0 - - - Check the **Included in Base Amount** option. - - The sequence for Ecotax must be lower than the VAT tax. - -3. For VAT taxes, check the **Base Affected by Previous Taxes?** option. - -4. Add an ecotax classification via the menu **Accounting > Configuration > Taxes > Ecotax Classification**. +1. Add an ecotax classification via the menu **Accounting > Configuration > Taxes > Ecotax Classification**. - The ecotax classification can be either a fixed ecotax or a weight-based ecotax. - Ecotax classification information can be used for legal declarations. - For the fixed ecotax, the ecotax amount is used as a default value, which can be overridden on the product. - For the weight-based ecotax, define one ecotax by a coefficient applied to the weight (depending on the product's materials). - - Set the appropriate tax in the **Sale Ecotax** field. -5. Assign one or more ecotax classifications to a product. +2. Assign one or more ecotax classifications to a product. - The ecotax amount can also be manually overridden on the product. +3. Create an invoice with this product + Bug Tracker =========== @@ -126,6 +111,7 @@ Contributors ~~~~~~~~~~~~ * Mourad EL HADJ MIMOUNE +* Florian da Costa Maintainers ~~~~~~~~~~~ @@ -143,10 +129,13 @@ promote its widespread use. .. |maintainer-mourad-ehm| image:: https://github.com/mourad-ehm.png?size=40px :target: https://github.com/mourad-ehm :alt: mourad-ehm +.. |maintainer-florian-dacosta| image:: https://github.com/florian-dacosta.png?size=40px + :target: https://github.com/florian-dacosta + :alt: florian-dacosta -Current `maintainer `__: +Current `maintainers `__: -|maintainer-mourad-ehm| +|maintainer-mourad-ehm| |maintainer-florian-dacosta| This module is part of the `OCA/account-fiscal-rule `_ project on GitHub. diff --git a/account_ecotax/__manifest__.py b/account_ecotax/__manifest__.py index 280ff417e..fba33c82e 100644 --- a/account_ecotax/__manifest__.py +++ b/account_ecotax/__manifest__.py @@ -10,10 +10,9 @@ "website": "https://github.com/OCA/account-fiscal-rule", "category": "Localization/Account Taxes", "license": "AGPL-3", - "maintainers": ["mourad-ehm"], + "maintainers": ["mourad-ehm", "florian-dacosta"], "depends": [ "account", - "account_tax_python", ], "data": [ "data/decimal_precision.xml", @@ -26,7 +25,6 @@ "views/account_move_view.xml", "views/product_template_view.xml", "views/product_view.xml", - "views/account_tax_view.xml", ], "installable": True, } diff --git a/account_ecotax/models/account_ecotax_classification.py b/account_ecotax/models/account_ecotax_classification.py index c1c294798..5e75b7b73 100644 --- a/account_ecotax/models/account_ecotax_classification.py +++ b/account_ecotax/models/account_ecotax_classification.py @@ -82,22 +82,6 @@ class AccountEcotaxClassification(models.Model): ) intrastat_code = fields.Char() scale_code = fields.Char() - sale_ecotax_ids = fields.Many2many( - "account.tax", - "ecotax_classif_taxes_rel", - "ecotax_classif_id", - "tax_id", - string="Sale EcoTax", - domain=[("is_ecotax", "=", True), ("type_tax_use", "=", "sale")], - ) - purchase_ecotax_ids = fields.Many2many( - "account.tax", - "ecotax_classif_purchase_taxes_rel", - "ecotax_classif_id", - "tax_id", - string="Purchase EcoTax", - domain=[("is_ecotax", "=", True), ("type_tax_use", "=", "purchase")], - ) @api.depends("ecotax_type") def _compute_ecotax_vals(self): diff --git a/account_ecotax/models/account_move_line.py b/account_ecotax/models/account_move_line.py index 3b6030b39..77e33ca98 100644 --- a/account_ecotax/models/account_move_line.py +++ b/account_ecotax/models/account_move_line.py @@ -24,43 +24,22 @@ class AcountMoveLine(models.Model): compute="_compute_ecotax", ) + def _get_ecotax_amounts(self): + self.ensure_one() + amount_unit = sum(self.ecotax_line_ids.mapped("amount_unit")) + subtotal_ecotax = sum(self.ecotax_line_ids.mapped("amount_total")) + return amount_unit, subtotal_ecotax + @api.depends( "currency_id", - "tax_ids", - "quantity", - "product_id", + "ecotax_line_ids.amount_unit", + "ecotax_line_ids.amount_total", ) def _compute_ecotax(self): for line in self: - ecotax_ids = line.tax_ids.filtered(lambda tax: tax.is_ecotax) - - if line.display_type == "tax" or not ecotax_ids: - continue - if line.display_type == "product" and line.move_id.is_invoice(True): - amount_currency = line.price_unit * (1 - line.discount / 100) - handle_price_include = True - quantity = line.quantity - else: - amount_currency = line.amount_currency - handle_price_include = False - quantity = 1 - compute_all_currency = ecotax_ids.compute_all( - amount_currency, - currency=line.currency_id, - quantity=quantity, - product=line.product_id, - partner=line.move_id.partner_id or line.partner_id, - is_refund=line.is_refund, - handle_price_include=handle_price_include, - include_caba_tags=line.move_id.always_tax_exigible, - ) - subtotal_ecotax = 0.0 - for tax in compute_all_currency["taxes"]: - subtotal_ecotax += tax["amount"] - - unit = subtotal_ecotax / quantity if quantity else subtotal_ecotax - line.ecotax_amount_unit = unit - line.subtotal_ecotax = subtotal_ecotax + amount_unit, amount_total = line._get_ecotax_amounts() + line.ecotax_amount_unit = amount_unit + line.subtotal_ecotax = amount_total @api.onchange("product_id") def _onchange_product_ecotax_line(self): @@ -89,31 +68,3 @@ def edit_ecotax_lines(self): "res_id": self.id, } return view - - def _get_computed_taxes(self): - tax_ids = super()._get_computed_taxes() - ecotax_ids = self.env["account.tax"] - if self.move_id.is_sale_document(include_receipts=True): - # Out invoice. - sale_ecotaxs = self.product_id.all_ecotax_line_product_ids.mapped( - "classification_id" - ).mapped("sale_ecotax_ids") - ecotax_ids = sale_ecotaxs.filtered( - lambda tax: tax.company_id == self.move_id.company_id - ) - - elif self.move_id.is_purchase_document(include_receipts=True): - # In invoice. - purchase_ecotaxs = self.product_id.all_ecotax_line_product_ids.mapped( - "classification_id" - ).mapped("purchase_ecotax_ids") - ecotax_ids = purchase_ecotaxs.filtered( - lambda tax: tax.company_id == self.move_id.company_id - ) - - if ecotax_ids and self.move_id.fiscal_position_id: - ecotax_ids = self.move_id.fiscal_position_id.map_tax(ecotax_ids) - if ecotax_ids: - tax_ids |= ecotax_ids - - return tax_ids diff --git a/account_ecotax/readme/CONTRIBUTORS.rst b/account_ecotax/readme/CONTRIBUTORS.rst index f55657f6b..bfb2a5c68 100644 --- a/account_ecotax/readme/CONTRIBUTORS.rst +++ b/account_ecotax/readme/CONTRIBUTORS.rst @@ -1 +1,2 @@ * Mourad EL HADJ MIMOUNE +* Florian da Costa diff --git a/account_ecotax/readme/DESCRIPTION.rst b/account_ecotax/readme/DESCRIPTION.rst index a0a6d4172..4e45a942f 100644 --- a/account_ecotax/readme/DESCRIPTION.rst +++ b/account_ecotax/readme/DESCRIPTION.rst @@ -11,6 +11,14 @@ ECOTAXE classification can either a fixed or weight based ecotaxe. A product can have one or serveral ecotaxe classifications. For exemple wooden window blinds equipped with electric motor can have ecotaxe for wood and ecotaxe for electric motor. +This module has some limits : +- The ecotax amount is always included in the price of the product. +- The ecotax amount is not isolated in an specific accounting account but is included in the product income account. + +If one of these limits is an issue, you could install the submodule account_ecotax_tax. +This second module lets you manage the ecotax as a tax, so you can configure if you want it to be included or excluded of product price and also configuring an accounting account to isolate it. +The main consequence of this approach is that the ecotax won't be considered in the turnover, since it is considered as a tax. + This module version add the possibility to manage several ecotaxe classification by product. A migration script is necessary to update from previous versions. diff --git a/account_ecotax/readme/USAGE.rst b/account_ecotax/readme/USAGE.rst index 1916d796c..b9d427336 100644 --- a/account_ecotax/readme/USAGE.rst +++ b/account_ecotax/readme/USAGE.rst @@ -1,35 +1,12 @@ -1. Create a tax group named **"Ecotaxes"**. The sequence must be lower than other tax groups. - - Set the **Preceding Subtotal** field to **"Without Ecotax"**. - -2. Create two taxes named **"Fixed Ecotax"** and **"Weight-Based Ecotax"**. - - Check the **Ecotax** checkbox. - - Set the correct Python code: - - - For the fixed ecotax: - - .. code-block:: python - - result = quantity and product.fixed_ecotax * quantity or 0.0 - - - For the weight-based ecotax: - - .. code-block:: python - - result = quantity and product.weight_based_ecotax * quantity or 0.0 - - - Check the **Included in Base Amount** option. - - The sequence for Ecotax must be lower than the VAT tax. - -3. For VAT taxes, check the **Base Affected by Previous Taxes?** option. - -4. Add an ecotax classification via the menu **Accounting > Configuration > Taxes > Ecotax Classification**. +1. Add an ecotax classification via the menu **Accounting > Configuration > Taxes > Ecotax Classification**. - The ecotax classification can be either a fixed ecotax or a weight-based ecotax. - Ecotax classification information can be used for legal declarations. - For the fixed ecotax, the ecotax amount is used as a default value, which can be overridden on the product. - For the weight-based ecotax, define one ecotax by a coefficient applied to the weight (depending on the product's materials). - - Set the appropriate tax in the **Sale Ecotax** field. -5. Assign one or more ecotax classifications to a product. +2. Assign one or more ecotax classifications to a product. - The ecotax amount can also be manually overridden on the product. + +3. Create an invoice with this product diff --git a/account_ecotax/static/description/index.html b/account_ecotax/static/description/index.html index e4f0bf311..03e212e06 100644 --- a/account_ecotax/static/description/index.html +++ b/account_ecotax/static/description/index.html @@ -379,6 +379,12 @@

Ecotax Management

ECOTAXE classification can either a fixed or weight based ecotaxe.

A product can have one or serveral ecotaxe classifications. For exemple wooden window blinds equipped with electric motor can have ecotaxe for wood and ecotaxe for electric motor.

+

This module has some limits : +- The ecotax amount is always included in the price of the product. +- The ecotax amount is not isolated in an specific accounting account but is included in the product income account.

+

If one of these limits is an issue, you could install the submodule account_ecotax_tax. +This second module lets you manage the ecotax as a tax, so you can configure if you want it to be included or excluded of product price and also configuring an accounting account to isolate it. +The main consequence of this approach is that the ecotax won’t be considered in the turnover, since it is considered as a tax.

This module version add the possibility to manage several ecotaxe classification by product. A migration script is necessary to update from previous versions.

There is the main change to manage in migration script:

@@ -408,48 +414,19 @@

Ecotax Management

Usage

-
    -
  1. Create a tax group named “Ecotaxes”. The sequence must be lower than other tax groups. -- Set the Preceding Subtotal field to “Without Ecotax”.

    -
  2. -
  3. Create two taxes named “Fixed Ecotax” and “Weight-Based Ecotax”. -- Check the Ecotax checkbox. -- Set the correct Python code:

    -
    -
      -
    • For the fixed ecotax:

      -
      -result = quantity and product.fixed_ecotax * quantity or 0.0
      -
      -
    • -
    • For the weight-based ecotax:

      -
      -result = quantity and product.weight_based_ecotax * quantity or 0.0
      -
      -
    • -
    -
    -
      -
    • Check the Included in Base Amount option.
    • -
    • The sequence for Ecotax must be lower than the VAT tax.
    • -
    -
  4. -
  5. For VAT taxes, check the Base Affected by Previous Taxes? option.

    -
  6. -
  7. Add an ecotax classification via the menu Accounting > Configuration > Taxes > Ecotax Classification.

    -
      +
        +
      1. Add an ecotax classification via the menu Accounting > Configuration > Taxes > Ecotax Classification.
        • The ecotax classification can be either a fixed ecotax or a weight-based ecotax.
        • Ecotax classification information can be used for legal declarations.
        • For the fixed ecotax, the ecotax amount is used as a default value, which can be overridden on the product.
        • For the weight-based ecotax, define one ecotax by a coefficient applied to the weight (depending on the product’s materials).
        • -
        • Set the appropriate tax in the Sale Ecotax field.
      2. -
      3. Assign one or more ecotax classifications to a product.

        -
          +
        • Assign one or more ecotax classifications to a product.
          • The ecotax amount can also be manually overridden on the product.
        • +
        • Create an invoice with this product
@@ -472,6 +449,7 @@

Authors

Contributors

@@ -483,8 +461,8 @@

Maintainers

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 maintainer:

-

mourad-ehm

+

Current maintainers:

+

mourad-ehm florian-dacosta

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

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

diff --git a/account_ecotax/tests/test_ecotax.py b/account_ecotax/tests/test_ecotax.py index 88d77e1f1..5308500cb 100644 --- a/account_ecotax/tests/test_ecotax.py +++ b/account_ecotax/tests/test_ecotax.py @@ -12,8 +12,7 @@ from odoo.addons.account.tests.common import AccountTestInvoicingCommon -@tagged("-at_install", "post_install") -class TestInvoiceEcotaxe(AccountTestInvoicingCommon): +class TestInvoiceEcotaxCommon(AccountTestInvoicingCommon): @classmethod def setUpClass(cls, chart_template_ref=None): super().setUpClass(chart_template_ref) @@ -29,14 +28,6 @@ def setUpClass(cls, chart_template_ref=None): "company_id": cls.env.user.company_id.id, } ) - cls.invoice_ecotax_account = cls.env["account.account"].create( - { - "code": "707120", - "name": "Ecotax Account", - "account_type": "income", - "company_id": cls.env.user.company_id.id, - } - ) # 2- Invoice tax with included price to avoid unwanted amounts in tests cls.invoice_tax = cls.env["account.tax"].create( { @@ -86,113 +77,6 @@ def setUpClass(cls, chart_template_ref=None): ], } ) - # 3 Ecotaxes tax - cls.invoice_fixed_ecotax = cls.env["account.tax"].create( - { - "name": "Fixed Ecotax", - "type_tax_use": "sale", - "company_id": cls.env.user.company_id.id, - "price_include": True, - "amount_type": "code", - "include_base_amount": True, - "sequence": 0, - "is_ecotax": True, - "python_compute": "result = (quantity and" - " product.fixed_ecotax * quantity or 0.0)", - "tax_exigibility": "on_invoice", - "invoice_repartition_line_ids": [ - ( - 0, - 0, - { - "factor_percent": 100, - "repartition_type": "base", - }, - ), - ( - 0, - 0, - { - "factor_percent": 100, - "repartition_type": "tax", - "account_id": cls.invoice_ecotax_account.id, - }, - ), - ], - "refund_repartition_line_ids": [ - ( - 0, - 0, - { - "factor_percent": 100, - "repartition_type": "base", - }, - ), - ( - 0, - 0, - { - "factor_percent": 100, - "repartition_type": "tax", - "account_id": cls.invoice_ecotax_account.id, - }, - ), - ], - } - ) - cls.invoice_weight_based_ecotax = cls.env["account.tax"].create( - { - "name": "Weight Based Ecotax", - "type_tax_use": "sale", - "company_id": cls.env.user.company_id.id, - "amount_type": "code", - "include_base_amount": True, - "price_include": True, - "sequence": 0, - "is_ecotax": True, - "python_compute": "result = (quantity and" - " product.weight_based_ecotax * quantity or 0.0)", - "tax_exigibility": "on_invoice", - "invoice_repartition_line_ids": [ - ( - 0, - 0, - { - "factor_percent": 100, - "repartition_type": "base", - }, - ), - ( - 0, - 0, - { - "factor_percent": 100, - "repartition_type": "tax", - "account_id": cls.invoice_ecotax_account.id, - }, - ), - ], - "refund_repartition_line_ids": [ - ( - 0, - 0, - { - "factor_percent": 100, - "repartition_type": "base", - }, - ), - ( - 0, - 0, - { - "factor_percent": 100, - "repartition_type": "tax", - "account_id": cls.invoice_ecotax_account.id, - }, - ), - ], - } - ) # ECOTAXES # 1- Fixed ecotax cls.ecotax_fixed = cls.env["account.ecotax.classification"].create( @@ -202,10 +86,8 @@ def setUpClass(cls, chart_template_ref=None): "default_fixed_ecotax": 5.0, "product_status": "M", "supplier_status": "MAN", - "sale_ecotax_ids": [(4, cls.invoice_fixed_ecotax.id)], } ) - cls.ecotax_fixed.sale_ecotax_ids = cls.invoice_fixed_ecotax # 2- Weight-based ecotax cls.ecotax_weight = cls.env["account.ecotax.classification"].create( { @@ -214,10 +96,8 @@ def setUpClass(cls, chart_template_ref=None): "ecotax_coef": 0.04, "product_status": "P", "supplier_status": "MAN", - "sale_ecotax_ids": [(4, cls.invoice_weight_based_ecotax.id)], } ) - cls.ecotax_weight.sale_ecotax_ids = cls.invoice_weight_based_ecotax # MISC # 1- Invoice partner cls.invoice_partner = cls.env["res.partner"].create({"name": "Test"}) @@ -338,7 +218,7 @@ def _run_checks(self, inv, inv_expected_amounts, inv_lines_expected_amounts): inv_line.subtotal_ecotax, inv_line_expected_amounts["subtotal_ecotax"] ) - def test_01_default_fixed_ecotax(self): + def _test_01_default_fixed_ecotax(self): """Test default fixed ecotax Ecotax classification data for this test: @@ -368,7 +248,7 @@ def test_01_default_fixed_ecotax(self): [{"ecotax_amount_unit": 5.0, "subtotal_ecotax": 5.0 * new_qty}], ) - def test_02_force_fixed_ecotax_on_product(self): + def _test_02_force_fixed_ecotax_on_product(self): """Test manual fixed ecotax Ecotax classification data for this test: @@ -400,7 +280,7 @@ def test_02_force_fixed_ecotax_on_product(self): [{"ecotax_amount_unit": 10.0, "subtotal_ecotax": 10.0 * new_qty}], ) - def test_03_weight_based_ecotax(self): + def _test_03_weight_based_ecotax(self): """Test weight based ecotax Ecotax classification data for this test: @@ -430,7 +310,7 @@ def test_03_weight_based_ecotax(self): [{"ecotax_amount_unit": 4.0, "subtotal_ecotax": 4.0 * new_qty}], ) - def test_04_mixed_ecotax(self): + def _test_04_mixed_ecotax(self): """Test mixed ecotax within the same invoice Creating an invoice with 3 lines (one per type with types tested above) @@ -477,7 +357,7 @@ def test_04_mixed_ecotax(self): ], ) - def test_06_product_variants(self): + def _test_05_product_variants(self): """ Data: A product template with two variants @@ -525,3 +405,21 @@ def test_06_product_variants(self): variant_2.all_ecotax_line_product_ids, variant_2.product_tmpl_id.ecotax_line_product_ids, ) + + +@tagged("-at_install", "post_install") +class TestInvoiceEcotax(TestInvoiceEcotaxCommon): + def test_01_default_fixed_ecotax(self): + self._test_01_default_fixed_ecotax() + + def test_02_force_fixed_ecotax_on_product(self): + self._test_02_force_fixed_ecotax_on_product() + + def test_03_weight_based_ecotax(self): + self._test_03_weight_based_ecotax() + + def test_04_mixed_ecotax(self): + self._test_04_mixed_ecotax() + + def test_05_product_variants(self): + self._test_05_product_variants() diff --git a/account_ecotax/views/account_ecotax_classification_view.xml b/account_ecotax/views/account_ecotax_classification_view.xml index db3c0197f..21fb08175 100644 --- a/account_ecotax/views/account_ecotax_classification_view.xml +++ b/account_ecotax/views/account_ecotax_classification_view.xml @@ -57,7 +57,7 @@ - + - - - - - diff --git a/account_ecotax_tax/README.rst b/account_ecotax_tax/README.rst new file mode 100644 index 000000000..7da60b567 --- /dev/null +++ b/account_ecotax_tax/README.rst @@ -0,0 +1,132 @@ +================================= +Ecotax Management (with Odoo tax) +================================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:23479e79cea1c7653013329021c55bf27b1d6fa0d64734b13f53ca3209feaffa + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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--fiscal--rule-lightgray.png?logo=github + :target: https://github.com/OCA/account-fiscal-rule/tree/16.0/account_ecotax_tax + :alt: OCA/account-fiscal-rule +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/account-fiscal-rule-16-0/account-fiscal-rule-16-0-account_ecotax_tax + :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/account-fiscal-rule&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows to compute the ecotax amounts from Odoo tax mechanism. +The advantages compared to the base account_ecotax module is that it allows to : +- Manage ecotax amount as included of excluded from the price of the product +- Isolate the amount of the ecotax in a specific accounting account (set on the tax) + +Then the ecotax amounts are not considered as turnover, which could be good not depending on your country's legistlation or accountant preferences. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +1. Create a tax group named **"Ecotaxes"**. The sequence must be lower than other tax groups. + - Set the **Preceding Subtotal** field to **"Without Ecotax"**. + +2. Create two taxes named **"Fixed Ecotax"** and **"Weight-Based Ecotax"**. + - Check the **Ecotax** checkbox. + - Set the correct Python code: + + - For the fixed ecotax: + + .. code-block:: python + + result = quantity and product.fixed_ecotax * quantity or 0.0 + + - For the weight-based ecotax: + + .. code-block:: python + + result = quantity and product.weight_based_ecotax * quantity or 0.0 + + - Check the **Included in Base Amount** option. + - The sequence for Ecotax must be lower than the VAT tax. + +3. For VAT taxes, check the **Base Affected by Previous Taxes?** option. + +4. Add an ecotax classification via the menu **Accounting > Configuration > Taxes > Ecotax Classification**. + + - The ecotax classification can be either a fixed ecotax or a weight-based ecotax. + - Ecotax classification information can be used for legal declarations. + - For the fixed ecotax, the ecotax amount is used as a default value, which can be overridden on the product. + - For the weight-based ecotax, define one ecotax by a coefficient applied to the weight (depending on the product's materials). + - Set the appropriate tax in the **Sale Ecotax** field. + +5. Assign one or more ecotax classifications to a product. + + - The ecotax amount can also be manually overridden on the product. + +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 +~~~~~~~ + +* Akretion + +Contributors +~~~~~~~~~~~~ + +* Mourad EL HADJ MIMOUNE +* Florian da Costa + +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-mourad-ehm| image:: https://github.com/mourad-ehm.png?size=40px + :target: https://github.com/mourad-ehm + :alt: mourad-ehm +.. |maintainer-florian-dacosta| image:: https://github.com/florian-dacosta.png?size=40px + :target: https://github.com/florian-dacosta + :alt: florian-dacosta + +Current `maintainers `__: + +|maintainer-mourad-ehm| |maintainer-florian-dacosta| + +This module is part of the `OCA/account-fiscal-rule `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/account_ecotax_tax/__init__.py b/account_ecotax_tax/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/account_ecotax_tax/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/account_ecotax_tax/__manifest__.py b/account_ecotax_tax/__manifest__.py new file mode 100644 index 000000000..5e078741d --- /dev/null +++ b/account_ecotax_tax/__manifest__.py @@ -0,0 +1,22 @@ +# © 2014-2023 Akretion (http://www.akretion.com) +# @author Mourad EL HADJ MIMOUNE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +{ + "name": "Ecotax Management (with Odoo tax)", + "summary": "Use Odoo tax mechanism to compute the ecotaxes ", + "version": "16.0.1.0.0", + "author": "Akretion, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/account-fiscal-rule", + "category": "Localization/Account Taxes", + "license": "AGPL-3", + "maintainers": ["mourad-ehm", "florian-dacosta"], + "depends": [ + "account_ecotax", + "account_tax_python", + ], + "data": [ + "views/account_ecotax_classification_view.xml", + "views/account_tax_view.xml", + ], + "installable": True, +} diff --git a/account_ecotax_tax/models/__init__.py b/account_ecotax_tax/models/__init__.py new file mode 100644 index 000000000..62a42c959 --- /dev/null +++ b/account_ecotax_tax/models/__init__.py @@ -0,0 +1,3 @@ +from . import account_ecotax_classification +from . import account_move_line +from . import account_tax diff --git a/account_ecotax_tax/models/account_ecotax_classification.py b/account_ecotax_tax/models/account_ecotax_classification.py new file mode 100644 index 000000000..e9ac21f0a --- /dev/null +++ b/account_ecotax_tax/models/account_ecotax_classification.py @@ -0,0 +1,26 @@ +# © 2014-2023 Akretion (http://www.akretion.com) +# @author Mourad EL HADJ MIMOUNE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class AccountEcotaxClassification(models.Model): + _inherit = "account.ecotax.classification" + + sale_ecotax_ids = fields.Many2many( + "account.tax", + "ecotax_classif_taxes_rel", + "ecotax_classif_id", + "tax_id", + string="Sale EcoTax", + domain=[("is_ecotax", "=", True), ("type_tax_use", "=", "sale")], + ) + purchase_ecotax_ids = fields.Many2many( + "account.tax", + "ecotax_classif_purchase_taxes_rel", + "ecotax_classif_id", + "tax_id", + string="Purchase EcoTax", + domain=[("is_ecotax", "=", True), ("type_tax_use", "=", "purchase")], + ) diff --git a/account_ecotax_tax/models/account_move_line.py b/account_ecotax_tax/models/account_move_line.py new file mode 100644 index 000000000..31ca80b3f --- /dev/null +++ b/account_ecotax_tax/models/account_move_line.py @@ -0,0 +1,77 @@ +# © 2014-2023 Akretion (http://www.akretion.com) +# @author Mourad EL HADJ MIMOUNE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import api, models + + +class AcountMoveLine(models.Model): + _inherit = "account.move.line" + + def _get_ecotax_amounts(self): + self.ensure_one() + ecotax_ids = self.tax_ids.filtered(lambda tax: tax.is_ecotax) + + if self.display_type == "tax" or not ecotax_ids: + return 0.0, 0.0 + if self.display_type == "product" and self.move_id.is_invoice(True): + amount_currency = self.price_unit * (1 - self.discount / 100) + handle_price_include = True + quantity = self.quantity + else: + amount_currency = self.amount_currency + handle_price_include = False + quantity = 1 + compute_all_currency = ecotax_ids.compute_all( + amount_currency, + currency=self.currency_id, + quantity=quantity, + product=self.product_id, + partner=self.move_id.partner_id or self.partner_id, + is_refund=self.is_refund, + handle_price_include=handle_price_include, + include_caba_tags=self.move_id.always_tax_exigible, + ) + subtotal_ecotax = 0.0 + for tax in compute_all_currency["taxes"]: + subtotal_ecotax += tax["amount"] + + amount_unit = subtotal_ecotax / quantity if quantity else subtotal_ecotax + return amount_unit, subtotal_ecotax + + @api.depends( + "currency_id", + "tax_ids", + "quantity", + "product_id", + ) + def _compute_ecotax(self): + return super()._compute_ecotax() + + def _get_computed_taxes(self): + tax_ids = super()._get_computed_taxes() + ecotax_ids = self.env["account.tax"] + if self.move_id.is_sale_document(include_receipts=True): + # Out invoice. + sale_ecotaxs = self.product_id.all_ecotax_line_product_ids.mapped( + "classification_id" + ).mapped("sale_ecotax_ids") + ecotax_ids = sale_ecotaxs.filtered( + lambda tax: tax.company_id == self.move_id.company_id + ) + + elif self.move_id.is_purchase_document(include_receipts=True): + # In invoice. + purchase_ecotaxs = self.product_id.all_ecotax_line_product_ids.mapped( + "classification_id" + ).mapped("purchase_ecotax_ids") + ecotax_ids = purchase_ecotaxs.filtered( + lambda tax: tax.company_id == self.move_id.company_id + ) + + if ecotax_ids and self.move_id.fiscal_position_id: + ecotax_ids = self.move_id.fiscal_position_id.map_tax(ecotax_ids) + if ecotax_ids: + tax_ids |= ecotax_ids + + return tax_ids diff --git a/account_ecotax_tax/models/account_tax.py b/account_ecotax_tax/models/account_tax.py new file mode 100644 index 000000000..fd592c692 --- /dev/null +++ b/account_ecotax_tax/models/account_tax.py @@ -0,0 +1,32 @@ +# © 2014-2024 Akretion (http://www.akretion.com) +# @author Mourad EL HADJ MIMOUNE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import api, fields, models + + +class AccountTax(models.Model): + _inherit = "account.tax" + + is_ecotax = fields.Boolean( + "Ecotax", + help="Warning : To include Ecotax " + "in the VAT tax check this :\n" + '1: check "included in base amount "\n' + "2: The Ecotax sequence must be less then " + "VAT tax (in sale and purchase)", + ) + + @api.onchange("is_ecotax") + def onchange_is_ecotax(self): + if self.is_ecotax: + self.amount_type = "code" + self.include_base_amount = True + self.python_compute = """ +# price_unit +# product: product.product object or None +# partner: res.partner object or None +# for weight based ecotax +# result = quantity and product.weight_based_ecotax * quantity or 0.0 +result = quantity and product.fixed_ecotax * quantity or 0.0 + """ diff --git a/account_ecotax_tax/readme/CONTRIBUTORS.rst b/account_ecotax_tax/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..bfb2a5c68 --- /dev/null +++ b/account_ecotax_tax/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Mourad EL HADJ MIMOUNE +* Florian da Costa diff --git a/account_ecotax_tax/readme/DESCRIPTION.rst b/account_ecotax_tax/readme/DESCRIPTION.rst new file mode 100644 index 000000000..4aab07678 --- /dev/null +++ b/account_ecotax_tax/readme/DESCRIPTION.rst @@ -0,0 +1,6 @@ +This module allows to compute the ecotax amounts from Odoo tax mechanism. +The advantages compared to the base account_ecotax module is that it allows to : +- Manage ecotax amount as included of excluded from the price of the product +- Isolate the amount of the ecotax in a specific accounting account (set on the tax) + +Then the ecotax amounts are not considered as turnover, which could be good not depending on your country's legistlation or accountant preferences. diff --git a/account_ecotax_tax/readme/USAGE.rst b/account_ecotax_tax/readme/USAGE.rst new file mode 100644 index 000000000..1916d796c --- /dev/null +++ b/account_ecotax_tax/readme/USAGE.rst @@ -0,0 +1,35 @@ +1. Create a tax group named **"Ecotaxes"**. The sequence must be lower than other tax groups. + - Set the **Preceding Subtotal** field to **"Without Ecotax"**. + +2. Create two taxes named **"Fixed Ecotax"** and **"Weight-Based Ecotax"**. + - Check the **Ecotax** checkbox. + - Set the correct Python code: + + - For the fixed ecotax: + + .. code-block:: python + + result = quantity and product.fixed_ecotax * quantity or 0.0 + + - For the weight-based ecotax: + + .. code-block:: python + + result = quantity and product.weight_based_ecotax * quantity or 0.0 + + - Check the **Included in Base Amount** option. + - The sequence for Ecotax must be lower than the VAT tax. + +3. For VAT taxes, check the **Base Affected by Previous Taxes?** option. + +4. Add an ecotax classification via the menu **Accounting > Configuration > Taxes > Ecotax Classification**. + + - The ecotax classification can be either a fixed ecotax or a weight-based ecotax. + - Ecotax classification information can be used for legal declarations. + - For the fixed ecotax, the ecotax amount is used as a default value, which can be overridden on the product. + - For the weight-based ecotax, define one ecotax by a coefficient applied to the weight (depending on the product's materials). + - Set the appropriate tax in the **Sale Ecotax** field. + +5. Assign one or more ecotax classifications to a product. + + - The ecotax amount can also be manually overridden on the product. diff --git a/account_ecotax_tax/static/description/icon.png b/account_ecotax_tax/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ee185a69f467c138ecfc6c2f234ed911e50860da GIT binary patch literal 3731 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 + + + + +Ecotax Management (with Odoo tax) + + + +
+

Ecotax Management (with Odoo tax)

+ + +

Beta License: AGPL-3 OCA/account-fiscal-rule Translate me on Weblate Try me on Runboat

+

This module allows to compute the ecotax amounts from Odoo tax mechanism. +The advantages compared to the base account_ecotax module is that it allows to : +- Manage ecotax amount as included of excluded from the price of the product +- Isolate the amount of the ecotax in a specific accounting account (set on the tax)

+

Then the ecotax amounts are not considered as turnover, which could be good not depending on your country’s legistlation or accountant preferences.

+

Table of contents

+ +
+

Usage

+
    +
  1. Create a tax group named “Ecotaxes”. The sequence must be lower than other tax groups. +- Set the Preceding Subtotal field to “Without Ecotax”.

    +
  2. +
  3. Create two taxes named “Fixed Ecotax” and “Weight-Based Ecotax”. +- Check the Ecotax checkbox. +- Set the correct Python code:

    +
    +
      +
    • For the fixed ecotax:

      +
      +result = quantity and product.fixed_ecotax * quantity or 0.0
      +
      +
    • +
    • For the weight-based ecotax:

      +
      +result = quantity and product.weight_based_ecotax * quantity or 0.0
      +
      +
    • +
    +
    +
      +
    • Check the Included in Base Amount option.
    • +
    • The sequence for Ecotax must be lower than the VAT tax.
    • +
    +
  4. +
  5. For VAT taxes, check the Base Affected by Previous Taxes? option.

    +
  6. +
  7. Add an ecotax classification via the menu Accounting > Configuration > Taxes > Ecotax Classification.

    +
      +
    • The ecotax classification can be either a fixed ecotax or a weight-based ecotax.
    • +
    • Ecotax classification information can be used for legal declarations.
    • +
    • For the fixed ecotax, the ecotax amount is used as a default value, which can be overridden on the product.
    • +
    • For the weight-based ecotax, define one ecotax by a coefficient applied to the weight (depending on the product’s materials).
    • +
    • Set the appropriate tax in the Sale Ecotax field.
    • +
    +
  8. +
  9. Assign one or more ecotax classifications to a product.

    +
      +
    • The ecotax amount can also be manually overridden on the product.
    • +
    +
  10. +
+
+
+

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

+
    +
  • Akretion
  • +
+
+
+

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:

+

mourad-ehm florian-dacosta

+

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

+

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

+
+
+
+ + diff --git a/account_ecotax_tax/tests/__init__.py b/account_ecotax_tax/tests/__init__.py new file mode 100644 index 000000000..88a931bae --- /dev/null +++ b/account_ecotax_tax/tests/__init__.py @@ -0,0 +1 @@ +from . import test_ecotax diff --git a/account_ecotax_tax/tests/test_ecotax.py b/account_ecotax_tax/tests/test_ecotax.py new file mode 100644 index 000000000..7422a2865 --- /dev/null +++ b/account_ecotax_tax/tests/test_ecotax.py @@ -0,0 +1,150 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + + +from odoo.tests.common import tagged + +from odoo.addons.account_ecotax.tests.test_ecotax import TestInvoiceEcotaxCommon + + +@tagged("-at_install", "post_install") +class TestInvoiceEcotaxTax(TestInvoiceEcotaxCommon): + @classmethod + def setUpClass(cls, chart_template_ref=None): + super().setUpClass(chart_template_ref) + cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) + + # ACCOUNTING STUFF + cls.invoice_ecotax_account = cls.env["account.account"].create( + { + "code": "707120", + "name": "Ecotax Account", + "account_type": "income", + "company_id": cls.env.user.company_id.id, + } + ) + cls.invoice_fixed_ecotax = cls.env["account.tax"].create( + { + "name": "Fixed Ecotax", + "type_tax_use": "sale", + "company_id": cls.env.user.company_id.id, + "price_include": True, + "amount_type": "code", + "include_base_amount": True, + "sequence": 0, + "is_ecotax": True, + "python_compute": "result = (quantity and" + " product.fixed_ecotax * quantity or 0.0)", + "tax_exigibility": "on_invoice", + "invoice_repartition_line_ids": [ + ( + 0, + 0, + { + "factor_percent": 100, + "repartition_type": "base", + }, + ), + ( + 0, + 0, + { + "factor_percent": 100, + "repartition_type": "tax", + "account_id": cls.invoice_ecotax_account.id, + }, + ), + ], + "refund_repartition_line_ids": [ + ( + 0, + 0, + { + "factor_percent": 100, + "repartition_type": "base", + }, + ), + ( + 0, + 0, + { + "factor_percent": 100, + "repartition_type": "tax", + "account_id": cls.invoice_ecotax_account.id, + }, + ), + ], + } + ) + cls.invoice_weight_based_ecotax = cls.env["account.tax"].create( + { + "name": "Weight Based Ecotax", + "type_tax_use": "sale", + "company_id": cls.env.user.company_id.id, + "amount_type": "code", + "include_base_amount": True, + "price_include": True, + "sequence": 0, + "is_ecotax": True, + "python_compute": "result = (quantity and" + " product.weight_based_ecotax * quantity or 0.0)", + "tax_exigibility": "on_invoice", + "invoice_repartition_line_ids": [ + ( + 0, + 0, + { + "factor_percent": 100, + "repartition_type": "base", + }, + ), + ( + 0, + 0, + { + "factor_percent": 100, + "repartition_type": "tax", + "account_id": cls.invoice_ecotax_account.id, + }, + ), + ], + "refund_repartition_line_ids": [ + ( + 0, + 0, + { + "factor_percent": 100, + "repartition_type": "base", + }, + ), + ( + 0, + 0, + { + "factor_percent": 100, + "repartition_type": "tax", + "account_id": cls.invoice_ecotax_account.id, + }, + ), + ], + } + ) + # ECOTAXES + # 1- Fixed ecotax + cls.ecotax_fixed.sale_ecotax_ids = cls.invoice_fixed_ecotax + # 2- Weight-based ecotax + cls.ecotax_weight.sale_ecotax_ids = cls.invoice_weight_based_ecotax + + def test_01_default_fixed_ecotax(self): + self._test_01_default_fixed_ecotax() + + def test_02_force_fixed_ecotax_on_product(self): + self._test_02_force_fixed_ecotax_on_product() + + def test_03_weight_based_ecotax(self): + self._test_03_weight_based_ecotax() + + def test_04_mixed_ecotax(self): + self._test_04_mixed_ecotax() + + def test_05_product_variants(self): + self._test_05_product_variants() diff --git a/account_ecotax_tax/views/account_ecotax_classification_view.xml b/account_ecotax_tax/views/account_ecotax_classification_view.xml new file mode 100644 index 000000000..5575c5b1b --- /dev/null +++ b/account_ecotax_tax/views/account_ecotax_classification_view.xml @@ -0,0 +1,30 @@ + + + + + account.ecotax.classification + + + + + + + + + + + + diff --git a/account_ecotax/views/account_tax_view.xml b/account_ecotax_tax/views/account_tax_view.xml similarity index 100% rename from account_ecotax/views/account_tax_view.xml rename to account_ecotax_tax/views/account_tax_view.xml diff --git a/setup/account_ecotax_tax/odoo/addons/account_ecotax_tax b/setup/account_ecotax_tax/odoo/addons/account_ecotax_tax new file mode 120000 index 000000000..92b2aefa1 --- /dev/null +++ b/setup/account_ecotax_tax/odoo/addons/account_ecotax_tax @@ -0,0 +1 @@ +../../../../account_ecotax_tax \ No newline at end of file diff --git a/setup/account_ecotax_tax/setup.py b/setup/account_ecotax_tax/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/account_ecotax_tax/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)