From dd56a2b0e54c91e0dda4495db2fddc0083613066 Mon Sep 17 00:00:00 2001 From: yaosutu <770858045@qq.com> Date: Sat, 15 Aug 2026 14:24:50 +0800 Subject: [PATCH] =?UTF-8?q?docs(changelog):=20=E6=A0=B8=E5=8D=95=E8=BD=A6?= =?UTF-8?q?=E8=BE=86=E8=B4=B9=E7=94=A8=E5=BD=92=E5=85=B6=E4=BB=96=E6=94=AF?= =?UTF-8?q?=E5=87=BA=EF=BC=88#5969=20/=20PR=20#5970=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 单团核算表 vehicleLines 行删 4 字段,5 类车辆费用行迁到 otherExpenseLines, expenseType 值域扩为 6 类;管理后台端 changelog。 --- ...单车辆费用归其他支出-修改接口-管理后台.md | 332 ++++++++++++++++++ 1 file changed, 332 insertions(+) create mode 100644 changelogs-v2/2026-08/15_5969_核单车辆费用归其他支出-修改接口-管理后台.md diff --git a/changelogs-v2/2026-08/15_5969_核单车辆费用归其他支出-修改接口-管理后台.md b/changelogs-v2/2026-08/15_5969_核单车辆费用归其他支出-修改接口-管理后台.md new file mode 100644 index 0000000..02c30a9 --- /dev/null +++ b/changelogs-v2/2026-08/15_5969_核单车辆费用归其他支出-修改接口-管理后台.md @@ -0,0 +1,332 @@ +--- +schema: "hl-changelog/v2" +ticket: "5969" +title: "核单车辆费用归其他支出——VEHICLE 只留 Fleet 配车日租,5 类车辆费用并入 OTHER_EXPENSE" +consumer: "admin" +change_type: "修改接口" +author: "yst" +backend_status: "deployed" +gateway_status: "verified" +frontend_status: "pending" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "" +status_note: "PR #5970 已合并 dev-v3(merge commit 522179ecfe),测试服已验证(实证单 HL20260811181352799:油费 300 归其他支出块,用车块只剩 3 行 Fleet 日租 3000)。破坏性变化:单团核算表 vehicleLines 行删 expenseType/expenseTypeName/projectName/expenseDate 4 字段;FUEL/TOLL/PARKING/RENTAL/MAINTENANCE 5 类车辆费用行从 vehicleLines 迁到 otherExpenseLines;otherExpenseLines.expenseType 值域由 OTHER 扩为 6 类。仅出参/归属口径变化,无入参变化、无 DDL。" +updated_at: "2026-08-15" +base: "dev-v3" +--- + +# 【修改接口·管理后台】核单车辆费用归其他支出——VEHICLE 只留 Fleet 配车日租,5 类车辆费用并入 OTHER_EXPENSE(#5969) + +## 1. 接口背景 + +单团核算表(reports/group)是管理后台订单核单页查看整团收入、成本、毛利全貌的只读报表,成本按 8 分类逐项展开(住宿/门票/餐食/用车/导游/摄影/其他支出/保险)。 + +此前分类口径存在一个错位:**油费、过路费、停车费、租车费、维修保养 5 类车辆费用在核单录入界面上本来就是在「其他支出」tab 录入的**,但单团核算表却把它们归到「用车(VEHICLE)」分类下展示,和录入界面不一致,财务看报表时同一笔费用录入位置和归集位置对不上。 + +本次变更把报表分类口径对齐录入界面: + +- 5 类车辆费用(FUEL/TOLL/PARKING/RENTAL/MAINTENANCE)从「用车」分类移到「其他支出(OTHER_EXPENSE)」分类; +- 「用车(VEHICLE)」分类此后只承载 Fleet 车务配车日租行(vehicle_fee 表逐日明细); +- 主报账人报账表(reports/reimbursement)的 OTHER_EXPENSE 展示块归属同步随动。 + +无入参变化、无新接口、无 DDL;totalCost 总成本口径不变。 + +## 2. 变更清单 + +| # | 位置 | 变更 | 类型 | +|---|------|------|------| +| 1 | vehicleLines[] 行 | **字段删除**:expenseType / expenseTypeName / projectName / expenseDate 4 个字段不再下发(车辆费用行已迁出本数组,这 4 个字段失去载体) | ⚠️ 破坏性删除 | +| 2 | vehicleLines[] 行归属 | **行为变化**:数组只含 Fleet 配车日租行(sourceType=FLEET);不再出现 5 类车辆费用行 | 🔧 行为变化 | +| 3 | otherExpenseLines[] 行归属 | **行为变化**:新增承载 5 类车辆费用行(expenseType=FUEL/TOLL/PARKING/RENTAL/MAINTENANCE),与原 OTHER 费用行、PHONE/OVERTIME 补贴行同数组混排(稀疏并集,每行仅本族字段非 null) | 🔧 行为变化 | +| 4 | otherExpenseLines[].expenseType | **值域扩大**:原来恒为 OTHER,现在可能返回 OTHER/FUEL/TOLL/PARKING/RENTAL/MAINTENANCE 6 值之一 | ✨ 枚举值域扩大 | +| 5 | 分类小计口径 | vehicleLines 合计下降、otherExpenseLines 合计上升(同一批行搬位置);**totalCost / paidCost / unpaidCost / grossProfit 不变** | 📝 口径声明 | +| 6 | 主报账人报账表 expenseLines | OTHER_EXPENSE 展示块(type=OTHER_EXPENSE 的行)同步纳入 5 类车辆费用行,其 expenseType 值域同步扩为 6 类 | 🔧 行为变化 | +| 7 | 预览态未确认行口径 | 未确认(UNCONFIRMED)车辆费用行旧口径挂 VEHICLE 下不计入成本;新口径归 OTHER_EXPENSE,与 OTHER 类型原有口径一致计入预览态成本。完成核单(finalize)门禁要求全行 CONFIRMED,**终态金额不变** | 📝 口径声明 | + +## 3. 接口详情 + +| 项 | 值 | +|---|---| +| 方法 + 路径 | GET /v3/admin/order/{orderId}/settlement/reports/group | +| 接口名 | 查询单团核算表 | +| 使用场景 | 管理后台订单核单页,查看整团收入/成本/毛利只读报表(含逐项明细) | +| 认证 | 管理后台 JWT(/v3/admin/* 走网关鉴权) | +| 角色限制 | 房务角色(HOUSE)不可访问,调了会被拦截(错误码 581045) | +| 幂等性 | 只读查询,幂等 | +| 限流 | 走网关默认限流,无接口级特殊限流 | + +同步受影响的接口(同 PR 一并说明,结构无变化、仅 OTHER_EXPENSE 展示块行归属随动): + +| 项 | 值 | +|---|---| +| 方法 + 路径 | GET /v3/admin/order/{orderId}/settlement/reports/reimbursement | +| 接口名 | 查询主报账人报账表 | +| 变化点 | expenseLines 中 type=OTHER_EXPENSE 的展示行纳入 5 类车辆费用行;expenseType 值域同步扩为 6 类 | + +## 4. 接口入参 + +### 4.1 路径参数 + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| orderId | Long | 是 | 订单 ID,必须 ≥ 1,否则 400 参数校验失败 | + +### 4.2 请求体 + +无请求体,无 Query 参数。 + +## 5. 出参字段 + +顶层结构不变(沿用 #5963 拍平后结构):抬头字段 + 收入/汇总金额字段 + incomeLines + 7 个成本分类明细数组(hotelLines/ticketLines/mealLines/vehicleLines/guideLines/photographerLines/otherExpenseLines)+ insuranceInfo。本 PR 只影响 vehicleLines 行结构与 otherExpenseLines 行归属/值域。 + +所有行 VO 均带 JsonInclude(NON_NULL):**null 字段不下发该键**,前端取值请用可选链。 + +### 5.1 vehicleLines[] 行(变更后,只含 Fleet 配车日租行) + +| 字段 | 类型 | 说明 | +|------|------|------| +| serviceDate | String(yyyy-MM-dd) | 服务日期 | +| startDate | String(yyyy-MM-dd) | 服务开始日期 | +| endDate | String(yyyy-MM-dd) | 服务结束日期 | +| vehiclePlate | String | 车牌号,如「蒙A-5376」 | +| vehicleModelName | String | 车型名称,如「坦克500」 | +| driverName | String | 司机姓名 | +| dailyPrice | BigDecimal | 日单价(即"核算单价"列),保留两位小数 | +| paymentTypeName | String | 车务付款类型名称,如「现金已付」 | +| amount | BigDecimal | 核算金额,保留两位小数,恒有值 | +| paymentMethod | String | 付款方式:CASH_PAID/COMPANY_PAID/SIGNED | +| paymentMethodName | String | 付款方式中文名(字典 settlement_payment_method,缺值回退硬编码) | +| sourceType | String | 明细来源类型,本数组恒为 FLEET | +| sourceTypeName | String | 来源中文名,本数组恒为「车务」 | +| remark | String | 备注;无备注时不下发 | +| voucherUrls | String[] | 凭证 URL 数组;无凭证时不下发 | + +**已删除(不再下发)**:expenseType / expenseTypeName / projectName / expenseDate。quantity 恒 null 本就不输出。 + +### 5.2 otherExpenseLines[] 行(变更后,费用行 6 类 + 补贴行稀疏并集) + +| 字段 | 类型 | 说明 | +|------|------|------| +| expenseDate | String(yyyy-MM-dd) | 费用发生日期 | +| projectName | String | 项目名称,如「全程油费」「全程矿泉水」 | +| expenseType | String | [EXPENSE 族] 费用类型,**值域 6 值**:OTHER/FUEL/TOLL/PARKING/RENTAL/MAINTENANCE | +| expenseTypeName | String | [EXPENSE 族] 费用类型中文名(字典 expense_type,后端已回填,前端无需再调字典) | +| subsidyType | String | [SUBSIDY 族] 补贴类型:PHONE/OVERTIME | +| subsidyTypeName | String | [SUBSIDY 族] 补贴类型中文名(字典 subsidy_type) | +| amount | BigDecimal | 核算金额(实际金额),保留两位小数,恒有值 | +| paymentMethod | String | 付款方式:CASH_PAID/COMPANY_PAID/SIGNED | +| paymentMethodName | String | 付款方式中文名(字典 settlement_payment_method,缺值回退硬编码) | +| sourceType | String | 明细来源类型;无来源时不下发 | +| sourceTypeName | String | 来源中文名(SettlementDetailSourceType 枚举 label) | +| remark | String | 备注;无备注时不下发 | +| voucherUrls | String[] | 凭证 URL 数组;无凭证时不下发 | + +稀疏并集规则:**EXPENSE 族行只输出 expenseType/expenseTypeName,SUBSIDY 族行只输出 subsidyType/subsidyTypeName**,两族字段互斥,另一族恒 null(不下发)。判别方式:expenseType 键存在即费用行,subsidyType 键存在即补贴行。 + +## 6. 枚举 / 数据字典 + +### 6.1 expenseType(字典 expense_type,存量字典已含 6 值,前端无需改字典配置) + +| 值 | 中文名 | 说明 | +|----|--------|------| +| FUEL | 油费 | 本次从 VEHICLE 迁入 | +| TOLL | 过路费 | 本次从 VEHICLE 迁入 | +| PARKING | 停车费 | 本次从 VEHICLE 迁入 | +| RENTAL | 租车费 | 本次从 VEHICLE 迁入 | +| MAINTENANCE | 维修保养 | 本次从 VEHICLE 迁入 | +| OTHER | 其他 | 原有,保持不变 | + +### 6.2 subsidyType(字典 subsidy_type,本接口仅出现 2 值) + +| 值 | 中文名 | +|----|--------| +| PHONE | 话补 | +| OVERTIME | 加班补贴 | + +### 6.3 paymentMethod(字典 settlement_payment_method) + +| 值 | 中文名 | +|----|--------| +| CASH_PAID | 现金已付 | +| COMPANY_PAID | 公司支付 | +| SIGNED | 签单 | + +### 6.4 sourceType(SettlementDetailSourceType 枚举 label,非字典) + +| 值 | 中文名 | +|----|--------| +| MANUAL | 手工 | +| HOUSE_ASSIGNMENT | 配房结果 | +| SCENIC_ASSIGNMENT | 景区 | +| ACTIVITY_ASSIGNMENT | 游玩项目 | +| MEAL_ASSIGNMENT | 餐饮安排 | +| FLEET | 车务 | +| STAFF_ASSIGNMENT | 人员安排 | +| ORDER_SURCHARGE | 订单增费 | +| SYSTEM | 系统 | + +## 7. 错误码 + +| 错误码 | 文案 | 触发条件 | +|--------|------|----------| +| 581007 | 订单不存在 | orderId 对应的订单不存在(或已软删) | +| 581045 | 房务角色无权查看订单详情,房务仅可配房 | 房务角色(HOUSE)调用本接口 | +| 400 | 订单 ID 必须大于 0 | orderId < 1(参数校验失败) | + +## 8. 示例 + +### 8.1 典型成功(测试服实证单 HL20260811181352799 口径:油费 300 归其他支出,用车只剩 Fleet 日租行) + +请求: + + GET /v3/admin/order/197820050123456789/settlement/reports/group + +响应(只截取本次变化的两个数组,其余字段省略): + +```json +{ + "code": 200, + "data": { + "id": "197820050123456789", + "orderId": "197820050123456789", + "orderNo": "HL20260811181352799", + "totalCost": 3300.00, + "vehicleLines": [ + { + "serviceDate": "2026-08-12", + "startDate": "2026-08-12", + "endDate": "2026-08-14", + "vehiclePlate": "蒙A-5376", + "vehicleModelName": "坦克500", + "driverName": "司机甲", + "dailyPrice": 1000.00, + "paymentTypeName": "现金已付", + "amount": 1000.00, + "paymentMethod": "CASH_PAID", + "paymentMethodName": "现金已付", + "sourceType": "FLEET", + "sourceTypeName": "车务" + } + ], + "otherExpenseLines": [ + { + "expenseDate": "2026-08-12", + "projectName": "全程油费", + "expenseType": "FUEL", + "expenseTypeName": "油费", + "amount": 300.00, + "paymentMethod": "CASH_PAID", + "paymentMethodName": "现金已付", + "sourceType": "MANUAL", + "sourceTypeName": "手工", + "remark": "途中加油" + }, + { + "expenseDate": "2026-08-13", + "projectName": "司机话补", + "subsidyType": "PHONE", + "subsidyTypeName": "话补", + "amount": 50.00, + "paymentMethod": "COMPANY_PAID", + "paymentMethodName": "公司支付" + } + ] + }, + "msg": "success" +} +``` + +要点:油费行的 expenseType=FUEL 出现在 **otherExpenseLines**;vehicleLines 里没有任何带 expenseType 的行。 + +### 8.2 边界(无车辆费用 + 无配车:两数组均为空) + +```json +{ + "code": 200, + "data": { + "orderNo": "HL20260810100000001", + "totalCost": 0.00, + "vehicleLines": [], + "otherExpenseLines": [] + }, + "msg": "success" +} +``` + +要点:空分类固定返回空数组 [],不返回 null;前端判空渲染空态即可。 + +### 8.3 业务失败(订单不存在) + +请求: + + GET /v3/admin/order/999999999999/settlement/reports/group + +响应: + +```json +{ + "code": 581007, + "data": null, + "msg": "订单不存在" +} +``` + +## 9. 业务边界 + +- **适用**:所有进入核单流程、需要查看整团成本构成的订单(含预览态与 finalize 终态)。 +- **不适用**:房务角色(HOUSE)不可调本接口(581045)。 +- **特殊边界**: + - 5 类车辆费用行的录入入口本来就在核单「其他支出」tab,本次只是报表归集对齐,**不需要重新录入历史数据**。 + - 预览态存在未确认(UNCONFIRMED)车辆费用行时,新口径计入 otherExpenseLines 预览成本(旧口径挂 VEHICLE 不计成本);finalize 门禁要求全行 CONFIRMED,终态两口径金额一致。 + - 核单已 finalize 的订单,报表行来自终态快照,口径以快照冻结时为准;反确认(reopen)后重新生成走新口径。 + +## 10. 修改前后对比 + +### 10.1 字段级 + +| 位置 | 修改前 | 修改后 | +|------|--------|--------| +| vehicleLines[] 行.expenseType | 有(FUEL/TOLL/PARKING/RENTAL/MAINTENANCE) | **删除,不下发** | +| vehicleLines[] 行.expenseTypeName | 有(油费等) | **删除,不下发** | +| vehicleLines[] 行.projectName | 有(车辆费用项目名) | **删除,不下发** | +| vehicleLines[] 行.expenseDate | 有(费用发生日期) | **删除,不下发** | +| otherExpenseLines[].expenseType | 恒 OTHER | OTHER/FUEL/TOLL/PARKING/RENTAL/MAINTENANCE 6 值之一 | +| 5 类车辆费用行所在数组 | vehicleLines | **otherExpenseLines** | + +### 10.2 行为级 + +| 场景 | 修改前 | 修改后 | +|------|--------|--------| +| 一笔 300 元油费(CASH_PAID) | 出现在 vehicleLines,带 expenseType=FUEL/projectName/expenseDate | 出现在 otherExpenseLines,字段同族(expenseType=FUEL/projectName/expenseDate/amount/...) | +| vehicleLines 内容 | Fleet 日租行 + 5 类车辆费用行混排 | 只含 Fleet 日租行(sourceType=FLEET) | +| 用车分类小计(vehicleLines 合计) | 含 5 类车辆费用 | 只含 Fleet 日租,数值下降 | +| 其他支出小计(otherExpenseLines 合计) | 只含 OTHER 费用 + 补贴 | 增加 5 类车辆费用,数值上升 | +| totalCost / grossProfit | —— | **不变** | +| 报账表 OTHER_EXPENSE 展示块 | 只含 OTHER 费用 + 补贴展示行 | 纳入 5 类车辆费用展示行 | + +## 11. 影响评估 / 回滚 + +- **破坏性**:⚠️ 是。vehicleLines 行 4 个字段删除 + 5 类费用行跨数组迁移,前端若按旧结构渲染「用车」块会丢车辆费用行。 +- **前端需要同步上线的改动**: + 1. 「用车」块/页签只渲染 Fleet 日租行,删除对 vehicleLines[].expenseType/expenseTypeName/projectName/expenseDate 的读取(键已不下发); + 2. 5 类车辆费用行改到「其他支出」块渲染,复用 otherExpenseLines 现有 EXPENSE 族渲染逻辑(expenseTypeName 后端已回填中文,前端无需改字典); + 3. 若有 workaround 代码把车辆费用从用车块搬到其他支出块展示,可清理; + 4. 分类小计若前端自算,无需改公式(数组内容已就位)。 +- **回滚方案**:后端 revert PR #5970 即恢复旧口径;纯代码口径调整,无 DDL、无数据迁移,回滚无副作用。前端若已按新结构上线,后端回滚需前端同步回退。 + +## 12. 注意事项 + +1. 行 VO 均带 JsonInclude(NON_NULL):null 字段不下发该键,前端取值用可选链 / 默认值兜底,不要假定键一定存在。 +2. expenseTypeName / subsidyTypeName / paymentMethodName / sourceTypeName 全部后端回填,前端**不要**再自行映射字典。 +3. 判别 otherExpenseLines 行族:expenseType 键存在 = 费用行(含 6 类),subsidyType 键存在 = 补贴行,两族字段互斥。 +4. 报账表(reports/reimbursement)expenseLines 中 type=OTHER_EXPENSE 展示行的 expenseType 实际值域同步扩为 6 类;该字段 Swagger 注解的 allowableValues 暂未同步更新,**以本文档与实际返回值为准**。 +5. 本次无入参变化、无新接口、无 DDL、无字典数据变更(expense_type 字典 6 值为存量)。 + +## 13. 关联 / 联系人 + +- Issue:https://git.1814.love:8443/wx/HL/issues/5969 +- PR:https://git.1814.love:8443/wx/HL/pulls/5970 +- Commit(merge):https://git.1814.love:8443/wx/HL/commit/522179ecfe +- 后端负责人:腰苏图