From 52a257abb16034134a50474fbbb2493a00c58b99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20S=C3=B3jko?= Date: Wed, 9 Nov 2022 11:25:21 +0100 Subject: [PATCH] feat(analytics): add saving revenue modifications upon subscription canceled --- .../SubscriptionCancelledEventHandler.spec.ts | 16 +++++++++++++++- .../SubscriptionCancelledEventHandler.ts | 18 +++++++++++++++++- .../SubscriptionCancelledEventHandler.spec.ts | 3 +++ .../Event/SubscriptionCancelledEventPayload.ts | 3 +++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/packages/analytics/src/Domain/Handler/SubscriptionCancelledEventHandler.spec.ts b/packages/analytics/src/Domain/Handler/SubscriptionCancelledEventHandler.spec.ts index 5a934ae3d..e3541ea60 100644 --- a/packages/analytics/src/Domain/Handler/SubscriptionCancelledEventHandler.spec.ts +++ b/packages/analytics/src/Domain/Handler/SubscriptionCancelledEventHandler.spec.ts @@ -9,14 +9,19 @@ import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface' import { StatisticsMeasure } from '../Statistics/StatisticsMeasure' import { StatisticsStoreInterface } from '../Statistics/StatisticsStoreInterface' import { Period } from '../Time/Period' +import { Result } from '../Core/Result' +import { RevenueModification } from '../Revenue/RevenueModification' +import { SaveRevenueModification } from '../UseCase/SaveRevenueModification/SaveRevenueModification' describe('SubscriptionCancelledEventHandler', () => { let event: SubscriptionCancelledEvent let getUserAnalyticsId: GetUserAnalyticsId let analyticsStore: AnalyticsStoreInterface let statisticsStore: StatisticsStoreInterface + let saveRevenueModification: SaveRevenueModification - const createHandler = () => new SubscriptionCancelledEventHandler(getUserAnalyticsId, analyticsStore, statisticsStore) + const createHandler = () => + new SubscriptionCancelledEventHandler(getUserAnalyticsId, analyticsStore, statisticsStore, saveRevenueModification) beforeEach(() => { getUserAnalyticsId = {} as jest.Mocked @@ -30,6 +35,7 @@ describe('SubscriptionCancelledEventHandler', () => { event = {} as jest.Mocked event.createdAt = new Date(1) + event.type = 'SUBSCRIPTION_CANCELLED' event.payload = { subscriptionId: 1, userEmail: 'test@test.com', @@ -41,7 +47,13 @@ describe('SubscriptionCancelledEventHandler', () => { timestamp: 1, offline: false, replaced: false, + userExistingSubscriptionsCount: 1, + billingFrequency: 1, + payAmount: 12.99, } + + saveRevenueModification = {} as jest.Mocked + saveRevenueModification.execute = jest.fn().mockReturnValue(Result.ok()) }) it('should track subscription cancelled statistics', async () => { @@ -55,6 +67,7 @@ describe('SubscriptionCancelledEventHandler', () => { Period.ThisWeek, Period.ThisMonth, ]) + expect(saveRevenueModification.execute).toHaveBeenCalled() }) it('should not track statistics for subscriptions that are in a legacy 5 year plan', async () => { @@ -65,5 +78,6 @@ describe('SubscriptionCancelledEventHandler', () => { await createHandler().handle(event) expect(statisticsStore.incrementMeasure).not.toHaveBeenCalled() + expect(saveRevenueModification.execute).toHaveBeenCalled() }) }) diff --git a/packages/analytics/src/Domain/Handler/SubscriptionCancelledEventHandler.ts b/packages/analytics/src/Domain/Handler/SubscriptionCancelledEventHandler.ts index 2fdf1d65a..ff394a5a7 100644 --- a/packages/analytics/src/Domain/Handler/SubscriptionCancelledEventHandler.ts +++ b/packages/analytics/src/Domain/Handler/SubscriptionCancelledEventHandler.ts @@ -4,10 +4,14 @@ import { inject, injectable } from 'inversify' import TYPES from '../../Bootstrap/Types' import { AnalyticsActivity } from '../Analytics/AnalyticsActivity' import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface' +import { Email } from '../Common/Email' import { StatisticsMeasure } from '../Statistics/StatisticsMeasure' import { StatisticsStoreInterface } from '../Statistics/StatisticsStoreInterface' +import { SubscriptionEventType } from '../Subscription/SubscriptionEventType' +import { SubscriptionPlanName } from '../Subscription/SubscriptionPlanName' import { Period } from '../Time/Period' import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId' +import { SaveRevenueModification } from '../UseCase/SaveRevenueModification/SaveRevenueModification' @injectable() export class SubscriptionCancelledEventHandler implements DomainEventHandlerInterface { @@ -15,10 +19,11 @@ export class SubscriptionCancelledEventHandler implements DomainEventHandlerInte @inject(TYPES.GetUserAnalyticsId) private getUserAnalyticsId: GetUserAnalyticsId, @inject(TYPES.AnalyticsStore) private analyticsStore: AnalyticsStoreInterface, @inject(TYPES.StatisticsStore) private statisticsStore: StatisticsStoreInterface, + @inject(TYPES.SaveRevenueModification) private saveRevenueModification: SaveRevenueModification, ) {} async handle(event: SubscriptionCancelledEvent): Promise { - const { analyticsId } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail }) + const { analyticsId, userUuid } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail }) await this.analyticsStore.markActivity([AnalyticsActivity.SubscriptionCancelled], analyticsId, [ Period.Today, Period.ThisWeek, @@ -26,6 +31,17 @@ export class SubscriptionCancelledEventHandler implements DomainEventHandlerInte ]) await this.trackSubscriptionStatistics(event) + + await this.saveRevenueModification.execute({ + billingFrequency: event.payload.billingFrequency, + eventType: SubscriptionEventType.create(event.type).getValue(), + newSubscriber: event.payload.userExistingSubscriptionsCount === 1, + payedAmount: event.payload.payAmount, + planName: SubscriptionPlanName.create(event.payload.subscriptionName).getValue(), + subscriptionId: event.payload.subscriptionId, + userEmail: Email.create(event.payload.userEmail).getValue(), + userUuid, + }) } private async trackSubscriptionStatistics(event: SubscriptionCancelledEvent) { diff --git a/packages/auth/src/Domain/Handler/SubscriptionCancelledEventHandler.spec.ts b/packages/auth/src/Domain/Handler/SubscriptionCancelledEventHandler.spec.ts index 2ed72f3ca..d926ebd95 100644 --- a/packages/auth/src/Domain/Handler/SubscriptionCancelledEventHandler.spec.ts +++ b/packages/auth/src/Domain/Handler/SubscriptionCancelledEventHandler.spec.ts @@ -40,6 +40,9 @@ describe('SubscriptionCancelledEventHandler', () => { subscriptionEndsAt: 2, subscriptionUpdatedAt: 2, lastPayedAt: 1, + userExistingSubscriptionsCount: 1, + billingFrequency: 1, + payAmount: 12.99, } }) diff --git a/packages/domain-events/src/Domain/Event/SubscriptionCancelledEventPayload.ts b/packages/domain-events/src/Domain/Event/SubscriptionCancelledEventPayload.ts index e5a64607e..1a46999be 100644 --- a/packages/domain-events/src/Domain/Event/SubscriptionCancelledEventPayload.ts +++ b/packages/domain-events/src/Domain/Event/SubscriptionCancelledEventPayload.ts @@ -11,4 +11,7 @@ export interface SubscriptionCancelledEventPayload { timestamp: number offline: boolean replaced: boolean + userExistingSubscriptionsCount: number + billingFrequency: number + payAmount: number }