From e80b8669dfd8249701d2588e27ce8a5cf5400f38 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Wed, 27 Mar 2024 20:56:52 +0100 Subject: [PATCH] Refactoring --- .../src/app/benchmark/benchmark.service.ts | 33 +++++--- .../src/app/portfolio/current-rate.service.ts | 4 +- .../src/app/portfolio/portfolio-calculator.ts | 33 +++++--- libs/common/src/lib/helper.spec.ts | 76 +------------------ libs/common/src/lib/helper.ts | 29 ------- 5 files changed, 46 insertions(+), 129 deletions(-) diff --git a/apps/api/src/app/benchmark/benchmark.service.ts b/apps/api/src/app/benchmark/benchmark.service.ts index f885b0cb6..6f2047210 100644 --- a/apps/api/src/app/benchmark/benchmark.service.ts +++ b/apps/api/src/app/benchmark/benchmark.service.ts @@ -13,7 +13,6 @@ import { import { DATE_FORMAT, calculateBenchmarkTrend, - eachDayOfInterval, parseDate, resetHours } from '@ghostfolio/common/helper'; @@ -29,7 +28,13 @@ import { BenchmarkTrend } from '@ghostfolio/common/types'; import { Injectable, Logger } from '@nestjs/common'; import { SymbolProfile } from '@prisma/client'; import { Big } from 'big.js'; -import { differenceInDays, format, isSameDay, subDays } from 'date-fns'; +import { + differenceInDays, + eachDayOfInterval, + format, + isSameDay, + subDays +} from 'date-fns'; import { isNumber, last, uniqBy } from 'lodash'; import ms from 'ms'; @@ -210,23 +215,26 @@ export class BenchmarkService { public async getMarketDataBySymbol({ dataSource, - startDate, endDate = new Date(), + startDate, symbol, userCurrency }: { - startDate: Date; endDate?: Date; + startDate: Date; userCurrency: string; } & UniqueAsset): Promise { const marketData: { date: string; value: number }[] = []; const days = differenceInDays(endDate, startDate) + 1; - const dates = eachDayOfInterval({ - start: startDate, - end: endDate, - step: Math.round(days / Math.min(days, MAX_CHART_ITEMS)), - includeEnd: true + const dates = eachDayOfInterval( + { + start: startDate, + end: endDate + }, + { step: Math.round(days / Math.min(days, MAX_CHART_ITEMS)) } + ).map((date) => { + return resetHours(date); }); const [currentSymbolItem, marketDataItems] = await Promise.all([ @@ -301,9 +309,12 @@ export class BenchmarkService { }); } - const includesToday = isSameDay(parseDate(last(marketData).date), endDate); + const includesEndDate = isSameDay( + parseDate(last(marketData).date), + endDate + ); - if (currentSymbolItem?.marketPrice && !includesToday) { + if (currentSymbolItem?.marketPrice && !includesEndDate) { const exchangeRate = exchangeRates[`${currentSymbolItem.currency}${userCurrency}`]?.[ format(endDate, DATE_FORMAT) diff --git a/apps/api/src/app/portfolio/current-rate.service.ts b/apps/api/src/app/portfolio/current-rate.service.ts index f4855329e..712d07e7a 100644 --- a/apps/api/src/app/portfolio/current-rate.service.ts +++ b/apps/api/src/app/portfolio/current-rate.service.ts @@ -34,7 +34,7 @@ export class CurrentRateService { }: GetValuesParams): Promise { const dataProviderInfos: DataProviderInfo[] = []; - const includeToday = + const includesToday = (!dateQuery.lt || isBefore(new Date(), dateQuery.lt)) && (!dateQuery.gte || isBefore(dateQuery.gte, new Date())) && (!dateQuery.in || this.containsToday(dateQuery.in)); @@ -43,7 +43,7 @@ export class CurrentRateService { const quoteErrors: ResponseError['errors'] = []; const today = resetHours(new Date()); - if (includeToday) { + if (includesToday) { promises.push( this.dataProviderService .getQuotes({ items: dataGatheringItems, user: this.request?.user }) diff --git a/apps/api/src/app/portfolio/portfolio-calculator.ts b/apps/api/src/app/portfolio/portfolio-calculator.ts index 5059d312a..4a3d1f07b 100644 --- a/apps/api/src/app/portfolio/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/portfolio-calculator.ts @@ -1,12 +1,7 @@ import { getFactor } from '@ghostfolio/api/helper/portfolio.helper'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; import { IDataGatheringItem } from '@ghostfolio/api/services/interfaces/interfaces'; -import { - DATE_FORMAT, - eachDayOfInterval, - parseDate, - resetHours -} from '@ghostfolio/common/helper'; +import { DATE_FORMAT, parseDate, resetHours } from '@ghostfolio/common/helper'; import { DataProviderInfo, HistoricalDataItem, @@ -23,10 +18,12 @@ import { addDays, addMilliseconds, differenceInDays, + eachDayOfInterval, endOfDay, format, isBefore, isSameDay, + isToday, max, subDays } from 'date-fns'; @@ -207,16 +204,28 @@ export class PortfolioCalculator { const dataGatheringItems: IDataGatheringItem[] = []; const firstIndex = transactionPointsBeforeEndDate.length; - const dates = eachDayOfInterval({ start, end, step, includeEnd: true }); + let dates = eachDayOfInterval({ start, end }, { step }).map((date) => { + return resetHours(date); + }); + + const includesEndDate = isSameDay(last(dates), end); + + if (!includesEndDate) { + dates.push(resetHours(end)); + } if (transactionPointsBeforeEndDate.length > 0) { - for (const item of transactionPointsBeforeEndDate[firstIndex - 1].items) { + for (const { + currency, + dataSource, + symbol + } of transactionPointsBeforeEndDate[firstIndex - 1].items) { dataGatheringItems.push({ - dataSource: item.dataSource, - symbol: item.symbol + dataSource, + symbol }); - currencies[item.symbol] = item.currency; - symbols[item.symbol] = true; + currencies[symbol] = currency; + symbols[symbol] = true; } } diff --git a/libs/common/src/lib/helper.spec.ts b/libs/common/src/lib/helper.spec.ts index bec289306..22a171168 100644 --- a/libs/common/src/lib/helper.spec.ts +++ b/libs/common/src/lib/helper.spec.ts @@ -1,7 +1,4 @@ -import { - eachDayOfInterval, - extractNumberFromString -} from '@ghostfolio/common/helper'; +import { extractNumberFromString } from '@ghostfolio/common/helper'; describe('Helper', () => { describe('Extract number from string', () => { @@ -39,75 +36,4 @@ describe('Helper', () => { expect(extractNumberFromString({ value: 'X' })).toEqual(NaN); }); }); - describe('eachDayOfInterval', () => { - describe('start and end', () => { - const expected = [ - new Date(Date.UTC(2021, 0, 1)), - new Date(Date.UTC(2021, 0, 2)), - new Date(Date.UTC(2021, 0, 3)) - ]; - it('as strings', () => { - const [start, end] = ['2021-01-01', '2021-01-03']; - expect(eachDayOfInterval({ start, end })).toEqual(expected); - }); - it('as numbers', () => { - const [start, end] = [Date.UTC(2021, 0, 1), Date.UTC(2021, 0, 3)]; - expect(eachDayOfInterval({ start, end })).toEqual(expected); - }); - it('as dates', () => { - const [start, end] = [ - new Date(Date.UTC(2021, 0, 1)), - new Date(Date.UTC(2021, 0, 3)) - ]; - expect(eachDayOfInterval({ start, end })).toEqual(expected); - }); - }); - describe('step', () => { - const [start, end] = ['2021-01-01', '2021-01-06']; - it('step size of 2', () => { - const expected = [ - new Date(Date.UTC(2021, 0, 1)), - new Date(Date.UTC(2021, 0, 3)), - new Date(Date.UTC(2021, 0, 5)) - ]; - expect(eachDayOfInterval({ start, end, step: 2 })).toEqual(expected); - }); - it('step size of 4', () => { - const expected = [ - new Date(Date.UTC(2021, 0, 1)), - new Date(Date.UTC(2021, 0, 5)) - ]; - expect(eachDayOfInterval({ start, end, step: 4 })).toEqual(expected); - }); - it('step size of 5', () => { - const expected = [ - new Date(Date.UTC(2021, 0, 1)), - new Date(Date.UTC(2021, 0, 6)) - ]; - expect(eachDayOfInterval({ start, end, step: 5 })).toEqual(expected); - }); - }); - describe('includeEnd', () => { - const [start, end] = ['2021-01-01', '2021-01-06']; - it('end is added', () => { - const expected = [ - new Date(Date.UTC(2021, 0, 1)), - new Date(Date.UTC(2021, 0, 5)), - new Date(Date.UTC(2021, 0, 6)) - ]; - expect( - eachDayOfInterval({ start, end, step: 4, includeEnd: true }) - ).toEqual(expected); - }); - it('end is not duplicated', () => { - const expected = [ - new Date(Date.UTC(2021, 0, 1)), - new Date(Date.UTC(2021, 0, 6)) - ]; - expect( - eachDayOfInterval({ start, end, step: 5, includeEnd: true }) - ).toEqual(expected); - }); - }); - }); }); diff --git a/libs/common/src/lib/helper.ts b/libs/common/src/lib/helper.ts index 209cb43b6..b49589aab 100644 --- a/libs/common/src/lib/helper.ts +++ b/libs/common/src/lib/helper.ts @@ -375,35 +375,6 @@ export function resetHours(aDate: Date) { return new Date(Date.UTC(year, month, day)); } -export function eachDayOfInterval({ - start, - end, - step = 1, - includeEnd = false -}: { - start: Date | string | number; - end: Date | string | number; - step?: number; - includeEnd?: boolean; -}) { - [start, end] = [new Date(start), new Date(end)]; - [start, end] = [resetHours(start), resetHours(end)]; - [start, end] = [start.getTime(), end.getTime()]; - - const DAY_IN_MS = 1000 * 60 * 60 * 24; - const dates: number[] = []; - - for (let date = start; date <= end; date += step * DAY_IN_MS) { - dates.push(date); - } - - if (includeEnd && end !== dates?.[dates.length - 1]) { - dates.push(end); - } - - return dates.map((date) => new Date(date)); -} - export function resolveFearAndGreedIndex(aValue: number) { if (aValue <= 25) { return { emoji: '🥵', key: 'EXTREME_FEAR', text: 'Extreme Fear' };