Merge pull request #748 from Tria-plc/alpha

Alpha
This commit is contained in:
Stephanos A.
2026-07-16 21:53:01 +03:00
committed by GitHub
3 changed files with 26 additions and 4 deletions

View File

@@ -0,0 +1,18 @@
-- Remove duplicate JourneySegment rows, keeping the one with the lowest id
-- (earliest created) per (scheduleId, seatId, departureStationId) group.
-- This cleans up any existing double-bookings before the unique index is applied.
DELETE FROM passenger."JourneySegment"
WHERE id NOT IN (
SELECT MIN(id)
FROM passenger."JourneySegment"
WHERE "seatId" IS NOT NULL
GROUP BY "scheduleId", "seatId", "departureStationId"
)
AND "seatId" IS NOT NULL;
-- Prevents two confirmed bookings from occupying the same seat on the same
-- schedule hop — the hard DB backstop against application-level race conditions.
-- Partial index: seatId IS NOT NULL excludes free-child rows that have no seat.
CREATE UNIQUE INDEX "JourneySegment_scheduleId_seatId_departureStationId_key"
ON passenger."JourneySegment" ("scheduleId", "seatId", "departureStationId")
WHERE "seatId" IS NOT NULL;

View File

@@ -991,6 +991,10 @@ model JourneySegment {
arrivalStationId String
journey Journey @relation(fields: [journeyId], references: [id])
schedule TrainSchedule @relation(fields: [scheduleId], references: [id])
// Prevents two confirmed bookings from occupying the same seat on the same
// schedule hop — the hard DB backstop against application-level race conditions.
@@unique([scheduleId, seatId, departureStationId])
@@schema("passenger")
}

View File

@@ -2,7 +2,7 @@ import { Body, Controller, Get, Param, Post, Query, UseGuards, Delete, Patch, Se
import { ApiTags, ApiOperation, ApiBearerAuth, ApiBody, ApiQuery } from '@nestjs/swagger';
import { TicketsService } from './tickets.service';
import { JwtGuard } from '../../common/jwt.guard';
import { PassengerStaff } from '../../common/passenger-guards';
import { PassengerStaff, PassengerAdmin } from '../../common/passenger-guards';
import { PASSENGER_PERMS } from '../../seed/passenger-permissions.registry';
@ApiTags('Tickets')
@@ -207,9 +207,9 @@ export class TicketsController {
}
@Delete(':id')
@UseGuards(JwtGuard)
@ApiBearerAuth('JWT-auth')
@ApiOperation({
@PassengerAdmin()
@ApiBearerAuth('IAM-auth')
@ApiOperation({
summary: 'Delete ticket (admin only)',
description: 'Permanently deletes a ticket record and removes associated seat blocks'
})