From d00fc3d73410b129be163bee275303143aedf511 Mon Sep 17 00:00:00 2001 From: Thomas <4159106+dtslvr@users.noreply.github.com> Date: Sat, 22 Jul 2023 07:31:54 +0200 Subject: [PATCH] Initial setup --- apps/api/src/app/account/account.module.ts | 2 ++ apps/api/src/app/account/account.service.ts | 36 ++++++++++++++++--- .../src/app/portfolio/portfolio.service.ts | 25 ++++++++----- .../account-balance/account-balance.module.ts | 11 ++++++ .../account-balance.service.ts | 17 +++++++++ prisma/schema.prisma | 29 ++++++++++----- 6 files changed, 99 insertions(+), 21 deletions(-) create mode 100644 apps/api/src/services/account-balance/account-balance.module.ts create mode 100644 apps/api/src/services/account-balance/account-balance.service.ts diff --git a/apps/api/src/app/account/account.module.ts b/apps/api/src/app/account/account.module.ts index f37ed34ee..26ace47c2 100644 --- a/apps/api/src/app/account/account.module.ts +++ b/apps/api/src/app/account/account.module.ts @@ -1,6 +1,7 @@ import { PortfolioModule } from '@ghostfolio/api/app/portfolio/portfolio.module'; import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; import { UserModule } from '@ghostfolio/api/app/user/user.module'; +import { AccountBalanceModule } from '@ghostfolio/api/services/account-balance/account-balance.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module'; @@ -15,6 +16,7 @@ import { AccountService } from './account.service'; controllers: [AccountController], exports: [AccountService], imports: [ + AccountBalanceModule, ConfigurationModule, DataProviderModule, ExchangeRateDataModule, diff --git a/apps/api/src/app/account/account.service.ts b/apps/api/src/app/account/account.service.ts index c6da815e4..8df5dc840 100644 --- a/apps/api/src/app/account/account.service.ts +++ b/apps/api/src/app/account/account.service.ts @@ -2,7 +2,13 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate- import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; import { Filter } from '@ghostfolio/common/interfaces'; import { Injectable } from '@nestjs/common'; -import { Account, Order, Platform, Prisma } from '@prisma/client'; +import { + Account, + AccountBalance, + Order, + Platform, + Prisma +} from '@prisma/client'; import Big from 'big.js'; import { groupBy } from 'lodash'; @@ -46,6 +52,7 @@ export class AccountService { orderBy?: Prisma.AccountOrderByWithRelationInput; }): Promise< (Account & { + balances?: AccountBalance[]; Order?: Order[]; Platform?: Platform; })[] @@ -82,7 +89,11 @@ export class AccountService { public async getAccounts(aUserId: string) { const accounts = await this.accounts({ - include: { Order: true, Platform: true }, + include: { + balances: { orderBy: { createdAt: 'desc' }, take: 1 }, + Order: true, + Platform: true + }, orderBy: { name: 'asc' }, where: { userId: aUserId } }); @@ -141,12 +152,17 @@ export class AccountService { }; } - const accounts = await this.accounts({ where }); + const accounts = await this.accounts({ + where, + include: { + balances: { orderBy: { createdAt: 'desc' }, take: 1 } + } + }); for (const account of accounts) { totalCashBalanceInBaseCurrency = totalCashBalanceInBaseCurrency.plus( this.exchangeRateDataService.toCurrency( - account.balance, + account.balances[0].value, account.currency, currency ) @@ -167,6 +183,18 @@ export class AccountService { aUserId: string ): Promise { const { data, where } = params; + + await this.prismaService.accountBalance.create({ + data: { + Account: { + connect: { + id_userId: where.id_userId + } + }, + value: data.balance + } + }); + return this.prismaService.account.update({ data, where diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 4f96d2716..440f259e0 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -51,6 +51,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { REQUEST } from '@nestjs/core'; import { Account, + AccountBalance, AssetClass, DataSource, Order, @@ -125,7 +126,10 @@ export class PortfolioService { const [accounts, details] = await Promise.all([ this.accountService.accounts({ where, - include: { Order: true, Platform: true }, + include: { + Order: true, + Platform: true + }, orderBy: { name: 'asc' } }), this.getDetails({ @@ -154,8 +158,9 @@ export class PortfolioService { ...account, transactionCount, valueInBaseCurrency, + balance: details.accounts[account.id].balance, balanceInBaseCurrency: this.exchangeRateDataService.toCurrency( - account.balance, + details.accounts[account.id].balance, account.currency, userCurrency ), @@ -1795,6 +1800,7 @@ export class PortfolioService { const platforms: PortfolioDetails['platforms'] = {}; let currentAccounts: (Account & { + balances?: AccountBalance[]; Order?: Order[]; Platform?: Platform; })[] = []; @@ -1803,7 +1809,10 @@ export class PortfolioService { currentAccounts = await this.accountService.getAccounts(userId); } else if (filters.length === 1 && filters[0].type === 'ACCOUNT') { currentAccounts = await this.accountService.accounts({ - include: { Platform: true }, + include: { + balances: { orderBy: { createdAt: 'desc' }, take: 1 }, + Platform: true + }, where: { id: filters[0].id } }); } else { @@ -1837,11 +1846,11 @@ export class PortfolioService { ordersByAccount = ordersByAccount.concat(ordersOfTypeItemByAccount); accounts[account.id] = { - balance: account.balance, + balance: account.balances[0].value, currency: account.currency, name: account.name, valueInBaseCurrency: this.exchangeRateDataService.toCurrency( - account.balance, + account.balances[0].value, account.currency, userCurrency ) @@ -1850,17 +1859,17 @@ export class PortfolioService { if (platforms[account.Platform?.id || UNKNOWN_KEY]?.valueInBaseCurrency) { platforms[account.Platform?.id || UNKNOWN_KEY].valueInBaseCurrency += this.exchangeRateDataService.toCurrency( - account.balance, + account.balances[0].value, account.currency, userCurrency ); } else { platforms[account.Platform?.id || UNKNOWN_KEY] = { - balance: account.balance, + balance: account.balances[0].value, currency: account.currency, name: account.Platform?.name, valueInBaseCurrency: this.exchangeRateDataService.toCurrency( - account.balance, + account.balances[0].value, account.currency, userCurrency ) diff --git a/apps/api/src/services/account-balance/account-balance.module.ts b/apps/api/src/services/account-balance/account-balance.module.ts new file mode 100644 index 000000000..0f9410ce2 --- /dev/null +++ b/apps/api/src/services/account-balance/account-balance.module.ts @@ -0,0 +1,11 @@ +import { AccountBalanceService } from '@ghostfolio/api/services/account-balance/account-balance.service'; +import { Module } from '@nestjs/common'; + +import { PrismaModule } from '../prisma/prisma.module'; + +@Module({ + exports: [AccountBalanceService], + imports: [PrismaModule], + providers: [AccountBalanceService] +}) +export class AccountBalanceModule {} diff --git a/apps/api/src/services/account-balance/account-balance.service.ts b/apps/api/src/services/account-balance/account-balance.service.ts new file mode 100644 index 000000000..65dd99711 --- /dev/null +++ b/apps/api/src/services/account-balance/account-balance.service.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@nestjs/common'; +import { AccountBalance, Prisma } from '@prisma/client'; + +import { PrismaService } from '../prisma/prisma.service'; + +@Injectable() +export class AccountBalanceService { + public constructor(private readonly prismaService: PrismaService) {} + + public async createAccountBalance( + data: Prisma.AccountBalanceCreateInput + ): Promise { + return this.prismaService.accountBalance.create({ + data + }); + } +} diff --git a/prisma/schema.prisma b/prisma/schema.prisma index f46272a54..785673180 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -21,20 +21,21 @@ model Access { } model Account { - accountType AccountType @default(SECURITIES) - balance Float @default(0) + accountType AccountType @default(SECURITIES) + balance Float @default(0) + balances AccountBalance[] comment String? - createdAt DateTime @default(now()) + createdAt DateTime @default(now()) currency String? - id String @default(uuid()) - isDefault Boolean @default(false) - isExcluded Boolean @default(false) + id String @default(uuid()) + isDefault Boolean @default(false) + isExcluded Boolean @default(false) name String? platformId String? - updatedAt DateTime @updatedAt + updatedAt DateTime @updatedAt userId String - Platform Platform? @relation(fields: [platformId], references: [id]) - User User @relation(fields: [userId], references: [id]) + Platform Platform? @relation(fields: [platformId], references: [id]) + User User @relation(fields: [userId], references: [id]) Order Order[] @@id([id, userId]) @@ -59,6 +60,16 @@ model AuthDevice { User User @relation(fields: [userId], references: [id]) } +model AccountBalance { + accountId String + createdAt DateTime @default(now()) + id String @id @default(uuid()) + value Float + updatedAt DateTime @updatedAt + userId String + Account Account @relation(fields: [accountId, userId], references: [id, userId]) +} + model MarketData { createdAt DateTime @default(now()) dataSource DataSource