refactor(utils): 修复密码哈希比较逻辑错误 feat(user): 新增按状态筛选优惠券接口 docs: 添加虚拟发货与任务中心相关文档 fix(wechat): 修正Code2Session上下文传递问题 test: 补充订单折扣与积分转换测试用例 build: 更新配置文件与构建脚本 style: 清理多余的空行与注释
79 lines
4.0 KiB
Markdown
79 lines
4.0 KiB
Markdown
## 目标
|
||
- 将现有单件发货接口扩展为批量接口,支持一次提交多个资产 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` 数组,必填,长度 1–100,去重后处理
|
||
- `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 注释与接口文档
|
||
- 单元测试:服务层批量逻辑、处理器参数校验
|
||
|
||
请确认按此方案实施,我将立即落地代码、接口与测试。 |