diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 054fb0123..d5b938283 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -1045,7 +1045,7 @@ export class PortfolioService { accounts ) ], - { baseCurrency: currency } + this.request.user.Settings.settings ), currencyClusterRisk: await this.rulesService.evaluate( [ @@ -1066,7 +1066,7 @@ export class PortfolioService { currentPositions ) ], - { baseCurrency: currency } + this.request.user.Settings.settings ), fees: await this.rulesService.evaluate( [ @@ -1076,7 +1076,7 @@ export class PortfolioService { this.getFees(orders).toNumber() ) ], - { baseCurrency: currency } + this.request.user.Settings.settings ) } }; diff --git a/apps/api/src/app/portfolio/rules.service.ts b/apps/api/src/app/portfolio/rules.service.ts index e3767c50f..8d46b3708 100644 --- a/apps/api/src/app/portfolio/rules.service.ts +++ b/apps/api/src/app/portfolio/rules.service.ts @@ -1,5 +1,6 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; import { Rule } from '@ghostfolio/api/models/rule'; +import { UserSettings } from '@ghostfolio/common/interfaces'; import { Injectable } from '@nestjs/common'; @Injectable() @@ -8,7 +9,7 @@ export class RulesService { public async evaluate( aRules: Rule[], - aUserSettings: { baseCurrency: string } + aUserSettings: UserSettings ) { return aRules .filter((rule) => { diff --git a/apps/api/src/app/user/interfaces/user-settings-params.interface.ts b/apps/api/src/app/user/interfaces/user-settings-params.interface.ts deleted file mode 100644 index 2df6285f6..000000000 --- a/apps/api/src/app/user/interfaces/user-settings-params.interface.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ViewMode } from '@prisma/client'; - -export interface UserSettingsParams { - currency?: string; - userId: string; - viewMode?: ViewMode; -} diff --git a/apps/api/src/app/user/update-user-setting.dto.ts b/apps/api/src/app/user/update-user-setting.dto.ts index 978b767fc..de3e9d658 100644 --- a/apps/api/src/app/user/update-user-setting.dto.ts +++ b/apps/api/src/app/user/update-user-setting.dto.ts @@ -1,4 +1,5 @@ -import { DateRange } from '@ghostfolio/common/types'; +import type { DateRange } from '@ghostfolio/common/types'; +import { ViewMode } from '@prisma/client'; import { IsBoolean, IsIn, @@ -8,6 +9,10 @@ import { } from 'class-validator'; export class UpdateUserSettingDto { + @IsOptional() + @IsString() + baseCurrency?: string; + @IsIn(['1d', '1y', '5y', 'max', 'ytd']) @IsOptional() dateRange?: DateRange; @@ -35,4 +40,8 @@ export class UpdateUserSettingDto { @IsNumber() @IsOptional() savingsRate?: number; + + @IsIn(['DEFAULT', 'ZEN']) + @IsOptional() + viewMode?: ViewMode; } diff --git a/apps/api/src/app/user/update-user-settings.dto.ts b/apps/api/src/app/user/update-user-settings.dto.ts deleted file mode 100644 index 6f7c6338e..000000000 --- a/apps/api/src/app/user/update-user-settings.dto.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { ViewMode } from '@prisma/client'; -import { IsString } from 'class-validator'; - -export class UpdateUserSettingsDto { - @IsString() - baseCurrency: string; - - @IsString() - viewMode: ViewMode; -} diff --git a/apps/api/src/app/user/user.controller.ts b/apps/api/src/app/user/user.controller.ts index 53f29645a..aa7db57ed 100644 --- a/apps/api/src/app/user/user.controller.ts +++ b/apps/api/src/app/user/user.controller.ts @@ -24,9 +24,7 @@ import { User as UserModel } from '@prisma/client'; import { StatusCodes, getReasonPhrase } from 'http-status-codes'; import { UserItem } from './interfaces/user-item.interface'; -import { UserSettingsParams } from './interfaces/user-settings-params.interface'; import { UpdateUserSettingDto } from './update-user-setting.dto'; -import { UpdateUserSettingsDto } from './update-user-settings.dto'; import { UserService } from './user.service'; @Controller('user') @@ -129,33 +127,4 @@ export class UserController { userId: this.request.user.id }); } - - @Put('settings') - @UseGuards(AuthGuard('jwt')) - public async updateUserSettings(@Body() data: UpdateUserSettingsDto) { - if ( - !hasPermission( - this.request.user.permissions, - permissions.updateUserSettings - ) - ) { - throw new HttpException( - getReasonPhrase(StatusCodes.FORBIDDEN), - StatusCodes.FORBIDDEN - ); - } - - const userSettings: UserSettingsParams = { - currency: data.baseCurrency, - userId: this.request.user.id - }; - - if ( - hasPermission(this.request.user.permissions, permissions.updateViewMode) - ) { - userSettings.viewMode = data.viewMode; - } - - return await this.userService.updateUserSettings(userSettings); - } } diff --git a/apps/api/src/app/user/user.service.ts b/apps/api/src/app/user/user.service.ts index 36ebacb8a..9ff37de89 100644 --- a/apps/api/src/app/user/user.service.ts +++ b/apps/api/src/app/user/user.service.ts @@ -15,11 +15,9 @@ import { permissions } from '@ghostfolio/common/permissions'; import { Injectable } from '@nestjs/common'; -import { Prisma, Role, User, ViewMode } from '@prisma/client'; +import { Prisma, Role, User } from '@prisma/client'; import { sortBy } from 'lodash'; -import { UserSettingsParams } from './interfaces/user-settings-params.interface'; - const crypto = require('crypto'); @Injectable() @@ -72,13 +70,7 @@ export class UserService { accounts: Account, settings: { ...((Settings.settings)), - baseCurrency: Settings?.currency ?? UserService.DEFAULT_CURRENCY, - dateRange: - Settings?.viewMode === 'ZEN' - ? 'max' - : ((Settings.settings))?.dateRange ?? 'max', - locale: ((Settings.settings))?.locale ?? aLocale, - viewMode: Settings?.viewMode ?? ViewMode.DEFAULT + locale: ((Settings.settings))?.locale ?? aLocale } }; } @@ -136,21 +128,37 @@ export class UserService { }; if (user?.Settings) { - if (!user.Settings.currency) { - // Set default currency if needed - user.Settings.currency = UserService.DEFAULT_CURRENCY; + if (!user.Settings.settings) { + user.Settings.settings = {}; } } else if (user) { // Set default settings if needed user.Settings = { - currency: UserService.DEFAULT_CURRENCY, - settings: null, + currency: null, + settings: {}, updatedAt: new Date(), userId: user?.id, - viewMode: ViewMode.DEFAULT + viewMode: 'DEFAULT' }; } + // Set default value for base currency + if (!(user.Settings.settings as UserSettings)?.baseCurrency) { + (user.Settings.settings as UserSettings).baseCurrency = + UserService.DEFAULT_CURRENCY; + } + + // Set default value for date range + (user.Settings.settings as UserSettings).dateRange = + (user.Settings.settings as UserSettings).viewMode === 'ZEN' + ? 'max' + : (user.Settings.settings as UserSettings)?.dateRange ?? 'max'; + + // Set default value for view mode + if (!(user.Settings.settings as UserSettings).viewMode) { + (user.Settings.settings as UserSettings).viewMode = 'DEFAULT'; + } + if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { user.subscription = this.subscriptionService.getSubscription(Subscription); @@ -327,33 +335,6 @@ export class UserService { return; } - public async updateUserSettings({ - currency, - userId, - viewMode - }: UserSettingsParams) { - await this.prismaService.settings.upsert({ - create: { - currency, - User: { - connect: { - id: userId - } - }, - viewMode - }, - update: { - currency, - viewMode - }, - where: { - userId: userId - } - }); - - return; - } - private getRandomString(length: number) { const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; const result = []; diff --git a/apps/api/src/models/interfaces/rule.interface.ts b/apps/api/src/models/interfaces/rule.interface.ts index d91d1ff5c..5dcd42317 100644 --- a/apps/api/src/models/interfaces/rule.interface.ts +++ b/apps/api/src/models/interfaces/rule.interface.ts @@ -1,5 +1,5 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; -import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.interface'; +import { UserSettings } from '@ghostfolio/common/interfaces'; import { EvaluationResult } from './evaluation-result.interface'; diff --git a/apps/api/src/models/interfaces/user-settings.interface.ts b/apps/api/src/models/interfaces/user-settings.interface.ts deleted file mode 100644 index 7da0c19ae..000000000 --- a/apps/api/src/models/interfaces/user-settings.interface.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface UserSettings { - baseCurrency: string; -} diff --git a/apps/api/src/models/rule.ts b/apps/api/src/models/rule.ts index 6bbb71e07..ad1629ac3 100644 --- a/apps/api/src/models/rule.ts +++ b/apps/api/src/models/rule.ts @@ -1,8 +1,7 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; -import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.interface'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; import { groupBy } from '@ghostfolio/common/helper'; -import { TimelinePosition } from '@ghostfolio/common/interfaces'; +import { TimelinePosition, UserSettings } from '@ghostfolio/common/interfaces'; import { EvaluationResult } from './interfaces/evaluation-result.interface'; import { RuleInterface } from './interfaces/rule.interface'; diff --git a/apps/api/src/models/rules/account-cluster-risk/current-investment.ts b/apps/api/src/models/rules/account-cluster-risk/current-investment.ts index 3893efd44..078123743 100644 --- a/apps/api/src/models/rules/account-cluster-risk/current-investment.ts +++ b/apps/api/src/models/rules/account-cluster-risk/current-investment.ts @@ -1,9 +1,9 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; -import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.interface'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; import { PortfolioDetails, - PortfolioPosition + PortfolioPosition, + UserSettings } from '@ghostfolio/common/interfaces'; import { Rule } from '../../rule'; diff --git a/apps/api/src/models/rules/account-cluster-risk/initial-investment.ts b/apps/api/src/models/rules/account-cluster-risk/initial-investment.ts index 7aa363c73..f490b0d6d 100644 --- a/apps/api/src/models/rules/account-cluster-risk/initial-investment.ts +++ b/apps/api/src/models/rules/account-cluster-risk/initial-investment.ts @@ -1,9 +1,9 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; -import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.interface'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; import { PortfolioDetails, - PortfolioPosition + PortfolioPosition, + UserSettings } from '@ghostfolio/common/interfaces'; import { Rule } from '../../rule'; diff --git a/apps/api/src/models/rules/account-cluster-risk/single-account.ts b/apps/api/src/models/rules/account-cluster-risk/single-account.ts index 41988ee68..c9bd0b35f 100644 --- a/apps/api/src/models/rules/account-cluster-risk/single-account.ts +++ b/apps/api/src/models/rules/account-cluster-risk/single-account.ts @@ -1,7 +1,6 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; -import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.interface'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; -import { PortfolioDetails } from '@ghostfolio/common/interfaces'; +import { PortfolioDetails, UserSettings } from '@ghostfolio/common/interfaces'; import { Rule } from '../../rule'; diff --git a/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts b/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts index bd313153f..5f1f4cf93 100644 --- a/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts +++ b/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts @@ -1,7 +1,7 @@ import { CurrentPositions } from '@ghostfolio/api/app/portfolio/interfaces/current-positions.interface'; import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; -import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.interface'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; +import { UserSettings } from '@ghostfolio/common/interfaces'; import { Rule } from '../../rule'; diff --git a/apps/api/src/models/rules/currency-cluster-risk/base-currency-initial-investment.ts b/apps/api/src/models/rules/currency-cluster-risk/base-currency-initial-investment.ts index ed7242d09..1d43f5619 100644 --- a/apps/api/src/models/rules/currency-cluster-risk/base-currency-initial-investment.ts +++ b/apps/api/src/models/rules/currency-cluster-risk/base-currency-initial-investment.ts @@ -1,7 +1,7 @@ import { CurrentPositions } from '@ghostfolio/api/app/portfolio/interfaces/current-positions.interface'; import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; -import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.interface'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; +import { UserSettings } from '@ghostfolio/common/interfaces'; import { Rule } from '../../rule'; diff --git a/apps/api/src/models/rules/currency-cluster-risk/current-investment.ts b/apps/api/src/models/rules/currency-cluster-risk/current-investment.ts index c8e3c30eb..c233ffc9c 100644 --- a/apps/api/src/models/rules/currency-cluster-risk/current-investment.ts +++ b/apps/api/src/models/rules/currency-cluster-risk/current-investment.ts @@ -1,7 +1,7 @@ import { CurrentPositions } from '@ghostfolio/api/app/portfolio/interfaces/current-positions.interface'; import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; -import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.interface'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; +import { UserSettings } from '@ghostfolio/common/interfaces'; import { Rule } from '../../rule'; diff --git a/apps/api/src/models/rules/currency-cluster-risk/initial-investment.ts b/apps/api/src/models/rules/currency-cluster-risk/initial-investment.ts index 95e3b4b76..331074f16 100644 --- a/apps/api/src/models/rules/currency-cluster-risk/initial-investment.ts +++ b/apps/api/src/models/rules/currency-cluster-risk/initial-investment.ts @@ -1,7 +1,7 @@ import { CurrentPositions } from '@ghostfolio/api/app/portfolio/interfaces/current-positions.interface'; import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; -import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.interface'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; +import { UserSettings } from '@ghostfolio/common/interfaces'; import { Rule } from '../../rule'; diff --git a/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts b/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts index f0ba72932..d3e4ea827 100644 --- a/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts +++ b/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts @@ -1,6 +1,6 @@ import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; -import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.interface'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; +import { UserSettings } from '@ghostfolio/common/interfaces'; import { Rule } from '../../rule'; diff --git a/apps/client/src/app/pages/account/account-page.component.ts b/apps/client/src/app/pages/account/account-page.component.ts index 03d95a7e4..cc475ee17 100644 --- a/apps/client/src/app/pages/account/account-page.component.ts +++ b/apps/client/src/app/pages/account/account-page.component.ts @@ -175,29 +175,6 @@ export class AccountPageComponent implements OnDestroy, OnInit { }); } - public onChangeUserSettings(aKey: string, aValue: string) { - const settings = { ...this.user.settings, [aKey]: aValue }; - - this.dataService - .putUserSettings({ - baseCurrency: settings?.baseCurrency, - viewMode: settings?.viewMode - }) - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe(() => { - this.userService.remove(); - - this.userService - .get() - .pipe(takeUntil(this.unsubscribeSubject)) - .subscribe((user) => { - this.user = user; - - this.changeDetectorRef.markForCheck(); - }); - }); - } - public onCheckout() { this.dataService .createCheckoutSession({ couponId: this.couponId, priceId: this.priceId }) diff --git a/apps/client/src/app/pages/account/account-page.html b/apps/client/src/app/pages/account/account-page.html index c0efac59a..306a9f70a 100644 --- a/apps/client/src/app/pages/account/account-page.html +++ b/apps/client/src/app/pages/account/account-page.html @@ -99,7 +99,7 @@ name="baseCurrency" [disabled]="!hasPermissionToUpdateUserSettings" [value]="user.settings.baseCurrency" - (selectionChange)="onChangeUserSettings('baseCurrency', $event.value)" + (selectionChange)="onChangeUserSetting('baseCurrency', $event.value)" > Default Zen diff --git a/apps/client/src/app/services/data.service.ts b/apps/client/src/app/services/data.service.ts index 763bf582f..49d7b1761 100644 --- a/apps/client/src/app/services/data.service.ts +++ b/apps/client/src/app/services/data.service.ts @@ -12,7 +12,6 @@ import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.in import { SymbolItem } from '@ghostfolio/api/app/symbol/interfaces/symbol-item.interface'; import { UserItem } from '@ghostfolio/api/app/user/interfaces/user-item.interface'; import { UpdateUserSettingDto } from '@ghostfolio/api/app/user/update-user-setting.dto'; -import { UpdateUserSettingsDto } from '@ghostfolio/api/app/user/update-user-settings.dto'; import { PropertyDto } from '@ghostfolio/api/services/property/property.dto'; import { DATE_FORMAT } from '@ghostfolio/common/helper'; import { @@ -448,10 +447,6 @@ export class DataService { return this.http.put(`/api/v1/user/setting`, aData); } - public putUserSettings(aData: UpdateUserSettingsDto) { - return this.http.put(`/api/v1/user/settings`, aData); - } - public redeemCoupon(couponCode: string) { return this.http.post('/api/v1/subscription/redeem-coupon', { couponCode