From 5eb957c82a8cc5fdcb6815e2cd30e49cd2b1e8ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20S=C3=B3jko?= Date: Fri, 16 Sep 2022 12:17:24 +0200 Subject: [PATCH] fix(auth): change remaining subscription time stats to percentage --- .../Domain/Statistics/StatisticsMeasure.ts | 2 +- packages/api-gateway/bin/report.ts | 2 +- .../1663321030000-add_renewed_at_column.ts | 13 ++++++++++ .../SubscriptionCancelledEventHandler.ts | 25 +++++++++++-------- .../Domain/Subscription/UserSubscription.ts | 7 ++++++ .../MySQLUserSubscriptionRepository.spec.ts | 3 ++- .../MySQL/MySQLUserSubscriptionRepository.ts | 5 ++-- 7 files changed, 42 insertions(+), 15 deletions(-) create mode 100644 packages/auth/migrations/1663321030000-add_renewed_at_column.ts diff --git a/packages/analytics/src/Domain/Statistics/StatisticsMeasure.ts b/packages/analytics/src/Domain/Statistics/StatisticsMeasure.ts index 102aaab37..6b71dd8c1 100644 --- a/packages/analytics/src/Domain/Statistics/StatisticsMeasure.ts +++ b/packages/analytics/src/Domain/Statistics/StatisticsMeasure.ts @@ -3,7 +3,7 @@ export enum StatisticsMeasure { SubscriptionLength = 'subscription-length', RegistrationLength = 'registration-length', RegistrationToSubscriptionTime = 'registration-to-subscription-time', - SubscriptionCancelToExpireTime = 'subscription-cancel-to-expire-time', + RemainingSubscriptionTimePercentage = 'remaining-subscription-time-percentage', Refunds = 'refunds', NotesCountFreeUsers = 'notes-count-free-users', NotesCountPaidUsers = 'notes-count-paid-users', diff --git a/packages/api-gateway/bin/report.ts b/packages/api-gateway/bin/report.ts index 219359a6a..161db950f 100644 --- a/packages/api-gateway/bin/report.ts +++ b/packages/api-gateway/bin/report.ts @@ -94,7 +94,7 @@ const requestReport = async ( StatisticsMeasure.RegistrationLength, StatisticsMeasure.SubscriptionLength, StatisticsMeasure.RegistrationToSubscriptionTime, - StatisticsMeasure.SubscriptionCancelToExpireTime, + StatisticsMeasure.RemainingSubscriptionTimePercentage, StatisticsMeasure.NotesCountFreeUsers, StatisticsMeasure.NotesCountPaidUsers, StatisticsMeasure.FilesCount, diff --git a/packages/auth/migrations/1663321030000-add_renewed_at_column.ts b/packages/auth/migrations/1663321030000-add_renewed_at_column.ts new file mode 100644 index 000000000..45550ec12 --- /dev/null +++ b/packages/auth/migrations/1663321030000-add_renewed_at_column.ts @@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from 'typeorm' + +export class addRenewedAtColumn1663321030000 implements MigrationInterface { + name = 'addRenewedAtColumn1663321030000' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query('ALTER TABLE `user_subscriptions` ADD `renewed_at` bigint NULL') + } + + public async down(): Promise { + return + } +} diff --git a/packages/auth/src/Domain/Handler/SubscriptionCancelledEventHandler.ts b/packages/auth/src/Domain/Handler/SubscriptionCancelledEventHandler.ts index 6386491bf..4030d717f 100644 --- a/packages/auth/src/Domain/Handler/SubscriptionCancelledEventHandler.ts +++ b/packages/auth/src/Domain/Handler/SubscriptionCancelledEventHandler.ts @@ -27,14 +27,6 @@ export class SubscriptionCancelledEventHandler implements DomainEventHandlerInte @inject(TYPES.StatisticsStore) private statisticsStore: StatisticsStoreInterface, ) {} async handle(event: SubscriptionCancelledEvent): Promise { - if (event.payload.offline) { - await this.updateOfflineSubscriptionCancelled(event.payload.subscriptionId, event.payload.timestamp) - - return - } - - await this.updateSubscriptionCancelled(event.payload.subscriptionId, event.payload.timestamp) - const user = await this.userRepository.findOneByEmail(event.payload.userEmail) if (user !== null) { const { analyticsId } = await this.getUserAnalyticsId.execute({ userUuid: user.uuid }) @@ -54,14 +46,27 @@ export class SubscriptionCancelledEventHandler implements DomainEventHandlerInte Period.ThisMonth, ]) + const lastPurchaseTime = lastSubscription.renewedAt ?? lastSubscription.updatedAt const remainingSubscriptionTime = lastSubscription.endsAt - event.payload.timestamp + const totalSubscriptionTime = lastSubscription.endsAt - lastPurchaseTime + + const remainingSubscriptionPercentage = Math.floor((remainingSubscriptionTime / totalSubscriptionTime) * 100) + await this.statisticsStore.incrementMeasure( - StatisticsMeasure.SubscriptionCancelToExpireTime, - remainingSubscriptionTime, + StatisticsMeasure.RemainingSubscriptionTimePercentage, + remainingSubscriptionPercentage, [Period.Today, Period.ThisWeek, Period.ThisMonth], ) } } + + if (event.payload.offline) { + await this.updateOfflineSubscriptionCancelled(event.payload.subscriptionId, event.payload.timestamp) + + return + } + + await this.updateSubscriptionCancelled(event.payload.subscriptionId, event.payload.timestamp) } private async updateSubscriptionCancelled(subscriptionId: number, timestamp: number): Promise { diff --git a/packages/auth/src/Domain/Subscription/UserSubscription.ts b/packages/auth/src/Domain/Subscription/UserSubscription.ts index 6c53c6706..641674694 100644 --- a/packages/auth/src/Domain/Subscription/UserSubscription.ts +++ b/packages/auth/src/Domain/Subscription/UserSubscription.ts @@ -34,6 +34,13 @@ export class UserSubscription { @Index('updated_at') declare updatedAt: number + @Column({ + name: 'renewed_at', + type: 'bigint', + nullable: true, + }) + declare renewedAt: number | null + @Column({ type: 'tinyint', width: 1, diff --git a/packages/auth/src/Infra/MySQL/MySQLUserSubscriptionRepository.spec.ts b/packages/auth/src/Infra/MySQL/MySQLUserSubscriptionRepository.spec.ts index a33114a69..cea967e30 100644 --- a/packages/auth/src/Infra/MySQL/MySQLUserSubscriptionRepository.spec.ts +++ b/packages/auth/src/Infra/MySQL/MySQLUserSubscriptionRepository.spec.ts @@ -138,7 +138,8 @@ describe('MySQLUserSubscriptionRepository', () => { expect(updateQueryBuilder.update).toHaveBeenCalled() expect(updateQueryBuilder.set).toHaveBeenCalledWith({ - updatedAt: expect.any(Number), + updatedAt: 1000, + renewedAt: 1000, endsAt: 1000, }) expect(updateQueryBuilder.where).toHaveBeenCalledWith('subscription_id = :subscriptionId', { diff --git a/packages/auth/src/Infra/MySQL/MySQLUserSubscriptionRepository.ts b/packages/auth/src/Infra/MySQL/MySQLUserSubscriptionRepository.ts index d95678282..f5bb2d5fe 100644 --- a/packages/auth/src/Infra/MySQL/MySQLUserSubscriptionRepository.ts +++ b/packages/auth/src/Infra/MySQL/MySQLUserSubscriptionRepository.ts @@ -88,13 +88,14 @@ export class MySQLUserSubscriptionRepository implements UserSubscriptionReposito return null } - async updateEndsAt(subscriptionId: number, endsAt: number, updatedAt: number): Promise { + async updateEndsAt(subscriptionId: number, endsAt: number, timestamp: number): Promise { await this.ormRepository .createQueryBuilder() .update() .set({ endsAt, - updatedAt, + updatedAt: timestamp, + renewedAt: timestamp, }) .where('subscription_id = :subscriptionId', { subscriptionId,