- 新增 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 标记完成
10 KiB
10 KiB
Requirements
Project: 君鸿卡管系统 Milestone: v1.0 — MVP 上线准备 Date: 2026-03-27
v1 Requirements
CRITICAL — P0 紧急 Bug 修复(方案 A)
- CRITICAL-01: 实名状态常量统一 —
parseRealnameStatus写入值 2 改为常量 1,Model 注释统一,全链路使用constants.RealNameStatusVerified - CRITICAL-02: C 端实名校验修复 —
client_order/service.go实名判断改用constants.RealNameStatusVerified(依赖 CRITICAL-01) - CRITICAL-03: 实名激活任务断链修复 —
PollingHandler注入asynq.Client,删除 RPush 降级方案,改用asynq.Client.EnqueueContext() - CRITICAL-04: 充值回调后自动购包触发 —
recharge/service.go在 HandlePaymentCallback 成功后入队TaskTypeAutoPurchaseAfterRecharge;注册AutoPurchaseHandler - CRITICAL-05: 自动购包佣金链补全 —
AutoPurchaseHandler.ProcessTask()事务提交成功后入队TaskTypeCommission - CRITICAL-06: 代购订单金额修正 — 场景 5(代理代购下级)
sellerCostPrice全部 6 处逐一审查,确保使用operatorCostPrice(非buyerCostPrice) - CRITICAL-07: 设备导入补充 IMEI 字段 —
DeviceRow新增 IMEI,ParseDeviceExcel列名映射新增 IMEI,device_import.go导入时填充 - CRITICAL-08: 提现冻结并发校验 —
my_commission/service.go冻结余额后检查RowsAffected == 0,余额不足并发场景返回错误而非静默继续
PERM — 企业端权限完善(方案 B)
- PERM-01: 移除 Resolve 接口对企业账号的错误拦截 — 企业账号应能查询被授权的资产
- PERM-02: Refresh 接口新增企业账号拦截 — 企业只读,不允许主动触发运营商刷新
FIN — 财务/提现流程完善(方案 C)
- FIN-01: 提现审批人字段补全 —
Approve()写入approved_by/approved_at(当前永远为空) - FIN-02: 提现拒绝 remark 必填校验 —
Reject()在 BodyParser 后补充validator.Validate() - FIN-03: 激活配置并发保护 — 提现配置和微信配置激活时,两步 UPDATE 前加
FOR UPDATE行锁
REALNAME — 实名激活架构重构(方案 G)
- REALNAME-01: 移除
tb_package.enable_realname_activation字段,新增expiry_base VARCHAR(30)字段(from_activation/from_purchase) - REALNAME-02:
activateMainPackage改写激活决策逻辑 — 按卡类型(industry/normal)+ 购买路径(C端/后台囤货)+expiry_base三维决策 - REALNAME-03:
client_order/service.go实名检查改为按卡类型判断(card_category == "normal"),删除packagesNeedRealname()函数 - REALNAME-04:
ActivateByRealname()按ExpiryBase选择激活时间基准(from_purchase用 CreatedAt,from_activation用当前时刻) - REALNAME-05: 套餐管理 API DTO 更新 — 移除
enable_realname_activation,新增expiry_base枚举字段
POLL — 轮询系统小修(方案 H)
- POLL-01:
polling:protect接入调度 —scheduler.go补充 processManualQueue + processTimedQueue 对 protect 任务的调度 - POLL-02: gatewayClient=nil 时停复机返回错误 —
stopCardWithRetry和resumeCardWithRetry两处改为返回业务错误而非 nil - POLL-03: packages 接口新增分页 —
GetPackages()默认 page=1, pageSize=50,最大 100 - POLL-04: Series 删除前检查关联套餐 —
package_series/service.go:Delete()前置CountBySeriesID()检查
DEVICE — 设备体系完善(方案 D)
- DEVICE-01: 设备模型字段扩展 — DB 迁移新增
online_status / last_online_time / software_version / switch_mode / last_gateway_sync_at - DEVICE-02: Gateway sync-info 同步接口对接 —
internal/gateway/device.go新增SyncDeviceInfo()方法 - DEVICE-03:
tb_device_sim_binding新增is_current字段 — DB 迁移 + Model + 更新逻辑 - 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: 新增
FuiouPayJSAPIResponseDTO,字段与微信官方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 |