diff --git a/sale_product_variant_attribute_tax/README.rst b/sale_product_variant_attribute_tax/README.rst new file mode 100644 index 000000000..5d9b46f36 --- /dev/null +++ b/sale_product_variant_attribute_tax/README.rst @@ -0,0 +1,107 @@ +=================================== +Put attribute taxes on sales orders +=================================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:9352d88ee2b52de80b7e744156585858898fb96f97bfdfedf9bb2819a9d573ed + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png + :target: https://odoo-community.org/page/development-status + :alt: Production/Stable +.. |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%2Fproduct--variant-lightgray.png?logo=github + :target: https://github.com/OCA/product-variant/tree/16.0/sale_product_variant_attribute_tax + :alt: OCA/product-variant +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/product-variant-16-0/product-variant-16-0-sale_product_variant_attribute_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/product-variant&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module uses *product_variant_attribute_tax* for adding the taxes set +on product attribute values when adding a product in sales orders that contains +this attribute value. + +**Table of contents** + +.. contents:: + :local: + +Use Cases / Context +=================== + +As the product taxes are defined at product template level, you can't have some variants with an specific tax. + +These modules family covers the gap, adding the taxes at attribute level. This design decision has been taken for allowing to define the tax only once, as other options like having taxes at product variant level will force you to define the specific taxes for each of the variants that are affected. + +Usage +===== + +To use this module, you need to: + +#. Go to *Sales > Orders > Quotations*, create a new quotation or edit + an existing one. +#. Create a new order line or edit an existing one. +#. when editing the table "Product attributes", the taxes of that sales + line will be completed with the default taxes of the attribute value + specified. + +Known issues / Roadmap +====================== + +- This module requires `sale_variant_configurator` as a way to avoid 2 glue modules, but it may be independent. + +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 +~~~~~~~ + +* Tecnativa + +Contributors +~~~~~~~~~~~~ + +* `Tecnativa `_: + + * Vicent Cubells + * Pedro M. Baeza + * Ernesto Tejeda + * Carolina Fernandez + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/product-variant `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/sale_product_variant_attribute_tax/__init__.py b/sale_product_variant_attribute_tax/__init__.py new file mode 100644 index 000000000..3275ac2ad --- /dev/null +++ b/sale_product_variant_attribute_tax/__init__.py @@ -0,0 +1,2 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from . import models diff --git a/sale_product_variant_attribute_tax/__manifest__.py b/sale_product_variant_attribute_tax/__manifest__.py new file mode 100644 index 000000000..340413919 --- /dev/null +++ b/sale_product_variant_attribute_tax/__manifest__.py @@ -0,0 +1,15 @@ +# Copyright 2016-2017 Tecnativa - Pedro M. Baeza +# Copyright 2024 Tecnativa - Carolina Fernandez +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "Put attribute taxes on sales orders", + "summary": "Bring the taxes associated to product values", + "version": "16.0.1.0.0", + "development_status": "Production/Stable", + "category": "Sales/Sales", + "website": "https://github.com/OCA/product-variant", + "author": "Tecnativa, Odoo Community Association (OCA)", + "license": "AGPL-3", + "depends": ["product_variant_attribute_tax", "sale_variant_configurator"], + "installable": True, +} diff --git a/sale_product_variant_attribute_tax/i18n/es.po b/sale_product_variant_attribute_tax/i18n/es.po new file mode 100644 index 000000000..d94cb032d --- /dev/null +++ b/sale_product_variant_attribute_tax/i18n/es.po @@ -0,0 +1,22 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_product_variant_attribute_tax +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 13.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2021-03-16 18:45+0000\n" +"Last-Translator: Ana Suárez \n" +"Language-Team: none\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.3.2\n" + +#. module: sale_product_variant_attribute_tax +#: model:ir.model,name:sale_product_variant_attribute_tax.model_sale_order_line +msgid "Sales Order Line" +msgstr "Línea de pedido de venta" diff --git a/sale_product_variant_attribute_tax/i18n/es_AR.po b/sale_product_variant_attribute_tax/i18n/es_AR.po new file mode 100644 index 000000000..fee2be51d --- /dev/null +++ b/sale_product_variant_attribute_tax/i18n/es_AR.po @@ -0,0 +1,22 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_product_variant_attribute_tax +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 13.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2021-04-04 20:46+0000\n" +"Last-Translator: Ignacio Buioli \n" +"Language-Team: none\n" +"Language: es_AR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.3.2\n" + +#. module: sale_product_variant_attribute_tax +#: model:ir.model,name:sale_product_variant_attribute_tax.model_sale_order_line +msgid "Sales Order Line" +msgstr "Línea del Pedido de Ventas" diff --git a/sale_product_variant_attribute_tax/i18n/it.po b/sale_product_variant_attribute_tax/i18n/it.po new file mode 100644 index 000000000..1a292f074 --- /dev/null +++ b/sale_product_variant_attribute_tax/i18n/it.po @@ -0,0 +1,22 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_product_variant_attribute_tax +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 13.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-11-10 16:36+0000\n" +"Last-Translator: mymage \n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: sale_product_variant_attribute_tax +#: model:ir.model,name:sale_product_variant_attribute_tax.model_sale_order_line +msgid "Sales Order Line" +msgstr "Riga ordine di vendita" diff --git a/sale_product_variant_attribute_tax/i18n/sale_product_variant_attribute_tax.pot b/sale_product_variant_attribute_tax/i18n/sale_product_variant_attribute_tax.pot new file mode 100644 index 000000000..1bb85d59f --- /dev/null +++ b/sale_product_variant_attribute_tax/i18n/sale_product_variant_attribute_tax.pot @@ -0,0 +1,19 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_product_variant_attribute_tax +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 13.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: sale_product_variant_attribute_tax +#: model:ir.model,name:sale_product_variant_attribute_tax.model_sale_order_line +msgid "Sales Order Line" +msgstr "" diff --git a/sale_product_variant_attribute_tax/models/__init__.py b/sale_product_variant_attribute_tax/models/__init__.py new file mode 100644 index 000000000..49fac809e --- /dev/null +++ b/sale_product_variant_attribute_tax/models/__init__.py @@ -0,0 +1,2 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from . import sale_order diff --git a/sale_product_variant_attribute_tax/models/sale_order.py b/sale_product_variant_attribute_tax/models/sale_order.py new file mode 100644 index 000000000..ace27bf21 --- /dev/null +++ b/sale_product_variant_attribute_tax/models/sale_order.py @@ -0,0 +1,25 @@ +# Copyright 2016-2017 Tecnativa - Pedro M. Baeza +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from odoo import api, models + + +class SaleOrderLine(models.Model): + _inherit = "sale.order.line" + + @api.onchange("product_attribute_ids") + def _onchange_product_attribute_ids_configurator(self): + res = super()._onchange_product_attribute_ids_configurator() + # if there's a product set, taxes on that product have priority + if self.product_id or not self.product_tmpl_id: + return res + values = self.mapped("product_attribute_ids.value_id") + taxes = values.mapped("tax_ids").filtered( + lambda x: x.type_tax_use == "sale" + and x.company_id == self.order_id.company_id + ) + fiscal_pos = self.order_id.fiscal_position_id + # We can call this method although the fiscal position is not set + taxes = fiscal_pos.map_tax(taxes) + template_taxes = fiscal_pos.map_tax(self.product_tmpl_id.taxes_id) + self.tax_id = template_taxes + taxes + return res diff --git a/sale_product_variant_attribute_tax/readme/CONTEXT.rst b/sale_product_variant_attribute_tax/readme/CONTEXT.rst new file mode 100644 index 000000000..61cf4e16a --- /dev/null +++ b/sale_product_variant_attribute_tax/readme/CONTEXT.rst @@ -0,0 +1,3 @@ +As the product taxes are defined at product template level, you can't have some variants with an specific tax. + +These modules family covers the gap, adding the taxes at attribute level. This design decision has been taken for allowing to define the tax only once, as other options like having taxes at product variant level will force you to define the specific taxes for each of the variants that are affected. diff --git a/sale_product_variant_attribute_tax/readme/CONTRIBUTORS.rst b/sale_product_variant_attribute_tax/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..dfc917a0e --- /dev/null +++ b/sale_product_variant_attribute_tax/readme/CONTRIBUTORS.rst @@ -0,0 +1,6 @@ +* `Tecnativa `_: + + * Vicent Cubells + * Pedro M. Baeza + * Ernesto Tejeda + * Carolina Fernandez diff --git a/sale_product_variant_attribute_tax/readme/DESCRIPTION.rst b/sale_product_variant_attribute_tax/readme/DESCRIPTION.rst new file mode 100644 index 000000000..c3f48fc37 --- /dev/null +++ b/sale_product_variant_attribute_tax/readme/DESCRIPTION.rst @@ -0,0 +1,3 @@ +This module uses *product_variant_attribute_tax* for adding the taxes set +on product attribute values when adding a product in sales orders that contains +this attribute value. diff --git a/sale_product_variant_attribute_tax/readme/ROADMAP.rst b/sale_product_variant_attribute_tax/readme/ROADMAP.rst new file mode 100644 index 000000000..edb435741 --- /dev/null +++ b/sale_product_variant_attribute_tax/readme/ROADMAP.rst @@ -0,0 +1 @@ +- This module requires `sale_variant_configurator` as a way to avoid 2 glue modules, but it may be independent. diff --git a/sale_product_variant_attribute_tax/readme/USAGE.rst b/sale_product_variant_attribute_tax/readme/USAGE.rst new file mode 100644 index 000000000..e5c6bf609 --- /dev/null +++ b/sale_product_variant_attribute_tax/readme/USAGE.rst @@ -0,0 +1,8 @@ +To use this module, you need to: + +#. Go to *Sales > Orders > Quotations*, create a new quotation or edit + an existing one. +#. Create a new order line or edit an existing one. +#. when editing the table "Product attributes", the taxes of that sales + line will be completed with the default taxes of the attribute value + specified. diff --git a/sale_product_variant_attribute_tax/static/description/icon.png b/sale_product_variant_attribute_tax/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/sale_product_variant_attribute_tax/static/description/icon.png differ diff --git a/sale_product_variant_attribute_tax/static/description/index.html b/sale_product_variant_attribute_tax/static/description/index.html new file mode 100644 index 000000000..84f74bd4c --- /dev/null +++ b/sale_product_variant_attribute_tax/static/description/index.html @@ -0,0 +1,454 @@ + + + + + +Put attribute taxes on sales orders + + + +
+

Put attribute taxes on sales orders

+ + +

Production/Stable License: AGPL-3 OCA/product-variant Translate me on Weblate Try me on Runboat

+

This module uses product_variant_attribute_tax for adding the taxes set +on product attribute values when adding a product in sales orders that contains +this attribute value.

+

Table of contents

+ +
+

Use Cases / Context

+

As the product taxes are defined at product template level, you can’t have some variants with an specific tax.

+

These modules family covers the gap, adding the taxes at attribute level. This design decision has been taken for allowing to define the tax only once, as other options like having taxes at product variant level will force you to define the specific taxes for each of the variants that are affected.

+
+
+

Usage

+

To use this module, you need to:

+
    +
  1. Go to Sales > Orders > Quotations, create a new quotation or edit +an existing one.
  2. +
  3. Create a new order line or edit an existing one.
  4. +
  5. when editing the table “Product attributes”, the taxes of that sales +line will be completed with the default taxes of the attribute value +specified.
  6. +
+
+
+

Known issues / Roadmap

+
    +
  • This module requires sale_variant_configurator as a way to avoid 2 glue modules, but it may be independent.
  • +
+
+
+

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

+
    +
  • Tecnativa
  • +
+
+
+

Contributors

+
    +
  • Tecnativa:
      +
    • Vicent Cubells
    • +
    • Pedro M. Baeza
    • +
    • Ernesto Tejeda
    • +
    • Carolina Fernandez
    • +
    +
  • +
+
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/product-variant project on GitHub.

+

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

+
+
+
+ + diff --git a/sale_product_variant_attribute_tax/tests/__init__.py b/sale_product_variant_attribute_tax/tests/__init__.py new file mode 100644 index 000000000..ada2becb3 --- /dev/null +++ b/sale_product_variant_attribute_tax/tests/__init__.py @@ -0,0 +1,2 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from . import test_sale_product_variant_attribute_tax diff --git a/sale_product_variant_attribute_tax/tests/test_sale_product_variant_attribute_tax.py b/sale_product_variant_attribute_tax/tests/test_sale_product_variant_attribute_tax.py new file mode 100644 index 000000000..1f13fa748 --- /dev/null +++ b/sale_product_variant_attribute_tax/tests/test_sale_product_variant_attribute_tax.py @@ -0,0 +1,140 @@ +# Copyright 2016-2017 Tecnativa - Pedro M. Baeza +# Copyright 2024 Tecnativa - Carolina Fernandez +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from odoo.tests import common + + +class TestSaleProductVariantAttributeTax(common.TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.tax = cls.env["account.tax"].create( + {"name": "Tax by attribute value", "amount": 10} + ) + cls.tax2 = cls.env["account.tax"].create( + {"name": "Replacement Tax", "amount": 10} + ) + cls.fiscal_position = cls.env["account.fiscal.position"].create( + { + "name": "Test fiscal position", + "tax_ids": [ + ( + 0, + 0, + {"tax_src_id": cls.tax.id, "tax_dest_id": cls.tax2.id}, + ), + ], + } + ) + cls.partner = cls.env["res.partner"].create( + {"name": "Test", "property_account_position_id": False} + ) + cls.attribute = cls.env["product.attribute"].create({"name": "Test attribute"}) + cls.attribute_value = cls.env["product.attribute.value"].create( + { + "name": "Test value", + "attribute_id": cls.attribute.id, + "tax_ids": [(6, 0, cls.tax.ids)], + } + ) + cls.attribute_value2 = cls.env["product.attribute.value"].create( + {"name": "Test value 2", "attribute_id": cls.attribute.id} + ) + obj = cls.env["product.template"].with_context(check_variant_creation=True) + cls.product_template = obj.create( + { + "name": "Test template", + "no_create_variants": "yes", + "taxes_id": False, + "attribute_line_ids": [ + ( + 0, + 0, + { + "attribute_id": cls.attribute.id, + "value_ids": [(6, 0, cls.attribute_value.ids)], + }, + ), + ], + } + ) + cls.order = cls.env["sale.order"].create({"partner_id": cls.partner.id}) + + def test_select_attribute_wo_tax(self): + line = self.env["sale.order.line"].new( + { + "order_id": self.order.id, + "product_tmpl_id": self.product_template.id, + "name": self.product_template.name, + "product_uom_qty": 1, + "product_uom": self.product_template.uom_id.id, + "product_attribute_ids": [ + ( + 0, + 0, + { + "product_tmpl_id": self.product_template.id, + "attribute_id": self.attribute.id, + "value_id": self.attribute_value2.id, + "owner_model": "sale.order.line", + }, + ) + ], + "create_product_variant": True, + } + ) + line._onchange_product_attribute_ids_configurator() + self.assertFalse(line.tax_id) + + def test_select_attribute_with_tax(self): + line = self.env["sale.order.line"].new( + { + "order_id": self.order.id, + "product_tmpl_id": self.product_template.id, + "name": self.product_template.name, + "product_uom_qty": 1, + "product_uom": self.product_template.uom_id.id, + "product_attribute_ids": [ + ( + 0, + 0, + { + "product_tmpl_id": self.product_template.id, + "attribute_id": self.attribute.id, + "value_id": self.attribute_value.id, + "owner_model": "sale.order.line", + }, + ) + ], + "create_product_variant": True, + } + ) + line._onchange_product_attribute_ids_configurator() + self.assertIn(self.tax.id, line.tax_id.ids) + + def test_select_attribute_with_tax_fp_mapped(self): + self.order.fiscal_position_id = self.fiscal_position + line = self.env["sale.order.line"].new( + { + "order_id": self.order.id, + "product_tmpl_id": self.product_template.id, + "name": self.product_template.name, + "product_uom_qty": 1, + "product_uom": self.product_template.uom_id.id, + "product_attribute_ids": [ + ( + 0, + 0, + { + "product_tmpl_id": self.product_template.id, + "attribute_id": self.attribute.id, + "value_id": self.attribute_value.id, + "owner_model": "sale.order.line", + }, + ) + ], + "create_product_variant": True, + } + ) + line._onchange_product_attribute_ids_configurator() + self.assertIn(self.tax2.id, line.tax_id.ids) diff --git a/setup/sale_product_variant_attribute_tax/odoo/addons/sale_product_variant_attribute_tax b/setup/sale_product_variant_attribute_tax/odoo/addons/sale_product_variant_attribute_tax new file mode 120000 index 000000000..212e70531 --- /dev/null +++ b/setup/sale_product_variant_attribute_tax/odoo/addons/sale_product_variant_attribute_tax @@ -0,0 +1 @@ +../../../../sale_product_variant_attribute_tax \ No newline at end of file diff --git a/setup/sale_product_variant_attribute_tax/setup.py b/setup/sale_product_variant_attribute_tax/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/sale_product_variant_attribute_tax/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)