Round trip booking and additional enhancements

This commit is contained in:
Stephanos A
2026-06-17 13:42:20 +03:00
parent 81a9c614b7
commit 24ee3b88f5
22 changed files with 502 additions and 205 deletions

View File

@@ -1,5 +1,5 @@
import { Body, Controller, Get, Param, Post, Query, UseGuards, Delete, Patch } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
import { ApiTags, ApiOperation, ApiBearerAuth, ApiBody, ApiQuery } from '@nestjs/swagger';
import { TicketsService } from './tickets.service';
import { JwtGuard } from '../../common/jwt.guard';
@@ -30,6 +30,10 @@ export class TicketsController {
@UseGuards(JwtGuard)
@ApiBearerAuth('JWT-auth')
@ApiOperation({ summary: 'List all tickets with optional filters' })
@ApiQuery({ name: 'search', required: false })
@ApiQuery({ name: 'status', required: false, description: 'ACTIVE | USED | CANCELLED' })
@ApiQuery({ name: 'skip', required: false })
@ApiQuery({ name: 'take', required: false })
listTickets(
@Query('search') search?: string,
@Query('status') status?: string,
@@ -77,14 +81,26 @@ export class TicketsController {
@ApiBearerAuth('JWT-auth')
@ApiOperation({
summary: 'Validate ticket at gate with audit logging',
description: 'Validates ticket QR/barcode at station gate. 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.'
})
@ApiBody({
schema: {
type: 'object',
required: ['validatorId'],
properties: {
validatorId: { type: 'string', example: 'agent-uuid' },
gateId: { type: 'string', example: 'gate-01' },
leg: { type: 'string', enum: ['OUTBOUND', 'RETURN'], description: 'Required for round-trip bookings' },
},
},
})
validate(
@Param('bookingRef') ref: string,
@Body('validatorId') validatorId: string,
@Body('gateId') gateId?: string
@Body('gateId') gateId?: string,
@Body('leg') leg?: 'OUTBOUND' | 'RETURN',
) {
return this.service.validate(ref, validatorId, gateId);
return this.service.validate(ref, validatorId, gateId, leg);
}
@Get(':ticketId/validation-logs')
@@ -106,7 +122,31 @@ export class TicketsController {
@Post('validate/offline')
@UseGuards(JwtGuard)
@ApiBearerAuth('JWT-auth')
@ApiOperation({ summary: 'Batch import offline validations' })
@ApiOperation({
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.'
})
@ApiBody({
schema: {
type: 'object',
properties: {
validations: {
type: 'array',
items: {
type: 'object',
required: ['bookingRef', 'validatorId', 'validatedAt'],
properties: {
bookingRef: { type: 'string' },
validatorId: { type: 'string' },
gateId: { type: 'string' },
validatedAt: { type: 'string', format: 'date-time' },
leg: { type: 'string', enum: ['OUTBOUND', 'RETURN'] },
},
},
},
},
},
})
validateOfflineBatch(@Body() body: { validations: any[] }) {
return this.service.validateOfflineBatch(body.validations);
}