Eliminate data source from order model (#730)
* Eliminate currency, data source and symbol from order model * Remove prefix for symbols with data source GHOSTFOLIO * Update changelog
This commit is contained in:
parent
86acbf06f4
commit
c216ab1d76
@ -11,10 +11,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
- Included data provider errors in API response
|
- Included data provider errors in API response
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Removed the redundant attributes (`currency`, `dataSource`, `symbol`) of the activity model
|
||||||
|
- Removed the prefix for symbols with the data source `GHOSTFOLIO`
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Improved the account calculations
|
- Improved the account calculations
|
||||||
|
|
||||||
|
### Todo
|
||||||
|
|
||||||
|
- Apply data migration (`yarn database:migrate`)
|
||||||
|
|
||||||
## 1.122.0 - 01.03.2022
|
## 1.122.0 - 01.03.2022
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -18,8 +18,6 @@ export class ExportService {
|
|||||||
orderBy: { date: 'desc' },
|
orderBy: { date: 'desc' },
|
||||||
select: {
|
select: {
|
||||||
accountId: true,
|
accountId: true,
|
||||||
currency: true,
|
|
||||||
dataSource: true,
|
|
||||||
date: true,
|
date: true,
|
||||||
fee: true,
|
fee: true,
|
||||||
id: true,
|
id: true,
|
||||||
@ -42,7 +40,6 @@ export class ExportService {
|
|||||||
orders: orders.map(
|
orders: orders.map(
|
||||||
({
|
({
|
||||||
accountId,
|
accountId,
|
||||||
currency,
|
|
||||||
date,
|
date,
|
||||||
fee,
|
fee,
|
||||||
quantity,
|
quantity,
|
||||||
@ -52,12 +49,12 @@ export class ExportService {
|
|||||||
}) => {
|
}) => {
|
||||||
return {
|
return {
|
||||||
accountId,
|
accountId,
|
||||||
currency,
|
|
||||||
date,
|
date,
|
||||||
fee,
|
fee,
|
||||||
quantity,
|
quantity,
|
||||||
type,
|
type,
|
||||||
unitPrice,
|
unitPrice,
|
||||||
|
currency: SymbolProfile.currency,
|
||||||
dataSource: SymbolProfile.dataSource,
|
dataSource: SymbolProfile.dataSource,
|
||||||
symbol: type === 'ITEM' ? SymbolProfile.name : SymbolProfile.symbol
|
symbol: type === 'ITEM' ? SymbolProfile.name : SymbolProfile.symbol
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto';
|
import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto';
|
||||||
import { Order } from '@prisma/client';
|
|
||||||
import { Type } from 'class-transformer';
|
import { Type } from 'class-transformer';
|
||||||
import { IsArray, ValidateNested } from 'class-validator';
|
import { IsArray, ValidateNested } from 'class-validator';
|
||||||
|
|
||||||
@ -7,5 +6,5 @@ export class ImportDataDto {
|
|||||||
@IsArray()
|
@IsArray()
|
||||||
@Type(() => CreateOrderDto)
|
@Type(() => CreateOrderDto)
|
||||||
@ValidateNested({ each: true })
|
@ValidateNested({ each: true })
|
||||||
orders: Order[];
|
orders: CreateOrderDto[];
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@ import { OrderService } from '@ghostfolio/api/app/order/order.service';
|
|||||||
import { ConfigurationService } from '@ghostfolio/api/services/configuration.service';
|
import { ConfigurationService } from '@ghostfolio/api/services/configuration.service';
|
||||||
import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service';
|
import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { Order } from '@prisma/client';
|
|
||||||
import { isSameDay, parseISO } from 'date-fns';
|
import { isSameDay, parseISO } from 'date-fns';
|
||||||
|
import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ImportService {
|
export class ImportService {
|
||||||
@ -19,7 +19,7 @@ export class ImportService {
|
|||||||
orders,
|
orders,
|
||||||
userId
|
userId
|
||||||
}: {
|
}: {
|
||||||
orders: Partial<Order>[];
|
orders: Partial<CreateOrderDto>[];
|
||||||
userId: string;
|
userId: string;
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
for (const order of orders) {
|
for (const order of orders) {
|
||||||
@ -52,11 +52,8 @@ export class ImportService {
|
|||||||
unitPrice
|
unitPrice
|
||||||
} of orders) {
|
} of orders) {
|
||||||
await this.orderService.createOrder({
|
await this.orderService.createOrder({
|
||||||
currency,
|
|
||||||
dataSource,
|
|
||||||
fee,
|
fee,
|
||||||
quantity,
|
quantity,
|
||||||
symbol,
|
|
||||||
type,
|
type,
|
||||||
unitPrice,
|
unitPrice,
|
||||||
userId,
|
userId,
|
||||||
@ -65,6 +62,7 @@ export class ImportService {
|
|||||||
SymbolProfile: {
|
SymbolProfile: {
|
||||||
connectOrCreate: {
|
connectOrCreate: {
|
||||||
create: {
|
create: {
|
||||||
|
currency,
|
||||||
dataSource,
|
dataSource,
|
||||||
symbol
|
symbol
|
||||||
},
|
},
|
||||||
@ -85,7 +83,7 @@ export class ImportService {
|
|||||||
orders,
|
orders,
|
||||||
userId
|
userId
|
||||||
}: {
|
}: {
|
||||||
orders: Partial<Order>[];
|
orders: Partial<CreateOrderDto>[];
|
||||||
userId: string;
|
userId: string;
|
||||||
}) {
|
}) {
|
||||||
if (
|
if (
|
||||||
@ -99,6 +97,7 @@ export class ImportService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const existingOrders = await this.orderService.orders({
|
const existingOrders = await this.orderService.orders({
|
||||||
|
include: { SymbolProfile: true },
|
||||||
orderBy: { date: 'desc' },
|
orderBy: { date: 'desc' },
|
||||||
where: { userId }
|
where: { userId }
|
||||||
});
|
});
|
||||||
@ -109,12 +108,12 @@ export class ImportService {
|
|||||||
] of orders.entries()) {
|
] of orders.entries()) {
|
||||||
const duplicateOrder = existingOrders.find((order) => {
|
const duplicateOrder = existingOrders.find((order) => {
|
||||||
return (
|
return (
|
||||||
order.currency === currency &&
|
order.SymbolProfile.currency === currency &&
|
||||||
order.dataSource === dataSource &&
|
order.SymbolProfile.dataSource === dataSource &&
|
||||||
isSameDay(order.date, parseISO(<string>(<unknown>date))) &&
|
isSameDay(order.date, parseISO(<string>(<unknown>date))) &&
|
||||||
order.fee === fee &&
|
order.fee === fee &&
|
||||||
order.quantity === quantity &&
|
order.quantity === quantity &&
|
||||||
order.symbol === symbol &&
|
order.SymbolProfile.symbol === symbol &&
|
||||||
order.type === type &&
|
order.type === type &&
|
||||||
order.unitPrice === unitPrice
|
order.unitPrice === unitPrice
|
||||||
);
|
);
|
||||||
|
@ -114,6 +114,7 @@ export class OrderController {
|
|||||||
SymbolProfile: {
|
SymbolProfile: {
|
||||||
connectOrCreate: {
|
connectOrCreate: {
|
||||||
create: {
|
create: {
|
||||||
|
currency: data.currency,
|
||||||
dataSource: data.dataSource,
|
dataSource: data.dataSource,
|
||||||
symbol: data.symbol
|
symbol: data.symbol
|
||||||
},
|
},
|
||||||
@ -171,6 +172,14 @@ export class OrderController {
|
|||||||
id_userId: { id: accountId, userId: this.request.user.id }
|
id_userId: { id: accountId, userId: this.request.user.id }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
SymbolProfile: {
|
||||||
|
connect: {
|
||||||
|
dataSource_symbol: {
|
||||||
|
dataSource: data.dataSource,
|
||||||
|
symbol: data.symbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
User: { connect: { id: this.request.user.id } }
|
User: { connect: { id: this.request.user.id } }
|
||||||
},
|
},
|
||||||
where: {
|
where: {
|
||||||
|
@ -53,7 +53,13 @@ export class OrderService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async createOrder(
|
public async createOrder(
|
||||||
data: Prisma.OrderCreateInput & { accountId?: string; userId: string }
|
data: Prisma.OrderCreateInput & {
|
||||||
|
accountId?: string;
|
||||||
|
currency?: string;
|
||||||
|
dataSource?: DataSource;
|
||||||
|
symbol?: string;
|
||||||
|
userId: string;
|
||||||
|
}
|
||||||
): Promise<Order> {
|
): Promise<Order> {
|
||||||
const defaultAccount = (
|
const defaultAccount = (
|
||||||
await this.accountService.getAccounts(data.userId)
|
await this.accountService.getAccounts(data.userId)
|
||||||
@ -71,15 +77,13 @@ export class OrderService {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (data.type === 'ITEM') {
|
if (data.type === 'ITEM') {
|
||||||
const currency = data.currency;
|
const currency = data.SymbolProfile.connectOrCreate.create.currency;
|
||||||
const dataSource: DataSource = 'MANUAL';
|
const dataSource: DataSource = 'MANUAL';
|
||||||
const id = uuidv4();
|
const id = uuidv4();
|
||||||
const name = data.SymbolProfile.connectOrCreate.create.symbol;
|
const name = data.SymbolProfile.connectOrCreate.create.symbol;
|
||||||
|
|
||||||
Account = undefined;
|
Account = undefined;
|
||||||
data.dataSource = dataSource;
|
|
||||||
data.id = id;
|
data.id = id;
|
||||||
data.symbol = null;
|
|
||||||
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;
|
||||||
@ -95,7 +99,7 @@ export class OrderService {
|
|||||||
|
|
||||||
await this.dataGatheringService.gatherProfileData([
|
await this.dataGatheringService.gatherProfileData([
|
||||||
{
|
{
|
||||||
dataSource: data.dataSource,
|
dataSource: data.SymbolProfile.connectOrCreate.create.dataSource,
|
||||||
symbol: data.SymbolProfile.connectOrCreate.create.symbol
|
symbol: data.SymbolProfile.connectOrCreate.create.symbol
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
@ -106,7 +110,7 @@ export class OrderService {
|
|||||||
// Gather symbol data of order in the background, if not draft
|
// Gather symbol data of order in the background, if not draft
|
||||||
this.dataGatheringService.gatherSymbols([
|
this.dataGatheringService.gatherSymbols([
|
||||||
{
|
{
|
||||||
dataSource: data.dataSource,
|
dataSource: data.SymbolProfile.connectOrCreate.create.dataSource,
|
||||||
date: <Date>data.date,
|
date: <Date>data.date,
|
||||||
symbol: data.SymbolProfile.connectOrCreate.create.symbol
|
symbol: data.SymbolProfile.connectOrCreate.create.symbol
|
||||||
}
|
}
|
||||||
@ -116,6 +120,9 @@ export class OrderService {
|
|||||||
await this.cacheService.flush();
|
await this.cacheService.flush();
|
||||||
|
|
||||||
delete data.accountId;
|
delete data.accountId;
|
||||||
|
delete data.currency;
|
||||||
|
delete data.dataSource;
|
||||||
|
delete data.symbol;
|
||||||
delete data.userId;
|
delete data.userId;
|
||||||
|
|
||||||
const orderData: Prisma.OrderCreateInput = data;
|
const orderData: Prisma.OrderCreateInput = data;
|
||||||
@ -193,50 +200,60 @@ export class OrderService {
|
|||||||
value,
|
value,
|
||||||
feeInBaseCurrency: this.exchangeRateDataService.toCurrency(
|
feeInBaseCurrency: this.exchangeRateDataService.toCurrency(
|
||||||
order.fee,
|
order.fee,
|
||||||
order.currency,
|
order.SymbolProfile.currency,
|
||||||
userCurrency
|
userCurrency
|
||||||
),
|
),
|
||||||
valueInBaseCurrency: this.exchangeRateDataService.toCurrency(
|
valueInBaseCurrency: this.exchangeRateDataService.toCurrency(
|
||||||
value,
|
value,
|
||||||
order.currency,
|
order.SymbolProfile.currency,
|
||||||
userCurrency
|
userCurrency
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateOrder(params: {
|
public async updateOrder({
|
||||||
|
data,
|
||||||
|
where
|
||||||
|
}: {
|
||||||
|
data: Prisma.OrderUpdateInput & {
|
||||||
|
currency?: string;
|
||||||
|
dataSource?: DataSource;
|
||||||
|
symbol?: string;
|
||||||
|
};
|
||||||
where: Prisma.OrderWhereUniqueInput;
|
where: Prisma.OrderWhereUniqueInput;
|
||||||
data: Prisma.OrderUpdateInput;
|
|
||||||
}): Promise<Order> {
|
}): Promise<Order> {
|
||||||
const { data, where } = params;
|
|
||||||
|
|
||||||
if (data.Account.connect.id_userId.id === null) {
|
if (data.Account.connect.id_userId.id === null) {
|
||||||
delete data.Account;
|
delete data.Account;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isDraft = false;
|
||||||
|
|
||||||
if (data.type === 'ITEM') {
|
if (data.type === 'ITEM') {
|
||||||
const name = data.symbol;
|
const name = data.SymbolProfile.connect.dataSource_symbol.symbol;
|
||||||
|
|
||||||
data.symbol = null;
|
|
||||||
data.SymbolProfile = { update: { name } };
|
data.SymbolProfile = { update: { name } };
|
||||||
}
|
} else {
|
||||||
|
isDraft = isAfter(data.date as Date, endOfToday());
|
||||||
|
|
||||||
const isDraft = isAfter(data.date as Date, endOfToday());
|
if (!isDraft) {
|
||||||
|
// Gather symbol data of order in the background, if not draft
|
||||||
if (!isDraft) {
|
this.dataGatheringService.gatherSymbols([
|
||||||
// Gather symbol data of order in the background, if not draft
|
{
|
||||||
this.dataGatheringService.gatherSymbols([
|
dataSource: data.SymbolProfile.connect.dataSource_symbol.dataSource,
|
||||||
{
|
date: <Date>data.date,
|
||||||
dataSource: <DataSource>data.dataSource,
|
symbol: data.SymbolProfile.connect.dataSource_symbol.symbol
|
||||||
date: <Date>data.date,
|
}
|
||||||
symbol: <string>data.symbol
|
]);
|
||||||
}
|
}
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.cacheService.flush();
|
await this.cacheService.flush();
|
||||||
|
|
||||||
|
delete data.currency;
|
||||||
|
delete data.dataSource;
|
||||||
|
delete data.symbol;
|
||||||
|
|
||||||
return this.prismaService.order.update({
|
return this.prismaService.order.update({
|
||||||
data: {
|
data: {
|
||||||
...data,
|
...data,
|
||||||
|
@ -450,7 +450,7 @@ export class PortfolioServiceNew {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const positionCurrency = orders[0].currency;
|
const positionCurrency = orders[0].SymbolProfile.currency;
|
||||||
const [SymbolProfile] = await this.symbolProfileService.getSymbolProfiles([
|
const [SymbolProfile] = await this.symbolProfileService.getSymbolProfiles([
|
||||||
aSymbol
|
aSymbol
|
||||||
]);
|
]);
|
||||||
@ -460,13 +460,13 @@ export class PortfolioServiceNew {
|
|||||||
return order.type === 'BUY' || order.type === 'SELL';
|
return order.type === 'BUY' || order.type === 'SELL';
|
||||||
})
|
})
|
||||||
.map((order) => ({
|
.map((order) => ({
|
||||||
currency: order.currency,
|
currency: order.SymbolProfile.currency,
|
||||||
dataSource: order.SymbolProfile?.dataSource ?? order.dataSource,
|
dataSource: order.SymbolProfile.dataSource,
|
||||||
date: format(order.date, DATE_FORMAT),
|
date: format(order.date, DATE_FORMAT),
|
||||||
fee: new Big(order.fee),
|
fee: new Big(order.fee),
|
||||||
name: order.SymbolProfile?.name,
|
name: order.SymbolProfile?.name,
|
||||||
quantity: new Big(order.quantity),
|
quantity: new Big(order.quantity),
|
||||||
symbol: order.symbol,
|
symbol: order.SymbolProfile.symbol,
|
||||||
type: order.type,
|
type: order.type,
|
||||||
unitPrice: new Big(order.unitPrice)
|
unitPrice: new Big(order.unitPrice)
|
||||||
}));
|
}));
|
||||||
@ -1023,7 +1023,7 @@ export class PortfolioServiceNew {
|
|||||||
.map((order) => {
|
.map((order) => {
|
||||||
return this.exchangeRateDataService.toCurrency(
|
return this.exchangeRateDataService.toCurrency(
|
||||||
new Big(order.quantity).mul(order.unitPrice).toNumber(),
|
new Big(order.quantity).mul(order.unitPrice).toNumber(),
|
||||||
order.currency,
|
order.SymbolProfile.currency,
|
||||||
this.request.user.Settings.currency
|
this.request.user.Settings.currency
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@ -1042,7 +1042,7 @@ export class PortfolioServiceNew {
|
|||||||
.map((order) => {
|
.map((order) => {
|
||||||
return this.exchangeRateDataService.toCurrency(
|
return this.exchangeRateDataService.toCurrency(
|
||||||
order.fee,
|
order.fee,
|
||||||
order.currency,
|
order.SymbolProfile.currency,
|
||||||
this.request.user.Settings.currency
|
this.request.user.Settings.currency
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@ -1064,7 +1064,7 @@ export class PortfolioServiceNew {
|
|||||||
.map((order) => {
|
.map((order) => {
|
||||||
return this.exchangeRateDataService.toCurrency(
|
return this.exchangeRateDataService.toCurrency(
|
||||||
new Big(order.quantity).mul(order.unitPrice).toNumber(),
|
new Big(order.quantity).mul(order.unitPrice).toNumber(),
|
||||||
order.currency,
|
order.SymbolProfile.currency,
|
||||||
this.request.user.Settings.currency
|
this.request.user.Settings.currency
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@ -1117,24 +1117,24 @@ export class PortfolioServiceNew {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const portfolioOrders: PortfolioOrder[] = orders.map((order) => ({
|
const portfolioOrders: PortfolioOrder[] = orders.map((order) => ({
|
||||||
currency: order.currency,
|
currency: order.SymbolProfile.currency,
|
||||||
dataSource: order.SymbolProfile?.dataSource ?? order.dataSource,
|
dataSource: order.SymbolProfile.dataSource,
|
||||||
date: format(order.date, DATE_FORMAT),
|
date: format(order.date, DATE_FORMAT),
|
||||||
fee: new Big(
|
fee: new Big(
|
||||||
this.exchangeRateDataService.toCurrency(
|
this.exchangeRateDataService.toCurrency(
|
||||||
order.fee,
|
order.fee,
|
||||||
order.currency,
|
order.SymbolProfile.currency,
|
||||||
userCurrency
|
userCurrency
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
name: order.SymbolProfile?.name,
|
name: order.SymbolProfile?.name,
|
||||||
quantity: new Big(order.quantity),
|
quantity: new Big(order.quantity),
|
||||||
symbol: order.symbol,
|
symbol: order.SymbolProfile.symbol,
|
||||||
type: order.type,
|
type: order.type,
|
||||||
unitPrice: new Big(
|
unitPrice: new Big(
|
||||||
this.exchangeRateDataService.toCurrency(
|
this.exchangeRateDataService.toCurrency(
|
||||||
order.unitPrice,
|
order.unitPrice,
|
||||||
order.currency,
|
order.SymbolProfile.currency,
|
||||||
userCurrency
|
userCurrency
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -1180,7 +1180,8 @@ export class PortfolioServiceNew {
|
|||||||
|
|
||||||
for (const order of ordersByAccount) {
|
for (const order of ordersByAccount) {
|
||||||
let currentValueOfSymbol =
|
let currentValueOfSymbol =
|
||||||
order.quantity * portfolioItemsNow[order.symbol].marketPrice;
|
order.quantity *
|
||||||
|
portfolioItemsNow[order.SymbolProfile.symbol].marketPrice;
|
||||||
let originalValueOfSymbol = order.quantity * order.unitPrice;
|
let originalValueOfSymbol = order.quantity * order.unitPrice;
|
||||||
|
|
||||||
if (order.type === 'SELL') {
|
if (order.type === 'SELL') {
|
||||||
@ -1230,7 +1231,7 @@ export class PortfolioServiceNew {
|
|||||||
.map((order) => {
|
.map((order) => {
|
||||||
return this.exchangeRateDataService.toCurrency(
|
return this.exchangeRateDataService.toCurrency(
|
||||||
order.quantity * order.unitPrice,
|
order.quantity * order.unitPrice,
|
||||||
order.currency,
|
order.SymbolProfile.currency,
|
||||||
currency
|
currency
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
@ -438,7 +438,7 @@ export class PortfolioService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const positionCurrency = orders[0].currency;
|
const positionCurrency = orders[0].SymbolProfile.currency;
|
||||||
const [SymbolProfile] = await this.symbolProfileService.getSymbolProfiles([
|
const [SymbolProfile] = await this.symbolProfileService.getSymbolProfiles([
|
||||||
aSymbol
|
aSymbol
|
||||||
]);
|
]);
|
||||||
@ -448,13 +448,13 @@ export class PortfolioService {
|
|||||||
return order.type === 'BUY' || order.type === 'SELL';
|
return order.type === 'BUY' || order.type === 'SELL';
|
||||||
})
|
})
|
||||||
.map((order) => ({
|
.map((order) => ({
|
||||||
currency: order.currency,
|
currency: order.SymbolProfile.currency,
|
||||||
dataSource: order.SymbolProfile?.dataSource ?? order.dataSource,
|
dataSource: order.SymbolProfile.dataSource,
|
||||||
date: format(order.date, DATE_FORMAT),
|
date: format(order.date, DATE_FORMAT),
|
||||||
fee: new Big(order.fee),
|
fee: new Big(order.fee),
|
||||||
name: order.SymbolProfile?.name,
|
name: order.SymbolProfile?.name,
|
||||||
quantity: new Big(order.quantity),
|
quantity: new Big(order.quantity),
|
||||||
symbol: order.symbol,
|
symbol: order.SymbolProfile.symbol,
|
||||||
type: order.type,
|
type: order.type,
|
||||||
unitPrice: new Big(order.unitPrice)
|
unitPrice: new Big(order.unitPrice)
|
||||||
}));
|
}));
|
||||||
@ -987,7 +987,7 @@ export class PortfolioService {
|
|||||||
.map((order) => {
|
.map((order) => {
|
||||||
return this.exchangeRateDataService.toCurrency(
|
return this.exchangeRateDataService.toCurrency(
|
||||||
new Big(order.quantity).mul(order.unitPrice).toNumber(),
|
new Big(order.quantity).mul(order.unitPrice).toNumber(),
|
||||||
order.currency,
|
order.SymbolProfile.currency,
|
||||||
this.request.user.Settings.currency
|
this.request.user.Settings.currency
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@ -1006,7 +1006,7 @@ export class PortfolioService {
|
|||||||
.map((order) => {
|
.map((order) => {
|
||||||
return this.exchangeRateDataService.toCurrency(
|
return this.exchangeRateDataService.toCurrency(
|
||||||
order.fee,
|
order.fee,
|
||||||
order.currency,
|
order.SymbolProfile.currency,
|
||||||
this.request.user.Settings.currency
|
this.request.user.Settings.currency
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@ -1028,7 +1028,7 @@ export class PortfolioService {
|
|||||||
.map((order) => {
|
.map((order) => {
|
||||||
return this.exchangeRateDataService.toCurrency(
|
return this.exchangeRateDataService.toCurrency(
|
||||||
new Big(order.quantity).mul(order.unitPrice).toNumber(),
|
new Big(order.quantity).mul(order.unitPrice).toNumber(),
|
||||||
order.currency,
|
order.SymbolProfile.currency,
|
||||||
this.request.user.Settings.currency
|
this.request.user.Settings.currency
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@ -1080,24 +1080,24 @@ export class PortfolioService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const portfolioOrders: PortfolioOrder[] = orders.map((order) => ({
|
const portfolioOrders: PortfolioOrder[] = orders.map((order) => ({
|
||||||
currency: order.currency,
|
currency: order.SymbolProfile.currency,
|
||||||
dataSource: order.SymbolProfile?.dataSource ?? order.dataSource,
|
dataSource: order.SymbolProfile.dataSource,
|
||||||
date: format(order.date, DATE_FORMAT),
|
date: format(order.date, DATE_FORMAT),
|
||||||
fee: new Big(
|
fee: new Big(
|
||||||
this.exchangeRateDataService.toCurrency(
|
this.exchangeRateDataService.toCurrency(
|
||||||
order.fee,
|
order.fee,
|
||||||
order.currency,
|
order.SymbolProfile.currency,
|
||||||
userCurrency
|
userCurrency
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
name: order.SymbolProfile?.name,
|
name: order.SymbolProfile?.name,
|
||||||
quantity: new Big(order.quantity),
|
quantity: new Big(order.quantity),
|
||||||
symbol: order.symbol,
|
symbol: order.SymbolProfile.symbol,
|
||||||
type: order.type,
|
type: order.type,
|
||||||
unitPrice: new Big(
|
unitPrice: new Big(
|
||||||
this.exchangeRateDataService.toCurrency(
|
this.exchangeRateDataService.toCurrency(
|
||||||
order.unitPrice,
|
order.unitPrice,
|
||||||
order.currency,
|
order.SymbolProfile.currency,
|
||||||
userCurrency
|
userCurrency
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -1139,7 +1139,8 @@ export class PortfolioService {
|
|||||||
|
|
||||||
for (const order of ordersByAccount) {
|
for (const order of ordersByAccount) {
|
||||||
let currentValueOfSymbol =
|
let currentValueOfSymbol =
|
||||||
order.quantity * portfolioItemsNow[order.symbol].marketPrice;
|
order.quantity *
|
||||||
|
portfolioItemsNow[order.SymbolProfile.symbol].marketPrice;
|
||||||
let originalValueOfSymbol = order.quantity * order.unitPrice;
|
let originalValueOfSymbol = order.quantity * order.unitPrice;
|
||||||
|
|
||||||
if (order.type === 'SELL') {
|
if (order.type === 'SELL') {
|
||||||
@ -1189,7 +1190,7 @@ export class PortfolioService {
|
|||||||
.map((order) => {
|
.map((order) => {
|
||||||
return this.exchangeRateDataService.toCurrency(
|
return this.exchangeRateDataService.toCurrency(
|
||||||
order.quantity * order.unitPrice,
|
order.quantity * order.unitPrice,
|
||||||
order.currency,
|
order.SymbolProfile.currency,
|
||||||
currency
|
currency
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
@ -32,7 +32,6 @@ export class TransformDataSourceInResponseInterceptor<T>
|
|||||||
activity.SymbolProfile.dataSource = encodeDataSource(
|
activity.SymbolProfile.dataSource = encodeDataSource(
|
||||||
activity.SymbolProfile.dataSource
|
activity.SymbolProfile.dataSource
|
||||||
);
|
);
|
||||||
activity.dataSource = encodeDataSource(activity.dataSource);
|
|
||||||
return activity;
|
return activity;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -66,13 +65,6 @@ export class TransformDataSourceInResponseInterceptor<T>
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.orders) {
|
|
||||||
data.orders.map((order) => {
|
|
||||||
order.dataSource = encodeDataSource(order.dataSource);
|
|
||||||
return order;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.positions) {
|
if (data.positions) {
|
||||||
data.positions.map((position) => {
|
data.positions.map((position) => {
|
||||||
position.dataSource = encodeDataSource(position.dataSource);
|
position.dataSource = encodeDataSource(position.dataSource);
|
||||||
|
@ -549,19 +549,24 @@ export class DataGatheringService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async getSymbolsProfileData(): Promise<IDataGatheringItem[]> {
|
private async getSymbolsProfileData(): Promise<IDataGatheringItem[]> {
|
||||||
const distinctOrders = await this.prismaService.order.findMany({
|
const symbolProfiles = await this.prismaService.symbolProfile.findMany({
|
||||||
distinct: ['symbol'],
|
orderBy: [{ symbol: 'asc' }]
|
||||||
orderBy: [{ symbol: 'asc' }],
|
|
||||||
select: { dataSource: true, symbol: true }
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return distinctOrders.filter((distinctOrder) => {
|
return symbolProfiles
|
||||||
return (
|
.filter((symbolProfile) => {
|
||||||
distinctOrder.dataSource !== DataSource.GHOSTFOLIO &&
|
return (
|
||||||
distinctOrder.dataSource !== DataSource.MANUAL &&
|
symbolProfile.dataSource !== DataSource.GHOSTFOLIO &&
|
||||||
distinctOrder.dataSource !== DataSource.RAKUTEN
|
symbolProfile.dataSource !== DataSource.MANUAL &&
|
||||||
);
|
symbolProfile.dataSource !== DataSource.RAKUTEN
|
||||||
});
|
);
|
||||||
|
})
|
||||||
|
.map((symbolProfile) => {
|
||||||
|
return {
|
||||||
|
dataSource: symbolProfile.dataSource,
|
||||||
|
symbol: symbolProfile.symbol
|
||||||
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async isDataGatheringNeeded() {
|
private async isDataGatheringNeeded() {
|
||||||
|
@ -7,11 +7,7 @@ import {
|
|||||||
} from '@ghostfolio/api/services/interfaces/interfaces';
|
} from '@ghostfolio/api/services/interfaces/interfaces';
|
||||||
import { PrismaService } from '@ghostfolio/api/services/prisma.service';
|
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 {
|
import { DATE_FORMAT, getYesterday } from '@ghostfolio/common/helper';
|
||||||
DATE_FORMAT,
|
|
||||||
getYesterday,
|
|
||||||
isGhostfolioScraperApiSymbol
|
|
||||||
} from '@ghostfolio/common/helper';
|
|
||||||
import { Granularity } from '@ghostfolio/common/types';
|
import { Granularity } from '@ghostfolio/common/types';
|
||||||
import { Injectable, Logger } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
import { DataSource, SymbolProfile } from '@prisma/client';
|
import { DataSource, SymbolProfile } from '@prisma/client';
|
||||||
@ -29,7 +25,7 @@ export class GhostfolioScraperApiService implements DataProviderInterface {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
public canHandle(symbol: string) {
|
public canHandle(symbol: string) {
|
||||||
return isGhostfolioScraperApiSymbol(symbol);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getAssetProfile(
|
public async getAssetProfile(
|
||||||
|
@ -191,12 +191,7 @@ export class ExchangeRateDataService {
|
|||||||
await this.prismaService.symbolProfile.findMany({
|
await this.prismaService.symbolProfile.findMany({
|
||||||
distinct: ['currency'],
|
distinct: ['currency'],
|
||||||
orderBy: [{ currency: 'asc' }],
|
orderBy: [{ currency: 'asc' }],
|
||||||
select: { currency: true },
|
select: { currency: true }
|
||||||
where: {
|
|
||||||
currency: {
|
|
||||||
not: null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
).forEach((symbolProfile) => {
|
).forEach((symbolProfile) => {
|
||||||
currencies.push(symbolProfile.currency);
|
currencies.push(symbolProfile.currency);
|
||||||
|
@ -158,11 +158,11 @@ export class CreateOrUpdateTransactionDialog implements OnDestroy {
|
|||||||
this.activityForm.controls['type'].disable();
|
this.activityForm.controls['type'].disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.data.activity?.symbol) {
|
if (this.data.activity?.SymbolProfile?.symbol) {
|
||||||
this.dataService
|
this.dataService
|
||||||
.fetchSymbolItem({
|
.fetchSymbolItem({
|
||||||
dataSource: this.data.activity?.dataSource,
|
dataSource: this.data.activity?.SymbolProfile?.dataSource,
|
||||||
symbol: this.data.activity?.symbol
|
symbol: this.data.activity?.SymbolProfile?.symbol
|
||||||
})
|
})
|
||||||
.pipe(takeUntil(this.unsubscribeSubject))
|
.pipe(takeUntil(this.unsubscribeSubject))
|
||||||
.subscribe(({ marketPrice }) => {
|
.subscribe(({ marketPrice }) => {
|
||||||
@ -196,9 +196,7 @@ export class CreateOrUpdateTransactionDialog implements OnDestroy {
|
|||||||
} else {
|
} else {
|
||||||
this.activityForm.controls['searchSymbol'].setErrors({ incorrect: true });
|
this.activityForm.controls['searchSymbol'].setErrors({ incorrect: true });
|
||||||
|
|
||||||
this.data.activity.currency = null;
|
this.data.activity.SymbolProfile = null;
|
||||||
this.data.activity.dataSource = null;
|
|
||||||
this.data.activity.symbol = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.changeDetectorRef.markForCheck();
|
this.changeDetectorRef.markForCheck();
|
||||||
@ -259,9 +257,7 @@ export class CreateOrUpdateTransactionDialog implements OnDestroy {
|
|||||||
})
|
})
|
||||||
.pipe(
|
.pipe(
|
||||||
catchError(() => {
|
catchError(() => {
|
||||||
this.data.activity.currency = null;
|
this.data.activity.SymbolProfile = null;
|
||||||
this.data.activity.dataSource = null;
|
|
||||||
this.data.activity.unitPrice = null;
|
|
||||||
|
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
|
|
||||||
|
@ -102,10 +102,6 @@ export function isCurrency(aSymbol = '') {
|
|||||||
return currencies[aSymbol];
|
return currencies[aSymbol];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isGhostfolioScraperApiSymbol(aSymbol = '') {
|
|
||||||
return aSymbol.startsWith(ghostfolioScraperApiSymbolPrefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function resetHours(aDate: Date) {
|
export function resetHours(aDate: Date) {
|
||||||
const year = getYear(aDate);
|
const year = getYear(aDate);
|
||||||
const month = getMonth(aDate);
|
const month = getMonth(aDate);
|
||||||
|
@ -144,7 +144,7 @@
|
|||||||
class="d-none d-lg-table-cell px-1"
|
class="d-none d-lg-table-cell px-1"
|
||||||
mat-cell
|
mat-cell
|
||||||
>
|
>
|
||||||
{{ element.currency }}
|
{{ element.SymbolProfile.currency }}
|
||||||
</td>
|
</td>
|
||||||
<td *matFooterCellDef class="d-none d-lg-table-cell px-1" mat-footer-cell>
|
<td *matFooterCellDef class="d-none d-lg-table-cell px-1" mat-footer-cell>
|
||||||
{{ baseCurrency }}
|
{{ baseCurrency }}
|
||||||
@ -362,7 +362,7 @@
|
|||||||
!row.isDraft &&
|
!row.isDraft &&
|
||||||
row.type !== 'ITEM' &&
|
row.type !== 'ITEM' &&
|
||||||
onOpenPositionDialog({
|
onOpenPositionDialog({
|
||||||
dataSource: row.dataSource,
|
dataSource: row.SymbolProfile.dataSource,
|
||||||
symbol: row.SymbolProfile.symbol
|
symbol: row.SymbolProfile.symbol
|
||||||
})
|
})
|
||||||
"
|
"
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Order" DROP COLUMN "dataSource";
|
@ -0,0 +1,2 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Order" DROP COLUMN "currency";
|
@ -0,0 +1,2 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Order" DROP COLUMN "symbol";
|
@ -0,0 +1,5 @@
|
|||||||
|
-- Set default value
|
||||||
|
UPDATE "SymbolProfile" SET "currency" = 'USD' WHERE "currency" IS NULL;
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "SymbolProfile" ALTER COLUMN "currency" SET NOT NULL;
|
@ -74,14 +74,11 @@ model Order {
|
|||||||
accountId String?
|
accountId String?
|
||||||
accountUserId String?
|
accountUserId String?
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
currency String?
|
|
||||||
dataSource DataSource?
|
|
||||||
date DateTime
|
date DateTime
|
||||||
fee Float
|
fee Float
|
||||||
id String @default(uuid())
|
id String @default(uuid())
|
||||||
isDraft Boolean @default(false)
|
isDraft Boolean @default(false)
|
||||||
quantity Float
|
quantity Float
|
||||||
symbol String?
|
|
||||||
SymbolProfile SymbolProfile @relation(fields: [symbolProfileId], references: [id])
|
SymbolProfile SymbolProfile @relation(fields: [symbolProfileId], references: [id])
|
||||||
symbolProfileId String
|
symbolProfileId String
|
||||||
type Type
|
type Type
|
||||||
@ -119,7 +116,7 @@ model SymbolProfile {
|
|||||||
assetSubClass AssetSubClass?
|
assetSubClass AssetSubClass?
|
||||||
countries Json?
|
countries Json?
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
currency String?
|
currency String
|
||||||
dataSource DataSource
|
dataSource DataSource
|
||||||
id String @id @default(uuid())
|
id String @id @default(uuid())
|
||||||
name String?
|
name String?
|
||||||
|
@ -192,14 +192,11 @@ async function main() {
|
|||||||
{
|
{
|
||||||
accountId: '65cfb79d-b6c7-4591-9d46-73426bc62094',
|
accountId: '65cfb79d-b6c7-4591-9d46-73426bc62094',
|
||||||
accountUserId: userDemo.id,
|
accountUserId: userDemo.id,
|
||||||
currency: 'USD',
|
|
||||||
dataSource: DataSource.YAHOO,
|
|
||||||
date: new Date(Date.UTC(2017, 0, 3, 0, 0, 0)),
|
date: new Date(Date.UTC(2017, 0, 3, 0, 0, 0)),
|
||||||
fee: 30,
|
fee: 30,
|
||||||
id: 'cf7c0418-8535-4089-ae3d-5dbfa0aec2e1',
|
id: 'cf7c0418-8535-4089-ae3d-5dbfa0aec2e1',
|
||||||
quantity: 50,
|
quantity: 50,
|
||||||
symbol: 'TSLA',
|
symbolProfileId: 'd1ee9681-fb21-4f99-a3b7-afd4fc04df2e', // TSLA
|
||||||
symbolProfileId: 'd1ee9681-fb21-4f99-a3b7-afd4fc04df2e',
|
|
||||||
type: Type.BUY,
|
type: Type.BUY,
|
||||||
unitPrice: 42.97,
|
unitPrice: 42.97,
|
||||||
userId: userDemo.id
|
userId: userDemo.id
|
||||||
@ -207,14 +204,11 @@ async function main() {
|
|||||||
{
|
{
|
||||||
accountId: 'd804de69-0429-42dc-b6ca-b308fd7dd926',
|
accountId: 'd804de69-0429-42dc-b6ca-b308fd7dd926',
|
||||||
accountUserId: userDemo.id,
|
accountUserId: userDemo.id,
|
||||||
currency: 'USD',
|
|
||||||
dataSource: DataSource.YAHOO,
|
|
||||||
date: new Date(Date.UTC(2017, 7, 16, 0, 0, 0)),
|
date: new Date(Date.UTC(2017, 7, 16, 0, 0, 0)),
|
||||||
fee: 29.9,
|
fee: 29.9,
|
||||||
id: 'a1c5d73a-8631-44e5-ac44-356827a5212c',
|
id: 'a1c5d73a-8631-44e5-ac44-356827a5212c',
|
||||||
quantity: 0.5614682,
|
quantity: 0.5614682,
|
||||||
symbol: 'BTCUSD',
|
symbolProfileId: 'fdc42ea6-1321-44f5-9fb0-d7f1f2cf9b1e', // BTCUSD
|
||||||
symbolProfileId: 'fdc42ea6-1321-44f5-9fb0-d7f1f2cf9b1e',
|
|
||||||
type: Type.BUY,
|
type: Type.BUY,
|
||||||
unitPrice: 3562.089535970158,
|
unitPrice: 3562.089535970158,
|
||||||
userId: userDemo.id
|
userId: userDemo.id
|
||||||
@ -222,14 +216,11 @@ async function main() {
|
|||||||
{
|
{
|
||||||
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
||||||
accountUserId: userDemo.id,
|
accountUserId: userDemo.id,
|
||||||
currency: 'USD',
|
|
||||||
dataSource: DataSource.YAHOO,
|
|
||||||
date: new Date(Date.UTC(2018, 9, 1, 0, 0, 0)),
|
date: new Date(Date.UTC(2018, 9, 1, 0, 0, 0)),
|
||||||
fee: 80.79,
|
fee: 80.79,
|
||||||
id: '71c08e2a-4a86-44ae-a890-c337de5d5f9b',
|
id: '71c08e2a-4a86-44ae-a890-c337de5d5f9b',
|
||||||
quantity: 5,
|
quantity: 5,
|
||||||
symbol: 'AMZN',
|
symbolProfileId: '2bd26362-136e-411c-b578-334084b4cdcc', // AMZN
|
||||||
symbolProfileId: '2bd26362-136e-411c-b578-334084b4cdcc',
|
|
||||||
type: Type.BUY,
|
type: Type.BUY,
|
||||||
unitPrice: 2021.99,
|
unitPrice: 2021.99,
|
||||||
userId: userDemo.id
|
userId: userDemo.id
|
||||||
@ -237,14 +228,11 @@ async function main() {
|
|||||||
{
|
{
|
||||||
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
||||||
accountUserId: userDemo.id,
|
accountUserId: userDemo.id,
|
||||||
currency: 'USD',
|
|
||||||
dataSource: DataSource.YAHOO,
|
|
||||||
date: new Date(Date.UTC(2019, 2, 1, 0, 0, 0)),
|
date: new Date(Date.UTC(2019, 2, 1, 0, 0, 0)),
|
||||||
fee: 19.9,
|
fee: 19.9,
|
||||||
id: '385f2c2c-d53e-4937-b0e5-e92ef6020d4e',
|
id: '385f2c2c-d53e-4937-b0e5-e92ef6020d4e',
|
||||||
quantity: 10,
|
quantity: 10,
|
||||||
symbol: 'VTI',
|
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796', // VTI
|
||||||
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796',
|
|
||||||
type: Type.BUY,
|
type: Type.BUY,
|
||||||
unitPrice: 144.38,
|
unitPrice: 144.38,
|
||||||
userId: userDemo.id
|
userId: userDemo.id
|
||||||
@ -252,14 +240,11 @@ async function main() {
|
|||||||
{
|
{
|
||||||
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
||||||
accountUserId: userDemo.id,
|
accountUserId: userDemo.id,
|
||||||
currency: 'USD',
|
|
||||||
dataSource: DataSource.YAHOO,
|
|
||||||
date: new Date(Date.UTC(2019, 8, 3, 0, 0, 0)),
|
date: new Date(Date.UTC(2019, 8, 3, 0, 0, 0)),
|
||||||
fee: 19.9,
|
fee: 19.9,
|
||||||
id: '185f2c2c-d53e-4937-b0e5-a93ef6020d4e',
|
id: '185f2c2c-d53e-4937-b0e5-a93ef6020d4e',
|
||||||
quantity: 10,
|
quantity: 10,
|
||||||
symbol: 'VTI',
|
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796', // VTI
|
||||||
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796',
|
|
||||||
type: Type.BUY,
|
type: Type.BUY,
|
||||||
unitPrice: 147.99,
|
unitPrice: 147.99,
|
||||||
userId: userDemo.id
|
userId: userDemo.id
|
||||||
@ -267,14 +252,11 @@ async function main() {
|
|||||||
{
|
{
|
||||||
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
||||||
accountUserId: userDemo.id,
|
accountUserId: userDemo.id,
|
||||||
currency: 'USD',
|
|
||||||
dataSource: DataSource.YAHOO,
|
|
||||||
date: new Date(Date.UTC(2020, 2, 2, 0, 0, 0)),
|
date: new Date(Date.UTC(2020, 2, 2, 0, 0, 0)),
|
||||||
fee: 19.9,
|
fee: 19.9,
|
||||||
id: '347b0430-a84f-4031-a0f9-390399066ad6',
|
id: '347b0430-a84f-4031-a0f9-390399066ad6',
|
||||||
quantity: 10,
|
quantity: 10,
|
||||||
symbol: 'VTI',
|
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796', // VTI
|
||||||
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796',
|
|
||||||
type: Type.BUY,
|
type: Type.BUY,
|
||||||
unitPrice: 151.41,
|
unitPrice: 151.41,
|
||||||
userId: userDemo.id
|
userId: userDemo.id
|
||||||
@ -282,14 +264,11 @@ async function main() {
|
|||||||
{
|
{
|
||||||
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
||||||
accountUserId: userDemo.id,
|
accountUserId: userDemo.id,
|
||||||
currency: 'USD',
|
|
||||||
dataSource: DataSource.YAHOO,
|
|
||||||
date: new Date(Date.UTC(2020, 8, 1, 0, 0, 0)),
|
date: new Date(Date.UTC(2020, 8, 1, 0, 0, 0)),
|
||||||
fee: 19.9,
|
fee: 19.9,
|
||||||
id: '67ec3f47-3189-4b63-ba05-60d3a06b302f',
|
id: '67ec3f47-3189-4b63-ba05-60d3a06b302f',
|
||||||
quantity: 10,
|
quantity: 10,
|
||||||
symbol: 'VTI',
|
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796', // VTI
|
||||||
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796',
|
|
||||||
type: Type.BUY,
|
type: Type.BUY,
|
||||||
unitPrice: 177.69,
|
unitPrice: 177.69,
|
||||||
userId: userDemo.id
|
userId: userDemo.id
|
||||||
@ -297,14 +276,11 @@ async function main() {
|
|||||||
{
|
{
|
||||||
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
||||||
accountUserId: userDemo.id,
|
accountUserId: userDemo.id,
|
||||||
currency: 'USD',
|
|
||||||
dataSource: DataSource.YAHOO,
|
|
||||||
date: new Date(Date.UTC(2020, 2, 1, 0, 0, 0)),
|
date: new Date(Date.UTC(2020, 2, 1, 0, 0, 0)),
|
||||||
fee: 19.9,
|
fee: 19.9,
|
||||||
id: 'd01c6fbc-fa8d-47e6-8e80-66f882d2bfd2',
|
id: 'd01c6fbc-fa8d-47e6-8e80-66f882d2bfd2',
|
||||||
quantity: 10,
|
quantity: 10,
|
||||||
symbol: 'VTI',
|
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796', // VTI
|
||||||
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796',
|
|
||||||
type: Type.BUY,
|
type: Type.BUY,
|
||||||
unitPrice: 203.15,
|
unitPrice: 203.15,
|
||||||
userId: userDemo.id
|
userId: userDemo.id
|
||||||
|
Loading…
x
Reference in New Issue
Block a user