Backend security / security (push) Successful in 8s
Backend verify / verify (push) Failing after 10m45s
Conventional commits / commits (pull_request) Successful in 29s
Backend security / security (pull_request) Successful in 8s
Backend verify / verify (pull_request) Failing after 10m37s
Store account membership, portfolio, operations, forecasts and market sources in SQLite. Coalesce scoped refreshes, fence connection revisions, preserve complete financial snapshots and stabilize operation period state. BREAKING CHANGE: investment reads return data/meta resource envelopes and locally persisted snapshots; consumers must use the matching OpenAPI contract and explicit synchronization endpoints.
158 lines
3.8 KiB
TypeScript
158 lines
3.8 KiB
TypeScript
import {
|
|
InvestmentReadQueryDto,
|
|
InvestmentResourceMetaDto,
|
|
} from '../../investment-resource.dto';
|
|
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
|
import { Transform, Type } from 'class-transformer';
|
|
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';
|
|
|
|
const MAX_CURSOR_LENGTH = 4096;
|
|
const MAX_OPERATIONS_PAGE_SIZE = 1000;
|
|
export const DEFAULT_OPERATIONS_PAGE_SIZE = 100;
|
|
|
|
export const operationCategories = [
|
|
'trade',
|
|
'income',
|
|
'tax',
|
|
'fee',
|
|
'transfer',
|
|
'other',
|
|
] as const;
|
|
export type OperationCategory = (typeof operationCategories)[number];
|
|
|
|
export class BrokerageOperationsQueryDto extends InvestmentReadQueryDto {
|
|
@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(MAX_CURSOR_LENGTH)
|
|
cursor?: string;
|
|
|
|
@ApiPropertyOptional({
|
|
minimum: 1,
|
|
maximum: MAX_OPERATIONS_PAGE_SIZE,
|
|
default: DEFAULT_OPERATIONS_PAGE_SIZE,
|
|
})
|
|
@IsOptional()
|
|
@Type(() => Number)
|
|
@IsInt()
|
|
@Min(1)
|
|
@Max(MAX_OPERATIONS_PAGE_SIZE)
|
|
limit?: number;
|
|
}
|
|
|
|
export class BrokerageOperationDto {
|
|
@ApiPropertyOptional({ type: AccountReferenceDto })
|
|
account?: AccountReferenceDto;
|
|
|
|
@ApiProperty()
|
|
declare id: string;
|
|
|
|
@ApiProperty({ format: 'date-time' })
|
|
declare occurredAt: string;
|
|
|
|
@ApiProperty()
|
|
declare type: string;
|
|
|
|
@ApiProperty({ enum: operationCategories })
|
|
declare category: OperationCategory;
|
|
|
|
@ApiProperty()
|
|
declare description: 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({ type: String, nullable: true })
|
|
declare logoName: string | null;
|
|
|
|
@ApiProperty({ type: MoneyDto, nullable: true })
|
|
declare payment: MoneyDto | null;
|
|
|
|
@ApiProperty({ type: String, nullable: true })
|
|
declare quantity: string | null;
|
|
|
|
@ApiProperty({ type: MoneyDto, nullable: true })
|
|
declare price: MoneyDto | null;
|
|
|
|
@ApiProperty({ type: MoneyDto, nullable: true })
|
|
declare accruedInterest: MoneyDto | null;
|
|
|
|
@ApiProperty({ type: MoneyDto, nullable: true })
|
|
declare commission: MoneyDto | null;
|
|
}
|
|
|
|
export class BrokerageOperationsPageDto {
|
|
@ApiProperty()
|
|
declare accountId: string;
|
|
|
|
@ApiProperty({ type: BrokerageOperationDto, isArray: true })
|
|
declare items: BrokerageOperationDto[];
|
|
|
|
@ApiProperty({ type: String, nullable: true })
|
|
declare nextCursor: string | null;
|
|
|
|
@ApiProperty()
|
|
declare hasNext: boolean;
|
|
|
|
@ApiProperty({ format: 'date-time' })
|
|
declare observedAt: string;
|
|
}
|
|
|
|
export class BrokerageOperationsResourceDto {
|
|
@ApiProperty({ type: BrokerageOperationsPageDto, nullable: true })
|
|
declare data: BrokerageOperationsPageDto | null;
|
|
@ApiProperty({ type: InvestmentResourceMetaDto })
|
|
declare meta: InvestmentResourceMetaDto;
|
|
}
|