From 9b86a9a73f2fe00509de2d74a51f3081a36cfd6a Mon Sep 17 00:00:00 2001
From: Akash Negi <95514575+AkashNegi1@users.noreply.github.com>
Date: Wed, 24 Jun 2026 23:44:14 +0530
Subject: [PATCH] Task/remove deprecated SymbolProfile from
PortfolioHoldingResponse (#7094)
* Remove deprecated SymbolProfile
* Update changelog
---
CHANGELOG.md | 4 +-
.../src/app/portfolio/portfolio.service.ts | 1 -
.../holding-detail-dialog.component.ts | 52 +++++++++++-------
.../holding-detail-dialog.html | 54 +++++++++----------
.../portfolio-holding-response.interface.ts | 4 --
5 files changed, 60 insertions(+), 55 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f8a0ca796..76dbe113a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,9 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improved the throughput of the market data gathering queue by applying the rate limit per data source
- Decreased the rate limiter duration of the market data gathering queue jobs from 4 to 3 seconds
-
-### Changed
-
+- Removed the deprecated `SymbolProfile` field from the endpoint `GET api/v1/portfolio/holding/:dataSource/:symbol`
- Upgraded `@simplewebauthn/browser` and `@simplewebauthn/server` from version `13.2.2` to `13.3`
### Fixed
diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts
index 77cbb5b49..41697b346 100644
--- a/apps/api/src/app/portfolio/portfolio.service.ts
+++ b/apps/api/src/app/portfolio/portfolio.service.ts
@@ -957,7 +957,6 @@ export class PortfolioService {
marketPrice,
marketPriceMax,
marketPriceMin,
- SymbolProfile,
tags,
assetProfile: {
assetClass: SymbolProfile.assetClass,
diff --git a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts
index e14c638be..6fa3a4853 100644
--- a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts
+++ b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts
@@ -116,6 +116,19 @@ export class GfHoldingDetailDialogComponent implements OnInit {
protected accounts: Account[];
protected activitiesCount: number;
protected assetClass: string;
+ protected assetProfile: Pick<
+ EnhancedSymbolProfile,
+ | 'assetClass'
+ | 'assetSubClass'
+ | 'countries'
+ | 'currency'
+ | 'dataSource'
+ | 'isin'
+ | 'name'
+ | 'sectors'
+ | 'symbol'
+ | 'userId'
+ >;
protected assetSubClass: string;
protected averagePrice: number;
protected averagePricePrecision = 2;
@@ -164,7 +177,6 @@ export class GfHoldingDetailDialogComponent implements OnInit {
};
protected sortColumn = 'date';
protected sortDirection: SortDirection = 'desc';
- protected SymbolProfile: EnhancedSymbolProfile;
protected tagsAvailable: Tag[];
protected readonly translate = translate;
protected user: User;
@@ -266,6 +278,7 @@ export class GfHoldingDetailDialogComponent implements OnInit {
.subscribe(
({
activitiesCount,
+ assetProfile,
averagePrice,
dataProviderInfo,
dateOfFirstActivity,
@@ -280,11 +293,11 @@ export class GfHoldingDetailDialogComponent implements OnInit {
netPerformancePercentWithCurrencyEffect,
netPerformanceWithCurrencyEffect,
quantity,
- SymbolProfile,
tags,
value
}) => {
this.activitiesCount = activitiesCount;
+ this.assetProfile = assetProfile;
this.averagePrice = averagePrice;
if (
@@ -322,8 +335,8 @@ export class GfHoldingDetailDialogComponent implements OnInit {
this.user?.permissions,
permissions.readMarketDataOfOwnAssetProfile
) &&
- SymbolProfile?.dataSource === 'MANUAL' &&
- SymbolProfile?.userId === this.user?.id;
+ assetProfile?.dataSource === 'MANUAL' &&
+ assetProfile?.userId === this.user?.id;
this.historicalDataItems = historicalData.map(
({ averagePrice, date, marketPrice }) => {
@@ -402,7 +415,7 @@ export class GfHoldingDetailDialogComponent implements OnInit {
if (Number.isInteger(this.quantity)) {
this.quantityPrecision = 0;
- } else if (SymbolProfile?.assetSubClass === 'CRYPTOCURRENCY') {
+ } else if (assetProfile?.assetSubClass === 'CRYPTOCURRENCY') {
if (this.quantity < 10) {
this.quantityPrecision = 8;
} else if (this.quantity < 1000) {
@@ -413,7 +426,6 @@ export class GfHoldingDetailDialogComponent implements OnInit {
}
this.sectors = {};
- this.SymbolProfile = SymbolProfile;
this.tags = tags.map((tag) => {
return {
@@ -427,21 +439,21 @@ export class GfHoldingDetailDialogComponent implements OnInit {
this.value = value;
const reportDataGlitchSubject = `Ghostfolio Data Glitch Report${
- this.SymbolProfile?.symbol ? ` (${this.SymbolProfile.symbol})` : ''
+ this.assetProfile?.symbol ? ` (${this.assetProfile.symbol})` : ''
}`;
- this.reportDataGlitchMail = `mailto:hi@ghostfol.io?Subject=${reportDataGlitchSubject}&body=Hello%0D%0DI would like to report a data glitch for%0D%0DSymbol: ${this.SymbolProfile?.symbol}%0DData Source: ${this.SymbolProfile?.dataSource}%0D%0DAdditional notes:%0D%0DCan you please take a look?%0D%0DKind regards`;
+ this.reportDataGlitchMail = `mailto:hi@ghostfol.io?Subject=${reportDataGlitchSubject}&body=Hello%0D%0DI would like to report a data glitch for%0D%0DSymbol: ${this.assetProfile?.symbol}%0DData Source: ${this.assetProfile?.dataSource}%0D%0DAdditional notes:%0D%0DCan you please take a look?%0D%0DKind regards`;
- if (this.SymbolProfile?.assetClass) {
- this.assetClass = translate(this.SymbolProfile?.assetClass);
+ if (this.assetProfile?.assetClass) {
+ this.assetClass = translate(this.assetProfile?.assetClass);
}
- if (this.SymbolProfile?.assetSubClass) {
- this.assetSubClass = translate(this.SymbolProfile?.assetSubClass);
+ if (this.assetProfile?.assetSubClass) {
+ this.assetSubClass = translate(this.assetProfile?.assetSubClass);
}
- if (this.SymbolProfile?.countries?.length > 0) {
- for (const country of this.SymbolProfile.countries) {
+ if (this.assetProfile?.countries?.length > 0) {
+ for (const country of this.assetProfile.countries) {
this.countries[country.code] = {
name: getCountryName({ code: country.code }),
value: country.weight
@@ -449,8 +461,8 @@ export class GfHoldingDetailDialogComponent implements OnInit {
}
}
- if (this.SymbolProfile?.sectors?.length > 0) {
- for (const sector of this.SymbolProfile.sectors) {
+ if (this.assetProfile?.sectors?.length > 0) {
+ for (const sector of this.assetProfile.sectors) {
this.sectors[sector.name] = {
name: translate(sector.name),
value: sector.weight
@@ -570,12 +582,12 @@ export class GfHoldingDetailDialogComponent implements OnInit {
const activity: CreateOrderDto = {
accountId: this.accounts.length === 1 ? this.accounts[0].id : undefined,
comment: undefined,
- currency: this.SymbolProfile?.currency ?? '',
- dataSource: this.SymbolProfile?.dataSource,
+ currency: this.assetProfile?.currency ?? '',
+ dataSource: this.assetProfile?.dataSource,
date: today.toISOString(),
fee: 0,
quantity: this.quantity,
- symbol: this.SymbolProfile?.symbol ?? '',
+ symbol: this.assetProfile?.symbol ?? '',
tags: this.tags.map(({ id }) => {
return id;
}),
@@ -606,7 +618,7 @@ export class GfHoldingDetailDialogComponent implements OnInit {
.subscribe((data) => {
downloadAsFile({
content: data,
- fileName: `ghostfolio-export-${this.SymbolProfile?.symbol}-${format(
+ fileName: `ghostfolio-export-${this.assetProfile?.symbol}-${format(
parseISO(data.meta.date),
'yyyyMMddHHmm'
)}.json`,
diff --git a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html
index 0d5691874..ff1d19cc3 100644
--- a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html
+++ b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html
@@ -1,7 +1,7 @@