mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
[10.0][FIX] stock_inventory_lockdown: locking unneded locations.
This commit is contained in:
@@ -5,13 +5,13 @@
|
|||||||
{
|
{
|
||||||
"name": "Inventory Lock Down",
|
"name": "Inventory Lock Down",
|
||||||
"summary": "Lock down stock locations during inventories.",
|
"summary": "Lock down stock locations during inventories.",
|
||||||
"version": "10.0.1.0.0",
|
"version": "10.0.1.0.1",
|
||||||
"depends": ["stock"],
|
"depends": ["stock"],
|
||||||
"author": "Numérigraphe,Eficent,Odoo Community Association (OCA)",
|
"author": "Numérigraphe, Eficent, Odoo Community Association (OCA)",
|
||||||
"category": "Warehouse Management",
|
"category": "Warehouse Management",
|
||||||
"images": [
|
"images": [
|
||||||
"images/move_error.png",
|
"images/move_error.png",
|
||||||
"images/location_locked.png"],
|
"images/location_locked.png"],
|
||||||
'license': 'AGPL-3',
|
"license": "AGPL-3",
|
||||||
"installable": True,
|
"installable": True,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,4 @@ class StockInventory(models.Model):
|
|||||||
location_domain = [
|
location_domain = [
|
||||||
('location_id', 'child_of', location_ids.ids),
|
('location_id', 'child_of', location_ids.ids),
|
||||||
('usage', 'in', ['internal', 'transit'])]
|
('usage', 'in', ['internal', 'transit'])]
|
||||||
if 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)
|
||||||
|
|||||||
@@ -11,15 +11,32 @@ from odoo.exceptions import ValidationError
|
|||||||
class StockMove(models.Model):
|
class StockMove(models.Model):
|
||||||
_inherit = 'stock.move'
|
_inherit = 'stock.move'
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def _get_reserved_locations(self):
|
||||||
|
self.ensure_one()
|
||||||
|
return self.reserved_quant_ids.mapped('location_id') + \
|
||||||
|
self.split_from.reserved_quant_ids.mapped('location_id')
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def _get_dest_locations(self):
|
||||||
|
self.ensure_one()
|
||||||
|
return self.linked_move_operation_ids.mapped(
|
||||||
|
'operation_id.location_dest_id')
|
||||||
|
|
||||||
@api.constrains('location_dest_id', 'location_id', 'state')
|
@api.constrains('location_dest_id', 'location_id', 'state')
|
||||||
def _check_locked_location(self):
|
def _check_locked_location(self):
|
||||||
for move in self.filtered(lambda m: m.state != 'draft'):
|
for move in self.filtered(lambda m: m.state != 'draft'):
|
||||||
locked_location_ids = self.env[
|
locked_location_ids = self.env[
|
||||||
'stock.inventory']._get_locations_open_inventories(
|
'stock.inventory']._get_locations_open_inventories(
|
||||||
[move.location_dest_id.id, move.location_id.id])
|
[move.location_dest_id.id, move.location_id.id])
|
||||||
|
reserved_locs = move._get_reserved_locations()
|
||||||
|
dest_locs = move._get_dest_locations()
|
||||||
if (locked_location_ids and
|
if (locked_location_ids and
|
||||||
move.product_id.property_stock_inventory not in [
|
move.product_id.property_stock_inventory not in [
|
||||||
move.location_dest_id, move.location_id]):
|
move.location_dest_id, move.location_id] and
|
||||||
|
(move.location_dest_id in locked_location_ids or
|
||||||
|
any([l in locked_location_ids for l in dest_locs]) or
|
||||||
|
any([l in locked_location_ids for l in reserved_locs]))):
|
||||||
location_names = locked_location_ids.mapped('complete_name')
|
location_names = locked_location_ids.mapped('complete_name')
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
_('An inventory is being conducted at the following '
|
_('An inventory is being conducted at the following '
|
||||||
|
|||||||
@@ -10,10 +10,14 @@ from odoo.addons.stock.tests.common import TestStockCommon
|
|||||||
class StockInventoryLocationTest(TestStockCommon):
|
class StockInventoryLocationTest(TestStockCommon):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(StockInventoryLocationTest, self).setUp()
|
super(StockInventoryLocationTest, self).setUp()
|
||||||
# Make a new location
|
# Make a new location with a parent and a child.
|
||||||
|
self.new_parent_location = self.env['stock.location'].create(
|
||||||
|
{'name': 'Test parent location',
|
||||||
|
'usage': 'internal'})
|
||||||
self.new_location = self.env['stock.location'].create(
|
self.new_location = self.env['stock.location'].create(
|
||||||
{'name': 'Test location',
|
{'name': 'Test location',
|
||||||
'usage': 'internal'})
|
'usage': 'internal',
|
||||||
|
'location_id': self.new_parent_location.id})
|
||||||
self.new_sublocation = self.env['stock.location'].create(
|
self.new_sublocation = self.env['stock.location'].create(
|
||||||
{'name': 'Test sublocation',
|
{'name': 'Test sublocation',
|
||||||
'usage': 'internal',
|
'usage': 'internal',
|
||||||
@@ -23,6 +27,10 @@ class StockInventoryLocationTest(TestStockCommon):
|
|||||||
{'location_id': self.new_location.id,
|
{'location_id': self.new_location.id,
|
||||||
'product_id': self.productA.id,
|
'product_id': self.productA.id,
|
||||||
'qty': 10.0})
|
'qty': 10.0})
|
||||||
|
self.env['stock.quant'].create(
|
||||||
|
{'location_id': self.new_parent_location.id,
|
||||||
|
'product_id': self.productB.id,
|
||||||
|
'qty': 5.0})
|
||||||
# Prepare an inventory
|
# Prepare an inventory
|
||||||
self.inventory = self.env['stock.inventory'].create(
|
self.inventory = self.env['stock.inventory'].create(
|
||||||
{'name': 'Lock down location',
|
{'name': 'Lock down location',
|
||||||
@@ -31,6 +39,16 @@ class StockInventoryLocationTest(TestStockCommon):
|
|||||||
self.inventory.prepare_inventory()
|
self.inventory.prepare_inventory()
|
||||||
self.assertTrue(self.inventory.line_ids, 'The inventory is empty.')
|
self.assertTrue(self.inventory.line_ids, 'The inventory is empty.')
|
||||||
|
|
||||||
|
def create_stock_move(self, product, origin_id=False, dest_id=False):
|
||||||
|
return self.env['stock.move'].create({
|
||||||
|
'name': 'Test move lock down',
|
||||||
|
'product_id': product.id,
|
||||||
|
'product_uom_qty': 10.0,
|
||||||
|
'product_uom': product.uom_id.id,
|
||||||
|
'location_id': origin_id or self.supplier_location,
|
||||||
|
'location_dest_id': dest_id or self.customer_location,
|
||||||
|
})
|
||||||
|
|
||||||
def test_update_parent_location(self):
|
def test_update_parent_location(self):
|
||||||
"""Updating the parent of a location is OK if no inv. in progress."""
|
"""Updating the parent of a location is OK if no inv. in progress."""
|
||||||
self.inventory.action_cancel_draft()
|
self.inventory.action_cancel_draft()
|
||||||
@@ -73,14 +91,37 @@ class StockInventoryLocationTest(TestStockCommon):
|
|||||||
location=line.location_id.id).qty_available, 22.0)
|
location=line.location_id.id).qty_available, 22.0)
|
||||||
|
|
||||||
def test_move(self):
|
def test_move(self):
|
||||||
"""Stock move must be forbidden during inventory"""
|
"""Stock moves must be forbidden during inventory from/to inventoried
|
||||||
move = self.env['stock.move'].create({
|
location."""
|
||||||
'name': 'Test move lock down',
|
move1 = self.create_stock_move(
|
||||||
'product_id': self.productA.id,
|
self.productA, origin_id=self.inventory.location_id.id)
|
||||||
'product_uom_qty': 10.0,
|
move1.action_confirm()
|
||||||
'product_uom': self.productA.uom_id.id,
|
|
||||||
'location_id': self.inventory.location_id.id,
|
|
||||||
'location_dest_id': self.customer_location
|
|
||||||
})
|
|
||||||
with self.assertRaises(ValidationError):
|
with self.assertRaises(ValidationError):
|
||||||
move.action_done()
|
move1.action_assign()
|
||||||
|
move1.action_done()
|
||||||
|
move2 = self.create_stock_move(
|
||||||
|
self.productA, dest_id=self.inventory.location_id.id)
|
||||||
|
with self.assertRaises(ValidationError):
|
||||||
|
move2.action_confirm()
|
||||||
|
move2.action_assign()
|
||||||
|
move2.action_done()
|
||||||
|
|
||||||
|
def test_move_reserved_quants(self):
|
||||||
|
"""Shipping stock should be allowed or not depending on reserved
|
||||||
|
quants' locations.
|
||||||
|
* move1: quants are fetched from the parent location.
|
||||||
|
* move2: quants are fetched from 'new location' which is being
|
||||||
|
inventoried."""
|
||||||
|
move1 = self.create_stock_move(
|
||||||
|
self.productB, self.new_parent_location.id)
|
||||||
|
move1.action_confirm()
|
||||||
|
move1.action_assign()
|
||||||
|
move1.action_done()
|
||||||
|
self.assertEqual(
|
||||||
|
move1.state, 'done', 'Move has not been completed')
|
||||||
|
move2 = self.create_stock_move(
|
||||||
|
self.productA, self.new_parent_location.id)
|
||||||
|
move2.action_confirm()
|
||||||
|
with self.assertRaises(ValidationError):
|
||||||
|
move2.action_assign()
|
||||||
|
move2.action_done()
|
||||||
|
|||||||
Reference in New Issue
Block a user