fix: 修复分页字段/角色DTO/套餐详情/批量分配Bug,新增C端测试登录接口和Hurl价格验证测试
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:
2026-03-31 09:54:08 +08:00
parent 33e7f99fdc
commit 2ef8b8a705
54 changed files with 1697 additions and 260 deletions

View File

@@ -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
- **失败**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 | 未修复,断言保留 |