Merge PR #2123 into 17.0

Signed-off-by pedrobaeza
This commit is contained in:
OCA-git-bot
2024-08-01 16:54:33 +00:00
17 changed files with 1193 additions and 0 deletions

View File

@@ -0,0 +1,101 @@
========================
Stock archive constraint
========================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:429fc0b78c525b9f08b711b0303b0c65ad452fdad9eb36c1b54c065dd22182ac
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
:target: https://odoo-community.org/page/development-status
:alt: Production/Stable
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github
:target: https://github.com/OCA/stock-logistics-warehouse/tree/17.0/stock_archive_constraint
: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_archive_constraint
: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|
Allows to block archiving products with associated stock.quant or
stock.move. Allows to block archiving locations with associated
stock.quant or stock.move.
**Table of contents**
.. contents::
:local:
Usage
=====
1. Go to Settings > Users > Edit a user and check the "Manage Multiple
Stock Locations" permission
2. Go to Inventory > Settings > Locations and archive one
3. Go to inventory > Products > Products and try to archive one product
associated to stock picking
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/stock-logistics-warehouse/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 <https://github.com/OCA/stock-logistics-warehouse/issues/new?body=module:%20stock_archive_constraint%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
-------
* Tecnativa
Contributors
------------
- `Tecnativa <https://www.tecnativa.com>`__:
..
- Carlos Daudén
- Víctor Martínez
- César A. Sánchez
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-victoralmau| image:: https://github.com/victoralmau.png?size=40px
:target: https://github.com/victoralmau
:alt: victoralmau
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-victoralmau|
This module is part of the `OCA/stock-logistics-warehouse <https://github.com/OCA/stock-logistics-warehouse/tree/17.0/stock_archive_constraint>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

@@ -0,0 +1,3 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import models

View File

@@ -0,0 +1,15 @@
# Copyright 2020 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
"name": "Stock archive constraint",
"version": "17.0.1.0.0",
"license": "AGPL-3",
"website": "https://github.com/OCA/stock-logistics-warehouse",
"author": "Tecnativa, Odoo Community Association (OCA)",
"development_status": "Production/Stable",
"category": "Warehouse",
"depends": ["stock"],
"installable": True,
"maintainers": ["victoralmau"],
}

View File

@@ -0,0 +1,87 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * stock_archive_constraint
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-07-27 19:55+0000\n"
"PO-Revision-Date: 2022-07-27 19:55+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_archive_constraint
#: model:ir.model,name:stock_archive_constraint.model_stock_location
msgid "Inventory Locations"
msgstr "Ubicaciones de inventario"
#. module: stock_archive_constraint
#: code:addons/stock_archive_constraint/models/stock_location.py:0
#, python-format
msgid ""
"It is not possible to archive location '%(display_name)s' which has "
"associated picking lines."
msgstr ""
"No es posible archivar la ubicación '%(display_name)s' que tiene líneas de "
"albarán asociadas."
#. module: stock_archive_constraint
#: code:addons/stock_archive_constraint/models/stock_location.py:0
#, python-format
msgid ""
"It is not possible to archive location '%(display_name)s' which has "
"associated stock quantities."
msgstr ""
"No es posible archivar la ubicación '%(display_name)s' que tiene cantidades "
"asociadas de stock."
#. module: stock_archive_constraint
#: code:addons/stock_archive_constraint/models/stock_location.py:0
#, python-format
msgid ""
"It is not possible to archive location '%(display_name)s' which has "
"associated stock reservations."
msgstr ""
"No es posible archivar la ubicación '%(display_name)s' que tiene reservas "
"asociadas."
#. module: stock_archive_constraint
#: code:addons/stock_archive_constraint/models/product_product.py:0
#, python-format
msgid ""
"It is not possible to archive product '%(display_name)s' which has "
"associated picking lines."
msgstr ""
"No es posible archivar el producto '%(display_name)s' que tiene lineas de "
"albarán asociadas."
#. module: stock_archive_constraint
#: code:addons/stock_archive_constraint/models/product_product.py:0
#, python-format
msgid ""
"It is not possible to archive product '%(display_name)s' which has "
"associated stock quantities."
msgstr ""
"No es posible archivar el producto '%(display_name)s' que tiene cantidades "
"asociadas de stock."
#. module: stock_archive_constraint
#: code:addons/stock_archive_constraint/models/product_product.py:0
#, python-format
msgid ""
"It is not possible to archive product '%(display_name)s' which has "
"associated stock reservations."
msgstr ""
"No es posible archivar el producto '%(display_name)s' que tiene reservas "
"asociadas."
#. module: stock_archive_constraint
#: model:ir.model,name:stock_archive_constraint.model_product_product
msgid "Product"
msgstr "Producto"

View File

@@ -0,0 +1,87 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * stock_archive_constraint
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2023-12-18 09:34+0000\n"
"Last-Translator: mymage <stefano.consolaro@mymage.it>\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_archive_constraint
#: model:ir.model,name:stock_archive_constraint.model_stock_location
msgid "Inventory Locations"
msgstr "Ubicazioni di inventario"
#. module: stock_archive_constraint
#: code:addons/stock_archive_constraint/models/stock_location.py:0
#, python-format
msgid ""
"It is not possible to archive location '%(display_name)s' which has "
"associated picking lines."
msgstr ""
"Non è possibile archiviare l'ubicazione '%(display_name)s' che è associata a "
"righe di prelievo."
#. module: stock_archive_constraint
#: code:addons/stock_archive_constraint/models/stock_location.py:0
#, python-format
msgid ""
"It is not possible to archive location '%(display_name)s' which has "
"associated stock quantities."
msgstr ""
"Non è possibile archiviare l'ubicazione '%(display_name)s' che è associata a "
"giacenze di magazzino."
#. module: stock_archive_constraint
#: code:addons/stock_archive_constraint/models/stock_location.py:0
#, python-format
msgid ""
"It is not possible to archive location '%(display_name)s' which has "
"associated stock reservations."
msgstr ""
"Non è possibile archiviare l'ubicazione '%(display_name)s' che è associata a "
"prenotazioni di magazzino."
#. module: stock_archive_constraint
#: code:addons/stock_archive_constraint/models/product_product.py:0
#, python-format
msgid ""
"It is not possible to archive product '%(display_name)s' which has "
"associated picking lines."
msgstr ""
"Non è possibile archiviare il prodotto '%(display_name)s' che è associato a "
"righe di prelievo."
#. module: stock_archive_constraint
#: code:addons/stock_archive_constraint/models/product_product.py:0
#, python-format
msgid ""
"It is not possible to archive product '%(display_name)s' which has "
"associated stock quantities."
msgstr ""
"Non è possibile archiviare il prodotto '%(display_name)s' che è associato a "
"giacenze di magazzino."
#. module: stock_archive_constraint
#: code:addons/stock_archive_constraint/models/product_product.py:0
#, python-format
msgid ""
"It is not possible to archive product '%(display_name)s' which has "
"associated stock reservations."
msgstr ""
"Non è possibile archiviare il prodotto '%(display_name)s' che è associato a "
"prenotazioni di magazzino."
#. module: stock_archive_constraint
#: model:ir.model,name:stock_archive_constraint.model_product_product
msgid "Product"
msgstr "Prodotto"

View File

@@ -0,0 +1,72 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * stock_archive_constraint
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.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_archive_constraint
#: model:ir.model,name:stock_archive_constraint.model_stock_location
msgid "Inventory Locations"
msgstr ""
#. module: stock_archive_constraint
#: code:addons/stock_archive_constraint/models/stock_location.py:0
#, python-format
msgid ""
"It is not possible to archive location '%(display_name)s' which has "
"associated picking lines."
msgstr ""
#. module: stock_archive_constraint
#: code:addons/stock_archive_constraint/models/stock_location.py:0
#, python-format
msgid ""
"It is not possible to archive location '%(display_name)s' which has "
"associated stock quantities."
msgstr ""
#. module: stock_archive_constraint
#: code:addons/stock_archive_constraint/models/stock_location.py:0
#, python-format
msgid ""
"It is not possible to archive location '%(display_name)s' which has "
"associated stock reservations."
msgstr ""
#. module: stock_archive_constraint
#: code:addons/stock_archive_constraint/models/product_product.py:0
#, python-format
msgid ""
"It is not possible to archive product '%(display_name)s' which has "
"associated picking lines."
msgstr ""
#. module: stock_archive_constraint
#: code:addons/stock_archive_constraint/models/product_product.py:0
#, python-format
msgid ""
"It is not possible to archive product '%(display_name)s' which has "
"associated stock quantities."
msgstr ""
#. module: stock_archive_constraint
#: code:addons/stock_archive_constraint/models/product_product.py:0
#, python-format
msgid ""
"It is not possible to archive product '%(display_name)s' which has "
"associated stock reservations."
msgstr ""
#. module: stock_archive_constraint
#: model:ir.model,name:stock_archive_constraint.model_product_product
msgid "Product"
msgstr ""

View File

@@ -0,0 +1,5 @@
# Copyright 2020 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import product_product
from . import stock_location

View File

@@ -0,0 +1,79 @@
# Copyright 2020 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import _, api, models
from odoo.exceptions import ValidationError
from odoo.tools import config
class ProductProduct(models.Model):
_inherit = "product.product"
def _skip_check_archive_constraint_condition(self):
return config["test_enable"] and not self.env.context.get(
"test_stock_archive_constraint"
)
@api.constrains("active")
def _check_active_stock_archive_constraint_stock_quant(self):
if self._skip_check_archive_constraint_condition():
return
res = self.env["stock.quant"].search(
[
("location_id.usage", "in", ("internal", "transit")),
("product_id", "in", self.filtered(lambda x: not x.active).ids),
("quantity", "!=", 0.0),
],
limit=1,
)
if res:
raise ValidationError(
_(
"It is not possible to archive product "
"'%(display_name)s' which has "
"associated stock quantities."
)
% {"display_name": res.product_id.display_name}
)
@api.constrains("active")
def _check_active_stock_archive_constraint_stock_move(self):
if self._skip_check_archive_constraint_condition():
return
res = self.env["stock.move"].search(
[
("product_id", "in", self.filtered(lambda x: not x.active).ids),
("state", "not in", ("done", "cancel")),
],
limit=1,
)
if res:
raise ValidationError(
_(
"It is not possible to archive product "
"'%(display_name)s' which has "
"associated picking lines."
)
% {"display_name": res.product_id.display_name}
)
@api.constrains("active")
def _check_active_stock_archive_constraint_stock_move_line(self):
if self._skip_check_archive_constraint_condition():
return
res = self.env["stock.move.line"].search(
[
("product_id", "in", self.filtered(lambda x: not x.active).ids),
("state", "not in", ("done", "cancel")),
],
limit=1,
)
if res:
raise ValidationError(
_(
"It is not possible to archive product "
"'%(display_name)s' which has "
"associated stock reservations."
)
% {"display_name": res.product_id.display_name}
)

View File

@@ -0,0 +1,87 @@
# Copyright 2020 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import _, api, models
from odoo.exceptions import ValidationError
from odoo.tools import config
class StockLocation(models.Model):
_inherit = "stock.location"
def _skip_check_archive_constraint_condition(self):
return config["test_enable"] and not self.env.context.get(
"test_stock_archive_constraint"
)
@api.constrains("active")
def _check_active_stock_archive_constraint_stock_quant(self):
if self._skip_check_archive_constraint_condition():
return
res = self.env["stock.quant"].search(
[
"&",
("location_id.usage", "in", ("internal", "transit")),
"|",
("location_id", "in", self.filtered(lambda x: not x.active).ids),
("location_id", "child_of", self.filtered(lambda x: not x.active).ids),
],
limit=1,
)
if res:
raise ValidationError(
_(
"It is not possible to archive location "
"'%(display_name)s' which has "
"associated stock quantities."
)
% {"display_name": res.display_name}
)
@api.constrains("active")
def _check_active_stock_archive_constraint_stock_move(self):
if self._skip_check_archive_constraint_condition():
return
res = self.env["stock.move"].search(
[
"&",
("state", "not in", ("done", "cancel")),
"|",
("location_id", "in", self.filtered(lambda x: not x.active).ids),
("location_id", "child_of", self.filtered(lambda x: not x.active).ids),
],
limit=1,
)
if res:
raise ValidationError(
_(
"It is not possible to archive location "
"'%(display_name)s' which has "
"associated picking lines."
)
% {"display_name": res.display_name}
)
@api.constrains("active")
def _check_active_stock_archive_constraint_stock_move_line(self):
if self._skip_check_archive_constraint_condition():
return
res = self.env["stock.move.line"].search(
[
"&",
("state", "not in", ("done", "cancel")),
"|",
("location_id", "in", self.filtered(lambda x: not x.active).ids),
("location_id", "child_of", self.filtered(lambda x: not x.active).ids),
],
limit=1,
)
if res:
raise ValidationError(
_(
"It is not possible to archive location "
"'%(display_name)s' which has "
"associated stock reservations."
)
% {"display_name": res.display_name}
)

View File

@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"

View File

@@ -0,0 +1,5 @@
- [Tecnativa](https://www.tecnativa.com):
> - Carlos Daudén
> - Víctor Martínez
> - César A. Sánchez

View File

@@ -0,0 +1,3 @@
Allows to block archiving products with associated stock.quant or
stock.move. Allows to block archiving locations with associated
stock.quant or stock.move.

View File

@@ -0,0 +1,4 @@
1. Go to Settings \> Users \> Edit a user and check the "Manage
Multiple Stock Locations" permission
2. Go to Inventory \> Settings \> Locations and archive one
3. Go to inventory \> Products \> Products and try to archive one product associated to stock picking

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -0,0 +1,446 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>Stock archive constraint</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic, pre.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="stock-archive-constraint">
<h1 class="title">Stock archive constraint</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:429fc0b78c525b9f08b711b0303b0c65ad452fdad9eb36c1b54c065dd22182ac
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Production/Stable" src="https://img.shields.io/badge/maturity-Production%2FStable-green.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/stock-logistics-warehouse/tree/17.0/stock_archive_constraint"><img alt="OCA/stock-logistics-warehouse" src="https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/stock-logistics-warehouse-17-0/stock-logistics-warehouse-17-0-stock_archive_constraint"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/stock-logistics-warehouse&amp;target_branch=17.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>Allows to block archiving products with associated stock.quant or
stock.move. Allows to block archiving locations with associated
stock.quant or stock.move.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#usage" id="toc-entry-1">Usage</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-2">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-3">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-4">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-5">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-6">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#toc-entry-1">Usage</a></h1>
<ol class="arabic simple">
<li>Go to Settings &gt; Users &gt; Edit a user and check the “Manage Multiple
Stock Locations” permission</li>
<li>Go to Inventory &gt; Settings &gt; Locations and archive one</li>
<li>Go to inventory &gt; Products &gt; Products and try to archive one product
associated to stock picking</li>
</ol>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/issues">GitHub Issues</a>.
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
<a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/issues/new?body=module:%20stock_archive_constraint%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#toc-entry-3">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-4">Authors</a></h2>
<ul class="simple">
<li>Tecnativa</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-5">Contributors</a></h2>
<ul class="simple">
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:</li>
</ul>
<!-- -->
<blockquote>
<ul class="simple">
<li>Carlos Daudén</li>
<li>Víctor Martínez</li>
<li>César A. Sánchez</li>
</ul>
</blockquote>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
</a>
<p>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.</p>
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
<p><a class="reference external image-reference" href="https://github.com/victoralmau"><img alt="victoralmau" src="https://github.com/victoralmau.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/tree/17.0/stock_archive_constraint">OCA/stock-logistics-warehouse</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,4 @@
# Copyright 2020 Tecnativa - Víctor Martínez
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from . import test_location_archive_constraint

View File

@@ -0,0 +1,192 @@
# Copyright 2021 Tecnativa - Víctor Martínez
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from odoo.exceptions import ValidationError
from odoo.tests.common import Form
from odoo.addons.base.tests.common import BaseCommon
class TestLocationArchiveConstraint(BaseCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(
context=dict(cls.env.context, test_stock_archive_constraint=True)
)
cls.company = cls.env.ref("base.main_company")
cls.product_1 = cls._create_product(cls, "Product 1")
cls.product_2 = cls._create_product(cls, "Product 2")
stock_location_stock = cls.env.ref("stock.stock_location_stock")
cls.stock_location = cls._create_stock_location(
cls, "%s (Copy)" % (stock_location_stock.name)
)
cls.stock_location_child = cls._create_stock_location(
cls, "%s (Child)" % (cls.stock_location.name)
)
cls.stock_location_child.location_id = cls.stock_location
def _create_product(self, name):
product_form = Form(self.env["product.product"])
product_form.name = name
product_form.detailed_type = "product"
return product_form.save()
def _create_stock_location(self, name):
stock_location_form = Form(self.env["stock.location"])
stock_location_form.name = name
stock_location_form.usage = self.env.ref("stock.stock_location_stock").usage
return stock_location_form.save()
def _create_stock_quant(self, location_id, product_id, qty):
self.env["stock.quant"].create(
{
"company_id": self.company.id,
"location_id": location_id.id,
"product_id": product_id.id,
"quantity": qty,
}
)
def _create_stock_move(self, location_id, location_dest_id, product_id, qty):
stock_move_form = Form(self.env["stock.move"])
stock_move_form.location_id = location_id
stock_move_form.location_dest_id = location_dest_id
stock_move_form.product_id = product_id
stock_move_form.product_uom_qty = qty
stock_move = stock_move_form.save()
stock_move._action_done()
def _create_stock_move_line(self, location_id, location_dest_id, product_id, qty):
self.env["stock.move.line"].create(
{
"company_id": self.company.id,
"location_id": location_id.id,
"location_dest_id": location_dest_id.id,
"product_id": product_id.id,
"product_uom_id": product_id.uom_id.id,
"quantity": qty,
"state": "done",
}
)
def _create_stock_picking(self, location_id, location_dest_id, product_id, qty):
stock_picking_form = Form(self.env["stock.picking"])
stock_picking_form.picking_type_id = self.env.ref("stock.picking_type_in")
with stock_picking_form.move_ids_without_package.new() as line:
line.product_id = product_id
line.product_uom_qty = qty
stock_picking = stock_picking_form.save()
stock_picking.write(
{"location_id": location_id.id, "location_dest_id": location_dest_id.id}
)
stock_picking.action_confirm()
for line in stock_picking.move_ids_without_package:
line.quantity = line.product_uom_qty
stock_picking.button_validate()
def test_archive_product_ok(self):
self.product_1.active = False
self.assertFalse(self.product_1.active)
self.product_2.active = False
self.assertFalse(self.product_2.active)
def test_archive_unarchive_product(self):
self.product_1.active = False
self.assertFalse(self.product_1.active)
self.product_1.active = True
self.assertTrue(self.product_1.active)
def test_archive_product_with_stock_move_in(self):
self._create_stock_move(
self.env.ref("stock.stock_location_suppliers"),
self.stock_location,
self.product_2,
20.00,
)
self.product_1.active = False
self.assertFalse(self.product_1.active)
with self.assertRaises(ValidationError):
self.product_2.active = False
def test_archive_product_with_stock_move_line_in(self):
self._create_stock_move_line(
self.env.ref("stock.stock_location_suppliers"),
self.stock_location,
self.product_2,
20.00,
)
self.product_1.active = False
self.assertFalse(self.product_1.active)
with self.assertRaises(ValidationError):
self.product_2.active = False
def test_archive_product_with_stock_picking_in(self):
self._create_stock_picking(
self.env.ref("stock.stock_location_suppliers"),
self.stock_location,
self.product_2,
20.00,
)
self.product_1.active = False
self.assertFalse(self.product_1.active)
with self.assertRaises(ValidationError):
self.product_2.active = False
def test_archive_product_with_stock_picking_in_out(self):
self._create_stock_picking(
self.env.ref("stock.stock_location_suppliers"),
self.stock_location,
self.product_2,
20.00,
)
self._create_stock_picking(
self.stock_location,
self.env.ref("stock.stock_location_customers"),
self.product_2,
20.00,
)
self.product_1.active = False
self.assertFalse(self.product_1.active)
self.product_2.active = False
self.assertFalse(self.product_2.active)
def test_archive_product_stock_location(self):
self._create_stock_quant(self.stock_location, self.product_2, 20.00)
self.product_1.active = False
self.assertFalse(self.product_1.active)
with self.assertRaises(ValidationError):
self.product_2.active = False
def test_archive_product_stock_location_child(self):
self._create_stock_quant(self.stock_location_child, self.product_2, 20.00)
self.product_1.active = False
self.assertFalse(self.product_1.active)
with self.assertRaises(ValidationError):
self.product_2.active = False
def test_archive_unarchive_stock_location(self):
self.stock_location.active = False
self.assertFalse(self.stock_location.active)
self.stock_location.active = True
self.assertTrue(self.stock_location.active)
def test_archive_stock_location_ok(self):
self.stock_location.active = False
self.assertFalse(self.stock_location.active)
def test_archive_stock_location(self):
self._create_stock_quant(self.stock_location, self.product_2, 20.00)
with self.assertRaises(ValidationError):
self.stock_location.with_context(do_not_check_quant=True).active = False
def test_archive_unarchive_stock_location_child(self):
self.stock_location_child.active = False
self.assertFalse(self.stock_location_child.active)
self.stock_location_child.active = True
self.assertTrue(self.stock_location_child.active)
def test_archive_stock_location_child(self):
self._create_stock_quant(self.stock_location_child, self.product_2, 20.00)
with self.assertRaises(ValidationError):
self.stock_location.with_context(do_not_check_quant=True).active = False