From 1beb4de62f6ea070c20ec6c581778665e423fe87 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 4 Dec 2021 21:05:11 +0100 Subject: [PATCH] Feature/support additional currencies (#517) * Support additional currencies * Update changelog --- CHANGELOG.md | 6 ++ apps/api/src/app/admin/admin.controller.ts | 27 ++++++ apps/api/src/app/admin/admin.module.ts | 2 + apps/api/src/app/admin/admin.service.ts | 16 +++- apps/api/src/app/info/info.service.ts | 3 +- .../portfolio/current-rate.service.spec.ts | 2 +- .../src/services/data-gathering.service.ts | 45 +++++---- .../src/services/exchange-rate-data.module.ts | 3 +- .../services/exchange-rate-data.service.ts | 16 +++- .../api/src/services/property/property.dto.ts | 6 ++ .../src/services/property/property.module.ts | 11 +++ .../src/services/property/property.service.ts | 43 +++++++++ .../admin-overview.component.ts | 42 ++++++++- .../admin-overview/admin-overview.html | 94 +++++++++++-------- .../admin-overview/admin-overview.scss | 6 ++ apps/client/src/app/services/data.service.ts | 6 ++ libs/common/src/lib/config.ts | 5 + .../lib/interfaces/admin-data.interface.ts | 3 + 18 files changed, 271 insertions(+), 65 deletions(-) create mode 100644 apps/api/src/services/property/property.dto.ts create mode 100644 apps/api/src/services/property/property.module.ts create mode 100644 apps/api/src/services/property/property.service.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index c87b59cfe..61be1dac1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Added + +- Supported the management of additional currencies in the admin control panel + ## 1.86.0 - 04.12.2021 ### Added diff --git a/apps/api/src/app/admin/admin.controller.ts b/apps/api/src/app/admin/admin.controller.ts index 4788a02c2..054371458 100644 --- a/apps/api/src/app/admin/admin.controller.ts +++ b/apps/api/src/app/admin/admin.controller.ts @@ -1,4 +1,7 @@ import { DataGatheringService } from '@ghostfolio/api/services/data-gathering.service'; +import { PropertyDto } from '@ghostfolio/api/services/property/property.dto'; +import { PropertyService } from '@ghostfolio/api/services/property/property.service'; +import { PROPERTY_CURRENCIES } from '@ghostfolio/common/config'; import { AdminData, AdminMarketData, @@ -11,12 +14,14 @@ import { } from '@ghostfolio/common/permissions'; import type { RequestWithUser } from '@ghostfolio/common/types'; import { + Body, Controller, Get, HttpException, Inject, Param, Post, + Put, UseGuards } from '@nestjs/common'; import { REQUEST } from '@nestjs/core'; @@ -31,6 +36,7 @@ export class AdminController { public constructor( private readonly adminService: AdminService, private readonly dataGatheringService: DataGatheringService, + private readonly propertyService: PropertyService, @Inject(REQUEST) private readonly request: RequestWithUser ) {} @@ -153,4 +159,25 @@ export class AdminController { return this.adminService.getMarketDataBySymbol(symbol); } + + @Put('settings/:key') + @UseGuards(AuthGuard('jwt')) + public async updateProperty( + @Param('key') key: string, + @Body() data: PropertyDto + ) { + if ( + !hasPermission( + getPermissions(this.request.user.role), + permissions.accessAdminControl + ) + ) { + throw new HttpException( + getReasonPhrase(StatusCodes.FORBIDDEN), + StatusCodes.FORBIDDEN + ); + } + + return await this.adminService.putSetting(key, data.value); + } } diff --git a/apps/api/src/app/admin/admin.module.ts b/apps/api/src/app/admin/admin.module.ts index 4184ff2fd..b8e96fa04 100644 --- a/apps/api/src/app/admin/admin.module.ts +++ b/apps/api/src/app/admin/admin.module.ts @@ -5,6 +5,7 @@ import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data- import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data.module'; import { MarketDataModule } from '@ghostfolio/api/services/market-data.module'; import { PrismaModule } from '@ghostfolio/api/services/prisma.module'; +import { PropertyModule } from '@ghostfolio/api/services/property/property.module'; import { Module } from '@nestjs/common'; import { AdminController } from './admin.controller'; @@ -18,6 +19,7 @@ import { AdminService } from './admin.service'; ExchangeRateDataModule, MarketDataModule, PrismaModule, + PropertyModule, SubscriptionModule ], controllers: [AdminController], diff --git a/apps/api/src/app/admin/admin.service.ts b/apps/api/src/app/admin/admin.service.ts index d4c21a29e..4b9aaad4c 100644 --- a/apps/api/src/app/admin/admin.service.ts +++ b/apps/api/src/app/admin/admin.service.ts @@ -4,7 +4,8 @@ import { DataGatheringService } from '@ghostfolio/api/services/data-gathering.se import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; import { MarketDataService } from '@ghostfolio/api/services/market-data.service'; import { PrismaService } from '@ghostfolio/api/services/prisma.service'; -import { baseCurrency } from '@ghostfolio/common/config'; +import { PropertyService } from '@ghostfolio/api/services/property/property.service'; +import { PROPERTY_CURRENCIES, baseCurrency } from '@ghostfolio/common/config'; import { AdminData, AdminMarketData, @@ -21,6 +22,7 @@ export class AdminService { private readonly exchangeRateDataService: ExchangeRateDataService, private readonly marketDataService: MarketDataService, private readonly prismaService: PrismaService, + private readonly propertyService: PropertyService, private readonly subscriptionService: SubscriptionService ) {} @@ -45,6 +47,7 @@ export class AdminService { }; }), lastDataGathering: await this.getLastDataGathering(), + settings: await this.propertyService.get(), transactionCount: await this.prismaService.order.count(), userCount: await this.prismaService.user.count(), users: await this.getUsersWithAnalytics() @@ -76,6 +79,17 @@ export class AdminService { }; } + public async putSetting(key: string, value: string) { + const response = await this.propertyService.put({ key, value }); + + if (key === PROPERTY_CURRENCIES) { + await this.exchangeRateDataService.initialize(); + await this.dataGatheringService.reset(); + } + + return response; + } + private async getLastDataGathering() { const lastDataGathering = await this.dataGatheringService.getLastDataGathering(); diff --git a/apps/api/src/app/info/info.service.ts b/apps/api/src/app/info/info.service.ts index 2d9c9a27b..25c5c9906 100644 --- a/apps/api/src/app/info/info.service.ts +++ b/apps/api/src/app/info/info.service.ts @@ -4,6 +4,7 @@ import { DataGatheringService } from '@ghostfolio/api/services/data-gathering.se import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; import { PrismaService } from '@ghostfolio/api/services/prisma.service'; +import { PROPERTY_STRIPE_CONFIG } from '@ghostfolio/common/config'; import { InfoItem } from '@ghostfolio/common/interfaces'; import { Statistics } from '@ghostfolio/common/interfaces/statistics.interface'; import { Subscription } from '@ghostfolio/common/interfaces/subscription.interface'; @@ -222,7 +223,7 @@ export class InfoService { } const stripeConfig = await this.prismaService.property.findUnique({ - where: { key: 'STRIPE_CONFIG' } + where: { key: PROPERTY_STRIPE_CONFIG } }); if (stripeConfig) { diff --git a/apps/api/src/app/portfolio/current-rate.service.spec.ts b/apps/api/src/app/portfolio/current-rate.service.spec.ts index f474a10f0..bb9aa78b6 100644 --- a/apps/api/src/app/portfolio/current-rate.service.spec.ts +++ b/apps/api/src/app/portfolio/current-rate.service.spec.ts @@ -73,7 +73,7 @@ describe('CurrentRateService', () => { beforeAll(async () => { dataProviderService = new DataProviderService(null, [], null); - exchangeRateDataService = new ExchangeRateDataService(null, null); + exchangeRateDataService = new ExchangeRateDataService(null, null, null); marketDataService = new MarketDataService(null); await exchangeRateDataService.initialize(); diff --git a/apps/api/src/services/data-gathering.service.ts b/apps/api/src/services/data-gathering.service.ts index fb2f34222..48ce87e02 100644 --- a/apps/api/src/services/data-gathering.service.ts +++ b/apps/api/src/services/data-gathering.service.ts @@ -1,5 +1,9 @@ import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile.service'; -import { ghostfolioFearAndGreedIndexSymbol } from '@ghostfolio/common/config'; +import { + PROPERTY_LAST_DATA_GATHERING, + PROPERTY_LOCKED_DATA_GATHERING, + ghostfolioFearAndGreedIndexSymbol +} from '@ghostfolio/common/config'; import { DATE_FORMAT, resetHours } from '@ghostfolio/common/helper'; import { Inject, Injectable, Logger } from '@nestjs/common'; import { DataSource } from '@prisma/client'; @@ -43,7 +47,7 @@ export class DataGatheringService { await this.prismaService.property.create({ data: { - key: 'LOCKED_DATA_GATHERING', + key: PROPERTY_LOCKED_DATA_GATHERING, value: new Date().toISOString() } }); @@ -55,11 +59,11 @@ export class DataGatheringService { await this.prismaService.property.upsert({ create: { - key: 'LAST_DATA_GATHERING', + key: PROPERTY_LAST_DATA_GATHERING, value: new Date().toISOString() }, update: { value: new Date().toISOString() }, - where: { key: 'LAST_DATA_GATHERING' } + where: { key: PROPERTY_LAST_DATA_GATHERING } }); } catch (error) { Logger.error(error); @@ -67,7 +71,7 @@ export class DataGatheringService { await this.prismaService.property.delete({ where: { - key: 'LOCKED_DATA_GATHERING' + key: PROPERTY_LOCKED_DATA_GATHERING } }); @@ -78,7 +82,7 @@ export class DataGatheringService { public async gatherMax() { const isDataGatheringLocked = await this.prismaService.property.findUnique({ - where: { key: 'LOCKED_DATA_GATHERING' } + where: { key: PROPERTY_LOCKED_DATA_GATHERING } }); if (!isDataGatheringLocked) { @@ -87,7 +91,7 @@ export class DataGatheringService { await this.prismaService.property.create({ data: { - key: 'LOCKED_DATA_GATHERING', + key: PROPERTY_LOCKED_DATA_GATHERING, value: new Date().toISOString() } }); @@ -99,11 +103,11 @@ export class DataGatheringService { await this.prismaService.property.upsert({ create: { - key: 'LAST_DATA_GATHERING', + key: PROPERTY_LAST_DATA_GATHERING, value: new Date().toISOString() }, update: { value: new Date().toISOString() }, - where: { key: 'LAST_DATA_GATHERING' } + where: { key: PROPERTY_LAST_DATA_GATHERING } }); } catch (error) { Logger.error(error); @@ -111,7 +115,7 @@ export class DataGatheringService { await this.prismaService.property.delete({ where: { - key: 'LOCKED_DATA_GATHERING' + key: PROPERTY_LOCKED_DATA_GATHERING } }); @@ -128,7 +132,7 @@ export class DataGatheringService { symbol: string; }) { const isDataGatheringLocked = await this.prismaService.property.findUnique({ - where: { key: 'LOCKED_DATA_GATHERING' } + where: { key: PROPERTY_LOCKED_DATA_GATHERING } }); if (!isDataGatheringLocked) { @@ -137,7 +141,7 @@ export class DataGatheringService { await this.prismaService.property.create({ data: { - key: 'LOCKED_DATA_GATHERING', + key: PROPERTY_LOCKED_DATA_GATHERING, value: new Date().toISOString() } }); @@ -156,11 +160,11 @@ export class DataGatheringService { await this.prismaService.property.upsert({ create: { - key: 'LAST_DATA_GATHERING', + key: PROPERTY_LAST_DATA_GATHERING, value: new Date().toISOString() }, update: { value: new Date().toISOString() }, - where: { key: 'LAST_DATA_GATHERING' } + where: { key: PROPERTY_LAST_DATA_GATHERING } }); } catch (error) { Logger.error(error); @@ -168,7 +172,7 @@ export class DataGatheringService { await this.prismaService.property.delete({ where: { - key: 'LOCKED_DATA_GATHERING' + key: PROPERTY_LOCKED_DATA_GATHERING } }); @@ -351,13 +355,13 @@ export class DataGatheringService { public async getIsInProgress() { return await this.prismaService.property.findUnique({ - where: { key: 'LOCKED_DATA_GATHERING' } + where: { key: PROPERTY_LOCKED_DATA_GATHERING } }); } public async getLastDataGathering() { const lastDataGathering = await this.prismaService.property.findUnique({ - where: { key: 'LAST_DATA_GATHERING' } + where: { key: PROPERTY_LAST_DATA_GATHERING } }); if (lastDataGathering?.value) { @@ -418,7 +422,10 @@ export class DataGatheringService { await this.prismaService.property.deleteMany({ where: { - OR: [{ key: 'LAST_DATA_GATHERING' }, { key: 'LOCKED_DATA_GATHERING' }] + OR: [ + { key: PROPERTY_LAST_DATA_GATHERING }, + { key: PROPERTY_LOCKED_DATA_GATHERING } + ] } }); } @@ -496,7 +503,7 @@ export class DataGatheringService { const lastDataGathering = await this.getLastDataGathering(); const isDataGatheringLocked = await this.prismaService.property.findUnique({ - where: { key: 'LOCKED_DATA_GATHERING' } + where: { key: PROPERTY_LOCKED_DATA_GATHERING } }); const diffInHours = differenceInHours(new Date(), lastDataGathering); diff --git a/apps/api/src/services/exchange-rate-data.module.ts b/apps/api/src/services/exchange-rate-data.module.ts index 4843b5c77..9c886b06a 100644 --- a/apps/api/src/services/exchange-rate-data.module.ts +++ b/apps/api/src/services/exchange-rate-data.module.ts @@ -3,9 +3,10 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate- import { Module } from '@nestjs/common'; import { PrismaModule } from './prisma.module'; +import { PropertyModule } from './property/property.module'; @Module({ - imports: [DataProviderModule, PrismaModule], + imports: [DataProviderModule, PrismaModule, PropertyModule], providers: [ExchangeRateDataService], exports: [ExchangeRateDataService] }) diff --git a/apps/api/src/services/exchange-rate-data.service.ts b/apps/api/src/services/exchange-rate-data.service.ts index d0d6bf74e..e0e0e614f 100644 --- a/apps/api/src/services/exchange-rate-data.service.ts +++ b/apps/api/src/services/exchange-rate-data.service.ts @@ -1,4 +1,4 @@ -import { baseCurrency } from '@ghostfolio/common/config'; +import { PROPERTY_CURRENCIES, baseCurrency } from '@ghostfolio/common/config'; import { DATE_FORMAT, getYesterday } from '@ghostfolio/common/helper'; import { Injectable, Logger } from '@nestjs/common'; import { format } from 'date-fns'; @@ -7,6 +7,7 @@ import { isEmpty, isNumber, uniq } from 'lodash'; import { DataProviderService } from './data-provider/data-provider.service'; import { IDataGatheringItem } from './interfaces/interfaces'; import { PrismaService } from './prisma.service'; +import { PropertyService } from './property/property.service'; @Injectable() export class ExchangeRateDataService { @@ -16,7 +17,8 @@ export class ExchangeRateDataService { public constructor( private readonly dataProviderService: DataProviderService, - private readonly prismaService: PrismaService + private readonly prismaService: PrismaService, + private readonly propertyService: PropertyService ) { this.initialize(); } @@ -149,7 +151,7 @@ export class ExchangeRateDataService { } private async prepareCurrencies(): Promise { - const currencies: string[] = []; + let currencies: string[] = []; ( await this.prismaService.account.findMany({ @@ -181,6 +183,14 @@ export class ExchangeRateDataService { currencies.push(symbolProfile.currency); }); + const customCurrencies = (await this.propertyService.getByKey( + PROPERTY_CURRENCIES + )) as string[]; + + if (customCurrencies?.length > 0) { + currencies = currencies.concat(customCurrencies); + } + return uniq(currencies).sort(); } diff --git a/apps/api/src/services/property/property.dto.ts b/apps/api/src/services/property/property.dto.ts new file mode 100644 index 000000000..62f90875a --- /dev/null +++ b/apps/api/src/services/property/property.dto.ts @@ -0,0 +1,6 @@ +import { IsString } from 'class-validator'; + +export class PropertyDto { + @IsString() + value: string; +} diff --git a/apps/api/src/services/property/property.module.ts b/apps/api/src/services/property/property.module.ts new file mode 100644 index 000000000..fcd89de40 --- /dev/null +++ b/apps/api/src/services/property/property.module.ts @@ -0,0 +1,11 @@ +import { PrismaModule } from '@ghostfolio/api/services/prisma.module'; +import { Module } from '@nestjs/common'; + +import { PropertyService } from './property.service'; + +@Module({ + exports: [PropertyService], + imports: [PrismaModule], + providers: [PropertyService] +}) +export class PropertyModule {} diff --git a/apps/api/src/services/property/property.service.ts b/apps/api/src/services/property/property.service.ts new file mode 100644 index 000000000..44c4f7e27 --- /dev/null +++ b/apps/api/src/services/property/property.service.ts @@ -0,0 +1,43 @@ +import { PrismaService } from '@ghostfolio/api/services/prisma.service'; +import { PROPERTY_CURRENCIES } from '@ghostfolio/common/config'; +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class PropertyService { + public constructor(private readonly prismaService: PrismaService) {} + + public async get() { + const response: { + [key: string]: object | string | string[]; + } = { + [PROPERTY_CURRENCIES]: [] + }; + + const properties = await this.prismaService.property.findMany(); + + for (const property of properties) { + let value = property.value; + + try { + value = JSON.parse(property.value); + } catch {} + + response[property.key] = value; + } + + return response; + } + + public async getByKey(aKey: string) { + const properties = await this.get(); + return properties?.[aKey]; + } + + public async put({ key, value }: { key: string; value: string }) { + return this.prismaService.property.upsert({ + create: { key, value }, + update: { value }, + where: { key } + }); + } +} diff --git a/apps/client/src/app/components/admin-overview/admin-overview.component.ts b/apps/client/src/app/components/admin-overview/admin-overview.component.ts index 5dd86f23d..ce4a9cd53 100644 --- a/apps/client/src/app/components/admin-overview/admin-overview.component.ts +++ b/apps/client/src/app/components/admin-overview/admin-overview.component.ts @@ -3,7 +3,10 @@ import { AdminService } from '@ghostfolio/client/services/admin.service'; import { CacheService } from '@ghostfolio/client/services/cache.service'; import { DataService } from '@ghostfolio/client/services/data.service'; import { UserService } from '@ghostfolio/client/services/user/user.service'; -import { DEFAULT_DATE_FORMAT } from '@ghostfolio/common/config'; +import { + DEFAULT_DATE_FORMAT, + PROPERTY_CURRENCIES +} from '@ghostfolio/common/config'; import { User } from '@ghostfolio/common/interfaces'; import { differenceInSeconds, @@ -11,6 +14,7 @@ import { isValid, parseISO } from 'date-fns'; +import { uniq } from 'lodash'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @@ -20,6 +24,7 @@ import { takeUntil } from 'rxjs/operators'; templateUrl: './admin-overview.html' }) export class AdminOverviewComponent implements OnDestroy, OnInit { + public customCurrencies: string[]; public dataGatheringInProgress: boolean; public dataGatheringProgress: number; public defaultDateFormat = DEFAULT_DATE_FORMAT; @@ -57,6 +62,26 @@ export class AdminOverviewComponent implements OnDestroy, OnInit { }); } + public onAddCurrency() { + const currency = prompt('Please add a currency:'); + + if (currency) { + const currencies = uniq([...this.customCurrencies, currency]); + this.putCurrencies(currencies); + } + } + + public onDeleteCurrency(aCurrency: string) { + const confirmation = confirm('Do you really want to delete this currency?'); + + if (confirmation) { + const currencies = this.customCurrencies.filter((currency) => { + return currency !== aCurrency; + }); + this.putCurrencies(currencies); + } + } + public onFlushCache() { this.cacheService .flush() @@ -121,9 +146,11 @@ export class AdminOverviewComponent implements OnDestroy, OnInit { dataGatheringProgress, exchangeRates, lastDataGathering, + settings, transactionCount, userCount }) => { + this.customCurrencies = settings[PROPERTY_CURRENCIES] as string[]; this.dataGatheringProgress = dataGatheringProgress; this.exchangeRates = exchangeRates; @@ -147,4 +174,17 @@ export class AdminOverviewComponent implements OnDestroy, OnInit { } ); } + + private putCurrencies(aCurrencies: string[]) { + this.dataService + .putAdminSetting(PROPERTY_CURRENCIES, { + value: JSON.stringify(aCurrencies) + }) + .pipe(takeUntil(this.unsubscribeSubject)) + .subscribe(() => { + setTimeout(() => { + window.location.reload(); + }, 300); + }); + } } diff --git a/apps/client/src/app/components/admin-overview/admin-overview.html b/apps/client/src/app/components/admin-overview/admin-overview.html index 2f6c0aa4d..3d702ac90 100644 --- a/apps/client/src/app/components/admin-overview/admin-overview.html +++ b/apps/client/src/app/components/admin-overview/admin-overview.html @@ -3,32 +3,17 @@
-
-
Exchange Rates
+
+
User Count
+
{{ userCount }}
+
+
+
Transaction Count
- - - - - - - - -
- - {{ exchangeRate.label1 }}= - - {{ exchangeRate.label2 }}
+ + {{ transactionCount }} ({{ transactionCount / userCount | number + : '1.2-2' }} per User) +
@@ -46,7 +31,6 @@
-
-
User Count
-
{{ userCount }}
-
-
-
Transaction Count
+
+
Exchange Rates
- - {{ transactionCount }} ({{ transactionCount / userCount | number - : '1.2-2' }} per User) - + + + + + + + + + +
+ + {{ exchangeRate.label1 }}= + + {{ exchangeRate.label2 }} + +
+
+ +
diff --git a/apps/client/src/app/components/admin-overview/admin-overview.scss b/apps/client/src/app/components/admin-overview/admin-overview.scss index ed7f589cd..46cadd6d7 100644 --- a/apps/client/src/app/components/admin-overview/admin-overview.scss +++ b/apps/client/src/app/components/admin-overview/admin-overview.scss @@ -3,6 +3,12 @@ :host { display: block; + .mat-button { + &.mini-icon { + line-height: 1.5; + } + } + .mat-flat-button { ::ng-deep { .mat-button-wrapper { diff --git a/apps/client/src/app/services/data.service.ts b/apps/client/src/app/services/data.service.ts index 0af1990ac..6a21db0da 100644 --- a/apps/client/src/app/services/data.service.ts +++ b/apps/client/src/app/services/data.service.ts @@ -12,6 +12,7 @@ import { SymbolItem } from '@ghostfolio/api/app/symbol/interfaces/symbol-item.in 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 { Access, Accounts, @@ -239,6 +240,11 @@ export class DataService { return this.http.put(`/api/account/${aAccount.id}`, aAccount); } + public putAdminSetting(key: string, aData: PropertyDto) { + console.log(key, aData); + return this.http.put(`/api/admin/settings/${key}`, aData); + } + public putOrder(aOrder: UpdateOrderDto) { return this.http.put(`/api/order/${aOrder.id}`, aOrder); } diff --git a/libs/common/src/lib/config.ts b/libs/common/src/lib/config.ts index 91267cf90..5781fc65c 100644 --- a/libs/common/src/lib/config.ts +++ b/libs/common/src/lib/config.ts @@ -30,4 +30,9 @@ export const warnColorRgb = { export const DEFAULT_DATE_FORMAT = 'dd.MM.yyyy'; export const DEFAULT_DATE_FORMAT_MONTH_YEAR = 'MMM yyyy'; +export const PROPERTY_CURRENCIES = 'CURRENCIES'; +export const PROPERTY_LAST_DATA_GATHERING = 'LAST_DATA_GATHERING'; +export const PROPERTY_LOCKED_DATA_GATHERING = 'LOCKED_DATA_GATHERING'; +export const PROPERTY_STRIPE_CONFIG = 'STRIPE_CONFIG'; + export const UNKNOWN_KEY = 'UNKNOWN'; diff --git a/libs/common/src/lib/interfaces/admin-data.interface.ts b/libs/common/src/lib/interfaces/admin-data.interface.ts index 71df57229..ce4ea8c0b 100644 --- a/libs/common/src/lib/interfaces/admin-data.interface.ts +++ b/libs/common/src/lib/interfaces/admin-data.interface.ts @@ -1,7 +1,10 @@ +import { Property } from '@prisma/client'; + export interface AdminData { dataGatheringProgress?: number; exchangeRates: { label1: string; label2: string; value: number }[]; lastDataGathering?: Date | 'IN_PROGRESS'; + settings: { [key: string]: object | string | string[] }; transactionCount: number; userCount: number; users: {