# 🔍 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 | 未修复,断言保留 |