import { Transform, Type } from 'class-transformer'; import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { IsArray, IsDateString, IsEnum, IsInt, IsOptional, IsString, IsUUID, Max, MaxLength, Min, } from 'class-validator'; import { MoneyDto } from '../common/money.dto'; import { AccountReferenceDto } from './account-reference.dto'; export const operationCategories = [ 'trade', 'income', 'tax', 'fee', 'transfer', 'other', ] as const; export type OperationCategory = (typeof operationCategories)[number]; export class BrokerageOperationsQueryDto { @ApiPropertyOptional({ format: 'uuid', description: 'Instrument UID. Without from, includes history since the earliest available account opening.', }) @IsOptional() @IsUUID() instrumentUid?: string; @ApiPropertyOptional({ format: 'date-time' }) @IsOptional() @IsDateString() from?: string; @ApiPropertyOptional({ format: 'date-time' }) @IsOptional() @IsDateString() to?: string; @ApiPropertyOptional({ enum: operationCategories, isArray: true }) @IsOptional() @Transform(({ value }: { value: unknown }) => typeof value === 'string' ? value.split(',').filter(Boolean) : value, ) @IsArray() @IsEnum(operationCategories, { each: true }) categories?: OperationCategory[]; @ApiPropertyOptional() @IsOptional() @IsString() @MaxLength(4096) cursor?: string; @ApiPropertyOptional({ minimum: 1, maximum: 1000, default: 100 }) @IsOptional() @Type(() => Number) @IsInt() @Min(1) @Max(1000) limit?: number; } export class BrokerageOperationDto { @ApiPropertyOptional({ type: AccountReferenceDto }) account?: AccountReferenceDto; @ApiProperty() id: string; @ApiProperty({ format: 'date-time' }) occurredAt: string; @ApiProperty() type: string; @ApiProperty({ enum: operationCategories }) category: OperationCategory; @ApiProperty() description: string; @ApiProperty({ type: String, nullable: true }) figi: string | null; @ApiProperty({ type: String, nullable: true }) instrumentUid: string | null; @ApiProperty({ type: String, nullable: true }) ticker: string | null; @ApiProperty({ type: String, nullable: true }) instrumentType: string | null; @ApiProperty({ type: String, nullable: true }) logoName: string | null; @ApiProperty({ type: MoneyDto, nullable: true }) payment: MoneyDto | null; @ApiProperty({ type: String, nullable: true }) quantity: string | null; @ApiProperty({ type: MoneyDto, nullable: true }) price: MoneyDto | null; @ApiProperty({ type: MoneyDto, nullable: true }) accruedInterest: MoneyDto | null; @ApiProperty({ type: MoneyDto, nullable: true }) commission: MoneyDto | null; } export class BrokerageOperationsPageDto { @ApiProperty() accountId: string; @ApiProperty({ type: BrokerageOperationDto, isArray: true }) items: BrokerageOperationDto[]; @ApiProperty({ type: String, nullable: true }) nextCursor: string | null; @ApiProperty() hasNext: boolean; @ApiProperty({ format: 'date-time' }) observedAt: string; }