90 lines
2.5 KiB
TypeScript
90 lines
2.5 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
|
|
|
import type { TbankFundamentals } from '../../../../../integrations/tbank/tbank.api';
|
|
|
|
import { CatalogEnrichmentService } from '../../application/catalog-enrichment.service';
|
|
import {
|
|
StockCompanyResourceDto,
|
|
StockMetricDto,
|
|
} from '../presentation/stock.dto';
|
|
@Injectable()
|
|
export class GetStockCompanyUseCase {
|
|
constructor(private readonly sources: CatalogEnrichmentService) {}
|
|
async execute(
|
|
userId: string,
|
|
uid: string,
|
|
observe = false,
|
|
): Promise<StockCompanyResourceDto> {
|
|
const result = await this.sources.section(
|
|
userId,
|
|
'share',
|
|
uid,
|
|
'company',
|
|
observe,
|
|
);
|
|
return {
|
|
data: result.values.instrument
|
|
? {
|
|
description: result.values.description ?? null,
|
|
metrics: metrics(
|
|
result.values.fundamentals ?? null,
|
|
result.values.instrument.sector,
|
|
),
|
|
unavailable: result.unavailable,
|
|
observedAt: result.observedAt,
|
|
}
|
|
: null,
|
|
meta: result.meta,
|
|
};
|
|
}
|
|
}
|
|
export function metrics(
|
|
values: null | TbankFundamentals,
|
|
sector?: string,
|
|
): StockMetricDto[] {
|
|
if (!values) return [];
|
|
const bank = sector?.toLowerCase() === 'financial';
|
|
const selection: [
|
|
keyof TbankFundamentals,
|
|
StockMetricDto['unit'],
|
|
StockMetricDto['period'],
|
|
][] = [
|
|
['marketCapitalization', 'money', null],
|
|
['peRatioTtm', 'ratio', 'TTM'],
|
|
...(bank
|
|
? ([
|
|
['priceToBookTtm', 'ratio', 'TTM'],
|
|
['roe', 'percent', null],
|
|
] as typeof selection)
|
|
: ([
|
|
['revenueTtm', 'money', 'TTM'],
|
|
['ebitdaTtm', 'money', 'TTM'],
|
|
] as typeof selection)),
|
|
['netIncomeTtm', 'money', 'TTM'],
|
|
...(!bank
|
|
? ([
|
|
['totalDebtMrq', 'money', 'MRQ'],
|
|
['netDebtToEbitda', 'ratio', null],
|
|
] as typeof selection)
|
|
: []),
|
|
];
|
|
return selection.flatMap(([key, unit, period]) => {
|
|
// eslint-disable-next-line security/detect-object-injection -- Keys come from the fixed metric selection declared above.
|
|
const value = values[key];
|
|
const currency = values.currency?.toUpperCase() || null;
|
|
return typeof value === 'number' &&
|
|
Number.isFinite(value) &&
|
|
(unit !== 'money' || currency)
|
|
? [
|
|
{
|
|
key,
|
|
value,
|
|
unit,
|
|
period,
|
|
currency: unit === 'money' ? currency : null,
|
|
},
|
|
]
|
|
: [];
|
|
});
|
|
}
|