CheckoutSession registra o handshake de checkout por QR Code antes da criação do checkout. A sessão nasce sem Customer, expõe um QR Code temporário, é vinculada quando o cliente autenticado escaneia o código e só então pode confirmar uma venda por dinheiro ou crédito corporativo.
Campos
| Campo | Tipo | Descrição |
|---|
checkoutSessionId | UUID | Identificador único |
tripId | UUID | Trip selecionada para a venda |
tripItineraryId | UUID? | Itinerário escolhido pelo Customer antes da confirmação |
seatId | UUID? | Assento escolhido pelo Customer antes da confirmação |
paymentMethod | CheckoutSessionPaymentMethod | Forma escolhida para o checkout |
qrTokenHash | String | Hash do token usado no QR Code; o token bruto não é persistido |
passengerDraft | Json? | Passageiro informado pelo Customer antes da criação do Passenger definitivo |
requestedCreditAmount | Int? | Valor de crédito solicitado pelo Customer para esta sessão |
promotionalCode | String? | Código promocional informado pelo Customer, quando aplicável |
expiresAt | DateTime | Data limite de validade do QR Code |
linkedAt | DateTime? | Data em que o Customer foi vinculado |
preparedAt | DateTime? | Data em que o Customer preparou o contexto do ticket |
confirmedAt | DateTime? | Data em que a venda foi confirmada |
canceledBy | UUID? | Usuário que cancelou a sessão, quando aplicável |
canceledAt | DateTime? | Data de cancelamento |
createdBy | UUID? | Usuário que criou o registro, quando aplicável |
createdAt | DateTime | Data de criação |
updatedBy | UUID? | Usuário que fez a última atualização, quando aplicável |
updatedAt | DateTime | Data da última atualização |
Relacionamentos
- Relaciona-se com Trip por
tripId.
- Relaciona-se com TripItinerary por
tripItineraryId, depois da preparação pelo app do cliente.
- Relaciona-se com Seat por
seatId, depois da preparação pelo app do cliente.
- A sessão não persiste
driverId, customerId ou checkoutId.
- O usuário que cria ou cancela a sessão é auditado por
createdBy e canceledBy, sem transformar a sessão em entidade de Driver.
- O Customer é resolvido pelo User autenticado no Customer API.
- O Checkout criado pela confirmação é retorno do fluxo de confirmação.
Regras de Negócio
- A sessão é criada por um canal autenticado de venda usando o User autenticado.
- O app do cliente deve autenticar o Customer e vincular a sessão antes de qualquer confirmação de compra.
- O canal que inicia a venda seleciona a Trip e
paymentMethod; o app do cliente prepara o contexto necessário para emitir Ticket, como passageiro, itinerário, assento, crédito e promoção.
tripItineraryId, seatId, passengerDraft, requestedCreditAmount, promotionalCode e preparedAt só são preenchidos depois que o Customer envia o contexto do ticket pelo app.
- A Trip deve estar elegível para venda pelo fluxo de QR Code e o usuário autenticado deve estar autorizado para operá-la.
- A sessão deve expirar em
expiresAt; sessões expiradas ou canceladas não podem criar Checkout.
- Apenas sessões vinculadas, preparadas, não expiradas, não canceladas e ainda não confirmadas podem ser confirmadas.
- Quando
paymentMethod = CREDIT_GRANT, a autorização e a validação de saldo acontecem no app do cliente. O canal de venda não seleciona crédito do Customer manualmente.
requestedCreditAmount é solicitação do Customer; o valor definitivo usado no checkout fica em Checkout, Order, Ticket e CreditLedgerEntry.
- Quando
paymentMethod = CASH, a confirmação significa que o dinheiro foi aceito. A prestação de contas posterior segue o fluxo financeiro do canal em CashSettlement.
- A confirmação cria Checkout, Order, Ticket e as reservas de assento necessárias.
- Depois da confirmação,
confirmedAt é preenchido e o Checkout criado é retornado pelo fluxo de confirmação.
- O QR Code não é estado do Checkout; o estado temporário do QR vive somente na CheckoutSession.
- O status da sessão é calculado a partir dos timestamps e não deve ser persistido.
paymentMethod = CREDIT_GRANT aqui não adiciona CREDIT_GRANT em PaymentMethod. Crédito corporativo continua sendo modelado por CreditGrant e CreditLedgerEntry.
Enums
CheckoutSessionPaymentMethod
| Valor | Descrição |
|---|
CASH | Venda em dinheiro |
CREDIT_GRANT | Venda paga com crédito corporativo autorizado pelo Customer |
CheckoutSessionComputedStatus
Status virtual calculado em repository/query, sem campo persistido.
| Valor | Descrição |
|---|
CREATED | linkedAt, preparedAt, confirmedAt e canceledAt vazios, com expiresAt futuro |
LINKED | linkedAt preenchido, sem preparação/confirmação/cancelamento e com expiresAt futuro |
PREPARED | preparedAt preenchido, sem confirmação/cancelamento e com expiresAt futuro |
CONFIRMED | confirmedAt preenchido |
EXPIRED | expiresAt no passado antes da confirmação |
CANCELED | canceledAt preenchido antes da confirmação |
Example
{
"checkoutSessionId": "01981255-3c7a-7bd4-bb5f-8b47bc4dce91",
"tripId": "0197a80f-2d8f-7710-b243-b67fb477a1c0",
"tripItineraryId": "0197a810-87ce-7b60-9d80-660d0ee1c413",
"seatId": "0197a80a-bc30-70c3-954f-657c74277162",
"paymentMethod": "CASH",
"qrTokenHash": "sha256:8f34d4b7c7b3a331a7e3f7c6f8fdb9e2637a7d94e95d2f7c22b8c411d4815c4f",
"passengerDraft": {
"name": "Mariana Costa",
"document": "12345678909",
"documentType": "CPF",
"birthDate": "1992-04-18"
},
"requestedCreditAmount": 0,
"promotionalCode": null,
"expiresAt": "2026-07-08T12:15:00.000Z",
"linkedAt": "2026-07-08T12:10:21.000Z",
"preparedAt": "2026-07-08T12:10:45.000Z",
"confirmedAt": "2026-07-08T12:11:08.000Z",
"canceledBy": null,
"canceledAt": null,
"createdBy": "0197a805-0910-7eb2-bae7-90a13df2a9b2",
"createdAt": "2026-07-08T12:10:00.000Z",
"updatedBy": "0197a805-0910-7eb2-bae7-90a13df2a9b2",
"updatedAt": "2026-07-08T12:11:08.000Z"
}