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

# Checkout QR

> Venda de ticket por QR Code entre canal de venda e app do cliente

Checkout QR é o fluxo em que um canal autenticado inicia uma venda, mostra um QR Code para o passageiro e o Customer autenticado vincula a sessão pelo app do cliente. A venda pode ser confirmada em dinheiro ou com crédito corporativo autorizado pelo próprio Customer.

## Fluxo

```mermaid theme={null}
sequenceDiagram
    actor D as Canal de venda
    participant DA as App de venda
    participant S as CheckoutSession
    actor C as Customer
    participant CA as Customer app
    participant Sales
    participant Credit as Credit Grant
    participant Billing

    D->>DA: Seleciona Trip e paymentMethod
    DA->>S: Cria sessão CREATED com QR temporário
    C->>CA: Escaneia QR Code autenticado
    CA->>S: Vincula sessão autenticada
    S-->>CA: Sessão LINKED

    CA->>S: Prepara itinerary, assento e passageiro

    alt paymentMethod = CREDIT_GRANT
        CA->>Credit: Valida crédito do Customer
        Credit-->>CA: Crédito reservado
    else paymentMethod = CASH
        D->>DA: Confirma recebimento do dinheiro
    end

    DA->>Sales: Confirma sessão vinculada
    Sales->>Sales: Cria Checkout, Order e Ticket

    alt CASH
        Sales->>Billing: Cria Payment CASH PAID
    else CREDIT_GRANT
        Sales->>Credit: Captura crédito por Ticket
    end

    Sales->>S: Marca CONFIRMED
```

## Estados da sessão

Os estados abaixo são calculados a partir de `linkedAt`, `preparedAt`, `confirmedAt`, `canceledAt` e `expiresAt`; não há campo `status` persistido na sessão.

```mermaid theme={null}
stateDiagram-v2
    [*] --> CREATED
    CREATED --> LINKED : Customer escaneia QR
    CREATED --> EXPIRED : expiresAt atingido
    CREATED --> CANCELED : canal de venda cancela
    LINKED --> PREPARED : Customer prepara ticket
    PREPARED --> CONFIRMED : venda confirmada
    LINKED --> EXPIRED : expiresAt atingido
    LINKED --> CANCELED : canal de venda ou customer cancela
    PREPARED --> EXPIRED : expiresAt atingido
    PREPARED --> CANCELED : canal de venda ou customer cancela
    CONFIRMED --> [*]
    EXPIRED --> [*]
    CANCELED --> [*]
```

## Responsabilidades

| Etapa              | Responsável               | Regra                                                                                    |
| ------------------ | ------------------------- | ---------------------------------------------------------------------------------------- |
| Criar sessão       | App de venda              | Usuário autenticado informa Trip e `paymentMethod`.                                      |
| Vincular sessão    | Customer app              | Customer autenticado escaneia QR; identidade vem do token autenticado.                   |
| Preparar ticket    | Customer app/Sales        | Passageiro, itinerary, assento, promoção e crédito seguem as regras normais de checkout. |
| Confirmar dinheiro | App de venda              | Usuário autenticado confirma que recebeu dinheiro.                                       |
| Autorizar crédito  | Customer app/Credit Grant | Customer autoriza uso de CreditGrant no próprio app.                                     |
| Emitir ticket      | Sales                     | Checkout, Order, Ticket e TripSeatSegments são criados na confirmação.                   |

## Dinheiro vs crédito

| Aspecto                 | `CASH`                                                                          | `CREDIT_GRANT`                                                                    |
| ----------------------- | ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| Autorização do Customer | Scan do QR vincula a sessão                                                     | Scan do QR vincula a sessão e Customer autoriza o crédito                         |
| Confirmação             | Canal de venda aceita o dinheiro                                                | Credit Grant reserva e captura crédito                                            |
| Payment                 | Cria Payment com `method = CASH`, `channel` do canal de venda e `status = PAID` | Só cria Payment se ainda houver `paidAmount` externo; crédito puro fica no ledger |
| Pós-venda               | Prestação de contas do canal via CashSettlement                                 | Uso fica rastreado em CreditLedgerEntry por Ticket                                |

## Validações

* O QR Code deve pertencer a uma sessão ativa, não expirada e não confirmada.
* O Customer deve estar autenticado no app do cliente.
* A sessão só pode ser vinculada por um Customer autenticado uma vez; tentativa de trocar o vínculo deve cancelar a sessão e criar outra.
* O usuário autenticado deve estar autorizado para a Trip selecionada.
* A Trip precisa estar elegível para venda embarcada, conforme política operacional da cooperativa.
* O ticket continua exigindo itinerary, passageiro, assento disponível e regras de benefício/promoção compatíveis.
* Vendas com `paymentMethod = CREDIT_GRANT` devem validar saldo ativo do Customer e criar movimentos de reserva/captura no Credit Grant.
* Vendas com `paymentMethod = CASH` não dependem de gateway e não aguardam webhook para emissão.

## Dados que não devem ser persistidos

* Saldo disponível do Customer na sessão; calcular a partir de CreditGrant.
* Valor esperado da prestação de contas; calcular a partir dos Payments em dinheiro.
* Diferença de caixa; calcular a partir do esperado, declarado e recebido.
* `CREDIT_GRANT` em PaymentMethod; crédito corporativo permanece no domínio Credit Grant.

Veja a modelagem em [CheckoutSession](/data-modelling/sales/checkout-session).
