import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { IsOptional, Matches } from 'class-validator'; import { MoneyDto } from '../../../common/money.dto'; import { BrokerageOperationDto } from '../operations/operations.api'; import { InvestmentDependencyDto, InvestmentReadQueryDto, InvestmentResourceMetaDto, } from '../investment-resource.dto'; const dateOnly = /^\d{4}-\d{2}-\d{2}$/; export class IncomeAnalyticsQueryDto extends InvestmentReadQueryDto { @ApiPropertyOptional({ format: 'date', description: 'Inclusive calendar date in Europe/Moscow. Supply both from/to or neither.', }) @IsOptional() @Matches(dateOnly) from?: string; @ApiPropertyOptional({ format: 'date', description: 'Inclusive calendar date in Europe/Moscow, no later than today. Supply both from/to or neither.', }) @IsOptional() @Matches(dateOnly) to?: string; } export class IncomePeriodDto { @ApiProperty({ format: 'date' }) declare from: string; @ApiProperty({ format: 'date' }) declare to: string; } export class IncomeCurrencySummaryDto { @ApiProperty() declare currency: string; @ApiProperty({ type: MoneyDto }) declare coupon: MoneyDto; @ApiProperty({ type: MoneyDto }) declare dividend: MoneyDto; @ApiProperty({ type: MoneyDto }) declare total: MoneyDto; } export class IncomeSummaryDto { @ApiProperty() declare accountId: string; @ApiProperty({ type: IncomePeriodDto }) declare period: IncomePeriodDto; @ApiProperty({ type: IncomeCurrencySummaryDto, isArray: true }) declare totalsByCurrency: IncomeCurrencySummaryDto[]; @ApiProperty({ format: 'date-time' }) declare calculatedAt: string; } export class IncomeComparisonCurrencyDto { @ApiProperty() declare currency: string; @ApiProperty({ type: IncomeCurrencySummaryDto }) declare selected: IncomeCurrencySummaryDto; @ApiProperty({ type: IncomeCurrencySummaryDto }) declare compared: IncomeCurrencySummaryDto; @ApiProperty({ type: IncomeCurrencySummaryDto }) declare difference: IncomeCurrencySummaryDto; } export class IncomeComparisonDto { @ApiProperty({ type: IncomePeriodDto }) declare period: IncomePeriodDto; @ApiProperty({ type: IncomeComparisonCurrencyDto, isArray: true }) declare totalsByCurrency: IncomeComparisonCurrencyDto[]; } export class IncomeBucketDto { @ApiProperty({ type: IncomePeriodDto }) declare period: IncomePeriodDto; @ApiProperty({ type: IncomeCurrencySummaryDto, isArray: true }) declare totalsByCurrency: IncomeCurrencySummaryDto[]; } export class IncomeInstrumentDto { @ApiProperty() declare key: string; @ApiProperty({ type: String, nullable: true }) declare figi: string | null; @ApiProperty({ type: String, nullable: true }) declare instrumentUid: string | null; @ApiProperty({ type: String, nullable: true }) declare ticker: string | null; @ApiProperty({ type: String, nullable: true }) declare instrumentType: string | null; @ApiProperty() declare displayName: string; @ApiProperty({ type: MoneyDto }) declare coupon: MoneyDto; @ApiProperty({ type: MoneyDto }) declare dividend: MoneyDto; @ApiProperty({ type: MoneyDto }) declare total: MoneyDto; @ApiProperty() declare receiptCount: number; } export class IncomeAnalyticsEntryDto extends BrokerageOperationDto { @ApiProperty() declare instrumentKey: string; } export class IncomeAnalyticsDto extends IncomeSummaryDto { @ApiProperty({ type: IncomeComparisonDto, nullable: true }) declare previous: IncomeComparisonDto | null; @ApiProperty({ type: IncomeComparisonDto, nullable: true }) declare yearComparison: IncomeComparisonDto | null; @ApiProperty({ enum: ['day', 'week', 'month'] }) declare bucketGranularity: 'day' | 'week' | 'month'; @ApiProperty({ type: IncomeBucketDto, isArray: true }) declare buckets: IncomeBucketDto[]; @ApiProperty({ type: IncomeInstrumentDto, isArray: true }) declare instruments: IncomeInstrumentDto[]; @ApiProperty({ type: IncomeAnalyticsEntryDto, isArray: true }) declare entries: IncomeAnalyticsEntryDto[]; } export class IncomeSummaryResourceDto { @ApiProperty({ type: IncomeSummaryDto, nullable: true }) declare data: IncomeSummaryDto | null; @ApiProperty({ type: InvestmentResourceMetaDto }) declare meta: InvestmentResourceMetaDto; } const incomeDependencyRoles = ['selected', 'previous', 'year'] as const; export class IncomeDependencyDto extends InvestmentDependencyDto { @ApiProperty({ enum: incomeDependencyRoles }) declare role: (typeof incomeDependencyRoles)[number]; } export class IncomeAnalyticsMetaDto extends InvestmentResourceMetaDto { @ApiProperty({ type: IncomeDependencyDto, isArray: true, required: true, description: 'Dependencies identified by role, not array order or resourceKey. A missing role is unavailable.', }) declare dependencies: IncomeDependencyDto[]; } export class IncomeAnalyticsResourceDto { @ApiProperty({ type: IncomeAnalyticsDto, nullable: true }) declare data: IncomeAnalyticsDto | null; @ApiProperty({ type: IncomeAnalyticsMetaDto }) declare meta: IncomeAnalyticsMetaDto; }