diff --git a/CHANGELOG.md b/CHANGELOG.md index dcdffbf53..537821977 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added + +- Added the endpoint `GET api/v1/account/:id/balances` which provides historical cash balances + ### Fixed - Displayed the transfer cash balance button based on a permission diff --git a/apps/api/src/app/account/account.controller.ts b/apps/api/src/app/account/account.controller.ts index 05d0c11de..4666e5084 100644 --- a/apps/api/src/app/account/account.controller.ts +++ b/apps/api/src/app/account/account.controller.ts @@ -1,8 +1,12 @@ import { PortfolioService } from '@ghostfolio/api/app/portfolio/portfolio.service'; import { RedactValuesInResponseInterceptor } from '@ghostfolio/api/interceptors/redact-values-in-response.interceptor'; +import { AccountBalanceService } from '@ghostfolio/api/services/account-balance/account-balance.service'; import { ImpersonationService } from '@ghostfolio/api/services/impersonation/impersonation.service'; import { HEADER_KEY_IMPERSONATION } from '@ghostfolio/common/config'; -import { Accounts } from '@ghostfolio/common/interfaces'; +import { + AccountBalancesResponse, + Accounts +} from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import type { AccountWithValue, @@ -35,6 +39,7 @@ import { UpdateAccountDto } from './update-account.dto'; @Controller('account') export class AccountController { public constructor( + private readonly accountBalanceService: AccountBalanceService, private readonly accountService: AccountService, private readonly impersonationService: ImpersonationService, private readonly portfolioService: PortfolioService, @@ -116,6 +121,18 @@ export class AccountController { return accountsWithAggregations.accounts[0]; } + @Get(':id/balances') + @UseGuards(AuthGuard('jwt')) + @UseInterceptors(RedactValuesInResponseInterceptor) + public async getAccountBalancesById( + @Param('id') id: string + ): Promise { + return this.accountBalanceService.getAccountBalances({ + accountId: id, + userId: this.request.user.id + }); + } + @Post() @UseGuards(AuthGuard('jwt')) public async createAccount( diff --git a/apps/api/src/services/account-balance/account-balance.service.ts b/apps/api/src/services/account-balance/account-balance.service.ts index 9cd2d31ac..9995bbc3e 100644 --- a/apps/api/src/services/account-balance/account-balance.service.ts +++ b/apps/api/src/services/account-balance/account-balance.service.ts @@ -1,4 +1,5 @@ import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service'; +import { AccountBalancesResponse } from '@ghostfolio/common/interfaces'; import { Injectable } from '@nestjs/common'; import { AccountBalance, Prisma } from '@prisma/client'; @@ -13,4 +14,29 @@ export class AccountBalanceService { data }); } + + public async getAccountBalances({ + accountId, + userId + }: { + accountId: string; + userId: string; + }): Promise { + const balances = await this.prismaService.accountBalance.findMany({ + orderBy: { + date: 'asc' + }, + select: { + date: true, + id: true, + value: true + }, + where: { + accountId, + userId + } + }); + + return { balances }; + } } diff --git a/libs/common/src/lib/interfaces/index.ts b/libs/common/src/lib/interfaces/index.ts index e33b6b55f..47df3d2f9 100644 --- a/libs/common/src/lib/interfaces/index.ts +++ b/libs/common/src/lib/interfaces/index.ts @@ -33,6 +33,7 @@ import type { PortfolioReport } from './portfolio-report.interface'; import type { PortfolioSummary } from './portfolio-summary.interface'; import type { Position } from './position.interface'; import type { Product } from './product'; +import type { AccountBalancesResponse } from './responses/account-balances-response.interface'; import type { BenchmarkResponse } from './responses/benchmark-response.interface'; import type { ResponseError } from './responses/errors.interface'; import type { ImportResponse } from './responses/import-response.interface'; @@ -49,6 +50,7 @@ import type { User } from './user.interface'; export { Access, + AccountBalancesResponse, Accounts, AdminData, AdminJobs, diff --git a/libs/common/src/lib/interfaces/responses/account-balances-response.interface.ts b/libs/common/src/lib/interfaces/responses/account-balances-response.interface.ts new file mode 100644 index 000000000..9b4ec2f6d --- /dev/null +++ b/libs/common/src/lib/interfaces/responses/account-balances-response.interface.ts @@ -0,0 +1,5 @@ +import { AccountBalance } from '@prisma/client'; + +export interface AccountBalancesResponse { + balances: Pick[]; +}