import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { IsNotEmpty, IsString, IsNumber, Min, IsOptional, ValidateNested, } from 'class-validator'; import { Type } from 'class-transformer'; import { RateSearchFiltersDto } from './rate-search-filters.dto'; /** * CSV Rate Search Request DTO * * Request body for searching rates in CSV-based system * Includes basic search parameters + optional advanced filters */ export class CsvRateSearchDto { @ApiProperty({ description: 'Origin port code (UN/LOCODE format)', example: 'NLRTM', pattern: '^[A-Z]{2}[A-Z0-9]{3}$', }) @IsNotEmpty() @IsString() origin: string; @ApiProperty({ description: 'Destination port code (UN/LOCODE format)', example: 'USNYC', pattern: '^[A-Z]{2}[A-Z0-9]{3}$', }) @IsNotEmpty() @IsString() destination: string; @ApiProperty({ description: 'Volume in cubic meters (CBM)', minimum: 0.01, example: 25.5, }) @IsNotEmpty() @IsNumber() @Min(0.01) volumeCBM: number; @ApiProperty({ description: 'Weight in kilograms', minimum: 1, example: 3500, }) @IsNotEmpty() @IsNumber() @Min(1) weightKG: number; @ApiPropertyOptional({ description: 'Number of pallets (0 if no pallets)', minimum: 0, example: 10, default: 0, }) @IsOptional() @IsNumber() @Min(0) palletCount?: number; @ApiPropertyOptional({ description: 'Container type filter (e.g., LCL, 20DRY, 40HC)', example: 'LCL', }) @IsOptional() @IsString() containerType?: string; @ApiPropertyOptional({ description: 'Advanced filters for narrowing results', type: RateSearchFiltersDto, }) @IsOptional() @ValidateNested() @Type(() => RateSearchFiltersDto) filters?: RateSearchFiltersDto; } /** * CSV Rate Search Response DTO * * Response containing matching rates with calculated prices */ export class CsvRateSearchResponseDto { @ApiProperty({ description: 'Array of matching rate results', type: [Object], // Will be replaced with RateResultDto }) results: CsvRateResultDto[]; @ApiProperty({ description: 'Total number of results found', example: 15, }) totalResults: number; @ApiProperty({ description: 'CSV files that were searched', type: [String], example: ['ssc-consolidation.csv', 'ecu-worldwide.csv'], }) searchedFiles: string[]; @ApiProperty({ description: 'Timestamp when search was executed', example: '2025-10-23T10:30:00Z', }) searchedAt: Date; @ApiProperty({ description: 'Filters that were applied to the search', type: RateSearchFiltersDto, }) appliedFilters: RateSearchFiltersDto; } /** * Single CSV Rate Result DTO */ export class CsvRateResultDto { @ApiProperty({ description: 'Company name', example: 'SSC Consolidation', }) companyName: string; @ApiProperty({ description: 'Origin port code', example: 'NLRTM', }) origin: string; @ApiProperty({ description: 'Destination port code', example: 'USNYC', }) destination: string; @ApiProperty({ description: 'Container type', example: 'LCL', }) containerType: string; @ApiProperty({ description: 'Calculated price in USD', example: 1850.50, }) priceUSD: number; @ApiProperty({ description: 'Calculated price in EUR', example: 1665.45, }) priceEUR: number; @ApiProperty({ description: 'Primary currency of the rate', enum: ['USD', 'EUR'], example: 'USD', }) primaryCurrency: string; @ApiProperty({ description: 'Whether this rate has separate surcharges', example: true, }) hasSurcharges: boolean; @ApiProperty({ description: 'Details of surcharges if any', example: 'BAF+CAF included', nullable: true, }) surchargeDetails: string | null; @ApiProperty({ description: 'Transit time in days', example: 28, }) transitDays: number; @ApiProperty({ description: 'Rate validity end date', example: '2025-12-31', }) validUntil: string; @ApiProperty({ description: 'Source of the rate', enum: ['CSV', 'API'], example: 'CSV', }) source: 'CSV' | 'API'; @ApiProperty({ description: 'Match score (0-100) indicating how well this rate matches the search', minimum: 0, maximum: 100, example: 95, }) matchScore: number; }