This document assumes familiarity with the following:

- [Create shipment tasks](https://developers.google.com/maps/documentation/mobility/fleet-engine/journeys/tasks/create-shipment-tasks.md.txt)
- The introduction to [Scheduled tasks](https://developers.google.com/maps/documentation/mobility/fleet-engine/essentials/tasks-intro.md.txt), which covers the relationship between tasks, stops, and vehicles in detail.

In a real-world delivery scenario, businesses assign delivery shipment tasks to
drivers, who then use a vehicle to deliver them to the recipient at a planned
location, such as a residence or a delivery room in a building complex. You
model this in Fleet Engine by creating a task and issuing a delivery vehicle
update request, which then updates the vehicle entity with a list of stops to
travel. You assign each stop a list of tasks to be completed at the stop.

You can update vehicle tasks at any time, but typically you do this for the
following purposes:

- **Schedule tasks** for a vehicle to complete. You can do this either with an update request that adds a new stop to the vehicle, or by an update request that adds a new task to an existing stop.
- **Update the order of existing tasks** associated with a given vehicle stop.
- **Change the location of the task completion.** By default, Fleet Engine marks the task completion location as the same location as the vehicle stop associated with the task. If you prefer, you can specify specific locations for individual tasks. For example, you might have a vehicle stop at a large complex to delivery a number of packages, each of which is assigned a specific mail delivery room.
- **Close any previously assigned tasks** to leave them out of the updated ordering. See [Finalize tasks](https://developers.google.com/maps/documentation/mobility/fleet-engine/journeys/tasks/finalize-tasks.md.txt) for details.

## Schedule or change delivery tasks

You can schedule or change tasks assigned to a vehicle from either a server
environment, or by using the Driver SDK if you provide the driver the ability to
manage tasks using a trusted device. Use only one method so that you avoid race
conditions and maintain a single source of truth.

To change a shipment from one vehicle to another, [close the original task](https://developers.google.com/maps/documentation/mobility/fleet-engine/journeys/tasks/finalize-tasks.md.txt#close-task)
and recreate it before assigning to a different vehicle. If you update a
delivery vehicle to include a task that is already assigned to a different
vehicle, you get an error.

> [!NOTE]
> **Note:** When you schedule a number of tasks for a vehicle to complete at the same location, you should create a one-to-many association between a stop and the tasks associated with that stop location. Avoid creating a list of stop-task pairs where the stop location is the same for each pair in the list. This helps when you want to share the task status with your consumers using journey sharing. For example, if a driver is making many deliveries to a single office building, you would assign all the delivery tasks to a single vehicle stop.

### Required fields for updating tasks

This section documents the required fields to set when updating a task for a
vehicle. No optional fields are provided. Fleet engine ignores all other fields
in the entity for the update.

<br />

| Required field | Value |
|---|---|
| `remainingVehicleJourneySegments` | A list of journey segments for tasks in the order they should be executed. The first task in the list is executed first. |
| `remainingVehicleJourneySegments[i].stop` | The stop for task *i* in the list. |
| `remainingVehicleJourneySegments[i].stop.plannedLocation` | The planned location for the stop. |
| `remainingVehicleJourneySegments[i].stop.tasks` | A list of tasks to be performed at this vehicle stop. |
| `remainingVehicleJourneySegments[i].stop.state` | `State.NEW` |

<br />

## Assign tasks example

The following examples show how to use the [Java gRPC library](https://developers.google.com/maps/documentation/mobility/fleet-engine/essentials/client-libraries-tasks.md.txt) and an HTTP
REST call to `UpdateDeliveryVehicle` to add two new tasks for the vehicle.

### gRPC

```java
 static final String PROJECT_ID = "my-delivery-co-gcp-project";
 static final String VEHICLE_ID = "vehicle-8241890";
 static final String TASK1_ID = "task-756390";
 static final String TASK2_ID = "task-849263";

 DeliveryServiceBlockingStub deliveryService =
   DeliveryServiceGrpc.newBlockingStub(channel);

 // Vehicle settings
 String vehicleName = "providers/" + PROJECT_ID + "/deliveryVehicles/" + VEHICLE_ID;
 DeliveryVehicle deliveryVehicle = DeliveryVehicle.newBuilder()
     .addRemainingVehicleJourneySegments(VehicleJourneySegment.newBuilder()  // 1st stop
        .setStop(VehicleStop.newBuilder()
            .setPlannedLocation(LocationInfo.newBuilder()
                .setPoint(LatLng.newBuilder()
                    .setLatitude(37.7749)
                    .setLongitude(122.4194)))
            .addTasks(TaskInfo.newBuilder().setTaskId(TASK1_ID))
            .setState(VehicleStop.State.NEW)))
     .addRemainingVehicleJourneySegments(VehicleJourneySegment.newBuilder()  // 2nd stop
        .setStop(VehicleStop.newBuilder()
            .setPlannedLocation(LocationInfo.newBuilder()
                .setPoint(LatLng.newBuilder()
                    .setLatitude(37.3382)
                    .setLongitude(121.8863)))
            .addTasks(TaskInfo.newBuilder().setTaskId(TASK2_ID))
            .setState(VehicleStop.State.NEW)))
     .build();

 // DeliveryVehicle request
 UpdateDeliveryVehicleRequest updateDeliveryRequest =
   UpdateDeliveryVehicleRequest.newBuilder()  // No need for the header
       .setName(vehicleName)
       .setDeliveryVehicle(deliveryVehicle)
       .setUpdateMask(FieldMask.newBuilder().addPaths("remaining_vehicle_journey_segments"))
       .build();

 try {
   DeliveryVehicle updatedDeliveryVehicle =
       deliveryService.updateDeliveryVehicle(updateDeliveryVehicleRequest);
 } catch (StatusRuntimeException e) {
   Status s = e.getStatus();
   switch (s.getCode()) {
      case NOT_FOUND:
        break;
      case PERMISSION_DENIED:
        break;
   }
   return;
 }
```

### REST

```console
 PATCH https://fleetengine.googleapis.com/v1/providers/<project_id>/deliveryVehicles/<id>?updateMask=remainingVehicleJourneySegments`
```

- *\<id\>* is a unique identifier for a delivery vehicle in your fleet
  for which you intend to update the task ordering. It is the identifier that
  you specified when creating the vehicle.

- The request header must contain a field *Authorization* with the value
  *Bearer \<token\>* , where *\<token\>* is issued by your server
  according to the guidelines described in [Service account roles](https://developers.google.com/maps/documentation/mobility/fleet-engine/essentials/set-up-fleet/service-accounts.md.txt) and
  [JSON Web tokens](https://developers.google.com/maps/documentation/mobility/fleet-engine/essentials/set-up-fleet/jwt.md.txt).

- The request body must contain a `DeliveryVehicle` entity

Example `curl` command:

> [!NOTE]
> **Note:** This command overwrites any `remainingVehicleJourneySegments` already set on the delivery vehicle.

```console
  # Set JWT, PROJECT_ID, VEHICLE_ID, TASK1_ID, and TASK2_ID in the local
  # environment
  curl -X PATCH "https://fleetengine.googleapis.com/v1/providers/${PROJECT_ID}/deliveryVehicles/${VEHICLE_ID}?updateMask=remainingVehicleJourneySegments" \
    -H "Content-type: application/json" \
    -H "Authorization: Bearer ${JWT}" \
    --data-binary @- << EOM
  {
    "remainingVehicleJourneySegments": [
      {
        "stop": {
          "state": "NEW",
          "plannedLocation": {
            "point": {
              "latitude": 37.7749,
              "longitude": -122.084061
            }
          },
          "tasks": [
            {
              "taskId": "${TASK1_ID}"
            }
          ]
        }
      },
      {
        "stop": {
          "state": "NEW",
          "plannedLocation": {
            "point": {
              "latitude": 37.3382,
              "longitude": 121.8863
            }
          },
          "tasks": [
            {
              "taskId": "${TASK2_ID}"
            }
          ]
        }
      }
    ]
  }
  EOM
```

> [!WARNING]
> **Experimental:** As an experimental feature, the `LocationInfo` ([gRPC](https://developers.google.com/maps/documentation/mobility/fleet-engine/reference/tasks/rpc/maps.fleetengine.delivery.v1.md.txt#locationinfo) or [REST](https://developers.google.com/maps/documentation/mobility/fleet-engine/reference/tasks/rest/v1/LocationInfo.md.txt)) field now supports using `place` ([gRPC](https://developers.google.com/maps/documentation/mobility/fleet-engine/reference/tasks/rpc/maps.fleetengine.delivery.v1.md.txt#maps.fleetengine.delivery.v1.LocationInfo.FIELDS.string.maps.fleetengine.delivery.v1.LocationInfo.place) or [REST](https://developers.google.com/maps/documentation/mobility/fleet-engine/reference/tasks/rest/v1/LocationInfo.md.txt#FIELDS.place)), either alongside or instead of `LatLng`.

## What's next

- [Update stop status](https://developers.google.com/maps/documentation/mobility/fleet-engine/journeys/tasks/update-stops.md.txt)