From a238d24b09157b9b5d8fef7562be15ff2dbaf753 Mon Sep 17 00:00:00 2001 From: Dmytro Pavlov Date: Wed, 10 Jan 2024 17:34:43 +0200 Subject: [PATCH 01/11] [16.0][ADD] product_optional_product_quantity: add module [16.0][ADD] product_optional_product_quantity: add icon [16.0][ADD] product_optional_product_quantity: add auto tests [16.0][REF] product_optional_product_quantity: fix typo [ADD] product_optional_product_quantity: add setting --- product_optional_product_quantity/README.rst | 99 ++++ product_optional_product_quantity/__init__.py | 3 + .../__manifest__.py | 22 + .../models/__init__.py | 5 + .../models/product_optional_line.py | 57 +++ .../models/product_template.py | 30 ++ .../models/res_config_settings.py | 12 + .../readme/CONFIGURE.md | 5 + .../readme/CONTEXT.md | 4 + .../readme/DESCRIPTION.md | 1 + .../readme/USAGE.md | 1 + .../security/ir.model.access.csv | 3 + .../security/res_groups.xml | 9 + .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 441 ++++++++++++++++++ .../tests/__init__.py | 3 + .../tests/test_optional_product_quantity.py | 87 ++++ .../views/product_template_views.xml | 31 ++ .../views/res_config_settings_views.xml | 27 ++ 19 files changed, 840 insertions(+) create mode 100644 product_optional_product_quantity/README.rst create mode 100644 product_optional_product_quantity/__init__.py create mode 100644 product_optional_product_quantity/__manifest__.py create mode 100644 product_optional_product_quantity/models/__init__.py create mode 100644 product_optional_product_quantity/models/product_optional_line.py create mode 100644 product_optional_product_quantity/models/product_template.py create mode 100644 product_optional_product_quantity/models/res_config_settings.py create mode 100644 product_optional_product_quantity/readme/CONFIGURE.md create mode 100644 product_optional_product_quantity/readme/CONTEXT.md create mode 100644 product_optional_product_quantity/readme/DESCRIPTION.md create mode 100644 product_optional_product_quantity/readme/USAGE.md create mode 100644 product_optional_product_quantity/security/ir.model.access.csv create mode 100644 product_optional_product_quantity/security/res_groups.xml create mode 100644 product_optional_product_quantity/static/description/icon.png create mode 100644 product_optional_product_quantity/static/description/index.html create mode 100644 product_optional_product_quantity/tests/__init__.py create mode 100644 product_optional_product_quantity/tests/test_optional_product_quantity.py create mode 100644 product_optional_product_quantity/views/product_template_views.xml create mode 100644 product_optional_product_quantity/views/res_config_settings_views.xml diff --git a/product_optional_product_quantity/README.rst b/product_optional_product_quantity/README.rst new file mode 100644 index 00000000000..141aba7e1d1 --- /dev/null +++ b/product_optional_product_quantity/README.rst @@ -0,0 +1,99 @@ +================================= +Product Optional Product Quantity +================================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:f2a67114bdec8d5f2b5384004168add3b7e6f0b89234bcb7e586891bee893fb0 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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_optional_product_quantity + :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_optional_product_quantity + :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| + +This module implements core functionality for the optional product +quantity multipliers. You can depend on this module to implement further +user features. + +**Table of contents** + +.. contents:: + :local: + +Use Cases / Context +=================== + +Odoo has an option to define optional products for products. However +sometimes optional product may have different quantity in relation to +the main one. For example you have a "Tea party set" product which +consists of 4 tea cups. Your customers can also buy same cups +separately. In this case "Tea cup" will be an optional product for "Tee +party set" with quantity multiplier 4. So when you add  "Tear party set" +with quantity=2 to quotation "Tea cup" with quantity=8 will be added in +the "Optional products" tab.  + +Configuration +============= + +Go to Settings > Sales tab In the "Product Catalog" section enable +"Optional Products Quantity" feature + +Open a product and go to the "Sales" tab. Add optional products with +quantities in the "Optional Products" field. + +Usage +===== + +Usage flow is implemented in modules depending on this one. + +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 +------- + +* Cetmix + +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_optional_product_quantity/__init__.py b/product_optional_product_quantity/__init__.py new file mode 100644 index 00000000000..88b2aa93281 --- /dev/null +++ b/product_optional_product_quantity/__init__.py @@ -0,0 +1,3 @@ +# Copyright 2024 Cetmix OÜ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from . import models diff --git a/product_optional_product_quantity/__manifest__.py b/product_optional_product_quantity/__manifest__.py new file mode 100644 index 00000000000..4581150d86e --- /dev/null +++ b/product_optional_product_quantity/__manifest__.py @@ -0,0 +1,22 @@ +# Copyright 2024 Cetmix OÜ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +{ + "name": "Product Optional Product Quantity", + "version": "16.0.1.0.0", + "category": "Product", + "summary": "Specify optional products quantity for product", + "author": "Cetmix, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/product-attribute", + "license": "AGPL-3", + "depends": [ + "sale_product_configurator", + ], + "data": [ + "security/res_groups.xml", + "security/ir.model.access.csv", + "views/product_template_views.xml", + "views/res_config_settings_views.xml", + ], + "installable": True, + "auto_install": False, +} diff --git a/product_optional_product_quantity/models/__init__.py b/product_optional_product_quantity/models/__init__.py new file mode 100644 index 00000000000..47cefa79d1f --- /dev/null +++ b/product_optional_product_quantity/models/__init__.py @@ -0,0 +1,5 @@ +# Copyright 2024 Cetmix OÜ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from . import product_optional_line +from . import res_config_settings +from . import product_template diff --git a/product_optional_product_quantity/models/product_optional_line.py b/product_optional_product_quantity/models/product_optional_line.py new file mode 100644 index 00000000000..151d946d51a --- /dev/null +++ b/product_optional_product_quantity/models/product_optional_line.py @@ -0,0 +1,57 @@ +# Copyright 2024 Cetmix OÜ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo import _, api, fields, models + + +class ProductOptionalLine(models.Model): + _name = "product.optional.line" + _description = "Optional Product" + + product_tmpl_id = fields.Many2one( + comodel_name="product.template", + domain="[('id', '!=', optional_product_tmpl_id)]", + string="Related Product", + required=True, + ) + company_id = fields.Many2one(related="product_tmpl_id.company_id") + optional_product_tmpl_id = fields.Many2one( + comodel_name="product.template", + domain="[('company_id', 'in', [company_id, False]), ('id', '!=', product_tmpl_id)]", + string="Product", + required=True, + ) + quantity = fields.Float( + default=1.0, + ) + + @api.constrains("product_tmpl_id", "optional_product_tmpl_id") + def _check_same_product_as_related(self): + """ + Restrict setting product template this line is related to as optional. + """ + for r in self: + if ( + r.product_tmpl_id + and r.optional_product_tmpl_id + and r.product_tmpl_id == r.optional_product_tmpl_id + ): + raise models.ValidationError( + _("You can't add product this line is related to as optional.") + ) + + @api.constrains("product_tmpl_id", "optional_product_tmpl_id") + def _check_unique_products_within_product(self): + """ + Make sure that all of the optional products are unique. + """ + for r in self: + if self.search_count( + [ + ("optional_product_tmpl_id", "=", r.optional_product_tmpl_id.id), + ("product_tmpl_id", "=", r.product_tmpl_id.id), + ("id", "!=", r.id), + ] + ): + raise models.ValidationError( + _("You can't add two same products as optional.") + ) diff --git a/product_optional_product_quantity/models/product_template.py b/product_optional_product_quantity/models/product_template.py new file mode 100644 index 00000000000..91f1b5741f1 --- /dev/null +++ b/product_optional_product_quantity/models/product_template.py @@ -0,0 +1,30 @@ +# Copyright 2024 Cetmix OÜ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo import api, fields, models + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + product_optional_line_ids = fields.One2many( + string="Optional Products", + comodel_name="product.optional.line", + inverse_name="product_tmpl_id", + ) + optional_product_ids = fields.Many2many( + compute="_compute_optional_product_ids", + readonly=False, + store=True, + ) + + @api.depends("product_optional_line_ids") + def _compute_optional_product_ids(self): + """ + To avoid possible issues with optional products in other modules, + we need to compute them based on optional product lines, because + we hide the original field. + """ + for r in self: + r.optional_product_ids = r.product_optional_line_ids.mapped( + "optional_product_tmpl_id" + ) diff --git a/product_optional_product_quantity/models/res_config_settings.py b/product_optional_product_quantity/models/res_config_settings.py new file mode 100644 index 00000000000..cc639269078 --- /dev/null +++ b/product_optional_product_quantity/models/res_config_settings.py @@ -0,0 +1,12 @@ +# Copyright 2024 Cetmix OÜ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + group_product_optional_quantity = fields.Boolean( + string="Optional Products Quantity", + implied_group="product_optional_product_quantity.group_product_optional_quantity", + ) diff --git a/product_optional_product_quantity/readme/CONFIGURE.md b/product_optional_product_quantity/readme/CONFIGURE.md new file mode 100644 index 00000000000..47af794bf4b --- /dev/null +++ b/product_optional_product_quantity/readme/CONFIGURE.md @@ -0,0 +1,5 @@ +Go to Settings > Sales tab +In the "Product Catalog" section enable "Optional Products Quantity" feature + + +Open a product and go to the "Sales" tab. Add optional products with quantities in the "Optional Products" field. \ No newline at end of file diff --git a/product_optional_product_quantity/readme/CONTEXT.md b/product_optional_product_quantity/readme/CONTEXT.md new file mode 100644 index 00000000000..04c16d567d3 --- /dev/null +++ b/product_optional_product_quantity/readme/CONTEXT.md @@ -0,0 +1,4 @@ +Odoo has an option to define optional products for products. However sometimes optional product may have different quantity in relation to the main one. +For example you have a "Tea party set" product which consists of 4 tea cups. Your customers can also buy same cups separately. +In this case "Tea cup" will be an optional product for "Tee party set" with quantity multiplier 4. +So when you add  "Tear party set" with quantity=2 to quotation "Tea cup" with quantity=8 will be added in the "Optional products" tab.  \ No newline at end of file diff --git a/product_optional_product_quantity/readme/DESCRIPTION.md b/product_optional_product_quantity/readme/DESCRIPTION.md new file mode 100644 index 00000000000..7052250c14c --- /dev/null +++ b/product_optional_product_quantity/readme/DESCRIPTION.md @@ -0,0 +1 @@ +This module implements core functionality for the optional product quantity multipliers. You can depend on this module to implement further user features. \ No newline at end of file diff --git a/product_optional_product_quantity/readme/USAGE.md b/product_optional_product_quantity/readme/USAGE.md new file mode 100644 index 00000000000..fcb0ab4d59a --- /dev/null +++ b/product_optional_product_quantity/readme/USAGE.md @@ -0,0 +1 @@ +Usage flow is implemented in modules depending on this one. \ No newline at end of file diff --git a/product_optional_product_quantity/security/ir.model.access.csv b/product_optional_product_quantity/security/ir.model.access.csv new file mode 100644 index 00000000000..aecd7220f9c --- /dev/null +++ b/product_optional_product_quantity/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_product_optional_line_user,product_optional_line_user,model_product_optional_line,base.group_user,1,0,0,0 +access_product_optional_line_salesman,product_optional_line_salesman,model_product_optional_line,sales_team.group_sale_salesman,1,1,1,1 diff --git a/product_optional_product_quantity/security/res_groups.xml b/product_optional_product_quantity/security/res_groups.xml new file mode 100644 index 00000000000..2837cde50f2 --- /dev/null +++ b/product_optional_product_quantity/security/res_groups.xml @@ -0,0 +1,9 @@ + + + + + Use Optional Products Quantity + + + + diff --git a/product_optional_product_quantity/static/description/icon.png b/product_optional_product_quantity/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_optional_product_quantity/static/description/index.html b/product_optional_product_quantity/static/description/index.html new file mode 100644 index 00000000000..a3338f33873 --- /dev/null +++ b/product_optional_product_quantity/static/description/index.html @@ -0,0 +1,441 @@ + + + + + + +Product Optional Product Quantity + + + +
+

Product Optional Product Quantity

+ + +

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

+

This module implements core functionality for the optional product +quantity multipliers. You can depend on this module to implement further +user features.

+

Table of contents

+ +
+

Use Cases / Context

+

Odoo has an option to define optional products for products. However +sometimes optional product may have different quantity in relation to +the main one. For example you have a “Tea party set” product which +consists of 4 tea cups. Your customers can also buy same cups +separately. In this case “Tea cup” will be an optional product for “Tee +party set” with quantity multiplier 4. So when you add  “Tear party set” +with quantity=2 to quotation “Tea cup” with quantity=8 will be added in +the “Optional products” tab.

+
+
+

Configuration

+

Go to Settings > Sales tab In the “Product Catalog” section enable +“Optional Products Quantity” feature

+

Open a product and go to the “Sales” tab. Add optional products with +quantities in the “Optional Products” field.

+
+
+

Usage

+

Usage flow is implemented in modules depending on this one.

+
+
+

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

+
    +
  • Cetmix
  • +
+
+
+

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_optional_product_quantity/tests/__init__.py b/product_optional_product_quantity/tests/__init__.py new file mode 100644 index 00000000000..bac69801585 --- /dev/null +++ b/product_optional_product_quantity/tests/__init__.py @@ -0,0 +1,3 @@ +# Copyright 2024 Cetmix OÜ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from . import test_optional_product_quantity diff --git a/product_optional_product_quantity/tests/test_optional_product_quantity.py b/product_optional_product_quantity/tests/test_optional_product_quantity.py new file mode 100644 index 00000000000..bb1234d9c53 --- /dev/null +++ b/product_optional_product_quantity/tests/test_optional_product_quantity.py @@ -0,0 +1,87 @@ +# Copyright 2024 Cetmix OÜ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo import exceptions +from odoo.tests.common import TransactionCase, tagged + + +@tagged("post_install", "-at_install") +class TestOptionalProductQuantity(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.product_template_1 = cls.env["product.template"].create( + { + "name": "Product 1", + "type": "product", + "categ_id": cls.env.ref("product.product_category_all").id, + } + ) + cls.product_template_2 = cls.env["product.template"].create( + { + "name": "Product 2", + "type": "product", + "categ_id": cls.env.ref("product.product_category_all").id, + } + ) + cls.product_template_3 = cls.env["product.template"].create( + { + "name": "Product 3", + "type": "product", + "categ_id": cls.env.ref("product.product_category_all").id, + } + ) + + def test_product_optional_line_constrains(self): + # Try to set parent product as an optional + with self.assertRaises(exceptions.ValidationError): + self.env["product.optional.line"].create( + { + "product_tmpl_id": self.product_template_1.id, + "optional_product_tmpl_id": self.product_template_1.id, + } + ) + + # Try to set two same products as optional + with self.assertRaises(exceptions.ValidationError): + self.env["product.optional.line"].create( + [ + { + "product_tmpl_id": self.product_template_1.id, + "optional_product_tmpl_id": self.product_template_2.id, + }, + { + "product_tmpl_id": self.product_template_1.id, + "optional_product_tmpl_id": self.product_template_2.id, + }, + ] + ) + + def test_optional_product_ids_computation(self): + # Create first optional product for Product 1 + self.env["product.optional.line"].create( + { + "product_tmpl_id": self.product_template_1.id, + "optional_product_tmpl_id": self.product_template_2.id, + } + ) + # optional_product_ids of Product 1 should contain 1 record with name 'Product 2' + self.assertTrue( + len(self.product_template_1.optional_product_ids) == 1 + and self.product_template_1.optional_product_ids[0].name == "Product 2", + msg="optional_product_ids of product.template has been computed incorrectly", + ) + # Create second optional product for Product 1 + self.env["product.optional.line"].create( + { + "product_tmpl_id": self.product_template_1.id, + "optional_product_tmpl_id": self.product_template_3.id, + } + ) + # optional_product_ids of Product 1 should contain 2 records + # with names 'Product 2' and 'Product 3' + self.assertTrue( + len(self.product_template_1.optional_product_ids) == 2 + and self.product_template_1.optional_product_ids[0].name == "Product 2" + and self.product_template_1.optional_product_ids[1].name == "Product 3", + msg="optional_product_ids of product.template has been computed incorrectly", + ) diff --git a/product_optional_product_quantity/views/product_template_views.xml b/product_optional_product_quantity/views/product_template_views.xml new file mode 100644 index 00000000000..d0f0c268157 --- /dev/null +++ b/product_optional_product_quantity/views/product_template_views.xml @@ -0,0 +1,31 @@ + + + + + product.template.view.form.inherit.optional.qty + product.template + + + + 1 + + + + + + + + + + + + + + + diff --git a/product_optional_product_quantity/views/res_config_settings_views.xml b/product_optional_product_quantity/views/res_config_settings_views.xml new file mode 100644 index 00000000000..1c926b43474 --- /dev/null +++ b/product_optional_product_quantity/views/res_config_settings_views.xml @@ -0,0 +1,27 @@ + + + + + res.config.settings.view.form.inherit.optional.qty + res.config.settings + + +
+
+
+ +
+
+
+
+
+
+
+
From f3962b40d3bf533769f8860e7472cf22de80dc1b Mon Sep 17 00:00:00 2001 From: oca-ci Date: Mon, 11 Mar 2024 10:25:47 +0000 Subject: [PATCH 02/11] [UPD] Update product_optional_product_quantity.pot --- .../product_optional_product_quantity.pot | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 product_optional_product_quantity/i18n/product_optional_product_quantity.pot diff --git a/product_optional_product_quantity/i18n/product_optional_product_quantity.pot b/product_optional_product_quantity/i18n/product_optional_product_quantity.pot new file mode 100644 index 00000000000..299e63434b2 --- /dev/null +++ b/product_optional_product_quantity/i18n/product_optional_product_quantity.pot @@ -0,0 +1,125 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_optional_product_quantity +# +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_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__company_id +msgid "Company" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model,name:product_optional_product_quantity.model_res_config_settings +msgid "Config Settings" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__create_uid +msgid "Created by" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__create_date +msgid "Created on" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__display_name +msgid "Display Name" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__id +msgid "ID" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line____last_update +msgid "Last Modified on" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__write_date +msgid "Last Updated on" +msgstr "" + +#. module: product_optional_product_quantity +#: model_terms:ir.ui.view,arch_db:product_optional_product_quantity.res_config_settings_view_form +msgid "Manage quantities of optional products" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model,name:product_optional_product_quantity.model_product_optional_line +msgid "Optional Product" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_product__optional_product_ids +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_product__product_optional_line_ids +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_template__optional_product_ids +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_template__product_optional_line_ids +msgid "Optional Products" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_res_config_settings__group_product_optional_quantity +msgid "Optional Products Quantity" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,help:product_optional_product_quantity.field_product_product__optional_product_ids +#: model:ir.model.fields,help:product_optional_product_quantity.field_product_template__optional_product_ids +msgid "" +"Optional Products are suggested whenever the customer hits *Add to Cart* " +"(cross-sell strategy, e.g. for computers: warranty, software, etc.)." +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model,name:product_optional_product_quantity.model_product_template +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__optional_product_tmpl_id +msgid "Product" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__quantity +msgid "Quantity" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__product_tmpl_id +msgid "Related Product" +msgstr "" + +#. module: product_optional_product_quantity +#: model:res.groups,name:product_optional_product_quantity.group_product_optional_quantity +msgid "Use Optional Products Quantity" +msgstr "" + +#. module: product_optional_product_quantity +#. odoo-python +#: code:addons/product_optional_product_quantity/models/product_optional_line.py:0 +#, python-format +msgid "You can't add product this line is related to as optional." +msgstr "" + +#. module: product_optional_product_quantity +#. odoo-python +#: code:addons/product_optional_product_quantity/models/product_optional_line.py:0 +#, python-format +msgid "You can't add two same products as optional." +msgstr "" From 3c60bfde5a2142027d70edf1d57e158258c3a749 Mon Sep 17 00:00:00 2001 From: mymage Date: Tue, 12 Mar 2024 10:02:33 +0000 Subject: [PATCH 03/11] Added translation using Weblate (Italian) --- product_optional_product_quantity/i18n/it.po | 126 +++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 product_optional_product_quantity/i18n/it.po diff --git a/product_optional_product_quantity/i18n/it.po b/product_optional_product_quantity/i18n/it.po new file mode 100644 index 00000000000..28a66fc48f2 --- /dev/null +++ b/product_optional_product_quantity/i18n/it.po @@ -0,0 +1,126 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_optional_product_quantity +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\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" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__company_id +msgid "Company" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model,name:product_optional_product_quantity.model_res_config_settings +msgid "Config Settings" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__create_uid +msgid "Created by" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__create_date +msgid "Created on" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__display_name +msgid "Display Name" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__id +msgid "ID" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line____last_update +msgid "Last Modified on" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__write_date +msgid "Last Updated on" +msgstr "" + +#. module: product_optional_product_quantity +#: model_terms:ir.ui.view,arch_db:product_optional_product_quantity.res_config_settings_view_form +msgid "Manage quantities of optional products" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model,name:product_optional_product_quantity.model_product_optional_line +msgid "Optional Product" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_product__optional_product_ids +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_product__product_optional_line_ids +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_template__optional_product_ids +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_template__product_optional_line_ids +msgid "Optional Products" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_res_config_settings__group_product_optional_quantity +msgid "Optional Products Quantity" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,help:product_optional_product_quantity.field_product_product__optional_product_ids +#: model:ir.model.fields,help:product_optional_product_quantity.field_product_template__optional_product_ids +msgid "" +"Optional Products are suggested whenever the customer hits *Add to Cart* " +"(cross-sell strategy, e.g. for computers: warranty, software, etc.)." +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model,name:product_optional_product_quantity.model_product_template +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__optional_product_tmpl_id +msgid "Product" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__quantity +msgid "Quantity" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__product_tmpl_id +msgid "Related Product" +msgstr "" + +#. module: product_optional_product_quantity +#: model:res.groups,name:product_optional_product_quantity.group_product_optional_quantity +msgid "Use Optional Products Quantity" +msgstr "" + +#. module: product_optional_product_quantity +#. odoo-python +#: code:addons/product_optional_product_quantity/models/product_optional_line.py:0 +#, python-format +msgid "You can't add product this line is related to as optional." +msgstr "" + +#. module: product_optional_product_quantity +#. odoo-python +#: code:addons/product_optional_product_quantity/models/product_optional_line.py:0 +#, python-format +msgid "You can't add two same products as optional." +msgstr "" From e29b1951896a87410908505b4329a80ccf6a0e77 Mon Sep 17 00:00:00 2001 From: mymage Date: Tue, 12 Mar 2024 11:31:24 +0000 Subject: [PATCH 04/11] Translated using Weblate (Italian) Currently translated at 100.0% (20 of 20 strings) Translation: product-attribute-16.0/product-attribute-16.0-product_optional_product_quantity Translate-URL: https://translation.odoo-community.org/projects/product-attribute-16-0/product-attribute-16-0-product_optional_product_quantity/it/ --- product_optional_product_quantity/i18n/it.po | 45 +++++++++++--------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/product_optional_product_quantity/i18n/it.po b/product_optional_product_quantity/i18n/it.po index 28a66fc48f2..6ec1d5eb3d3 100644 --- a/product_optional_product_quantity/i18n/it.po +++ b/product_optional_product_quantity/i18n/it.po @@ -6,68 +6,70 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 16.0\n" "Report-Msgid-Bugs-To: \n" -"Last-Translator: Automatically generated\n" +"PO-Revision-Date: 2024-03-12 13:34+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_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__company_id msgid "Company" -msgstr "" +msgstr "Azienda" #. module: product_optional_product_quantity #: model:ir.model,name:product_optional_product_quantity.model_res_config_settings msgid "Config Settings" -msgstr "" +msgstr "Impostazioni configurazione" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__create_uid msgid "Created by" -msgstr "" +msgstr "Creato da" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__create_date msgid "Created on" -msgstr "" +msgstr "Creato il" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__display_name msgid "Display Name" -msgstr "" +msgstr "Nome visualizzato" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__id msgid "ID" -msgstr "" +msgstr "ID" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line____last_update msgid "Last Modified on" -msgstr "" +msgstr "Ultima modifica il" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__write_uid msgid "Last Updated by" -msgstr "" +msgstr "Ultimo aggiornamento di" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__write_date msgid "Last Updated on" -msgstr "" +msgstr "Ultimo aggiornamento il" #. module: product_optional_product_quantity #: model_terms:ir.ui.view,arch_db:product_optional_product_quantity.res_config_settings_view_form msgid "Manage quantities of optional products" -msgstr "" +msgstr "Gestione quantità di prodotti opzionali" #. module: product_optional_product_quantity #: model:ir.model,name:product_optional_product_quantity.model_product_optional_line msgid "Optional Product" -msgstr "" +msgstr "Prodotto opzionale" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_product__optional_product_ids @@ -75,12 +77,12 @@ msgstr "" #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_template__optional_product_ids #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_template__product_optional_line_ids msgid "Optional Products" -msgstr "" +msgstr "Prodotti opzionali" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_res_config_settings__group_product_optional_quantity msgid "Optional Products Quantity" -msgstr "" +msgstr "Quantità prodotti opzionali" #. module: product_optional_product_quantity #: model:ir.model.fields,help:product_optional_product_quantity.field_product_product__optional_product_ids @@ -89,27 +91,30 @@ msgid "" "Optional Products are suggested whenever the customer hits *Add to Cart* " "(cross-sell strategy, e.g. for computers: warranty, software, etc.)." msgstr "" +"I prodotti opzionali sono suggeriti qando il cliente fa clic si \"Aggiungi " +"al carrello\" (strategia crss-selling, es. per computer: garanzia, " +"programmi, ecc.)." #. module: product_optional_product_quantity #: model:ir.model,name:product_optional_product_quantity.model_product_template #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__optional_product_tmpl_id msgid "Product" -msgstr "" +msgstr "Prodotto" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__quantity msgid "Quantity" -msgstr "" +msgstr "Quantità" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__product_tmpl_id msgid "Related Product" -msgstr "" +msgstr "Prodotto collegato" #. module: product_optional_product_quantity #: model:res.groups,name:product_optional_product_quantity.group_product_optional_quantity msgid "Use Optional Products Quantity" -msgstr "" +msgstr "Usare quantità prodotti opzionali" #. module: product_optional_product_quantity #. odoo-python @@ -117,10 +122,12 @@ msgstr "" #, python-format msgid "You can't add product this line is related to as optional." msgstr "" +"Non è possibile aggiungere il prodotto a cui è correlata questa riga come " +"facoltativo." #. module: product_optional_product_quantity #. odoo-python #: code:addons/product_optional_product_quantity/models/product_optional_line.py:0 #, python-format msgid "You can't add two same products as optional." -msgstr "" +msgstr "Non è possibile aggiungere due prodotti uguali come facoltativi." From 5440c1987da0e14247575c1e69b4fe9d0c84ae03 Mon Sep 17 00:00:00 2001 From: Ivorra78 Date: Tue, 26 Mar 2024 20:50:44 +0000 Subject: [PATCH 05/11] Added translation using Weblate (Spanish) --- product_optional_product_quantity/i18n/es.po | 126 +++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 product_optional_product_quantity/i18n/es.po diff --git a/product_optional_product_quantity/i18n/es.po b/product_optional_product_quantity/i18n/es.po new file mode 100644 index 00000000000..7127278ee9e --- /dev/null +++ b/product_optional_product_quantity/i18n/es.po @@ -0,0 +1,126 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_optional_product_quantity +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\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" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__company_id +msgid "Company" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model,name:product_optional_product_quantity.model_res_config_settings +msgid "Config Settings" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__create_uid +msgid "Created by" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__create_date +msgid "Created on" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__display_name +msgid "Display Name" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__id +msgid "ID" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line____last_update +msgid "Last Modified on" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__write_date +msgid "Last Updated on" +msgstr "" + +#. module: product_optional_product_quantity +#: model_terms:ir.ui.view,arch_db:product_optional_product_quantity.res_config_settings_view_form +msgid "Manage quantities of optional products" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model,name:product_optional_product_quantity.model_product_optional_line +msgid "Optional Product" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_product__optional_product_ids +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_product__product_optional_line_ids +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_template__optional_product_ids +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_template__product_optional_line_ids +msgid "Optional Products" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_res_config_settings__group_product_optional_quantity +msgid "Optional Products Quantity" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,help:product_optional_product_quantity.field_product_product__optional_product_ids +#: model:ir.model.fields,help:product_optional_product_quantity.field_product_template__optional_product_ids +msgid "" +"Optional Products are suggested whenever the customer hits *Add to Cart* " +"(cross-sell strategy, e.g. for computers: warranty, software, etc.)." +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model,name:product_optional_product_quantity.model_product_template +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__optional_product_tmpl_id +msgid "Product" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__quantity +msgid "Quantity" +msgstr "" + +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__product_tmpl_id +msgid "Related Product" +msgstr "" + +#. module: product_optional_product_quantity +#: model:res.groups,name:product_optional_product_quantity.group_product_optional_quantity +msgid "Use Optional Products Quantity" +msgstr "" + +#. module: product_optional_product_quantity +#. odoo-python +#: code:addons/product_optional_product_quantity/models/product_optional_line.py:0 +#, python-format +msgid "You can't add product this line is related to as optional." +msgstr "" + +#. module: product_optional_product_quantity +#. odoo-python +#: code:addons/product_optional_product_quantity/models/product_optional_line.py:0 +#, python-format +msgid "You can't add two same products as optional." +msgstr "" From 37f4de69a482ecca6e8d1d8d4008e8c94f639d7c Mon Sep 17 00:00:00 2001 From: Ivorra78 Date: Tue, 26 Mar 2024 20:52:04 +0000 Subject: [PATCH 06/11] Translated using Weblate (Spanish) Currently translated at 100.0% (20 of 20 strings) Translation: product-attribute-16.0/product-attribute-16.0-product_optional_product_quantity Translate-URL: https://translation.odoo-community.org/projects/product-attribute-16-0/product-attribute-16-0-product_optional_product_quantity/es/ --- product_optional_product_quantity/i18n/es.po | 45 +++++++++++--------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/product_optional_product_quantity/i18n/es.po b/product_optional_product_quantity/i18n/es.po index 7127278ee9e..46f093c1f8d 100644 --- a/product_optional_product_quantity/i18n/es.po +++ b/product_optional_product_quantity/i18n/es.po @@ -6,68 +6,70 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 16.0\n" "Report-Msgid-Bugs-To: \n" -"Last-Translator: Automatically generated\n" +"PO-Revision-Date: 2024-03-26 22:36+0000\n" +"Last-Translator: Ivorra78 \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.17\n" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__company_id msgid "Company" -msgstr "" +msgstr "Compañía" #. module: product_optional_product_quantity #: model:ir.model,name:product_optional_product_quantity.model_res_config_settings msgid "Config Settings" -msgstr "" +msgstr "Ajustes Config" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__create_uid msgid "Created by" -msgstr "" +msgstr "Creado por" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__create_date msgid "Created on" -msgstr "" +msgstr "Creado el" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__display_name msgid "Display Name" -msgstr "" +msgstr "Mostrar Nombre" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__id msgid "ID" -msgstr "" +msgstr "ID" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line____last_update msgid "Last Modified on" -msgstr "" +msgstr "Última Modificación el" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__write_uid msgid "Last Updated by" -msgstr "" +msgstr "Última actualización por" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__write_date msgid "Last Updated on" -msgstr "" +msgstr "Última Actualización Realizada el" #. module: product_optional_product_quantity #: model_terms:ir.ui.view,arch_db:product_optional_product_quantity.res_config_settings_view_form msgid "Manage quantities of optional products" -msgstr "" +msgstr "Gestionar las cantidades de productos opcionales" #. module: product_optional_product_quantity #: model:ir.model,name:product_optional_product_quantity.model_product_optional_line msgid "Optional Product" -msgstr "" +msgstr "Producto Opcional" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_product__optional_product_ids @@ -75,12 +77,12 @@ msgstr "" #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_template__optional_product_ids #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_template__product_optional_line_ids msgid "Optional Products" -msgstr "" +msgstr "Productos Opcionales" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_res_config_settings__group_product_optional_quantity msgid "Optional Products Quantity" -msgstr "" +msgstr "Productos Opcionales Cantidad" #. module: product_optional_product_quantity #: model:ir.model.fields,help:product_optional_product_quantity.field_product_product__optional_product_ids @@ -89,27 +91,30 @@ msgid "" "Optional Products are suggested whenever the customer hits *Add to Cart* " "(cross-sell strategy, e.g. for computers: warranty, software, etc.)." msgstr "" +"Los Productos opcionales se sugieren cada vez que el cliente pulsa *Añadir " +"al carrito* (estrategia de venta cruzada, por ejemplo, para ordenadores: " +"garantía, software, etc.)." #. module: product_optional_product_quantity #: model:ir.model,name:product_optional_product_quantity.model_product_template #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__optional_product_tmpl_id msgid "Product" -msgstr "" +msgstr "Producto" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__quantity msgid "Quantity" -msgstr "" +msgstr "Cantidad" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__product_tmpl_id msgid "Related Product" -msgstr "" +msgstr "Productos Relacionados" #. module: product_optional_product_quantity #: model:res.groups,name:product_optional_product_quantity.group_product_optional_quantity msgid "Use Optional Products Quantity" -msgstr "" +msgstr "Utilizar Productos Opcionales Cantidad" #. module: product_optional_product_quantity #. odoo-python @@ -117,10 +122,12 @@ msgstr "" #, python-format msgid "You can't add product this line is related to as optional." msgstr "" +"No se puede añadir como opcional el producto con el que está relacionada " +"esta línea." #. module: product_optional_product_quantity #. odoo-python #: code:addons/product_optional_product_quantity/models/product_optional_line.py:0 #, python-format msgid "You can't add two same products as optional." -msgstr "" +msgstr "No puedes añadir dos productos iguales como opcionales." From 6340b44ff9857601191c31b9482899645ce65746 Mon Sep 17 00:00:00 2001 From: Carolina Fernandez Date: Wed, 22 May 2024 16:58:06 +0200 Subject: [PATCH 07/11] [FIX] product_optional_product_quantity: Fix warning labels optional products --- product_optional_product_quantity/i18n/es.po | 8 ++++++-- product_optional_product_quantity/i18n/it.po | 8 ++++++-- .../i18n/product_optional_product_quantity.pot | 8 ++++++-- .../models/product_template.py | 2 +- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/product_optional_product_quantity/i18n/es.po b/product_optional_product_quantity/i18n/es.po index 46f093c1f8d..c0b63b7ff6f 100644 --- a/product_optional_product_quantity/i18n/es.po +++ b/product_optional_product_quantity/i18n/es.po @@ -73,12 +73,16 @@ msgstr "Producto Opcional" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_product__optional_product_ids -#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_product__product_optional_line_ids #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_template__optional_product_ids -#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_template__product_optional_line_ids msgid "Optional Products" msgstr "Productos Opcionales" +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_product__product_optional_line_ids +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_template__product_optional_line_ids +msgid "Optional Products Line" +msgstr "Línea Productos Opcionales" + #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_res_config_settings__group_product_optional_quantity msgid "Optional Products Quantity" diff --git a/product_optional_product_quantity/i18n/it.po b/product_optional_product_quantity/i18n/it.po index 6ec1d5eb3d3..5db5f6e7a78 100644 --- a/product_optional_product_quantity/i18n/it.po +++ b/product_optional_product_quantity/i18n/it.po @@ -73,12 +73,16 @@ msgstr "Prodotto opzionale" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_product__optional_product_ids -#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_product__product_optional_line_ids #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_template__optional_product_ids -#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_template__product_optional_line_ids msgid "Optional Products" msgstr "Prodotti opzionali" +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_product__product_optional_line_ids +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_template__product_optional_line_ids +msgid "Optional Products Line" +msgstr "Linea di Prodotti Opzionale" + #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_res_config_settings__group_product_optional_quantity msgid "Optional Products Quantity" diff --git a/product_optional_product_quantity/i18n/product_optional_product_quantity.pot b/product_optional_product_quantity/i18n/product_optional_product_quantity.pot index 299e63434b2..745506d144d 100644 --- a/product_optional_product_quantity/i18n/product_optional_product_quantity.pot +++ b/product_optional_product_quantity/i18n/product_optional_product_quantity.pot @@ -70,12 +70,16 @@ msgstr "" #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_product__optional_product_ids -#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_product__product_optional_line_ids #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_template__optional_product_ids -#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_template__product_optional_line_ids msgid "Optional Products" msgstr "" +#. module: product_optional_product_quantity +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_product__product_optional_line_ids +#: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_template__product_optional_line_ids +msgid "Optional Products Line" +msgstr "" + #. module: product_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_res_config_settings__group_product_optional_quantity msgid "Optional Products Quantity" diff --git a/product_optional_product_quantity/models/product_template.py b/product_optional_product_quantity/models/product_template.py index 91f1b5741f1..0d1069da714 100644 --- a/product_optional_product_quantity/models/product_template.py +++ b/product_optional_product_quantity/models/product_template.py @@ -7,7 +7,7 @@ class ProductTemplate(models.Model): _inherit = "product.template" product_optional_line_ids = fields.One2many( - string="Optional Products", + string="Optional Products Line", comodel_name="product.optional.line", inverse_name="product_tmpl_id", ) From 19cabbab428275a71c2187123ed5674a9cc93fc1 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Thu, 23 May 2024 10:00:24 +0000 Subject: [PATCH 08/11] [BOT] post-merge updates --- product_optional_product_quantity/README.rst | 2 +- product_optional_product_quantity/__manifest__.py | 2 +- .../static/description/index.html | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/product_optional_product_quantity/README.rst b/product_optional_product_quantity/README.rst index 141aba7e1d1..19afb4b74de 100644 --- a/product_optional_product_quantity/README.rst +++ b/product_optional_product_quantity/README.rst @@ -7,7 +7,7 @@ Product Optional Product Quantity !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:f2a67114bdec8d5f2b5384004168add3b7e6f0b89234bcb7e586891bee893fb0 + !! source digest: sha256:19c5748e08443684d61807c9a609fcd25cd03d10eb4a7420bd715a19eefb771f !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/product_optional_product_quantity/__manifest__.py b/product_optional_product_quantity/__manifest__.py index 4581150d86e..5eafc05873a 100644 --- a/product_optional_product_quantity/__manifest__.py +++ b/product_optional_product_quantity/__manifest__.py @@ -2,7 +2,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { "name": "Product Optional Product Quantity", - "version": "16.0.1.0.0", + "version": "16.0.1.1.0", "category": "Product", "summary": "Specify optional products quantity for product", "author": "Cetmix, Odoo Community Association (OCA)", diff --git a/product_optional_product_quantity/static/description/index.html b/product_optional_product_quantity/static/description/index.html index a3338f33873..30166831c26 100644 --- a/product_optional_product_quantity/static/description/index.html +++ b/product_optional_product_quantity/static/description/index.html @@ -1,4 +1,3 @@ - @@ -367,7 +366,7 @@

Product Optional Product Quantity

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

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

This module implements core functionality for the optional product From 1467b71e049caefdf3a072c1c24adf5486008e85 Mon Sep 17 00:00:00 2001 From: mymage Date: Thu, 3 Oct 2024 15:10:18 +0000 Subject: [PATCH 09/11] Translated using Weblate (Italian) Currently translated at 100.0% (21 of 21 strings) Translation: product-attribute-16.0/product-attribute-16.0-product_optional_product_quantity Translate-URL: https://translation.odoo-community.org/projects/product-attribute-16-0/product-attribute-16-0-product_optional_product_quantity/it/ --- product_optional_product_quantity/i18n/it.po | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/product_optional_product_quantity/i18n/it.po b/product_optional_product_quantity/i18n/it.po index 5db5f6e7a78..b2678627155 100644 --- a/product_optional_product_quantity/i18n/it.po +++ b/product_optional_product_quantity/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-03-12 13:34+0000\n" +"PO-Revision-Date: 2024-10-03 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_optional_product_quantity #: model:ir.model.fields,field_description:product_optional_product_quantity.field_product_optional_line__company_id @@ -95,8 +95,8 @@ msgid "" "Optional Products are suggested whenever the customer hits *Add to Cart* " "(cross-sell strategy, e.g. for computers: warranty, software, etc.)." msgstr "" -"I prodotti opzionali sono suggeriti qando il cliente fa clic si \"Aggiungi " -"al carrello\" (strategia crss-selling, es. per computer: garanzia, " +"I prodotti opzionali sono suggeriti quando il cliente fa clic su \"Aggiungi " +"al carrello\" (strategia cross-selling, es. per computer: garanzia, " "programmi, ecc.)." #. module: product_optional_product_quantity From 6271fb1b2c4ef6e4ae2c160a0c139b812ec8615f Mon Sep 17 00:00:00 2001 From: Bhavesh Heliconia Date: Wed, 12 Mar 2025 16:02:23 +0530 Subject: [PATCH 10/11] [IMP] product_optional_product_quantity: pre-commit auto fixes --- .../models/product_optional_line.py | 5 ++++- product_optional_product_quantity/pyproject.toml | 3 +++ .../security/res_groups.xml | 2 -- .../tests/test_optional_product_quantity.py | 9 ++++++--- .../views/product_template_views.xml | 2 -- .../views/res_config_settings_views.xml | 1 - 6 files changed, 13 insertions(+), 9 deletions(-) create mode 100644 product_optional_product_quantity/pyproject.toml diff --git a/product_optional_product_quantity/models/product_optional_line.py b/product_optional_product_quantity/models/product_optional_line.py index 151d946d51a..4716faa0ffb 100644 --- a/product_optional_product_quantity/models/product_optional_line.py +++ b/product_optional_product_quantity/models/product_optional_line.py @@ -16,7 +16,10 @@ class ProductOptionalLine(models.Model): company_id = fields.Many2one(related="product_tmpl_id.company_id") optional_product_tmpl_id = fields.Many2one( comodel_name="product.template", - domain="[('company_id', 'in', [company_id, False]), ('id', '!=', product_tmpl_id)]", + domain=[ + ("company_id", "in", [company_id, False]), + ("id", "!=", product_tmpl_id), + ], string="Product", required=True, ) diff --git a/product_optional_product_quantity/pyproject.toml b/product_optional_product_quantity/pyproject.toml new file mode 100644 index 00000000000..4231d0cccb3 --- /dev/null +++ b/product_optional_product_quantity/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/product_optional_product_quantity/security/res_groups.xml b/product_optional_product_quantity/security/res_groups.xml index 2837cde50f2..858ead1e8b3 100644 --- a/product_optional_product_quantity/security/res_groups.xml +++ b/product_optional_product_quantity/security/res_groups.xml @@ -1,9 +1,7 @@ - Use Optional Products Quantity - diff --git a/product_optional_product_quantity/tests/test_optional_product_quantity.py b/product_optional_product_quantity/tests/test_optional_product_quantity.py index bb1234d9c53..eb61e1e679f 100644 --- a/product_optional_product_quantity/tests/test_optional_product_quantity.py +++ b/product_optional_product_quantity/tests/test_optional_product_quantity.py @@ -64,11 +64,13 @@ def test_optional_product_ids_computation(self): "optional_product_tmpl_id": self.product_template_2.id, } ) - # optional_product_ids of Product 1 should contain 1 record with name 'Product 2' + # optional_product_ids of Product 1 should contain 1 + # record with name 'Product 2' self.assertTrue( len(self.product_template_1.optional_product_ids) == 1 and self.product_template_1.optional_product_ids[0].name == "Product 2", - msg="optional_product_ids of product.template has been computed incorrectly", + msg="optional_product_ids of product.template " + "has been computed incorrectly", ) # Create second optional product for Product 1 self.env["product.optional.line"].create( @@ -83,5 +85,6 @@ def test_optional_product_ids_computation(self): len(self.product_template_1.optional_product_ids) == 2 and self.product_template_1.optional_product_ids[0].name == "Product 2" and self.product_template_1.optional_product_ids[1].name == "Product 3", - msg="optional_product_ids of product.template has been computed incorrectly", + msg="optional_product_ids of product.template has " + "been computed incorrectly", ) diff --git a/product_optional_product_quantity/views/product_template_views.xml b/product_optional_product_quantity/views/product_template_views.xml index d0f0c268157..eb270ef796d 100644 --- a/product_optional_product_quantity/views/product_template_views.xml +++ b/product_optional_product_quantity/views/product_template_views.xml @@ -1,6 +1,5 @@ - product.template.view.form.inherit.optional.qty product.template @@ -27,5 +26,4 @@ - diff --git a/product_optional_product_quantity/views/res_config_settings_views.xml b/product_optional_product_quantity/views/res_config_settings_views.xml index 1c926b43474..10c002050de 100644 --- a/product_optional_product_quantity/views/res_config_settings_views.xml +++ b/product_optional_product_quantity/views/res_config_settings_views.xml @@ -1,6 +1,5 @@ - res.config.settings.view.form.inherit.optional.qty res.config.settings From 047e2aa332a05d778d3965a076dde805ccee2545 Mon Sep 17 00:00:00 2001 From: Bhavesh Heliconia Date: Wed, 12 Mar 2025 16:10:26 +0530 Subject: [PATCH 11/11] [MIG] product_optional_product_quantity: Migration to 18.0 --- product_optional_product_quantity/README.rst | 17 +++++++--- .../__manifest__.py | 4 +-- .../models/product_optional_line.py | 8 +++-- .../readme/CONTRIBUTORS.md | 2 ++ .../static/description/index.html | 31 +++++++++++++------ .../tests/test_optional_product_quantity.py | 12 ++++--- .../views/product_template_views.xml | 13 +++----- .../views/res_config_settings_views.xml | 20 ++++-------- 8 files changed, 61 insertions(+), 46 deletions(-) create mode 100644 product_optional_product_quantity/readme/CONTRIBUTORS.md diff --git a/product_optional_product_quantity/README.rst b/product_optional_product_quantity/README.rst index 19afb4b74de..f0b3b167d03 100644 --- a/product_optional_product_quantity/README.rst +++ b/product_optional_product_quantity/README.rst @@ -17,13 +17,13 @@ Product Optional Product Quantity :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_optional_product_quantity + :target: https://github.com/OCA/product-attribute/tree/18.0/product_optional_product_quantity :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_optional_product_quantity + :target: https://translation.odoo-community.org/projects/product-attribute-18-0/product-attribute-18-0-product_optional_product_quantity :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| @@ -69,7 +69,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. @@ -81,6 +81,13 @@ Authors * Cetmix +Contributors +------------ + +- `Heliconia Solutions Pvt. Ltd. `__ + + - Bhavesh Heliconia + Maintainers ----------- @@ -94,6 +101,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_optional_product_quantity/__manifest__.py b/product_optional_product_quantity/__manifest__.py index 5eafc05873a..1eedaee307c 100644 --- a/product_optional_product_quantity/__manifest__.py +++ b/product_optional_product_quantity/__manifest__.py @@ -2,14 +2,14 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { "name": "Product Optional Product Quantity", - "version": "16.0.1.1.0", + "version": "18.0.1.0.0", "category": "Product", "summary": "Specify optional products quantity for product", "author": "Cetmix, Odoo Community Association (OCA)", "website": "https://github.com/OCA/product-attribute", "license": "AGPL-3", "depends": [ - "sale_product_configurator", + "sale", ], "data": [ "security/res_groups.xml", diff --git a/product_optional_product_quantity/models/product_optional_line.py b/product_optional_product_quantity/models/product_optional_line.py index 4716faa0ffb..120c702dbc5 100644 --- a/product_optional_product_quantity/models/product_optional_line.py +++ b/product_optional_product_quantity/models/product_optional_line.py @@ -1,6 +1,6 @@ # Copyright 2024 Cetmix OÜ # 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 class ProductOptionalLine(models.Model): @@ -39,7 +39,9 @@ def _check_same_product_as_related(self): and r.product_tmpl_id == r.optional_product_tmpl_id ): raise models.ValidationError( - _("You can't add product this line is related to as optional.") + self.env._( + "You can't add product this line is related to as optional." + ) ) @api.constrains("product_tmpl_id", "optional_product_tmpl_id") @@ -56,5 +58,5 @@ def _check_unique_products_within_product(self): ] ): raise models.ValidationError( - _("You can't add two same products as optional.") + self.env._("You can't add two same products as optional.") ) diff --git a/product_optional_product_quantity/readme/CONTRIBUTORS.md b/product_optional_product_quantity/readme/CONTRIBUTORS.md new file mode 100644 index 00000000000..2f6060845e2 --- /dev/null +++ b/product_optional_product_quantity/readme/CONTRIBUTORS.md @@ -0,0 +1,2 @@ +- [Heliconia Solutions Pvt. Ltd.](https://www.heliconia.io) + - Bhavesh Heliconia diff --git a/product_optional_product_quantity/static/description/index.html b/product_optional_product_quantity/static/description/index.html index 30166831c26..65c919c1474 100644 --- a/product_optional_product_quantity/static/description/index.html +++ b/product_optional_product_quantity/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 { @@ -368,7 +369,7 @@

Product Optional Product Quantity

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:19c5748e08443684d61807c9a609fcd25cd03d10eb4a7420bd715a19eefb771f !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

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

This module implements core functionality for the optional product quantity multipliers. You can depend on this module to implement further user features.

@@ -381,7 +382,8 @@

Product Optional Product Quantity

  • Bug Tracker
  • Credits
  • @@ -413,7 +415,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.

    @@ -424,14 +426,25 @@

    Authors

  • Cetmix
  • +
    +

    Contributors

    + +
    -

    Maintainers

    +

    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.

    -

    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_optional_product_quantity/tests/test_optional_product_quantity.py b/product_optional_product_quantity/tests/test_optional_product_quantity.py index eb61e1e679f..5fa1e154749 100644 --- a/product_optional_product_quantity/tests/test_optional_product_quantity.py +++ b/product_optional_product_quantity/tests/test_optional_product_quantity.py @@ -1,32 +1,34 @@ # Copyright 2024 Cetmix OÜ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from odoo import exceptions -from odoo.tests.common import TransactionCase, tagged +from odoo.tests.common import tagged + +from odoo.addons.base.tests.common import BaseCommon @tagged("post_install", "-at_install") -class TestOptionalProductQuantity(TransactionCase): +class TestOptionalProductQuantity(BaseCommon): @classmethod def setUpClass(cls): super().setUpClass() cls.product_template_1 = cls.env["product.template"].create( { "name": "Product 1", - "type": "product", + "type": "consu", "categ_id": cls.env.ref("product.product_category_all").id, } ) cls.product_template_2 = cls.env["product.template"].create( { "name": "Product 2", - "type": "product", + "type": "consu", "categ_id": cls.env.ref("product.product_category_all").id, } ) cls.product_template_3 = cls.env["product.template"].create( { "name": "Product 3", - "type": "product", + "type": "consu", "categ_id": cls.env.ref("product.product_category_all").id, } ) diff --git a/product_optional_product_quantity/views/product_template_views.xml b/product_optional_product_quantity/views/product_template_views.xml index eb270ef796d..cf8f2766546 100644 --- a/product_optional_product_quantity/views/product_template_views.xml +++ b/product_optional_product_quantity/views/product_template_views.xml @@ -3,25 +3,22 @@ product.template.view.form.inherit.optional.qty product.template - + 1 - - - + + + - + diff --git a/product_optional_product_quantity/views/res_config_settings_views.xml b/product_optional_product_quantity/views/res_config_settings_views.xml index 10c002050de..5a42e2543bd 100644 --- a/product_optional_product_quantity/views/res_config_settings_views.xml +++ b/product_optional_product_quantity/views/res_config_settings_views.xml @@ -5,22 +5,14 @@ res.config.settings -
    -
    + -
    - -
    -
    -
    -
    -
    + + +