docs: add fleet insurance API handoff

这个提交包含在:
API Changelog Bot 2026-07-06 09:32:59 +08:00
父节点 68627376f1
当前提交 31e2bc4fec
共有 2 个文件被更改,包括 322 次插入4 次删除

查看文件

@ -22,7 +22,7 @@
| 场景 | 前端处理 | | 场景 | 前端处理 |
|------|----------| |------|----------|
| 当前角色 | 车务菜单只能由 `VEHICLE_MANAGER``SUPER_ADMIN` 访问;`wx/CUSTOMIZER` 访问 `/admin/fleet/**` 返回 `403`,提示切换车务角色。 | | 当前角色 | 车务菜单只能由 `VEHICLE_MANAGER``SUPER_ADMIN` 访问;`wx/CUSTOMIZER` 访问 `/admin/fleet/**` 返回 `403`,提示切换车务角色。 |
| 司机结算方式 | 司机新增/编辑/导入使用字典 `driver_settlement_mode``direct`=直接结算,`fleet_leader`=车队长结算。 | | 司机结算方式 | 司机新增/编辑/导入使用字典 `driver_settlement_mode``direct`=直接结算,`captain`=车队长结算。 |
| 待审核详情 ID | `GET /admin/fleet/drivers/pending/{pendingId}` 响应主键字段是 `id`,不是 `pendingId`;路径变量仍叫 `pendingId`。 | | 待审核详情 ID | `GET /admin/fleet/drivers/pending/{pendingId}` 响应主键字段是 `id`,不是 `pendingId`;路径变量仍叫 `pendingId`。 |
| 派单重复确认 | `POST /admin/fleet/assignments/{assignmentId}/confirm` 只允许 `holding -> assigned`;非 `holding` 返回 `605020`。 | | 派单重复确认 | `POST /admin/fleet/assignments/{assignmentId}/confirm` 只允许 `holding -> assigned`;非 `holding` 返回 `605020`。 |
| 取消重复操作 | 终态派单再次取消也返回 `605020`。 | | 取消重复操作 | 终态派单再次取消也返回 `605020`。 |
@ -737,7 +737,7 @@ PUT /admin/fleet/drivers/{driverId}
"preferredTypeKey": "suv", "preferredTypeKey": "suv",
"preferredModel": "SUV", "preferredModel": "SUV",
"vehicleSource": "company", "vehicleSource": "company",
"settlementMode": "fleet_leader", "settlementMode": "captain",
"license": { "license": {
"no": "L6966520260705", "no": "L6966520260705",
"type": "C1", "type": "C1",
@ -762,7 +762,7 @@ PUT /admin/fleet/drivers/{driverId}
"phone": "199****9999", "phone": "199****9999",
"driverStatus": "idle", "driverStatus": "idle",
"season": "active", "season": "active",
"settlementMode": "fleet_leader", "settlementMode": "captain",
"license": { "no": "L6966520260705", "type": "C1", "expire": "2035-12-31" }, "license": { "no": "L6966520260705", "type": "C1", "expire": "2035-12-31" },
"insurance": { "type": "none" }, "insurance": { "type": "none" },
"tags": ["API_TEST_FLEET_FULL"] "tags": ["API_TEST_FLEET_FULL"]
@ -775,7 +775,7 @@ PUT /admin/fleet/drivers/{driverId}
| 值 | 展示 | | 值 | 展示 |
|----|------| |----|------|
| `direct` | 直接结算 | | `direct` | 直接结算 |
| `fleet_leader` | 车队长结算 | | `captain` | 车队长结算 |
非法值响应: 非法值响应:

查看文件

@ -0,0 +1,318 @@
# 【前端对接·管理后台】车务司机险自动投退保闭环与保险菜单契约
> **Issue**: [wx/HL#4760](https://git.1814.love:8443/wx/HL/issues/4760)
> **服务**: hl-fleet-service + hl-order-service-v3 insurance Feign
> **日期**: 2026-07-06
> **影响范围**: 车务管理 / 保险菜单 / 派单确认 / 取消 / 提前完结 / 车队对账
---
## 1. 结论
- 车务保险菜单只展示司机险任务,不展示游客保险、订单保险、客户退款保险明细。
- `insurance.type=perTrip` 的司机在派单确认进入 `assigned` 后,后端按 `driverId + serviceDate` 自动一日一保投保。
- 同一司机同一服务日只能有一份司机险;前后订单相接同日不重复买。
- 取消/提前完结后,只退该司机该服务日已无其它 active 派单占用的单日险。
- 司机险只进入车队/司机成本,不进入客户退款、订单收款、游客保险或合同保险。
- 自动投退保失败不阻断派单主流程,但必须进入车务保险任务待处理。
---
## 2. 角色与菜单
| 角色 | 行为 |
|------|------|
| `admin` / 车务角色 | 可访问 `/admin/fleet/insurance/**`,可查看任务、重试、标记线下完成、忽略 |
| `wx` / 定制师 | 不应展示车务保险菜单;若访问 `/admin/fleet/**` 按角色守卫返回 `403` |
前端不要复用订单保险页面的数据源。车务保险菜单只调本文件接口。
---
## 3. 接口一:司机险任务/流水分页
```http
GET /admin/fleet/insurance/tasks
```
### 3.1 Query 参数
| 参数 | 类型 | 必填 | 示例 | 说明 |
|------|------|------|------|------|
| `page` | number | 否 | `1` | 页码 |
| `pageSize` | number | 否 | `20` | 每页条数 |
| `pendingOnly` | boolean | 否 | `true` | `true` 只查 `PENDING/PROCESSING`;不传查全部 |
| `taskType` | string | 否 | `PURCHASE` | `PURCHASE` 投保 / `REFUND` 退保 |
| `taskStatus` | string | 否 | `PENDING` | `PENDING/PROCESSING/SUCCESS/RESOLVED/IGNORED` |
| `driverId` | string | 否 | `188800000000000001` | 司机 ID |
| `assignmentId` | string | 否 | `194000000000000001` | 派单 ID |
| `orderId` | string | 否 | `193900000000000001` | 订单 ID |
| `serviceDateFrom` | string | 否 | `2026-07-01` | 服务日起,`yyyy-MM-dd` |
| `serviceDateTo` | string | 否 | `2026-07-31` | 服务日止,不能早于起始日 |
### 3.2 请求例子
```http
GET /admin/fleet/insurance/tasks?pendingOnly=true&taskType=PURCHASE&serviceDateFrom=2026-07-01&serviceDateTo=2026-07-31&page=1&pageSize=20
Authorization: Bearer <admin-token>
```
### 3.3 响应例子
```json
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"page": 1,
"pageSize": 20,
"total": 2,
"records": [
{
"taskId": "194100000000000001",
"bizKey": "PURCHASE:188800000000000001:2026-07-06",
"taskType": "PURCHASE",
"taskTypeLabel": "投保",
"taskStatus": "PENDING",
"taskStatusLabel": "待处理",
"driverId": "188800000000000001",
"driverName": "王师傅",
"assignmentId": "194000000000000001",
"orderId": "193900000000000001",
"orderNo": "HL20260705001",
"insuranceOrderId": null,
"policyNo": "",
"serviceDate": "2026-07-06",
"coverageStartDate": "2026-07-06",
"coverageEndDate": "2026-07-06",
"premiumAmount": "0.00",
"source": "BAOYOU",
"sourceLabel": "保游网",
"errorCode": "540007",
"errorMessage": "保险计划没有匹配该保障天数的费率",
"suggestedAction": "保险计划没有匹配该保障天数的费率,请维护费率后重试",
"retryCount": 1,
"proofUrls": [],
"handledBy": null,
"handledAt": null,
"handleRemark": "",
"createTime": "2026-07-06T09:10:00",
"updateTime": "2026-07-06T09:12:00"
},
{
"taskId": "194100000000000002",
"bizKey": "PURCHASE:188800000000000001:2026-07-07",
"taskType": "PURCHASE",
"taskTypeLabel": "投保",
"taskStatus": "SUCCESS",
"taskStatusLabel": "已成功",
"driverId": "188800000000000001",
"driverName": "王师傅",
"assignmentId": "194000000000000002",
"orderId": "193900000000000002",
"orderNo": "HL20260705002",
"insuranceOrderId": "194200000000000001",
"policyNo": "BY-20260707001",
"serviceDate": "2026-07-07",
"coverageStartDate": "2026-07-07",
"coverageEndDate": "2026-07-07",
"premiumAmount": "18.00",
"source": "BAOYOU",
"sourceLabel": "保游网",
"errorCode": "",
"errorMessage": "",
"suggestedAction": "",
"retryCount": 0,
"proofUrls": [],
"handledBy": "0",
"handledAt": "2026-07-06T09:10:05",
"handleRemark": "",
"createTime": "2026-07-06T09:10:05",
"updateTime": "2026-07-06T09:10:05"
}
]
}
}
```
### 3.4 字段说明
| 字段 | 说明 |
|------|------|
| `bizKey` | 后端幂等键,前端只展示/排查,不要拼业务逻辑 |
| `taskType` | `PURCHASE` 投保,`REFUND` 退保 |
| `taskStatus` | `PENDING` 待处理,`PROCESSING` 处理中,`SUCCESS` 线上成功,`RESOLVED` 线下解决,`IGNORED` 已忽略 |
| `premiumAmount` | 真实保费/退回金额,字符串;前端不要转 number 做精度运算 |
| `source` | `BAOYOU` 保游网,`OFFLINE` 线下处理 |
| `proofUrls` | 线下处理凭证 URL;线上成功通常为空数组 |
| `handledBy=0` | 后端自动成功流水,不是人工账号 |
---
## 4. 接口二:重试任务
```http
POST /admin/fleet/insurance/tasks/{taskId}/retry
```
### 4.1 请求例子
```http
POST /admin/fleet/insurance/tasks/194100000000000001/retry
Authorization: Bearer <admin-token>
```
无 body。
### 4.2 响应例子
```json
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"taskId": "194100000000000001",
"taskStatus": "SUCCESS",
"taskStatusLabel": "已成功"
}
}
```
### 4.3 前端处理
- 点击后按钮加 loading,接口有幂等保护,不要连续提交。
- 成功后刷新分页列表。
- 如果仍返回 `PENDING`,说明重试失败但已更新错误信息和 `retryCount`,前端展示最新 `errorMessage/suggestedAction`
---
## 5. 接口三:标记线下完成
```http
POST /admin/fleet/insurance/tasks/{taskId}/offline-done
```
### 5.1 请求参数
| 字段 | 类型 | 必填 | 示例 | 说明 |
|------|------|------|------|------|
| `policyNo` | string | 是 | `OFFLINE-20260701001` | 真实保单号 / 退保凭证号 |
| `premiumAmount` | decimal string | 是 | `"18.00"` | 真实保费金额;退保填实际退回/冲减金额 |
| `proofUrls` | string[] | 是 | `["https://...jpg"]` | 至少 1 个凭证 URL |
| `remark` | string | 否 | `保司后台线下补投` | 处理备注 |
### 5.2 请求例子
```json
{
"policyNo": "OFFLINE-20260701001",
"premiumAmount": "18.00",
"proofUrls": [
"https://oss.test.1814.love/fleet/insurance/OFFLINE-20260701001.jpg"
],
"remark": "保司后台线下补投,截图已上传"
}
```
### 5.3 响应例子
```json
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"taskId": "194100000000000001",
"taskStatus": "RESOLVED",
"taskStatusLabel": "已解决"
}
}
```
### 5.4 校验
- `policyNo` 为空:参数校验失败。
- `premiumAmount` 为空或负数:参数校验失败。
- `proofUrls` 为空数组或不传:返回 `100001` / 参数校验失败。
---
## 6. 接口四:忽略任务
```http
POST /admin/fleet/insurance/tasks/{taskId}/ignore
```
### 6.1 请求例子
```json
{
"remark": "重复人工记录,保单已由另一任务处理"
}
```
### 6.2 响应例子
```json
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"taskId": "194100000000000001",
"taskStatus": "IGNORED",
"taskStatusLabel": "已忽略"
}
}
```
---
## 7. 自动触发场景
| 场景 | 后端行为 | 前端关注 |
|------|----------|----------|
| 派单确认 `holding -> assigned` | perTrip 司机按服务日逐日投保 | 确认派单成功不代表保险一定成功,需看保险任务 |
| 已有线上保单覆盖同司机同日 | 不重复购买,写 `SUCCESS` 幂等流水 | 不要提示重复投保 |
| 已有手工/年保覆盖同司机同日 | 不买按单险,写 `PENDING` 提醒核对 | 展示 `suggestedAction` |
| 派单取消 | 只退该司机该服务日无其它 active 派单占用的单日险 | 同日仍有其它订单时不会退 |
| 提前完结 | 退新 `endDate` 之后不再使用的单日险 | 定时完结通常无动作 |
| 撤销取消恢复为 assigned | 如果之前已退险,恢复后补买 | 前端刷新任务列表 |
---
## 8. 前端不要做的事
- 不要用大交通日期推导司机险保障日期;司机险保障日期以派单服务日为准。
- 不要把司机险退保结果参与客户退款计算。
- 不要把 `premiumAmount` 转成 JS number 再计算。
- 不要在前端拼重试业务参数,重试只传 `taskId`
- 不要在车务保险菜单展示订单游客险。
- 不要把 `SUCCESS` 自动流水当成待办提示;待办只看 `PENDING/PROCESSING`
---
## 9. 错误码提示
| code | 场景 | 前端文案建议 |
|------|------|--------------|
| `100001` | 参数非法、任务缺上下文、服务日区间反了 | 展示后端 message |
| `100502` | 幂等保护,重复提交 | “正在处理,请勿重复提交” |
| `540007` | 保险计划缺费率 | “请维护保险计划费率后重试” |
| `540032` | 同司机服务日已有保单覆盖 | “已有保单覆盖,请核对后处理” |
| `605601` | 保险服务不可用 | “保险服务暂不可用,请稍后重试或线下处理” |
---
## 10. 测试要求
前端联调不要只测接口 200。至少覆盖
- 新建订单 -> 补出行人 -> 补大交通 -> 提用车需求 -> 车务派单确认 -> 保险任务生成。
- 同一司机同一服务日多订单,不重复买保险。
- 取消派单时,同司机同日还有其它 active 派单则不退保。
- 投保失败后重试成功。
- 线下完成必须上传凭证。
- 定制师角色不可见车务保险菜单。