bindbox-game/.trae/documents/批量申请发货设计与实现方案.md
邹方成 45815bfb7d chore: 清理无用文件与优化代码结构
refactor(utils): 修复密码哈希比较逻辑错误
feat(user): 新增按状态筛选优惠券接口
docs: 添加虚拟发货与任务中心相关文档
fix(wechat): 修正Code2Session上下文传递问题
test: 补充订单折扣与积分转换测试用例
build: 更新配置文件与构建脚本
style: 清理多余的空行与注释
2025-12-18 17:35:55 +08:00

79 lines
4.0 KiB
Markdown
Raw 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.

## 目标
- 将现有单件发货接口扩展为批量接口,支持一次提交多个资产 ID{"inventory_ids":[52,53,...]})。
- 复用现有发货能力(默认地址、资产状态迁移、备注标记),保证幂等与错误可追踪。
## 现状
- 单件接口:`POST /api/app/users/{user_id}/inventory/request-shipping`,请求体 `{ inventory_id }`
- 处理器位置internal/api/user/request_shipping_app.go:30-47
- 服务层:`RequestShipping(ctx, userID, inventoryID)` 设置资产状态为已申请发货并记录备注
- 代码位置internal/service/user/address_share.go:120-126`UPDATE user_inventory SET status=3, ... remark+='|shipping_requested' WHERE status=1`
## 接口设计
- 新增:`POST /api/app/users/{user_id}/inventory/request-shipping-batch`
- 请求体:
- `inventory_ids` 数组,必填,长度 1100去重后处理
- `address_id` 可选;若不提供则使用用户默认地址
- 返回体:
- `address_id` 实际使用的地址 ID
- `success_ids` 已成功提交的资产 ID 列表
- `skipped` 数组:[{ id, reason }](如 not_found、not_owned、invalid_status、already_requested
- `failed` 数组:[{ id, reason }](如 DB 错误等)
## 行为与规则
- 地址选择
- 若提供 `address_id`:校验属于该用户且有效;否则返回 400
- 若未提供:读取默认地址;不存在则返回 400沿用现有单件逻辑
- 资产校验(逐个)
- 必须属于该用户
- `status=1`(可发货)才处理;`status=3`(已申请)则标记为 `already_requested` 并 skip幂等
- 不存在或不属于该用户 → `skipped.not_owned/not_found`
- 幂等性
- 若 remark 已包含 `shipping_requested` 或状态为 3则视为已处理加入 `skipped` 并不报错
- 原子性
- 批量以“逐条子事务”处理(每条调用服务层更新),确保单条失败不影响其他条目;最终返回成功/跳过/失败三类列表
- 审计
-`user_points_ledger` 无需记录(该流程与积分无关);如需审计可在后续增加 `user_operations` 表留痕
## 服务层扩展
- 新增:`RequestShippings(ctx, userID int64, inventoryIDs []int64, addressID *int64) (addrID int64, success []int64, skipped []struct{id int64; reason string}, failed []struct{id int64; reason string}, err error)`
- 内部:
-`addressID==nil`,读取默认地址(沿用单件方法)
- 循环:校验→调用现有 `RequestShipping(ctx, userID, inventoryID)`;捕获错误进行分流
- 可选优化:对同一用户的多件,合并一次地址校验;对 DB 更新使用独立事务(已在现有方法内处理)
## 处理器实现
- 新增处理器:`RequestShippingBatch()`
- 位置internal/api/user/request_shipping_app.go或新文件 `request_shipping_batch_app.go`
- 解析 `inventory_ids`(去重、长度限制);解析可选 `address_id`
- 调用服务层批量方法,组装响应
- 统一错误码:参数错误 `code.ParamBindError`,无地址 `10021`(沿用或新增),其他子项错误填入 `failed` 字段
## 错误码与返回示例
- 400 参数错误:`{"code":10023,"message":"invalid inventory_ids"}`
- 200 成功+部分跳过:
```
{
"address_id": 888,
"success_ids": [52, 53],
"skipped": [{"id": 54, "reason": "already_requested"}],
"failed": []
}
```
## 测试用例
- 有默认地址,提交 1、N 个有效资产 → 全成功
- 混合:包含非本用户、已申请、不存在 → 分别进 `skipped`
- 指定 address_id 非本用户 → 400
- 无默认地址且未指定 address → 400
- 幂等:重复提交相同资产 → 均进入 `already_requested`
## 兼容性
- 不改动现有单件接口;前端可增设批量勾选后调用新接口
- DB 无结构变化;仍依赖 `user_inventory.status``remark` 标记
## 交付内容
- 新增批量处理器与服务方法
- Swagger 注释与接口文档
- 单元测试:服务层批量逻辑、处理器参数校验
请确认按此方案实施,我将立即落地代码、接口与测试。