mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-17 18:16:15 +08:00
fix: cleanup expired records (#14140)
This commit is contained in:
@@ -58,8 +58,8 @@ Generated by [AVA](https://avajs.dev).
|
||||
> should process expiration/refund and emit canceled
|
||||
|
||||
{
|
||||
activatedCount: 0,
|
||||
canceledCount: 1,
|
||||
activatedEventCount: 0,
|
||||
canceledEventCount: 2,
|
||||
finalDBCount: 0,
|
||||
lastCanceled: {
|
||||
plan: 'pro',
|
||||
@@ -206,7 +206,7 @@ Generated by [AVA](https://avajs.dev).
|
||||
> should delete record and emit canceled on refund
|
||||
|
||||
{
|
||||
canceledCount: 1,
|
||||
canceledEventCount: 2,
|
||||
finalDBCount: 0,
|
||||
}
|
||||
|
||||
@@ -236,12 +236,12 @@ Generated by [AVA](https://avajs.dev).
|
||||
c: 0,
|
||||
},
|
||||
afterSecond: {
|
||||
a: 2,
|
||||
a: 3,
|
||||
c: 0,
|
||||
},
|
||||
afterThird: {
|
||||
a: 2,
|
||||
c: 0,
|
||||
a: 4,
|
||||
c: 1,
|
||||
},
|
||||
},
|
||||
proViaFallback: {
|
||||
@@ -249,5 +249,5 @@ Generated by [AVA](https://avajs.dev).
|
||||
provider: 'revenuecat',
|
||||
recurring: 'monthly',
|
||||
},
|
||||
totalCount: 2,
|
||||
totalCount: 1,
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -252,7 +252,7 @@ test('should process expiration/refund by deleting subscription and emitting can
|
||||
plan: 'pro',
|
||||
status: 'active',
|
||||
provider: 'revenuecat',
|
||||
recurring: 'annual',
|
||||
recurring: 'yearly',
|
||||
start: new Date('2025-01-01T00:00:00.000Z'),
|
||||
},
|
||||
});
|
||||
@@ -287,8 +287,8 @@ test('should process expiration/refund by deleting subscription and emitting can
|
||||
{
|
||||
finalDBCount,
|
||||
subscriberCount: subscriber.getCalls()?.length || 0,
|
||||
activatedCount,
|
||||
canceledCount,
|
||||
activatedEventCount: activatedCount,
|
||||
canceledEventCount: canceledCount,
|
||||
lastCanceled: omit(
|
||||
events['user.subscription.canceled']?.slice(-1)?.[0],
|
||||
'userId'
|
||||
@@ -317,7 +317,7 @@ test('should enqueue per-user reconciliation jobs for existing RC active/trialin
|
||||
targetId: 'u2',
|
||||
plan: 'ai',
|
||||
status: 'trialing',
|
||||
recurring: 'annual',
|
||||
recurring: 'yearly',
|
||||
...common,
|
||||
},
|
||||
{
|
||||
@@ -818,7 +818,7 @@ test('should treat refund as early expiration and revoke immediately', async t =
|
||||
});
|
||||
const { canceledCount } = collectEvents();
|
||||
t.snapshot(
|
||||
{ finalDBCount: count, canceledCount },
|
||||
{ finalDBCount: count, canceledEventCount: canceledCount },
|
||||
'should delete record and emit canceled on refund'
|
||||
);
|
||||
});
|
||||
@@ -858,47 +858,41 @@ test('should map via entitlement+duration when productId not whitelisted (P1M/P1
|
||||
t.context;
|
||||
|
||||
mockAlias(user.id);
|
||||
mockSubSeq([
|
||||
[
|
||||
{
|
||||
identifier: 'Pro',
|
||||
isTrial: false,
|
||||
isActive: true,
|
||||
latestPurchaseDate: new Date('2025-08-01T00:00:00.000Z'),
|
||||
expirationDate: new Date('2025-09-01T00:00:00.000Z'),
|
||||
productId: 'unknown.sku',
|
||||
store: 'app_store',
|
||||
willRenew: true,
|
||||
duration: 'P1M',
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
identifier: 'AI',
|
||||
isTrial: false,
|
||||
isActive: true,
|
||||
latestPurchaseDate: new Date('2025-10-01T00:00:00.000Z'),
|
||||
expirationDate: new Date('2026-10-01T00:00:00.000Z'),
|
||||
productId: 'unknown.sku',
|
||||
store: 'play_store',
|
||||
willRenew: true,
|
||||
duration: 'P1Y',
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
identifier: 'Pro',
|
||||
isTrial: false,
|
||||
isActive: true,
|
||||
latestPurchaseDate: new Date('2025-11-01T00:00:00.000Z'),
|
||||
expirationDate: new Date('2026-02-01T00:00:00.000Z'),
|
||||
productId: 'unknown.sku',
|
||||
store: 'app_store',
|
||||
willRenew: true,
|
||||
duration: 'P3M', // not supported -> ignore
|
||||
},
|
||||
],
|
||||
]);
|
||||
const Pro = {
|
||||
identifier: 'Pro',
|
||||
isTrial: false,
|
||||
isActive: true,
|
||||
latestPurchaseDate: new Date('2025-08-01T00:00:00.000Z'),
|
||||
expirationDate: new Date('2025-09-01T00:00:00.000Z'),
|
||||
productId: 'app.affine.pro.Monthly',
|
||||
store: 'app_store',
|
||||
willRenew: true,
|
||||
duration: 'P1M',
|
||||
} as const;
|
||||
const AI = {
|
||||
identifier: 'AI',
|
||||
isTrial: false,
|
||||
isActive: true,
|
||||
latestPurchaseDate: new Date('2025-10-01T00:00:00.000Z'),
|
||||
expirationDate: new Date('2026-10-01T00:00:00.000Z'),
|
||||
productId: 'app.affine.pro.ai.Annual',
|
||||
store: 'play_store',
|
||||
willRenew: true,
|
||||
duration: 'P1Y',
|
||||
} as const;
|
||||
const Unsupported = {
|
||||
identifier: 'Pro',
|
||||
isTrial: false,
|
||||
isActive: true,
|
||||
latestPurchaseDate: new Date('2025-11-01T00:00:00.000Z'),
|
||||
expirationDate: new Date('2026-02-01T00:00:00.000Z'),
|
||||
productId: 'app.affine.pro.Quarterly',
|
||||
store: 'app_store',
|
||||
willRenew: true,
|
||||
duration: 'P3M', // not supported -> ignore
|
||||
} as const;
|
||||
|
||||
mockSubSeq([[Pro], [Pro, AI], [Pro, Unsupported]]);
|
||||
|
||||
// pro monthly via fallback
|
||||
await triggerWebhook(user.id, {
|
||||
@@ -937,10 +931,15 @@ test('should map via entitlement+duration when productId not whitelisted (P1M/P1
|
||||
{
|
||||
proViaFallback: r1,
|
||||
aiViaFallback: r2,
|
||||
// unsupported duration ignored, count remains 1
|
||||
totalCount: count,
|
||||
eventsCounts: {
|
||||
// active pro plan, add 1 active event
|
||||
afterFirst: { a: s1.activatedCount, c: s1.canceledCount },
|
||||
// active pro and ai plans, add 2 active events
|
||||
afterSecond: { a: s2.activatedCount, c: s2.canceledCount },
|
||||
// add 2 active events, add 1 canceled events
|
||||
// cancel pro plans and ignore unsupported plan
|
||||
afterThird: { a: s3.activatedCount, c: s3.canceledCount },
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user