|
|
@ -29,16 +29,18 @@ import { |
|
|
|
} from '@ghostfolio/common/types'; |
|
|
|
import { Inject, Injectable } from '@nestjs/common'; |
|
|
|
import { REQUEST } from '@nestjs/core'; |
|
|
|
import { DataSource } from '@prisma/client'; |
|
|
|
import { DataSource, Currency, Type as TypeOfOrder } from '@prisma/client'; |
|
|
|
import Big from 'big.js'; |
|
|
|
import { |
|
|
|
add, |
|
|
|
addMonths, |
|
|
|
endOfToday, |
|
|
|
format, |
|
|
|
getDate, |
|
|
|
getMonth, |
|
|
|
getYear, |
|
|
|
isAfter, |
|
|
|
isBefore, |
|
|
|
isSameDay, |
|
|
|
max, |
|
|
|
parse, |
|
|
@ -204,30 +206,25 @@ export class PortfolioService { |
|
|
|
public async getOverview( |
|
|
|
aImpersonationId: string |
|
|
|
): Promise<PortfolioOverview> { |
|
|
|
const impersonationUserId = |
|
|
|
await this.impersonationService.validateImpersonationId( |
|
|
|
aImpersonationId, |
|
|
|
this.request.user.id |
|
|
|
); |
|
|
|
|
|
|
|
const portfolio = await this.createPortfolio( |
|
|
|
impersonationUserId || this.request.user.id |
|
|
|
); |
|
|
|
const userId = await this.getUserId(aImpersonationId); |
|
|
|
|
|
|
|
const currency = this.request.user.Settings.currency; |
|
|
|
const { balance } = await this.accountService.getCashDetails( |
|
|
|
impersonationUserId || this.request.user.id, |
|
|
|
this.request.user.Settings.currency |
|
|
|
userId, |
|
|
|
currency |
|
|
|
); |
|
|
|
const committedFunds = portfolio.getCommittedFunds(); |
|
|
|
const fees = portfolio.getFees(); |
|
|
|
const orders = await this.getOrders(userId); |
|
|
|
const fees = this.getFees(orders); |
|
|
|
|
|
|
|
const totalBuy = this.getTotalByType(orders, currency, TypeOfOrder.BUY); |
|
|
|
const totalSell = this.getTotalByType(orders, currency, TypeOfOrder.SELL); |
|
|
|
return { |
|
|
|
committedFunds, |
|
|
|
committedFunds: totalBuy - totalSell, |
|
|
|
fees, |
|
|
|
cash: balance, |
|
|
|
ordersCount: portfolio.getOrders().length, |
|
|
|
totalBuy: portfolio.getTotalBuy(), |
|
|
|
totalSell: portfolio.getTotalSell() |
|
|
|
ordersCount: orders.length, |
|
|
|
totalBuy: totalBuy, |
|
|
|
totalSell: totalSell |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
@ -586,6 +583,22 @@ export class PortfolioService { |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
public getFees(orders: OrderWithAccount[], date = new Date(0)) { |
|
|
|
return orders |
|
|
|
.filter((order) => { |
|
|
|
// Filter out all orders before given date
|
|
|
|
return isBefore(date, new Date(order.date)); |
|
|
|
}) |
|
|
|
.map((order) => { |
|
|
|
return this.exchangeRateDataService.toCurrency( |
|
|
|
order.fee, |
|
|
|
order.currency, |
|
|
|
this.request.user.Settings.currency |
|
|
|
); |
|
|
|
}) |
|
|
|
.reduce((previous, current) => previous + current, 0); |
|
|
|
} |
|
|
|
|
|
|
|
private getStartDate(aDateRange: DateRange, portfolioStart: Date) { |
|
|
|
switch (aDateRange) { |
|
|
|
case '1d': |
|
|
@ -742,4 +755,23 @@ export class PortfolioService { |
|
|
|
|
|
|
|
return impersonationUserId || this.request.user.id; |
|
|
|
} |
|
|
|
|
|
|
|
private getTotalByType( |
|
|
|
orders: OrderWithAccount[], |
|
|
|
currency: Currency, |
|
|
|
type: TypeOfOrder |
|
|
|
) { |
|
|
|
return orders |
|
|
|
.filter( |
|
|
|
(order) => !isAfter(order.date, endOfToday()) && order.type === type |
|
|
|
) |
|
|
|
.map((order) => { |
|
|
|
return this.exchangeRateDataService.toCurrency( |
|
|
|
order.quantity * order.unitPrice, |
|
|
|
order.currency, |
|
|
|
currency |
|
|
|
); |
|
|
|
}) |
|
|
|
.reduce((previous, current) => previous + current, 0); |
|
|
|
} |
|
|
|
} |
|
|
|