diff --git a/CHANGELOG.md b/CHANGELOG.md index f8d47dd37..6b8671505 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Fixed + +- Fixed an issue with the exchange rate calculation of (wealth) items in accounts + ## 2.58.0 - 2024-02-27 ### Changed diff --git a/apps/api/src/app/order/interfaces/activities.interface.ts b/apps/api/src/app/order/interfaces/activities.interface.ts index 7c612d464..0f6c0bee8 100644 --- a/apps/api/src/app/order/interfaces/activities.interface.ts +++ b/apps/api/src/app/order/interfaces/activities.interface.ts @@ -7,10 +7,8 @@ export interface Activities { export interface Activity extends OrderWithAccount { error?: ActivityError; - feeInBaseCurrency: number; updateAccountBalance?: boolean; value: number; - valueInBaseCurrency: number; } export interface ActivityError { diff --git a/apps/api/src/app/order/order.service.ts b/apps/api/src/app/order/order.service.ts index a88aa4462..53d388621 100644 --- a/apps/api/src/app/order/order.service.ts +++ b/apps/api/src/app/order/order.service.ts @@ -328,17 +328,7 @@ export class OrderService { return { ...order, - value, - feeInBaseCurrency: this.exchangeRateDataService.toCurrency( - order.fee, - order.SymbolProfile.currency, - userCurrency - ), - valueInBaseCurrency: this.exchangeRateDataService.toCurrency( - value, - order.SymbolProfile.currency, - userCurrency - ) + value }; }); diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 92461dce8..1c4dd039a 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -119,7 +119,7 @@ export class PortfolioService { userId: string; withExcludedAccounts?: boolean; }): Promise { - const where: Prisma.AccountWhereInput = { userId: userId }; + const where: Prisma.AccountWhereInput = { userId }; const accountFilter = filters?.find(({ type }) => { return type === 'ACCOUNT'; @@ -227,18 +227,24 @@ export class PortfolioService { impersonationId: string; }): Promise { const userId = await this.getUserId(impersonationId, this.request.user.id); + const user = await this.userService.user({ id: userId }); + const userCurrency = this.getUserCurrency(user); const { activities } = await this.orderService.getOrders({ filters, + userCurrency, userId, - types: ['DIVIDEND'], - userCurrency: this.request.user.Settings.settings.baseCurrency + types: ['DIVIDEND'] }); - let dividends = activities.map((dividend) => { + let dividends = activities.map(({ date, SymbolProfile, value }) => { return { - date: format(dividend.date, DATE_FORMAT), - investment: dividend.valueInBaseCurrency + date: format(date, DATE_FORMAT), + investment: this.exchangeRateDataService.toCurrency( + value, + SymbolProfile.currency, + userCurrency + ) }; }); @@ -762,8 +768,14 @@ export class PortfolioService { .filter(({ type }) => { return type === 'DIVIDEND'; }) - .map(({ valueInBaseCurrency }) => { - return new Big(valueInBaseCurrency); + .map(({ SymbolProfile, value }) => { + return new Big( + this.exchangeRateDataService.toCurrency( + value, + SymbolProfile.currency, + userCurrency + ) + ); }) ); @@ -1992,7 +2004,7 @@ export class PortfolioService { withExcludedAccounts = false }: { filters?: Filter[]; - orders: OrderWithAccount[]; + orders: Activity[]; portfolioItemsNow: { [p: string]: TimelinePosition }; userCurrency: string; userId: string; @@ -2088,41 +2100,50 @@ export class PortfolioService { }; } - for (const order of ordersByAccount) { + for (const { + Account, + quantity, + SymbolProfile, + type, + unitPrice + } of ordersByAccount) { + const unitPriceInBaseCurrency = + portfolioItemsNow[SymbolProfile.symbol]?.marketPriceInBaseCurrency ?? + this.exchangeRateDataService.toCurrency( + unitPrice, + SymbolProfile.currency, + userCurrency + ) ?? + 0; + let currentValueOfSymbolInBaseCurrency = - order.quantity * - (portfolioItemsNow[order.SymbolProfile.symbol] - ?.marketPriceInBaseCurrency ?? - order.unitPrice ?? - 0); + quantity * unitPriceInBaseCurrency; - if (order.type === 'LIABILITY' || order.type === 'SELL') { + if (type === 'LIABILITY' || type === 'SELL') { currentValueOfSymbolInBaseCurrency *= -1; } - if (accounts[order.Account?.id || UNKNOWN_KEY]?.valueInBaseCurrency) { - accounts[order.Account?.id || UNKNOWN_KEY].valueInBaseCurrency += + if (accounts[Account?.id || UNKNOWN_KEY]?.valueInBaseCurrency) { + accounts[Account?.id || UNKNOWN_KEY].valueInBaseCurrency += currentValueOfSymbolInBaseCurrency; } else { - accounts[order.Account?.id || UNKNOWN_KEY] = { + accounts[Account?.id || UNKNOWN_KEY] = { balance: 0, - currency: order.Account?.currency, + currency: Account?.currency, name: account.name, valueInBaseCurrency: currentValueOfSymbolInBaseCurrency }; } if ( - platforms[order.Account?.Platform?.id || UNKNOWN_KEY] - ?.valueInBaseCurrency + platforms[Account?.Platform?.id || UNKNOWN_KEY]?.valueInBaseCurrency ) { - platforms[ - order.Account?.Platform?.id || UNKNOWN_KEY - ].valueInBaseCurrency += currentValueOfSymbolInBaseCurrency; + platforms[Account?.Platform?.id || UNKNOWN_KEY].valueInBaseCurrency += + currentValueOfSymbolInBaseCurrency; } else { - platforms[order.Account?.Platform?.id || UNKNOWN_KEY] = { + platforms[Account?.Platform?.id || UNKNOWN_KEY] = { balance: 0, - currency: order.Account?.currency, + currency: Account?.currency, name: account.Platform?.name, valueInBaseCurrency: currentValueOfSymbolInBaseCurrency };