diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d3bcedf2..ce859cb5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Changed + +- Refactored various `lodash` functions with native JavaScript equivalents + ### Fixed - Fixed an issue with the renaming of activities with type `FEE`, `INTEREST`, `ITEM` or `LIABILITY` diff --git a/apps/api/src/app/benchmark/benchmark.service.ts b/apps/api/src/app/benchmark/benchmark.service.ts index a659281d7..4e466668c 100644 --- a/apps/api/src/app/benchmark/benchmark.service.ts +++ b/apps/api/src/app/benchmark/benchmark.service.ts @@ -38,7 +38,7 @@ import { isSameDay, subDays } from 'date-fns'; -import { isNumber, last, uniqBy } from 'lodash'; +import { isNumber, uniqBy } from 'lodash'; import ms from 'ms'; import { BenchmarkValue } from './interfaces/benchmark-value.interface'; @@ -258,7 +258,7 @@ export class BenchmarkService { } const includesEndDate = isSameDay( - parseDate(last(marketData).date), + parseDate(marketData.at(-1).date), endDate ); diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts index eb18b3584..2f8a9f0c9 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts @@ -49,7 +49,7 @@ import { min, subDays } from 'date-fns'; -import { first, isNumber, last, sortBy, sum, uniq, uniqBy } from 'lodash'; +import { isNumber, sortBy, sum, uniq, uniqBy } from 'lodash'; export abstract class PortfolioCalculator { protected static readonly ENABLE_LOGGING = false; @@ -167,7 +167,7 @@ export abstract class PortfolioCalculator { @LogPerformance public async computeSnapshot(): Promise { - const lastTransactionPoint = last(this.transactionPoints); + const lastTransactionPoint = this.transactionPoints.at(-1); const transactionPoints = this.transactionPoints?.filter(({ date }) => { return isBefore(parseDate(date), this.endDate); @@ -772,9 +772,7 @@ export abstract class PortfolioCalculator { let firstActivityDate: Date; try { - const firstAccountBalanceDateString = first( - this.accountBalanceItems - )?.date; + const firstAccountBalanceDateString = this.accountBalanceItems[0]?.date; firstAccountBalanceDate = firstAccountBalanceDateString ? parseDate(firstAccountBalanceDateString) : new Date(); diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts index 37499f0e3..deb3cd72f 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts @@ -19,7 +19,6 @@ import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/po import { parseDate } from '@ghostfolio/common/helper'; import { Big } from 'big.js'; -import { last } from 'lodash'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { @@ -201,7 +200,7 @@ describe('PortfolioCalculator', () => { totalValuablesWithCurrencyEffect: new Big('0') }); - expect(last(portfolioSnapshot.historicalData)).toMatchObject( + expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect.objectContaining({ netPerformance: -15.8, netPerformanceInPercentage: -0.05528341497550734703, diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts index 23c594e5b..7b4d53b2f 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts @@ -19,7 +19,6 @@ import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/po import { parseDate } from '@ghostfolio/common/helper'; import { Big } from 'big.js'; -import { last } from 'lodash'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { @@ -186,7 +185,7 @@ describe('PortfolioCalculator', () => { totalValuablesWithCurrencyEffect: new Big('0') }); - expect(last(portfolioSnapshot.historicalData)).toMatchObject( + expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect.objectContaining({ netPerformance: -15.8, netPerformanceInPercentage: -0.05528341497550734703, diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts index 90f6a59d1..002cbd5e9 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts @@ -19,7 +19,6 @@ import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/po import { parseDate } from '@ghostfolio/common/helper'; import { Big } from 'big.js'; -import { last } from 'lodash'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { @@ -177,7 +176,7 @@ describe('PortfolioCalculator', () => { totalValuablesWithCurrencyEffect: new Big('0') }); - expect(last(portfolioSnapshot.historicalData)).toMatchObject( + expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect.objectContaining({ netPerformance: 23.05, netPerformanceInPercentage: 0.08437042459736457, diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts index e232b42c4..640de3985 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts @@ -20,7 +20,6 @@ import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/po import { parseDate } from '@ghostfolio/common/helper'; import { Big } from 'big.js'; -import { last } from 'lodash'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { @@ -205,7 +204,7 @@ describe('PortfolioCalculator', () => { totalValuablesWithCurrencyEffect: new Big('0') }); - expect(last(portfolioSnapshot.historicalData)).toMatchObject( + expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect.objectContaining({ netPerformance: new Big('27172.74').mul(0.97373).toNumber(), netPerformanceInPercentage: 42.41983590271396609433, diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-fee.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-fee.spec.ts index fe379a92a..6f030a73d 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-fee.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-fee.spec.ts @@ -19,7 +19,6 @@ import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/po import { parseDate } from '@ghostfolio/common/helper'; import { Big } from 'big.js'; -import { last } from 'lodash'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { @@ -158,7 +157,7 @@ describe('PortfolioCalculator', () => { totalValuablesWithCurrencyEffect: new Big('0') }); - expect(last(portfolioSnapshot.historicalData)).toMatchObject( + expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect.objectContaining({ netPerformance: 0, netPerformanceInPercentage: 0, diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts index 60fe6dc6b..4e25c17f7 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts @@ -20,7 +20,6 @@ import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/po import { parseDate } from '@ghostfolio/common/helper'; import { Big } from 'big.js'; -import { last } from 'lodash'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { @@ -184,7 +183,7 @@ describe('PortfolioCalculator', () => { totalValuablesWithCurrencyEffect: new Big('0') }); - expect(last(portfolioSnapshot.historicalData)).toMatchObject( + expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect.objectContaining({ netPerformance: new Big('26.33').mul(0.8854).toNumber(), netPerformanceInPercentage: 0.29544434470377019749, diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-item.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-item.spec.ts index 228568374..7fc5c526d 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-item.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-item.spec.ts @@ -19,7 +19,6 @@ import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/po import { parseDate } from '@ghostfolio/common/helper'; import { Big } from 'big.js'; -import { last } from 'lodash'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { @@ -158,7 +157,7 @@ describe('PortfolioCalculator', () => { totalValuablesWithCurrencyEffect: new Big('0') }); - expect(last(portfolioSnapshot.historicalData)).toMatchObject( + expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect.objectContaining({ netPerformance: 0, netPerformanceInPercentage: 0, diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts index ba1cbeb3c..543985424 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts @@ -20,7 +20,6 @@ import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/po import { parseDate } from '@ghostfolio/common/helper'; import { Big } from 'big.js'; -import { last } from 'lodash'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { return { @@ -190,7 +189,7 @@ describe('PortfolioCalculator', () => { totalValuablesWithCurrencyEffect: new Big('0') }); - expect(last(portfolioSnapshot.historicalData)).toMatchObject( + expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect.objectContaining({ totalInvestmentValueWithCurrencyEffect: 298.58 }) diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts index f9f99ee45..37f22e2f6 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts @@ -21,7 +21,6 @@ import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/po import { parseDate } from '@ghostfolio/common/helper'; import { Big } from 'big.js'; -import { last } from 'lodash'; import { join } from 'path'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { @@ -182,7 +181,7 @@ describe('PortfolioCalculator', () => { totalValuablesWithCurrencyEffect: new Big('0') }); - expect(last(portfolioSnapshot.historicalData)).toMatchObject( + expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect.objectContaining({ netPerformance: 17.68, netPerformanceInPercentage: 0.12184460284330327256, diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts index 66cdb9e8e..caf196f54 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts @@ -21,7 +21,6 @@ import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/po import { parseDate } from '@ghostfolio/common/helper'; import { Big } from 'big.js'; -import { last } from 'lodash'; import { join } from 'path'; jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { @@ -229,7 +228,7 @@ describe('PortfolioCalculator', () => { totalValuablesWithCurrencyEffect: new Big('0') }); - expect(last(portfolioSnapshot.historicalData)).toMatchObject( + expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject( expect.objectContaining({ netPerformance: 19.86, netPerformanceInPercentage: 0.13100263852242744063, diff --git a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts index 3f53ee04b..cf808debb 100644 --- a/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts @@ -13,7 +13,7 @@ import { DateRange } from '@ghostfolio/common/types'; import { Logger } from '@nestjs/common'; import { Big } from 'big.js'; import { addMilliseconds, differenceInDays, format, isBefore } from 'date-fns'; -import { cloneDeep, first, last, sortBy } from 'lodash'; +import { cloneDeep, sortBy } from 'lodash'; export class TWRPortfolioCalculator extends PortfolioCalculator { private chartDates: string[]; @@ -221,7 +221,7 @@ export class TWRPortfolioCalculator extends PortfolioCalculator { }; } - const dateOfFirstTransaction = new Date(first(orders).date); + const dateOfFirstTransaction = new Date(orders[0].date); const endDateString = format(end, DATE_FORMAT); const startDateString = format(start, DATE_FORMAT); @@ -342,7 +342,7 @@ export class TWRPortfolioCalculator extends PortfolioCalculator { }); } - const lastOrder = last(orders); + const lastOrder = orders.at(-1); lastUnitPrice = lastOrder.unitPriceFromMarketData ?? lastOrder.unitPrice; } diff --git a/apps/api/src/app/portfolio/current-rate.service.ts b/apps/api/src/app/portfolio/current-rate.service.ts index ab7bf2ebf..058bf1dd5 100644 --- a/apps/api/src/app/portfolio/current-rate.service.ts +++ b/apps/api/src/app/portfolio/current-rate.service.ts @@ -13,7 +13,7 @@ import type { RequestWithUser } from '@ghostfolio/common/types'; import { Inject, Injectable } from '@nestjs/common'; import { REQUEST } from '@nestjs/core'; import { isBefore, isToday } from 'date-fns'; -import { flatten, isEmpty, uniqBy } from 'lodash'; +import { isEmpty, uniqBy } from 'lodash'; import { GetValueObject } from './interfaces/get-value-object.interface'; import { GetValuesObject } from './interfaces/get-values-object.interface'; @@ -102,7 +102,9 @@ export class CurrentRateService { }) ); - const values = flatten(await Promise.all(promises)); + const values = await Promise.all(promises).then((array) => { + return array.flat(); + }); const response: GetValuesObject = { dataProviderInfos, diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 400b0c3a9..8b295aad4 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -77,7 +77,7 @@ import { parseISO, set } from 'date-fns'; -import { isEmpty, last, uniq } from 'lodash'; +import { isEmpty, uniq } from 'lodash'; import { PortfolioCalculator } from './calculator/portfolio-calculator'; import { @@ -1133,18 +1133,15 @@ export class PortfolioService { netWorth, totalInvestment, valueWithCurrencyEffect - } = - chart?.length > 0 - ? last(chart) - : { - netPerformance: 0, - netPerformanceInPercentage: 0, - netPerformanceInPercentageWithCurrencyEffect: 0, - netPerformanceWithCurrencyEffect: 0, - netWorth: 0, - totalInvestment: 0, - valueWithCurrencyEffect: 0 - }; + } = chart?.at(-1) ?? { + netPerformance: 0, + netPerformanceInPercentage: 0, + netPerformanceInPercentageWithCurrencyEffect: 0, + netPerformanceWithCurrencyEffect: 0, + netWorth: 0, + totalInvestment: 0, + valueWithCurrencyEffect: 0 + }; return { chart,