Files
junhong_cmp_fiber/tests/hurl/reports/findings-package-resource-full-flow-2026-03-30.md
huang 2ef8b8a705
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
fix: 修复分页字段/角色DTO/套餐详情/批量分配Bug,新增C端测试登录接口和Hurl价格验证测试
- 修复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测试变量
2026-03-31 09:54:08 +08:00

134 lines
6.6 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.
# 🔍 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
- **失败**1C-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 | 未修复,断言保留 |