> ## 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.

# Order Lifecycle

> Ciclo de vida de pedidos: criação, pagamento, confirmação e cancelamento.

Um **Checkout** representa a compra do cliente. Ele pode gerar um ou mais **Orders**, sempre separados por empresa. Cada Order possui um pagamento associado e tickets que ocupam assentos em segmentos específicos da viagem.

O Order pode nascer no canal digital (`ONLINE`) ou presencial (`POS`). Em venda POS, o sistema resolve ou cria `User` + `Customer` antes de criar o pedido; se a conta for nova, emite um Invite de ativação para uso posterior do app.

## Status

```mermaid theme={null}
stateDiagram-v2
    [*] --> PENDING
    PENDING --> PAID : pagamento confirmado
    PENDING --> PAYMENT_FAILED : pagamento recusado
    PENDING --> CANCELED : cancelamento
    PAID --> CANCELED : cancelamento
    PAYMENT_FAILED --> [*]
    CANCELED --> [*]
```

| Status           | Descrição                                           |
| ---------------- | --------------------------------------------------- |
| `PENDING`        | Pedido criado, aguardando confirmação do pagamento. |
| `PAID`           | Pagamento confirmado.                               |
| `PAYMENT_FAILED` | Pagamento recusado ou falhou.                       |
| `CANCELED`       | Pedido cancelado.                                   |

O status inicial depende do resultado retornado pelo provider de billing. Transições posteriores chegam por webhook.

## Criação do pedido

```mermaid theme={null}
flowchart TD
    START["Checkout"] --> CUSTOMER["Resolve cliente e passageiros"]
    CUSTOMER --> AVAIL["Valida trip, itinerary e assentos"]
    AVAIL --> PRICE["Calcula preço, benefícios e promoções"]
    PRICE --> CREDIT["Reserva crédito interno quando usado"]
    CREDIT --> GROUP["Agrupa tickets por Company"]
    GROUP --> BILLING["Cria cobrança por Order"]
    BILLING --> ORDER["Cria Checkout, Orders, Tickets, Payments e reservas de assento"]
    ORDER --> DONE["Pedido retornado"]
```

### Validações

| Validação                                 | Resultado                                                                        |
| ----------------------------------------- | -------------------------------------------------------------------------------- |
| Itinerário e assento existem na trip      | Pedido rejeitado quando não encontrados                                          |
| Trip disponível para venda                | Apenas viagens `SCHEDULED` e futuras são vendáveis                               |
| Assento pertence ao veículo               | Pedido rejeitado se o assento não faz parte do veículo da viagem                 |
| Assento livre nos segmentos do itinerário | Pedido rejeitado quando algum segmento já está ocupado                           |
| Tickets agrupados por empresa             | Cada empresa gera um Order próprio                                               |
| Customer obrigatório                      | Pedido POS também exige Customer resolvido ou criado                             |
| Benefícios e promoções válidos            | Descontos só entram no Order quando as regras dos domains responsáveis permitem  |
| Crédito interno da mesma empresa          | Crédito só pode ser usado quando pertence ao Customer e à mesma Company do Order |

Cada ticket recebe `seatPrice`, `tripItineraryPrice`, `price`, `qrCode`, `code`, `snapshot` e os segmentos cobertos.

Quando o canal é `POS`, o operador informa ou resolve o Customer antes da criação do Order. Se o sistema criar uma conta sem senha para o passageiro, um Invite `ACCOUNT_ACTIVATION` é emitido para ativação posterior no app.

## Reserva de assentos

A reserva é segmentada. Um ticket SP → Ribeirão ocupa todos os segmentos entre a parada de embarque e a parada de desembarque. Outro passageiro só pode usar o mesmo assento em segmentos que não se sobrepõem.

Se algum segmento já estiver ocupado, o pedido é rejeitado e nenhuma reserva parcial permanece.

## Pagamento e confirmação

O pagamento é criado no provider de billing durante o checkout. Cada Order tem seu próprio Payment, pois cada Order pertence a uma única empresa. O pedido pode nascer `PENDING` ou já `PAID`, conforme a resposta do provider.

Confirmações, recusas e estornos posteriores chegam por webhook de billing e atualizam o pedido e o pagamento.

## Cancelamento total

Um pedido pode ser cancelado quando suas regras de status permitem. Em pedidos pagos, o cancelamento solicita estorno ao provider antes de atualizar tickets e pagamento.

Efeitos do cancelamento total:

* Tickets válidos ficam `CANCELLED`.
* Reservas de assento dos tickets são liberadas.
* Payment é marcado como `REFUNDED` quando há estorno.
* Benefícios, promoções e créditos aplicados são revertidos conforme a regra de cada domínio.
* Order fica `CANCELED`.

## Cancelamento de ticket

Um ticket individual pode ser cancelado quando ainda restam outros tickets válidos no pedido.

1. O valor do ticket cancelado define o estorno parcial.
2. As reservas daquele ticket são liberadas.
3. O `Order.amount` passa a refletir a soma dos tickets restantes.
4. Se o ticket cancelado era o último válido, o fluxo vira cancelamento total.

<Info>
  O preço do ticket é congelado no momento da compra. Mudanças posteriores na rota ou no assento não alteram tickets já emitidos.
</Info>

## Atividades do ticket

Validações de QR Code, embarques, rejeições, falhas e reimpressões são registradas em [Ticket Activity](/domain/sales/ticket-activity). O Ticket guarda o estado consolidado; o histórico operacional fica append-only.
