fix(billing): backfill finite image quota after free-plan rebuild

Expired paid users were rebuilt as free with period_images_limit=0, which the quota system treats as unlimited. Write the catalog quota on rebuild and repair existing finite plans on schema ensure.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-08-14 21:39:55 +08:00
parent 41f245c88a
commit 8cf1c772a7
4 changed files with 113 additions and 3 deletions
+14 -2
View File
@@ -74,12 +74,24 @@ describe('ensurePlanCatalogSchema', () => {
await ensurePlanCatalogSchema(pool);
const planUpdates = queries.filter(({ sql }) => sql.includes('UPDATE h5_plan_catalog'));
const subUpdates = queries.filter(({ sql }) => sql.includes('UPDATE h5_subscriptions'));
const tokenSubUpdates = queries.filter(({ sql }) => (
sql.includes('UPDATE h5_subscriptions') && sql.includes('period_tokens_limit')
));
const imageSubUpdates = queries.filter(({ sql }) => (
sql.includes('UPDATE h5_subscriptions s') && sql.includes('period_images_limit')
));
const imageLedgerInserts = queries.filter(({ sql }) => (
sql.includes('INSERT INTO h5_image_quota_ledger') && sql.includes('补建漏写')
));
assert.ok(planUpdates.some(({ params }) => params[0] === 450_000 && params[2] === 'free' && params[3] === 150_000));
assert.ok(planUpdates.some(({ params }) => params[0] === 3_600_000 && params[2] === 'lite' && params[3] === 1_200_000));
assert.ok(planUpdates.some(({ params }) => params[0] === 13_500_000 && params[2] === 'standard' && params[3] === 4_500_000));
assert.equal(subUpdates.length, 3);
assert.equal(tokenSubUpdates.length, 3);
assert.equal(imageSubUpdates.length, 1);
assert.equal(imageLedgerInserts.length, 1);
assert.match(imageSubUpdates[0].sql, /p\.period_images > 0/);
assert.match(imageSubUpdates[0].sql, /s\.period_images_limit = 0/);
});
});