feat: expose instrument brand logo name in portfolio positions

This commit is contained in:
2026-08-24 23:41:48 +03:00
parent 2772d53647
commit 5375e5598a
4 changed files with 21 additions and 3 deletions
+3
View File
@@ -44,6 +44,9 @@ export class PortfolioPositionDto {
@ApiProperty({ type: String, nullable: true }) @ApiProperty({ type: String, nullable: true })
isin: string | null; isin: string | null;
@ApiProperty({ type: String, nullable: true })
logoName: string | null;
} }
export class PortfolioDto { export class PortfolioDto {
+4 -1
View File
@@ -92,6 +92,7 @@ describe('PortfolioService', () => {
ticker: 'ONE', ticker: 'ONE',
name: 'Первая позиция', name: 'Первая позиция',
isin: 'RU000A0JX0J2', isin: 'RU000A0JX0J2',
brand: { logoName: 'RU000A0JX0J2x160.png' },
}) })
.mockRejectedValueOnce(new Error('unavailable')); .mockRejectedValueOnce(new Error('unavailable'));
@@ -105,6 +106,7 @@ describe('PortfolioService', () => {
currentValue: { currency: 'RUB', value: '6' }, currentValue: { currency: 'RUB', value: '6' },
absoluteReturn: { currency: 'RUB', value: '2' }, absoluteReturn: { currency: 'RUB', value: '2' },
isin: 'RU000A0JX0J2', isin: 'RU000A0JX0J2',
logoName: 'RU000A0JX0J2x160.png',
}, },
{ {
figi: 'TWO', figi: 'TWO',
@@ -113,6 +115,7 @@ describe('PortfolioService', () => {
quantity: '-0.5', quantity: '-0.5',
currentValue: { currency: 'USD', value: '-2' }, currentValue: { currency: 'USD', value: '-2' },
isin: null, isin: null,
logoName: null,
}, },
], ],
cashBalances: [{ currency: 'RUB', value: '1.5' }], cashBalances: [{ currency: 'RUB', value: '1.5' }],
@@ -137,7 +140,7 @@ describe('PortfolioService', () => {
tbank.getInstrumentByUid.mockResolvedValue({ name: 'Имя по UID' }); tbank.getInstrumentByUid.mockResolvedValue({ name: 'Имя по UID' });
await expect(service.get('user', 'account')).resolves.toMatchObject({ await expect(service.get('user', 'account')).resolves.toMatchObject({
positions: [{ displayName: 'Имя по UID' }], positions: [{ displayName: 'Имя по UID', logoName: null }],
}); });
expect(tbank.getInstrumentByFigi).not.toHaveBeenCalled(); expect(tbank.getInstrumentByFigi).not.toHaveBeenCalled();
}); });
+8 -1
View File
@@ -44,7 +44,12 @@ 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; isin?: string } | null; value: {
ticker?: string;
name?: string;
isin?: string;
brand?: { logoName?: string | null };
} | null;
storedAt: number; storedAt: number;
}; };
@@ -210,6 +215,7 @@ export class PortfolioService {
averagePurchasePrice, averagePurchasePrice,
absoluteReturn, absoluteReturn,
isin: metadata?.isin?.trim() || null, isin: metadata?.isin?.trim() || null,
logoName: metadata?.brand?.logoName?.trim() || null,
}; };
} }
@@ -241,6 +247,7 @@ export class PortfolioService {
ticker?: string; ticker?: string;
name?: string; name?: string;
isin?: string; isin?: string;
brand?: { logoName?: string | null };
} | null>, } | null>,
) => { ) => {
const cached = this.metadata.get(key); const cached = this.metadata.get(key);
+6 -1
View File
@@ -44,7 +44,12 @@ export type TbankPortfolio = {
}[]; }[];
}; };
export type TbankPositions = { money?: TbankMoney[] }; export type TbankPositions = { money?: TbankMoney[] };
export type TbankInstrument = { ticker?: string; name?: string; isin?: string }; export type TbankInstrument = {
ticker?: string;
name?: string;
isin?: string;
brand?: { logoName?: string | null };
};
export type TbankDividend = { export type TbankDividend = {
dividendNet?: TbankMoney; dividendNet?: TbankMoney;
recordDate?: TbankTimestamp; recordDate?: TbankTimestamp;