refactor: replace ignored numeric literals with constants
This commit is contained in:
@@ -12,6 +12,8 @@ import {
|
||||
StockSearchResourceDto,
|
||||
} from '../presentation/stock.dto';
|
||||
|
||||
const MIN_LOT_EXCLUSIVE = 0;
|
||||
|
||||
type IdentifiedShare = TbankShare & { uid: string };
|
||||
|
||||
@Injectable()
|
||||
@@ -102,7 +104,7 @@ function stock(share: IdentifiedShare): StockDto {
|
||||
currency: share.currency?.toUpperCase() || null,
|
||||
shareType: share.shareType || null,
|
||||
sector: share.sector || null,
|
||||
lot: share.lot && share.lot > 0 ? share.lot : null,
|
||||
lot: share.lot && share.lot > MIN_LOT_EXCLUSIVE ? share.lot : null,
|
||||
historyFrom: timestamp(share.first_1dayCandleDate),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
formatDecimal,
|
||||
multiply,
|
||||
} from '../../../../../common/decimal';
|
||||
import { ISO_DATE_LENGTH, ISO_DATE_START } from '../../../../../common/time';
|
||||
import { decimal } from '../../../../../integrations/tbank/decimal';
|
||||
import {
|
||||
TbankAccessService,
|
||||
@@ -23,6 +24,10 @@ import {
|
||||
StockDividendsResourceDto,
|
||||
StockPositionDto,
|
||||
} from '../presentation/stock.dto';
|
||||
|
||||
const INCOME_FORECAST_YEARS = 1;
|
||||
const ZERO_QUANTITY = 0n;
|
||||
|
||||
const ISO_YEAR_LENGTH = 4;
|
||||
const INCOME_HISTORY_YEARS = 5;
|
||||
@Injectable()
|
||||
@@ -49,8 +54,8 @@ export class StockIncomeService {
|
||||
): Promise<StockDividendsResourceDto> {
|
||||
const connection = await this.access.local(userId);
|
||||
const today = moscowDay(new Date().toISOString());
|
||||
const from = `${Number(today.slice(0, ISO_YEAR_LENGTH)) - INCOME_HISTORY_YEARS}${today.slice(ISO_YEAR_LENGTH)}`;
|
||||
const to = `${Number(today.slice(0, ISO_YEAR_LENGTH)) + 1}${today.slice(ISO_YEAR_LENGTH)}`;
|
||||
const from = `${Number(today.slice(ISO_DATE_START, ISO_YEAR_LENGTH)) - INCOME_HISTORY_YEARS}${today.slice(ISO_YEAR_LENGTH)}`;
|
||||
const to = `${Number(today.slice(ISO_DATE_START, ISO_YEAR_LENGTH)) + INCOME_FORECAST_YEARS}${today.slice(ISO_YEAR_LENGTH)}`;
|
||||
const portfolio = await this.portfolios.read(userId, 'all', observe);
|
||||
const sources = await this.sources.readMany(
|
||||
userId,
|
||||
@@ -112,15 +117,15 @@ export function stockDividends(
|
||||
const quantity =
|
||||
position &&
|
||||
position.accounts.length &&
|
||||
position.accounts.every((p) => decimalFromString(p.quantity).value > 0n) ?
|
||||
position.accounts.every((p) => decimalFromString(p.quantity).value > ZERO_QUANTITY) ?
|
||||
decimalFromString(position.quantity) :
|
||||
null;
|
||||
const dividends: StockDividendDto[] = events
|
||||
.filter((event) => event.dividendType?.toLowerCase() !== 'cancelled')
|
||||
.map((event) => {
|
||||
const recordDate = timestamp(event.recordDate)?.slice(0, 10) ?? null;
|
||||
const paymentDate = timestamp(event.paymentDate)?.slice(0, 10) ?? null;
|
||||
const lastBuyDate = timestamp(event.lastBuyDate)?.slice(0, 10) ?? null;
|
||||
const recordDate = timestamp(event.recordDate)?.slice(ISO_DATE_START, ISO_DATE_LENGTH) ?? null;
|
||||
const paymentDate = timestamp(event.paymentDate)?.slice(ISO_DATE_START, ISO_DATE_LENGTH) ?? null;
|
||||
const lastBuyDate = timestamp(event.lastBuyDate)?.slice(ISO_DATE_START, ISO_DATE_LENGTH) ?? null;
|
||||
const currency = event.dividendNet?.currency?.toUpperCase();
|
||||
const perShare =
|
||||
currency && event.dividendNet ?
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
multiply,
|
||||
subtract,
|
||||
} from '../../../../../common/decimal';
|
||||
import { ISO_DATE_LENGTH, ISO_DATE_START } from '../../../../../common/time';
|
||||
import { decimal } from '../../../../../integrations/tbank/decimal';
|
||||
import { CandleService } from '../../application/candle.service';
|
||||
import {
|
||||
@@ -20,6 +21,8 @@ import {
|
||||
StockQuoteResourceDto,
|
||||
} from '../presentation/stock.dto';
|
||||
|
||||
const ZERO_AMOUNT = 0n;
|
||||
|
||||
const CHANGE_PERCENT_DECIMAL_PLACES = 6;
|
||||
@Injectable()
|
||||
export class StockMarketService {
|
||||
@@ -90,7 +93,7 @@ export function stockQuote(
|
||||
price,
|
||||
priceAt,
|
||||
tradingStatus,
|
||||
previousCloseDate: timestamp(previous?.time)?.slice(0, 10) ?? null,
|
||||
previousCloseDate: timestamp(previous?.time)?.slice(ISO_DATE_START, ISO_DATE_LENGTH) ?? null,
|
||||
previousClose: previousPrice,
|
||||
change:
|
||||
difference && currency ?
|
||||
@@ -99,7 +102,7 @@ export function stockQuote(
|
||||
changePercent:
|
||||
difference &&
|
||||
previousPrice &&
|
||||
decimalFromString(previousPrice.value).value > 0n ?
|
||||
decimalFromString(previousPrice.value).value > ZERO_AMOUNT ?
|
||||
formatDecimal(
|
||||
divide(
|
||||
multiply(difference, decimalFromString('100')),
|
||||
|
||||
@@ -10,32 +10,36 @@ import {
|
||||
} from 'class-validator';
|
||||
|
||||
import { MoneyDto } from '../../../../../common/money.dto';
|
||||
import {
|
||||
MAX_INSTRUMENT_QUERY_LENGTH,
|
||||
MIN_INSTRUMENT_QUERY_LENGTH,
|
||||
} from '../../../instrument-query';
|
||||
import {
|
||||
InvestmentReadQueryDto,
|
||||
InvestmentResourceMetaDto,
|
||||
} from '../../../investment-resource.dto';
|
||||
import { PortfolioPositionDto } from '../../../portfolio/portfolio.api';
|
||||
|
||||
const MAX_INSTRUMENT_QUERY_LENGTH = 80;
|
||||
const MIN_TICKER_LENGTH = 1;
|
||||
|
||||
export class StockSearchQueryDto extends InvestmentReadQueryDto {
|
||||
@ApiProperty({ minLength: 2, maxLength: MAX_INSTRUMENT_QUERY_LENGTH })
|
||||
@ApiProperty({ minLength: MIN_INSTRUMENT_QUERY_LENGTH, maxLength: MAX_INSTRUMENT_QUERY_LENGTH })
|
||||
@Transform(({ value }: { value: unknown }) =>
|
||||
typeof value === 'string' ? value.trim() : value,
|
||||
)
|
||||
@IsString()
|
||||
@MinLength(2)
|
||||
@MinLength(MIN_INSTRUMENT_QUERY_LENGTH)
|
||||
@MaxLength(MAX_INSTRUMENT_QUERY_LENGTH)
|
||||
declare query: string;
|
||||
}
|
||||
export class StockTickerParamsDto {
|
||||
@ApiProperty({
|
||||
minLength: 1,
|
||||
minLength: MIN_TICKER_LENGTH,
|
||||
maxLength: MAX_INSTRUMENT_QUERY_LENGTH,
|
||||
pattern: '^[A-Za-z0-9][A-Za-z0-9._@+-]*$',
|
||||
})
|
||||
@IsString()
|
||||
@MinLength(1)
|
||||
@MinLength(MIN_TICKER_LENGTH)
|
||||
@MaxLength(MAX_INSTRUMENT_QUERY_LENGTH)
|
||||
@Matches(/^[A-Z0-9][\w.@+-]*$/i)
|
||||
declare ticker: string;
|
||||
|
||||
Reference in New Issue
Block a user