From 62e3f70d24241e0068ac50fba0218727e28f9a24 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 12 Oct 2026 19:49:52 +0200 Subject: [PATCH] Bugfix/start date of investment timeline (#8122) * Fix start date of investment timeline * Update changelog --- CHANGELOG.md | 1 + .../app/portfolio/portfolio.service.spec.ts | 46 ++++++++++++++++++- .../src/app/portfolio/portfolio.service.ts | 3 +- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f04aa58104..e2fc877bc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Fixed the border color of the drop area in the import activities dialog (dark mode) +- Fixed the start date of the investment timeline chart on the analysis page - Fixed the matching of assets and accounts in the import of activities with _Ghostfolio AI_ (experimental) - Fixed an issue where the update of an activity could change the asset class and asset sub class of an asset profile which does not belong to the user diff --git a/apps/api/src/app/portfolio/portfolio.service.spec.ts b/apps/api/src/app/portfolio/portfolio.service.spec.ts index ac5dfebd49..a043a10309 100644 --- a/apps/api/src/app/portfolio/portfolio.service.spec.ts +++ b/apps/api/src/app/portfolio/portfolio.service.spec.ts @@ -23,7 +23,7 @@ import { Filter, PortfolioSummary } from '@ghostfolio/common/interfaces'; -import { AccountWithBalance } from '@ghostfolio/common/types'; +import { AccountWithBalance, DateRange } from '@ghostfolio/common/types'; import { AssetClass, DataSource, Prisma } from '@prisma/client'; import { Big } from 'big.js'; @@ -842,6 +842,50 @@ describe('PortfolioService', () => { }); }); + describe('getInvestments', () => { + afterEach(() => { + jest.useRealTimers(); + }); + + it.each(['2025', 'ytd'] as DateRange[])( + 'should exclude the investment of the start date of the date range %s', + async (dateRange) => { + jest.useFakeTimers().setSystemTime(parseDate('2025-06-15').getTime()); + + jest + .spyOn(activitiesService, 'getActivitiesForPortfolioCalculator') + .mockResolvedValue({ activities: [{} as Activity], count: 1 }); + + jest + .spyOn(portfolioCalculatorFactory, 'createCalculator') + .mockReturnValue({ + getSnapshot: jest.fn().mockResolvedValue({ + historicalData: [ + { date: '2024-12-31', investmentValueWithCurrencyEffect: 100 }, + { date: '2025-01-01', investmentValueWithCurrencyEffect: 200 } + ] + }) + } as unknown as PortfolioCalculator); + + jest.spyOn(userService, 'user').mockResolvedValue({ + id: userDummyData.id, + settings: { + settings: { + baseCurrency: 'CHF' + } + } + } as unknown as Awaited>); + + const { investments } = await portfolioService.getInvestments({ + dateRange, + userId: userDummyData.id + }); + + expect(investments).toEqual([{ date: '2025-01-01', investment: 200 }]); + } + ); + }); + describe('getPerformance', () => { let getPerformanceOfCalculator: jest.Mock; diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index c67bb51064..ebd05805f5 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -98,7 +98,6 @@ import { endOfDay, format, isAfter, - isBefore, isSameMonth, isSameYear, min, @@ -564,7 +563,7 @@ export class PortfolioService { const date = resetHours(parseDate(historicalDataItem.date)); return ( - !isBefore(date, resetHours(startDate)) && + isAfter(date, resetHours(startDate)) && !isAfter(date, resetHours(endDate)) ); });