diff options
| author | svs-odoo <svs@odoo.com> | 2019-05-03 08:02:16 +0000 |
|---|---|---|
| committer | svs-odoo <svs@odoo.com> | 2019-05-29 13:59:01 +0000 |
| commit | da33eb36b80d1b2a0004c28cf20d6b0263bcb643 (patch) | |
| tree | e3a93c2ab2bac21dc43401013af28f491429d1a8 /addons/stock/tests/test_quant_inventory_mode.py | |
| parent | be2795513644f09f6b443f462bb67cc5a0762e8d (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.py | 215 |
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) |
