mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 16:28:12 +00:00
Separate ticket generation for portal and back office
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
import { Body, Controller, Get, Param, Post, Query, UseGuards, Delete, Patch, SetMetadata } from '@nestjs/common';
|
import { Body, Controller, Get, Param, Post, Query, UseGuards, Delete, Patch, SetMetadata } from '@nestjs/common';
|
||||||
import { ApiTags, ApiOperation, ApiBearerAuth, ApiBody, ApiQuery } from '@nestjs/swagger';
|
import { ApiTags, ApiOperation, ApiBearerAuth, ApiBody, ApiQuery } from '@nestjs/swagger';
|
||||||
import { TicketsService } from './tickets.service';
|
import { TicketsService } from './tickets.service';
|
||||||
import { JwtGuard } from '../../common/jwt.guard';
|
|
||||||
import { PassengerStaff, PassengerAdmin } from '../../common/passenger-guards';
|
import { PassengerStaff, PassengerAdmin } from '../../common/passenger-guards';
|
||||||
import { PASSENGER_PERMS } from '../../seed/passenger-permissions.registry';
|
import { PASSENGER_PERMS } from '../../seed/passenger-permissions.registry';
|
||||||
|
|
||||||
@@ -24,13 +23,23 @@ export class TicketsController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Post('generate/:bookingId')
|
@Post('generate/:bookingId')
|
||||||
|
@SetMetadata('isPublic', true)
|
||||||
|
@ApiOperation({
|
||||||
|
summary: 'Generate ticket for booking (confirmation page)',
|
||||||
|
description: 'Creates a ticket when confirmation page is reached and permanently holds all associated seats with SeatBlock records. Requires payment to be SUCCEEDED and booking to be CONFIRMED.'
|
||||||
|
})
|
||||||
|
generateTicket(@Param('bookingId') bookingId: string) {
|
||||||
|
return this.service.generate(bookingId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('force-generate/:bookingId')
|
||||||
@PassengerStaff(PASSENGER_PERMS.tickets.generate)
|
@PassengerStaff(PASSENGER_PERMS.tickets.generate)
|
||||||
@ApiBearerAuth('IAM-auth')
|
@ApiBearerAuth('IAM-auth')
|
||||||
@ApiOperation({
|
@ApiOperation({
|
||||||
summary: 'Generate ticket for booking (confirmation page)',
|
summary: 'Force-generate ticket for booking (staff only)',
|
||||||
description: 'Creates a ticket when confirmation page is reached and permanently holds all associated seats with SeatBlock records.'
|
description: 'Staff override: regenerates tickets for a confirmed booking regardless of prior state.'
|
||||||
})
|
})
|
||||||
generateTicket(@Param('bookingId') bookingId: string) {
|
forceGenerateTicket(@Param('bookingId') bookingId: string) {
|
||||||
return this.service.generate(bookingId);
|
return this.service.generate(bookingId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,8 +54,8 @@ export class TicketsController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
@UseGuards(JwtGuard)
|
@PassengerStaff(PASSENGER_PERMS.tickets.generate)
|
||||||
@ApiBearerAuth('JWT-auth')
|
@ApiBearerAuth('IAM-auth')
|
||||||
@ApiOperation({ summary: 'List all tickets with optional filters' })
|
@ApiOperation({ summary: 'List all tickets with optional filters' })
|
||||||
@ApiQuery({ name: 'search', required: false })
|
@ApiQuery({ name: 'search', required: false })
|
||||||
@ApiQuery({ name: 'status', required: false })
|
@ApiQuery({ name: 'status', required: false })
|
||||||
@@ -88,8 +97,8 @@ export class TicketsController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Get('by-order/:merchantOrderId')
|
@Get('by-order/:merchantOrderId')
|
||||||
@UseGuards(JwtGuard)
|
@PassengerStaff(PASSENGER_PERMS.tickets.generate)
|
||||||
@ApiBearerAuth('JWT-auth')
|
@ApiBearerAuth('IAM-auth')
|
||||||
@ApiOperation({
|
@ApiOperation({
|
||||||
summary: 'Get ticket by merchant order ID',
|
summary: 'Get ticket by merchant order ID',
|
||||||
description: 'Looks up the booking ID from the PaymentIntent using merchantOrderId, then returns the full ticket information.'
|
description: 'Looks up the booking ID from the PaymentIntent using merchantOrderId, then returns the full ticket information.'
|
||||||
@@ -106,8 +115,8 @@ export class TicketsController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Post('scan-board/:qrCodeOrRef')
|
@Post('scan-board/:qrCodeOrRef')
|
||||||
@UseGuards(JwtGuard)
|
@PassengerStaff(PASSENGER_PERMS.tickets.generate)
|
||||||
@ApiBearerAuth('JWT-auth')
|
@ApiBearerAuth('IAM-auth')
|
||||||
@ApiOperation({
|
@ApiOperation({
|
||||||
summary: 'Scan QR code or booking ref and automatically board ticket',
|
summary: 'Scan QR code or booking ref and automatically board ticket',
|
||||||
description: 'Scans ticket QR code or booking reference and automatically boards the passenger. Handles errors like expired tickets, already used tickets, etc. Designed for mobile boarding interface.'
|
description: 'Scans ticket QR code or booking reference and automatically boards the passenger. Handles errors like expired tickets, already used tickets, etc. Designed for mobile boarding interface.'
|
||||||
@@ -131,8 +140,8 @@ export class TicketsController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Post(':bookingRef/validate')
|
@Post(':bookingRef/validate')
|
||||||
@UseGuards(JwtGuard)
|
@PassengerStaff(PASSENGER_PERMS.tickets.generate)
|
||||||
@ApiBearerAuth('JWT-auth')
|
@ApiBearerAuth('IAM-auth')
|
||||||
@ApiOperation({
|
@ApiOperation({
|
||||||
summary: 'Validate ticket at gate with audit logging',
|
summary: 'Validate ticket at gate with audit logging',
|
||||||
description: 'Validates ticket QR/barcode at station gate. For round-trip bookings, supply `leg` (OUTBOUND or RETURN) to record which leg is being used. Defaults to OUTBOUND if omitted. Records validation in audit log with timestamp, gate, and validator.'
|
description: 'Validates ticket QR/barcode at station gate. For round-trip bookings, supply `leg` (OUTBOUND or RETURN) to record which leg is being used. Defaults to OUTBOUND if omitted. Records validation in audit log with timestamp, gate, and validator.'
|
||||||
@@ -162,24 +171,24 @@ export class TicketsController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Get(':ticketId/validation-logs')
|
@Get(':ticketId/validation-logs')
|
||||||
@UseGuards(JwtGuard)
|
@PassengerStaff(PASSENGER_PERMS.tickets.generate)
|
||||||
@ApiBearerAuth('JWT-auth')
|
@ApiBearerAuth('IAM-auth')
|
||||||
@ApiOperation({ summary: 'Get validation logs for ticket' })
|
@ApiOperation({ summary: 'Get validation logs for ticket' })
|
||||||
getValidationLogs(@Param('ticketId') ticketId: string) {
|
getValidationLogs(@Param('ticketId') ticketId: string) {
|
||||||
return this.service.getValidationLogs(ticketId);
|
return this.service.getValidationLogs(ticketId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('offline/export')
|
@Get('offline/export')
|
||||||
@UseGuards(JwtGuard)
|
@PassengerStaff(PASSENGER_PERMS.tickets.generate)
|
||||||
@ApiBearerAuth('JWT-auth')
|
@ApiBearerAuth('IAM-auth')
|
||||||
@ApiOperation({ summary: 'Export tickets for offline validation' })
|
@ApiOperation({ summary: 'Export tickets for offline validation' })
|
||||||
exportOfflineData(@Query('scheduleId') scheduleId: string) {
|
exportOfflineData(@Query('scheduleId') scheduleId: string) {
|
||||||
return this.service.exportOfflineData(scheduleId);
|
return this.service.exportOfflineData(scheduleId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('validate/offline')
|
@Post('validate/offline')
|
||||||
@UseGuards(JwtGuard)
|
@PassengerStaff(PASSENGER_PERMS.tickets.generate)
|
||||||
@ApiBearerAuth('JWT-auth')
|
@ApiBearerAuth('IAM-auth')
|
||||||
@ApiOperation({
|
@ApiOperation({
|
||||||
summary: 'Batch import offline validations',
|
summary: 'Batch import offline validations',
|
||||||
description: 'Processes validations collected offline. Each entry may include an optional `leg` field (OUTBOUND | RETURN) for round-trip tickets. Deduplication is per bookingRef+leg combination so both legs of the same booking can be submitted in one batch.'
|
description: 'Processes validations collected offline. Each entry may include an optional `leg` field (OUTBOUND | RETURN) for round-trip tickets. Deduplication is per bookingRef+leg combination so both legs of the same booking can be submitted in one batch.'
|
||||||
@@ -221,8 +230,8 @@ export class TicketsController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id/restore')
|
@Patch(':id/restore')
|
||||||
@UseGuards(JwtGuard)
|
@PassengerStaff(PASSENGER_PERMS.tickets.generate)
|
||||||
@ApiBearerAuth('JWT-auth')
|
@ApiBearerAuth('IAM-auth')
|
||||||
@ApiOperation({ summary: 'Restore a cancelled ticket by resetting its status to ACTIVE' })
|
@ApiOperation({ summary: 'Restore a cancelled ticket by resetting its status to ACTIVE' })
|
||||||
restore(@Param('id') id: string) {
|
restore(@Param('id') id: string) {
|
||||||
return this.service.restore(id);
|
return this.service.restore(id);
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ export const bookingsApi = {
|
|||||||
apiClient.post<any>(`/payments/${bookingId}/force-confirm`, data),
|
apiClient.post<any>(`/payments/${bookingId}/force-confirm`, data),
|
||||||
smartAssign: (bookingId: string) =>
|
smartAssign: (bookingId: string) =>
|
||||||
apiClient.post<any>(`/tickets/smart-assign/${bookingId}`, {}),
|
apiClient.post<any>(`/tickets/smart-assign/${bookingId}`, {}),
|
||||||
|
forceGenerate: (bookingId: string) =>
|
||||||
|
apiClient.post<any>(`/tickets/force-generate/${bookingId}`, {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Passengers API
|
// Passengers API
|
||||||
|
|||||||
Reference in New Issue
Block a user