# 安全学习使用学时套餐接口说明

## 1. 功能说明

- 场景：移动端驾驶员进行安全学习时，前端在学习完成后调用独立接口扣减已购买的学时套餐
- 扣减顺序：按照学时套餐购买先后顺序依次扣减，先买先用
- 扣减时机：课程学习记录完成后，由前端显式调用扣减接口触发
- 幂等控制：学习记录增加标识字段，已经扣减过的记录不会重复扣减
- 使用记录：每次扣减都会生成学时套餐使用明细

说明：

- 前端需要在学习完成后新增一次“扣减学时套餐”的请求动作
- 学习记录新增/修改接口只负责保存学习状态
- 后端会在独立扣减接口中处理套餐扣减、明细写入、剩余学时更新

## 2. 影响范围

本次主要影响以下接口：

### 2.1 学习记录接口

- `POST /securityManagement/trainingCourseRecord`
- `PUT /securityManagement/trainingCourseRecord`
- `GET /securityManagement/trainingCourseRecord/{id}`
- `GET /securityManagement/trainingCourseRecord/list`
- `POST /securityManagement/trainingCourseRecord/{id}/deductHourPackage`

说明：

- 新增/修改学习记录时，仅保存学习记录本身，不自动扣减学时套餐
- 查询学习记录详情和列表时，返回新增的套餐扣减标识字段
- 前端在确认课程已完成后，再调用独立扣减接口触发扣减

### 2.2 答题提交接口

- `POST /courseAnswer/trainingAnswerRecord/submit`

说明：

- 如果移动端通过“提交随堂练习/提交课程答题”来完成课程学习，后端内部也会更新学习记录
- 答题提交本身不再自动触发学时套餐扣减
- 前端需要在答题完成且学习记录已完成后，再调用扣减接口

## 3. 扣减规则

- 仅在前端显式调用扣减接口，且课程学习记录满足“已完成”时触发扣减
- 同一条课程学习记录只扣减一次
- 已扣减过的记录，通过 `isUseHourPackage` 标识防止重复扣减
- 扣减数量按课程配置的学习时长 `studyDuration` 处理
- 学时套餐从 `hot_hour_purchase_detail` 中按 `id` 升序依次扣减
- 扣减成功后，同时更新：
    - 学时套餐购买明细的 `remainingHours`
    - 学时套餐购买明细的 `usedHours`
    - 学时套餐购买明细的 `lastUseTime`
    - 学时套餐使用明细表 `hot_hour_usage_detail`

## 4. 前端请求参数说明

### 4.1 学习记录保存接口无新增字段

前端调用以下接口时，无需新增任何参数：

- `POST /securityManagement/trainingCourseRecord`
- `PUT /securityManagement/trainingCourseRecord`
- `POST /courseAnswer/trainingAnswerRecord/submit`

特别说明：

- 不需要前端传 `isUseHourPackage`
- 不需要前端传 `hourPackageUsedHours`
- 不需要前端传“套餐ID”“购买记录ID”“扣减顺序”等参数

这些字段不会在保存学习记录时自动扣减，由独立扣减接口处理。

### 4.2 扣减接口

- 地址：`POST /securityManagement/trainingCourseRecord/{id}/deductHourPackage`
- 说明：按学习记录ID显式扣减学时套餐
- 路径参数：
  - `id`：学习记录ID

请求示例：

```http
POST /securityManagement/trainingCourseRecord/9001/deductHourPackage
```

### 4.3 学习记录原有请求示例

```json
{
  "companyId": 1,
  "trainingId": 1001,
  "userId": "20001",
  "userName": "张三",
  "trainingCourseId": 3001,
  "checkStatus": 1,
  "progressRate": 100,
  "learnDurationMin": 45,
  "completeTime": "2026-05-12 10:30:00"
}
```

说明：

- 仍按原有方式提交即可
- 当 `checkStatus=1` 时，表示学习记录已完成；前端应在此后调用独立扣减接口

## 5. 新增返回字段

学习记录详情接口、学习记录列表接口会新增以下字段：

| 字段名                    | 类型     | 说明                      |
|------------------------|--------|-------------------------|
| `isUseHourPackage`     | `Long` | 是否已使用购买课时套餐：`0=否`，`1=是` |
| `hourPackageUsedHours` | `Long` | 本条学习记录已扣减课时数            |

### 5.1 返回示例

```json
{
  "code": 200,
  "data": {
    "id": 9001,
    "companyId": 1,
    "trainingId": 1001,
    "userId": "20001",
    "userName": "张三",
    "trainingCourseId": 3001,
    "checkStatus": 1,
    "progressRate": 100.00,
    "learnDurationMin": 45,
    "completeTime": "2026-05-12 10:30:00",
    "signatureOssId": 8888,
    "isUseHourPackage": 1,
    "hourPackageUsedHours": 45
  },
  "msg": "操作成功"
}
```

## 6. 前端展示建议

### 6.1 学习记录页面

如果页面需要展示本次学习是否已使用套餐，可直接使用：

- `isUseHourPackage=1` 显示“已使用套餐学时”
- `isUseHourPackage=0` 显示“未使用套餐学时”

### 6.2 已扣减学时展示

- 当 `hourPackageUsedHours > 0` 时，可显示“本次已扣减 XX 课时”
- 当 `hourPackageUsedHours = 0` 或为空时，可显示 `-`

### 6.3 前端是否需要防重

- 前端仍建议保留按钮防连点、重复提交控制
- 但最终防重复扣减由后端 `isUseHourPackage` 字段保证

## 7. 失败提示

如果学习完成时需要扣减学时套餐，但当前没有可用套餐，接口可能返回以下错误：

```json
{
  "code": 500,
  "msg": "可用学时套餐不足，请先购买学时套餐",
  "data": null
}
```

前端建议处理方式：

- 直接 toast 提示后端返回的 `msg`
- 引导用户前往学时套餐购买页面
- 不要在前端本地自行计算剩余可用课时

## 8. 联调要点

- 前端联调时重点确认课程完成后会调用独立扣减接口
- 同一课程记录重复调用扣减接口时，不应重复扣减
- 学习记录查询接口应能看到：
    - `isUseHourPackage`
    - `hourPackageUsedHours`
- 若学时套餐余额不足，应正确提示失败信息

## 9. 前端结论

- 前端请求参数：学习记录接口无新增；扣减接口新增 `id` 路径参数
- 前端调用流程：学习完成后新增一次扣减接口调用
- 前端返回处理：新增关注两个字段
    - `isUseHourPackage`
    - `hourPackageUsedHours`
- 前端异常处理：直接展示后端返回的套餐不足提示
