docs(changelog): order-v3 合同/保险镜像状态 NONE→null 前端变更说明 (#3956)
- 受影响接口:GET /v3/admin/order/{id}、GET /v3/admin/order/{id}/contract-insurance、GET /v3/admin/order/group-batch/{groupBatchId}/orders
- 无合同/无保险时 contractStatus/insuranceStatus 由 "NONE" 改为 null
- Issue #3953 / PR #3956
这个提交包含在:
父节点
cee040f814
当前提交
5a6f8675b6
@ -0,0 +1,342 @@
|
|||||||
|
# 合同/保险镜像状态"无记录"时从 `"NONE"` 改为 `null`
|
||||||
|
|
||||||
|
- **变更类型**:修改接口
|
||||||
|
- **端类型**:管理后台
|
||||||
|
- **日期**:2026-06-18
|
||||||
|
- **Issue**:[#3953](https://git.1814.love:8443/wx/HL/issues/3953)
|
||||||
|
- **PR**:[#3956](https://git.1814.love:8443/wx/HL/pulls/3956)
|
||||||
|
- **Commit**:[dc21950a9](https://git.1814.love:8443/wx/HL/commit/dc21950a9)(feature)/ [41cfd5ad8](https://git.1814.love:8443/wx/HL/commit/41cfd5ad8)(merge)
|
||||||
|
- **后端负责人**:腰苏图
|
||||||
|
|
||||||
|
---
|
||||||
|
## ① 接口背景
|
||||||
|
|
||||||
|
order-v3 主表 `order_main` 中有两个镜像状态列:`contract_status`(合同状态)和 `insurance_status`(保险状态)。
|
||||||
|
|
||||||
|
以往在订单**尚无合同**或**尚无保险**时,这两列的值以字符串 `"NONE"` 写入并通过接口返回给前端。此次统一语义:「无记录」状态改为返回 `null`,不再返回字符串 `"NONE"`。
|
||||||
|
|
||||||
|
涉及枚举值(有进展时不变):
|
||||||
|
- 合同:`GENERATING` / `GENERATED` / `SIGNED` / `VOIDED` / `RESIGNING`
|
||||||
|
- 保险:`INSURING` / `INSURED` / `CANCELLED` / `FAILED`
|
||||||
|
|
||||||
|
---
|
||||||
|
## ② 变更清单
|
||||||
|
|
||||||
|
| # | 接口 | 字段路径 | 变更 |
|
||||||
|
|---|------|----------|------|
|
||||||
|
| 1 | `GET /v3/admin/order/{id}` | `main.contractStatus` | 无合同时:`"NONE"` → `null` |
|
||||||
|
| 2 | `GET /v3/admin/order/{id}` | `main.insuranceStatus` | 无保险时:`"NONE"` → `null` |
|
||||||
|
| 3 | `GET /v3/admin/order/{id}/contract-insurance` | `contract.contractStatus` | 无合同时:`"NONE"` → `null` |
|
||||||
|
| 4 | `GET /v3/admin/order/{id}/contract-insurance` | `insurance.insuranceStatus` | 无保险时:`"NONE"` → `null` |
|
||||||
|
| 5 | `GET /v3/admin/order/group-batch/{groupBatchId}/orders` | `[*].contractStatus` | 无合同时:`"NONE"` → `null` |
|
||||||
|
| 6 | `GET /v3/admin/order/group-batch/{groupBatchId}/orders` | `[*].insuranceStatus` | 无保险时:`"NONE"` → `null` |
|
||||||
|
|
||||||
|
> 订单列表 `GET /v3/admin/order/list` 返回的 `OrderListItemRespVO` **不含**这两个字段,不受影响。
|
||||||
|
|
||||||
|
---
|
||||||
|
## ③ 接口详情
|
||||||
|
|
||||||
|
### 接口一:订单详情(9 Tab 聚合)
|
||||||
|
|
||||||
|
| 项 | 值 |
|
||||||
|
|---|---|
|
||||||
|
| 方法 + 路径 | `GET /v3/admin/order/{id}` |
|
||||||
|
| 接口名 | 订单详情(9 Tab 聚合) |
|
||||||
|
| 认证 | 需要 JWT(管理后台 token) |
|
||||||
|
| 幂等性 | 只读,天然幂等 |
|
||||||
|
| 限流 | 无特殊限流 |
|
||||||
|
|
||||||
|
### 接口二:合同保险 Tab
|
||||||
|
|
||||||
|
| 项 | 值 |
|
||||||
|
|---|---|
|
||||||
|
| 方法 + 路径 | `GET /v3/admin/order/{id}/contract-insurance` |
|
||||||
|
| 接口名 | 订单合同保险 Tab |
|
||||||
|
| 认证 | 需要 JWT(管理后台 token) |
|
||||||
|
| 幂等性 | 只读,天然幂等 |
|
||||||
|
| 限流 | 无特殊限流 |
|
||||||
|
|
||||||
|
### 接口三:团期子订单列表
|
||||||
|
|
||||||
|
| 项 | 值 |
|
||||||
|
|---|---|
|
||||||
|
| 方法 + 路径 | `GET /v3/admin/order/group-batch/{groupBatchId}/orders` |
|
||||||
|
| 接口名 | 团期子订单列表 |
|
||||||
|
| 认证 | 需要 JWT(管理后台 token) |
|
||||||
|
| 幂等性 | 只读,天然幂等 |
|
||||||
|
| 限流 | 无特殊限流 |
|
||||||
|
|
||||||
|
---
|
||||||
|
## ④ 接口入参
|
||||||
|
|
||||||
|
三个接口均为路径参数,本次变更不影响入参。
|
||||||
|
|
||||||
|
| 参数 | 位置 | 类型 | 必填 | 说明 |
|
||||||
|
|------|------|------|------|------|
|
||||||
|
| `id` | Path | Long | 是 | 订单 ID(接口一、二) |
|
||||||
|
| `groupBatchId` | Path | Long | 是 | 团期 ID(接口三) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⑤ 出参字段(受影响字段)
|
||||||
|
|
||||||
|
### 接口一 `GET /v3/admin/order/{id}` — `main` 节点
|
||||||
|
|
||||||
|
| 字段路径 | 类型 | 说明 |
|
||||||
|
|----------|------|------|
|
||||||
|
| `main.contractStatus` | `String \| null` | 合同状态。**无合同时返回 `null`**(原来返回 `"NONE"`);有合同时为枚举值,见 § ⑥ |
|
||||||
|
| `main.insuranceStatus` | `String \| null` | 保险状态。**无保险时返回 `null`**(原来返回 `"NONE"`);有保险时为枚举值,见 § ⑥ |
|
||||||
|
|
||||||
|
### 接口二 `GET /v3/admin/order/{id}/contract-insurance`
|
||||||
|
|
||||||
|
| 字段路径 | 类型 | 说明 |
|
||||||
|
|----------|------|------|
|
||||||
|
| `contract.contractStatus` | `String \| null` | 合同状态。**无合同时返回 `null`** |
|
||||||
|
| `insurance.insuranceStatus` | `String \| null` | 保险状态。**无保险时返回 `null`** |
|
||||||
|
|
||||||
|
其余字段(`contractSignedAt`、`contractFileUrl`、`events`、`insurancePolicyNo`、`insurancePremium` 等)在无合同/无保险时仍返回 `null`,无变化。
|
||||||
|
|
||||||
|
### 接口三 `GET /v3/admin/order/group-batch/{groupBatchId}/orders` — 列表项
|
||||||
|
|
||||||
|
| 字段路径 | 类型 | 说明 |
|
||||||
|
|----------|------|------|
|
||||||
|
| `[*].contractStatus` | `String \| null` | 合同状态。**无合同时返回 `null`** |
|
||||||
|
| `[*].insuranceStatus` | `String \| null` | 保险状态。**无保险时返回 `null`** |
|
||||||
|
|
||||||
|
---
|
||||||
|
## ⑥ 枚举 / 数据字典
|
||||||
|
|
||||||
|
### contractStatus 合同状态
|
||||||
|
|
||||||
|
| 枚举值 | 含义 | 备注 |
|
||||||
|
|--------|------|------|
|
||||||
|
| `null` | 无合同记录 | **本次新值**(原来是 `"NONE"`) |
|
||||||
|
| `GENERATING` | 合同生成中 | |
|
||||||
|
| `GENERATED` | 合同已生成(待签署) | |
|
||||||
|
| `SIGNED` | 已签署 | |
|
||||||
|
| `VOIDED` | 已作废 | |
|
||||||
|
| `RESIGNING` | 重新签署中 | |
|
||||||
|
|
||||||
|
### insuranceStatus 保险状态
|
||||||
|
|
||||||
|
| 枚举值 | 含义 | 备注 |
|
||||||
|
|--------|------|------|
|
||||||
|
| `null` | 无保险记录 | **本次新值**(原来是 `"NONE"`) |
|
||||||
|
| `INSURING` | 出单中 | |
|
||||||
|
| `INSURED` | 已投保 | |
|
||||||
|
| `CANCELLED` | 已取消 | |
|
||||||
|
| `FAILED` | 出单失败 | |
|
||||||
|
|
||||||
|
---
|
||||||
|
## ⑦ 错误码
|
||||||
|
|
||||||
|
本次变更不新增错误码。以下为接口既有错误码:
|
||||||
|
|
||||||
|
| 错误码 | HTTP 状态 | 说明 |
|
||||||
|
|--------|-----------|------|
|
||||||
|
| `587000` | 400 | 订单不存在 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⑧ 示例
|
||||||
|
|
||||||
|
### 8.1 典型成功——订单已签约并已投保
|
||||||
|
|
||||||
|
**请求**
|
||||||
|
```http
|
||||||
|
GET /v3/admin/order/2000000001
|
||||||
|
Authorization: Bearer <token>
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应(main 节点节选)**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"data": {
|
||||||
|
"main": {
|
||||||
|
"id": "2000000001",
|
||||||
|
"orderNo": "HL20260601001",
|
||||||
|
"orderStatus": "ON_TRIP",
|
||||||
|
"contractStatus": "SIGNED",
|
||||||
|
"insuranceStatus": "INSURED",
|
||||||
|
"refundStatus": null,
|
||||||
|
"hasRefund": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**合同保险 Tab(`GET /v3/admin/order/2000000001/contract-insurance`)**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"data": {
|
||||||
|
"contract": {
|
||||||
|
"contractStatus": "SIGNED",
|
||||||
|
"contractSignedAt": "2026-06-01T10:30:00",
|
||||||
|
"contractFileUrl": "https://oss.hulalv.com/contract/HL20260601001.pdf",
|
||||||
|
"events": [
|
||||||
|
{ "eventType": "GENERATE", "occurredAt": "2026-06-01T10:00:00" },
|
||||||
|
{ "eventType": "SIGN", "occurredAt": "2026-06-01T10:30:00" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"insurance": {
|
||||||
|
"insuranceStatus": "INSURED",
|
||||||
|
"insurancePolicyNo": "PICC2026060100123",
|
||||||
|
"insurancePremium": 88.00,
|
||||||
|
"events": [
|
||||||
|
{ "eventType": "ISSUE", "occurredAt": "2026-06-01T10:35:00" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
### 8.2 边界情况——订单刚创建,尚无合同和保险
|
||||||
|
|
||||||
|
**响应(main 节点节选)**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"data": {
|
||||||
|
"main": {
|
||||||
|
"id": "2000000002",
|
||||||
|
"orderNo": "HL20260602001",
|
||||||
|
"orderStatus": "CUSTOMIZING",
|
||||||
|
"contractStatus": null,
|
||||||
|
"insuranceStatus": null,
|
||||||
|
"hasRefund": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**合同保险 Tab**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"data": {
|
||||||
|
"contract": {
|
||||||
|
"contractStatus": null,
|
||||||
|
"contractSignedAt": null,
|
||||||
|
"contractFileUrl": null,
|
||||||
|
"events": []
|
||||||
|
},
|
||||||
|
"insurance": {
|
||||||
|
"insuranceStatus": null,
|
||||||
|
"insurancePolicyNo": null,
|
||||||
|
"insurancePremium": null,
|
||||||
|
"events": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**团期子订单列表(`GET /v3/admin/order/group-batch/3000000001/orders`,无合同无保险的子订单项节选)**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"orderId": "2000000002",
|
||||||
|
"orderNo": "HL20260602001",
|
||||||
|
"contractStatus": null,
|
||||||
|
"insuranceStatus": null,
|
||||||
|
"payStatus": "UNPAID"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.3 业务失败——订单 ID 不存在
|
||||||
|
|
||||||
|
**请求**
|
||||||
|
```http
|
||||||
|
GET /v3/admin/order/9999999999
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 587000,
|
||||||
|
"msg": "订单不存在"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
## ⑨ 业务边界
|
||||||
|
|
||||||
|
**适用**:
|
||||||
|
- 创建后尚未触发签约的订单:`contractStatus` 返回 `null`
|
||||||
|
- 创建后尚未触发投保的订单:`insuranceStatus` 返回 `null`
|
||||||
|
- 合同被作废后重新签署流程未开始的中间态仍走枚举值(`VOIDED` → `RESIGNING`),不返回 `null`
|
||||||
|
|
||||||
|
**不适用(不返回 null)**:
|
||||||
|
- 合同/保险流程一旦触发(任意枚举值),即使中途失败(`FAILED`)也返回枚举值而非 `null`
|
||||||
|
|
||||||
|
**特殊边界**:
|
||||||
|
- 若历史订单数据库列值为 `"NONE"`(迁移前旧数据),后端读取时统一转换为 `null` 再返回,前端不会收到字符串 `"NONE"`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⑩ 修改前后对比
|
||||||
|
|
||||||
|
### 字段级对比
|
||||||
|
|
||||||
|
| 字段 | 无合同/无保险时修改前 | 无合同/无保险时修改后 |
|
||||||
|
|------|---------------------|---------------------|
|
||||||
|
| `contractStatus` | `"NONE"` | `null` |
|
||||||
|
| `insuranceStatus` | `"NONE"` | `null` |
|
||||||
|
|
||||||
|
三个接口均适用此对比。有合同/有保险时枚举值**不变**。
|
||||||
|
|
||||||
|
### 行为级对比
|
||||||
|
|
||||||
|
| 场景 | 修改前 | 修改后 |
|
||||||
|
|------|--------|--------|
|
||||||
|
| 新建订单查详情 | `contractStatus: "NONE"` | `contractStatus: null` |
|
||||||
|
| 查合同保险 Tab | `contract.contractStatus: "NONE"` | `contract.contractStatus: null` |
|
||||||
|
| 团期子订单列表 | `contractStatus: "NONE"` | `contractStatus: null` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⑪ 影响评估 / 回滚
|
||||||
|
|
||||||
|
### 破坏兼容
|
||||||
|
|
||||||
|
**破坏性变更**。若前端代码以 `contractStatus === "NONE"` 或 `insuranceStatus === "NONE"` 判断「无状态」,**需改为 `contractStatus == null`**(或 `!contractStatus`),否则判断会失效。
|
||||||
|
|
||||||
|
### 前端同步要求
|
||||||
|
|
||||||
|
前端需在本次后端上线前(或同时)完成如下改动:
|
||||||
|
|
||||||
|
1. 所有判断 `contractStatus === "NONE"` 的地方改为 `contractStatus == null`(或 `!contractStatus`)
|
||||||
|
2. 所有判断 `insuranceStatus === "NONE"` 的地方改为 `insuranceStatus == null`(或 `!insuranceStatus`)
|
||||||
|
3. 合同 Tab 徽标逻辑:判断是否显示「无合同」状态从 `=== "NONE"` 改为 `=== null`
|
||||||
|
4. 保险 Tab 徽标逻辑:同上
|
||||||
|
|
||||||
|
### 回滚方案
|
||||||
|
|
||||||
|
后端可在镜像写入层回退 `null → "NONE"` 兜底逻辑,重新发布即生效,无需 DDL。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⑫ 注意事项
|
||||||
|
|
||||||
|
1. **三个接口同时生效**:`GET /v3/admin/order/{id}`、`GET /v3/admin/order/{id}/contract-insurance`、`GET /v3/admin/order/group-batch/{groupBatchId}/orders` 同批上线,需一次性适配,不存在分步过渡。
|
||||||
|
2. **历史数据已处理**:后端上线时同步处理库中存量 `"NONE"` 值,前端永远不会收到字符串 `"NONE"`,无需做兼容两个值的过渡逻辑。
|
||||||
|
3. **列表接口不受影响**:`GET /v3/admin/order/list` 返回的列表项 VO 不含 `contractStatus` / `insuranceStatus`,无需处理。
|
||||||
|
4. **枚举值语义不变**:除 `"NONE"` 变为 `null` 外,其余枚举值含义和拼写完全不变。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⑬ 关联 / 联系人
|
||||||
|
|
||||||
|
| 项 | 链接 |
|
||||||
|
|---|------|
|
||||||
|
| Issue | [#3953 合同/保险镜像状态统一 NONE→null](https://git.1814.love:8443/wx/HL/issues/3953) |
|
||||||
|
| PR | [#3956 refactor(order-v3): 合同/保险镜像状态统一 NONE→null](https://git.1814.love:8443/wx/HL/pulls/3956) |
|
||||||
|
| Feature Commit | [dc21950a9](https://git.1814.love:8443/wx/HL/commit/dc21950a9) |
|
||||||
|
| Merge Commit | [41cfd5ad8](https://git.1814.love:8443/wx/HL/commit/41cfd5ad8) |
|
||||||
|
| 后端负责人 | 腰苏图(yaosutu) |
|
||||||
正在加载...
x
在新工单中引用
屏蔽一个用户