diff --git a/shopfloor_reception/tests/common.py b/shopfloor_reception/tests/common.py index 607065ae65..6811f10a71 100644 --- a/shopfloor_reception/tests/common.py +++ b/shopfloor_reception/tests/common.py @@ -143,3 +143,30 @@ def _get_today_pickings(self): @classmethod def _enable_allow_select_document_by_product(cls): cls.menu.sudo().allow_select_document_by_product = True + + def assertMessage(self, response, expected_message): + message = response.get("message") + for key, value in expected_message.items(): + self.assertEqual(message.get(key), value) + + @classmethod + def _get_move_ids_from_response(cls, response): + state = response.get("next_state") + data = response["data"][state] + picking_data = data.get("pickings") or [data.get("picking")] + moves_data = [] + for picking in picking_data: + moves_data.extend(picking["moves"]) + return [move["id"] for move in moves_data] + + def _get_service_for_user(self, user): + user_env = self.env(user=user) + return self.get_service( + "reception", menu=self.menu, profile=self.profile, env=user_env + ) + + @classmethod + def _shopfloor_manager_values(cls): + vals = super()._shopfloor_manager_values() + vals["groups_id"] = [(6, 0, [cls.env.ref("stock.group_stock_user").id])] + return vals diff --git a/shopfloor_reception/tests/test_set_quantity.py b/shopfloor_reception/tests/test_set_quantity.py index 59594bc4ae..25c3285d0c 100644 --- a/shopfloor_reception/tests/test_set_quantity.py +++ b/shopfloor_reception/tests/test_set_quantity.py @@ -382,18 +382,6 @@ def test_scan_new_package(self): }, ) - @classmethod - def _shopfloor_manager_values(cls): - vals = super()._shopfloor_manager_values() - vals["groups_id"] = [(6, 0, [cls.env.ref("stock.group_stock_user").id])] - return vals - - def _get_service_for_user(self, user): - user_env = self.env(user=user) - return self.get_service( - "reception", menu=self.menu, profile=self.profile, env=user_env - ) - def test_concurrent_update(self): # We're testing that move line's product uom qties are updated correctly # when users are workng on the same move in parallel @@ -679,7 +667,6 @@ def test_concurrent_update_2(self): lines_after = self.env["stock.move.line"].search( [("id", "not in", lines_before.ids)] ) - # After move_line is posted, its state is done, and its qty_done is 1.0 self.assertEqual(move_line_user_1.state, "done") @@ -692,3 +679,104 @@ def test_concurrent_update_2(self): self.assertEqual( lines_after.product_uom_qty + move_line_user_2.product_uom_qty, 9.0 ) + + def test_move_states(self): + # as only assigned moves can be posted, we need to ensure that + # we got the right states in any case, especially when users are working + # concurrently + picking = self._create_picking() + move_product_a = picking.move_lines.filtered( + lambda l: l.product_id == self.product_a + ) + # user1 processes 10 units + move_line_user_1 = move_product_a.move_line_ids + service_user_1 = self.service + service_user_1.dispatch("scan_document", params={"barcode": picking.name}) + service_user_1.dispatch( + "scan_line", + params={"picking_id": picking.id, "barcode": self.product_a.barcode}, + ) + response = service_user_1.dispatch( + "set_quantity", + params={ + "picking_id": picking.id, + "selected_line_id": move_line_user_1.id, + "quantity": move_product_a.product_qty - 1, + "barcode": self.product_a.barcode, + }, + ) + # user2 selects the same picking + user2 = self.shopfloor_manager + service_user_2 = self._get_service_for_user(user2) + response = service_user_2.dispatch( + "scan_document", params={"barcode": picking.name} + ) + # And the same line + service_user_2.dispatch( + "scan_line", + params={"picking_id": picking.id, "barcode": self.product_a.barcode}, + ) + move_line_user_2 = move_product_a.move_line_ids - move_line_user_1 + # user1 shouldn't be able to process his move, since + # move qty_done > move product_qty + response = service_user_1.dispatch( + "process_with_new_pack", + params={ + "picking_id": picking.id, + "selected_line_id": move_line_user_1.id, + "quantity": 10.0, + }, + ) + # + expected_message = { + "body": "You cannot process that much units.", + "message_type": "error", + } + self.assertMessage(response, expected_message) + # user1 cancels the operation + service_user_1.dispatch( + "set_quantity__cancel_action", + params={ + "picking_id": picking.id, + "selected_line_id": move_line_user_1.id, + }, + ) + self.assertFalse(move_line_user_1.shopfloor_user_id) + self.assertEqual(move_line_user_1.qty_done, 0) + # User2 should be able to process 1 unit + response = service_user_2.dispatch( + "process_with_new_pack", + params={ + "picking_id": picking.id, + "selected_line_id": move_line_user_2.id, + "quantity": 1.0, + }, + ) + data = self.data.picking(picking) + self.assert_response( + response, + next_state="set_destination", + data={ + "picking": data, + "selected_move_line": self.data.move_lines(move_line_user_2), + }, + ) + self.assertEqual(move_product_a.quantity_done, 1.0) + response = service_user_2.dispatch( + "set_destination", + params={ + "picking_id": picking.id, + "selected_line_id": move_line_user_2.id, + "location_name": self.dispatch_location.name, + }, + ) + # When posted, the move line product_uom_qty has been set to qty_done + self.assertEqual(move_line_user_2.qty_done, move_line_user_2.product_qty) + self.assert_response( + response, next_state="select_move", data=self._data_for_select_move(picking) + ) + # Now, user1 can start working on this again + service_user_1.dispatch( + "scan_line", + params={"picking_id": picking.id, "barcode": self.product_a.barcode}, + )