mirror of
https://github.com/standardnotes/server
synced 2026-07-14 00:01:54 -04:00
fix(auth): change remaining subscription time stats to percentage
This commit is contained in:
@@ -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',
|
||||
|
||||
@@ -94,7 +94,7 @@ const requestReport = async (
|
||||
StatisticsMeasure.RegistrationLength,
|
||||
StatisticsMeasure.SubscriptionLength,
|
||||
StatisticsMeasure.RegistrationToSubscriptionTime,
|
||||
StatisticsMeasure.SubscriptionCancelToExpireTime,
|
||||
StatisticsMeasure.RemainingSubscriptionTimePercentage,
|
||||
StatisticsMeasure.NotesCountFreeUsers,
|
||||
StatisticsMeasure.NotesCountPaidUsers,
|
||||
StatisticsMeasure.FilesCount,
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class addRenewedAtColumn1663321030000 implements MigrationInterface {
|
||||
name = 'addRenewedAtColumn1663321030000'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('ALTER TABLE `user_subscriptions` ADD `renewed_at` bigint NULL')
|
||||
}
|
||||
|
||||
public async down(): Promise<void> {
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -27,14 +27,6 @@ export class SubscriptionCancelledEventHandler implements DomainEventHandlerInte
|
||||
@inject(TYPES.StatisticsStore) private statisticsStore: StatisticsStoreInterface,
|
||||
) {}
|
||||
async handle(event: SubscriptionCancelledEvent): Promise<void> {
|
||||
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<void> {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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', {
|
||||
|
||||
@@ -88,13 +88,14 @@ export class MySQLUserSubscriptionRepository implements UserSubscriptionReposito
|
||||
return null
|
||||
}
|
||||
|
||||
async updateEndsAt(subscriptionId: number, endsAt: number, updatedAt: number): Promise<void> {
|
||||
async updateEndsAt(subscriptionId: number, endsAt: number, timestamp: number): Promise<void> {
|
||||
await this.ormRepository
|
||||
.createQueryBuilder()
|
||||
.update()
|
||||
.set({
|
||||
endsAt,
|
||||
updatedAt,
|
||||
updatedAt: timestamp,
|
||||
renewedAt: timestamp,
|
||||
})
|
||||
.where('subscription_id = :subscriptionId', {
|
||||
subscriptionId,
|
||||
|
||||
Reference in New Issue
Block a user