Compare commits

..

2 Commits

Author SHA1 Message Date
standardci
c7cbc8966e chore(release): publish new version
- @standardnotes/analytics@2.7.1
2022-11-09 11:43:39 +00:00
Karol Sójko
89502bed63 fix(analytics): add missing created at column 2022-11-09 12:41:45 +01:00
11 changed files with 45 additions and 13 deletions

View File

@@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.7.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.7.0...@standardnotes/analytics@2.7.1) (2022-11-09)
### Bug Fixes
* **analytics:** add missing created at column ([89502be](https://github.com/standardnotes/server/commit/89502bed638b17301e42e0d5916635b0a59f585d))
# [2.7.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.6.0...@standardnotes/analytics@2.7.0) (2022-11-09)
### Features

View File

@@ -0,0 +1,13 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class addMissingCreatedAt1667994036734 implements MigrationInterface {
name = 'addMissingCreatedAt1667994036734'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('ALTER TABLE `revenue_modifications` ADD `created_at` bigint NOT NULL')
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('ALTER TABLE `revenue_modifications` DROP COLUMN `created_at`')
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/analytics",
"version": "2.7.0",
"version": "2.7.1",
"engines": {
"node": ">=14.0.0 <17.0.0"
},

View File

@@ -37,6 +37,7 @@ export class RevenueModificationMap implements MapInterface<RevenueModification,
subscription,
eventType: SubscriptionEventType.create(persistence.eventType).getValue(),
previousMonthlyRevenue: previousMonthlyRevenueOrError.getValue(),
createdAt: persistence.createdAt,
},
new UniqueEntityId(persistence.uuid),
)
@@ -55,6 +56,7 @@ export class RevenueModificationMap implements MapInterface<RevenueModification,
persistence.subscriptionPlan = subscription.props.planName.value
persistence.userEmail = user.props.email.value
persistence.userUuid = user.id.toString()
persistence.createdAt = domain.props.createdAt
return persistence
}

View File

@@ -24,6 +24,7 @@ describe('RevenueModification', () => {
it('should create an aggregate for purchased subscription', () => {
const revenueModification = RevenueModification.create({
createdAt: 2,
eventType: SubscriptionEventType.create('SUBSCRIPTION_PURCHASED').getValue(),
previousMonthlyRevenue: MonthlyRevenue.create(123).getValue(),
subscription,
@@ -36,7 +37,7 @@ describe('RevenueModification', () => {
it('should create an aggregate for subscription expired', () => {
const revenueModification = RevenueModification.create({
createdAt: new Date(1),
createdAt: 1,
eventType: SubscriptionEventType.create('SUBSCRIPTION_EXPIRED').getValue(),
previousMonthlyRevenue: MonthlyRevenue.create(123).getValue(),
subscription,
@@ -49,6 +50,7 @@ describe('RevenueModification', () => {
it('should create an aggregate for subscription cancelled', () => {
const revenueModification = RevenueModification.create({
createdAt: 2,
eventType: SubscriptionEventType.create('SUBSCRIPTION_CANCELLED').getValue(),
previousMonthlyRevenue: MonthlyRevenue.create(123).getValue(),
subscription,

View File

@@ -9,15 +9,7 @@ export class RevenueModification extends Aggregate<RevenueModificationProps> {
}
static create(props: RevenueModificationProps, id?: UniqueEntityId): RevenueModification {
const revenueModification = new RevenueModification(
{
...props,
createdAt: props.createdAt ? props.createdAt : new Date(),
},
id,
)
return revenueModification
return new RevenueModification(props, id)
}
get newMonthlyRevenue(): MonthlyRevenue {
@@ -27,6 +19,7 @@ export class RevenueModification extends Aggregate<RevenueModificationProps> {
switch (this.props.eventType.value) {
case 'SUBSCRIPTION_PURCHASED':
case 'SUBSCRIPTION_RENEWED':
case 'SUBSCRIPTION_DATA_MIGRATED':
revenue = subscription.props.payedAmount / subscription.props.billingFrequency
break
case 'SUBSCRIPTION_EXPIRED':

View File

@@ -8,5 +8,5 @@ export interface RevenueModificationProps {
subscription: Subscription
eventType: SubscriptionEventType
previousMonthlyRevenue: MonthlyRevenue
createdAt?: Date
createdAt: number
}

View File

@@ -19,6 +19,7 @@ export class SubscriptionEventType extends ValueObject<SubscriptionEventTypeProp
'SUBSCRIPTION_EXPIRED',
'SUBSCRIPTION_REFUNDED',
'SUBSCRIPTION_CANCELLED',
'SUBSCRIPTION_DATA_MIGRATED',
].includes(subscriptionEventType)
) {
return Result.fail<SubscriptionEventType>(`Invalid subscription event type ${subscriptionEventType}`)

View File

@@ -1,5 +1,7 @@
import 'reflect-metadata'
import { TimerInterface } from '@standardnotes/time'
import { Email } from '../../Common/Email'
import { Uuid } from '../../Common/Uuid'
import { MonthlyRevenue } from '../../Revenue/MonthlyRevenue'
@@ -13,8 +15,9 @@ import { SaveRevenueModification } from './SaveRevenueModification'
describe('SaveRevenueModification', () => {
let revenueModificationRepository: RevenueModificationRepositoryInterface
let previousMonthlyRevenue: RevenueModification
let timer: TimerInterface
const createUseCase = () => new SaveRevenueModification(revenueModificationRepository)
const createUseCase = () => new SaveRevenueModification(revenueModificationRepository, timer)
beforeEach(() => {
previousMonthlyRevenue = {
@@ -24,6 +27,9 @@ describe('SaveRevenueModification', () => {
revenueModificationRepository = {} as jest.Mocked<RevenueModificationRepositoryInterface>
revenueModificationRepository.findLastByUserUuid = jest.fn().mockReturnValue(previousMonthlyRevenue)
revenueModificationRepository.save = jest.fn()
timer = {} as jest.Mocked<TimerInterface>
timer.getTimestampInMicroseconds = jest.fn().mockReturnValue(1)
})
it('should persist a revenue modification', async () => {

View File

@@ -9,12 +9,14 @@ import { User } from '../../User/User'
import { Result } from '../../Core/Result'
import { DomainUseCaseInterface } from '../DomainUseCaseInterface'
import { SaveRevenueModificationDTO } from './SaveRevenueModificationDTO'
import { TimerInterface } from '@standardnotes/time'
@injectable()
export class SaveRevenueModification implements DomainUseCaseInterface<RevenueModification> {
constructor(
@inject(TYPES.RevenueModificationRepository)
private revenueModificationRepository: RevenueModificationRepositoryInterface,
@inject(TYPES.Timer) private timer: TimerInterface,
) {}
async execute(dto: SaveRevenueModificationDTO): Promise<Result<RevenueModification>> {
@@ -45,6 +47,7 @@ export class SaveRevenueModification implements DomainUseCaseInterface<RevenueMo
subscription,
user,
previousMonthlyRevenue,
createdAt: this.timer.getTimestampInMicroseconds(),
})
await this.revenueModificationRepository.save(revenueModification)

View File

@@ -56,4 +56,10 @@ export class TypeORMRevenueModification {
name: 'new_mrr',
})
declare newMonthlyRevenue: number
@Column({
name: 'created_at',
type: 'bigint',
})
declare createdAt: number
}