Files
stock-logistics-warehouse/stock_request/tests/test_stock_request.py
Víctor Martínez c1cacf84ae [IMP] stock_request: Convert the state field of stock.request.order as compute store to complete all use cases.
This change prevents stock.request.order from remaining in the open state when they have already finished.

TT44811
2023-08-25 16:25:25 +02:00

1174 lines
47 KiB
Python

# Copyright 2017 ForgeFlow S.L.
# Copyright 2022-2023 Tecnativa - Víctor Martínez
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0).
from collections import Counter
from datetime import datetime
from odoo import exceptions, fields
from odoo.tests import common, new_test_user
class TestStockRequest(common.TransactionCase):
def setUp(self):
super().setUp()
self.env = self.env(
context=dict(
self.env.context,
mail_create_nolog=True,
mail_create_nosubscribe=True,
mail_notrack=True,
no_reset_password=True,
tracking_disable=True,
)
)
# common models
self.stock_request = self.env["stock.request"]
self.request_order = self.env["stock.request.order"]
# refs
self.stock_request_user_group = self.env.ref(
"stock_request.group_stock_request_user"
)
self.main_company = self.env.ref("base.main_company")
self.warehouse = self.env.ref("stock.warehouse0")
self.categ_unit = self.env.ref("uom.product_uom_categ_unit")
self.virtual_loc = self.env.ref("stock.stock_location_customers")
# common data
self.company_2 = self.env["res.company"].create(
{"name": "Comp2", "parent_id": self.main_company.id}
)
self.company_2_address = (
self.env["res.partner"]
.with_context(company_id=self.company_2.id)
.create({"name": "Peñiscola"})
)
self.wh2 = self.env["stock.warehouse"].search(
[("company_id", "=", self.company_2.id)], limit=1
)
self.stock_request_user = new_test_user(
self.env,
login="stock_request_user",
groups="stock_request.group_stock_request_user",
company_ids=[(6, 0, [self.main_company.id, self.company_2.id])],
)
self.stock_request_manager = new_test_user(
self.env,
login="stock_request_manager",
groups="stock_request.group_stock_request_manager",
company_ids=[(6, 0, [self.main_company.id, self.company_2.id])],
)
self.product = self._create_product("SH", "Shoes", False)
self.product_company_2 = self._create_product(
"SH_2", "Shoes", self.company_2.id
)
self.ressuply_loc = self._create_location(
name="Ressuply",
location_id=self.warehouse.view_location_id.id,
company_id=self.main_company.id,
)
self.ressuply_loc_2 = self._create_location(
name="Ressuply",
location_id=self.wh2.view_location_id.id,
company_id=self.company_2.id,
)
self.route = self._create_location_route(
name="Transfer", company_id=self.main_company.id
)
self.route_2 = self._create_location_route(
name="Transfer", company_id=self.company_2.id
)
self.uom_dozen = self.env["uom.uom"].create(
{
"name": "Test-DozenA",
"category_id": self.categ_unit.id,
"factor_inv": 12,
"uom_type": "bigger",
"rounding": 0.001,
}
)
self.env["stock.rule"].create(
{
"name": "Transfer",
"route_id": self.route.id,
"location_src_id": self.ressuply_loc.id,
"location_id": self.warehouse.lot_stock_id.id,
"action": "pull",
"picking_type_id": self.warehouse.int_type_id.id,
"procure_method": "make_to_stock",
"warehouse_id": self.warehouse.id,
"company_id": self.main_company.id,
}
)
self.env["stock.rule"].create(
{
"name": "Transfer",
"route_id": self.route_2.id,
"location_src_id": self.ressuply_loc_2.id,
"location_id": self.wh2.lot_stock_id.id,
"action": "pull",
"picking_type_id": self.wh2.int_type_id.id,
"procure_method": "make_to_stock",
"warehouse_id": self.wh2.id,
"company_id": self.company_2.id,
}
)
self.env["ir.config_parameter"].sudo().set_param(
"stock.no_auto_scheduler", "True"
)
def _create_product(self, default_code, name, company_id, **vals):
return self.env["product.product"].create(
dict(
name=name,
default_code=default_code,
uom_id=self.env.ref("uom.product_uom_unit").id,
company_id=company_id,
type="product",
**vals
)
)
def _create_location(self, **vals):
return self.env["stock.location"].create(dict(usage="internal", **vals))
def _create_location_route(self, **vals):
return self.env["stock.location.route"].create(
dict(
product_categ_selectable=False,
product_selectable=True,
sequence=10,
**vals
)
)
class TestStockRequestBase(TestStockRequest):
def setUp(self):
super().setUp()
def test_defaults(self):
vals = {
"product_id": self.product.id,
"product_uom_id": self.product.uom_id.id,
"product_uom_qty": 5.0,
}
stock_request = (
self.stock_request.with_user(self.stock_request_user)
.with_context(company_id=self.main_company.id)
.create(vals)
)
self.assertEqual(stock_request.requested_by, self.stock_request_user)
self.assertEqual(stock_request.warehouse_id, self.warehouse)
self.assertEqual(stock_request.location_id, self.warehouse.lot_stock_id)
def test_defaults_order(self):
vals = {}
order = (
self.request_order.with_user(self.stock_request_user)
.with_context(company_id=self.main_company.id)
.create(vals)
)
self.assertEqual(order.requested_by, self.stock_request_user)
self.assertEqual(order.warehouse_id, self.warehouse)
self.assertEqual(order.location_id, self.warehouse.lot_stock_id)
def test_onchanges_order(self):
expected_date = fields.Datetime.now()
vals = {
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"expected_date": expected_date,
"stock_request_ids": [
(
0,
0,
{
"product_id": self.product.id,
"product_uom_id": self.product.uom_id.id,
"product_uom_qty": 5.0,
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"expected_date": expected_date,
},
)
],
}
order = self.request_order.with_user(self.stock_request_user).new(vals)
self.stock_request_user.company_id = self.company_2
order.company_id = self.company_2
order.onchange_company_id()
stock_request = order.stock_request_ids
self.assertEqual(order.warehouse_id, self.wh2)
self.assertEqual(order.location_id, self.wh2.lot_stock_id)
self.assertEqual(order.warehouse_id, stock_request.warehouse_id)
procurement_group = self.env["procurement.group"].create({"name": "TEST"})
order.procurement_group_id = procurement_group
order.onchange_procurement_group_id()
self.assertEqual(
order.procurement_group_id, order.stock_request_ids.procurement_group_id
)
order.procurement_group_id = procurement_group
order.onchange_procurement_group_id()
self.assertEqual(
order.procurement_group_id, order.stock_request_ids.procurement_group_id
)
order.picking_policy = "one"
order.onchange_picking_policy()
self.assertEqual(order.picking_policy, order.stock_request_ids.picking_policy)
order.expected_date = datetime.now()
order.onchange_expected_date()
self.assertEqual(order.expected_date, order.stock_request_ids.expected_date)
order.requested_by = self.stock_request_manager
order.onchange_requested_by()
self.assertEqual(order.requested_by, order.stock_request_ids.requested_by)
def test_onchanges(self):
self.product.route_ids = [(6, 0, self.route.ids)]
vals = {
"product_uom_id": self.product.uom_id.id,
"product_uom_qty": 5.0,
"company_id": self.main_company.id,
}
stock_request = self.stock_request.with_user(self.stock_request_user).new(vals)
stock_request.product_id = self.product
vals = stock_request.default_get(["warehouse_id", "company_id"])
stock_request.update(vals)
stock_request.onchange_product_id()
self.assertIn(self.route.id, stock_request.route_ids.ids)
self.stock_request_user.company_id = self.company_2
stock_request.company_id = self.company_2
stock_request.onchange_company_id()
self.assertEqual(stock_request.warehouse_id, self.wh2)
self.assertEqual(stock_request.location_id, self.wh2.lot_stock_id)
product = self.env["product.product"].create(
{
"name": "Wheat",
"uom_id": self.env.ref("uom.product_uom_kgm").id,
"uom_po_id": self.env.ref("uom.product_uom_kgm").id,
}
)
# Test onchange_product_id
stock_request.product_id = product
stock_request.onchange_product_id()
self.assertEqual(
stock_request.product_uom_id, self.env.ref("uom.product_uom_kgm")
)
stock_request.product_id = self.env["product.product"]
# Test onchange_warehouse_id
wh2_2 = (
self.env["stock.warehouse"]
.with_context(company_id=self.company_2.id)
.create(
{
"name": "C2_2",
"code": "C2_2",
"company_id": self.company_2.id,
"partner_id": self.company_2_address.id,
}
)
)
stock_request.warehouse_id = wh2_2
stock_request.onchange_warehouse_id()
self.assertEqual(stock_request.warehouse_id, wh2_2)
self.stock_request_user.company_id = self.main_company
stock_request.warehouse_id = self.warehouse
stock_request.onchange_warehouse_id()
self.assertEqual(stock_request.company_id, self.main_company)
self.assertEqual(stock_request.location_id, self.warehouse.lot_stock_id)
def test_stock_request_order_validations_01(self):
"""Testing the discrepancy in warehouse_id between
stock request and order"""
expected_date = fields.Datetime.now()
vals = {
"company_id": self.main_company.id,
"warehouse_id": self.wh2.id,
"location_id": self.warehouse.lot_stock_id.id,
"expected_date": expected_date,
"stock_request_ids": [
(
0,
0,
{
"product_id": self.product.id,
"product_uom_id": self.product.uom_id.id,
"product_uom_qty": 5.0,
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"expected_date": expected_date,
},
)
],
}
with self.assertRaises(exceptions.ValidationError):
self.request_order.with_user(self.stock_request_user).create(vals)
def test_stock_request_order_validations_02(self):
"""Testing the discrepancy in location_id between
stock request and order"""
expected_date = fields.Datetime.now()
vals = {
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.wh2.lot_stock_id.id,
"expected_date": expected_date,
"stock_request_ids": [
(
0,
0,
{
"product_id": self.product.id,
"product_uom_id": self.product.uom_id.id,
"product_uom_qty": 5.0,
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"expected_date": expected_date,
},
)
],
}
with self.assertRaises(exceptions.ValidationError):
self.request_order.with_user(self.stock_request_user).create(vals)
def test_stock_request_order_validations_03(self):
"""Testing the discrepancy in requested_by between
stock request and order"""
expected_date = fields.Datetime.now()
vals = {
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"requested_by": self.stock_request_user.id,
"expected_date": expected_date,
"stock_request_ids": [
(
0,
0,
{
"product_id": self.product.id,
"product_uom_id": self.product.uom_id.id,
"product_uom_qty": 5.0,
"requested_by": self.stock_request_manager.id,
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"expected_date": expected_date,
},
)
],
}
with self.assertRaises(exceptions.ValidationError):
self.request_order.with_user(self.stock_request_user).create(vals)
def test_stock_request_order_validations_04(self):
"""Testing the discrepancy in procurement_group_id between
stock request and order"""
procurement_group = self.env["procurement.group"].create(
{"name": "Procurement"}
)
expected_date = fields.Datetime.now()
vals = {
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"procurement_group_id": procurement_group.id,
"expected_date": expected_date,
"stock_request_ids": [
(
0,
0,
{
"product_id": self.product.id,
"product_uom_id": self.product.uom_id.id,
"product_uom_qty": 5.0,
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"expected_date": expected_date,
},
)
],
}
with self.assertRaises(exceptions.ValidationError):
self.request_order.with_user(self.stock_request_user).create(vals)
def test_stock_request_order_validations_05(self):
"""Testing the discrepancy in company between
stock request and order"""
expected_date = fields.Datetime.now()
vals = {
"company_id": self.company_2.id,
"warehouse_id": self.wh2.id,
"location_id": self.wh2.lot_stock_id.id,
"expected_date": expected_date,
"stock_request_ids": [
(
0,
0,
{
"product_id": self.product.id,
"product_uom_id": self.product.uom_id.id,
"product_uom_qty": 5.0,
"company_id": self.company_2.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"expected_date": expected_date,
},
)
],
}
with self.assertRaises(exceptions.ValidationError):
self.request_order.with_user(self.stock_request_user).create(vals)
def test_stock_request_order_validations_06(self):
"""Testing the discrepancy in expected dates between
stock request and order"""
expected_date = fields.Datetime.now()
child_expected_date = "2015-01-01"
vals = {
"company_id": self.company_2.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"expected_date": expected_date,
"stock_request_ids": [
(
0,
0,
{
"product_id": self.product.id,
"product_uom_id": self.product.uom_id.id,
"product_uom_qty": 5.0,
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"expected_date": child_expected_date,
},
)
],
}
with self.assertRaises(exceptions.ValidationError):
self.request_order.create(vals)
def test_stock_request_order_validations_07(self):
"""Testing the discrepancy in picking policy between
stock request and order"""
expected_date = fields.Datetime.now()
vals = {
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"picking_policy": "one",
"expected_date": expected_date,
"stock_request_ids": [
(
0,
0,
{
"product_id": self.product.id,
"product_uom_id": self.product.uom_id.id,
"product_uom_qty": 5.0,
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"expected_date": expected_date,
},
)
],
}
with self.assertRaises(exceptions.ValidationError):
self.request_order.with_user(self.stock_request_user).create(vals)
def test_stock_request_validations_01(self):
vals = {
"product_id": self.product.id,
"product_uom_id": self.env.ref("uom.product_uom_kgm").id,
"product_uom_qty": 5.0,
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
}
# Select a UoM that is incompatible with the product's UoM
with self.assertRaises(exceptions.ValidationError):
self.stock_request.with_user(self.stock_request_user).create(vals)
def test_create_request_01(self):
expected_date = fields.Datetime.now()
vals = {
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"expected_date": expected_date,
"stock_request_ids": [
(
0,
0,
{
"product_id": self.product.id,
"product_uom_id": self.product.uom_id.id,
"product_uom_qty": 5.0,
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"expected_date": expected_date,
},
)
],
}
order = self.request_order.with_user(self.stock_request_user).create(vals)
stock_request = order.stock_request_ids
self.product.route_ids = [(6, 0, self.route.ids)]
order.with_user(self.stock_request_manager).action_confirm()
self.assertEqual(order.state, "open")
self.assertEqual(stock_request.state, "open")
self.assertEqual(len(order.picking_ids), 1)
self.assertEqual(len(order.move_ids), 1)
self.assertEqual(len(stock_request.picking_ids), 1)
self.assertEqual(len(stock_request.move_ids), 1)
self.assertEqual(
stock_request.move_ids[0].location_dest_id, stock_request.location_id
)
self.assertEqual(stock_request.qty_in_progress, stock_request.product_uom_qty)
self.env["stock.quant"].create(
{
"product_id": self.product.id,
"location_id": self.ressuply_loc.id,
"quantity": 5.0,
}
)
picking = stock_request.picking_ids[0]
picking.with_user(self.stock_request_manager).action_confirm()
self.assertEqual(stock_request.qty_in_progress, 5.0)
self.assertEqual(stock_request.qty_done, 0.0)
picking.with_user(self.stock_request_manager).action_assign()
self.assertEqual(picking.origin, order.name)
packout1 = picking.move_line_ids[0]
packout1.qty_done = 5
picking.with_user(self.stock_request_manager)._action_done()
self.assertEqual(stock_request.qty_in_progress, 0.0)
self.assertEqual(stock_request.qty_done, stock_request.product_uom_qty)
self.assertEqual(order.state, "done")
self.assertEqual(stock_request.state, "done")
def test_create_request_02(self):
"""Use different UoM's"""
vals = {
"product_id": self.product.id,
"product_uom_id": self.uom_dozen.id,
"product_uom_qty": 1.0,
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
}
stock_request = self.stock_request.with_user(self.stock_request_user).create(
vals
)
self.product.route_ids = [(6, 0, self.route.ids)]
stock_request.with_user(self.stock_request_manager).action_confirm()
self.assertEqual(stock_request.state, "open")
self.assertEqual(len(stock_request.picking_ids), 1)
self.assertEqual(len(stock_request.move_ids), 1)
self.assertEqual(
stock_request.move_ids[0].location_dest_id, stock_request.location_id
)
self.assertEqual(stock_request.qty_in_progress, stock_request.product_uom_qty)
self.env["stock.quant"].create(
{
"product_id": self.product.id,
"location_id": self.ressuply_loc.id,
"quantity": 12.0,
}
)
picking = stock_request.picking_ids[0]
picking.with_user(self.stock_request_manager).action_confirm()
self.assertEqual(stock_request.qty_in_progress, 1.0)
self.assertEqual(stock_request.qty_done, 0.0)
picking.with_user(self.stock_request_manager).action_assign()
packout1 = picking.move_line_ids[0]
packout1.qty_done = 1
picking.with_user(self.stock_request_manager)._action_done()
self.assertEqual(stock_request.qty_in_progress, 0.0)
self.assertEqual(stock_request.qty_done, stock_request.product_uom_qty)
self.assertEqual(stock_request.state, "done")
def test_create_request_03(self):
"""Multiple stock requests"""
vals = {
"product_id": self.product.id,
"product_uom_id": self.product.uom_id.id,
"product_uom_qty": 4.0,
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
}
stock_request_1 = (
self.env["stock.request"].with_user(self.stock_request_user).create(vals)
)
stock_request_2 = (
self.env["stock.request"]
.with_user(self.stock_request_manager.id)
.create(vals)
)
stock_request_2.product_uom_qty = 6.0
self.product.route_ids = [(6, 0, self.route.ids)]
stock_request_1.sudo().action_confirm()
stock_request_2.sudo().action_confirm()
self.assertEqual(len(stock_request_1.sudo().picking_ids), 1)
self.assertEqual(
stock_request_1.sudo().picking_ids, stock_request_2.sudo().picking_ids
)
self.assertEqual(
stock_request_1.sudo().move_ids, stock_request_2.sudo().move_ids
)
self.env["stock.quant"].create(
{
"product_id": self.product.id,
"location_id": self.ressuply_loc.id,
"quantity": 10.0,
}
)
picking = stock_request_1.sudo().picking_ids[0]
picking.action_confirm()
picking.action_assign()
self.assertEqual(stock_request_1.qty_in_progress, 4)
self.assertEqual(stock_request_1.qty_done, 0)
self.assertEqual(stock_request_1.qty_cancelled, 0)
self.assertEqual(stock_request_2.qty_in_progress, 6)
self.assertEqual(stock_request_2.qty_done, 0)
self.assertEqual(stock_request_2.qty_cancelled, 0)
packout1 = picking.move_line_ids[0]
packout1.qty_done = 4
self.env["stock.backorder.confirmation"].with_context(
button_validate_picking_ids=[picking.id]
).create({"pick_ids": [(4, picking.id)]}).process_cancel_backorder()
self.assertEqual(stock_request_1.qty_in_progress, 0)
self.assertEqual(stock_request_1.qty_done, 4)
self.assertEqual(stock_request_1.qty_cancelled, 0)
self.assertEqual(stock_request_1.state, "done")
self.assertEqual(stock_request_2.qty_in_progress, 0)
self.assertEqual(stock_request_2.qty_done, 0)
self.assertEqual(stock_request_2.qty_cancelled, 6)
self.assertEqual(stock_request_2.state, "cancel")
def test_cancel_request(self):
expected_date = fields.Datetime.now()
vals = {
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"expected_date": expected_date,
"stock_request_ids": [
(
0,
0,
{
"product_id": self.product.id,
"product_uom_id": self.product.uom_id.id,
"product_uom_qty": 5.0,
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"expected_date": expected_date,
},
)
],
}
order = self.request_order.with_user(self.stock_request_user).create(vals)
self.product.route_ids = [(6, 0, self.route.ids)]
order.with_user(self.stock_request_manager).action_confirm()
stock_request = order.stock_request_ids
self.assertEqual(len(order.picking_ids), 1)
self.assertEqual(len(order.move_ids), 1)
self.assertEqual(len(stock_request.picking_ids), 1)
self.assertEqual(len(stock_request.move_ids), 1)
self.assertEqual(
stock_request.move_ids[0].location_dest_id, stock_request.location_id
)
self.assertEqual(stock_request.qty_in_progress, stock_request.product_uom_qty)
self.env["stock.quant"].create(
{
"product_id": self.product.id,
"location_id": self.ressuply_loc.id,
"quantity": 5.0,
}
)
picking = stock_request.picking_ids[0]
picking.with_user(self.stock_request_user).action_confirm()
self.assertEqual(stock_request.qty_in_progress, 5.0)
self.assertEqual(stock_request.qty_done, 0.0)
picking.with_user(self.stock_request_manager).action_assign()
order.with_user(self.stock_request_manager).action_cancel()
self.assertEqual(stock_request.qty_in_progress, 0.0)
self.assertEqual(stock_request.qty_done, 0.0)
self.assertEqual(len(stock_request.picking_ids), 0)
# Set the request back to draft
order.with_user(self.stock_request_user).action_draft()
self.assertEqual(order.state, "draft")
self.assertEqual(stock_request.state, "draft")
# Re-confirm. We expect new pickings to be created
order.with_user(self.stock_request_manager).action_confirm()
self.assertEqual(len(stock_request.picking_ids), 1)
self.assertEqual(len(stock_request.move_ids), 2)
def test_view_actions(self):
expected_date = fields.Datetime.now()
vals = {
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"expected_date": expected_date,
"stock_request_ids": [
(
0,
0,
{
"product_id": self.product.id,
"product_uom_id": self.product.uom_id.id,
"product_uom_qty": 5.0,
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"expected_date": expected_date,
},
)
],
}
order = self.request_order.create(vals)
self.product.route_ids = [(6, 0, self.route.ids)]
order.with_user(self.stock_request_manager).action_confirm()
stock_request = order.stock_request_ids
self.assertTrue(stock_request.picking_ids)
self.assertTrue(order.picking_ids)
action = order.action_view_transfer()
self.assertEqual("domain" in action.keys(), True)
self.assertEqual("views" in action.keys(), True)
self.assertEqual(action["res_id"], order.picking_ids[0].id)
action = order.action_view_stock_requests()
self.assertEqual("domain" in action.keys(), True)
self.assertEqual("views" in action.keys(), True)
self.assertEqual(action["res_id"], stock_request[0].id)
action = stock_request.action_view_transfer()
self.assertEqual("domain" in action.keys(), True)
self.assertEqual("views" in action.keys(), True)
self.assertEqual(action["res_id"], stock_request.picking_ids[0].id)
action = stock_request.picking_ids[0].action_view_stock_request()
self.assertEqual(action["type"], "ir.actions.act_window")
self.assertEqual(action["res_id"], stock_request.id)
def test_stock_request_constrains(self):
vals = {
"product_id": self.product.id,
"product_uom_id": self.product.uom_id.id,
"product_uom_qty": 5.0,
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
}
stock_request = self.stock_request.with_user(self.stock_request_user).create(
vals
)
# Cannot assign a warehouse that belongs to another company
with self.assertRaises(exceptions.ValidationError):
stock_request.warehouse_id = self.wh2
# Cannot assign a product that belongs to another company
with self.assertRaises(exceptions.ValidationError):
stock_request.product_id = self.product_company_2
# Cannot assign a location that belongs to another company
with self.assertRaises(exceptions.ValidationError):
stock_request.location_id = self.wh2.lot_stock_id
# Cannot assign a route that belongs to another company
with self.assertRaises(exceptions.ValidationError):
stock_request.route_id = self.route_2
def test_stock_request_order_from_products(self):
product_a1 = self._create_product("CODEA1", "Product A1", self.main_company.id)
template_a = product_a1.product_tmpl_id
product_a2 = self._create_product(
"CODEA2", "Product A2", self.main_company.id, product_tmpl_id=template_a.id
)
product_a3 = self._create_product(
"CODEA3", "Product A3", self.main_company.id, product_tmpl_id=template_a.id
)
product_b1 = self._create_product("CODEB1", "Product B1", self.main_company.id)
template_b = product_b1.product_tmpl_id
# One archived variant of B
self._create_product(
"CODEB2",
"Product B2",
self.main_company.id,
product_tmpl_id=template_b.id,
active=False,
)
order = self.request_order
# Selecting some variants and creating an order
preexisting = order.search([])
wanted_products = product_a1 + product_a2 + product_b1
action = order._create_from_product_multiselect(wanted_products)
new_order = order.search([]) - preexisting
self.assertEqual(len(new_order), 1)
self.assertEqual(
action["res_id"],
new_order.id,
msg="Returned action references the wrong record",
)
self.assertEqual(
Counter(wanted_products),
Counter(new_order.stock_request_ids.mapped("product_id")),
msg="Not all wanted products were ordered",
)
# Selecting a template and creating an order
preexisting = order.search([])
action = order._create_from_product_multiselect(template_a)
new_order = order.search([]) - preexisting
self.assertEqual(len(new_order), 1)
self.assertEqual(
action["res_id"],
new_order.id,
msg="Returned action references the wrong record",
)
self.assertEqual(
Counter(product_a1 + product_a2 + product_a3),
Counter(new_order.stock_request_ids.mapped("product_id")),
msg="Not all of the template's variants were ordered",
)
# Selecting a template
preexisting = order.search([])
action = order._create_from_product_multiselect(template_a + template_b)
new_order = order.search([]) - preexisting
self.assertEqual(len(new_order), 1)
self.assertEqual(
action["res_id"],
new_order.id,
msg="Returned action references the wrong record",
)
self.assertEqual(
Counter(product_a1 + product_a2 + product_a3 + product_b1),
Counter(new_order.stock_request_ids.mapped("product_id")),
msg="Inactive variant was ordered though it shouldn't have been",
)
# If a user does not have stock request rights, they can still trigger
# the action from the products, so test that they get a friendlier
# error message.
self.stock_request_user.groups_id -= self.stock_request_user_group
with self.assertRaisesRegex(
exceptions.UserError,
"Unfortunately it seems you do not have the necessary rights "
"for creating stock requests. Please contact your "
"administrator.",
):
order.with_user(self.stock_request_user)._create_from_product_multiselect(
template_a + template_b
)
# Empty recordsets should just return False
self.assertFalse(
order._create_from_product_multiselect(self.env["product.product"])
)
# Wrong model should just raise ValidationError
with self.assertRaises(exceptions.ValidationError):
order._create_from_product_multiselect(self.stock_request_user)
def test_allow_virtual_location(self):
self.main_company.stock_request_allow_virtual_loc = True
vals = {
"product_id": self.product.id,
"product_uom_id": self.product.uom_id.id,
"product_uom_qty": 5.0,
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.virtual_loc.id,
}
stock_request = self.stock_request.with_user(self.stock_request_user).create(
vals
)
self.assertTrue(stock_request.allow_virtual_location)
vals = {
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.virtual_loc.id,
}
order = self.request_order.with_user(self.stock_request_user).create(vals)
self.assertTrue(order.allow_virtual_location)
def test_onchange_wh_no_effect_from_order(self):
expected_date = fields.Datetime.now()
vals = {
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.virtual_loc.id,
"expected_date": expected_date,
"stock_request_ids": [
(
0,
0,
{
"product_id": self.product.id,
"product_uom_id": self.product.uom_id.id,
"product_uom_qty": 5.0,
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.virtual_loc.id,
"expected_date": expected_date,
},
)
],
}
order = self.request_order.with_user(self.stock_request_user).create(vals)
order.stock_request_ids.onchange_warehouse_id()
self.assertEqual(order.stock_request_ids[0].location_id, self.virtual_loc)
def test_cancellation(self):
group = self.env["procurement.group"].create({"name": "Procurement group"})
product2 = self._create_product("SH2", "Shoes2", False)
product3 = self._create_product("SH3", "Shoes3", False)
self.product.type = "consu"
product2.type = "consu"
product3.type = "consu"
vals = {
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.virtual_loc.id,
"procurement_group_id": group.id,
"stock_request_ids": [
(
0,
0,
{
"product_id": self.product.id,
"product_uom_id": self.product.uom_id.id,
"procurement_group_id": group.id,
"product_uom_qty": 5.0,
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.virtual_loc.id,
},
),
(
0,
0,
{
"product_id": product2.id,
"product_uom_id": self.product.uom_id.id,
"procurement_group_id": group.id,
"product_uom_qty": 5.0,
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.virtual_loc.id,
},
),
(
0,
0,
{
"product_id": product3.id,
"product_uom_id": self.product.uom_id.id,
"procurement_group_id": group.id,
"product_uom_qty": 5.0,
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.virtual_loc.id,
},
),
],
}
order = self.request_order.create(vals)
self.product.route_ids = [(6, 0, self.route.ids)]
product2.route_ids = [(6, 0, self.route.ids)]
product3.route_ids = [(6, 0, self.route.ids)]
order.action_confirm()
picking = order.picking_ids
self.assertEqual(1, len(picking))
picking.action_assign()
self.assertEqual(3, len(picking.move_lines))
line = picking.move_lines.filtered(lambda r: r.product_id == self.product)
line.quantity_done = 1
sr1 = order.stock_request_ids.filtered(lambda r: r.product_id == self.product)
sr2 = order.stock_request_ids.filtered(lambda r: r.product_id == product2)
sr3 = order.stock_request_ids.filtered(lambda r: r.product_id == product3)
self.assertNotEqual(sr1.state, "done")
self.assertNotEqual(sr2.state, "done")
self.assertNotEqual(sr3.state, "done")
self.env["stock.backorder.confirmation"].with_context(
button_validate_picking_ids=[picking.id]
).create({"pick_ids": [(4, picking.id)]}).process()
sr1.refresh()
sr2.refresh()
sr3.refresh()
self.assertNotEqual(sr1.state, "done")
self.assertNotEqual(sr2.state, "done")
self.assertNotEqual(sr3.state, "done")
picking = order.picking_ids.filtered(
lambda r: r.state not in ["done", "cancel"]
)
self.assertEqual(1, len(picking))
picking.action_assign()
self.assertEqual(3, len(picking.move_lines))
line = picking.move_lines.filtered(lambda r: r.product_id == self.product)
line.quantity_done = 4
line = picking.move_lines.filtered(lambda r: r.product_id == product2)
line.quantity_done = 1
self.env["stock.backorder.confirmation"].with_context(
button_validate_picking_ids=[picking.id]
).create({"pick_ids": [(4, picking.id)]}).process_cancel_backorder()
sr1.refresh()
sr2.refresh()
sr3.refresh()
self.assertEqual(sr1.state, "done")
self.assertEqual(sr1.qty_done, 5)
self.assertEqual(sr1.qty_cancelled, 0)
self.assertEqual(sr2.state, "cancel")
self.assertEqual(sr2.qty_done, 1)
self.assertEqual(sr2.qty_cancelled, 4)
self.assertEqual(sr3.state, "cancel")
self.assertEqual(sr3.qty_done, 0)
self.assertEqual(sr3.qty_cancelled, 5)
# Set the request order to done if there are any delivered lines
self.assertEqual(order.state, "done")
class TestStockRequestOrderState(TestStockRequest):
def setUp(self):
super().setUp()
self.product_a = self._create_product(
"CODEA",
"Product A",
self.main_company.id,
)
self.product_a.route_ids = [(6, 0, self.route.ids)]
self.product_b = self._create_product(
"CODEB",
"Product B",
self.main_company.id,
)
self.product_b.route_ids = [(6, 0, self.route.ids)]
expected_date = fields.Datetime.now()
vals = {
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"expected_date": expected_date,
"stock_request_ids": [
(
0,
0,
{
"product_id": self.product_a.id,
"product_uom_id": self.product_a.uom_id.id,
"product_uom_qty": 1.0,
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"expected_date": expected_date,
},
),
(
0,
0,
{
"product_id": self.product_b.id,
"product_uom_id": self.product_b.uom_id.id,
"product_uom_qty": 1.0,
"company_id": self.main_company.id,
"warehouse_id": self.warehouse.id,
"location_id": self.warehouse.lot_stock_id.id,
"expected_date": expected_date,
},
),
],
}
self.order = self.request_order.new(vals)
self.request_a = self.order.stock_request_ids.filtered(
lambda x: x.product_id == self.product_a
)
self.request_b = self.order.stock_request_ids.filtered(
lambda x: x.product_id == self.product_b
)
def test_stock_request_order_state_01(self):
"""Request A: Done + Request B: Done = Done."""
self.order.action_confirm()
self.request_a.action_done()
self.request_b.action_done()
self.assertEqual(self.request_a.state, "done")
self.assertEqual(self.request_b.state, "done")
self.assertEqual(self.order.state, "done")
def test_stock_request_order_state_02(self):
"""Request A: Cancel + Request B: Cancel = Cancel."""
self.order.action_confirm()
self.request_a.action_cancel()
self.request_b.action_cancel()
self.assertEqual(self.request_a.state, "cancel")
self.assertEqual(self.request_b.state, "cancel")
self.assertEqual(self.order.state, "cancel")
def test_stock_request_order_state_03(self):
"""Request A: Done + Request B: Cancel = Done."""
self.order.action_confirm()
self.request_a.action_done()
self.request_b.action_cancel()
self.assertEqual(self.request_a.state, "done")
self.assertEqual(self.request_b.state, "cancel")
self.assertEqual(self.order.state, "done")
def test_stock_request_order_state_04(self):
"""Request A: Cancel + Request B: Done = DOne."""
self.order.action_confirm()
self.request_a.action_cancel()
self.request_b.action_done()
self.assertEqual(self.request_a.state, "cancel")
self.assertEqual(self.request_b.state, "done")
self.assertEqual(self.order.state, "done")