diff --git a/CHANGELOG.md b/CHANGELOG.md index 747526656..67e0c9380 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Added support for sub-labels in the value component +- Added a symbol profile overrides model for manual adjustments ### Changed @@ -21,6 +22,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed the calculation of the total value for sell and dividend activities in the create or edit transaction dialog +### Todo + +- Apply data migration (`yarn database:migrate`) + ## 1.139.0 - 18.04.2022 ### Added diff --git a/apps/api/src/services/symbol-profile.service.ts b/apps/api/src/services/symbol-profile.service.ts index b45c44af9..8b119de78 100644 --- a/apps/api/src/services/symbol-profile.service.ts +++ b/apps/api/src/services/symbol-profile.service.ts @@ -4,7 +4,12 @@ import { UNKNOWN_KEY } from '@ghostfolio/common/config'; import { Country } from '@ghostfolio/common/interfaces/country.interface'; import { Sector } from '@ghostfolio/common/interfaces/sector.interface'; import { Injectable } from '@nestjs/common'; -import { DataSource, Prisma, SymbolProfile } from '@prisma/client'; +import { + DataSource, + Prisma, + SymbolProfile, + SymbolProfileOverrides +} from '@prisma/client'; import { continents, countries } from 'countries-list'; import { ScraperConfiguration } from './data-provider/ghostfolio-scraper-api/interfaces/scraper-configuration.interface'; @@ -36,6 +41,7 @@ export class SymbolProfileService { ): Promise { return this.prismaService.symbolProfile .findMany({ + include: { SymbolProfileOverrides: true }, where: { symbol: { in: symbols @@ -45,14 +51,38 @@ export class SymbolProfileService { .then((symbolProfiles) => this.getSymbols(symbolProfiles)); } - private getSymbols(symbolProfiles: SymbolProfile[]): EnhancedSymbolProfile[] { - return symbolProfiles.map((symbolProfile) => ({ - ...symbolProfile, - countries: this.getCountries(symbolProfile), - scraperConfiguration: this.getScraperConfiguration(symbolProfile), - sectors: this.getSectors(symbolProfile), - symbolMapping: this.getSymbolMapping(symbolProfile) - })); + private getSymbols( + symbolProfiles: (SymbolProfile & { + SymbolProfileOverrides: SymbolProfileOverrides; + })[] + ): EnhancedSymbolProfile[] { + return symbolProfiles.map((symbolProfile) => { + const item = { + ...symbolProfile, + countries: this.getCountries(symbolProfile), + scraperConfiguration: this.getScraperConfiguration(symbolProfile), + sectors: this.getSectors(symbolProfile), + symbolMapping: this.getSymbolMapping(symbolProfile) + }; + + if (item.SymbolProfileOverrides) { + item.assetClass = + item.SymbolProfileOverrides.assetClass ?? item.assetClass; + item.assetSubClass = + item.SymbolProfileOverrides.assetSubClass ?? item.assetSubClass; + item.countries = + (item.SymbolProfileOverrides.sectors as unknown as Country[]) ?? + item.countries; + item.name = item.SymbolProfileOverrides?.name ?? item.name; + item.sectors = + (item.SymbolProfileOverrides.sectors as unknown as Sector[]) ?? + item.sectors; + + delete item.SymbolProfileOverrides; + } + + return item; + }); } private getCountries(symbolProfile: SymbolProfile): Country[] { diff --git a/prisma/migrations/20220422174935_added_symbol_profile_overrides/migration.sql b/prisma/migrations/20220422174935_added_symbol_profile_overrides/migration.sql new file mode 100644 index 000000000..b0af4d5e6 --- /dev/null +++ b/prisma/migrations/20220422174935_added_symbol_profile_overrides/migration.sql @@ -0,0 +1,15 @@ +-- CreateTable +CREATE TABLE "SymbolProfileOverrides" ( + "assetClass" "AssetClass", + "assetSubClass" "AssetSubClass", + "countries" JSONB, + "name" TEXT, + "sectors" JSONB, + "symbolProfileId" TEXT NOT NULL, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "SymbolProfileOverrides_pkey" PRIMARY KEY ("symbolProfileId") +); + +-- AddForeignKey +ALTER TABLE "SymbolProfileOverrides" ADD CONSTRAINT "SymbolProfileOverrides_symbolProfileId_fkey" FOREIGN KEY ("symbolProfileId") REFERENCES "SymbolProfile"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20220422183831_added_commodity_to_asset_sub_class/migration.sql b/prisma/migrations/20220422183831_added_commodity_to_asset_sub_class/migration.sql new file mode 100644 index 000000000..17e69547f --- /dev/null +++ b/prisma/migrations/20220422183831_added_commodity_to_asset_sub_class/migration.sql @@ -0,0 +1,2 @@ +-- AlterEnum +ALTER TYPE "AssetSubClass" ADD VALUE 'COMMODITY'; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 6dea69159..7ffca1690 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -112,25 +112,37 @@ model Settings { } model SymbolProfile { - assetClass AssetClass? - assetSubClass AssetSubClass? - countries Json? - createdAt DateTime @default(now()) - currency String - dataSource DataSource - id String @id @default(uuid()) - name String? - Order Order[] - updatedAt DateTime @updatedAt - scraperConfiguration Json? - sectors Json? - symbol String - symbolMapping Json? - url String? + assetClass AssetClass? + assetSubClass AssetSubClass? + countries Json? + createdAt DateTime @default(now()) + currency String + dataSource DataSource + id String @id @default(uuid()) + name String? + Order Order[] + updatedAt DateTime @updatedAt + scraperConfiguration Json? + sectors Json? + symbol String + symbolMapping Json? + SymbolProfileOverrides SymbolProfileOverrides? + url String? @@unique([dataSource, symbol]) } +model SymbolProfileOverrides { + assetClass AssetClass? + assetSubClass AssetSubClass? + countries Json? + name String? + sectors Json? + SymbolProfile SymbolProfile @relation(fields: [symbolProfileId], references: [id]) + symbolProfileId String @id + updatedAt DateTime @updatedAt +} + model Subscription { createdAt DateTime @default(now()) expiresAt DateTime @@ -176,6 +188,7 @@ enum AssetClass { enum AssetSubClass { BOND + COMMODITY CRYPTOCURRENCY ETF MUTUALFUND