From a2a836572b40a968c78303c484dd155e395ead3d Mon Sep 17 00:00:00 2001 From: Sonlis Date: Fri, 12 Apr 2024 09:40:33 +0300 Subject: [PATCH] Add support for creating account cash balances from the account detail dialogue tab --- .../account-balance.controller.ts | 24 +++ .../account-detail-dialog.component.ts | 25 +++ .../account-detail-dialog.html | 1 + apps/client/src/app/services/data.service.ts | 28 ++++ libs/common/src/lib/permissions.ts | 3 + .../account-balances.component.html | 147 +++++++++++------- .../account-balances.component.scss | 7 + .../account-balances.component.ts | 37 ++++- 8 files changed, 216 insertions(+), 56 deletions(-) diff --git a/apps/api/src/app/account-balance/account-balance.controller.ts b/apps/api/src/app/account-balance/account-balance.controller.ts index 943d0aeb5..a64217025 100644 --- a/apps/api/src/app/account-balance/account-balance.controller.ts +++ b/apps/api/src/app/account-balance/account-balance.controller.ts @@ -5,6 +5,8 @@ import type { RequestWithUser } from '@ghostfolio/common/types'; import { Controller, + Body, + Post, Delete, HttpException, Inject, @@ -46,4 +48,26 @@ export class AccountBalanceController { id }); } + + @HasPermission(permissions.createAccountBalance) + @Post() + @UseGuards(AuthGuard('jwt'), HasPermissionGuard) + public async createAccountBalance( + @Body() body: any + ): Promise { + const account = body.Account.connect.id_userId; + const data = { + Account: { + connect: { + id_userId: { + id: account.id, + userId: account.userId + } + } + }, + value: body.balance, + date: body.date + }; + return this.accountBalanceService.createAccountBalance(data); + } } diff --git a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts index 537adf1d1..d0f3aa242 100644 --- a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts +++ b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts @@ -140,6 +140,31 @@ export class AccountDetailDialog implements OnDestroy, OnInit { this.dialogRef.close(); } + public onAddAccountBalance({ + date, + balance + }: { + date: string; + balance: number; + }) { + const formattedDate = new Date(date); + this.dataService + .postAccountBalance({ + userId: this.user.id, + accountId: this.data.accountId, + balance: balance, + currency: this.currency, + date: formattedDate + }) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe({ + next: () => { + this.fetchAccountBalances(); + this.fetchPortfolioPerformance(); + } + }); + } + public onDeleteAccountBalance(aId: string) { this.dataService .deleteAccountBalance(aId) diff --git a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html index 041a779c4..3f697361f 100644 --- a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html +++ b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html @@ -122,6 +122,7 @@ hasPermissionToDeleteAccountBalance && !user.settings.isRestrictedView " + (accountBalanceCreated)="onAddAccountBalance($event)" (accountBalanceDeleted)="onDeleteAccountBalance($event)" /> diff --git a/apps/client/src/app/services/data.service.ts b/apps/client/src/app/services/data.service.ts index a1d94c646..c2845a117 100644 --- a/apps/client/src/app/services/data.service.ts +++ b/apps/client/src/app/services/data.service.ts @@ -611,6 +611,34 @@ export class DataService { return this.http.post(`/api/v1/account`, aAccount); } + public postAccountBalance({ + date, + accountId, + balance, + currency, + userId + }: { + date: Date; + accountId: string; + balance: number; + currency: string; + userId: string; + }) { + return this.http.post(`/api/v1/account-balance`, { + Account: { + connect: { + id_userId: { + id: accountId, + userId + } + } + }, + currency, + date, + balance: balance + }); + } + public postBenchmark(benchmark: UniqueAsset) { return this.http.post(`/api/v1/benchmark`, benchmark); } diff --git a/libs/common/src/lib/permissions.ts b/libs/common/src/lib/permissions.ts index 09bbfa1bd..890cb8b63 100644 --- a/libs/common/src/lib/permissions.ts +++ b/libs/common/src/lib/permissions.ts @@ -7,6 +7,7 @@ export const permissions = { accessAssistant: 'accessAssistant', createAccess: 'createAccess', createAccount: 'createAccount', + createAccountBalance: 'createAccountBalance', createOrder: 'createOrder', createPlatform: 'createPlatform', createTag: 'createTag', @@ -47,6 +48,7 @@ export function getPermissions(aRole: Role): string[] { permissions.accessAssistant, permissions.createAccess, permissions.createAccount, + permissions.createAccountBalance, permissions.deleteAccountBalance, permissions.createOrder, permissions.createPlatform, @@ -75,6 +77,7 @@ export function getPermissions(aRole: Role): string[] { permissions.accessAssistant, permissions.createAccess, permissions.createAccount, + permissions.createAccountBalance, permissions.createOrder, permissions.deleteAccess, permissions.deleteAccount, diff --git a/libs/ui/src/lib/account-balances/account-balances.component.html b/libs/ui/src/lib/account-balances/account-balances.component.html index 0d1a79f41..05e5e1199 100644 --- a/libs/ui/src/lib/account-balances/account-balances.component.html +++ b/libs/ui/src/lib/account-balances/account-balances.component.html @@ -1,60 +1,101 @@ - - - - - + +
- Date - - -
+ + + + + - - - - + + + + + - - - + + - + + - - -
+ Date + + + + + Date + + + + + + + - Value - -
- -
-
+ Value + +
+ +
+
+
+ + + +
+
- @if (showActions) { + + + @if (showActions) { + + } + + + + - } - - - -
+ + + + + diff --git a/libs/ui/src/lib/account-balances/account-balances.component.scss b/libs/ui/src/lib/account-balances/account-balances.component.scss index 5d4e87f30..0bf48a9e7 100644 --- a/libs/ui/src/lib/account-balances/account-balances.component.scss +++ b/libs/ui/src/lib/account-balances/account-balances.component.scss @@ -1,3 +1,10 @@ :host { display: block; } + +:host-context(.is-dark-theme) { + input { + color: rgb(var(--light-primary-text)); + background-color: rgb(var(--palette-foreground-text-light)); + } +} diff --git a/libs/ui/src/lib/account-balances/account-balances.component.ts b/libs/ui/src/lib/account-balances/account-balances.component.ts index 9d9e8ab19..e68c99abe 100644 --- a/libs/ui/src/lib/account-balances/account-balances.component.ts +++ b/libs/ui/src/lib/account-balances/account-balances.component.ts @@ -14,7 +14,17 @@ import { Output, ViewChild } from '@angular/core'; +import { + FormGroup, + FormControl, + Validators, + ReactiveFormsModule +} from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; +import { DateAdapter } from '@angular/material/core'; +import { MatDatepickerModule } from '@angular/material/datepicker'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatInputModule } from '@angular/material/input'; import { MatMenuModule } from '@angular/material/menu'; import { MatSort, MatSortModule } from '@angular/material/sort'; import { MatTableDataSource, MatTableModule } from '@angular/material/table'; @@ -29,9 +39,13 @@ import { GfValueComponent } from '../value'; CommonModule, GfValueComponent, MatButtonModule, + MatDatepickerModule, + MatFormFieldModule, + MatInputModule, MatMenuModule, MatSortModule, - MatTableModule + MatTableModule, + ReactiveFormsModule ], schemas: [CUSTOM_ELEMENTS_SCHEMA], selector: 'gf-account-balances', @@ -47,10 +61,16 @@ export class GfAccountBalancesComponent @Input() locale = getLocale(); @Input() showActions = true; + @Output() accountBalanceCreated = new EventEmitter<{ + balance: number; + date: string; + }>(); @Output() accountBalanceDeleted = new EventEmitter(); @ViewChild(MatSort) sort: MatSort; + public Validators = Validators; + public dataSource: MatTableDataSource< AccountBalancesResponse['balances'][0] > = new MatTableDataSource(); @@ -58,9 +78,16 @@ export class GfAccountBalancesComponent private unsubscribeSubject = new Subject(); - public constructor() {} + public constructor(private dateAdapter: DateAdapter) {} + + public accountBalanceForm = new FormGroup({ + balance: new FormControl(0, Validators.required), + date: new FormControl(new Date().toISOString(), Validators.required) + }); - public ngOnInit() {} + public ngOnInit() { + this.dateAdapter.setLocale(this.locale); + } public ngOnChanges() { if (this.accountBalances) { @@ -81,6 +108,10 @@ export class GfAccountBalancesComponent } } + public onSubmitAccountBalance() { + this.accountBalanceCreated.emit(this.accountBalanceForm.getRawValue()); + } + public ngOnDestroy() { this.unsubscribeSubject.next(); this.unsubscribeSubject.complete();