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

4.0 KiB
Raw Blame History

目标

  • 将现有单件发货接口扩展为批量接口,支持一次提交多个资产 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-126UPDATE 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.statusremark 标记

交付内容

  • 新增批量处理器与服务方法
  • Swagger 注释与接口文档
  • 单元测试:服务层批量逻辑、处理器参数校验

请确认按此方案实施,我将立即落地代码、接口与测试。