fix: 修复分页字段/角色DTO/套餐详情/批量分配Bug,新增C端测试登录接口和Hurl价格验证测试
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
- 修复B-2:27个分页DTO字段名统一(list→items, page_size→size,删除total_pages) - 修复B-1:角色接口统一返回DTO(id小写,消除GORM大写字段名) - 修复C-1:套餐详情接口(GET /packages/:id)补充代理佣金字段 - 修复C-2:批量分配已存在记录由500改为静默跳过 - 修复C-3:创建系列授权响应在事务提交后构建,packages数组不再为空 - 新增C端开发测试登录接口(POST /api/c/v1/auth/dev-login,仅logging.development=true时生效) - 新增Hurl测试:card-price-verification-flow.hurl(导入卡→分配→C端价格验证) - 新增测试Excel数据文件和dev.env测试变量
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
# 🔍 Hurl 测试发现报告
|
||||
|
||||
- **测试文件**:`flows/package-resource-full-flow.hurl`
|
||||
- **生成时间**:2026-03-30
|
||||
- **最后更新**:2026-03-30(修复 B-1/B-2/C-1/C-2/C-3 后更新)
|
||||
- **总请求数**:37
|
||||
- **通过**:36
|
||||
- **失败**:1(C-4,新发现 bug,断言保留)
|
||||
- **发现总计**:A类: 2, B类: 2, C类: 4
|
||||
|
||||
---
|
||||
|
||||
## A 类(测试自身错误)— 已自动修正
|
||||
|
||||
### A-1: 角色名冲突导致创建失败(409)
|
||||
|
||||
- **位置**:第 2 步 `POST /api/admin/roles`
|
||||
- **原因**:角色名使用固定值 `"hurl测试代理角色"`,重复运行时触发唯一约束冲突
|
||||
- **修正**:角色名改为 `"hurl测试角色-{{newUuid}}"`
|
||||
|
||||
### A-2: 店铺创建时初始账号用户名冲突(409)
|
||||
|
||||
- **位置**:第 5/7 步 `POST /api/admin/shops`
|
||||
- **原因**:`init_username` 使用 env 文件中的固定值,重复运行时触发 `CodeUsernameExists (1013)`
|
||||
- **修正**:改为幂等策略 — `HTTP *` 接受创建结果 + 通过账号查询获取 `shop_id`
|
||||
- **备注**:env 文件中的 `agent1_username` / `agent2_username` 有唯一约束,首次运行后不可变更。如需重新创建,需先清理旧数据。
|
||||
|
||||
---
|
||||
|
||||
## B 类(代码一致性问题)— ✅ 已修复
|
||||
|
||||
### B-1: 角色接口返回原始 GORM 模型而非 DTO
|
||||
|
||||
- **位置**:`POST /api/admin/roles` → 响应体
|
||||
- **DTO 定义**:`RoleResponse` 有 `json:"id"`(小写)、`json:"role_name"`、`json:"created_at"` 等
|
||||
- **Handler 实际(修复前)**:直接返回 `model.Role`,字段为 `"ID"`(大写 GORM 默认)、`"CreatedAt"` 等
|
||||
- **影响**:前端按 API 文档对接会取不到 `id` 字段
|
||||
- **决策**:添加 model→DTO 转换保持一致性
|
||||
- **✅ 修复**:`internal/service/role/service.go` — `Create`/`Get`/`Update` 返回 `*dto.RoleResponse`,新增 `toResponse()` 辅助函数
|
||||
- **验证**:hurl 测试断言 `$.data.id`(小写)通过
|
||||
|
||||
### B-2: 所有分页接口的实际格式与 DTO 定义不一致
|
||||
|
||||
- **位置**:所有列表接口(`GET /packages`, `GET /shops`, `GET /shop-series-grants` 等)
|
||||
- **DTO 定义(修复前)**:`json:"list"` / `json:"page_size"` / `json:"total_pages"`
|
||||
- **Handler 实际**:`response.SuccessWithPagination()` 返回 `{items, total, page, size}`
|
||||
- **影响**:前端按 DTO 文档对接分页字段名不匹配
|
||||
- **决策**:DTO 定义改为匹配 `SuccessWithPagination` 格式
|
||||
- **✅ 修复**:27 个 DTO 文件 json tag 统一(`list→items`, `page_size→size`),删除 `TotalPages` 字段及 12 个 service/handler 中的计算逻辑
|
||||
- **验证**:hurl 测试断言 `$.data.items` / `$.data.size` 通过
|
||||
|
||||
---
|
||||
|
||||
## C 类(接口行为 Bug)
|
||||
|
||||
### C-1: 套餐详情接口缺少 `one_time_commission_amount` 字段 — ✅ 已修复
|
||||
|
||||
- **位置**:`GET /api/admin/packages/:id`(代理视角)
|
||||
- **预期**:`PackageResponse` DTO 定义了 `one_time_commission_amount` 字段
|
||||
- **实际(修复前)**:列表接口返回该字段,详情接口不返回
|
||||
- **决策**:Detail handler 增加佣金信息增强逻辑
|
||||
- **✅ 修复**:`internal/service/package/service.go` → `Get()` 方法增加代理用户佣金信息增强,调用 `fillCommissionInfo` 与 `List` 保持一致
|
||||
- **验证**:hurl 断言 `$.data.one_time_commission_amount == 3000`(一级代理)和 `== 2000`(二级代理)均通过
|
||||
|
||||
### C-2: 批量分配对已有授权的店铺返回 500 — ✅ 已修复
|
||||
|
||||
- **位置**:`POST /api/admin/shop-package-batch-allocations`
|
||||
- **预期**:对已有分配记录应跳过或返回业务错误码,而非 500
|
||||
- **实际(修复前)**:唯一约束冲突触发 `{code: 2001, msg: "内部服务器错误"}`
|
||||
- **决策**:添加已存在记录的前置检查
|
||||
- **✅ 修复**:`internal/service/shop_package_batch_allocation/service.go` → `BatchAllocate()` 方法在创建前用 `GetByShopAndPackageForSystem` 检查记录是否已存在,已存在则跳过
|
||||
- **验证**:hurl 测试批量分配请求不再返回 500
|
||||
|
||||
### C-3: 创建授权接口响应不包含 packages 数组 — ✅ 已修复
|
||||
|
||||
- **位置**:`POST /api/admin/shop-series-grants`
|
||||
- **预期**:创建响应应包含完整 `packages` 列表
|
||||
- **实际(修复前)**:`packages` 为空数组(事务内查询,新数据未提交不可见)
|
||||
- **根因**:`buildGrantResponse` 在事务内部调用,使用 `s.db` 而非事务 `tx` 查询 packages
|
||||
- **决策**:创建授权后返回完整响应
|
||||
- **✅ 修复**:`internal/service/shop_series_grant/service.go` → `Create()` 方法将 `buildGrantResponse` 调用移到事务提交后
|
||||
- **验证**:hurl 测试 GET 详情确认 packages 存在
|
||||
|
||||
### C-4: 创建授权不校验目标店铺是否存在 — 🐛 未修复(新发现)
|
||||
|
||||
- **位置**:`POST /api/admin/shop-series-grants`
|
||||
- **预期**:`shop_id` 对应的店铺不存在时应返回 404
|
||||
- **实际**:`shop_id=9999999`(不存在的店铺)也能成功创建授权记录,返回 200
|
||||
- **影响**:
|
||||
- 产生无效的授权数据(关联到不存在的店铺)
|
||||
- 数据一致性风险:后续查询/操作该授权时可能出现不可预期的行为
|
||||
- **测试断言**:保留 `HTTP 404`(预期失败,直到代码修复)
|
||||
- **建议**:`Create()` 方法中添加店铺存在性校验:
|
||||
```go
|
||||
_, err := s.shopStore.GetByID(ctx, req.ShopID)
|
||||
if err != nil {
|
||||
return nil, errors.New(errors.CodeNotFound, "目标店铺不存在")
|
||||
}
|
||||
```
|
||||
|
||||
- 决策: 修复吧
|
||||
|
||||
---
|
||||
|
||||
## 非 Bug 项(已确认的正常业务逻辑)
|
||||
|
||||
### 强充金额锁定机制
|
||||
|
||||
- **位置**:`PUT /api/admin/shop-series-grants/:id`
|
||||
- **行为**:当 `force_recharge_locked=true` 时,grant 级别无法修改 `force_recharge_amount`,金额由套餐系列配置控制
|
||||
- **判定**:正常业务逻辑,非 Bug
|
||||
- **断言**:已按实际行为编写(`force_recharge_amount == 5000`)
|
||||
|
||||
### 有下级分配时不可修改成本价
|
||||
|
||||
- **位置**:`PUT /api/admin/shop-series-grants/:id/packages`
|
||||
- **行为**:存在下级分配记录时返回 `{code: 1005, msg: "存在下级分配记录,请先回收后再修改成本价"}`
|
||||
- **判定**:正常业务保护机制,非 Bug
|
||||
- **断言**:改为只读验证(GET 详情),不再尝试修改
|
||||
|
||||
---
|
||||
|
||||
## 修复历史
|
||||
|
||||
| 日期 | 操作 | 涉及文件 |
|
||||
|------|------|---------|
|
||||
| 2026-03-30 | 初始报告生成 | — |
|
||||
| 2026-03-30 | 修复 B-1 | `internal/service/role/service.go` |
|
||||
| 2026-03-30 | 修复 B-2 | 27 个 DTO + 12 个 service/handler |
|
||||
| 2026-03-30 | 修复 C-1 | `internal/service/package/service.go` |
|
||||
| 2026-03-30 | 修复 C-2 | `internal/service/shop_package_batch_allocation/service.go` |
|
||||
| 2026-03-30 | 修复 C-3 | `internal/service/shop_series_grant/service.go` |
|
||||
| 2026-03-30 | 新增 C-4 | 未修复,断言保留 |
|
||||
Reference in New Issue
Block a user