Browse Source

Merge 48d8e17a7d into 747dbce8ee

pull/7576/merge
Thomas Kaul 3 weeks ago
committed by GitHub
parent
commit
281f05aa22
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 10
      CHANGELOG.md
  2. 9
      apps/api/src/app/admin/admin.controller.ts
  3. 33
      apps/api/src/app/endpoints/market-data/market-data.controller.ts
  4. 3
      libs/common/src/lib/dtos/update-bulk-market-data.dto.ts
  5. 5
      libs/common/src/lib/dtos/update-market-data.dto.ts
  6. 2
      libs/common/src/lib/helper.ts

10
CHANGELOG.md

@ -5,6 +5,16 @@ 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).
## Unreleased
### Changed
- Improved the validation of the market data items in the market data update endpoint
### Fixed
- Fixed the date normalization in the market data endpoints in time zones with a non-zero _UTC_ offset
## 3.45.0 - 2026-08-08
### Added

9
apps/api/src/app/admin/admin.controller.ts

@ -19,7 +19,8 @@ import {
} from '@ghostfolio/common/dtos';
import {
canDeleteAssetProfile,
getAssetProfileIdentifier
getAssetProfileIdentifier,
getStartOfUtcDate
} from '@ghostfolio/common/helper';
import {
AdminData,
@ -55,7 +56,7 @@ import {
import { REQUEST } from '@nestjs/core';
import { AuthGuard } from '@nestjs/passport';
import { DataSource, MarketData, Prisma, SymbolProfile } from '@prisma/client';
import { isDate, parseISO } from 'date-fns';
import { isValid } from 'date-fns';
import { StatusCodes, getReasonPhrase } from 'http-status-codes';
import { AdminService } from './admin.service';
@ -201,9 +202,9 @@ export class AdminController {
@Param('dateString') dateString: string,
@Param('symbol') symbol: string
): Promise<MarketData> {
const date = parseISO(dateString);
const date = getStartOfUtcDate(dateString);
if (!isDate(date)) {
if (!isValid(date)) {
throw new HttpException(
getReasonPhrase(StatusCodes.BAD_REQUEST),
StatusCodes.BAD_REQUEST

33
apps/api/src/app/endpoints/market-data/market-data.controller.ts

@ -4,7 +4,11 @@ import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'
import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service';
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service';
import { UpdateBulkMarketDataDto } from '@ghostfolio/common/dtos';
import { getCurrencyFromSymbol, isCurrency } from '@ghostfolio/common/helper';
import {
getCurrencyFromSymbol,
getStartOfUtcDate,
isCurrency
} from '@ghostfolio/common/helper';
import { MarketDataOfMarketsResponse } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { RequestWithUser } from '@ghostfolio/common/types';
@ -24,7 +28,7 @@ import {
import { REQUEST } from '@nestjs/core';
import { AuthGuard } from '@nestjs/passport';
import { DataSource, Prisma } from '@prisma/client';
import { parseISO } from 'date-fns';
import { isValid } from 'date-fns';
import { getReasonPhrase, StatusCodes } from 'http-status-codes';
@Controller('market-data')
@ -95,13 +99,24 @@ export class MarketDataController {
}
const dataBulkUpdate: Prisma.MarketDataUpdateInput[] = data.marketData.map(
({ date, marketPrice }) => ({
dataSource,
marketPrice,
symbol,
date: parseISO(date),
state: 'CLOSE'
})
({ date, marketPrice }) => {
const startOfUtcDate = getStartOfUtcDate(date);
if (!isValid(startOfUtcDate)) {
throw new HttpException(
getReasonPhrase(StatusCodes.BAD_REQUEST),
StatusCodes.BAD_REQUEST
);
}
return {
dataSource,
marketPrice,
symbol,
date: startOfUtcDate,
state: 'CLOSE'
};
}
);
return this.marketDataService.updateMany({

3
libs/common/src/lib/dtos/update-bulk-market-data.dto.ts

@ -1,11 +1,12 @@
import { UpdateMarketDataDto } from '@ghostfolio/common/dtos';
import { Type } from 'class-transformer';
import { ArrayNotEmpty, IsArray } from 'class-validator';
import { ArrayNotEmpty, IsArray, ValidateNested } from 'class-validator';
export class UpdateBulkMarketDataDto {
@ArrayNotEmpty()
@IsArray()
@Type(() => UpdateMarketDataDto)
@ValidateNested({ each: true })
marketData: UpdateMarketDataDto[];
}

5
libs/common/src/lib/dtos/update-market-data.dto.ts

@ -1,9 +1,8 @@
import { IsISO8601, IsNumber, IsOptional } from 'class-validator';
import { IsISO8601, IsNumber } from 'class-validator';
export class UpdateMarketDataDto {
@IsISO8601()
@IsOptional()
date?: string;
date: string;
@IsNumber()
marketPrice: number;

2
libs/common/src/lib/helper.ts

@ -403,7 +403,7 @@ export function getNumberFormatGroup(aLocale = getLocale()) {
})?.value;
}
export function getStartOfUtcDate(aDate: Date) {
export function getStartOfUtcDate(aDate: Date | string) {
const date = new Date(aDate);
date.setUTCHours(0, 0, 0, 0);

Loading…
Cancel
Save