Optionally update cash balance when adding activity (#1926)

* Optionally update cash balance when adding activity

* Update changelog
pull/1922/head^2
Francisco Silva 1 year ago committed by GitHub
parent 876b66f324
commit 8ba15f8f72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
### Added
- Introduced the option to update the cash balance of an account when adding an activity
### Changed
- Upgraded `class-transformer` from version `0.3.2` to `0.5.1`

@ -172,4 +172,47 @@ export class AccountService {
where
});
}
public async updateAccountBalance({
accountId,
amount,
currency,
date,
userId
}: {
accountId: string;
amount: number;
currency: string;
date: Date;
userId: string;
}) {
const { balance, currency: currencyOfAccount } = await this.account({
id_userId: {
userId,
id: accountId
}
});
const amountInCurrencyOfAccount =
await this.exchangeRateDataService.toCurrencyAtDate(
amount,
currency,
currencyOfAccount,
date
);
if (amountInCurrencyOfAccount) {
await this.prismaService.account.update({
data: {
balance: new Big(balance).plus(amountInCurrencyOfAccount).toNumber()
},
where: {
id_userId: {
userId,
id: accountId
}
}
});
}
}
}

@ -303,6 +303,7 @@ export class ImportService {
}
}
},
updateAccountBalance: false,
User: { connect: { id: userId } }
});
}

@ -8,6 +8,7 @@ import {
import { Transform, TransformFnParams } from 'class-transformer';
import {
IsArray,
IsBoolean,
IsEnum,
IsISO8601,
IsNumber,
@ -64,4 +65,8 @@ export class CreateOrderDto {
@IsNumber()
unitPrice: number;
@IsBoolean()
@IsOptional()
updateAccountBalance: boolean;
}

@ -6,6 +6,7 @@ export interface Activities {
export interface Activity extends OrderWithAccount {
feeInBaseCurrency: number;
updateAccountBalance?: boolean;
value: number;
valueInBaseCurrency: number;
}

@ -73,6 +73,7 @@ export class OrderService {
dataSource?: DataSource;
symbol?: string;
tags?: Tag[];
updateAccountBalance?: boolean;
userId: string;
}
): Promise<Order> {
@ -89,12 +90,16 @@ export class OrderService {
};
}
const accountId = data.accountId;
let currency = data.currency;
const tags = data.tags ?? [];
const updateAccountBalance = data.updateAccountBalance ?? false;
const userId = data.userId;
if (data.type === 'ITEM') {
const assetClass = data.assetClass;
const assetSubClass = data.assetSubClass;
const currency = data.SymbolProfile.connectOrCreate.create.currency;
currency = data.SymbolProfile.connectOrCreate.create.currency;
const dataSource: DataSource = 'MANUAL';
const id = uuidv4();
const name = data.SymbolProfile.connectOrCreate.create.symbol;
@ -149,11 +154,12 @@ export class OrderService {
delete data.dataSource;
delete data.symbol;
delete data.tags;
delete data.updateAccountBalance;
delete data.userId;
const orderData: Prisma.OrderCreateInput = data;
return this.prismaService.order.create({
const order = await this.prismaService.order.create({
data: {
...orderData,
Account,
@ -165,6 +171,27 @@ export class OrderService {
}
}
});
if (updateAccountBalance === true) {
let amount = new Big(data.unitPrice)
.mul(data.quantity)
.plus(data.fee)
.toNumber();
if (data.type === 'BUY') {
amount = new Big(amount).mul(-1).toNumber();
}
await this.accountService.updateAccountBalance({
accountId,
amount,
currency,
userId,
date: data.date as Date
});
}
return order;
}
public async deleteOrder(

@ -8,6 +8,7 @@ import {
import { Transform, TransformFnParams } from 'class-transformer';
import {
IsArray,
IsBoolean,
IsEnum,
IsISO8601,
IsNumber,
@ -66,4 +67,8 @@ export class UpdateOrderDto {
@IsNumber()
unitPrice: number;
@IsBoolean()
@IsOptional()
updateAccountBalance: boolean;
}

@ -139,7 +139,8 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
unitPriceInCustomCurrency: [
this.data.activity?.unitPrice,
Validators.required
]
],
updateAccountBalance: [false]
});
this.activityForm.valueChanges
@ -297,6 +298,8 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
Validators.required
);
this.activityForm.controls['searchSymbol'].updateValueAndValidity();
this.activityForm.controls['updateAccountBalance'].disable();
this.activityForm.controls['updateAccountBalance'].setValue(false);
} else {
this.activityForm.controls['accountId'].setValidators(
Validators.required
@ -314,6 +317,7 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
Validators.required
);
this.activityForm.controls['searchSymbol'].updateValueAndValidity();
this.activityForm.controls['updateAccountBalance'].enable();
}
this.changeDetectorRef.markForCheck();
@ -411,7 +415,9 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
: this.activityForm.controls['searchSymbol'].value.symbol,
tags: this.activityForm.controls['tags'].value,
type: this.activityForm.controls['type'].value,
unitPrice: this.activityForm.controls['unitPrice'].value
unitPrice: this.activityForm.controls['unitPrice'].value,
updateAccountBalance:
this.activityForm.controls['updateAccountBalance'].value
};
if (this.data.activity.id) {

@ -18,8 +18,8 @@
</mat-select>
</mat-form-field>
</div>
<div class="mb-3">
<mat-form-field appearance="outline" class="w-100">
<div>
<mat-form-field appearance="outline" class="mb-1 without-hint w-100">
<mat-label i18n>Account</mat-label>
<mat-select formControlName="accountId">
<mat-option
@ -32,6 +32,11 @@
</mat-select>
</mat-form-field>
</div>
<div class="mb-3">
<mat-checkbox color="primary" formControlName="updateAccountBalance" i18n
>Update Cash Balance</mat-checkbox
>
</div>
<div
class="mb-3"
[ngClass]="{ 'd-none': !activityForm.controls['searchSymbol'].hasValidator(Validators.required) }"

@ -8,6 +8,7 @@ import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatDialogModule } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSelectModule } from '@angular/material/select';
import { GfSymbolModule } from '@ghostfolio/client/pipes/symbol/symbol.module';
@ -24,6 +25,7 @@ import { CreateOrUpdateActivityDialog } from './create-or-update-activity-dialog
GfValueModule,
MatAutocompleteModule,
MatButtonModule,
MatCheckboxModule,
MatChipsModule,
MatDatepickerModule,
MatDialogModule,

@ -59,7 +59,8 @@ export class ImportActivitiesService {
quantity: this.parseQuantity({ content, index, item }),
symbol: this.parseSymbol({ content, index, item }),
type: this.parseType({ content, index, item }),
unitPrice: this.parseUnitPrice({ content, index, item })
unitPrice: this.parseUnitPrice({ content, index, item }),
updateAccountBalance: false
});
}
@ -126,7 +127,8 @@ export class ImportActivitiesService {
quantity,
SymbolProfile,
type,
unitPrice
unitPrice,
updateAccountBalance
}: Activity): CreateOrderDto {
return {
accountId,
@ -134,6 +136,7 @@ export class ImportActivitiesService {
quantity,
type,
unitPrice,
updateAccountBalance,
currency: SymbolProfile.currency,
date: date.toString(),
symbol: SymbolProfile.symbol

Loading…
Cancel
Save