Browse Source

Merge 1c9b626858 into 00d908c7e2

pull/7298/merge
Chirag Dodia 2 days ago
committed by GitHub
parent
commit
ed4b12233f
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      CHANGELOG.md
  2. 7
      apps/api/src/app/portfolio/portfolio.controller.ts
  3. 14
      apps/api/src/helper/object.helper.ts

4
CHANGELOG.md

@ -52,6 +52,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improved the language localization for Chinese (`zh`) - Improved the language localization for Chinese (`zh`)
- Improved the language localization for German (`de`) - Improved the language localization for German (`de`)
### Fixed
- Fixed an issue in the portfolio details endpoint that incorrectly reported an error when a holding contained undefined optional values
## 3.22.0 - 2026-07-08 ## 3.22.0 - 2026-07-08
### Added ### Added

7
apps/api/src/app/portfolio/portfolio.controller.ts

@ -2,10 +2,7 @@ import { ActivitiesService } from '@ghostfolio/api/app/activities/activities.ser
import { UserService } from '@ghostfolio/api/app/user/user.service'; import { UserService } from '@ghostfolio/api/app/user/user.service';
import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator'; import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator';
import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard';
import { import { nullifyValuesInObject } from '@ghostfolio/api/helper/object.helper';
hasNotDefinedValuesInObject,
nullifyValuesInObject
} from '@ghostfolio/api/helper/object.helper';
import { PerformanceLoggingInterceptor } from '@ghostfolio/api/interceptors/performance-logging/performance-logging.interceptor'; import { PerformanceLoggingInterceptor } from '@ghostfolio/api/interceptors/performance-logging/performance-logging.interceptor';
import { RedactValuesInResponseInterceptor } from '@ghostfolio/api/interceptors/redact-values-in-response/redact-values-in-response.interceptor'; import { RedactValuesInResponseInterceptor } from '@ghostfolio/api/interceptors/redact-values-in-response/redact-values-in-response.interceptor';
import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor'; import { TransformDataSourceInRequestInterceptor } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.interceptor';
@ -126,7 +123,7 @@ export class PortfolioController {
withSummary: true withSummary: true
}); });
if (hasErrors || hasNotDefinedValuesInObject(holdings)) { if (hasErrors) {
hasError = true; hasError = true;
} }

14
apps/api/src/helper/object.helper.ts

@ -1,18 +1,6 @@
import fastRedact from 'fast-redact'; import fastRedact from 'fast-redact';
import jsonpath from 'jsonpath'; import jsonpath from 'jsonpath';
import { cloneDeep, isObject } from 'lodash'; import { cloneDeep } from 'lodash';
export function hasNotDefinedValuesInObject(aObject: Object): boolean {
for (const key in aObject) {
if (aObject[key] === null || aObject[key] === undefined) {
return true;
} else if (isObject(aObject[key])) {
return hasNotDefinedValuesInObject(aObject[key]);
}
}
return false;
}
export function nullifyValuesInObject<T>(aObject: T, keys: string[]): T { export function nullifyValuesInObject<T>(aObject: T, keys: string[]): T {
const object = cloneDeep(aObject); const object = cloneDeep(aObject);

Loading…
Cancel
Save