Feature/add currency to order database schema (#3251)
* Add currency to Order database schema * Update changelog
This commit is contained in:
parent
719bbe156e
commit
07c0e5a612
@ -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…
x
Reference in New Issue
Block a user