# 共识文档 **Change**: package-system-upgrade (套餐系统升级-支持自然月按天套餐与多套餐管理) **确认时间**: 2026-02-10 **确认人**: 用户 --- ## 1. 要做什么 - [x] **套餐类型扩展**:新增「自然月套餐」和「按天套餐」两种类型(已确认) - 自然月套餐:按自然月边界计算有效期(如1月15日生效→1月31日失效) - 按天套餐:按天数计算有效期(如1月15日+30天→2月13日失效) - [x] **流量重置周期**:支持套餐流量按「日/月/年/不重置」四种周期重置(已确认) - 独立于套餐有效期 - 例如:12个月套餐可配置为按月重置或按年重置 - [x] **首次实名激活机制**(后台囤货场景)(已确认) - 支持未实名状态购买套餐(仅后台管理) - 载体(设备/卡)首次实名时自动激活套餐 - 有效期从实名时刻开始计算 - 设备绑定多卡场景:任意一张卡首次实名即触发 - [x] **主套餐排队生效**(已确认) - 同时只能有1个生效中的主套餐 - 后续购买的主套餐按购买顺序排队 - 当前主套餐到期后自动激活下一个 - [x] **加油包生命周期管理**(已确认) - 加油包必须在有主套餐时才能购买 - 支持「独立有效期」和「跟随主套餐」两种模式 - 主套餐过期时,其关联加油包自动失效(即使流量未用完) - [x] **流量扣减优先级**(已确认) - 先扣加油包流量(按购买顺序) - 最后扣主套餐流量 - [x] **停机条件调整**(已确认) - 主套餐 + 所有加油包流量都用完才停机 - [x] **三套流量统计系统**(已确认) - 系统A(客户视图):主套餐和加油包分开展示,含总计 - 系统B(卡流量详单):按日统计卡总流量,与套餐无关 - 系统C(套餐流量详单):按套餐维度记录每日增量流量 - [x] **上游流量适配**(已确认) - 适配运营商周期(联通27号重置/其他1号重置) - 每日增量 = 当前查询用量 - 昨日记录用量 - [x] **现有API改造**(已确认) - 套餐管理API:支持新增字段(套餐类型、重置周期等) - 订单API:支持主套餐排队逻辑、加油包购买限制 - 流量查询API:支持三套统计系统的数据展示 ## 2. 不做什么 - [x] **不支持旧加油包继承**(已确认) - 旧主套餐过期时,其加油包不会继承到新主套餐 - 新主套餐需要重新购买加油包 - [x] **不支持多主套餐并行生效**(已确认) - 不允许同时有多个主套餐处于生效中状态 - 必须按排队顺序逐个生效 - [x] **不支持客户端未实名购买**(已确认) - 首次实名激活机制仅限后台管理端 - 客户端购买套餐必须已实名 - [x] **不支持流量跨套餐转移**(已确认) - 套餐过期后,剩余流量不能转移到新套餐 - 每个套餐独立计算流量 - [x] **不支持手动指定主套餐生效时间**(已确认) - 主套餐生效时间由系统自动管理(按排队顺序) - 不允许用户指定"下个月生效"等特定时间 - [x] **不支持加油包独立存在**(已确认) - 加油包必须依附于主套餐 - 没有主套餐时不能单独使用加油包 **注**: 因处于开发阶段,可以完全重构,不受历史数据限制 ## 3. 关键约束 - [x] **技术栈约束**(已确认) - 必须使用 GORM 修改数据模型,禁止直接使用 database/sql - 套餐生效调度使用现有轮询系统(Scheduler + PollingHandler) - 使用 Asynq 处理异步任务(实名回调、套餐激活等) - [x] **数据库设计约束**(已确认) - 禁止建立外键约束 - 禁止使用 GORM 关联关系标签(foreignKey, hasMany, belongsTo) - 关联通过 ID 字段手动维护,在代码层面显式查询 - [x] **架构分层约束**(已确认) - 必须遵循 Handler → Service → Store → Model 分层 - Handler 层只处理 HTTP 请求/响应,不包含业务逻辑 - Service 层包含所有业务逻辑,支持事务管理 - [x] **错误处理约束**(已确认) - 所有错误必须在 pkg/errors/ 中定义 - Service 层禁止使用 fmt.Errorf,必须返回 errors.New/errors.Wrap - Handler 层禁止直接拼接底层错误信息给客户端 - [x] **并发安全约束**(已确认) - 套餐激活逻辑必须支持并发安全(乐观锁/事务) - 流量扣减逻辑必须使用数据库事务 - 主套餐排队逻辑必须防止竞态条件 - [x] **性能约束**(已确认) - 轮询系统必须支持千万级卡规模(现有能力) - 流量查询 API P95 < 200ms, P99 < 500ms - 套餐激活调度延迟 < 1分钟 - [x] **测试约束**(已确认) - 核心业务逻辑测试覆盖率 ≥ 90% - 必须编写验收测试(基于 Spec Scenarios) - 禁止绕过核心逻辑的测试(例如传递 nil 跳过依赖) - [x] **文档约束**(已确认) - 所有注释必须使用中文 - 新增 API 必须更新 OpenAPI 文档生成器 - 必须更新 CLAUDE.md 中的相关规范 ## 4. 验收标准 ### 数据库层 - [x] 1. Package 表包含 calendar_type, data_reset_cycle, enable_realname_activation 字段(已确认) - [x] 2. PackageUsage 表 status 支持 0-待生效, 1-生效中, 2-已用完, 3-已过期, 4-已失效(已确认) - [x] 3. 新表 PackageUsageDailyRecord 存在且有正确索引(package_usage_id + date)(已确认) - [x] 4. 数据库迁移脚本执行成功,无数据丢失(已确认) ### 套餐购买逻辑 - [x] 5. 后台管理端可为未实名载体购买套餐,状态为"待生效"(已确认) - [x] 6. 客户端未实名时购买套餐返回错误提示(已确认) - [x] 7. 购买第2个主套餐时,priority 自动递增,状态为"待生效"(已确认) - [x] 8. 购买加油包时,无主套餐返回错误"必须有主套餐才能购买加油包"(已确认) ### 实名激活逻辑 - [x] 9. 设备第1张卡实名后,待生效套餐自动变为"生效中"(已确认) - [x] 10. 设备第2、第3张卡实名后,套餐状态不变(已确认) - [x] 11. 实名激活的套餐,activated_at = 实名时刻,expires_at 按套餐类型计算(已确认) ### 主套餐排队逻辑 - [x] 12. 当前主套餐过期后,1分钟内 priority 最小的待生效主套餐自动激活(已确认) - [x] 13. 自然月套餐激活时,expires_at 为当月最后一天 23:59:59(已确认) - [x] 14. 按天套餐激活时,expires_at = activated_at + duration_days(已确认) ### 加油包生命周期 - [x] 15. 主套餐过期时,其关联加油包状态变为"已失效"(已确认) - [x] 16. 独立有效期的加油包过期时,状态变为"已过期"(已确认) ### 流量扣减逻辑 - [x] 17. 新增流量时,优先扣减 priority 最小的加油包(已确认) - [x] 18. 所有加油包用完后,才开始扣减主套餐流量(已确认) - [x] 19. 主套餐 + 所有加油包流量都用完时,轮询系统触发停机(已确认) ### 流量统计系统 - [x] 20. 客户视图 API 返回:主套餐、每个加油包、总计(三个数据)(已确认) - [x] 21. 卡流量详单 API 按日返回,包含 date, daily_increase_mb, total_mb(已确认) - [x] 22. 套餐流量详单 API 按套餐维度,按日返回,包含 date, daily_usage_mb, cumulative_mb(已确认) ### 流量重置逻辑 - [x] 23. reset_cycle=daily 的套餐,每天0点重置 data_usage_mb 为 0(已确认) - [x] 24. reset_cycle=monthly 的套餐,每月1号0点重置(或根据运营商配置)(已确认) - [x] 25. reset_cycle=yearly 的套餐,每年1月1号0点重置(已确认) ### API 改造 - [x] 26. POST /api/admin/packages 支持新增字段创建套餐(已确认) - [x] 27. GET /api/admin/packages/:id 返回包含新增字段(已确认) - [x] 28. POST /api/admin/orders 支持主套餐排队逻辑(已确认) - [x] 29. 新增 GET /api/h5/packages/my-usage 返回客户视图数据(已确认) - [x] 30. 新增 GET /api/admin/package-usage/:id/daily-records 返回套餐流量详单(已确认) ### 性能指标 - [x] 31. 流量查询 API 响应时间 P95 < 200ms(已确认) - [x] 32. 套餐激活调度延迟 < 1分钟(已确认) - [x] 33. 轮询系统支持千万级卡规模(现有能力不退化)(已确认) ### 测试覆盖 - [x] 34. 核心业务逻辑单元测试覆盖率 ≥ 90%(已确认) - [x] 35. 所有 Spec Scenarios 有对应的验收测试(已确认) - [x] 36. 所有验收测试在实现前生成且预期 FAIL(已确认) --- ## 讨论背景 在探索阶段,用户提出了需求方补充的套餐系统需求,核心问题包括: 1. **套餐类型多样化**:现有系统只有按月计算的简单套餐,需要支持自然月和按天两种计算方式 2. **囤货场景支持**:代理商需要提前为未实名设备囤货(低价采购),等待首次实名时自动激活 3. **多套餐管理复杂度**:需要支持主套餐排队、加油包生命周期管理、流量扣减优先级等复杂逻辑 4. **流量统计精细化**:需要三套独立的流量统计系统分别服务于客户视图、卡维度统计、套餐维度统计 通过详细讨论,澄清了以下关键点: - 套餐周期类型(自然月/按天)独立于流量重置周期(日/月/年/不重置) - 首次实名激活仅限后台管理端,客户端必须已实名才能购买 - 主套餐同时只能有一个生效,后续购买自动排队 - 加油包完全依附于主套餐,主套餐过期时加油包也失效 - 流量扣减优先级:加油包 > 主套餐 ## 关键决策记录 | 决策点 | 选择 | 原因 | |--------|------|------| | 套餐类型与重置周期 | 分为两个独立维度 | 灵活性更高,支持"自然月年套餐按年重置"等复杂场景 | | 首次实名激活权限 | 仅限后台管理端 | 防止客户端恶意囤货,保证正常业务流程 | | 主套餐并发控制 | 同时只能有1个生效 | 简化业务逻辑,符合运营商套餐习惯 | | 加油包继承机制 | 不继承,跟随主套餐失效 | 避免复杂的跨套餐关联,符合运营商逻辑 | | 流量扣减优先级 | 加油包优先 | 鼓励用户购买加油包,提升营收 | | 历史数据处理 | 可完全重构 | 开发阶段,无需兼容历史数据 | | 流量统计系统 | 三套独立系统 | 满足不同场景需求(客户视图、数据统计、套餐分析)| --- **签字确认**: 用户已通过 Question_tool 逐条确认以上内容 ## 后续步骤 1. **生成 Proposal** - 使用 `/opsx:continue` 创建提案,定义 Capabilities 2. **设计数据模型** - 创建 Design artifact,详细设计数据库结构和业务流程 3. **编写 Spec** - 定义详细的 API 规范和业务场景 4. **生成验收测试** - 从 Spec Scenarios 自动生成测试骨架 5. **实现功能** - 按照 Tasks 逐步实现 6. **验证完成** - 确保所有验收标准通过