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
pull/739/head
Thomas Kaul 2 years ago committed by GitHub
parent 86acbf06f4
commit c216ab1d76
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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
### Changed
- Removed the redundant attributes (`currency`, `dataSource`, `symbol`) of the activity model
- Removed the prefix for symbols with the data source `GHOSTFOLIO`
### Fixed
- Improved the account calculations
### Todo
- Apply data migration (`yarn database:migrate`)
## 1.122.0 - 01.03.2022
### Added

@ -18,8 +18,6 @@ export class ExportService {
orderBy: { date: 'desc' },
select: {
accountId: true,
currency: true,
dataSource: true,
date: true,
fee: true,
id: true,
@ -42,7 +40,6 @@ export class ExportService {
orders: orders.map(
({
accountId,
currency,
date,
fee,
quantity,
@ -52,12 +49,12 @@ export class ExportService {
}) => {
return {
accountId,
currency,
date,
fee,
quantity,
type,
unitPrice,
currency: SymbolProfile.currency,
dataSource: SymbolProfile.dataSource,
symbol: type === 'ITEM' ? SymbolProfile.name : SymbolProfile.symbol
};

@ -1,5 +1,4 @@
import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto';
import { Order } from '@prisma/client';
import { Type } from 'class-transformer';
import { IsArray, ValidateNested } from 'class-validator';
@ -7,5 +6,5 @@ export class ImportDataDto {
@IsArray()
@Type(() => CreateOrderDto)
@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 { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service';
import { Injectable } from '@nestjs/common';
import { Order } from '@prisma/client';
import { isSameDay, parseISO } from 'date-fns';
import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto';
@Injectable()
export class ImportService {
@ -19,7 +19,7 @@ export class ImportService {
orders,
userId
}: {
orders: Partial<Order>[];
orders: Partial<CreateOrderDto>[];
userId: string;
}): Promise<void> {
for (const order of orders) {
@ -52,11 +52,8 @@ export class ImportService {
unitPrice
} of orders) {
await this.orderService.createOrder({
currency,
dataSource,
fee,
quantity,
symbol,
type,
unitPrice,
userId,
@ -65,6 +62,7 @@ export class ImportService {
SymbolProfile: {
connectOrCreate: {
create: {
currency,
dataSource,
symbol
},
@ -85,7 +83,7 @@ export class ImportService {
orders,
userId
}: {
orders: Partial<Order>[];
orders: Partial<CreateOrderDto>[];
userId: string;
}) {
if (
@ -99,6 +97,7 @@ export class ImportService {
}
const existingOrders = await this.orderService.orders({
include: { SymbolProfile: true },
orderBy: { date: 'desc' },
where: { userId }
});
@ -109,12 +108,12 @@ export class ImportService {
] of orders.entries()) {
const duplicateOrder = existingOrders.find((order) => {
return (
order.currency === currency &&
order.dataSource === dataSource &&
order.SymbolProfile.currency === currency &&
order.SymbolProfile.dataSource === dataSource &&
isSameDay(order.date, parseISO(<string>(<unknown>date))) &&
order.fee === fee &&
order.quantity === quantity &&
order.symbol === symbol &&
order.SymbolProfile.symbol === symbol &&
order.type === type &&
order.unitPrice === unitPrice
);

@ -114,6 +114,7 @@ export class OrderController {
SymbolProfile: {
connectOrCreate: {
create: {
currency: data.currency,
dataSource: data.dataSource,
symbol: data.symbol
},
@ -171,6 +172,14 @@ export class OrderController {
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 } }
},
where: {

@ -53,7 +53,13 @@ export class OrderService {
}
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> {
const defaultAccount = (
await this.accountService.getAccounts(data.userId)
@ -71,15 +77,13 @@ export class OrderService {
};
if (data.type === 'ITEM') {
const currency = data.currency;
const currency = data.SymbolProfile.connectOrCreate.create.currency;
const dataSource: DataSource = 'MANUAL';
const id = uuidv4();
const name = data.SymbolProfile.connectOrCreate.create.symbol;
Account = undefined;
data.dataSource = dataSource;
data.id = id;
data.symbol = null;
data.SymbolProfile.connectOrCreate.create.currency = currency;
data.SymbolProfile.connectOrCreate.create.dataSource = dataSource;
data.SymbolProfile.connectOrCreate.create.name = name;
@ -95,7 +99,7 @@ export class OrderService {
await this.dataGatheringService.gatherProfileData([
{
dataSource: data.dataSource,
dataSource: data.SymbolProfile.connectOrCreate.create.dataSource,
symbol: data.SymbolProfile.connectOrCreate.create.symbol
}
]);
@ -106,7 +110,7 @@ export class OrderService {
// Gather symbol data of order in the background, if not draft
this.dataGatheringService.gatherSymbols([
{
dataSource: data.dataSource,
dataSource: data.SymbolProfile.connectOrCreate.create.dataSource,
date: <Date>data.date,
symbol: data.SymbolProfile.connectOrCreate.create.symbol
}
@ -116,6 +120,9 @@ export class OrderService {
await this.cacheService.flush();
delete data.accountId;
delete data.currency;
delete data.dataSource;
delete data.symbol;
delete data.userId;
const orderData: Prisma.OrderCreateInput = data;
@ -193,50 +200,60 @@ export class OrderService {
value,
feeInBaseCurrency: this.exchangeRateDataService.toCurrency(
order.fee,
order.currency,
order.SymbolProfile.currency,
userCurrency
),
valueInBaseCurrency: this.exchangeRateDataService.toCurrency(
value,
order.currency,
order.SymbolProfile.currency,
userCurrency
)
};
});
}
public async updateOrder(params: {
public async updateOrder({
data,
where
}: {
data: Prisma.OrderUpdateInput & {
currency?: string;
dataSource?: DataSource;
symbol?: string;
};
where: Prisma.OrderWhereUniqueInput;
data: Prisma.OrderUpdateInput;
}): Promise<Order> {
const { data, where } = params;
if (data.Account.connect.id_userId.id === null) {
delete data.Account;
}
let isDraft = false;
if (data.type === 'ITEM') {
const name = data.symbol;
const name = data.SymbolProfile.connect.dataSource_symbol.symbol;
data.symbol = null;
data.SymbolProfile = { update: { name } };
}
const isDraft = isAfter(data.date as Date, endOfToday());
if (!isDraft) {
// Gather symbol data of order in the background, if not draft
this.dataGatheringService.gatherSymbols([
{
dataSource: <DataSource>data.dataSource,
date: <Date>data.date,
symbol: <string>data.symbol
}
]);
} else {
isDraft = isAfter(data.date as Date, endOfToday());
if (!isDraft) {
// 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,
symbol: data.SymbolProfile.connect.dataSource_symbol.symbol
}
]);
}
}
await this.cacheService.flush();
delete data.currency;
delete data.dataSource;
delete data.symbol;
return this.prismaService.order.update({
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([
aSymbol
]);
@ -460,13 +460,13 @@ export class PortfolioServiceNew {
return order.type === 'BUY' || order.type === 'SELL';
})
.map((order) => ({
currency: order.currency,
dataSource: order.SymbolProfile?.dataSource ?? order.dataSource,
currency: order.SymbolProfile.currency,
dataSource: order.SymbolProfile.dataSource,
date: format(order.date, DATE_FORMAT),
fee: new Big(order.fee),
name: order.SymbolProfile?.name,
quantity: new Big(order.quantity),
symbol: order.symbol,
symbol: order.SymbolProfile.symbol,
type: order.type,
unitPrice: new Big(order.unitPrice)
}));
@ -1023,7 +1023,7 @@ export class PortfolioServiceNew {
.map((order) => {
return this.exchangeRateDataService.toCurrency(
new Big(order.quantity).mul(order.unitPrice).toNumber(),
order.currency,
order.SymbolProfile.currency,
this.request.user.Settings.currency
);
})
@ -1042,7 +1042,7 @@ export class PortfolioServiceNew {
.map((order) => {
return this.exchangeRateDataService.toCurrency(
order.fee,
order.currency,
order.SymbolProfile.currency,
this.request.user.Settings.currency
);
})
@ -1064,7 +1064,7 @@ export class PortfolioServiceNew {
.map((order) => {
return this.exchangeRateDataService.toCurrency(
new Big(order.quantity).mul(order.unitPrice).toNumber(),
order.currency,
order.SymbolProfile.currency,
this.request.user.Settings.currency
);
})
@ -1117,24 +1117,24 @@ export class PortfolioServiceNew {
}
const portfolioOrders: PortfolioOrder[] = orders.map((order) => ({
currency: order.currency,
dataSource: order.SymbolProfile?.dataSource ?? order.dataSource,
currency: order.SymbolProfile.currency,
dataSource: order.SymbolProfile.dataSource,
date: format(order.date, DATE_FORMAT),
fee: new Big(
this.exchangeRateDataService.toCurrency(
order.fee,
order.currency,
order.SymbolProfile.currency,
userCurrency
)
),
name: order.SymbolProfile?.name,
quantity: new Big(order.quantity),
symbol: order.symbol,
symbol: order.SymbolProfile.symbol,
type: order.type,
unitPrice: new Big(
this.exchangeRateDataService.toCurrency(
order.unitPrice,
order.currency,
order.SymbolProfile.currency,
userCurrency
)
)
@ -1180,7 +1180,8 @@ export class PortfolioServiceNew {
for (const order of ordersByAccount) {
let currentValueOfSymbol =
order.quantity * portfolioItemsNow[order.symbol].marketPrice;
order.quantity *
portfolioItemsNow[order.SymbolProfile.symbol].marketPrice;
let originalValueOfSymbol = order.quantity * order.unitPrice;
if (order.type === 'SELL') {
@ -1230,7 +1231,7 @@ export class PortfolioServiceNew {
.map((order) => {
return this.exchangeRateDataService.toCurrency(
order.quantity * order.unitPrice,
order.currency,
order.SymbolProfile.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([
aSymbol
]);
@ -448,13 +448,13 @@ export class PortfolioService {
return order.type === 'BUY' || order.type === 'SELL';
})
.map((order) => ({
currency: order.currency,
dataSource: order.SymbolProfile?.dataSource ?? order.dataSource,
currency: order.SymbolProfile.currency,
dataSource: order.SymbolProfile.dataSource,
date: format(order.date, DATE_FORMAT),
fee: new Big(order.fee),
name: order.SymbolProfile?.name,
quantity: new Big(order.quantity),
symbol: order.symbol,
symbol: order.SymbolProfile.symbol,
type: order.type,
unitPrice: new Big(order.unitPrice)
}));
@ -987,7 +987,7 @@ export class PortfolioService {
.map((order) => {
return this.exchangeRateDataService.toCurrency(
new Big(order.quantity).mul(order.unitPrice).toNumber(),
order.currency,
order.SymbolProfile.currency,
this.request.user.Settings.currency
);
})
@ -1006,7 +1006,7 @@ export class PortfolioService {
.map((order) => {
return this.exchangeRateDataService.toCurrency(
order.fee,
order.currency,
order.SymbolProfile.currency,
this.request.user.Settings.currency
);
})
@ -1028,7 +1028,7 @@ export class PortfolioService {
.map((order) => {
return this.exchangeRateDataService.toCurrency(
new Big(order.quantity).mul(order.unitPrice).toNumber(),
order.currency,
order.SymbolProfile.currency,
this.request.user.Settings.currency
);
})
@ -1080,24 +1080,24 @@ export class PortfolioService {
}
const portfolioOrders: PortfolioOrder[] = orders.map((order) => ({
currency: order.currency,
dataSource: order.SymbolProfile?.dataSource ?? order.dataSource,
currency: order.SymbolProfile.currency,
dataSource: order.SymbolProfile.dataSource,
date: format(order.date, DATE_FORMAT),
fee: new Big(
this.exchangeRateDataService.toCurrency(
order.fee,
order.currency,
order.SymbolProfile.currency,
userCurrency
)
),
name: order.SymbolProfile?.name,
quantity: new Big(order.quantity),
symbol: order.symbol,
symbol: order.SymbolProfile.symbol,
type: order.type,
unitPrice: new Big(
this.exchangeRateDataService.toCurrency(
order.unitPrice,
order.currency,
order.SymbolProfile.currency,
userCurrency
)
)
@ -1139,7 +1139,8 @@ export class PortfolioService {
for (const order of ordersByAccount) {
let currentValueOfSymbol =
order.quantity * portfolioItemsNow[order.symbol].marketPrice;
order.quantity *
portfolioItemsNow[order.SymbolProfile.symbol].marketPrice;
let originalValueOfSymbol = order.quantity * order.unitPrice;
if (order.type === 'SELL') {
@ -1189,7 +1190,7 @@ export class PortfolioService {
.map((order) => {
return this.exchangeRateDataService.toCurrency(
order.quantity * order.unitPrice,
order.currency,
order.SymbolProfile.currency,
currency
);
})

@ -32,7 +32,6 @@ export class TransformDataSourceInResponseInterceptor<T>
activity.SymbolProfile.dataSource = encodeDataSource(
activity.SymbolProfile.dataSource
);
activity.dataSource = encodeDataSource(activity.dataSource);
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) {
data.positions.map((position) => {
position.dataSource = encodeDataSource(position.dataSource);

@ -549,19 +549,24 @@ export class DataGatheringService {
}
private async getSymbolsProfileData(): Promise<IDataGatheringItem[]> {
const distinctOrders = await this.prismaService.order.findMany({
distinct: ['symbol'],
orderBy: [{ symbol: 'asc' }],
select: { dataSource: true, symbol: true }
const symbolProfiles = await this.prismaService.symbolProfile.findMany({
orderBy: [{ symbol: 'asc' }]
});
return distinctOrders.filter((distinctOrder) => {
return (
distinctOrder.dataSource !== DataSource.GHOSTFOLIO &&
distinctOrder.dataSource !== DataSource.MANUAL &&
distinctOrder.dataSource !== DataSource.RAKUTEN
);
});
return symbolProfiles
.filter((symbolProfile) => {
return (
symbolProfile.dataSource !== DataSource.GHOSTFOLIO &&
symbolProfile.dataSource !== DataSource.MANUAL &&
symbolProfile.dataSource !== DataSource.RAKUTEN
);
})
.map((symbolProfile) => {
return {
dataSource: symbolProfile.dataSource,
symbol: symbolProfile.symbol
};
});
}
private async isDataGatheringNeeded() {

@ -7,11 +7,7 @@ import {
} from '@ghostfolio/api/services/interfaces/interfaces';
import { PrismaService } from '@ghostfolio/api/services/prisma.service';
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile.service';
import {
DATE_FORMAT,
getYesterday,
isGhostfolioScraperApiSymbol
} from '@ghostfolio/common/helper';
import { DATE_FORMAT, getYesterday } from '@ghostfolio/common/helper';
import { Granularity } from '@ghostfolio/common/types';
import { Injectable, Logger } from '@nestjs/common';
import { DataSource, SymbolProfile } from '@prisma/client';
@ -29,7 +25,7 @@ export class GhostfolioScraperApiService implements DataProviderInterface {
) {}
public canHandle(symbol: string) {
return isGhostfolioScraperApiSymbol(symbol);
return true;
}
public async getAssetProfile(

@ -191,12 +191,7 @@ export class ExchangeRateDataService {
await this.prismaService.symbolProfile.findMany({
distinct: ['currency'],
orderBy: [{ currency: 'asc' }],
select: { currency: true },
where: {
currency: {
not: null
}
}
select: { currency: true }
})
).forEach((symbolProfile) => {
currencies.push(symbolProfile.currency);

@ -158,11 +158,11 @@ export class CreateOrUpdateTransactionDialog implements OnDestroy {
this.activityForm.controls['type'].disable();
}
if (this.data.activity?.symbol) {
if (this.data.activity?.SymbolProfile?.symbol) {
this.dataService
.fetchSymbolItem({
dataSource: this.data.activity?.dataSource,
symbol: this.data.activity?.symbol
dataSource: this.data.activity?.SymbolProfile?.dataSource,
symbol: this.data.activity?.SymbolProfile?.symbol
})
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(({ marketPrice }) => {
@ -196,9 +196,7 @@ export class CreateOrUpdateTransactionDialog implements OnDestroy {
} else {
this.activityForm.controls['searchSymbol'].setErrors({ incorrect: true });
this.data.activity.currency = null;
this.data.activity.dataSource = null;
this.data.activity.symbol = null;
this.data.activity.SymbolProfile = null;
}
this.changeDetectorRef.markForCheck();
@ -259,9 +257,7 @@ export class CreateOrUpdateTransactionDialog implements OnDestroy {
})
.pipe(
catchError(() => {
this.data.activity.currency = null;
this.data.activity.dataSource = null;
this.data.activity.unitPrice = null;
this.data.activity.SymbolProfile = null;
this.isLoading = false;

@ -102,10 +102,6 @@ export function isCurrency(aSymbol = '') {
return currencies[aSymbol];
}
export function isGhostfolioScraperApiSymbol(aSymbol = '') {
return aSymbol.startsWith(ghostfolioScraperApiSymbolPrefix);
}
export function resetHours(aDate: Date) {
const year = getYear(aDate);
const month = getMonth(aDate);

@ -144,7 +144,7 @@
class="d-none d-lg-table-cell px-1"
mat-cell
>
{{ element.currency }}
{{ element.SymbolProfile.currency }}
</td>
<td *matFooterCellDef class="d-none d-lg-table-cell px-1" mat-footer-cell>
{{ baseCurrency }}
@ -362,7 +362,7 @@
!row.isDraft &&
row.type !== 'ITEM' &&
onOpenPositionDialog({
dataSource: row.dataSource,
dataSource: row.SymbolProfile.dataSource,
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?
accountUserId String?
createdAt DateTime @default(now())
currency String?
dataSource DataSource?
date DateTime
fee Float
id String @default(uuid())
isDraft Boolean @default(false)
quantity Float
symbol String?
SymbolProfile SymbolProfile @relation(fields: [symbolProfileId], references: [id])
symbolProfileId String
type Type
@ -119,7 +116,7 @@ model SymbolProfile {
assetSubClass AssetSubClass?
countries Json?
createdAt DateTime @default(now())
currency String?
currency String
dataSource DataSource
id String @id @default(uuid())
name String?

@ -192,14 +192,11 @@ async function main() {
{
accountId: '65cfb79d-b6c7-4591-9d46-73426bc62094',
accountUserId: userDemo.id,
currency: 'USD',
dataSource: DataSource.YAHOO,
date: new Date(Date.UTC(2017, 0, 3, 0, 0, 0)),
fee: 30,
id: 'cf7c0418-8535-4089-ae3d-5dbfa0aec2e1',
quantity: 50,
symbol: 'TSLA',
symbolProfileId: 'd1ee9681-fb21-4f99-a3b7-afd4fc04df2e',
symbolProfileId: 'd1ee9681-fb21-4f99-a3b7-afd4fc04df2e', // TSLA
type: Type.BUY,
unitPrice: 42.97,
userId: userDemo.id
@ -207,14 +204,11 @@ async function main() {
{
accountId: 'd804de69-0429-42dc-b6ca-b308fd7dd926',
accountUserId: userDemo.id,
currency: 'USD',
dataSource: DataSource.YAHOO,
date: new Date(Date.UTC(2017, 7, 16, 0, 0, 0)),
fee: 29.9,
id: 'a1c5d73a-8631-44e5-ac44-356827a5212c',
quantity: 0.5614682,
symbol: 'BTCUSD',
symbolProfileId: 'fdc42ea6-1321-44f5-9fb0-d7f1f2cf9b1e',
symbolProfileId: 'fdc42ea6-1321-44f5-9fb0-d7f1f2cf9b1e', // BTCUSD
type: Type.BUY,
unitPrice: 3562.089535970158,
userId: userDemo.id
@ -222,14 +216,11 @@ async function main() {
{
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
accountUserId: userDemo.id,
currency: 'USD',
dataSource: DataSource.YAHOO,
date: new Date(Date.UTC(2018, 9, 1, 0, 0, 0)),
fee: 80.79,
id: '71c08e2a-4a86-44ae-a890-c337de5d5f9b',
quantity: 5,
symbol: 'AMZN',
symbolProfileId: '2bd26362-136e-411c-b578-334084b4cdcc',
symbolProfileId: '2bd26362-136e-411c-b578-334084b4cdcc', // AMZN
type: Type.BUY,
unitPrice: 2021.99,
userId: userDemo.id
@ -237,14 +228,11 @@ async function main() {
{
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
accountUserId: userDemo.id,
currency: 'USD',
dataSource: DataSource.YAHOO,
date: new Date(Date.UTC(2019, 2, 1, 0, 0, 0)),
fee: 19.9,
id: '385f2c2c-d53e-4937-b0e5-e92ef6020d4e',
quantity: 10,
symbol: 'VTI',
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796',
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796', // VTI
type: Type.BUY,
unitPrice: 144.38,
userId: userDemo.id
@ -252,14 +240,11 @@ async function main() {
{
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
accountUserId: userDemo.id,
currency: 'USD',
dataSource: DataSource.YAHOO,
date: new Date(Date.UTC(2019, 8, 3, 0, 0, 0)),
fee: 19.9,
id: '185f2c2c-d53e-4937-b0e5-a93ef6020d4e',
quantity: 10,
symbol: 'VTI',
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796',
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796', // VTI
type: Type.BUY,
unitPrice: 147.99,
userId: userDemo.id
@ -267,14 +252,11 @@ async function main() {
{
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
accountUserId: userDemo.id,
currency: 'USD',
dataSource: DataSource.YAHOO,
date: new Date(Date.UTC(2020, 2, 2, 0, 0, 0)),
fee: 19.9,
id: '347b0430-a84f-4031-a0f9-390399066ad6',
quantity: 10,
symbol: 'VTI',
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796',
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796', // VTI
type: Type.BUY,
unitPrice: 151.41,
userId: userDemo.id
@ -282,14 +264,11 @@ async function main() {
{
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
accountUserId: userDemo.id,
currency: 'USD',
dataSource: DataSource.YAHOO,
date: new Date(Date.UTC(2020, 8, 1, 0, 0, 0)),
fee: 19.9,
id: '67ec3f47-3189-4b63-ba05-60d3a06b302f',
quantity: 10,
symbol: 'VTI',
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796',
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796', // VTI
type: Type.BUY,
unitPrice: 177.69,
userId: userDemo.id
@ -297,14 +276,11 @@ async function main() {
{
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
accountUserId: userDemo.id,
currency: 'USD',
dataSource: DataSource.YAHOO,
date: new Date(Date.UTC(2020, 2, 1, 0, 0, 0)),
fee: 19.9,
id: 'd01c6fbc-fa8d-47e6-8e80-66f882d2bfd2',
quantity: 10,
symbol: 'VTI',
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796',
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796', // VTI
type: Type.BUY,
unitPrice: 203.15,
userId: userDemo.id

Loading…
Cancel
Save