diff --git a/apps/api/src/app/portfolio/interfaces/portfolio-position-detail.interface.ts b/apps/api/src/app/portfolio/interfaces/portfolio-position-detail.interface.ts index 4d13a1ae3..8a2721324 100644 --- a/apps/api/src/app/portfolio/interfaces/portfolio-position-detail.interface.ts +++ b/apps/api/src/app/portfolio/interfaces/portfolio-position-detail.interface.ts @@ -7,6 +7,8 @@ import { Tag } from '@prisma/client'; export interface PortfolioPositionDetail { averagePrice: number; + dividendInBaseCurrency: number; + feesInBaseCurrency: number; firstBuyDate: string; grossPerformance: number; grossPerformancePercent: number; diff --git a/apps/api/src/app/portfolio/portfolio-calculator.ts b/apps/api/src/app/portfolio/portfolio-calculator.ts index 9c659c167..8edd552b7 100644 --- a/apps/api/src/app/portfolio/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/portfolio-calculator.ts @@ -431,6 +431,7 @@ export class PortfolioCalculator { : item.investment.div(item.quantity), currency: item.currency, dataSource: item.dataSource, + fees: item.fee, firstBuyDate: item.firstBuyDate, grossPerformance: !hasErrors ? grossPerformance ?? null : null, grossPerformancePercentage: !hasErrors diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index bce6de674..9aefdff64 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -24,7 +24,7 @@ import { MAX_CHART_ITEMS, UNKNOWN_KEY } from '@ghostfolio/common/config'; -import { DATE_FORMAT, parseDate } from '@ghostfolio/common/helper'; +import { DATE_FORMAT, getSum, parseDate } from '@ghostfolio/common/helper'; import { Accounts, EnhancedSymbolProfile, @@ -680,6 +680,8 @@ export class PortfolioService { return { tags, averagePrice: undefined, + dividendInBaseCurrency: undefined, + feesInBaseCurrency: undefined, firstBuyDate: undefined, grossPerformance: undefined, grossPerformancePercent: undefined, @@ -746,12 +748,23 @@ export class PortfolioService { averagePrice, currency, dataSource, + fees, firstBuyDate, marketPrice, quantity, transactionCount } = position; + const dividendInBaseCurrency = getSum( + orders + .filter(({ type }) => { + return type === 'DIVIDEND'; + }) + .map(({ valueInBaseCurrency }) => { + return new Big(valueInBaseCurrency); + }) + ); + // Convert investment, gross and net performance to currency of user const investment = this.exchangeRateDataService.toCurrency( position.investment?.toNumber(), @@ -838,6 +851,12 @@ export class PortfolioService { tags, transactionCount, averagePrice: averagePrice.toNumber(), + dividendInBaseCurrency: dividendInBaseCurrency.toNumber(), + feesInBaseCurrency: this.exchangeRateDataService.toCurrency( + fees.toNumber(), + SymbolProfile.currency, + userCurrency + ), grossPerformancePercent: position.grossPerformancePercentage?.toNumber(), historicalData: historicalDataArray, @@ -894,6 +913,8 @@ export class PortfolioService { SymbolProfile, tags, averagePrice: 0, + dividendInBaseCurrency: 0, + feesInBaseCurrency: 0, firstBuyDate: undefined, grossPerformance: undefined, grossPerformancePercent: undefined, diff --git a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.ts b/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.ts index fef9011d3..c2fa4721f 100644 --- a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.ts +++ b/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.component.ts @@ -37,6 +37,8 @@ export class PositionDetailDialog implements OnDestroy, OnInit { public countries: { [code: string]: { name: string; value: number }; }; + public dividendInBaseCurrency: number; + public feesInBaseCurrency: number; public firstBuyDate: string; public grossPerformance: number; public grossPerformancePercent: number; @@ -78,6 +80,8 @@ export class PositionDetailDialog implements OnDestroy, OnInit { .subscribe( ({ averagePrice, + dividendInBaseCurrency, + feesInBaseCurrency, firstBuyDate, grossPerformance, grossPerformancePercent, @@ -98,7 +102,8 @@ export class PositionDetailDialog implements OnDestroy, OnInit { this.averagePrice = averagePrice; this.benchmarkDataItems = []; this.countries = {}; - this.reportDataGlitchMail = `mailto:hi@ghostfol.io?Subject=Ghostfolio Data Glitch Report&body=Hello%0D%0DI would like to report a data glitch for%0D%0DSymbol: ${SymbolProfile?.symbol}%0DData Source: ${SymbolProfile?.dataSource}%0D%0DAdditional notes:%0D%0DCan you please take a look?%0D%0DKind regards`; + this.dividendInBaseCurrency = dividendInBaseCurrency; + this.feesInBaseCurrency = feesInBaseCurrency; this.firstBuyDate = firstBuyDate; this.grossPerformance = grossPerformance; this.grossPerformancePercent = grossPerformancePercent; @@ -123,6 +128,7 @@ export class PositionDetailDialog implements OnDestroy, OnInit { this.netPerformancePercent = netPerformancePercent; this.orders = orders; this.quantity = quantity; + this.reportDataGlitchMail = `mailto:hi@ghostfol.io?Subject=Ghostfolio Data Glitch Report&body=Hello%0D%0DI would like to report a data glitch for%0D%0DSymbol: ${SymbolProfile?.symbol}%0DData Source: ${SymbolProfile?.dataSource}%0D%0DAdditional notes:%0D%0DCan you please take a look?%0D%0DKind regards`; this.sectors = {}; this.SymbolProfile = SymbolProfile; this.tags = tags.map(({ id, name }) => { diff --git a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html b/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html index c888ab9be..7c63fbe59 100644 --- a/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html +++ b/apps/client/src/app/components/position/position-detail-dialog/position-detail-dialog.html @@ -119,6 +119,26 @@ >Investment +