Files
junhong_cmp_fiber/.planning/REQUIREMENTS.md
huang 129a38f942 docs(03-02): 完成设备体系 sync-info 接入计划(DEVICE-04)
- 新增 03-02-SUMMARY.md,记录 updateDeviceFromSyncInfo 实现细节
- STATE.md:Phase 3 完成标记,追加 DEVICE-04 决策,Next Action 更新为 Phase 4
- ROADMAP.md:Phase 3 进度更新为 Complete(2/2 plans)
- REQUIREMENTS.md:DEVICE-04 标记完成
2026-03-28 11:40:04 +08:00

169 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Requirements
**Project:** 君鸿卡管系统
**Milestone:** v1.0 — MVP 上线准备
**Date:** 2026-03-27
---
## v1 Requirements
### CRITICAL — P0 紧急 Bug 修复(方案 A
- [x] **CRITICAL-01**: 实名状态常量统一 — `parseRealnameStatus` 写入值 2 改为常量 1Model 注释统一,全链路使用 `constants.RealNameStatusVerified`
- [x] **CRITICAL-02**: C 端实名校验修复 — `client_order/service.go` 实名判断改用 `constants.RealNameStatusVerified`(依赖 CRITICAL-01
- [x] **CRITICAL-03**: 实名激活任务断链修复 — `PollingHandler` 注入 `asynq.Client`,删除 RPush 降级方案,改用 `asynq.Client.EnqueueContext()`
- [x] **CRITICAL-04**: 充值回调后自动购包触发 — `recharge/service.go` 在 HandlePaymentCallback 成功后入队 `TaskTypeAutoPurchaseAfterRecharge`;注册 `AutoPurchaseHandler`
- [x] **CRITICAL-05**: 自动购包佣金链补全 — `AutoPurchaseHandler.ProcessTask()` 事务提交成功后入队 `TaskTypeCommission`
- [x] **CRITICAL-06**: 代购订单金额修正 — 场景 5代理代购下级`sellerCostPrice` 全部 6 处逐一审查,确保使用 `operatorCostPrice`(非 `buyerCostPrice`
- [x] **CRITICAL-07**: 设备导入补充 IMEI 字段 — `DeviceRow` 新增 IMEI`ParseDeviceExcel` 列名映射新增 IMEI`device_import.go` 导入时填充
- [x] **CRITICAL-08**: 提现冻结并发校验 — `my_commission/service.go` 冻结余额后检查 `RowsAffected == 0`,余额不足并发场景返回错误而非静默继续
### PERM — 企业端权限完善(方案 B
- [x] **PERM-01**: 移除 Resolve 接口对企业账号的错误拦截 — 企业账号应能查询被授权的资产
- [x] **PERM-02**: Refresh 接口新增企业账号拦截 — 企业只读,不允许主动触发运营商刷新
### FIN — 财务/提现流程完善(方案 C
- [x] **FIN-01**: 提现审批人字段补全 — `Approve()` 写入 `approved_by` / `approved_at`(当前永远为空)
- [x] **FIN-02**: 提现拒绝 remark 必填校验 — `Reject()` 在 BodyParser 后补充 `validator.Validate()`
- [x] **FIN-03**: 激活配置并发保护 — 提现配置和微信配置激活时,两步 UPDATE 前加 `FOR UPDATE` 行锁
### REALNAME — 实名激活架构重构(方案 G
- [x] **REALNAME-01**: 移除 `tb_package.enable_realname_activation` 字段,新增 `expiry_base VARCHAR(30)` 字段(`from_activation` / `from_purchase`
- [x] **REALNAME-02**: `activateMainPackage` 改写激活决策逻辑 — 按卡类型industry/normal+ 购买路径C端/后台囤货)+ `expiry_base` 三维决策
- [x] **REALNAME-03**: `client_order/service.go` 实名检查改为按卡类型判断(`card_category == "normal"`),删除 `packagesNeedRealname()` 函数
- [x] **REALNAME-04**: `ActivateByRealname()``ExpiryBase` 选择激活时间基准(`from_purchase` 用 CreatedAt`from_activation` 用当前时刻)
- [x] **REALNAME-05**: 套餐管理 API DTO 更新 — 移除 `enable_realname_activation`,新增 `expiry_base` 枚举字段
### POLL — 轮询系统小修(方案 H
- [x] **POLL-01**: `polling:protect` 接入调度 — `scheduler.go` 补充 processManualQueue + processTimedQueue 对 protect 任务的调度
- [x] **POLL-02**: gatewayClient=nil 时停复机返回错误 — `stopCardWithRetry``resumeCardWithRetry` 两处改为返回业务错误而非 nil
- [x] **POLL-03**: packages 接口新增分页 — `GetPackages()` 默认 page=1, pageSize=50最大 100
- [x] **POLL-04**: Series 删除前检查关联套餐 — `package_series/service.go:Delete()` 前置 `CountBySeriesID()` 检查
### DEVICE — 设备体系完善(方案 D
- [x] **DEVICE-01**: 设备模型字段扩展 — DB 迁移新增 `online_status / last_online_time / software_version / switch_mode / last_gateway_sync_at`
- [x] **DEVICE-02**: Gateway sync-info 同步接口对接 — `internal/gateway/device.go` 新增 `SyncDeviceInfo()` 方法
- [x] **DEVICE-03**: `tb_device_sim_binding` 新增 `is_current` 字段 — DB 迁移 + Model + 更新逻辑
- [x] **DEVICE-04**: 设备 Refresh + 详情接入 sync-info — `RefreshDevice()` 在刷新卡数据后调用 `SyncDeviceInfo()`,更新设备在线状态/固件版本/当前卡标识
### REFUND — 退款完整功能(方案 I
- [ ] **REFUND-01**: 新建 `tb_refund_request` 数据模型 — DB 迁移 + GORM Model
- [ ] **REFUND-02**: 退款接口实现 — Handler + Service + Store + 路由注册Create / List / Get / Approve / Reject / Return / Resubmit 共 7 个接口)
- [ ] **REFUND-03**: 审批通过后按比例扣减代理佣金钱包 — 使用整数算术(`amount * approvedRefund / actualReceived`),禁用 float64写负向交易流水
### PAY — 支付功能补全(方案 J-1 + J-2
- [ ] **PAY-01**: 富友支付 JSAPI 接口实现 — 替换留桩,实现预下单 + 返回前端调起支付参数
- [ ] **PAY-02**: 富友支付小程序接口实现 — 与 JSAPI 相同逻辑tradeType 改为 `LETPAY`
- [ ] **PAY-03**: 新增 `FuiouPayJSAPIResponse` DTO字段与微信官方 `wx.requestPayment()` 参数对齐
- [ ] **PAY-04**: 平台代理钱包代购 — `CreateLegacy` 支持 `buyerType="" && resourceShopID != nil` 场景,使用资产所属代理的成本价和钱包
### OPS — 运营逻辑修复(方案 J-3 + J-4
- [ ] **OPS-01**: IoT 卡/设备 status 字段 3/4 业务触发 — 套餐激活成功后更新为 3最后一个 active 套餐到期后更新为 4
- [ ] **OPS-02**: payment_status 枚举统一 — 删除 C 端 `orderStatusToClientStatus()` 映射函数C 端直接输出与管理端一致的 1/2/3/4 枚举
### CLEAN — 代码质量清理(方案 F
- [ ] **CLEAN-01**: 佣金链断裂改为零额待审记录 — 新增 `CommissionStatusPendingReview = 99`,断链时创建 amount=0 的待审记录,不再静默 break
- [ ] **CLEAN-02**: 废弃 sim:status:sync 任务代码删除 — 移除注册行 + 常量 + `internal/task/sim.go` + `internal/service/sync/service.go`
- [ ] **CLEAN-03**: 错误不应被吞 — `asset/service.go``cards, _ :=` 改为记录 Warn 日志
- [ ] **CLEAN-04**: C 端 Handler 迁移到 Service 层 — `handler/app/client_order.go` 订单查询改为调用 `client_order/service.go`,删除直接 DB 访问
- [ ] **CLEAN-05**: Handler/Service 权限不一致修复 — `handler/admin/order.go` 创建订单时补充钱包支付仅允许代理账号的前置校验
- [ ] **CLEAN-06**: StopResumeCallback / ResumeCallback 注入 — `internal/bootstrap/services.go` 中初始化后调用 `SetStopResumeCallback``SetResumeCallback`
### TRAFFIC — 流量体系改革(方案 E破坏性变更
- [ ] **TRAFFIC-01**: 新建 `tb_card_daily_usage` 日粒度流量表 — DB 迁移 + 唯一约束 `(iot_card_id, date)`
- [ ] **TRAFFIC-02**: 轮询流量写入改为 Redis 增量缓存 — `insertDataUsageRecord()` 仅在有增量时写 `RedisCardDailyTrafficKey`
- [ ] **TRAFFIC-03**: 每日落盘定时任务 — Asynq Scheduler 凌晨 2 点 SCAN Redis Key → UPSERT `tb_card_daily_usage` → 删 Key
- [ ] **TRAFFIC-04**: 流量增量累加 — `calculateFlowUpdates()` 改为 `current_month_usage_mb += increment`,检测运营商重置日,新增 `tb_carrier.data_reset_day``tb_iot_card.last_gateway_reading_mb`
- [ ] **TRAFFIC-05**: 流量查询层适配 — 新建 `TrafficQueryService.GetDailyUsage()` 兼容"今日 Redis + 历史 DB"两段数据
---
## v2 Requirements延后
- 卡/资产批量操作(停/复/注销)— 运营场景必须,当前仅有单卡接口
- 卡/订单批量导出Excel/CSV— 财务对账标配,已有导入缺导出
- 套餐到期前微信模板消息提醒 — 用户体验,竞品标配
- 代理商完整资金流水账单(按时间倒序,标注来源类型)
- 下级代理业绩报表(订单数/金额/活跃卡数)
- 卡状态变更历史记录(溯源谁什么时候停了哪张卡)
- SaaS 多租户架构 — v2+ 规划
---
## Out of Scope
- 自动化测试unit/integration/e2e— 项目明确不做
- 设备定期轮询P1-9— 伪需求,改为按需实时拉取
- P1-2 企业认证中间件 — 复用 AdminAuth无需新中间件
- P1-3 提现"已到账"确认接口 — 线下打款,系统无法感知
- P2-6 告警通知渠道 — 优先级低,暂不做
- P2-9 asset_type 校验 — Service 层已有兜底
- P2-24 Carrier→Series 强绑定 — 系列可跨运营商
- P2-30 轮询配置通用化 — 设备轮询取消后此问题不存在
---
## Traceability
*(由 roadmapper 在创建 ROADMAP.md 时填充 — 2026-03-27*
| REQ-ID | Phase | Status |
|--------|-------|--------|
| CRITICAL-01 | Phase 1 | Complete |
| CRITICAL-02 | Phase 1 | Complete |
| CRITICAL-03 | Phase 1 | Complete |
| CRITICAL-04 | Phase 1 | Complete |
| CRITICAL-05 | Phase 1 | Complete |
| CRITICAL-06 | Phase 1 | Complete |
| CRITICAL-07 | Phase 1 | Complete |
| CRITICAL-08 | Phase 1 | Complete |
| PERM-01 | Phase 2 | Complete |
| PERM-02 | Phase 2 | Complete |
| FIN-01 | Phase 2 | Complete |
| FIN-02 | Phase 2 | Complete |
| FIN-03 | Phase 2 | Complete |
| REALNAME-01 | Phase 2 | Complete |
| REALNAME-02 | Phase 2 | Complete |
| REALNAME-03 | Phase 2 | Complete |
| REALNAME-04 | Phase 2 | Complete |
| REALNAME-05 | Phase 2 | Complete |
| POLL-01 | Phase 2 | Complete |
| POLL-02 | Phase 2 | Complete |
| POLL-03 | Phase 2 | Complete |
| POLL-04 | Phase 2 | Complete |
| DEVICE-01 | Phase 3 | Complete |
| DEVICE-02 | Phase 3 | Complete |
| DEVICE-03 | Phase 3 | Complete |
| DEVICE-04 | Phase 3 | Complete |
| REFUND-01 | Phase 4 | Pending |
| REFUND-02 | Phase 4 | Pending |
| REFUND-03 | Phase 4 | Pending |
| PAY-01 | Phase 4 | Pending |
| PAY-02 | Phase 4 | Pending |
| PAY-03 | Phase 4 | Pending |
| PAY-04 | Phase 4 | Pending |
| OPS-01 | Phase 4 | Pending |
| OPS-02 | Phase 4 | Pending |
| CLEAN-01 | Phase 5 | Pending |
| CLEAN-02 | Phase 5 | Pending |
| CLEAN-03 | Phase 5 | Pending |
| CLEAN-04 | Phase 5 | Pending |
| CLEAN-05 | Phase 5 | Pending |
| CLEAN-06 | Phase 5 | Pending |
| TRAFFIC-01 | Phase 6 | Pending |
| TRAFFIC-02 | Phase 6 | Pending |
| TRAFFIC-03 | Phase 6 | Pending |
| TRAFFIC-04 | Phase 6 | Pending |
| TRAFFIC-05 | Phase 6 | Pending |