From 06295c0091aad50599cbd136d1441f1cd1144a92 Mon Sep 17 00:00:00 2001 From: Thomas <4159106+dtslvr@users.noreply.github.com> Date: Sat, 7 Jan 2023 12:21:06 +0100 Subject: [PATCH] Get quantity from position --- apps/api/src/app/import/import.controller.ts | 5 +- apps/api/src/app/import/import.service.ts | 78 +++++++++++++++---- .../src/app/portfolio/portfolio.service.ts | 9 ++- .../historical-data-item.interface.ts | 1 + .../lib/types/account-with-platform.type.ts | 3 + libs/common/src/lib/types/index.ts | 2 + .../src/lib/types/order-with-account.type.ts | 4 +- 7 files changed, 80 insertions(+), 22 deletions(-) create mode 100644 libs/common/src/lib/types/account-with-platform.type.ts diff --git a/apps/api/src/app/import/import.controller.ts b/apps/api/src/app/import/import.controller.ts index e0c4f2760..0df72f463 100644 --- a/apps/api/src/app/import/import.controller.ts +++ b/apps/api/src/app/import/import.controller.ts @@ -90,9 +90,12 @@ export class ImportController { @Param('dataSource') dataSource: DataSource, @Param('symbol') symbol: string ): Promise { + const userCurrency = this.request.user.Settings.settings.baseCurrency; + const result = await this.importService.getDividends({ dataSource, - symbol + symbol, + userCurrency }); if (!result || isEmpty(result)) { diff --git a/apps/api/src/app/import/import.service.ts b/apps/api/src/app/import/import.service.ts index 37845c6c9..49504b1dc 100644 --- a/apps/api/src/app/import/import.service.ts +++ b/apps/api/src/app/import/import.service.ts @@ -8,7 +8,10 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate- import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile.service'; import { parseDate } from '@ghostfolio/common/helper'; import { ImportResponse, UniqueAsset } from '@ghostfolio/common/interfaces'; -import { OrderWithAccount } from '@ghostfolio/common/types'; +import { + AccountWithPlatform, + OrderWithAccount +} from '@ghostfolio/common/types'; import { Injectable } from '@nestjs/common'; import { SymbolProfile } from '@prisma/client'; import Big from 'big.js'; @@ -28,14 +31,18 @@ export class ImportService { public async getDividends({ dataSource, - symbol - }: UniqueAsset): Promise { + symbol, + userCurrency + }: UniqueAsset & { userCurrency: string }): Promise { try { - const { firstBuyDate } = await this.portfolioService.getPosition( - dataSource, - undefined, - symbol - ); + const { firstBuyDate, historicalData, orders } = + await this.portfolioService.getPosition(dataSource, undefined, symbol); + + const accounts = orders.map(({ Account }) => { + return Account; + }); + + const mostFrequentAccount = this.getMostFrequentAccount(accounts); const [[assetProfile], dividends] = await Promise.all([ this.symbolProfileService.getSymbolProfiles([ @@ -55,10 +62,20 @@ export class ImportService { return { activities: Object.entries(dividends).map( - ([dateString, historicalDataItem]) => { + ([dateString, { marketPrice }]) => { + const quantity = + historicalData.find((historicalDataItem) => { + return historicalDataItem.date === dateString; + })?.quantity ?? 0; + + const value = new Big(quantity).mul(marketPrice).toNumber(); + return { - accountId: undefined, - accountUserId: undefined, + quantity, + value, + Account: mostFrequentAccount, + accountId: mostFrequentAccount.id, + accountUserId: mostFrequentAccount.userId, comment: undefined, createdAt: undefined, date: parseDate(dateString), @@ -66,15 +83,17 @@ export class ImportService { feeInBaseCurrency: 0, id: assetProfile.id, isDraft: false, - quantity: 0, SymbolProfile: (assetProfile), - symbolProfileId: undefined, + symbolProfileId: assetProfile.id, type: 'DIVIDEND', - unitPrice: historicalDataItem.marketPrice, + unitPrice: marketPrice, updatedAt: undefined, - userId: undefined, - value: 0, - valueInBaseCurrency: 0 + userId: mostFrequentAccount.userId, + valueInBaseCurrency: this.exchangeRateDataService.toCurrency( + value, + assetProfile.currency, + userCurrency + ) }; } ) @@ -225,6 +244,31 @@ export class ImportService { return activities; } + private getMostFrequentAccount(accounts: AccountWithPlatform[]) { + const accountFrequencyCountMap: { [accountId: string]: number } = {}; + + // Iterate through the array of accounts and increment the frequency for each account + for (const account of accounts) { + accountFrequencyCountMap[account.id] = + (accountFrequencyCountMap[account.id] || 0) + 1; + } + + // Find the account with the highest frequency + let maxFrequencyCount = 0; + let mostFrequentAccount: AccountWithPlatform; + + for (const accountId in accountFrequencyCountMap) { + if (accountFrequencyCountMap[accountId] > maxFrequencyCount) { + mostFrequentAccount = accounts.find( + (account) => account.id === accountId + ); + maxFrequencyCount = accountFrequencyCountMap[accountId]; + } + } + + return mostFrequentAccount; + } + private async validateActivities({ activitiesDto, maxActivitiesToImport, diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 02b95ab54..37fae84d7 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -660,8 +660,9 @@ export class PortfolioService { } const positionCurrency = orders[0].SymbolProfile.currency; - const [SymbolProfile] = - await this.symbolProfileService.getSymbolProfilesBySymbols([aSymbol]); + const [SymbolProfile] = await this.symbolProfileService.getSymbolProfiles([ + { dataSource: aDataSource, symbol: aSymbol } + ]); const portfolioOrders: PortfolioOrder[] = orders .filter((order) => { @@ -745,6 +746,7 @@ export class PortfolioService { historicalDataArray.push({ averagePrice: orders[0].unitPrice, date: firstBuyDate, + quantity: orders[0].quantity, value: orders[0].unitPrice }); } @@ -761,6 +763,7 @@ export class PortfolioService { j++; } let currentAveragePrice = 0; + let currentQuantity = 0; const currentSymbol = transactionPoints[j].items.find( (item) => item.symbol === aSymbol ); @@ -768,11 +771,13 @@ export class PortfolioService { currentAveragePrice = currentSymbol.quantity.eq(0) ? 0 : currentSymbol.investment.div(currentSymbol.quantity).toNumber(); + currentQuantity = currentSymbol.quantity.toNumber(); } historicalDataArray.push({ date, averagePrice: currentAveragePrice, + quantity: currentQuantity, value: marketPrice }); diff --git a/libs/common/src/lib/interfaces/historical-data-item.interface.ts b/libs/common/src/lib/interfaces/historical-data-item.interface.ts index dd7bb84d8..59a53ee94 100644 --- a/libs/common/src/lib/interfaces/historical-data-item.interface.ts +++ b/libs/common/src/lib/interfaces/historical-data-item.interface.ts @@ -4,6 +4,7 @@ export interface HistoricalDataItem { grossPerformancePercent?: number; netPerformance?: number; netPerformanceInPercentage?: number; + quantity?: number; totalInvestment?: number; value?: number; } diff --git a/libs/common/src/lib/types/account-with-platform.type.ts b/libs/common/src/lib/types/account-with-platform.type.ts new file mode 100644 index 000000000..b0730abce --- /dev/null +++ b/libs/common/src/lib/types/account-with-platform.type.ts @@ -0,0 +1,3 @@ +import { Account, Platform } from '@prisma/client'; + +export type AccountWithPlatform = Account & { Platform?: Platform }; diff --git a/libs/common/src/lib/types/index.ts b/libs/common/src/lib/types/index.ts index d70295b53..255a1c3fe 100644 --- a/libs/common/src/lib/types/index.ts +++ b/libs/common/src/lib/types/index.ts @@ -1,4 +1,5 @@ import type { AccessWithGranteeUser } from './access-with-grantee-user.type'; +import { AccountWithPlatform } from './account-with-platform.type'; import { AccountWithValue } from './account-with-value.type'; import type { ColorScheme } from './color-scheme'; import type { DateRange } from './date-range.type'; @@ -13,6 +14,7 @@ import type { ViewMode } from './view-mode.type'; export type { AccessWithGranteeUser, + AccountWithPlatform, AccountWithValue, ColorScheme, DateRange, diff --git a/libs/common/src/lib/types/order-with-account.type.ts b/libs/common/src/lib/types/order-with-account.type.ts index 09c64a283..af8803091 100644 --- a/libs/common/src/lib/types/order-with-account.type.ts +++ b/libs/common/src/lib/types/order-with-account.type.ts @@ -1,6 +1,6 @@ -import { Account, Order, Platform, SymbolProfile, Tag } from '@prisma/client'; +import { Order, SymbolProfile, Tag } from '@prisma/client'; -type AccountWithPlatform = Account & { Platform?: Platform }; +import { AccountWithPlatform } from './account-with-platform.type'; export type OrderWithAccount = Order & { Account?: AccountWithPlatform;