From fa108274430d8dff1016ddcba5bbcb2778eb781b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20S=C3=B3jko?= Date: Mon, 5 Sep 2022 21:13:07 +0200 Subject: [PATCH] feat(auth): add measuring subscription length --- .../Domain/Statistics/StatisticsMeasure.ts | 1 + .../SubscriptionCancelledEventHandler.spec.ts | 21 +++++++++++++++++-- .../SubscriptionCancelledEventHandler.ts | 21 ++++++++++++++++++- .../MySQLUserSubscriptionRepository.spec.ts | 2 ++ .../MySQL/MySQLUserSubscriptionRepository.ts | 1 + 5 files changed, 43 insertions(+), 3 deletions(-) diff --git a/packages/analytics/src/Domain/Statistics/StatisticsMeasure.ts b/packages/analytics/src/Domain/Statistics/StatisticsMeasure.ts index ec21f7c60..19f5a36cd 100644 --- a/packages/analytics/src/Domain/Statistics/StatisticsMeasure.ts +++ b/packages/analytics/src/Domain/Statistics/StatisticsMeasure.ts @@ -1,3 +1,4 @@ export enum StatisticsMeasure { PaymentSuccess = 'payment-success', + SubscriptionLength = 'subscription-length', } diff --git a/packages/auth/src/Domain/Handler/SubscriptionCancelledEventHandler.spec.ts b/packages/auth/src/Domain/Handler/SubscriptionCancelledEventHandler.spec.ts index b9a1a0af7..bf103b10d 100644 --- a/packages/auth/src/Domain/Handler/SubscriptionCancelledEventHandler.spec.ts +++ b/packages/auth/src/Domain/Handler/SubscriptionCancelledEventHandler.spec.ts @@ -8,10 +8,11 @@ import * as dayjs from 'dayjs' import { SubscriptionCancelledEventHandler } from './SubscriptionCancelledEventHandler' import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface' import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface' -import { AnalyticsStoreInterface } from '@standardnotes/analytics' +import { AnalyticsStoreInterface, Period, StatisticsMeasure, StatisticsStoreInterface } from '@standardnotes/analytics' import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId' import { UserRepositoryInterface } from '../User/UserRepositoryInterface' import { User } from '../User/User' +import { UserSubscription } from '../Subscription/UserSubscription' describe('SubscriptionCancelledEventHandler', () => { let userSubscriptionRepository: UserSubscriptionRepositoryInterface @@ -20,6 +21,7 @@ describe('SubscriptionCancelledEventHandler', () => { let userRepository: UserRepositoryInterface let getUserAnalyticsId: GetUserAnalyticsId let analyticsStore: AnalyticsStoreInterface + let statisticsStore: StatisticsStoreInterface let timestamp: number const createHandler = () => @@ -29,6 +31,7 @@ describe('SubscriptionCancelledEventHandler', () => { userRepository, getUserAnalyticsId, analyticsStore, + statisticsStore, ) beforeEach(() => { @@ -43,8 +46,16 @@ describe('SubscriptionCancelledEventHandler', () => { analyticsStore = {} as jest.Mocked analyticsStore.markActivity = jest.fn() + statisticsStore = {} as jest.Mocked + statisticsStore.incrementMeasure = jest.fn() + + const userSubscription = { + createdAt: 1642395451515000, + } as jest.Mocked + userSubscriptionRepository = {} as jest.Mocked userSubscriptionRepository.updateCancelled = jest.fn() + userSubscriptionRepository.findBySubscriptionId = jest.fn().mockReturnValue([userSubscription]) offlineUserSubscriptionRepository = {} as jest.Mocked offlineUserSubscriptionRepository.updateCancelled = jest.fn() @@ -64,10 +75,16 @@ describe('SubscriptionCancelledEventHandler', () => { }) it('should update subscription cancelled', async () => { + event.payload.timestamp = 1642395451516000 await createHandler().handle(event) - expect(userSubscriptionRepository.updateCancelled).toHaveBeenCalledWith(1, true, timestamp) + expect(userSubscriptionRepository.updateCancelled).toHaveBeenCalledWith(1, true, 1642395451516000) expect(analyticsStore.markActivity).toHaveBeenCalled() + expect(statisticsStore.incrementMeasure).toHaveBeenCalledWith(StatisticsMeasure.SubscriptionLength, 1000, [ + Period.Today, + Period.ThisWeek, + Period.ThisMonth, + ]) }) it('should update subscription cancelled - user not found', async () => { diff --git a/packages/auth/src/Domain/Handler/SubscriptionCancelledEventHandler.ts b/packages/auth/src/Domain/Handler/SubscriptionCancelledEventHandler.ts index 29af170d7..f130dfb32 100644 --- a/packages/auth/src/Domain/Handler/SubscriptionCancelledEventHandler.ts +++ b/packages/auth/src/Domain/Handler/SubscriptionCancelledEventHandler.ts @@ -1,12 +1,19 @@ import { DomainEventHandlerInterface, SubscriptionCancelledEvent } from '@standardnotes/domain-events' import { inject, injectable } from 'inversify' +import { + AnalyticsActivity, + AnalyticsStoreInterface, + Period, + StatisticsMeasure, + StatisticsStoreInterface, +} from '@standardnotes/analytics' import TYPES from '../../Bootstrap/Types' import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface' import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface' import { UserRepositoryInterface } from '../User/UserRepositoryInterface' import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId' -import { AnalyticsActivity, AnalyticsStoreInterface, Period } from '@standardnotes/analytics' +import { UserSubscription } from '../Subscription/UserSubscription' @injectable() export class SubscriptionCancelledEventHandler implements DomainEventHandlerInterface { @@ -17,6 +24,7 @@ export class SubscriptionCancelledEventHandler implements DomainEventHandlerInte @inject(TYPES.UserRepository) private userRepository: UserRepositoryInterface, @inject(TYPES.GetUserAnalyticsId) private getUserAnalyticsId: GetUserAnalyticsId, @inject(TYPES.AnalyticsStore) private analyticsStore: AnalyticsStoreInterface, + @inject(TYPES.StatisticsStore) private statisticsStore: StatisticsStoreInterface, ) {} async handle(event: SubscriptionCancelledEvent): Promise { if (event.payload.offline) { @@ -35,6 +43,17 @@ export class SubscriptionCancelledEventHandler implements DomainEventHandlerInte Period.ThisWeek, Period.ThisMonth, ]) + + const subscriptions = await this.userSubscriptionRepository.findBySubscriptionId(event.payload.subscriptionId) + if (subscriptions.length !== 0) { + const lastSubscription = subscriptions.shift() + const subscriptionLength = event.payload.timestamp - (lastSubscription as UserSubscription).createdAt + await this.statisticsStore.incrementMeasure(StatisticsMeasure.SubscriptionLength, subscriptionLength, [ + Period.Today, + Period.ThisWeek, + Period.ThisMonth, + ]) + } } } diff --git a/packages/auth/src/Infra/MySQL/MySQLUserSubscriptionRepository.spec.ts b/packages/auth/src/Infra/MySQL/MySQLUserSubscriptionRepository.spec.ts index ae3e171db..d857fdb9a 100644 --- a/packages/auth/src/Infra/MySQL/MySQLUserSubscriptionRepository.spec.ts +++ b/packages/auth/src/Infra/MySQL/MySQLUserSubscriptionRepository.spec.ts @@ -157,6 +157,7 @@ describe('MySQLUserSubscriptionRepository', () => { ormRepository.createQueryBuilder = jest.fn().mockImplementation(() => selectQueryBuilder) selectQueryBuilder.where = jest.fn().mockReturnThis() + selectQueryBuilder.orderBy = jest.fn().mockReturnThis() selectQueryBuilder.getMany = jest.fn().mockReturnValue([subscription]) const result = await createRepository().findBySubscriptionId(123) @@ -164,6 +165,7 @@ describe('MySQLUserSubscriptionRepository', () => { expect(selectQueryBuilder.where).toHaveBeenCalledWith('subscription_id = :subscriptionId', { subscriptionId: 123, }) + expect(selectQueryBuilder.orderBy).toHaveBeenCalledWith('created_at', 'DESC') expect(selectQueryBuilder.getMany).toHaveBeenCalled() expect(result).toEqual([subscription]) }) diff --git a/packages/auth/src/Infra/MySQL/MySQLUserSubscriptionRepository.ts b/packages/auth/src/Infra/MySQL/MySQLUserSubscriptionRepository.ts index 11db2fff7..0fcbd34eb 100644 --- a/packages/auth/src/Infra/MySQL/MySQLUserSubscriptionRepository.ts +++ b/packages/auth/src/Infra/MySQL/MySQLUserSubscriptionRepository.ts @@ -44,6 +44,7 @@ export class MySQLUserSubscriptionRepository implements UserSubscriptionReposito .where('subscription_id = :subscriptionId', { subscriptionId, }) + .orderBy('created_at', 'DESC') .getMany() }