diff --git a/shopfloor/services/location_content_transfer.py b/shopfloor/services/location_content_transfer.py index 4d28698ff6..f9ebfc3d1d 100644 --- a/shopfloor/services/location_content_transfer.py +++ b/shopfloor/services/location_content_transfer.py @@ -47,9 +47,9 @@ class LocationContentTransfer(Component): _usage = "location_content_transfer" _description = __doc__ - def _response_for_start(self, message=None): + def _response_for_start(self, message=None, popup=None): """Transition to the 'start' state""" - return self._response(next_state="start", message=message) + return self._response(next_state="start", message=message, popup=popup) def _response_for_scan_destination_all( self, pickings, message=None, confirmation_required=False @@ -70,7 +70,7 @@ def _response_for_scan_destination_all( next_state="scan_destination_all", data=data, message=message ) - def _response_for_start_single(self, pickings, message=None): + def _response_for_start_single(self, pickings, message=None, popup=None): """Transition to the 'start_single' state The client screen shows details of the package level or move line to move. @@ -79,11 +79,12 @@ def _response_for_start_single(self, pickings, message=None): next_content = self._next_content(pickings) if not next_content: # TODO test (no more lines) - return self._response_for_start(message=message) + return self._response_for_start(message=message, popup=popup) return self._response( next_state="start_single", data=self._data_content_line_for_location(location, next_content), message=message, + popup=popup, ) def _response_for_scan_destination( @@ -384,10 +385,13 @@ def set_destination_all(self, location_id, barcode, confirmation=False): self._set_all_destination_lines_and_done(pickings, move_lines, scanned_location) + completion_info = self.actions_for("completion.info") + completion_info_popup = completion_info.popup(move_lines) return self._response_for_start( message=self.msg_store.location_content_transfer_complete( location, scanned_location - ) + ), + popup=completion_info_popup, ) def go_to_single(self, location_id): @@ -574,8 +578,12 @@ def set_destination_package( message = self.msg_store.location_content_transfer_item_complete( scanned_location ) + completion_info = self.actions_for("completion.info") + completion_info_popup = completion_info.popup(package_moves.move_line_ids) return self._response_for_start_single( - move_lines.mapped("picking_id"), message=message + move_lines.mapped("picking_id"), + message=message, + popup=completion_info_popup, ) def set_destination_line( @@ -644,8 +652,12 @@ def set_destination_line( message = self.msg_store.location_content_transfer_item_complete( scanned_location ) + completion_info = self.actions_for("completion.info") + completion_info_popup = completion_info.popup(move_line) return self._response_for_start_single( - move_lines.mapped("picking_id"), message=message + move_lines.mapped("picking_id"), + message=message, + popup=completion_info_popup, ) def postpone_package(self, location_id, package_level_id): diff --git a/shopfloor/tests/test_location_content_transfer_base.py b/shopfloor/tests/test_location_content_transfer_base.py index 6c89326b34..40e24385c5 100644 --- a/shopfloor/tests/test_location_content_transfer_base.py +++ b/shopfloor/tests/test_location_content_transfer_base.py @@ -46,8 +46,8 @@ def _simulate_pickings_selected(cls, pickings): for line in pickings.mapped("move_line_ids"): line.qty_done = line.product_uom_qty - def assert_response_start(self, response, message=None): - self.assert_response(response, next_state="start", message=message) + def assert_response_start(self, response, message=None, popup=None): + self.assert_response(response, next_state="start", message=message, popup=popup) def _assert_response_scan_destination_all( self, state, response, pickings, message=None, confirmation_required=False @@ -81,7 +81,9 @@ def assert_response_scan_destination_all( confirmation_required=confirmation_required, ) - def assert_response_start_single(self, response, pickings, message=None): + def assert_response_start_single( + self, response, pickings, message=None, popup=None + ): sorter = self.service.actions_for("location_content_transfer.sorter") sorter.feed_pickings(pickings) location = pickings.mapped("location_id") @@ -90,6 +92,7 @@ def assert_response_start_single(self, response, pickings, message=None): next_state="start_single", data=self.service._data_content_line_for_location(location, next(sorter)), message=message, + popup=popup, ) def _assert_response_scan_destination( diff --git a/shopfloor/tests/test_location_content_transfer_set_destination_all.py b/shopfloor/tests/test_location_content_transfer_set_destination_all.py index fc33a4d742..93cd3d80bc 100644 --- a/shopfloor/tests/test_location_content_transfer_set_destination_all.py +++ b/shopfloor/tests/test_location_content_transfer_set_destination_all.py @@ -78,6 +78,48 @@ def test_set_destination_all_dest_location_ok(self): ) self.assert_all_done(sub_shelf1) + def test_set_destination_all_dest_location_ok_with_completion_info(self): + """Scanned destination location valid, moves set to done accepted + and completion info is returned as the next transfer is ready. + """ + move = self.picking1.move_lines[0] + next_move = move.copy( + { + "location_id": move.location_dest_id.id, + "location_dest_id": self.customer_location.id, + "move_orig_ids": [(6, 0, move.ids)], + } + ) + next_move._action_confirm(merge=False) + next_move._assign_picking() + self.assertEqual(next_move.state, "waiting") + sub_shelf1 = ( + self.env["stock.location"] + .sudo() + .create( + { + "name": "Sub Shelf 1", + "barcode": "subshelf1", + "location_id": self.shelf1.id, + } + ) + ) + move_lines = self.service._find_transfer_move_lines(self.content_loc) + response = self.service.dispatch( + "set_destination_all", + params={"location_id": self.content_loc.id, "barcode": sub_shelf1.barcode}, + ) + self.assertEqual(next_move.state, "assigned") + completion_info = self.service.actions_for("completion.info") + completion_info_popup = completion_info.popup(move_lines) + self.assert_response_start( + response, + message=self.service.msg_store.location_content_transfer_complete( + self.content_loc, sub_shelf1 + ), + popup=completion_info_popup, + ) + def test_set_destination_all_dest_location_not_found(self): """Barcode scanned for destination location is not found""" response = self.service.dispatch( diff --git a/shopfloor/tests/test_location_content_transfer_set_destination_package_or_line.py b/shopfloor/tests/test_location_content_transfer_set_destination_package_or_line.py index 2e5b9c27aa..6212307b49 100644 --- a/shopfloor/tests/test_location_content_transfer_set_destination_package_or_line.py +++ b/shopfloor/tests/test_location_content_transfer_set_destination_package_or_line.py @@ -180,6 +180,53 @@ def test_set_destination_package_dest_location_ok(self): for move in package_level.move_line_ids.mapped("move_id"): self.assertEqual(move.state, "done") + def test_set_destination_package_dest_location_ok_with_completion_info(self): + """Scanned destination location valid, moves set to done + and completion info is returned as the next transfer is ready. + """ + original_picking = self.picking1 + package_level = original_picking.package_level_ids[0] + move = package_level.move_line_ids.move_id[0] + next_move = move.copy( + { + "picking_id": False, + "location_id": move.location_dest_id.id, + "location_dest_id": self.customer_location.id, + "move_orig_ids": [(6, 0, move.ids)], + } + ) + next_move._action_confirm(merge=False) + next_move._assign_picking() + self.assertEqual(next_move.state, "waiting") + self.assertTrue(next_move.picking_id) + response = self.service.dispatch( + "set_destination_package", + params={ + "location_id": self.content_loc.id, + "package_level_id": package_level.id, + "barcode": self.dest_location.barcode, + }, + ) + # Check the data (the whole transfer has been validated here w/o backorder) + self.assertFalse(original_picking.backorder_ids) + self.assertEqual(original_picking.state, "done") + self.assertEqual(package_level.state, "done") + self.assertEqual(next_move.state, "assigned") + # Check the response + move_lines = self.service._find_transfer_move_lines(self.content_loc) + completion_info = self.service.actions_for("completion.info") + completion_info_popup = completion_info.popup(package_level.move_line_ids) + self.assert_response_start_single( + response, + move_lines.mapped("picking_id"), + message=self.service.msg_store.location_content_transfer_item_complete( + self.dest_location + ), + popup=completion_info_popup, + ) + for move in package_level.move_line_ids.mapped("move_id"): + self.assertEqual(move.state, "done") + def test_set_destination_line_wrong_parameters(self): """Wrong 'location' and 'move_line_id' parameters, redirect the user to the 'start' screen. @@ -317,6 +364,56 @@ def test_set_destination_line_dest_location_ok(self): ), ) + def test_set_destination_line_dest_location_ok_with_completion_info(self): + """Scanned destination location valid, moves set to done + and completion info is returned as the next transfer is ready. + """ + original_picking = self.picking2 + move_line = original_picking.move_line_ids[0] + move = move_line.move_id + next_move = move.copy( + { + "picking_id": False, + "location_id": move.location_dest_id.id, + "location_dest_id": self.customer_location.id, + "move_orig_ids": [(6, 0, move.ids)], + } + ) + next_move._action_confirm(merge=False) + next_move._assign_picking() + self.assertEqual(next_move.state, "waiting") + self.assertTrue(next_move.picking_id) + response = self.service.dispatch( + "set_destination_line", + params={ + "location_id": self.content_loc.id, + "move_line_id": move_line.id, + "quantity": move_line.product_uom_qty, + "barcode": self.dest_location.barcode, + }, + ) + # Check the resulting data + # We got a new picking as the original one had two moves (and we + # validated only one) + new_picking = move_line.picking_id + self.assertTrue(new_picking != original_picking) + self.assertEqual(move_line.move_id.state, "done") + self.assertEqual(move_line.picking_id.state, "done") + self.assertEqual(original_picking.state, "assigned") + self.assertEqual(next_move.state, "assigned") + # Check the response + move_lines = self.service._find_transfer_move_lines(self.content_loc) + completion_info = self.service.actions_for("completion.info") + completion_info_popup = completion_info.popup(move_line) + self.assert_response_start_single( + response, + move_lines.mapped("picking_id"), + message=self.service.msg_store.location_content_transfer_item_complete( + self.dest_location + ), + popup=completion_info_popup, + ) + def test_set_destination_line_partial_qty(self): """Scanned destination location with partial qty, but related moves has to be splitted.