summaryrefslogtreecommitdiff
path: root/addons/stock/tests/test_quant_inventory_mode.py
diff options
context:
space:
mode:
authorsvs-odoo <svs@odoo.com>2019-05-03 08:02:16 +0000
committersvs-odoo <svs@odoo.com>2019-05-29 13:59:01 +0000
commitda33eb36b80d1b2a0004c28cf20d6b0263bcb643 (patch)
treee3a93c2ab2bac21dc43401013af28f491429d1a8 /addons/stock/tests/test_quant_inventory_mode.py
parentbe2795513644f09f6b443f462bb67cc5a0762e8d (diff)
[IMP] stock: editable quants
Made some changes in stock.quant model to allow user to modify product quantity easier. To allow the edition of quant without opening more permissions on the model, we switch to sudo in create mode and write if the conditions are met (special key in context + access rights on the current user + write on a specific field). Also, we have two list views for the quant: - The old list view who still readonly. - A new list view where user can create new quant or edit quantity of existing ones We display the second one if user is a stock manager. For existing quants, user can modify counted quantity (which will modify product quantity). User can also create new quant, in this case: - The quant is really a new one (ex.: new product/location association) so will simply create a new quant. - A corresponding quant already exist, so will modify the existing quant instead of create a new one. When an user creates a new quant, the model will check each time a non-quantity field (product, location, SN/LN, package or owner) is modified to see if corresponding quant exists. In this case, it'll get the quant ID and will update reserved and on hand quantities. If user didn't change the inventory quantity, it'll be updated too. On product form view, the 'Update quantity' button was removed as user can now simply modify quant with 'On Hand' stat button. Task #1935921 Co-authored-by: sle-odoo <sle@odoo.com>
Diffstat (limited to 'addons/stock/tests/test_quant_inventory_mode.py')
-rw-r--r--addons/stock/tests/test_quant_inventory_mode.py215
1 files changed, 215 insertions, 0 deletions
diff --git a/addons/stock/tests/test_quant_inventory_mode.py b/addons/stock/tests/test_quant_inventory_mode.py
new file mode 100644
index 00000000000..98f8d064cad
--- /dev/null
+++ b/addons/stock/tests/test_quant_inventory_mode.py
@@ -0,0 +1,215 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo.tests.common import SavepointCase
+from odoo.exceptions import AccessError, UserError
+
+
+class TestEditableQuant(SavepointCase):
+ @classmethod
+ def setUpClass(cls):
+ super(TestEditableQuant, cls).setUpClass()
+
+ # Shortcut to call `stock.quant` with `inventory mode` set in the context
+ cls.Quant = cls.env['stock.quant'].with_context(inventory_mode=True)
+
+ Product = cls.env['product.product']
+ Location = cls.env['stock.location']
+ cls.product = Product.create({
+ 'name': 'Product A',
+ 'type': 'product',
+ 'categ_id': cls.env.ref('product.product_category_all').id,
+ })
+ cls.product2 = Product.create({
+ 'name': 'Product B',
+ 'type': 'product',
+ 'categ_id': cls.env.ref('product.product_category_all').id,
+ })
+ cls.product_tracked_sn = Product.create({
+ 'name': 'Product tracked by SN',
+ 'type': 'product',
+ 'tracking': 'serial',
+ 'categ_id': cls.env.ref('product.product_category_all').id,
+ })
+ cls.warehouse = Location.create({
+ 'name': 'Warehouse',
+ 'usage': 'internal',
+ })
+ cls.stock = Location.create({
+ 'name': 'Stock',
+ 'usage': 'internal',
+ 'location_id': cls.warehouse.id,
+ })
+ cls.room1 = Location.create({
+ 'name': 'Room A',
+ 'usage': 'internal',
+ 'location_id': cls.stock.id,
+ })
+ cls.room2 = Location.create({
+ 'name': 'Room B',
+ 'usage': 'internal',
+ 'location_id': cls.stock.id,
+ })
+ cls.inventory_loss = cls.product.property_stock_inventory
+
+ def test_create_quant_1(self):
+ """ Create a new quant who don't exist yet.
+ """
+ # Checks we don't have any quant for this product.
+ quants = self.env['stock.quant'].search([('product_id', '=', self.product.id)])
+ self.assertEqual(len(quants), 0)
+ self.Quant.create({
+ 'product_id': self.product.id,
+ 'location_id': self.stock.id,
+ 'inventory_quantity': 24
+ })
+ quants = self.env['stock.quant'].search([
+ ('product_id', '=', self.product.id),
+ ('quantity', '>', 0),
+ ])
+ # Checks we have now a quant, and also checks the quantity is equals to
+ # what we set in `inventory_quantity` field.
+ self.assertEqual(len(quants), 1)
+ self.assertEqual(quants.quantity, 24)
+
+ stock_move = self.env['stock.move'].search([
+ ('product_id', '=', self.product.id),
+ ])
+ self.assertEqual(stock_move.location_id.id, self.inventory_loss.id)
+ self.assertEqual(stock_move.location_dest_id.id, self.stock.id)
+
+ def test_create_quant_2(self):
+ """ Try to create a quant who already exist.
+ Must update the existing quant instead of creating a new one.
+ """
+ # Creates a quants...
+ first_quant = self.Quant.create({
+ 'product_id': self.product.id,
+ 'location_id': self.room1.id,
+ 'quantity': 12,
+ })
+ quants = self.env['stock.quant'].search([
+ ('product_id', '=', self.product.id),
+ ('quantity', '>', 0),
+ ])
+ self.assertEqual(len(quants), 1)
+ # ... then try to create an another quant for the same product/location.
+ second_quant = self.Quant.create({
+ 'product_id': self.product.id,
+ 'location_id': self.room1.id,
+ 'inventory_quantity': 24,
+ })
+ quants = self.env['stock.quant'].search([
+ ('product_id', '=', self.product.id),
+ ('quantity', '>', 0),
+ ])
+ # Checks we still have only one quant, and first quant quantity was
+ # updated, and second quant had the same ID than the first quant.
+ self.assertEqual(len(quants), 1)
+ self.assertEqual(first_quant.quantity, 24)
+ self.assertEqual(first_quant.id, second_quant.id)
+ stock_move = self.env['stock.move'].search([
+ ('product_id', '=', self.product.id),
+ ])
+ self.assertEqual(len(stock_move), 1)
+
+ def test_create_quant_3(self):
+ """ Try to create a quant with `inventory_quantity` but not in inventory mode.
+ Creates two quants not in inventory mode:
+ - One with `quantity` (this one must be OK)
+ - One with `inventory_quantity` (this one must be null)
+ """
+ valid_quant = self.env['stock.quant'].create({
+ 'product_id': self.product.id,
+ 'location_id': self.room1.id,
+ 'quantity': 10,
+ })
+ invalid_quant = self.env['stock.quant'].create({
+ 'product_id': self.product2.id,
+ 'location_id': self.room1.id,
+ 'inventory_quantity': 20,
+ })
+ self.assertEqual(valid_quant.quantity, 10)
+ self.assertEqual(invalid_quant.quantity, 0)
+
+ def test_create_quant_4(self):
+ """ Try to create tree quants in inventory mode with `quantity` and/or `inventory_quantity`.
+ Creates two quants not in inventory mode:
+ - One with `quantity` (this one must be OK, but `inventory_mode` is useless here as it
+ doesn't enter in the inventory mode case and create quant as usual)
+ - One with `inventory_quantity` (this one must be OK)
+ - One with the two values (this one must raises an error as it enters in the inventory
+ mode but user can't edit directly `quantity` in inventory mode)
+ """
+ valid_quant = self.env['stock.quant'].with_context(inventory_mode=True).create({
+ 'product_id': self.product.id,
+ 'location_id': self.room1.id,
+ 'quantity': 10,
+ })
+ inventoried_quant = self.env['stock.quant'].with_context(inventory_mode=True).create({
+ 'product_id': self.product2.id,
+ 'location_id': self.room1.id,
+ 'inventory_quantity': 20,
+ })
+ with self.assertRaises(UserError):
+ invalid_quant = self.env['stock.quant'].with_context(inventory_mode=True).create({
+ 'product_id': self.product.id,
+ 'location_id': self.room2.id,
+ 'quantity': 10,
+ 'inventory_quantity': 20,
+ })
+ self.assertEqual(valid_quant.quantity, 10)
+ self.assertEqual(inventoried_quant.quantity, 20)
+
+ def test_edit_quant_1(self):
+ """ Increases manually quantity of a quant.
+ """
+ quant = self.Quant.create({
+ 'product_id': self.product.id,
+ 'location_id': self.room1.id,
+ 'quantity': 12,
+ })
+ quant.inventory_quantity = 24
+ self.assertEqual(quant.quantity, 24)
+ stock_move = self.env['stock.move'].search([
+ ('product_id', '=', self.product.id),
+ ])
+ self.assertEqual(stock_move.location_id.id, self.inventory_loss.id)
+ self.assertEqual(stock_move.location_dest_id.id, self.room1.id)
+
+ def test_edit_quant_2(self):
+ """ Decreases manually quantity of a quant.
+ """
+ quant = self.Quant.create({
+ 'product_id': self.product.id,
+ 'location_id': self.room1.id,
+ 'quantity': 12,
+ })
+ quant.inventory_quantity = 8
+ self.assertEqual(quant.quantity, 8)
+ stock_move = self.env['stock.move'].search([
+ ('product_id', '=', self.product.id),
+ ])
+ self.assertEqual(stock_move.location_id.id, self.room1.id)
+ self.assertEqual(stock_move.location_dest_id.id, self.inventory_loss.id)
+
+ def test_edit_quant_3(self):
+ """ Try to edit a record without the inventory mode.
+ Must raise an error.
+ """
+ user_demo = self.env.ref('base.user_demo')
+ user_admin = self.env.ref('base.user_admin')
+ quant = self.Quant.create({
+ 'product_id': self.product.id,
+ 'location_id': self.room1.id,
+ 'quantity': 12
+ })
+ self.assertEqual(quant.quantity, 12)
+ # Try to write on quant without permission
+ with self.assertRaises(AccessError):
+ quant.sudo(user_demo).write({'inventory_quantity': 8})
+ self.assertEqual(quant.quantity, 12)
+
+ # Try to write on quant with permission
+ quant.sudo(user_admin).write({'inventory_quantity': 8})
+ self.assertEqual(quant.quantity, 8)