All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m26s
45 lines
4.0 KiB
Markdown
45 lines
4.0 KiB
Markdown
# 资产套餐批量订购功能总结
|
||
|
||
## 交付范围
|
||
|
||
本功能复用现有对象存储、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` 仅允许超级管理员或平台账号,必须提交 1~5 个凭证 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 消费、钱包扣款和线下订单需在后续联调流程验证。
|