更新预支管理终态文档:新增 GET /advance/payee-candidates 候选下拉+AdvancePayeeCandidateVO 出参+创建入参 payeeStaffId 必填+585007 错误码+585002 废弃;借款对象语义从强制主报账人改为本单人员下拉选定(默认主报账人)。
13 KiB
订单预支管理(创建/审批/驳回/撤回/列表)
- 端类型:管理后台
- 变更类型:新增接口
- 关联:Issue #4429 / #4440 / #4452 | PR #4429 / #4442 / #4453
- 服务:hl-order-service-v3
- 日期:2026-06-26
本文为「订单预支借款」功能的最终态契约(合并 #4429 落地 + #4440 借款类型字典 + #4452 去草稿态),前端按本文对接即可,无需翻历史版本。
① 接口背景
常规订单详情提供「预支借款」能力:定制师为订单的某位人员(借款对象,从本单人员下拉选定,默认主报账人,#4465)申请一笔预支款,财务审批通过/驳回。预支金额受订单待收尾款上限约束,借款类型走数据字典。
流程(去草稿后,#4452):创建即进「待审批」→ 财务通过(APPROVED,触发后置事件)/ 驳回(REJECTED)。财务审批前申请人可撤回。
② 变更清单
| # | 方法 | 路径 | 说明 |
|---|---|---|---|
| 1 | GET | /v3/admin/order/{orderId}/advance/payee-candidates |
借款对象候选下拉(全部人员,主报账人默认,#4465) |
| 2 | POST | /v3/admin/order/{orderId}/advance |
创建预支(创建即待审批 SUBMITTED;#4465 入参加 payeeStaffId) |
| 3 | PUT | /v3/admin/order/advance/{advanceId}/approve |
财务审批通过 |
| 4 | PUT | /v3/admin/order/advance/{advanceId}/reject |
财务审批驳回 |
| 5 | DELETE | /v3/admin/order/advance/{advanceId} |
撤回待审批预支(仅 SUBMITTED 可撤) |
| 6 | GET | /v3/admin/order/{orderId}/advances |
分页查询本单预支列表 |
⚠️ 已删除端点(#4452,旧路径调用返回 code=404「接口不存在」):
| 方法 | 旧路径 | 处理 |
|---|---|---|
| PUT | /v3/admin/order/advance/{advanceId}/submit |
已删除。去草稿后创建即待审批,无需单独提交动作 |
③ 接口详情
统一响应包:{ code, message, data, success },code=200 成功;业务异常 code 为对应错误码(见 ⑦),HTTP 状态恒 200。
0. 借款对象候选下拉 — GET /v3/admin/order/{orderId}/advance/payee-candidates(#4465)
返回本单全部人员(order 人员配置),供创建预支时选择借款对象。主报账人(reporter_rank=PRIMARY)排第一并标 isDefault=true,前端默认选中。候选项 id 即创建预支的 payeeStaffId 入参。返回 PageResult(单页全量,records / total)。
1. 创建预支 — POST /v3/admin/order/{orderId}/advance
入口门槛(不满足抛对应错误码):
- 订单状态 ∈ {待出发 PENDING_DEPARTURE / 出行中 TRAVELLING},否则 585001(#4462 收紧:已完成 COMPLETED、已取消 CANCELLED、定制中、待付款均不可创建预支)
- 订单结算状态 ≠ 已结算完成,否则 585001
- 借款对象
payeeStaffId须为本单人员(取候选下拉的 id),否则 585007(#4465) - 借款类型须为字典
advance_type内的值,否则 585006 - 预支金额 0 < amount ≤ 可用上限(可用上限 = 待收尾款 − 本单在途预支之和),否则 585003 / 585004
借款对象由前端从候选下拉选定(#4465,不再强制主报账人,去掉原 585002 门槛),后端校验属本单后快照该人员姓名/角色写入。创建成功状态直接为 SUBMITTED。
2. 审批通过 — PUT /v3/admin/order/advance/{advanceId}/approve
仅 SUBMITTED 可通过,否则 585005。写 approvedBy/approvedAt,状态置 APPROVED,触发后置事件(出账逻辑后续补充)。
3. 审批驳回 — PUT /v3/admin/order/advance/{advanceId}/reject
仅 SUBMITTED 可驳回,否则 585005。须填驳回原因,状态置 REJECTED。
4. 撤回待审批 — DELETE /v3/admin/order/advance/{advanceId}
仅 SUBMITTED 可撤回(软删),财务已审批(APPROVED/REJECTED)不可撤回,否则 585005。
5. 分页查询 — GET /v3/admin/order/{orderId}/advances
按 create_time 倒序返回本单预支列表,分页参数 page/pageSize。
④ 入参
创建预支 请求体 CreateAdvanceReqVO
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| payeeStaffId | Long(字符串) | 是 | 借款对象,取候选下拉项的 id(#4465),须为本单人员,否则 585007 |
| advanceType | String | 是 | 借款类型,取字典 advance_type 的 dictValue(见 ⑥) |
| amount | BigDecimal | 是 | 预支金额,须 > 0(≥ 0.01) |
| purpose | String | 否 | 用途说明 |
| voucherUrl | String | 否 | 凭证文件 URL |
候选下拉 / 分页查询 path
候选下拉 GET /v3/admin/order/{orderId}/advance/payee-candidates 仅路径参数 orderId,无 query。
驳回 请求体 RejectAdvanceReqVO
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| reason | String | 是 | 驳回原因 |
分页查询 query
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
| page | int | 否 | 1 | 页码 |
| pageSize | int | 否 | 20 | 每页条数 |
approve / reject / revoke 仅路径参数 advanceId(approve/revoke 无请求体)。
⑤ 出参
创建/审批/驳回 返回 data 为单个 OrderAdvanceRespVO;分页查询 data 为 PageResult<OrderAdvanceRespVO>;候选下拉 data 为 PageResult<AdvancePayeeCandidateVO>。
AdvancePayeeCandidateVO(借款对象候选,#4465)
| 字段 | 类型 | 说明 |
|---|---|---|
| id | String | 候选 ID(=创建预支 payeeStaffId,order 人员分配 ID) |
| staffName | String | 员工姓名 |
| staffRole | String | 员工角色代码(DRIVER/LEADER/PHOTOGRAPHER/OTHER 等) |
| staffRoleText | String | 员工角色文案(司机/导游/摄影师/其他) |
| reporterRank | String | 报账人等级(PRIMARY/SECONDARY/NONE) |
| isDefault | boolean | 是否默认选中(主报账人为 true,前端默认选此项) |
OrderAdvanceRespVO
| 字段 | 类型 | 说明 |
|---|---|---|
| id | String | 预支 ID(雪花,字符串) |
| orderId | String | 订单 ID(字符串) |
| payeeStaffId | String | 报账人 staff 分配 ID(快照) |
| payeeName | String | 报账人姓名 |
| payeeRole | String | 报账人角色代码(DRIVER/LEADER/PHOTOGRAPHER/OTHER 等) |
| payeeRoleText | String | 报账人角色文案(DRIVER→司机/LEADER→导游/PHOTOGRAPHER→摄影师/OTHER→其他) |
| advanceType | String | 借款类型代码(字典 advance_type dictValue) |
| amount | BigDecimal | 预支金额 |
| purpose | String | 用途说明 |
| voucherUrl | String | 凭证文件 URL |
| status | String | 状态代码(SUBMITTED/APPROVED/REJECTED) |
| statusText | String | 状态文案(待审批/已通过/已驳回) |
| rejectReason | String | 驳回原因(仅 REJECTED 有值) |
| createdByName | String | 创建人姓名 |
| createTime | DateTime | 创建时间 |
| submittedAt | DateTime | 提交审批时间(创建即填充) |
| approvedAt | DateTime | 审批时间(通过/驳回时填充) |
| approvedBy | String | 审批人姓名 |
⑥ 枚举 / 数据字典
状态 status(#4452 去 DRAFT,3 态)
| code | 文案 statusText | 说明 |
|---|---|---|
| SUBMITTED | 待审批 | 创建后初始态,财务未审批前可撤回 |
| APPROVED | 已通过 | 财务审批通过(终态,触发后置事件) |
| REJECTED | 已驳回 | 财务审批驳回,含 rejectReason(终态) |
旧
DRAFT(草稿)状态已删除,出参不再出现。
借款类型 advanceType(数据字典 advance_type,#4440)
| dictValue | dictLabel |
|---|---|
| ACCOMMODATION_DEPOSIT | 住宿押金 |
| TICKET | 门票 |
| CATERING | 餐饮 |
| TRANSPORT | 交通用车 |
字典项可后台维护,前端建议通过字典接口
GET /admin/dict/data/advance_type动态取值,不要硬编码。
⑦ 错误码
| code | 含义 |
|---|---|
| 585000 | 预支记录不存在 |
| 585001 | 订单当前状态不可创建预支 |
| 585002 | |
| 585003 | 预支金额必须大于 0 |
| 585004 | 预支金额超过可用余额上限 |
| 585005 | 预支当前状态不允许此操作(如撤回/审批一条非 SUBMITTED 的记录) |
| 585006 | 借款类型非法(须为字典 advance_type 内的值) |
| 585007 | 借款对象不属于本订单人员(payeeStaffId 非本单人员,#4465) |
| 400 | 参数校验失败(如 payeeStaffId 未填「借款对象必填」、advanceType 未填「借款类型必填」、amount 为空/≤0、reason 未填) |
⑧ 示例
典型:借款对象候选下拉(#4465)
请求 GET /v3/admin/order/2070038865875230722/advance/payee-candidates
{
"code": 200, "success": true, "message": "成功",
"data": {
"total": 2, "page": 1, "pageSize": 2,
"records": [
{ "id": "9000000000000000001", "staffName": "刘领队", "staffRole": "LEADER", "staffRoleText": "导游", "reporterRank": "PRIMARY", "isDefault": true },
{ "id": "9000000000000000002", "staffName": "孙师傅", "staffRole": "DRIVER", "staffRoleText": "司机", "reporterRank": "NONE", "isDefault": false }
]
}
}
典型:创建预支(#4465 带 payeeStaffId)
请求 POST /v3/admin/order/2070038865875230722/advance
{ "payeeStaffId": "9000000000000000002", "advanceType": "TICKET", "amount": 100, "purpose": "景区门票预付" }
响应
{
"code": 200, "success": true, "message": "成功",
"data": {
"id": "2070423136842539010", "orderId": "2070038865875230722",
"payeeStaffId": "9000000000000000002", "payeeName": "孙师傅",
"payeeRole": "DRIVER", "payeeRoleText": "司机",
"advanceType": "TICKET", "amount": 100, "purpose": "景区门票预付",
"status": "SUBMITTED", "statusText": "待审批",
"createdByName": "定制师A", "submittedAt": "2026-06-26 16:25:17",
"approvedAt": null, "approvedBy": null, "rejectReason": null
}
}
异常:借款对象不属于本单(#4465)
请求体 { "payeeStaffId": "999999", "advanceType": "TICKET", "amount": 100 }
{ "code": 585007, "success": false, "message": "借款对象不属于本订单人员", "data": null }
边界:审批通过
请求 PUT /v3/admin/order/advance/2070423411452010498/approve
{ "code": 200, "success": true, "data": { "status": "APPROVED", "statusText": "已通过", "approvedBy": "admin", "approvedAt": "2026-06-26 16:25:40" } }
异常:撤回一条已审批的预支
请求 DELETE /v3/admin/order/advance/2070423411452010498
{ "code": 585005, "success": false, "message": "预支当前状态不允许此操作", "data": null }
异常:调用已删除的 submit 端点
请求 PUT /v3/admin/order/advance/{advanceId}/submit
{ "code": 404, "success": false, "message": "接口不存在: PUT /v3/admin/order/advance/{advanceId}/submit", "data": null }
异常:借款类型非法
请求体 { "advanceType": "FOO", "amount": 100 }
{ "code": 585006, "success": false, "message": "借款类型非法(须为字典 advance_type 内的值)", "data": null }
⑨ 业务边界
- 仅订单状态为「待出发 / 出行中」时可创建预支(#4462);已完成、已取消、定制中、待付款均返 585001。
- 一个订单可有多笔预支;在途(SUBMITTED + APPROVED)金额之和不得超过订单待收尾款。
- 借款对象(payee)由前端从本单人员候选下拉选定(#4465),创建时快照该人员姓名/角色,预支记录创建后不随人员变更而变化;候选默认选中主报账人。
- 仅 SUBMITTED 可被 approve / reject / 撤回;APPROVED / REJECTED 为终态。
- 撤回为软删,列表不再返回被撤回记录。
⑩ 修改前后对比(#4452 去草稿)
| 维度 | 旧(#4429 初版) | 新(#4452) |
|---|---|---|
| 流程 | 草稿 DRAFT → 提交 SUBMITTED → 审批 | 创建即 SUBMITTED → 审批 |
| 创建后状态 | DRAFT(草稿) | SUBMITTED(待审批) |
| 提交端点 | PUT .../submit |
已删除(404) |
| DELETE 语义 | 删除草稿(仅 DRAFT) | 撤回待审批(仅 SUBMITTED) |
| status 取值 | DRAFT/SUBMITTED/APPROVED/REJECTED | SUBMITTED/APPROVED/REJECTED |
⑪ 影响评估 / 回滚
- 前端:去掉「保存草稿 / 提交」两步交互,改为「创建即提交审批」;删除按钮语义改为「撤回」(仅待审批可点);状态枚举去掉草稿。
- 后端:去草稿态随 PR #4453 上线,Flyway V20260626_005 已执行(status 默认值 SUBMITTED + 历史 DRAFT 行迁移)。
⑫ 注意事项
- 所有 ID 字段(id/orderId/payeeStaffId)为字符串,避免 JS 精度丢失。
- 借款类型务必从字典接口取值,字典可后台扩展。
- 金额上限由后端依据订单待收尾款实时计算,前端提交后以后端校验为准。
⑬ 关联 / 联系人
- Issue:wx/HL#4429 | /4440 | /4452 | /4462 | /4465
- PR:wx/HL#4429 | /4442 | /4453 | /4463 | /4466
- 负责人:yst(腰苏图)