From 10e725b51adc1104ec8eefc8c6308c86f55a639c Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Wed, 30 Oct 2024 21:39:20 +0100 Subject: [PATCH] Feature/Add dataProviderGhostfolioDailyRequests to Analytics (#4001) * Add dataProviderGhostfolioDailyRequests to Analytics --- apps/api/src/app/user/user.service.ts | 53 ++++++++++++------- apps/api/src/services/cron.service.ts | 13 ++++- .../migration.sql | 2 + prisma/schema.prisma | 11 ++-- 4 files changed, 54 insertions(+), 25 deletions(-) create mode 100644 prisma/migrations/20241029190323_added_data_provider_ghostfolio_daily_requests_to_analytics/migration.sql diff --git a/apps/api/src/app/user/user.service.ts b/apps/api/src/app/user/user.service.ts index 288e2aba2..443a2a052 100644 --- a/apps/api/src/app/user/user.service.ts +++ b/apps/api/src/app/user/user.service.ts @@ -37,7 +37,7 @@ import { UserWithSettings } from '@ghostfolio/common/types'; import { Injectable } from '@nestjs/common'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { Prisma, Role, User } from '@prisma/client'; -import { differenceInDays } from 'date-fns'; +import { differenceInDays, subDays } from 'date-fns'; import { sortBy, without } from 'lodash'; const crypto = require('crypto'); @@ -60,6 +60,13 @@ export class UserService { return this.prismaService.user.count(args); } + public createAccessToken(password: string, salt: string): string { + const hash = crypto.createHmac('sha512', salt); + hash.update(password); + + return hash.digest('hex'); + } + public async getUser( { Account, id, permissions, Settings, subscription }: UserWithSettings, aLocale = locale @@ -358,13 +365,6 @@ export class UserService { }); } - public createAccessToken(password: string, salt: string): string { - const hash = crypto.createHmac('sha512', salt); - hash.update(password); - - return hash.digest('hex'); - } - public async createUser({ data }: { @@ -426,17 +426,6 @@ export class UserService { return user; } - public async updateUser(params: { - where: Prisma.UserWhereUniqueInput; - data: Prisma.UserUpdateInput; - }): Promise { - const { where, data } = params; - return this.prismaService.user.update({ - data, - where - }); - } - public async deleteUser(where: Prisma.UserWhereUniqueInput): Promise { try { await this.prismaService.access.deleteMany({ @@ -473,6 +462,32 @@ export class UserService { }); } + public async resetAnalytics() { + return this.prismaService.analytics.updateMany({ + data: { + dataProviderGhostfolioDailyRequests: 0 + }, + where: { + updatedAt: { + gte: subDays(new Date(), 1) + } + } + }); + } + + public async updateUser({ + data, + where + }: { + data: Prisma.UserUpdateInput; + where: Prisma.UserWhereUniqueInput; + }): Promise { + return this.prismaService.user.update({ + data, + where + }); + } + public async updateUserSetting({ emitPortfolioChangedEvent, userId, diff --git a/apps/api/src/services/cron.service.ts b/apps/api/src/services/cron.service.ts index 17e970c1b..7a1b30b5f 100644 --- a/apps/api/src/services/cron.service.ts +++ b/apps/api/src/services/cron.service.ts @@ -1,3 +1,4 @@ +import { UserService } from '@ghostfolio/api/app/user/user.service'; import { DATA_GATHERING_QUEUE_PRIORITY_LOW, GATHER_ASSET_PROFILE_PROCESS, @@ -9,6 +10,7 @@ import { getAssetProfileIdentifier } from '@ghostfolio/common/helper'; import { Injectable } from '@nestjs/common'; import { Cron, CronExpression } from '@nestjs/schedule'; +import { ConfigurationService } from './configuration/configuration.service'; import { ExchangeRateDataService } from './exchange-rate-data/exchange-rate-data.service'; import { PropertyService } from './property/property.service'; import { DataGatheringService } from './queues/data-gathering/data-gathering.service'; @@ -19,10 +21,12 @@ export class CronService { private static readonly EVERY_SUNDAY_AT_LUNCH_TIME = '0 12 * * 0'; public constructor( + private readonly configurationService: ConfigurationService, private readonly dataGatheringService: DataGatheringService, private readonly exchangeRateDataService: ExchangeRateDataService, private readonly propertyService: PropertyService, - private readonly twitterBotService: TwitterBotService + private readonly twitterBotService: TwitterBotService, + private readonly userService: UserService ) {} @Cron(CronExpression.EVERY_HOUR) @@ -42,6 +46,13 @@ export class CronService { this.twitterBotService.tweetFearAndGreedIndex(); } + @Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT) + public async runEveryDayAtMidnight() { + if (this.configurationService.get('ENABLE_FEATURE_SUBSCRIPTION')) { + this.userService.resetAnalytics(); + } + } + @Cron(CronService.EVERY_SUNDAY_AT_LUNCH_TIME) public async runEverySundayAtTwelvePm() { if (await this.isDataGatheringEnabled()) { diff --git a/prisma/migrations/20241029190323_added_data_provider_ghostfolio_daily_requests_to_analytics/migration.sql b/prisma/migrations/20241029190323_added_data_provider_ghostfolio_daily_requests_to_analytics/migration.sql new file mode 100644 index 000000000..a9566dd82 --- /dev/null +++ b/prisma/migrations/20241029190323_added_data_provider_ghostfolio_daily_requests_to_analytics/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Analytics" ADD COLUMN "dataProviderGhostfolioDailyRequests" INTEGER NOT NULL DEFAULT 0; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 9fa550762..7f386a712 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -65,11 +65,12 @@ model AccountBalance { } model Analytics { - activityCount Int @default(0) - country String? - updatedAt DateTime @updatedAt - userId String @id - User User @relation(fields: [userId], onDelete: Cascade, references: [id]) + activityCount Int @default(0) + country String? + dataProviderGhostfolioDailyRequests Int @default(0) + updatedAt DateTime @updatedAt + userId String @id + User User @relation(fields: [userId], onDelete: Cascade, references: [id]) @@index([updatedAt]) }