import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsArray, IsDateString, IsIn, IsInt, IsOptional, IsString, IsUUID, Max, MaxLength, Min, MinLength, ValidateNested, } from 'class-validator'; import { InvestmentResourceMetaDto } from '../investment-resource.dto'; import { operationCategories } from '../operations/operations.api'; const maxAccountIdLength = 256; const maxQueryLength = 80; const maxPageSize = 1000; export const investmentScreens = [ 'accounts', 'account', 'operations', 'income', 'events', 'stocks', 'bonds', 'stock', 'bond', ] as const; export class SyncCandleRangeDto { @ApiProperty({ format: 'date-time' }) @IsDateString() declare from: string; @ApiProperty({ format: 'date-time' }) @IsDateString() declare to: string; } export class InvestmentScreenDto { @ApiProperty({ enum: investmentScreens }) @IsIn(investmentScreens) declare screen: (typeof investmentScreens)[number]; @ApiPropertyOptional() @IsOptional() @IsString() @MinLength(1) @MaxLength(maxAccountIdLength) accountId?: string; @ApiPropertyOptional({ format: 'date-time' }) @IsOptional() @IsDateString({ strict: true }) from?: string; @ApiPropertyOptional({ format: 'date-time' }) @IsOptional() @IsDateString({ strict: true }) to?: string; @ApiPropertyOptional({ format: 'uuid' }) @IsOptional() @IsUUID() instrumentUid?: string; @ApiPropertyOptional() @IsOptional() @IsString() @MinLength(2) @MaxLength(maxQueryLength) query?: string; @ApiPropertyOptional({ enum: ['month', 'halfYear', 'year', 'all'] }) @IsOptional() @IsIn(['month', 'halfYear', 'year', 'all']) candlePeriod?: 'month' | 'halfYear' | 'year' | 'all'; @ApiPropertyOptional({ type: SyncCandleRangeDto }) @IsOptional() @ValidateNested() @Type(() => SyncCandleRangeDto) candleRange?: SyncCandleRangeDto; @ApiPropertyOptional({ enum: operationCategories, isArray: true }) @IsOptional() @IsArray() @IsIn(operationCategories, { each: true }) categories?: (typeof operationCategories)[number][]; @ApiPropertyOptional({ minimum: 1, maximum: maxPageSize }) @IsOptional() @IsInt() @Min(1) @Max(maxPageSize) limit?: number; } export class TbankSyncAcceptedDto { @ApiProperty({ format: 'uuid' }) declare id: string; @ApiProperty({ type: InvestmentScreenDto }) declare scope: InvestmentScreenDto; @ApiProperty({ format: 'date-time' }) declare now: string; } export class TbankSyncProgressDto { @ApiProperty() declare completed: number; @ApiProperty() declare total: number; @ApiProperty() declare discovering: boolean; } export class TbankSyncStatusDto { @ApiProperty({ format: 'uuid' }) declare id: string; @ApiProperty({ type: InvestmentScreenDto, nullable: true }) declare scope: InvestmentScreenDto | null; @ApiProperty({ format: 'date-time' }) declare now: string; @ApiProperty({ enum: ['running', 'succeeded', 'failed', 'cancelled'] }) declare state: 'running' | 'succeeded' | 'failed' | 'cancelled'; @ApiProperty({ type: String, nullable: true }) declare errorCode: string | null; @ApiProperty({ type: TbankSyncProgressDto }) declare progress: TbankSyncProgressDto; @ApiProperty({ type: InvestmentResourceMetaDto, isArray: true }) declare resources: InvestmentResourceMetaDto[]; }