From addedb3091ddae81618d56663e18f2ae76a43c4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20S=C3=B3jko?= Date: Tue, 20 Dec 2022 08:45:37 +0100 Subject: [PATCH] fix(auth): add persisting statistics for all subscription plans --- .../Domain/Statistics/StatisticMeasureName.ts | 3 ++ .../SessionTraceRepositoryInterface.ts | 3 +- .../PersistStatistics.spec.ts | 3 +- .../PersistStatistics/PersistStatistics.ts | 38 ++++++++++++++++++- .../MySQL/MySQLSessionTraceRepository.ts | 14 ++++++- 5 files changed, 56 insertions(+), 5 deletions(-) diff --git a/packages/analytics/src/Domain/Statistics/StatisticMeasureName.ts b/packages/analytics/src/Domain/Statistics/StatisticMeasureName.ts index be8a7c09a..4a476a340 100644 --- a/packages/analytics/src/Domain/Statistics/StatisticMeasureName.ts +++ b/packages/analytics/src/Domain/Statistics/StatisticMeasureName.ts @@ -27,6 +27,9 @@ export class StatisticMeasureName extends ValueObject ProPlansMRR: 'pro-plans-mrr', PlusPlansMRR: 'plus-plans-mrr', ActiveUsers: 'active-users', + ActiveProUsers: 'active-pro-users', + ActivePlusUsers: 'active-plus-users', + ActiveFreeUsers: 'active-free-users', } get value(): string { diff --git a/packages/auth/src/Domain/Session/SessionTraceRepositoryInterface.ts b/packages/auth/src/Domain/Session/SessionTraceRepositoryInterface.ts index ba71c2cdd..b31d0bc6c 100644 --- a/packages/auth/src/Domain/Session/SessionTraceRepositoryInterface.ts +++ b/packages/auth/src/Domain/Session/SessionTraceRepositoryInterface.ts @@ -1,4 +1,4 @@ -import { Uuid } from '@standardnotes/domain-core' +import { SubscriptionPlanName, Uuid } from '@standardnotes/domain-core' import { SessionTrace } from './SessionTrace' @@ -7,4 +7,5 @@ export interface SessionTraceRepositoryInterface { removeExpiredBefore(date: Date): Promise findOneByUserUuidAndDate(userUuid: Uuid, date: Date): Promise countByDate(date: Date): Promise + countByDateAndSubscriptionPlanName(date: Date, subscriptionPlanName: SubscriptionPlanName): Promise } diff --git a/packages/auth/src/Domain/UseCase/PersistStatistics/PersistStatistics.spec.ts b/packages/auth/src/Domain/UseCase/PersistStatistics/PersistStatistics.spec.ts index 642b3fdec..dc72a18cd 100644 --- a/packages/auth/src/Domain/UseCase/PersistStatistics/PersistStatistics.spec.ts +++ b/packages/auth/src/Domain/UseCase/PersistStatistics/PersistStatistics.spec.ts @@ -14,6 +14,7 @@ describe('PersistStatistics', () => { beforeEach(() => { sessionTracesRepository = {} as jest.Mocked sessionTracesRepository.countByDate = jest.fn().mockReturnValue(1) + sessionTracesRepository.countByDateAndSubscriptionPlanName = jest.fn().mockReturnValue(2) domainEventFactory = {} as jest.Mocked domainEventFactory.createStatisticPersistenceRequestedEvent = jest @@ -27,6 +28,6 @@ describe('PersistStatistics', () => { it('should request statistic persistence', async () => { await createUseCase().execute({ sessionsInADay: new Date() }) - expect(domainEventPublisher.publish).toHaveBeenCalled() + expect(domainEventPublisher.publish).toHaveBeenCalledTimes(4) }) }) diff --git a/packages/auth/src/Domain/UseCase/PersistStatistics/PersistStatistics.ts b/packages/auth/src/Domain/UseCase/PersistStatistics/PersistStatistics.ts index 2446b9b7f..c2aaea554 100644 --- a/packages/auth/src/Domain/UseCase/PersistStatistics/PersistStatistics.ts +++ b/packages/auth/src/Domain/UseCase/PersistStatistics/PersistStatistics.ts @@ -1,4 +1,4 @@ -import { Result, UseCaseInterface } from '@standardnotes/domain-core' +import { Result, SubscriptionPlanName, UseCaseInterface } from '@standardnotes/domain-core' import { DomainEventPublisherInterface } from '@standardnotes/domain-events' import { DomainEventFactoryInterface } from '../../Event/DomainEventFactoryInterface' import { SessionTraceRepositoryInterface } from '../../Session/SessionTraceRepositoryInterface' @@ -13,7 +13,6 @@ export class PersistStatistics implements UseCaseInterface { async execute(dto: PersistStatisticsDTO): Promise> { const countSessionsInADay = await this.sessionTracesRepository.countByDate(dto.sessionsInADay) - await this.domainEventPublisher.publish( this.domainEventFactory.createStatisticPersistenceRequestedEvent({ statisticMeasureName: 'active-users', @@ -22,6 +21,41 @@ export class PersistStatistics implements UseCaseInterface { }), ) + const proSubscriptionPlanName = SubscriptionPlanName.create(SubscriptionPlanName.NAMES.ProPlan).getValue() + const countProSessionsInADay = await this.sessionTracesRepository.countByDateAndSubscriptionPlanName( + dto.sessionsInADay, + proSubscriptionPlanName, + ) + await this.domainEventPublisher.publish( + this.domainEventFactory.createStatisticPersistenceRequestedEvent({ + statisticMeasureName: 'active-pro-users', + value: countProSessionsInADay, + date: dto.sessionsInADay, + }), + ) + + const plusSubscriptionPlanName = SubscriptionPlanName.create(SubscriptionPlanName.NAMES.PlusPlan).getValue() + const countPlusSessionsInADay = await this.sessionTracesRepository.countByDateAndSubscriptionPlanName( + dto.sessionsInADay, + plusSubscriptionPlanName, + ) + await this.domainEventPublisher.publish( + this.domainEventFactory.createStatisticPersistenceRequestedEvent({ + statisticMeasureName: 'active-plus-users', + value: countPlusSessionsInADay, + date: dto.sessionsInADay, + }), + ) + + const countFreeSessionsInADay = countSessionsInADay - countProSessionsInADay - countPlusSessionsInADay + await this.domainEventPublisher.publish( + this.domainEventFactory.createStatisticPersistenceRequestedEvent({ + statisticMeasureName: 'active-free-users', + value: countFreeSessionsInADay, + date: dto.sessionsInADay, + }), + ) + return Result.ok('Statistics persisted.') } } diff --git a/packages/auth/src/Infra/MySQL/MySQLSessionTraceRepository.ts b/packages/auth/src/Infra/MySQL/MySQLSessionTraceRepository.ts index 4c5c0d6e6..a59edad7d 100644 --- a/packages/auth/src/Infra/MySQL/MySQLSessionTraceRepository.ts +++ b/packages/auth/src/Infra/MySQL/MySQLSessionTraceRepository.ts @@ -1,4 +1,4 @@ -import { MapperInterface, Uuid } from '@standardnotes/domain-core' +import { MapperInterface, SubscriptionPlanName, Uuid } from '@standardnotes/domain-core' import { Repository } from 'typeorm' import { SessionTrace } from '../../Domain/Session/SessionTrace' import { SessionTraceRepositoryInterface } from '../../Domain/Session/SessionTraceRepositoryInterface' @@ -10,6 +10,18 @@ export class MySQLSessionTraceRepository implements SessionTraceRepositoryInterf private mapper: MapperInterface, ) {} + async countByDateAndSubscriptionPlanName(date: Date, subscriptionPlanName: SubscriptionPlanName): Promise { + return this.ormRepository + .createQueryBuilder('trace') + .where('trace.creation_date = :creationDate', { + creationDate: new Date(date.getFullYear(), date.getMonth(), date.getDate()), + }) + .andWhere('trace.subscription_plan_name = :subscriptionPlanName', { + subscriptionPlanName: subscriptionPlanName.value, + }) + .getCount() + } + async countByDate(date: Date): Promise { return this.ormRepository .createQueryBuilder('trace')