Files
edr-platform/apps/edr-passenger-api/src/modules/seats/seats.dto.ts
2026-08-02 23:08:15 +03:00

96 lines
3.3 KiB
TypeScript

import { IsString, IsArray, ValidateNested, IsOptional, IsEnum } from 'class-validator';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Type } from 'class-transformer';
export enum JourneyDirection {
ONE_WAY = 'ONE_WAY',
OUTBOUND = 'OUTBOUND',
RETURN = 'RETURN'
}
export class PassengerSeatDto {
@ApiProperty({ example: 'passenger-uuid', description: 'Passenger UUID' })
@IsString() passengerId: string;
@ApiProperty({ example: 'seat-uuid', description: 'Seat UUID assigned to this passenger' })
@IsString() seatId: string;
}
export class HoldSeatsDto {
@ApiProperty({ example: 'schedule-uuid', description: 'TrainSchedule UUID' })
@IsString() scheduleId: string;
@ApiProperty({ example: 'station-uuid', description: 'Origin station UUID — scopes the hold to a leg so the seat can be reused on non-overlapping legs' })
@IsString() originStationId: string;
@ApiProperty({ example: 'station-uuid', description: 'Destination station UUID for this leg' })
@IsString() destinationStationId: string;
@ApiPropertyOptional({
enum: JourneyDirection,
example: JourneyDirection.OUTBOUND,
description: 'Journey direction for round-trip bookings. ONE_WAY for single journeys, OUTBOUND/RETURN for round-trip legs. Allows same seats to be held for different directions.'
})
@IsOptional()
@IsEnum(JourneyDirection)
journeyDirection?: JourneyDirection;
@ApiProperty({
type: [PassengerSeatDto],
description: 'One entry per passenger. Each passenger is assigned exactly one seat. Duplicate passengerId or seatId within the same request is rejected.',
example: [
{ passengerId: 'passenger-uuid-1', seatId: 'seat-uuid-1' },
{ passengerId: 'passenger-uuid-2', seatId: 'seat-uuid-2' },
],
})
@IsArray()
@ValidateNested({ each: true })
@Type(() => PassengerSeatDto)
passengers: PassengerSeatDto[];
}
export class ReleaseHoldDto {
@ApiProperty({ example: 'hold-uuid', description: 'SeatHold UUID to release' })
@IsString() holdId: string;
}
/** Coarse bucket for *why* a seat was pulled out of sale — mirrors the Prisma
* `SeatBlockReasonCategory` enum. The free-text `reason` stays the detail. */
export enum SeatBlockReasonCategory {
MAINTENANCE = 'MAINTENANCE',
VIP_RESERVED = 'VIP_RESERVED',
SAFETY = 'SAFETY',
OPERATIONAL = 'OPERATIONAL',
OTHER = 'OTHER',
}
export class BlockSeatDto {
@ApiProperty({
example: 'Torn upholstery — awaiting replacement',
description: 'Free-text detail explaining the block. Shown verbatim in the revenue-loss report.',
})
@IsString() reason: string;
@ApiPropertyOptional({
example: 'schedule-uuid',
description:
'When set, the block applies only to this schedule. Omit for a global block that pulls the seat out of sale on every schedule its coach runs on.',
})
@IsOptional() @IsString() scheduleId?: string;
@ApiPropertyOptional({
enum: SeatBlockReasonCategory,
default: SeatBlockReasonCategory.OTHER,
description:
'Reporting bucket for this block. Defaults to OTHER. Drives the reason-category breakdown in the Blocked Seat Revenue Loss report.',
})
@IsOptional()
@IsEnum(SeatBlockReasonCategory)
reasonCategory?: SeatBlockReasonCategory;
}
export class SetMaintenanceDto {
@ApiProperty({ example: 'Seat recline mechanism jammed' })
@IsString() reason: string;
}