From dc22bf98bc142dea1d3e09126a39158d3eab31ca Mon Sep 17 00:00:00 2001 From: Telmo Santos Date: Tue, 19 Mar 2024 07:55:03 +0100 Subject: [PATCH 01/10] [ADD] product_pricelist_alternative --- product_pricelist_alternative/README.rst | 80 ++++ product_pricelist_alternative/__init__.py | 1 + product_pricelist_alternative/__manifest__.py | 22 + product_pricelist_alternative/i18n/fr.po | 46 ++ .../i18n/product_pricelist_alternative.pot | 71 +++ .../models/__init__.py | 2 + .../models/product_pricelist.py | 76 ++++ .../models/product_pricelist_item.py | 17 + .../readme/CONTRIBUTORS.rst | 2 + .../readme/DESCRIPTION.rst | 4 + .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 424 ++++++++++++++++++ .../tests/__init__.py | 1 + .../tests/test_pricelist_alternative.py | 176 ++++++++ .../views/product_pricelist_item_view.xml | 38 ++ .../views/product_pricelist_view.xml | 50 +++ 16 files changed, 1010 insertions(+) create mode 100644 product_pricelist_alternative/README.rst create mode 100644 product_pricelist_alternative/__init__.py create mode 100644 product_pricelist_alternative/__manifest__.py create mode 100644 product_pricelist_alternative/i18n/fr.po create mode 100644 product_pricelist_alternative/i18n/product_pricelist_alternative.pot create mode 100644 product_pricelist_alternative/models/__init__.py create mode 100644 product_pricelist_alternative/models/product_pricelist.py create mode 100644 product_pricelist_alternative/models/product_pricelist_item.py create mode 100644 product_pricelist_alternative/readme/CONTRIBUTORS.rst create mode 100644 product_pricelist_alternative/readme/DESCRIPTION.rst create mode 100644 product_pricelist_alternative/static/description/icon.png create mode 100644 product_pricelist_alternative/static/description/index.html create mode 100644 product_pricelist_alternative/tests/__init__.py create mode 100644 product_pricelist_alternative/tests/test_pricelist_alternative.py create mode 100644 product_pricelist_alternative/views/product_pricelist_item_view.xml create mode 100644 product_pricelist_alternative/views/product_pricelist_view.xml diff --git a/product_pricelist_alternative/README.rst b/product_pricelist_alternative/README.rst new file mode 100644 index 00000000000..197b4f44711 --- /dev/null +++ b/product_pricelist_alternative/README.rst @@ -0,0 +1,80 @@ +============================= +Product Pricelist Alternative +============================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:86e2eb1f76f677e2d3704362fdf38f1f275251b62d7ac5273c956935e824eade + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Fproduct--attribute-lightgray.png?logo=github + :target: https://github.com/OCA/product-attribute/tree/16.0/product_pricelist_alternative + :alt: OCA/product-attribute +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/product-attribute-16-0/product-attribute-16-0-product_pricelist_alternative + :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-attribute&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +It allows you to define alternative price lists to a reference price list. +As a general rule, the price of a given product is obtained from the minimum between its reference price list and the alternative price lists. + +However, if the product's reference price has been calculated on the basis of a price rule in which the "Alternative Pricelist Policy = Ignore" field is selected, the alternative price lists will not be taken into account. + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Camptocamp + +Contributors +~~~~~~~~~~~~ + +* Telmo Santos +* Akim Juillerat + +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-attribute `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/product_pricelist_alternative/__init__.py b/product_pricelist_alternative/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/product_pricelist_alternative/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/product_pricelist_alternative/__manifest__.py b/product_pricelist_alternative/__manifest__.py new file mode 100644 index 00000000000..07bc701fbca --- /dev/null +++ b/product_pricelist_alternative/__manifest__.py @@ -0,0 +1,22 @@ +# Copyright 2024 Camptocamp (). +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + "name": "Product Pricelist Alternative", + "version": "16.0.1.0.0", + "development_status": "Beta", + "category": "Product", + "summary": "Calculate product price based on alternative pricelists", + "author": "Camptocamp, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/product-attribute", + "license": "AGPL-3", + "depends": [ + "product", + ], + "data": [ + "views/product_pricelist_item_view.xml", + "views/product_pricelist_view.xml", + ], + "installable": True, + "auto_install": False, +} diff --git a/product_pricelist_alternative/i18n/fr.po b/product_pricelist_alternative/i18n/fr.po new file mode 100644 index 00000000000..e536a68109e --- /dev/null +++ b/product_pricelist_alternative/i18n/fr.po @@ -0,0 +1,46 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_pricelist_alternative +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-03-19 09:06+0000\n" +"PO-Revision-Date: 2024-03-19 09:06+0000\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: product_pricelist_alternative +#: model:ir.model.fields,field_description:product_pricelist_alternative.field_product_pricelist_item__alternative_pricelist_policy +msgid "Alternative Pricelist Policy" +msgstr "Politique de prix alternatifs" + +#. module: product_pricelist_alternative +#: model_terms:ir.ui.view,arch_db:product_pricelist_alternative.product_pricelist_view +msgid "Alternative Pricelists" +msgstr "Listes de prix alternatives" + +#. module: product_pricelist_alternative +#: model:ir.model.fields,field_description:product_pricelist_alternative.field_product_pricelist__alternative_pricelist_ids +msgid "Alternative pricelists" +msgstr "Listes de prix alternatives" + +#. module: product_pricelist_alternative +#: model_terms:ir.ui.view,arch_db:product_pricelist_alternative.product_pricelist_view +msgid "Alternative to Pricelist" +msgstr "Alternative à la liste de prix" + +#. module: product_pricelist_alternative +#: model:ir.model.fields.selection,name:product_pricelist_alternative.selection__product_pricelist_item__alternative_pricelist_policy__ignore +msgid "Ignore alternatives" +msgstr "Ignorer les alternatives" + +#. module: product_pricelist_alternative +#: model:ir.model.fields.selection,name:product_pricelist_alternative.selection__product_pricelist_item__alternative_pricelist_policy__use_lower_price +msgid "Use lower price" +msgstr "Utiliser le prix le plus bas" diff --git a/product_pricelist_alternative/i18n/product_pricelist_alternative.pot b/product_pricelist_alternative/i18n/product_pricelist_alternative.pot new file mode 100644 index 00000000000..1e95b04c24f --- /dev/null +++ b/product_pricelist_alternative/i18n/product_pricelist_alternative.pot @@ -0,0 +1,71 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_pricelist_alternative +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: product_pricelist_alternative +#: model:ir.model.fields,field_description:product_pricelist_alternative.field_product_pricelist_item__alternative_pricelist_policy +msgid "Alternative Pricelist Policy" +msgstr "" + +#. module: product_pricelist_alternative +#: model_terms:ir.ui.view,arch_db:product_pricelist_alternative.product_pricelist_view +msgid "Alternative Pricelists" +msgstr "" + +#. module: product_pricelist_alternative +#: model:ir.model.fields,field_description:product_pricelist_alternative.field_product_pricelist__alternative_pricelist_ids +msgid "Alternative pricelists" +msgstr "" + +#. module: product_pricelist_alternative +#: model_terms:ir.ui.view,arch_db:product_pricelist_alternative.product_pricelist_view +msgid "Alternative to Pricelist" +msgstr "" + +#. module: product_pricelist_alternative +#: model:ir.model.fields.selection,name:product_pricelist_alternative.selection__product_pricelist_item__alternative_pricelist_policy__ignore +msgid "Ignore alternatives" +msgstr "" + +#. module: product_pricelist_alternative +#: model:ir.model.fields,field_description:product_pricelist_alternative.field_product_pricelist__is_alternative_to_pricelist_count +msgid "Is Alternative To Pricelist Count" +msgstr "" + +#. module: product_pricelist_alternative +#. odoo-python +#: code:addons/product_pricelist_alternative/models/product_pricelist.py:0 +#, python-format +msgid "Is Alternative to Pricelist" +msgstr "" + +#. module: product_pricelist_alternative +#: model:ir.model.fields,field_description:product_pricelist_alternative.field_product_pricelist__is_alternative_to_pricelist_ids +msgid "Is alternative to pricelists" +msgstr "" + +#. module: product_pricelist_alternative +#: model:ir.model,name:product_pricelist_alternative.model_product_pricelist +msgid "Pricelist" +msgstr "" + +#. module: product_pricelist_alternative +#: model:ir.model,name:product_pricelist_alternative.model_product_pricelist_item +msgid "Pricelist Rule" +msgstr "" + +#. module: product_pricelist_alternative +#: model:ir.model.fields.selection,name:product_pricelist_alternative.selection__product_pricelist_item__alternative_pricelist_policy__use_lower_price +msgid "Use lower price" +msgstr "" diff --git a/product_pricelist_alternative/models/__init__.py b/product_pricelist_alternative/models/__init__.py new file mode 100644 index 00000000000..cb6c4e8fef5 --- /dev/null +++ b/product_pricelist_alternative/models/__init__.py @@ -0,0 +1,2 @@ +from . import product_pricelist +from . import product_pricelist_item diff --git a/product_pricelist_alternative/models/product_pricelist.py b/product_pricelist_alternative/models/product_pricelist.py new file mode 100644 index 00000000000..4c96b17c7ba --- /dev/null +++ b/product_pricelist_alternative/models/product_pricelist.py @@ -0,0 +1,76 @@ +# Copyright 2024 Camptocamp (). +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import _, api, fields, models + + +class Pricelist(models.Model): + _inherit = "product.pricelist" + + alternative_pricelist_ids = fields.Many2many( + comodel_name="product.pricelist", + string="Alternative pricelists", + relation="product_pricelist_alternative_rel", + column1="origin_id", + column2="alternative_id", + domain="[('id', '!=', id)]", + ) + is_alternative_to_pricelist_ids = fields.Many2many( + comodel_name="product.pricelist", + string="Is alternative to pricelists", + relation="product_pricelist_alternative_rel", + column1="alternative_id", + column2="origin_id", + ) + is_alternative_to_pricelist_count = fields.Integer( + compute="_compute_is_alternative_to_pricelist_count" + ) + + @api.depends("is_alternative_to_pricelist_ids") + def _compute_is_alternative_to_pricelist_count(self): + groups = self.read_group( + [("alternative_pricelist_ids", "in", self.ids)], + ["alternative_pricelist_ids"], + "alternative_pricelist_ids", + lazy=False, + ) + data = { + group["alternative_pricelist_ids"][0]: group["__count"] for group in groups + } + for pricelist in self: + pricelist.is_alternative_to_pricelist_count = data.get(pricelist.id, 0) + + def action_view_is_alternative_to_pricelist(self): + self.ensure_one() + action = { + "type": "ir.actions.act_window", + "name": _("Is Alternative to Pricelist"), + "res_model": "product.pricelist", + "view_mode": "tree,form", + "domain": [("id", "in", self.is_alternative_to_pricelist_ids.ids)], + "context": dict(self.env.context, create=False), + } + if self.is_alternative_to_pricelist_count == 1: + action.update( + {"view_mode": "form", "res_id": self.is_alternative_to_pricelist_ids.id} + ) + return action + + def _compute_price_rule(self, products, qty, uom=None, date=False, **kwargs): + res = super()._compute_price_rule(products, qty, uom=uom, date=date, **kwargs) + for product in products: + reference_pricelist_item = self.env["product.pricelist.item"].browse( + res[product.id][1] + ) + if ( + reference_pricelist_item.alternative_pricelist_policy + == "use_lower_price" + ): + for alternative_pricelist in self.alternative_pricelist_ids: + alternative_price_rule = alternative_pricelist._compute_price_rule( + product, qty, uom=uom, date=date, **kwargs + ) + # use alternative price if lower + if alternative_price_rule[product.id][0] < res[product.id][0]: + res[product.id] = alternative_price_rule[product.id] + return res diff --git a/product_pricelist_alternative/models/product_pricelist_item.py b/product_pricelist_alternative/models/product_pricelist_item.py new file mode 100644 index 00000000000..55c69d34ca7 --- /dev/null +++ b/product_pricelist_alternative/models/product_pricelist_item.py @@ -0,0 +1,17 @@ +# Copyright 2024 Camptocamp (). +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class PricelistItem(models.Model): + _inherit = "product.pricelist.item" + + alternative_pricelist_policy = fields.Selection( + selection=[ + ("use_lower_price", "Use lower price"), + ("ignore", "Ignore alternatives"), + ], + default="use_lower_price", + required=True, + ) diff --git a/product_pricelist_alternative/readme/CONTRIBUTORS.rst b/product_pricelist_alternative/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000000..2052422f4dc --- /dev/null +++ b/product_pricelist_alternative/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Telmo Santos +* Akim Juillerat diff --git a/product_pricelist_alternative/readme/DESCRIPTION.rst b/product_pricelist_alternative/readme/DESCRIPTION.rst new file mode 100644 index 00000000000..a535b85646a --- /dev/null +++ b/product_pricelist_alternative/readme/DESCRIPTION.rst @@ -0,0 +1,4 @@ +It allows you to define alternative price lists to a reference price list. +As a general rule, the price of a given product is obtained from the minimum between its reference price list and the alternative price lists. + +However, if the product's reference price has been calculated on the basis of a price rule in which the "Alternative Pricelist Policy = Ignore" field is selected, the alternative price lists will not be taken into account. diff --git a/product_pricelist_alternative/static/description/icon.png b/product_pricelist_alternative/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/product_pricelist_alternative/static/description/index.html b/product_pricelist_alternative/static/description/index.html new file mode 100644 index 00000000000..899ce051196 --- /dev/null +++ b/product_pricelist_alternative/static/description/index.html @@ -0,0 +1,424 @@ + + + + + + +Product Pricelist Alternative + + + +
+

Product Pricelist Alternative

+ + +

Beta License: AGPL-3 OCA/product-attribute Translate me on Weblate Try me on Runboat

+

It allows you to define alternative price lists to a reference price list. +As a general rule, the price of a given product is obtained from the minimum between its reference price list and the alternative price lists.

+

However, if the product’s reference price has been calculated on the basis of a price rule in which the “Alternative Pricelist Policy = Ignore” field is selected, the alternative price lists will not be taken into account.

+

Table of contents

+ +
+

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

+
    +
  • Camptocamp
  • +
+
+ +
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

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

+

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

+

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

+
+
+
+ + diff --git a/product_pricelist_alternative/tests/__init__.py b/product_pricelist_alternative/tests/__init__.py new file mode 100644 index 00000000000..8cc19ce9ce3 --- /dev/null +++ b/product_pricelist_alternative/tests/__init__.py @@ -0,0 +1 @@ +from . import test_pricelist_alternative diff --git a/product_pricelist_alternative/tests/test_pricelist_alternative.py b/product_pricelist_alternative/tests/test_pricelist_alternative.py new file mode 100644 index 00000000000..4206c0c7454 --- /dev/null +++ b/product_pricelist_alternative/tests/test_pricelist_alternative.py @@ -0,0 +1,176 @@ +# Copyright 2024 Camptocamp (). +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo.fields import Command +from odoo.tests import common, tagged + +from odoo.addons.base.tests.common import DISABLED_MAIL_CONTEXT + + +@tagged("post_install", "-at_install") +class TestPricelistAlternative(common.TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env["base"].with_context(**DISABLED_MAIL_CONTEXT).env + cls.datacard = cls.env["product.product"].create( + {"name": "Data card", "list_price": 100} + ) + cls.usb_adapter = cls.env["product.product"].create( + {"name": "Usb adapter", "list_price": 100} + ) + + cls.alternative_pricelist_01 = cls.env["product.pricelist"].create( + { + "name": "Alternative pricelist 01", + "item_ids": [ + Command.create( + { + "compute_price": "fixed", + "product_id": cls.usb_adapter.id, + "applied_on": "0_product_variant", + "fixed_price": 70, + } + ), + ], + } + ) + cls.alternative_pricelist_02 = cls.env["product.pricelist"].create( + { + "name": "Alternative pricelist 02", + "item_ids": [ + Command.create( + { + "compute_price": "fixed", + "product_id": cls.datacard.id, + "applied_on": "0_product_variant", + "fixed_price": 80, + } + ), + ], + } + ) + + cls.pricelist01 = cls.env["product.pricelist"].create( + { + "name": "Sale pricelist", + "item_ids": [ + Command.create( + { + "compute_price": "fixed", + "product_id": cls.usb_adapter.id, + "applied_on": "0_product_variant", + "fixed_price": 95, + } + ), + Command.create( + { + "compute_price": "fixed", + "product_id": cls.datacard.id, + "applied_on": "0_product_variant", + "fixed_price": 70, + } + ), + ], + "alternative_pricelist_ids": [ + (4, cls.alternative_pricelist_01.id), + (4, cls.alternative_pricelist_02.id), + ], + } + ) + + cls.product_categ01 = cls.env["product.category"].create( + {"name": "Category 01"} + ) + cls.usb_adapter.categ_id = cls.product_categ01 + + cls.pricelist02 = cls.env["product.pricelist"].create( + { + "name": "Sale pricelist", + "item_ids": [ + Command.create( + { + "compute_price": "percentage", + "applied_on": "2_product_category", + "categ_id": cls.product_categ01.id, + "percent_price": 40, + } + ), + ], + "alternative_pricelist_ids": [ + (4, cls.alternative_pricelist_01.id), + ], + } + ) + + def test_is_alternative_to_pricelist_count(self): + """Test that the is_alternative_to_pricelist_count is correctly computed""" + + self.assertEqual( + self.alternative_pricelist_01.is_alternative_to_pricelist_count, 2 + ) + self.assertEqual( + self.alternative_pricelist_02.is_alternative_to_pricelist_count, 1 + ) + + def test_action_view_is_alternative_to_pricelist(self): + action = self.alternative_pricelist_01.action_view_is_alternative_to_pricelist() + self.assertEqual(action["view_mode"], "tree,form") + self.assertEqual( + action["domain"][0][2], + self.alternative_pricelist_01.is_alternative_to_pricelist_ids.ids, + ) + + action = self.alternative_pricelist_02.action_view_is_alternative_to_pricelist() + self.assertEqual(action["view_mode"], "form") + self.assertEqual( + action["domain"][0][2], + self.alternative_pricelist_02.is_alternative_to_pricelist_ids.ids, + ) + + def test_product_price_considering_alternative_pricelist_with_lower_price(self): + """Test that the product price is computed considering the alternative + pricelist with the lower price""" + + # Best price on alternative pricelist01 + result = self.pricelist01._compute_price_rule( + self.usb_adapter, 1.0, self.usb_adapter.uom_id + ) + self.assertEqual(result[self.usb_adapter.id][0], 70.0) + self.assertEqual( + result[self.usb_adapter.id][1], self.alternative_pricelist_01.item_ids[0].id + ) + # Best price on pricelist02 + result = self.pricelist02._compute_price_rule( + self.usb_adapter, 1.0, self.usb_adapter.uom_id + ) + self.assertEqual(result[self.usb_adapter.id][0], 60.0) + self.assertEqual( + result[self.usb_adapter.id][1], self.pricelist02.item_ids[0].id + ) + + def test_product_price_ignore_alternative_pricelist(self): + """Test that the product price ignore alternative pricelist""" + + # Set the pricelist items policy to ignore alternative pricelist + self.pricelist01.item_ids.write({"alternative_pricelist_policy": "ignore"}) + self.pricelist02.item_ids.write({"alternative_pricelist_policy": "ignore"}) + + # We won't consider the alternative pricelist + self.assertEqual(self.pricelist01._get_product_price(self.usb_adapter, 1.0), 95) + self.assertEqual(self.pricelist02._get_product_price(self.usb_adapter, 1.0), 60) + + result = self.pricelist01._compute_price_rule( + self.usb_adapter, 1.0, self.usb_adapter.uom_id + ) + self.assertEqual(result[self.usb_adapter.id][0], 95.0) + self.assertEqual( + result[self.usb_adapter.id][1], self.pricelist01.item_ids[1].id + ) + result = self.pricelist02._compute_price_rule( + self.usb_adapter, 1.0, self.usb_adapter.uom_id + ) + self.assertEqual(result[self.usb_adapter.id][0], 60.0) + self.assertEqual( + result[self.usb_adapter.id][1], self.pricelist02.item_ids[0].id + ) diff --git a/product_pricelist_alternative/views/product_pricelist_item_view.xml b/product_pricelist_alternative/views/product_pricelist_item_view.xml new file mode 100644 index 00000000000..501c4c2ef58 --- /dev/null +++ b/product_pricelist_alternative/views/product_pricelist_item_view.xml @@ -0,0 +1,38 @@ + + + + product.pricelist.item.form + product.pricelist.item + + + + + + + + + + product.pricelist.item.tree + product.pricelist.item + + + + + + + + + + product.pricelist.item.tree + product.pricelist.item + + + + + + + + diff --git a/product_pricelist_alternative/views/product_pricelist_view.xml b/product_pricelist_alternative/views/product_pricelist_view.xml new file mode 100644 index 00000000000..eb04039b56c --- /dev/null +++ b/product_pricelist_alternative/views/product_pricelist_view.xml @@ -0,0 +1,50 @@ + + + + product.pricelist.form + product.pricelist + + + +
+ +
+
+ + + + + + + + + + + + +
+
+
From 4eeb9b2993b75bd6f1e9716ce8f080dc6c518652 Mon Sep 17 00:00:00 2001 From: mymage Date: Tue, 2 Apr 2024 09:48:28 +0000 Subject: [PATCH 02/10] Added translation using Weblate (Italian) --- product_pricelist_alternative/i18n/it.po | 74 ++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 product_pricelist_alternative/i18n/it.po diff --git a/product_pricelist_alternative/i18n/it.po b/product_pricelist_alternative/i18n/it.po new file mode 100644 index 00000000000..173e46817f6 --- /dev/null +++ b/product_pricelist_alternative/i18n/it.po @@ -0,0 +1,74 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_pricelist_alternative +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-04-02 11:38+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: product_pricelist_alternative +#: model:ir.model.fields,field_description:product_pricelist_alternative.field_product_pricelist_item__alternative_pricelist_policy +msgid "Alternative Pricelist Policy" +msgstr "Politica dei listini alternativi" + +#. module: product_pricelist_alternative +#: model_terms:ir.ui.view,arch_db:product_pricelist_alternative.product_pricelist_view +msgid "Alternative Pricelists" +msgstr "Listini alternativi" + +#. module: product_pricelist_alternative +#: model:ir.model.fields,field_description:product_pricelist_alternative.field_product_pricelist__alternative_pricelist_ids +msgid "Alternative pricelists" +msgstr "Listini alternativi" + +#. module: product_pricelist_alternative +#: model_terms:ir.ui.view,arch_db:product_pricelist_alternative.product_pricelist_view +msgid "Alternative to Pricelist" +msgstr "Alternativa al listino" + +#. module: product_pricelist_alternative +#: model:ir.model.fields.selection,name:product_pricelist_alternative.selection__product_pricelist_item__alternative_pricelist_policy__ignore +msgid "Ignore alternatives" +msgstr "Ignora alternative" + +#. module: product_pricelist_alternative +#: model:ir.model.fields,field_description:product_pricelist_alternative.field_product_pricelist__is_alternative_to_pricelist_count +msgid "Is Alternative To Pricelist Count" +msgstr "Conteggio alternative ai listino" + +#. module: product_pricelist_alternative +#. odoo-python +#: code:addons/product_pricelist_alternative/models/product_pricelist.py:0 +#, python-format +msgid "Is Alternative to Pricelist" +msgstr "È alternativa al listino" + +#. module: product_pricelist_alternative +#: model:ir.model.fields,field_description:product_pricelist_alternative.field_product_pricelist__is_alternative_to_pricelist_ids +msgid "Is alternative to pricelists" +msgstr "È alternativa ai listini" + +#. module: product_pricelist_alternative +#: model:ir.model,name:product_pricelist_alternative.model_product_pricelist +msgid "Pricelist" +msgstr "Listino prezzi" + +#. module: product_pricelist_alternative +#: model:ir.model,name:product_pricelist_alternative.model_product_pricelist_item +msgid "Pricelist Rule" +msgstr "Regola listino prezzi" + +#. module: product_pricelist_alternative +#: model:ir.model.fields.selection,name:product_pricelist_alternative.selection__product_pricelist_item__alternative_pricelist_policy__use_lower_price +msgid "Use lower price" +msgstr "Utilizzare prezzo minimo" From fc20d828a121458c6cb7e32c9085d5aef9874830 Mon Sep 17 00:00:00 2001 From: Telmo Santos Date: Mon, 17 Jun 2024 11:12:06 +0200 Subject: [PATCH 03/10] [IMP] product_pricelist_alternative skip_alternative_pricelist --- .../models/product_pricelist.py | 6 ++++++ .../tests/test_pricelist_alternative.py | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/product_pricelist_alternative/models/product_pricelist.py b/product_pricelist_alternative/models/product_pricelist.py index 4c96b17c7ba..417f8d5c8ab 100644 --- a/product_pricelist_alternative/models/product_pricelist.py +++ b/product_pricelist_alternative/models/product_pricelist.py @@ -58,6 +58,12 @@ def action_view_is_alternative_to_pricelist(self): def _compute_price_rule(self, products, qty, uom=None, date=False, **kwargs): res = super()._compute_price_rule(products, qty, uom=uom, date=date, **kwargs) + + # In some contexts we want to ignore alternative pricelists + # and return the original price + if self.env.context.get("skip_alternative_pricelist", False): + return res + for product in products: reference_pricelist_item = self.env["product.pricelist.item"].browse( res[product.id][1] diff --git a/product_pricelist_alternative/tests/test_pricelist_alternative.py b/product_pricelist_alternative/tests/test_pricelist_alternative.py index 4206c0c7454..75035b4a3ec 100644 --- a/product_pricelist_alternative/tests/test_pricelist_alternative.py +++ b/product_pricelist_alternative/tests/test_pricelist_alternative.py @@ -174,3 +174,14 @@ def test_product_price_ignore_alternative_pricelist(self): self.assertEqual( result[self.usb_adapter.id][1], self.pricelist02.item_ids[0].id ) + + def test_skip_alternative_pricelist(self): + """Test product price computation with skip alternative pricelist""" + self.assertEqual(self.pricelist01._get_product_price(self.usb_adapter, 1.0), 70) + # Set the context to skip alternative pricelist + self.assertEqual( + self.pricelist01.with_context( + skip_alternative_pricelist=True + )._get_product_price(self.usb_adapter, 1.0), + 95, + ) From 4b999c905b0a7eb428e89ed04316d8977ff9ad4d Mon Sep 17 00:00:00 2001 From: Telmo Santos Date: Mon, 17 Jun 2024 11:13:36 +0200 Subject: [PATCH 04/10] [IMP] product_pricelist_alternative move test setup code to common file --- product_pricelist_alternative/README.rst | 2 +- product_pricelist_alternative/__manifest__.py | 2 +- .../static/description/index.html | 3 +- product_pricelist_alternative/tests/common.py | 104 ++++++++++++++++++ .../tests/test_pricelist_alternative.py | 101 +---------------- 5 files changed, 111 insertions(+), 101 deletions(-) create mode 100644 product_pricelist_alternative/tests/common.py diff --git a/product_pricelist_alternative/README.rst b/product_pricelist_alternative/README.rst index 197b4f44711..41f3c081839 100644 --- a/product_pricelist_alternative/README.rst +++ b/product_pricelist_alternative/README.rst @@ -7,7 +7,7 @@ Product Pricelist Alternative !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:86e2eb1f76f677e2d3704362fdf38f1f275251b62d7ac5273c956935e824eade + !! source digest: sha256:dff2812f29ba92a28c38d97a2aeb70093bfcaeba432764d5f80c73ea6e52040b !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/product_pricelist_alternative/__manifest__.py b/product_pricelist_alternative/__manifest__.py index 07bc701fbca..740ca72fed4 100644 --- a/product_pricelist_alternative/__manifest__.py +++ b/product_pricelist_alternative/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Product Pricelist Alternative", - "version": "16.0.1.0.0", + "version": "16.0.1.1.0", "development_status": "Beta", "category": "Product", "summary": "Calculate product price based on alternative pricelists", diff --git a/product_pricelist_alternative/static/description/index.html b/product_pricelist_alternative/static/description/index.html index 899ce051196..75a11f81f15 100644 --- a/product_pricelist_alternative/static/description/index.html +++ b/product_pricelist_alternative/static/description/index.html @@ -1,4 +1,3 @@ - @@ -367,7 +366,7 @@

Product Pricelist Alternative

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:86e2eb1f76f677e2d3704362fdf38f1f275251b62d7ac5273c956935e824eade +!! source digest: sha256:dff2812f29ba92a28c38d97a2aeb70093bfcaeba432764d5f80c73ea6e52040b !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 OCA/product-attribute Translate me on Weblate Try me on Runboat

It allows you to define alternative price lists to a reference price list. diff --git a/product_pricelist_alternative/tests/common.py b/product_pricelist_alternative/tests/common.py new file mode 100644 index 00000000000..1e700c5168c --- /dev/null +++ b/product_pricelist_alternative/tests/common.py @@ -0,0 +1,104 @@ +# Copyright 2024 Camptocamp (). +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo.fields import Command +from odoo.tests import common, tagged + +from odoo.addons.base.tests.common import DISABLED_MAIL_CONTEXT + + +@tagged("post_install", "-at_install") +class CommonProductPricelistAlternative(common.TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env["base"].with_context(**DISABLED_MAIL_CONTEXT).env + cls.datacard = cls.env["product.product"].create( + {"name": "Data card", "list_price": 100} + ) + cls.usb_adapter = cls.env["product.product"].create( + {"name": "Usb adapter", "list_price": 100} + ) + + cls.alternative_pricelist_01 = cls.env["product.pricelist"].create( + { + "name": "Alternative pricelist 01", + "item_ids": [ + Command.create( + { + "compute_price": "fixed", + "product_id": cls.usb_adapter.id, + "applied_on": "0_product_variant", + "fixed_price": 70, + } + ), + ], + } + ) + cls.alternative_pricelist_02 = cls.env["product.pricelist"].create( + { + "name": "Alternative pricelist 02", + "item_ids": [ + Command.create( + { + "compute_price": "fixed", + "product_id": cls.datacard.id, + "applied_on": "0_product_variant", + "fixed_price": 80, + } + ), + ], + } + ) + + cls.pricelist01 = cls.env["product.pricelist"].create( + { + "name": "Sale pricelist", + "item_ids": [ + Command.create( + { + "compute_price": "fixed", + "product_id": cls.usb_adapter.id, + "applied_on": "0_product_variant", + "fixed_price": 95, + } + ), + Command.create( + { + "compute_price": "fixed", + "product_id": cls.datacard.id, + "applied_on": "0_product_variant", + "fixed_price": 70, + } + ), + ], + "alternative_pricelist_ids": [ + (4, cls.alternative_pricelist_01.id), + (4, cls.alternative_pricelist_02.id), + ], + } + ) + + cls.product_categ01 = cls.env["product.category"].create( + {"name": "Category 01"} + ) + cls.usb_adapter.categ_id = cls.product_categ01 + + cls.pricelist02 = cls.env["product.pricelist"].create( + { + "name": "Sale pricelist", + "item_ids": [ + Command.create( + { + "compute_price": "percentage", + "applied_on": "2_product_category", + "categ_id": cls.product_categ01.id, + "percent_price": 40, + } + ), + ], + "alternative_pricelist_ids": [ + (4, cls.alternative_pricelist_01.id), + ], + } + ) diff --git a/product_pricelist_alternative/tests/test_pricelist_alternative.py b/product_pricelist_alternative/tests/test_pricelist_alternative.py index 75035b4a3ec..28f5f7902e3 100644 --- a/product_pricelist_alternative/tests/test_pricelist_alternative.py +++ b/product_pricelist_alternative/tests/test_pricelist_alternative.py @@ -1,108 +1,15 @@ # Copyright 2024 Camptocamp (). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo.fields import Command from odoo.tests import common, tagged -from odoo.addons.base.tests.common import DISABLED_MAIL_CONTEXT +from .common import CommonProductPricelistAlternative @tagged("post_install", "-at_install") -class TestPricelistAlternative(common.TransactionCase): - @classmethod - def setUpClass(cls): - super().setUpClass() - cls.env = cls.env["base"].with_context(**DISABLED_MAIL_CONTEXT).env - cls.datacard = cls.env["product.product"].create( - {"name": "Data card", "list_price": 100} - ) - cls.usb_adapter = cls.env["product.product"].create( - {"name": "Usb adapter", "list_price": 100} - ) - - cls.alternative_pricelist_01 = cls.env["product.pricelist"].create( - { - "name": "Alternative pricelist 01", - "item_ids": [ - Command.create( - { - "compute_price": "fixed", - "product_id": cls.usb_adapter.id, - "applied_on": "0_product_variant", - "fixed_price": 70, - } - ), - ], - } - ) - cls.alternative_pricelist_02 = cls.env["product.pricelist"].create( - { - "name": "Alternative pricelist 02", - "item_ids": [ - Command.create( - { - "compute_price": "fixed", - "product_id": cls.datacard.id, - "applied_on": "0_product_variant", - "fixed_price": 80, - } - ), - ], - } - ) - - cls.pricelist01 = cls.env["product.pricelist"].create( - { - "name": "Sale pricelist", - "item_ids": [ - Command.create( - { - "compute_price": "fixed", - "product_id": cls.usb_adapter.id, - "applied_on": "0_product_variant", - "fixed_price": 95, - } - ), - Command.create( - { - "compute_price": "fixed", - "product_id": cls.datacard.id, - "applied_on": "0_product_variant", - "fixed_price": 70, - } - ), - ], - "alternative_pricelist_ids": [ - (4, cls.alternative_pricelist_01.id), - (4, cls.alternative_pricelist_02.id), - ], - } - ) - - cls.product_categ01 = cls.env["product.category"].create( - {"name": "Category 01"} - ) - cls.usb_adapter.categ_id = cls.product_categ01 - - cls.pricelist02 = cls.env["product.pricelist"].create( - { - "name": "Sale pricelist", - "item_ids": [ - Command.create( - { - "compute_price": "percentage", - "applied_on": "2_product_category", - "categ_id": cls.product_categ01.id, - "percent_price": 40, - } - ), - ], - "alternative_pricelist_ids": [ - (4, cls.alternative_pricelist_01.id), - ], - } - ) - +class TestPricelistAlternative( + CommonProductPricelistAlternative, common.TransactionCase +): def test_is_alternative_to_pricelist_count(self): """Test that the is_alternative_to_pricelist_count is correctly computed""" From 207a455dbc9ba90d88327a694d0f240d0f7317d4 Mon Sep 17 00:00:00 2001 From: Telmo Santos Date: Wed, 10 Apr 2024 15:45:41 +0200 Subject: [PATCH 05/10] [IMP] product_pricelist_alternative validate alternative pricelist with based formula pricelist --- product_pricelist_alternative/README.rst | 2 +- product_pricelist_alternative/__manifest__.py | 2 +- product_pricelist_alternative/i18n/fr.po | 52 +++++++++++++++++++ product_pricelist_alternative/i18n/it.po | 19 +++++++ .../i18n/product_pricelist_alternative.pot | 19 +++++++ .../models/product_pricelist.py | 16 ++++++ .../models/product_pricelist_item.py | 20 ++++++- .../static/description/index.html | 13 +++-- .../tests/test_pricelist_alternative.py | 14 ++++- 9 files changed, 148 insertions(+), 9 deletions(-) diff --git a/product_pricelist_alternative/README.rst b/product_pricelist_alternative/README.rst index 41f3c081839..209fddb2efc 100644 --- a/product_pricelist_alternative/README.rst +++ b/product_pricelist_alternative/README.rst @@ -7,7 +7,7 @@ Product Pricelist Alternative !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:dff2812f29ba92a28c38d97a2aeb70093bfcaeba432764d5f80c73ea6e52040b + !! source digest: sha256:d0c65497950562e7e7984650f3fd3c19fe1edb10d0bf08eb62523523436aa7f1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/product_pricelist_alternative/__manifest__.py b/product_pricelist_alternative/__manifest__.py index 740ca72fed4..880a658da63 100644 --- a/product_pricelist_alternative/__manifest__.py +++ b/product_pricelist_alternative/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Product Pricelist Alternative", - "version": "16.0.1.1.0", + "version": "16.0.1.2.0", "development_status": "Beta", "category": "Product", "summary": "Calculate product price based on alternative pricelists", diff --git a/product_pricelist_alternative/i18n/fr.po b/product_pricelist_alternative/i18n/fr.po index e536a68109e..b02592ac26f 100644 --- a/product_pricelist_alternative/i18n/fr.po +++ b/product_pricelist_alternative/i18n/fr.po @@ -10,6 +10,7 @@ msgstr "" "PO-Revision-Date: 2024-03-19 09:06+0000\n" "Last-Translator: \n" "Language-Team: \n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" @@ -35,11 +36,62 @@ msgstr "Listes de prix alternatives" msgid "Alternative to Pricelist" msgstr "Alternative à la liste de prix" +#. module: product_pricelist_alternative +#. odoo-python +#: code:addons/product_pricelist_alternative/models/product_pricelist.py:0 +#, python-format +msgid "" +"Formulas based on another pricelist are not allowed on alternative " +"pricelists." +msgstr "" +"Les formules basées sur un autre liste de prix ne sont pas autorisées sur " +"les listes de prix alternatives alternatifs." + #. module: product_pricelist_alternative #: model:ir.model.fields.selection,name:product_pricelist_alternative.selection__product_pricelist_item__alternative_pricelist_policy__ignore msgid "Ignore alternatives" msgstr "Ignorer les alternatives" +#. module: product_pricelist_alternative +#: model:ir.model.fields,field_description:product_pricelist_alternative.field_product_pricelist__is_alternative_to_pricelist_count +msgid "Is Alternative To Pricelist Count" +msgstr "" + +#. module: product_pricelist_alternative +#. odoo-python +#: code:addons/product_pricelist_alternative/models/product_pricelist.py:0 +#, python-format +msgid "Is Alternative to Pricelist" +msgstr "" + +#. module: product_pricelist_alternative +#: model:ir.model.fields,field_description:product_pricelist_alternative.field_product_pricelist__is_alternative_to_pricelist_ids +msgid "Is alternative to pricelists" +msgstr "" + +#. module: product_pricelist_alternative +#. odoo-python +#: code:addons/product_pricelist_alternative/models/product_pricelist_item.py:0 +#, python-format +msgid "" +"It is not possible to encode this price rule. Formulas based on another " +"pricelist are not allowed on alternative pricelists. Please change to " +"another type of price computation." +msgstr "" +"Il n'est pas possible d'encoder cette règle de prix. Les formules basées sur " +"une autre ne sont pas autorisées dans les listes de prix alternatives. " +"Veuillez passer à un autre type de calcul de prix." + +#. module: product_pricelist_alternative +#: model:ir.model,name:product_pricelist_alternative.model_product_pricelist +msgid "Pricelist" +msgstr "" + +#. module: product_pricelist_alternative +#: model:ir.model,name:product_pricelist_alternative.model_product_pricelist_item +msgid "Pricelist Rule" +msgstr "" + #. module: product_pricelist_alternative #: model:ir.model.fields.selection,name:product_pricelist_alternative.selection__product_pricelist_item__alternative_pricelist_policy__use_lower_price msgid "Use lower price" diff --git a/product_pricelist_alternative/i18n/it.po b/product_pricelist_alternative/i18n/it.po index 173e46817f6..02138f6d8a5 100644 --- a/product_pricelist_alternative/i18n/it.po +++ b/product_pricelist_alternative/i18n/it.po @@ -36,6 +36,15 @@ msgstr "Listini alternativi" msgid "Alternative to Pricelist" msgstr "Alternativa al listino" +#. module: product_pricelist_alternative +#. odoo-python +#: code:addons/product_pricelist_alternative/models/product_pricelist.py:0 +#, python-format +msgid "" +"Formulas based on another pricelist are not allowed on alternative " +"pricelists." +msgstr "" + #. module: product_pricelist_alternative #: model:ir.model.fields.selection,name:product_pricelist_alternative.selection__product_pricelist_item__alternative_pricelist_policy__ignore msgid "Ignore alternatives" @@ -58,6 +67,16 @@ msgstr "È alternativa al listino" msgid "Is alternative to pricelists" msgstr "È alternativa ai listini" +#. module: product_pricelist_alternative +#. odoo-python +#: code:addons/product_pricelist_alternative/models/product_pricelist_item.py:0 +#, python-format +msgid "" +"It is not possible to encode this price rule. Formulas based on another " +"pricelist are not allowed on alternative pricelists. Please change to " +"another type of price computation." +msgstr "" + #. module: product_pricelist_alternative #: model:ir.model,name:product_pricelist_alternative.model_product_pricelist msgid "Pricelist" diff --git a/product_pricelist_alternative/i18n/product_pricelist_alternative.pot b/product_pricelist_alternative/i18n/product_pricelist_alternative.pot index 1e95b04c24f..71293661ee4 100644 --- a/product_pricelist_alternative/i18n/product_pricelist_alternative.pot +++ b/product_pricelist_alternative/i18n/product_pricelist_alternative.pot @@ -33,6 +33,15 @@ msgstr "" msgid "Alternative to Pricelist" msgstr "" +#. module: product_pricelist_alternative +#. odoo-python +#: code:addons/product_pricelist_alternative/models/product_pricelist.py:0 +#, python-format +msgid "" +"Formulas based on another pricelist are not allowed on alternative " +"pricelists." +msgstr "" + #. module: product_pricelist_alternative #: model:ir.model.fields.selection,name:product_pricelist_alternative.selection__product_pricelist_item__alternative_pricelist_policy__ignore msgid "Ignore alternatives" @@ -55,6 +64,16 @@ msgstr "" msgid "Is alternative to pricelists" msgstr "" +#. module: product_pricelist_alternative +#. odoo-python +#: code:addons/product_pricelist_alternative/models/product_pricelist_item.py:0 +#, python-format +msgid "" +"It is not possible to encode this price rule. Formulas based on another " +"pricelist are not allowed on alternative pricelists. Please change to " +"another type of price computation." +msgstr "" + #. module: product_pricelist_alternative #: model:ir.model,name:product_pricelist_alternative.model_product_pricelist msgid "Pricelist" diff --git a/product_pricelist_alternative/models/product_pricelist.py b/product_pricelist_alternative/models/product_pricelist.py index 417f8d5c8ab..532c605ae53 100644 --- a/product_pricelist_alternative/models/product_pricelist.py +++ b/product_pricelist_alternative/models/product_pricelist.py @@ -2,6 +2,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from odoo import _, api, fields, models +from odoo.exceptions import ValidationError class Pricelist(models.Model): @@ -80,3 +81,18 @@ def _compute_price_rule(self, products, qty, uom=None, date=False, **kwargs): if alternative_price_rule[product.id][0] < res[product.id][0]: res[product.id] = alternative_price_rule[product.id] return res + + @api.constrains("alternative_pricelist_ids") + def _check_pricelist_alternative_items_based_on_other_pricelist(self): + """Alternative pricelists can not contain items based on other pricelist""" + for pricelist in self: + if pricelist.alternative_pricelist_ids.item_ids.filtered( + lambda item: item.compute_price == "formula" + and item.base == "pricelist" + ): + raise ValidationError( + _( + "Formulas based on another pricelist are not allowed " + "on alternative pricelists." + ) + ) diff --git a/product_pricelist_alternative/models/product_pricelist_item.py b/product_pricelist_alternative/models/product_pricelist_item.py index 55c69d34ca7..34c6a31bf0d 100644 --- a/product_pricelist_alternative/models/product_pricelist_item.py +++ b/product_pricelist_alternative/models/product_pricelist_item.py @@ -1,7 +1,8 @@ # Copyright 2024 Camptocamp (). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import fields, models +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError class PricelistItem(models.Model): @@ -15,3 +16,20 @@ class PricelistItem(models.Model): default="use_lower_price", required=True, ) + + @api.constrains("base") + def _check_pricelist_alternative_items_based_on_other_pricelist(self): + """Alternative pricelists can not contain items based on other pricelist""" + for item in self: + if ( + item.compute_price == "formula" + and item.base == "pricelist" + and item.pricelist_id.is_alternative_to_pricelist_count + ): + raise ValidationError( + _( + "It is not possible to encode this price rule. Formulas based " + "on another pricelist are not allowed on alternative pricelists." + " Please change to another type of price computation." + ) + ) diff --git a/product_pricelist_alternative/static/description/index.html b/product_pricelist_alternative/static/description/index.html index 75a11f81f15..22e3efcdb69 100644 --- a/product_pricelist_alternative/static/description/index.html +++ b/product_pricelist_alternative/static/description/index.html @@ -8,10 +8,11 @@ /* :Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $ +:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $ :Copyright: This stylesheet has been placed in the public domain. Default cascading style sheet for the HTML output of Docutils. +Despite the name, some widely supported CSS2 features are used. See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to customize this style sheet. @@ -274,7 +275,7 @@ margin-left: 2em ; margin-right: 2em } -pre.code .ln { color: grey; } /* line numbers */ +pre.code .ln { color: gray; } /* line numbers */ pre.code, code { background-color: #eeeeee } pre.code .comment, code .comment { color: #5C6576 } pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } @@ -300,7 +301,7 @@ span.pre { white-space: pre } -span.problematic { +span.problematic, pre.problematic { color: red } span.section-subtitle { @@ -366,7 +367,7 @@

Product Pricelist Alternative

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:dff2812f29ba92a28c38d97a2aeb70093bfcaeba432764d5f80c73ea6e52040b +!! source digest: sha256:d0c65497950562e7e7984650f3fd3c19fe1edb10d0bf08eb62523523436aa7f1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 OCA/product-attribute Translate me on Weblate Try me on Runboat

It allows you to define alternative price lists to a reference price list. @@ -410,7 +411,9 @@

Contributors

Maintainers

This module is maintained by the OCA.

-Odoo Community Association + +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.

diff --git a/product_pricelist_alternative/tests/test_pricelist_alternative.py b/product_pricelist_alternative/tests/test_pricelist_alternative.py index 28f5f7902e3..79a69e06445 100644 --- a/product_pricelist_alternative/tests/test_pricelist_alternative.py +++ b/product_pricelist_alternative/tests/test_pricelist_alternative.py @@ -1,6 +1,6 @@ # Copyright 2024 Camptocamp (). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - +from odoo.exceptions import ValidationError from odoo.tests import common, tagged from .common import CommonProductPricelistAlternative @@ -92,3 +92,15 @@ def test_skip_alternative_pricelist(self): )._get_product_price(self.usb_adapter, 1.0), 95, ) + + def test_check_pricelist_alternative_items_based_on_other_pricelist(self): + with self.assertRaises(ValidationError) as e: + self.alternative_pricelist_01.item_ids.write( + { + "compute_price": "formula", + "base": "pricelist", + "base_pricelist_id": self.alternative_pricelist_02.id, + } + ) + msg = "Formulas based on another pricelist are not allowed on alternative pricelists." + self.assertIn(msg, e.exception.args[0]) From 34b061903588bfc39e928d7cdcec76ebc0e19a96 Mon Sep 17 00:00:00 2001 From: mymage Date: Sun, 13 Oct 2024 15:29:48 +0000 Subject: [PATCH 06/10] Translated using Weblate (Italian) Currently translated at 100.0% (13 of 13 strings) Translation: product-attribute-16.0/product-attribute-16.0-product_pricelist_alternative Translate-URL: https://translation.odoo-community.org/projects/product-attribute-16-0/product-attribute-16-0-product_pricelist_alternative/it/ --- product_pricelist_alternative/i18n/it.po | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/product_pricelist_alternative/i18n/it.po b/product_pricelist_alternative/i18n/it.po index 02138f6d8a5..bb06afeb354 100644 --- a/product_pricelist_alternative/i18n/it.po +++ b/product_pricelist_alternative/i18n/it.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 16.0\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2024-04-02 11:38+0000\n" +"PO-Revision-Date: 2024-10-13 18:06+0000\n" "Last-Translator: mymage \n" "Language-Team: none\n" "Language: it\n" @@ -14,7 +14,7 @@ msgstr "" "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" +"X-Generator: Weblate 5.6.2\n" #. module: product_pricelist_alternative #: model:ir.model.fields,field_description:product_pricelist_alternative.field_product_pricelist_item__alternative_pricelist_policy @@ -44,6 +44,8 @@ msgid "" "Formulas based on another pricelist are not allowed on alternative " "pricelists." msgstr "" +"Le formule che si basano su un altro listino non sono consentite nei listini " +"alternativi." #. module: product_pricelist_alternative #: model:ir.model.fields.selection,name:product_pricelist_alternative.selection__product_pricelist_item__alternative_pricelist_policy__ignore @@ -76,6 +78,9 @@ msgid "" "pricelist are not allowed on alternative pricelists. Please change to " "another type of price computation." msgstr "" +"Non è possibile codificare questa regola di prezzo. Le formule che si basano " +"su un altro listino non sono consentite nei listini alternativi. Scegliere " +"un altro tipo di calcolo del prezzo." #. module: product_pricelist_alternative #: model:ir.model,name:product_pricelist_alternative.model_product_pricelist From f49a8d64ead362625a0f367b1e13d3b8e5a9e665 Mon Sep 17 00:00:00 2001 From: Vincent Van Rossem Date: Tue, 28 Jan 2025 14:19:45 +0100 Subject: [PATCH 07/10] [IMP] product_pricelist_alternative: pre-commit auto fixes --- product_pricelist_alternative/README.rst | 31 +++++++++++-------- .../models/product_pricelist_item.py | 7 +++-- product_pricelist_alternative/pyproject.toml | 3 ++ .../readme/CONTRIBUTORS.md | 2 ++ .../readme/CONTRIBUTORS.rst | 2 -- .../readme/DESCRIPTION.md | 9 ++++++ .../readme/DESCRIPTION.rst | 4 --- .../static/description/index.html | 17 ++++++---- .../tests/test_pricelist_alternative.py | 5 ++- 9 files changed, 51 insertions(+), 29 deletions(-) create mode 100644 product_pricelist_alternative/pyproject.toml create mode 100644 product_pricelist_alternative/readme/CONTRIBUTORS.md delete mode 100644 product_pricelist_alternative/readme/CONTRIBUTORS.rst create mode 100644 product_pricelist_alternative/readme/DESCRIPTION.md delete mode 100644 product_pricelist_alternative/readme/DESCRIPTION.rst diff --git a/product_pricelist_alternative/README.rst b/product_pricelist_alternative/README.rst index 209fddb2efc..e5bb59394d6 100644 --- a/product_pricelist_alternative/README.rst +++ b/product_pricelist_alternative/README.rst @@ -17,21 +17,26 @@ Product Pricelist Alternative :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--attribute-lightgray.png?logo=github - :target: https://github.com/OCA/product-attribute/tree/16.0/product_pricelist_alternative + :target: https://github.com/OCA/product-attribute/tree/18.0/product_pricelist_alternative :alt: OCA/product-attribute .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/product-attribute-16-0/product-attribute-16-0-product_pricelist_alternative + :target: https://translation.odoo-community.org/projects/product-attribute-18-0/product-attribute-18-0-product_pricelist_alternative :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-attribute&target_branch=16.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/product-attribute&target_branch=18.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| -It allows you to define alternative price lists to a reference price list. -As a general rule, the price of a given product is obtained from the minimum between its reference price list and the alternative price lists. +It allows you to define alternative price lists to a reference price +list. As a general rule, the price of a given product is obtained from +the minimum between its reference price list and the alternative price +lists. -However, if the product's reference price has been calculated on the basis of a price rule in which the "Alternative Pricelist Policy = Ignore" field is selected, the alternative price lists will not be taken into account. +However, if the product's reference price has been calculated on the +basis of a price rule in which the "Alternative Pricelist Policy = +Ignore" field is selected, the alternative price lists will not be taken +into account. **Table of contents** @@ -44,7 +49,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -52,18 +57,18 @@ Credits ======= Authors -~~~~~~~ +------- * Camptocamp Contributors -~~~~~~~~~~~~ +------------ -* Telmo Santos -* Akim Juillerat +- Telmo Santos +- Akim Juillerat Maintainers -~~~~~~~~~~~ +----------- This module is maintained by the OCA. @@ -75,6 +80,6 @@ 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-attribute `_ project on GitHub. +This module is part of the `OCA/product-attribute `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/product_pricelist_alternative/models/product_pricelist_item.py b/product_pricelist_alternative/models/product_pricelist_item.py index 34c6a31bf0d..08efc2c0676 100644 --- a/product_pricelist_alternative/models/product_pricelist_item.py +++ b/product_pricelist_alternative/models/product_pricelist_item.py @@ -28,8 +28,9 @@ def _check_pricelist_alternative_items_based_on_other_pricelist(self): ): raise ValidationError( _( - "It is not possible to encode this price rule. Formulas based " - "on another pricelist are not allowed on alternative pricelists." - " Please change to another type of price computation." + "It is not possible to encode this price rule. " + "Formulas based on another pricelist " + "are not allowed on alternative pricelists. " + "Please change to another type of price computation." ) ) diff --git a/product_pricelist_alternative/pyproject.toml b/product_pricelist_alternative/pyproject.toml new file mode 100644 index 00000000000..4231d0cccb3 --- /dev/null +++ b/product_pricelist_alternative/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/product_pricelist_alternative/readme/CONTRIBUTORS.md b/product_pricelist_alternative/readme/CONTRIBUTORS.md new file mode 100644 index 00000000000..f5fcdc50207 --- /dev/null +++ b/product_pricelist_alternative/readme/CONTRIBUTORS.md @@ -0,0 +1,2 @@ +- Telmo Santos \<\> +- Akim Juillerat \<\> diff --git a/product_pricelist_alternative/readme/CONTRIBUTORS.rst b/product_pricelist_alternative/readme/CONTRIBUTORS.rst deleted file mode 100644 index 2052422f4dc..00000000000 --- a/product_pricelist_alternative/readme/CONTRIBUTORS.rst +++ /dev/null @@ -1,2 +0,0 @@ -* Telmo Santos -* Akim Juillerat diff --git a/product_pricelist_alternative/readme/DESCRIPTION.md b/product_pricelist_alternative/readme/DESCRIPTION.md new file mode 100644 index 00000000000..6fde5f4ce61 --- /dev/null +++ b/product_pricelist_alternative/readme/DESCRIPTION.md @@ -0,0 +1,9 @@ +It allows you to define alternative price lists to a reference price +list. As a general rule, the price of a given product is obtained from +the minimum between its reference price list and the alternative price +lists. + +However, if the product's reference price has been calculated on the +basis of a price rule in which the "Alternative Pricelist Policy = +Ignore" field is selected, the alternative price lists will not be taken +into account. diff --git a/product_pricelist_alternative/readme/DESCRIPTION.rst b/product_pricelist_alternative/readme/DESCRIPTION.rst deleted file mode 100644 index a535b85646a..00000000000 --- a/product_pricelist_alternative/readme/DESCRIPTION.rst +++ /dev/null @@ -1,4 +0,0 @@ -It allows you to define alternative price lists to a reference price list. -As a general rule, the price of a given product is obtained from the minimum between its reference price list and the alternative price lists. - -However, if the product's reference price has been calculated on the basis of a price rule in which the "Alternative Pricelist Policy = Ignore" field is selected, the alternative price lists will not be taken into account. diff --git a/product_pricelist_alternative/static/description/index.html b/product_pricelist_alternative/static/description/index.html index 22e3efcdb69..8d826836907 100644 --- a/product_pricelist_alternative/static/description/index.html +++ b/product_pricelist_alternative/static/description/index.html @@ -369,10 +369,15 @@

Product Pricelist Alternative

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:d0c65497950562e7e7984650f3fd3c19fe1edb10d0bf08eb62523523436aa7f1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: AGPL-3 OCA/product-attribute Translate me on Weblate Try me on Runboat

-

It allows you to define alternative price lists to a reference price list. -As a general rule, the price of a given product is obtained from the minimum between its reference price list and the alternative price lists.

-

However, if the product’s reference price has been calculated on the basis of a price rule in which the “Alternative Pricelist Policy = Ignore” field is selected, the alternative price lists will not be taken into account.

+

Beta License: AGPL-3 OCA/product-attribute Translate me on Weblate Try me on Runboat

+

It allows you to define alternative price lists to a reference price +list. As a general rule, the price of a given product is obtained from +the minimum between its reference price list and the alternative price +lists.

+

However, if the product’s reference price has been calculated on the +basis of a price rule in which the “Alternative Pricelist Policy = +Ignore” field is selected, the alternative price lists will not be taken +into account.

Table of contents

    @@ -390,7 +395,7 @@

    Bug Tracker

    Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -feedback.

    +feedback.

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

@@ -417,7 +422,7 @@

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.

-

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

+

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

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

diff --git a/product_pricelist_alternative/tests/test_pricelist_alternative.py b/product_pricelist_alternative/tests/test_pricelist_alternative.py index 79a69e06445..5ede1c2eb99 100644 --- a/product_pricelist_alternative/tests/test_pricelist_alternative.py +++ b/product_pricelist_alternative/tests/test_pricelist_alternative.py @@ -102,5 +102,8 @@ def test_check_pricelist_alternative_items_based_on_other_pricelist(self): "base_pricelist_id": self.alternative_pricelist_02.id, } ) - msg = "Formulas based on another pricelist are not allowed on alternative pricelists." + msg = ( + "Formulas based on another pricelist " + "are not allowed on alternative pricelists." + ) self.assertIn(msg, e.exception.args[0]) From a13167675c71fcda956821c7e36f895665e4c4f5 Mon Sep 17 00:00:00 2001 From: Vincent Van Rossem Date: Tue, 28 Jan 2025 14:43:11 +0100 Subject: [PATCH 08/10] [MIG] product_pricelist_alternative: Migration to 18.0 --- product_pricelist_alternative/__manifest__.py | 2 +- .../i18n/product_pricelist_alternative.pot | 2 +- .../models/product_pricelist.py | 37 +++++++++++++++---- .../models/product_pricelist_item.py | 4 +- product_pricelist_alternative/tests/common.py | 7 ++-- .../tests/test_pricelist_alternative.py | 8 ++-- .../views/product_pricelist_item_view.xml | 4 +- .../views/product_pricelist_view.xml | 8 +--- 8 files changed, 43 insertions(+), 29 deletions(-) diff --git a/product_pricelist_alternative/__manifest__.py b/product_pricelist_alternative/__manifest__.py index 880a658da63..047ddef6d4e 100644 --- a/product_pricelist_alternative/__manifest__.py +++ b/product_pricelist_alternative/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Product Pricelist Alternative", - "version": "16.0.1.2.0", + "version": "18.0.1.0.0", "development_status": "Beta", "category": "Product", "summary": "Calculate product price based on alternative pricelists", diff --git a/product_pricelist_alternative/i18n/product_pricelist_alternative.pot b/product_pricelist_alternative/i18n/product_pricelist_alternative.pot index 71293661ee4..5ced616f942 100644 --- a/product_pricelist_alternative/i18n/product_pricelist_alternative.pot +++ b/product_pricelist_alternative/i18n/product_pricelist_alternative.pot @@ -4,7 +4,7 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 16.0\n" +"Project-Id-Version: Odoo Server 18.0+e\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: \n" "Language-Team: \n" diff --git a/product_pricelist_alternative/models/product_pricelist.py b/product_pricelist_alternative/models/product_pricelist.py index 532c605ae53..497fc4be852 100644 --- a/product_pricelist_alternative/models/product_pricelist.py +++ b/product_pricelist_alternative/models/product_pricelist.py @@ -1,7 +1,7 @@ # Copyright 2024 Camptocamp (). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import _, api, fields, models +from odoo import api, fields, models from odoo.exceptions import ValidationError @@ -45,9 +45,9 @@ def action_view_is_alternative_to_pricelist(self): self.ensure_one() action = { "type": "ir.actions.act_window", - "name": _("Is Alternative to Pricelist"), + "name": self.env._("Is Alternative to Pricelist"), "res_model": "product.pricelist", - "view_mode": "tree,form", + "view_mode": "list,form", "domain": [("id", "in", self.is_alternative_to_pricelist_ids.ids)], "context": dict(self.env.context, create=False), } @@ -57,8 +57,25 @@ def action_view_is_alternative_to_pricelist(self): ) return action - def _compute_price_rule(self, products, qty, uom=None, date=False, **kwargs): - res = super()._compute_price_rule(products, qty, uom=uom, date=date, **kwargs) + def _compute_price_rule( + self, + products, + quantity, + currency=None, + uom=None, + date=False, + compute_price=True, + **kwargs, + ): + res = super()._compute_price_rule( + products, + quantity, + currency=currency, + uom=uom, + date=date, + compute_price=compute_price, + **kwargs, + ) # In some contexts we want to ignore alternative pricelists # and return the original price @@ -75,7 +92,13 @@ def _compute_price_rule(self, products, qty, uom=None, date=False, **kwargs): ): for alternative_pricelist in self.alternative_pricelist_ids: alternative_price_rule = alternative_pricelist._compute_price_rule( - product, qty, uom=uom, date=date, **kwargs + product, + quantity, + currency=currency, + uom=uom, + date=date, + compute_price=compute_price, + **kwargs, ) # use alternative price if lower if alternative_price_rule[product.id][0] < res[product.id][0]: @@ -91,7 +114,7 @@ def _check_pricelist_alternative_items_based_on_other_pricelist(self): and item.base == "pricelist" ): raise ValidationError( - _( + self.env._( "Formulas based on another pricelist are not allowed " "on alternative pricelists." ) diff --git a/product_pricelist_alternative/models/product_pricelist_item.py b/product_pricelist_alternative/models/product_pricelist_item.py index 08efc2c0676..f2a869a93f1 100644 --- a/product_pricelist_alternative/models/product_pricelist_item.py +++ b/product_pricelist_alternative/models/product_pricelist_item.py @@ -1,7 +1,7 @@ # Copyright 2024 Camptocamp (). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import _, api, fields, models +from odoo import api, fields, models from odoo.exceptions import ValidationError @@ -27,7 +27,7 @@ def _check_pricelist_alternative_items_based_on_other_pricelist(self): and item.pricelist_id.is_alternative_to_pricelist_count ): raise ValidationError( - _( + self.env._( "It is not possible to encode this price rule. " "Formulas based on another pricelist " "are not allowed on alternative pricelists. " diff --git a/product_pricelist_alternative/tests/common.py b/product_pricelist_alternative/tests/common.py index 1e700c5168c..56fc6ae6797 100644 --- a/product_pricelist_alternative/tests/common.py +++ b/product_pricelist_alternative/tests/common.py @@ -2,17 +2,16 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from odoo.fields import Command -from odoo.tests import common, tagged +from odoo.tests import tagged -from odoo.addons.base.tests.common import DISABLED_MAIL_CONTEXT +from odoo.addons.base.tests.common import BaseCommon @tagged("post_install", "-at_install") -class CommonProductPricelistAlternative(common.TransactionCase): +class CommonProductPricelistAlternative(BaseCommon): @classmethod def setUpClass(cls): super().setUpClass() - cls.env = cls.env["base"].with_context(**DISABLED_MAIL_CONTEXT).env cls.datacard = cls.env["product.product"].create( {"name": "Data card", "list_price": 100} ) diff --git a/product_pricelist_alternative/tests/test_pricelist_alternative.py b/product_pricelist_alternative/tests/test_pricelist_alternative.py index 5ede1c2eb99..c19837e1db9 100644 --- a/product_pricelist_alternative/tests/test_pricelist_alternative.py +++ b/product_pricelist_alternative/tests/test_pricelist_alternative.py @@ -1,15 +1,13 @@ # Copyright 2024 Camptocamp (). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from odoo.exceptions import ValidationError -from odoo.tests import common, tagged +from odoo.tests import tagged from .common import CommonProductPricelistAlternative @tagged("post_install", "-at_install") -class TestPricelistAlternative( - CommonProductPricelistAlternative, common.TransactionCase -): +class TestPricelistAlternative(CommonProductPricelistAlternative): def test_is_alternative_to_pricelist_count(self): """Test that the is_alternative_to_pricelist_count is correctly computed""" @@ -22,7 +20,7 @@ def test_is_alternative_to_pricelist_count(self): def test_action_view_is_alternative_to_pricelist(self): action = self.alternative_pricelist_01.action_view_is_alternative_to_pricelist() - self.assertEqual(action["view_mode"], "tree,form") + self.assertEqual(action["view_mode"], "list,form") self.assertEqual( action["domain"][0][2], self.alternative_pricelist_01.is_alternative_to_pricelist_ids.ids, diff --git a/product_pricelist_alternative/views/product_pricelist_item_view.xml b/product_pricelist_alternative/views/product_pricelist_item_view.xml index 501c4c2ef58..affae72e624 100644 --- a/product_pricelist_alternative/views/product_pricelist_item_view.xml +++ b/product_pricelist_alternative/views/product_pricelist_item_view.xml @@ -12,7 +12,7 @@ - product.pricelist.item.tree + product.pricelist.item.list product.pricelist.item @@ -23,7 +23,7 @@ - product.pricelist.item.tree + product.pricelist.item.list product.pricelist.item - - - From 5785cb58d43bba7e421647d8cfad3558effb1036 Mon Sep 17 00:00:00 2001 From: Vincent Van Rossem Date: Wed, 5 Feb 2025 18:07:58 +0100 Subject: [PATCH 09/10] [IMP] product_pricelist_alternative: force_price_recomputation --- product_pricelist_alternative/README.rst | 6 +++--- .../i18n/product_pricelist_alternative.pot | 5 +---- product_pricelist_alternative/models/product_pricelist.py | 7 ++++++- .../static/description/index.html | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/product_pricelist_alternative/README.rst b/product_pricelist_alternative/README.rst index e5bb59394d6..b2716aafd03 100644 --- a/product_pricelist_alternative/README.rst +++ b/product_pricelist_alternative/README.rst @@ -7,7 +7,7 @@ Product Pricelist Alternative !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:d0c65497950562e7e7984650f3fd3c19fe1edb10d0bf08eb62523523436aa7f1 + !! source digest: sha256:5dc2e5c2e1b7beb953f47024ca1795590124ec9aa86e4b7615c2c4bcb35e03e4 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png @@ -64,8 +64,8 @@ Authors Contributors ------------ -- Telmo Santos -- Akim Juillerat +- Telmo Santos +- Akim Juillerat Maintainers ----------- diff --git a/product_pricelist_alternative/i18n/product_pricelist_alternative.pot b/product_pricelist_alternative/i18n/product_pricelist_alternative.pot index 5ced616f942..f4d942199a5 100644 --- a/product_pricelist_alternative/i18n/product_pricelist_alternative.pot +++ b/product_pricelist_alternative/i18n/product_pricelist_alternative.pot @@ -4,7 +4,7 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 18.0+e\n" +"Project-Id-Version: Odoo Server 18.0\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: \n" "Language-Team: \n" @@ -36,7 +36,6 @@ msgstr "" #. module: product_pricelist_alternative #. odoo-python #: code:addons/product_pricelist_alternative/models/product_pricelist.py:0 -#, python-format msgid "" "Formulas based on another pricelist are not allowed on alternative " "pricelists." @@ -55,7 +54,6 @@ msgstr "" #. module: product_pricelist_alternative #. odoo-python #: code:addons/product_pricelist_alternative/models/product_pricelist.py:0 -#, python-format msgid "Is Alternative to Pricelist" msgstr "" @@ -67,7 +65,6 @@ msgstr "" #. module: product_pricelist_alternative #. odoo-python #: code:addons/product_pricelist_alternative/models/product_pricelist_item.py:0 -#, python-format msgid "" "It is not possible to encode this price rule. Formulas based on another " "pricelist are not allowed on alternative pricelists. Please change to " diff --git a/product_pricelist_alternative/models/product_pricelist.py b/product_pricelist_alternative/models/product_pricelist.py index 497fc4be852..f4378f3a2e1 100644 --- a/product_pricelist_alternative/models/product_pricelist.py +++ b/product_pricelist_alternative/models/product_pricelist.py @@ -67,6 +67,12 @@ def _compute_price_rule( compute_price=True, **kwargs, ): + # This context key is used in `sale.order::_recompute_prices()`, + # triggered by `action_update_prices()` button that recomputes + # the unit price of all products based on the new pricelist. + if self.env.context.get("force_price_recomputation"): + compute_price = True + res = super()._compute_price_rule( products, quantity, @@ -76,7 +82,6 @@ def _compute_price_rule( compute_price=compute_price, **kwargs, ) - # In some contexts we want to ignore alternative pricelists # and return the original price if self.env.context.get("skip_alternative_pricelist", False): diff --git a/product_pricelist_alternative/static/description/index.html b/product_pricelist_alternative/static/description/index.html index 8d826836907..03b4d5e8cf7 100644 --- a/product_pricelist_alternative/static/description/index.html +++ b/product_pricelist_alternative/static/description/index.html @@ -367,7 +367,7 @@

Product Pricelist Alternative

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:d0c65497950562e7e7984650f3fd3c19fe1edb10d0bf08eb62523523436aa7f1 +!! source digest: sha256:5dc2e5c2e1b7beb953f47024ca1795590124ec9aa86e4b7615c2c4bcb35e03e4 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 OCA/product-attribute Translate me on Weblate Try me on Runboat

It allows you to define alternative price lists to a reference price From 3795fa22c27e695a9e430ec9d92fb1ef5dd97536 Mon Sep 17 00:00:00 2001 From: Ruchir Shukla Date: Tue, 23 Dec 2025 11:48:36 +0530 Subject: [PATCH 10/10] [MIG] product_pricelist_alternative: Migration to 19.0 --- product_pricelist_alternative/README.rst | 20 +++++++------ product_pricelist_alternative/__manifest__.py | 2 +- .../models/product_pricelist.py | 9 ++---- .../static/description/index.html | 28 +++++++++++-------- 4 files changed, 33 insertions(+), 26 deletions(-) diff --git a/product_pricelist_alternative/README.rst b/product_pricelist_alternative/README.rst index b2716aafd03..a264994ca89 100644 --- a/product_pricelist_alternative/README.rst +++ b/product_pricelist_alternative/README.rst @@ -1,3 +1,7 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + ============================= Product Pricelist Alternative ============================= @@ -13,17 +17,17 @@ Product Pricelist Alternative .. |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 +.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fproduct--attribute-lightgray.png?logo=github - :target: https://github.com/OCA/product-attribute/tree/18.0/product_pricelist_alternative + :target: https://github.com/OCA/product-attribute/tree/19.0/product_pricelist_alternative :alt: OCA/product-attribute .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/product-attribute-18-0/product-attribute-18-0-product_pricelist_alternative + :target: https://translation.odoo-community.org/projects/product-attribute-19-0/product-attribute-19-0-product_pricelist_alternative :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-attribute&target_branch=18.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/product-attribute&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -49,7 +53,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -64,8 +68,8 @@ Authors Contributors ------------ -- Telmo Santos -- Akim Juillerat +- Telmo Santos +- Akim Juillerat Maintainers ----------- @@ -80,6 +84,6 @@ 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-attribute `_ project on GitHub. +This module is part of the `OCA/product-attribute `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/product_pricelist_alternative/__manifest__.py b/product_pricelist_alternative/__manifest__.py index 047ddef6d4e..4975198cfee 100644 --- a/product_pricelist_alternative/__manifest__.py +++ b/product_pricelist_alternative/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Product Pricelist Alternative", - "version": "18.0.1.0.0", + "version": "19.0.1.0.0", "development_status": "Beta", "category": "Product", "summary": "Calculate product price based on alternative pricelists", diff --git a/product_pricelist_alternative/models/product_pricelist.py b/product_pricelist_alternative/models/product_pricelist.py index f4378f3a2e1..fb91e15aa19 100644 --- a/product_pricelist_alternative/models/product_pricelist.py +++ b/product_pricelist_alternative/models/product_pricelist.py @@ -29,15 +29,12 @@ class Pricelist(models.Model): @api.depends("is_alternative_to_pricelist_ids") def _compute_is_alternative_to_pricelist_count(self): - groups = self.read_group( + groups = self.env["product.pricelist"]._read_group( [("alternative_pricelist_ids", "in", self.ids)], ["alternative_pricelist_ids"], - "alternative_pricelist_ids", - lazy=False, + ["__count"], ) - data = { - group["alternative_pricelist_ids"][0]: group["__count"] for group in groups - } + data = {pricelist.id: count for pricelist, count in groups} for pricelist in self: pricelist.is_alternative_to_pricelist_count = data.get(pricelist.id, 0) diff --git a/product_pricelist_alternative/static/description/index.html b/product_pricelist_alternative/static/description/index.html index 03b4d5e8cf7..3c85956f109 100644 --- a/product_pricelist_alternative/static/description/index.html +++ b/product_pricelist_alternative/static/description/index.html @@ -3,7 +3,7 @@ -Product Pricelist Alternative +README.rst -

-

Product Pricelist Alternative

+
+ + +Odoo Community Association + +
+

Product Pricelist Alternative

-

Beta License: AGPL-3 OCA/product-attribute Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/product-attribute Translate me on Weblate Try me on Runboat

It allows you to define alternative price lists to a reference price list. As a general rule, the price of a given product is obtained from the minimum between its reference price list and the alternative price @@ -391,30 +396,30 @@

Product Pricelist Alternative

-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -feedback.

+feedback.

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

-

Credits

+

Credits

-

Authors

+

Authors

  • Camptocamp
-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -422,10 +427,11 @@

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.

-

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

+

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

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

+