feat: expose instrument isin in portfolio positions

This commit is contained in:
2026-08-17 13:34:38 +03:00
parent 25d7c5780b
commit 5aa9bd395a
4 changed files with 10 additions and 4 deletions
+3
View File
@@ -41,6 +41,9 @@ export class PortfolioPositionDto {
@ApiProperty({ type: MoneyDto, nullable: true }) @ApiProperty({ type: MoneyDto, nullable: true })
absoluteReturn: MoneyDto | null; absoluteReturn: MoneyDto | null;
@ApiProperty({ type: String, nullable: true })
isin: string | null;
} }
export class PortfolioDto { export class PortfolioDto {
+3 -1
View File
@@ -88,7 +88,7 @@ describe('PortfolioService', () => {
], ],
}); });
tbank.getInstrumentByFigi tbank.getInstrumentByFigi
.mockResolvedValueOnce({ ticker: 'ONE', name: 'Первая позиция' }) .mockResolvedValueOnce({ ticker: 'ONE', name: 'Первая позиция', isin: 'RU000A0JX0J2' })
.mockRejectedValueOnce(new Error('unavailable')); .mockRejectedValueOnce(new Error('unavailable'));
await expect(service.get('user', 'account')).resolves.toMatchObject({ await expect(service.get('user', 'account')).resolves.toMatchObject({
@@ -100,6 +100,7 @@ describe('PortfolioService', () => {
quantity: '2', quantity: '2',
currentValue: { currency: 'RUB', value: '6' }, currentValue: { currency: 'RUB', value: '6' },
absoluteReturn: { currency: 'RUB', value: '2' }, absoluteReturn: { currency: 'RUB', value: '2' },
isin: 'RU000A0JX0J2',
}, },
{ {
figi: 'TWO', figi: 'TWO',
@@ -107,6 +108,7 @@ describe('PortfolioService', () => {
type: 'OTHER', type: 'OTHER',
quantity: '-0.5', quantity: '-0.5',
currentValue: { currency: 'USD', value: '-2' }, currentValue: { currency: 'USD', value: '-2' },
isin: null,
}, },
], ],
cashBalances: [{ currency: 'RUB', value: '1.5' }], cashBalances: [{ currency: 'RUB', value: '1.5' }],
+3 -2
View File
@@ -44,7 +44,7 @@ const types: Record<string, string> = {
type CachedSnapshot = { snapshot: PortfolioDto; storedAt: number }; type CachedSnapshot = { snapshot: PortfolioDto; storedAt: number };
type CachedMetadata = { type CachedMetadata = {
value: { ticker?: string; name?: string } | null; value: { ticker?: string; name?: string; isin?: string } | null;
storedAt: number; storedAt: number;
}; };
@@ -209,6 +209,7 @@ export class PortfolioService {
currentValue, currentValue,
averagePurchasePrice, averagePurchasePrice,
absoluteReturn, absoluteReturn,
isin: metadata?.isin?.trim() || null,
}; };
} }
@@ -236,7 +237,7 @@ export class PortfolioService {
) { ) {
const lookup = async ( const lookup = async (
key: string, key: string,
fetch: () => Promise<{ ticker?: string; name?: string } | null>, fetch: () => Promise<{ ticker?: string; name?: string; isin?: string } | null>,
) => { ) => {
const cached = this.metadata.get(key); const cached = this.metadata.get(key);
if (cached && Date.now() - cached.storedAt <= metadataForMs) if (cached && Date.now() - cached.storedAt <= metadataForMs)
+1 -1
View File
@@ -44,7 +44,7 @@ export type TbankPortfolio = {
}[]; }[];
}; };
export type TbankPositions = { money?: TbankMoney[] }; export type TbankPositions = { money?: TbankMoney[] };
export type TbankInstrument = { ticker?: string; name?: string }; export type TbankInstrument = { ticker?: string; name?: string; isin?: string };
export type TbankTimestamp = { seconds?: string | number; nanos?: number }; export type TbankTimestamp = { seconds?: string | number; nanos?: number };
export type TbankOperationItem = { export type TbankOperationItem = {
cursor?: string; cursor?: string;