Thomas
4 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with
68 additions and
17 deletions
-
CHANGELOG.md
-
apps/api/src/app/experimental/experimental.service.ts
-
apps/api/src/app/order/create-order.dto.ts
-
apps/api/src/app/order/update-order.dto.ts
-
apps/api/src/app/portfolio/interfaces/portfolio-position-detail.interface.ts
-
apps/api/src/app/symbol/interfaces/symbol-item.interface.ts
-
apps/api/src/app/symbol/symbol.service.ts
-
apps/api/src/services/data-provider/ghostfolio-scraper-api/ghostfolio-scraper-api.service.ts
-
apps/api/src/services/data-provider/rakuten-rapid-api/rakuten-rapid-api.service.ts
-
apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts
-
apps/api/src/services/interfaces/interfaces.ts
-
apps/client/src/app/pages/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.component.ts
-
apps/client/src/app/pages/transactions/create-or-update-transaction-dialog/create-or-update-transaction-dialog.html
-
apps/client/src/app/pages/transactions/interfaces/order.interface.ts
-
apps/client/src/app/pages/transactions/transactions-page.component.ts
-
package.json
-
prisma/schema.prisma
|
|
@ -5,6 +5,12 @@ 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.95.0 - 28.04.2021 |
|
|
|
|
|
|
|
### Added |
|
|
|
|
|
|
|
- Added a data source attribute to the transactions model |
|
|
|
|
|
|
|
## 0.94.0 - 27.04.2021 |
|
|
|
|
|
|
|
### Added |
|
|
|
|
|
@ -39,6 +39,7 @@ export class ExperimentalService { |
|
|
|
accountId: undefined, |
|
|
|
accountUserId: undefined, |
|
|
|
createdAt: new Date(), |
|
|
|
dataSource: undefined, |
|
|
|
date: parseISO(order.date), |
|
|
|
fee: 0, |
|
|
|
id: undefined, |
|
|
|
|
|
@ -1,4 +1,4 @@ |
|
|
|
import { Currency, Type } from '@prisma/client'; |
|
|
|
import { Currency, DataSource, Type } from '@prisma/client'; |
|
|
|
import { IsISO8601, IsNumber, IsString, ValidateIf } from 'class-validator'; |
|
|
|
|
|
|
|
export class CreateOrderDto { |
|
|
@ -8,6 +8,9 @@ export class CreateOrderDto { |
|
|
|
@IsString() |
|
|
|
currency: Currency; |
|
|
|
|
|
|
|
@IsString() |
|
|
|
dataSource: DataSource; |
|
|
|
|
|
|
|
@IsISO8601() |
|
|
|
date: string; |
|
|
|
|
|
|
|
|
|
@ -1,4 +1,4 @@ |
|
|
|
import { Currency, Type } from '@prisma/client'; |
|
|
|
import { Currency, DataSource, Type } from '@prisma/client'; |
|
|
|
import { IsISO8601, IsNumber, IsString, ValidateIf } from 'class-validator'; |
|
|
|
|
|
|
|
export class UpdateOrderDto { |
|
|
@ -8,6 +8,9 @@ export class UpdateOrderDto { |
|
|
|
@IsString() |
|
|
|
currency: Currency; |
|
|
|
|
|
|
|
@IsString() |
|
|
|
dataSource: DataSource; |
|
|
|
|
|
|
|
@IsISO8601() |
|
|
|
date: string; |
|
|
|
|
|
|
|
|
|
@ -1,6 +1,8 @@ |
|
|
|
import { Currency } from '@prisma/client'; |
|
|
|
|
|
|
|
export interface PortfolioPositionDetail { |
|
|
|
averagePrice: number; |
|
|
|
currency: string; |
|
|
|
currency: Currency; |
|
|
|
firstBuyDate: string; |
|
|
|
grossPerformance: number; |
|
|
|
grossPerformancePercent: number; |
|
|
|
|
|
@ -1,6 +1,7 @@ |
|
|
|
import { Currency } from '@prisma/client'; |
|
|
|
import { Currency, DataSource } from '@prisma/client'; |
|
|
|
|
|
|
|
export interface SymbolItem { |
|
|
|
currency: Currency; |
|
|
|
dataSource: DataSource; |
|
|
|
marketPrice: number; |
|
|
|
} |
|
|
|
|
|
@ -18,9 +18,10 @@ export class SymbolService { |
|
|
|
|
|
|
|
public async get(aSymbol: string): Promise<SymbolItem> { |
|
|
|
const response = await this.dataProviderService.get([aSymbol]); |
|
|
|
const { currency, marketPrice } = response[aSymbol]; |
|
|
|
const { currency, dataSource, marketPrice } = response[aSymbol]; |
|
|
|
|
|
|
|
return { |
|
|
|
dataSource, |
|
|
|
marketPrice, |
|
|
|
currency: <Currency>(<unknown>currency) |
|
|
|
}; |
|
|
|
|
|
@ -1,3 +1,4 @@ |
|
|
|
import { DataSource } from '.prisma/client'; |
|
|
|
import { getYesterday } from '@ghostfolio/helper'; |
|
|
|
import { Injectable } from '@nestjs/common'; |
|
|
|
import * as bent from 'bent'; |
|
|
@ -45,6 +46,7 @@ export class GhostfolioScraperApiService implements DataProviderInterface { |
|
|
|
[symbol]: { |
|
|
|
marketPrice, |
|
|
|
currency: scraperConfig?.currency, |
|
|
|
dataSource: DataSource.GHOSTFOLIO, |
|
|
|
marketState: MarketState.delayed, |
|
|
|
name: scraperConfig?.name |
|
|
|
} |
|
|
|
|
|
@ -1,3 +1,4 @@ |
|
|
|
import { DataSource } from '.prisma/client'; |
|
|
|
import { getToday, getYesterday } from '@ghostfolio/helper'; |
|
|
|
import { Injectable } from '@nestjs/common'; |
|
|
|
import * as bent from 'bent'; |
|
|
@ -39,6 +40,7 @@ export class RakutenRapidApiService implements DataProviderInterface { |
|
|
|
return { |
|
|
|
'GF.FEAR_AND_GREED_INDEX': { |
|
|
|
currency: undefined, |
|
|
|
dataSource: DataSource.RAKUTEN, |
|
|
|
marketPrice: fgi.now.value, |
|
|
|
marketState: MarketState.open, |
|
|
|
name: RakutenRapidApiService.FEAR_AND_GREED_INDEX_NAME |
|
|
|
|
|
@ -1,3 +1,4 @@ |
|
|
|
import { DataSource } from '.prisma/client'; |
|
|
|
import { isCrypto, isCurrency, parseCurrency } from '@ghostfolio/helper'; |
|
|
|
import { Injectable } from '@nestjs/common'; |
|
|
|
import { format } from 'date-fns'; |
|
|
@ -49,6 +50,7 @@ export class YahooFinanceService implements DataProviderInterface { |
|
|
|
|
|
|
|
response[symbol] = { |
|
|
|
currency: parseCurrency(value.price?.currency), |
|
|
|
dataSource: DataSource.YAHOO, |
|
|
|
exchange: this.parseExchange(value.price?.exchangeName), |
|
|
|
marketState: |
|
|
|
value.price?.marketState === 'REGULAR' || isCrypto(symbol) |
|
|
|
|
|
@ -1,4 +1,4 @@ |
|
|
|
import { Currency, Platform } from '@prisma/client'; |
|
|
|
import { Currency, DataSource, Platform } from '@prisma/client'; |
|
|
|
|
|
|
|
import { OrderType } from '../../models/order-type'; |
|
|
|
|
|
|
@ -51,6 +51,7 @@ export interface IDataProviderHistoricalResponse { |
|
|
|
|
|
|
|
export interface IDataProviderResponse { |
|
|
|
currency: Currency; |
|
|
|
dataSource: DataSource; |
|
|
|
exchange?: string; |
|
|
|
industry?: Industry; |
|
|
|
marketChange?: number; |
|
|
|
|
|
@ -78,8 +78,9 @@ export class CreateOrUpdateTransactionDialog { |
|
|
|
this.dataService |
|
|
|
.fetchSymbolItem(this.data.transaction.symbol) |
|
|
|
.pipe(takeUntil(this.unsubscribeSubject)) |
|
|
|
.subscribe(({ currency, marketPrice }) => { |
|
|
|
.subscribe(({ currency, dataSource, marketPrice }) => { |
|
|
|
this.data.transaction.currency = currency; |
|
|
|
this.data.transaction.dataSource = dataSource; |
|
|
|
this.data.transaction.unitPrice = marketPrice; |
|
|
|
|
|
|
|
this.isLoading = false; |
|
|
@ -90,6 +91,7 @@ export class CreateOrUpdateTransactionDialog { |
|
|
|
|
|
|
|
public onUpdateSymbolByTyping(value: string) { |
|
|
|
this.data.transaction.currency = null; |
|
|
|
this.data.transaction.dataSource = null; |
|
|
|
this.data.transaction.unitPrice = null; |
|
|
|
|
|
|
|
this.data.transaction.symbol = value; |
|
|
|
|
|
@ -58,6 +58,18 @@ |
|
|
|
</mat-select> |
|
|
|
</mat-form-field> |
|
|
|
</div> |
|
|
|
<div class="d-none"> |
|
|
|
<mat-form-field appearance="outline" class="w-100"> |
|
|
|
<mat-label i18n>Data Source</mat-label> |
|
|
|
<input |
|
|
|
disabled |
|
|
|
matInput |
|
|
|
name="dataSource" |
|
|
|
required |
|
|
|
[(ngModel)]="data.transaction.dataSource" |
|
|
|
/> |
|
|
|
</mat-form-field> |
|
|
|
</div> |
|
|
|
<div> |
|
|
|
<mat-form-field appearance="outline" class="w-100"> |
|
|
|
<mat-label i18n>Date</mat-label> |
|
|
@ -113,6 +125,7 @@ |
|
|
|
<mat-form-field appearance="outline" class="w-100"> |
|
|
|
<mat-label i18n>Account</mat-label> |
|
|
|
<mat-select |
|
|
|
disabled |
|
|
|
name="accountId" |
|
|
|
required |
|
|
|
[(value)]="data.transaction.accountId" |
|
|
|
|
|
@ -1,6 +1,9 @@ |
|
|
|
import { Currency, DataSource } from '.prisma/client'; |
|
|
|
|
|
|
|
export interface Order { |
|
|
|
accountId: string; |
|
|
|
currency: string; |
|
|
|
currency: Currency; |
|
|
|
dataSource: DataSource; |
|
|
|
date: Date; |
|
|
|
fee: number; |
|
|
|
id: string; |
|
|
|
|
|
@ -125,6 +125,7 @@ export class TransactionsPageComponent implements OnInit { |
|
|
|
public openUpdateTransactionDialog({ |
|
|
|
accountId, |
|
|
|
currency, |
|
|
|
dataSource, |
|
|
|
date, |
|
|
|
fee, |
|
|
|
id, |
|
|
@ -140,6 +141,7 @@ export class TransactionsPageComponent implements OnInit { |
|
|
|
transaction: { |
|
|
|
accountId, |
|
|
|
currency, |
|
|
|
dataSource, |
|
|
|
date, |
|
|
|
fee, |
|
|
|
id, |
|
|
@ -177,9 +179,9 @@ export class TransactionsPageComponent implements OnInit { |
|
|
|
private openCreateTransactionDialog(): void { |
|
|
|
const dialogRef = this.dialog.open(CreateOrUpdateTransactionDialog, { |
|
|
|
data: { |
|
|
|
accounts: this.user.accounts, |
|
|
|
accounts: this.user?.accounts, |
|
|
|
transaction: { |
|
|
|
accountId: this.user.accounts.find((account) => { |
|
|
|
accountId: this.user?.accounts.find((account) => { |
|
|
|
return account.isDefault; |
|
|
|
})?.id, |
|
|
|
currency: null, |
|
|
|
|
|
@ -1,6 +1,6 @@ |
|
|
|
{ |
|
|
|
"name": "ghostfolio", |
|
|
|
"version": "0.94.0", |
|
|
|
"version": "0.95.0", |
|
|
|
"homepage": "https://ghostfol.io", |
|
|
|
"license": "AGPL-3.0", |
|
|
|
"scripts": { |
|
|
|
|
|
@ -59,22 +59,23 @@ model MarketData { |
|
|
|
} |
|
|
|
|
|
|
|
model Order { |
|
|
|
Account Account? @relation(fields: [accountId, accountUserId], references: [id, userId]) |
|
|
|
Account Account? @relation(fields: [accountId, accountUserId], references: [id, userId]) |
|
|
|
accountId String? |
|
|
|
accountUserId String? |
|
|
|
createdAt DateTime @default(now()) |
|
|
|
createdAt DateTime @default(now()) |
|
|
|
currency Currency |
|
|
|
dataSource DataSource @default(YAHOO) |
|
|
|
date DateTime |
|
|
|
fee Float |
|
|
|
id String @default(uuid()) |
|
|
|
Platform Platform? @relation(fields: [platformId], references: [id]) |
|
|
|
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]) |
|
|
|
updatedAt DateTime @updatedAt |
|
|
|
User User @relation(fields: [userId], references: [id]) |
|
|
|
userId String |
|
|
|
|
|
|
|
@@id([id, userId]) |
|
|
@ -128,6 +129,12 @@ enum Currency { |
|
|
|
USD |
|
|
|
} |
|
|
|
|
|
|
|
enum DataSource { |
|
|
|
GHOSTFOLIO |
|
|
|
RAKUTEN |
|
|
|
YAHOO |
|
|
|
} |
|
|
|
|
|
|
|
enum Provider { |
|
|
|
ANONYMOUS |
|
|
|
GOOGLE |
|
|
|