diff --git a/stock_location_lockdown/README.rst b/stock_location_lockdown/README.rst new file mode 100644 index 000000000000..3a3faaa9c2c0 --- /dev/null +++ b/stock_location_lockdown/README.rst @@ -0,0 +1,96 @@ +======================= +Stock Location Lockdown +======================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:a3c846698d800affc1c0751b171d7a5bf571e0672e46183980535ee98e23298e + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Fstock--logistics--warehouse-lightgray.png?logo=github + :target: https://github.com/OCA/stock-logistics-warehouse/tree/17.0/stock_location_lockdown + :alt: OCA/stock-logistics-warehouse +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/stock-logistics-warehouse-17-0/stock-logistics-warehouse-17-0-stock_location_lockdown + :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/stock-logistics-warehouse&target_branch=17.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +The aim of this module is to mark internal locations where no product +should transit. Indeed, in complex warehouse setups, we may have a +complicated tree of internal locations with parent locations only used +to create the hierarchy of the internal locations. We may want to avoid +to put stock on these parent internal locations since they are not +physical locations, they just represent a zone of the warehouse. Theses +locations must have *Location Type* set to *Internal Location* because +they belong to a warehouse (they can't be configured with *Location +Type* set to *View*, cf `Odoo bug +#26679 `__). With this +module, you will be able to enable a new option *Block stock entrance* +for these locations. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +- Once the module is installed, select any internal location for which + you want to prevent stock entrance and check the box *Block Stock + Entrance*. Then, you won't be allow to add stock on these locations. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Akretion + +Contributors +------------ + +- Florian da Costa +- David Montull Guasch +- Urvisha Desai + +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/stock-logistics-warehouse `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_location_lockdown/__init__.py b/stock_location_lockdown/__init__.py new file mode 100644 index 000000000000..79e06e260482 --- /dev/null +++ b/stock_location_lockdown/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2018 Akretion +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import models diff --git a/stock_location_lockdown/__manifest__.py b/stock_location_lockdown/__manifest__.py new file mode 100644 index 000000000000..1e1767c4ac14 --- /dev/null +++ b/stock_location_lockdown/__manifest__.py @@ -0,0 +1,16 @@ +# Copyright 2018 Akretion +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Stock Location Lockdown", + "summary": "Prevent to add stock on locked locations", + "author": "Akretion, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/stock-logistics-warehouse", + "category": "Warehouse", + "version": "17.0.1.0.0", + "license": "AGPL-3", + "application": False, + "installable": True, + "depends": ["stock"], + "data": ["views/stock_location.xml"], +} diff --git a/stock_location_lockdown/i18n/es.po b/stock_location_lockdown/i18n/es.po new file mode 100644 index 000000000000..06738fd51036 --- /dev/null +++ b/stock_location_lockdown/i18n/es.po @@ -0,0 +1,64 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_location_lockdown +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-07-27 23:12+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: stock_location_lockdown +#: model:ir.model.fields,field_description:stock_location_lockdown.field_stock_location__block_stock_entrance +msgid "Block Stock Entrance" +msgstr "Bloquear la entrada de existencias" + +#. module: stock_location_lockdown +#: model:ir.model,name:stock_location_lockdown.model_stock_location +msgid "Inventory Locations" +msgstr "Localizaciones de Inventario" + +#. module: stock_location_lockdown +#. odoo-python +#: code:addons/stock_location_lockdown/models/stock_location.py:0 +#, python-format +msgid "" +"It is impossible to prohibit this location from receiving " +"products as it already contains some." +msgstr "" +"Es imposible prohibir que este lugar " +"reciba productos, puesto que " +"ya contiene algunos." + +#. module: stock_location_lockdown +#: model:ir.model,name:stock_location_lockdown.model_stock_quant +msgid "Quants" +msgstr "Cantidades" + +#. module: stock_location_lockdown +#. odoo-python +#: code:addons/stock_location_lockdown/models/stock_quant.py:0 +#, python-format +msgid "" +"The location %(location)s is blocked and can not be used for moving the " +"product %(product)s" +msgstr "" +"La ubicación %(location)s esta bloqueada, no puede ser usada para mover el " +"producto %(product)s" + +#. module: stock_location_lockdown +#: model:ir.model.fields,help:stock_location_lockdown.field_stock_location__block_stock_entrance +msgid "" +"if this box is checked, putting stock on this location won't be allowed. " +"Usually used for a virtual location that has childrens." +msgstr "" +"si esta casilla está marcada, no se permitirá poner acciones en esta " +"ubicación. Normalmente se utiliza para una ubicación virtual que tiene niños." diff --git a/stock_location_lockdown/i18n/fr.po b/stock_location_lockdown/i18n/fr.po new file mode 100644 index 000000000000..aa71f0f20020 --- /dev/null +++ b/stock_location_lockdown/i18n/fr.po @@ -0,0 +1,69 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_location_lockdown +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 9.0c\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-09-06 13:10+0000\n" +"PO-Revision-Date: 2018-09-06 13:10+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: stock_location_lockdown +#: model:ir.model.fields,field_description:stock_location_lockdown.field_stock_location__block_stock_entrance +#, fuzzy +msgid "Block Stock Entrance" +msgstr "Bloquer les entrées de stock" + +#. module: stock_location_lockdown +#: model:ir.model,name:stock_location_lockdown.model_stock_location +msgid "Inventory Locations" +msgstr "" + +#. module: stock_location_lockdown +#. odoo-python +#: code:addons/stock_location_lockdown/models/stock_location.py:0 +#, python-format +msgid "" +"It is impossible to prohibit this location from receiving " +"products as it already contains some." +msgstr "" + +#. module: stock_location_lockdown +#: model:ir.model,name:stock_location_lockdown.model_stock_quant +msgid "Quants" +msgstr "" + +#. module: stock_location_lockdown +#. odoo-python +#: code:addons/stock_location_lockdown/models/stock_quant.py:0 +#, python-format +msgid "" +"The location %(location)s is blocked and can not be used for moving the " +"product %(product)s" +msgstr "" + +#. module: stock_location_lockdown +#: model:ir.model.fields,help:stock_location_lockdown.field_stock_location__block_stock_entrance +#, fuzzy +msgid "" +"if this box is checked, putting stock on this location won't be allowed. " +"Usually used for a virtual location that has childrens." +msgstr "" +"Si cette case est cochée, il ne sera pas possible d'ajouter du stock dans " +"cette emplacement. Habituellement utilisée pour les emplacements virtuels " +"ayant des enfants." + +#, fuzzy +#~ msgid "The location '%s' is not configured to receive stock." +#~ msgstr "L'emplacement %s n'est pas configuré pour recevoir du stock." + +#~ msgid "Location" +#~ msgstr "Emplacement" diff --git a/stock_location_lockdown/i18n/it.po b/stock_location_lockdown/i18n/it.po new file mode 100644 index 000000000000..4cb57c85eeaa --- /dev/null +++ b/stock_location_lockdown/i18n/it.po @@ -0,0 +1,63 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_location_lockdown +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-11-21 13:33+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: stock_location_lockdown +#: model:ir.model.fields,field_description:stock_location_lockdown.field_stock_location__block_stock_entrance +msgid "Block Stock Entrance" +msgstr "Blocco entrata magazzino" + +#. module: stock_location_lockdown +#: model:ir.model,name:stock_location_lockdown.model_stock_location +msgid "Inventory Locations" +msgstr "Ubicazioni di inventario" + +#. module: stock_location_lockdown +#. odoo-python +#: code:addons/stock_location_lockdown/models/stock_location.py:0 +#, python-format +msgid "" +"It is impossible to prohibit this location from receiving" +" products as it already contains some." +msgstr "" +"Non è possibile bloccare la ricezione di prodotti in " +"questa ubicazione perché ha già giacenze." + +#. module: stock_location_lockdown +#: model:ir.model,name:stock_location_lockdown.model_stock_quant +msgid "Quants" +msgstr "Quanti" + +#. module: stock_location_lockdown +#. odoo-python +#: code:addons/stock_location_lockdown/models/stock_quant.py:0 +#, python-format +msgid "" +"The location %(location)s is blocked and can not be used for moving the " +"product %(product)s" +msgstr "" +"L'ubicazione %(location)s è bloccata e non può essere utilizzata per " +"movimentare il prodotto %(product)s" + +#. module: stock_location_lockdown +#: model:ir.model.fields,help:stock_location_lockdown.field_stock_location__block_stock_entrance +msgid "" +"if this box is checked, putting stock on this location won't be allowed. " +"Usually used for a virtual location that has childrens." +msgstr "" +"Se selezionato, non è possibile caricare merce in questa ubicazione. " +"Normalmente utilizzato per una ubicazione virtuale con elementi derivati." diff --git a/stock_location_lockdown/i18n/pt.po b/stock_location_lockdown/i18n/pt.po new file mode 100644 index 000000000000..0b549c4715a7 --- /dev/null +++ b/stock_location_lockdown/i18n/pt.po @@ -0,0 +1,64 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_location_lockdown +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2018-12-28 01:41+0000\n" +"Last-Translator: Pedro Castro Silva \n" +"Language-Team: none\n" +"Language: pt\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.3\n" + +#. module: stock_location_lockdown +#: model:ir.model.fields,field_description:stock_location_lockdown.field_stock_location__block_stock_entrance +#, fuzzy +msgid "Block Stock Entrance" +msgstr "Bloquear entradas de stock" + +#. module: stock_location_lockdown +#: model:ir.model,name:stock_location_lockdown.model_stock_location +msgid "Inventory Locations" +msgstr "Localizações de Inventário" + +#. module: stock_location_lockdown +#. odoo-python +#: code:addons/stock_location_lockdown/models/stock_location.py:0 +#, python-format +msgid "" +"It is impossible to prohibit this location from receiving " +"products as it already contains some." +msgstr "" + +#. module: stock_location_lockdown +#: model:ir.model,name:stock_location_lockdown.model_stock_quant +msgid "Quants" +msgstr "" + +#. module: stock_location_lockdown +#. odoo-python +#: code:addons/stock_location_lockdown/models/stock_quant.py:0 +#, python-format +msgid "" +"The location %(location)s is blocked and can not be used for moving the " +"product %(product)s" +msgstr "" + +#. module: stock_location_lockdown +#: model:ir.model.fields,help:stock_location_lockdown.field_stock_location__block_stock_entrance +msgid "" +"if this box is checked, putting stock on this location won't be allowed. " +"Usually used for a virtual location that has childrens." +msgstr "" +"Se esta caixa estiver selecionada, não será permitido colocar stock nesta " +"localização. É geralmente utilizada em localizações virtuais com " +"descendentes." + +#~ msgid "The location '%s' is not configured to receive stock." +#~ msgstr "A localização '%s' não está configurada para receber stock." diff --git a/stock_location_lockdown/i18n/stock_location_lockdown.pot b/stock_location_lockdown/i18n/stock_location_lockdown.pot new file mode 100644 index 000000000000..b377cf0bcb68 --- /dev/null +++ b/stock_location_lockdown/i18n/stock_location_lockdown.pot @@ -0,0 +1,54 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_location_lockdown +# +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: stock_location_lockdown +#: model:ir.model.fields,field_description:stock_location_lockdown.field_stock_location__block_stock_entrance +msgid "Block Stock Entrance" +msgstr "" + +#. module: stock_location_lockdown +#: model:ir.model,name:stock_location_lockdown.model_stock_location +msgid "Inventory Locations" +msgstr "" + +#. module: stock_location_lockdown +#. odoo-python +#: code:addons/stock_location_lockdown/models/stock_location.py:0 +#, python-format +msgid "" +"It is impossible to prohibit this location from receiving" +" products as it already contains some." +msgstr "" + +#. module: stock_location_lockdown +#: model:ir.model,name:stock_location_lockdown.model_stock_quant +msgid "Quants" +msgstr "" + +#. module: stock_location_lockdown +#. odoo-python +#: code:addons/stock_location_lockdown/models/stock_quant.py:0 +#, python-format +msgid "" +"The location %(location)s is blocked and can not be used for moving the " +"product %(product)s" +msgstr "" + +#. module: stock_location_lockdown +#: model:ir.model.fields,help:stock_location_lockdown.field_stock_location__block_stock_entrance +msgid "" +"if this box is checked, putting stock on this location won't be allowed. " +"Usually used for a virtual location that has childrens." +msgstr "" diff --git a/stock_location_lockdown/i18n/zh_CN.po b/stock_location_lockdown/i18n/zh_CN.po new file mode 100644 index 000000000000..8de7ef6cab52 --- /dev/null +++ b/stock_location_lockdown/i18n/zh_CN.po @@ -0,0 +1,62 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_location_lockdown +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2019-10-16 16:05+0000\n" +"Last-Translator: 黎伟杰 <674416404@qq.com>\n" +"Language-Team: none\n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 3.8\n" + +#. module: stock_location_lockdown +#: model:ir.model.fields,field_description:stock_location_lockdown.field_stock_location__block_stock_entrance +msgid "Block Stock Entrance" +msgstr "阻止入库" + +#. module: stock_location_lockdown +#: model:ir.model,name:stock_location_lockdown.model_stock_location +msgid "Inventory Locations" +msgstr "库存位置" + +#. module: stock_location_lockdown +#. odoo-python +#: code:addons/stock_location_lockdown/models/stock_location.py:0 +#, python-format +msgid "" +"It is impossible to prohibit this location from receiving " +"products as it already contains some." +msgstr "因为已经包含一些产品,所以无法禁止此位置接收产品。" + +#. module: stock_location_lockdown +#: model:ir.model,name:stock_location_lockdown.model_stock_quant +msgid "Quants" +msgstr "数量分析" + +#. module: stock_location_lockdown +#. odoo-python +#: code:addons/stock_location_lockdown/models/stock_quant.py:0 +#, python-format +msgid "" +"The location %(location)s is blocked and can not be used for moving the " +"product %(product)s" +msgstr "" + +#. module: stock_location_lockdown +#: model:ir.model.fields,help:stock_location_lockdown.field_stock_location__block_stock_entrance +msgid "" +"if this box is checked, putting stock on this location won't be allowed. " +"Usually used for a virtual location that has childrens." +msgstr "如果选中此框,则不允许在此位置放货。通常用于有子位置的虚拟位置。" + +#, python-format +#~ msgid "" +#~ "The location %s is blocked and can not be used for moving the product %s" +#~ msgstr "位置%s被阻止,无法用于移动产品%s" diff --git a/stock_location_lockdown/models/__init__.py b/stock_location_lockdown/models/__init__.py new file mode 100644 index 000000000000..d081518d5f9a --- /dev/null +++ b/stock_location_lockdown/models/__init__.py @@ -0,0 +1,5 @@ +# Copyright 2019 Akretion +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import stock_location +from . import stock_quant diff --git a/stock_location_lockdown/models/stock_location.py b/stock_location_lockdown/models/stock_location.py new file mode 100644 index 000000000000..8b69b922f778 --- /dev/null +++ b/stock_location_lockdown/models/stock_location.py @@ -0,0 +1,33 @@ +# Copyright 2019 Akretion +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import _, fields, models +from odoo.exceptions import UserError + + +class StockLocation(models.Model): + _inherit = "stock.location" + + block_stock_entrance = fields.Boolean( + help="if this box is checked, putting stock on this location won't be " + "allowed. Usually used for a virtual location that has " + "childrens." + ) + + # Raise error if the location that you're trying to block + # has already got quants + def write(self, values): + res = super().write(values) + + if "block_stock_entrance" in values and values["block_stock_entrance"]: + # Unlink zero quants before checking + # if there are quants on the location + self.env["stock.quant"]._unlink_zero_quants() + if self.mapped("quant_ids"): + raise UserError( + _( + "It is impossible to prohibit this location from\ + receiving products as it already contains some." + ) + ) + return res diff --git a/stock_location_lockdown/models/stock_quant.py b/stock_location_lockdown/models/stock_quant.py new file mode 100644 index 000000000000..f23a566d556d --- /dev/null +++ b/stock_location_lockdown/models/stock_quant.py @@ -0,0 +1,26 @@ +# Copyright 2019 Akretion +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import _, api, models +from odoo.exceptions import ValidationError + + +class StockQuant(models.Model): + _inherit = "stock.quant" + + # Raise an error when trying to change a quant + # which corresponding stock location is blocked + @api.constrains("location_id") + def check_location_blocked(self): + for record in self: + if record.location_id.block_stock_entrance: + raise ValidationError( + _( + "The location %(location)s is blocked and can " + "not be used for moving the product %(product)s" + ) + % { + "location": record.location_id.display_name, + "product": record.product_id.display_name, + } + ) diff --git a/stock_location_lockdown/pyproject.toml b/stock_location_lockdown/pyproject.toml new file mode 100644 index 000000000000..4231d0cccb3d --- /dev/null +++ b/stock_location_lockdown/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/stock_location_lockdown/readme/CONTRIBUTORS.md b/stock_location_lockdown/readme/CONTRIBUTORS.md new file mode 100644 index 000000000000..32e2ef5c1242 --- /dev/null +++ b/stock_location_lockdown/readme/CONTRIBUTORS.md @@ -0,0 +1,3 @@ +- Florian da Costa \<\> +- David Montull Guasch \<\> +- Urvisha Desai \<\> diff --git a/stock_location_lockdown/readme/DESCRIPTION.md b/stock_location_lockdown/readme/DESCRIPTION.md new file mode 100644 index 000000000000..1e5b8a3d8cc8 --- /dev/null +++ b/stock_location_lockdown/readme/DESCRIPTION.md @@ -0,0 +1,12 @@ +The aim of this module is to mark internal locations where no product +should transit. Indeed, in complex warehouse setups, we may have a +complicated tree of internal locations with parent locations only used +to create the hierarchy of the internal locations. We may want to avoid +to put stock on these parent internal locations since they are not +physical locations, they just represent a zone of the warehouse. Theses +locations must have *Location Type* set to *Internal Location* because +they belong to a warehouse (they can't be configured with *Location +Type* set to *View*, cf [Odoo bug +\#26679](https://github.com/odoo/odoo/issues/26679)). With this module, +you will be able to enable a new option *Block stock entrance* for these +locations. diff --git a/stock_location_lockdown/readme/USAGE.md b/stock_location_lockdown/readme/USAGE.md new file mode 100644 index 000000000000..96634d8313a0 --- /dev/null +++ b/stock_location_lockdown/readme/USAGE.md @@ -0,0 +1,3 @@ +- Once the module is installed, select any internal location for which + you want to prevent stock entrance and check the box *Block Stock + Entrance*. Then, you won't be allow to add stock on these locations. diff --git a/stock_location_lockdown/static/description/icon.png b/stock_location_lockdown/static/description/icon.png new file mode 100644 index 000000000000..3a0328b516c4 Binary files /dev/null and b/stock_location_lockdown/static/description/icon.png differ diff --git a/stock_location_lockdown/static/description/index.html b/stock_location_lockdown/static/description/index.html new file mode 100644 index 000000000000..6addb5a27590 --- /dev/null +++ b/stock_location_lockdown/static/description/index.html @@ -0,0 +1,443 @@ + + + + + + +Stock Location Lockdown + + + +
+

Stock Location Lockdown

+ + +

Beta License: AGPL-3 OCA/stock-logistics-warehouse Translate me on Weblate Try me on Runboat

+

The aim of this module is to mark internal locations where no product +should transit. Indeed, in complex warehouse setups, we may have a +complicated tree of internal locations with parent locations only used +to create the hierarchy of the internal locations. We may want to avoid +to put stock on these parent internal locations since they are not +physical locations, they just represent a zone of the warehouse. Theses +locations must have Location Type set to Internal Location because +they belong to a warehouse (they can’t be configured with Location +Type set to View, cf Odoo bug +#26679). With this +module, you will be able to enable a new option Block stock entrance +for these locations.

+

Table of contents

+ +
+

Usage

+
    +
  • Once the module is installed, select any internal location for which +you want to prevent stock entrance and check the box Block Stock +Entrance. Then, you won’t be allow to add stock on these locations.
  • +
+
+
+

Bug Tracker

+

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

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • Akretion
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

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

+

This module is part of the OCA/stock-logistics-warehouse project on GitHub.

+

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

+
+
+
+ + diff --git a/stock_location_lockdown/tests/__init__.py b/stock_location_lockdown/tests/__init__.py new file mode 100644 index 000000000000..2f0a9ad06e2a --- /dev/null +++ b/stock_location_lockdown/tests/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2019 Akretion +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import test_block_stock_location_entrance diff --git a/stock_location_lockdown/tests/test_block_stock_location_entrance.py b/stock_location_lockdown/tests/test_block_stock_location_entrance.py new file mode 100644 index 000000000000..1f7017db9f46 --- /dev/null +++ b/stock_location_lockdown/tests/test_block_stock_location_entrance.py @@ -0,0 +1,100 @@ +# Copyright 2019 Akretion France +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.exceptions import UserError, ValidationError +from odoo.tests.common import TransactionCase + + +class TestStockLocationLockdown(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + # Create a new stock location with no quants and blocked stock entrance + new_loc = {"name": "location_test", "usage": "internal"} + cls.new_stock_location = cls.env["stock.location"].create(new_loc) + cls.new_stock_location.block_stock_entrance = True + + cls.supplier_location = cls.env.ref("stock.stock_location_suppliers") + cls.customer_location = cls.env.ref("stock.stock_location_customers") + + # Call an existing product and force no Lot/Serial Number tracking + cls.product = cls.env.ref("product.product_product_27") + cls.product.tracking = "none" + + # Catch the first quant's stock location + cls.stock_location = cls.env["stock.quant"].search([])[0].location_id + + def test_transfer_stock_in_locked_location(self): + """ + Test to move stock within a location that should not accept + stock entrance. + """ + move_vals = { + "location_id": self.supplier_location.id, + "location_dest_id": self.new_stock_location.id, + "product_id": self.product.id, + "product_uom_qty": self.product.qty_available + 1, + "quantity": self.product.qty_available + 1, + "picked": True, + "product_uom": self.product.uom_id.id, + "name": "test", + "move_line_ids": [ + ( + 0, + 0, + { + "product_id": self.product.id, + "product_uom_id": self.product.uom_id.id, + "quantity": self.product.qty_available + 1, + "location_id": self.supplier_location.id, + "location_dest_id": self.new_stock_location.id, + }, + ) + ], + } + stock_move = self.env["stock.move"].create(move_vals) + + with self.assertRaises(ValidationError): + stock_move._action_done() + + def test_transfer_stock_out_locked_location(self): + """ + Test to move stock out from a location that should not accept + stock removal. + """ + move_vals = { + "location_id": self.new_stock_location.id, + "location_dest_id": self.customer_location.id, + "product_id": self.product.id, + "product_uom_qty": self.product.qty_available + 1, + "quantity": self.product.qty_available + 1, + "picked": True, + "product_uom": self.product.uom_id.id, + "name": "test", + "move_line_ids": [ + ( + 0, + 0, + { + "product_id": self.product.id, + "product_uom_id": self.product.uom_id.id, + "quantity": self.product.qty_available + 1, + "location_id": self.supplier_location.id, + "location_dest_id": self.new_stock_location.id, + }, + ) + ], + } + stock_move = self.env["stock.move"].create(move_vals) + + with self.assertRaises(ValidationError): + stock_move._action_done() + + def test_block_location_with_quants(self): + """ + Test to click on block_stock_entrance checkbox in a location + that should not be blocked because it has already got quants + """ + with self.assertRaises(UserError): + self.stock_location.write({"block_stock_entrance": True}) diff --git a/stock_location_lockdown/views/stock_location.xml b/stock_location_lockdown/views/stock_location.xml new file mode 100644 index 000000000000..2b03277b93aa --- /dev/null +++ b/stock_location_lockdown/views/stock_location.xml @@ -0,0 +1,16 @@ + + + + + + stock.location + + + + + + + + +