七月迭代短暂完结,还有很多后端的关键东西没有弄,这是一版赶时间做的东西
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m26s

This commit is contained in:
2026-07-25 17:06:58 +08:00
parent ad9f613dd6
commit 73f5125d3d
249 changed files with 17137 additions and 877 deletions

View File

@@ -0,0 +1,44 @@
# 资产套餐批量订购功能总结
## 交付范围
本功能复用现有对象存储、Asynq、统一异步任务五态和后台单笔订单 Service为一批卡或设备统一购买一个套餐
- `POST /api/admin/storage/upload-url` 使用 `purpose=batch_purchase` 获取只允许 `.csv` 的上传地址和稳定 `file_key`
- `POST /api/admin/asset-package-batch-orders` 接收 CSV `file_key`、一个 `package_id`、整批统一的 `wallet|offline` 支付方式及可选线下凭证;请求不选择代理。
- `GET /api/admin/asset-package-batch-orders` 分页查询任务,默认 20、最大 100可按统一五态筛选。
- `GET /api/admin/asset-package-batch-orders/:id` 返回任务汇总和逐行成功/失败明细。
- 平台可查看全部任务;代理只能查看自己及下级店铺创建的任务,权限上下文缺失时失败关闭。
## CSV 契约
- 文件必须为 UTF-8 编码的 `.csv`,允许 UTF-8 BOM最大 10MB、最多 1000 个业务行。
- 文件只能有一列,每行填写一个资产标识。首行可使用 `资产标识``identifier``iccid``iccid/虚拟号` 表头,也可直接从第一行填写数据。
- 空资产标识作为行级失败;多列、非法 CSV、非 UTF-8、空文件和超限作为任务级失败在任何订单写入前终止。
- 同一输入标识重复时仅第一行进入订单规则;不同标识解析为同一资产时复用订单幂等结果,后续行记录重复原因,不重复下单或扣款。
## 支付和订单规则
- 整批只选择一个套餐和一种支付方式,不选择代理。每行由现有订单 Service 根据资产当前归属解析结算关系、套餐授权、价格和钱包。
- `wallet` 不允许凭证,支持超级管理员、平台和代理账号;逐行复用现有代理主钱包扣款、信用边界、成功流水、套餐激活、佣金任务和订单幂等规则。
- `offline` 仅允许超级管理员或平台账号,必须提交 15 个凭证 Key每个成功订单保存同一批凭证快照并按现有线下订单规则立即激活不扣钱包。
- 每行独立处理,业务失败不回滚其他成功行。全部行业务失败仍表示任务完成,通过 `success_count=0``fail_count=total_count` 表达。
## 任务与幂等
- 任务状态固定为 `1:待处理, 2:处理中, 3:已完成, 4:已失败, 5:已取消`;当前版本没有取消入口,仅保留统一状态契约。
- Asynq 载荷只包含结构化 `task_id`,不传 CSV 字节、临时路径或预序列化 `[]byte`
- Worker 通过任务状态和超时时间条件领取任务;重复消息发现任务正在有效执行或已终结时直接跳过。
- 超过任务最长执行时间仍停留在“处理中”的记录可被重新领取,用于 Worker 崩溃后恢复;未超时的处理中任务不会并发重入。
- Worker 使用任务快照恢复创建人权限;代理创建的任务仅能处理自己及下级店铺资产,权限范围查询失败时收紧为仅自己店铺,不会按平台无限制权限执行。
- 单行继续复用订单 Service 的资产级锁、Redis 业务键和钱包订单数据库幂等指纹,重复消费不得重复创建订单或扣款。
## 数据与发布
- 迁移 `000192_create_asset_package_batch_order_task` 新增 `tb_asset_package_batch_order_task`,保存套餐/操作者/支付/文件快照、五态、汇总及最多 1000 行 JSONB 结果;不建立外键。
- Worker 必须配置 Redis/Asynq 和对象存储,并监听 `asset:package:batch_order` 独立队列。
- 回滚时先隐藏创建入口并停止新任务,等待已领取任务完成。已经创建的订单、钱包流水、套餐使用和任务结果均为业务事实,不做反向删除。
## 当前验证边界
本次未运行测试、完整构建、LSP 或迁移;按用户后续明确要求已运行 OpenAPI 生成器,并执行 `gofmt`、只读一致性检查和 `git diff --check`。真实对象存储上传、Worker 消费、钱包扣款和线下订单需在后续联调流程验证。