diff --git a/product_assortment/README.rst b/product_assortment/README.rst new file mode 100644 index 00000000000..91c23ca55a1 --- /dev/null +++ b/product_assortment/README.rst @@ -0,0 +1,119 @@ +================== +Product Assortment +================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:d6a41e8eb60ae14e641778ae346f917d1fce31a834dff76a21ef4e2780129b5e + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png + :target: https://odoo-community.org/page/development-status + :alt: Production/Stable +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fproduct--attribute-lightgray.png?logo=github + :target: https://github.com/OCA/product-attribute/tree/17.0/product_assortment + :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-17-0/product-attribute-17-0-product_assortment + :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=17.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This addon intends to manage product assortment. In Odoo you can only +define some filters defined by a domain but it can be sometimes really +complicated. With this addon you will be able to define a domain but +also add some products to include or to exclude through a allowed list +and a restricted list. This is done by overriding ir.capability but +without influencing its standard behaviour. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +To use this module, you need to: + +1. Enter the menu through Product Assortment Icon +2. Create a new filter where you can define your domain and add allowed + and restricted products + +Changelog +========= + +10.0.1.0.0 (2018-08-27) +----------------------- + +- [10.0][ADD] product_assortment + +12.0.1.0.0 (2019-06-03) +----------------------- + +- [12.0][MIG] product_assortment + +14.0.1.0.0 (2019-06-03) +----------------------- + +- [14.0][MIG] product_assortment + +16.0.1.0.0 (2022-09-15) +----------------------- + +- [16.0][MIG] product_assortment + +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 +------- + +* ACSONE SA/NV + +Contributors +------------ + +- Denis Roussel +- Cédric Pigeon +- Xavier Bouquiaux +- `Tecnativa `__: + + - Carlos Roca + - Sergio Teruel + +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_assortment/__init__.py b/product_assortment/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/product_assortment/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/product_assortment/__manifest__.py b/product_assortment/__manifest__.py new file mode 100644 index 00000000000..aa106fb32ba --- /dev/null +++ b/product_assortment/__manifest__.py @@ -0,0 +1,22 @@ +# Copyright 2021 ACSONE SA/NV +# Copyright 2023 Tecnativa - Carlos Dauden +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Product Assortment", + "summary": """ + Adds the ability to manage products assortment""", + "version": "17.0.1.0.0", + "license": "AGPL-3", + "development_status": "Production/Stable", + "author": "ACSONE SA/NV,Odoo Community Association (OCA)", + "website": "https://github.com/OCA/product-attribute", + "depends": ["base", "product"], + "data": [ + "data/ir_cron.xml", + "security/product_assortment_security.xml", + "views/product_assortment.xml", + "views/res_partner_view.xml", + ], + "installable": True, +} diff --git a/product_assortment/data/ir_cron.xml b/product_assortment/data/ir_cron.xml new file mode 100644 index 00000000000..1315b9a1fca --- /dev/null +++ b/product_assortment/data/ir_cron.xml @@ -0,0 +1,33 @@ + + + + + Product assortment recompute all partbers + + + code + model.search([])._compute_all_partner_ids() + + + + + + 1 + days + -1 + + + + + + diff --git a/product_assortment/i18n/ca.po b/product_assortment/i18n/ca.po new file mode 100644 index 00000000000..acc0fc5d49a --- /dev/null +++ b/product_assortment/i18n/ca.po @@ -0,0 +1,197 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_assortment +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 13.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2022-03-22 13:17+0000\n" +"Last-Translator: Noel estudillo \n" +"Language-Team: none\n" +"Language: ca\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.3.2\n" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid ">" +msgstr "" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "" +"\n" +" Product\n" +" " +msgstr "" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.view_partner_form +msgid "Product Assortments" +msgstr "Assortiment de producte" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__all_partner_ids +msgid "All Partner" +msgstr "Tots socis" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Allowed product domain" +msgstr "" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__whitelist_product_ids +msgid "Allowed products" +msgstr "" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_res_partner__applied_assortment_ids +#: model:ir.model.fields,field_description:product_assortment.field_res_users__applied_assortment_ids +msgid "Applied Assortment" +msgstr "" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__apply_black_list_product_domain +msgid "Apply restricted product domain" +msgstr "" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Archived" +msgstr "" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_search +msgid "Assortment Name" +msgstr "Nom de l'assortiment" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_search +msgid "Assortments" +msgstr "Assortiments" + +#. module: product_assortment +#: model:ir.model,name:product_assortment.model_res_partner +msgid "Contact" +msgstr "Contacte" + +#. module: product_assortment +#: model:ir.model,name:product_assortment.model_ir_filters +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Filters" +msgstr "Filtres" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__is_assortment +msgid "Is Assortment" +msgstr "És Assortiment" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__partner_ids +msgid "Partner" +msgstr "Soci" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__partner_domain +msgid "Partner Domain" +msgstr "Domini del soci" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Partner domain" +msgstr "" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Partners to apply" +msgstr "Socis a aplicar" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_product_view_tree +msgid "Product" +msgstr "Producte" + +#. module: product_assortment +#: model:ir.ui.menu,name:product_assortment.menu_product_assortments +msgid "Product Assortment" +msgstr "Assortiment de producte" + +#. module: product_assortment +#: model:ir.actions.act_window,name:product_assortment.actions_product_assortment_view +msgid "Product assortment" +msgstr "Assortiment de producte" + +#. module: product_assortment +#: model:ir.actions.server,name:product_assortment.action_product_assortment_recompute_all_partners +#: model:ir.cron,cron_name:product_assortment.ir_cron_product_assortment_recompute_all_partners +msgid "Product assortment recompute all partbers" +msgstr "" + +#. module: product_assortment +#. odoo-python +#: code:addons/product_assortment/models/ir_filters.py:0 +#, python-format +msgid "Products" +msgstr "Productes" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Products to exclude" +msgstr "Productes a excloure" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Products to include" +msgstr "Productes a incloure" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__record_count +msgid "Record Count" +msgstr "Recompte de registres" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__black_list_product_domain +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Restricted product domain" +msgstr "" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__blacklist_product_ids +msgid "Restricted products" +msgstr "" + +#. module: product_assortment +#: model:ir.model.fields,help:product_assortment.field_ir_filters__partner_ids +msgid "This field allow to relate a partner to a domain of products" +msgstr "Aquest camp permet relacionar un soci amb un domini de productes" + +#~ msgid "Products" +#~ msgstr "Productes" + +#~ msgid "Blacklist Product" +#~ msgstr "Producte de la llista negra" + +#~ msgid "Display Name" +#~ msgstr "Nom de visualització" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "Last Modified on" +#~ msgstr "Última modificació el" + +#~ msgid "Whitelist Product" +#~ msgstr "Producte de la llista blanca" + +#~ msgid "Model" +#~ msgstr "Model" diff --git a/product_assortment/i18n/de.po b/product_assortment/i18n/de.po new file mode 100644 index 00000000000..d2680cdcdba --- /dev/null +++ b/product_assortment/i18n/de.po @@ -0,0 +1,183 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_assortment +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2022-11-04 14:44+0000\n" +"Last-Translator: Maria Sparenberg \n" +"Language-Team: none\n" +"Language: de\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.14.1\n" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid ">" +msgstr ">" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "" +"\n" +" Product\n" +" " +msgstr "" +"\n" +" Produkt\n" +" " + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.view_partner_form +msgid "Product Assortments" +msgstr "Produkt-Sortiment" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__all_partner_ids +msgid "All Partner" +msgstr "Alle Partner" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Allowed product domain" +msgstr "Erlaubte Produkt-Domäne" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__whitelist_product_ids +msgid "Allowed products" +msgstr "Erlaubte Produkte" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_res_partner__applied_assortment_ids +#: model:ir.model.fields,field_description:product_assortment.field_res_users__applied_assortment_ids +msgid "Applied Assortment" +msgstr "" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__apply_black_list_product_domain +msgid "Apply restricted product domain" +msgstr "Domäne zum Beschränken der Produkte anwenden" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Archived" +msgstr "Archiviert" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_search +msgid "Assortment Name" +msgstr "Sortimentsname" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_search +msgid "Assortments" +msgstr "Sortimente" + +#. module: product_assortment +#: model:ir.model,name:product_assortment.model_res_partner +msgid "Contact" +msgstr "Kontakt" + +#. module: product_assortment +#: model:ir.model,name:product_assortment.model_ir_filters +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Filters" +msgstr "Filter" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__is_assortment +msgid "Is Assortment" +msgstr "Ist ein Sortiment" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__partner_ids +msgid "Partner" +msgstr "Partner" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__partner_domain +msgid "Partner Domain" +msgstr "Partner-Domäne" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Partner domain" +msgstr "Partner-Domäne" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Partners to apply" +msgstr "" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_product_view_tree +msgid "Product" +msgstr "Produkt" + +#. module: product_assortment +#: model:ir.ui.menu,name:product_assortment.menu_product_assortments +msgid "Product Assortment" +msgstr "Produkt-Sortiment" + +#. module: product_assortment +#: model:ir.actions.act_window,name:product_assortment.actions_product_assortment_view +msgid "Product assortment" +msgstr "Produkt-Sortiment" + +#. module: product_assortment +#: model:ir.actions.server,name:product_assortment.action_product_assortment_recompute_all_partners +#: model:ir.cron,cron_name:product_assortment.ir_cron_product_assortment_recompute_all_partners +msgid "Product assortment recompute all partbers" +msgstr "" + +#. module: product_assortment +#. odoo-python +#: code:addons/product_assortment/models/ir_filters.py:0 +#, python-format +msgid "Products" +msgstr "Produkte" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Products to exclude" +msgstr "Auszuschließende Produkte" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Products to include" +msgstr "Einzuschließende Produkte" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__record_count +msgid "Record Count" +msgstr "Anzahl der Objekte" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__black_list_product_domain +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Restricted product domain" +msgstr "Domäne für Produkt-Einschränkung" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__blacklist_product_ids +msgid "Restricted products" +msgstr "Eingeschränkte Produkte" + +#. module: product_assortment +#: model:ir.model.fields,help:product_assortment.field_ir_filters__partner_ids +msgid "This field allow to relate a partner to a domain of products" +msgstr "" diff --git a/product_assortment/i18n/es.po b/product_assortment/i18n/es.po new file mode 100644 index 00000000000..e80bf29645f --- /dev/null +++ b/product_assortment/i18n/es.po @@ -0,0 +1,190 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_assortment +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 13.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-03-06 11:12+0000\n" +"PO-Revision-Date: 2023-03-06 12:14+0100\n" +"Last-Translator: Carlos Dauden \n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid ">" +msgstr ">" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "" +"\n" +" Product\n" +" " +msgstr "" +"\n" +" Producto\n" +" " + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.view_partner_form +msgid "Product Assortments" +msgstr "Surtido de productos" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__all_partner_ids +msgid "All Partner" +msgstr "Todos los contactos" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Allowed product domain" +msgstr "Dominio de productos permitidos" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__whitelist_product_ids +msgid "Allowed products" +msgstr "Productos permitidos" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_res_partner__applied_assortment_ids +#: model:ir.model.fields,field_description:product_assortment.field_res_users__applied_assortment_ids +msgid "Applied Assortment" +msgstr "" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__apply_black_list_product_domain +msgid "Apply restricted product domain" +msgstr "Aplicar dominio de productos restringidos" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Archived" +msgstr "Archivado" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_search +msgid "Assortment Name" +msgstr "Nombre del surtido" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_search +msgid "Assortments" +msgstr "Surtidos" + +#. module: product_assortment +#: model:ir.model,name:product_assortment.model_res_partner +msgid "Contact" +msgstr "Contacto" + +#. module: product_assortment +#: model:ir.model,name:product_assortment.model_ir_filters +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Filters" +msgstr "Filtros" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__is_assortment +msgid "Is Assortment" +msgstr "Es surtido" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__partner_ids +msgid "Partner" +msgstr "Contacto" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__partner_domain +msgid "Partner Domain" +msgstr "Dominio de contactos" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Partner domain" +msgstr "Dominio de contactos" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Partners to apply" +msgstr "Contactos a los que aplica" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_product_view_tree +msgid "Product" +msgstr "Producto" + +#. module: product_assortment +#: model:ir.ui.menu,name:product_assortment.menu_product_assortments +msgid "Product Assortment" +msgstr "Surtido de producto" + +#. module: product_assortment +#: model:ir.actions.act_window,name:product_assortment.actions_product_assortment_view +msgid "Product assortment" +msgstr "Surtido de producto" + +#. module: product_assortment +#: model:ir.actions.server,name:product_assortment.action_product_assortment_recompute_all_partners +#: model:ir.cron,cron_name:product_assortment.ir_cron_product_assortment_recompute_all_partners +msgid "Product assortment recompute all partbers" +msgstr "" + +#. module: product_assortment +#. odoo-python +#: code:addons/product_assortment/models/ir_filters.py:0 +#, python-format +msgid "Products" +msgstr "Productos" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Products to exclude" +msgstr "Productos a excluir" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Products to include" +msgstr "Productos a incluir" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__record_count +msgid "Record Count" +msgstr "Número de registros" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__black_list_product_domain +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Restricted product domain" +msgstr "Dominio de productos restringidos" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__blacklist_product_ids +msgid "Restricted products" +msgstr "Productos restringidos" + +#. module: product_assortment +#: model:ir.model.fields,help:product_assortment.field_ir_filters__partner_ids +msgid "This field allow to relate a partner to a domain of products" +msgstr "Este campo permite relacionar un contacto con un dominio de productos" + +#~ msgid "Product assortment reset cache" +#~ msgstr "Resetear cache de surtido de producto" + +#~ msgid "Products" +#~ msgstr "Productos" diff --git a/product_assortment/i18n/fr.po b/product_assortment/i18n/fr.po new file mode 100644 index 00000000000..ebd062220a0 --- /dev/null +++ b/product_assortment/i18n/fr.po @@ -0,0 +1,182 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_assortment +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-11-07 15:06+0000\n" +"Last-Translator: samibc2c \n" +"Language-Team: none\n" +"Language: fr\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 5.6.2\n" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid ">" +msgstr "" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "" +"\n" +" Product\n" +" " +msgstr "" +"\n" +" Produit\n" +" " + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.view_partner_form +msgid "Product Assortments" +msgstr "Assortiments de Produits" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__all_partner_ids +msgid "All Partner" +msgstr "Tous les partenaires" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Allowed product domain" +msgstr "Domaine de produit autorisé" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__whitelist_product_ids +msgid "Allowed products" +msgstr "Produits autorisés" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_res_partner__applied_assortment_ids +#: model:ir.model.fields,field_description:product_assortment.field_res_users__applied_assortment_ids +msgid "Applied Assortment" +msgstr "Assortiment appliqué" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__apply_black_list_product_domain +msgid "Apply restricted product domain" +msgstr "Appliquer un domaine de produit restreint" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Archived" +msgstr "Archivé" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_search +msgid "Assortment Name" +msgstr "Nome de l'assortiment" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_search +msgid "Assortments" +msgstr "Assortiments" + +#. module: product_assortment +#: model:ir.model,name:product_assortment.model_res_partner +msgid "Contact" +msgstr "Contact" + +#. module: product_assortment +#: model:ir.model,name:product_assortment.model_ir_filters +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Filters" +msgstr "Filtres" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__is_assortment +msgid "Is Assortment" +msgstr "Est un assortiment" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__partner_ids +msgid "Partner" +msgstr "Partenaire" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__partner_domain +msgid "Partner Domain" +msgstr "Domaine du partenaire" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Partner domain" +msgstr "Domaine du partenaire" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Partners to apply" +msgstr "Appliquer aux partenaires" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_product_view_tree +msgid "Product" +msgstr "Produit" + +#. module: product_assortment +#: model:ir.ui.menu,name:product_assortment.menu_product_assortments +msgid "Product Assortment" +msgstr "Assortiment de produits" + +#. module: product_assortment +#: model:ir.actions.act_window,name:product_assortment.actions_product_assortment_view +msgid "Product assortment" +msgstr "Assortiement de produits" + +#. module: product_assortment +#: model:ir.actions.server,name:product_assortment.action_product_assortment_recompute_all_partners +#: model:ir.cron,cron_name:product_assortment.ir_cron_product_assortment_recompute_all_partners +msgid "Product assortment recompute all partbers" +msgstr "" + +#. module: product_assortment +#. odoo-python +#: code:addons/product_assortment/models/ir_filters.py:0 +#, python-format +msgid "Products" +msgstr "Produits" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Products to exclude" +msgstr "Produits à exclure" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Products to include" +msgstr "Produits à inclure" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__record_count +msgid "Record Count" +msgstr "Nombre d'enregistrements" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__black_list_product_domain +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Restricted product domain" +msgstr "Domaine de produits restreint" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__blacklist_product_ids +msgid "Restricted products" +msgstr "Produits restreints" + +#. module: product_assortment +#: model:ir.model.fields,help:product_assortment.field_ir_filters__partner_ids +msgid "This field allow to relate a partner to a domain of products" +msgstr "Ce champ permet de relier un partenaire à un domaine de produits" diff --git a/product_assortment/i18n/it.po b/product_assortment/i18n/it.po new file mode 100644 index 00000000000..ab71abd1bad --- /dev/null +++ b/product_assortment/i18n/it.po @@ -0,0 +1,202 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_assortment +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-07-15 09:58+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 5.6.2\n" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid ">" +msgstr ">" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "" +"\n" +" Product\n" +" " +msgstr "" +"\n" +" Prodotto\n" +" " + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.view_partner_form +msgid "Product Assortments" +msgstr "Assortimento dei prodotti " + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__all_partner_ids +msgid "All Partner" +msgstr "Tutti i partner" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Allowed product domain" +msgstr "Dominio prodotto consentito" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__whitelist_product_ids +msgid "Allowed products" +msgstr "Prodotti consentiti" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_res_partner__applied_assortment_ids +#: model:ir.model.fields,field_description:product_assortment.field_res_users__applied_assortment_ids +msgid "Applied Assortment" +msgstr "Assortimento applicato" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__apply_black_list_product_domain +msgid "Apply restricted product domain" +msgstr "Applica dominio prodotti limitati" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Archived" +msgstr "In archivio" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_search +msgid "Assortment Name" +msgstr "Nome assortimento" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_search +msgid "Assortments" +msgstr "Assortimenti" + +#. module: product_assortment +#: model:ir.model,name:product_assortment.model_res_partner +msgid "Contact" +msgstr "Contatto" + +#. module: product_assortment +#: model:ir.model,name:product_assortment.model_ir_filters +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Filters" +msgstr "Filtri" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__is_assortment +msgid "Is Assortment" +msgstr "È assortimento" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__partner_ids +msgid "Partner" +msgstr "Partner" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__partner_domain +msgid "Partner Domain" +msgstr "Dominio partner" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Partner domain" +msgstr "Dominio partner" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Partners to apply" +msgstr "Partner da applicare" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_product_view_tree +msgid "Product" +msgstr "Prodotto" + +#. module: product_assortment +#: model:ir.ui.menu,name:product_assortment.menu_product_assortments +msgid "Product Assortment" +msgstr "Assortimento prodotto" + +#. module: product_assortment +#: model:ir.actions.act_window,name:product_assortment.actions_product_assortment_view +msgid "Product assortment" +msgstr "Assortimento prodotto" + +#. module: product_assortment +#: model:ir.actions.server,name:product_assortment.action_product_assortment_recompute_all_partners +#: model:ir.cron,cron_name:product_assortment.ir_cron_product_assortment_recompute_all_partners +msgid "Product assortment recompute all partbers" +msgstr "Ricalcolo assortimento prodotto per tutti i partner" + +#. module: product_assortment +#. odoo-python +#: code:addons/product_assortment/models/ir_filters.py:0 +#, python-format +msgid "Products" +msgstr "Prodotti" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Products to exclude" +msgstr "Prodotti da escludere" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Products to include" +msgstr "Prodotti da includere" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__record_count +msgid "Record Count" +msgstr "Conteggio record" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__black_list_product_domain +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Restricted product domain" +msgstr "Dominio prodotto limitato" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__blacklist_product_ids +msgid "Restricted products" +msgstr "Prodotti limitati" + +#. module: product_assortment +#: model:ir.model.fields,help:product_assortment.field_ir_filters__partner_ids +msgid "This field allow to relate a partner to a domain of products" +msgstr "" +"Questo campo consente di relazionare un partner con un dominio di prodotti" + +#~ msgid "Products" +#~ msgstr "Prodotti" + +#~ msgid "Blacklist Product" +#~ msgstr "Prodotti da escludere" + +#~ msgid "Display Name" +#~ msgstr "Nome visualizzato" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "Last Modified on" +#~ msgstr "Ultima modifica il" + +#~ msgid "Whitelist Product" +#~ msgstr "Prodotti da includere" diff --git a/product_assortment/i18n/nl.po b/product_assortment/i18n/nl.po new file mode 100644 index 00000000000..9b6f2d13957 --- /dev/null +++ b/product_assortment/i18n/nl.po @@ -0,0 +1,177 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_assortment +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2025-02-03 00:06+0000\n" +"Last-Translator: Bosd \n" +"Language-Team: none\n" +"Language: nl\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 5.6.2\n" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid ">" +msgstr "" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "" +"\n" +" Product\n" +" " +msgstr "" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.view_partner_form +msgid "Product Assortments" +msgstr "Productassortimenten" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__all_partner_ids +msgid "All Partner" +msgstr "Alle partners" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Allowed product domain" +msgstr "Toegestaan productdomein" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__whitelist_product_ids +msgid "Allowed products" +msgstr "Toegestane producten" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_res_partner__applied_assortment_ids +#: model:ir.model.fields,field_description:product_assortment.field_res_users__applied_assortment_ids +msgid "Applied Assortment" +msgstr "Toegepast assortiment" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__apply_black_list_product_domain +msgid "Apply restricted product domain" +msgstr "Beperkt productdomein toepassen" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Archived" +msgstr "Gearchiveerd" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_search +msgid "Assortment Name" +msgstr "Assortimentnaam" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_search +msgid "Assortments" +msgstr "Assortimenten" + +#. module: product_assortment +#: model:ir.model,name:product_assortment.model_res_partner +msgid "Contact" +msgstr "Contactpersoon" + +#. module: product_assortment +#: model:ir.model,name:product_assortment.model_ir_filters +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Filters" +msgstr "Filters" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__is_assortment +msgid "Is Assortment" +msgstr "Is assortiment" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__partner_ids +msgid "Partner" +msgstr "Partner" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__partner_domain +msgid "Partner Domain" +msgstr "Partnerdomein" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Partner domain" +msgstr "Partnerdomein" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Partners to apply" +msgstr "Partners om toe te passen" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_product_view_tree +msgid "Product" +msgstr "Product" + +#. module: product_assortment +#: model:ir.ui.menu,name:product_assortment.menu_product_assortments +msgid "Product Assortment" +msgstr "Productassortiment" + +#. module: product_assortment +#: model:ir.actions.act_window,name:product_assortment.actions_product_assortment_view +msgid "Product assortment" +msgstr "Productassortiment" + +#. module: product_assortment +#: model:ir.actions.server,name:product_assortment.action_product_assortment_recompute_all_partners +#: model:ir.cron,cron_name:product_assortment.ir_cron_product_assortment_recompute_all_partners +msgid "Product assortment recompute all partbers" +msgstr "Productassortiment herbereken alle partners" + +#. module: product_assortment +#. odoo-python +#: code:addons/product_assortment/models/ir_filters.py:0 +#, python-format +msgid "Products" +msgstr "Producten" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Products to exclude" +msgstr "Producten om uit te sluiten" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Products to include" +msgstr "Producten om op te nemen" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__record_count +msgid "Record Count" +msgstr "Aantal records" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__black_list_product_domain +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Restricted product domain" +msgstr "Beperkt productdomein" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__blacklist_product_ids +msgid "Restricted products" +msgstr "Beperkte producten" + +#. module: product_assortment +#: model:ir.model.fields,help:product_assortment.field_ir_filters__partner_ids +msgid "This field allow to relate a partner to a domain of products" +msgstr "" +"Dit veld maakt het mogelijk om een partner te koppelen aan een domein van " +"producten" diff --git a/product_assortment/i18n/product_assortment.pot b/product_assortment/i18n/product_assortment.pot new file mode 100644 index 00000000000..a858aea9223 --- /dev/null +++ b/product_assortment/i18n/product_assortment.pot @@ -0,0 +1,172 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_assortment +# +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_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid ">" +msgstr "" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "" +"\n" +" Product\n" +" " +msgstr "" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.view_partner_form +msgid "Product Assortments" +msgstr "" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__all_partner_ids +msgid "All Partner" +msgstr "" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Allowed product domain" +msgstr "" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__whitelist_product_ids +msgid "Allowed products" +msgstr "" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_res_partner__applied_assortment_ids +#: model:ir.model.fields,field_description:product_assortment.field_res_users__applied_assortment_ids +msgid "Applied Assortment" +msgstr "" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__apply_black_list_product_domain +msgid "Apply restricted product domain" +msgstr "" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Archived" +msgstr "" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_search +msgid "Assortment Name" +msgstr "" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_search +msgid "Assortments" +msgstr "" + +#. module: product_assortment +#: model:ir.model,name:product_assortment.model_res_partner +msgid "Contact" +msgstr "" + +#. module: product_assortment +#: model:ir.model,name:product_assortment.model_ir_filters +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Filters" +msgstr "" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__is_assortment +msgid "Is Assortment" +msgstr "" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__partner_ids +msgid "Partner" +msgstr "" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__partner_domain +msgid "Partner Domain" +msgstr "" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Partner domain" +msgstr "" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Partners to apply" +msgstr "" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_product_view_tree +msgid "Product" +msgstr "" + +#. module: product_assortment +#: model:ir.ui.menu,name:product_assortment.menu_product_assortments +msgid "Product Assortment" +msgstr "" + +#. module: product_assortment +#: model:ir.actions.act_window,name:product_assortment.actions_product_assortment_view +msgid "Product assortment" +msgstr "" + +#. module: product_assortment +#: model:ir.actions.server,name:product_assortment.action_product_assortment_recompute_all_partners +#: model:ir.cron,cron_name:product_assortment.ir_cron_product_assortment_recompute_all_partners +msgid "Product assortment recompute all partbers" +msgstr "" + +#. module: product_assortment +#. odoo-python +#: code:addons/product_assortment/models/ir_filters.py:0 +#, python-format +msgid "Products" +msgstr "" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Products to exclude" +msgstr "" + +#. module: product_assortment +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Products to include" +msgstr "" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__record_count +msgid "Record Count" +msgstr "" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__black_list_product_domain +#: model_terms:ir.ui.view,arch_db:product_assortment.product_assortment_view_form +msgid "Restricted product domain" +msgstr "" + +#. module: product_assortment +#: model:ir.model.fields,field_description:product_assortment.field_ir_filters__blacklist_product_ids +msgid "Restricted products" +msgstr "" + +#. module: product_assortment +#: model:ir.model.fields,help:product_assortment.field_ir_filters__partner_ids +msgid "This field allow to relate a partner to a domain of products" +msgstr "" diff --git a/product_assortment/models/__init__.py b/product_assortment/models/__init__.py new file mode 100644 index 00000000000..c03968c0074 --- /dev/null +++ b/product_assortment/models/__init__.py @@ -0,0 +1,2 @@ +from . import ir_filters +from . import res_partner diff --git a/product_assortment/models/ir_filters.py b/product_assortment/models/ir_filters.py new file mode 100644 index 00000000000..5c75a79b0c4 --- /dev/null +++ b/product_assortment/models/ir_filters.py @@ -0,0 +1,174 @@ +# Copyright 2021 ACSONE SA/NV +# Copyright 2023 Tecnativa - Carlos Dauden +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import _, api, fields, models +from odoo.osv import expression +from odoo.tools import ormcache +from odoo.tools.safe_eval import datetime, safe_eval + + +class IrFilters(models.Model): + _inherit = "ir.filters" + + partner_ids = fields.Many2many( + comodel_name="res.partner", + help="This field allow to relate a partner to a domain of products", + default=lambda p: p.env.context.get("default_partner_ids"), + ) + + blacklist_product_ids = fields.Many2many( + comodel_name="product.product", + string="Restricted products", + relation="assortment_product_blacklisted", + ) + + whitelist_product_ids = fields.Many2many( + comodel_name="product.product", + string="Allowed products", + relation="assortment_product_whitelisted", + ) + + record_count = fields.Integer(compute="_compute_record_count") + + is_assortment = fields.Boolean(default=lambda x: x._get_default_is_assortment()) + partner_domain = fields.Text(default="[]", required=True) + all_partner_ids = fields.Many2many( + comodel_name="res.partner", + compute="_compute_all_partner_ids", + # Make it store=True because we will need this field to search by involved + # partners + store=True, + relation="ir_filter_all_partner_rel", + column1="filter_id", + column2="partner_id", + ) + apply_black_list_product_domain = fields.Boolean( + string="Apply restricted product domain" + ) + black_list_product_domain = fields.Text( + string="Restricted product domain", default="[]", required=True + ) + + @api.model + def _get_default_is_assortment(self): + if self.env.context.get("product_assortment", False): + return True + return False + + @api.model + def _update_assortment_default_values(self, vals_list): + """ + If we create the filter through the assortment, we need to force + model_id to product.product + """ + product_assortment = self.env.context.get("product_assortment", False) + if not product_assortment: + return vals_list + model = self.env.ref("product.model_product_product") + for vals in vals_list: + if not vals.get("model_id"): + vals.update({"model_id": model.model}) + return vals_list + + @api.model_create_multi + def create(self, vals_list): + self._update_assortment_default_values(vals_list=vals_list) + return super().create(vals_list) + + @api.model + @ormcache() + def get_partner_domain_fields(self): + field_set = set() + for ir_filter in self.sudo().search([("is_assortment", "=", True)]): + domain = ir_filter._get_eval_partner_domain() + for item in domain: + if isinstance(item, list | tuple) and isinstance(item[0], str): + field_set.add(item[0].split(".")[0]) + return field_set + + @api.depends("partner_ids", "partner_domain") + def _compute_all_partner_ids(self): + """Summarize selected partners and partners from partner domain field""" + for ir_filter in self: + if not ir_filter.is_assortment: + ir_filter.all_partner_ids = False + elif ir_filter.partner_domain != "[]": + ir_filter.all_partner_ids = ( + self.env["res.partner"].search(ir_filter._get_eval_partner_domain()) + + ir_filter.partner_ids + ) + else: + ir_filter.all_partner_ids = ir_filter.partner_ids + + def _get_eval_domain(self): + res = super()._get_eval_domain() + if self.apply_black_list_product_domain: + black_list_domain = safe_eval( + self.black_list_product_domain, + {"datetime": datetime, "context_today": datetime.datetime.now}, + ) + res = expression.AND( + [expression.distribute_not(["!"] + black_list_domain), res] + ) + if self.whitelist_product_ids: + result_domain = [("id", "in", self.whitelist_product_ids.ids)] + res = expression.OR([result_domain, res]) + if self.blacklist_product_ids: + result_domain = [("id", "not in", self.blacklist_product_ids.ids)] + res = expression.AND([result_domain, res]) + return res + + def _get_eval_black_list_domain(self): + res = safe_eval( + self.black_list_product_domain, + {"datetime": datetime, "context_today": datetime.datetime.now}, + ) + if self.blacklist_product_ids: + result_domain = [("id", "not in", self.blacklist_product_ids.ids)] + res = expression.AND([result_domain, res]) + return res + + def _get_eval_partner_domain(self): + self.ensure_one() + return safe_eval( + self.partner_domain, + {"datetime": datetime, "context_today": datetime.datetime.now}, + ) + + def _compute_record_count(self): + for record in self: + if not record.is_assortment: + record.record_count = 0 + continue + domain = record._get_eval_domain() + record.record_count = self.env[record.model_id].search_count(domain) + + @api.model + def _get_action_domain(self, action_id=None): + # tricky way to act on get_filter method to prevent returning + # assortment in search view filters + domain = super()._get_action_domain(action_id=action_id) + domain = expression.AND([[("is_assortment", "=", False)], domain]) + + return domain + + def write(self, vals): + res = super().write(vals) + if "partner_ids" in vals or "partner_domain" in vals: + self.clear_caches() + return res + + def show_products(self): + self.ensure_one() + xmlid = "product.product_normal_action_sell" + action = self.env["ir.actions.act_window"]._for_xml_id(xmlid) + action.update( + { + "domain": self._get_eval_domain(), + "name": _("Products"), + "context": self.env.context, + "target": "current", + } + ) + return action diff --git a/product_assortment/models/res_partner.py b/product_assortment/models/res_partner.py new file mode 100644 index 00000000000..dd6721400cd --- /dev/null +++ b/product_assortment/models/res_partner.py @@ -0,0 +1,61 @@ +# Copyright 2021 Tecnativa - Carlos Roca +# Copyright 2021 Tecnativa - Carlos Dauden +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). +from odoo import api, fields, models + + +class ResPartner(models.Model): + _inherit = "res.partner" + + applied_assortment_ids = fields.Many2many( + comodel_name="ir.filters", + relation="ir_filter_all_partner_rel", + column1="partner_id", + column2="filter_id", + ) + + def action_define_product_assortment(self): + self.ensure_one() + xmlid = "product_assortment.actions_product_assortment_view" + action = self.env["ir.actions.act_window"]._for_xml_id(xmlid) + action["domain"] = [ + ("partner_ids", "in", self.ids), + ("is_assortment", "=", True), + ] + ctx = self.env.context.copy() + ctx.update( + { + "default_partner_ids": self.ids, + "default_is_assortment": True, + "product_assortment": True, + } + ) + action["context"] = ctx + return action + + def _update_partner_assortments(self): + # Using sudo to contemplate evaluation of domains with restricted fields + self = self.sudo() + assortments = self.env["ir.filters"].search([("is_assortment", "=", True)]) + for partner in self: + # Use ids instead of record to improve performance (Remove in next versions) + partner_assortment_ids = [] + for assortment in assortments: + if partner in assortment.partner_ids or partner.filtered_domain( + assortment._get_eval_partner_domain() + ): + partner_assortment_ids.append(assortment.id) + partner.applied_assortment_ids = assortments.browse(partner_assortment_ids) + + @api.model_create_multi + def create(self, vals_list): + partners = super().create(vals_list) + self._update_partner_assortments() + return partners + + def write(self, vals): + res = super().write(vals) + IrFilters = self.env["ir.filters"] + if IrFilters.get_partner_domain_fields() & set(vals.keys()): + self._update_partner_assortments() + return res diff --git a/product_assortment/pyproject.toml b/product_assortment/pyproject.toml new file mode 100644 index 00000000000..4231d0cccb3 --- /dev/null +++ b/product_assortment/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/product_assortment/readme/CONTRIBUTORS.md b/product_assortment/readme/CONTRIBUTORS.md new file mode 100644 index 00000000000..78aeddace92 --- /dev/null +++ b/product_assortment/readme/CONTRIBUTORS.md @@ -0,0 +1,6 @@ +- Denis Roussel \<\> +- Cédric Pigeon \<\> +- Xavier Bouquiaux \<\> +- [Tecnativa](https://www.tecnativa.com): + - Carlos Roca + - Sergio Teruel diff --git a/product_assortment/readme/DESCRIPTION.md b/product_assortment/readme/DESCRIPTION.md new file mode 100644 index 00000000000..9c60a45bb2c --- /dev/null +++ b/product_assortment/readme/DESCRIPTION.md @@ -0,0 +1,6 @@ +This addon intends to manage product assortment. In Odoo you can only +define some filters defined by a domain but it can be sometimes really +complicated. With this addon you will be able to define a domain but +also add some products to include or to exclude through a allowed list +and a restricted list. This is done by overriding ir.capability but +without influencing its standard behaviour. diff --git a/product_assortment/readme/HISTORY.md b/product_assortment/readme/HISTORY.md new file mode 100644 index 00000000000..57deefd9203 --- /dev/null +++ b/product_assortment/readme/HISTORY.md @@ -0,0 +1,15 @@ +## 10.0.1.0.0 (2018-08-27) + +- \[10.0\]\[ADD\] product_assortment + +## 12.0.1.0.0 (2019-06-03) + +- \[12.0\]\[MIG\] product_assortment + +## 14.0.1.0.0 (2019-06-03) + +- \[14.0\]\[MIG\] product_assortment + +## 16.0.1.0.0 (2022-09-15) + +- \[16.0\]\[MIG\] product_assortment diff --git a/product_assortment/readme/USAGE.md b/product_assortment/readme/USAGE.md new file mode 100644 index 00000000000..dbc0b08586f --- /dev/null +++ b/product_assortment/readme/USAGE.md @@ -0,0 +1,5 @@ +To use this module, you need to: + +1. Enter the menu through Product Assortment Icon +2. Create a new filter where you can define your domain and add allowed + and restricted products diff --git a/product_assortment/security/product_assortment_security.xml b/product_assortment/security/product_assortment_security.xml new file mode 100644 index 00000000000..64b21121afe --- /dev/null +++ b/product_assortment/security/product_assortment_security.xml @@ -0,0 +1,17 @@ + + + Product Assortment Manager + Access to all product assortment + + + + ir.filters.product.assortment.manager.rule + + [('is_assortment','=', True)] + + + + diff --git a/product_assortment/static/description/icon.png b/product_assortment/static/description/icon.png new file mode 100644 index 00000000000..809e4c63d63 Binary files /dev/null and b/product_assortment/static/description/icon.png differ diff --git a/product_assortment/static/description/index.html b/product_assortment/static/description/index.html new file mode 100644 index 00000000000..7dc8ee57316 --- /dev/null +++ b/product_assortment/static/description/index.html @@ -0,0 +1,479 @@ + + + + + +Product Assortment + + + +
+

Product Assortment

+ + +

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

+

This addon intends to manage product assortment. In Odoo you can only +define some filters defined by a domain but it can be sometimes really +complicated. With this addon you will be able to define a domain but +also add some products to include or to exclude through a allowed list +and a restricted list. This is done by overriding ir.capability but +without influencing its standard behaviour.

+

Table of contents

+ +
+

Usage

+

To use this module, you need to:

+
    +
  1. Enter the menu through Product Assortment Icon
  2. +
  3. Create a new filter where you can define your domain and add allowed +and restricted products
  4. +
+
+
+

Changelog

+
+

10.0.1.0.0 (2018-08-27)

+
    +
  • [10.0][ADD] product_assortment
  • +
+
+
+

12.0.1.0.0 (2019-06-03)

+
    +
  • [12.0][MIG] product_assortment
  • +
+
+
+

14.0.1.0.0 (2019-06-03)

+
    +
  • [14.0][MIG] product_assortment
  • +
+
+
+

16.0.1.0.0 (2022-09-15)

+
    +
  • [16.0][MIG] product_assortment
  • +
+
+
+
+

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

+
    +
  • ACSONE SA/NV
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

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

+

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_assortment/tests/__init__.py b/product_assortment/tests/__init__.py new file mode 100644 index 00000000000..7c6e5f94694 --- /dev/null +++ b/product_assortment/tests/__init__.py @@ -0,0 +1 @@ +from . import test_product_assortment diff --git a/product_assortment/tests/test_product_assortment.py b/product_assortment/tests/test_product_assortment.py new file mode 100644 index 00000000000..b1d1cda6bf7 --- /dev/null +++ b/product_assortment/tests/test_product_assortment.py @@ -0,0 +1,179 @@ +# Copyright 2021 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from psycopg2 import IntegrityError + +from odoo.tests.common import TransactionCase +from odoo.tools.misc import mute_logger + + +class TestProductAssortment(TransactionCase): + def setUp(self): + super().setUp() + self.filter_obj = self.env["ir.filters"] + self.product_obj = self.env["product.product"] + self.assortment = self.filter_obj.create( + { + "name": "Test Assortment", + "model_id": "product.product", + "is_assortment": True, + "domain": [], + } + ) + self.filter_no_assortment = self.filter_obj.create( + { + "name": "Test No Assortment", + "model_id": "product.product", + "is_assortment": False, + "domain": [], + } + ) + self.partner = self.env["res.partner"].create({"name": "Test partner"}) + self.partner2 = self.env["res.partner"].create({"name": "Test partner 2"}) + + def test_assortment(self): + products = self.product_obj.search([]) + domain = self.assortment._get_eval_domain() + products_filtered = self.product_obj.search(domain) + self.assertEqual(products.ids, products_filtered.ids) + + # reduce assortment to services products + domain = [("type", "=", "service")] + self.assortment.domain = domain + + products = self.product_obj.search(domain) + domain = self.assortment._get_eval_domain() + products_filtered = self.product_obj.search(domain) + self.assertEqual(products.ids, products_filtered.ids) + + # include one product not in initial filter + included_product = self.env.ref("product.product_product_7") + self.assortment.write({"whitelist_product_ids": [(4, included_product.id)]}) + domain = self.assortment._get_eval_domain() + products_filtered = self.product_obj.search(domain) + self.assertIn(included_product.id, products_filtered.ids) + + # exclude one product not in initial filter + excluded_product = self.env.ref("product.product_product_2") + domain = self.assortment._get_eval_domain() + products_filtered = self.product_obj.search(domain) + self.assertIn(excluded_product.id, products_filtered.ids) + self.assortment.write({"blacklist_product_ids": [(4, excluded_product.id)]}) + domain = self.assortment._get_eval_domain() + products_filtered = self.product_obj.search(domain) + self.assertNotIn(excluded_product.id, products_filtered.ids) + + def test_assortment_not_available_search_view(self): + model = self.env.ref("product.model_product_product") + filters = self.filter_obj.get_filters(model.id) + self.assertFalse(filters) + + def test_create_assortment_with_context(self): + assortment = self.filter_obj.with_context(product_assortment=True).create( + {"name": "Test Assortment Context", "domain": []} + ) + self.assertTrue(assortment.is_assortment) + self.assertEqual(assortment.model_id, "product.product") + + @mute_logger("odoo.sql_db") + def test_create_assortment_without_context(self): + with self.assertRaises(IntegrityError), self.env.cr.savepoint(): + self.filter_obj.with_context(product_assortment=False).create( + {"name": "Test Assortment No Context", "domain": []} + ) + + def test_search_assortment_with_partner(self): + self.filter_obj.with_context(product_assortment=True).create( + { + "name": "Test Assortment Partner", + "domain": [], + "partner_ids": [(4, self.partner.id)], + } + ) + search_domain = self.partner.action_define_product_assortment()["domain"] + self.assertEqual( + search_domain, + [("partner_ids", "in", [self.partner.id]), ("is_assortment", "=", True)], + ) + + def test_product_assortment_view(self): + included_product = self.env.ref("product.product_product_7") + self.assortment.write({"whitelist_product_ids": [(4, included_product.id)]}) + res = self.assortment.show_products() + self.assertEqual(res["domain"], [("id", "in", [included_product.id])]) + + def test_product_assortment_view_with_black_list(self): + excluded_product = self.env.ref("product.product_product_7") + self.assortment.write( + { + "blacklist_product_ids": [(4, excluded_product.id)], + } + ) + res = self.assortment.show_products() + self.assertEqual(res["domain"], [("id", "not in", excluded_product.ids)]) + + def test_product_assortment_mixed_view(self): + included_product = self.env.ref("product.product_product_7") + excluded_product = self.env.ref("product.product_product_2") + self.assortment.write( + { + "whitelist_product_ids": [(4, included_product.id)], + "blacklist_product_ids": [(4, excluded_product.id)], + } + ) + res = self.assortment.show_products() + self.assertEqual(res["domain"][1], ("id", "not in", excluded_product.ids)) + self.assertEqual(res["domain"][2], ("id", "in", included_product.ids)) + + def test_record_count(self): + self.assertEqual(self.filter_no_assortment.record_count, 0) + + products = self.product_obj.search([]) + self.assertEqual(self.assortment.record_count, len(products)) + + # reduce assortment to services products + domain = [("type", "=", "service")] + self.assortment.domain = domain + + products = self.product_obj.search(domain) + domain = self.assortment._get_eval_domain() + products_filtered = self.product_obj.search(domain) + self.assortment.invalidate_recordset() + self.assertEqual(self.assortment.record_count, len(products_filtered)) + + def test_assortment_with_partner_domain(self): + assortment = self.filter_obj.with_context(product_assortment=True).create( + { + "name": "Test Assortment Partner domain", + "partner_domain": "[('id', '=', %s)]" % self.partner.id, + "partner_ids": [(4, self.partner2.id)], + } + ) + self.assertEqual(assortment.all_partner_ids, self.partner + self.partner2) + + def test_assortment_update_with_multiple_partner(self): + assortment = self.filter_obj.with_context(product_assortment=True).create( + { + "name": "Test Assortment multiple partner", + "partner_domain": "[('name', '=', 'Test partner updated')]", + "partner_ids": [(4, self.partner.id), (4, self.partner2.id)], + } + ) + self.partner.name = "Test partner updated" + self.assertIn(assortment.id, self.partner.applied_assortment_ids.ids) + self.assertEqual(assortment.all_partner_ids, self.partner + self.partner2) + + def test_assortment_with_black_list_product_domain(self): + excluded_product = self.env.ref("product.product_product_7") + assortment = self.filter_obj.with_context(product_assortment=True).create( + { + "name": "Test Assortment black product domain", + "domain": [], + "partner_ids": [(4, self.partner2.id)], + "apply_black_list_product_domain": True, + "black_list_product_domain": [("id", "=", excluded_product.id)], + } + ) + allowed_products = self.env["product.product"].search( + assortment._get_eval_domain() + ) + self.assertNotIn(excluded_product, allowed_products) diff --git a/product_assortment/views/product_assortment.xml b/product_assortment/views/product_assortment.xml new file mode 100644 index 00000000000..d94d9e2de9a --- /dev/null +++ b/product_assortment/views/product_assortment.xml @@ -0,0 +1,161 @@ + + + + + product.assortment.search + ir.filters + + + + + + + + + ir.filters + + + + + + + + + product.assortment.form + ir.filters + +
+
+ +
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + > + + + + + + +
+ + + + + product.product + + + + + + + + Product assortment + ir.actions.act_window + ir.filters + [('is_assortment', '=', True)] + {'product_assortment': True, + 'default_is_assortment': 1} + + + + diff --git a/product_assortment/views/res_partner_view.xml b/product_assortment/views/res_partner_view.xml new file mode 100644 index 00000000000..b9bd5b55e67 --- /dev/null +++ b/product_assortment/views/res_partner_view.xml @@ -0,0 +1,21 @@ + + + + res.partner + form + + +
+ +
+
+
+