From 2fe84fd2171c5b96807bc1f98ae4c46c1e55c26b Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Tue, 7 Nov 2017 09:00:38 +0100 Subject: [PATCH] [FIX] stock: a view location cannot contain any quant --- addons/stock/models/stock_location.py | 7 +++++++ addons/stock/models/stock_quant.py | 6 ++++++ addons/stock/tests/test_quant.py | 29 +++++++++++++++++++++++++-- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/addons/stock/models/stock_location.py b/addons/stock/models/stock_location.py index db80965fbfe..0dc090173f2 100644 --- a/addons/stock/models/stock_location.py +++ b/addons/stock/models/stock_location.py @@ -66,6 +66,7 @@ class Location(models.Model): removal_strategy_id = fields.Many2one('product.removal', 'Removal Strategy', help="Defines the default method used for suggesting the exact location (shelf) where to take the products from, which lot etc. for this location. This method can be enforced at the product category level, and a fallback is made on the parent locations if none is set here.") putaway_strategy_id = fields.Many2one('product.putaway', 'Put Away Strategy', help="Defines the default method used for suggesting the exact location (shelf) where to store the products. This method can be enforced at the product category level, and a fallback is made on the parent locations if none is set here.") barcode = fields.Char('Barcode', copy=False, oldname='loc_barcode') + quant_ids = fields.One2many('stock.quant', 'location_id') _sql_constraints = [('barcode_company_uniq', 'unique (barcode,company_id)', 'The barcode for a location must be unique per company !')] @@ -80,6 +81,12 @@ class Location(models.Model): name = '%s/%s' % (current.name, name) self.complete_name = name + def write(self, values): + if 'usage' in values and values['usage'] == 'view': + if self.mapped('quant_ids'): + raise UserError(_("This location's usage cannot be changed to view as it contains products.")) + return super(Location, self).write(values) + def name_get(self): ret_list = [] for location in self: diff --git a/addons/stock/models/stock_quant.py b/addons/stock/models/stock_quant.py index c6d5700c366..4a8170d9f4e 100644 --- a/addons/stock/models/stock_quant.py +++ b/addons/stock/models/stock_quant.py @@ -80,6 +80,12 @@ class StockQuant(models.Model): if quant.in_date and not quant.lot_id: raise ValidationError(_('An incoming date cannot be set to an untracked product.')) + @api.constrains('location_id') + def check_location_id(self): + for quant in self: + if quant.location_id.usage == 'view': + raise ValidationError(_('A product cannot be stored in a "view" location.')) + @api.one def _compute_name(self): self.name = '%s: %s%s' % (self.lot_id.name or self.product_id.code or '', self.quantity, self.product_id.uom_id.name) diff --git a/addons/stock/tests/test_quant.py b/addons/stock/tests/test_quant.py index f28fa3c4ef2..bff1f902ba5 100644 --- a/addons/stock/tests/test_quant.py +++ b/addons/stock/tests/test_quant.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +from datetime import datetime, timedelta + from odoo.exceptions import ValidationError from odoo.tests.common import TransactionCase from odoo.exceptions import AccessError, UserError -from datetime import datetime, timedelta - class StockQuant(TransactionCase): def setUp(self): @@ -275,6 +275,31 @@ class StockQuant(TransactionCase): self.assertEqual(self.env['stock.quant']._get_available_quantity(product2, stock_location), 2.0) self.assertEqual(self.env['stock.quant']._get_available_quantity(product2, stock_sub_location), 1.0) + def test_increase_available_quantity_6(self): + """ Increasing the available quantity in a view location should be forbidden. + """ + stock_location = self.env.ref('stock.stock_location_stock') + location1 = self.env['stock.location'].create({ + 'name': 'viewloc1', + 'usage': 'view', + 'location_id': stock_location.id, + }) + product1 = self.env['product.product'].create({ + 'name': 'Product A', + 'type': 'product', + }) + with self.assertRaises(ValidationError): + self.env['stock.quant']._update_available_quantity(product1, location1, 1.0) + + def test_increase_available_quantity_7(self): + """ Setting a location's usage as "view" should be forbidden if it already + contains quant. + """ + stock_location = self.env.ref('stock.stock_location_stock') + self.assertTrue(len(stock_location.quant_ids.ids) > 0) + with self.assertRaises(UserError): + stock_location.usage = 'view' + def test_decrease_available_quantity_1(self): """ Decrease the available quantity when no quants are already in a location. """