docs(changelog): #8684 预支相关 8 个接口出参新增 canRevoke(修改接口·管理后台)
changelog-filename-gate / validate (push) Failing after 2s
changelog-filename-gate / validate (push) Failing after 2s
Refs wx/HL#8684 · PR #8723 · merge 806058c66
这个提交包含在:
@@ -0,0 +1,834 @@
|
||||
---
|
||||
schema: "hl-changelog/v2"
|
||||
ticket: "8684"
|
||||
title: "预支相关 8 个接口出参新增 canRevoke:当前操作人点「撤回」能否成功,与撤回接口共用同一个判定"
|
||||
consumer: "admin"
|
||||
author: "jw(GIT)"
|
||||
change_type: "修改接口"
|
||||
backend_status: "deployed"
|
||||
gateway_status: "verified"
|
||||
frontend_status: "pending"
|
||||
frontend_owner: ""
|
||||
frontend_ref: ""
|
||||
target_release: ""
|
||||
verified_at: ""
|
||||
status_note: "已合并 dev-v3(806058c66)并部署 TEST,自签低权限 token 经网关实测:三个列表逐角色取值、联表 created_by 探针、开关关闭→还原往返(md5 逐字节还原,渲染期间拒绝日志零新增)、按 canRevoke 抽样真实撤回。前端待改两处撤回按钮:订单详情预支弹窗 AdvanceModal.vue 与团期财务页签 FinanceTab.vue 的 v-if 改为 a.canRevoke;审批中心本来没有撤回按钮。"
|
||||
updated_at: "2026-10-02"
|
||||
base: "dev-v3"
|
||||
---
|
||||
|
||||
# order-v3: 预支列表出参新增 canRevoke
|
||||
|
||||
**服务**: hl-order-service-v3
|
||||
**PR**: `#8723`(已合入 `dev-v3`,合并提交 `806058c66`)
|
||||
**Issue**: #8684
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 关键变化
|
||||
|
||||
🟢 **8 个接口的出参新增一个字段 `canRevoke`(Boolean)**:当前操作人现在点「撤回」能不能成功。其余入参、出参、判权、错误码全部不变。
|
||||
|
||||
🔴 **同一行,不同人看到的值不同。** 不要缓存后跨账号复用,也不要拿它当这笔预支本身的属性。
|
||||
|
||||
🟢 **前端只需把撤回按钮的显示条件改成 `a.canRevoke`**,不用自己判断角色、申请人和开关。
|
||||
|
||||
---
|
||||
|
||||
## 一、背景
|
||||
|
||||
#8517 之后,撤回待审批预支(`DELETE /v3/admin/order/advance/:advanceId`)只放行申请人本人和超管、管理员,其余返回 `585009`。但列表只返回申请人姓名,没有申请人账号 ID,也没有「能不能撤」的标记,前端只能按「待审批」显示撤回按钮:非申请人也能看到,点了才提示 `585009`。
|
||||
|
||||
本单在出参里补 `canRevoke`,由后端按撤回接口的同一套规则算好。撤回接口本身的判权不变。
|
||||
|
||||
---
|
||||
|
||||
## 二、变更接口清单
|
||||
|
||||
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|
||||
|---|------|------|------|----------|------|
|
||||
| 1 | 本单预支列表 | GET | `/v3/admin/order/:orderId/advances` | 修改 | `records[]` 新增 `canRevoke` |
|
||||
| 2 | 预支审批列表 | GET | `/v3/admin/order/advance-approvals/page` | 修改 | `records[]` 新增 `canRevoke` |
|
||||
| 3 | 团期预支记录(财务页签) | GET | `/v3/admin/order/group-batch/:groupBatchId/advances` | 修改 | 每行新增 `canRevoke` |
|
||||
| 4 | 发起订单级预支 | POST | `/v3/admin/order/:orderId/advance` | 修改 | 返回体新增 `canRevoke` |
|
||||
| 5 | 预支审批通过 | PUT | `/v3/admin/order/advance/:advanceId/approve` | 修改 | 返回体新增 `canRevoke`(恒 `false`) |
|
||||
| 6 | 预支审批驳回 | PUT | `/v3/admin/order/advance/:advanceId/reject` | 修改 | 返回体新增 `canRevoke`(恒 `false`) |
|
||||
| 7 | 发起团期级预支 | POST | `/v3/admin/order/group-batch/:groupBatchId/advance` | 修改 | 返回体新增 `canRevoke` |
|
||||
| 8 | 核单汇总快照 | GET | `/v3/admin/order/:orderId/settlement/summary` | 修改 | `advanceSummary.records[]` 新增 `canRevoke`(只含已通过,恒 `false`) |
|
||||
|
||||
---
|
||||
|
||||
## 三、接口详情
|
||||
|
||||
**`canRevoke` 取值规则**(8 个接口相同,按顺序判,命中即返回):
|
||||
|
||||
| # | 条件 | 取值 |
|
||||
|---|---|---|
|
||||
| 1 | 这笔预支不是待审批(`status ≠ SUBMITTED`) | `false` |
|
||||
| 2 | 没有请求上下文(定时任务、消息消费等) | `false` |
|
||||
| 3 | 当前角色是团期管理员 `GROUP_BATCH_MANAGER` | `false`(撤回接口先返回 `581008`,不受开关影响) |
|
||||
| 4 | 当前角色是 `SUPER_ADMIN` / `ADMIN` | `true` |
|
||||
| 5 | 当前账号就是申请人(创建人账号 ID 相等) | `true` |
|
||||
| 6 | 其余:开关 `advance.acl.enforce.role-guard` 为 `true`(默认) | `false` |
|
||||
| 6' | 其余:开关已关闭 | `true`(撤回接口回到 #8517 之前的行为) |
|
||||
|
||||
创建人账号 ID 为空的存量行,只有第 4 条能得到 `true`。
|
||||
|
||||
### 1. 本单预支列表 `GET /v3/admin/order/:orderId/advances`
|
||||
|
||||
**VO**: `PageParam` → `Result<PageResult<OrderAdvanceRespVO>>`
|
||||
|
||||
#### 使用场景
|
||||
|
||||
订单详情的「预支」弹窗。前端据 `canRevoke` 决定每一行显不显示「撤回」按钮。
|
||||
|
||||
#### 入参字段表
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|------|------|------|------|------|------|
|
||||
| orderId | Path | Long | ✅ | 订单 ID | **不变** |
|
||||
| page | Query | Integer | ❌ | ≥1 | **不变** |
|
||||
| pageSize | Query | Integer | ❌ | ≥1 | **不变** |
|
||||
|
||||
#### 出参字段表
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| records[].canRevoke | Boolean | 🆕 当前操作人点撤回能否成功,规则见上表 |
|
||||
| 其余字段 | — | **不变**(`id` / `status` / `createdByName` 等) |
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```http
|
||||
GET /v3/admin/order/2100743225424621570/advances?page=1&pageSize=20 HTTP/1.1
|
||||
Authorization: Bearer <本单定制师 token>
|
||||
```
|
||||
|
||||
#### 响应示例
|
||||
|
||||
本单定制师看:自己申请的待审批为 `true`,管理员申请的待审批为 `false`,已通过的为 `false`。
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"records": [
|
||||
{
|
||||
"id": "2105886435083206657",
|
||||
"orderId": "2100743225424621570",
|
||||
"teamNo": "26-8707",
|
||||
"payeeName": "刘大山",
|
||||
"payeeRole": "LEADER",
|
||||
"payeeRoleText": "导游",
|
||||
"advanceType": "TICKET",
|
||||
"amount": 180.0,
|
||||
"purpose": "呼伦贝尔大草原景区门票代垫",
|
||||
"status": "SUBMITTED",
|
||||
"statusText": "待审批",
|
||||
"createdByName": "admin",
|
||||
"canRevoke": true
|
||||
},
|
||||
{
|
||||
"id": "2105886437624999938",
|
||||
"orderId": "2100743225424621570",
|
||||
"teamNo": "26-8707",
|
||||
"payeeName": "刘大山",
|
||||
"advanceType": "CATERING",
|
||||
"amount": 120.0,
|
||||
"purpose": "额尔古纳湿地午餐代垫",
|
||||
"status": "SUBMITTED",
|
||||
"statusText": "待审批",
|
||||
"createdByName": "jw",
|
||||
"canRevoke": false
|
||||
}
|
||||
],
|
||||
"total": 2,
|
||||
"page": 1,
|
||||
"pageSize": 20
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
无预支时 `records` 为空数组(不变)。开关 `advance.acl.enforce.role-guard` 关闭时,非团期管理员看待审批行都为 `true`。
|
||||
|
||||
#### 错误响应
|
||||
|
||||
判权不变:非本单定制师、财务等无权角色仍返回 `581008`。
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 581008,
|
||||
"message": "无权查看此订单",
|
||||
"data": null,
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- 每行单独计算,同一页里可以有 `true` 也有 `false`。
|
||||
- 车务管理员能看这个列表,但看所有行都是 `false`。
|
||||
|
||||
---
|
||||
|
||||
### 2. 预支审批列表 `GET /v3/admin/order/advance-approvals/page`
|
||||
|
||||
**VO**: `AdvanceApprovalPageReqVO` → `Result<PageResult<AdvanceApprovalPageItemRespVO>>`
|
||||
|
||||
#### 使用场景
|
||||
|
||||
「财务管理 → 预支审批」列表。页面目前没有撤回按钮,字段供后续使用。只有超管、管理员、财务能进(不变)。
|
||||
|
||||
#### 入参字段表
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|------|------|------|------|------|------|
|
||||
| status | Query | String | ❌ | `SUBMITTED` / `APPROVED` / `REJECTED` / `PAID` | **不变** |
|
||||
| page | Query | Integer | ❌ | ≥1 | **不变** |
|
||||
| pageSize | Query | Integer | ❌ | ≥1 | **不变** |
|
||||
| 其余筛选项 | Query | — | ❌ | — | **不变** |
|
||||
|
||||
#### 出参字段表
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| records[].canRevoke | Boolean | 🆕 规则见上表;财务看别人申请的为 `false` |
|
||||
| 其余字段 | — | **不变** |
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```http
|
||||
GET /v3/admin/order/advance-approvals/page?status=SUBMITTED&page=1&pageSize=20 HTTP/1.1
|
||||
Authorization: Bearer <财务 token>
|
||||
```
|
||||
|
||||
#### 响应示例
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"records": [
|
||||
{
|
||||
"id": "2105886435083206657",
|
||||
"orderId": "2100743225424621570",
|
||||
"orderNo": "HL20260918082629372",
|
||||
"teamNo": "26-8707",
|
||||
"scope": "ORDER",
|
||||
"amount": 180.0,
|
||||
"status": "SUBMITTED",
|
||||
"createdByName": "admin",
|
||||
"canRevoke": false
|
||||
}
|
||||
],
|
||||
"total": 1,
|
||||
"page": 1,
|
||||
"pageSize": 20
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
无数据时 `records` 为空数组(不变)。开关关闭时财务看待审批行都为 `true`。
|
||||
|
||||
#### 错误响应
|
||||
|
||||
判权不变:非超管 / 管理员 / 财务返回 `585008`。
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 585008,
|
||||
"message": "仅财务或管理员可查看预支审批、审批或驳回预支",
|
||||
"data": null,
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- 本接口多查了一列申请人账号 ID 用于计算,**不出参**。
|
||||
- 团期级行(`scope=GROUP_BATCH`)同样按规则计算。
|
||||
|
||||
---
|
||||
|
||||
### 3. 团期预支记录(财务页签) `GET /v3/admin/order/group-batch/:groupBatchId/advances`
|
||||
|
||||
**VO**: `List<GroupBatchAdvanceItemVO>`(继承 `OrderAdvanceRespVO`)
|
||||
|
||||
#### 使用场景
|
||||
|
||||
团期详情「财务」页签的预支记录。前端据 `canRevoke` 决定显不显示「撤回」。
|
||||
|
||||
#### 入参字段表
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|------|------|------|------|------|------|
|
||||
| groupBatchId | Path | Long | ✅ | 团期 ID | **不变** |
|
||||
|
||||
#### 出参字段表
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| [].canRevoke | Boolean | 🆕 规则见上表;团期管理员恒为 `false` |
|
||||
| 其余字段 | — | **不变**(`scope` / `orderNo` / `teamNo` 等) |
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```http
|
||||
GET /v3/admin/order/group-batch/2104839654727618562/advances HTTP/1.1
|
||||
Authorization: Bearer <管理员 token>
|
||||
```
|
||||
|
||||
#### 响应示例
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": [
|
||||
{
|
||||
"id": "2105589347598368769",
|
||||
"scope": "GROUP_BATCH",
|
||||
"scopeName": "团期级",
|
||||
"orderId": null,
|
||||
"orderNo": null,
|
||||
"amount": 5000.0,
|
||||
"status": "SUBMITTED",
|
||||
"statusText": "待审批",
|
||||
"createdByName": "金卫",
|
||||
"canRevoke": true
|
||||
}
|
||||
],
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
无预支时返回空数组(不变)。开关关闭时,非团期管理员看待审批行都为 `true`,团期管理员仍为 `false`。
|
||||
|
||||
#### 错误响应
|
||||
|
||||
判权不变。团期不存在:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 589500,
|
||||
"message": "团期不存在",
|
||||
"data": null,
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- 原来前端写的 `a.status === 'SUBMITTED' && !isGroupBatchManager` 可以整体换成 `a.canRevoke`。
|
||||
- 子订单级行与团期级行规则相同。
|
||||
|
||||
---
|
||||
|
||||
### 4. 发起订单级预支 `POST /v3/admin/order/:orderId/advance`
|
||||
|
||||
**VO**: `CreateAdvanceReqVO` → `Result<OrderAdvanceRespVO>`
|
||||
|
||||
#### 使用场景
|
||||
|
||||
订单详情「发起预支」。返回体里 `canRevoke` 对发起人本人为 `true`(刚建的待审批,自己可以撤)。
|
||||
|
||||
#### 入参字段表
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|------|------|------|------|------|------|
|
||||
| orderId | Path | Long | ✅ | 订单 ID | **不变** |
|
||||
| payeeStaffId | Body | Long | ✅ | 本单人员 | **不变** |
|
||||
| advanceType | Body | String | ✅ | 字典 `advance_type` | **不变** |
|
||||
| amount | Body | BigDecimal | ✅ | >0,不超可用上限 | **不变** |
|
||||
| purpose | Body | String | ❌ | — | **不变** |
|
||||
| voucherUrl | Body | String | ❌ | — | **不变** |
|
||||
|
||||
#### 出参字段表
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| data.canRevoke | Boolean | 🆕 发起人本人为 `true` |
|
||||
| 其余字段 | — | **不变** |
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```json
|
||||
{
|
||||
"payeeStaffId": "2100747615736897537",
|
||||
"advanceType": "TICKET",
|
||||
"amount": 180.00,
|
||||
"purpose": "呼伦贝尔大草原景区门票代垫"
|
||||
}
|
||||
```
|
||||
|
||||
#### 响应示例
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"id": "2105886435083206657",
|
||||
"orderId": "2100743225424621570",
|
||||
"status": "SUBMITTED",
|
||||
"statusText": "待审批",
|
||||
"amount": 180.0,
|
||||
"canRevoke": true
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
无。
|
||||
|
||||
#### 错误响应
|
||||
|
||||
判权与校验不变。金额超可用上限:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 585004,
|
||||
"message": "预支金额超过可用余额上限",
|
||||
"data": null,
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- 只是返回体多一个字段,创建逻辑不变。
|
||||
|
||||
---
|
||||
|
||||
### 5. 预支审批通过 `PUT /v3/admin/order/advance/:advanceId/approve`
|
||||
|
||||
**VO**: `Result<OrderAdvanceRespVO>`(无请求体)
|
||||
|
||||
#### 使用场景
|
||||
|
||||
审批中心「通过」。审批后状态是已通过,`canRevoke` 恒为 `false`。
|
||||
|
||||
#### 入参字段表
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|------|------|------|------|------|------|
|
||||
| advanceId | Path | Long | ✅ | 预支 ID | **不变** |
|
||||
|
||||
#### 出参字段表
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| data.canRevoke | Boolean | 🆕 恒 `false` |
|
||||
| 其余字段 | — | **不变** |
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```http
|
||||
PUT /v3/admin/order/advance/2105886444679774210/approve HTTP/1.1
|
||||
Authorization: Bearer <财务 token>
|
||||
```
|
||||
|
||||
#### 响应示例
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"id": "2105886444679774210",
|
||||
"status": "APPROVED",
|
||||
"statusText": "已通过",
|
||||
"approvedBy": "yaosutu",
|
||||
"canRevoke": false
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
无。
|
||||
|
||||
#### 错误响应
|
||||
|
||||
判权不变。预支不存在(财务 / 管理员):
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 585000,
|
||||
"message": "预支记录不存在",
|
||||
"data": null,
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- 审批逻辑与出纳待付款的生成不变。
|
||||
|
||||
---
|
||||
|
||||
### 6. 预支审批驳回 `PUT /v3/admin/order/advance/:advanceId/reject`
|
||||
|
||||
**VO**: `RejectAdvanceReqVO` → `Result<OrderAdvanceRespVO>`
|
||||
|
||||
#### 使用场景
|
||||
|
||||
审批中心「驳回」。驳回后状态是已驳回,`canRevoke` 恒为 `false`。
|
||||
|
||||
#### 入参字段表
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|------|------|------|------|------|------|
|
||||
| advanceId | Path | Long | ✅ | 预支 ID | **不变** |
|
||||
| reason | Body | String | ✅ | 驳回原因 | **不变** |
|
||||
|
||||
#### 出参字段表
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| data.canRevoke | Boolean | 🆕 恒 `false` |
|
||||
| 其余字段 | — | **不变** |
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```json
|
||||
{
|
||||
"reason": "门票已由地接社统一采购,无需个人垫付"
|
||||
}
|
||||
```
|
||||
|
||||
#### 响应示例
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"id": "2104861622562627585",
|
||||
"status": "REJECTED",
|
||||
"statusText": "已驳回",
|
||||
"rejectReason": "门票已由地接社统一采购,无需个人垫付",
|
||||
"canRevoke": false
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
无。
|
||||
|
||||
#### 错误响应
|
||||
|
||||
判权不变。预支不存在(财务 / 管理员):
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 585000,
|
||||
"message": "预支记录不存在",
|
||||
"data": null,
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- 驳回逻辑不变。
|
||||
|
||||
---
|
||||
|
||||
### 7. 发起团期级预支 `POST /v3/admin/order/group-batch/:groupBatchId/advance`
|
||||
|
||||
**VO**: `CreateGroupBatchAdvanceReqVO` → `Result<OrderAdvanceRespVO>`
|
||||
|
||||
#### 使用场景
|
||||
|
||||
团期财务页签「发起预支」。返回体里 `canRevoke` 对发起人本人为 `true`;团期管理员发起的为 `false`(团期管理员撤回会先被 `581008` 拦下)。
|
||||
|
||||
#### 入参字段表
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|------|------|------|------|------|------|
|
||||
| groupBatchId | Path | Long | ✅ | 团期 ID | **不变** |
|
||||
| payeeStaffId | Body | Long | ✅ | 团期人员 | **不变** |
|
||||
| advanceType | Body | String | ✅ | 字典 `advance_type` | **不变** |
|
||||
| amount | Body | BigDecimal | ✅ | >0,不超团期统一池上限 | **不变** |
|
||||
| purpose | Body | String | ❌ | — | **不变** |
|
||||
| voucherUrl | Body | String | ❌ | — | **不变** |
|
||||
|
||||
#### 出参字段表
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| data.canRevoke | Boolean | 🆕 发起人本人为 `true`,团期管理员为 `false` |
|
||||
| 其余字段 | — | **不变** |
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```json
|
||||
{
|
||||
"payeeStaffId": "2100747615736897537",
|
||||
"advanceType": "CATERING",
|
||||
"amount": 600.00,
|
||||
"purpose": "满洲里套娃广场团餐代垫"
|
||||
}
|
||||
```
|
||||
|
||||
#### 响应示例
|
||||
|
||||
示例值(发起人本人调用):
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"id": "2105890177461317634",
|
||||
"orderId": null,
|
||||
"status": "SUBMITTED",
|
||||
"statusText": "待审批",
|
||||
"amount": 600.0,
|
||||
"canRevoke": true
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
无。
|
||||
|
||||
#### 错误响应
|
||||
|
||||
判权与校验不变。团期不存在:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 589500,
|
||||
"message": "团期不存在",
|
||||
"data": null,
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- 只是返回体多一个字段,创建逻辑与额度池不变。
|
||||
|
||||
---
|
||||
|
||||
### 8. 核单汇总快照 `GET /v3/admin/order/:orderId/settlement/summary`
|
||||
|
||||
**VO**: `Result<SettlementSummaryRespVO>`
|
||||
|
||||
#### 使用场景
|
||||
|
||||
核单页的汇总快照。`advanceSummary.records` 与预支列表共用同一个 VO,所以一并带上 `canRevoke`。这里只列已通过的预支,恒为 `false`。
|
||||
|
||||
#### 入参字段表
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|------|------|------|------|------|------|
|
||||
| orderId | Path | Long | ✅ | 订单 ID | **不变** |
|
||||
|
||||
#### 出参字段表
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| advanceSummary.records[].canRevoke | Boolean | 🆕 恒 `false`(只含已通过) |
|
||||
| 其余字段 | — | **不变** |
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```http
|
||||
GET /v3/admin/order/2100743225424621570/settlement/summary HTTP/1.1
|
||||
Authorization: Bearer <管理员 token>
|
||||
```
|
||||
|
||||
#### 响应示例
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"settled": false,
|
||||
"orderId": "2100743225424621570",
|
||||
"teamNo": "26-8707",
|
||||
"advanceSummary": {
|
||||
"approvedAmount": "90.00",
|
||||
"records": [
|
||||
{
|
||||
"id": "2105886444679774210",
|
||||
"status": "APPROVED",
|
||||
"statusText": "已通过",
|
||||
"amount": 90.0,
|
||||
"canRevoke": false
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
没有已通过的预支时 `records` 为空数组(不变)。
|
||||
|
||||
#### 错误响应
|
||||
|
||||
本接口没有业务错误码,订单不存在时也返回 `200` 和 `settled=false` 的空壳(行为不变)。网关层未带 token(TEST 2026-10-02 实打):
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 401,
|
||||
"message": "缺少有效的 Authorization 头",
|
||||
"data": null,
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- 前端不需要用这里的 `canRevoke`。
|
||||
|
||||
---
|
||||
|
||||
## 四、契约约束与正确调用方式
|
||||
|
||||
- 撤回按钮显示条件改成 `a.canRevoke`,不要再自己拼「待审批 + 角色 + 是否团期管理员」。
|
||||
- `canRevoke` 跟着当前登录账号和当前角色变;切换角色后要重新拉列表。
|
||||
- `canRevoke=true` 只表示列表渲染那一刻能撤;点击时若已被别人审批,仍会返回 `585005`(状态不允许),照常提示即可。
|
||||
- 撤回接口的判权与错误码不变:非申请人、非管理员 `585009`,团期管理员 `581008`。
|
||||
|
||||
---
|
||||
|
||||
## 五、数据库行为
|
||||
|
||||
- 零 DDL、零数据迁移、零写入。
|
||||
- 取值用预支记录既有的创建人账号 ID(提交时自动写入);审批中心的联表查询多 select 这一列,不出参。
|
||||
- 发起、审批、驳回的写库逻辑不变。
|
||||
|
||||
---
|
||||
|
||||
## 六、边界行为
|
||||
|
||||
- 定时任务、消息消费等无请求上下文的场景算出来恒为 `false`(这些场景不渲染列表)。
|
||||
- 计算 `canRevoke` 不打 `ADVANCE_ACL_DENY` 日志;只有真调撤回被拒时才打。
|
||||
- 缺角色的 token 若正好是申请人本人,`canRevoke=true`,与撤回接口一致(#8517 有意的设计)。
|
||||
|
||||
## 六.6、修改前后对比
|
||||
|
||||
| 场景 | 改前 | 改后 |
|
||||
|---|---|---|
|
||||
| 非申请人、非管理员看待审批行 | 按钮显示,点了 `585009` | `canRevoke=false`,前端可隐藏 |
|
||||
| 申请人本人 / 管理员看待审批行 | 按钮显示,能撤 | `canRevoke=true` |
|
||||
| 团期管理员看团期页签 | 前端用 `!isGroupBatchManager` 自己藏 | `canRevoke=false` |
|
||||
| 非待审批行 | 前端按状态藏 | `canRevoke=false` |
|
||||
| 开关关闭 | 前端不知道开关状态 | 非团期管理员都为 `true`,跟撤回接口一致 |
|
||||
|
||||
## 六.7、影响评估
|
||||
|
||||
- **是否破坏向后兼容**:否,纯新增字段。
|
||||
- **前端是否必须同步上线**:否。不改前端时行为与改前相同(按钮照旧显示);改了才能隐藏点不了的按钮。
|
||||
- **回滚**:revert PR #8723 后重新部署 order-v3。
|
||||
|
||||
---
|
||||
|
||||
## 七、不影响范围
|
||||
|
||||
- 撤回接口 `DELETE /v3/admin/order/advance/:advanceId` 的判权与返回:不变。
|
||||
- 各接口的入参、判权、其余出参:不变。
|
||||
- 出纳付款、核单计算:不变。
|
||||
- 小程序端:无影响。
|
||||
|
||||
---
|
||||
|
||||
## 八、测试环境已验证
|
||||
|
||||
**环境**:TEST(`https://api.test.1814.love`) **验证时间**:2026-10-02 13:03~13:30
|
||||
**构建身份**:order-v3 部署 `dev-v3 @ 806058c66`(本单合并提交),12:57 完成。零写入判据:部署后连查 6 次订单级预支列表,每行都带 `canRevoke` 键(旧字节没有这个键)。
|
||||
**身份**:自签 token 直打网关,用 TEST 真实账号 ID 配对应角色;TEST 上没有在用的财务账号,财务用 `role=FINANCE` 的自签 token。
|
||||
|
||||
### 8.1 造数
|
||||
|
||||
在待出发订单 `HL20260918082629372`(定制师 1001)上:C1 定制师申请门票 180(待审批)、C2 管理员 jw 申请餐费 120(待审批)、C3 定制师申请门票 90 后由财务审批(已通过)。另有该单既有的已付款、已驳回各一笔。
|
||||
|
||||
### 8.2 三个列表逐角色取值
|
||||
|
||||
| 列表 | 查看人 | C1(1001 申请,待审批) | C2(jw 申请,待审批) | 已通过 / 已付款 / 已驳回 |
|
||||
|---|---|---|---|---|
|
||||
| 订单级 | 本单定制师 1001 | `true` | `false` | 均 `false` |
|
||||
| 订单级 | 管理员 | `true` | `true` | 均 `false` |
|
||||
| 订单级 | 车务管理员 | `false` | `false` | 均 `false` |
|
||||
| 审批中心 | 财务 | `false` | `false` | 已通过 `false` |
|
||||
| 审批中心 | 管理员 | `true` | `true` | 已通过 `false` |
|
||||
|
||||
团期财务页签(团期级待审批一笔,jw 申请):财务 `false`、团期管理员 `false`、管理员 `true`。
|
||||
联表探针:财务角色、账号 ID 设为 1001 查审批中心,C1 为 `true`、C2 为 `false`,证明审批中心带出了创建人。
|
||||
核单汇总:只含 C3,`canRevoke=false`。
|
||||
|
||||
### 8.3 按 canRevoke 抽样真实撤回
|
||||
|
||||
| 操作 | 结果 |
|
||||
|---|---|
|
||||
| 财务、其他定制师撤 C1;车务、定制师 1001 撤 C2(均为 `false`) | 均 `585009`,未删除 |
|
||||
| 团期管理员撤 C1 | `581008` |
|
||||
| 定制师 1001 撤 C1、管理员撤 C2(均为 `true`) | 均 `200`,已软删 |
|
||||
|
||||
### 8.4 nacos 回滚开关往返
|
||||
|
||||
| 态 | 订单级:定制师 / 车务看 C2 | 团期页签:财务 / 团期管理员 | 审批中心:财务看 C1、C2、团期级 |
|
||||
|---|---|---|---|
|
||||
| A 默认 | `false` / `false` | `false` / `false` | 全 `false` |
|
||||
| B 关闭(10.5 秒生效) | `true` / `true` | `true` / `false` | 全 `true` |
|
||||
| C 还原(7.7 秒生效) | `false` / `false` | `false` / `false` | 全 `false` |
|
||||
|
||||
- 发布带 `casMd5`,还原写在 `finally` 里;还原后 md5 与原值同为 `c2206934960057f70b7173159046dc54`。
|
||||
- 两个实例的 `ADVANCE_ACL_DENY` 计数在三态的列表渲染前后都是 0;随后 4 次被拒的真实撤回让计数各 +2,证明计数有效。
|
||||
|
||||
### 8.5 回归(零写入)
|
||||
|
||||
不存在的预支 ID 调审批 / 驳回 / 撤回:定制师、车务 `585008` / `585008` / `585009`;财务 `585000` / `585000` / `585009`;管理员三个 `585000`;团期管理员三个 `581008`。与 #8517 验收读数一致,前后表行数不变。
|
||||
|
||||
### 本地证据
|
||||
|
||||
| 项 | 读数 |
|
||||
|---|---|
|
||||
| 相关 16 个测试类定向 | 265/0/0/0 |
|
||||
| 一致性矩阵 | `canRevoke` 与撤回守卫在 144 种角色 × 账号 × 创建人 × 开关组合下逐条一致 |
|
||||
| 变异 | 删掉审批中心联表那一列 → 1 例红;让 `canRevoke` 对财务放宽 → 2 例红;已还原 |
|
||||
| order-v3 全量(有 Docker,两半) | 1115 个可执行测试类全部有报告;红 2 个类、`hl-finance` 红 25 个类,在基底 `3bad2ad27` 上读数与用例名逐条一致,本单零新增 |
|
||||
|
||||
---
|
||||
|
||||
## 十、相关文档
|
||||
|
||||
- Issue `#8684`;PR `#8723`
|
||||
- 前置:Issue `#8517`(撤回判权本身)
|
||||
|
||||
## 关联 / 联系人
|
||||
|
||||
### 链接
|
||||
|
||||
- **Issue**: [#8684](https://git.1814.love/wx/HL/issues/8684)
|
||||
- **PR**: [#8723](https://git.1814.love/wx/HL/pulls/8723)
|
||||
- **Merge commit**: [806058c66](https://git.1814.love/wx/HL/commit/806058c66)
|
||||
|
||||
### 联系人
|
||||
|
||||
- **后端负责人**: @jw
|
||||
在新工单中引用
屏蔽一个用户