mirror of https://github.com/ghostfolio/ghostfolio
13 changed files with 195 additions and 45 deletions
@ -0,0 +1,88 @@ |
|||||
|
import { AdminService } from '@ghostfolio/api/app/admin/admin.service'; |
||||
|
import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; |
||||
|
import { MarketDataDetailsResponse } from '@ghostfolio/common/interfaces'; |
||||
|
import { hasPermission, permissions } from '@ghostfolio/common/permissions'; |
||||
|
import { RequestWithUser } from '@ghostfolio/common/types'; |
||||
|
|
||||
|
import { |
||||
|
Body, |
||||
|
Controller, |
||||
|
Get, |
||||
|
HttpException, |
||||
|
Inject, |
||||
|
Param, |
||||
|
Post, |
||||
|
UseGuards |
||||
|
} from '@nestjs/common'; |
||||
|
import { REQUEST } from '@nestjs/core'; |
||||
|
import { AuthGuard } from '@nestjs/passport'; |
||||
|
import { DataSource, Prisma } from '@prisma/client'; |
||||
|
import { parseISO } from 'date-fns'; |
||||
|
import { getReasonPhrase, StatusCodes } from 'http-status-codes'; |
||||
|
|
||||
|
import { UpdateBulkMarketDataDto } from './update-bulk-market-data.dto'; |
||||
|
|
||||
|
@Controller('market-data') |
||||
|
export class MarketDataController { |
||||
|
public constructor( |
||||
|
private readonly adminService: AdminService, |
||||
|
private readonly marketDataService: MarketDataService, |
||||
|
@Inject(REQUEST) private readonly request: RequestWithUser |
||||
|
) {} |
||||
|
|
||||
|
@Get(':dataSource/:symbol') |
||||
|
@UseGuards(AuthGuard('jwt')) |
||||
|
public async getMarketDataBySymbol( |
||||
|
@Param('dataSource') dataSource: DataSource, |
||||
|
@Param('symbol') symbol: string |
||||
|
): Promise<MarketDataDetailsResponse> { |
||||
|
if ( |
||||
|
!hasPermission(this.request.user.permissions, permissions.readMarketData) |
||||
|
) { |
||||
|
throw new HttpException( |
||||
|
getReasonPhrase(StatusCodes.FORBIDDEN), |
||||
|
StatusCodes.FORBIDDEN |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
return this.adminService.getMarketDataBySymbol({ dataSource, symbol }); |
||||
|
} |
||||
|
|
||||
|
@Post(':dataSource/:symbol') |
||||
|
@UseGuards(AuthGuard('jwt')) |
||||
|
public async updateMarketData( |
||||
|
@Body() data: UpdateBulkMarketDataDto, |
||||
|
@Param('dataSource') dataSource: DataSource, |
||||
|
@Param('symbol') symbol: string |
||||
|
) { |
||||
|
if ( |
||||
|
!hasPermission( |
||||
|
this.request.user.permissions, |
||||
|
permissions.createMarketData |
||||
|
) || |
||||
|
!hasPermission( |
||||
|
this.request.user.permissions, |
||||
|
permissions.updateMarketData |
||||
|
) |
||||
|
) { |
||||
|
throw new HttpException( |
||||
|
getReasonPhrase(StatusCodes.FORBIDDEN), |
||||
|
StatusCodes.FORBIDDEN |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
const dataBulkUpdate: Prisma.MarketDataUpdateInput[] = data.marketData.map( |
||||
|
({ date, marketPrice }) => ({ |
||||
|
dataSource, |
||||
|
marketPrice, |
||||
|
symbol, |
||||
|
date: parseISO(date), |
||||
|
state: 'CLOSE' |
||||
|
}) |
||||
|
); |
||||
|
|
||||
|
return this.marketDataService.updateMany({ |
||||
|
data: dataBulkUpdate |
||||
|
}); |
||||
|
} |
||||
|
} |
@ -0,0 +1,12 @@ |
|||||
|
import { AdminModule } from '@ghostfolio/api/app/admin/admin.module'; |
||||
|
import { MarketDataModule as MarketDataServiceModule } from '@ghostfolio/api/services/market-data/market-data.module'; |
||||
|
|
||||
|
import { Module } from '@nestjs/common'; |
||||
|
|
||||
|
import { MarketDataController } from './market-data.controller'; |
||||
|
|
||||
|
@Module({ |
||||
|
controllers: [MarketDataController], |
||||
|
imports: [AdminModule, MarketDataServiceModule] |
||||
|
}) |
||||
|
export class MarketDataModule {} |
@ -0,0 +1,24 @@ |
|||||
|
import { Type } from 'class-transformer'; |
||||
|
import { |
||||
|
ArrayNotEmpty, |
||||
|
IsArray, |
||||
|
IsISO8601, |
||||
|
IsNumber, |
||||
|
IsOptional |
||||
|
} from 'class-validator'; |
||||
|
|
||||
|
export class UpdateBulkMarketDataDto { |
||||
|
@ArrayNotEmpty() |
||||
|
@IsArray() |
||||
|
@Type(() => UpdateMarketDataDto) |
||||
|
marketData: UpdateMarketDataDto[]; |
||||
|
} |
||||
|
|
||||
|
class UpdateMarketDataDto { |
||||
|
@IsISO8601() |
||||
|
@IsOptional() |
||||
|
date?: string; |
||||
|
|
||||
|
@IsNumber() |
||||
|
marketPrice: number; |
||||
|
} |
@ -0,0 +1,8 @@ |
|||||
|
import { MarketData } from '@prisma/client'; |
||||
|
|
||||
|
import { EnhancedSymbolProfile } from '../enhanced-symbol-profile.interface'; |
||||
|
|
||||
|
export interface MarketDataDetailsResponse { |
||||
|
assetProfile: Partial<EnhancedSymbolProfile>; |
||||
|
marketData: MarketData[]; |
||||
|
} |
Loading…
Reference in new issue