mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
[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
This commit is contained in:
@@ -272,19 +272,16 @@ class StockRequest(models.Model):
|
||||
def action_cancel(self):
|
||||
self.sudo().mapped("move_ids")._action_cancel()
|
||||
self.write({"state": "cancel"})
|
||||
self.mapped("order_id").check_cancel()
|
||||
return True
|
||||
|
||||
def action_done(self):
|
||||
self.write({"state": "done"})
|
||||
self.mapped("order_id").check_done()
|
||||
return True
|
||||
|
||||
def check_cancel(self):
|
||||
for request in self:
|
||||
if request._check_cancel_allocation():
|
||||
request.write({"state": "cancel"})
|
||||
request.mapped("order_id").check_cancel()
|
||||
|
||||
def check_done(self):
|
||||
precision = self.env["decimal.precision"].precision_get(
|
||||
@@ -305,7 +302,6 @@ class StockRequest(models.Model):
|
||||
elif request._check_cancel_allocation():
|
||||
# If qty_done=0 and qty_cancelled>0 it's cancelled
|
||||
request.write({"state": "cancel"})
|
||||
request.mapped("order_id").check_cancel()
|
||||
return True
|
||||
|
||||
def _check_cancel_allocation(self):
|
||||
|
||||
@@ -51,6 +51,8 @@ class StockRequestOrder(models.Model):
|
||||
index=True,
|
||||
readonly=True,
|
||||
tracking=True,
|
||||
compute="_compute_state",
|
||||
store=True,
|
||||
)
|
||||
requested_by = fields.Many2one(
|
||||
"res.users",
|
||||
@@ -144,6 +146,19 @@ class StockRequestOrder(models.Model):
|
||||
("name_uniq", "unique(name, company_id)", "Stock Request name must be unique")
|
||||
]
|
||||
|
||||
@api.depends("stock_request_ids.state")
|
||||
def _compute_state(self):
|
||||
for item in self:
|
||||
states = item.stock_request_ids.mapped("state")
|
||||
if not item.stock_request_ids or all(x == "draft" for x in states):
|
||||
item.state = "draft"
|
||||
elif all(x == "cancel" for x in states):
|
||||
item.state = "cancel"
|
||||
elif all(x in ("done", "cancel") for x in states):
|
||||
item.state = "done"
|
||||
else:
|
||||
item.state = "open"
|
||||
|
||||
@api.depends("stock_request_ids.allocation_ids")
|
||||
def _compute_picking_ids(self):
|
||||
for record in self:
|
||||
@@ -226,37 +241,19 @@ class StockRequestOrder(models.Model):
|
||||
_("There should be at least one request item for confirming the order.")
|
||||
)
|
||||
self.mapped("stock_request_ids").action_confirm()
|
||||
self.write({"state": "open"})
|
||||
return True
|
||||
|
||||
def action_draft(self):
|
||||
self.mapped("stock_request_ids").action_draft()
|
||||
self.write({"state": "draft"})
|
||||
return True
|
||||
|
||||
def action_cancel(self):
|
||||
self.mapped("stock_request_ids").action_cancel()
|
||||
self.write({"state": "cancel"})
|
||||
return True
|
||||
|
||||
def action_done(self):
|
||||
self.write({"state": "done"})
|
||||
return True
|
||||
|
||||
def check_done(self):
|
||||
for rec in self:
|
||||
if not rec.stock_request_ids.filtered(
|
||||
lambda r: r.state not in ["done", "cancel"]
|
||||
):
|
||||
rec.action_done()
|
||||
return
|
||||
|
||||
def check_cancel(self):
|
||||
for rec in self:
|
||||
if not rec.stock_request_ids.filtered(lambda r: r.state != "cancel"):
|
||||
rec.write({"state": "cancel"})
|
||||
return
|
||||
|
||||
def action_view_transfer(self):
|
||||
action = self.env["ir.actions.act_window"]._for_xml_id(
|
||||
"stock.action_picking_tree_all"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Copyright 2017 ForgeFlow S.L.
|
||||
# Copyright 2022 Tecnativa - Víctor Martínez
|
||||
# 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
|
||||
@@ -12,6 +12,16 @@ 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"]
|
||||
@@ -35,25 +45,17 @@ class TestStockRequest(common.TransactionCase):
|
||||
self.wh2 = self.env["stock.warehouse"].search(
|
||||
[("company_id", "=", self.company_2.id)], limit=1
|
||||
)
|
||||
ctx = {
|
||||
"mail_create_nolog": True,
|
||||
"mail_create_nosubscribe": True,
|
||||
"mail_notrack": True,
|
||||
"no_reset_password": True,
|
||||
}
|
||||
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])],
|
||||
context=ctx,
|
||||
)
|
||||
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])],
|
||||
context=ctx,
|
||||
)
|
||||
self.product = self._create_product("SH", "Shoes", False)
|
||||
self.product_company_2 = self._create_product(
|
||||
@@ -1074,3 +1076,98 @@ class TestStockRequestBase(TestStockRequest):
|
||||
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")
|
||||
|
||||
Reference in New Issue
Block a user