feat: grant transition plan to existing users

This commit is contained in:
QiuSW
2026-07-22 16:56:13 +08:00
parent 09d13ff64a
commit 82c338cbe7
10 changed files with 374 additions and 4 deletions
+11
View File
@@ -2153,3 +2153,14 @@
- 方案:新增默认只预演的 `grant_existing_users_plan` 命令。实际执行必须指定套餐 ID、非空原因、`--execute` 和与预演一致的预期授予人数;默认排除后台/超级用户,并跳过已有同产品有效或宽限期权益的账号。
- 安全边界:批量授予必须在单事务中锁定套餐和目标用户,逐项复用 `grant_software_entitlement()` 生成套餐快照、席位和授权事件;任一失败整批回滚。不得直接写权益表,不修改订阅模式、点数、充值、软件订单或生成任务。
- 发布顺序:任务文档提交后实现命令和测试;线上部署后先备份数据库,再预演、按预演人数执行并抽样验证订阅状态。测试结束后的正式套餐切换另行立项。
## 2026-07-22 完成:T-633 存量用户批量授予过渡测试套餐
- 实现:新增 `grant_plan_to_existing_users()` 与 `grant_existing_users_plan`。默认只预演;执行要求套餐 ID、非空原因、`--execute` 和预期授予人数。范围为启用的非后台/非超级用户;同产品已有有效或宽限期权益时跳过。
- 安全:执行阶段锁套餐和目标用户,在单事务中逐项复用 `grant_software_entitlement()`,所以套餐快照、席位和 `LicenseEvent(granted)` 保持既有规则,任一异常整批回滚。未新增迁移,也未调用点数、充值或软件订单服务。
- 本地验证:专项 5 条测试通过;SQLite 完整 licensing 回归 35 条中 33 条通过,2 条既有并发测试因 SQLite 表级锁失败;`check`、迁移一致性、编译和 `git diff --check` 通过。本地旧 MySQL `43.128.3.240` 拒绝连接,因此未声称取得本地 MySQL 全量测试结果。
- 生产备份:执行前生成 `/root/cmhub-t633-backup-20260722_164956/cmhub-before-t633.sql.gz`,并复制到本地 `deploy/185.216.248.75/20260722_164956_t633/`;两端 SHA256 均为 `ae53d3edd329a3ed16e55958f2a93453f420b5026bbb3294edb6b4e91ad17162`。
- 线上预演:套餐 ID 2、产品 `cmshopee`,`eligible=30`、`skipped_existing=0`、`grant_count=30`;使用 `--expected-grant-count 30` 执行成功。
- 线上结果:30 个不同普通用户获得“测试”权益,产生 30 条授予事件和 3030 条套餐席位快照;后台账号为 0,目标用户缺失为 0,重复有效权益为 0。反向预演为 `skipped_existing=30`、`grant_count=0`。
- API 抽样:订阅状态返回 `active`、`access_source=entitlement`、`entitlement_status=active` 和套餐“测试”,抽样账号点数保持 148。
- 并发说明:执行前后有 4 个生图任务运行,点数聚合从 22221 变为 22219、流水从 10180 变为 10181;最新流水为关联调用的 `consume -2`,属于并发生图业务,不是 T-633 授权命令写账。