chore: strengthen backend eslint profile
This commit is contained in:
@@ -1,27 +1,28 @@
|
||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
decimalFromString,
|
||||
formatDecimal,
|
||||
multiply,
|
||||
} from '../../../../../common/decimal';
|
||||
import { decimal } from '../../../../../integrations/tbank/decimal';
|
||||
import {
|
||||
TbankAccessService,
|
||||
type TbankDividend,
|
||||
} from '../../../../../integrations/tbank/tbank.api';
|
||||
import {
|
||||
PortfolioService,
|
||||
ForecastService,
|
||||
PortfolioService,
|
||||
} from '../../../portfolio/portfolio.api';
|
||||
import { CatalogEnrichmentService } from '../../application/catalog-enrichment.service';
|
||||
import { moscowDay, timestamp } from '../../application/instrument-market';
|
||||
import { instrumentPosition } from '../../application/instrument-position';
|
||||
import {
|
||||
StockDividendDto,
|
||||
StockDividendsDto,
|
||||
StockDividendsResourceDto,
|
||||
StockPositionDto,
|
||||
StockDividendDto,
|
||||
} from '../presentation/stock.dto';
|
||||
import { decimal } from '../../../../../integrations/tbank/decimal';
|
||||
const ISO_YEAR_LENGTH = 4;
|
||||
const INCOME_HISTORY_YEARS = 5;
|
||||
@Injectable()
|
||||
@@ -40,6 +41,7 @@ export class StockIncomeService {
|
||||
meta: { ...saved.meta, resourceKey: `stock/position/${uid}` },
|
||||
};
|
||||
}
|
||||
|
||||
async dividends(
|
||||
userId: string,
|
||||
uid: string,
|
||||
@@ -58,21 +60,22 @@ export class StockIncomeService {
|
||||
['detail', 'dividends'],
|
||||
{ from, to },
|
||||
);
|
||||
if (sources[0].meta.availability === 'complete' && !sources[0].instrument)
|
||||
if (sources[0].meta.availability === 'complete' && !sources[0].instrument) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
const events = sources[1].payload?.dividends;
|
||||
const position = portfolio.data
|
||||
? instrumentPosition(portfolio.data, uid, 'STOCK')
|
||||
: null;
|
||||
const projected = events
|
||||
? stockDividends(
|
||||
const position = portfolio.data ?
|
||||
instrumentPosition(portfolio.data, uid, 'STOCK') :
|
||||
null;
|
||||
const projected = events ?
|
||||
stockDividends(
|
||||
events,
|
||||
position,
|
||||
{ from, to, today },
|
||||
sources[1].meta.lastSuccessfulAt ?? new Date().toISOString(),
|
||||
!portfolio.data,
|
||||
)
|
||||
: undefined;
|
||||
) :
|
||||
undefined;
|
||||
const result = await this.forecasts.result({
|
||||
userId,
|
||||
revision: connection.revision,
|
||||
@@ -83,9 +86,9 @@ export class StockIncomeService {
|
||||
candidate:
|
||||
portfolio.data && sources[0].instrument ? projected : undefined,
|
||||
});
|
||||
return result.data || !projected
|
||||
? result
|
||||
: {
|
||||
return result.data || !projected ?
|
||||
result :
|
||||
{
|
||||
data: stockDividends(
|
||||
events ?? [],
|
||||
null,
|
||||
@@ -100,7 +103,7 @@ export class StockIncomeService {
|
||||
|
||||
export function stockDividends(
|
||||
events: TbankDividend[],
|
||||
position: StockPositionDto | null,
|
||||
position: null | StockPositionDto,
|
||||
window: { from: string; to: string; today: string },
|
||||
observedAt: string,
|
||||
positionUnavailable: boolean,
|
||||
@@ -109,9 +112,9 @@ export function stockDividends(
|
||||
const quantity =
|
||||
position &&
|
||||
position.accounts.length &&
|
||||
position.accounts.every((p) => decimalFromString(p.quantity).value > 0n)
|
||||
? decimalFromString(position.quantity)
|
||||
: null;
|
||||
position.accounts.every((p) => decimalFromString(p.quantity).value > 0n) ?
|
||||
decimalFromString(position.quantity) :
|
||||
null;
|
||||
const dividends: StockDividendDto[] = events
|
||||
.filter((event) => event.dividendType?.toLowerCase() !== 'cancelled')
|
||||
.map((event) => {
|
||||
@@ -120,29 +123,29 @@ export function stockDividends(
|
||||
const lastBuyDate = timestamp(event.lastBuyDate)?.slice(0, 10) ?? null;
|
||||
const currency = event.dividendNet?.currency?.toUpperCase();
|
||||
const perShare =
|
||||
currency && event.dividendNet
|
||||
? { currency, value: formatDecimal(decimal(event.dividendNet)) }
|
||||
: null;
|
||||
currency && event.dividendNet ?
|
||||
{ currency, value: formatDecimal(decimal(event.dividendNet)) } :
|
||||
null;
|
||||
// A future payment can have an already-fixed register: keep the event, but do not estimate entitlement from today's holding.
|
||||
const eventDate = paymentDate ?? recordDate;
|
||||
const timing: StockDividendDto['timing'] = eventDate
|
||||
? eventDate >= today
|
||||
? 'upcoming'
|
||||
: 'past'
|
||||
: 'undated';
|
||||
const timing: StockDividendDto['timing'] = eventDate ?
|
||||
eventDate >= today ?
|
||||
'upcoming' :
|
||||
'past' :
|
||||
'undated';
|
||||
const estimatedAmount =
|
||||
quantity &&
|
||||
perShare &&
|
||||
recordDate &&
|
||||
recordDate >= today &&
|
||||
timing === 'upcoming'
|
||||
? {
|
||||
timing === 'upcoming' ?
|
||||
{
|
||||
currency: perShare.currency,
|
||||
value: formatDecimal(
|
||||
multiply(quantity, decimalFromString(perShare.value)),
|
||||
),
|
||||
}
|
||||
: null;
|
||||
} :
|
||||
null;
|
||||
return {
|
||||
perShare,
|
||||
recordDate,
|
||||
|
||||
Reference in New Issue
Block a user