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:
@@ -0,0 +1,43 @@
|
||||
# 2026-08-14 过期后补建免费套餐把图片额度写成无限
|
||||
|
||||
## 现象
|
||||
|
||||
生产管理后台用户详情里,部分普通用户的图片额度显示「无限」,输入框和「保存额度」被禁用。典型用户:柯彤(`wx_1ugymxba`),当时有效套餐为免费版,备注「系统迁移补建免费套餐」,`period_images_limit = 0`,已用 4 张。
|
||||
|
||||
后台把 `period_images_limit === 0` 视为无限,用户详情和 `setImageQuota` 都拒绝调整。这些用户可以无限制调用 `image_make`。
|
||||
|
||||
## 根因
|
||||
|
||||
1. `initSchema` / `migrateSchema` 在用户没有有效订阅时会补建免费套餐,INSERT 只写了 token 额度,没有写 `period_images_limit`。
|
||||
2. 该列 `DEFAULT 0`,而计费把 `0` 设计成「无限」,不是「没有额度」。
|
||||
3. 付费套餐过期后,Portal / Plaza 下次启动会给该用户补建免费套餐,于是变成无限生图。
|
||||
|
||||
生产套餐目录里免费版是 10 张/周期,不是无限。事故发生时有 33 条有效免费订阅命中该补建备注且上限为 0;另有 86 条正常免费订阅上限为 10。
|
||||
|
||||
## 修复
|
||||
|
||||
- 补建免费套餐时写入套餐目录的 `period_images`(无目录时回退 10)。
|
||||
- `ensurePlanCatalogSchema` 启动时把「有效订阅上限为 0,但目录额度 > 0」的记录回填为目录值,并记一条 `plan_change` 流水。真正无限套餐(目录 `period_images = 0`)不改。
|
||||
- 生产已对这 33 条有效订阅做一次数据回填。代码修复需随 Memind 发布后才会阻止再次补建漏写。
|
||||
|
||||
## 排查入口
|
||||
|
||||
```sql
|
||||
SELECT u.username, u.display_name, s.plan_type, s.note,
|
||||
s.period_images_limit, s.period_images_used, s.period_images_bonus
|
||||
FROM h5_subscriptions s
|
||||
JOIN h5_users u ON u.id = s.user_id
|
||||
WHERE s.status = 'active'
|
||||
AND s.expires_at > UNIX_TIMESTAMP() * 1000
|
||||
AND s.period_images_limit = 0;
|
||||
|
||||
SELECT plan_type, name, period_images FROM h5_plan_catalog;
|
||||
```
|
||||
|
||||
管理后台:用户详情「图片生成额度」显示无限且无法保存,同时计费里该用户是免费套餐、备注含「系统迁移补建」。
|
||||
|
||||
## 影响边界与回滚
|
||||
|
||||
- 目录里本身就是无限的套餐(`period_images = 0`)不会被回填。
|
||||
- 已用量超过目录额度的用户回填后剩余为 0,不能再继续按无限额度生图。
|
||||
- 回滚代码不会自动把已回填的上限改回 0;如需恢复无限,要显式改订阅或目录。
|
||||
Reference in New Issue
Block a user