Seat reservation unique constrains, package totalMinor updates

This commit is contained in:
Stephanos A
2026-07-18 11:30:43 +03:00
parent 0669635095
commit 854177c93b
9 changed files with 46 additions and 8 deletions

View File

@@ -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);

View File

@@ -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")
}

View File

@@ -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

View File

@@ -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,

View File

@@ -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,

View File

@@ -440,8 +440,8 @@ export class PackagesService {
passengerCount,
adultCount,
childCount,
totalMinor,
currency: 'ETB',
totalMinor: displayTotalMinor,
currency: displayCurrency,
displayCurrency,
displayTotalMinor,
status: 'PENDING_PAYMENT',

View File

@@ -118,6 +118,7 @@ describe("Payments E2E", () => {
data: {
bookingId: booking.id,
seatId: seat.id,
scheduleId: schedule.id,
passengerName: "Test Passenger",
},
});

View File

@@ -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,
};

View File

@@ -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'] } },
},