diff --git a/apps/edr-passenger-api/prisma/migrations/20260717000003_booking_seat_schedule_unique/migration.sql b/apps/edr-passenger-api/prisma/migrations/20260717000003_booking_seat_schedule_unique/migration.sql new file mode 100644 index 000000000..2a9a1be65 --- /dev/null +++ b/apps/edr-passenger-api/prisma/migrations/20260717000003_booking_seat_schedule_unique/migration.sql @@ -0,0 +1,33 @@ +-- Make scheduleId non-nullable: backfill from the parent booking, then add NOT NULL. +UPDATE passenger."BookingSeat" bs +SET schedule_id = b.schedule_id +FROM passenger."Booking" b +WHERE bs.booking_id = b.id + AND bs.schedule_id IS NULL + AND bs.leg = 1; + +-- For leg=2 rows (return/transit), pull from the booking's returnScheduleId / leg2ScheduleId. +UPDATE passenger."BookingSeat" bs +SET schedule_id = COALESCE( + (b.return_schedule_id), + (b.leg2_schedule_id), + b.schedule_id +) +FROM passenger."Booking" b +WHERE bs.booking_id = b.id + AND bs.schedule_id IS NULL + AND bs.leg = 2; + +-- Catch any remaining NULLs (leg 3/4 from ROUND_TRIP_TRANSIT) using the booking's schedule. +UPDATE passenger."BookingSeat" bs +SET schedule_id = b.schedule_id +FROM passenger."Booking" b +WHERE bs.booking_id = b.id + AND bs.schedule_id IS NULL; + +-- Now enforce NOT NULL. +ALTER TABLE passenger."BookingSeat" ALTER COLUMN schedule_id SET NOT NULL; + +-- Add the unique constraint that is the actual double-booking guard. +CREATE UNIQUE INDEX "BookingSeat_scheduleId_seatId_key" + ON passenger."BookingSeat"(schedule_id, seat_id); diff --git a/apps/edr-passenger-api/prisma/schema.prisma b/apps/edr-passenger-api/prisma/schema.prisma index fb9db346f..601410fae 100644 --- a/apps/edr-passenger-api/prisma/schema.prisma +++ b/apps/edr-passenger-api/prisma/schema.prisma @@ -580,7 +580,7 @@ model BookingSeat { bookingId String seatId String leg Int @default(1) // 1=outbound/leg-1, 2=return/leg-2 - scheduleId String? // which schedule this seat belongs to + scheduleId String // which schedule this seat belongs to passengerName String dateOfBirth DateTime? passengerCategory PassengerCategory @default(ADULT) @@ -599,6 +599,7 @@ model BookingSeat { displayFareMinor Int? booking Booking @relation(fields: [bookingId], references: [id]) seat Seat @relation(fields: [seatId], references: [id]) + @@unique([scheduleId, seatId]) @@schema("passenger") } diff --git a/apps/edr-passenger-api/src/modules/agents/agents.service.ts b/apps/edr-passenger-api/src/modules/agents/agents.service.ts index 4ba7afcf1..57f33c5aa 100644 --- a/apps/edr-passenger-api/src/modules/agents/agents.service.ts +++ b/apps/edr-passenger-api/src/modules/agents/agents.service.ts @@ -85,6 +85,7 @@ export class AgentsService { seats: { create: dto.passengers.map(p => ({ seat: { connect: { id: p.seatId } }, + scheduleId: dto.scheduleId, passengerName: p.fullName, idDocumentType: p.idDocumentType as IdDocumentType | undefined, idDocumentNumber: p.idDocumentNumber diff --git a/apps/edr-passenger-api/src/modules/bookings/bookings.service.ts b/apps/edr-passenger-api/src/modules/bookings/bookings.service.ts index a0994d1be..ada6e2a78 100644 --- a/apps/edr-passenger-api/src/modules/bookings/bookings.service.ts +++ b/apps/edr-passenger-api/src/modules/bookings/bookings.service.ts @@ -910,6 +910,7 @@ export class BookingsService { seats: { create: passengersWithFares.map(p => ({ seat: { connect: { id: p.seatId } }, + scheduleId: dto.scheduleId, passengerName: p.passengerName, dateOfBirth: p.dateOfBirth, passengerCategory: p.category, diff --git a/apps/edr-passenger-api/src/modules/bookings/guest-booking.service.ts b/apps/edr-passenger-api/src/modules/bookings/guest-booking.service.ts index 43470c160..17e3a585e 100644 --- a/apps/edr-passenger-api/src/modules/bookings/guest-booking.service.ts +++ b/apps/edr-passenger-api/src/modules/bookings/guest-booking.service.ts @@ -299,6 +299,7 @@ export class GuestBookingService { seats: { create: passengersWithFares.map((p) => ({ seat: { connect: { id: p.seatId } }, + scheduleId: dto.scheduleId, passengerName: p.passengerName, dateOfBirth: p.dateOfBirth, passengerCategory: p.category, diff --git a/apps/edr-passenger-api/src/modules/packages/packages.service.ts b/apps/edr-passenger-api/src/modules/packages/packages.service.ts index 9ddc1fb0a..1528b2967 100644 --- a/apps/edr-passenger-api/src/modules/packages/packages.service.ts +++ b/apps/edr-passenger-api/src/modules/packages/packages.service.ts @@ -440,8 +440,8 @@ export class PackagesService { passengerCount, adultCount, childCount, - totalMinor, - currency: 'ETB', + totalMinor: displayTotalMinor, + currency: displayCurrency, displayCurrency, displayTotalMinor, status: 'PENDING_PAYMENT', diff --git a/apps/edr-passenger-api/src/modules/payments/payments.e2e-spec.ts b/apps/edr-passenger-api/src/modules/payments/payments.e2e-spec.ts index 5393696bf..058b2f9f6 100644 --- a/apps/edr-passenger-api/src/modules/payments/payments.e2e-spec.ts +++ b/apps/edr-passenger-api/src/modules/payments/payments.e2e-spec.ts @@ -118,6 +118,7 @@ describe("Payments E2E", () => { data: { bookingId: booking.id, seatId: seat.id, + scheduleId: schedule.id, passengerName: "Test Passenger", }, }); diff --git a/apps/edr-passenger-api/src/modules/search/search.service.ts b/apps/edr-passenger-api/src/modules/search/search.service.ts index a51dc0142..29be84adc 100644 --- a/apps/edr-passenger-api/src/modules/search/search.service.ts +++ b/apps/edr-passenger-api/src/modules/search/search.service.ts @@ -535,8 +535,8 @@ export class SearchService { discountMinor: fare.discountMinor, taxesFeesMinor: 0, loyaltyRedemptionMinor: loyaltyMinor, - totalMinor, - currency: 'ETB', + totalMinor: displayTotalMinor, + currency: displayCurrency, displayCurrency, displayTotalMinor, }; @@ -653,8 +653,8 @@ export class SearchService { passengers: passengerLines, subtotalMinor, discountMinor, - totalMinor, - currency: 'ETB', + totalMinor: displayTotalMinor, + currency: displayCurrency, displayCurrency, displayTotalMinor, }; diff --git a/apps/edr-passenger-api/src/modules/seats/seats.service.ts b/apps/edr-passenger-api/src/modules/seats/seats.service.ts index 963cc571d..3d87c8331 100644 --- a/apps/edr-passenger-api/src/modules/seats/seats.service.ts +++ b/apps/edr-passenger-api/src/modules/seats/seats.service.ts @@ -1020,7 +1020,7 @@ export class SeatsService { where: { OR: [ { scheduleId: schedule.id }, - { scheduleId: null, booking: { scheduleId: schedule.id } }, + { booking: { scheduleId: schedule.id } }, ], booking: { status: { in: ['CONFIRMED', 'BOARDED'] } }, },