diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000000..9cd1629223b --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +# generated from manifests external_dependencies diff --git a/sale_restricted_qty/README.rst b/sale_restricted_qty/README.rst new file mode 100644 index 00000000000..fc3b70d22dc --- /dev/null +++ b/sale_restricted_qty/README.rst @@ -0,0 +1,114 @@ +======================= +Sale order min quantity +======================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:11c109b03c7404989c3814a5675fcc5ae0cb3088674059b409bc202355156177 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Fsale--workflow-lightgray.png?logo=github + :target: https://github.com/OCA/sale-workflow/tree/16.0/sale_restricted_qty + :alt: OCA/sale-workflow +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/sale-workflow-16-0/sale-workflow-16-0-sale_restricted_qty + :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/sale-workflow&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows to define min, max and multiple order quantity on product. +Min and Max order quantity is either required or recommanded. +If you check "Force mini/max Qty" on product the min/max qty do not block sale +order. +This can be used if the available stock is less then the min qty +or if you want to sell sample products. +Max qty can be used if we dont want to sale more than available qty +(end of series product) + +Setings are defined on product, if values are not set we use settings from +product template. +If settings are not set on product template we use settings from +product category otherwise parent category. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +#. Go to **Sales > Products > Product Variants** and Set "Min Sale Qty". + If you dont want block product sale if qty is less the "Min Sale Qty", + chek "Force Min Qty" +#. Create a sale order and add a sale order line with this product and check + if Qty is less then "Min Qty" A message in displayed "Min Qty Required" + Or "Min Qty Recommanded". Check if Min qty is required you can't + validate order. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Akretion + +Contributors +~~~~~~~~~~~~ + +* Mourad EL HADJ MIMOUN + +* `Ooops `_: + + * Ashish Hirpara +* `Aion Tech `_: + + * Simone Rubino + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-ashishhirapara| image:: https://github.com/ashishhirapara.png?size=40px + :target: https://github.com/ashishhirapara + :alt: ashishhirapara + +Current `maintainer `__: + +|maintainer-ashishhirapara| + +This module is part of the `OCA/sale-workflow `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/sale_restricted_qty/__init__.py b/sale_restricted_qty/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/sale_restricted_qty/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/sale_restricted_qty/__manifest__.py b/sale_restricted_qty/__manifest__.py new file mode 100644 index 00000000000..fe43bc7ba30 --- /dev/null +++ b/sale_restricted_qty/__manifest__.py @@ -0,0 +1,22 @@ +# Copyright 2019 Akretion () +# Copyright 2023 Simone Rubino - Aion Tech +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Sale order min quantity", + "version": "16.0.1.0.0", + "category": "Sales Management", + "author": "Akretion, Odoo Community Association (OCA)", + "contributors": ["Ashish Hirpara"], + "maintainers": ["ashishhirapara"], + "website": "https://github.com/OCA/sale-workflow", + "license": "AGPL-3", + "depends": ["sale_management"], + "data": [ + "views/product_category_views.xml", + "views/product_template_views.xml", + "views/product_product_views.xml", + "views/sale_views.xml", + ], + "installable": True, +} diff --git a/sale_restricted_qty/i18n/fr.po b/sale_restricted_qty/i18n/fr.po new file mode 100644 index 00000000000..8e9595c6e21 --- /dev/null +++ b/sale_restricted_qty/i18n/fr.po @@ -0,0 +1,444 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_restricted_qty +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-06-17 11:09+0000\n" +"Last-Translator: Claude R Perrin \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 4.17\n" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:0 +#, python-format +msgid "" +"\n" +"* If you want sell quantity bigger than max Quantity,Check \"force max quatity\" on product" +msgstr "" +"\n" +"* Si vous voulez vendre une quantité supérieure à la quantité maximale, " +"cochez « Forcer Qté Max » sur l'article" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:0 +#, python-format +msgid "" +"\n" +"* If you want sell quantity less than Min Quantity,Check \"force min quatity\" on product" +msgstr "" +"\n" +"* Si vous souhaitez vendre une quantité inférieure à la quantité minimale, " +"cochez « Forcer Qté Min » sur l'article" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:0 +#, python-format +msgid "" +"\n" +"* If you want sell quantity not multiple Quantity,Set multiple quantity to 0 on product or product template or product category" +msgstr "" +"\n" +"* Si vous souhaitez vendre la quantité et non plusieurs, définissez la " +"quantité multiple sur 0 sur l'article ou le modèle d'article ou la catégorie " +"d'article" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:0 +#, python-format +msgid "Check maximum order quantity for this products: * \n" +msgstr "Vérifiez la quantité maximale de commande pour ces articles : * \n" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:0 +#, python-format +msgid "Check minimum order quantity for this products: * \n" +msgstr "Vérifiez la quantité minimale de commande pour ces articles : * \n" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:0 +#, python-format +msgid "Check multiple order quantity for this products: * \n" +msgstr "Vérifiez la quantité de commande multiple pour ces articles : * \n" + +#. module: sale_restricted_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_category__force_sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_product__force_sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_restricted_qty_mixin__force_sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_template__force_sale_max_qty +msgid "" +"Define if user can force sale max qty 'If not set', Odoo will use the value " +"defined in the parent object.Hierarchy is in this order :Product/product " +"Template/product category/parent categoroies " +msgstr "" +"Définir si l’utilisateur peut forcer la qté max de commande 'Si ce n’est pas " +"défini', Odoo utilisera la valeur définie dans l’objet parent. La hiérarchie " +"suit cet ordre :Produit/Modèle de produit/catégorie de produit/catégories " +"parentes " + +#. module: sale_restricted_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_category__force_sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_product__force_sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_restricted_qty_mixin__force_sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_template__force_sale_min_qty +msgid "" +"Define if user can force sale min qty 'If not set', Odoo will use the value " +"defined in the parent object.Hierarchy is in this order :Product/product " +"Template/product category/parent categoroies " +msgstr "" +"Définir si l’utilisateur peut forcer la qté min de commande 'Si ce n’est pas " +"défini', Odoo utilisera la valeur définie dans l’objet parent. La hiérarchie " +"suit cet ordre :Produit/Modèle de produit/catégorie de produit/catégories " +"parentes " + +#. module: sale_restricted_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_category__sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_product__sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_restricted_qty_mixin__sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_template__sale_max_qty +msgid "" +"Define sale max qty 'If not set, Odoo will use the value defined in the " +"parent object.Hierarchy is in this order :Product/product Template/product " +"category/parent categoroies " +msgstr "" +"Définir la vente max qté 'S’elle n’est pas définie, Odoo utilisera la valeur " +"définie dans l’objet parent. La hiérarchie suite cet ordre :Produit/Modèle " +"de produit/catégorie de produit/catégories parentes " + +#. module: sale_restricted_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_category__sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_product__sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_restricted_qty_mixin__sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_template__sale_min_qty +msgid "" +"Define sale min qty 'If not set, Odoo will use the value defined in the " +"parent object.Hierarchy is in this order :Product/product Template/product " +"category/parent categoroies " +msgstr "" +"Définir la vente min qté 'Si elle n’est pas définie, Odoo utilisera la " +"valeur définie dans l’objet parent. La hiérarchie suit cet ordre :Produit/" +"Modèle de produit/catégorie de produit/catégories parentes " + +#. module: sale_restricted_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_category__sale_multiple_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_product__sale_multiple_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_restricted_qty_mixin__sale_multiple_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_template__sale_multiple_qty +msgid "" +"Define sale multiple qty 'If not set', Odoo will use the value defined in " +"the parent object.Hierarchy is in this order :Product/product " +"Template/product category/parent categoroies " +msgstr "" +"Définir la vente multiple 'Si elle n’est pas défini', Odoo utilisera la " +"valeur définie dans l’objet parent. La hiérarchie suit cet ordre :Produit/" +"Modèle de produit/catégorie de produit/catégories parentes " + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__display_name +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__display_name +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__display_name +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__display_name +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__display_name +msgid "Display Name" +msgstr "Nom affiché" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__force_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__force_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__force_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__force_sale_max_qty +msgid "Force Max Qty" +msgstr "Forcer qté Max" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__force_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__force_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__force_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__force_sale_min_qty +msgid "Force Min Qty" +msgstr "Forcer qté Min" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__force_sale_max_qty +msgid "Force Sale Max Qty" +msgstr "Forcer qté max vendable" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__force_sale_min_qty +msgid "Force Sale Min Qty" +msgstr "Forcer qté min vendable" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__id +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__id +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__id +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__id +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__id +msgid "ID" +msgstr "ID" + +#. module: sale_restricted_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_category__manual_force_sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_product__manual_force_sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_restricted_qty_mixin__manual_force_sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_template__manual_force_sale_max_qty +msgid "" +"If force max qty is checked, the max quantity is only indicative value.If is" +" not test we check parent value" +msgstr "" +"Si forcer qté max est cochée, la quantité max n’est qu’une valeur " +"indicative. Si c’est pas coché, nous vérifions la valeur parente" + +#. module: sale_restricted_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_category__manual_force_sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_product__manual_force_sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_restricted_qty_mixin__manual_force_sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_template__manual_force_sale_min_qty +msgid "" +"If force min qty is checked, the min quantity is only indicative value.If is" +" not test we check parent value" +msgstr "" +"Si forcer qté min est cochée, la quantité min n’est qu’indicative. Si ce n’" +"est pas coché, nous vérifions la valeur parente" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category____last_update +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product____last_update +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin____last_update +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template____last_update +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line____last_update +msgid "Last Modified on" +msgstr "Dernière modification le" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__manual_force_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__manual_force_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__manual_force_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__manual_force_sale_max_qty +msgid "Manual Force Max Qty" +msgstr "Force manuellement Qté max" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__manual_force_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__manual_force_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__manual_force_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__manual_force_sale_min_qty +msgid "Manual Force Min Qty" +msgstr "Force manuellement Qté min" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__sale_max_qty +msgid "Max Qty" +msgstr "Qté max" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_order_form +msgid "Max Quantity Exceeded" +msgstr "Quantité maximale dépassée" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_order_form +msgid "Max Quantity Recommended" +msgstr "Quantité maximale recommandée" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__manual_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__manual_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__manual_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__manual_sale_max_qty +msgid "Max Sale Qty" +msgstr "Qté max vendable" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__sale_min_qty +msgid "Min Qty" +msgstr "Qté Min" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_order_form +msgid "Min Quantity Recommended" +msgstr "Quantité minimale recommandée" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_order_form +msgid "Min Quantity Required" +msgstr "Quantité minimale requise" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__manual_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__manual_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__manual_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__manual_sale_min_qty +msgid "Min Sale Qty" +msgstr "Qty min vendable" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__sale_multiple_qty +msgid "Multiple Qty" +msgstr "Quantité multiple" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_order_form +msgid "Multiple Quantity Required" +msgstr "Quantité multiple requise" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__manual_sale_multiple_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__manual_sale_multiple_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__manual_sale_multiple_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__manual_sale_multiple_qty +msgid "Multiple Sale Qty" +msgstr "Qty vente multiple" + +#. module: sale_restricted_qty +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_category__manual_force_sale_max_qty__not_force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_category__manual_force_sale_min_qty__not_force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_product__manual_force_sale_max_qty__not_force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_product__manual_force_sale_min_qty__not_force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_restricted_qty_mixin__manual_force_sale_max_qty__not_force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_restricted_qty_mixin__manual_force_sale_min_qty__not_force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_template__manual_force_sale_max_qty__not_force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_template__manual_force_sale_min_qty__not_force +msgid "No" +msgstr "Non" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__is_qty_not_multiple_qty +msgid "Not Multiple Qty" +msgstr "Pas de qté multiples" + +#. module: sale_restricted_qty +#: model:ir.model,name:sale_restricted_qty.model_product_product +msgid "Product" +msgstr "Article" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:0 +#, python-format +msgid "Product \"%s\": Min Quantity %s." +msgstr "Article « %s » : quantité minimale %s." + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:0 +#, python-format +msgid "Product \"%s\": max Quantity %s." +msgstr "Article « %s » : quantité maximale %s." + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:0 +#, python-format +msgid "Product \"%s\": multiple Quantity %s." +msgstr "Articles « %s » : quantités multiples %s." + +#. module: sale_restricted_qty +#: model:ir.model,name:sale_restricted_qty.model_product_category +msgid "Product Category" +msgstr "Catégorie d'articles" + +#. module: sale_restricted_qty +#: model:ir.model,name:sale_restricted_qty.model_product_restricted_qty_mixin +msgid "Product Restrict Qty Mixin" +msgstr "Mixin limitations quantités vendables" + +#. module: sale_restricted_qty +#: model:ir.model,name:sale_restricted_qty.model_product_template +msgid "Product Template" +msgstr "Modèle d'article" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__is_qty_less_min_qty +msgid "Qty < Min Qty" +msgstr "Qté < Qté min" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__is_qty_bigger_max_qty +msgid "Qty > max Qty" +msgstr "Qté > Qté max" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__sale_max_qty +msgid "Sale Max Qty" +msgstr "Qté max vendable" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.min_order_qty_product_product_form_view +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_category_form +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_template_form +msgid "Sale Max qty" +msgstr "Qté max vendable" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.min_order_qty_product_product_form_view +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_category_form +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_template_form +msgid "Sale Miltiple qty" +msgstr "Qté multiple par commande" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__sale_min_qty +msgid "Sale Min Qty" +msgstr "Qté min vendable" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.min_order_qty_product_product_form_view +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_category_form +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_template_form +msgid "Sale Min qty" +msgstr "Qté min vendable" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__sale_multiple_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__sale_multiple_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__sale_multiple_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__sale_multiple_qty +msgid "Sale Multiple Qty" +msgstr "Qté multiple vendable" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.min_order_qty_product_product_form_view +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_category_form +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_template_form +msgid "Sale restricted qty" +msgstr "Limitations des quantités vendables" + +#. module: sale_restricted_qty +#: model:ir.model,name:sale_restricted_qty.model_sale_order_line +msgid "Sales Order Line" +msgstr "Ligne de bon de commande" + +#. module: sale_restricted_qty +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_category__manual_force_sale_max_qty__use_parent +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_category__manual_force_sale_min_qty__use_parent +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_product__manual_force_sale_max_qty__use_parent +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_product__manual_force_sale_min_qty__use_parent +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_restricted_qty_mixin__manual_force_sale_max_qty__use_parent +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_restricted_qty_mixin__manual_force_sale_min_qty__use_parent +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_template__manual_force_sale_max_qty__use_parent +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_template__manual_force_sale_min_qty__use_parent +msgid "Use Parent Setting" +msgstr "Utiliser le paramètre parent" + +#. module: sale_restricted_qty +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_category__manual_force_sale_max_qty__force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_category__manual_force_sale_min_qty__force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_product__manual_force_sale_max_qty__force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_product__manual_force_sale_min_qty__force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_restricted_qty_mixin__manual_force_sale_max_qty__force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_restricted_qty_mixin__manual_force_sale_min_qty__force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_template__manual_force_sale_max_qty__force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_template__manual_force_sale_min_qty__force +msgid "Yes" +msgstr "Oui" diff --git a/sale_restricted_qty/i18n/it.po b/sale_restricted_qty/i18n/it.po new file mode 100644 index 00000000000..c6df581e4b1 --- /dev/null +++ b/sale_restricted_qty/i18n/it.po @@ -0,0 +1,412 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_restricted_qty +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-06-20 14:09+0000\n" +"Last-Translator: mymage \n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:89 +#, python-format +msgid "\n" +"* If you want sell quantity bigger than max Quantity,Check \"force max quatity\" on product" +msgstr "" +"\n" +"* se vuoi vendere una quantità maggiore della Quantità massima, Seleziona " +"\"forza quantità massima\" nel prodotto" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:70 +#, python-format +msgid "\n" +"* If you want sell quantity less than Min Quantity,Check \"force min quatity\" on product" +msgstr "" +"\n" +"* se vuoi vendere una quantità inferiore alla Quantità Minima, Seleziona " +"\"forza quantità minima\" nel prodotto" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:105 +#, python-format +msgid "\n" +"* If you want sell quantity not multiple Quantity,Set multiple quantity to 0 on product or product template or product category" +msgstr "" +"\n" +"* se vuoi vendere quantità non multiple, Imposta quantità multiple a 0 nella " +"Prodotto o Modello Prodotto o Categoria Prodotto" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:86 +#, python-format +msgid "Check maximum order quantity for this products: * \n" +"" +msgstr "Controlla la quantità di vendita massima per questi prodotti: * \n" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:67 +#, python-format +msgid "Check minimum order quantity for this products: * \n" +"" +msgstr "Controlla la quantità di vendita minima per questi prodotti: * \n" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:102 +#, python-format +msgid "Check multiple order quantity for this products: * \n" +"" +msgstr "Controlla la quantità di vendita multipla per questi prodotti: * \n" + +#. module: sale_restricted_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_category__force_sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_product__force_sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_restricted_qty_mixin__force_sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_template__force_sale_max_qty +msgid "Define if user can force sale max qty 'If not set', Odoo will use the value defined in the parent object.Hierarchy is in this order :Product/product Template/product category/parent categoroies " +msgstr "" +"Definisci se l'utente può forzare la quantità massima di vendita 'Se non " +"impostato', Odoo utilizzerà il valore definito nell'oggetto padre. La " +"gerarchia è in questo ordine: Prodotto/Modello prodotto/categoria prodotto/" +"categorie padre " + +#. module: sale_restricted_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_category__force_sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_product__force_sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_restricted_qty_mixin__force_sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_template__force_sale_min_qty +msgid "Define if user can force sale min qty 'If not set', Odoo will use the value defined in the parent object.Hierarchy is in this order :Product/product Template/product category/parent categoroies " +msgstr "" +"Definisci se l'utente può forzare la quantità minima di vendita 'Se non " +"impostato', Odoo utilizzerà il valore definito nell'oggetto padre. La " +"gerarchia è in questo ordine: Prodotto/Modello prodotto/categoria prodotto/" +"categorie padre " + +#. module: sale_restricted_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_category__sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_product__sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_restricted_qty_mixin__sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_template__sale_max_qty +msgid "Define sale max qty 'If not set, Odoo will use the value defined in the parent object.Hierarchy is in this order :Product/product Template/product category/parent categoroies " +msgstr "" +"Definisci la qtà massima di vendita 'Se non impostato', Odoo utilizzerà il " +"valore definito nell'oggetto padre. La gerarchia è in questo ordine: " +"Prodotto/Modello prodotto/categoria prodotto/categorie padre " + +#. module: sale_restricted_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_category__sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_product__sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_restricted_qty_mixin__sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_template__sale_min_qty +msgid "Define sale min qty 'If not set, Odoo will use the value defined in the parent object.Hierarchy is in this order :Product/product Template/product category/parent categoroies " +msgstr "" +"Definisci la qtà minima di vendita 'Se non impostato', Odoo utilizzerà il " +"valore definito nell'oggetto padre. La gerarchia è in questo ordine: " +"Prodotto/Modello prodotto/categoria prodotto/categorie padre " + +#. module: sale_restricted_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_category__sale_multiple_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_product__sale_multiple_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_restricted_qty_mixin__sale_multiple_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_template__sale_multiple_qty +msgid "Define sale multiple qty 'If not set', Odoo will use the value defined in the parent object.Hierarchy is in this order :Product/product Template/product category/parent categoroies " +msgstr "" +"Definisci la qtà multipla di vendita 'Se non impostato', Odoo utilizzerà il " +"valore definito nell'oggetto padre. La gerarchia è in questo ordine: " +"Prodotto/Modello prodotto/categoria prodotto/categorie padre " + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__display_name +msgid "Display Name" +msgstr "Nome visualizzato" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__force_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__force_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__force_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__force_sale_max_qty +msgid "Force Max Qty" +msgstr "Forza Qtà Massima" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__force_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__force_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__force_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__force_sale_min_qty +msgid "Force Min Qty" +msgstr "Forza Qtà Minima" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__force_sale_max_qty +msgid "Force Sale Max Qty" +msgstr "Forza Qtà Minima di Vendita" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__force_sale_min_qty +msgid "Force Sale Min Qty" +msgstr "Forza Qtà Massima di Vendita" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__id +msgid "ID" +msgstr "ID" + +#. module: sale_restricted_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_category__manual_force_sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_product__manual_force_sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_restricted_qty_mixin__manual_force_sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_template__manual_force_sale_max_qty +msgid "If force max qty is checked, the max quantity is only indicative value.If is not test we check parent value" +msgstr "" +"Se forza qtà massima è selezionata, la quantità massima è solo un valore " +"indicativo. Se non è test controlliamo il valore genitore" + +#. module: sale_restricted_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_category__manual_force_sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_product__manual_force_sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_restricted_qty_mixin__manual_force_sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_template__manual_force_sale_min_qty +msgid "If force min qty is checked, the min quantity is only indicative value.If is not test we check parent value" +msgstr "" +"Se forza qtà minima è selezionata, la quantità minima è solo un valore " +"indicativo. Se non è test controlliamo il valore genitore" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin____last_update +msgid "Last Modified on" +msgstr "Ultima Modifica il" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__manual_force_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__manual_force_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__manual_force_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__manual_force_sale_max_qty +msgid "Manual Force Max Qty" +msgstr "Forza Manualmente Qtà Massima" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__manual_force_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__manual_force_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__manual_force_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__manual_force_sale_min_qty +msgid "Manual Force Min Qty" +msgstr "Forza Manualmente Qtà Minima" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__sale_max_qty +msgid "Max Qty" +msgstr "Quantità Massima" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_order_form +msgid "Max Quantity Exceeded" +msgstr "Quantità Massima Superata" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_order_form +msgid "Max Quantity Recommended" +msgstr "Qtà Massima Consigliata" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__manual_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__manual_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__manual_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__manual_sale_max_qty +msgid "Max Sale Qty" +msgstr "Qtà di Vendita Massima" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__sale_min_qty +msgid "Min Qty" +msgstr "Qtà Minima" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_order_form +msgid "Min Quantity Recommended" +msgstr "Qtà Minima Consigliata" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_order_form +msgid "Min Quantity Required" +msgstr "Qtà Minima Richiesta" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__manual_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__manual_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__manual_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__manual_sale_min_qty +msgid "Min Sale Qty" +msgstr "Qtà di Vendita Minima" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__sale_multiple_qty +msgid "Multiple Qty" +msgstr "Qtà Multiple" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_order_form +msgid "Multiple Quantity Required" +msgstr "Quantità Multipla Richiesta" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__manual_sale_multiple_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__manual_sale_multiple_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__manual_sale_multiple_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__manual_sale_multiple_qty +msgid "Multiple Sale Qty" +msgstr "Quantità di Vendita Multipla" + +#. module: sale_restricted_qty +#: selection:product.category,manual_force_sale_max_qty:0 +#: selection:product.category,manual_force_sale_min_qty:0 +#: selection:product.product,manual_force_sale_max_qty:0 +#: selection:product.product,manual_force_sale_min_qty:0 +#: selection:product.restricted.qty.mixin,manual_force_sale_max_qty:0 +#: selection:product.restricted.qty.mixin,manual_force_sale_min_qty:0 +#: selection:product.template,manual_force_sale_max_qty:0 +#: selection:product.template,manual_force_sale_min_qty:0 +msgid "No" +msgstr "No" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__is_qty_not_multiple_qty +msgid "Not Multiple Qty" +msgstr "Qtà Non Multipla" + +#. module: sale_restricted_qty +#: model:ir.model,name:sale_restricted_qty.model_product_product +msgid "Product" +msgstr "Prodotto" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:62 +#, python-format +msgid "Product \"%s\": Min Quantity %s." +msgstr "Prodotto \"%s\": Quantità Minima %s." + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:81 +#, python-format +msgid "Product \"%s\": max Quantity %s." +msgstr "Prodotto \"%s\": Quantità Massima %s." + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:97 +#, python-format +msgid "Product \"%s\": multiple Quantity %s." +msgstr "prodotto \"%s\": Quantità Multipla %s." + +#. module: sale_restricted_qty +#: model:ir.model,name:sale_restricted_qty.model_product_category +msgid "Product Category" +msgstr "Categoria prodotto" + +#. module: sale_restricted_qty +#: model:ir.model,name:sale_restricted_qty.model_product_restricted_qty_mixin +msgid "Product Restrict Qty Mixin" +msgstr "Mixin Limite di Quantità Prodotto" + +#. module: sale_restricted_qty +#: model:ir.model,name:sale_restricted_qty.model_product_template +msgid "Product Template" +msgstr "Modello Prodotto" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__is_qty_less_min_qty +msgid "Qty < Min Qty" +msgstr "Qtà < Qtà Minima" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__is_qty_bigger_max_qty +msgid "Qty > max Qty" +msgstr "Qtà > Qtà Massima" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__sale_max_qty +msgid "Sale Max Qty" +msgstr "Qtà Massima di Vendita" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.min_order_qty_product_product_form_view +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_category_form +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_template_form +msgid "Sale Max qty" +msgstr "qtà Massima di Vendita" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.min_order_qty_product_product_form_view +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_category_form +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_template_form +msgid "Sale Miltiple qty" +msgstr "qtà Multipla di Vendita" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__sale_min_qty +msgid "Sale Min Qty" +msgstr "Qtà Minima di Vendita" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.min_order_qty_product_product_form_view +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_category_form +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_template_form +msgid "Sale Min qty" +msgstr "qtà Minima di Vendita" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__sale_multiple_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__sale_multiple_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__sale_multiple_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__sale_multiple_qty +msgid "Sale Multiple Qty" +msgstr "Qtà Multipla di Vendita" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.min_order_qty_product_product_form_view +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_category_form +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_template_form +msgid "Sale restricted qty" +msgstr "Quantità di vendita limitata" + +#. module: sale_restricted_qty +#: model:ir.model,name:sale_restricted_qty.model_sale_order_line +msgid "Sales Order Line" +msgstr "Riga ordine di vendita" + +#. module: sale_restricted_qty +#: selection:product.category,manual_force_sale_max_qty:0 +#: selection:product.category,manual_force_sale_min_qty:0 +#: selection:product.product,manual_force_sale_max_qty:0 +#: selection:product.product,manual_force_sale_min_qty:0 +#: selection:product.restricted.qty.mixin,manual_force_sale_max_qty:0 +#: selection:product.restricted.qty.mixin,manual_force_sale_min_qty:0 +#: selection:product.template,manual_force_sale_max_qty:0 +#: selection:product.template,manual_force_sale_min_qty:0 +msgid "Use Parent Setting" +msgstr "Usa Impostazioni Genitore" + +#. module: sale_restricted_qty +#: selection:product.category,manual_force_sale_max_qty:0 +#: selection:product.category,manual_force_sale_min_qty:0 +#: selection:product.product,manual_force_sale_max_qty:0 +#: selection:product.product,manual_force_sale_min_qty:0 +#: selection:product.restricted.qty.mixin,manual_force_sale_max_qty:0 +#: selection:product.restricted.qty.mixin,manual_force_sale_min_qty:0 +#: selection:product.template,manual_force_sale_max_qty:0 +#: selection:product.template,manual_force_sale_min_qty:0 +msgid "Yes" +msgstr "Sì" diff --git a/sale_restricted_qty/i18n/sale_order_min_qty.pot b/sale_restricted_qty/i18n/sale_order_min_qty.pot new file mode 100644 index 00000000000..1400edffa5d --- /dev/null +++ b/sale_restricted_qty/i18n/sale_order_min_qty.pot @@ -0,0 +1,82 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_order_min_qty +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: sale_order_min_qty +#: code:addons/sale_order_min_qty/models/sale.py:51 +#, python-format +msgid "\n" +"* If you want sell quantity less than Min Quantity,Check \"force min quatity\" on product" +msgstr "" + +#. module: sale_order_min_qty +#: code:addons/sale_order_min_qty/models/sale.py:48 +#, python-format +msgid "Check minimum order quantity for this products: * \n" +"" +msgstr "" + +#. module: sale_order_min_qty +#: model:ir.model.fields,field_description:sale_order_min_qty.field_product_product__force_sale_min_qty +#: model:ir.model.fields,field_description:sale_order_min_qty.field_sale_order_line__force_sale_min_qty +msgid "Force Min Qty" +msgstr "" + +#. module: sale_order_min_qty +#: model:ir.model.fields,help:sale_order_min_qty.field_product_product__force_sale_min_qty +#: model:ir.model.fields,help:sale_order_min_qty.field_sale_order_line__force_sale_min_qty +msgid "If force min qty is checked, the min quantity is only indicative value." +msgstr "" + +#. module: sale_order_min_qty +#: model:ir.model.fields,field_description:sale_order_min_qty.field_sale_order_line__sale_min_qty +msgid "Min Qty" +msgstr "" + +#. module: sale_order_min_qty +#: model_terms:ir.ui.view,arch_db:sale_order_min_qty.view_order_form +msgid "Min Quantity Recommended" +msgstr "" + +#. module: sale_order_min_qty +#: model_terms:ir.ui.view,arch_db:sale_order_min_qty.view_order_form +msgid "Min Quantity Required" +msgstr "" + +#. module: sale_order_min_qty +#: model:ir.model.fields,field_description:sale_order_min_qty.field_product_product__sale_min_qty +msgid "Min Sale Qty" +msgstr "" + +#. module: sale_order_min_qty +#: model:ir.model,name:sale_order_min_qty.model_product_product +msgid "Product" +msgstr "" + +#. module: sale_order_min_qty +#: code:addons/sale_order_min_qty/models/sale.py:43 +#, python-format +msgid "Product \"%s\": Min Quantity %s." +msgstr "" + +#. module: sale_order_min_qty +#: model:ir.model.fields,field_description:sale_order_min_qty.field_sale_order_line__is_qty_less_min_qty +msgid "Qty < Min Qty" +msgstr "" + +#. module: sale_order_min_qty +#: model:ir.model,name:sale_order_min_qty.model_sale_order_line +msgid "Sales Order Line" +msgstr "" + diff --git a/sale_restricted_qty/i18n/sale_restricted_qty.pot b/sale_restricted_qty/i18n/sale_restricted_qty.pot new file mode 100644 index 00000000000..c20b2373a25 --- /dev/null +++ b/sale_restricted_qty/i18n/sale_restricted_qty.pot @@ -0,0 +1,410 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_restricted_qty +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:0 +#, python-format +msgid "" +"\n" +"* If you want sell quantity bigger than max Quantity,Check \"force max quatity\" on product" +msgstr "" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:0 +#, python-format +msgid "" +"\n" +"* If you want sell quantity less than Min Quantity,Check \"force min quatity\" on product" +msgstr "" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:0 +#, python-format +msgid "" +"\n" +"* If you want sell quantity not multiple Quantity,Set multiple quantity to 0 on product or product template or product category" +msgstr "" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:0 +#, python-format +msgid "Check maximum order quantity for this products: * \n" +msgstr "" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:0 +#, python-format +msgid "Check minimum order quantity for this products: * \n" +msgstr "" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:0 +#, python-format +msgid "Check multiple order quantity for this products: * \n" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_category__force_sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_product__force_sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_restricted_qty_mixin__force_sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_template__force_sale_max_qty +msgid "" +"Define if user can force sale max qty 'If not set', Odoo will use the value " +"defined in the parent object.Hierarchy is in this order :Product/product " +"Template/product category/parent categoroies " +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_category__force_sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_product__force_sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_restricted_qty_mixin__force_sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_template__force_sale_min_qty +msgid "" +"Define if user can force sale min qty 'If not set', Odoo will use the value " +"defined in the parent object.Hierarchy is in this order :Product/product " +"Template/product category/parent categoroies " +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_category__sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_product__sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_restricted_qty_mixin__sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_template__sale_max_qty +msgid "" +"Define sale max qty 'If not set, Odoo will use the value defined in the " +"parent object.Hierarchy is in this order :Product/product Template/product " +"category/parent categoroies " +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_category__sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_product__sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_restricted_qty_mixin__sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_template__sale_min_qty +msgid "" +"Define sale min qty 'If not set, Odoo will use the value defined in the " +"parent object.Hierarchy is in this order :Product/product Template/product " +"category/parent categoroies " +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_category__sale_multiple_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_product__sale_multiple_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_restricted_qty_mixin__sale_multiple_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_template__sale_multiple_qty +msgid "" +"Define sale multiple qty 'If not set', Odoo will use the value defined in " +"the parent object.Hierarchy is in this order :Product/product " +"Template/product category/parent categoroies " +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__display_name +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__display_name +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__display_name +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__display_name +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__display_name +msgid "Display Name" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__force_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__force_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__force_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__force_sale_max_qty +msgid "Force Max Qty" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__force_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__force_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__force_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__force_sale_min_qty +msgid "Force Min Qty" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__force_sale_max_qty +msgid "Force Sale Max Qty" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__force_sale_min_qty +msgid "Force Sale Min Qty" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__id +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__id +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__id +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__id +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__id +msgid "ID" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_category__manual_force_sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_product__manual_force_sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_restricted_qty_mixin__manual_force_sale_max_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_template__manual_force_sale_max_qty +msgid "" +"If force max qty is checked, the max quantity is only indicative value.If is" +" not test we check parent value" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_category__manual_force_sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_product__manual_force_sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_restricted_qty_mixin__manual_force_sale_min_qty +#: model:ir.model.fields,help:sale_restricted_qty.field_product_template__manual_force_sale_min_qty +msgid "" +"If force min qty is checked, the min quantity is only indicative value.If is" +" not test we check parent value" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category____last_update +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product____last_update +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin____last_update +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template____last_update +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line____last_update +msgid "Last Modified on" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__manual_force_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__manual_force_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__manual_force_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__manual_force_sale_max_qty +msgid "Manual Force Max Qty" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__manual_force_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__manual_force_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__manual_force_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__manual_force_sale_min_qty +msgid "Manual Force Min Qty" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__sale_max_qty +msgid "Max Qty" +msgstr "" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_order_form +msgid "Max Quantity Exceeded" +msgstr "" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_order_form +msgid "Max Quantity Recommended" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__manual_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__manual_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__manual_sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__manual_sale_max_qty +msgid "Max Sale Qty" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__sale_min_qty +msgid "Min Qty" +msgstr "" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_order_form +msgid "Min Quantity Recommended" +msgstr "" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_order_form +msgid "Min Quantity Required" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__manual_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__manual_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__manual_sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__manual_sale_min_qty +msgid "Min Sale Qty" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__sale_multiple_qty +msgid "Multiple Qty" +msgstr "" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_order_form +msgid "Multiple Quantity Required" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__manual_sale_multiple_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__manual_sale_multiple_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__manual_sale_multiple_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__manual_sale_multiple_qty +msgid "Multiple Sale Qty" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_category__manual_force_sale_max_qty__not_force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_category__manual_force_sale_min_qty__not_force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_product__manual_force_sale_max_qty__not_force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_product__manual_force_sale_min_qty__not_force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_restricted_qty_mixin__manual_force_sale_max_qty__not_force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_restricted_qty_mixin__manual_force_sale_min_qty__not_force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_template__manual_force_sale_max_qty__not_force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_template__manual_force_sale_min_qty__not_force +msgid "No" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__is_qty_not_multiple_qty +msgid "Not Multiple Qty" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model,name:sale_restricted_qty.model_product_product +msgid "Product" +msgstr "" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:0 +#, python-format +msgid "Product \"%s\": Min Quantity %s." +msgstr "" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:0 +#, python-format +msgid "Product \"%s\": max Quantity %s." +msgstr "" + +#. module: sale_restricted_qty +#: code:addons/sale_restricted_qty/models/sale.py:0 +#, python-format +msgid "Product \"%s\": multiple Quantity %s." +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model,name:sale_restricted_qty.model_product_category +msgid "Product Category" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model,name:sale_restricted_qty.model_product_restricted_qty_mixin +msgid "Product Restrict Qty Mixin" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model,name:sale_restricted_qty.model_product_template +msgid "Product Template" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__is_qty_less_min_qty +msgid "Qty < Min Qty" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_sale_order_line__is_qty_bigger_max_qty +msgid "Qty > max Qty" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__sale_max_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__sale_max_qty +msgid "Sale Max Qty" +msgstr "" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.min_order_qty_product_product_form_view +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_category_form +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_template_form +msgid "Sale Max qty" +msgstr "" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.min_order_qty_product_product_form_view +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_category_form +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_template_form +msgid "Sale Miltiple qty" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__sale_min_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__sale_min_qty +msgid "Sale Min Qty" +msgstr "" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.min_order_qty_product_product_form_view +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_category_form +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_template_form +msgid "Sale Min qty" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_category__sale_multiple_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_product__sale_multiple_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_restricted_qty_mixin__sale_multiple_qty +#: model:ir.model.fields,field_description:sale_restricted_qty.field_product_template__sale_multiple_qty +msgid "Sale Multiple Qty" +msgstr "" + +#. module: sale_restricted_qty +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.min_order_qty_product_product_form_view +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_category_form +#: model_terms:ir.ui.view,arch_db:sale_restricted_qty.view_product_template_form +msgid "Sale restricted qty" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model,name:sale_restricted_qty.model_sale_order_line +msgid "Sales Order Line" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_category__manual_force_sale_max_qty__use_parent +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_category__manual_force_sale_min_qty__use_parent +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_product__manual_force_sale_max_qty__use_parent +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_product__manual_force_sale_min_qty__use_parent +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_restricted_qty_mixin__manual_force_sale_max_qty__use_parent +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_restricted_qty_mixin__manual_force_sale_min_qty__use_parent +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_template__manual_force_sale_max_qty__use_parent +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_template__manual_force_sale_min_qty__use_parent +msgid "Use Parent Setting" +msgstr "" + +#. module: sale_restricted_qty +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_category__manual_force_sale_max_qty__force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_category__manual_force_sale_min_qty__force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_product__manual_force_sale_max_qty__force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_product__manual_force_sale_min_qty__force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_restricted_qty_mixin__manual_force_sale_max_qty__force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_restricted_qty_mixin__manual_force_sale_min_qty__force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_template__manual_force_sale_max_qty__force +#: model:ir.model.fields.selection,name:sale_restricted_qty.selection__product_template__manual_force_sale_min_qty__force +msgid "Yes" +msgstr "" diff --git a/sale_restricted_qty/models/__init__.py b/sale_restricted_qty/models/__init__.py new file mode 100644 index 00000000000..a1cc9138a71 --- /dev/null +++ b/sale_restricted_qty/models/__init__.py @@ -0,0 +1,5 @@ +from . import product_restricted_qty_mixin +from . import product_category +from . import product_template +from . import product_product +from . import sale diff --git a/sale_restricted_qty/models/product_category.py b/sale_restricted_qty/models/product_category.py new file mode 100644 index 00000000000..b7bb761da88 --- /dev/null +++ b/sale_restricted_qty/models/product_category.py @@ -0,0 +1,65 @@ +# Copyright 2019 Akretion +# Copyright 2023 Simone Rubino - Aion Tech +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class ProductCategory(models.Model): + _name = "product.category" + _inherit = ["product.category", "product.restricted.qty.mixin"] + + sale_multiple_qty = fields.Float( + recursive=True, + ) + sale_min_qty = fields.Float( + recursive=True, + ) + force_sale_min_qty = fields.Boolean( + recursive=True, + ) + sale_max_qty = fields.Float( + recursive=True, + ) + force_sale_max_qty = fields.Boolean( + recursive=True, + ) + + def _get_sale_restricted_qty(self): + res = super()._get_sale_restricted_qty() + force_sale_min_qty = False + if self.manual_force_sale_min_qty == "force": + force_sale_min_qty = True + elif self.manual_force_sale_min_qty == "not_force": + force_sale_min_qty = False + else: + force_sale_min_qty = self.parent_id.force_sale_min_qty + force_sale_max_qty = False + if self.manual_force_sale_max_qty == "force": + force_sale_max_qty = True + elif self.manual_force_sale_max_qty == "not_force": + force_sale_max_qty = False + else: + force_sale_max_qty = self.parent_id.force_sale_max_qty + res.update( + { + "sale_min_qty": self.manual_sale_min_qty or self.parent_id.sale_min_qty, + "force_sale_min_qty": force_sale_min_qty, + "sale_max_qty": self.manual_sale_max_qty or self.parent_id.sale_max_qty, + "force_sale_max_qty": force_sale_max_qty, + "sale_multiple_qty": self.manual_sale_multiple_qty + or self.parent_id.sale_multiple_qty, + } + ) + return res + + @api.depends( + "parent_id.force_sale_min_qty", + "parent_id.sale_min_qty", + "parent_id.force_sale_max_qty", + "parent_id.sale_max_qty", + "parent_id.sale_multiple_qty", + ) + def _compute_sale_restricted_qty(self): + for rec in self: + rec.update(rec._get_sale_restricted_qty()) diff --git a/sale_restricted_qty/models/product_product.py b/sale_restricted_qty/models/product_product.py new file mode 100644 index 00000000000..3991b4eb86a --- /dev/null +++ b/sale_restricted_qty/models/product_product.py @@ -0,0 +1,51 @@ +# Copyright 2019 Akretion +# @author Mourad EL HADJ MIMOUNE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, models + + +class ProductProduct(models.Model): + _name = "product.product" + _inherit = ["product.product", "product.restricted.qty.mixin"] + + def _get_sale_restricted_qty(self): + res = super()._get_sale_restricted_qty() + force_sale_min_qty = False + if self.manual_force_sale_min_qty == "force": + force_sale_min_qty = True + elif self.manual_force_sale_min_qty == "not_force": + force_sale_min_qty = False + else: + force_sale_min_qty = self.product_tmpl_id.force_sale_min_qty + force_sale_max_qty = False + if self.manual_force_sale_max_qty == "force": + force_sale_max_qty = True + elif self.manual_force_sale_max_qty == "not_force": + force_sale_max_qty = False + else: + force_sale_max_qty = self.product_tmpl_id.force_sale_max_qty + res.update( + { + "sale_min_qty": self.manual_sale_min_qty + or self.product_tmpl_id.sale_min_qty, + "force_sale_min_qty": force_sale_min_qty, + "sale_max_qty": self.manual_sale_max_qty + or self.product_tmpl_id.sale_max_qty, + "force_sale_max_qty": force_sale_max_qty, + "sale_multiple_qty": self.manual_sale_multiple_qty + or self.product_tmpl_id.sale_multiple_qty, + } + ) + return res + + @api.depends( + "product_tmpl_id.force_sale_min_qty", + "product_tmpl_id.sale_min_qty", + "product_tmpl_id.force_sale_max_qty", + "product_tmpl_id.sale_max_qty", + "product_tmpl_id.sale_multiple_qty", + ) + def _compute_sale_restricted_qty(self): + for rec in self: + rec.update(rec._get_sale_restricted_qty()) diff --git a/sale_restricted_qty/models/product_restricted_qty_mixin.py b/sale_restricted_qty/models/product_restricted_qty_mixin.py new file mode 100644 index 00000000000..22ecd557434 --- /dev/null +++ b/sale_restricted_qty/models/product_restricted_qty_mixin.py @@ -0,0 +1,117 @@ +# Copyright 2019 Akretion +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class ProductMinMultipleMixin(models.AbstractModel): + _name = "product.restricted.qty.mixin" + _description = "Product Restrict Qty Mixin" + + sale_multiple_qty = fields.Float( + compute="_compute_sale_restricted_qty", + store=True, + help="Define sale multiple qty" + " 'If not set', Odoo will" + " use the value defined in the parent object." + "Hierarchy is in this order :" + "Product/product Template/product category/parent categoroies ", + digits="Product Unit of Measure", + ) + manual_sale_multiple_qty = fields.Float( + string="Multiple Sale Qty", digits="Product Unit of Measure" + ) + sale_min_qty = fields.Float( + compute="_compute_sale_restricted_qty", + store=True, + help="Define sale min qty" + " 'If not set, Odoo will" + " use the value defined in the parent object." + "Hierarchy is in this order :" + "Product/product Template/product category/parent categoroies ", + digits="Product Unit of Measure", + ) + manual_sale_min_qty = fields.Float( + string="Min Sale Qty", digits="Product Unit of Measure" + ) + force_sale_min_qty = fields.Boolean( + compute="_compute_sale_restricted_qty", + string="Force Min Qty", + store=True, + help="Define if user can force sale min qty" + " 'If not set', Odoo will" + " use the value defined in the parent object." + "Hierarchy is in this order :" + "Product/product Template/product category/parent categoroies ", + ) + manual_force_sale_min_qty = fields.Selection( + [ + ("use_parent", "Use Parent Setting"), + ("force", "Yes"), + ("not_force", "No"), + ], + string="Manual Force Min Qty", + required=True, + default="use_parent", + help="If force min qty is checked, the min quantity " + "is only indicative value." + "If is not test we check parent value", + ) + sale_max_qty = fields.Float( + compute="_compute_sale_restricted_qty", + store=True, + help="Define sale max qty" + " 'If not set, Odoo will" + " use the value defined in the parent object." + "Hierarchy is in this order :" + "Product/product Template/product category/parent categoroies ", + digits="Product Unit of Measure", + ) + manual_sale_max_qty = fields.Float( + string="Max Sale Qty", digits="Product Unit of Measure" + ) + force_sale_max_qty = fields.Boolean( + compute="_compute_sale_restricted_qty", + string="Force Max Qty", + store=True, + help="Define if user can force sale max qty" + " 'If not set', Odoo will" + " use the value defined in the parent object." + "Hierarchy is in this order :" + "Product/product Template/product category/parent categoroies ", + ) + manual_force_sale_max_qty = fields.Selection( + [ + ("use_parent", "Use Parent Setting"), + ("force", "Yes"), + ("not_force", "No"), + ], + required=True, + default="use_parent", + string="Manual Force Max Qty", + help="If force max qty is checked, the max quantity " + "is only indicative value." + "If is not test we check parent value", + ) + + def _get_sale_restricted_qty(self): + self.ensure_one() + res = { + "sale_min_qty": self.manual_sale_min_qty, + "force_sale_min_qty": self.manual_force_sale_min_qty == "force", + "sale_max_qty": self.manual_sale_max_qty, + "force_sale_max_qty": self.manual_force_sale_max_qty == "force", + "sale_multiple_qty": self.manual_sale_multiple_qty, + } + return res + + @api.depends( + "manual_force_sale_min_qty", + "manual_sale_min_qty", + "manual_force_sale_max_qty", + "manual_sale_max_qty", + "manual_sale_multiple_qty", + ) + def _compute_sale_restricted_qty(self): + for rec in self: + rec.update(rec._get_sale_restricted_qty()) diff --git a/sale_restricted_qty/models/product_template.py b/sale_restricted_qty/models/product_template.py new file mode 100644 index 00000000000..6b95d382d99 --- /dev/null +++ b/sale_restricted_qty/models/product_template.py @@ -0,0 +1,49 @@ +# Copyright 2019 Akretion +# @author Mourad EL HADJ MIMOUNE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, models + + +class ProductTemplate(models.Model): + _name = "product.template" + _inherit = ["product.template", "product.restricted.qty.mixin"] + + def _get_sale_restricted_qty(self): + res = super()._get_sale_restricted_qty() + force_sale_min_qty = False + if self.manual_force_sale_min_qty == "force": + force_sale_min_qty = True + elif self.manual_force_sale_min_qty == "not_force": + force_sale_min_qty = False + else: + force_sale_min_qty = self.categ_id.force_sale_min_qty + force_sale_max_qty = False + if self.manual_force_sale_max_qty == "force": + force_sale_max_qty = True + elif self.manual_force_sale_max_qty == "not_force": + force_sale_max_qty = False + else: + force_sale_max_qty = self.categ_id.force_sale_max_qty + res.update( + { + "sale_min_qty": self.manual_sale_min_qty or self.categ_id.sale_min_qty, + "force_sale_min_qty": force_sale_min_qty, + "sale_max_qty": self.manual_sale_max_qty or self.categ_id.sale_max_qty, + "force_sale_max_qty": force_sale_max_qty, + "sale_multiple_qty": self.manual_sale_multiple_qty + or self.categ_id.sale_multiple_qty, + } + ) + return res + + @api.depends( + "categ_id.force_sale_min_qty", + "categ_id.sale_min_qty", + "categ_id.force_sale_max_qty", + "categ_id.sale_max_qty", + "categ_id.sale_multiple_qty", + ) + def _compute_sale_restricted_qty(self): + for rec in self: + rec.update(rec._get_sale_restricted_qty()) diff --git a/sale_restricted_qty/models/sale.py b/sale_restricted_qty/models/sale.py new file mode 100644 index 00000000000..7584ca3ac9b --- /dev/null +++ b/sale_restricted_qty/models/sale.py @@ -0,0 +1,189 @@ +# Copyright 2019 Akretion +# Copyright 2023 Simone Rubino - Aion Tech +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError +from odoo.tools import float_compare + + +class SaleOrderLine(models.Model): + _inherit = "sale.order.line" + + sale_min_qty = fields.Float( + string="Min Qty", + compute="_compute_sale_restricted_qty", + store=True, + digits="Product Unit of Measure", + ) + force_sale_min_qty = fields.Boolean( + compute="_compute_sale_restricted_qty", readonly=True, store=True + ) + is_qty_less_min_qty = fields.Boolean( + string="Qty < Min Qty", compute="_compute_is_qty_less_min_qty" + ) + + sale_max_qty = fields.Float( + string="Max Qty", + compute="_compute_sale_restricted_qty", + store=True, + digits="Product Unit of Measure", + ) + force_sale_max_qty = fields.Boolean( + compute="_compute_sale_restricted_qty", readonly=True, store=True + ) + is_qty_bigger_max_qty = fields.Boolean( + string="Qty > max Qty", compute="_compute_is_qty_bigger_max_qty" + ) + sale_multiple_qty = fields.Float( + string="Multiple Qty", + compute="_compute_sale_restricted_qty", + store=True, + digits="Product Unit of Measure", + ) + is_qty_not_multiple_qty = fields.Boolean( + string="Not Multiple Qty", compute="_compute_is_qty_not_multiple_qty" + ) + + @api.constrains( + "product_uom_qty", "sale_min_qty", "sale_max_qty", "sale_multiple_qty" + ) + def check_constraint_restricted_qty(self): + + msg = "" + invaild_min_lines = [] + line_to_test = self.filtered( + lambda sl: not sl.product_id.force_sale_min_qty and sl.is_qty_less_min_qty + ) + for line in line_to_test: + invaild_min_lines.append( + _( + 'Product "%(product)s": Min Quantity %(min_qty)s.', + product=line.product_id.name, + min_qty=line.sale_min_qty, + ) + ) + + if invaild_min_lines: + msg += _( + "Check minimum order quantity for this products: * \n" + ) + "\n ".join(invaild_min_lines) + msg += _( + "\n* If you want sell quantity less than Min Quantity" + ',Check "force min quatity" on product' + ) + invaild_max_lines = [] + line_to_test = self.filtered( + lambda sl: not sl.product_id.force_sale_max_qty and sl.is_qty_bigger_max_qty + ) + for line in line_to_test: + invaild_max_lines.append( + _( + 'Product "%(product)s": max Quantity %(max_qty)s.', + product=line.product_id.name, + max_qty=line.sale_max_qty, + ) + ) + + if invaild_max_lines: + msg += _( + "Check maximum order quantity for this products: * \n" + ) + "\n ".join(invaild_max_lines) + msg += _( + "\n* If you want sell quantity bigger than max Quantity" + ',Check "force max quatity" on product' + ) + invaild_multiple_lines = [] + line_to_test = self.filtered(lambda sl: sl.is_qty_not_multiple_qty) + for line in line_to_test: + invaild_multiple_lines.append( + _( + 'Product "%(product)s": multiple Quantity %(multiple_qty)s.', + product=line.product_id.name, + multiple_qty=line.sale_multiple_qty, + ) + ) + + if invaild_multiple_lines: + msg += _( + "Check multiple order quantity for this products: * \n" + ) + "\n ".join(invaild_multiple_lines) + msg += _( + "\n* If you want sell quantity not multiple Quantity" + ",Set multiple quantity to 0 on product or product template" + " or product category" + ) + + if msg: + raise ValidationError(msg) + + def _get_product_qty_in_product_unit(self): + self.ensure_one() + return self.product_uom._compute_quantity( + self.product_uom_qty, self.product_id.uom_id + ) + + @api.depends("product_id", "product_uom_qty", "sale_min_qty") + def _compute_is_qty_less_min_qty(self): + for line in self: + rounding = line.product_uom.rounding + product_qty = line._get_product_qty_in_product_unit() + line.is_qty_less_min_qty = ( + line.sale_min_qty + and ( + float_compare( + product_qty, line.sale_min_qty, precision_rounding=rounding + ) + < 0 + ) + or False + ) + + @api.depends("product_id", "product_uom_qty", "sale_max_qty") + def _compute_is_qty_bigger_max_qty(self): + for line in self: + rounding = line.product_uom.rounding + product_qty = line._get_product_qty_in_product_unit() + line.is_qty_bigger_max_qty = ( + line.sale_max_qty + and ( + float_compare( + product_qty, line.sale_max_qty, precision_rounding=rounding + ) + > 0 + ) + or False + ) + + @api.depends("product_id", "product_uom_qty", "sale_multiple_qty") + def _compute_is_qty_not_multiple_qty(self): + for line in self: + product_qty = line.product_uom._compute_quantity( + line.product_uom_qty, line.product_id.uom_id + ) + line.is_qty_not_multiple_qty = ( + line.sale_multiple_qty > 0 and product_qty % line.sale_multiple_qty != 0 + ) + + def _get_sale_restricted_qty(self): + """Overridable function to change qty values (ex: form stock)""" + self.ensure_one() + res = { + "sale_min_qty": (self.product_id and self.product_id.sale_min_qty or 0), + "force_sale_min_qty": ( + self.product_id and self.product_id.force_sale_min_qty or False + ), + "sale_max_qty": (self.product_id and self.product_id.sale_max_qty or 0), + "force_sale_max_qty": ( + self.product_id and self.product_id.force_sale_max_qty or False + ), + "sale_multiple_qty": ( + self.product_id and self.product_id.sale_multiple_qty or 0 + ), + } + return res + + @api.depends("product_id") + def _compute_sale_restricted_qty(self): + for rec in self: + rec.update(rec._get_sale_restricted_qty()) diff --git a/sale_restricted_qty/readme/CONTRIBUTORS.rst b/sale_restricted_qty/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000000..bd4c1d61bef --- /dev/null +++ b/sale_restricted_qty/readme/CONTRIBUTORS.rst @@ -0,0 +1,8 @@ +* Mourad EL HADJ MIMOUN + +* `Ooops `_: + + * Ashish Hirpara +* `Aion Tech `_: + + * Simone Rubino diff --git a/sale_restricted_qty/readme/DESCRIPTION.rst b/sale_restricted_qty/readme/DESCRIPTION.rst new file mode 100644 index 00000000000..47ad576a40f --- /dev/null +++ b/sale_restricted_qty/readme/DESCRIPTION.rst @@ -0,0 +1,13 @@ +This module allows to define min, max and multiple order quantity on product. +Min and Max order quantity is either required or recommanded. +If you check "Force mini/max Qty" on product the min/max qty do not block sale +order. +This can be used if the available stock is less then the min qty +or if you want to sell sample products. +Max qty can be used if we dont want to sale more than available qty +(end of series product) + +Setings are defined on product, if values are not set we use settings from +product template. +If settings are not set on product template we use settings from +product category otherwise parent category. diff --git a/sale_restricted_qty/readme/USAGE.rst b/sale_restricted_qty/readme/USAGE.rst new file mode 100644 index 00000000000..5623152596f --- /dev/null +++ b/sale_restricted_qty/readme/USAGE.rst @@ -0,0 +1,7 @@ +#. Go to **Sales > Products > Product Variants** and Set "Min Sale Qty". + If you dont want block product sale if qty is less the "Min Sale Qty", + chek "Force Min Qty" +#. Create a sale order and add a sale order line with this product and check + if Qty is less then "Min Qty" A message in displayed "Min Qty Required" + Or "Min Qty Recommanded". Check if Min qty is required you can't + validate order. diff --git a/sale_restricted_qty/static/description/icon.png b/sale_restricted_qty/static/description/icon.png new file mode 100644 index 00000000000..3a0328b516c Binary files /dev/null and b/sale_restricted_qty/static/description/icon.png differ diff --git a/sale_restricted_qty/static/description/index.html b/sale_restricted_qty/static/description/index.html new file mode 100644 index 00000000000..5b4c747c076 --- /dev/null +++ b/sale_restricted_qty/static/description/index.html @@ -0,0 +1,461 @@ + + + + + + +Sale order min quantity + + + +
+

Sale order min quantity

+ + +

Beta License: AGPL-3 OCA/sale-workflow Translate me on Weblate Try me on Runboat

+

This module allows to define min, max and multiple order quantity on product. +Min and Max order quantity is either required or recommanded. +If you check “Force mini/max Qty” on product the min/max qty do not block sale +order. +This can be used if the available stock is less then the min qty +or if you want to sell sample products. +Max qty can be used if we dont want to sale more than available qty +(end of series product)

+

Setings are defined on product, if values are not set we use settings from +product template. +If settings are not set on product template we use settings from +product category otherwise parent category.

+

Table of contents

+ +
+

Usage

+
    +
  1. +
    Go to Sales > Products > Product Variants and Set “Min Sale Qty”.
    +
    If you dont want block product sale if qty is less the “Min Sale Qty”, +chek “Force Min Qty”
    +
    +
  2. +
  3. +
    Create a sale order and add a sale order line with this product and check
    +
    if Qty is less then “Min Qty” A message in displayed “Min Qty Required” +Or “Min Qty Recommanded”. Check if Min qty is required you can’t +validate order.
    +
    +
  4. +
+
+
+

Bug Tracker

+

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

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • Akretion
  • +
+
+
+

Contributors

+ +
+
+

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.

+

Current maintainer:

+

ashishhirapara

+

This module is part of the OCA/sale-workflow project on GitHub.

+

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

+
+
+
+ + diff --git a/sale_restricted_qty/tests/__init__.py b/sale_restricted_qty/tests/__init__.py new file mode 100644 index 00000000000..67709762e39 --- /dev/null +++ b/sale_restricted_qty/tests/__init__.py @@ -0,0 +1 @@ +from . import test_sale diff --git a/sale_restricted_qty/tests/test_sale.py b/sale_restricted_qty/tests/test_sale.py new file mode 100644 index 00000000000..d1e0aaa8ca8 --- /dev/null +++ b/sale_restricted_qty/tests/test_sale.py @@ -0,0 +1,189 @@ +# Copyright 2019 Akretion +# Update (Migration) 2022 Ooops - Ashish Hirpara +# Copyright 2023 Simone Rubino - Aion Tech +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import odoo.tests.common as common +from odoo.exceptions import ValidationError +from odoo.tests import tagged + + +@tagged("post_install", "-at_install") +class TestSaleOrderLineMinQty(common.TransactionCase): + def setUp(self): + super(TestSaleOrderLineMinQty, self).setUp() + + # Create models + self.sale_order_model = self.env["sale.order"] + self.sale_order_line_model = self.env["sale.order.line"] + self.partner_model = self.env["res.partner"] + self.product_categ_model = self.env["product.category"] + self.product_model = self.env["product.product"] + self.sale_order = self.sale_order_model + # Create partner and product + self.partner = self.partner_model.create({"name": "Test partner"}) + self.categ_parent = self.product_categ_model.create( + { + "name": "Test Parent categ", + "manual_sale_min_qty": 10.0, + "manual_force_sale_min_qty": "use_parent", + "manual_sale_max_qty": 100.0, + "manual_force_sale_max_qty": "use_parent", + "manual_sale_multiple_qty": 5.0, + } + ) + + self.categ = self.product_categ_model.create( + { + "name": "Test categ", + "parent_id": self.categ_parent.id, + "manual_force_sale_min_qty": "use_parent", + "manual_force_sale_max_qty": "use_parent", + } + ) + + self.product = self.product_model.create( + { + "name": "Test product", + "force_sale_min_qty": False, + "force_sale_max_qty": False, + } + ) + + def test_check_sale_order_min_qty_required(self): + line_values = {"product_id": self.product.id, "product_uom_qty": 5.0} + self.product.manual_sale_min_qty = 10 + # Create sale order line with Qty less than min Qty + with self.assertRaises(ValidationError): + self.sale_order_model.create( + { + "partner_id": self.partner.id, + "order_line": [(0, 0, line_values)], + "pricelist_id": 1, + } + ) + line_values["product_uom_qty"] = 12.0 + # Create sale order line with Qty great then min Qty + self.sale_order = self.sale_order_model.create( + {"partner_id": self.partner.id, "order_line": [(0, 0, line_values)]} + ) + self.sale_order.order_line._compute_sale_restricted_qty() + self.assertFalse(self.sale_order.order_line.is_qty_less_min_qty) + + self.assertEqual(self.sale_order.order_line.product_uom_qty, 12.0) + + def test_check_sale_order_min_qty_recommended(self): + line_values = {"product_id": self.product.id, "product_uom_qty": 5.0} + self.product.manual_sale_min_qty = 10 + # Set Force min Qty to true + self.product.manual_force_sale_min_qty = "force" + + # Create sale order line with Qty less than min Qty + self.sale_order = self.sale_order_model.create( + {"partner_id": self.partner.id, "order_line": [(0, 0, line_values)]} + ) + self.sale_order.order_line._compute_sale_restricted_qty() + self.assertTrue(self.sale_order.order_line.is_qty_less_min_qty) + + self.assertEqual(self.sale_order.order_line.product_uom_qty, 5.0) + + def test_check_sale_order_max_qty_required(self): + line_values = {"product_id": self.product.id, "product_uom_qty": 15.0} + self.product.manual_sale_max_qty = 10 + # Create sale order line with Qty bigger than max Qty + with self.assertRaises(ValidationError): + sale_order = self.sale_order_model.create( + {"partner_id": self.partner.id, "order_line": [(0, 0, line_values)]} + ) + sale_values = self.refrech_sale_values(sale_order) + self.sale_order_model.create(sale_values) + line_values["product_uom_qty"] = 2.0 + # Create sale order line with Qty great then max Qty + self.sale_order = self.sale_order_model.create( + {"partner_id": self.partner.id, "order_line": [(0, 0, line_values)]} + ) + self.sale_order.order_line._compute_sale_restricted_qty() + self.assertFalse(self.sale_order.order_line.is_qty_bigger_max_qty) + + self.assertEqual(self.sale_order.order_line.product_uom_qty, 2.0) + + def test_check_sale_order_max_qty_recommended(self): + line_values = {"product_id": self.product.id, "product_uom_qty": 15.0} + self.product.manual_sale_max_qty = 10 + # Set Force max Qty to true + self.product.manual_force_sale_max_qty = "force" + + # Create sale order line with Qty bigger than max Qty + self.sale_order = self.sale_order_model.create( + {"partner_id": self.partner.id, "order_line": [(0, 0, line_values)]} + ) + self.sale_order.order_line._compute_sale_restricted_qty() + self.assertTrue(self.sale_order.order_line.is_qty_bigger_max_qty) + + self.assertEqual(self.sale_order.order_line.product_uom_qty, 15.0) + + def test_check_sale_order_multiple_qty_required(self): + line_values = {"product_id": self.product.id, "product_uom_qty": 15.0} + self.product.manual_sale_min_qty = 10 + self.product.manual_sale_multiple_qty = 10 + # Create sale order line with Qty not multiple Qty + with self.assertRaises(ValidationError): + sale_order = self.sale_order_model.create( + {"partner_id": self.partner.id, "order_line": [(0, 0, line_values)]} + ) + sale_values = self.refrech_sale_values(sale_order) + self.sale_order_model.create(sale_values) + line_values["product_uom_qty"] = 20 + # Create sale order line with Qty multiple Qty + self.sale_order = self.sale_order_model.create( + {"partner_id": self.partner.id, "order_line": [(0, 0, line_values)]} + ) + self.sale_order.order_line._compute_sale_restricted_qty() + self.assertFalse(self.sale_order.order_line.is_qty_not_multiple_qty) + + self.assertEqual(self.sale_order.order_line.product_uom_qty, 20) + + def test_check_restricted_qty_category_hierarchy(self): + # Check Restricted Qty from parent category + self.product.categ_id = self.categ + self.assertEqual(self.product.manual_sale_min_qty, 0) + self.assertEqual(self.product.manual_sale_multiple_qty, 0) + self.product.categ_id.parent_id._compute_sale_restricted_qty() + + self.assertEqual(self.product.sale_min_qty, 10) + self.assertEqual(self.product.sale_max_qty, 100) + self.assertEqual(self.product.sale_multiple_qty, 5) + self.categ_parent.manual_force_sale_min_qty = "force" + self.assertEqual(self.product.manual_force_sale_min_qty, "use_parent") + self.assertEqual(self.product.force_sale_min_qty, True) + # Check Restricted Qty from category + self.categ.manual_sale_min_qty = 15 + self.categ.manual_sale_multiple_qty = 10 + self.categ.manual_force_sale_min_qty = "not_force" + self.assertEqual(self.product.sale_min_qty, 15) + self.assertEqual(self.product.sale_multiple_qty, 10) + self.assertEqual(self.product.force_sale_min_qty, False) + self.categ.manual_sale_max_qty = 200 + self.categ.manual_force_sale_max_qty = "not_force" + self.assertEqual(self.product.sale_max_qty, 200) + self.assertEqual(self.product.force_sale_max_qty, False) + + def test_check_restricted_qty_tmpl_hierarchy(self): + # Check Restricted from product template + self.product.product_tmpl_id.manual_sale_min_qty = 20 + self.product.product_tmpl_id.manual_sale_max_qty = 250 + self.product.product_tmpl_id.manual_sale_multiple_qty = 30 + self.product.product_tmpl_id._compute_sale_restricted_qty() + self.assertEqual(self.product.manual_sale_min_qty, 0) + self.assertEqual(self.product.sale_min_qty, 20) + self.assertEqual(self.product.manual_sale_max_qty, 0) + self.assertEqual(self.product.sale_max_qty, 250) + self.assertEqual(self.product.manual_sale_multiple_qty, 0) + self.assertEqual(self.product.sale_multiple_qty, 30) + # Check Restricted Qty from product + self.product.manual_sale_min_qty = 25 + self.product.manual_sale_max_qty = 150 + self.product.manual_sale_multiple_qty = 25 + self.assertEqual(self.product.sale_min_qty, 25) + self.assertEqual(self.product.sale_max_qty, 150) + self.assertEqual(self.product.sale_multiple_qty, 25) diff --git a/sale_restricted_qty/views/product_category_views.xml b/sale_restricted_qty/views/product_category_views.xml new file mode 100644 index 00000000000..41d857c5c7f --- /dev/null +++ b/sale_restricted_qty/views/product_category_views.xml @@ -0,0 +1,58 @@ + + + + product.category + + + + + + + + + + + + + + + + + + diff --git a/sale_restricted_qty/views/product_product_views.xml b/sale_restricted_qty/views/product_product_views.xml new file mode 100644 index 00000000000..21dca704f45 --- /dev/null +++ b/sale_restricted_qty/views/product_product_views.xml @@ -0,0 +1,64 @@ + + + + + + product.product.form + product.product + + + + + + + + + + + + + + + + + + diff --git a/sale_restricted_qty/views/product_template_views.xml b/sale_restricted_qty/views/product_template_views.xml new file mode 100644 index 00000000000..fd49ebffe74 --- /dev/null +++ b/sale_restricted_qty/views/product_template_views.xml @@ -0,0 +1,60 @@ + + + + + product.template + + + + + + + + + + + + + + + + + + + diff --git a/sale_restricted_qty/views/sale_views.xml b/sale_restricted_qty/views/sale_views.xml new file mode 100644 index 00000000000..cae2196f01b --- /dev/null +++ b/sale_restricted_qty/views/sale_views.xml @@ -0,0 +1,93 @@ + + + + + sale.order + + + + + + + + + + + + + + + + + + + + + + + + is_qty_less_min_qty == True and force_sale_min_qty == False + is_qty_less_min_qty == True and force_sale_min_qty == True + is_qty_bigger_max_qty == True and force_sale_max_qty == False + is_qty_bigger_max_qty == True and force_sale_max_qty == True + is_qty_not_multiple_qty == True + + + + diff --git a/setup/sale_restricted_qty/odoo/addons/sale_restricted_qty b/setup/sale_restricted_qty/odoo/addons/sale_restricted_qty new file mode 120000 index 00000000000..9f1a71654a9 --- /dev/null +++ b/setup/sale_restricted_qty/odoo/addons/sale_restricted_qty @@ -0,0 +1 @@ +../../../../sale_restricted_qty \ No newline at end of file diff --git a/setup/sale_restricted_qty/setup.py b/setup/sale_restricted_qty/setup.py new file mode 100644 index 00000000000..28c57bb6403 --- /dev/null +++ b/setup/sale_restricted_qty/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)