完成模块2

This commit was merged in pull request #14.
This commit is contained in:
2026-06-02 16:58:49 +08:00
parent bdcd3b2bf0
commit 8af444b7ee
36 changed files with 3576 additions and 105 deletions
@@ -0,0 +1,400 @@
# 团课预约场景测试数据文档
## 概述
本文档描述了团课预约功能的测试数据,覆盖了各种预约场景,用于验证系统在不同业务条件下的正确性和健壮性。
---
## 一、测试数据概览
| 数据类别 | 数量 | 说明 |
|---------|------|------|
| 测试会员 | 5个 | 覆盖不同会员卡状态 |
| 会员卡类型 | 8种 | 次卡/时长卡/储值卡 |
| 会员卡记录 | 5条 | 会员持有的实际卡 |
| 团课预约记录 | 4条 | 不同状态的预约 |
| 交易流水 | 27条 | 完整的消费记录 |
---
## 二、会员测试数据
### 2.1 会员列表
| 会员ID | 会员编号 | 昵称 | 手机号 | 性别 | 会员卡状态 |
|--------|---------|------|--------|------|-----------|
| 1001 | MEM202606001 | 新用户小张 | 13800138001 | 男 | 无会员卡 |
| 1002 | MEM202606002 | 额度耗尽用户 | 13800138002 | 女 | 次卡已用完 |
| 1003 | MEM202606003 | 额度充足用户 | 13800138003 | 男 | 次卡剩余8次 |
| 1004 | MEM202606004 | 过期卡用户 | 13800138004 | 女 | 月卡已过期 |
| 1005 | MEM202606005 | 多卡用户小李 | 13800138005 | 男 | 次卡+储值卡 |
### 2.2 会员详情
**会员1001 - 新用户小张**
- 状态:新注册用户,尚未购买任何会员卡
- 用途:测试无会员卡情况下的预约行为
**会员1002 - 额度耗尽用户**
- 状态:持有10次团课卡,已全部用完
- 用途:测试会员卡额度耗尽时的预约行为
**会员1003 - 额度充足用户**
- 状态:持有20次团课卡,剩余8次
- 用途:测试正常预约流程
**会员1004 - 过期卡用户**
- 状态:持有月卡,已于2026-05-31过期
- 用途:测试过期会员卡的预约行为
**会员1005 - 多卡用户小李**
- 状态:持有50次团课卡(剩余45次) + 500元储值卡(剩余350元)
- 用途:测试多会员卡用户选择支付方式的场景
---
## 三、会员卡类型数据
### 3.1 次卡类型
| 卡类型ID | 卡名称 | 类型 | 价格 | 有效天数 | 总次数 | 状态 |
|---------|-------|------|------|---------|-------|------|
| 101 | 10次团课卡 | COUNT_CARD | 299.00 | 90 | 10 | 上架 |
| 102 | 20次团课卡 | COUNT_CARD | 499.00 | 180 | 20 | 上架 |
| 103 | 50次团课卡 | COUNT_CARD | 999.00 | 365 | 50 | 上架 |
### 3.2 时长卡类型
| 卡类型ID | 卡名称 | 类型 | 价格 | 有效天数 | 状态 |
|---------|-------|------|------|---------|------|
| 201 | 月卡 | TIME_CARD | 399.00 | 30 | 上架 |
| 202 | 季卡 | TIME_CARD | 899.00 | 90 | 上架 |
| 203 | 年卡 | TIME_CARD | 2999.00 | 365 | 上架 |
### 3.3 储值卡类型
| 卡类型ID | 卡名称 | 类型 | 价格 | 面额 | 有效天数 | 状态 |
|---------|-------|------|------|------|---------|------|
| 301 | 500元储值卡 | STORED_VALUE_CARD | 500.00 | 500.00 | 365 | 上架 |
| 302 | 1000元储值卡 | STORED_VALUE_CARD | 1000.00 | 1000.00 | 365 | 上架 |
---
## 四、会员卡记录数据(会员持有的卡)
| 记录ID | 会员ID | 卡类型ID | 状态 | 剩余次数 | 剩余金额 | 到期时间 | 购买时间 |
|-------|--------|---------|------|---------|---------|---------|---------|
| 2001 | 1002 | 101 | USED_UP | 0 | 0.00 | 2026-09-01 | 2026-06-01 |
| 2002 | 1003 | 102 | ACTIVE | 8 | 0.00 | 2026-12-01 | 2026-06-01 |
| 2003 | 1004 | 201 | EXPIRED | 0 | 0.00 | 2026-05-31 | 2026-05-01 |
| 2004 | 1005 | 103 | ACTIVE | 45 | 0.00 | 2027-06-01 | 2026-06-01 |
| 2005 | 1005 | 301 | ACTIVE | 0 | 350.00 | 2027-06-01 | 2026-05-15 |
---
## 五、团课预约记录数据
| 预约ID | 课程ID | 会员ID | 会员卡记录ID | 预约时间 | 状态 | 课程名称 |
|-------|-------|--------|-------------|---------|------|---------|
| 3001 | 1 | 1003 | 2002 | 2026-06-01 15:30 | 已预约(0) | 极速燃脂单车 |
| 3002 | 2 | 1003 | 2002 | 2026-06-01 10:00 | 已取消(1) | 清晨流瑜伽 |
| 3003 | 6 | 1003 | 2002 | 2026-05-28 19:00 | 已出席(2) | 蜜桃臀塑造 |
| 3004 | 7 | 1002 | 2001 | 2026-05-30 10:00 | 缺席(3) | 午间冥想放松 |
### 状态说明
| 状态码 | 状态名称 | 说明 |
|-------|---------|------|
| 0 | 已预约 | 用户已成功预约,等待上课 |
| 1 | 已取消 | 用户主动取消预约 |
| 2 | 已出席 | 用户已按时参加课程 |
| 3 | 缺席 | 用户预约后未出席 |
---
## 六、测试场景详解
### 场景1:新注册用户无会员卡预约
**测试目标**:验证系统对无会员卡用户的预约拦截
**测试数据**
- 用户ID1001(新用户小张)
- 目标课程:任意课程
**预期结果**
- 返回错误信息:"未绑定会员卡,请先购买会员卡"
- HTTP状态码:400 Bad Request
---
### 场景2:会员卡额度耗尽预约
**测试目标**:验证系统对额度耗尽会员卡的预约拦截
**测试数据**
- 用户ID1002(额度耗尽用户)
- 会员卡记录ID2001
- 剩余次数:0
**预期结果**
- 返回错误信息:"会员卡余额不足"
- HTTP状态码:400 Bad Request
---
### 场景3:会员卡额度充足预约
**测试目标**:验证正常预约流程
**测试数据**
- 用户ID1003(额度充足用户)
- 会员卡记录ID2002
- 剩余次数:8
- 目标课程:课程ID=1(极速燃脂单车)
**预期结果**
- 预约成功
- 会员卡剩余次数减1(变为7次)
- 生成预约记录
- HTTP状态码:200 OK
---
### 场景4:会员卡已过期预约
**测试目标**:验证系统对过期会员卡的预约拦截
**测试数据**
- 用户ID1004(过期卡用户)
- 会员卡记录ID2003
- 状态:EXPIRED
- 到期时间:2026-05-31
**预期结果**
- 返回错误信息:"会员卡已过期"
- HTTP状态码:400 Bad Request
---
### 场景5:课程已满员预约---------------
**测试目标**:验证系统对满员课程的预约拦截
**测试数据**
- 课程ID3(燃脂搏击)
- 当前人数:20/20
**预期结果**
- 返回错误信息:"课程已满员"
- HTTP状态码:400 Bad Request
---
### 场景6:课程已取消预约
**测试目标**:验证系统对已取消课程的预约拦截
**测试数据**
- 课程ID5(周末冥想修复)
- 状态:1(已取消)
**预期结果**
- 返回错误信息:"课程已取消"
- HTTP状态码:400 Bad Request
---
### 场景7:课程已结束预约
**测试目标**:验证系统对已结束课程的预约拦截
**测试数据**
- 课程ID:6(蜜桃臀塑造)或 7(午间冥想放松)
- 状态:2(已结束)
**预期结果**
- 返回错误信息:"课程已结束"
- HTTP状态码:400 Bad Request
---
### 场景8:超出预约时间预约
**测试目标**:验证系统对预约时间窗口的控制
**测试数据**
- 课程ID4(哈他瑜伽)
- 开始时间:2026-06-01 15:20:00
- 测试时间:课程开始前30分钟内
**预期结果**
- 返回错误信息:"已过预约时间"
- HTTP状态码:400 Bad Request
---
### 场景9:重复预约同一课程
**测试目标**:验证系统对重复预约的拦截
**测试数据**
- 用户ID1003(额度充足用户)
- 课程ID1(极速燃脂单车)
- 已有预约记录:booking_id=3001
**预期结果**
- 返回错误信息:"已预约该课程"
- HTTP状态码:400 Bad Request
---
### 场景10:多会员卡用户选择支付方式
**测试目标**:验证多卡用户的支付方式选择功能
**测试数据**
- 用户ID1005(多卡用户小李)
- 可用卡1:次卡(记录ID=2004,剩余45次)
- 可用卡2:储值卡(记录ID=2005,剩余350元)
**预期结果**
- 系统列出用户所有可用会员卡
- 用户可选择使用次卡或储值卡支付
- 根据选择的卡类型扣减相应额度
---
## 七、交易流水说明
### 7.1 会员1002(额度耗尽用户)消费记录
| 操作顺序 | 操作类型 | 变动次数 | 剩余次数 | 备注 |
|---------|---------|---------|---------|------|
| 1 | PURCHASE | +10 | 10 | 购买10次团课卡 |
| 2-11 | DEDUCT | -1×10 | 0 | 10次课程消费 |
### 7.2 会员1003(额度充足用户)消费记录
| 操作顺序 | 操作类型 | 变动次数 | 剩余次数 | 备注 |
|---------|---------|---------|---------|------|
| 1 | PURCHASE | +20 | 20 | 购买20次团课卡 |
| 2-12 | DEDUCT | -12 | 8 | 12次课程消费 |
### 7.3 会员1005(多卡用户)消费记录
| 会员卡记录ID | 操作类型 | 变动次数 | 变动金额 | 备注 |
|-------------|---------|---------|---------|------|
| 2004 | PURCHASE | +50 | 0 | 购买50次团课卡 |
| 2004 | DEDUCT | -5 | 0 | 预约5节课程 |
| 2005 | PURCHASE | 0 | +500 | 购买500元储值卡 |
| 2005 | DEDUCT | 0 | -150 | 私教课消费150元 |
---
## 八、API测试示例
### 8.1 预约接口
```http
POST /api/group-course/bookings
Content-Type: application/json
{
"courseId": 1,
"memberCardRecordId": 2002
}
```
### 8.2 取消预约接口
```http
PUT /api/group-course/bookings/{bookingId}/cancel
Content-Type: application/json
{
"reason": ""
}
```
### 8.3 查询用户预约列表
```http
GET /api/group-course/bookings?memberId=1003
```
---
## 九、测试数据对应关系图
```
会员表 (member_user)
├── 1001 ──→ (无会员卡)
├── 1002 ──→ 会员卡记录 2001 (USED_UP)
├── 1003 ──→ 会员卡记录 2002 (ACTIVE, 8次)
├── 1004 ──→ 会员卡记录 2003 (EXPIRED)
└── 1005 ──→ 会员卡记录 2004 (ACTIVE, 45次)
└── 会员卡记录 2005 (ACTIVE, 350元)
预约记录表 (group_course_booking)
├── 3001: 已预约
├── 3002: 已取消
├── 3003: 已出席
└── 3004: 缺席
```
---
## 十、数据初始化
测试数据通过 Flyway 迁移脚本 `V10__Insert_Booking_Test_Data.sql` 初始化,需在数据库初始化时执行。
**执行顺序**
1. V1__Create_all_tables.sql - 创建基础表结构
2. V2__Insert_initial_data.sql - 插入初始数据
3. V6__Create_GroupCourse_table.sql - 创建团课表
4. V7__Insert_GroupCourse_test_data.sql - 插入团课测试数据
5. V8__Create_Member_And_MemberCard.sql - 创建会员和会员卡表
6. V9__Add_GroupCourse_Booking_Snapshot_Fields.sql - 添加冗余字段
7. V10__Insert_Booking_Test_Data.sql - 插入预约测试数据(本文件)
---
**文档版本**: v1.1
**创建时间**: 2026-06-02
**更新时间**: 2026-06-02
**适用场景**: 团课预约功能测试
---
## 十一、重要说明
### 11.1 字段说明
`member_card_record` 表包含两个ID字段:
- `id` - 数据库主键(BIGSERIAL PRIMARY KEY
- `member_card_record_id` - 业务ID(BIGSERIAL),代码中使用此字段作为查询和更新条件
### 11.2 测试数据修复记录
**v1.1 修复内容**
- 修复了 `member_card_record` 表测试数据缺失 `member_card_record_id` 字段的问题
- 原问题:测试数据只插入了 `id` 字段,导致 `member_card_record_id` 为 NULL
- 影响:代码使用 `member_card_record_id` 作为WHERE条件时无法匹配到记录,导致扣减权益失败
- 解决:在INSERT语句中添加 `member_card_record_id` 字段,值与 `id` 相同
**修复前**
```sql
INSERT INTO member_card_record (id, member_id, member_card_id, ...) VALUES
(2001, 1002, 101, ...);
```
**修复后**
```sql
INSERT INTO member_card_record (id, member_card_record_id, member_id, member_card_id, ...) VALUES
(2001, 2001, 1002, 101, ...);
```