> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devmob.app.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Trips

> Ciclo de vida da viagem: máquina de estados, criação avulsa e materialização a partir de programações.

Uma **Trip** representa uma viagem agendada — a combinação de uma rota, um veículo e um motorista em uma data/hora específica. É a entidade central do domínio de Operations.

## Máquina de Estados

```mermaid theme={null}
stateDiagram-v2
    [*] --> SCHEDULED

    SCHEDULED --> IN_PROGRESS : Iniciar
    SCHEDULED --> CANCELLED : Cancelar

    IN_PROGRESS --> COMPLETED : Concluir
    IN_PROGRESS --> CANCELLED : Cancelar

    COMPLETED --> [*]
    CANCELLED --> [*]
```

### TripStatus

| Status        | Descrição                                                                 |
| ------------- | ------------------------------------------------------------------------- |
| `SCHEDULED`   | Viagem agendada. Disponível para venda enquanto `departureAt` for futuro. |
| `IN_PROGRESS` | Viagem em andamento.                                                      |
| `COMPLETED`   | Viagem concluída.                                                         |
| `CANCELLED`   | Viagem cancelada.                                                         |

### Transições

| De                          | Para          | Regra                                                        |
| --------------------------- | ------------- | ------------------------------------------------------------ |
| `SCHEDULED`                 | `IN_PROGRESS` | Só viagens agendadas podem iniciar                           |
| `IN_PROGRESS`               | `COMPLETED`   | Só viagens em andamento podem concluir                       |
| `SCHEDULED` / `IN_PROGRESS` | `CANCELLED`   | Viagens concluídas ou já canceladas não podem ser canceladas |

Cada transição atualiza o status da viagem.

<Warning>
  As transições são **explícitas**. Horário de partida e registro de embarque não alteram o status por conta própria. Registrar `BOARDING_COMPLETED` mantém a viagem no status atual.
</Warning>

### Disponibilidade

Uma viagem é considerada disponível para venda quando está `SCHEDULED` **e** `departureAt` ainda é futuro. A busca de ofertas só retorna viagens nessa condição.

## Rastreamento GPS

Trip não guarda campos de tracking diretamente. O último ping GPS aceito fica na tabela auxiliar 1:1 [TripTracking](/data-modelling/operations/trip-tracking).

```mermaid theme={null}
flowchart TD
    START["Trip entra em IN_PROGRESS"] --> PING["App do motorista envia localização"]
    PING --> VALIDATE["Backend valida status e coordenadas"]
    VALIDATE --> UPDATE["TripTracking é criado ou atualizado"]
    UPDATE --> STALE["acceptedAt permite detectar tracking desatualizado"]
    STALE --> FINISH["GPS deixa de ser aceito ao completar ou cancelar"]
```

| Regra            | Descrição                                                                                                                                |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| Status permitido | GPS só é aceito quando a Trip está `IN_PROGRESS`.                                                                                        |
| Tabela auxiliar  | Cada Trip pode ter no máximo um [TripTracking](/data-modelling/operations/trip-tracking).                                                |
| Último ponto     | `latitude`, `longitude`, `accuracyMeters`, `speedKmh`, `headingDegrees` e `acceptedAt` em TripTracking representam o último ping aceito. |
| Atualização      | Cada novo ping aceito atualiza o mesmo TripTracking da viagem.                                                                           |
| Sem histórico    | TripTracking não guarda pings antigos.                                                                                                   |

## Relação com Outros Domínios

* **Fleet**: a Trip referencia um Vehicle e um Driver da empresa.
* **Operations**: a Trip contém TripStops (paradas) e TripItineraries (trechos compráveis); a venda de tickets gera TripSeatSegments.
* **Sales**: Orders e Tickets são vendidos referenciando os TripItineraries da viagem.

***

## Criação avulsa de viagem

Criação avulsa registra uma única viagem.

### Dados esperados

| Campo                | Descrição                       |
| -------------------- | ------------------------------- |
| `routeId`            | Rota da viagem                  |
| `vehicleId`          | Veículo escalado                |
| `driverId`           | Motorista escalado              |
| `departureAt`        | Data/hora de partida            |
| `estimatedArrivalAt` | Data/hora estimada de chegada   |
| `stops`              | Paradas físicas da viagem       |
| `itineraries`        | Trechos vendáveis entre paradas |

<Info>
  A empresa (`companyId`) vem do escopo da organização autenticada. Os itinerários referenciam paradas por `stopOrder`.
</Info>

### Fluxo passo-a-passo

```mermaid theme={null}
flowchart TD
    REQ["Operador envia viagem"] --> SCOPE["Organização e rota são validadas"]
    SCOPE --> CONFLICT["Veículo e motorista são checados contra conflitos de horário"]
    CONFLICT --> CREATE["Trip, paradas e itinerários são criados juntos"]
    CREATE --> DONE["Viagem criada com status SCHEDULED"]
```

### Validações na criação

| Validação                        | Comportamento                                                                                                                          |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| Rota pertence à organização      | Rota de outra organização retorna 404                                                                                                  |
| Conflito de horário do veículo   | Sobreposição de janela `[departureAt, estimatedArrivalAt)` com viagens `SCHEDULED`/`IN_PROGRESS` do mesmo veículo → `vehicle_conflict` |
| Conflito de horário do motorista | Mesma checagem para o motorista → `driver_conflict`                                                                                    |

<Warning>
  A criação avulsa valida escopo da rota e conflitos de horário de veículo e motorista.
</Warning>

### Geração de TripStops e TripItineraries

Os TripStops representam as paradas físicas da viagem; os TripItineraries referenciam pares de paradas como trechos compráveis.

**Exemplo**: viagem São Paulo → Campinas → Ribeirão Preto

**TripStops** (nome resolvido via `pointId` no catálogo global):

| stopOrder | Point          | departureAt | arrivalAt |
| --------- | -------------- | ----------- | --------- |
| 0         | São Paulo      | 08:00       | null      |
| 1         | Campinas       | 09:45       | 09:30     |
| 2         | Ribeirão Preto | null        | 12:00     |

**TripItineraries:**

| TripItinerary          | fromStopOrder | toStopOrder | Preço     |
| ---------------------- | ------------- | ----------- | --------- |
| SP → Campinas          | 0             | 1           | R\$ 50,00 |
| Campinas → Ribeirão    | 1             | 2           | R\$ 40,00 |
| SP → Ribeirão (direto) | 0             | 2           | R\$ 80,00 |

<Info>
  É possível criar itinerários para trechos intermediários e para o trajeto completo, cada um com preço independente. Isso permite precificação flexível — o trecho completo pode custar menos que a soma dos parciais.
</Info>

***

## Materialização a partir de programações

Além da criação avulsa, viagens são geradas em lote a partir de uma [programação recorrente (TripSchedule)](/domain/operations/trip-schedules). A programação define rota, veículo, motorista, frequência e paradas-template, e o DEVMOB materializa as ocorrências em um horizonte móvel de 90 dias.

Cada viagem candidata é avaliada antes da criação: candidatas duplicadas ou em conflito são ignoradas, e somente as `MATERIALIZABLE` são criadas. Detalhes de frequência, idempotência e detecção de conflitos estão na página de [Trip Schedules](/domain/operations/trip-schedules).

***

## Cancelamento

```mermaid theme={null}
flowchart TD
    REQ["Operador solicita cancelamento"] --> CHECK["Viagem não pode estar COMPLETED ou CANCELLED"]
    CHECK --> CANCEL["Status muda para CANCELLED"]
    CANCEL --> DONE["Viagem cancelada"]
```

<Warning>
  O cancelamento marca a viagem como `CANCELLED`. Tickets, orders, payments e receivables permanecem fora do escopo dessa operação.
</Warning>
