summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThibault Delavallée <tde@openerp.com>2016-03-23 16:18:40 +0100
committerThibault Delavallée <tde@openerp.com>2016-04-29 12:18:29 +0200
commitbdd2080d044f0afa3714a6bbf5894e6f2fb07b99 (patch)
tree65026134ff15419a7799dfc7ed1ea6f1fc6b63a7
parent42bb99d9c4a6c7afef39853eef12aec86f748ede (diff)
[TESTS] stocl: Some new tests and yml to py
Including - unit tests for test/inventory.yml - unit tests for test/move.yml - unit tests for test/shipment.yml - integration of test_reuspply.py - integration of test_owner_available into test_product.py New tests are temporarily deactivated. Indeed they rely on onchange methods that will change during migration. Tests will be reactivated after migration and updated.
-rw-r--r--addons/product/tests/__init__.py2
-rw-r--r--addons/product/tests/common.py67
-rw-r--r--addons/stock/__openerp__.py3
-rw-r--r--addons/stock/test/inventory.yml93
-rw-r--r--addons/stock/test/move.yml108
-rw-r--r--addons/stock/test/shipment.yml66
-rw-r--r--addons/stock/tests/__init__.py5
-rw-r--r--addons/stock/tests/common2.py92
-rw-r--r--addons/stock/tests/test_owner_available.py72
-rw-r--r--addons/stock/tests/test_product.py64
-rw-r--r--addons/stock/tests/test_resupply.py51
-rw-r--r--addons/stock/tests/test_shipment.py49
-rw-r--r--addons/stock/tests/test_warehouse.py145
13 files changed, 421 insertions, 396 deletions
diff --git a/addons/product/tests/__init__.py b/addons/product/tests/__init__.py
index 7c05b1bf791..6af057825cd 100644
--- a/addons/product/tests/__init__.py
+++ b/addons/product/tests/__init__.py
@@ -1 +1 @@
-from . import test_uom, test_pricelist
+from . import common, test_uom, test_pricelist
diff --git a/addons/product/tests/common.py b/addons/product/tests/common.py
new file mode 100644
index 00000000000..fac4c1dba74
--- /dev/null
+++ b/addons/product/tests/common.py
@@ -0,0 +1,67 @@
+# -*- coding: utf-8 -*-
+
+from odoo.tests import common
+
+
+class TestProductCommon(common.SavepointCase):
+
+ @classmethod
+ def setUpClass(cls):
+ super(TestProductCommon, cls).setUpClass()
+
+ # Customer related data
+ cls.partner_1 = cls.env['res.partner'].create({
+ 'name': 'Julia Agrolait',
+ 'email': 'julia@agrolait.example.com',
+ })
+
+ # Product environment related data
+ Uom = cls.env['product.uom']
+ categ_unit = cls.env.ref('product.product_uom_categ_unit')
+ weight_unit = cls.env.ref('product.product_uom_categ_kgm')
+ cls.uom_unit = Uom.create({
+ 'name': 'TestUnit',
+ 'category_id': categ_unit.id,
+ 'factor_inv': 1.0,
+ 'factor': 1.0,
+ 'uom_type': 'reference',
+ 'rounding': 0.000001})
+ cls.uom_kunit = Uom.create({
+ 'name': 'KTestUnit',
+ 'category_id': categ_unit.id,
+ 'factor_inv': 1000.0,
+ 'factor': 0.001,
+ 'uom_type': 'bigger',
+ 'rounding': 0.001})
+ cls.uom_munit = Uom.create({
+ 'name': 'mTestUnit',
+ 'category_id': categ_unit.id,
+ 'factor_inv': 0.001,
+ 'factor': 1000.0,
+ 'uom_type': 'smaller',
+ 'rounding': 0.001})
+ cls.uom_weight = Uom.create({
+ 'name': 'TestWeight',
+ 'category_id': weight_unit.id,
+ 'factor_inv': 1.0,
+ 'factor': 1.0,
+ 'uom_type': 'reference',
+ 'rounding': 0.000001
+ })
+ Product = cls.env['product.product']
+ cls.product_1 = Product.create({
+ 'name': 'TestProduct 1',
+ 'uom_id': cls.uom_unit.id,
+ 'uom_po_id': cls.uom_unit.id})
+ cls.product_2 = Product.create({
+ 'name': 'TestProduct 2',
+ 'uom_id': cls.uom_unit.id,
+ 'uom_po_id': cls.uom_unit.id})
+ cls.product_3 = Product.create({
+ 'name': 'TestProduct 3 (KTestUnit)',
+ 'uom_id': cls.uom_kunit.id,
+ 'uom_po_id': cls.uom_kunit.id})
+ cls.product_4 = Product.create({
+ 'name': 'TestProduct 4 (mTestUnit)',
+ 'uom_id': cls.uom_munit.id,
+ 'uom_po_id': cls.uom_munit.id})
diff --git a/addons/stock/__openerp__.py b/addons/stock/__openerp__.py
index 7169f2b610b..54f573fd9c6 100644
--- a/addons/stock/__openerp__.py
+++ b/addons/stock/__openerp__.py
@@ -77,11 +77,8 @@ Dashboard / Reports for Inventory Management will include:
'data/web_planner_data.xml',
],
'test': [
- 'test/inventory.yml',
- 'test/move.yml',
'test/procrule.yml',
'test/stock_users.yml',
- 'test/shipment.yml',
'test/packing.yml',
'test/packingneg.yml',
'test/wiseoperator.yml',
diff --git a/addons/stock/test/inventory.yml b/addons/stock/test/inventory.yml
deleted file mode 100644
index 4bfc70d3dd1..00000000000
--- a/addons/stock/test/inventory.yml
+++ /dev/null
@@ -1,93 +0,0 @@
--
- In order to test the inventory, I create a new product
--
- !record {model: product.product, id: inventory_product}:
- name: inventory prod
- type: product
--
- I create an inventory for this product only
--
- !record {model: stock.inventory, id: inventory_test0}:
- name: Test
- filter: product
- product_id: inventory_product
--
- I confirm the inventory and check that my inventory has no line, as the product is a new one.
--
- !python {model: stock.inventory}: |
- self.prepare_inventory(cr, uid, [ref('inventory_test0')], context=context)
- inv = self.browse(cr, uid, ref('inventory_test0'), context=context)
- assert len(inv.line_ids) == 0, "Wrong number of inventory lines."
--
- I add an inventory line and say i have 10 products in stock
--
- !record {model: stock.inventory.line, id: inventory_testline0}:
- inventory_id: stock.inventory_test0
- product_uom_id: product.product_uom_unit
- product_id: inventory_product
- product_qty: 10
- location_id: stock.stock_location_14
--
- I Validate this inventory
--
- !python {model: stock.inventory}: |
- self.action_done(cr, uid, [ref('inventory_test0')], context=context)
--
- I check that this inventory has a stock.move and a quant
--
- !python {model: stock.inventory}: |
- inv = self.browse(cr, uid, ref('inventory_test0'), context=context)
- assert len(inv.move_ids) >= 1, "No move created for the inventory."
- assert len(inv.move_ids[0].quant_ids) >= 1, "No quant created for this inventory"
--
- I check that the quantity on hand is 10 on the location and its parent.
--
- !python {model: product.product}: |
- context['location'] = ref('stock.stock_location_14')
- product = self.browse(cr, uid, ref('inventory_product'), context=context)
- assert product.qty_available == 10, 'Expecting 10 products, got %.2f on location stock_location_14!' % (product.qty_available,)
- context['location'] = ref('stock.stock_location_stock')
- product = self.browse(cr, uid, ref('inventory_product'), context=context)
- assert product.qty_available == 10, 'Expecting 10 products, got %.2f on location stock_location_stock!' % (product.qty_available,)
--
- I check that the quantity on hand is 0 on a brother location
--
- !python {model: product.product}: |
- context['location'] = ref('stock.stock_location_components')
- product = self.browse(cr, uid, ref('inventory_product'), context=context)
- assert product.qty_available == 0, 'Expecting 0 products, got %.2f on location stock_location_components!' % (product.qty_available,)
--
- I create another inventory
--
- !record {model: stock.inventory, id: inventory_test1}:
- name: second test inventory
- filter: product
- product_id: inventory_product
--
- I confirm the inventory and check that my inventory has one line, with a quantity of 10.
--
- !python {model: stock.inventory}: |
- self.prepare_inventory(cr, uid, [ref('inventory_test1')], context=context)
- inv = self.browse(cr, uid, ref('inventory_test1'), context=context)
- assert inv.line_ids and len(inv.line_ids) == 1, "Wrong number of inventory lines."
- assert inv.line_ids[0].product_qty == 10, "Wrong quantity in inventory line."
- assert inv.line_ids[0].product_id.id == ref('inventory_product'), "Wrong product in inventory line."
--
- I modify the inventory line and set the quantity to 20 product on this new inventory
--
- !python {model: stock.inventory}: |
- inv = self.browse(cr, uid, ref('inventory_test1'), context=context)
- self.pool.get('stock.inventory.line').write(cr, uid, inv.line_ids[0].id, {'product_qty': 20})
--
- I Validate this inventory
--
- !python {model: stock.inventory}: |
- self.action_done(cr, uid, [ref('inventory_test1')], context=context)
--
- I check that the quantity on hand is 20 on the location and it's parent.
--
- !python {model: product.product}: |
- context['location'] = ref('stock.stock_location_14')
- product = self.browse(cr, uid, ref('inventory_product'), context=context)
- assert product.qty_available == 20, 'Expecting 20 products, got %.2f on location stock_location_14!' % (product.qty_available,)
-
diff --git a/addons/stock/test/move.yml b/addons/stock/test/move.yml
deleted file mode 100644
index c03a77e23b8..00000000000
--- a/addons/stock/test/move.yml
+++ /dev/null
@@ -1,108 +0,0 @@
--
- I first create a new product
--
- !record {model: product.product, id: move_product}:
- name: move prod
- type: product
--
- In order to test the negative quants, I create a move of 5 products from stock to customer
--
- !record {model: stock.move, id: move_test0}:
- name: Move Products
- product_id: move_product
- product_uom_qty: 5
- product_uom: product.product_uom_unit
- location_id: stock.stock_location_stock
- location_dest_id: stock.stock_location_customers
--
- I confirm the move to be processed in the future
--
- !python {model: stock.move}: |
- self.action_confirm(cr, uid, [ref('move_test0')], context=context)
--
- I check that the quantity on hand is 0 and virtual is -5
--
- !python {model: product.product}: |
- context['location'] = False
- product = self.browse(cr, uid, ref('move_product'), context=context)
- assert product.qty_available == 0, 'Expecting 0 products in stock, got %.2f!' % (product.qty_available,)
- assert product.virtual_available == -5.0, 'Expecting -5 products in virtual stock, got %.2f!' % (product.virtual_available,)
--
- I validate the move
--
- !python {model: stock.move}: |
- self.action_done(cr, uid, [ref('move_test0')], context=context)
--
- I check that the quantity on hand is -5 and 5 products are at customer location
--
- !python {model: product.product}: |
- context['location'] = False
- product = self.browse(cr, uid, ref('move_product'), context=context)
- assert product.qty_available == -5, 'Expecting -5 products in stock, got %.2f!' % (product.qty_available,)
-
- context['location'] = ref('stock.stock_location_customers')
- product = self.browse(cr, uid, ref('move_product'), context=context)
- assert product.qty_available == 5, 'Expecting 5 products in customer location, got %.2f!' % (product.qty_available,)
--
- To compensate negative quants, I will receive 15 products from the supplier
--
- !record {model: stock.move, id: move_test2}:
- name: Move 15 Products
- product_id: move_product
- product_uom_qty: 15
- product_uom: product.product_uom_unit
- location_id: stock.stock_location_suppliers
- location_dest_id: stock.stock_location_stock
--
- I confirm and validate the move
--
- !python {model: stock.move}: |
- self.action_confirm(cr, uid, [ref('move_test2')], context=context)
- self.action_done(cr, uid, [ref('move_test2')], context=context)
--
- I check that the quantity on hand is 10
--
- !python {model: product.product}: |
- context['location'] = False
- product = self.browse(cr, uid, ref('move_product'), context=context)
- assert product.qty_available == 10, 'Expecting 10 products in stock, got %.2f!' % (product.qty_available,)
- assert product.virtual_available == 10.0, 'Expecting 10 products in virtual stock, got %.2f!' % (product.virtual_available,)
--
- I create a move of 2 products from stock to customer
--
- !record {model: stock.move, id: move_test1}:
- name: Move Products
- product_id: move_product
- product_uom_qty: 2
- product_uom: product.product_uom_unit
- location_id: stock.stock_location_stock
- location_dest_id: stock.stock_location_customers
--
- I confirm the move to be processed in the future
--
- !python {model: stock.move}: |
- self.action_confirm(cr, uid, [ref('move_test1')], context=context)
--
- I check that the quantity on hand is 10 and virtual is 8
--
- !python {model: product.product}: |
- context['location'] = False
- product = self.browse(cr, uid, ref('move_product'), context=context)
- assert product.qty_available == 10, 'Expecting 10 products in stock, got %.2f!' % (product.qty_available,)
- assert product.virtual_available == 8.0, 'Expecting 8 products in virtual stock, got %.2f!' % (product.virtual_available,)
--
- I validate the move
--
- !python {model: stock.move}: |
- self.action_done(cr, uid, [ref('move_test1')], context=context)
--
- I check that the quantity on hand is 8 and 7 products are at customer location
--
- !python {model: product.product}: |
- context['location'] = False
- product = self.browse(cr, uid, ref('move_product'), context=context)
- assert product.qty_available == 8, 'Expecting 10 products in stock, got %.2f!' % (product.qty_available,)
-
- context['location'] = ref('stock.stock_location_customers')
- product = self.browse(cr, uid, ref('move_product'), context=context)
- assert product.qty_available == 7, 'Expecting 7 products in customer location, got %.2f!' % (product.qty_available,)
diff --git a/addons/stock/test/shipment.yml b/addons/stock/test/shipment.yml
deleted file mode 100644
index ed670d69caf..00000000000
--- a/addons/stock/test/shipment.yml
+++ /dev/null
@@ -1,66 +0,0 @@
--
- Stock manager can only test whole process related to Shipment, so we check data with stock manager.
--
- !context
- uid: 'res_users_stock_manager'
--
- I confirm incoming move of 50 kgm Ice-cream
--
- !python {model: stock.move}: |
- incoming_move = self.browse(cr, uid, ref("incomming_shipment_icecream"))
- self.action_confirm(cr, uid, [incoming_move.id])
--
- I receive 40kgm Ice-cream so It will make backorder of incomming shipment for 10 kgm.
--
- !python {model: stock.picking}: |
- pick = self.browse(cr, uid, ref("incomming_shipment"), context=context)
- newid = self.pool.get('stock.pack.operation').create(cr, uid, {
- 'picking_id': pick.id,
- 'product_id': ref('product_icecream'),
- 'product_uom_id': ref('product.product_uom_kgm'),
- 'product_qty': 40,
- 'qty_done': 40,
- 'location_id': ref('stock.stock_location_suppliers'),
- 'location_dest_id': ref('stock.stock_location_14')
- })
- context.update({'active_model': 'stock.picking', 'active_id': ref('incomming_shipment'), 'active_ids': [ref('incomming_shipment')]})
- pick = self.browse(cr, uid, pick.id, context=context)
- pick.do_transfer()
--
- I check backorder shipment after received partial shipment and check remaining shipment.
--
- !python {model: stock.picking}: |
- shipment = self.browse(cr, uid, ref("incomming_shipment"))
- for move_line in shipment.move_lines:
- assert move_line.product_qty == 40, "Qty in shipment does not correspond."
- assert move_line.state == 'done', "Move line of shipment should be closed."
- backorder_id = self.search(cr, uid, [('backorder_id', '=', ref("incomming_shipment"))],context=context)
- backorder = self.browse(cr, uid, backorder_id)[0]
- for move_line in backorder.move_lines:
- assert move_line.product_qty == 10, "Qty in backorder does not correspond."
- assert (move_line.state == 'assigned' or move_line.state == 'waiting' or move_line.state == 'confirmed'), "Move line of backorder should be assigned, confirmed or waiting."
- context.update({'active_model': 'stock.picking', 'active_id': backorder_id[0], 'active_ids': backorder_id})
--
- I receive the remaining 10kgm Ice-cream from the backorder.
--
- !python {model: stock.picking}: |
- backorder_id = self.search(cr, uid, [('backorder_id', '=', ref("incomming_shipment"))],context=context)
- backorder = self.browse(cr, uid, backorder_id, context=context)[0]
- self.pool.get('stock.pack.operation').create(cr, uid, {
- 'picking_id': backorder.id,
- 'product_id': ref('product_icecream'),
- 'product_uom_id': ref('product.product_uom_kgm'),
- 'product_qty': 10,
- 'qty_done': 10,
- 'location_id': ref('stock.stock_location_suppliers'),
- 'location_dest_id': ref('stock.stock_location_14')
- })
- backorder.do_transfer()
--
- I check incomming shipment after receipt.
--
- !python {model: stock.picking}: |
- shipment = self.browse(cr, uid, self.search(cr, uid, [('backorder_id', '=', ref("incomming_shipment"))]))[0]
- assert shipment.state == 'done', "shipment should be close after received."
- for move_line in shipment.move_lines:
- assert move_line.state == 'done', "Move line should be closed."
diff --git a/addons/stock/tests/__init__.py b/addons/stock/tests/__init__.py
index c372f3c8fb5..e51047f6353 100644
--- a/addons/stock/tests/__init__.py
+++ b/addons/stock/tests/__init__.py
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
from . import test_stock_flow
-from . import test_owner_available
-from . import test_resupply
+import test_product
+# import test_warehouse
+# import test_shipment
diff --git a/addons/stock/tests/common2.py b/addons/stock/tests/common2.py
new file mode 100644
index 00000000000..4204b88afe5
--- /dev/null
+++ b/addons/stock/tests/common2.py
@@ -0,0 +1,92 @@
+# -*- coding: utf-8 -*-
+
+from odoo.addons.product.tests import common
+
+
+class TestStockCommon(common.TestProductCommon):
+
+ def _create_pack_operation(self, product, product_qty, picking_id, **values):
+ PackOperation = self.env['stock.pack.operation'].sudo(self.user_stock_manager)
+ vals = PackOperation.product_id_change(product.id, False, product_qty)['value']
+ vals.update({
+ 'picking_id': picking_id.id,
+ 'product_id': product.id,
+ 'product_qty': product_qty,
+ 'qty_done': product_qty})
+ vals.update(**values)
+ return PackOperation.create(vals)
+
+ def _create_picking_in(self, warehouse):
+ Picking = self.env['stock.picking']
+ picking_values = {
+ 'picking_type_id': warehouse.in_type_id.id,
+ 'location_id': self.env.ref('stock.stock_location_suppliers').id,
+ 'location_dest_id': warehouse.lot_stock_id.id,
+ }
+ return Picking.create(picking_values)
+
+ def _create_move(self, product, src_location, dst_location, **values):
+ # TDE FIXME: user as parameter
+ Move = self.env['stock.move'].sudo(self.user_stock_manager)
+ # simulate create + onchange
+ move_values = Move.onchange_product_id(product.id, src_location.id, dst_location.id)['value']
+ move_values.update(product_id=product.id)
+ move_values.update(**values)
+ return Move.create(move_values)
+
+ def _create_move_in(self, product, warehouse, picking=None, create_picking=False, **values):
+ if not picking and create_picking:
+ picking = self._create_picking_in(warehouse)
+ if picking:
+ values['picking_id'] = picking.id
+ # TDE FIXME: shouldn't location come from picking ??
+ return self._create_move(product, self.env.ref('stock.stock_location_suppliers'), warehouse.lot_stock_id, **values)
+
+ @classmethod
+ def setUpClass(cls):
+ super(TestStockCommon, cls).setUpClass()
+
+ # Fetch stock-related user groups
+ user_group_employee = cls.env.ref('base.group_user')
+ user_group_stock_user = cls.env.ref('stock.group_stock_user')
+ user_group_stock_manager = cls.env.ref('stock.group_stock_manager')
+
+ # User Data: stock user and stock manager
+ Users = cls.env['res.users'].with_context({'no_reset_password': True, 'mail_create_nosubscribe': True})
+ cls.user_stock_user = Users.create({
+ 'name': 'Pauline Poivraisselle',
+ 'login': 'pauline',
+ 'email': 'p.p@example.com',
+ 'notify_email': 'none',
+ 'groups_id': [(6, 0, [user_group_stock_user.id])]})
+ cls.user_stock_manager = Users.create({
+ 'name': 'Julie Tablier',
+ 'login': 'julie',
+ 'email': 'j.j@example.com',
+ 'notify_email': 'none',
+ 'groups_id': [(6, 0, [user_group_stock_manager.id])]})
+
+ # Warehouses
+ cls.warehouse_1 = cls.env['stock.warehouse'].create({
+ 'name': 'Base Warehouse',
+ 'reception_steps': 'one_step',
+ 'delivery_steps': 'ship_only',
+ 'code': 'BWH'})
+
+ # Locations
+ cls.location_1 = cls.env['stock.location'].create({
+ 'name': 'TestLocation1',
+ 'posx': 3,
+ 'location_id': cls.warehouse_1.lot_stock_id.id,
+ })
+ # Existing data
+ cls.existing_inventories = cls.env['stock.inventory'].search([])
+ cls.existing_quants = cls.env['stock.quant'].search([])
+
+ # Inventory
+ inventory_wizard = cls.env['stock.change.product.qty'].create({
+ 'product_id': cls.product_1.id,
+ 'new_quantity': 50.0,
+ 'location_id': cls.warehouse_1.lot_stock_id.id,
+ })
+ inventory_wizard.change_product_qty()
diff --git a/addons/stock/tests/test_owner_available.py b/addons/stock/tests/test_owner_available.py
deleted file mode 100644
index 7aa1e30d2e4..00000000000
--- a/addons/stock/tests/test_owner_available.py
+++ /dev/null
@@ -1,72 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-# Author: Leonardo Pistone
-# Copyright 2015 Camptocamp SA
-
-from openerp.addons.stock.tests.common import TestStockCommon
-
-
-class TestVirtualAvailable(TestStockCommon):
-
- def setUp(self):
- super(TestVirtualAvailable, self).setUp()
-
- self.env['stock.quant'].create({
- 'product_id': self.productA.id,
- 'location_id': self.stock_location,
- 'qty': 30.0,
- })
-
- self.env['stock.quant'].create({
- 'product_id': self.productA.id,
- 'location_id': self.stock_location,
- 'qty': 10.0,
- 'owner_id': self.ref('base.res_partner_4'),
- })
-
- self.picking_out = self.env['stock.picking'].create({
- 'picking_type_id': self.ref('stock.picking_type_out'),
- 'location_id': self.stock_location,
- 'location_dest_id': self.customer_location})
- self.env['stock.move'].create({
- 'name': 'a move',
- 'product_id': self.productA.id,
- 'product_uom_qty': 3.0,
- 'product_uom': self.productA.uom_id.id,
- 'picking_id': self.picking_out.id,
- 'location_id': self.stock_location,
- 'location_dest_id': self.customer_location
- })
-
- self.picking_out_2 = self.env['stock.picking'].create({
- 'picking_type_id': self.ref('stock.picking_type_out'),
- 'location_id': self.stock_location,
- 'location_dest_id': self.customer_location})
- self.env['stock.move'].create({
- 'restrict_partner_id': self.ref('base.res_partner_4'),
- 'name': 'another move',
- 'product_id': self.productA.id,
- 'product_uom_qty': 5.0,
- 'product_uom': self.productA.uom_id.id,
- 'picking_id': self.picking_out_2.id,
- 'location_id': self.stock_location,
- 'location_dest_id': self.customer_location
- })
-
-
- def test_without_owner(self):
- self.assertAlmostEqual(40.0, self.productA.virtual_available)
- self.picking_out.action_assign()
- self.picking_out_2.action_assign()
-
- self.assertAlmostEqual(32.0, self.productA.virtual_available)
-
- def test_with_owner(self):
- prod_context = self.productA.with_context(
- owner_id=self.ref('base.res_partner_4')
- )
- self.assertAlmostEqual(10.0, prod_context.virtual_available)
- self.picking_out.action_assign()
- self.picking_out_2.action_assign()
- self.assertAlmostEqual(5.0, prod_context.virtual_available)
diff --git a/addons/stock/tests/test_product.py b/addons/stock/tests/test_product.py
new file mode 100644
index 00000000000..5c67553585b
--- /dev/null
+++ b/addons/stock/tests/test_product.py
@@ -0,0 +1,64 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+# Author: Leonardo Pistone
+# Copyright 2015 Camptocamp SA
+
+from openerp.addons.stock.tests.common2 import TestStockCommon
+
+
+class TestVirtualAvailable(TestStockCommon):
+
+ def setUp(self):
+ super(TestVirtualAvailable, self).setUp()
+
+ self.env['stock.quant'].create({
+ 'product_id': self.product_3.id,
+ 'location_id': self.env.ref('stock.stock_location_stock').id,
+ 'qty': 30.0})
+
+ self.env['stock.quant'].create({
+ 'product_id': self.product_3.id,
+ 'location_id': self.env.ref('stock.stock_location_stock').id,
+ 'qty': 10.0,
+ 'owner_id': self.user_stock_user.partner_id.id})
+
+ self.picking_out = self.env['stock.picking'].create({
+ 'picking_type_id': self.ref('stock.picking_type_out'),
+ 'location_id': self.env.ref('stock.stock_location_stock').id,
+ 'location_dest_id': self.env.ref('stock.stock_location_customers').id})
+ self.env['stock.move'].create({
+ 'name': 'a move',
+ 'product_id': self.product_3.id,
+ 'product_uom_qty': 3.0,
+ 'product_uom': self.product_3.uom_id.id,
+ 'picking_id': self.picking_out.id,
+ 'location_id': self.env.ref('stock.stock_location_stock').id,
+ 'location_dest_id': self.env.ref('stock.stock_location_customers').id})
+
+ self.picking_out_2 = self.env['stock.picking'].create({
+ 'picking_type_id': self.ref('stock.picking_type_out'),
+ 'location_id': self.env.ref('stock.stock_location_stock').id,
+ 'location_dest_id': self.env.ref('stock.stock_location_customers').id})
+ self.env['stock.move'].create({
+ 'restrict_partner_id': self.user_stock_user.partner_id.id,
+ 'name': 'another move',
+ 'product_id': self.product_3.id,
+ 'product_uom_qty': 5.0,
+ 'product_uom': self.product_3.uom_id.id,
+ 'picking_id': self.picking_out_2.id,
+ 'location_id': self.env.ref('stock.stock_location_stock').id,
+ 'location_dest_id': self.env.ref('stock.stock_location_customers').id})
+
+ def test_without_owner(self):
+ self.assertAlmostEqual(40.0, self.product_3.virtual_available)
+ self.picking_out.action_assign()
+ self.picking_out_2.action_assign()
+ self.assertAlmostEqual(32.0, self.product_3.virtual_available)
+
+ def test_with_owner(self):
+ prod_context = self.product_3.with_context(owner_id=self.user_stock_user.partner_id.id)
+ self.assertAlmostEqual(10.0, prod_context.virtual_available)
+ self.picking_out.action_assign()
+ self.picking_out_2.action_assign()
+ self.assertAlmostEqual(5.0, prod_context.virtual_available)
diff --git a/addons/stock/tests/test_resupply.py b/addons/stock/tests/test_resupply.py
deleted file mode 100644
index 79ecbf456b7..00000000000
--- a/addons/stock/tests/test_resupply.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from openerp.addons.stock.tests.common import TestStockCommon
-from openerp.tools import mute_logger, float_round
-
-
-class TestResupply(TestStockCommon):
- def setUp(self):
- super(TestResupply, self).setUp()
- self.Warehouse = self.env['stock.warehouse']
- # create 2 WH, BIG and SMALL
- # SMALL resupplies from BIG
- self.bigwh = self.Warehouse.create({'name': 'BIG', 'code': 'B'})
- self.smallwh = self.Warehouse.create({'name': 'SMALL', 'code': 'S',
- 'default_resupply_wh_id': self.bigwh.id,
- 'resupply_wh_ids': [(6, 0, [self.bigwh.id])],
- })
- # minimum stock rule for Product A on SMALL
- Orderpoint = self.env['stock.warehouse.orderpoint']
- Orderpoint.create({'warehouse_id': self.smallwh.id,
- 'location_id': self.smallwh.lot_stock_id.id,
- 'product_id': self.productA.id,
- 'product_min_qty': 100,
- 'product_max_qty': 200,
- 'product_uom': self.uom_unit.id,
- })
- # create some stock on BIG
- Wiz = self.env['stock.change.product.qty']
- wiz = Wiz.create({'product_id': self.productA.id,
- 'new_quantity': 1000,
- 'location_id': self.bigwh.lot_stock_id.id,
- })
- wiz.change_product_qty()
-
- def test_resupply_from_wh(self):
- sched = self.env['procurement.order']
- sched.run_scheduler()
- # we generated 2 procurements for product A: one on small wh and the
- # other one on the transit location
- procs = sched.search([('product_id', '=', self.productA.id)])
- self.assertEqual(len(procs), 2)
- proc1 = sched.search([('product_id', '=', self.productA.id),
- ('warehouse_id', '=', self.smallwh.id)])
- self.assertEqual(proc1.state, 'running')
- proc2 = sched.search([('product_id', '=', self.productA.id),
- ('warehouse_id', '=', self.bigwh.id)])
- self.assertEqual(proc2.location_id.usage, 'transit')
- self.assertNotEqual(proc2.state, 'exception')
- proc2.run()
- self.assertEqual(proc2.state, 'running')
- self.assertTrue(proc2.rule_id)
diff --git a/addons/stock/tests/test_shipment.py b/addons/stock/tests/test_shipment.py
new file mode 100644
index 00000000000..98eb9f66d02
--- /dev/null
+++ b/addons/stock/tests/test_shipment.py
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+
+from odoo.addons.stock.tests.common2 import TestStockCommon
+
+
+class TestInventory(TestStockCommon):
+
+ def test_shipment(self):
+ # TDE NOTE: this test replaces test/shipment.yml present until saas-10
+ # 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]).do_transfer()
+
+ # 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.do_transfer()
+
+ # 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')
diff --git a/addons/stock/tests/test_warehouse.py b/addons/stock/tests/test_warehouse.py
new file mode 100644
index 00000000000..048392f5085
--- /dev/null
+++ b/addons/stock/tests/test_warehouse.py
@@ -0,0 +1,145 @@
+# -*- coding: utf-8 -*-
+
+from odoo.addons.stock.tests.common2 import TestStockCommon
+
+
+class TestInventory(TestStockCommon):
+
+ def test_inventory_product(self):
+ # TDE NOTE: replaces test/inventory.yml present until saas-10
+ inventory = self.env['stock.inventory'].sudo(self.user_stock_manager).create({
+ 'name': 'Starting for product_1',
+ 'filter': 'product',
+ 'location_id': self.warehouse_1.lot_stock_id.id,
+ 'product_id': self.product_1.id,
+ })
+ inventory.prepare_inventory()
+
+ # As done in common.py, there is already an inventory line existing
+ self.assertEqual(len(inventory.line_ids), 1)
+ self.assertEqual(inventory.line_ids.theoretical_qty, 50.0)
+ self.assertEqual(inventory.line_ids.product_id, self.product_1)
+ self.assertEqual(inventory.line_ids.product_uom_id, self.uom_unit)
+
+ # Update the line, set to 35
+ inventory.line_ids.write({'product_qty': 35.0})
+ inventory.action_done()
+
+ # Check related move and quants
+ self.assertIn(inventory.name, inventory.move_ids.name)
+ self.assertEqual(inventory.move_ids.product_qty, 15.0)
+ self.assertEqual(inventory.move_ids.location_id, self.warehouse_1.lot_stock_id)
+ self.assertEqual(inventory.move_ids.location_dest_id, self.env.ref('stock.location_inventory')) # Inventory loss
+ self.assertEqual(inventory.move_ids.state, 'done')
+ self.assertEqual(inventory.move_ids.quant_ids.location_id, self.env.ref('stock.location_inventory')) # Inventory loss
+ self.assertEqual(inventory.move_ids.quant_ids.qty, 15.0)
+ self.assertEqual(inventory.move_ids.quant_ids.history_ids[0].product_qty, 50.0)
+
+ # Check quantity of product in various locations: current, its parent, brother and other
+ self.assertEqual(self.product_1.with_context(location=self.warehouse_1.lot_stock_id.id).qty_available, 35.0)
+ self.assertEqual(self.product_1.with_context(location=self.warehouse_1.lot_stock_id.location_id.id).qty_available, 35.0)
+ self.assertEqual(self.product_1.with_context(location=self.warehouse_1.view_location_id.id).qty_available, 35.0)
+ self.assertEqual(self.product_1.with_context(location=self.warehouse_1.wh_input_stock_loc_id.id).qty_available, 0.0)
+ self.assertEqual(self.product_1.with_context(location=self.env.ref('stock.stock_location_stock').id).qty_available, 0.0)
+
+ def test_inventory_wizard(self):
+ # Check inventory performed in setup was effectivley performed
+ self.assertEqual(self.product_1.virtual_available, 50.0)
+ self.assertEqual(self.product_1.qty_available, 50.0)
+
+ # Check inventory obj details (1 inventory with 1 line, because 1 product change)
+ inventory = self.env['stock.inventory'].search([('id', 'not in', self.existing_inventories.ids)])
+ self.assertEqual(len(inventory), 1)
+ self.assertIn('INV: %s' % self.product_1.name, inventory.name)
+ self.assertEqual(len(inventory.line_ids), 1)
+ self.assertEqual(inventory.line_ids.product_id, self.product_1)
+ self.assertEqual(inventory.line_ids.product_qty, 50.0)
+
+ # Check associated quants: 1 quant for the product and the quantity
+ quant = self.env['stock.quant'].search([('id', 'not in', self.existing_quants.ids)])
+ self.assertEqual(len(quant), 1)
+ # print quant.name, quant.product_id, quant.location_id
+ # TDE TODO: expand this test
+
+ def test_basic_move(self):
+ # TDE NOTE: replaces test/move.yml present until saas-10, including onchanges
+ Move = self.env['stock.move'].sudo(self.user_stock_manager)
+ product = self.product_3.sudo(self.user_stock_manager)
+
+ # simulate create + onchange
+ customer_move = self._create_move(product, self.warehouse_1.lot_stock_id, self.env.ref('stock.stock_location_customers'), product_uom_qty=5)
+
+ # test move values
+ self.assertEqual(customer_move.product_uom, self.uom_kunit)
+ self.assertEqual(customer_move.location_id, self.warehouse_1.lot_stock_id)
+ self.assertEqual(customer_move.location_dest_id, self.env.ref('stock.stock_location_customers'))
+
+ # confirm move, check quantity on hand and virtually available, without location context
+ customer_move.action_confirm()
+ self.assertEqual(product.qty_available, 0.0)
+ self.assertEqual(product.virtual_available, -5.0)
+
+ customer_move.action_done()
+ self.assertEqual(product.qty_available, -5.0)
+ self.assertEqual(product.with_context(location=self.env.ref('stock.stock_location_customers').id).qty_available, 5.0)
+
+ # compensate negative quants by receiving products from supplier
+ receive_move = self._create_move(product, self.env.ref('stock.stock_location_suppliers'), self.warehouse_1.lot_stock_id, product_uom_qty=15)
+
+ receive_move.action_confirm()
+ receive_move.action_done()
+
+ self.assertEqual(product.qty_available, 10.0)
+ self.assertEqual(product.virtual_available, 10.0)
+
+ # new move towards customer
+ customer_move_2 = self._create_move(product, self.warehouse_1.lot_stock_id, self.env.ref('stock.stock_location_customers'), product_uom_qty=2)
+
+ customer_move_2.action_confirm()
+ self.assertEqual(product.qty_available, 10.0)
+ self.assertEqual(product.virtual_available, 8.0)
+
+ customer_move_2.action_done()
+ self.assertEqual(product.qty_available, 8.0)
+ self.assertEqual(product.with_context(location=self.env.ref('stock.stock_location_customers').id).qty_available, 7.0)
+
+
+class TestResupply(TestStockCommon):
+ def setUp(self):
+ super(TestResupply, self).setUp()
+
+ self.warehouse_2 = self.env['stock.warehouse'].create({
+ 'name': 'Small Warehouse',
+ 'code': 'SWH',
+ 'default_resupply_wh_id': self.warehouse_1.id,
+ '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,
+ })
+
+ def test_resupply_from_wh(self):
+ # TDE NOTE: replaces tests/test_resupply.py, present until saas-10
+ OrderScheduler = self.env['procurement.order']
+ OrderScheduler.run_scheduler()
+ # we generated 2 procurements for product A: one on small wh and the other one on the transit location
+ procs = OrderScheduler.search([('product_id', '=', self.product_1.id)])
+ self.assertEqual(len(procs), 2)
+
+ proc1 = procs.filtered(lambda order: order.warehouse_id == self.warehouse_2)
+ self.assertEqual(proc1.state, 'running')
+
+ proc2 = procs.filtered(lambda order: order.warehouse_id == self.warehouse_1)
+ self.assertEqual(proc2.location_id.usage, 'transit')
+ self.assertNotEqual(proc2.state, 'exception')
+
+ proc2.run()
+ self.assertEqual(proc2.state, 'running')
+ self.assertTrue(proc2.rule_id)