Feature/simplify database seeding (#1763)
* Simplify database seeding * Update documentation * Update changelog
This commit is contained in:
parent
261a0fb0b9
commit
cc6320acfd
@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Changed
|
||||
|
||||
- Simplified the database seeding
|
||||
|
||||
### Fixed
|
||||
|
||||
- Downgraded `Node.js` from version `18` to `16` (Dockerfile) to resolve `SIGSEGV` (segmentation fault) during the `prisma` database migrations (see https://github.com/prisma/prisma/issues/10649)
|
||||
|
12
README.md
12
README.md
@ -126,13 +126,10 @@ docker-compose --env-file ./.env -f docker/docker-compose.build.yml build
|
||||
docker-compose --env-file ./.env -f docker/docker-compose.build.yml up -d
|
||||
```
|
||||
|
||||
#### Fetch Historical Data
|
||||
|
||||
Open http://localhost:3333 in your browser and accomplish these steps:
|
||||
#### Setup
|
||||
|
||||
1. Open http://localhost:3333 in your browser
|
||||
1. Create a new user via _Get Started_ (this first user will get the role `ADMIN`)
|
||||
1. Go to the _Market Data_ tab in the _Admin Control Panel_ and click _Gather All Data_ to fetch historical data
|
||||
1. Click _Sign out_ and check out the _Live Demo_
|
||||
|
||||
#### Upgrade Version
|
||||
|
||||
@ -159,11 +156,10 @@ Please follow the instructions of the Ghostfolio [Unraid Community App](https://
|
||||
1. Run `yarn install`
|
||||
1. Run `yarn build:dev` to build the source code including the assets
|
||||
1. Run `docker-compose --env-file ./.env -f docker/docker-compose.dev.yml up -d` to start [PostgreSQL](https://www.postgresql.org) and [Redis](https://redis.io)
|
||||
1. Run `yarn database:setup` to initialize the database schema and populate your database with (example) data
|
||||
1. Run `yarn database:setup` to initialize the database schema
|
||||
1. Start the server and the client (see [_Development_](#Development))
|
||||
1. Open http://localhost:4200/en in your browser
|
||||
1. Create a new user via _Get Started_ (this first user will get the role `ADMIN`)
|
||||
1. Go to the _Market Data_ tab in the _Admin Control Panel_ and click _Gather All Data_ to fetch historical data
|
||||
1. Click _Sign out_ and check out the _Live Demo_
|
||||
|
||||
### Start Server
|
||||
|
||||
|
@ -6,12 +6,12 @@ import { PrismaService } from '@ghostfolio/api/services/prisma.service';
|
||||
import { PropertyService } from '@ghostfolio/api/services/property/property.service';
|
||||
import { TagService } from '@ghostfolio/api/services/tag/tag.service';
|
||||
import {
|
||||
DEMO_USER_ID,
|
||||
PROPERTY_COUNTRIES_OF_SUBSCRIBERS,
|
||||
PROPERTY_IS_READ_ONLY_MODE,
|
||||
PROPERTY_SLACK_COMMUNITY_USERS,
|
||||
PROPERTY_STRIPE_CONFIG,
|
||||
PROPERTY_SYSTEM_MESSAGE,
|
||||
PROPERTY_DEMO_USER_ID,
|
||||
ghostfolioFearAndGreedIndexDataSource
|
||||
} from '@ghostfolio/common/config';
|
||||
import {
|
||||
@ -118,7 +118,7 @@ export class InfoService {
|
||||
baseCurrency: this.configurationService.get('BASE_CURRENCY'),
|
||||
benchmarks: await this.benchmarkService.getBenchmarkAssetProfiles(),
|
||||
currencies: this.exchangeRateDataService.getCurrencies(),
|
||||
demoAuthToken: this.getDemoAuthToken(),
|
||||
demoAuthToken: await this.getDemoAuthToken(),
|
||||
statistics: await this.getStatistics(),
|
||||
subscriptions: await this.getSubscriptions(),
|
||||
tags: await this.tagService.get()
|
||||
@ -246,12 +246,20 @@ export class InfoService {
|
||||
)) as string;
|
||||
}
|
||||
|
||||
private getDemoAuthToken() {
|
||||
private async getDemoAuthToken() {
|
||||
const demoUserId = (await this.propertyService.getByKey(
|
||||
PROPERTY_DEMO_USER_ID
|
||||
)) as string;
|
||||
|
||||
if (demoUserId) {
|
||||
return this.jwtService.sign({
|
||||
id: DEMO_USER_ID
|
||||
id: demoUserId
|
||||
});
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private async getStatistics() {
|
||||
if (!this.configurationService.get('ENABLE_FEATURE_STATISTICS')) {
|
||||
return undefined;
|
||||
|
@ -17,8 +17,8 @@ export class LandingPageComponent implements OnDestroy, OnInit {
|
||||
[code: string]: { value: number };
|
||||
} = {};
|
||||
public currentYear = format(new Date(), 'yyyy');
|
||||
public demoAuthToken: string;
|
||||
public deviceType: string;
|
||||
public hasPermissionForDemo: boolean;
|
||||
public hasPermissionForStatistics: boolean;
|
||||
public hasPermissionForSubscription: boolean;
|
||||
public hasPermissionToCreateUser: boolean;
|
||||
@ -54,6 +54,7 @@ export class LandingPageComponent implements OnDestroy, OnInit {
|
||||
) {
|
||||
const {
|
||||
countriesOfSubscribers = [],
|
||||
demoAuthToken,
|
||||
globalPermissions,
|
||||
statistics
|
||||
} = this.dataService.fetchInfo();
|
||||
@ -64,6 +65,7 @@ export class LandingPageComponent implements OnDestroy, OnInit {
|
||||
};
|
||||
}
|
||||
|
||||
this.hasPermissionForDemo = !!demoAuthToken;
|
||||
this.hasPermissionForStatistics = hasPermission(
|
||||
globalPermissions,
|
||||
permissions.enableStatistics
|
||||
|
@ -40,12 +40,18 @@
|
||||
>
|
||||
Get Started
|
||||
</a>
|
||||
<div class="d-inline-block mx-3 text-muted">or</div></ng-container
|
||||
</ng-container>
|
||||
<ng-container *ngIf="hasPermissionForDemo">
|
||||
<div
|
||||
*ngIf="hasPermissionToCreateUser"
|
||||
class="d-inline-block mx-3 text-muted"
|
||||
>
|
||||
|
||||
or
|
||||
</div>
|
||||
<a class="d-inline-block" mat-stroked-button [routerLink]="['/demo']">
|
||||
Live Demo
|
||||
</a>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -379,16 +385,20 @@
|
||||
<div class="col">
|
||||
<h2 class="h4 mb-1 text-center">Are <strong>you</strong> ready?</h2>
|
||||
<p class="lead mb-3 text-center">
|
||||
Join now or check out the example account
|
||||
Join now<ng-container *ngIf="hasPermissionForDemo">
|
||||
or check out the example account</ng-container
|
||||
>
|
||||
</p>
|
||||
<div class="py-2 text-center">
|
||||
<a color="primary" mat-flat-button [routerLink]="['/register']">
|
||||
Get Started
|
||||
</a>
|
||||
<ng-container *ngIf="hasPermissionForDemo">
|
||||
<div class="d-inline-block mx-3 text-muted">or</div>
|
||||
<a class="d-inline-block" mat-stroked-button [routerLink]="['/demo']">
|
||||
Live Demo
|
||||
</a>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -21,7 +21,6 @@
|
||||
class="d-inline-block"
|
||||
color="primary"
|
||||
mat-flat-button
|
||||
[disabled]="!demoAuthToken"
|
||||
(click)="createAccount()"
|
||||
>
|
||||
<ng-container i18n>Create Account</ng-container>
|
||||
|
@ -2,8 +2,6 @@ import { DataSource } from '@prisma/client';
|
||||
import { JobOptions, JobStatus } from 'bull';
|
||||
import ms from 'ms';
|
||||
|
||||
export const DEMO_USER_ID = '9b112b4d-3b7d-4bad-9bdd-3b0f7b4dac2f';
|
||||
|
||||
export const ghostfolioPrefix = 'GF';
|
||||
export const ghostfolioScraperApiSymbolPrefix = `_${ghostfolioPrefix}_`;
|
||||
export const ghostfolioCashSymbol = `${ghostfolioScraperApiSymbolPrefix}CASH`;
|
||||
@ -79,6 +77,7 @@ export const PROPERTY_BENCHMARKS = 'BENCHMARKS';
|
||||
export const PROPERTY_COUNTRIES_OF_SUBSCRIBERS = 'COUNTRIES_OF_SUBSCRIBERS';
|
||||
export const PROPERTY_COUPONS = 'COUPONS';
|
||||
export const PROPERTY_CURRENCIES = 'CURRENCIES';
|
||||
export const PROPERTY_DEMO_USER_ID = 'DEMO_USER_ID';
|
||||
export const PROPERTY_IS_READ_ONLY_MODE = 'IS_READ_ONLY_MODE';
|
||||
export const PROPERTY_IS_USER_SIGNUP_ENABLED = 'IS_USER_SIGNUP_ENABLED';
|
||||
export const PROPERTY_SLACK_COMMUNITY_USERS = 'SLACK_COMMUNITY_USERS';
|
||||
|
299
prisma/seed.js
299
prisma/seed.js
@ -1,293 +1,7 @@
|
||||
const {
|
||||
AccountType,
|
||||
DataSource,
|
||||
PrismaClient,
|
||||
Role,
|
||||
Type
|
||||
} = require('@prisma/client');
|
||||
const { PrismaClient } = require('@prisma/client');
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function main() {
|
||||
const platformBitcoinSuisse = await prisma.platform.upsert({
|
||||
create: {
|
||||
id: '70b6e475-a2b9-4527-99db-943e4f38ce45',
|
||||
name: 'Bitcoin Suisse',
|
||||
url: 'https://www.bitcoinsuisse.com'
|
||||
},
|
||||
update: {},
|
||||
where: { id: '70b6e475-a2b9-4527-99db-943e4f38ce45' }
|
||||
});
|
||||
|
||||
const platformBitpanda = await prisma.platform.upsert({
|
||||
create: {
|
||||
id: 'debf9110-498f-4811-b972-7ebbd317e730',
|
||||
name: 'Bitpanda',
|
||||
url: 'https://www.bitpanda.com'
|
||||
},
|
||||
update: {},
|
||||
where: { id: 'debf9110-498f-4811-b972-7ebbd317e730' }
|
||||
});
|
||||
|
||||
const platformCoinbase = await prisma.platform.upsert({
|
||||
create: {
|
||||
id: '8dc24b88-bb92-4152-af25-fe6a31643e26',
|
||||
name: 'Coinbase',
|
||||
url: 'https://www.coinbase.com'
|
||||
},
|
||||
update: {},
|
||||
where: { id: '8dc24b88-bb92-4152-af25-fe6a31643e26' }
|
||||
});
|
||||
|
||||
const platformDegiro = await prisma.platform.upsert({
|
||||
create: {
|
||||
id: '94c1a2f4-a666-47be-84cd-4c8952e74c81',
|
||||
name: 'DEGIRO',
|
||||
url: 'https://www.degiro.eu'
|
||||
},
|
||||
update: {},
|
||||
where: { id: '94c1a2f4-a666-47be-84cd-4c8952e74c81' }
|
||||
});
|
||||
|
||||
const platformInteractiveBrokers = await prisma.platform.upsert({
|
||||
create: {
|
||||
id: '9da3a8a7-4795-43e3-a6db-ccb914189737',
|
||||
name: 'Interactive Brokers',
|
||||
url: 'https://www.interactivebrokers.com'
|
||||
},
|
||||
update: {},
|
||||
where: { id: '9da3a8a7-4795-43e3-a6db-ccb914189737' }
|
||||
});
|
||||
|
||||
const platformPostFinance = await prisma.platform.upsert({
|
||||
create: {
|
||||
id: '5377d9df-0d25-42c2-9d9b-e4c63166281e',
|
||||
name: 'PostFinance',
|
||||
url: 'https://www.postfinance.ch'
|
||||
},
|
||||
update: {},
|
||||
where: { id: '5377d9df-0d25-42c2-9d9b-e4c63166281e' }
|
||||
});
|
||||
|
||||
const platformSwissquote = await prisma.platform.upsert({
|
||||
create: {
|
||||
id: '1377d9df-0d25-42c2-9d9b-e4c63156291f',
|
||||
name: 'Swissquote',
|
||||
url: 'https://swissquote.com'
|
||||
},
|
||||
update: {},
|
||||
where: { id: '1377d9df-0d25-42c2-9d9b-e4c63156291f' }
|
||||
});
|
||||
|
||||
const userDemo = await prisma.user.upsert({
|
||||
create: {
|
||||
accessToken:
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjliMTEyYjRkLTNiN2QtNGJhZC05YmRkLTNiMGY3YjRkYWMyZiIsImlhdCI6MTYxODUxMjAxNCwiZXhwIjoxNjIxMTA0MDE0fQ.l3WUxpI0hxuQtdPrD0kd7sem6S2kx_7CrdNvkmlKuWw',
|
||||
Account: {
|
||||
create: [
|
||||
{
|
||||
accountType: AccountType.SECURITIES,
|
||||
balance: 0,
|
||||
currency: 'USD',
|
||||
id: 'd804de69-0429-42dc-b6ca-b308fd7dd926',
|
||||
name: 'Coinbase Account',
|
||||
platformId: platformCoinbase.id
|
||||
},
|
||||
{
|
||||
accountType: AccountType.SECURITIES,
|
||||
balance: 0,
|
||||
currency: 'EUR',
|
||||
id: '65cfb79d-b6c7-4591-9d46-73426bc62094',
|
||||
name: 'DEGIRO Account',
|
||||
platformId: platformDegiro.id
|
||||
},
|
||||
{
|
||||
accountType: AccountType.SECURITIES,
|
||||
balance: 0,
|
||||
currency: 'USD',
|
||||
id: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
||||
isDefault: true,
|
||||
name: 'Interactive Brokers Account',
|
||||
platformId: platformInteractiveBrokers.id
|
||||
}
|
||||
]
|
||||
},
|
||||
id: '9b112b4d-3b7d-4bad-9bdd-3b0f7b4dac2f',
|
||||
role: Role.DEMO
|
||||
},
|
||||
update: {},
|
||||
where: { id: '9b112b4d-3b7d-4bad-9bdd-3b0f7b4dac2f' }
|
||||
});
|
||||
|
||||
await prisma.symbolProfile.createMany({
|
||||
data: [
|
||||
{
|
||||
assetClass: 'EQUITY',
|
||||
assetSubClass: 'STOCK',
|
||||
countries: [{ code: 'US', weight: 1 }],
|
||||
currency: 'USD',
|
||||
dataSource: DataSource.YAHOO,
|
||||
id: '2bd26362-136e-411c-b578-334084b4cdcc',
|
||||
name: 'Amazon.com Inc.',
|
||||
sectors: [{ name: 'Consumer Cyclical', weight: 1 }],
|
||||
symbol: 'AMZN'
|
||||
},
|
||||
{
|
||||
assetClass: 'CASH',
|
||||
assetSubClass: 'CRYPTOCURRENCY',
|
||||
countries: undefined,
|
||||
currency: 'USD',
|
||||
dataSource: DataSource.YAHOO,
|
||||
id: 'fdc42ea6-1321-44f5-9fb0-d7f1f2cf9b1e',
|
||||
name: 'Bitcoin USD',
|
||||
sectors: undefined,
|
||||
symbol: 'BTCUSD'
|
||||
},
|
||||
{
|
||||
assetClass: 'EQUITY',
|
||||
assetSubClass: 'STOCK',
|
||||
countries: [{ code: 'US', weight: 1 }],
|
||||
currency: 'USD',
|
||||
dataSource: DataSource.YAHOO,
|
||||
id: 'd1ee9681-fb21-4f99-a3b7-afd4fc04df2e',
|
||||
name: 'Tesla Inc.',
|
||||
sectors: [{ name: 'Consumer Cyclical', weight: 1 }],
|
||||
symbol: 'TSLA'
|
||||
},
|
||||
{
|
||||
assetClass: 'EQUITY',
|
||||
assetSubClass: 'ETF',
|
||||
countries: [
|
||||
{ code: 'US', weight: 0.9886789999999981 },
|
||||
{ code: 'NL', weight: 0.000203 },
|
||||
{ code: 'CA', weight: 0.000362 }
|
||||
],
|
||||
currency: 'USD',
|
||||
dataSource: DataSource.YAHOO,
|
||||
id: '7d9c8540-061e-4e7e-b019-0d0f4a84e796',
|
||||
name: 'Vanguard Total Stock Market Index Fund ETF',
|
||||
sectors: [
|
||||
{ name: 'Technology', weight: 0.31393799999999955 },
|
||||
{ name: 'Consumer Cyclical', weight: 0.149224 },
|
||||
{ name: 'Financials', weight: 0.11716100000000002 },
|
||||
{ name: 'Healthcare', weight: 0.13285199999999994 },
|
||||
{ name: 'Consumer Staples', weight: 0.053919000000000016 },
|
||||
{ name: 'Energy', weight: 0.025529999999999997 },
|
||||
{ name: 'Telecommunications', weight: 0.012579 },
|
||||
{ name: 'Industrials', weight: 0.09526399999999995 },
|
||||
{ name: 'Utilities', weight: 0.024791999999999988 },
|
||||
{ name: 'Materials', weight: 0.027664 },
|
||||
{ name: 'Real Estate', weight: 0.03239999999999998 },
|
||||
{ name: 'Communication', weight: 0.0036139999999999996 },
|
||||
{ name: 'Other', weight: 0.000218 }
|
||||
],
|
||||
symbol: 'VTI'
|
||||
}
|
||||
],
|
||||
skipDuplicates: true
|
||||
});
|
||||
|
||||
await prisma.order.createMany({
|
||||
data: [
|
||||
{
|
||||
accountId: '65cfb79d-b6c7-4591-9d46-73426bc62094',
|
||||
accountUserId: userDemo.id,
|
||||
date: new Date(Date.UTC(2017, 0, 3, 0, 0, 0)),
|
||||
fee: 30,
|
||||
id: 'cf7c0418-8535-4089-ae3d-5dbfa0aec2e1',
|
||||
quantity: 50,
|
||||
symbolProfileId: 'd1ee9681-fb21-4f99-a3b7-afd4fc04df2e', // TSLA
|
||||
type: Type.BUY,
|
||||
unitPrice: 42.97,
|
||||
userId: userDemo.id
|
||||
},
|
||||
{
|
||||
accountId: 'd804de69-0429-42dc-b6ca-b308fd7dd926',
|
||||
accountUserId: userDemo.id,
|
||||
date: new Date(Date.UTC(2017, 7, 16, 0, 0, 0)),
|
||||
fee: 29.9,
|
||||
id: 'a1c5d73a-8631-44e5-ac44-356827a5212c',
|
||||
quantity: 0.5614682,
|
||||
symbolProfileId: 'fdc42ea6-1321-44f5-9fb0-d7f1f2cf9b1e', // BTCUSD
|
||||
type: Type.BUY,
|
||||
unitPrice: 3562.089535970158,
|
||||
userId: userDemo.id
|
||||
},
|
||||
{
|
||||
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
||||
accountUserId: userDemo.id,
|
||||
date: new Date(Date.UTC(2018, 9, 1, 0, 0, 0)),
|
||||
fee: 80.79,
|
||||
id: '71c08e2a-4a86-44ae-a890-c337de5d5f9b',
|
||||
quantity: 5,
|
||||
symbolProfileId: '2bd26362-136e-411c-b578-334084b4cdcc', // AMZN
|
||||
type: Type.BUY,
|
||||
unitPrice: 2021.99,
|
||||
userId: userDemo.id
|
||||
},
|
||||
{
|
||||
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
||||
accountUserId: userDemo.id,
|
||||
date: new Date(Date.UTC(2019, 2, 1, 0, 0, 0)),
|
||||
fee: 19.9,
|
||||
id: '385f2c2c-d53e-4937-b0e5-e92ef6020d4e',
|
||||
quantity: 10,
|
||||
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796', // VTI
|
||||
type: Type.BUY,
|
||||
unitPrice: 144.38,
|
||||
userId: userDemo.id
|
||||
},
|
||||
{
|
||||
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
||||
accountUserId: userDemo.id,
|
||||
date: new Date(Date.UTC(2019, 8, 3, 0, 0, 0)),
|
||||
fee: 19.9,
|
||||
id: '185f2c2c-d53e-4937-b0e5-a93ef6020d4e',
|
||||
quantity: 10,
|
||||
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796', // VTI
|
||||
type: Type.BUY,
|
||||
unitPrice: 147.99,
|
||||
userId: userDemo.id
|
||||
},
|
||||
{
|
||||
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
||||
accountUserId: userDemo.id,
|
||||
date: new Date(Date.UTC(2020, 2, 2, 0, 0, 0)),
|
||||
fee: 19.9,
|
||||
id: '347b0430-a84f-4031-a0f9-390399066ad6',
|
||||
quantity: 10,
|
||||
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796', // VTI
|
||||
type: Type.BUY,
|
||||
unitPrice: 151.41,
|
||||
userId: userDemo.id
|
||||
},
|
||||
{
|
||||
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
||||
accountUserId: userDemo.id,
|
||||
date: new Date(Date.UTC(2020, 8, 1, 0, 0, 0)),
|
||||
fee: 19.9,
|
||||
id: '67ec3f47-3189-4b63-ba05-60d3a06b302f',
|
||||
quantity: 10,
|
||||
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796', // VTI
|
||||
type: Type.BUY,
|
||||
unitPrice: 177.69,
|
||||
userId: userDemo.id
|
||||
},
|
||||
{
|
||||
accountId: '480269ce-e12a-4fd1-ac88-c4b0ff3f899c',
|
||||
accountUserId: userDemo.id,
|
||||
date: new Date(Date.UTC(2020, 2, 1, 0, 0, 0)),
|
||||
fee: 19.9,
|
||||
id: 'd01c6fbc-fa8d-47e6-8e80-66f882d2bfd2',
|
||||
quantity: 10,
|
||||
symbolProfileId: '7d9c8540-061e-4e7e-b019-0d0f4a84e796', // VTI
|
||||
type: Type.BUY,
|
||||
unitPrice: 203.15,
|
||||
userId: userDemo.id
|
||||
}
|
||||
],
|
||||
skipDuplicates: true
|
||||
});
|
||||
|
||||
await prisma.tag.createMany({
|
||||
data: [
|
||||
{
|
||||
@ -297,17 +11,6 @@ async function main() {
|
||||
],
|
||||
skipDuplicates: true
|
||||
});
|
||||
|
||||
console.log({
|
||||
platformBitcoinSuisse,
|
||||
platformBitpanda,
|
||||
platformCoinbase,
|
||||
platformDegiro,
|
||||
platformInteractiveBrokers,
|
||||
platformPostFinance,
|
||||
platformSwissquote,
|
||||
userDemo
|
||||
});
|
||||
}
|
||||
|
||||
main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user