[REF] stock: speedup tests

before on runbot:
odoo.addons.stock.tests.test_move tested in 31.79s, 63166 queries
odoo.addons.stock.tests.test_move2 tested in 33.69s, 68046 queries
odoo.addons.stock.tests.test_quant tested in 8.48s, 15351 queries
odoo.addons.stock.tests.test_stock_flow tested in 16.99s, 31506 queries
amounting to 90 seconds on a build page

after om runbot:
odoo.addons.stock.tests.test_move tested in 12.41s, 24197 queries
odoo.addons.stock.tests.test_move2 tested in 13.55s, 24254 queries
odoo.addons.stock.tests.test_stock_flow tested in 9.74s, 15795 queries
amounting to 37 seconds on a build page

Use savepoint case instead of transaction case.

We took the opportunity to rename the master data more appropriately,
which results now in a bigger diff in TestMove and TestQuant. In
TestQuant, the master data creation had to be moved in the setUpClass
too.

We removed test_shipment as test_backorder_1-4 in tet_move_2 covers the
same parts of the code.
This commit is contained in:
Simon Lejeune
2019-04-15 07:32:32 +00:00
parent 12da02d161
commit c5ff803fcc
10 changed files with 938 additions and 1163 deletions
-1
View File
@@ -3,7 +3,6 @@
from . import test_stock_flow
from . import test_product
from . import test_warehouse
from . import test_shipment
from . import test_stock_location_search
from . import test_quant
from . import test_inventory
+55 -54
View File
@@ -3,98 +3,99 @@
from odoo.tests import common
class TestStockCommon(common.TransactionCase):
class TestStockCommon(common.SavepointCase):
def setUp(self):
super(TestStockCommon, self).setUp()
@classmethod
def setUpClass(cls):
super(TestStockCommon, cls).setUpClass()
self.ProductObj = self.env['product.product']
self.UomObj = self.env['uom.uom']
self.PartnerObj = self.env['res.partner']
self.ModelDataObj = self.env['ir.model.data']
self.StockPackObj = self.env['stock.move.line']
self.StockQuantObj = self.env['stock.quant']
self.PickingObj = self.env['stock.picking']
self.MoveObj = self.env['stock.move']
self.InvObj = self.env['stock.inventory']
self.InvLineObj = self.env['stock.inventory.line']
self.LotObj = self.env['stock.production.lot']
cls.ProductObj = cls.env['product.product']
cls.UomObj = cls.env['uom.uom']
cls.PartnerObj = cls.env['res.partner']
cls.ModelDataObj = cls.env['ir.model.data']
cls.StockPackObj = cls.env['stock.move.line']
cls.StockQuantObj = cls.env['stock.quant']
cls.PickingObj = cls.env['stock.picking']
cls.MoveObj = cls.env['stock.move']
cls.InvObj = cls.env['stock.inventory']
cls.InvLineObj = cls.env['stock.inventory.line']
cls.LotObj = cls.env['stock.production.lot']
# Model Data
self.partner_agrolite_id = self.ModelDataObj.xmlid_to_res_id('base.res_partner_2')
self.partner_delta_id = self.ModelDataObj.xmlid_to_res_id('base.res_partner_4')
self.picking_type_in = self.ModelDataObj.xmlid_to_res_id('stock.picking_type_in')
self.picking_type_out = self.ModelDataObj.xmlid_to_res_id('stock.picking_type_out')
self.supplier_location = self.ModelDataObj.xmlid_to_res_id('stock.stock_location_suppliers')
self.stock_location = self.ModelDataObj.xmlid_to_res_id('stock.stock_location_stock')
pack_location = self.env.ref('stock.location_pack_zone')
cls.partner_agrolite_id = cls.ModelDataObj.xmlid_to_res_id('base.res_partner_2')
cls.partner_delta_id = cls.ModelDataObj.xmlid_to_res_id('base.res_partner_4')
cls.picking_type_in = cls.ModelDataObj.xmlid_to_res_id('stock.picking_type_in')
cls.picking_type_out = cls.ModelDataObj.xmlid_to_res_id('stock.picking_type_out')
cls.supplier_location = cls.ModelDataObj.xmlid_to_res_id('stock.stock_location_suppliers')
cls.stock_location = cls.ModelDataObj.xmlid_to_res_id('stock.stock_location_stock')
pack_location = cls.env.ref('stock.location_pack_zone')
pack_location.active = True
self.pack_location = pack_location.id
output_location = self.env.ref('stock.stock_location_output')
cls.pack_location = pack_location.id
output_location = cls.env.ref('stock.stock_location_output')
output_location.active = True
self.output_location = output_location.id
self.customer_location = self.ModelDataObj.xmlid_to_res_id('stock.stock_location_customers')
self.categ_unit = self.ModelDataObj.xmlid_to_res_id('uom.product_uom_categ_unit')
self.categ_kgm = self.ModelDataObj.xmlid_to_res_id('uom.product_uom_categ_kgm')
cls.output_location = output_location.id
cls.customer_location = cls.ModelDataObj.xmlid_to_res_id('stock.stock_location_customers')
cls.categ_unit = cls.ModelDataObj.xmlid_to_res_id('uom.product_uom_categ_unit')
cls.categ_kgm = cls.ModelDataObj.xmlid_to_res_id('uom.product_uom_categ_kgm')
# Product Created A, B, C, D
self.productA = self.ProductObj.create({'name': 'Product A', 'type': 'product'})
self.productB = self.ProductObj.create({'name': 'Product B', 'type': 'product'})
self.productC = self.ProductObj.create({'name': 'Product C', 'type': 'product'})
self.productD = self.ProductObj.create({'name': 'Product D', 'type': 'product'})
self.productE = self.ProductObj.create({'name': 'Product E', 'type': 'product'})
cls.productA = cls.ProductObj.create({'name': 'Product A', 'type': 'product'})
cls.productB = cls.ProductObj.create({'name': 'Product B', 'type': 'product'})
cls.productC = cls.ProductObj.create({'name': 'Product C', 'type': 'product'})
cls.productD = cls.ProductObj.create({'name': 'Product D', 'type': 'product'})
cls.productE = cls.ProductObj.create({'name': 'Product E', 'type': 'product'})
# Configure unit of measure.
self.uom_kg = self.env['uom.uom'].search([('category_id', '=', self.categ_kgm), ('uom_type', '=', 'reference')], limit=1)
self.uom_kg.write({
cls.uom_kg = cls.env['uom.uom'].search([('category_id', '=', cls.categ_kgm), ('uom_type', '=', 'reference')], limit=1)
cls.uom_kg.write({
'name': 'Test-KG',
'rounding': 0.000001})
self.uom_tone = self.UomObj.create({
cls.uom_tone = cls.UomObj.create({
'name': 'Test-Tone',
'category_id': self.categ_kgm,
'category_id': cls.categ_kgm,
'uom_type': 'bigger',
'factor_inv': 1000.0,
'rounding': 0.001})
self.uom_gm = self.UomObj.create({
cls.uom_gm = cls.UomObj.create({
'name': 'Test-G',
'category_id': self.categ_kgm,
'category_id': cls.categ_kgm,
'uom_type': 'smaller',
'factor': 1000.0,
'rounding': 0.001})
self.uom_mg = self.UomObj.create({
cls.uom_mg = cls.UomObj.create({
'name': 'Test-MG',
'category_id': self.categ_kgm,
'category_id': cls.categ_kgm,
'uom_type': 'smaller',
'factor': 100000.0,
'rounding': 0.001})
# Check Unit
self.uom_unit = self.env['uom.uom'].search([('category_id', '=', self.categ_unit), ('uom_type', '=', 'reference')], limit=1)
self.uom_unit.write({
cls.uom_unit = cls.env['uom.uom'].search([('category_id', '=', cls.categ_unit), ('uom_type', '=', 'reference')], limit=1)
cls.uom_unit.write({
'name': 'Test-Unit',
'rounding': 1.0})
self.uom_dozen = self.UomObj.create({
cls.uom_dozen = cls.UomObj.create({
'name': 'Test-DozenA',
'category_id': self.categ_unit,
'category_id': cls.categ_unit,
'factor_inv': 12,
'uom_type': 'bigger',
'rounding': 0.001})
self.uom_sdozen = self.UomObj.create({
cls.uom_sdozen = cls.UomObj.create({
'name': 'Test-SDozenA',
'category_id': self.categ_unit,
'category_id': cls.categ_unit,
'factor_inv': 144,
'uom_type': 'bigger',
'rounding': 0.001})
self.uom_sdozen_round = self.UomObj.create({
cls.uom_sdozen_round = cls.UomObj.create({
'name': 'Test-SDozenA Round',
'category_id': self.categ_unit,
'category_id': cls.categ_unit,
'factor_inv': 144,
'uom_type': 'bigger',
'rounding': 1.0})
# Product for different unit of measure.
self.DozA = self.ProductObj.create({'name': 'Dozon-A', 'type': 'product', 'uom_id': self.uom_dozen.id, 'uom_po_id': self.uom_dozen.id})
self.SDozA = self.ProductObj.create({'name': 'SuperDozon-A', 'type': 'product', 'uom_id': self.uom_sdozen.id, 'uom_po_id': self.uom_sdozen.id})
self.SDozARound = self.ProductObj.create({'name': 'SuperDozenRound-A', 'type': 'product', 'uom_id': self.uom_sdozen_round.id, 'uom_po_id': self.uom_sdozen_round.id})
self.UnitA = self.ProductObj.create({'name': 'Unit-A', 'type': 'product'})
self.kgB = self.ProductObj.create({'name': 'kg-B', 'type': 'product', 'uom_id': self.uom_kg.id, 'uom_po_id': self.uom_kg.id})
self.gB = self.ProductObj.create({'name': 'g-B', 'type': 'product', 'uom_id': self.uom_gm.id, 'uom_po_id': self.uom_gm.id})
cls.DozA = cls.ProductObj.create({'name': 'Dozon-A', 'type': 'product', 'uom_id': cls.uom_dozen.id, 'uom_po_id': cls.uom_dozen.id})
cls.SDozA = cls.ProductObj.create({'name': 'SuperDozon-A', 'type': 'product', 'uom_id': cls.uom_sdozen.id, 'uom_po_id': cls.uom_sdozen.id})
cls.SDozARound = cls.ProductObj.create({'name': 'SuperDozenRound-A', 'type': 'product', 'uom_id': cls.uom_sdozen_round.id, 'uom_po_id': cls.uom_sdozen_round.id})
cls.UnitA = cls.ProductObj.create({'name': 'Unit-A', 'type': 'product'})
cls.kgB = cls.ProductObj.create({'name': 'kg-B', 'type': 'product', 'uom_id': cls.uom_kg.id, 'uom_po_id': cls.uom_kg.id})
cls.gB = cls.ProductObj.create({'name': 'g-B', 'type': 'product', 'uom_id': cls.uom_gm.id, 'uom_po_id': cls.uom_gm.id})
+14 -13
View File
@@ -1,27 +1,28 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.exceptions import ValidationError
from odoo.tests.common import TransactionCase
from odoo.tests.common import SavepointCase
class TestInventory(TransactionCase):
def setUp(self):
super(TestInventory, self).setUp()
self.stock_location = self.env.ref('stock.stock_location_stock')
self.pack_location = self.env.ref('stock.location_pack_zone')
self.pack_location.active = True
self.customer_location = self.env.ref('stock.stock_location_customers')
self.uom_unit = self.env.ref('uom.product_uom_unit')
self.product1 = self.env['product.product'].create({
class TestInventory(SavepointCase):
@classmethod
def setUpClass(cls):
super(TestInventory, cls).setUpClass()
cls.stock_location = cls.env.ref('stock.stock_location_stock')
cls.pack_location = cls.env.ref('stock.location_pack_zone')
cls.pack_location.active = True
cls.customer_location = cls.env.ref('stock.stock_location_customers')
cls.uom_unit = cls.env.ref('uom.product_uom_unit')
cls.product1 = cls.env['product.product'].create({
'name': 'Product A',
'type': 'product',
'categ_id': self.env.ref('product.product_category_all').id,
'categ_id': cls.env.ref('product.product_category_all').id,
})
self.product2 = self.env['product.product'].create({
cls.product2 = cls.env['product.product'].create({
'name': 'Product A',
'type': 'product',
'tracking': 'serial',
'categ_id': self.env.ref('product.product_category_all').id,
'categ_id': cls.env.ref('product.product_category_all').id,
})
def test_inventory_1(self):
File diff suppressed because it is too large Load Diff
+13 -14
View File
@@ -1,22 +1,22 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.tests.common import TransactionCase
from odoo.tests.common import SavepointCase
class TestPacking(TransactionCase):
class TestPacking(SavepointCase):
@classmethod
def setUpClass(cls):
super(TestPacking, cls).setUpClass()
cls.stock_location = cls.env.ref('stock.stock_location_stock')
cls.warehouse = cls.env['stock.warehouse'].search([('lot_stock_id', '=', cls.stock_location.id)], limit=1)
cls.warehouse.write({'delivery_steps': 'pick_pack_ship'})
cls.pack_location = cls.warehouse.wh_pack_stock_loc_id
cls.ship_location = cls.warehouse.wh_output_stock_loc_id
cls.customer_location = cls.env.ref('stock.stock_location_customers')
def setUp(self):
super(TestPacking, self).setUp()
self.stock_location = self.env.ref('stock.stock_location_stock')
self.warehouse = self.env['stock.warehouse'].search([('lot_stock_id', '=', self.stock_location.id)], limit=1)
self.warehouse.write({'delivery_steps': 'pick_pack_ship'})
self.pack_location = self.warehouse.wh_pack_stock_loc_id
self.ship_location = self.warehouse.wh_output_stock_loc_id
self.customer_location = self.env.ref('stock.stock_location_customers')
self.productA = self.env['product.product'].create({'name': 'Product A', 'type': 'product'})
self.productB = self.env['product.product'].create({'name': 'Product B', 'type': 'product'})
cls.productA = cls.env['product.product'].create({'name': 'Product A', 'type': 'product'})
cls.productB = cls.env['product.product'].create({'name': 'Product B', 'type': 'product'})
def test_put_in_pack(self):
""" In a pick pack ship scenario, create two packs in pick and check that
@@ -88,7 +88,6 @@ class TestPacking(TransactionCase):
packing_picking.package_level_ids.write({'is_done': True})
packing_picking.action_done()
def test_pick_a_pack_confirm(self):
pack = self.env['stock.quant.package'].create({'name': 'The pack to pick'})
self.env['stock.quant']._update_available_quantity(self.productA, self.stock_location, 20.0, package_id=pack)
-1
View File
@@ -8,7 +8,6 @@ from odoo.addons.stock.tests.common2 import TestStockCommon
class TestVirtualAvailable(TestStockCommon):
def setUp(self):
super(TestVirtualAvailable, self).setUp()
+221 -380
View File
@@ -5,28 +5,50 @@ from contextlib import closing
from datetime import datetime, timedelta
from odoo.exceptions import ValidationError
from odoo.tests.common import TransactionCase
from odoo.tests.common import SavepointCase
from odoo.exceptions import AccessError, UserError
class StockQuant(TransactionCase):
def setUp(self):
super(StockQuant, self).setUp()
Users = self.env['res.users'].with_context({'no_reset_password': True, 'mail_create_nosubscribe': True})
self.demo_user = Users.create({
class StockQuant(SavepointCase):
@classmethod
def setUpClass(cls):
super(StockQuant, cls).setUpClass()
Users = cls.env['res.users'].with_context({'no_reset_password': True, 'mail_create_nosubscribe': True})
cls.demo_user = Users.create({
'name': 'Pauline Poivraisselle',
'login': 'pauline',
'email': 'p.p@example.com',
'notification_type': 'inbox',
'groups_id': [(6, 0, [self.env.ref('base.group_user').id])]
'groups_id': [(6, 0, [cls.env.ref('base.group_user').id])]
})
self.stock_user = Users.create({
cls.stock_user = Users.create({
'name': 'Pauline Poivraisselle',
'login': 'pauline2',
'email': 'p.p@example.com',
'notification_type': 'inbox',
'groups_id': [(6, 0, [self.env.ref('stock.group_stock_user').id])]
'groups_id': [(6, 0, [cls.env.ref('stock.group_stock_user').id])]
})
cls.product = cls.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
cls.product_lot = cls.env['product.product'].create({
'name': 'Product A',
'type': 'product',
'tracking': 'lot',
})
cls.product_consu = cls.env['product.product'].create({
'name': 'Product A',
'type': 'consu',
})
cls.product_serial = cls.env['product.product'].create({
'name': 'Product A',
'type': 'product',
'tracking': 'serial',
})
cls.stock_location = cls.env.ref('stock.stock_location_stock')
def gather_relevant(self, product_id, location_id, lot_id=None, package_id=None, owner_id=None, strict=False):
quants = self.env['stock.quant']._gather(product_id, location_id, lot_id=lot_id, package_id=package_id, owner_id=owner_id, strict=strict)
return quants.filtered(lambda q: not (q.quantity == 0 and q.reserved_quantity == 0))
@@ -34,572 +56,432 @@ class StockQuant(TransactionCase):
def test_get_available_quantity_1(self):
""" Quantity availability with only one quant in a location.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 1.0,
})
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 1.0)
def test_get_available_quantity_2(self):
""" Quantity availability with multiple quants in a location.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
for i in range(3):
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 1.0,
})
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 3.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 3.0)
def test_get_available_quantity_3(self):
""" Quantity availability with multiple quants (including negatives ones) in a location.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
for i in range(3):
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 1.0,
})
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': -3.0,
})
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 0.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 0.0)
def test_get_available_quantity_4(self):
""" Quantity availability with no quants in a location.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 0.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 0.0)
def test_get_available_quantity_5(self):
""" Quantity availability with multiple partially reserved quants in a location.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 10.0,
'reserved_quantity': 9.0,
})
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 1.0,
'reserved_quantity': 1.0,
})
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 1.0)
def test_get_available_quantity_6(self):
""" Quantity availability with multiple partially reserved quants in a location.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 10.0,
'reserved_quantity': 20.0,
})
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 5.0,
'reserved_quantity': 0.0,
})
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 0.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location, allow_negative=True), -5.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 0.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location, allow_negative=True), -5.0)
def test_get_available_quantity_7(self):
""" Quantity availability with only one tracked quant in a location.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
'tracking': 'lot',
})
lot1 = self.env['stock.production.lot'].create({
'name': 'lot1',
'product_id': product1.id,
'product_id': self.product_lot.id,
})
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product_lot.id,
'location_id': self.stock_location.id,
'quantity': 10.0,
'reserved_quantity': 20.0,
'lot_id': lot1.id,
})
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location, lot_id=lot1), 0.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location, lot_id=lot1, allow_negative=True), -10.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product_lot, self.stock_location, lot_id=lot1), 0.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product_lot, self.stock_location, lot_id=lot1, allow_negative=True), -10.0)
def test_get_available_quantity_8(self):
""" Quantity availability with a consumable product.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'consu',
})
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 0.0)
self.assertEqual(len(self.gather_relevant(product1, stock_location)), 0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product_consu, self.stock_location), 0.0)
self.assertEqual(len(self.gather_relevant(self.product_consu, self.stock_location)), 0)
with self.assertRaises(ValidationError):
self.env['stock.quant']._update_available_quantity(product1, stock_location, 1.0)
self.env['stock.quant']._update_available_quantity(self.product_consu, self.stock_location, 1.0)
def test_get_available_quantity_9(self):
""" Quantity availability by a demo user with access rights/rules.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 1.0,
})
self.env = self.env(user=self.env.ref('base.user_demo'))
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 1.0)
def test_increase_available_quantity_1(self):
""" Increase the available quantity when no quants are already in a location.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
self.env['stock.quant']._update_available_quantity(product1, stock_location, 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 1.0)
self.env['stock.quant']._update_available_quantity(self.product, self.stock_location, 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 1.0)
def test_increase_available_quantity_2(self):
""" Increase the available quantity when multiple quants are already in a location.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
for i in range(2):
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 1.0,
})
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 2.0)
self.env['stock.quant']._update_available_quantity(product1, stock_location, 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 3.0)
self.assertEqual(len(self.gather_relevant(product1, stock_location)), 2)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 2.0)
self.env['stock.quant']._update_available_quantity(self.product, self.stock_location, 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 3.0)
self.assertEqual(len(self.gather_relevant(self.product, self.stock_location)), 2)
def test_increase_available_quantity_3(self):
""" Increase the available quantity when a concurrent transaction is already increasing
the reserved quanntity for the same product.
"""
stock_location = self.env.ref('stock.stock_location_stock')
quant = self.env['stock.quant'].search([('location_id', '=', stock_location.id)], limit=1)
quant = self.env['stock.quant'].search([('location_id', '=', self.stock_location.id)], limit=1)
product = quant.product_id
available_quantity = self.env['stock.quant']._get_available_quantity(product, stock_location)
available_quantity = self.env['stock.quant']._get_available_quantity(product, self.stock_location)
# opens a new cursor and SELECT FOR UPDATE the quant, to simulate another concurrent reserved
# quantity increase
with closing(self.registry.cursor()) as cr:
cr.execute("SELECT id FROM stock_quant WHERE product_id=%s AND location_id=%s", (product.id, stock_location.id))
cr.execute("SELECT id FROM stock_quant WHERE product_id=%s AND location_id=%s", (product.id, self.stock_location.id))
quant_id = cr.fetchone()
cr.execute("SELECT 1 FROM stock_quant WHERE id=%s FOR UPDATE", quant_id)
self.env['stock.quant']._update_available_quantity(product, stock_location, 1.0)
self.env['stock.quant']._update_available_quantity(product, self.stock_location, 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product, stock_location), available_quantity + 1)
self.assertEqual(len(self.gather_relevant(product, stock_location, strict=True)), 2)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product, self.stock_location), available_quantity + 1)
self.assertEqual(len(self.gather_relevant(product, self.stock_location, strict=True)), 2)
def test_increase_available_quantity_4(self):
""" Increase the available quantity when no quants are already in a location with a user without access right.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
self.env = self.env(user=self.env.ref('base.user_demo'))
self.env['stock.quant']._update_available_quantity(product1, stock_location, 1.0)
self.env['stock.quant']._update_available_quantity(self.product, self.stock_location, 1.0)
def test_increase_available_quantity_5(self):
""" Increase the available quantity when no quants are already in stock.
Increase a subLocation and check that quants are in this location. Also test inverse.
"""
stock_location = self.env.ref('stock.stock_location_stock')
stock_sub_location = stock_location.child_ids[0]
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
stock_sub_location = self.stock_location.child_ids[0]
product2 = self.env['product.product'].create({
'name': 'Product B',
'type': 'product',
})
self.env['stock.quant']._update_available_quantity(product1, stock_location, 1.0)
self.env['stock.quant']._update_available_quantity(product1, stock_sub_location, 1.0)
self.env['stock.quant']._update_available_quantity(self.product, self.stock_location, 1.0)
self.env['stock.quant']._update_available_quantity(self.product, stock_sub_location, 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 2.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_sub_location), 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 2.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, stock_sub_location), 1.0)
self.env['stock.quant']._update_available_quantity(product2, stock_sub_location, 1.0)
self.env['stock.quant']._update_available_quantity(product2, stock_location, 1.0)
self.env['stock.quant']._update_available_quantity(product2, self.stock_location, 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product2, stock_location), 2.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product2, self.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',
'location_id': self.stock_location.id,
})
with self.assertRaises(ValidationError):
self.env['stock.quant']._update_available_quantity(product1, location1, 1.0)
self.env['stock.quant']._update_available_quantity(self.product, 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)
self.assertTrue(len(self.stock_location.quant_ids.ids) > 0)
with self.assertRaises(UserError):
stock_location.usage = 'view'
self.stock_location.usage = 'view'
def test_decrease_available_quantity_1(self):
""" Decrease the available quantity when no quants are already in a location.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
self.env['stock.quant']._update_available_quantity(product1, stock_location, -1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 0.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location, allow_negative=True), -1.0)
self.env['stock.quant']._update_available_quantity(self.product, self.stock_location, -1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 0.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location, allow_negative=True), -1.0)
def test_decrease_available_quantity_2(self):
""" Decrease the available quantity when multiple quants are already in a location.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
for i in range(2):
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 1.0,
})
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 2.0)
self.assertEqual(len(self.gather_relevant(product1, stock_location)), 2)
self.env['stock.quant']._update_available_quantity(product1, stock_location, -1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 1.0)
self.assertEqual(len(self.gather_relevant(product1, stock_location)), 1)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 2.0)
self.assertEqual(len(self.gather_relevant(self.product, self.stock_location)), 2)
self.env['stock.quant']._update_available_quantity(self.product, self.stock_location, -1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 1.0)
self.assertEqual(len(self.gather_relevant(self.product, self.stock_location)), 1)
def test_decrease_available_quantity_3(self):
""" Decrease the available quantity when a concurrent transaction is already increasing
the reserved quanntity for the same product.
"""
stock_location = self.env.ref('stock.stock_location_stock')
quant = self.env['stock.quant'].search([('location_id', '=', stock_location.id)], limit=1)
quant = self.env['stock.quant'].search([('location_id', '=', self.stock_location.id)], limit=1)
product = quant.product_id
available_quantity = self.env['stock.quant']._get_available_quantity(product, stock_location)
available_quantity = self.env['stock.quant']._get_available_quantity(product, self.stock_location)
# opens a new cursor and SELECT FOR UPDATE the quant, to simulate another concurrent reserved
# quantity increase
with closing(self.registry.cursor()) as cr:
cr.execute("SELECT 1 FROM stock_quant WHERE id = %s FOR UPDATE", quant.ids)
self.env['stock.quant']._update_available_quantity(product, stock_location, -1.0)
self.env['stock.quant']._update_available_quantity(product, self.stock_location, -1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product, stock_location), available_quantity - 1)
self.assertEqual(len(self.gather_relevant(product, stock_location, strict=True)), 2)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product, self.stock_location), available_quantity - 1)
self.assertEqual(len(self.gather_relevant(product, self.stock_location, strict=True)), 2)
def test_decrease_available_quantity_4(self):
""" Decrease the available quantity that delete the quant. The active user should have
read,write and unlink rights
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 1.0,
})
self.env = self.env(user=self.demo_user)
self.env['stock.quant']._update_available_quantity(product1, stock_location, -1.0)
self.assertEqual(len(self.gather_relevant(product1, stock_location)), 0)
self.env['stock.quant']._update_available_quantity(self.product, self.stock_location, -1.0)
self.assertEqual(len(self.gather_relevant(self.product, self.stock_location)), 0)
def test_increase_reserved_quantity_1(self):
""" Increase the reserved quantity of quantity x when there's a single quant in a given
location which has an available quantity of x.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 10.0,
})
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 10.0)
self.assertEqual(len(self.gather_relevant(product1, stock_location)), 1)
self.env['stock.quant']._update_reserved_quantity(product1, stock_location, 10.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 0.0)
self.assertEqual(len(self.gather_relevant(product1, stock_location)), 1)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 10.0)
self.assertEqual(len(self.gather_relevant(self.product, self.stock_location)), 1)
self.env['stock.quant']._update_reserved_quantity(self.product, self.stock_location, 10.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 0.0)
self.assertEqual(len(self.gather_relevant(self.product, self.stock_location)), 1)
def test_increase_reserved_quantity_2(self):
""" Increase the reserved quantity of quantity x when there's two quants in a given
location which have an available quantity of x together.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
for i in range(2):
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 5.0,
})
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 10.0)
self.assertEqual(len(self.gather_relevant(product1, stock_location)), 2)
self.env['stock.quant']._update_reserved_quantity(product1, stock_location, 10.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 0.0)
self.assertEqual(len(self.gather_relevant(product1, stock_location)), 2)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 10.0)
self.assertEqual(len(self.gather_relevant(self.product, self.stock_location)), 2)
self.env['stock.quant']._update_reserved_quantity(self.product, self.stock_location, 10.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 0.0)
self.assertEqual(len(self.gather_relevant(self.product, self.stock_location)), 2)
def test_increase_reserved_quantity_3(self):
""" Increase the reserved quantity of quantity x when there's multiple quants in a given
location which have an available quantity of x together.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 5.0,
'reserved_quantity': 2.0,
})
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 10.0,
'reserved_quantity': 12.0,
})
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 8.0,
'reserved_quantity': 3.0,
})
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 35.0,
'reserved_quantity': 12.0,
})
# total quantity: 58
# total reserved quantity: 29
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 29.0)
self.assertEqual(len(self.gather_relevant(product1, stock_location)), 4)
self.env['stock.quant']._update_reserved_quantity(product1, stock_location, 10.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 19.0)
self.assertEqual(len(self.gather_relevant(product1, stock_location)), 4)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 29.0)
self.assertEqual(len(self.gather_relevant(self.product, self.stock_location)), 4)
self.env['stock.quant']._update_reserved_quantity(self.product, self.stock_location, 10.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 19.0)
self.assertEqual(len(self.gather_relevant(self.product, self.stock_location)), 4)
def test_increase_reserved_quantity_4(self):
""" Increase the reserved quantity of quantity x when there's multiple quants in a given
location which have an available quantity of x together.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 5.0,
'reserved_quantity': 7.0,
})
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 12.0,
'reserved_quantity': 10.0,
})
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 0.0)
self.assertEqual(len(self.gather_relevant(product1, stock_location)), 2)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 0.0)
self.assertEqual(len(self.gather_relevant(self.product, self.stock_location)), 2)
with self.assertRaises(UserError):
self.env['stock.quant']._update_reserved_quantity(product1, stock_location, 10.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 0.0)
self.env['stock.quant']._update_reserved_quantity(self.product, self.stock_location, 10.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 0.0)
def test_increase_reserved_quantity_5(self):
""" Decrease the available quantity when no quant are in a location.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
with self.assertRaises(UserError):
self.env['stock.quant']._update_reserved_quantity(product1, stock_location, 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 0.0)
self.env['stock.quant']._update_reserved_quantity(self.product, self.stock_location, 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 0.0)
def test_decrease_reserved_quantity_1(self):
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 10.0,
'reserved_quantity': 10.0,
})
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 0.0)
self.assertEqual(len(self.gather_relevant(product1, stock_location)), 1)
self.env['stock.quant']._update_reserved_quantity(product1, stock_location, -10.0, strict=True)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 10.0)
self.assertEqual(len(self.gather_relevant(product1, stock_location)), 1)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 0.0)
self.assertEqual(len(self.gather_relevant(self.product, self.stock_location)), 1)
self.env['stock.quant']._update_reserved_quantity(self.product, self.stock_location, -10.0, strict=True)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 10.0)
self.assertEqual(len(self.gather_relevant(self.product, self.stock_location)), 1)
def test_increase_decrease_reserved_quantity_1(self):
""" Decrease then increase reserved quantity when no quant are in a location.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
with self.assertRaises(UserError):
self.env['stock.quant']._update_reserved_quantity(product1, stock_location, 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 0.0)
self.env['stock.quant']._update_reserved_quantity(self.product, self.stock_location, 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 0.0)
with self.assertRaises(UserError):
self.env['stock.quant']._update_reserved_quantity(product1, stock_location, -1.0, strict=True)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 0.0)
self.env['stock.quant']._update_reserved_quantity(self.product, self.stock_location, -1.0, strict=True)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 0.0)
def test_action_done_1(self):
stock_location = self.env.ref('stock.stock_location_stock')
pack_location = self.env.ref('stock.location_pack_zone')
pack_location.active = True
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
self.env['stock.quant']._update_available_quantity(product1, stock_location, 2.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 2.0)
self.env['stock.quant']._update_reserved_quantity(product1, stock_location, 2.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 0.0)
self.env['stock.quant']._update_reserved_quantity(product1, stock_location, -2.0, strict=True)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 2.0)
self.env['stock.quant']._update_available_quantity(product1, stock_location, -2.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 0.0)
self.env['stock.quant']._update_available_quantity(product1, pack_location, 2.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, pack_location), 2.0)
self.env['stock.quant']._update_available_quantity(self.product, self.stock_location, 2.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 2.0)
self.env['stock.quant']._update_reserved_quantity(self.product, self.stock_location, 2.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 0.0)
self.env['stock.quant']._update_reserved_quantity(self.product, self.stock_location, -2.0, strict=True)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 2.0)
self.env['stock.quant']._update_available_quantity(self.product, self.stock_location, -2.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 0.0)
self.env['stock.quant']._update_available_quantity(self.product, pack_location, 2.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, pack_location), 2.0)
def test_mix_tracked_untracked_1(self):
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
'tracking': 'serial',
})
lot1 = self.env['stock.production.lot'].create({
'name': 'lot1',
'product_id': product1.id,
'product_id': self.product_serial.id,
})
# add one tracked, one untracked
self.env['stock.quant']._update_available_quantity(product1, stock_location, 1.0)
self.env['stock.quant']._update_available_quantity(product1, stock_location, 1.0, lot_id=lot1)
self.env['stock.quant']._update_available_quantity(self.product_serial, self.stock_location, 1.0)
self.env['stock.quant']._update_available_quantity(self.product_serial, self.stock_location, 1.0, lot_id=lot1)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 2.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location, strict=True), 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location, lot_id=lot1), 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product_serial, self.stock_location), 2.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product_serial, self.stock_location, strict=True), 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product_serial, self.stock_location, lot_id=lot1), 1.0)
self.env['stock.quant']._update_reserved_quantity(product1, stock_location, 1.0, lot_id=lot1, strict=True)
self.env['stock.quant']._update_reserved_quantity(self.product_serial, self.stock_location, 1.0, lot_id=lot1, strict=True)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location, strict=True), 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location, lot_id=lot1), 0.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product_serial, self.stock_location), 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product_serial, self.stock_location, strict=True), 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product_serial, self.stock_location, lot_id=lot1), 0.0)
self.env['stock.quant']._update_reserved_quantity(product1, stock_location, -1.0, lot_id=lot1, strict=True)
self.env['stock.quant']._update_reserved_quantity(self.product_serial, self.stock_location, -1.0, lot_id=lot1, strict=True)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 2.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location, strict=True), 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location, lot_id=lot1), 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product_serial, self.stock_location), 2.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product_serial, self.stock_location, strict=True), 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product_serial, self.stock_location, lot_id=lot1), 1.0)
with self.assertRaises(UserError):
self.env['stock.quant']._update_reserved_quantity(product1, stock_location, -1.0, strict=True)
self.env['stock.quant']._update_reserved_quantity(self.product_serial, self.stock_location, -1.0, strict=True)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location), 2.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location, strict=True), 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(product1, stock_location, lot_id=lot1), 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product_serial, self.stock_location), 2.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product_serial, self.stock_location, strict=True), 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product_serial, self.stock_location, lot_id=lot1), 1.0)
def test_access_rights_1(self):
""" Directly update the quant with a user with or without stock access rights sould raise
an AccessError.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
quant = self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 1.0,
})
self.env = self.env(user=self.demo_user)
with self.assertRaises(AccessError):
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 1.0,
})
with self.assertRaises(AccessError):
@@ -610,8 +492,8 @@ class StockQuant(TransactionCase):
self.env = self.env(user=self.stock_user)
with self.assertRaises(AccessError):
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 1.0,
})
with self.assertRaises(AccessError):
@@ -622,47 +504,29 @@ class StockQuant(TransactionCase):
def test_in_date_1(self):
""" Check that no incoming date is set when updating the quantity of an untracked quant.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
quantity, in_date = self.env['stock.quant']._update_available_quantity(product1, stock_location, 1.0)
quantity, in_date = self.env['stock.quant']._update_available_quantity(self.product, self.stock_location, 1.0)
self.assertEqual(quantity, 1)
self.assertNotEqual(in_date, None)
def test_in_date_1b(self):
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
})
self.env['stock.quant'].create({
'product_id': product1.id,
'location_id': stock_location.id,
'product_id': self.product.id,
'location_id': self.stock_location.id,
'quantity': 1.0,
})
quantity, in_date = self.env['stock.quant']._update_available_quantity(product1, stock_location, 2.0)
quantity, in_date = self.env['stock.quant']._update_available_quantity(self.product, self.stock_location, 2.0)
self.assertEqual(quantity, 3)
self.assertNotEqual(in_date, None)
def test_in_date_2(self):
""" Check that an incoming date is correctly set when updating the quantity of a tracked
quant.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
'tracking': 'serial',
})
lot1 = self.env['stock.production.lot'].create({
'name': 'lot1',
'product_id': product1.id,
'product_id': self.product_serial.id,
})
quantity, in_date = self.env['stock.quant']._update_available_quantity(product1, stock_location, 1.0, lot_id=lot1)
quantity, in_date = self.env['stock.quant']._update_available_quantity(self.product_serial, self.stock_location, 1.0, lot_id=lot1)
self.assertEqual(quantity, 1)
self.assertNotEqual(in_date, None)
@@ -670,26 +534,20 @@ class StockQuant(TransactionCase):
""" Check that the FIFO strategies correctly applies when you have multiple lot received
at different times for a tracked product.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
'tracking': 'serial',
})
lot1 = self.env['stock.production.lot'].create({
'name': 'lot1',
'product_id': product1.id,
'product_id': self.product_serial.id,
})
lot2 = self.env['stock.production.lot'].create({
'name': 'lot2',
'product_id': product1.id,
'product_id': self.product_serial.id,
})
in_date_lot1 = datetime.now()
in_date_lot2 = datetime.now() - timedelta(days=5)
self.env['stock.quant']._update_available_quantity(product1, stock_location, 1.0, lot_id=lot1, in_date=in_date_lot1)
self.env['stock.quant']._update_available_quantity(product1, stock_location, 1.0, lot_id=lot2, in_date=in_date_lot2)
self.env['stock.quant']._update_available_quantity(self.product_serial, self.stock_location, 1.0, lot_id=lot1, in_date=in_date_lot1)
self.env['stock.quant']._update_available_quantity(self.product_serial, self.stock_location, 1.0, lot_id=lot2, in_date=in_date_lot2)
quants = self.env['stock.quant']._update_reserved_quantity(product1, stock_location, 1)
quants = self.env['stock.quant']._update_reserved_quantity(self.product_serial, self.stock_location, 1)
# Default removal strategy is FIFO, so lot2 should be received as it was received earlier.
self.assertEqual(quants[0][0].lot_id.id, lot2.id)
@@ -698,28 +556,22 @@ class StockQuant(TransactionCase):
""" Check that the LIFO strategies correctly applies when you have multiple lot received
at different times for a tracked product.
"""
stock_location = self.env.ref('stock.stock_location_stock')
lifo_strategy = self.env['product.removal'].search([('method', '=', 'lifo')])
stock_location.removal_strategy_id = lifo_strategy
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
'tracking': 'serial',
})
self.stock_location.removal_strategy_id = lifo_strategy
lot1 = self.env['stock.production.lot'].create({
'name': 'lot1',
'product_id': product1.id,
'product_id': self.product_serial.id,
})
lot2 = self.env['stock.production.lot'].create({
'name': 'lot2',
'product_id': product1.id,
'product_id': self.product_serial.id,
})
in_date_lot1 = datetime.now()
in_date_lot2 = datetime.now() - timedelta(days=5)
self.env['stock.quant']._update_available_quantity(product1, stock_location, 1.0, lot_id=lot1, in_date=in_date_lot1)
self.env['stock.quant']._update_available_quantity(product1, stock_location, 1.0, lot_id=lot2, in_date=in_date_lot2)
self.env['stock.quant']._update_available_quantity(self.product_serial, self.stock_location, 1.0, lot_id=lot1, in_date=in_date_lot1)
self.env['stock.quant']._update_available_quantity(self.product_serial, self.stock_location, 1.0, lot_id=lot2, in_date=in_date_lot2)
quants = self.env['stock.quant']._update_reserved_quantity(product1, stock_location, 1)
quants = self.env['stock.quant']._update_reserved_quantity(self.product_serial, self.stock_location, 1)
# Removal strategy is LIFO, so lot1 should be received as it was received later.
self.assertEqual(quants[0][0].lot_id.id, lot1.id)
@@ -727,27 +579,21 @@ class StockQuant(TransactionCase):
def test_in_date_4b(self):
""" Check for LIFO and max with/without in_date that it handles the LIFO NULLS LAST well
"""
stock_location = self.env.ref('stock.stock_location_stock')
stock_location1 = self.env.ref('stock.stock_location_components')
stock_location2 = self.env.ref('stock.stock_location_14')
lifo_strategy = self.env['product.removal'].search([('method', '=', 'lifo')])
stock_location.removal_strategy_id = lifo_strategy
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
'tracking': 'serial',
})
self.stock_location.removal_strategy_id = lifo_strategy
self.env['stock.quant'].create({
'product_id': product1.id,
'product_id': self.product_serial.id,
'location_id': stock_location1.id,
'quantity': 1.0,
})
in_date_location2 = datetime.now()
self.env['stock.quant']._update_available_quantity(product1, stock_location2, 1.0, in_date=in_date_location2)
self.env['stock.quant']._update_available_quantity(self.product_serial, stock_location2, 1.0, in_date=in_date_location2)
quants = self.env['stock.quant']._update_reserved_quantity(product1, stock_location, 1)
quants = self.env['stock.quant']._update_reserved_quantity(self.product_serial, self.stock_location, 1)
# Removal strategy is LIFO, so the one with date is the most recent one and should be selected
self.assertEqual(quants[0][0].location_id.id, stock_location2.id)
@@ -756,24 +602,18 @@ class StockQuant(TransactionCase):
""" Receive the same lot at different times, once they're in the same location, the quants
are merged and only the earliest incoming date is kept.
"""
stock_location = self.env.ref('stock.stock_location_stock')
product1 = self.env['product.product'].create({
'name': 'Product A',
'type': 'product',
'tracking': 'lot',
})
lot1 = self.env['stock.production.lot'].create({
'name': 'lot1',
'product_id': product1.id,
'product_id': self.product_lot.id,
})
from odoo.fields import Datetime
in_date1 = Datetime.now()
self.env['stock.quant']._update_available_quantity(product1, stock_location, 1.0, lot_id=lot1, in_date=in_date1)
self.env['stock.quant']._update_available_quantity(self.product_lot, self.stock_location, 1.0, lot_id=lot1, in_date=in_date1)
quant = self.env['stock.quant'].search([
('product_id', '=', product1.id),
('location_id', '=', stock_location.id),
('product_id', '=', self.product_lot.id),
('location_id', '=', self.stock_location.id),
])
self.assertEqual(len(quant), 1)
self.assertEqual(quant.quantity, 1)
@@ -781,13 +621,14 @@ class StockQuant(TransactionCase):
self.assertEqual(quant.in_date, in_date1)
in_date2 = Datetime.now() - timedelta(days=5)
self.env['stock.quant']._update_available_quantity(product1, stock_location, 1.0, lot_id=lot1, in_date=in_date2)
self.env['stock.quant']._update_available_quantity(self.product_lot, self.stock_location, 1.0, lot_id=lot1, in_date=in_date2)
quant = self.env['stock.quant'].search([
('product_id', '=', product1.id),
('location_id', '=', stock_location.id),
('product_id', '=', self.product_lot.id),
('location_id', '=', self.stock_location.id),
])
self.assertEqual(len(quant), 1)
self.assertEqual(quant.quantity, 2)
self.assertEqual(quant.lot_id.id, lot1.id)
self.assertEqual(quant.in_date, in_date2)
+11 -10
View File
@@ -2,20 +2,21 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.exceptions import UserError, ValidationError
from odoo.tests.common import TransactionCase
from odoo.tests.common import SavepointCase
class TestRobustness(TransactionCase):
def setUp(self):
super(TestRobustness, self).setUp()
self.stock_location = self.env.ref('stock.stock_location_stock')
self.customer_location = self.env.ref('stock.stock_location_customers')
self.uom_unit = self.env.ref('uom.product_uom_unit')
self.uom_dozen = self.env.ref('uom.product_uom_dozen')
self.product1 = self.env['product.product'].create({
class TestRobustness(SavepointCase):
@classmethod
def setUpClass(cls):
super(TestRobustness, cls).setUpClass()
cls.stock_location = cls.env.ref('stock.stock_location_stock')
cls.customer_location = cls.env.ref('stock.stock_location_customers')
cls.uom_unit = cls.env.ref('uom.product_uom_unit')
cls.uom_dozen = cls.env.ref('uom.product_uom_dozen')
cls.product1 = cls.env['product.product'].create({
'name': 'Product A',
'type': 'product',
'categ_id': self.env.ref('product.product_category_all').id,
'categ_id': cls.env.ref('product.product_category_all').id,
})
def test_uom_factor(self):
-48
View File
@@ -1,48 +0,0 @@
# -*- coding: utf-8 -*-
from odoo.addons.stock.tests.common2 import TestStockCommon
class TestInventory(TestStockCommon):
def test_shipment(self):
# TDE TODO
# pickign.action_confirm -> confirm moves
# picking.do_prepare_partial, should create pack ops, write on it ?
# create and confirm an incoming move of product 3
incoming_move = self._create_move_in(self.product_3, self.warehouse_1, create_picking=True, product_uom_qty=50)
incoming_move._action_confirm()
# receive only 40 units of products; this will create a backorder of incoming shipment for the remaining 10
pack_operation = self._create_pack_operation(
self.product_3, 40.0, incoming_move.picking_id,
location_id=self.env.ref('stock.stock_location_suppliers').id, # TDE FIXME: locations
location_dest_id=self.location_1.id)
incoming_move.picking_id.with_context(active_model='stock.picking', active_id=incoming_move.picking_id.id, active_ids=[incoming_move.picking_id.id]).action_done()
# check backorder shipment after receiving partial shipment and check remaining shipment
for move_line in incoming_move.picking_id.move_lines:
self.assertEqual(move_line.product_qty, 40)
self.assertEqual(move_line.state, 'done')
backorder = self.env['stock.picking'].search([('backorder_id', '=', incoming_move.picking_id.id)])
for move_line in backorder.move_lines:
self.assertEqual(move_line.product_qty, 10)
self.assertIn(move_line.state, ['assigned', 'waiting', 'confirmed'])
backorder.with_context(active_model='stock.picking', active_id=backorder.id, active_ids=[backorder.id])
# receive the remaining 10 units from the backorder
pack_operation = self._create_pack_operation(
self.product_3, 10.0, backorder,
location_id=self.env.ref('stock.stock_location_suppliers').id, # TDE FIXME: locations
location_dest_id=self.location_1.id)
backorder.action_done()
# check the incoming shipment after receipt
backorder = self.env['stock.picking'].search([('backorder_id', '=', incoming_move.picking_id.id)])
self.assertEqual(backorder.state, 'done')
for move_line in backorder.move_lines:
self.assertEqual(move_line.state, 'done')
+1 -20
View File
@@ -3,8 +3,8 @@
from odoo.addons.stock.tests.common2 import TestStockCommon
from odoo.tests import Form
class TestWarehouse(TestStockCommon):
class TestWarehouse(TestStockCommon):
def test_inventory_product(self):
self.product_1.type = 'product'
inventory_wizard = self.env['stock.change.product.qty'].create({
@@ -574,22 +574,3 @@ class TestWarehouse(TestStockCommon):
self.assertTrue(warehouse.pick_type_id.active)
self.assertTrue(warehouse.pack_type_id.active)
class TestResupply(TestStockCommon):
def setUp(self):
super(TestResupply, self).setUp()
self.warehouse_2 = self.env['stock.warehouse'].create({
'name': 'Small Warehouse',
'code': 'SWH',
'resupply_wh_ids': [(6, 0, [self.warehouse_1.id])]
})
# minimum stock rule for test product on this warehouse
self.env['stock.warehouse.orderpoint'].create({
'warehouse_id': self.warehouse_2.id,
'location_id': self.warehouse_2.lot_stock_id.id,
'product_id': self.product_1.id,
'product_min_qty': 10,
'product_max_qty': 100,
'product_uom': self.uom_unit.id,
})