mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-01 20:33:27 +00:00
Introduction of segment-based seat reservation
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
import { Controller, Post, Get, Body, Query, Param } from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';
|
||||
import { EnhancedSeatsService } from './enhanced-seats.service';
|
||||
import { HoldSeatsDto, ConfirmBookingDto, SeatAvailabilityDto, ReleaseSeatsDto } from './segments.dto';
|
||||
|
||||
@ApiTags('Segment-based Seats')
|
||||
@Controller('segments/seats')
|
||||
export class SegmentSeatsController {
|
||||
constructor(private enhancedSeatsService: EnhancedSeatsService) {}
|
||||
|
||||
@Post('hold')
|
||||
@ApiOperation({
|
||||
summary: 'Hold seats for specific journey segments',
|
||||
description: 'Reserve seats for a partial journey (e.g., Addis Ababa → Dire Dawa) with 10-minute expiry'
|
||||
})
|
||||
@ApiResponse({
|
||||
status: 201,
|
||||
description: 'Seats held successfully',
|
||||
schema: {
|
||||
example: {
|
||||
holdId: 'hold_123',
|
||||
expiresAt: '2024-01-15T10:10:00Z',
|
||||
segments: [
|
||||
{ fromName: 'Addis Ababa', toName: 'Adama', fromSequence: 0, toSequence: 1 },
|
||||
{ fromName: 'Adama', toName: 'Awash', fromSequence: 1, toSequence: 2 },
|
||||
{ fromName: 'Awash', toName: 'Dire Dawa', fromSequence: 2, toSequence: 3 }
|
||||
],
|
||||
seats: ['seat_1', 'seat_2']
|
||||
}
|
||||
}
|
||||
})
|
||||
@ApiResponse({ status: 409, description: 'Seats not available for requested segments' })
|
||||
async holdSeats(@Body() dto: HoldSeatsDto) {
|
||||
return this.enhancedSeatsService.holdSeats({
|
||||
tripId: dto.tripId,
|
||||
seatIds: dto.seatIds,
|
||||
passengerId: dto.passengerId,
|
||||
originStationId: dto.originStationId,
|
||||
destinationStationId: dto.destinationStationId,
|
||||
fareQuoteId: dto.fareQuoteId
|
||||
});
|
||||
}
|
||||
|
||||
@Post('confirm')
|
||||
@ApiOperation({
|
||||
summary: 'Confirm booking and convert hold to reservation',
|
||||
description: 'Convert seat hold to confirmed booking after payment success'
|
||||
})
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'Booking confirmed successfully',
|
||||
schema: {
|
||||
example: {
|
||||
bookingId: 'booking_123',
|
||||
confirmedSeats: ['seat_1', 'seat_2'],
|
||||
segments: [
|
||||
{ fromName: 'Addis Ababa', toName: 'Adama' },
|
||||
{ fromName: 'Adama', toName: 'Awash' },
|
||||
{ fromName: 'Awash', toName: 'Dire Dawa' }
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
@ApiResponse({ status: 400, description: 'Hold expired or not found' })
|
||||
async confirmBooking(@Body() dto: ConfirmBookingDto) {
|
||||
return this.enhancedSeatsService.confirmBooking(dto);
|
||||
}
|
||||
|
||||
@Post('release')
|
||||
@ApiOperation({
|
||||
summary: 'Release seats when train reaches station',
|
||||
description: 'Automatically release seats for passengers who have reached their destination'
|
||||
})
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'Seats released successfully',
|
||||
schema: {
|
||||
example: {
|
||||
releasedSeats: ['seat_1', 'seat_2'],
|
||||
stationId: 'st_DRE'
|
||||
}
|
||||
}
|
||||
})
|
||||
async releaseSeats(@Body() dto: ReleaseSeatsDto) {
|
||||
return this.enhancedSeatsService.releaseSeats(dto.tripId, dto.currentStationId);
|
||||
}
|
||||
|
||||
@Get('availability')
|
||||
@ApiOperation({
|
||||
summary: 'Check seat availability for journey segments',
|
||||
description: 'Get available seats for a specific origin-destination pair'
|
||||
})
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'Seat availability retrieved',
|
||||
schema: {
|
||||
example: {
|
||||
segments: [
|
||||
{ fromName: 'Addis Ababa', toName: 'Adama', fromSequence: 0, toSequence: 1 },
|
||||
{ fromName: 'Adama', toName: 'Awash', fromSequence: 1, toSequence: 2 }
|
||||
],
|
||||
availableSeats: [
|
||||
{ id: 'seat_1', label: '1A', coach: 'A', serviceClass: 'ECONOMY', row: 1, col: 'A' },
|
||||
{ id: 'seat_2', label: '1B', coach: 'A', serviceClass: 'ECONOMY', row: 1, col: 'B' }
|
||||
],
|
||||
totalAvailable: 2
|
||||
}
|
||||
}
|
||||
})
|
||||
async getSeatAvailability(@Query() dto: SeatAvailabilityDto) {
|
||||
return this.enhancedSeatsService.getSeatAvailability(
|
||||
dto.tripId,
|
||||
dto.originStationId,
|
||||
dto.destinationStationId
|
||||
);
|
||||
}
|
||||
|
||||
@Post('expire-holds')
|
||||
@ApiOperation({
|
||||
summary: 'Expire old seat holds (background job)',
|
||||
description: 'Release seats from expired holds and make them available'
|
||||
})
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'Expired holds processed',
|
||||
schema: {
|
||||
example: {
|
||||
expiredHolds: 5,
|
||||
releasedSeats: ['seat_1', 'seat_2', 'seat_3']
|
||||
}
|
||||
}
|
||||
})
|
||||
async expireHolds() {
|
||||
return this.enhancedSeatsService.expireHolds();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user