# Ride Stops

## Overview

Ordered intermediate stops on ride requests and immutable ride stop snapshots.

- Request path:
  - Pickup -> Stop(s) -> Destination
- Ride path snapshot:
  - Sequence `0`: `PICKUP`
  - Sequence `1..N`: `STOP`
  - Last sequence: `DESTINATION`

Stops are **route/location data only**. They do not have a status lifecycle.

Ride lifecycle is controlled only by `Ride.status`:

```text
ACCEPTED → DRIVER_ARRIVING → DRIVER_ARRIVED → IN_PROGRESS → COMPLETED
```

## Limits

- `RIDE_MAX_STOPS` (default `5`) controls max stops per request.
- Validation rejects:
  - More than max stops
  - Consecutive identical coordinates
  - Stop matching destination coordinates
  - Invalid latitude/longitude ranges

## Data Model

- `ride_request_stops`
  - `UNIQUE(rideRequestId, sequence)`
- `ride_stops`
  - `UNIQUE(rideId, sequence)`
  - `type`: `PICKUP | STOP | DESTINATION`
  - No `status` column

## Fare Distance Calculation

Distance is summed across route segments:

`pickup -> stop1 -> stop2 -> ... -> destination`

Estimated fare:

`estimatedFare = totalDistanceKm * pricePerKm`

Rounded to 2 decimals with server-side monetary rounding.

## Driver Visibility

Driver open ride requests include:

- Category + `pricePerKm`
- Pickup, stops, destination
- `estimatedDistanceKm`
- `estimatedFare`
- Existing `proposedFare`

## GPS Proximity (Ride lifecycle)

- `ACCEPTED → DRIVER_ARRIVING`: driver must be within `RIDE_PICKUP_PROXIMITY_METERS` of pickup
- `DRIVER_ARRIVED → IN_PROGRESS`: via `POST /rides/:id/verify-pin` (Ride PIN); does not replace pickup GPS
- `IN_PROGRESS → COMPLETED`: driver must be within `RIDE_DESTINATION_PROXIMITY_METERS` of destination

There is no stop-status endpoint and no stop-arrival GPS check.

See also: [RIDE-PIN.md](./RIDE-PIN.md).

## Ride Response

Ride detail includes ordered `stops` (coordinates + address + type + sequence).

`eta` remains `null` until a routing provider is integrated.
