## Context

批量订购包含文件上传、异步任务处理、任务恢复和逐行失败查看四个阶段。任务创建需要绑定一个代理商和一种支付方式，线下支付还需要上传整批凭证；任务处理过程中可能出现部分成功和钱包余额不足，前端必须展示后端结果而不能把整批操作当成原子事务。

## Goals / Non-Goals

- Goals: 提供批量订单 Excel 上传、支付方式选择、任务进度展示、任务恢复和逐行失败明细。
- Goals: 使用 `request_id` 防止重复提交，并按任务 ID 查询服务端真实状态。
- Goals: 复用公共异步任务的五态语义和终态规则。
- Non-Goals: 不在前端解析 Excel 业务行、不执行订单创建、不计算订单金额、不回滚已成功订单。
- Non-Goals: 不改造现有单笔订单创建和单笔支付凭证上传流程。
- Non-Goals: 不新增后端模板下载接口。

## Decisions

- Decision: 批量订购页面使用独立任务视图，订单列表只提供入口，不把逐行结果嵌入订单列表表格。
- Rationale: 批量任务有独立生命周期和大量逐行结果，独立页面更适合恢复、轮询和分页查看。

- Decision: `payment_method` 在创建表单中为单选值，并在请求中对整批固定；线下支付时才允许提交 `voucher_file`。
- Rationale: 产品明确一个批次不能混合支付方式，前端应避免生成含混请求。

- Decision: 使用前端静态 Excel 模板资源。
- Rationale: 产品明确模板下载不依赖后端动态生成，减少接口依赖。

- Decision: 使用 `request_id` 作为客户端幂等键，并在创建前生成一次、提交重试时复用同一值。
- Rationale: 防止网络重试或重复点击创建多个相同批次。

- Decision: 部分成功、钱包余额不足和逐行业务失败均由后端任务结果表达；前端只展示计数和失败明细，不自行推断或回滚。
- Rationale: 钱包扣款和订单事务边界属于后端职责，前端不能可靠重建。

## Data Model

- Create request: `shop_id`、`payment_method`、`file`、可选 `voucher_file`、`request_id`。
- Task identity: `task_id`、`task_no`。
- Task status: `1=待处理`、`2=处理中`、`3=已完成`、`4=已失败`、`5=已取消`；部分成功仍属于已完成终态。
- Task summary: status, total count, success count, failed count, amount summary, timestamps and safe error summary when returned.
- Item result: row number, asset identifier, package code, row status and safe error reason.
- Item query: task ID, page, size and optional row status filter.

## Risks / Trade-offs

- Risk: 后端金额字段名称或单位未在产品文档中明确。
- Mitigation: API 类型和页面以接口实际返回字段为准，统一标注金额单位；实施前补齐字段契约，前端不自行计算汇总。

- Risk: 文件或凭证上传成功但任务创建请求失败，可能留下孤立对象。
- Mitigation: 创建失败时保留用户选择和错误提示；对象清理策略由后端存储生命周期或接口约定处理。

- Risk: 任务详情恢复时任务已过期、删除或用户失去权限。
- Mitigation: 按页面权限和接口错误处理展示对应状态，不重复创建原任务。

## Migration Plan

1. 确认批量订购任务摘要、金额和逐行结果字段契约。
2. 新增 API、类型、权限和静态模板资源。
3. 实现批量订购入口、文件上传、线下凭证上传和幂等提交。
4. 实现任务详情、公共状态展示、轮询和 `task_id` 恢复。
5. 实现逐行结果分页、状态筛选和失败明细展示。
6. 验证钱包余额不足、部分成功、重复提交、刷新恢复和权限组合。

## Open Questions

- 批量订购任务摘要中的金额字段名称、金额单位和金额分类需要以后端接口文档确认。
- 失败明细中的资产字段是统一 `asset_identifier`，还是按资产类型返回 `iccid` / `virtual_no`，需要以后端确认。
- `voucher_file` 是单文件、文件数组还是已上传对象存储 key，需要与 multipart 接口契约确认。
- 批量订购入口的最终路由、菜单名称和权限编码需要产品/后端确认。
