diff --git a/website_sale_stock_available/README.rst b/website_sale_stock_available/README.rst new file mode 100644 index 0000000000..4fc39cb16a --- /dev/null +++ b/website_sale_stock_available/README.rst @@ -0,0 +1,123 @@ +============================ +Website Sale Stock Available +============================ + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:1466d69a1e2c40adc4684708bb2ff48b1be5525fd4e80230e935e8da4c717232 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Fe--commerce-lightgray.png?logo=github + :target: https://github.com/OCA/e-commerce/tree/18.0/website_sale_stock_available + :alt: OCA/e-commerce +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/e-commerce-18-0/e-commerce-18-0-website_sale_stock_available + :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/e-commerce&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module extends the functionality of the *Product Availability* +module (technical name: ``website_sale_stock``) so that for the +eCommerce the *Available* quantity of a product is taken into account +instead of the *free* quantity. + +Note that in the past the eCommerce availability was based in +*Forecasted quantity*. This isn't true anymore from version 15.0. + +If a product is configured to *prevent sales if not enough stock* (see +configuration section) and its page is accessed in the Website Shop, the +availability messages will be based on the *Available* quantity instead +of *Free* quantity. And also, the eCommerce won't allow you to buy more +products than *Available* quantity (not *Free* quantity isn't taken into +account). + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +To configure this module, you need to: + +1. Go to *Inventory > Products > Products* and edit a product that you + only want to sell in the eCommerce if there is enough stock. +2. Navigate to *Out-of-stock (continue selling)* field in the *Sales* + tab and unset it. + +Usage +===== + +To use this module, you need to: + +1. Go to your eCommerce. +2. Select a product that you has been previously configured to *prevent + sales if not enough stock* for the web product page. +3. Odoo doesn't allow you to add the product to the cart if *Available* + quantity (not *Free to use* quantity) is equal or less than zero. + Besides, availability messages will be based on the *Available* + quantity instead of the *Free to use* quantity. + +|Availability message| + +.. |Availability message| image:: https://raw.githubusercontent.com/OCA/e-commerce/18.0/website_sale_stock_available/static/description/availability_message.png + +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 + +Contributors +------------ + +- `Tecnativa `__: + + - Ernesto Tejeda + - Pedro M. Baeza + - David Vidal + - Carlos Lopez + +- Iván Todorovich + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/e-commerce `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/website_sale_stock_available/__init__.py b/website_sale_stock_available/__init__.py new file mode 100644 index 0000000000..df9b9c226b --- /dev/null +++ b/website_sale_stock_available/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +from . import controllers +from . import models diff --git a/website_sale_stock_available/__manifest__.py b/website_sale_stock_available/__manifest__.py new file mode 100644 index 0000000000..1601ee23d8 --- /dev/null +++ b/website_sale_stock_available/__manifest__.py @@ -0,0 +1,18 @@ +# Copyright 2020 Tecnativa - Ernesto Tejeda +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "Website Sale Stock Available", + "summary": "Display 'Available to promise' in shop online instead " + "of 'Free To Use Quantity'", + "version": "18.0.1.0.0", + "category": "Website", + "website": "https://github.com/OCA/e-commerce", + "author": "Tecnativa, Odoo Community Association (OCA)", + "license": "AGPL-3", + "depends": [ + "stock_available", + "website_sale_stock", + ], + "data": [], + "installable": True, +} diff --git a/website_sale_stock_available/controllers/__init__.py b/website_sale_stock_available/controllers/__init__.py new file mode 100644 index 0000000000..12a7e529b6 --- /dev/null +++ b/website_sale_stock_available/controllers/__init__.py @@ -0,0 +1 @@ +from . import main diff --git a/website_sale_stock_available/controllers/main.py b/website_sale_stock_available/controllers/main.py new file mode 100644 index 0000000000..5d3307606c --- /dev/null +++ b/website_sale_stock_available/controllers/main.py @@ -0,0 +1,15 @@ +# Copyright 2020 Tecnativa - David Vidal +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo.http import request, route + +from odoo.addons.website_sale.controllers.payment import PaymentPortal + + +class PaymentPortal(PaymentPortal): + @route() + def shop_payment_transaction(self, *args, **kwargs): + """Inject a context when potential or promised stock is set""" + request.website = request.website.with_context( + website_sale_stock_available=True + ) + return super().shop_payment_transaction(*args, **kwargs) diff --git a/website_sale_stock_available/i18n/ca_ES.po b/website_sale_stock_available/i18n/ca_ES.po new file mode 100644 index 0000000000..edb49a6349 --- /dev/null +++ b/website_sale_stock_available/i18n/ca_ES.po @@ -0,0 +1,29 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * website_sale_stock_available +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.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: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_product_template +msgid "Product" +msgstr "Producte" + +#. module: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_product_product +msgid "Product Variant" +msgstr "" + +#. module: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_sale_order +msgid "Sales Order" +msgstr "" diff --git a/website_sale_stock_available/i18n/es.po b/website_sale_stock_available/i18n/es.po new file mode 100644 index 0000000000..86dd562f23 --- /dev/null +++ b/website_sale_stock_available/i18n/es.po @@ -0,0 +1,32 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * website_sale_stock_available +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-08-03 20:09+0000\n" +"Last-Translator: Ivorra78 \n" +"Language-Team: none\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_product_template +msgid "Product" +msgstr "Producto" + +#. module: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_product_product +msgid "Product Variant" +msgstr "Variante de Producto" + +#. module: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_sale_order +msgid "Sales Order" +msgstr "Órdenes de venta" diff --git a/website_sale_stock_available/i18n/es_AR.po b/website_sale_stock_available/i18n/es_AR.po new file mode 100644 index 0000000000..8ac0a0b6e7 --- /dev/null +++ b/website_sale_stock_available/i18n/es_AR.po @@ -0,0 +1,32 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * website_sale_stock_available +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-03-12 22:23+0000\n" +"Last-Translator: Ignacio Buioli \n" +"Language-Team: none\n" +"Language: es_AR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.14.1\n" + +#. module: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_product_template +msgid "Product" +msgstr "Producto" + +#. module: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_product_product +msgid "Product Variant" +msgstr "Variante de Producto" + +#. module: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_sale_order +msgid "Sales Order" +msgstr "Pedidos de Ventas" diff --git a/website_sale_stock_available/i18n/es_CL.po b/website_sale_stock_available/i18n/es_CL.po new file mode 100644 index 0000000000..8c51610ae5 --- /dev/null +++ b/website_sale_stock_available/i18n/es_CL.po @@ -0,0 +1,32 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * website_sale_stock_available +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2020-05-30 05:19+0000\n" +"Last-Translator: Nelson Ramírez Sánchez \n" +"Language-Team: none\n" +"Language: es_CL\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: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_product_template +msgid "Product" +msgstr "Producto" + +#. module: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_product_product +msgid "Product Variant" +msgstr "" + +#. module: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_sale_order +msgid "Sales Order" +msgstr "" diff --git a/website_sale_stock_available/i18n/fr.po b/website_sale_stock_available/i18n/fr.po new file mode 100644 index 0000000000..76c3fda48a --- /dev/null +++ b/website_sale_stock_available/i18n/fr.po @@ -0,0 +1,32 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * website_sale_stock_available +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-08-05 17:58+0000\n" +"Last-Translator: Rémi \n" +"Language-Team: none\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 5.6.2\n" + +#. module: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_product_template +msgid "Product" +msgstr "Produit" + +#. module: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_product_product +msgid "Product Variant" +msgstr "Variante de produit" + +#. module: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_sale_order +msgid "Sales Order" +msgstr "Bon de commande" diff --git a/website_sale_stock_available/i18n/it.po b/website_sale_stock_available/i18n/it.po new file mode 100644 index 0000000000..23a34d7ba6 --- /dev/null +++ b/website_sale_stock_available/i18n/it.po @@ -0,0 +1,32 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * website_sale_stock_available +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-05-08 16:34+0000\n" +"Last-Translator: mymage \n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_product_template +msgid "Product" +msgstr "Prodotto" + +#. module: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_product_product +msgid "Product Variant" +msgstr "Variante prodotto" + +#. module: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_sale_order +msgid "Sales Order" +msgstr "Ordine di vendita" diff --git a/website_sale_stock_available/i18n/nl.po b/website_sale_stock_available/i18n/nl.po new file mode 100644 index 0000000000..2643b17f01 --- /dev/null +++ b/website_sale_stock_available/i18n/nl.po @@ -0,0 +1,32 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * website_sale_stock_available +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2020-12-15 13:19+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: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_product_template +msgid "Product" +msgstr "Product" + +#. module: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_product_product +msgid "Product Variant" +msgstr "" + +#. module: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_sale_order +msgid "Sales Order" +msgstr "" diff --git a/website_sale_stock_available/i18n/website_sale_stock_available.pot b/website_sale_stock_available/i18n/website_sale_stock_available.pot new file mode 100644 index 0000000000..21dcc34993 --- /dev/null +++ b/website_sale_stock_available/i18n/website_sale_stock_available.pot @@ -0,0 +1,29 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * website_sale_stock_available +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.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: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_product_template +msgid "Product" +msgstr "" + +#. module: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_product_product +msgid "Product Variant" +msgstr "" + +#. module: website_sale_stock_available +#: model:ir.model,name:website_sale_stock_available.model_sale_order +msgid "Sales Order" +msgstr "" diff --git a/website_sale_stock_available/models/__init__.py b/website_sale_stock_available/models/__init__.py new file mode 100644 index 0000000000..5486cb6719 --- /dev/null +++ b/website_sale_stock_available/models/__init__.py @@ -0,0 +1,5 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import product_product +from . import product_template +from . import sale_order diff --git a/website_sale_stock_available/models/product_product.py b/website_sale_stock_available/models/product_product.py new file mode 100644 index 0000000000..1519b4cc2f --- /dev/null +++ b/website_sale_stock_available/models/product_product.py @@ -0,0 +1,24 @@ +# Copyright 2020 Tecnativa - Ernesto Tejeda +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, models + + +class Product(models.Model): + _inherit = "product.product" + + def _compute_quantities_dict( + self, lot_id, owner_id, package_id, from_date=False, to_date=False + ): + res = super()._compute_quantities_dict( + lot_id, owner_id, package_id, from_date, to_date + ) + if self.env.context.get("website_sale_stock_available"): + for product in self.with_context(website_sale_stock_available=False): + immediately = product.immediately_usable_qty + res[product.id]["free_qty"] = immediately + return res + + @api.depends_context("website_sale_stock_available") + def _compute_quantities(self): + return super()._compute_quantities() diff --git a/website_sale_stock_available/models/product_template.py b/website_sale_stock_available/models/product_template.py new file mode 100644 index 0000000000..6639e67685 --- /dev/null +++ b/website_sale_stock_available/models/product_template.py @@ -0,0 +1,25 @@ +# Copyright 2020 Tecnativa - Ernesto Tejeda +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import models + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + def _get_combination_info( + self, + combination=False, + product_id=False, + add_qty=1.0, + parent_combination=False, + only_template=False, + ): + template = self.with_context(website_sale_stock_available=True) + return super(ProductTemplate, template)._get_combination_info( + combination=combination, + product_id=product_id, + add_qty=add_qty, + parent_combination=parent_combination, + only_template=only_template, + ) diff --git a/website_sale_stock_available/models/sale_order.py b/website_sale_stock_available/models/sale_order.py new file mode 100644 index 0000000000..8a665110f8 --- /dev/null +++ b/website_sale_stock_available/models/sale_order.py @@ -0,0 +1,12 @@ +# Copyright 2020 Tecnativa - Ernesto Tejeda +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import models + + +class SaleOrder(models.Model): + _inherit = "sale.order" + + def _cart_update(self, *args, **kwargs): + order = self.with_context(website_sale_stock_available=True) + return super(SaleOrder, order)._cart_update(*args, **kwargs) diff --git a/website_sale_stock_available/pyproject.toml b/website_sale_stock_available/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/website_sale_stock_available/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/website_sale_stock_available/readme/CONFIGURE.md b/website_sale_stock_available/readme/CONFIGURE.md new file mode 100644 index 0000000000..f93af6d020 --- /dev/null +++ b/website_sale_stock_available/readme/CONFIGURE.md @@ -0,0 +1,6 @@ +To configure this module, you need to: + +1. Go to *Inventory \> Products \> Products* and edit a product that + you only want to sell in the eCommerce if there is enough stock. +2. Navigate to *Out-of-stock (continue selling)* field in the *Sales* + tab and unset it. diff --git a/website_sale_stock_available/readme/CONTRIBUTORS.md b/website_sale_stock_available/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..9f5c2def12 --- /dev/null +++ b/website_sale_stock_available/readme/CONTRIBUTORS.md @@ -0,0 +1,6 @@ +- [Tecnativa](https://www.tecnativa.com): + - Ernesto Tejeda + - Pedro M. Baeza + - David Vidal + - Carlos Lopez +- Iván Todorovich diff --git a/website_sale_stock_available/readme/DESCRIPTION.md b/website_sale_stock_available/readme/DESCRIPTION.md new file mode 100644 index 0000000000..8bbf6d1572 --- /dev/null +++ b/website_sale_stock_available/readme/DESCRIPTION.md @@ -0,0 +1,14 @@ +This module extends the functionality of the *Product Availability* +module (technical name: `website_sale_stock`) so that for the eCommerce +the *Available* quantity of a product is taken into account instead of +the *free* quantity. + +Note that in the past the eCommerce availability was based in +*Forecasted quantity*. This isn't true anymore from version 15.0. + +If a product is configured to *prevent sales if not enough stock* (see +configuration section) and its page is accessed in the Website Shop, the +availability messages will be based on the *Available* quantity instead +of *Free* quantity. And also, the eCommerce won't allow you to buy more +products than *Available* quantity (not *Free* quantity isn't taken into +account). diff --git a/website_sale_stock_available/readme/USAGE.md b/website_sale_stock_available/readme/USAGE.md new file mode 100644 index 0000000000..972e978296 --- /dev/null +++ b/website_sale_stock_available/readme/USAGE.md @@ -0,0 +1,11 @@ +To use this module, you need to: + +1. Go to your eCommerce. +2. Select a product that you has been previously configured to *prevent + sales if not enough stock* for the web product page. +3. Odoo doesn't allow you to add the product to the cart if *Available* + quantity (not *Free to use* quantity) is equal or less than zero. + Besides, availability messages will be based on the *Available* + quantity instead of the *Free to use* quantity. + +![Availability message](../static/description/availability_message.png) diff --git a/website_sale_stock_available/static/description/availability_message.png b/website_sale_stock_available/static/description/availability_message.png new file mode 100644 index 0000000000..61b61318d2 Binary files /dev/null and b/website_sale_stock_available/static/description/availability_message.png differ diff --git a/website_sale_stock_available/static/description/icon.png b/website_sale_stock_available/static/description/icon.png new file mode 100644 index 0000000000..06c0dd0c4c Binary files /dev/null and b/website_sale_stock_available/static/description/icon.png differ diff --git a/website_sale_stock_available/static/description/index.html b/website_sale_stock_available/static/description/index.html new file mode 100644 index 0000000000..39cb4f19d2 --- /dev/null +++ b/website_sale_stock_available/static/description/index.html @@ -0,0 +1,467 @@ + + + + + +Website Sale Stock Available + + + +
+

Website Sale Stock Available

+ + +

Beta License: AGPL-3 OCA/e-commerce Translate me on Weblate Try me on Runboat

+

This module extends the functionality of the Product Availability +module (technical name: website_sale_stock) so that for the +eCommerce the Available quantity of a product is taken into account +instead of the free quantity.

+

Note that in the past the eCommerce availability was based in +Forecasted quantity. This isn’t true anymore from version 15.0.

+

If a product is configured to prevent sales if not enough stock (see +configuration section) and its page is accessed in the Website Shop, the +availability messages will be based on the Available quantity instead +of Free quantity. And also, the eCommerce won’t allow you to buy more +products than Available quantity (not Free quantity isn’t taken into +account).

+

Table of contents

+ +
+

Configuration

+

To configure this module, you need to:

+
    +
  1. Go to Inventory > Products > Products and edit a product that you +only want to sell in the eCommerce if there is enough stock.
  2. +
  3. Navigate to Out-of-stock (continue selling) field in the Sales +tab and unset it.
  4. +
+
+
+

Usage

+

To use this module, you need to:

+
    +
  1. Go to your eCommerce.
  2. +
  3. Select a product that you has been previously configured to prevent +sales if not enough stock for the web product page.
  4. +
  5. Odoo doesn’t allow you to add the product to the cart if Available +quantity (not Free to use quantity) is equal or less than zero. +Besides, availability messages will be based on the Available +quantity instead of the Free to use quantity.
  6. +
+

Availability message

+
+
+

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
  • +
+
+
+

Contributors

+
    +
  • Tecnativa:
      +
    • Ernesto Tejeda
    • +
    • Pedro M. Baeza
    • +
    • David Vidal
    • +
    • Carlos Lopez
    • +
    +
  • +
  • Iván Todorovich
  • +
+
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

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

+

This module is part of the OCA/e-commerce project on GitHub.

+

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

+
+
+
+ + diff --git a/website_sale_stock_available/tests/__init__.py b/website_sale_stock_available/tests/__init__.py new file mode 100644 index 0000000000..59a5546ae0 --- /dev/null +++ b/website_sale_stock_available/tests/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import test_website_sale_stock_available diff --git a/website_sale_stock_available/tests/test_website_sale_stock_available.py b/website_sale_stock_available/tests/test_website_sale_stock_available.py new file mode 100644 index 0000000000..4b0cc76e87 --- /dev/null +++ b/website_sale_stock_available/tests/test_website_sale_stock_available.py @@ -0,0 +1,94 @@ +# Copyright 2020 Tecnativa - Ernesto Tejeda +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import Command + +from odoo.addons.base.tests.common import BaseCommon + + +class SaleStockAvailableInfoPopup(BaseCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + user_group_stock_user = cls.env.ref("stock.group_stock_user") + cls.user_stock_user = cls.env["res.users"].create( + { + "name": "Pauline Poivraisselle", + "login": "pauline", + "email": "p.p@example.com", + "notification_type": "inbox", + "groups_id": [Command.link(user_group_stock_user.id)], + } + ) + cls.product = cls.env["product.product"].create( + { + "name": "Storable product", + "type": "consu", + "is_storable": True, + } + ) + cls.stock_location = cls.env.ref("stock.stock_location_stock") + cls.customers_location = cls.env.ref("stock.stock_location_customers") + cls.suppliers_location = cls.env.ref("stock.stock_location_suppliers") + cls.env["stock.quant"].create( + { + "product_id": cls.product.id, + "location_id": cls.stock_location.id, + "quantity": 40.0, + } + ) + cls.picking_out = cls.env["stock.picking"].create( + { + "picking_type_id": cls.env.ref("stock.picking_type_out").id, + "location_id": cls.stock_location.id, + "location_dest_id": cls.customers_location.id, + } + ) + cls.env["stock.move"].create( + { + "name": "a move", + "product_id": cls.product.id, + "product_uom_qty": 3.0, + "product_uom": cls.product.uom_id.id, + "picking_id": cls.picking_out.id, + "location_id": cls.stock_location.id, + "location_dest_id": cls.customers_location.id, + } + ) + cls.picking_in = cls.env["stock.picking"].create( + { + "picking_type_id": cls.env.ref("stock.picking_type_in").id, + "location_id": cls.suppliers_location.id, + "location_dest_id": cls.stock_location.id, + } + ) + cls.env["stock.move"].create( + { + "restrict_partner_id": cls.user_stock_user.partner_id.id, + "name": "another move", + "product_id": cls.product.id, + "product_uom_qty": 5.0, + "product_uom": cls.product.uom_id.id, + "picking_id": cls.picking_in.id, + "location_id": cls.suppliers_location.id, + "location_dest_id": cls.stock_location.id, + } + ) + + def test_get_combination_info(self): + product_tmpl = self.product.product_tmpl_id + combination_info = product_tmpl.with_context( + website_sale_stock_get_quantity=True, + )._get_combination_info() + self.assertEqual( + combination_info["free_qty"], + 40, + ) + self.picking_out.action_confirm() + self.picking_in.action_assign() + combination_info = product_tmpl.with_context( + website_sale_stock_get_quantity=True, + )._get_combination_info() + self.assertEqual( + combination_info["free_qty"], self.product.immediately_usable_qty + )