|
@ -4,9 +4,12 @@ import { |
|
|
hasNotDefinedValuesInObject, |
|
|
hasNotDefinedValuesInObject, |
|
|
nullifyValuesInObject |
|
|
nullifyValuesInObject |
|
|
} from '@ghostfolio/api/helper/object.helper'; |
|
|
} from '@ghostfolio/api/helper/object.helper'; |
|
|
|
|
|
import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request.interceptor'; |
|
|
|
|
|
import { TransformDataSourceInResponseInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-response.interceptor'; |
|
|
import { ConfigurationService } from '@ghostfolio/api/services/configuration.service'; |
|
|
import { ConfigurationService } from '@ghostfolio/api/services/configuration.service'; |
|
|
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; |
|
|
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; |
|
|
import { baseCurrency } from '@ghostfolio/common/config'; |
|
|
import { baseCurrency } from '@ghostfolio/common/config'; |
|
|
|
|
|
import { parseDate } from '@ghostfolio/common/helper'; |
|
|
import { |
|
|
import { |
|
|
PortfolioChart, |
|
|
PortfolioChart, |
|
|
PortfolioDetails, |
|
|
PortfolioDetails, |
|
@ -25,13 +28,11 @@ import { |
|
|
Inject, |
|
|
Inject, |
|
|
Param, |
|
|
Param, |
|
|
Query, |
|
|
Query, |
|
|
Res, |
|
|
UseGuards, |
|
|
UseGuards |
|
|
UseInterceptors |
|
|
} from '@nestjs/common'; |
|
|
} from '@nestjs/common'; |
|
|
import { REQUEST } from '@nestjs/core'; |
|
|
import { REQUEST } from '@nestjs/core'; |
|
|
import { AuthGuard } from '@nestjs/passport'; |
|
|
import { AuthGuard } from '@nestjs/passport'; |
|
|
import { DataSource } from '@prisma/client'; |
|
|
|
|
|
import { Response } from 'express'; |
|
|
|
|
|
import { StatusCodes, getReasonPhrase } from 'http-status-codes'; |
|
|
import { StatusCodes, getReasonPhrase } from 'http-status-codes'; |
|
|
|
|
|
|
|
|
import { PortfolioPositionDetail } from './interfaces/portfolio-position-detail.interface'; |
|
|
import { PortfolioPositionDetail } from './interfaces/portfolio-position-detail.interface'; |
|
@ -53,8 +54,7 @@ export class PortfolioController { |
|
|
@UseGuards(AuthGuard('jwt')) |
|
|
@UseGuards(AuthGuard('jwt')) |
|
|
public async getChart( |
|
|
public async getChart( |
|
|
@Headers('impersonation-id') impersonationId: string, |
|
|
@Headers('impersonation-id') impersonationId: string, |
|
|
@Query('range') range, |
|
|
@Query('range') range |
|
|
@Res() res: Response |
|
|
|
|
|
): Promise<PortfolioChart> { |
|
|
): Promise<PortfolioChart> { |
|
|
const historicalDataContainer = await this.portfolioServiceStrategy |
|
|
const historicalDataContainer = await this.portfolioServiceStrategy |
|
|
.get() |
|
|
.get() |
|
@ -90,27 +90,29 @@ export class PortfolioController { |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return <any>res.json({ |
|
|
return { |
|
|
hasError, |
|
|
hasError, |
|
|
chart: chartData, |
|
|
chart: chartData, |
|
|
isAllTimeHigh: historicalDataContainer.isAllTimeHigh, |
|
|
isAllTimeHigh: historicalDataContainer.isAllTimeHigh, |
|
|
isAllTimeLow: historicalDataContainer.isAllTimeLow |
|
|
isAllTimeLow: historicalDataContainer.isAllTimeLow |
|
|
}); |
|
|
}; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Get('details') |
|
|
@Get('details') |
|
|
@UseGuards(AuthGuard('jwt')) |
|
|
@UseGuards(AuthGuard('jwt')) |
|
|
|
|
|
@UseInterceptors(TransformDataSourceInResponseInterceptor) |
|
|
public async getDetails( |
|
|
public async getDetails( |
|
|
@Headers('impersonation-id') impersonationId: string, |
|
|
@Headers('impersonation-id') impersonationId: string, |
|
|
@Query('range') range, |
|
|
@Query('range') range |
|
|
@Res() res: Response |
|
|
): Promise<PortfolioDetails & { hasError: boolean }> { |
|
|
): Promise<PortfolioDetails> { |
|
|
|
|
|
if ( |
|
|
if ( |
|
|
this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && |
|
|
this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && |
|
|
this.request.user.subscription.type === 'Basic' |
|
|
this.request.user.subscription.type === 'Basic' |
|
|
) { |
|
|
) { |
|
|
res.status(StatusCodes.FORBIDDEN); |
|
|
throw new HttpException( |
|
|
return <any>res.json({ accounts: {}, holdings: {} }); |
|
|
getReasonPhrase(StatusCodes.FORBIDDEN), |
|
|
|
|
|
StatusCodes.FORBIDDEN |
|
|
|
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
let hasError = false; |
|
|
let hasError = false; |
|
@ -159,21 +161,22 @@ export class PortfolioController { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return <any>res.json({ accounts, hasError, holdings }); |
|
|
return { accounts, hasError, holdings }; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Get('investments') |
|
|
@Get('investments') |
|
|
@UseGuards(AuthGuard('jwt')) |
|
|
@UseGuards(AuthGuard('jwt')) |
|
|
public async getInvestments( |
|
|
public async getInvestments( |
|
|
@Headers('impersonation-id') impersonationId: string, |
|
|
@Headers('impersonation-id') impersonationId: string |
|
|
@Res() res: Response |
|
|
|
|
|
): Promise<PortfolioInvestments> { |
|
|
): Promise<PortfolioInvestments> { |
|
|
if ( |
|
|
if ( |
|
|
this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && |
|
|
this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && |
|
|
this.request.user.subscription.type === 'Basic' |
|
|
this.request.user.subscription.type === 'Basic' |
|
|
) { |
|
|
) { |
|
|
res.status(StatusCodes.FORBIDDEN); |
|
|
throw new HttpException( |
|
|
return <any>res.json({}); |
|
|
getReasonPhrase(StatusCodes.FORBIDDEN), |
|
|
|
|
|
StatusCodes.FORBIDDEN |
|
|
|
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
let investments = await this.portfolioServiceStrategy |
|
|
let investments = await this.portfolioServiceStrategy |
|
@ -195,15 +198,14 @@ export class PortfolioController { |
|
|
})); |
|
|
})); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return <any>res.json({ firstOrderDate: investments[0]?.date, investments }); |
|
|
return { firstOrderDate: parseDate(investments[0]?.date), investments }; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Get('performance') |
|
|
@Get('performance') |
|
|
@UseGuards(AuthGuard('jwt')) |
|
|
@UseGuards(AuthGuard('jwt')) |
|
|
public async getPerformance( |
|
|
public async getPerformance( |
|
|
@Headers('impersonation-id') impersonationId: string, |
|
|
@Headers('impersonation-id') impersonationId: string, |
|
|
@Query('range') range, |
|
|
@Query('range') range |
|
|
@Res() res: Response |
|
|
|
|
|
): Promise<{ hasErrors: boolean; performance: PortfolioPerformance }> { |
|
|
): Promise<{ hasErrors: boolean; performance: PortfolioPerformance }> { |
|
|
const performanceInformation = await this.portfolioServiceStrategy |
|
|
const performanceInformation = await this.portfolioServiceStrategy |
|
|
.get() |
|
|
.get() |
|
@ -219,15 +221,15 @@ export class PortfolioController { |
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return <any>res.json(performanceInformation); |
|
|
return performanceInformation; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Get('positions') |
|
|
@Get('positions') |
|
|
|
|
|
@UseInterceptors(TransformDataSourceInResponseInterceptor) |
|
|
@UseGuards(AuthGuard('jwt')) |
|
|
@UseGuards(AuthGuard('jwt')) |
|
|
public async getPositions( |
|
|
public async getPositions( |
|
|
@Headers('impersonation-id') impersonationId: string, |
|
|
@Headers('impersonation-id') impersonationId: string, |
|
|
@Query('range') range, |
|
|
@Query('range') range |
|
|
@Res() res: Response |
|
|
|
|
|
): Promise<PortfolioPositions> { |
|
|
): Promise<PortfolioPositions> { |
|
|
const result = await this.portfolioServiceStrategy |
|
|
const result = await this.portfolioServiceStrategy |
|
|
.get() |
|
|
.get() |
|
@ -247,13 +249,12 @@ export class PortfolioController { |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return <any>res.json(result); |
|
|
return result; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Get('public/:accessId') |
|
|
@Get('public/:accessId') |
|
|
public async getPublic( |
|
|
public async getPublic( |
|
|
@Param('accessId') accessId, |
|
|
@Param('accessId') accessId |
|
|
@Res() res: Response |
|
|
|
|
|
): Promise<PortfolioPublicDetails> { |
|
|
): Promise<PortfolioPublicDetails> { |
|
|
const access = await this.accessService.access({ id: accessId }); |
|
|
const access = await this.accessService.access({ id: accessId }); |
|
|
const user = await this.userService.user({ |
|
|
const user = await this.userService.user({ |
|
@ -261,8 +262,10 @@ export class PortfolioController { |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
if (!access) { |
|
|
if (!access) { |
|
|
res.status(StatusCodes.NOT_FOUND); |
|
|
throw new HttpException( |
|
|
return <any>res.json({ accounts: {}, holdings: {} }); |
|
|
getReasonPhrase(StatusCodes.NOT_FOUND), |
|
|
|
|
|
StatusCodes.NOT_FOUND |
|
|
|
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
let hasDetails = true; |
|
|
let hasDetails = true; |
|
@ -305,7 +308,7 @@ export class PortfolioController { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return <any>res.json(portfolioPublicDetails); |
|
|
return portfolioPublicDetails; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Get('summary') |
|
|
@Get('summary') |
|
@ -339,6 +342,7 @@ export class PortfolioController { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Get('position/:dataSource/:symbol') |
|
|
@Get('position/:dataSource/:symbol') |
|
|
|
|
|
@UseInterceptors(TransformDataSourceInRequestInterceptor) |
|
|
@UseGuards(AuthGuard('jwt')) |
|
|
@UseGuards(AuthGuard('jwt')) |
|
|
public async getPosition( |
|
|
public async getPosition( |
|
|
@Headers('impersonation-id') impersonationId: string, |
|
|
@Headers('impersonation-id') impersonationId: string, |
|
@ -376,21 +380,18 @@ export class PortfolioController { |
|
|
@Get('report') |
|
|
@Get('report') |
|
|
@UseGuards(AuthGuard('jwt')) |
|
|
@UseGuards(AuthGuard('jwt')) |
|
|
public async getReport( |
|
|
public async getReport( |
|
|
@Headers('impersonation-id') impersonationId: string, |
|
|
@Headers('impersonation-id') impersonationId: string |
|
|
@Res() res: Response |
|
|
|
|
|
): Promise<PortfolioReport> { |
|
|
): Promise<PortfolioReport> { |
|
|
if ( |
|
|
if ( |
|
|
this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && |
|
|
this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION') && |
|
|
this.request.user.subscription.type === 'Basic' |
|
|
this.request.user.subscription.type === 'Basic' |
|
|
) { |
|
|
) { |
|
|
res.status(StatusCodes.FORBIDDEN); |
|
|
throw new HttpException( |
|
|
return <any>res.json({ rules: [] }); |
|
|
getReasonPhrase(StatusCodes.FORBIDDEN), |
|
|
|
|
|
StatusCodes.FORBIDDEN |
|
|
|
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return <any>( |
|
|
return await this.portfolioServiceStrategy.get().getReport(impersonationId); |
|
|
res.json( |
|
|
|
|
|
await this.portfolioServiceStrategy.get().getReport(impersonationId) |
|
|
|
|
|
) |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|