Feature/add currency to order database schema (#3251)

* Add currency to Order database schema

* Update changelog
pull/3252/head
Thomas Kaul 2 months ago committed by GitHub
parent 719bbe156e
commit 07c0e5a612
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added the asset profile icon to the asset profile details dialog of the admin control
- Added the platform icon to the create or update platform dialog of the admin control
- Extended the rules in the _X-ray_ section by a `key`
- Added `currency` to the `Order` database schema as a preparation to set a custom currency
- Extended the content of the _Self-Hosting_ section by the data providers on the Frequently Asked Questions (FAQ) page
### Changed

@ -112,6 +112,7 @@ export class ImportService {
accountId: Account?.id,
accountUserId: undefined,
comment: undefined,
currency: undefined,
createdAt: undefined,
fee: 0,
feeInBaseCurrency: 0,
@ -261,6 +262,7 @@ export class ImportService {
{
accountId,
comment,
currency,
date,
error,
fee,
@ -285,7 +287,6 @@ export class ImportService {
assetSubClass,
countries,
createdAt,
currency,
dataSource,
figi,
figiComposite,
@ -342,6 +343,7 @@ export class ImportService {
if (isDryRun) {
order = {
comment,
currency,
date,
fee,
quantity,
@ -357,7 +359,6 @@ export class ImportService {
assetSubClass,
countries,
createdAt,
currency,
dataSource,
figi,
figiComposite,
@ -371,6 +372,7 @@ export class ImportService {
symbolMapping,
updatedAt,
url,
currency: assetProfile.currency,
comment: assetProfile.comment
},
Account: validatedAccount,
@ -394,9 +396,9 @@ export class ImportService {
SymbolProfile: {
connectOrCreate: {
create: {
currency,
dataSource,
symbol
symbol,
currency: assetProfile.currency
},
where: {
dataSource_symbol: {
@ -420,14 +422,14 @@ export class ImportService {
value,
feeInBaseCurrency: this.exchangeRateDataService.toCurrency(
fee,
currency,
assetProfile.currency,
userCurrency
),
// @ts-ignore
SymbolProfile: assetProfile,
valueInBaseCurrency: this.exchangeRateDataService.toCurrency(
value,
currency,
assetProfile.currency,
userCurrency
)
});

@ -42,6 +42,10 @@ export class CreateOrderDto {
@IsISO4217CurrencyCode()
currency: string;
@IsISO4217CurrencyCode()
@IsOptional()
customCurrency?: string;
@IsOptional()
@IsEnum(DataSource, { each: true })
dataSource?: DataSource;

@ -126,13 +126,22 @@ export class OrderController {
@UseGuards(AuthGuard('jwt'), HasPermissionGuard)
@UseInterceptors(TransformDataSourceInRequestInterceptor)
public async createOrder(@Body() data: CreateOrderDto): Promise<OrderModel> {
const currency = data.currency;
const customCurrency = data.customCurrency;
if (customCurrency) {
data.currency = customCurrency;
delete data.customCurrency;
}
const order = await this.orderService.createOrder({
...data,
date: parseISO(data.date),
SymbolProfile: {
connectOrCreate: {
create: {
currency: data.currency,
currency,
dataSource: data.dataSource,
symbol: data.symbol
},
@ -182,8 +191,16 @@ export class OrderController {
const date = parseISO(data.date);
const accountId = data.accountId;
const customCurrency = data.customCurrency;
delete data.accountId;
if (customCurrency) {
data.currency = customCurrency;
delete data.customCurrency;
}
return this.orderService.updateOrder({
data: {
...data,

@ -26,6 +26,7 @@ import { endOfToday, isAfter } from 'date-fns';
import { groupBy, uniqBy } from 'lodash';
import { v4 as uuidv4 } from 'uuid';
import { CreateOrderDto } from './create-order.dto';
import { Activities } from './interfaces/activities.interface';
@Injectable()
@ -65,7 +66,6 @@ export class OrderService {
}
const accountId = data.accountId;
let currency = data.currency;
const tags = data.tags ?? [];
const updateAccountBalance = data.updateAccountBalance ?? false;
const userId = data.userId;
@ -73,7 +73,6 @@ export class OrderService {
if (['FEE', 'INTEREST', 'ITEM', 'LIABILITY'].includes(data.type)) {
const assetClass = data.assetClass;
const assetSubClass = data.assetSubClass;
currency = data.SymbolProfile.connectOrCreate.create.currency;
const dataSource: DataSource = 'MANUAL';
const id = uuidv4();
const name = data.SymbolProfile.connectOrCreate.create.symbol;
@ -81,7 +80,6 @@ export class OrderService {
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.dataSource = dataSource;
data.SymbolProfile.connectOrCreate.create.name = name;
data.SymbolProfile.connectOrCreate.create.symbol = id;
@ -116,7 +114,6 @@ export class OrderService {
delete data.comment;
}
delete data.currency;
delete data.dataSource;
delete data.symbol;
delete data.tags;
@ -155,8 +152,8 @@ export class OrderService {
await this.accountService.updateAccountBalance({
accountId,
amount,
currency,
userId,
currency: data.SymbolProfile.connectOrCreate.create.currency,
date: data.date as Date
});
}
@ -442,7 +439,6 @@ export class OrderService {
delete data.assetClass;
delete data.assetSubClass;
delete data.currency;
delete data.dataSource;
delete data.symbol;
delete data.tags;

@ -41,6 +41,10 @@ export class UpdateOrderDto {
@IsISO4217CurrencyCode()
currency: string;
@IsISO4217CurrencyCode()
@IsOptional()
customCurrency?: string;
@IsString()
dataSource: DataSource;

@ -3,6 +3,7 @@ export const activityDummyData = {
accountUserId: undefined,
comment: undefined,
createdAt: new Date(),
currency: undefined,
feeInBaseCurrency: undefined,
id: undefined,
isDraft: false,

@ -98,10 +98,6 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
this.data.activity?.SymbolProfile?.currency,
Validators.required
],
currencyOfFee: [
this.data.activity?.SymbolProfile?.currency,
Validators.required
],
currencyOfUnitPrice: [
this.data.activity?.SymbolProfile?.currency,
Validators.required
@ -149,45 +145,16 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
takeUntil(this.unsubscribeSubject)
)
.subscribe(async () => {
let exchangeRateOfFee = 1;
let exchangeRateOfUnitPrice = 1;
this.activityForm.controls['feeInCustomCurrency'].setErrors(null);
this.activityForm.controls['unitPriceInCustomCurrency'].setErrors(null);
const currency = this.activityForm.controls['currency'].value;
const currencyOfFee = this.activityForm.controls['currencyOfFee'].value;
const currencyOfUnitPrice =
this.activityForm.controls['currencyOfUnitPrice'].value;
const date = this.activityForm.controls['date'].value;
if (currency && currencyOfFee && currency !== currencyOfFee && date) {
try {
const { marketPrice } = await lastValueFrom(
this.dataService
.fetchExchangeRateForDate({
date,
symbol: `${currencyOfFee}-${currency}`
})
.pipe(takeUntil(this.unsubscribeSubject))
);
exchangeRateOfFee = marketPrice;
} catch {
this.activityForm.controls['feeInCustomCurrency'].setErrors({
invalid: true
});
}
}
const feeInCustomCurrency =
this.activityForm.controls['feeInCustomCurrency'].value *
exchangeRateOfFee;
this.activityForm.controls['fee'].setValue(feeInCustomCurrency, {
emitEvent: false
});
if (
currency &&
currencyOfUnitPrice &&
@ -212,10 +179,18 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
}
}
const feeInCustomCurrency =
this.activityForm.controls['feeInCustomCurrency'].value *
exchangeRateOfUnitPrice;
const unitPriceInCustomCurrency =
this.activityForm.controls['unitPriceInCustomCurrency'].value *
exchangeRateOfUnitPrice;
this.activityForm.controls['fee'].setValue(feeInCustomCurrency, {
emitEvent: false
});
this.activityForm.controls['unitPrice'].setValue(
unitPriceInCustomCurrency,
{
@ -258,7 +233,6 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
})?.currency ?? this.data.user.settings.baseCurrency;
this.activityForm.controls['currency'].setValue(currency);
this.activityForm.controls['currencyOfFee'].setValue(currency);
this.activityForm.controls['currencyOfUnitPrice'].setValue(currency);
if (['FEE', 'INTEREST'].includes(type)) {
@ -328,7 +302,6 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
})?.currency ?? this.data.user.settings.baseCurrency;
this.activityForm.controls['currency'].setValue(currency);
this.activityForm.controls['currencyOfFee'].setValue(currency);
this.activityForm.controls['currencyOfUnitPrice'].setValue(currency);
this.activityForm.controls['dataSource'].removeValidators(
@ -361,7 +334,6 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
})?.currency ?? this.data.user.settings.baseCurrency;
this.activityForm.controls['currency'].setValue(currency);
this.activityForm.controls['currencyOfFee'].setValue(currency);
this.activityForm.controls['currencyOfUnitPrice'].setValue(currency);
this.activityForm.controls['dataSource'].removeValidators(
@ -486,6 +458,7 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
assetSubClass: this.activityForm.controls['assetSubClass'].value,
comment: this.activityForm.controls['comment'].value,
currency: this.activityForm.controls['currency'].value,
customCurrency: this.activityForm.controls['currencyOfUnitPrice'].value,
date: this.activityForm.controls['date'].value,
dataSource: this.activityForm.controls['dataSource'].value,
fee: this.activityForm.controls['fee'].value,
@ -549,7 +522,6 @@ export class CreateOrUpdateActivityDialog implements OnDestroy {
)
.subscribe(({ currency, dataSource, marketPrice }) => {
this.activityForm.controls['currency'].setValue(currency);
this.activityForm.controls['currencyOfFee'].setValue(currency);
this.activityForm.controls['currencyOfUnitPrice'].setValue(currency);
this.activityForm.controls['dataSource'].setValue(dataSource);

@ -290,11 +290,7 @@
matTextSuffix
[ngClass]="{ 'd-none': !activityForm.controls['currency']?.value }"
>
<mat-select formControlName="currencyOfFee">
<mat-option *ngFor="let currency of currencies" [value]="currency">
{{ currency }}
</mat-option>
</mat-select>
{{ activityForm.controls['currencyOfUnitPrice'].value }}
</div>
<mat-error
*ngIf="

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Order" ADD COLUMN "currency" TEXT;

@ -109,6 +109,7 @@ model Order {
accountUserId String?
comment String?
createdAt DateTime @default(now())
currency String?
date DateTime
fee Float
id String @id @default(uuid())

Loading…
Cancel
Save