Browse Source

Bugfix/value in portfolio performance with expired snapshot (#8378)

* Fix value in portfolio performance with expired snapshot

* Update changelog
pull/8368/head
Thomas Kaul 2 days ago
committed by GitHub
parent
commit
175a059aa8
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      CHANGELOG.md
  2. 3
      apps/api/src/app/portfolio/portfolio.controller.ts
  3. 75
      apps/api/src/app/portfolio/portfolio.service.spec.ts
  4. 20
      apps/api/src/app/portfolio/portfolio.service.ts

4
CHANGELOG.md

@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Upgraded `stripe` from version `23.0.0` to `23.0.1`
### Fixed
- Fixed the value of zero in the portfolio performance for date ranges starting after the end of an expired portfolio snapshot
## 3.96.0 - 2026-10-31
### Added

3
apps/api/src/app/portfolio/portfolio.controller.ts

@ -575,7 +575,8 @@ export class PortfolioController {
'grossPerformanceWithCurrencyEffect',
'netPerformance',
'netPerformanceWithCurrencyEffect',
'totalInvestment'
'totalInvestment',
'totalInvestmentValueWithCurrencyEffect'
]
);
}

75
apps/api/src/app/portfolio/portfolio.service.spec.ts

@ -1202,6 +1202,81 @@ describe('PortfolioService', () => {
{ date: '2025-01-01', investmentValueWithCurrencyEffect: 200 }
]);
});
describe('with an empty chart of the date range', () => {
const historicalData = [
{ date: '2023-03-01' },
{
date: '2025-06-12',
dividendInBaseCurrency: 50,
netPerformance: 600,
netPerformanceInPercentage: 0.6,
netPerformanceInPercentageWithCurrencyEffect: 0.5,
netPerformanceWithCurrencyEffect: 500,
netWorth: 2000,
totalInvestment: 1000,
totalInvestmentValueWithCurrencyEffect: 1100,
valueWithCurrencyEffect: 1600
}
];
beforeEach(() => {
getPerformanceOfCalculator.mockResolvedValueOnce({ chart: [] });
jest
.spyOn(portfolioCalculatorFactory, 'createCalculator')
.mockReturnValue({
getPerformance: getPerformanceOfCalculator,
getSnapshot: jest.fn().mockResolvedValue({
historicalData,
errors: [],
hasErrors: false
})
} as unknown as PortfolioCalculator);
});
it('should return the latest values of the portfolio snapshot without any performance when the portfolio snapshot ends before the date range', async () => {
const { chart, performance } = await portfolioService.getPerformance({
dateRange: '1d',
userId: userDummyData.id
});
expect(chart).toEqual([]);
expect(performance).toEqual({
currentNetWorth: 2000,
currentValueInBaseCurrency: 1600,
dividendInBaseCurrency: 0,
dividendPercentageWithCurrencyEffect: 0,
netPerformance: 0,
netPerformancePercentage: 0,
netPerformancePercentageWithCurrencyEffect: 0,
netPerformanceWithCurrencyEffect: 0,
totalInvestment: 1000,
totalInvestmentValueWithCurrencyEffect: 1100
});
});
it('should return no values when the portfolio snapshot ends after the date range', async () => {
const { chart, performance } = await portfolioService.getPerformance({
dateRange: '2022',
userId: userDummyData.id
});
expect(chart).toEqual([]);
expect(performance).toEqual({
currentNetWorth: 0,
currentValueInBaseCurrency: 0,
dividendInBaseCurrency: 0,
dividendPercentageWithCurrencyEffect: 0,
netPerformance: 0,
netPerformancePercentage: 0,
netPerformancePercentageWithCurrencyEffect: 0,
netPerformanceWithCurrencyEffect: 0,
totalInvestment: 0,
totalInvestmentValueWithCurrencyEffect: 0
});
});
});
});
describe('getSummary', () => {

20
apps/api/src/app/portfolio/portfolio.service.ts

@ -98,6 +98,7 @@ import {
endOfDay,
format,
isAfter,
isBefore,
isSameMonth,
isSameYear,
min,
@ -1234,6 +1235,17 @@ export class PortfolioService {
start: startDate
});
// An expired portfolio snapshot can end before the date range until its
// computation in the background is complete. In this case, the performance
// in the date range is not known, but the latest values are available.
const latestHistoricalDataItem = historicalData.at(-1);
const latestValues =
latestHistoricalDataItem &&
isBefore(parseDate(latestHistoricalDataItem.date), startDate)
? latestHistoricalDataItem
: undefined;
const {
dividendInBaseCurrency,
dividendInPercentageWithCurrencyEffect,
@ -1252,9 +1264,11 @@ export class PortfolioService {
netPerformanceInPercentage: 0,
netPerformanceInPercentageWithCurrencyEffect: 0,
netPerformanceWithCurrencyEffect: 0,
netWorth: 0,
totalInvestment: 0,
valueWithCurrencyEffect: 0
netWorth: latestValues?.netWorth ?? 0,
totalInvestment: latestValues?.totalInvestment ?? 0,
totalInvestmentValueWithCurrencyEffect:
latestValues?.totalInvestmentValueWithCurrencyEffect ?? 0,
valueWithCurrencyEffect: latestValues?.valueWithCurrencyEffect ?? 0
};
const chart =

Loading…
Cancel
Save