O preço final de uma passagem (Ticket) é composto por dois componentes independentes: o preço do itinerário e o preço da categoria do assento. Ambos são congelados no momento da compra.
Campos de Preço no Ticket
| Campo | Tipo | Descrição |
|---|
tripItineraryPrice | integer | Preço do itinerário em centavos (copiado do TripItinerary no momento da compra) |
seatPrice | integer | Preço da categoria do assento em centavos (copiado do SeatType no momento da compra) |
price | integer | Preço final da passagem em centavos |
Composição do Preço
O price (preço final) é a soma dos dois componentes:
price = seatPrice + tripItineraryPrice
Exemplo
| Componente | Valor |
|---|
| Itinerário SP → Rio | R$ 120,00 (12000 centavos) |
| Assento Executivo | R$ 30,00 (3000 centavos) |
| Preço final | R$ 150,00 (15000 centavos) |
Congelamento de Preços
Os preços são congelados (snapshot) no Ticket no momento da compra. Se o preço do itinerário ou da categoria de assento mudar depois, passagens já emitidas não são afetadas.
Esse design garante:
- Integridade financeira: O valor cobrado do passageiro é exatamente o registrado no Ticket.
- Rastreabilidade: É possível verificar o preço de cada componente no momento da venda. O Ticket também guarda um
snapshot denormalizado (trip, itinerário, assento, passageiro) para exibição.
- Independência: Alterações de preço não causam efeitos colaterais em vendas passadas.
O amount do Order é a soma dos price de todos os seus Tickets:
Order.amount = sum(Ticket[].price)
| Order | Ticket 1 | Ticket 2 | Total |
|---|
| ORD-001 | R$ 150,00 (SP→Rio, Executivo) | R$ 120,00 (SP→Rio, Comum) | R$ 270,00 |
Todos os valores monetários no sistema são armazenados em centavos (integer) para evitar imprecisões de ponto flutuante. A conversão para reais acontece apenas na camada de apresentação.