diff --git a/product_pricelist_supplierinfo/README.rst b/product_pricelist_supplierinfo/README.rst new file mode 100644 index 00000000000..556ebd5dbe9 --- /dev/null +++ b/product_pricelist_supplierinfo/README.rst @@ -0,0 +1,157 @@ +======================================== +Supplier info prices in sales pricelists +======================================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:e6539df59b27f0932ee4afb66ee75503be8c81c9ec41fd11623a5abcfca59e9c + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fproduct--attribute-lightgray.png?logo=github + :target: https://github.com/OCA/product-attribute/tree/17.0/product_pricelist_supplierinfo + :alt: OCA/product-attribute +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/product-attribute-17-0/product-attribute-17-0-product_pricelist_supplierinfo + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/product-attribute&target_branch=17.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows you to create a sales pricelist based on product +supplierinfo prices. If you want, you can bypass minimum quantity in +pricelist item. + +We can also define sale marging applied on purchase price directly on +supplier info. For this, you must add users to "Show sale margin on +Product Supplierinfo" group. + +**Table of contents** + +.. contents:: + :local: + +Installation +============ + +Although this module doesn't depend technically on **Sales Management**, +you must install it for configuring and seeing the effects of it. + +Configuration +============= + +To configure pricelists with the new feature of this module, you need +to: + +1. Go to *Sales > Configuration > Settings* and check "Pricelists" + option and "Advanced price rules (discounts, formulas)" after that. + You must have correct permissions and you must install **Sales + Management** app (sale) and **Purchase** app to see these settings. +2. Create or edit a Sales Pricelist at *Sales > Products > Pricelists*. +3. Add or edit a pricelist item and check "Formula" option in "Price + Computation" section. +4. You will see the new option "Prices based on supplier info". +5. If you want to bypass the "Min.Quantity" field of the supplier info + and always select the lowest quantity price, check the option "Ignore + Supplier Info Min. Quantity". + +Usage +===== + +For adding supplier info: + +1. Go to *Sales > Products > Products* +2. Open or create a product. +3. Go to "Purchase" page. +4. On "Vendors" section, add the supplier and prices. +5. You can drag and drop for reordering these lines. + +Check the remark in known issues about the supplier info line selection. + +For checking pricelists in action, you can (with sale module installed): + +1. Go to *Sales > Orders > Quotations* +2. Create or edit a quotation. +3. Add a line. +4. Select a product with the criteria to match the pricelist from + supplier info. +5. See the proper price appears in the line. + +Known issues / Roadmap +====================== + +- First line that matches by minimum quantity criteria, independently + from the supplier, will be the one that provides the price for the + pricelist. +- There's no mechanism for selecting the supplier from possible sources + like sales orders. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Tecnativa +* Vauxoo + +Contributors +------------ + +- `Tecnativa `__: + + - Vicent Cubells + - Pedro M. Baeza + - Carlos Roca + +- Nikul Chaudhary +- `TAKOBI `__: + + - Lorenzo Battistini + +- Andrea Gidalti + +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-luisg123v| image:: https://github.com/luisg123v.png?size=40px + :target: https://github.com/luisg123v + :alt: luisg123v + +Current `maintainer `__: + +|maintainer-luisg123v| + +This module is part of the `OCA/product-attribute `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/product_pricelist_supplierinfo/__init__.py b/product_pricelist_supplierinfo/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/product_pricelist_supplierinfo/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/product_pricelist_supplierinfo/__manifest__.py b/product_pricelist_supplierinfo/__manifest__.py new file mode 100644 index 00000000000..cf43b8bb15c --- /dev/null +++ b/product_pricelist_supplierinfo/__manifest__.py @@ -0,0 +1,20 @@ +# Copyright 2018 Tecnativa - Vicent Cubells +# Copyright 2018 Tecnativa - Pedro M. Baeza +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +{ + "name": "Supplier info prices in sales pricelists", + "summary": "Allows to create priceslists based on supplier info", + "version": "17.0.1.0.0", + "category": "Sales/Sales", + "website": "https://github.com/OCA/product-attribute", + "author": "Tecnativa, Odoo Community Association (OCA), Vauxoo", + "maintainers": ["luisg123v"], + "license": "AGPL-3", + "depends": ["product"], + "data": [ + "security/res_groups.xml", + "views/product_pricelist_item_views.xml", + "views/product_supplierinfo_view.xml", + ], + "installable": True, +} diff --git a/product_pricelist_supplierinfo/i18n/ca.po b/product_pricelist_supplierinfo/i18n/ca.po new file mode 100644 index 00000000000..d91135d1d7b --- /dev/null +++ b/product_pricelist_supplierinfo/i18n/ca.po @@ -0,0 +1,138 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_pricelist_supplierinfo +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2021-02-15 17:45+0000\n" +"Last-Translator: claudiagn \n" +"Language-Team: none\n" +"Language: ca\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.3.2\n" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,help:product_pricelist_supplierinfo.field_product_pricelist_item__base +msgid "" +"Base price for computation.\n" +"Sales Price: The base price will be the Sales Price.\n" +"Cost Price : The base price will be the cost price.\n" +"Other Pricelist : Computation of the base price based on another Pricelist." +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_pricelist_item__base +msgid "Based on" +msgstr "Basat en" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_pricelist_item__no_supplierinfo_min_quantity +msgid "Ignore Supplier Info Min. Quantity" +msgstr "Ignora la informació del proveïdor Min. Quantitat" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,help:product_pricelist_supplierinfo.field_product_supplierinfo__sale_margin +msgid "Margin to apply on price to obtain sale price" +msgstr "Marge a aplicar sobre el preu per obtenir el preu de venda" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,help:product_pricelist_supplierinfo.field_product_pricelist_item__filter_supplier_id +msgid "Only match prices from the selected supplier" +msgstr "Coincideix només amb els preus del proveïdor seleccionat" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_pricelist_item +msgid "Pricelist Rule" +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields.selection,name:product_pricelist_supplierinfo.selection__product_pricelist_item__base__supplierinfo +msgid "Prices based on supplier info" +msgstr "Preu basat en la informació del proveedor" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_template +msgid "Product" +msgstr "Producte" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_product +msgid "Product Variant" +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_supplierinfo__sale_margin +msgid "Sale Margin" +msgstr "Marge de vendes" + +#. module: product_pricelist_supplierinfo +#: model_terms:ir.ui.view,arch_db:product_pricelist_supplierinfo.product_supplierinfo_tree_view +msgid "Sale margin" +msgstr "Marge de venda" + +#. module: product_pricelist_supplierinfo +#: model:res.groups,name:product_pricelist_supplierinfo.group_supplierinfo_pricelist_sale_margin +msgid "Show sale margin on Product Supplierinfo" +msgstr "Mostra el marge de venda a la informació del proveïdor de productes" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_supplierinfo +msgid "Supplier Pricelist" +msgstr "Tarifa de proveedor" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_pricelist_item__filter_supplier_id +msgid "Supplier filter" +msgstr "Filtre de proveïdor" + +#~ msgid "Pricelist" +#~ msgstr "Tarifa" + +#~ msgid "" +#~ "Supplier " +#~ "price - " +#~ msgstr "" +#~ "Preu de " +#~ "proveïdor - " + +#~ msgid "" +#~ "Base price for computation.\n" +#~ "Public Price: The base price will be the Sale/public Price.\n" +#~ "Cost Price : The base price will be the cost price.\n" +#~ "Other Pricelist : Computation of the base price based on another " +#~ "Pricelist." +#~ msgstr "" +#~ "Preu base de càlcul.\n" +#~ "Preu públic: el preu base serà el preu de venda / públic.\n" +#~ "Preu de cost: el preu base serà el preu de cost.\n" +#~ "Una altra llista de preus: càlcul del preu base basat en una altra llista " +#~ "de preus." + +#~ msgid "Cost" +#~ msgstr "Cost" + +#~ msgid "Cost Price Tax Included" +#~ msgstr "Preu de cost impost inclòs" + +#~ msgid "Other Price" +#~ msgstr "Altre preu" + +#~ msgid "Other Pricelist" +#~ msgstr "Altra tarifa" + +#~ msgid "Partner Prices on the product form" +#~ msgstr "Preus de soci al formulari de producte" + +#~ msgid "Pricelist Item" +#~ msgstr "Element de tarifa" + +#~ msgid "Product Template" +#~ msgstr "Plantilla de producte" + +#~ msgid "Public Price" +#~ msgstr "Preu públic" diff --git a/product_pricelist_supplierinfo/i18n/es.po b/product_pricelist_supplierinfo/i18n/es.po new file mode 100644 index 00000000000..555d40852a4 --- /dev/null +++ b/product_pricelist_supplierinfo/i18n/es.po @@ -0,0 +1,145 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_pricelist_supplierinfo +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-10-31 17:35+0000\n" +"PO-Revision-Date: 2023-08-29 08:30+0000\n" +"Last-Translator: Ivorra78 \n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,help:product_pricelist_supplierinfo.field_product_pricelist_item__base +msgid "" +"Base price for computation.\n" +"Sales Price: The base price will be the Sales Price.\n" +"Cost Price : The base price will be the cost price.\n" +"Other Pricelist : Computation of the base price based on another Pricelist." +msgstr "" +"Precio base para el cómputo.\n" +"Precio de Venta: El precio base será el Precio de Venta.\n" +"Precio de Costo: El precio base será el precio de costo.\n" +"Otra Lista de Precios: Cálculo del precio base en base a otra Lista de " +"Precios." + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_pricelist_item__base +msgid "Based on" +msgstr "Basado en" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_pricelist_item__no_supplierinfo_min_quantity +msgid "Ignore Supplier Info Min. Quantity" +msgstr "Ignorar cantidad mínima de la info de proveedor" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,help:product_pricelist_supplierinfo.field_product_supplierinfo__sale_margin +msgid "Margin to apply on price to obtain sale price" +msgstr "Margen a aplicar sobre el precio para obtener precio de venta" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,help:product_pricelist_supplierinfo.field_product_pricelist_item__filter_supplier_id +msgid "Only match prices from the selected supplier" +msgstr "Igualar sólo los precios del proveedor seleccionado" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_pricelist_item +msgid "Pricelist Rule" +msgstr "Regla de la lista de precios" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields.selection,name:product_pricelist_supplierinfo.selection__product_pricelist_item__base__supplierinfo +msgid "Prices based on supplier info" +msgstr "Precios basados en la información del proveedor" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_template +msgid "Product" +msgstr "Producto" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_product +msgid "Product Variant" +msgstr "Variante del producto" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_supplierinfo__sale_margin +msgid "Sale Margin" +msgstr "Margen de venta" + +#. module: product_pricelist_supplierinfo +#: model_terms:ir.ui.view,arch_db:product_pricelist_supplierinfo.product_supplierinfo_tree_view +msgid "Sale margin" +msgstr "Margen de venta" + +#. module: product_pricelist_supplierinfo +#: model:res.groups,name:product_pricelist_supplierinfo.group_supplierinfo_pricelist_sale_margin +msgid "Show sale margin on Product Supplierinfo" +msgstr "Mostrar margen de venta en Producto Proveedorinfo" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_supplierinfo +msgid "Supplier Pricelist" +msgstr "Lista de precios de proveedor" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_pricelist_item__filter_supplier_id +msgid "Supplier filter" +msgstr "Filtro de Proveedor" + +#~ msgid "Pricelist" +#~ msgstr "Tarifa" + +#~ msgid "" +#~ "Supplier " +#~ "price - " +#~ msgstr "" +#~ "Precio de " +#~ "proveedor - " + +#~ msgid "" +#~ "Base price for computation.\n" +#~ "Public Price: The base price will be the Sale/public Price.\n" +#~ "Cost Price : The base price will be the cost price.\n" +#~ "Other Pricelist : Computation of the base price based on another " +#~ "Pricelist." +#~ msgstr "" +#~ "Precio base de cálculo.\n" +#~ "Precio Público: El precio base será el Precio Público / Venta.\n" +#~ "Precio de costo: El precio base será el precio de costo.\n" +#~ "Otra lista de precios: cálculo del precio base basado en otra lista de " +#~ "precios." + +#~ msgid "Cost" +#~ msgstr "Coste" + +#~ msgid "Cost Price Tax Included" +#~ msgstr "Precio de coste con impuesto incluido" + +#~ msgid "Other Price" +#~ msgstr "Otro precio" + +#~ msgid "Other Pricelist" +#~ msgstr "Otras tarifas" + +#~ msgid "Partner Prices on the product form" +#~ msgstr "Precios de socios en el formulario de producto" + +#, fuzzy +#~ msgid "Pricelist Item" +#~ msgstr "Item de Lista de precios" + +#~ msgid "Product Template" +#~ msgstr "Plantilla de producto" + +#~ msgid "Public Price" +#~ msgstr "Precio público" diff --git a/product_pricelist_supplierinfo/i18n/fr.po b/product_pricelist_supplierinfo/i18n/fr.po new file mode 100644 index 00000000000..5a9b7b182fb --- /dev/null +++ b/product_pricelist_supplierinfo/i18n/fr.po @@ -0,0 +1,140 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_pricelist_supplierinfo +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2020-10-08 15:16+0000\n" +"Last-Translator: Yann Papouin \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 3.10\n" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,help:product_pricelist_supplierinfo.field_product_pricelist_item__base +msgid "" +"Base price for computation.\n" +"Sales Price: The base price will be the Sales Price.\n" +"Cost Price : The base price will be the cost price.\n" +"Other Pricelist : Computation of the base price based on another Pricelist." +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_pricelist_item__base +msgid "Based on" +msgstr "Basée sur" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_pricelist_item__no_supplierinfo_min_quantity +msgid "Ignore Supplier Info Min. Quantity" +msgstr "Ignorer le champ Quantité minimale" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,help:product_pricelist_supplierinfo.field_product_supplierinfo__sale_margin +msgid "Margin to apply on price to obtain sale price" +msgstr "Marge à appliquer pour obtenir le prix de vente" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,help:product_pricelist_supplierinfo.field_product_pricelist_item__filter_supplier_id +msgid "Only match prices from the selected supplier" +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_pricelist_item +msgid "Pricelist Rule" +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields.selection,name:product_pricelist_supplierinfo.selection__product_pricelist_item__base__supplierinfo +msgid "Prices based on supplier info" +msgstr "Section Achats/Fournisseurs de la fiche produit" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_template +msgid "Product" +msgstr "Article" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_product +msgid "Product Variant" +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_supplierinfo__sale_margin +msgid "Sale Margin" +msgstr "Marge à la revente" + +#. module: product_pricelist_supplierinfo +#: model_terms:ir.ui.view,arch_db:product_pricelist_supplierinfo.product_supplierinfo_tree_view +msgid "Sale margin" +msgstr "Marge à la revente" + +#. module: product_pricelist_supplierinfo +#: model:res.groups,name:product_pricelist_supplierinfo.group_supplierinfo_pricelist_sale_margin +msgid "Show sale margin on Product Supplierinfo" +msgstr "" +"Afficher la marge commerciale dans la section Achats/Fournisseurs de la " +"fiche produit" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_supplierinfo +msgid "Supplier Pricelist" +msgstr "Liste de prix du fournisseur" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_pricelist_item__filter_supplier_id +msgid "Supplier filter" +msgstr "" + +#~ msgid "Pricelist" +#~ msgstr "Liste de prix" + +#~ msgid "" +#~ "Supplier " +#~ "price - " +#~ msgstr "" +#~ "Prix " +#~ "fournisseur - " + +#~ msgid "" +#~ "Base price for computation.\n" +#~ "Public Price: The base price will be the Sale/public Price.\n" +#~ "Cost Price : The base price will be the cost price.\n" +#~ "Other Pricelist : Computation of the base price based on another " +#~ "Pricelist." +#~ msgstr "" +#~ "Prix de base pour le calcul.\n" +#~ "Prix public : le prix de base sera le prix de vente/prix public.\n" +#~ "Prix de revient : le prix de base sera le prix de revient.\n" +#~ "Autre liste de prix : calcul du prix de base, basé sur une autre liste de " +#~ "prix." + +#~ msgid "Cost" +#~ msgstr "Coût" + +#~ msgid "Cost Price Tax Included" +#~ msgstr "Coût de revient taxes comprises" + +#~ msgid "Other Price" +#~ msgstr "Autre prix" + +#~ msgid "Other Pricelist" +#~ msgstr "Autre liste de prix" + +#~ msgid "Partner Prices on the product form" +#~ msgstr "Prix fournisseurs sur la fiche produit" + +#~ msgid "Pricelist Item" +#~ msgstr "Élément de la liste de prix" + +#~ msgid "Product Template" +#~ msgstr "Modèle de produit" + +#~ msgid "Public Price" +#~ msgstr "Prix public" diff --git a/product_pricelist_supplierinfo/i18n/it.po b/product_pricelist_supplierinfo/i18n/it.po new file mode 100644 index 00000000000..4639e7d76f6 --- /dev/null +++ b/product_pricelist_supplierinfo/i18n/it.po @@ -0,0 +1,140 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_pricelist_supplierinfo +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-10-29 13:26+0000\n" +"Last-Translator: mymage \n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,help:product_pricelist_supplierinfo.field_product_pricelist_item__base +msgid "" +"Base price for computation.\n" +"Sales Price: The base price will be the Sales Price.\n" +"Cost Price : The base price will be the cost price.\n" +"Other Pricelist : Computation of the base price based on another Pricelist." +msgstr "" +"Prezzo base per il calcolo.\n" +"Prezzo di vendita: il prezzo base sarà il prezzo di vendita.\n" +"Prezzo di costo: il prezzo base sarà il prezzo di costo.\n" +"Altri listini prezzi: il calcolo del prezzo base sarà basato su un altro " +"listino prezzi." + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_pricelist_item__base +msgid "Based on" +msgstr "Basato su" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_pricelist_item__no_supplierinfo_min_quantity +msgid "Ignore Supplier Info Min. Quantity" +msgstr "Ignorare la quantità min del listino fornitore" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,help:product_pricelist_supplierinfo.field_product_supplierinfo__sale_margin +msgid "Margin to apply on price to obtain sale price" +msgstr "Margine da applicare per ottenere il prezzo di vendita" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,help:product_pricelist_supplierinfo.field_product_pricelist_item__filter_supplier_id +msgid "Only match prices from the selected supplier" +msgstr "Solo prezzi corrispondenti dal fornitore selezionato" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_pricelist_item +msgid "Pricelist Rule" +msgstr "Regola listino prezzi" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields.selection,name:product_pricelist_supplierinfo.selection__product_pricelist_item__base__supplierinfo +msgid "Prices based on supplier info" +msgstr "Prezzi basati su listino fornitore" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_template +msgid "Product" +msgstr "Prodotto" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_product +msgid "Product Variant" +msgstr "Variante prodotto" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_supplierinfo__sale_margin +msgid "Sale Margin" +msgstr "Margine di vendita" + +#. module: product_pricelist_supplierinfo +#: model_terms:ir.ui.view,arch_db:product_pricelist_supplierinfo.product_supplierinfo_tree_view +msgid "Sale margin" +msgstr "Margine di vendita" + +#. module: product_pricelist_supplierinfo +#: model:res.groups,name:product_pricelist_supplierinfo.group_supplierinfo_pricelist_sale_margin +msgid "Show sale margin on Product Supplierinfo" +msgstr "Visualizza margine di vendita sulle informazioni fornitore prodotto" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_supplierinfo +msgid "Supplier Pricelist" +msgstr "Listino prezzi fornitore" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_pricelist_item__filter_supplier_id +msgid "Supplier filter" +msgstr "Filtro fornitore" + +#~ msgid "Pricelist" +#~ msgstr "Listino prezzi" + +#~ msgid "" +#~ "Supplier " +#~ "price - " +#~ msgstr "" +#~ "Prezzo " +#~ "fornitore - " + +#~ msgid "" +#~ "Base price for computation.\n" +#~ "Public Price: The base price will be the Sale/public Price.\n" +#~ "Cost Price : The base price will be the cost price.\n" +#~ "Other Pricelist : Computation of the base price based on another " +#~ "Pricelist." +#~ msgstr "" +#~ "Prezzo base per il calcolo.\n" +#~ "Prezzo pubblico: il prezzo base sarà il prezzo di vendita / pubblico.\n" +#~ "Prezzo di costo: il prezzo base sarà il prezzo di costo.\n" +#~ "Altro listino: calcolo del prezzo base basato su un altro listino." + +#~ msgid "Cost" +#~ msgstr "Costo" + +#, fuzzy +#~ msgid "Other Price" +#~ msgstr "Altro listino" + +#~ msgid "Other Pricelist" +#~ msgstr "Altro listino" + +#~ msgid "Partner Prices on the product form" +#~ msgstr "Prezzi partner nella scheda prodotto" + +#~ msgid "Pricelist Item" +#~ msgstr "Articolo listino prezzi" + +#~ msgid "Product Template" +#~ msgstr "Modello prodotto" + +#~ msgid "Public Price" +#~ msgstr "Prezzo pubblico" diff --git a/product_pricelist_supplierinfo/i18n/nl.po b/product_pricelist_supplierinfo/i18n/nl.po new file mode 100644 index 00000000000..1fe7d46c31a --- /dev/null +++ b/product_pricelist_supplierinfo/i18n/nl.po @@ -0,0 +1,142 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_pricelist_supplierinfo +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2021-01-24 18:44+0000\n" +"Last-Translator: Bosd \n" +"Language-Team: none\n" +"Language: nl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.3.2\n" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,help:product_pricelist_supplierinfo.field_product_pricelist_item__base +msgid "" +"Base price for computation.\n" +"Sales Price: The base price will be the Sales Price.\n" +"Cost Price : The base price will be the cost price.\n" +"Other Pricelist : Computation of the base price based on another Pricelist." +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_pricelist_item__base +msgid "Based on" +msgstr "Gebaseerd op" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_pricelist_item__no_supplierinfo_min_quantity +msgid "Ignore Supplier Info Min. Quantity" +msgstr "Negeer leveranciers info Minimum aantal" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,help:product_pricelist_supplierinfo.field_product_supplierinfo__sale_margin +msgid "Margin to apply on price to obtain sale price" +msgstr "" +"Marge om toe te passen op de prijs voor de berekening van de verkoopsprijs" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,help:product_pricelist_supplierinfo.field_product_pricelist_item__filter_supplier_id +#, fuzzy +msgid "Only match prices from the selected supplier" +msgstr "Alleen prijzen vergelijken van de geselecteerde leverancier" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_pricelist_item +msgid "Pricelist Rule" +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields.selection,name:product_pricelist_supplierinfo.selection__product_pricelist_item__base__supplierinfo +msgid "Prices based on supplier info" +msgstr "Prijzen gebaseerd op leveranciers info" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_template +msgid "Product" +msgstr "Product" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_product +msgid "Product Variant" +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_supplierinfo__sale_margin +msgid "Sale Margin" +msgstr "Verkoopsmarge" + +#. module: product_pricelist_supplierinfo +#: model_terms:ir.ui.view,arch_db:product_pricelist_supplierinfo.product_supplierinfo_tree_view +msgid "Sale margin" +msgstr "Verkoopsmarge" + +#. module: product_pricelist_supplierinfo +#: model:res.groups,name:product_pricelist_supplierinfo.group_supplierinfo_pricelist_sale_margin +#, fuzzy +msgid "Show sale margin on Product Supplierinfo" +msgstr "Weergave van verkoop marge op products leveranciersinfo" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_supplierinfo +msgid "Supplier Pricelist" +msgstr "Leveranciers Prijslijst" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_pricelist_item__filter_supplier_id +msgid "Supplier filter" +msgstr "Leveranciersfilter" + +#~ msgid "" +#~ "Supplier " +#~ "price - " +#~ msgstr "" +#~ "Leveranciers prijs - " + +#~ msgid "" +#~ "Base price for computation.\n" +#~ "Public Price: The base price will be the Sale/public Price.\n" +#~ "Cost Price : The base price will be the cost price.\n" +#~ "Other Pricelist : Computation of the base price based on another " +#~ "Pricelist." +#~ msgstr "" +#~ "Basis prijs voor de berekening.\n" +#~ "Publieke Prijs: Als basisprijs zal de verkoop/publieke prijs gebruikt " +#~ "worden.\n" +#~ "Kostprijs : Als basisprijs zal de kostprijs gebruikt worden.\n" +#~ "Andere Prijslijst : Berekening van de basisprijs gebaseerd op een andere " +#~ "prijslijst." + +#~ msgid "Cost" +#~ msgstr "Kost" + +#~ msgid "Cost Price Tax Included" +#~ msgstr "Kostprijs inclusief belasting" + +#~ msgid "Other Price" +#~ msgstr "Andere prijs" + +#~ msgid "Other Pricelist" +#~ msgstr "Andere Prijslijst" + +#~ msgid "Partner Prices on the product form" +#~ msgstr "Partner's prijs van het product formulier" + +#~ msgid "Pricelist" +#~ msgstr "Prijslijst" + +#~ msgid "Pricelist Item" +#~ msgstr "Prijslijst item" + +#~ msgid "Product Template" +#~ msgstr "Product sjabloon" + +#~ msgid "Public Price" +#~ msgstr "Publieke prijs" diff --git a/product_pricelist_supplierinfo/i18n/product_pricelist_supplierinfo.pot b/product_pricelist_supplierinfo/i18n/product_pricelist_supplierinfo.pot new file mode 100644 index 00000000000..85508b21e52 --- /dev/null +++ b/product_pricelist_supplierinfo/i18n/product_pricelist_supplierinfo.pot @@ -0,0 +1,88 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_pricelist_supplierinfo +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,help:product_pricelist_supplierinfo.field_product_pricelist_item__base +msgid "" +"Base price for computation.\n" +"Sales Price: The base price will be the Sales Price.\n" +"Cost Price : The base price will be the cost price.\n" +"Other Pricelist : Computation of the base price based on another Pricelist." +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_pricelist_item__base +msgid "Based on" +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_pricelist_item__no_supplierinfo_min_quantity +msgid "Ignore Supplier Info Min. Quantity" +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,help:product_pricelist_supplierinfo.field_product_supplierinfo__sale_margin +msgid "Margin to apply on price to obtain sale price" +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,help:product_pricelist_supplierinfo.field_product_pricelist_item__filter_supplier_id +msgid "Only match prices from the selected supplier" +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_pricelist_item +msgid "Pricelist Rule" +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields.selection,name:product_pricelist_supplierinfo.selection__product_pricelist_item__base__supplierinfo +msgid "Prices based on supplier info" +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_template +msgid "Product" +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_product +msgid "Product Variant" +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_supplierinfo__sale_margin +msgid "Sale Margin" +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model_terms:ir.ui.view,arch_db:product_pricelist_supplierinfo.product_supplierinfo_tree_view +msgid "Sale margin" +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:res.groups,name:product_pricelist_supplierinfo.group_supplierinfo_pricelist_sale_margin +msgid "Show sale margin on Product Supplierinfo" +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_supplierinfo +msgid "Supplier Pricelist" +msgstr "" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_pricelist_item__filter_supplier_id +msgid "Supplier filter" +msgstr "" diff --git a/product_pricelist_supplierinfo/i18n/pt_BR.po b/product_pricelist_supplierinfo/i18n/pt_BR.po new file mode 100644 index 00000000000..2b47e686644 --- /dev/null +++ b/product_pricelist_supplierinfo/i18n/pt_BR.po @@ -0,0 +1,96 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_pricelist_supplierinfo +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-10-28 21:26+0000\n" +"Last-Translator: Adriano Prado \n" +"Language-Team: none\n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,help:product_pricelist_supplierinfo.field_product_pricelist_item__base +msgid "" +"Base price for computation.\n" +"Sales Price: The base price will be the Sales Price.\n" +"Cost Price : The base price will be the cost price.\n" +"Other Pricelist : Computation of the base price based on another Pricelist." +msgstr "" +"Preço base para cálculo.\n" +"Preço de Venda: O preço base será o Preço de Venda.\n" +"Preço de custo: O preço base será o preço de custo.\n" +"Outra Lista de Preços: Cálculo do preço base com base em outra Lista de " +"Preços." + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_pricelist_item__base +msgid "Based on" +msgstr "Baseado Em" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_pricelist_item__no_supplierinfo_min_quantity +msgid "Ignore Supplier Info Min. Quantity" +msgstr "Ignorar informações mínimas do fornecedor. Quantidade" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,help:product_pricelist_supplierinfo.field_product_supplierinfo__sale_margin +msgid "Margin to apply on price to obtain sale price" +msgstr "Margem a aplicar sobre o preço para obter o preço de venda" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,help:product_pricelist_supplierinfo.field_product_pricelist_item__filter_supplier_id +msgid "Only match prices from the selected supplier" +msgstr "Combine apenas os preços do fornecedor selecionado" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_pricelist_item +msgid "Pricelist Rule" +msgstr "Regra Lista de Preço" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields.selection,name:product_pricelist_supplierinfo.selection__product_pricelist_item__base__supplierinfo +msgid "Prices based on supplier info" +msgstr "Preços baseados em informações do fornecedor" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_template +msgid "Product" +msgstr "Produto" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_product +msgid "Product Variant" +msgstr "Variante do produto" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_supplierinfo__sale_margin +msgid "Sale Margin" +msgstr "Margem de Venda" + +#. module: product_pricelist_supplierinfo +#: model_terms:ir.ui.view,arch_db:product_pricelist_supplierinfo.product_supplierinfo_tree_view +msgid "Sale margin" +msgstr "Margem de venda" + +#. module: product_pricelist_supplierinfo +#: model:res.groups,name:product_pricelist_supplierinfo.group_supplierinfo_pricelist_sale_margin +msgid "Show sale margin on Product Supplierinfo" +msgstr "Mostrar margem de venda nas informações do fornecedor do produto" + +#. module: product_pricelist_supplierinfo +#: model:ir.model,name:product_pricelist_supplierinfo.model_product_supplierinfo +msgid "Supplier Pricelist" +msgstr "Lista de Preço Fornecedor" + +#. module: product_pricelist_supplierinfo +#: model:ir.model.fields,field_description:product_pricelist_supplierinfo.field_product_pricelist_item__filter_supplier_id +msgid "Supplier filter" +msgstr "Filtro Fornecedor" diff --git a/product_pricelist_supplierinfo/models/__init__.py b/product_pricelist_supplierinfo/models/__init__.py new file mode 100644 index 00000000000..c4e59fd136d --- /dev/null +++ b/product_pricelist_supplierinfo/models/__init__.py @@ -0,0 +1,6 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import product_supplierinfo +from . import product_pricelist_item +from . import product_product +from . import product_template diff --git a/product_pricelist_supplierinfo/models/product_pricelist_item.py b/product_pricelist_supplierinfo/models/product_pricelist_item.py new file mode 100644 index 00000000000..c490d920df0 --- /dev/null +++ b/product_pricelist_supplierinfo/models/product_pricelist_item.py @@ -0,0 +1,33 @@ +# Copyright 2018 Tecnativa - Vicent Cubells +# Copyright 2018 Tecnativa - Pedro M. Baeza +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class ProductPricelistItem(models.Model): + _inherit = "product.pricelist.item" + + base = fields.Selection( + selection_add=[("supplierinfo", "Prices based on supplier info")], + ondelete={"supplierinfo": "set default"}, + ) + no_supplierinfo_min_quantity = fields.Boolean( + string="Ignore Supplier Info Min. Quantity", + ) + filter_supplier_id = fields.Many2one( + comodel_name="res.partner", + string="Supplier filter", + help="Only match prices from the selected supplier", + ) + + def _compute_price(self, product, quantity, uom, date, currency=None): + result = super()._compute_price(product, quantity, uom, date, currency) + context = self.env.context + if self.compute_price == "formula" and self.base == "supplierinfo": + result = product.sudo()._get_supplierinfo_pricelist_price( + self, + date=date or context.get("date", fields.Date.today()), + quantity=quantity, + ) + return result diff --git a/product_pricelist_supplierinfo/models/product_product.py b/product_pricelist_supplierinfo/models/product_product.py new file mode 100644 index 00000000000..fcac5c2fbc6 --- /dev/null +++ b/product_pricelist_supplierinfo/models/product_product.py @@ -0,0 +1,43 @@ +# Copyright 2018 Tecnativa - Vicent Cubells +# Copyright 2018 Tecnativa - Pedro M. Baeza +# Copyright 2019 Tecnativa - Carlos Dauden +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import models + + +class ProductProduct(models.Model): + _inherit = "product.product" + + def _prepare_sellers(self, params=False): + """When we override min qty we want that _select_sellers gives us the + first possible seller for every other criteria ignoring the quantity. As + supplierinfos are sorted by min_qty descending, we want to revert such + order so we get the very first one, which is probably the one to go. + """ + sellers = super()._prepare_sellers(params) + if self.env.context.get("override_min_qty"): + sellers = sellers.sorted("min_qty") + return sellers + + def _get_supplierinfo_pricelist_price(self, rule, date=None, quantity=None): + return self.product_tmpl_id._get_supplierinfo_pricelist_price( + rule, date=date, quantity=quantity, product_id=self.id + ) + + def _price_compute( + self, price_type, uom=None, currency=None, company=None, date=False + ): + """Return dummy not falsy prices when computation is done from supplier + info for avoiding error on super method. We will later fill these with + correct values. + """ + if price_type == "supplierinfo": + return dict.fromkeys(self.ids, 1.0) + return super()._price_compute( + price_type, + uom=uom, + currency=currency, + company=company, + date=date, + ) diff --git a/product_pricelist_supplierinfo/models/product_supplierinfo.py b/product_pricelist_supplierinfo/models/product_supplierinfo.py new file mode 100644 index 00000000000..1a8e637cbba --- /dev/null +++ b/product_pricelist_supplierinfo/models/product_supplierinfo.py @@ -0,0 +1,21 @@ +# Copyright 2020 Akretion - Mourad EL HADJ MIMOUNE +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class ProductSupplierinfo(models.Model): + _inherit = "product.supplierinfo" + + sale_margin = fields.Float( + default=0, + digits=(16, 2), + help="Margin to apply on price to obtain sale price", + ) + + def _get_supplierinfo_pricelist_price(self): + self.ensure_one() + sale_price = self.price + if self.sale_margin: + sale_price = (self.price + (self.price * (self.sale_margin / 100))) or 0.0 + return sale_price diff --git a/product_pricelist_supplierinfo/models/product_template.py b/product_pricelist_supplierinfo/models/product_template.py new file mode 100644 index 00000000000..589855500b9 --- /dev/null +++ b/product_pricelist_supplierinfo/models/product_template.py @@ -0,0 +1,96 @@ +# Copyright 2018 Tecnativa - Vicent Cubells +# Copyright 2018 Tecnativa - Pedro M. Baeza +# Copyright 2019 Tecnativa - Carlos Dauden +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from datetime import datetime + +from odoo import fields, models, tools + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + def _get_supplierinfo_pricelist_price( + self, rule, date=None, quantity=None, product_id=None + ): + """Method for getting the price from supplier info.""" + self.ensure_one() + price = 0.0 + product = self.product_variant_id + if product_id: + product = product.browse(product_id) + if rule.no_supplierinfo_min_quantity: + # No matter which minimum qty, we'll get every seller. We set a + # number absurdidly high + quantity = 1e9 + # The product_variant_id returns empty recordset if template is not + # active, so we must ensure variant exists or _select_seller fails. + if product: + if type(date) == datetime: + date = date.date() + seller = product.with_context( + override_min_qty=rule.no_supplierinfo_min_quantity + )._select_seller( + # For a public user this record could be not accessible, but we + # need to get the price anyway + partner_id=self.env.context.get( + "force_filter_supplier_id", rule.sudo().filter_supplier_id + ), + quantity=quantity, + date=date, + ) + if seller: + price = seller._get_supplierinfo_pricelist_price() + if price: + # We need to convert the price if the pricelist and seller have + # different currencies so the price have the pricelist currency + if rule.currency_id != seller.currency_id: + convert_date = date or self.env.context.get("date", fields.Date.today()) + price = seller.currency_id._convert( + price, rule.currency_id, seller.company_id, convert_date + ) + + # We have to replicate this logic in this method as pricelist + # method are atomic and we can't hack inside. + # Verbatim copy of part of product.pricelist._compute_price_rule. + qty_uom_id = self._context.get("uom") or self.uom_id.id + price_uom = self.env["uom.uom"].browse([qty_uom_id]) + + # We need to convert the price to the uom used on the sale, if the + # uom on the seller is a different one that the one used there. + if seller and seller.product_uom != price_uom: + price = seller.product_uom._compute_price(price, price_uom) + price_limit = price + price = (price - (price * (rule.price_discount / 100))) or 0.0 + if rule.price_round: + price = tools.float_round(price, precision_rounding=rule.price_round) + if rule.price_surcharge: + price_surcharge = self.uom_id._compute_price( + rule.price_surcharge, price_uom + ) + price += price_surcharge + if rule.price_min_margin: + price_min_margin = self.uom_id._compute_price( + rule.price_min_margin, price_uom + ) + price = max(price, price_limit + price_min_margin) + if rule.price_max_margin: + price_max_margin = self.uom_id._compute_price( + rule.price_max_margin, price_uom + ) + price = min(price, price_limit + price_max_margin) + return price + + def _price_compute( + self, price_type, uom=None, currency=None, company=False, date=False + ): + """Return dummy not falsy prices when computation is done from supplier + info for avoiding error on super method. We will later fill these with + correct values. + """ + if price_type == "supplierinfo": + return dict.fromkeys(self.ids, 1.0) + return super()._price_compute( + price_type, uom=uom, currency=currency, company=company, date=date + ) diff --git a/product_pricelist_supplierinfo/pyproject.toml b/product_pricelist_supplierinfo/pyproject.toml new file mode 100644 index 00000000000..4231d0cccb3 --- /dev/null +++ b/product_pricelist_supplierinfo/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/product_pricelist_supplierinfo/readme/CONFIGURE.md b/product_pricelist_supplierinfo/readme/CONFIGURE.md new file mode 100644 index 00000000000..48997a2db75 --- /dev/null +++ b/product_pricelist_supplierinfo/readme/CONFIGURE.md @@ -0,0 +1,15 @@ +To configure pricelists with the new feature of this module, you need +to: + +1. Go to *Sales \> Configuration \> Settings* and check "Pricelists" + option and "Advanced price rules (discounts, formulas)" after that. + You must have correct permissions and you must install **Sales + Management** app (sale) and **Purchase** app to see these settings. +2. Create or edit a Sales Pricelist at *Sales \> Products \> + Pricelists*. +3. Add or edit a pricelist item and check "Formula" option in "Price + Computation" section. +4. You will see the new option "Prices based on supplier info". +5. If you want to bypass the "Min.Quantity" field of the supplier info + and always select the lowest quantity price, check the option + "Ignore Supplier Info Min. Quantity". diff --git a/product_pricelist_supplierinfo/readme/CONTRIBUTORS.md b/product_pricelist_supplierinfo/readme/CONTRIBUTORS.md new file mode 100644 index 00000000000..8eccff75049 --- /dev/null +++ b/product_pricelist_supplierinfo/readme/CONTRIBUTORS.md @@ -0,0 +1,8 @@ +- [Tecnativa](https://www.tecnativa.com/): + - Vicent Cubells + - Pedro M. Baeza + - Carlos Roca +- Nikul Chaudhary \<\> +- [TAKOBI](https://takobi.online/): + - Lorenzo Battistini +- Andrea Gidalti \<\> diff --git a/product_pricelist_supplierinfo/readme/DESCRIPTION.md b/product_pricelist_supplierinfo/readme/DESCRIPTION.md new file mode 100644 index 00000000000..1e0b4069391 --- /dev/null +++ b/product_pricelist_supplierinfo/readme/DESCRIPTION.md @@ -0,0 +1,7 @@ +This module allows you to create a sales pricelist based on product +supplierinfo prices. If you want, you can bypass minimum quantity in +pricelist item. + +We can also define sale marging applied on purchase price directly on +supplier info. For this, you must add users to "Show sale margin on +Product Supplierinfo" group. diff --git a/product_pricelist_supplierinfo/readme/INSTALL.md b/product_pricelist_supplierinfo/readme/INSTALL.md new file mode 100644 index 00000000000..b0254a4a46a --- /dev/null +++ b/product_pricelist_supplierinfo/readme/INSTALL.md @@ -0,0 +1,2 @@ +Although this module doesn't depend technically on **Sales Management**, +you must install it for configuring and seeing the effects of it. diff --git a/product_pricelist_supplierinfo/readme/ROADMAP.md b/product_pricelist_supplierinfo/readme/ROADMAP.md new file mode 100644 index 00000000000..98de803c832 --- /dev/null +++ b/product_pricelist_supplierinfo/readme/ROADMAP.md @@ -0,0 +1,5 @@ +- First line that matches by minimum quantity criteria, independently + from the supplier, will be the one that provides the price for the + pricelist. +- There's no mechanism for selecting the supplier from possible sources + like sales orders. diff --git a/product_pricelist_supplierinfo/readme/USAGE.md b/product_pricelist_supplierinfo/readme/USAGE.md new file mode 100644 index 00000000000..b7fb448c863 --- /dev/null +++ b/product_pricelist_supplierinfo/readme/USAGE.md @@ -0,0 +1,18 @@ +For adding supplier info: + +1. Go to *Sales \> Products \> Products* +2. Open or create a product. +3. Go to "Purchase" page. +4. On "Vendors" section, add the supplier and prices. +5. You can drag and drop for reordering these lines. + +Check the remark in known issues about the supplier info line selection. + +For checking pricelists in action, you can (with sale module installed): + +1. Go to *Sales \> Orders \> Quotations* +2. Create or edit a quotation. +3. Add a line. +4. Select a product with the criteria to match the pricelist from + supplier info. +5. See the proper price appears in the line. diff --git a/product_pricelist_supplierinfo/security/res_groups.xml b/product_pricelist_supplierinfo/security/res_groups.xml new file mode 100644 index 00000000000..15c907f0042 --- /dev/null +++ b/product_pricelist_supplierinfo/security/res_groups.xml @@ -0,0 +1,9 @@ + + + + + Show sale margin on Product Supplierinfo + + + + diff --git a/product_pricelist_supplierinfo/static/description/icon.png b/product_pricelist_supplierinfo/static/description/icon.png new file mode 100644 index 00000000000..3a0328b516c Binary files /dev/null and b/product_pricelist_supplierinfo/static/description/icon.png differ diff --git a/product_pricelist_supplierinfo/static/description/index.html b/product_pricelist_supplierinfo/static/description/index.html new file mode 100644 index 00000000000..b17380eaaea --- /dev/null +++ b/product_pricelist_supplierinfo/static/description/index.html @@ -0,0 +1,500 @@ + + + + + +Supplier info prices in sales pricelists + + + +
+

Supplier info prices in sales pricelists

+ + +

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

+

This module allows you to create a sales pricelist based on product +supplierinfo prices. If you want, you can bypass minimum quantity in +pricelist item.

+

We can also define sale marging applied on purchase price directly on +supplier info. For this, you must add users to “Show sale margin on +Product Supplierinfo” group.

+

Table of contents

+ +
+

Installation

+

Although this module doesn’t depend technically on Sales Management, +you must install it for configuring and seeing the effects of it.

+
+
+

Configuration

+

To configure pricelists with the new feature of this module, you need +to:

+
    +
  1. Go to Sales > Configuration > Settings and check “Pricelists” +option and “Advanced price rules (discounts, formulas)” after that. +You must have correct permissions and you must install Sales +Management app (sale) and Purchase app to see these settings.
  2. +
  3. Create or edit a Sales Pricelist at Sales > Products > Pricelists.
  4. +
  5. Add or edit a pricelist item and check “Formula” option in “Price +Computation” section.
  6. +
  7. You will see the new option “Prices based on supplier info”.
  8. +
  9. If you want to bypass the “Min.Quantity” field of the supplier info +and always select the lowest quantity price, check the option “Ignore +Supplier Info Min. Quantity”.
  10. +
+
+
+

Usage

+

For adding supplier info:

+
    +
  1. Go to Sales > Products > Products
  2. +
  3. Open or create a product.
  4. +
  5. Go to “Purchase” page.
  6. +
  7. On “Vendors” section, add the supplier and prices.
  8. +
  9. You can drag and drop for reordering these lines.
  10. +
+

Check the remark in known issues about the supplier info line selection.

+

For checking pricelists in action, you can (with sale module installed):

+
    +
  1. Go to Sales > Orders > Quotations
  2. +
  3. Create or edit a quotation.
  4. +
  5. Add a line.
  6. +
  7. Select a product with the criteria to match the pricelist from +supplier info.
  8. +
  9. See the proper price appears in the line.
  10. +
+
+
+

Known issues / Roadmap

+
    +
  • First line that matches by minimum quantity criteria, independently +from the supplier, will be the one that provides the price for the +pricelist.
  • +
  • There’s no mechanism for selecting the supplier from possible sources +like sales orders.
  • +
+
+
+

Bug Tracker

+

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

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • Tecnativa
  • +
  • Vauxoo
  • +
+
+
+

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:

+

luisg123v

+

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

+

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

+
+
+
+ + diff --git a/product_pricelist_supplierinfo/tests/__init__.py b/product_pricelist_supplierinfo/tests/__init__.py new file mode 100644 index 00000000000..0ff6e5eba5e --- /dev/null +++ b/product_pricelist_supplierinfo/tests/__init__.py @@ -0,0 +1 @@ +from . import test_product_supplierinfo diff --git a/product_pricelist_supplierinfo/tests/test_product_supplierinfo.py b/product_pricelist_supplierinfo/tests/test_product_supplierinfo.py new file mode 100644 index 00000000000..31521cfa97e --- /dev/null +++ b/product_pricelist_supplierinfo/tests/test_product_supplierinfo.py @@ -0,0 +1,313 @@ +# Copyright 2018 Tecnativa - Vicent Cubells +# Copyright 2018 Tecnativa - Pedro M. Baeza +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from datetime import date + +from odoo import Command +from odoo.tests import TransactionCase, tagged + + +@tagged("product_supplier_info") +class TestProductSupplierinfo(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.partner_obj = cls.env["res.partner"] + cls.currency_rate_obj = cls.env["res.currency.rate"] + cls.partner = cls.partner_obj.create({"name": "Partner Test"}) + cls.supplier1 = cls.partner_obj.create({"name": "Supplier #1"}) + cls.supplier2 = cls.partner_obj.create({"name": "Supplier #2"}) + cls.product = cls.env["product.product"].create( + { + "name": "Product Test", + "seller_ids": [ + Command.create( + {"partner_id": cls.supplier1.id, "min_qty": 5, "price": 50}, + ), + Command.create( + {"partner_id": cls.supplier2.id, "min_qty": 1, "price": 10}, + ), + ], + } + ) + cls.product_with_diff_uom = cls.env["product.product"].create( + { + "name": "Product UOM Test", + "uom_id": cls.env.ref("uom.product_uom_unit").id, + "uom_po_id": cls.env.ref("uom.product_uom_dozen").id, + "seller_ids": [ + Command.create( + {"partner_id": cls.supplier1.id, "min_qty": 1, "price": 1200}, + ) + ], + } + ) + cls.pricelist = cls.env["product.pricelist"].create( + { + "name": "Supplierinfo Pricelist", + "item_ids": [ + Command.create( + { + "compute_price": "formula", + "base": "supplierinfo", + "price_discount": 0, + "min_quantity": 1.0, + }, + ) + ], + } + ) + + @classmethod + def _update_rate(cls, currency_id, rate): + currency_rate = cls.currency_rate_obj.search( + [("name", "=", date.today()), ("currency_id", "=", currency_id.id)], limit=1 + ) + if not currency_rate: + cls.currency_rate_obj.create( + { + "currency_id": currency_id.id, + "rate": rate, + "name": date.today(), + } + ) + else: + currency_rate.write({"rate": rate}) + + def test_pricelist_based_on_product_category(self): + self.pricelist.item_ids[0].write( + { + "price_discount": 50, + "applied_on": "2_product_category", + "categ_id": self.env.ref("product.product_category_all").id, + } + ) + self.assertAlmostEqual( + self.pricelist._get_product_price(self.product, 1), + 5.0, + ) + + def test_pricelist_based_on_product(self): + self.pricelist.item_ids[0].write( + { + "applied_on": "1_product", + "product_tmpl_id": self.product.product_tmpl_id.id, + } + ) + self.assertAlmostEqual( + self.pricelist._get_product_price(self.product, 1), + 10.0, + ) + + def test_pricelist_based_on_product_variant(self): + self.pricelist.item_ids[0].write( + { + "price_discount": -25, + "applied_on": "0_product_variant", + "product_id": self.product.id, + } + ) + self.assertAlmostEqual( + self.pricelist._get_product_price(self.product, 1), + 12.5, + ) + + def test_pricelist_min_quantity(self): + self.assertAlmostEqual( + self.pricelist._get_product_price(self.product, 1), + 10, + ) + self.assertAlmostEqual( + self.pricelist._get_product_price(self.product, 5), + 50, + ) + self.assertAlmostEqual( + self.pricelist._get_product_price(self.product, 10), + 50, + ) + self.pricelist.item_ids[0].no_supplierinfo_min_quantity = True + self.assertAlmostEqual( + self.pricelist._get_product_price(self.product, 5), + 10, + ) + + def test_pricelist_supplier_filter(self): + self.assertAlmostEqual( + self.pricelist._get_product_price(self.product, 5), + 50, + ) + self.pricelist.item_ids[0].filter_supplier_id = self.supplier2.id + self.assertAlmostEqual( + self.pricelist._get_product_price(self.product, 5), + 10, + ) + + def test_pricelist_dates(self): + """Test pricelist and supplierinfo dates""" + self.product.seller_ids.filtered(lambda x: x.min_qty == 5)[ + 0 + ].date_start = "2018-12-31" + self.assertAlmostEqual( + self.pricelist._get_product_price( + self.product, + 5, + date=date(2019, 1, 1), + ), + 50, + ) + + def test_pricelist_based_price_round(self): + self.pricelist.item_ids[0].write( + { + "price_discount": 50, + "applied_on": "2_product_category", + "categ_id": self.product.categ_id.id, + "price_round": 1, + "price_surcharge": 5, + "price_min_margin": 10, + "price_max_margin": 100, + } + ) + self.assertAlmostEqual( + self.pricelist._get_product_price(self.product, 1), + 20.0, + ) + + def test_pricelist_based_on_sale_margin(self): + self.pricelist.item_ids[0].write( + { + "applied_on": "1_product", + "product_tmpl_id": self.product.product_tmpl_id.id, + } + ) + seller = self.product.seller_ids[0] + seller.sale_margin = 50 + self.assertAlmostEqual( + seller._get_supplierinfo_pricelist_price(), + 75.0, + ) + self.assertAlmostEqual( + self.pricelist._get_product_price(self.product, 6), + 75.0, + ) + + def test_supplierinfo_per_variant(self): + tmpl = self.env["product.template"].create( + { + "name": "Test Product", + "attribute_line_ids": [ + Command.create( + { + "attribute_id": self.env.ref( + "product.product_attribute_1" + ).id, + "value_ids": [ + Command.link( + self.env.ref( + "product.product_attribute_value_1" + ).id, + ), + Command.link( + self.env.ref( + "product.product_attribute_value_2" + ).id, + ), + ], + }, + ) + ], + } + ) + variant1 = tmpl.product_variant_ids[0] + variant2 = tmpl.product_variant_ids[1] + tmpl.write( + { + "seller_ids": [ + Command.create( + { + "partner_id": self.supplier1.id, + "product_id": variant1.id, + "price": 15, + } + ), + Command.create( + { + "partner_id": self.supplier1.id, + "product_id": variant2.id, + "price": 25, + }, + ), + ] + } + ) + self.assertAlmostEqual( + self.pricelist._get_product_price(variant1, 1), + 15.0, + ) + self.assertAlmostEqual( + self.pricelist._get_product_price(variant2, 1), + 25.0, + ) + + def test_pricelist_and_supplierinfo_currencies(self): + """Test when we have 2 records of supplierinfo in two currencies, on a same + pricelist as pricelist items, the currency on the supplier that have a + different currency will be converted to the pricelist's currency. + """ + # Setting the currencies and rates for the test, so we can have a supplierinfo + # and pricelist with different currencies + currency_usd = self.env.ref("base.USD") + currency_mxn = self.env.ref("base.MXN") + self._update_rate(currency_usd, 1) + self._update_rate(currency_mxn, 20) + + # Setting the item with the product + self.pricelist.item_ids[0].write( + { + "applied_on": "0_product_variant", + "product_id": self.product.id, + } + ) + self.product.seller_ids[0].currency_id = currency_mxn + self.pricelist.currency_id = currency_usd + + product_seller_price = self.product.seller_ids[0].price + product_pricelist_price = self.pricelist._get_product_price(self.product, 5) + # The price with MXN Currency will be 50 as is set in the setup + self.assertEqual(product_seller_price, 50) + # And the price with the pricelist (USD Currency) will be 2.5 + self.assertEqual(product_pricelist_price, 2.5) + + def test_line_uom_and_supplierinfo_uom(self): + """Test when we have a product is sold in a different uom from the one on set + for purchase. + """ + # Setting the item with the product + self.pricelist.item_ids[0].write( + { + "applied_on": "0_product_variant", + "product_id": self.product_with_diff_uom.id, + "price_discount": -20, + } + ) + + product_seller_price = self.product_with_diff_uom.seller_ids[0].price + uom_dozen = self.env.ref("uom.product_uom_dozen") + product_pricelist_price_dozen = self.pricelist._get_product_price( + self.product_with_diff_uom.with_context(uom=uom_dozen.id), 1 + ) + uom_unit = self.env.ref("uom.product_uom_unit") + product_pricelist_price_unit = self.pricelist._get_product_price( + self.product_with_diff_uom.with_context(uom=uom_unit.id), 1 + ) + # The price with the will be 1200 on the seller (1 Dozen) + self.assertEqual(product_seller_price, 1200) + + # The price with the will be 1200 plus the increment of the 20% which will + # give us a total of 1440 (1 Dozen) + self.assertEqual(product_pricelist_price_dozen, 1440) + + # And the price with the pricelist and the uom of Units (Instead of Dozen) + # will be 100, plus the 20% the total will be 120 per Unit + self.assertEqual(product_pricelist_price_unit, 120) diff --git a/product_pricelist_supplierinfo/views/product_pricelist_item_views.xml b/product_pricelist_supplierinfo/views/product_pricelist_item_views.xml new file mode 100644 index 00000000000..7089a7a33a5 --- /dev/null +++ b/product_pricelist_supplierinfo/views/product_pricelist_item_views.xml @@ -0,0 +1,19 @@ + + + + + product.pricelist.item.form + product.pricelist.item + + + + + + + + + + diff --git a/product_pricelist_supplierinfo/views/product_supplierinfo_view.xml b/product_pricelist_supplierinfo/views/product_supplierinfo_view.xml new file mode 100644 index 00000000000..fcf823e23c4 --- /dev/null +++ b/product_pricelist_supplierinfo/views/product_supplierinfo_view.xml @@ -0,0 +1,38 @@ + + + + + product.supplierinfo.tree.view.pricelist + product.supplierinfo + + + + + + + + + + product.supplierinfo.form.view.pricelist + product.supplierinfo + + + + + + + +