feat(analytics): add mrr for annual, monthly, pro and plus subscription plans

This commit is contained in:
Karol Sójko
2022-11-10 15:17:35 +01:00
parent 87361f90b1
commit ce3e259bde
5 changed files with 65 additions and 8 deletions
+7 -1
View File
@@ -109,7 +109,13 @@ const requestReport = async (
}>
}> = []
const thirtyDaysStatisticsNames = [StatisticsMeasure.MRR]
const thirtyDaysStatisticsNames = [
StatisticsMeasure.MRR,
StatisticsMeasure.AnnualPlansMRR,
StatisticsMeasure.MonthlyPlansMRR,
StatisticsMeasure.PlusPlansMRR,
StatisticsMeasure.ProPlansMRR,
]
for (const statisticName of thirtyDaysStatisticsNames) {
statisticsOverTime.push({
name: statisticName,
@@ -3,6 +3,6 @@ import { RevenueModification } from './RevenueModification'
export interface RevenueModificationRepositoryInterface {
findLastByUserUuid(userUuid: Uuid): Promise<RevenueModification | null>
sumMRRDiff(): Promise<number>
sumMRRDiff(dto: { planName?: string; billingFrequency?: number }): Promise<number>
save(revenueModification: RevenueModification): Promise<RevenueModification>
}
@@ -16,4 +16,8 @@ export enum StatisticsMeasure {
NewCustomers = 'new-customers',
TotalCustomers = 'total-customers',
MRR = 'mrr',
MonthlyPlansMRR = 'monthly-plans-mrr',
AnnualPlansMRR = 'annual-plans-mrr',
ProPlansMRR = 'pro-plans-mrr',
PlusPlansMRR = 'plus-plans-mrr',
}
@@ -1,3 +1,4 @@
import { SubscriptionBillingFrequency, SubscriptionName } from '@standardnotes/common'
import { inject, injectable } from 'inversify'
import TYPES from '../../../Bootstrap/Types'
import { Result } from '../../Core/Result'
@@ -18,7 +19,7 @@ export class CalculateMonthlyRecurringRevenue implements DomainUseCaseInterface<
) {}
async execute(_dto: CalculateMonthlyRecurringRevenueDTO): Promise<Result<MonthlyRevenue>> {
const mrrDiff = await this.revenueModificationRepository.sumMRRDiff()
const mrrDiff = await this.revenueModificationRepository.sumMRRDiff({})
await this.statisticsStore.setMeasure(StatisticsMeasure.MRR, mrrDiff, [
Period.Today,
@@ -26,6 +27,46 @@ export class CalculateMonthlyRecurringRevenue implements DomainUseCaseInterface<
Period.ThisYear,
])
const monthlyPlansMrrDiff = await this.revenueModificationRepository.sumMRRDiff({
billingFrequency: SubscriptionBillingFrequency.Monthly,
})
await this.statisticsStore.setMeasure(StatisticsMeasure.MonthlyPlansMRR, monthlyPlansMrrDiff, [
Period.Today,
Period.ThisMonth,
Period.ThisYear,
])
const annualPlansMrrDiff = await this.revenueModificationRepository.sumMRRDiff({
billingFrequency: SubscriptionBillingFrequency.Annual,
})
await this.statisticsStore.setMeasure(StatisticsMeasure.AnnualPlansMRR, annualPlansMrrDiff, [
Period.Today,
Period.ThisMonth,
Period.ThisYear,
])
const proPlansMrrDiff = await this.revenueModificationRepository.sumMRRDiff({
planName: SubscriptionName.ProPlan,
})
await this.statisticsStore.setMeasure(StatisticsMeasure.ProPlansMRR, proPlansMrrDiff, [
Period.Today,
Period.ThisMonth,
Period.ThisYear,
])
const plusPlansMrrDiff = await this.revenueModificationRepository.sumMRRDiff({
planName: SubscriptionName.PlusPlan,
})
await this.statisticsStore.setMeasure(StatisticsMeasure.PlusPlansMRR, plusPlansMrrDiff, [
Period.Today,
Period.ThisMonth,
Period.ThisYear,
])
return MonthlyRevenue.create(mrrDiff)
}
}
@@ -17,11 +17,17 @@ export class MySQLRevenueModificationRepository implements RevenueModificationRe
private revenueModificationMap: MapInterface<RevenueModification, TypeORMRevenueModification>,
) {}
async sumMRRDiff(): Promise<number> {
const result = await this.ormRepository
.createQueryBuilder()
.select('sum(new_mrr - previous_mrr)', 'mrrDiff')
.getRawOne()
async sumMRRDiff(dto: { planName?: string; billingFrequency?: number }): Promise<number> {
const query = this.ormRepository.createQueryBuilder().select('sum(new_mrr - previous_mrr)', 'mrrDiff')
if (dto.planName !== undefined) {
query.where('subscription_plan = :planName', { planName: dto.planName })
}
if (dto.billingFrequency !== undefined) {
query.where('billing_frequency = :billingFrequency', { billingFrequency: dto.billingFrequency })
}
const result = await query.getRawOne()
if (result === undefined) {
return 0