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
-
-Create a tax group named “Ecotaxes”. The sequence must be lower than other tax groups.
-- Set the Preceding Subtotal field to “Without Ecotax”.
-
-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.
-
-
-For VAT taxes, check the Base Affected by Previous Taxes? option.
-
-Add an ecotax classification via the menu Accounting > Configuration > Taxes > Ecotax Classification.
-
+
+- 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.
-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
@@ -483,8 +461,8 @@
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:
-
+
Current maintainers:
+
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)
+
+
+
+
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
+
+
+
+
+Create a tax group named “Ecotaxes”. The sequence must be lower than other tax groups.
+- Set the Preceding Subtotal field to “Without Ecotax”.
+
+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.
+
+
+For VAT taxes, check the Base Affected by Previous Taxes? option.
+
+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.
+
+
+Assign one or more ecotax classifications to a product.
+
+- The ecotax amount can also be manually overridden on the product.
+
+
+
+
+
+
+
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.
+
+
+
+
+
+
+
+
This module is maintained by the OCA.
+
+
+
+
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:
+
+
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,
+)