refactor the module to perform lockdown validations using constraint

in stock move instead of checks in quants. This will allow for a more
 robust lockdown, and still make it possible to perform inventory adjustments
 in the locked location. Also resolves an outstanding issue related to the
 previous design not allowing inventory adjustments where negative quants existed.
This commit is contained in:
Jordi Ballester
2017-06-27 12:24:38 +02:00
committed by Ben Stannard
parent b1f4d9244e
commit 28fbc3c5d2
6 changed files with 32 additions and 59 deletions

View File

@@ -39,6 +39,10 @@ Contributors
* Loïc Bellier (Numérigraphe) <lb@numerigraphe.com> * Loïc Bellier (Numérigraphe) <lb@numerigraphe.com>
* Lionel Sausin (Numérigraphe) <ls@numerigraphe.com> * Lionel Sausin (Numérigraphe) <ls@numerigraphe.com>
* Laetitia Gangloff (Acsone) <laetitia.gangloff@acsone.eu> * Laetitia Gangloff (Acsone) <laetitia.gangloff@acsone.eu>
* Laurent Mignon (Acsone) <laurent.mignon@acsone.eu>
* Lois Rilo (Eficent) <lois.rilo@eficent.com>
* Jordi Ballester (Eficent) <jordi.ballester@eficent.com>
Maintainer Maintainer
---------- ----------

View File

@@ -5,7 +5,7 @@
{ {
"name": "Inventory Lock Down", "name": "Inventory Lock Down",
"summary": "Lock down stock locations during inventories.", "summary": "Lock down stock locations during inventories.",
"version": "9.0.1.0.0", "version": "9.0.1.0.1",
"depends": ["stock"], "depends": ["stock"],
"author": "Numérigraphe,Odoo Community Association (OCA)", "author": "Numérigraphe,Odoo Community Association (OCA)",
"category": "Warehouse Management", "category": "Warehouse Management",

View File

@@ -2,6 +2,6 @@
# © 2013-2016 Numérigraphe SARL # © 2013-2016 Numérigraphe SARL
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import stock_quant from . import stock_move
from . import stock_inventory from . import stock_inventory
from . import stock_location from . import stock_location

View File

@@ -27,9 +27,3 @@ class StockInventory(models.Model):
if locations_ids: if locations_ids:
location_domain.append(('location_id', 'child_of', locations_ids)) location_domain.append(('location_id', 'child_of', locations_ids))
return self.env['stock.location'].search(location_domain) return self.env['stock.location'].search(location_domain)
@api.multi
def action_done(self):
"""Add value in the context to ignore the lockdown"""
return super(StockInventory,
self.with_context(bypass_lockdown=True)).action_done()

View File

@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# © 2016 Numérigraphe SARL
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from openerp import models, api, _
from openerp.exceptions import ValidationError
class StockMove(models.Model):
_inherit = 'stock.move'
@api.constrains('location_dest_id', 'location_id', 'state')
def _check_locked_location(self):
for move in self:
if move.state == 'draft':
continue
locked_location_ids = self.env[
'stock.inventory']._get_locations_open_inventories(
[move.location_dest_id.id, move.location_id.id])
if (locked_location_ids and
move.product_id.property_stock_inventory not in [
move.location_dest_id, move.location_id]):
location_names = locked_location_ids.mapped('complete_name')
raise ValidationError(
_('An inventory is being conducted at the following '
'location(s):\n%s') % "\n - ".join(location_names))

View File

@@ -1,51 +0,0 @@
# -*- coding: utf-8 -*-
# © 2016 Numérigraphe SARL
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from openerp import models, api, _
from openerp.exceptions import ValidationError
class StockQuant(models.Model):
_inherit = 'stock.quant'
@api.multi
def write(self, vals):
"""Check that the location is not locked by an open inventory.
Check both the location as it was (source) and the location as
it will be (destination).
We verify the locations even if they are unchanged, because changing
ie. the quantity is not acceptable either.
@raise ValidationError if they are.
"""
if not self.env.context.get('bypass_lockdown', False):
# Find the locked locations
locked_location_ids = []
if 'location_id' in vals.keys():
locked_location_ids = self.env[
'stock.inventory']._get_locations_open_inventories(
self.env['stock.location'].browse(
vals['location_id']).ids + self.mapped(
'location_id').ids
)
if locked_location_ids:
location_names = locked_location_ids.mapped('name')
raise ValidationError(
_('An inventory is being conducted at the following '
'location(s):\n%s') % "\n - ".join(location_names))
return super(StockQuant, self).write(vals)
@api.model
def create(self, vals):
"""Check that the locations are not locked by an open inventory.
@raise ValidationError if they are.
"""
quant = super(StockQuant, self).create(vals)
if not self.env.context.get('bypass_lockdown', False):
locked_location_ids = self.env['stock.inventory'].\
_get_locations_open_inventories(quant.location_id.ids)
if locked_location_ids:
raise ValidationError(
_('An inventory is being conducted at the following '
'location(s):\n%s') % " - " + quant.location_id.name)
return quant