Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
aee7c12c44 | |||
125956eb3e | |||
954224401d | |||
d268de3e12 | |||
39cfb4603b |
32
CHANGELOG.md
32
CHANGELOG.md
@ -5,14 +5,28 @@ 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/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 0.91.0 - 25.04.2021
|
||||
|
||||
### Added
|
||||
|
||||
- Extended the support for feature flags to simplify the initial project setup
|
||||
- Prepared for multi accounts support
|
||||
|
||||
### Changed
|
||||
|
||||
- Improved the styling of the rules in the _X-ray_ section
|
||||
|
||||
## 0.90.0 - 22.04.2021
|
||||
|
||||
### Added
|
||||
|
||||
- Improved the user table of the admin control panel
|
||||
- Added the symbol logo to the position detail dialog
|
||||
- Introduced a third option for the market state: `delayed` (besides `open` and `closed`)
|
||||
|
||||
### Changed
|
||||
|
||||
- Improved the user table of the admin control panel
|
||||
|
||||
## 0.89.0 - 21.04.2021
|
||||
|
||||
### Added
|
||||
@ -92,7 +106,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Fixed
|
||||
|
||||
- Fixed an issue in the portfolio update on deleting a transaction
|
||||
- Fixed an issue in the _X-Ray_ section (missing redirection on logout)
|
||||
- Fixed an issue in the _X-ray_ section (missing redirection on logout)
|
||||
|
||||
## 0.82.0 - 10.04.2021
|
||||
|
||||
@ -165,7 +179,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Changed
|
||||
|
||||
- Grouped the _X-Ray_ section visually in _Currency Cluster Risk_ and _Platform Cluster Risk_
|
||||
- Grouped the _X-ray_ section visually in _Currency Cluster Risk_ and _Platform Cluster Risk_
|
||||
|
||||
## 0.76.0 - 02.04.2021
|
||||
|
||||
@ -177,7 +191,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed an issue in the _X-Ray_ section (empty portfolio)
|
||||
- Fixed an issue in the _X-ray_ section (empty portfolio)
|
||||
|
||||
## 0.75.0 - 01.04.2021
|
||||
|
||||
@ -190,7 +204,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Added
|
||||
|
||||
- Added a _Create Account_ message in the _Live Demo_
|
||||
- Added skeleton loaders to the _X-Ray_ section
|
||||
- Added skeleton loaders to the _X-ray_ section
|
||||
|
||||
### Changed
|
||||
|
||||
@ -206,7 +220,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Changed
|
||||
|
||||
- Improved the intro text in the _X-Ray_ section
|
||||
- Improved the intro text in the _X-ray_ section
|
||||
|
||||
### Fixed
|
||||
|
||||
@ -222,7 +236,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Added
|
||||
|
||||
- Added an intro text to the _X-Ray_ section
|
||||
- Added an intro text to the _X-ray_ section
|
||||
|
||||
### Changed
|
||||
|
||||
@ -241,7 +255,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Changed
|
||||
|
||||
- Improved the styling in the _X-Ray_ section
|
||||
- Improved the styling in the _X-ray_ section
|
||||
|
||||
## 0.70.0 - 27.03.2021
|
||||
|
||||
@ -249,7 +263,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
- Added the current _Fear & Greed Index_ as text
|
||||
- Extended the landing page text: _Ghostfolio_ empowers busy folks...
|
||||
- Added the first static portfolio analysis rule in the brand new _X-Ray_ section
|
||||
- Added the first static portfolio analysis rule in the brand new _X-ray_ section
|
||||
|
||||
### Changed
|
||||
|
||||
|
@ -26,7 +26,11 @@ export class InfoService {
|
||||
const globalPermissions: string[] = [];
|
||||
|
||||
if (this.configurationService.get('ENABLE_FEATURE_SOCIAL_LOGIN')) {
|
||||
globalPermissions.push(permissions.useSocialLogin);
|
||||
globalPermissions.push(permissions.enableSocialLogin);
|
||||
}
|
||||
|
||||
if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) {
|
||||
globalPermissions.push(permissions.enableSubscription);
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -116,7 +116,15 @@ export class UserService {
|
||||
|
||||
public async createUser(data?: Prisma.UserCreateInput): Promise<User> {
|
||||
let user = await this.prisma.user.create({
|
||||
data
|
||||
data: {
|
||||
...data,
|
||||
Account: {
|
||||
create: {
|
||||
isDefault: true,
|
||||
name: 'Default Account'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (data.provider === Provider.ANONYMOUS) {
|
||||
|
@ -15,6 +15,7 @@ export class ConfigurationService {
|
||||
ENABLE_FEATURE_CUSTOM_SYMBOLS: bool({ default: false }),
|
||||
ENABLE_FEATURE_FEAR_AND_GREED_INDEX: bool({ default: false }),
|
||||
ENABLE_FEATURE_SOCIAL_LOGIN: bool({ default: false }),
|
||||
ENABLE_FEATURE_SUBSCRIPTION: bool({ default: false }),
|
||||
GOOGLE_CLIENT_ID: str({ default: 'dummyClientId' }),
|
||||
GOOGLE_SECRET: str({ default: 'dummySecret' }),
|
||||
JWT_SECRET_KEY: str({}),
|
||||
|
@ -15,6 +15,8 @@ import { PrismaService } from '../../prisma.service';
|
||||
|
||||
@Injectable()
|
||||
export class GhostfolioScraperApiService implements DataProviderInterface {
|
||||
private static NUMERIC_REGEXP = /[-]{0,1}[\d]*[.,]{0,1}[\d]+/g;
|
||||
|
||||
public constructor(private prisma: PrismaService) {}
|
||||
|
||||
public async get(
|
||||
@ -75,12 +77,9 @@ export class GhostfolioScraperApiService implements DataProviderInterface {
|
||||
const html = await get();
|
||||
const $ = cheerio.load(html);
|
||||
|
||||
const string = $(scraperConfig?.selector)
|
||||
.text()
|
||||
.replace('CHF', '')
|
||||
.trim();
|
||||
|
||||
const value = parseFloat(string);
|
||||
const value = this.extractNumberFromString(
|
||||
$(scraperConfig?.selector).text()
|
||||
);
|
||||
|
||||
return {
|
||||
[symbol]: {
|
||||
@ -96,6 +95,17 @@ export class GhostfolioScraperApiService implements DataProviderInterface {
|
||||
return {};
|
||||
}
|
||||
|
||||
private extractNumberFromString(aString: string): number {
|
||||
try {
|
||||
const [numberString] = aString.match(
|
||||
GhostfolioScraperApiService.NUMERIC_REGEXP
|
||||
);
|
||||
return parseFloat(numberString.trim());
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
private async getScraperConfig(aSymbol: string) {
|
||||
try {
|
||||
const {
|
||||
|
@ -7,6 +7,7 @@ export interface Environment extends CleanedEnvAccessors {
|
||||
ENABLE_FEATURE_CUSTOM_SYMBOLS: boolean;
|
||||
ENABLE_FEATURE_FEAR_AND_GREED_INDEX: boolean;
|
||||
ENABLE_FEATURE_SOCIAL_LOGIN: boolean;
|
||||
ENABLE_FEATURE_SUBSCRIPTION: boolean;
|
||||
GOOGLE_CLIENT_ID: string;
|
||||
GOOGLE_SECRET: string;
|
||||
JWT_SECRET_KEY: string;
|
||||
|
@ -2,7 +2,8 @@ import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
@Injectable()
|
||||
export class PrismaService extends PrismaClient
|
||||
export class PrismaService
|
||||
extends PrismaClient
|
||||
implements OnModuleInit, OnModuleDestroy {
|
||||
async onModuleInit() {
|
||||
await this.$connect();
|
||||
|
@ -37,7 +37,7 @@
|
||||
>Transactions</a
|
||||
>
|
||||
<a
|
||||
*ngIf="canAccessAdminAccessControl"
|
||||
*ngIf="hasPermissionToAccessAdminControl"
|
||||
class="d-none d-sm-block mx-1"
|
||||
[routerLink]="['/admin']"
|
||||
i18n
|
||||
@ -150,7 +150,7 @@
|
||||
>Account</a
|
||||
>
|
||||
<a
|
||||
*ngIf="canAccessAdminAccessControl"
|
||||
*ngIf="hasPermissionForAdminControl"
|
||||
class="d-block d-sm-none"
|
||||
[routerLink]="['/admin']"
|
||||
i18n
|
||||
|
@ -27,8 +27,8 @@ export class HeaderComponent implements OnChanges {
|
||||
@Input() info: InfoItem;
|
||||
@Input() user: User;
|
||||
|
||||
public canAccessAdminAccessControl: boolean;
|
||||
public hasPermissionToUseSocialLogin: boolean;
|
||||
public hasPermissionToAccessAdminControl: boolean;
|
||||
public hasPermissionForSocialLogin: boolean;
|
||||
public impersonationId: string;
|
||||
|
||||
private unsubscribeSubject = new Subject<void>();
|
||||
@ -49,15 +49,15 @@ export class HeaderComponent implements OnChanges {
|
||||
|
||||
public ngOnChanges() {
|
||||
if (this.user) {
|
||||
this.canAccessAdminAccessControl = hasPermission(
|
||||
this.hasPermissionToAccessAdminControl = hasPermission(
|
||||
this.user.permissions,
|
||||
permissions.accessAdminControl
|
||||
);
|
||||
}
|
||||
|
||||
this.hasPermissionToUseSocialLogin = hasPermission(
|
||||
this.hasPermissionForSocialLogin = hasPermission(
|
||||
this.info?.globalPermissions,
|
||||
permissions.useSocialLogin
|
||||
permissions.enableSocialLogin
|
||||
);
|
||||
}
|
||||
|
||||
@ -81,7 +81,7 @@ export class HeaderComponent implements OnChanges {
|
||||
autoFocus: false,
|
||||
data: {
|
||||
accessToken: '',
|
||||
hasPermissionToUseSocialLogin: this.hasPermissionToUseSocialLogin
|
||||
hasPermissionToUseSocialLogin: this.hasPermissionForSocialLogin
|
||||
},
|
||||
width: '30rem'
|
||||
});
|
||||
|
@ -1,18 +1,18 @@
|
||||
<div class="py-3">
|
||||
<div class="flex-nowrap no-gutters row">
|
||||
<div class="align-items-center flex-nowrap no-gutters row">
|
||||
<div *ngIf="isLoading">
|
||||
<ngx-skeleton-loader
|
||||
animation="pulse"
|
||||
class="mr-3"
|
||||
class="mr-2"
|
||||
[theme]="{
|
||||
height: '3rem',
|
||||
width: '3rem'
|
||||
height: '2rem',
|
||||
width: '2rem'
|
||||
}"
|
||||
></ngx-skeleton-loader>
|
||||
</div>
|
||||
<div
|
||||
*ngIf="!isLoading"
|
||||
class="align-items-center d-flex icon-container mr-3 px-3"
|
||||
class="align-items-center d-flex icon-container mr-2 px-2"
|
||||
[ngClass]="{ okay: rule?.value === true, warn: rule?.value === false }"
|
||||
>
|
||||
<ion-icon
|
||||
|
@ -2,15 +2,16 @@
|
||||
display: block;
|
||||
|
||||
.icon-container {
|
||||
background-color: rgba(var(--dark-primary-text), 0.05);
|
||||
border-radius: 0.25rem;
|
||||
height: 3rem;
|
||||
height: 2rem;
|
||||
|
||||
&.okay {
|
||||
background-color: var(--success);
|
||||
color: var(--success);
|
||||
}
|
||||
|
||||
&.warn {
|
||||
background-color: var(--warning);
|
||||
color: var(--danger);
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,6 +22,6 @@
|
||||
|
||||
:host-context(.is-dark-theme) {
|
||||
.icon-container {
|
||||
color: rgba(var(--dark-primary-text));
|
||||
background-color: rgba(var(--light-primary-text), 0.05);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
|
||||
import { InfoItem } from '@ghostfolio/api/app/info/interfaces/info-item.interface';
|
||||
import { User } from '@ghostfolio/api/app/user/interfaces/user.interface';
|
||||
import { DataService } from '@ghostfolio/client/services/data.service';
|
||||
import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service';
|
||||
import { baseCurrency } from '@ghostfolio/helper';
|
||||
import { baseCurrency, hasPermission, permissions } from '@ghostfolio/helper';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
@ -15,6 +16,7 @@ import { environment } from '../../../environments/environment';
|
||||
})
|
||||
export class AboutPageComponent implements OnInit {
|
||||
public baseCurrency = baseCurrency;
|
||||
public hasPermissionForSubscription: boolean;
|
||||
public isLoggedIn: boolean;
|
||||
public lastPublish = environment.lastPublish;
|
||||
public user: User;
|
||||
@ -35,6 +37,13 @@ export class AboutPageComponent implements OnInit {
|
||||
* Initializes the controller
|
||||
*/
|
||||
public ngOnInit() {
|
||||
this.dataService.fetchInfo().subscribe((info) => {
|
||||
this.hasPermissionForSubscription = hasPermission(
|
||||
info.globalPermissions,
|
||||
permissions.enableSubscription
|
||||
);
|
||||
});
|
||||
|
||||
this.isLoggedIn = !!this.tokenStorageService.getToken();
|
||||
|
||||
if (this.isLoggedIn)
|
||||
|
@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-5 row">
|
||||
<div *ngIf="hasPermissionForSubscription" class="mb-5 row">
|
||||
<div class="col">
|
||||
<h3 class="mb-3 text-center" i18n>Pricing Plans</h3>
|
||||
<div class="row">
|
||||
|
@ -3,7 +3,11 @@ import { Access } from '@ghostfolio/api/app/access/interfaces/access.interface';
|
||||
import { User } from '@ghostfolio/api/app/user/interfaces/user.interface';
|
||||
import { DataService } from '@ghostfolio/client/services/data.service';
|
||||
import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service';
|
||||
import { DEFAULT_DATE_FORMAT } from '@ghostfolio/helper';
|
||||
import {
|
||||
DEFAULT_DATE_FORMAT,
|
||||
hasPermission,
|
||||
permissions
|
||||
} from '@ghostfolio/helper';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
@ -19,6 +23,7 @@ export class AccountPageComponent implements OnDestroy, OnInit {
|
||||
public baseCurrency: Currency;
|
||||
public currencies: Currency[] = [];
|
||||
public defaultDateFormat = DEFAULT_DATE_FORMAT;
|
||||
public hasPermissionForSubscription: boolean;
|
||||
public user: User;
|
||||
|
||||
private unsubscribeSubject = new Subject<void>();
|
||||
@ -34,8 +39,13 @@ export class AccountPageComponent implements OnDestroy, OnInit {
|
||||
this.dataService
|
||||
.fetchInfo()
|
||||
.pipe(takeUntil(this.unsubscribeSubject))
|
||||
.subscribe(({ currencies }) => {
|
||||
.subscribe(({ currencies, globalPermissions }) => {
|
||||
this.currencies = currencies;
|
||||
|
||||
this.hasPermissionForSubscription = hasPermission(
|
||||
globalPermissions,
|
||||
permissions.enableSubscription
|
||||
);
|
||||
});
|
||||
|
||||
this.tokenStorageService
|
||||
@ -70,6 +80,11 @@ export class AccountPageComponent implements OnDestroy, OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
public ngOnDestroy() {
|
||||
this.unsubscribeSubject.next();
|
||||
this.unsubscribeSubject.complete();
|
||||
}
|
||||
|
||||
private update() {
|
||||
this.dataService
|
||||
.fetchAccesses()
|
||||
@ -80,9 +95,4 @@ export class AccountPageComponent implements OnDestroy, OnInit {
|
||||
this.cd.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
public ngOnDestroy() {
|
||||
this.unsubscribeSubject.next();
|
||||
this.unsubscribeSubject.complete();
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
<div class="w-50" i18n>Alias</div>
|
||||
<div class="w-50">{{ user.alias }}</div>
|
||||
</div>
|
||||
<div class="d-flex py-1">
|
||||
<div *ngIf="hasPermissionForSubscription" class="d-flex py-1">
|
||||
<div class="w-50" i18n>Membership</div>
|
||||
<div class="w-50">
|
||||
<div class="align-items-center d-flex mb-1">
|
||||
|
@ -10,10 +10,11 @@ export const permissions = {
|
||||
createAccount: 'createAccount',
|
||||
createOrder: 'createOrder',
|
||||
deleteOrder: 'deleteOrder',
|
||||
enableSocialLogin: 'enableSocialLogin',
|
||||
enableSubscription: 'enableSubscription',
|
||||
readForeignPortfolio: 'readForeignPortfolio',
|
||||
updateOrder: 'updateOrder',
|
||||
updateUserSettings: 'updateUserSettings',
|
||||
useSocialLogin: 'useSocialLogin'
|
||||
updateUserSettings: 'updateUserSettings'
|
||||
};
|
||||
|
||||
export function hasPermission(
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ghostfolio",
|
||||
"version": "0.90.0",
|
||||
"version": "0.91.0",
|
||||
"homepage": "https://ghostfol.io",
|
||||
"license": "AGPL-3.0",
|
||||
"scripts": {
|
||||
@ -15,6 +15,9 @@
|
||||
"angular": "node --max_old_space_size=32768 ./node_modules/@angular/cli/bin/ng",
|
||||
"build:all": "ng build --prod api && ng build --prod client && yarn replace-placeholders-in-build",
|
||||
"clean": "rimraf dist",
|
||||
"database:format-schema": "prisma format",
|
||||
"database:generate-typings": "prisma generate",
|
||||
"database:gui": "prisma studio",
|
||||
"database:push": "prisma db push --preview-feature",
|
||||
"database:seed": "prisma db seed --preview-feature",
|
||||
"dep-graph": "nx dep-graph",
|
||||
|
@ -24,6 +24,22 @@ model Access {
|
||||
@@id([id, userId])
|
||||
}
|
||||
|
||||
model Account {
|
||||
accountType AccountType @default(SECURITIES)
|
||||
createdAt DateTime @default(now())
|
||||
id String @default(uuid())
|
||||
isDefault Boolean @default(false)
|
||||
name String?
|
||||
Order Order[]
|
||||
Platform Platform? @relation(fields: [platformId], references: [id])
|
||||
platformId String?
|
||||
updatedAt DateTime @updatedAt
|
||||
User User @relation(fields: [userId], references: [id])
|
||||
userId String
|
||||
|
||||
@@id([id, userId])
|
||||
}
|
||||
|
||||
model Analytics {
|
||||
activityCount Int @default(0)
|
||||
updatedAt DateTime @updatedAt
|
||||
@ -43,29 +59,33 @@ model MarketData {
|
||||
}
|
||||
|
||||
model Order {
|
||||
createdAt DateTime @default(now())
|
||||
currency Currency
|
||||
date DateTime
|
||||
fee Float
|
||||
id String @default(uuid())
|
||||
Platform Platform? @relation(fields: [platformId], references: [id])
|
||||
platformId String?
|
||||
quantity Float
|
||||
symbol String
|
||||
type Type
|
||||
unitPrice Float
|
||||
updatedAt DateTime @updatedAt
|
||||
User User @relation(fields: [userId], references: [id])
|
||||
userId String
|
||||
Account Account? @relation(fields: [accountId, accountUserId], references: [id, userId])
|
||||
accountId String?
|
||||
accountUserId String?
|
||||
createdAt DateTime @default(now())
|
||||
currency Currency
|
||||
date DateTime
|
||||
fee Float
|
||||
id String @default(uuid())
|
||||
Platform Platform? @relation(fields: [platformId], references: [id])
|
||||
platformId String?
|
||||
quantity Float
|
||||
symbol String
|
||||
type Type
|
||||
unitPrice Float
|
||||
updatedAt DateTime @updatedAt
|
||||
User User @relation(fields: [userId], references: [id])
|
||||
userId String
|
||||
|
||||
@@id([id, userId])
|
||||
}
|
||||
|
||||
model Platform {
|
||||
id String @id @default(uuid())
|
||||
name String?
|
||||
url String @unique
|
||||
Order Order[]
|
||||
Account Account[]
|
||||
id String @id @default(uuid())
|
||||
name String?
|
||||
Order Order[]
|
||||
url String @unique
|
||||
}
|
||||
|
||||
model Property {
|
||||
@ -84,6 +104,7 @@ model User {
|
||||
Access Access[] @relation("accessGet")
|
||||
AccessGive Access[] @relation(name: "accessGive")
|
||||
accessToken String?
|
||||
Account Account[]
|
||||
alias String?
|
||||
Analytics Analytics?
|
||||
createdAt DateTime @default(now())
|
||||
@ -96,6 +117,10 @@ model User {
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
enum AccountType {
|
||||
SECURITIES
|
||||
}
|
||||
|
||||
enum Currency {
|
||||
CHF
|
||||
EUR
|
||||
|
231
prisma/seed.ts
231
prisma/seed.ts
@ -1,4 +1,10 @@
|
||||
import { Currency, PrismaClient, Role, Type } from '@prisma/client';
|
||||
import {
|
||||
AccountType,
|
||||
Currency,
|
||||
PrismaClient,
|
||||
Role,
|
||||
Type
|
||||
} from '@prisma/client';
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function main() {
|
||||
@ -88,106 +94,155 @@ async function main() {
|
||||
create: {
|
||||
accessToken:
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjliMTEyYjRkLTNiN2QtNGJhZC05YmRkLTNiMGY3YjRkYWMyZiIsImlhdCI6MTYxODUxMjAxNCwiZXhwIjoxNjIxMTA0MDE0fQ.l3WUxpI0hxuQtdPrD0kd7sem6S2kx_7CrdNvkmlKuWw',
|
||||
alias: 'Demo',
|
||||
id: '9b112b4d-3b7d-4bad-9bdd-3b0f7b4dac2f',
|
||||
role: Role.DEMO,
|
||||
Order: {
|
||||
Account: {
|
||||
create: [
|
||||
{
|
||||
currency: Currency.USD,
|
||||
date: new Date(Date.UTC(2017, 0, 3, 0, 0, 0)),
|
||||
fee: 30,
|
||||
id: 'cf7c0418-8535-4089-ae3d-5dbfa0aec2e1',
|
||||
platformId: platformDegiro.id,
|
||||
quantity: 50,
|
||||
symbol: 'TSLA',
|
||||
type: Type.BUY,
|
||||
unitPrice: 42.97
|
||||
accountType: AccountType.SECURITIES,
|
||||
id: 'd804de69-0429-42dc-b6ca-b308fd7dd926',
|
||||
name: 'Coinbase Account',
|
||||
platformId: platformCoinbase.id
|
||||
},
|
||||
{
|
||||
currency: Currency.USD,
|
||||
date: new Date(Date.UTC(2017, 7, 16, 0, 0, 0)),
|
||||
fee: 29.9,
|
||||
id: 'a1c5d73a-8631-44e5-ac44-356827a5212c',
|
||||
platformId: platformCoinbase.id,
|
||||
quantity: 0.5614682,
|
||||
symbol: 'BTCUSD',
|
||||
type: Type.BUY,
|
||||
unitPrice: 3562.089535970158
|
||||
accountType: AccountType.SECURITIES,
|
||||
id: '65cfb79d-b6c7-4591-9d46-73426bc62094',
|
||||
name: 'DEGIRO Account',
|
||||
platformId: platformDegiro.id
|
||||
},
|
||||
{
|
||||
currency: Currency.USD,
|
||||
date: new Date(Date.UTC(2018, 9, 1, 0, 0, 0)),
|
||||
fee: 80.79,
|
||||
id: '71c08e2a-4a86-44ae-a890-c337de5d5f9b',
|
||||
platformId: platformInteractiveBrokers.id,
|
||||
quantity: 5,
|
||||
symbol: 'AMZN',
|
||||
type: Type.BUY,
|
||||
unitPrice: 2021.99
|
||||
},
|
||||
{
|
||||
currency: Currency.USD,
|
||||
date: new Date(Date.UTC(2019, 2, 1, 0, 0, 0)),
|
||||
fee: 19.9,
|
||||
id: '385f2c2c-d53e-4937-b0e5-e92ef6020d4e',
|
||||
platformId: platformInteractiveBrokers.id,
|
||||
quantity: 10,
|
||||
symbol: 'VTI',
|
||||
type: Type.BUY,
|
||||
unitPrice: 144.38
|
||||
},
|
||||
{
|
||||
currency: Currency.USD,
|
||||
date: new Date(Date.UTC(2019, 8, 3, 0, 0, 0)),
|
||||
fee: 19.9,
|
||||
id: '185f2c2c-d53e-4937-b0e5-a93ef6020d4e',
|
||||
platformId: platformInteractiveBrokers.id,
|
||||
quantity: 10,
|
||||
symbol: 'VTI',
|
||||
type: Type.BUY,
|
||||
unitPrice: 147.99
|
||||
},
|
||||
{
|
||||
currency: Currency.USD,
|
||||
date: new Date(Date.UTC(2020, 2, 2, 0, 0, 0)),
|
||||
fee: 19.9,
|
||||
id: '347b0430-a84f-4031-a0f9-390399066ad6',
|
||||
platformId: platformInteractiveBrokers.id,
|
||||
quantity: 10,
|
||||
symbol: 'VTI',
|
||||
type: Type.BUY,
|
||||
unitPrice: 151.41
|
||||
},
|
||||
{
|
||||
currency: Currency.USD,
|
||||
date: new Date(Date.UTC(2020, 8, 1, 0, 0, 0)),
|
||||
fee: 19.9,
|
||||
id: '67ec3f47-3189-4b63-ba05-60d3a06b302f',
|
||||
platformId: platformInteractiveBrokers.id,
|
||||
quantity: 10,
|
||||
symbol: 'VTI',
|
||||
type: Type.BUY,
|
||||
unitPrice: 177.69
|
||||
},
|
||||
{
|
||||
currency: Currency.USD,
|
||||
date: new Date(Date.UTC(2020, 2, 1, 0, 0, 0)),
|
||||
fee: 19.9,
|
||||
id: 'd01c6fbc-fa8d-47e6-8e80-66f882d2bfd2',
|
||||
platformId: platformInteractiveBrokers.id,
|
||||
quantity: 10,
|
||||
symbol: 'VTI',
|
||||
type: Type.BUY,
|
||||
unitPrice: 203.15
|
||||
accountType: AccountType.SECURITIES,
|
||||
id: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
||||
isDefault: true,
|
||||
name: 'Interactive Brokers Account',
|
||||
platformId: platformInteractiveBrokers.id
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
alias: 'Demo',
|
||||
id: '9b112b4d-3b7d-4bad-9bdd-3b0f7b4dac2f',
|
||||
role: Role.DEMO
|
||||
},
|
||||
update: {},
|
||||
where: { id: '9b112b4d-3b7d-4bad-9bdd-3b0f7b4dac2f' }
|
||||
});
|
||||
|
||||
await prisma.order.createMany({
|
||||
data: [
|
||||
{
|
||||
accountId: '65cfb79d-b6c7-4591-9d46-73426bc62094',
|
||||
accountUserId: userDemo.id,
|
||||
currency: Currency.USD,
|
||||
date: new Date(Date.UTC(2017, 0, 3, 0, 0, 0)),
|
||||
fee: 30,
|
||||
id: 'cf7c0418-8535-4089-ae3d-5dbfa0aec2e1',
|
||||
platformId: platformDegiro.id,
|
||||
quantity: 50,
|
||||
symbol: 'TSLA',
|
||||
type: Type.BUY,
|
||||
unitPrice: 42.97,
|
||||
userId: userDemo.id
|
||||
},
|
||||
{
|
||||
accountId: 'd804de69-0429-42dc-b6ca-b308fd7dd926',
|
||||
accountUserId: userDemo.id,
|
||||
currency: Currency.USD,
|
||||
date: new Date(Date.UTC(2017, 7, 16, 0, 0, 0)),
|
||||
fee: 29.9,
|
||||
id: 'a1c5d73a-8631-44e5-ac44-356827a5212c',
|
||||
platformId: platformCoinbase.id,
|
||||
quantity: 0.5614682,
|
||||
symbol: 'BTCUSD',
|
||||
type: Type.BUY,
|
||||
unitPrice: 3562.089535970158,
|
||||
userId: userDemo.id
|
||||
},
|
||||
{
|
||||
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
||||
accountUserId: userDemo.id,
|
||||
currency: Currency.USD,
|
||||
date: new Date(Date.UTC(2018, 9, 1, 0, 0, 0)),
|
||||
fee: 80.79,
|
||||
id: '71c08e2a-4a86-44ae-a890-c337de5d5f9b',
|
||||
platformId: platformInteractiveBrokers.id,
|
||||
quantity: 5,
|
||||
symbol: 'AMZN',
|
||||
type: Type.BUY,
|
||||
unitPrice: 2021.99,
|
||||
userId: userDemo.id
|
||||
},
|
||||
{
|
||||
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
||||
accountUserId: userDemo.id,
|
||||
currency: Currency.USD,
|
||||
date: new Date(Date.UTC(2019, 2, 1, 0, 0, 0)),
|
||||
fee: 19.9,
|
||||
id: '385f2c2c-d53e-4937-b0e5-e92ef6020d4e',
|
||||
platformId: platformInteractiveBrokers.id,
|
||||
quantity: 10,
|
||||
symbol: 'VTI',
|
||||
type: Type.BUY,
|
||||
unitPrice: 144.38,
|
||||
userId: userDemo.id
|
||||
},
|
||||
{
|
||||
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
||||
accountUserId: userDemo.id,
|
||||
currency: Currency.USD,
|
||||
date: new Date(Date.UTC(2019, 8, 3, 0, 0, 0)),
|
||||
fee: 19.9,
|
||||
id: '185f2c2c-d53e-4937-b0e5-a93ef6020d4e',
|
||||
platformId: platformInteractiveBrokers.id,
|
||||
quantity: 10,
|
||||
symbol: 'VTI',
|
||||
type: Type.BUY,
|
||||
unitPrice: 147.99,
|
||||
userId: userDemo.id
|
||||
},
|
||||
{
|
||||
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
||||
accountUserId: userDemo.id,
|
||||
currency: Currency.USD,
|
||||
date: new Date(Date.UTC(2020, 2, 2, 0, 0, 0)),
|
||||
fee: 19.9,
|
||||
id: '347b0430-a84f-4031-a0f9-390399066ad6',
|
||||
platformId: platformInteractiveBrokers.id,
|
||||
quantity: 10,
|
||||
symbol: 'VTI',
|
||||
type: Type.BUY,
|
||||
unitPrice: 151.41,
|
||||
userId: userDemo.id
|
||||
},
|
||||
{
|
||||
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
||||
accountUserId: userDemo.id,
|
||||
currency: Currency.USD,
|
||||
date: new Date(Date.UTC(2020, 8, 1, 0, 0, 0)),
|
||||
fee: 19.9,
|
||||
id: '67ec3f47-3189-4b63-ba05-60d3a06b302f',
|
||||
platformId: platformInteractiveBrokers.id,
|
||||
quantity: 10,
|
||||
symbol: 'VTI',
|
||||
type: Type.BUY,
|
||||
unitPrice: 177.69,
|
||||
userId: userDemo.id
|
||||
},
|
||||
{
|
||||
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
||||
accountUserId: userDemo.id,
|
||||
currency: Currency.USD,
|
||||
date: new Date(Date.UTC(2020, 2, 1, 0, 0, 0)),
|
||||
fee: 19.9,
|
||||
id: 'd01c6fbc-fa8d-47e6-8e80-66f882d2bfd2',
|
||||
platformId: platformInteractiveBrokers.id,
|
||||
quantity: 10,
|
||||
symbol: 'VTI',
|
||||
type: Type.BUY,
|
||||
unitPrice: 203.15,
|
||||
userId: userDemo.id
|
||||
}
|
||||
],
|
||||
skipDuplicates: true
|
||||
});
|
||||
|
||||
console.log({
|
||||
platformBitcoinSuisse,
|
||||
platformBitpanda,
|
||||
|
Reference in New Issue
Block a user