From 263e064fd6b1c55cc547a071023f4dced6185037 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 1 Aug 2026 14:27:47 +0200 Subject: [PATCH] Task/remove deprecated attribute isExcluded from account (#7253) * Remove deprecated attribute isExcluded from account * Update changelog --- CHANGELOG.md | 1 + apps/api/src/app/export/export.service.ts | 2 -- apps/api/src/app/import/import.service.ts | 21 +++++++++++++++++-- .../roai/portfolio-calculator-cash.spec.ts | 3 --- .../app/portfolio/portfolio.service.spec.ts | 3 --- apps/api/src/helper/account.helper.ts | 1 - .../pages/accounts/accounts-page.component.ts | 3 --- ...eate-or-update-account-dialog.component.ts | 4 ---- .../create-or-update-account-dialog.html | 5 ----- .../dtos/create-account-with-balances.dto.ts | 10 ++++++++- .../common/src/lib/dtos/create-account.dto.ts | 8 ------- .../common/src/lib/dtos/update-account.dto.ts | 8 ------- libs/common/src/lib/helper.ts | 6 +----- .../accounts-table.component.stories.ts | 3 --- .../activities-table.component.stories.ts | 5 ----- .../migration.sql | 21 +++++++++++++++++++ prisma/schema.prisma | 3 --- 17 files changed, 51 insertions(+), 56 deletions(-) create mode 100644 prisma/migrations/20260801103609_removed_is_excluded_from_account/migration.sql diff --git a/CHANGELOG.md b/CHANGELOG.md index b80a682c4..72a0cc95f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Harmonized the data format of the export functionality - Removed the deprecated `firstOrderDate` attribute from the `GET api/v2/portfolio/performance` endpoint response +- Removed the deprecated `isExcluded` attribute of the account in favor of the _Exclude from Analysis_ tag including a data migration - Improved the language localization for German (`de`) - Upgraded `prisma` from version `7.8.0` to `7.9.1` diff --git a/apps/api/src/app/export/export.service.ts b/apps/api/src/app/export/export.service.ts index ec9b89a81..02ccb46b3 100644 --- a/apps/api/src/app/export/export.service.ts +++ b/apps/api/src/app/export/export.service.ts @@ -107,7 +107,6 @@ export class ExportService { comment, currency, id, - isExcluded, name, platform, platformId, @@ -125,7 +124,6 @@ export class ExportService { comment, currency, id, - isExcluded, name, platformId, tags: tags.map(({ id: tagId }) => { diff --git a/apps/api/src/app/import/import.service.ts b/apps/api/src/app/import/import.service.ts index b706baa8d..b8579b795 100644 --- a/apps/api/src/app/import/import.service.ts +++ b/apps/api/src/app/import/import.service.ts @@ -9,7 +9,10 @@ import { MarketDataService } from '@ghostfolio/api/services/market-data/market-d import { DataGatheringService } from '@ghostfolio/api/services/queues/data-gathering/data-gathering.service'; import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service'; import { TagService } from '@ghostfolio/api/services/tag/tag.service'; -import { DATA_GATHERING_QUEUE_PRIORITY_HIGH } from '@ghostfolio/common/config'; +import { + DATA_GATHERING_QUEUE_PRIORITY_HIGH, + TAG_ID_EXCLUDE_FROM_ANALYSIS +} from '@ghostfolio/common/config'; import { CreateAssetProfileDto, CreateOrderDto } from '@ghostfolio/common/dtos'; import { getAssetProfileIdentifier, @@ -272,7 +275,11 @@ export class ImportService { // If there is no account or if the account belongs to a different user then create a new account if (!accountWithSameId || accountWithSameId.userId !== user.id) { - const account = omit(accountWithBalances, ['balances', 'tags']); + const account = omit(accountWithBalances, [ + 'balances', + 'isExcluded', + 'tags' + ]); let oldAccountId: string; const platformId = account.platformId; @@ -292,6 +299,16 @@ export class ImportService { return existingTagIds.has(tagId); }); + // Map the legacy isExcluded attribute of old export files to + // the "Exclude from Analysis" tag + if ( + accountWithBalances.isExcluded && + existingTagIds.has(TAG_ID_EXCLUDE_FROM_ANALYSIS) && + !tagIds.includes(TAG_ID_EXCLUDE_FROM_ANALYSIS) + ) { + tagIds.push(TAG_ID_EXCLUDE_FROM_ANALYSIS); + } + let accountObject: Prisma.AccountCreateInput = { ...account, balances: { diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts index 1fc705b46..aaa2f63cf 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts @@ -186,7 +186,6 @@ describe('PortfolioCalculator', () => { createdAt: parseDate('2023-12-31'), currency: 'USD', id: accountId, - isExcluded: false, name: 'USD', platformId: null, updatedAt: parseDate('2023-12-31'), @@ -362,7 +361,6 @@ describe('PortfolioCalculator', () => { createdAt: parseDate('2023-12-31'), currency: 'CHF', id: accountId, - isExcluded: false, name: 'CHF', platformId: null, updatedAt: parseDate('2023-12-31'), @@ -494,7 +492,6 @@ describe('PortfolioCalculator', () => { createdAt: parseDate('2023-12-31'), currency: 'CHF', id: accountId, - isExcluded: false, name: 'CHF', platformId: null, updatedAt: parseDate('2023-12-31'), diff --git a/apps/api/src/app/portfolio/portfolio.service.spec.ts b/apps/api/src/app/portfolio/portfolio.service.spec.ts index 699e79e0d..97635553f 100644 --- a/apps/api/src/app/portfolio/portfolio.service.spec.ts +++ b/apps/api/src/app/portfolio/portfolio.service.spec.ts @@ -192,7 +192,6 @@ describe('PortfolioService', () => { createdAt: parseDate('2024-01-01'), currency: 'USD', id: randomUUID(), - isExcluded: false, name: 'USD', platformId: null, updatedAt: parseDate('2024-01-01'), @@ -226,7 +225,6 @@ describe('PortfolioService', () => { createdAt: parseDate('2024-01-01'), currency: 'USD', id: accountId, - isExcluded: false, name: 'USD', platformId: null, updatedAt: parseDate('2024-01-01'), @@ -438,7 +436,6 @@ describe('PortfolioService', () => { balance: 100, currency: 'USD', id: randomUUID(), - isExcluded: false, name: 'Account 1', platform: { name: 'Platform 1' }, platformId: randomUUID() diff --git a/apps/api/src/helper/account.helper.ts b/apps/api/src/helper/account.helper.ts index 8e7520d0a..da0762ba5 100644 --- a/apps/api/src/helper/account.helper.ts +++ b/apps/api/src/helper/account.helper.ts @@ -4,7 +4,6 @@ import { Prisma } from '@prisma/client'; import { endOfToday, isAfter } from 'date-fns'; export const WHERE_ACCOUNT_NOT_EXCLUDED: Prisma.AccountWhereInput = { - isExcluded: false, tags: { none: { tagId: TAG_ID_EXCLUDE_FROM_ANALYSIS diff --git a/apps/client/src/app/pages/accounts/accounts-page.component.ts b/apps/client/src/app/pages/accounts/accounts-page.component.ts index 1cf0e44a7..291a7f3f9 100644 --- a/apps/client/src/app/pages/accounts/accounts-page.component.ts +++ b/apps/client/src/app/pages/accounts/accounts-page.component.ts @@ -191,7 +191,6 @@ export class GfAccountsPageComponent implements OnInit { comment, currency, id, - isExcluded, name, platformId, tags @@ -206,7 +205,6 @@ export class GfAccountsPageComponent implements OnInit { comment, currency, id, - isExcluded, name, platformId, tags @@ -288,7 +286,6 @@ export class GfAccountsPageComponent implements OnInit { comment: null, currency: this.user?.settings?.baseCurrency ?? null, id: null, - isExcluded: false, name: null, platformId: null, tags: [] diff --git a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts index de0172eac..8b0536ebf 100644 --- a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts +++ b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.component.ts @@ -27,7 +27,6 @@ import { } from '@angular/forms'; import { MatAutocompleteModule } from '@angular/material/autocomplete'; import { MatButtonModule } from '@angular/material/button'; -import { MatCheckboxModule } from '@angular/material/checkbox'; import { MAT_DIALOG_DATA, MatDialogModule, @@ -51,7 +50,6 @@ import { CreateOrUpdateAccountDialogParams } from './interfaces/interfaces'; GfTagsSelectorComponent, MatAutocompleteModule, MatButtonModule, - MatCheckboxModule, MatDialogModule, MatFormFieldModule, MatInputModule, @@ -106,7 +104,6 @@ export class GfCreateOrUpdateAccountDialogComponent { balance: [this.data.account.balance, Validators.required], comment: [this.data.account.comment], currency: [this.data.account.currency, Validators.required], - isExcluded: [this.data.account.isExcluded], name: [this.data.account.name, Validators.required], platformId: [null, this.autocompleteObjectValidator()], tags: [ @@ -204,7 +201,6 @@ export class GfCreateOrUpdateAccountDialogComponent { comment: this.accountForm.get('comment')?.value ?? null, currency: this.accountForm.get('currency')?.value, id: this.accountForm.get('accountId')?.value, - isExcluded: this.accountForm.get('isExcluded')?.value, name: this.accountForm.get('name')?.value, platformId: this.accountForm.get('platformId')?.value?.id ?? null, tags: this.accountForm diff --git a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html index d5743313d..4e4c62b6f 100644 --- a/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html +++ b/apps/client/src/app/pages/accounts/create-or-update-account-dialog/create-or-update-account-dialog.html @@ -92,11 +92,6 @@ [tagsAvailable]="tagsAvailable" /> -
- Exclude from Analysis -
@if (data.account.id) {
diff --git a/libs/common/src/lib/dtos/create-account-with-balances.dto.ts b/libs/common/src/lib/dtos/create-account-with-balances.dto.ts index 2d1d3ed2a..8fc6f78e4 100644 --- a/libs/common/src/lib/dtos/create-account-with-balances.dto.ts +++ b/libs/common/src/lib/dtos/create-account-with-balances.dto.ts @@ -1,6 +1,6 @@ import { AccountBalance } from '@ghostfolio/common/interfaces'; -import { IsArray, IsOptional } from 'class-validator'; +import { IsArray, IsBoolean, IsOptional } from 'class-validator'; import { CreateAccountDto } from './create-account.dto'; @@ -8,4 +8,12 @@ export class CreateAccountWithBalancesDto extends CreateAccountDto { @IsArray() @IsOptional() balances?: AccountBalance[]; + + /** + * @deprecated Accepted for backward compatibility with old export files + * and mapped to the "Exclude from Analysis" tag (`TAG_ID_EXCLUDE_FROM_ANALYSIS`) + */ + @IsBoolean() + @IsOptional() + isExcluded?: boolean; } diff --git a/libs/common/src/lib/dtos/create-account.dto.ts b/libs/common/src/lib/dtos/create-account.dto.ts index b04193020..e4a0c64fe 100644 --- a/libs/common/src/lib/dtos/create-account.dto.ts +++ b/libs/common/src/lib/dtos/create-account.dto.ts @@ -4,7 +4,6 @@ import { Transform, TransformFnParams } from 'class-transformer'; import { ArrayUnique, IsArray, - IsBoolean, IsNumber, IsOptional, IsString, @@ -30,13 +29,6 @@ export class CreateAccountDto { @IsString() id?: string; - /** - * @deprecated Use the "Exclude from Analysis" tag (`TAG_ID_EXCLUDE_FROM_ANALYSIS`) instead - */ - @IsBoolean() - @IsOptional() - isExcluded?: boolean; - @IsString() name: string; diff --git a/libs/common/src/lib/dtos/update-account.dto.ts b/libs/common/src/lib/dtos/update-account.dto.ts index 7a33da2df..a6a3e6ac6 100644 --- a/libs/common/src/lib/dtos/update-account.dto.ts +++ b/libs/common/src/lib/dtos/update-account.dto.ts @@ -4,7 +4,6 @@ import { Transform, TransformFnParams } from 'class-transformer'; import { ArrayUnique, IsArray, - IsBoolean, IsNumber, IsOptional, IsString, @@ -29,13 +28,6 @@ export class UpdateAccountDto { @IsString() id: string; - /** - * @deprecated Use the "Exclude from Analysis" tag (`TAG_ID_EXCLUDE_FROM_ANALYSIS`) instead - */ - @IsBoolean() - @IsOptional() - isExcluded?: boolean; - @IsString() name: string; diff --git a/libs/common/src/lib/helper.ts b/libs/common/src/lib/helper.ts index 98f097b44..db1d3c2a2 100644 --- a/libs/common/src/lib/helper.ts +++ b/libs/common/src/lib/helper.ts @@ -456,12 +456,8 @@ export function interpolate(template: string, context: any) { }); } -export function isAccountExcluded(account: { - isExcluded: boolean; - tags?: { id: string }[]; -}) { +export function isAccountExcluded(account: { tags?: { id: string }[] }) { return ( - account.isExcluded || account.tags?.some(({ id }) => { return id === TAG_ID_EXCLUDE_FROM_ANALYSIS; }) === true diff --git a/libs/ui/src/lib/accounts-table/accounts-table.component.stories.ts b/libs/ui/src/lib/accounts-table/accounts-table.component.stories.ts index 62a01164f..a38ca826c 100644 --- a/libs/ui/src/lib/accounts-table/accounts-table.component.stories.ts +++ b/libs/ui/src/lib/accounts-table/accounts-table.component.stories.ts @@ -24,7 +24,6 @@ const accounts = [ createdAt: new Date('2025-06-01T06:52:49.063Z'), currency: 'USD', id: '460d7401-ca43-4ed4-b08e-349f1822e9db', - isExcluded: false, name: 'Coinbase Account', platform: { id: '8dc24b88-bb92-4152-af25-fe6a31643e26', @@ -46,7 +45,6 @@ const accounts = [ createdAt: new Date('2025-06-01T06:48:53.055Z'), currency: 'USD', id: '6d773e31-0583-4c85-a247-e69870b4f1ee', - isExcluded: false, name: 'Private Banking Account', platform: { id: '43e8fcd1-5b79-4100-b678-d2229bd1660d', @@ -68,7 +66,6 @@ const accounts = [ createdAt: new Date('2025-05-31T13:00:13.940Z'), currency: 'USD', id: '776bd1e9-b2f6-4f7e-933d-18756c2f0625', - isExcluded: false, name: 'Trading Account', platform: { id: '9da3a8a7-4795-43e3-a6db-ccb914189737', diff --git a/libs/ui/src/lib/activities-table/activities-table.component.stories.ts b/libs/ui/src/lib/activities-table/activities-table.component.stories.ts index 057747cf1..0136545cf 100644 --- a/libs/ui/src/lib/activities-table/activities-table.component.stories.ts +++ b/libs/ui/src/lib/activities-table/activities-table.component.stories.ts @@ -44,7 +44,6 @@ const activities: Activity[] = [ createdAt: new Date('2025-05-31T13:00:13.940Z'), currency: 'USD', id: '776bd1e9-b2f6-4f7e-933d-18756c2f0625', - isExcluded: false, name: 'Trading Account', platformId: '9da3a8a7-4795-43e3-a6db-ccb914189737', updatedAt: new Date('2025-06-01T06:53:10.569Z'), @@ -111,7 +110,6 @@ const activities: Activity[] = [ createdAt: new Date('2025-05-31T13:00:13.940Z'), currency: 'USD', id: '776bd1e9-b2f6-4f7e-933d-18756c2f0625', - isExcluded: false, name: 'Trading Account', platformId: '9da3a8a7-4795-43e3-a6db-ccb914189737', updatedAt: new Date('2025-06-01T06:53:10.569Z'), @@ -178,7 +176,6 @@ const activities: Activity[] = [ createdAt: new Date('2025-05-31T13:00:13.940Z'), currency: 'USD', id: '776bd1e9-b2f6-4f7e-933d-18756c2f0625', - isExcluded: false, name: 'Trading Account', platformId: '9da3a8a7-4795-43e3-a6db-ccb914189737', updatedAt: new Date('2025-06-01T06:53:10.569Z'), @@ -245,7 +242,6 @@ const activities: Activity[] = [ createdAt: new Date('2025-05-31T13:00:13.940Z'), currency: 'USD', id: '776bd1e9-b2f6-4f7e-933d-18756c2f0625', - isExcluded: false, name: 'Trading Account', platformId: '9da3a8a7-4795-43e3-a6db-ccb914189737', updatedAt: new Date('2025-06-01T06:53:10.569Z'), @@ -312,7 +308,6 @@ const activities: Activity[] = [ createdAt: new Date('2025-05-31T13:00:13.940Z'), currency: 'USD', id: '776bd1e9-b2f6-4f7e-933d-18756c2f0625', - isExcluded: false, name: 'Trading Account', platformId: '9da3a8a7-4795-43e3-a6db-ccb914189737', updatedAt: new Date('2025-06-01T06:53:10.569Z'), diff --git a/prisma/migrations/20260801103609_removed_is_excluded_from_account/migration.sql b/prisma/migrations/20260801103609_removed_is_excluded_from_account/migration.sql new file mode 100644 index 000000000..5fb01f5d2 --- /dev/null +++ b/prisma/migrations/20260801103609_removed_is_excluded_from_account/migration.sql @@ -0,0 +1,21 @@ +-- Create the "EXCLUDE_FROM_ANALYSIS" tag if it does not exist yet +INSERT INTO "Tag" ("id", "name") +VALUES ('f2e868af-8333-459f-b161-cbc6544c24bd', 'EXCLUDE_FROM_ANALYSIS') +ON CONFLICT DO NOTHING; + +-- Migrate accounts with "isExcluded" to the "EXCLUDE_FROM_ANALYSIS" tag +INSERT INTO "TagsOnAccounts" ("accountId", "tagId", "updatedAt", "userId") +SELECT + "id", + 'f2e868af-8333-459f-b161-cbc6544c24bd', + CURRENT_TIMESTAMP, + "userId" +FROM "Account" +WHERE "isExcluded" = true +ON CONFLICT DO NOTHING; + +-- DropIndex +DROP INDEX "Account_isExcluded_idx"; + +-- AlterTable +ALTER TABLE "Account" DROP COLUMN "isExcluded"; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 733399506..faf7a9259 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -33,8 +33,6 @@ model Account { createdAt DateTime @default(now()) currency String? id String @default(uuid()) - /// @deprecated Use the "Exclude from Analysis" tag (`TAG_ID_EXCLUDE_FROM_ANALYSIS`) instead - isExcluded Boolean @default(false) name String? platform Platform? @relation(fields: [platformId], references: [id]) platformId String? @@ -46,7 +44,6 @@ model Account { @@id([id, userId]) @@index([currency]) @@index([id]) - @@index([isExcluded]) @@index([name]) @@index([userId]) }