Feature/add support for wealth items (#666)
* Add support for wealth items * Update changelog
This commit is contained in:
@@ -142,6 +142,17 @@
|
||||
></gf-value>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row px-3 py-1">
|
||||
<div class="d-flex flex-grow-1" i18n>Items</div>
|
||||
<div class="d-flex justify-content-end">
|
||||
<gf-value
|
||||
class="justify-content-end"
|
||||
[currency]="baseCurrency"
|
||||
[locale]="locale"
|
||||
[value]="isLoading ? undefined : summary?.items"
|
||||
></gf-value>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col"><hr /></div>
|
||||
</div>
|
||||
|
@@ -6,11 +6,15 @@ import {
|
||||
OnDestroy,
|
||||
ViewChild
|
||||
} from '@angular/core';
|
||||
import { FormControl, Validators } from '@angular/forms';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto';
|
||||
import { UpdateOrderDto } from '@ghostfolio/api/app/order/update-order.dto';
|
||||
import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface';
|
||||
import { DataService } from '@ghostfolio/client/services/data.service';
|
||||
import { Type } from '@prisma/client';
|
||||
import { isUUID } from 'class-validator';
|
||||
import { isString } from 'lodash';
|
||||
import { EMPTY, Observable, Subject } from 'rxjs';
|
||||
import {
|
||||
@@ -34,19 +38,15 @@ import { CreateOrUpdateTransactionDialogParams } from './interfaces/interfaces';
|
||||
export class CreateOrUpdateTransactionDialog implements OnDestroy {
|
||||
@ViewChild('autocomplete') autocomplete;
|
||||
|
||||
public activityForm: FormGroup;
|
||||
|
||||
public currencies: string[] = [];
|
||||
public currentMarketPrice = null;
|
||||
public filteredLookupItems: LookupItem[];
|
||||
public filteredLookupItemsObservable: Observable<LookupItem[]>;
|
||||
public isLoading = false;
|
||||
public platforms: { id: string; name: string }[];
|
||||
public searchSymbolCtrl = new FormControl(
|
||||
{
|
||||
dataSource: this.data.transaction.dataSource,
|
||||
symbol: this.data.transaction.symbol
|
||||
},
|
||||
Validators.required
|
||||
);
|
||||
public Validators = Validators;
|
||||
|
||||
private unsubscribeSubject = new Subject<void>();
|
||||
|
||||
@@ -54,6 +54,7 @@ export class CreateOrUpdateTransactionDialog implements OnDestroy {
|
||||
private changeDetectorRef: ChangeDetectorRef,
|
||||
private dataService: DataService,
|
||||
public dialogRef: MatDialogRef<CreateOrUpdateTransactionDialog>,
|
||||
private formBuilder: FormBuilder,
|
||||
@Inject(MAT_DIALOG_DATA) public data: CreateOrUpdateTransactionDialogParams
|
||||
) {}
|
||||
|
||||
@@ -63,36 +64,105 @@ export class CreateOrUpdateTransactionDialog implements OnDestroy {
|
||||
this.currencies = currencies;
|
||||
this.platforms = platforms;
|
||||
|
||||
this.filteredLookupItemsObservable =
|
||||
this.searchSymbolCtrl.valueChanges.pipe(
|
||||
startWith(''),
|
||||
debounceTime(400),
|
||||
distinctUntilChanged(),
|
||||
switchMap((query: string) => {
|
||||
if (isString(query)) {
|
||||
const filteredLookupItemsObservable =
|
||||
this.dataService.fetchSymbols(query);
|
||||
this.activityForm = this.formBuilder.group({
|
||||
accountId: [this.data.activity?.accountId, Validators.required],
|
||||
currency: [
|
||||
this.data.activity?.SymbolProfile?.currency,
|
||||
Validators.required
|
||||
],
|
||||
dataSource: [
|
||||
this.data.activity?.SymbolProfile?.dataSource,
|
||||
Validators.required
|
||||
],
|
||||
date: [this.data.activity?.date, Validators.required],
|
||||
fee: [this.data.activity?.fee, Validators.required],
|
||||
name: [this.data.activity?.SymbolProfile?.name, Validators.required],
|
||||
quantity: [this.data.activity?.quantity, Validators.required],
|
||||
searchSymbol: [
|
||||
{
|
||||
dataSource: this.data.activity?.SymbolProfile?.dataSource,
|
||||
symbol: this.data.activity?.SymbolProfile?.symbol
|
||||
},
|
||||
Validators.required
|
||||
],
|
||||
type: [undefined, Validators.required], // Set after value changes subscription
|
||||
unitPrice: [this.data.activity?.unitPrice, Validators.required]
|
||||
});
|
||||
|
||||
filteredLookupItemsObservable.subscribe((filteredLookupItems) => {
|
||||
this.filteredLookupItems = filteredLookupItems;
|
||||
});
|
||||
this.filteredLookupItemsObservable = this.activityForm.controls[
|
||||
'searchSymbol'
|
||||
].valueChanges.pipe(
|
||||
startWith(''),
|
||||
debounceTime(400),
|
||||
distinctUntilChanged(),
|
||||
switchMap((query: string) => {
|
||||
if (isString(query)) {
|
||||
const filteredLookupItemsObservable =
|
||||
this.dataService.fetchSymbols(query);
|
||||
|
||||
return filteredLookupItemsObservable;
|
||||
}
|
||||
filteredLookupItemsObservable.subscribe((filteredLookupItems) => {
|
||||
this.filteredLookupItems = filteredLookupItems;
|
||||
});
|
||||
|
||||
return [];
|
||||
})
|
||||
);
|
||||
return filteredLookupItemsObservable;
|
||||
}
|
||||
|
||||
if (this.data.transaction.id) {
|
||||
this.searchSymbolCtrl.disable();
|
||||
return [];
|
||||
})
|
||||
);
|
||||
|
||||
this.activityForm.controls['type'].valueChanges.subscribe((type: Type) => {
|
||||
if (type === 'ITEM') {
|
||||
this.activityForm.controls['accountId'].removeValidators(
|
||||
Validators.required
|
||||
);
|
||||
this.activityForm.controls['accountId'].updateValueAndValidity();
|
||||
this.activityForm.controls['currency'].setValue(
|
||||
this.data.user.settings.baseCurrency
|
||||
);
|
||||
this.activityForm.controls['dataSource'].removeValidators(
|
||||
Validators.required
|
||||
);
|
||||
this.activityForm.controls['dataSource'].updateValueAndValidity();
|
||||
this.activityForm.controls['name'].setValidators(Validators.required);
|
||||
this.activityForm.controls['name'].updateValueAndValidity();
|
||||
this.activityForm.controls['quantity'].setValue(1);
|
||||
this.activityForm.controls['searchSymbol'].removeValidators(
|
||||
Validators.required
|
||||
);
|
||||
this.activityForm.controls['searchSymbol'].updateValueAndValidity();
|
||||
} else {
|
||||
this.activityForm.controls['accountId'].setValidators(
|
||||
Validators.required
|
||||
);
|
||||
this.activityForm.controls['accountId'].updateValueAndValidity();
|
||||
this.activityForm.controls['dataSource'].setValidators(
|
||||
Validators.required
|
||||
);
|
||||
this.activityForm.controls['dataSource'].updateValueAndValidity();
|
||||
this.activityForm.controls['name'].removeValidators(
|
||||
Validators.required
|
||||
);
|
||||
this.activityForm.controls['name'].updateValueAndValidity();
|
||||
this.activityForm.controls['searchSymbol'].setValidators(
|
||||
Validators.required
|
||||
);
|
||||
this.activityForm.controls['searchSymbol'].updateValueAndValidity();
|
||||
}
|
||||
});
|
||||
|
||||
this.activityForm.controls['type'].setValue(this.data.activity?.type);
|
||||
|
||||
if (this.data.activity?.id) {
|
||||
this.activityForm.controls['searchSymbol'].disable();
|
||||
this.activityForm.controls['type'].disable();
|
||||
}
|
||||
|
||||
if (this.data.transaction.symbol) {
|
||||
if (this.data.activity?.symbol) {
|
||||
this.dataService
|
||||
.fetchSymbolItem({
|
||||
dataSource: this.data.transaction.dataSource,
|
||||
symbol: this.data.transaction.symbol
|
||||
dataSource: this.data.activity?.dataSource,
|
||||
symbol: this.data.activity?.symbol
|
||||
})
|
||||
.pipe(takeUntil(this.unsubscribeSubject))
|
||||
.subscribe(({ marketPrice }) => {
|
||||
@@ -104,7 +174,9 @@ export class CreateOrUpdateTransactionDialog implements OnDestroy {
|
||||
}
|
||||
|
||||
public applyCurrentMarketPrice() {
|
||||
this.data.transaction.unitPrice = this.currentMarketPrice;
|
||||
this.activityForm.patchValue({
|
||||
unitPrice: this.currentMarketPrice
|
||||
});
|
||||
}
|
||||
|
||||
public displayFn(aLookupItem: LookupItem) {
|
||||
@@ -113,17 +185,20 @@ export class CreateOrUpdateTransactionDialog implements OnDestroy {
|
||||
|
||||
public onBlurSymbol() {
|
||||
const currentLookupItem = this.filteredLookupItems.find((lookupItem) => {
|
||||
return lookupItem.symbol === this.data.transaction.symbol;
|
||||
return (
|
||||
lookupItem.symbol ===
|
||||
this.activityForm.controls['searchSymbol'].value.symbol
|
||||
);
|
||||
});
|
||||
|
||||
if (currentLookupItem) {
|
||||
this.updateSymbol(currentLookupItem.symbol);
|
||||
} else {
|
||||
this.searchSymbolCtrl.setErrors({ incorrect: true });
|
||||
this.activityForm.controls['searchSymbol'].setErrors({ incorrect: true });
|
||||
|
||||
this.data.transaction.currency = null;
|
||||
this.data.transaction.dataSource = null;
|
||||
this.data.transaction.symbol = null;
|
||||
this.data.activity.currency = null;
|
||||
this.data.activity.dataSource = null;
|
||||
this.data.activity.symbol = null;
|
||||
}
|
||||
|
||||
this.changeDetectorRef.markForCheck();
|
||||
@@ -133,8 +208,32 @@ export class CreateOrUpdateTransactionDialog implements OnDestroy {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
public onSubmit() {
|
||||
const activity: CreateOrderDto | UpdateOrderDto = {
|
||||
accountId: this.activityForm.controls['accountId'].value,
|
||||
currency: this.activityForm.controls['currency'].value,
|
||||
date: this.activityForm.controls['date'].value,
|
||||
dataSource: this.activityForm.controls['dataSource'].value,
|
||||
fee: this.activityForm.controls['fee'].value,
|
||||
quantity: this.activityForm.controls['quantity'].value,
|
||||
symbol: isUUID(this.activityForm.controls['searchSymbol'].value.symbol)
|
||||
? this.activityForm.controls['name'].value
|
||||
: this.activityForm.controls['searchSymbol'].value.symbol,
|
||||
type: this.activityForm.controls['type'].value,
|
||||
unitPrice: this.activityForm.controls['unitPrice'].value
|
||||
};
|
||||
|
||||
if (this.data.activity.id) {
|
||||
(activity as UpdateOrderDto).id = this.data.activity.id;
|
||||
}
|
||||
|
||||
this.dialogRef.close({ activity });
|
||||
}
|
||||
|
||||
public onUpdateSymbol(event: MatAutocompleteSelectedEvent) {
|
||||
this.data.transaction.dataSource = event.option.value.dataSource;
|
||||
this.activityForm.controls['dataSource'].setValue(
|
||||
event.option.value.dataSource
|
||||
);
|
||||
this.updateSymbol(event.option.value.symbol);
|
||||
}
|
||||
|
||||
@@ -146,20 +245,21 @@ export class CreateOrUpdateTransactionDialog implements OnDestroy {
|
||||
private updateSymbol(symbol: string) {
|
||||
this.isLoading = true;
|
||||
|
||||
this.searchSymbolCtrl.setErrors(null);
|
||||
this.activityForm.controls['searchSymbol'].setErrors(null);
|
||||
this.activityForm.controls['searchSymbol'].setValue({ symbol });
|
||||
|
||||
this.data.transaction.symbol = symbol;
|
||||
this.changeDetectorRef.markForCheck();
|
||||
|
||||
this.dataService
|
||||
.fetchSymbolItem({
|
||||
dataSource: this.data.transaction.dataSource,
|
||||
symbol: this.data.transaction.symbol
|
||||
dataSource: this.activityForm.controls['dataSource'].value,
|
||||
symbol: this.activityForm.controls['searchSymbol'].value.symbol
|
||||
})
|
||||
.pipe(
|
||||
catchError(() => {
|
||||
this.data.transaction.currency = null;
|
||||
this.data.transaction.dataSource = null;
|
||||
this.data.transaction.unitPrice = null;
|
||||
this.data.activity.currency = null;
|
||||
this.data.activity.dataSource = null;
|
||||
this.data.activity.unitPrice = null;
|
||||
|
||||
this.isLoading = false;
|
||||
|
||||
@@ -170,8 +270,9 @@ export class CreateOrUpdateTransactionDialog implements OnDestroy {
|
||||
takeUntil(this.unsubscribeSubject)
|
||||
)
|
||||
.subscribe(({ currency, dataSource, marketPrice }) => {
|
||||
this.data.transaction.currency = currency;
|
||||
this.data.transaction.dataSource = dataSource;
|
||||
this.activityForm.controls['currency'].setValue(currency);
|
||||
this.activityForm.controls['dataSource'].setValue(dataSource);
|
||||
|
||||
this.currentMarketPrice = marketPrice;
|
||||
|
||||
this.isLoading = false;
|
||||
|
@@ -1,31 +1,45 @@
|
||||
<form #addTransactionForm="ngForm" class="d-flex flex-column h-100">
|
||||
<h1 *ngIf="data.transaction.id" mat-dialog-title i18n>Update activity</h1>
|
||||
<h1 *ngIf="!data.transaction.id" mat-dialog-title i18n>Add activity</h1>
|
||||
<form
|
||||
class="d-flex flex-column h-100"
|
||||
[formGroup]="activityForm"
|
||||
(ngSubmit)="onSubmit()"
|
||||
>
|
||||
<h1 *ngIf="data.activity.id" mat-dialog-title i18n>Update activity</h1>
|
||||
<h1 *ngIf="!data.activity.id" mat-dialog-title i18n>Add activity</h1>
|
||||
<div class="flex-grow-1" mat-dialog-content>
|
||||
<div>
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-label i18n>Type</mat-label>
|
||||
<mat-select formControlName="type">
|
||||
<mat-option value="BUY" i18n>BUY</mat-option>
|
||||
<mat-option value="DIVIDEND" i18n>DIVIDEND</mat-option>
|
||||
<mat-option value="ITEM" i18n>ITEM</mat-option>
|
||||
<mat-option value="SELL" i18n>SELL</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div
|
||||
[ngClass]="{ 'd-none': !activityForm.controls['accountId'].hasValidator(Validators.required) }"
|
||||
>
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-label i18n>Account</mat-label>
|
||||
<mat-select
|
||||
name="accountId"
|
||||
required
|
||||
[(value)]="data.transaction.accountId"
|
||||
>
|
||||
<mat-select formControlName="accountId">
|
||||
<mat-option *ngFor="let account of data.accounts" [value]="account.id"
|
||||
>{{ account.name }}</mat-option
|
||||
>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
[ngClass]="{ 'd-none': !activityForm.controls['searchSymbol'].hasValidator(Validators.required) }"
|
||||
>
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-label i18n>Symbol or ISIN</mat-label>
|
||||
<input
|
||||
autocapitalize="off"
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
formControlName="searchSymbol"
|
||||
matInput
|
||||
required
|
||||
[formControl]="searchSymbolCtrl"
|
||||
[matAutocomplete]="autocomplete"
|
||||
(blur)="onBlurSymbol()"
|
||||
/>
|
||||
@@ -48,26 +62,18 @@
|
||||
<mat-spinner *ngIf="isLoading" matSuffix [diameter]="20"></mat-spinner>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
[ngClass]="{ 'd-none': !activityForm.controls['name'].hasValidator(Validators.required) }"
|
||||
>
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-label i18n>Type</mat-label>
|
||||
<mat-select name="type" required [(value)]="data.transaction.type">
|
||||
<mat-option value="BUY" i18n>BUY</mat-option>
|
||||
<mat-option value="DIVIDEND" i18n>DIVIDEND</mat-option>
|
||||
<mat-option value="SELL" i18n>SELL</mat-option>
|
||||
</mat-select>
|
||||
<mat-label i18n>Name</mat-label>
|
||||
<input formControlName="name" matInput />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="d-none">
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-label i18n>Currency</mat-label>
|
||||
<mat-select
|
||||
class="no-arrow"
|
||||
disabled
|
||||
name="currency"
|
||||
required
|
||||
[(value)]="data.transaction.currency"
|
||||
>
|
||||
<mat-select class="no-arrow" formControlName="currency">
|
||||
<mat-option *ngFor="let currency of currencies" [value]="currency"
|
||||
>{{ currency }}</mat-option
|
||||
>
|
||||
@@ -77,26 +83,13 @@
|
||||
<div class="d-none">
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-label i18n>Data Source</mat-label>
|
||||
<input
|
||||
disabled
|
||||
matInput
|
||||
name="dataSource"
|
||||
required
|
||||
[(ngModel)]="data.transaction.dataSource"
|
||||
/>
|
||||
<input formControlName="dataSource" matInput />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div>
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-label i18n>Date</mat-label>
|
||||
<input
|
||||
disabled
|
||||
matInput
|
||||
name="date"
|
||||
required
|
||||
[matDatepicker]="date"
|
||||
[(ngModel)]="data.transaction.date"
|
||||
/>
|
||||
<input formControlName="date" matInput [matDatepicker]="date" />
|
||||
<mat-datepicker-toggle matSuffix [for]="date">
|
||||
<ion-icon
|
||||
class="text-muted"
|
||||
@@ -110,31 +103,22 @@
|
||||
<div>
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-label i18n>Quantity</mat-label>
|
||||
<input
|
||||
matInput
|
||||
name="quantity"
|
||||
required
|
||||
type="number"
|
||||
[(ngModel)]="data.transaction.quantity"
|
||||
/>
|
||||
<input formControlName="quantity" matInput type="number" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div>
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-label i18n>Unit Price</mat-label>
|
||||
<input
|
||||
matInput
|
||||
name="unitPrice"
|
||||
required
|
||||
type="number"
|
||||
[(ngModel)]="data.transaction.unitPrice"
|
||||
/>
|
||||
<span class="ml-2" matSuffix>{{ data.transaction.currency }}</span>
|
||||
<input formControlName="unitPrice" matInput type="number" />
|
||||
<span class="ml-2" matSuffix
|
||||
>{{ activityForm.controls['currency'].value }}</span
|
||||
>
|
||||
<button
|
||||
*ngIf="currentMarketPrice && (data.transaction.type === 'BUY' || data.transaction.type === 'SELL')"
|
||||
*ngIf="currentMarketPrice && (data.activity.type === 'BUY' || data.activity.type === 'SELL')"
|
||||
mat-icon-button
|
||||
matSuffix
|
||||
title="Apply current market price"
|
||||
type="button"
|
||||
(click)="applyCurrentMarketPrice()"
|
||||
>
|
||||
<ion-icon class="text-muted" name="refresh-outline"></ion-icon>
|
||||
@@ -144,32 +128,28 @@
|
||||
<div>
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-label i18n>Fee</mat-label>
|
||||
<input
|
||||
matInput
|
||||
name="fee"
|
||||
required
|
||||
type="number"
|
||||
[(ngModel)]="data.transaction.fee"
|
||||
/>
|
||||
<span class="ml-2" matSuffix>{{ data.transaction.currency }}</span>
|
||||
<input formControlName="fee" matInput type="number" />
|
||||
<span class="ml-2" matSuffix
|
||||
>{{ activityForm.controls['currency'].value }}</span
|
||||
>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex" mat-dialog-actions>
|
||||
<gf-value
|
||||
class="flex-grow-1"
|
||||
[currency]="data.transaction.currency"
|
||||
[currency]="activityForm.controls['currency'].value"
|
||||
[locale]="data.user?.settings?.locale"
|
||||
[value]="data.transaction.fee + (data.transaction.quantity * data.transaction.unitPrice)"
|
||||
[value]="activityForm.controls['fee'].value + (activityForm.controls['quantity'].value * activityForm.controls['unitPrice'].value) ?? 0"
|
||||
></gf-value>
|
||||
<div>
|
||||
<button i18n mat-button (click)="onCancel()">Cancel</button>
|
||||
<button i18n mat-button type="button" (click)="onCancel()">Cancel</button>
|
||||
<button
|
||||
color="primary"
|
||||
i18n
|
||||
mat-flat-button
|
||||
[disabled]="!(addTransactionForm.form.valid && data.transaction.currency && data.transaction.symbol)"
|
||||
[mat-dialog-close]="data"
|
||||
type="submit"
|
||||
[disabled]="!activityForm.valid"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
|
@@ -1,9 +1,10 @@
|
||||
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
|
||||
import { User } from '@ghostfolio/common/interfaces';
|
||||
import { Account, Order } from '@prisma/client';
|
||||
import { Account } from '@prisma/client';
|
||||
|
||||
export interface CreateOrUpdateTransactionDialogParams {
|
||||
accountId: string;
|
||||
accounts: Account[];
|
||||
transaction: Order;
|
||||
activity: Activity;
|
||||
user: User;
|
||||
}
|
||||
|
@@ -132,8 +132,8 @@ export class TransactionsPageComponent implements OnDestroy, OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
public onCloneTransaction(aTransaction: OrderModel) {
|
||||
this.openCreateTransactionDialog(aTransaction);
|
||||
public onCloneTransaction(aActivity: Activity) {
|
||||
this.openCreateTransactionDialog(aActivity);
|
||||
}
|
||||
|
||||
public onDeleteTransaction(aId: string) {
|
||||
@@ -242,35 +242,13 @@ export class TransactionsPageComponent implements OnDestroy, OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
public openUpdateTransactionDialog({
|
||||
accountId,
|
||||
currency,
|
||||
dataSource,
|
||||
date,
|
||||
fee,
|
||||
id,
|
||||
quantity,
|
||||
symbol,
|
||||
type,
|
||||
unitPrice
|
||||
}: OrderModel): void {
|
||||
public openUpdateTransactionDialog(activity: Activity): void {
|
||||
const dialogRef = this.dialog.open(CreateOrUpdateTransactionDialog, {
|
||||
data: {
|
||||
activity,
|
||||
accounts: this.user?.accounts?.filter((account) => {
|
||||
return account.accountType === 'SECURITIES';
|
||||
}),
|
||||
transaction: {
|
||||
accountId,
|
||||
currency,
|
||||
dataSource,
|
||||
date,
|
||||
fee,
|
||||
id,
|
||||
quantity,
|
||||
symbol,
|
||||
type,
|
||||
unitPrice
|
||||
},
|
||||
user: this.user
|
||||
},
|
||||
height: this.deviceType === 'mobile' ? '97.5vh' : '80vh',
|
||||
@@ -281,7 +259,7 @@ export class TransactionsPageComponent implements OnDestroy, OnInit {
|
||||
.afterClosed()
|
||||
.pipe(takeUntil(this.unsubscribeSubject))
|
||||
.subscribe((data: any) => {
|
||||
const transaction: UpdateOrderDto = data?.transaction;
|
||||
const transaction: UpdateOrderDto = data?.activity;
|
||||
|
||||
if (transaction) {
|
||||
this.dataService
|
||||
@@ -324,7 +302,7 @@ export class TransactionsPageComponent implements OnDestroy, OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
private openCreateTransactionDialog(aTransaction?: OrderModel): void {
|
||||
private openCreateTransactionDialog(aActivity?: Activity): void {
|
||||
this.userService
|
||||
.get()
|
||||
.pipe(takeUntil(this.unsubscribeSubject))
|
||||
@@ -336,15 +314,14 @@ export class TransactionsPageComponent implements OnDestroy, OnInit {
|
||||
accounts: this.user?.accounts?.filter((account) => {
|
||||
return account.accountType === 'SECURITIES';
|
||||
}),
|
||||
transaction: {
|
||||
accountId: aTransaction?.accountId ?? this.defaultAccountId,
|
||||
currency: aTransaction?.currency ?? null,
|
||||
dataSource: aTransaction?.dataSource ?? null,
|
||||
activity: {
|
||||
...aActivity,
|
||||
accountId: aActivity?.accountId ?? this.defaultAccountId,
|
||||
date: new Date(),
|
||||
id: null,
|
||||
fee: 0,
|
||||
quantity: null,
|
||||
symbol: aTransaction?.symbol ?? null,
|
||||
type: aTransaction?.type ?? 'BUY',
|
||||
type: aActivity?.type ?? 'BUY',
|
||||
unitPrice: null
|
||||
},
|
||||
user: this.user
|
||||
@@ -357,7 +334,7 @@ export class TransactionsPageComponent implements OnDestroy, OnInit {
|
||||
.afterClosed()
|
||||
.pipe(takeUntil(this.unsubscribeSubject))
|
||||
.subscribe((data: any) => {
|
||||
const transaction: CreateOrderDto = data?.transaction;
|
||||
const transaction: CreateOrderDto = data?.activity;
|
||||
|
||||
if (transaction) {
|
||||
this.dataService.postOrder(transaction).subscribe({
|
||||
|
@@ -6,7 +6,7 @@ import { DATE_FORMAT } from '@ghostfolio/common/helper';
|
||||
import { AdminMarketDataDetails } from '@ghostfolio/common/interfaces';
|
||||
import { DataSource, MarketData } from '@prisma/client';
|
||||
import { format, parseISO } from 'date-fns';
|
||||
import { map, Observable } from 'rxjs';
|
||||
import { Observable, map } from 'rxjs';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
@@ -245,6 +245,8 @@ export class ImportTransactionsService {
|
||||
return Type.BUY;
|
||||
case 'dividend':
|
||||
return Type.DIVIDEND;
|
||||
case 'item':
|
||||
return Type.ITEM;
|
||||
case 'sell':
|
||||
return Type.SELL;
|
||||
default:
|
||||
|
Reference in New Issue
Block a user