mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-07 18:55:42 +00:00
feat: (upgrade) implement per-passenger fare class upgrade with configurable policies
This commit is contained in:
@@ -81,6 +81,7 @@ model CoachType {
|
||||
coaches Coach[]
|
||||
seatClasses SeatClass[]
|
||||
reschedulePolicy ReschedulePolicy?
|
||||
upgradePolicy UpgradePolicy?
|
||||
@@schema("passenger")
|
||||
}
|
||||
|
||||
@@ -570,6 +571,7 @@ model Booking {
|
||||
agentBooking AgentBooking?
|
||||
modifications BookingModification[]
|
||||
reschedules BookingReschedule[]
|
||||
upgrades BookingUpgrade[]
|
||||
cancellation BookingCancellation?
|
||||
baggage BaggageBooking[]
|
||||
excessBaggageCharges ExcessBaggageCharge[]
|
||||
@@ -1207,6 +1209,64 @@ model AgentCommission {
|
||||
@@schema("passenger")
|
||||
}
|
||||
|
||||
/// Fare-class upgrade rule, one row per coach type (policy US-17). A coach type with no row here
|
||||
/// can be neither upgraded from nor to — the same "no policy = not allowed" semantics
|
||||
/// ReschedulePolicy uses. Edited in backoffice Master Data → Upgrade Policies.
|
||||
model UpgradePolicy {
|
||||
id String @id @default(uuid())
|
||||
coachTypeId String @unique
|
||||
/// Position on the ladder — an upgrade requires target.rank > source.rank. An explicit column
|
||||
/// rather than a price comparison: SeatClass.baseFareMinor is a per-km tariff, while the fare
|
||||
/// actually charged resolves through SegmentFareRule/FareRule first, so on some segments the
|
||||
/// price order differs from the class order. Which class is "higher" is a business decision
|
||||
/// and must not flip because someone edited a tariff.
|
||||
rank Int @default(0)
|
||||
feePercent Int @default(0) // % of the passenger's original fare
|
||||
feeMinMinor Int @default(0) // fee floor, ETB minor units
|
||||
feeWaived Boolean @default(false)
|
||||
isUpgradable Boolean @default(true) // passengers may leave this class
|
||||
isTargetable Boolean @default(true) // passengers may arrive in this class
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
coachType CoachType @relation(fields: [coachTypeId], references: [id])
|
||||
|
||||
@@schema("passenger")
|
||||
}
|
||||
|
||||
/// One fare-class upgrade request for one leg. Same lifecycle as BookingReschedule
|
||||
/// (PENDING_PAYMENT → APPLIED | EXPIRED) but the schedule never changes — only the seats, and
|
||||
/// only for the passengers named in `items`.
|
||||
model BookingUpgrade {
|
||||
id String @id @default(uuid())
|
||||
bookingId String
|
||||
leg Int @default(1)
|
||||
status String @default("PENDING_PAYMENT") // PENDING_PAYMENT | APPLIED | EXPIRED
|
||||
requestedBy String
|
||||
scheduleId String // unchanged by the upgrade; recorded so the audit row reads standalone
|
||||
/// Frozen per-passenger quote, keyed on bookingSeatId — NOT array position. Only some
|
||||
/// passengers move, so a positional pairing (as BookingReschedule uses) would be fragile.
|
||||
/// Each element: { bookingSeatId, passengerName, passengerCategory,
|
||||
/// oldSeatId, oldSeatLabel, oldCoachTypeId, oldSeatClassId, oldFareMinor,
|
||||
/// newSeatId, newSeatLabel, newCoachTypeId, newSeatClassId, newFareMinor,
|
||||
/// feeMinor, fareDifferenceMinor }
|
||||
items Json
|
||||
holdId String?
|
||||
oldFareMinor Int
|
||||
newFareMinor Int
|
||||
fareDifferenceMinor Int
|
||||
feeMinor Int
|
||||
amountDueMinor Int
|
||||
supplementaryChargeId String? @unique
|
||||
expiresAt DateTime?
|
||||
appliedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
booking Booking @relation(fields: [bookingId], references: [id])
|
||||
|
||||
@@index([bookingId, status])
|
||||
@@schema("passenger")
|
||||
}
|
||||
|
||||
/// Rescheduling rule per fare class. Fare families from the passenger policy map 1:1 onto
|
||||
/// coach types (HSC = Standard, HBC = Flex, SBC = Premium). Seeded by migration from the policy
|
||||
/// doc; edited in backoffice Settings → Reschedule Policy.
|
||||
|
||||
Reference in New Issue
Block a user