In the web client, in a real use case, it's not possible to write on fields which are invisible, as it's not possible to write on fields which are readonly. This is a first step in the goal to change the behavior of the `groups=` attribute in the back-end views, to remove them for the view instead of making them invisible. This is mainly to reduce the diff of the revision that will introduce the mentioned above behavior change. As nodes with `groups=` will be removed from the view when the user doesn't have the group, it's no longer possible to set a value on a field having a `groups=` the user doesn't have in the `Form` test class, as the field will no longer be at all in the view. However, these unit tests shouldn't have been able to set values on invisible fields in the first place. This revision therefore aims to correct the unit tests setting value on fields which were invisible because the user executing the test was not part of the required group(s) for these fields to be visible in the view. closes odoo/odoo#94337 Related: odoo/enterprise#28936 Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
632 lines
29 KiB
Python
632 lines
29 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
from odoo.addons.stock.tests.common2 import TestStockCommon
|
|
from odoo.tests import Form
|
|
from odoo.exceptions import UserError
|
|
from odoo.tools import mute_logger
|
|
|
|
|
|
class TestWarehouse(TestStockCommon):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
cls.partner = cls.env['res.partner'].create({'name': 'Deco Addict'})
|
|
|
|
def test_inventory_product(self):
|
|
self.product_1.type = 'product'
|
|
product_1_quant = self.env['stock.quant'].with_context(inventory_mode=True).create({
|
|
'product_id': self.product_1.id,
|
|
'inventory_quantity': 50.0,
|
|
'location_id': self.warehouse_1.lot_stock_id.id,
|
|
})
|
|
product_1_quant.action_apply_inventory()
|
|
|
|
# Make sure the inventory was successful
|
|
move_in_id = self.env['stock.move'].search([('is_inventory', '=', True), ('product_id', '=', self.product_1.id)])
|
|
self.assertEqual(len(move_in_id), 1)
|
|
self.assertEqual(move_in_id.product_qty, 50.0)
|
|
self.assertEqual(product_1_quant.quantity, 50.0)
|
|
self.assertEqual(move_in_id.product_uom, self.product_1.uom_id)
|
|
self.assertEqual(move_in_id.state, 'done')
|
|
|
|
# Update the inventory, set to 35
|
|
product_1_quant.inventory_quantity = 35.0
|
|
product_1_quant.action_apply_inventory()
|
|
|
|
# Check related move and quants
|
|
move_ids = self.env['stock.move'].search([('is_inventory', '=', True), ('product_id', '=', self.product_1.id)])
|
|
self.assertEqual(len(move_ids), 2)
|
|
move_out_id = move_ids[-1]
|
|
self.assertEqual(move_out_id.product_qty, 15.0)
|
|
self.assertEqual(move_out_id.location_id, self.warehouse_1.lot_stock_id)
|
|
self.assertEqual(move_out_id.location_dest_id, self.product_1.property_stock_inventory) # Inventory loss
|
|
self.assertEqual(move_out_id.state, 'done')
|
|
|
|
quants = self.env['stock.quant']._gather(self.product_1, self.product_1.property_stock_inventory)
|
|
self.assertEqual(len(quants), 1) # One quant created for inventory loss
|
|
|
|
# Check quantity of product in various locations: current, its parent, brother and other
|
|
self.assertEqual(self.env['stock.quant']._gather(self.product_1, self.warehouse_1.lot_stock_id).quantity, 35.0)
|
|
self.assertEqual(self.env['stock.quant']._gather(self.product_1, self.warehouse_1.lot_stock_id.location_id).quantity, 35.0)
|
|
self.assertEqual(self.env['stock.quant']._gather(self.product_1, self.warehouse_1.view_location_id).quantity, 35.0)
|
|
|
|
self.assertEqual(self.env['stock.quant']._gather(self.product_1, self.warehouse_1.wh_input_stock_loc_id).quantity, 0.0)
|
|
self.assertEqual(self.env['stock.quant']._gather(self.product_1, self.env.ref('stock.stock_location_stock')).quantity, 0.0)
|
|
|
|
def test_inventory_wizard_as_manager(self):
|
|
""" Using the "Update Quantity" wizard as stock manager.
|
|
"""
|
|
self.product_1.type = 'product'
|
|
InventoryWizard = self.env['stock.change.product.qty'].with_user(self.user_stock_manager)
|
|
inventory_wizard = InventoryWizard.create({
|
|
'product_id': self.product_1.id,
|
|
'product_tmpl_id': self.product_1.product_tmpl_id.id,
|
|
'new_quantity': 50.0,
|
|
})
|
|
inventory_wizard.change_product_qty()
|
|
# Check quantity was updated
|
|
self.assertEqual(self.product_1.virtual_available, 50.0)
|
|
self.assertEqual(self.product_1.qty_available, 50.0)
|
|
|
|
# Check associated quants: 2 quants for the product and the quantity (1 in stock, 1 in inventory adjustment)
|
|
quant = self.env['stock.quant'].search([('id', 'not in', self.existing_quants.ids)])
|
|
self.assertEqual(len(quant), 2)
|
|
|
|
def test_inventory_wizard_as_user(self):
|
|
""" Using the "Update Quantity" wizard as stock user.
|
|
"""
|
|
self.product_1.type = 'product'
|
|
InventoryWizard = self.env['stock.change.product.qty'].with_user(self.user_stock_user)
|
|
inventory_wizard = InventoryWizard.create({
|
|
'product_id': self.product_1.id,
|
|
'product_tmpl_id': self.product_1.product_tmpl_id.id,
|
|
'new_quantity': 50.0,
|
|
})
|
|
# User has no right on quant, must raise an AccessError
|
|
with self.assertRaises(UserError):
|
|
inventory_wizard.change_product_qty()
|
|
|
|
def test_basic_move(self):
|
|
product = self.product_3.with_user(self.user_stock_manager)
|
|
product.type = 'product'
|
|
picking_out = self.env['stock.picking'].create({
|
|
'partner_id': self.partner.id,
|
|
'picking_type_id': self.env.ref('stock.picking_type_out').id,
|
|
'location_id': self.warehouse_1.lot_stock_id.id,
|
|
'location_dest_id': self.env.ref('stock.stock_location_customers').id,
|
|
})
|
|
customer_move = self.env['stock.move'].create({
|
|
'name': product.name,
|
|
'product_id': product.id,
|
|
'product_uom_qty': 5,
|
|
'product_uom': product.uom_id.id,
|
|
'picking_id': picking_out.id,
|
|
'location_id': self.warehouse_1.lot_stock_id.id,
|
|
'location_dest_id': self.env.ref('stock.stock_location_customers').id,
|
|
})
|
|
# simulate create + onchange
|
|
# test move values
|
|
self.assertEqual(customer_move.product_uom, product.uom_id)
|
|
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.quantity_done = 5
|
|
customer_move._action_done()
|
|
self.assertEqual(product.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.quantity_done = 15
|
|
receive_move._action_done()
|
|
|
|
product._compute_quantities()
|
|
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()
|
|
product._compute_quantities()
|
|
self.assertEqual(product.qty_available, 10.0)
|
|
self.assertEqual(product.virtual_available, 8.0)
|
|
|
|
customer_move_2.quantity_done = 2.0
|
|
customer_move_2._action_done()
|
|
product._compute_quantities()
|
|
self.assertEqual(product.qty_available, 8.0)
|
|
|
|
def test_inventory_adjustment_and_negative_quants_1(self):
|
|
"""Make sure negative quants from returns get wiped out with an inventory adjustment"""
|
|
productA = self.env['product.product'].create({'name': 'Product A', 'type': 'product'})
|
|
stock_location = self.env.ref('stock.stock_location_stock')
|
|
customer_location = self.env.ref('stock.stock_location_customers')
|
|
|
|
# Create a picking out and force availability
|
|
picking_out = self.env['stock.picking'].create({
|
|
'partner_id': self.partner.id,
|
|
'picking_type_id': self.env.ref('stock.picking_type_out').id,
|
|
'location_id': stock_location.id,
|
|
'location_dest_id': customer_location.id,
|
|
})
|
|
self.env['stock.move'].create({
|
|
'name': productA.name,
|
|
'product_id': productA.id,
|
|
'product_uom_qty': 1,
|
|
'product_uom': productA.uom_id.id,
|
|
'picking_id': picking_out.id,
|
|
'location_id': stock_location.id,
|
|
'location_dest_id': customer_location.id,
|
|
})
|
|
picking_out.action_confirm()
|
|
picking_out.move_ids.quantity_done = 1
|
|
picking_out._action_done()
|
|
|
|
quant = self.env['stock.quant'].search([('product_id', '=', productA.id), ('location_id', '=', stock_location.id)])
|
|
self.assertEqual(len(quant), 1)
|
|
stock_return_picking_form = Form(self.env['stock.return.picking']
|
|
.with_context(active_ids=picking_out.ids, active_id=picking_out.ids[0],
|
|
active_model='stock.picking'))
|
|
stock_return_picking = stock_return_picking_form.save()
|
|
stock_return_picking.product_return_moves.quantity = 1.0
|
|
stock_return_picking_action = stock_return_picking.create_returns()
|
|
return_pick = self.env['stock.picking'].browse(stock_return_picking_action['res_id'])
|
|
return_pick.action_assign()
|
|
return_pick.move_ids.quantity_done = 1
|
|
return_pick._action_done()
|
|
|
|
quant = self.env['stock.quant'].search([('product_id', '=', productA.id), ('location_id', '=', stock_location.id)])
|
|
self.assertEqual(sum(quant.mapped('quantity')), 0)
|
|
|
|
def test_inventory_adjustment_and_negative_quants_2(self):
|
|
"""Make sure negative quants get wiped out with an inventory adjustment"""
|
|
productA = self.env['product.product'].create({'name': 'Product A', 'type': 'product'})
|
|
stock_location = self.env.ref('stock.stock_location_stock')
|
|
customer_location = self.env.ref('stock.stock_location_customers')
|
|
location_loss = productA.property_stock_inventory
|
|
|
|
# Create a picking out and force availability
|
|
picking_out = self.env['stock.picking'].create({
|
|
'partner_id': self.partner.id,
|
|
'picking_type_id': self.env.ref('stock.picking_type_out').id,
|
|
'location_id': stock_location.id,
|
|
'location_dest_id': customer_location.id,
|
|
})
|
|
self.env['stock.move'].create({
|
|
'name': productA.name,
|
|
'product_id': productA.id,
|
|
'product_uom_qty': 1,
|
|
'product_uom': productA.uom_id.id,
|
|
'picking_id': picking_out.id,
|
|
'location_id': stock_location.id,
|
|
'location_dest_id': customer_location.id,
|
|
})
|
|
picking_out.action_confirm()
|
|
picking_out.move_ids.quantity_done = 1
|
|
picking_out._action_done()
|
|
|
|
# Make an inventory adjustment to set the quantity to 0
|
|
quant = self.env['stock.quant'].search([('product_id', '=', productA.id), ('location_id', '=', stock_location.id)])
|
|
self.assertEqual(len(quant), 1, "Wrong number of quants created.")
|
|
self.assertEqual(quant.quantity, -1, "Theoretical quantity should be -1.")
|
|
# Put the quantity back to 0
|
|
quant.inventory_quantity = 0
|
|
quant.action_apply_inventory()
|
|
|
|
# The inventory adjustment should have created one
|
|
move = self.env['stock.move'].search([('product_id', '=', productA.id), ('is_inventory', '=', True)])
|
|
self.assertEqual(len(move), 1)
|
|
self.assertEqual(move.product_qty, 1, "Moves created with wrong quantity.")
|
|
self.assertEqual(move.location_id.id, location_loss.id)
|
|
|
|
# There should be no quant in the stock location
|
|
self.env['stock.quant']._quant_tasks()
|
|
quants = self.env['stock.quant'].search([('product_id', '=', productA.id), ('location_id', '=', stock_location.id)])
|
|
self.assertEqual(sum(quants.mapped('quantity')), 0)
|
|
|
|
# There should be one quant in the inventory loss location
|
|
quant = self.env['stock.quant'].search([('product_id', '=', productA.id), ('location_id', '=', location_loss.id)])
|
|
self.assertEqual(len(quant), 1)
|
|
|
|
def test_resupply_route(self):
|
|
""" Simulate a resupply chain between warehouses.
|
|
Stock -> transit -> Dist. -> transit -> Shop -> Customer
|
|
Create the move from Shop to Customer and ensure that all the pull
|
|
rules are triggered in order to complete the move chain to Stock.
|
|
"""
|
|
warehouse_stock = self.env['stock.warehouse'].create({
|
|
'name': 'Stock.',
|
|
'code': 'STK',
|
|
})
|
|
|
|
distribution_partner = self.env['res.partner'].create({'name': 'Distribution Center'})
|
|
warehouse_distribution = self.env['stock.warehouse'].create({
|
|
'name': 'Dist.',
|
|
'code': 'DIST',
|
|
'resupply_wh_ids': [(6, 0, [warehouse_stock.id])],
|
|
'partner_id': distribution_partner.id,
|
|
})
|
|
|
|
warehouse_shop = self.env['stock.warehouse'].create({
|
|
'name': 'Shop',
|
|
'code': 'SHOP',
|
|
'resupply_wh_ids': [(6, 0, [warehouse_distribution.id])]
|
|
})
|
|
|
|
route_stock_to_dist = warehouse_distribution.resupply_route_ids
|
|
route_dist_to_shop = warehouse_shop.resupply_route_ids
|
|
|
|
# Change the procure_method on the pull rules between dist and shop
|
|
# warehouses. Since mto and resupply routes are both on product it will
|
|
# select one randomly between them and if it select the resupply it is
|
|
# 'make to stock' and it will not create the picking between stock and
|
|
# dist warehouses.
|
|
route_dist_to_shop.rule_ids.write({'procure_method': 'make_to_order'})
|
|
|
|
product = self.env['product.product'].create({
|
|
'name': 'Fakir',
|
|
'type': 'product',
|
|
'route_ids': [(4, route_id) for route_id in [route_stock_to_dist.id, route_dist_to_shop.id, self.env.ref('stock.route_warehouse0_mto').id]],
|
|
})
|
|
|
|
picking_out = self.env['stock.picking'].create({
|
|
'partner_id': self.partner.id,
|
|
'picking_type_id': self.env.ref('stock.picking_type_out').id,
|
|
'location_id': warehouse_shop.lot_stock_id.id,
|
|
'location_dest_id': self.env.ref('stock.stock_location_customers').id,
|
|
})
|
|
self.env['stock.move'].create({
|
|
'name': product.name,
|
|
'product_id': product.id,
|
|
'product_uom_qty': 1,
|
|
'product_uom': product.uom_id.id,
|
|
'picking_id': picking_out.id,
|
|
'location_id': warehouse_shop.lot_stock_id.id,
|
|
'location_dest_id': self.env.ref('stock.stock_location_customers').id,
|
|
'warehouse_id': warehouse_shop.id,
|
|
'procure_method': 'make_to_order',
|
|
})
|
|
picking_out.action_confirm()
|
|
|
|
moves = self.env['stock.move'].search([('product_id', '=', product.id)])
|
|
# Shop/Stock -> Customer
|
|
# Transit -> Shop/Stock
|
|
# Dist/Stock -> Transit
|
|
# Transit -> Dist/Stock
|
|
# Stock/Stock -> Transit
|
|
self.assertEqual(len(moves), 5, 'Invalid moves number.')
|
|
self.assertTrue(self.env['stock.move'].search([('location_id', '=', warehouse_stock.lot_stock_id.id)]))
|
|
self.assertTrue(self.env['stock.move'].search([('location_dest_id', '=', warehouse_distribution.lot_stock_id.id)]))
|
|
self.assertTrue(self.env['stock.move'].search([('location_id', '=', warehouse_distribution.lot_stock_id.id)]))
|
|
self.assertTrue(self.env['stock.move'].search([('location_dest_id', '=', warehouse_shop.lot_stock_id.id)]))
|
|
self.assertTrue(self.env['stock.move'].search([('location_id', '=', warehouse_shop.lot_stock_id.id)]))
|
|
|
|
self.assertTrue(self.env['stock.picking'].search([('location_id', '=', self.env.company.internal_transit_location_id.id), ('partner_id', '=', distribution_partner.id)]))
|
|
self.assertTrue(self.env['stock.picking'].search([('location_dest_id', '=', self.env.company.internal_transit_location_id.id), ('partner_id', '=', distribution_partner.id)]))
|
|
|
|
def test_mutiple_resupply_warehouse(self):
|
|
""" Simulate the following situation:
|
|
- 2 shops with stock are resupply by 2 distinct warehouses
|
|
- Shop Namur is resupply by the warehouse stock Namur
|
|
- Shop Wavre is resupply by the warehouse stock Wavre
|
|
- Simulate 2 moves for the same product but in different shop.
|
|
This test ensure that the move are supplied by the correct distribution
|
|
warehouse.
|
|
"""
|
|
customer_location = self.env.ref('stock.stock_location_customers')
|
|
|
|
warehouse_distribution_wavre = self.env['stock.warehouse'].create({
|
|
'name': 'Stock Wavre.',
|
|
'code': 'WV',
|
|
})
|
|
|
|
warehouse_shop_wavre = self.env['stock.warehouse'].create({
|
|
'name': 'Shop Wavre',
|
|
'code': 'SHWV',
|
|
'resupply_wh_ids': [(6, 0, [warehouse_distribution_wavre.id])]
|
|
})
|
|
|
|
warehouse_distribution_namur = self.env['stock.warehouse'].create({
|
|
'name': 'Stock Namur.',
|
|
'code': 'NM',
|
|
})
|
|
|
|
warehouse_shop_namur = self.env['stock.warehouse'].create({
|
|
'name': 'Shop Namur',
|
|
'code': 'SHNM',
|
|
'resupply_wh_ids': [(6, 0, [warehouse_distribution_namur.id])]
|
|
})
|
|
|
|
route_shop_namur = warehouse_shop_namur.resupply_route_ids
|
|
route_shop_wavre = warehouse_shop_wavre.resupply_route_ids
|
|
# The product contains the 2 resupply routes.
|
|
product = self.env['product.product'].create({
|
|
'name': 'Fakir',
|
|
'type': 'product',
|
|
'route_ids': [(4, route_id) for route_id in [route_shop_namur.id, route_shop_wavre.id, self.env.ref('stock.route_warehouse0_mto').id]],
|
|
})
|
|
|
|
# Add 1 quant in each distribution warehouse.
|
|
self.env['stock.quant']._update_available_quantity(product, warehouse_distribution_wavre.lot_stock_id, 1.0)
|
|
self.env['stock.quant']._update_available_quantity(product, warehouse_distribution_namur.lot_stock_id, 1.0)
|
|
|
|
# Create the move for the shop Namur. Should create a resupply from
|
|
# distribution warehouse Namur.
|
|
picking_out_namur = self.env['stock.picking'].create({
|
|
'partner_id': self.partner.id,
|
|
'picking_type_id': self.env.ref('stock.picking_type_out').id,
|
|
'location_id': warehouse_shop_namur.lot_stock_id.id,
|
|
'location_dest_id': customer_location.id,
|
|
})
|
|
self.env['stock.move'].create({
|
|
'name': product.name,
|
|
'product_id': product.id,
|
|
'product_uom_qty': 1,
|
|
'product_uom': product.uom_id.id,
|
|
'picking_id': picking_out_namur.id,
|
|
'location_id': warehouse_shop_namur.lot_stock_id.id,
|
|
'location_dest_id': customer_location.id,
|
|
'warehouse_id': warehouse_shop_namur.id,
|
|
'procure_method': 'make_to_order',
|
|
})
|
|
picking_out_namur.action_confirm()
|
|
|
|
# Validate the picking
|
|
# Dist. warehouse Namur -> transit Location -> Shop Namur
|
|
picking_stock_transit = self.env['stock.picking'].search([('location_id', '=', warehouse_distribution_namur.lot_stock_id.id)])
|
|
self.assertTrue(picking_stock_transit)
|
|
picking_stock_transit.action_assign()
|
|
picking_stock_transit.move_ids[0].quantity_done = 1.0
|
|
picking_stock_transit._action_done()
|
|
|
|
picking_transit_shop_namur = self.env['stock.picking'].search([('location_dest_id', '=', warehouse_shop_namur.lot_stock_id.id)])
|
|
self.assertTrue(picking_transit_shop_namur)
|
|
picking_transit_shop_namur.action_assign()
|
|
picking_transit_shop_namur.move_ids[0].quantity_done = 1.0
|
|
picking_transit_shop_namur._action_done()
|
|
|
|
picking_out_namur.action_assign()
|
|
picking_out_namur.move_ids[0].quantity_done = 1.0
|
|
picking_out_namur._action_done()
|
|
|
|
# Check that the correct quantity has been provided to customer
|
|
self.assertEqual(self.env['stock.quant']._gather(product, customer_location).quantity, 1)
|
|
# Ensure there still no quants in distribution warehouse
|
|
self.assertEqual(sum(self.env['stock.quant']._gather(product, warehouse_distribution_namur.lot_stock_id).mapped('quantity')), 0)
|
|
|
|
# Create the move for the shop Wavre. Should create a resupply from
|
|
# distribution warehouse Wavre.
|
|
picking_out_wavre = self.env['stock.picking'].create({
|
|
'partner_id': self.partner.id,
|
|
'picking_type_id': self.env.ref('stock.picking_type_out').id,
|
|
'location_id': warehouse_shop_wavre.lot_stock_id.id,
|
|
'location_dest_id': customer_location.id,
|
|
})
|
|
self.env['stock.move'].create({
|
|
'name': product.name,
|
|
'product_id': product.id,
|
|
'product_uom_qty': 1,
|
|
'product_uom': product.uom_id.id,
|
|
'picking_id': picking_out_wavre.id,
|
|
'location_id': warehouse_shop_wavre.lot_stock_id.id,
|
|
'location_dest_id': customer_location.id,
|
|
'warehouse_id': warehouse_shop_wavre.id,
|
|
'procure_method': 'make_to_order',
|
|
})
|
|
picking_out_wavre.action_confirm()
|
|
|
|
# Validate the picking
|
|
# Dist. warehouse Wavre -> transit Location -> Shop Wavre
|
|
picking_stock_transit = self.env['stock.picking'].search([('location_id', '=', warehouse_distribution_wavre.lot_stock_id.id)])
|
|
self.assertTrue(picking_stock_transit)
|
|
picking_stock_transit.action_assign()
|
|
picking_stock_transit.move_ids[0].quantity_done = 1.0
|
|
picking_stock_transit._action_done()
|
|
|
|
picking_transit_shop_wavre = self.env['stock.picking'].search([('location_dest_id', '=', warehouse_shop_wavre.lot_stock_id.id)])
|
|
self.assertTrue(picking_transit_shop_wavre)
|
|
picking_transit_shop_wavre.action_assign()
|
|
picking_transit_shop_wavre.move_ids[0].quantity_done = 1.0
|
|
picking_transit_shop_wavre._action_done()
|
|
|
|
picking_out_wavre.action_assign()
|
|
picking_out_wavre.move_ids[0].quantity_done = 1.0
|
|
picking_out_wavre._action_done()
|
|
|
|
# Check that the correct quantity has been provided to customer
|
|
self.assertEqual(self.env['stock.quant']._gather(product, customer_location).quantity, 2)
|
|
# Ensure there still no quants in distribution warehouse
|
|
self.assertEqual(sum(self.env['stock.quant']._gather(product, warehouse_distribution_wavre.lot_stock_id).mapped('quantity')), 0)
|
|
|
|
def test_noleak(self):
|
|
# non-regression test to avoid company_id leaking to other warehouses (see blame)
|
|
partner = self.env['res.partner'].create({'name': 'Chicago partner'})
|
|
company = self.env['res.company'].create({
|
|
'name': 'My Company (Chicago)1',
|
|
'currency_id': self.ref('base.USD')
|
|
})
|
|
self.env['stock.warehouse'].create({
|
|
'name': 'Chicago Warehouse2',
|
|
'company_id': company.id,
|
|
'code': 'Chic2',
|
|
'partner_id': partner.id
|
|
})
|
|
wh = self.env["stock.warehouse"].search([])
|
|
|
|
assert len(set(wh.mapped("company_id.id"))) > 1
|
|
|
|
companies_before = wh.mapped(lambda w: (w.id, w.company_id))
|
|
# writing on any field should change the company of warehouses
|
|
wh.write({"name": "whatever"})
|
|
companies_after = wh.mapped(lambda w: (w.id, w.company_id))
|
|
|
|
self.assertEqual(companies_after, companies_before)
|
|
|
|
def test_toggle_active_warehouse_1(self):
|
|
""" Basic test that create a warehouse with classic configuration.
|
|
Archive it and check that locations, picking types, routes, rules are
|
|
correclty active or archive.
|
|
"""
|
|
wh = Form(self.env['stock.warehouse'])
|
|
wh.name = "The attic of Willy"
|
|
wh.code = "WIL"
|
|
warehouse = wh.save()
|
|
|
|
custom_location = Form(self.env['stock.location'])
|
|
custom_location.name = "A Trunk"
|
|
custom_location.location_id = warehouse.lot_stock_id
|
|
custom_location = custom_location.save()
|
|
|
|
# Archive warehouse
|
|
warehouse.toggle_active()
|
|
# Global rule
|
|
self.assertFalse(warehouse.mto_pull_id.active)
|
|
|
|
# Route
|
|
self.assertFalse(warehouse.reception_route_id.active)
|
|
self.assertFalse(warehouse.delivery_route_id.active)
|
|
|
|
# Location
|
|
self.assertFalse(warehouse.lot_stock_id.active)
|
|
self.assertFalse(warehouse.wh_input_stock_loc_id.active)
|
|
self.assertFalse(warehouse.wh_qc_stock_loc_id.active)
|
|
self.assertFalse(warehouse.wh_output_stock_loc_id.active)
|
|
self.assertFalse(warehouse.wh_pack_stock_loc_id.active)
|
|
self.assertFalse(custom_location.active)
|
|
|
|
# Picking Type
|
|
self.assertFalse(warehouse.in_type_id.active)
|
|
self.assertFalse(warehouse.in_type_id.show_operations)
|
|
self.assertFalse(warehouse.out_type_id.active)
|
|
self.assertFalse(warehouse.int_type_id.active)
|
|
self.assertFalse(warehouse.pick_type_id.active)
|
|
self.assertFalse(warehouse.pack_type_id.active)
|
|
|
|
# Active warehouse
|
|
warehouse.toggle_active()
|
|
# Global rule
|
|
self.assertTrue(warehouse.mto_pull_id.active)
|
|
|
|
# Route
|
|
self.assertTrue(warehouse.reception_route_id.active)
|
|
self.assertTrue(warehouse.delivery_route_id.active)
|
|
|
|
# Location
|
|
self.assertTrue(warehouse.lot_stock_id.active)
|
|
self.assertFalse(warehouse.wh_input_stock_loc_id.active)
|
|
self.assertFalse(warehouse.wh_qc_stock_loc_id.active)
|
|
self.assertFalse(warehouse.wh_output_stock_loc_id.active)
|
|
self.assertFalse(warehouse.wh_pack_stock_loc_id.active)
|
|
self.assertTrue(custom_location.active)
|
|
|
|
# Picking Type
|
|
self.assertTrue(warehouse.in_type_id.active)
|
|
self.assertFalse(warehouse.in_type_id.show_operations)
|
|
self.assertTrue(warehouse.out_type_id.active)
|
|
self.assertTrue(warehouse.int_type_id.active)
|
|
self.assertFalse(warehouse.pick_type_id.active)
|
|
self.assertFalse(warehouse.pack_type_id.active)
|
|
|
|
def test_toggle_active_warehouse_2(self):
|
|
# Required for `delivery_steps` to be visible in the view
|
|
self.env.user.groups_id += self.env.ref('stock.group_adv_location')
|
|
wh = Form(self.env['stock.warehouse'])
|
|
wh.name = "The attic of Willy"
|
|
wh.code = "WIL"
|
|
wh.reception_steps = "two_steps"
|
|
wh.delivery_steps = "pick_pack_ship"
|
|
warehouse = wh.save()
|
|
|
|
warehouse.resupply_wh_ids = [(6, 0, [self.warehouse_1.id])]
|
|
|
|
custom_location = Form(self.env['stock.location'])
|
|
custom_location.name = "A Trunk"
|
|
custom_location.location_id = warehouse.lot_stock_id
|
|
custom_location = custom_location.save()
|
|
|
|
# Add a warehouse on the route.
|
|
warehouse.reception_route_id.write({
|
|
'warehouse_ids': [(4, self.warehouse_1.id)]
|
|
})
|
|
|
|
route = Form(self.env['stock.route'])
|
|
route.name = "Stair"
|
|
route = route.save()
|
|
|
|
route.warehouse_ids = [(6, 0, [warehouse.id, self.warehouse_1.id])]
|
|
|
|
# Pre archive a location and a route
|
|
warehouse.delivery_route_id.toggle_active()
|
|
warehouse.wh_pack_stock_loc_id.toggle_active()
|
|
|
|
# Archive warehouse
|
|
warehouse.toggle_active()
|
|
# Global rule
|
|
self.assertFalse(warehouse.mto_pull_id.active)
|
|
|
|
# Route
|
|
self.assertTrue(warehouse.reception_route_id.active)
|
|
self.assertFalse(warehouse.delivery_route_id.active)
|
|
self.assertTrue(route.active)
|
|
|
|
# Location
|
|
self.assertFalse(warehouse.lot_stock_id.active)
|
|
self.assertFalse(warehouse.wh_input_stock_loc_id.active)
|
|
self.assertFalse(warehouse.wh_qc_stock_loc_id.active)
|
|
self.assertFalse(warehouse.wh_output_stock_loc_id.active)
|
|
self.assertFalse(warehouse.wh_pack_stock_loc_id.active)
|
|
self.assertFalse(custom_location.active)
|
|
|
|
# Picking Type
|
|
self.assertFalse(warehouse.in_type_id.active)
|
|
self.assertFalse(warehouse.out_type_id.active)
|
|
self.assertFalse(warehouse.int_type_id.active)
|
|
self.assertFalse(warehouse.pick_type_id.active)
|
|
self.assertFalse(warehouse.pack_type_id.active)
|
|
|
|
# Active warehouse
|
|
warehouse.toggle_active()
|
|
# Global rule
|
|
self.assertTrue(warehouse.mto_pull_id.active)
|
|
|
|
# Route
|
|
self.assertTrue(warehouse.reception_route_id.active)
|
|
self.assertTrue(warehouse.delivery_route_id.active)
|
|
|
|
# Location
|
|
self.assertTrue(warehouse.lot_stock_id.active)
|
|
self.assertTrue(warehouse.wh_input_stock_loc_id.active)
|
|
self.assertFalse(warehouse.wh_qc_stock_loc_id.active)
|
|
self.assertTrue(warehouse.wh_output_stock_loc_id.active)
|
|
self.assertTrue(warehouse.wh_pack_stock_loc_id.active)
|
|
self.assertTrue(custom_location.active)
|
|
|
|
# Picking Type
|
|
self.assertTrue(warehouse.in_type_id.active)
|
|
self.assertTrue(warehouse.out_type_id.active)
|
|
self.assertTrue(warehouse.int_type_id.active)
|
|
self.assertTrue(warehouse.pick_type_id.active)
|
|
self.assertTrue(warehouse.pack_type_id.active)
|
|
|
|
def test_edit_warehouse_1(self):
|
|
wh = Form(self.env['stock.warehouse'])
|
|
wh.name = "Chicago"
|
|
wh.code = "chic"
|
|
warehouse = wh.save()
|
|
self.assertEqual(warehouse.int_type_id.barcode, 'CHIC-INTERNAL')
|
|
self.assertEqual(warehouse.int_type_id.sequence_id.prefix, 'chic/INT/')
|
|
|
|
wh = Form(warehouse)
|
|
wh.code = 'CH'
|
|
wh.save()
|
|
self.assertEqual(warehouse.int_type_id.barcode, 'CH-INTERNAL')
|
|
self.assertEqual(warehouse.int_type_id.sequence_id.prefix, 'CH/INT/')
|