推送核单来源确认与车辆Step3接口变更说明
所有检测均成功
changelog-filename-gate / validate (push) Successful in 2s

这个提交包含在:
yaosutu 2026-07-30 16:27:58 +08:00
父节点 3851666575
当前提交 9e8dfc6360

查看文件

@ -0,0 +1,911 @@
---
schema: "hl-changelog/v2"
ticket: "5356"
title: "核单八类来源确认状态与车辆 Step3 接口统一"
consumer: "admin"
change_type: "修改接口"
backend_status: "deployed"
gateway_status: "verified"
frontend_status: "pending"
frontend_owner: ""
frontend_ref: ""
target_release: ""
verified_at: ""
status_note: "部署任务 80f1695a 已完成 order-v3 主副实例滚动;测试网关已验证新车辆 Step3 路由进入新代码并返回业务前置码 584102,旧车辆费用接口返回 404。车辆 DTO 正向数据与 Full E2E 尚未验证。"
updated_at: "2026-07-30"
base: "dev-v3"
---
# ⚠️【修改接口·管理后台】核单八类来源确认状态与车辆 Step3 接口统一 (#5356)
> **PR**: #5362 | **服务**: hl-order-service-v3 | **更新时间**: 2026-07-30 15:46
## 1. 接口背景
核单页面需要用同一套规则识别“手工行”和“系统来源行”,并逐行完成确认。此前各 Tab 的 `sourceType`、确认状态和车辆费用入口不一致,车辆数据还残留过已下线接口的字段口径。本次统一八类核单来源与逐行确认语义,并新增 Order 侧车辆 Step3 草稿查询、全量保存接口。
管理后台应以本文列出的 Order 侧接口为准;已删除的
`GET /v3/admin/order/:orderId/settlement/vehicle-fees`
`POST /v3/admin/order/:orderId/settlement/vehicle-fees/confirm`
继续保持下线,不得恢复调用。
## 变更接口2. 变更清单)
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | Step 1 查询住宿核单明细 | GET | `/v3/admin/order/:orderId/settlement/step1` | 修改 | 来源值统一;系统派生行初始为未确认;ID 按字符串返回 |
| 2 | Step 1 保存住宿核单明细 | PUT | `/v3/admin/order/:orderId/settlement/step1` | 修改 | 支持逐行 `UNCONFIRMED/CONFIRMED`;手工新行必须先未确认 |
| 3 | Step 2 查询门票核单明细 | GET | `/v3/admin/order/:orderId/settlement/step2` | 修改 | 响应新增逐行确认状态;ID 按字符串返回 |
| 4 | Step 2 保存门票核单明细 | PUT | `/v3/admin/order/:orderId/settlement/step2` | 修改 | 请求新增逐行确认状态;手工新行必须先未确认 |
| 5 | 查询车辆核单草稿 | GET | `/v3/admin/order/:orderId/settlement/step3/vehicles` | 新增 | Order 侧车辆 Step3 唯一查询入口 |
| 6 | 全量保存车辆核单草稿 | PUT | `/v3/admin/order/:orderId/settlement/step3/vehicles` | 新增 | 带 `version` 全量保存,支持车务行确认和手工行维护 |
| 7 | 查询领队人员费用 | GET | `/v3/admin/order/:orderId/settlement/staff-fees/leaders` | 修改 | 新增来源与确认状态名称 |
| 8 | 保存领队人员费用 | PUT | `/v3/admin/order/:orderId/settlement/staff-fees/leaders` | 修改 | 请求行新增 `id/sourceType/settlementConfirmStatus` |
| 9 | 查询司机人员费用 | GET | `/v3/admin/order/:orderId/settlement/staff-fees/drivers` | 修改 | 新增来源与确认状态名称 |
| 10 | 保存司机人员费用 | PUT | `/v3/admin/order/:orderId/settlement/staff-fees/drivers` | 修改 | 请求行新增 `id/sourceType/settlementConfirmStatus` |
| 11 | 查询导游人员费用 | GET | `/v3/admin/order/:orderId/settlement/staff-fees/guides` | 修改 | 新增来源与确认状态名称 |
| 12 | 保存导游人员费用 | PUT | `/v3/admin/order/:orderId/settlement/staff-fees/guides` | 修改 | 请求行新增 `id/sourceType/settlementConfirmStatus` |
| 13 | 查询摄影师人员费用 | GET | `/v3/admin/order/:orderId/settlement/staff-fees/photographers` | 修改 | 新增来源与确认状态名称 |
| 14 | 保存摄影师人员费用 | PUT | `/v3/admin/order/:orderId/settlement/staff-fees/photographers` | 修改 | 请求行新增 `id/sourceType/settlementConfirmStatus` |
| 15 | 查询其他人员费用 | GET | `/v3/admin/order/:orderId/settlement/staff-fees/others` | 修改 | 新增来源与确认状态名称 |
| 16 | 保存其他人员费用 | PUT | `/v3/admin/order/:orderId/settlement/staff-fees/others` | 修改 | 请求行新增 `id/sourceType/settlementConfirmStatus` |
| 17 | 查询餐食费用 | GET | `/v3/admin/order/:orderId/settlement/meals` | 修改 | 响应新增来源、来源名称、确认状态名称 |
| 18 | 新增餐食费用 | POST | `/v3/admin/order/:orderId/settlement/meals` | 修改 | 请求新增来源和确认状态;新行必须先未确认 |
| 19 | 修改餐食费用 | PUT | `/v3/admin/order/:orderId/settlement/meals/:settlementId` | 修改 | 可把已存在未确认行保存为已确认 |
| 20 | 查询其他支出 | GET | `/v3/admin/order/:orderId/settlement/other-expenses` | 修改 | 响应新增来源、来源名称、确认状态名称 |
| 21 | 新增其他支出 | POST | `/v3/admin/order/:orderId/settlement/other-expenses` | 修改 | 手工新行必须先未确认 |
| 22 | 修改其他支出 | PUT | `/v3/admin/order/:orderId/settlement/other-expenses/:settlementId` | 修改 | 可把已存在未确认行保存为已确认 |
| 23 | 查询其他收入 | GET | `/v3/admin/order/:orderId/settlement/other-incomes` | 修改 | `sourceType` 从内部来源值改为 `MANUAL/SYSTEM` |
| 24 | 新增其他收入 | POST | `/v3/admin/order/:orderId/settlement/other-incomes` | 修改 | 手工新行必须先未确认 |
| 25 | 修改其他收入 | PUT | `/v3/admin/order/:orderId/settlement/other-incomes/:incomeId` | 修改 | 可把已存在未确认行保存为已确认 |
| 26 | 完成核单 | POST | `/v3/admin/order/:orderId/settlement/finalize` | 修改 | 只接受八类来源同步完成且所有非空明细均已确认的数据 |
## 3. 接口详情
以下接口均需登录态 JWT 和现有订单查看/核单权限;无接口级特殊限流。GET 为只读幂等;PUT 为全量替换幂等;POST 新增其他收入使用 `requestId` 保证同订单幂等。
### 3.1 住宿 Step 1
**接口**
| 方法 | 路径 | 使用场景 |
|---|---|---|
| GET | `/v3/admin/order/:orderId/settlement/step1` | 打开住宿 Tab、刷新系统配房来源 |
| PUT | `/v3/admin/order/:orderId/settlement/step1` | 全量保存住宿行及逐行确认状态 |
**路径参数**
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `orderId` | String(Long) | 是 | 订单 ID,必须大于 0 |
**PUT 请求体**
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `items` | HotelItem[] | 是 | 全量数组;缺少的手工现存行按删除处理 |
| `items[].id` | String(Long) | 更新时是 | 已保存行 ID;新行为空 |
| `items[].hotelAssignmentId` | String(Long) | 否 | 配房来源行 ID;手工行为空 |
| `items[].hotelId` | String(Long) | 否 | 酒店 ID |
| `items[].roomTypeId` | String(Long) | 否 | 房型 ID |
| `items[].stayDate` | Date | 是 | `yyyy-MM-dd` |
| `items[].hotelName` | String | 是 | 最长 200 字符 |
| `items[].roomType` | String | 否 | 房型摘要,最长 64 字符 |
| `items[].roomTypeName` | String | 否 | 房型/规格名称,最长 128 字符 |
| `items[].roomCount` | Integer | 是 | 总间数 |
| `items[].unitPrice` | Decimal | 否 | 核算单价,必须大于等于 0 |
| `items[].plannedCost` | Decimal | 是 | 计划成本,必须大于等于 0 |
| `items[].actualCost` | Decimal | 是 | 实际成本,必须大于等于 0 |
| `items[].paymentMethod` | String | 条件必填 | `SIGNED/COMPANY_PAID/CASH_PAID`;手工行必填 |
| `items[].settleType` | String | 否 | `cash/sign/company`,兼容配房来源付款口径 |
| `items[].sourceType` | String | 是 | `HOUSE_ASSIGNMENT/MANUAL/SYSTEM``TEMPLATE` 仅兼容旧入参 |
| `items[].sourceId` | String(Long) | 否 | 系统来源业务 ID |
| `items[].settlementConfirmStatus` | String | 是 | `UNCONFIRMED/CONFIRMED` |
| `items[].remark` | String | 否 | 最长 500 字符 |
| `items[].voucherUrls` | String[] | 否 | 凭证 URL |
**GET 响应 `data[]`**
除上述行字段外,还返回:
| 字段 | 类型 | 说明 |
|---|---|---|
| `paymentMethodName` | String | 付款方式名称 |
| `sourceTypeName` | String | 来源名称:配房结果/手工/系统 |
| `settlementConfirmStatusName` | String | 未确认/已确认 |
**PUT 响应 `data`**
| 字段 | 类型 | 说明 |
|---|---|---|
| `addedIds` | Long[] | 新增行 ID |
| `updatedIds` | Long[] | 更新行 ID |
| `deletedIds` | Long[] | 删除行 ID |
| `totalActualCost` | String(Decimal) | 保存后住宿实际成本合计 |
**业务边界**
- 配房来源行首次进入草稿返回 `UNCONFIRMED`;带已有 `id` 保存时可改为 `CONFIRMED`
- 手工新行 `id=null` 时只允许 `UNCONFIRMED`;保存取得 ID 后,下一次 PUT 才可改为 `CONFIRMED`
- `TEMPLATE` 只兼容旧请求,响应统一为 `SYSTEM`
### 3.2 门票 Step 2
**接口**
| 方法 | 路径 | 使用场景 |
|---|---|---|
| GET | `/v3/admin/order/:orderId/settlement/step2` | 打开门票/游玩项目 Tab、刷新行程来源 |
| PUT | `/v3/admin/order/:orderId/settlement/step2` | 全量保存门票行及逐行确认状态 |
**PUT 请求体**
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `items` | TicketItem[] | 是 | 全量数组 |
| `items[].id` | String(Long) | 更新时是 | 已保存行 ID;新行为空 |
| `items[].sourceType` | String | 是 | `SCENIC_ASSIGNMENT/ACTIVITY_ASSIGNMENT/MANUAL``CUSTOM_ASSIGNMENT` 仅兼容旧入参 |
| `items[].scenicAssignmentId` | String(Long) | 系统行是 | 景区或活动来源 ID |
| `items[].dayNumber` | Integer | 否 | 行程第几天,响应派生 |
| `items[].dayDate` | Date | 是 | 行程日 |
| `items[].scenicName` | String | 是 | 项目名,最长 200 字符 |
| `items[].specName` | String | 否 | 票型/规格,最长 128 字符 |
| `items[].ticketCount` | Integer | 是 | 实际购票数量,可为 0 |
| `items[].ticketUnitPrice` | Decimal | 否 | 参考单价 |
| `items[].sellPrice` | Decimal | 否 | 客户成交单价,必须大于等于 0 |
| `items[].totalAmount` | Decimal | 否 | 客户成交小计,必须大于等于 0 |
| `items[].plannedCost` | Decimal | 是 | 计划成本,必须大于等于 0 |
| `items[].actualCost` | Decimal | 是 | 实际成本,必须大于等于 0 |
| `items[].paymentMethod` | String | 否 | `SIGNED/COMPANY_PAID/CASH_PAID` |
| `items[].voucherUrls` | String[] | 否 | 凭证 URL |
| `items[].remark` | String | 否 | 最长 500 字符 |
| `items[].settlementConfirmStatus` | String | 是 | `UNCONFIRMED/CONFIRMED` |
**GET 响应 `data[]`**
返回完整 `TicketItem`,并增加:
| 字段 | 类型 | 说明 |
|---|---|---|
| `sourceTypeName` | String | 景区/游玩项目/手工 |
| `paymentMethodName` | String | 付款方式名称 |
| `settlementConfirmStatusName` | String | 未确认/已确认 |
**PUT 响应**与住宿 Step 1 相同:`addedIds/updatedIds/deletedIds/totalActualCost`
**业务边界**
- 系统来源首次同步为 `UNCONFIRMED`,来源事实变化后会重新变为 `UNCONFIRMED`
- 手工新行必须先保存为 `UNCONFIRMED`,已有 ID 后可保存为 `CONFIRMED`
- 响应不再返回 `CUSTOM_ASSIGNMENT`,历史自定义值统一返回 `MANUAL`
### 3.3 车辆 Step 3
**接口**
| 方法 | 路径 | 使用场景 |
|---|---|---|
| GET | `/v3/admin/order/:orderId/settlement/step3/vehicles` | 查询 Order 侧车辆核单草稿 |
| PUT | `/v3/admin/order/:orderId/settlement/step3/vehicles` | 带版本全量保存车辆行 |
**PUT 请求体**
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `version` | Long | 是 | GET 返回的草稿版本,最小 0 |
| `items` | VehicleItem[] | 是 | 全量明细;所有现存 `FLEET` 行必须原样带回 |
| `items[].id` | String(Long) | FLEET/更新时是 | 行 ID;手工新行为空 |
| `items[].sourceType` | String | 是 | `FLEET/MANUAL` |
| `items[].serviceDate` | Date | 是 | 服务日期 |
| `items[].vehicleId` | String(Long) | 否 | 车辆 ID |
| `items[].vehiclePlate` | String | 否 | 车牌,最长 64 字符 |
| `items[].vehicleModelId` | String(Long) | 否 | 车型 ID |
| `items[].vehicleModelName` | String | 否 | 车型名,最长 128 字符 |
| `items[].driverId` | String(Long) | 否 | 司机 ID |
| `items[].driverName` | String | 否 | 司机名,最长 64 字符 |
| `items[].amount` | Decimal | 是 | 金额,010 位整数、2 位小数 |
| `items[].paymentMethod` | String | 是 | `CASH_PAID/SIGNED/COMPANY_PAID` |
| `items[].settlementConfirmStatus` | String | 是 | `UNCONFIRMED/CONFIRMED` |
| `items[].remark` | String | 否 | 最长 500 字符 |
| `items[].voucherUrls` | String[] | 否 | 最多 9 个 http/https URL,单个最长 1024 字符 |
未知字段会被拒绝。
**GET/PUT 响应 `data`**
| 字段 | 类型 | 说明 |
|---|---|---|
| `orderId` | String(Long) | 订单 ID |
| `version` | Long | 当前草稿版本 |
| `totalAmount` | Decimal | 当前全部明细金额合计 |
| `allConfirmed` | Boolean | 非空行是否全部已确认;合法空集为 `true` |
| `items` | VehicleItem[] | 当前全量明细 |
| `items[].id` | String(Long) | 行 ID |
| `items[].sourceType` | String | `FLEET/MANUAL` |
| `items[].sourceTypeName` | String | 车务/手工 |
| `items[].serviceDate` | Date | 服务日期 |
| `items[].vehicleId` | String(Long) | 车辆 ID,可空 |
| `items[].vehiclePlate` | String | 车牌,可空 |
| `items[].vehicleModelId` | String(Long) | 车型 ID,可空 |
| `items[].vehicleModelName` | String | 车型名,可空 |
| `items[].driverId` | String(Long) | 司机 ID,可空 |
| `items[].driverName` | String | 司机名,可空 |
| `items[].amount` | Decimal | 核单金额 |
| `items[].paymentMethod` | String | 付款方式编码 |
| `items[].paymentMethodName` | String | 付款方式名称 |
| `items[].settlementConfirmStatus` | String | 确认状态 |
| `items[].settlementConfirmStatusName` | String | 未确认/已确认 |
| `items[].remark` | String | 备注 |
| `items[].voucherUrls` | String[] | 凭证 URL |
**业务边界**
- `FLEET` 行的日期、车辆、司机、金额和付款方式不可修改或删除;只允许修改确认状态、备注、凭证。
- 全量保存时必须带回全部 `FLEET` 行。手工行可新增、修改或从全量数组中删除。
- 手工新行必须先保存为 `UNCONFIRMED`;已有 ID 后可保存为 `CONFIRMED`
- `version` 不匹配返回 584108,必须重新 GET 后再保存。
- 旧响应字段 `frozen/requirementId/settlementReady/totalVehicleFee` 及 Fleet 对账明细字段不再对管理后台输出。
### 3.4 人员费用五个 Tab
**接口路径**
| 角色 | GET/PUT 路径 | `detail` 结构 |
|---|---|---|
| 领队 | `/v3/admin/order/:orderId/settlement/staff-fees/leaders` | `days + per_day` |
| 司机 | `/v3/admin/order/:orderId/settlement/staff-fees/drivers` | `days[] + extra_cost + extra_breakdown[]` |
| 导游 | `/v3/admin/order/:orderId/settlement/staff-fees/guides` | `persons[]` |
| 摄影师 | `/v3/admin/order/:orderId/settlement/staff-fees/photographers` | `persons[]` |
| 其他 | `/v3/admin/order/:orderId/settlement/staff-fees/others` | `items[]` |
**PUT 请求体**
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `items` | StaffItem[] | 是 | 当前角色全量数组;空数组清空该 Tab 可删除的行 |
| `items[].id` | String(Long) | 更新时是 | 已保存行 ID;新行为空 |
| `items[].sourceType` | String | 是 | `STAFF_ASSIGNMENT/MANUAL/SYSTEM` |
| `items[].staffId` | String(Long) | 否 | 人员安排 ID;聚合或手工行可空 |
| `items[].detail` | Object | 是 | 由路径角色固定,结构见下表 |
| `items[].reimburse` | Decimal | 否 | 小额报销,空按 0 |
| `items[].paymentMethod` | String | 否 | 空按 `COMPANY_PAID` |
| `items[].voucherUrls` | String[] | 否 | 最多 9 个 http/https URL |
| `items[].settlementConfirmStatus` | String | 是 | `UNCONFIRMED/CONFIRMED` |
| `items[].settleStatus` | String | 否 | 辅助人员 `PENDING/COMPLETED`,空按 `PENDING` |
| `items[].settledDate` | Date | 否 | 辅助人员结算日期 |
| `items[].transferRef` | String | 条件必填 | `settleStatus=COMPLETED` 时必填,最长 128 字符 |
| `items[].remark` | String | 否 | 最长 500 字符 |
**角色 `detail` 字段**
| 路径角色 | 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| leaders | `days` | Integer | 是 | 天数,最小 0 |
| leaders | `per_day` | Decimal | 是 | 每天费用,最小 0 |
| drivers | `days` | DriverDay[] | 是 | 服务日明细 |
| drivers | `days[].service_date` | Date | 是 | 服务日期 |
| drivers | `days[].vehicle_brief` | String | 否 | 车辆摘要 |
| drivers | `days[].daily_fee` | Decimal | 是 | 日费,仅回显,不计入人员费用 |
| drivers | `days[].is_used` | Boolean | 否 | 是否使用 |
| drivers | `days[].note` | String | 否 | 备注 |
| drivers | `extra_cost` | Decimal | 否 | 额外费用,空按 0 |
| drivers | `extra_breakdown` | ExtraItem[] | 否 | 合计必须等于 `extra_cost` |
| drivers | `extra_breakdown[].name` | String | 是 | 费用名 |
| drivers | `extra_breakdown[].amount` | Decimal | 是 | 金额,最小 0 |
| drivers | `extra_breakdown[].note` | String | 否 | 备注 |
| guides/photographers | `persons` | Person[] | 是 | 人员计费明细 |
| guides/photographers | `persons[].name` | String | 是 | 姓名 |
| guides/photographers | `persons[].days` | Integer | 是 | 天数,最小 0 |
| guides/photographers | `persons[].per_day` | Decimal | 是 | 每天费用,最小 0 |
| guides/photographers | `persons[].note` | String | 否 | 备注 |
| others | `items` | OtherItem[] | 是 | 其他人员费用项 |
| others | `items[].name` | String | 是 | 费用名称 |
| others | `items[].amount` | Decimal | 是 | 金额,最小 0 |
| others | `items[].note` | String | 否 | 备注 |
**GET 响应 `data`**
| 字段 | 类型 | 说明 |
|---|---|---|
| `totalActualCost` | Decimal | 当前 Tab 实际费用合计 |
| `items` | StaffItem[] | 已保存行;未保存时可返回候选草稿 |
| `items[].id` | String(Long) | 行 ID;未保存候选为空 |
| `items[].sourceType` | String | 来源编码 |
| `items[].sourceTypeName` | String | 人员安排/手工/系统 |
| `items[].staffId` | String(Long) | 人员安排 ID,可空 |
| `items[].staffName` | String | 人员姓名或聚合摘要 |
| `items[].detail` | Object | 对应角色明细 |
| `items[].totalPlannedCost` | Decimal | 计划成本 |
| `items[].totalActualCost` | Decimal | 实际成本 |
| `items[].reimburse` | Decimal | 小额报销 |
| `items[].paymentMethod` | String | 付款方式 |
| `items[].voucherUrls` | String[] | 凭证 URL |
| `items[].settlementConfirmStatus` | String | 确认状态 |
| `items[].settlementConfirmStatusName` | String | 未确认/已确认 |
| `items[].settleStatus` | String | 辅助人员结算状态;主报账人为空 |
| `items[].settledDate` | Date | 结算日期 |
| `items[].transferRef` | String | 转账流水号 |
| `items[].isPrimaryReporter` | Boolean | 是否主报账人 |
| `items[].remark` | String | 备注 |
PUT 成功返回统一成功包,`data=null`
### 3.5 餐食费用
**接口**
| 方法 | 路径 | 请求/响应 |
|---|---|---|
| GET | `/v3/admin/order/:orderId/settlement/meals` | `data` 为 MealItem[] |
| POST | `/v3/admin/order/:orderId/settlement/meals` | 请求 MealSave;响应 MealItem |
| PUT | `/v3/admin/order/:orderId/settlement/meals/:settlementId` | 请求 MealSave;响应 MealItem |
**MealSave 请求**
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `mealType` | String | 是 | `BREAKFAST/LUNCH/DINNER` |
| `mealDate` | Date | 否 | 发生日期 |
| `mealName` | String | 是 | 最长 200 字符 |
| `quantity` | Integer | 是 | 110000 |
| `unitPrice` | Decimal | 是 | 最多 8 位整数、2 位小数,最小 0 |
| `paymentMethod` | String | 是 | `CASH_PAID/COMPANY_PAID/SIGNED` |
| `sourceType` | String | 是 | `MEAL_ASSIGNMENT/MANUAL/SYSTEM`;新增接口请传 `MANUAL` |
| `settlementConfirmStatus` | String | 是 | `UNCONFIRMED/CONFIRMED` |
| `voucherUrls` | String[] | 否 | 最多 9 个 http/https URL |
| `remark` | String | 否 | 最长 512 字符 |
`unitPrice × quantity` 不得超过 `99999999.99`
**MealItem 响应**
| 字段 | 类型 | 说明 |
|---|---|---|
| `id` | String(Long) | 餐食费用 ID |
| `mealType` | String | 餐型 |
| `mealDate` | Date | 发生日期 |
| `mealName` | String | 餐食名称 |
| `quantity` | Integer | 数量 |
| `unitPrice` | String(Decimal) | 单价 |
| `actualAmount` | String(Decimal) | 实际金额 |
| `paymentMethod` | String | 付款类型 |
| `sourceType` | String | 来源编码 |
| `sourceTypeName` | String | 餐饮安排/手工/系统 |
| `voucherUrls` | String[] | 凭证 URL |
| `settlementConfirmStatus` | String | 确认状态 |
| `settlementConfirmStatusName` | String | 未确认/已确认 |
| `remark` | String | 备注 |
POST 创建的是手工行,必须先传 `UNCONFIRMED`;PUT 已存在行时可传 `CONFIRMED`,且不得改变原 `sourceType`
### 3.6 其他支出
**接口**
| 方法 | 路径 | 请求/响应 |
|---|---|---|
| GET | `/v3/admin/order/:orderId/settlement/other-expenses` | `data` 为 OtherExpenseItem[] |
| POST | `/v3/admin/order/:orderId/settlement/other-expenses` | 请求 OtherExpenseSave;响应 OtherExpenseItem |
| PUT | `/v3/admin/order/:orderId/settlement/other-expenses/:settlementId` | 请求 OtherExpenseSave;响应 OtherExpenseItem |
**OtherExpenseSave 请求**
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `expenseType` | String | 是 | `FUEL/TOLL/PARKING/RENTAL/MAINTENANCE/OTHER` |
| `projectName` | String | 是 | 最长 200 字符 |
| `expenseDate` | Date | 否 | 发生日期 |
| `actualAmount` | Decimal | 是 | 最多 8 位整数、2 位小数,最小 0 |
| `paymentMethod` | String | 是 | `CASH_PAID/COMPANY_PAID/SIGNED` |
| `settlementConfirmStatus` | String | 是 | `UNCONFIRMED/CONFIRMED` |
| `voucherUrls` | String[] | 否 | 最多 9 个 http/https URL |
| `remark` | String | 否 | 最长 512 字符 |
**OtherExpenseItem 响应**
| 字段 | 类型 | 说明 |
|---|---|---|
| `id` | String(Long) | 其他支出 ID |
| `expenseType` | String | 支出类型 |
| `projectName` | String | 项目名称 |
| `expenseDate` | Date | 发生日期 |
| `actualAmount` | String(Decimal) | 实际金额 |
| `paymentMethod` | String | 付款类型 |
| `sourceType` | String | `MANUAL/SYSTEM` |
| `sourceTypeName` | String | 手工/系统 |
| `voucherUrls` | String[] | 凭证 URL |
| `settlementConfirmStatus` | String | 确认状态 |
| `settlementConfirmStatusName` | String | 未确认/已确认 |
| `remark` | String | 备注 |
POST 创建的是 `MANUAL` 行且必须先为 `UNCONFIRMED`;已有 ID 后通过 PUT 可改为 `CONFIRMED`
### 3.7 其他收入
**接口**
| 方法 | 路径 | 请求/响应 |
|---|---|---|
| GET | `/v3/admin/order/:orderId/settlement/other-incomes` | `data` 为列表聚合对象 |
| POST | `/v3/admin/order/:orderId/settlement/other-incomes` | 请求 Create;响应 OtherIncomeItem |
| PUT | `/v3/admin/order/:orderId/settlement/other-incomes/:incomeId` | 请求 Update;响应 OtherIncomeItem |
**Create/Update 请求**
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `requestId` | String | 仅 POST 是 | 同订单永久唯一,最长 64 字符 |
| `incomeDate` | Date | 是 | 收入日期 |
| `projectName` | String | 是 | 最长 100 字符 |
| `projectCategory` | String | 是 | 启用字典值,最长 64 字符 |
| `specification` | String | 否 | 票种/规格,最长 100 字符 |
| `quantity` | Decimal | 是 | 最多 8 位整数、4 位小数,最小 0 |
| `unitPrice` | Decimal | 是 | 最多 8 位整数、2 位小数,最小 0 |
| `settlementAmount` | Decimal | 是 | 最多 8 位整数、2 位小数,必须大于 0,且等于数量乘单价四舍五入到 2 位) |
| `paymentMethod` | String | 是 | `CASH_PAID/COMPANY_PAID/SIGNED` |
| `settlementConfirmStatus` | String | 是 | `UNCONFIRMED/CONFIRMED` |
| `voucherUrls` | String[] | 否 | 最多 9 个 http/https URL |
| `remark` | String | 否 | 最长 500 字符 |
**OtherIncomeItem 响应**
| 字段 | 类型 | 说明 |
|---|---|---|
| `id` | String(Long) | 其他收入 ID |
| `requestId` | String | 手工新增幂等 ID;系统投影为空 |
| `incomeDate` | Date | 收入日期 |
| `projectName` | String | 项目名称 |
| `projectCategory` | String | 项目类别 |
| `projectCategoryName` | String | 项目类别名称 |
| `specification` | String | 票种/规格 |
| `quantity` | Decimal | 数量 |
| `unitPrice` | Decimal | 核算单价 |
| `settlementAmount` | Decimal | 核算金额 |
| `paymentMethod` | String | 付款类型 |
| `paymentMethodName` | String | 付款类型名称 |
| `voucherUrls` | String[] | 凭证 URL |
| `settlementConfirmStatus` | String | 确认状态 |
| `settlementConfirmStatusName` | String | 未确认/已确认 |
| `remark` | String | 备注 |
| `sourceType` | String | `MANUAL/SYSTEM` |
| `sourceTypeName` | String | 手工/系统 |
| `sourceId` | String(Long) | 关联来源 ID |
**GET 聚合响应**
| 字段 | 类型 | 说明 |
|---|---|---|
| `items` | OtherIncomeItem[] | 其他收入明细 |
| `deductions` | Deduction[] | 只读减费明细 |
| `deductions[].id` | String(Long) | 减费 ID |
| `deductions[].discountName` | String | 减费名称 |
| `deductions[].discountAmount` | Decimal | 减费金额 |
| `deductions[].sourceType` | String | 减费来源 |
| `deductions[].sourceId` | String(Long) | 来源业务 ID |
| `deductions[].createdAt` | DateTime | 创建时间 |
| `summary.surchargeAmount` | Decimal | 有效增费合计 |
| `summary.discountAmount` | Decimal | 有效减费合计 |
| `summary.netAdjustmentAmount` | Decimal | 增费减去减费 |
手工新增行的公开来源为 `MANUAL`;系统自动投影行公开来源为 `SYSTEM`。原公开值 `ORDER_SURCHARGE` 不再返回。
### 3.8 完成核单
**接口**`POST /v3/admin/order/:orderId/settlement/finalize`
**请求体**
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `remark` | String | 否 | 整体备注,最长 500 字符 |
| `reimbursementExpectedSourceFingerprint` | String | 是 | 主报账表 64 位小写 SHA-256 指纹 |
| `groupExpectedSourceFingerprint` | String | 是 | 单团核算表 64 位小写 SHA-256 指纹 |
| `reimbursementConfirmation` | Object | 是 | 主报账确认凭据 |
| `reimbursementConfirmation.transferDate` | Date | 条件必填 | 主报账净额非 0 时必填 |
| `reimbursementConfirmation.transferRef` | String | 条件必填 | 主报账净额非 0 时必填,最长 128 字符 |
| `reimbursementConfirmation.advanceSettledFlag` | Boolean | 是 | 预支是否已处理;`false` 是合法值 |
| `reimbursementConfirmation.signedVoucher` | Object | 是 | 签字凭证 |
| `reimbursementConfirmation.signedVoucher.files` | File[] | 是 | 19 项 |
| `reimbursementConfirmation.signedVoucher.files[].name` | String | 否 | 文件名,最长 255 字符 |
| `reimbursementConfirmation.signedVoucher.files[].url` | String | 是 | 文件 URL,最长 1024 字符 |
| `reimbursementConfirmation.signedVoucher.note` | String | 否 | 最长 500 字符 |
**响应 `data`**
| 字段 | 类型 | 说明 |
|---|---|---|
| `summaryId` | String(Long) | 核单汇总 ID |
| `finalSnapshotId` | String(Long) | 终态快照 ID |
| `finalSnapshotVersionNo` | Integer | 快照版本 |
| `finalSnapshotStatus` | String | 成功时为 `FINALIZED` |
| `orderId` | String(Long) | 订单 ID |
| `settledAt` | DateTime | 核单完成时间 |
| `totalAmount` | String(Decimal) | 订单总金额快照 |
| `paidAmount` | String(Decimal) | 已付金额快照 |
| `balanceAmount` | String(Decimal) | 尾款金额快照 |
| `roomCost` | String(Decimal) | 住宿实际成本 |
| `ticketCost` | String(Decimal) | 门票实际成本 |
| `staffCost` | String(Decimal) | 人员费用实际成本 |
| `subsidyCost` | String(Decimal) | 补助实际成本 |
| `mealCost` | String(Decimal) | 餐食实际成本 |
| `vehicleCost` | String(Decimal) | 车辆实际成本 |
| `otherExpenseCost` | String(Decimal) | 其他支出实际成本 |
| `insurancePremium` | String(Decimal) | 保险实际保费 |
| `totalActualCost` | String(Decimal) | 总实际成本 |
| `driverTransferAmount` | String(Decimal) | 给主报账人的转回金额 |
| `profitAmount` | String(Decimal) | 公司毛利 |
| `profitRate` | Decimal | 毛利率小数 |
| `orderStatusAfter` | String | 完成后的订单状态 |
| `mqTriggered` | Boolean | 当前固定为 `false` |
| `warnings` | String[] | 不阻塞完成核单的软预警 |
**业务边界**
- 住宿、门票/游玩、餐食、车辆、导游、摄影、其他收入、其他支出八类来源必须同步完成。
- 任一非空分类存在 `UNCONFIRMED` 行时,finalize 返回 584310,不生成终态快照。
- 系统来源事实变化会使对应行重新变为 `UNCONFIRMED`;应刷新、复核并保存后再 finalize。
## 4. 接口入参汇总
| 输入类型 | 适用接口 | 关键变化 |
|---|---|---|
| 路径参数 | 全部 26 个接口 | `orderId` 必填;行级修改另有 `settlementId/incomeId` |
| 全量明细 | 住宿、门票、车辆、五个人员 Tab | 必须提交完整 `items`;新增手工行先传 `UNCONFIRMED` |
| 单行保存 | 餐食、其他支出、其他收入 | POST 新增先未确认,PUT 已有行可确认 |
| 车辆版本 | 车辆 PUT | 必须原样回传最近 GET 的 `version` |
| 完成核单凭据 | finalize | 双报告指纹 + 主报账转账/签字凭据 |
完整字段、必填性和校验已分别内联在 §3.1§3.8。
## 5. 出参字段汇总
| 变化 | 适用响应 |
|---|---|
| 新增 `sourceType/sourceTypeName` | 人员、餐食、其他支出;其他收入的来源语义调整 |
| 新增 `settlementConfirmStatus/settlementConfirmStatusName` | 门票;餐食、其他支出、人员补齐名称 |
| Long ID 按字符串返回 | 住宿、门票、人员、车辆以及已有明确字符串序列化的资金明细 |
| 新车辆草稿结构 | `orderId/version/totalAmount/allConfirmed/items` |
| 删除车辆内部/兼容字段 | 不再输出 `frozen/requirementId/settlementReady/totalVehicleFee` 及 Fleet 对账字段 |
## 6. 枚举 / 数据字典
### 6.1 住宿 `sourceType`
| 值 | 中文 | 说明 |
|---|---|---|
| `HOUSE_ASSIGNMENT` | 配房结果 | 系统配房来源 |
| `MANUAL` | 手工 | 管理后台手工新增 |
| `SYSTEM` | 系统 | 其他系统来源;替代旧公开值 `TEMPLATE` |
| `TEMPLATE` | 历史兼容 | 仅请求兼容,响应不返回 |
### 6.2 门票 `sourceType`
| 值 | 中文 | 说明 |
|---|---|---|
| `SCENIC_ASSIGNMENT` | 景区 | 景区安排来源 |
| `ACTIVITY_ASSIGNMENT` | 游玩项目 | 活动安排来源 |
| `MANUAL` | 手工 | 手工新增;响应统一值 |
| `CUSTOM_ASSIGNMENT` | 历史兼容 | 仅请求兼容,响应归一为 `MANUAL` |
### 6.3 餐食 `sourceType`
| 值 | 中文 | 说明 |
|---|---|---|
| `MEAL_ASSIGNMENT` | 餐饮安排 | 系统餐饮安排来源 |
| `MANUAL` | 手工 | 管理后台新增 |
| `SYSTEM` | 系统 | 其他系统来源 |
### 6.4 车辆 `sourceType`
| 值 | 中文 | 说明 |
|---|---|---|
| `FLEET` | 车务 | 车务同步行,业务字段不可改删 |
| `MANUAL` | 手工 | 核单页手工补录 |
### 6.5 人员 `sourceType`
| 值 | 中文 | 说明 |
|---|---|---|
| `STAFF_ASSIGNMENT` | 人员安排 | 系统人员安排来源 |
| `MANUAL` | 手工 | 手工新增 |
| `SYSTEM` | 系统 | 其他系统来源 |
### 6.6 其他收入/其他支出 `sourceType`
| 值 | 中文 | 说明 |
|---|---|---|
| `MANUAL` | 手工 | 管理后台创建 |
| `SYSTEM` | 系统 | 自动投影或系统来源 |
### 6.7 `settlementConfirmStatus`
| 值 | 中文 | 说明 |
|---|---|---|
| `UNCONFIRMED` | 未确认 | 首次系统同步或手工新行的初始状态 |
| `CONFIRMED` | 已确认 | 已有行复核后保存的状态 |
### 6.8 `paymentMethod`
| 值 | 中文 | 说明 |
|---|---|---|
| `CASH_PAID` | 现付 | 现场/主报账人支付 |
| `COMPANY_PAID` | 公司付款 | 公司直接支付 |
| `SIGNED` | 签单 | 签单结算 |
### 6.9 餐型 `mealType`
| 值 | 中文 |
|---|---|
| `BREAKFAST` | 早餐 |
| `LUNCH` | 午餐 |
| `DINNER` | 晚餐 |
### 6.10 支出类型 `expenseType`
| 值 | 中文 |
|---|---|
| `FUEL` | 油费 |
| `TOLL` | 过路费 |
| `PARKING` | 停车费 |
| `RENTAL` | 租赁费 |
| `MAINTENANCE` | 维修保养 |
| `OTHER` | 其他 |
### 6.11 人员辅助结算状态 `settleStatus`
| 值 | 中文 | 说明 |
|---|---|---|
| `PENDING` | 待结算 | 默认值 |
| `COMPLETED` | 已结算 | 必须同时提交 `transferRef` |
## 7. 错误码
| code | 含义 | 触发场景 |
|---|---|---|
| `400` | 参数校验失败 | 必填缺失、格式/长度/枚举错误、车辆或人员请求出现未知字段 |
| `584001/584010/584020/584050/584070` | 订单不存在 | 对应住宿、门票、人员、finalize 或通用查询找不到订单 |
| `584002/584011/584021` | 当前状态不可写 | 住宿、门票、人员费用不在允许的核单阶段 |
| `584006/584012/584022` | 枚举或角色非法 | 住宿付款、门票来源、人员角色非法 |
| `584067/584068/584069` | 住宿资源无效或暂不可用 | 手工酒店/房型无效或资源服务不可用 |
| `584071` | 无权访问该订单 | 公司隔离或现有订单权限不满足 |
| `584073` | 其他收入不存在 | `incomeId` 不属于当前订单 |
| `584074` | 当前状态不允许修改其他收入 | 核单状态不可写 |
| `584076` | 其他收入金额不一致 | `settlementAmount != quantity × unitPrice` |
| `584077` | 存在未确认的其他收入 | 生成报告或完成核单前仍有其他收入未确认 |
| `584086` | 无权修改核单资金数据 | 非主管、管理员或财务 |
| `584087` | `requestId` 冲突 | 同订单相同 `requestId` 被另一笔请求占用 |
| `584089` | 核单或结算已完成 | 再次修改资金明细 |
| `584090/584091` | 餐食/其他支出不存在 | 行 ID 不属于当前订单 |
| `584092` | 存在未确认的人员费用 | 生成报告或完成核单前仍有人员费用未确认 |
| `584094/584095` | 餐食/其他支出字段非法 | 字段越界或试图改变系统来源 |
| `584096/584097` | 付款方式/凭证非法 | 枚举错误或 URL 数量、格式错误 |
| `584098` | 餐食或其他支出存在未确认记录 | 生成报告或完成核单前仍有餐食/其他支出未确认 |
| `584100/584101/584102` | 车辆来源不可用/未就绪/为空 | 车务数据不可读、未完结/未确认、无可核单费用 |
| `584103/584104/584105` | 其他收入字典非法或不可用 | 项目类别、规格无效或字典不可用 |
| `584106` | 确认状态非法 | 非 `UNCONFIRMED/CONFIRMED` |
| `584107` | 手工新增行必须先未确认 | `id=null` 的手工新行直接传 `CONFIRMED` |
| `584108` | 车辆草稿版本冲突 | PUT 的 `version` 已过期 |
| `584109` | 车务来源字段不可改删 | 修改/漏传 `FLEET` 行的权威字段 |
| `584310` | 八类核单未全部确认或数据已变化 | finalize 前有非空未确认行、来源未就绪 |
| `584315` | 报告来源已变化 | finalize 双报告指纹过期 |
| `584317` | 当前报告状态不允许操作 | finalize 凭据结构或状态不满足 |
| `584325` | 完成核单必须提交当前指纹 | 双报告指纹缺失 |
## 验证证据8. 示例:典型 / 边界 / 异常)
已完成以下测试环境路由与业务负向验证:
- 部署任务 `80f1695a` 成功,order-v3 主、副实例滚动完成。
- 两个核算中订单实调
`GET /v3/admin/order/:orderId/settlement/step3/vehicles`
均进入新代码并返回业务前置码 `584102`,证明新路由已生效。
- 旧 `GET /v3/admin/order/:orderId/settlement/vehicle-fees` 返回 `404`,证明旧入口已下线。
本节下列 JSON 是按已合并 Controller/VO 契约给出的自包含调用示例。由于测试订单缺少可核单车辆费用,本次未取得车辆 DTO 正向数据,也未完成车辆链路 Full E2E;不得把上述 584102 负向结果描述为正向业务通过。
### 8.1 典型成功:确认车辆系统来源行
**请求**
```http
PUT /v3/admin/order/900000000001/settlement/step3/vehicles
Authorization: Bearer <JWT>
Content-Type: application/json
```
```json
{
"version": 3,
"items": [
{
"id": "930000000001",
"sourceType": "FLEET",
"serviceDate": "2026-07-30",
"vehicleId": "880000000001",
"vehiclePlate": "藏A12345",
"vehicleModelId": "870000000001",
"vehicleModelName": "七座商务车",
"driverId": "860000000001",
"driverName": "张师傅",
"amount": 1200.00,
"paymentMethod": "COMPANY_PAID",
"settlementConfirmStatus": "CONFIRMED",
"remark": "金额已核对",
"voucherUrls": []
}
]
}
```
**响应**
```json
{
"code": 200,
"message": "成功",
"data": {
"orderId": "900000000001",
"version": 4,
"totalAmount": 1200.00,
"allConfirmed": true,
"items": [
{
"id": "930000000001",
"sourceType": "FLEET",
"sourceTypeName": "车务",
"serviceDate": "2026-07-30",
"vehicleId": "880000000001",
"vehiclePlate": "藏A12345",
"vehicleModelId": "870000000001",
"vehicleModelName": "七座商务车",
"driverId": "860000000001",
"driverName": "张师傅",
"amount": 1200.00,
"paymentMethod": "COMPANY_PAID",
"paymentMethodName": "公司付款",
"settlementConfirmStatus": "CONFIRMED",
"settlementConfirmStatusName": "已确认",
"remark": "金额已核对",
"voucherUrls": []
}
]
},
"success": true
}
```
### 8.2 边界情况:合法空车辆草稿
无当前用车需求时,GET 可返回合法空集;`allConfirmed=true` 表示“空集中没有未确认行”,不表示存在车辆费用。
**请求**
```http
GET /v3/admin/order/900000000001/settlement/step3/vehicles
Authorization: Bearer <JWT>
```
无请求体。
**响应**
```json
{
"code": 200,
"message": "成功",
"data": {
"orderId": "900000000001",
"version": 1,
"totalAmount": 0.00,
"allConfirmed": true,
"items": []
},
"success": true
}
```
### 8.3 业务失败:手工新行直接确认
**请求**
```http
POST /v3/admin/order/900000000001/settlement/meals
Authorization: Bearer <JWT>
Content-Type: application/json
```
```json
{
"mealType": "LUNCH",
"mealDate": "2026-07-30",
"mealName": "团队午餐",
"quantity": 10,
"unitPrice": 50.00,
"paymentMethod": "CASH_PAID",
"sourceType": "MANUAL",
"settlementConfirmStatus": "CONFIRMED",
"voucherUrls": [],
"remark": null
}
```
**响应**
```json
{
"code": 584107,
"message": "手工新增核单明细必须先保存为未确认",
"data": null,
"success": false
}
```
## 9. 业务边界
- ✅ **系统来源首次同步**:生成已有 ID 的 `UNCONFIRMED` 行;复核后可直接在对应 PUT 中保存为 `CONFIRMED`
- ✅ **手工新增**:第一次必须保存为 `UNCONFIRMED`;接口返回 ID 后,第二次更新才允许保存为 `CONFIRMED`
- ✅ **来源统一**:手工行统一公开为 `MANUAL`;系统行公开为各分类系统来源值,无法细分的系统行为 `SYSTEM`
- ❌ **不可混用确认和辅助结算状态**`settlementConfirmStatus` 表示核单确认;人员 `settleStatus` 表示辅助人员款项是否结清。
- ❌ **不可修改系统权威字段**:系统来源事实变化后应重新 GET;车辆 `FLEET` 行不得由前端改删。
- ⚠️ **finalize 门禁**:八个核单分类来源必须就绪,且每个非空分类全部逐行 `CONFIRMED`
- ⚠️ **空分类**:合法空分类没有未确认行,但来源同步仍必须就绪;`allConfirmed=true` 不等于有费用。
## 10. 修改前后对比
### 10.1 字段级对比
| 范围 | 改前 | 改后 |
|---|---|---|
| 住宿系统来源 | `TEMPLATE` | `SYSTEM``TEMPLATE` 仅兼容旧入参 |
| 门票手工来源 | 可能返回 `CUSTOM_ASSIGNMENT` | 统一返回 `MANUAL` |
| 其他收入来源 | `ORDER_SURCHARGE` | `MANUAL``SYSTEM` |
| 门票行确认 | 无逐行确认字段 | 新增 `settlementConfirmStatus/Name` |
| 人员请求行 | 无 `id/sourceType/settlementConfirmStatus` | 三字段纳入全量保存契约 |
| 餐食请求/响应 | 无公开来源,确认名称不完整 | 增加 `sourceType/sourceTypeName/settlementConfirmStatusName` |
| 其他支出响应 | 无公开来源和确认名称 | 增加 `sourceType/sourceTypeName/settlementConfirmStatusName` |
| 住宿/门票/人员 ID | 部分按 JSON 数字输出 | 明细 `id`、来源 ID 按字符串输出 |
| 车辆顶层响应 | `frozen/requirementId/settlementReady/totalVehicleFee/items` | `orderId/version/totalAmount/allConfirmed/items` |
| 车辆行响应 | 暴露 Fleet 对账、冻结和自动车费字段 | 仅输出核单需要的来源、车辆、司机、金额、付款、确认、凭证字段 |
### 10.2 行为级对比
| 行为 | 改前 | 改后 |
|---|---|---|
| 系统派生行初始状态 | 分类规则不一致,部分直接视为已确认 | 统一先 `UNCONFIRMED`,用户复核后保存为 `CONFIRMED` |
| 手工新增并确认 | 部分接口允许一次保存即确认 | 必须先未确认,取得 ID 后再确认 |
| 车辆入口 | 旧 `/settlement/vehicle-fees` 已下线且无新独立编辑入口 | 使用 `/settlement/step3/vehicles` GET/PUT |
| 车辆并发保存 | 无前端草稿版本 | 必须携带 `version`,冲突时刷新 |
| 完成核单 | 分类确认来源不完全统一 | 只接受八类来源就绪且非空行全部已确认的数据 |
## 11. 影响评估 / 回滚
### 11.1 影响评估
- **是否破坏向后兼容**:是。车辆入口和响应结构为新契约;其他收入 `sourceType` 值发生变化;多个请求/响应新增确认与来源字段。
- **前端是否必须同步上线**:是。需切换车辆接口、适配字符串 ID、新来源枚举和“先保存未确认、再确认”的交互。
### 11.2 回滚说明
若后端回滚,前端需同时回滚车辆 Step3 新入口及新增字段依赖;旧
`/settlement/vehicle-fees` 两个接口在本次变更前已下线,不能作为回滚兜底。
## 12. 注意事项
- 删除对旧 `GET /settlement/vehicle-fees``POST /settlement/vehicle-fees/confirm` 的任何残留调用。
- 车辆保存必须回传最近 GET 的 `version` 和全部 `FLEET` 行;584108 时刷新后让用户重新确认。
- 不再把 `ORDER_SURCHARGE``TEMPLATE``CUSTOM_ASSIGNMENT` 当作新响应值。
- 所有 Long 类型字符串 ID 按字符串比较、传递,不转为 JavaScript Number。
- finalize 返回 584310 时,应刷新相关 Tab;来源变化可能已把已确认行重新置为未确认。
## 13. 关联 / 联系人
### 13.1 链接
- **Issue**: [#5356](https://git.1814.love:8443/wx/HL/issues/5356)
- **PR**: [#5362](https://git.1814.love:8443/wx/HL/pulls/5362)
- **Feature commit**: [6e396f6fc4](https://git.1814.love:8443/wx/HL/commit/6e396f6fc48fbf6581e87224bb85f2c811759727)
- **Merge commit**: [cfac945db2](https://git.1814.love:8443/wx/HL/commit/cfac945db268640b0b9e60b4d8c7ab55739a69e3)
### 13.2 联系人
- **后端负责人**: @yaosutu