Feature/add asset and asset sub class to wealth items form (#880)
* Add asset and asset sub class * Update changelog
This commit is contained in:
parent
e9e9f1a124
commit
01103f3db4
@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Extended the form to set the asset and asset sub class for (wealth) items
|
||||||
|
|
||||||
## 1.144.0 - 30.04.2022
|
## 1.144.0 - 30.04.2022
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { DataSource, Type } from '@prisma/client';
|
import { AssetClass, AssetSubClass, DataSource, Type } from '@prisma/client';
|
||||||
import {
|
import {
|
||||||
IsEnum,
|
IsEnum,
|
||||||
IsISO8601,
|
IsISO8601,
|
||||||
@ -10,14 +10,22 @@ import {
|
|||||||
export class CreateOrderDto {
|
export class CreateOrderDto {
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
accountId: string;
|
accountId?: string;
|
||||||
|
|
||||||
|
@IsEnum(AssetClass, { each: true })
|
||||||
|
@IsOptional()
|
||||||
|
assetClass?: AssetClass;
|
||||||
|
|
||||||
|
@IsEnum(AssetSubClass, { each: true })
|
||||||
|
@IsOptional()
|
||||||
|
assetSubClass?: AssetSubClass;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
currency: string;
|
currency: string;
|
||||||
|
|
||||||
@IsEnum(DataSource, { each: true })
|
@IsEnum(DataSource, { each: true })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
dataSource: DataSource;
|
dataSource?: DataSource;
|
||||||
|
|
||||||
@IsISO8601()
|
@IsISO8601()
|
||||||
date: string;
|
date: string;
|
||||||
|
@ -171,6 +171,11 @@ export class OrderController {
|
|||||||
dataSource: data.dataSource,
|
dataSource: data.dataSource,
|
||||||
symbol: data.symbol
|
symbol: data.symbol
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
assetClass: data.assetClass,
|
||||||
|
assetSubClass: data.assetSubClass,
|
||||||
|
name: data.symbol
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
User: { connect: { id: this.request.user.id } }
|
User: { connect: { id: this.request.user.id } }
|
||||||
|
@ -6,7 +6,14 @@ import { PrismaService } from '@ghostfolio/api/services/prisma.service';
|
|||||||
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile.service';
|
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile.service';
|
||||||
import { OrderWithAccount } from '@ghostfolio/common/types';
|
import { OrderWithAccount } from '@ghostfolio/common/types';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { DataSource, Order, Prisma, Type as TypeOfOrder } from '@prisma/client';
|
import {
|
||||||
|
AssetClass,
|
||||||
|
AssetSubClass,
|
||||||
|
DataSource,
|
||||||
|
Order,
|
||||||
|
Prisma,
|
||||||
|
Type as TypeOfOrder
|
||||||
|
} from '@prisma/client';
|
||||||
import Big from 'big.js';
|
import Big from 'big.js';
|
||||||
import { endOfToday, isAfter } from 'date-fns';
|
import { endOfToday, isAfter } from 'date-fns';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
@ -55,6 +62,8 @@ export class OrderService {
|
|||||||
public async createOrder(
|
public async createOrder(
|
||||||
data: Prisma.OrderCreateInput & {
|
data: Prisma.OrderCreateInput & {
|
||||||
accountId?: string;
|
accountId?: string;
|
||||||
|
assetClass?: AssetClass;
|
||||||
|
assetSubClass?: AssetSubClass;
|
||||||
currency?: string;
|
currency?: string;
|
||||||
dataSource?: DataSource;
|
dataSource?: DataSource;
|
||||||
symbol?: string;
|
symbol?: string;
|
||||||
@ -77,6 +86,8 @@ export class OrderService {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (data.type === 'ITEM') {
|
if (data.type === 'ITEM') {
|
||||||
|
const assetClass = data.assetClass;
|
||||||
|
const assetSubClass = data.assetSubClass;
|
||||||
const currency = data.SymbolProfile.connectOrCreate.create.currency;
|
const currency = data.SymbolProfile.connectOrCreate.create.currency;
|
||||||
const dataSource: DataSource = 'MANUAL';
|
const dataSource: DataSource = 'MANUAL';
|
||||||
const id = uuidv4();
|
const id = uuidv4();
|
||||||
@ -84,6 +95,8 @@ export class OrderService {
|
|||||||
|
|
||||||
Account = undefined;
|
Account = undefined;
|
||||||
data.id = id;
|
data.id = id;
|
||||||
|
data.SymbolProfile.connectOrCreate.create.assetClass = assetClass;
|
||||||
|
data.SymbolProfile.connectOrCreate.create.assetSubClass = assetSubClass;
|
||||||
data.SymbolProfile.connectOrCreate.create.currency = currency;
|
data.SymbolProfile.connectOrCreate.create.currency = currency;
|
||||||
data.SymbolProfile.connectOrCreate.create.dataSource = dataSource;
|
data.SymbolProfile.connectOrCreate.create.dataSource = dataSource;
|
||||||
data.SymbolProfile.connectOrCreate.create.name = name;
|
data.SymbolProfile.connectOrCreate.create.name = name;
|
||||||
@ -120,6 +133,8 @@ export class OrderService {
|
|||||||
await this.cacheService.flush();
|
await this.cacheService.flush();
|
||||||
|
|
||||||
delete data.accountId;
|
delete data.accountId;
|
||||||
|
delete data.assetClass;
|
||||||
|
delete data.assetSubClass;
|
||||||
delete data.currency;
|
delete data.currency;
|
||||||
delete data.dataSource;
|
delete data.dataSource;
|
||||||
delete data.symbol;
|
delete data.symbol;
|
||||||
@ -232,6 +247,8 @@ export class OrderService {
|
|||||||
where
|
where
|
||||||
}: {
|
}: {
|
||||||
data: Prisma.OrderUpdateInput & {
|
data: Prisma.OrderUpdateInput & {
|
||||||
|
assetClass?: AssetClass;
|
||||||
|
assetSubClass?: AssetSubClass;
|
||||||
currency?: string;
|
currency?: string;
|
||||||
dataSource?: DataSource;
|
dataSource?: DataSource;
|
||||||
symbol?: string;
|
symbol?: string;
|
||||||
@ -245,10 +262,10 @@ export class OrderService {
|
|||||||
let isDraft = false;
|
let isDraft = false;
|
||||||
|
|
||||||
if (data.type === 'ITEM') {
|
if (data.type === 'ITEM') {
|
||||||
const name = data.SymbolProfile.connect.dataSource_symbol.symbol;
|
delete data.SymbolProfile.connect;
|
||||||
|
|
||||||
data.SymbolProfile = { update: { name } };
|
|
||||||
} else {
|
} else {
|
||||||
|
delete data.SymbolProfile.update;
|
||||||
|
|
||||||
isDraft = isAfter(data.date as Date, endOfToday());
|
isDraft = isAfter(data.date as Date, endOfToday());
|
||||||
|
|
||||||
if (!isDraft) {
|
if (!isDraft) {
|
||||||
@ -265,6 +282,8 @@ export class OrderService {
|
|||||||
|
|
||||||
await this.cacheService.flush();
|
await this.cacheService.flush();
|
||||||
|
|
||||||
|
delete data.assetClass;
|
||||||
|
delete data.assetSubClass;
|
||||||
delete data.currency;
|
delete data.currency;
|
||||||
delete data.dataSource;
|
delete data.dataSource;
|
||||||
delete data.symbol;
|
delete data.symbol;
|
||||||
|
@ -1,10 +1,24 @@
|
|||||||
import { DataSource, Type } from '@prisma/client';
|
import { AssetClass, AssetSubClass, DataSource, Type } from '@prisma/client';
|
||||||
import { IsISO8601, IsNumber, IsOptional, IsString } from 'class-validator';
|
import {
|
||||||
|
IsEnum,
|
||||||
|
IsISO8601,
|
||||||
|
IsNumber,
|
||||||
|
IsOptional,
|
||||||
|
IsString
|
||||||
|
} from 'class-validator';
|
||||||
|
|
||||||
export class UpdateOrderDto {
|
export class UpdateOrderDto {
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsString()
|
@IsString()
|
||||||
accountId: string;
|
accountId?: string;
|
||||||
|
|
||||||
|
@IsEnum(AssetClass, { each: true })
|
||||||
|
@IsOptional()
|
||||||
|
assetClass?: AssetClass;
|
||||||
|
|
||||||
|
@IsEnum(AssetSubClass, { each: true })
|
||||||
|
@IsOptional()
|
||||||
|
assetSubClass?: AssetSubClass;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
currency: string;
|
currency: string;
|
||||||
|
@ -13,7 +13,7 @@ import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto';
|
|||||||
import { UpdateOrderDto } from '@ghostfolio/api/app/order/update-order.dto';
|
import { UpdateOrderDto } from '@ghostfolio/api/app/order/update-order.dto';
|
||||||
import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface';
|
import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface';
|
||||||
import { DataService } from '@ghostfolio/client/services/data.service';
|
import { DataService } from '@ghostfolio/client/services/data.service';
|
||||||
import { Type } from '@prisma/client';
|
import { AssetClass, AssetSubClass, Type } from '@prisma/client';
|
||||||
import { isUUID } from 'class-validator';
|
import { isUUID } from 'class-validator';
|
||||||
import { isString } from 'lodash';
|
import { isString } from 'lodash';
|
||||||
import { EMPTY, Observable, Subject } from 'rxjs';
|
import { EMPTY, Observable, Subject } from 'rxjs';
|
||||||
@ -39,7 +39,8 @@ export class CreateOrUpdateTransactionDialog implements OnDestroy {
|
|||||||
@ViewChild('autocomplete') autocomplete;
|
@ViewChild('autocomplete') autocomplete;
|
||||||
|
|
||||||
public activityForm: FormGroup;
|
public activityForm: FormGroup;
|
||||||
|
public assetClasses = Object.keys(AssetClass);
|
||||||
|
public assetSubClasses = Object.keys(AssetSubClass);
|
||||||
public currencies: string[] = [];
|
public currencies: string[] = [];
|
||||||
public currentMarketPrice = null;
|
public currentMarketPrice = null;
|
||||||
public filteredLookupItems: LookupItem[];
|
public filteredLookupItems: LookupItem[];
|
||||||
@ -67,6 +68,8 @@ export class CreateOrUpdateTransactionDialog implements OnDestroy {
|
|||||||
|
|
||||||
this.activityForm = this.formBuilder.group({
|
this.activityForm = this.formBuilder.group({
|
||||||
accountId: [this.data.activity?.accountId, Validators.required],
|
accountId: [this.data.activity?.accountId, Validators.required],
|
||||||
|
assetClass: [this.data.activity?.SymbolProfile?.assetClass],
|
||||||
|
assetSubClass: [this.data.activity?.SymbolProfile?.assetSubClass],
|
||||||
currency: [
|
currency: [
|
||||||
this.data.activity?.SymbolProfile?.currency,
|
this.data.activity?.SymbolProfile?.currency,
|
||||||
Validators.required
|
Validators.required
|
||||||
@ -234,6 +237,8 @@ export class CreateOrUpdateTransactionDialog implements OnDestroy {
|
|||||||
public onSubmit() {
|
public onSubmit() {
|
||||||
const activity: CreateOrderDto | UpdateOrderDto = {
|
const activity: CreateOrderDto | UpdateOrderDto = {
|
||||||
accountId: this.activityForm.controls['accountId'].value,
|
accountId: this.activityForm.controls['accountId'].value,
|
||||||
|
assetClass: this.activityForm.controls['assetClass'].value,
|
||||||
|
assetSubClass: this.activityForm.controls['assetSubClass'].value,
|
||||||
currency: this.activityForm.controls['currency'].value,
|
currency: this.activityForm.controls['currency'].value,
|
||||||
date: this.activityForm.controls['date'].value,
|
date: this.activityForm.controls['date'].value,
|
||||||
dataSource: this.activityForm.controls['dataSource'].value,
|
dataSource: this.activityForm.controls['dataSource'].value,
|
||||||
|
@ -134,6 +134,36 @@
|
|||||||
>
|
>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
[ngClass]="{ 'd-none': activityForm.controls['type']?.value !== 'ITEM' }"
|
||||||
|
>
|
||||||
|
<mat-form-field appearance="outline" class="w-100">
|
||||||
|
<mat-label i18n>Asset Class</mat-label>
|
||||||
|
<mat-select formControlName="assetClass">
|
||||||
|
<mat-option [value]="null"></mat-option>
|
||||||
|
<mat-option
|
||||||
|
*ngFor="let assetClass of assetClasses"
|
||||||
|
[value]="assetClass"
|
||||||
|
>{{ assetClass }}</mat-option
|
||||||
|
>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
[ngClass]="{ 'd-none': activityForm.controls['type']?.value !== 'ITEM' }"
|
||||||
|
>
|
||||||
|
<mat-form-field appearance="outline" class="w-100">
|
||||||
|
<mat-label i18n>Asset Sub-Class</mat-label>
|
||||||
|
<mat-select formControlName="assetSubClass">
|
||||||
|
<mat-option [value]="null"></mat-option>
|
||||||
|
<mat-option
|
||||||
|
*ngFor="let assetSubClass of assetSubClasses"
|
||||||
|
[value]="assetSubClass"
|
||||||
|
>{{ assetSubClass }}</mat-option
|
||||||
|
>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
[ngClass]="{ 'd-none': activityForm.controls['tags']?.value?.length <= 0 }"
|
[ngClass]="{ 'd-none': activityForm.controls['tags']?.value?.length <= 0 }"
|
||||||
>
|
>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user