From cf8eac3d443956ef7306578378a10fdaf847c8bc Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sun, 6 Jul 2025 10:00:41 +0200 Subject: [PATCH] Feature/rename Settings to settings in User database schema (#5100) * Rename Settings to settings in User database schema * Update changelog --- CHANGELOG.md | 1 + .../api/src/app/account/account.controller.ts | 2 +- apps/api/src/app/admin/admin.controller.ts | 2 +- apps/api/src/app/auth/jwt.strategy.ts | 8 +- .../api/src/app/endpoints/ai/ai.controller.ts | 4 +- .../benchmarks/benchmarks.service.ts | 2 +- .../app/endpoints/public/public.controller.ts | 2 +- apps/api/src/app/export/export.controller.ts | 2 +- apps/api/src/app/import/import.service.ts | 2 +- apps/api/src/app/order/order.controller.ts | 4 +- .../src/app/portfolio/portfolio.controller.ts | 6 +- .../src/app/portfolio/portfolio.service.ts | 14 ++-- .../app/subscription/subscription.service.ts | 4 +- apps/api/src/app/user/user.controller.ts | 2 +- apps/api/src/app/user/user.service.ts | 78 +++++++++---------- .../data-provider/data-provider.service.ts | 2 +- libs/common/src/lib/permissions.ts | 2 +- .../src/lib/types/user-with-settings.type.ts | 2 +- prisma/schema.prisma | 2 +- 19 files changed, 71 insertions(+), 70 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81f0eef1d..eda1e2f83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Renamed `Settings` to `settings` in the `User` database schema - Improved the language localization for Dutch (`nl`) - Improved the language localization for EspaƱol (`es`) diff --git a/apps/api/src/app/account/account.controller.ts b/apps/api/src/app/account/account.controller.ts index 635570f8f..51a33fa9e 100644 --- a/apps/api/src/app/account/account.controller.ts +++ b/apps/api/src/app/account/account.controller.ts @@ -134,7 +134,7 @@ export class AccountController { ): Promise { return this.accountBalanceService.getAccountBalances({ filters: [{ id, type: 'ACCOUNT' }], - userCurrency: this.request.user.Settings.settings.baseCurrency, + userCurrency: this.request.user.settings.settings.baseCurrency, userId: this.request.user.id }); } diff --git a/apps/api/src/app/admin/admin.controller.ts b/apps/api/src/app/admin/admin.controller.ts index 8531cf95c..8b2118ab1 100644 --- a/apps/api/src/app/admin/admin.controller.ts +++ b/apps/api/src/app/admin/admin.controller.ts @@ -255,7 +255,7 @@ export class AdminController { return this.adminService.addAssetProfile({ dataSource, symbol, - currency: this.request.user.Settings.settings.baseCurrency + currency: this.request.user.settings.settings.baseCurrency }); } diff --git a/apps/api/src/app/auth/jwt.strategy.ts b/apps/api/src/app/auth/jwt.strategy.ts index 7faf428da..c70e8fb60 100644 --- a/apps/api/src/app/auth/jwt.strategy.ts +++ b/apps/api/src/app/auth/jwt.strategy.ts @@ -56,12 +56,12 @@ export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') { }); } - if (!user.Settings.settings.baseCurrency) { - user.Settings.settings.baseCurrency = DEFAULT_CURRENCY; + if (!user.settings.settings.baseCurrency) { + user.settings.settings.baseCurrency = DEFAULT_CURRENCY; } - if (!user.Settings.settings.language) { - user.Settings.settings.language = DEFAULT_LANGUAGE_CODE; + if (!user.settings.settings.language) { + user.settings.settings.language = DEFAULT_LANGUAGE_CODE; } return user; diff --git a/apps/api/src/app/endpoints/ai/ai.controller.ts b/apps/api/src/app/endpoints/ai/ai.controller.ts index 8050c675b..b1607b53b 100644 --- a/apps/api/src/app/endpoints/ai/ai.controller.ts +++ b/apps/api/src/app/endpoints/ai/ai.controller.ts @@ -49,8 +49,8 @@ export class AiController { filters, mode, impersonationId: undefined, - languageCode: this.request.user.Settings.settings.language, - userCurrency: this.request.user.Settings.settings.baseCurrency, + languageCode: this.request.user.settings.settings.language, + userCurrency: this.request.user.settings.settings.baseCurrency, userId: this.request.user.id }); diff --git a/apps/api/src/app/endpoints/benchmarks/benchmarks.service.ts b/apps/api/src/app/endpoints/benchmarks/benchmarks.service.ts index 237f0d153..aa53564b7 100644 --- a/apps/api/src/app/endpoints/benchmarks/benchmarks.service.ts +++ b/apps/api/src/app/endpoints/benchmarks/benchmarks.service.ts @@ -45,7 +45,7 @@ export class BenchmarksService { withExcludedAccounts?: boolean; } & AssetProfileIdentifier): Promise { const marketData: { date: string; value: number }[] = []; - const userCurrency = user.Settings.settings.baseCurrency; + const userCurrency = user.settings.settings.baseCurrency; const userId = user.id; const { chart } = await this.portfolioService.getPerformance({ diff --git a/apps/api/src/app/endpoints/public/public.controller.ts b/apps/api/src/app/endpoints/public/public.controller.ts index bdcd86afb..0175b6ce8 100644 --- a/apps/api/src/app/endpoints/public/public.controller.ts +++ b/apps/api/src/app/endpoints/public/public.controller.ts @@ -108,7 +108,7 @@ export class PublicController { this.exchangeRateDataService.toCurrency( quantity * marketPrice, currency, - this.request.user?.Settings?.settings.baseCurrency ?? + this.request.user?.settings?.settings.baseCurrency ?? DEFAULT_CURRENCY ) ); diff --git a/apps/api/src/app/export/export.controller.ts b/apps/api/src/app/export/export.controller.ts index db2c7e3d9..8fa2baa43 100644 --- a/apps/api/src/app/export/export.controller.ts +++ b/apps/api/src/app/export/export.controller.ts @@ -48,7 +48,7 @@ export class ExportController { return this.exportService.export({ activityIds, filters, - userCurrency: this.request.user.Settings.settings.baseCurrency, + userCurrency: this.request.user.settings.settings.baseCurrency, userId: this.request.user.id }); } diff --git a/apps/api/src/app/import/import.service.ts b/apps/api/src/app/import/import.service.ts index c48df08d0..e41dcd819 100644 --- a/apps/api/src/app/import/import.service.ts +++ b/apps/api/src/app/import/import.service.ts @@ -159,7 +159,7 @@ export class ImportService { user: UserWithSettings; }): Promise { const accountIdMapping: { [oldAccountId: string]: string } = {}; - const userCurrency = user.Settings.settings.baseCurrency; + const userCurrency = user.settings.settings.baseCurrency; if (!isDryRun && accountsWithBalancesDto?.length) { const [existingAccounts, existingPlatforms] = await Promise.all([ diff --git a/apps/api/src/app/order/order.controller.ts b/apps/api/src/app/order/order.controller.ts index b30920e90..cd8012cec 100644 --- a/apps/api/src/app/order/order.controller.ts +++ b/apps/api/src/app/order/order.controller.ts @@ -131,7 +131,7 @@ export class OrderController { const impersonationUserId = await this.impersonationService.validateImpersonationId(impersonationId); - const userCurrency = this.request.user.Settings.settings.baseCurrency; + const userCurrency = this.request.user.settings.settings.baseCurrency; const { activities, count } = await this.orderService.getOrders({ endDate, @@ -160,7 +160,7 @@ export class OrderController { ): Promise { const impersonationUserId = await this.impersonationService.validateImpersonationId(impersonationId); - const userCurrency = this.request.user.Settings.settings.baseCurrency; + const userCurrency = this.request.user.settings.settings.baseCurrency; const { activities } = await this.orderService.getOrders({ userCurrency, diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index 0b3d5dd41..2c71a4668 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -317,7 +317,7 @@ export class PortfolioController { const impersonationUserId = await this.impersonationService.validateImpersonationId(impersonationId); - const userCurrency = this.request.user.Settings.settings.baseCurrency; + const userCurrency = this.request.user.settings.settings.baseCurrency; const { endDate, startDate } = getIntervalFromDateRange(dateRange); @@ -454,7 +454,7 @@ export class PortfolioController { filters, groupBy, impersonationId, - savingsRate: this.request.user?.Settings?.settings.savingsRate, + savingsRate: this.request.user?.settings?.settings.savingsRate, userId: this.request.user.id }); @@ -538,7 +538,7 @@ export class PortfolioController { user: this.request.user }) || isRestrictedView(this.request.user) || - this.request.user.Settings.settings.viewMode === 'ZEN' + this.request.user.settings.settings.viewMode === 'ZEN' ) { performanceInformation.chart = performanceInformation.chart.map( ({ diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index c64995fe0..a343015c5 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -173,7 +173,7 @@ export class PortfolioService { }) ]); - const userCurrency = this.request.user.Settings.settings.baseCurrency; + const userCurrency = this.request.user.settings.settings.baseCurrency; return accounts.map((account) => { let transactionCount = 0; @@ -409,7 +409,7 @@ export class PortfolioService { const userCurrency = this.getUserCurrency(user); const emergencyFund = new Big( - (user.Settings?.settings as UserSettings)?.emergencyFund ?? 0 + (user.settings?.settings as UserSettings)?.emergencyFund ?? 0 ); const { activities } = @@ -1134,7 +1134,7 @@ export class PortfolioService { userId: string; }): Promise { userId = await this.getUserId(impersonationId, userId); - const userSettings = this.request.user.Settings.settings as UserSettings; + const userSettings = this.request.user.settings.settings as UserSettings; const { accounts, holdings, markets, marketsAdvanced, summary } = await this.getDetails({ @@ -1813,7 +1813,7 @@ export class PortfolioService { const totalEmergencyFund = this.getTotalEmergencyFund({ emergencyFundHoldingsValueInBaseCurrency, - userSettings: user.Settings?.settings as UserSettings + userSettings: user.settings?.settings as UserSettings }); const fees = await portfolioCalculator.getFeesInBaseCurrency(); @@ -1980,8 +1980,8 @@ export class PortfolioService { private getUserCurrency(aUser?: UserWithSettings) { return ( - aUser?.Settings?.settings.baseCurrency ?? - this.request.user?.Settings?.settings.baseCurrency ?? + aUser?.settings?.settings.baseCurrency ?? + this.request.user?.settings?.settings.baseCurrency ?? DEFAULT_CURRENCY ); } @@ -1996,7 +1996,7 @@ export class PortfolioService { private getUserPerformanceCalculationType( aUser: UserWithSettings ): PerformanceCalculationType { - return aUser?.Settings?.settings.performanceCalculationType; + return aUser?.settings?.settings.performanceCalculationType; } private async getValueOfAccountsAndPlatforms({ diff --git a/apps/api/src/app/subscription/subscription.service.ts b/apps/api/src/app/subscription/subscription.service.ts index 679d4590d..9dfd7d01b 100644 --- a/apps/api/src/app/subscription/subscription.service.ts +++ b/apps/api/src/app/subscription/subscription.service.ts @@ -60,7 +60,7 @@ export class SubscriptionService { const checkoutSessionCreateParams: Stripe.Checkout.SessionCreateParams = { cancel_url: `${this.configurationService.get('ROOT_URL')}/${ - user.Settings.settings.language + user.settings.settings.language }/account`, client_reference_id: user.id, line_items: [ @@ -70,7 +70,7 @@ export class SubscriptionService { } ], locale: - (user.Settings?.settings + (user.settings?.settings ?.language as Stripe.Checkout.SessionCreateParams.Locale) ?? DEFAULT_LANGUAGE_CODE, metadata: subscriptionOffer diff --git a/apps/api/src/app/user/user.controller.ts b/apps/api/src/app/user/user.controller.ts index 7190060ff..e545fd335 100644 --- a/apps/api/src/app/user/user.controller.ts +++ b/apps/api/src/app/user/user.controller.ts @@ -166,7 +166,7 @@ export class UserController { const userSettings: UserSettings = merge( {}, - this.request.user.Settings.settings as UserSettings, + this.request.user.settings.settings as UserSettings, data ); diff --git a/apps/api/src/app/user/user.service.ts b/apps/api/src/app/user/user.service.ts index 1652a2b91..14da87208 100644 --- a/apps/api/src/app/user/user.service.ts +++ b/apps/api/src/app/user/user.service.ts @@ -95,7 +95,7 @@ export class UserService { } public async getUser( - { accounts, id, permissions, Settings, subscription }: UserWithSettings, + { accounts, id, permissions, settings, subscription }: UserWithSettings, aLocale = locale ): Promise { const userData = await Promise.all([ @@ -158,8 +158,8 @@ export class UserService { }), dateOfFirstActivity: firstActivity?.date ?? new Date(), settings: { - ...(Settings.settings as UserSettings), - locale: (Settings.settings as UserSettings)?.locale ?? aLocale + ...(settings.settings as UserSettings), + locale: (settings.settings as UserSettings)?.locale ?? aLocale } }; } @@ -189,7 +189,7 @@ export class UserService { id, provider, role, - Settings, + settings, subscriptions, thirdPartyId, updatedAt @@ -200,7 +200,7 @@ export class UserService { include: { platform: true } }, analytics: true, - Settings: true, + settings: true, subscriptions: true }, where: userWhereUniqueInput @@ -215,7 +215,7 @@ export class UserService { id, provider, role, - Settings: Settings as UserWithSettings['Settings'], + settings: settings as UserWithSettings['settings'], thirdPartyId, updatedAt, activityCount: analytics?.activityCount, @@ -223,13 +223,13 @@ export class UserService { analytics?.dataProviderGhostfolioDailyRequests }; - if (user?.Settings) { - if (!user.Settings.settings) { - user.Settings.settings = {}; + if (user?.settings) { + if (!user.settings.settings) { + user.settings.settings = {}; } } else if (user) { // Set default settings if needed - user.Settings = { + user.settings = { settings: {}, updatedAt: new Date(), userId: user?.id @@ -237,120 +237,120 @@ export class UserService { } // Set default value for base currency - if (!(user.Settings.settings as UserSettings)?.baseCurrency) { - (user.Settings.settings as UserSettings).baseCurrency = DEFAULT_CURRENCY; + if (!(user.settings.settings as UserSettings)?.baseCurrency) { + (user.settings.settings as UserSettings).baseCurrency = DEFAULT_CURRENCY; } // Set default value for date range - (user.Settings.settings as UserSettings).dateRange = - (user.Settings.settings as UserSettings).viewMode === 'ZEN' + (user.settings.settings as UserSettings).dateRange = + (user.settings.settings as UserSettings).viewMode === 'ZEN' ? 'max' - : ((user.Settings.settings as UserSettings)?.dateRange ?? 'max'); + : ((user.settings.settings as UserSettings)?.dateRange ?? 'max'); // Set default value for performance calculation type - if (!(user.Settings.settings as UserSettings)?.performanceCalculationType) { - (user.Settings.settings as UserSettings).performanceCalculationType = + if (!(user.settings.settings as UserSettings)?.performanceCalculationType) { + (user.settings.settings as UserSettings).performanceCalculationType = PerformanceCalculationType.ROAI; } // Set default value for view mode - if (!(user.Settings.settings as UserSettings).viewMode) { - (user.Settings.settings as UserSettings).viewMode = 'DEFAULT'; + if (!(user.settings.settings as UserSettings).viewMode) { + (user.settings.settings as UserSettings).viewMode = 'DEFAULT'; } - (user.Settings.settings as UserSettings).xRayRules = { + (user.settings.settings as UserSettings).xRayRules = { AccountClusterRiskCurrentInvestment: new AccountClusterRiskCurrentInvestment( undefined, undefined, undefined, {} - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), AccountClusterRiskSingleAccount: new AccountClusterRiskSingleAccount( undefined, undefined, undefined, {} - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), AssetClassClusterRiskEquity: new AssetClassClusterRiskEquity( undefined, undefined, undefined, undefined - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), AssetClassClusterRiskFixedIncome: new AssetClassClusterRiskFixedIncome( undefined, undefined, undefined, undefined - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), CurrencyClusterRiskBaseCurrencyCurrentInvestment: new CurrencyClusterRiskBaseCurrencyCurrentInvestment( undefined, undefined, undefined, undefined - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), CurrencyClusterRiskCurrentInvestment: new CurrencyClusterRiskCurrentInvestment( undefined, undefined, undefined, undefined - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), EconomicMarketClusterRiskDevelopedMarkets: new EconomicMarketClusterRiskDevelopedMarkets( undefined, undefined, undefined - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), EconomicMarketClusterRiskEmergingMarkets: new EconomicMarketClusterRiskEmergingMarkets( undefined, undefined, undefined - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), EmergencyFundSetup: new EmergencyFundSetup( undefined, undefined, undefined, undefined - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), FeeRatioInitialInvestment: new FeeRatioInitialInvestment( undefined, undefined, undefined, undefined, undefined - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), RegionalMarketClusterRiskAsiaPacific: new RegionalMarketClusterRiskAsiaPacific( undefined, undefined, undefined - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), RegionalMarketClusterRiskEmergingMarkets: new RegionalMarketClusterRiskEmergingMarkets( undefined, undefined, undefined - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), RegionalMarketClusterRiskEurope: new RegionalMarketClusterRiskEurope( undefined, undefined, undefined - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), RegionalMarketClusterRiskJapan: new RegionalMarketClusterRiskJapan( undefined, undefined, undefined - ).getSettings(user.Settings.settings), + ).getSettings(user.settings.settings), RegionalMarketClusterRiskNorthAmerica: new RegionalMarketClusterRiskNorthAmerica( undefined, undefined, undefined - ).getSettings(user.Settings.settings) + ).getSettings(user.settings.settings) }; let currentPermissions = getPermissions(user.role); @@ -360,7 +360,7 @@ export class UserService { currentPermissions.push(permissions.updateOwnAccessToken); } - if (!(user.Settings.settings as UserSettings).isExperimentalFeatures) { + if (!(user.settings.settings as UserSettings).isExperimentalFeatures) { // currentPermissions = without( // currentPermissions, // permissions.xyz @@ -411,10 +411,10 @@ export class UserService { ); // Reset benchmark - user.Settings.settings.benchmark = undefined; + user.settings.settings.benchmark = undefined; // Reset holdings view mode - user.Settings.settings.holdingsViewMode = undefined; + user.settings.settings.holdingsViewMode = undefined; } else if (user.subscription?.type === 'Premium') { if (!hasRole(user, Role.DEMO)) { currentPermissions.push(permissions.createApiKey); @@ -510,7 +510,7 @@ export class UserService { }) } }, - Settings: { + settings: { create: { settings: { currency: DEFAULT_CURRENCY diff --git a/apps/api/src/services/data-provider/data-provider.service.ts b/apps/api/src/services/data-provider/data-provider.service.ts index a850991f3..674672326 100644 --- a/apps/api/src/services/data-provider/data-provider.service.ts +++ b/apps/api/src/services/data-provider/data-provider.service.ts @@ -678,7 +678,7 @@ export class DataProviderService implements OnModuleInit { if ( lookupItem.assetSubClass === 'CRYPTOCURRENCY' && - user?.Settings?.settings.isExperimentalFeatures + user?.settings?.settings.isExperimentalFeatures ) { // Remove DEFAULT_CURRENCY at the end of cryptocurrency names lookupItem.name = lookupItem.name.replace( diff --git a/libs/common/src/lib/permissions.ts b/libs/common/src/lib/permissions.ts index 83ccdbb42..48ffc95aa 100644 --- a/libs/common/src/lib/permissions.ts +++ b/libs/common/src/lib/permissions.ts @@ -197,5 +197,5 @@ export function hasRole(aUser: UserWithSettings, aRole: Role) { } export function isRestrictedView(aUser: UserWithSettings) { - return aUser.Settings.settings.isRestrictedView ?? false; + return aUser.settings.settings.isRestrictedView ?? false; } diff --git a/libs/common/src/lib/types/user-with-settings.type.ts b/libs/common/src/lib/types/user-with-settings.type.ts index fc4a81280..18fc90a5c 100644 --- a/libs/common/src/lib/types/user-with-settings.type.ts +++ b/libs/common/src/lib/types/user-with-settings.type.ts @@ -10,7 +10,7 @@ export type UserWithSettings = User & { activityCount: number; dataProviderGhostfolioDailyRequests: number; permissions?: string[]; - Settings: Settings & { settings: UserSettings }; + settings: Settings & { settings: UserSettings }; subscription?: { expiresAt?: Date; offer: SubscriptionOffer; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index a7ffe4d21..bddb0f78c 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -256,13 +256,13 @@ model User { id String @id @default(uuid()) provider Provider @default(ANONYMOUS) role Role @default(USER) + settings Settings? subscriptions Subscription[] tags Tag[] thirdPartyId String? updatedAt DateTime @updatedAt watchlist SymbolProfile[] @relation("UserWatchlist") AccessGive Access[] @relation("accessGive") - Settings Settings? SymbolProfile SymbolProfile[] @@index([accessToken])