---
schema: "hl-changelog/v2"
ticket: "5781"
title: "单团核算表扩充逐项明细出参（incomeLines.details / costCategories.lines）"
consumer: "admin"
change_type: "修改接口"
author: "yaosutu(GIT)"
backend_status: "deployed"
gateway_status: "verified"
frontend_status: "implemented"
frontend_owner: "mmg"
frontend_ref: "3993f15a"
target_release: ""
verified_at: "2026-08-11"
status_note: "前端已实现(3993f15a):单团核算表收入行 incomeLines[].details、成本分类 costCategories[].lines 逐项明细行内展开——detailColumns 显式剔除 details/lines/voucherUrls 父列(否则嵌套结构被 detailCellValue JSON.stringify 成多余列,后端已 deployed 老前端会自动渲出),新增 expand 列+renderChildTable 渲染逐项子表(仅当行确有非空逐项才显示展开入口,空数组不渲染);REPORT_FIELD_LABELS 补逐项字段中文表头(stayDate/hotelName/dailyPrice/totalPremium 等),REPORT_CODE_TO_NAME_FIELD 补 source/serviceType/bizType code→Name(后端回填 sourceName/serviceTypeName/bizTypeName,缺名回退 code)。负数金额不取绝对值、*Name 中文名直接展示均遵循 changelog 边界。ReportModal.spec 新增展开用例:父表不渲 JSON 列、展开后显示逐项子表。核单域 spec 全过,checkpoint 全绿。"
updated_at: "2026-08-11"
base: "dev-v3"
---

# 【✨ 修改接口·管理后台】单团核算表扩充逐项明细出参（#5781）

> **PR**: #5786 | **服务**: hl-order-service-v3 | **更新时间**: 2026-08-10

## 1. 接口背景

单团核算表（GET /v3/admin/order/{orderId}/settlement/reports/group）此前只返回「4 行收入合计 + 8 行成本合计」，财务/运营在核对某一行合计时看不到它是由哪些逐项明细加总出来的，只能跳回各分类明细页签逐条对账。

本次变更为**纯出参增量**：在每条收入行下挂 details（收入逐项明细）、在每个成本分类下挂 lines（成本逐项明细，分类专属结构），让前端在核算表内直接展开逐项，无需再跳页签拼装。

**不变的部分**：顶部汇总字段（baseOrderAmount / totalCost / grossProfit 等全部金额字段）、incomeLines 仍固定 4 行、costCategories 仍固定 8 行、各行 amount 合计口径，全部与变更前一致。

## 2. 变更清单

| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|------|------|------|----------|------|
| 1 | 查询单团核算表 | GET | /v3/admin/order/{orderId}/settlement/reports/group | 修改（出参纯增量） | incomeLines[i] 新增 details 数组；costCategories[i] 新增 lines 数组（元素结构随 category 不同而不同，按 category 窄化） |

配套数据字典（前端可调 GET /admin/dict/data/{dictType} 动态渲染中文名）：

| 字典 type | 用途 | 本次状态 |
|-----------|------|----------|
| settlement_category | 成本分类中文名 | 已存在（不变） |
| settlement_payment_method | 付款方式中文名 | 已存在（不变） |
| settlement_report_line_type | 收入行类型中文名 | 已存在（不变） |
| insurance_biz_type | 保险业务类型中文名 | **本次新增** |
| settlement_refund_source | 人工返还来源中文名 | **本次新增** |

## 3. 接口详情

### 3.1 查询单团核算表

- **使用场景**：核单工作台「单团核算」页签，财务/运营查看单团收入成本毛利全貌及逐项明细
- **认证**：管理后台 JWT；房务角色（ROOM_MANAGER / HOUSE_KEEPER_LEAD）无权调用（返 581045）
- **幂等性**：是（GET 只读）
- **限流**：无

## 4. 接口入参

### 4.1 路径参数

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `orderId` | Long | ✅ | 订单 ID，必须 > 0，否则返参数校验错误 |

### 4.2 请求体字段

无请求体。

## 5. 出参（响应）

响应类型：`Result<SettlementGroupReportRespVO>`（`code=200` 表示成功，`data` 为下表结构）。

### 5.1 顶层字段（SettlementGroupReportRespVO）

> ⚠️ 本表全部字段与变更前一致，**本次无增删改**，列出仅为自包含。

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | String | 报表 ID（Long 序列化为字符串，无落库记录时可能缺省） |
| `orderId` | String | 订单 ID（Long 序列化为字符串） |
| `reportStatus` | String | 报表状态：`GENERATED`=已生成（实时组装）/ `CONFIRMED`=已确认（终态快照回放） |
| `baseOrderAmount` | Number | 订单应收金额，两位小数 |
| `otherIncomeAmount` | Number | 其他收入合计 |
| `discountAmount` | Number | 优惠合计（负数） |
| `adjustedReceivableAmount` | Number | 调整后应收 |
| `paidAmount` | Number | 已收金额 |
| `actualRefundedAmount` | Number | 实际退款合计（负数） |
| `netRevenueAmount` | Number | 净收入 |
| `netReceivedAmount` | Number | 实收净额 |
| `outstandingAmount` | Number | 未收尾款 |
| `hotelCost` / `ticketCost` / `mealCost` / `vehicleCost` / `guideCost` / `photographerCost` / `otherExpenseCost` / `insurancePremium` | Number | 8 个成本分类合计（住宿/门票/餐食/车辆/导游/摄影/其他支出/保险） |
| `totalCost` | Number | 成本总计 |
| `paidCost` | Number | 已付成本合计 |
| `unpaidCost` | Number | 未付成本合计 |
| `grossProfit` | Number | 毛利 |
| `grossProfitRate` | Number | 毛利率 |
| `travelerCount` | Number | 出行人数 |
| `perCapitaRevenue` / `perCapitaCost` / `perCapitaProfit` | Number | 人均收入 / 人均成本 / 人均毛利 |
| `incomeLines` | Array | 收入行，**固定 4 行**，结构见 5.2 |
| `costCategories` | Array | 成本分类行，**固定 8 行**，结构见 5.3 |
| `generatedBy` / `generatedByName` / `generatedAt` | String / String / String | 生成人 ID / 姓名 / 生成时间 |
| `confirmedBy` / `confirmedByName` / `confirmedAt` | String / String / String | 确认人 ID / 姓名 / 确认时间（未确认时缺省） |

### 5.2 收入行（SettlementGroupIncomeLineVO）

| 字段 | 类型 | 说明 |
|------|------|------|
| `type` | String | 行类型：`BASE_ORDER`=订单应收 / `OTHER_INCOME`=其他收入 / `DISCOUNT`=优惠 / `ACTUAL_REFUND`=实际退款 |
| `typeName` | String | 行类型中文名（字典 `settlement_report_line_type` 回填） |
| `amount` | Number | 行合计金额，两位小数；`DISCOUNT` / `ACTUAL_REFUND` 为负数 |
| `details` | Array | ✨ **本次新增**：收入逐项明细（`SettlementGroupIncomeDetailVO`），无逐项时为空数组 `[]` |

### 5.3 收入逐项明细（SettlementGroupIncomeDetailVO）✨ 本次新增

| 字段 | 类型 | 说明 |
|------|------|------|
| `itemName` | String | 项目名（订单应收 / 增费项目名 / 优惠名称 / 退款来源中文名） |
| `content` | String | 内容说明（如规格、退款原因） |
| `source` | String | 人工返还来源 code，**仅** `ACTUAL_REFUND` 下的人工返还行透出：`DRIVER_ONSITE` / `COMPANY_COMPENSATION` |
| `sourceName` | String | 人工返还来源中文名（字典 `settlement_refund_source`） |
| `unitPrice` | Number | 单价，两位小数；无单价概念时缺省 |
| `headCount` | Number | 人数；无人数概念时缺省 |
| `quantity` | Number | 数量；无数量概念时缺省 |
| `amount` | Number | 金额，两位小数；`DISCOUNT` / `ACTUAL_REFUND` 明细为负数 |
| `paymentMethod` | String | 付款方式：`CASH_PAID` / `COMPANY_PAID` / `SIGNED`；无付款方式时缺省 |
| `paymentMethodName` | String | 付款方式中文名（字典 `settlement_payment_method`） |
| `sourceType` | String | 来源类型（9 值，见 §6.6）；无来源时缺省 |
| `sourceTypeName` | String | 来源中文名 |
| `remark` | String | 备注 |
| `voucherUrls` | Array&lt;String&gt; | 凭证 URL 数组 |

**各 type 下 details 的内容口径**：

| type | details 内容 |
|------|-------------|
| `BASE_ORDER` | 订单应收一行汇总（订单侧无逐项时单行） |
| `OTHER_INCOME` | 其他收入逐项 |
| `DISCOUNT` | 优惠逐项（金额取负） |
| `ACTUAL_REFUND` | 实际退款逐项：线上退款 + 人工返还（`source` = DRIVER_ONSITE / COMPANY_COMPENSATION），金额取负 |

### 5.4 成本分类行（SettlementGroupCostCategoryVO）

| 字段 | 类型 | 说明 |
|------|------|------|
| `category` | String | 费用类别：`HOTEL` / `TICKET` / `MEAL` / `VEHICLE` / `GUIDE` / `PHOTOGRAPHER` / `OTHER_EXPENSE` / `INSURANCE` |
| `categoryName` | String | 费用类别中文名（字典 `settlement_category`） |
| `amount` | Number | 分类合计金额，两位小数 |
| `lines` | Array | ✨ **本次新增**：成本逐项明细，**元素结构随 `category` 不同而不同**（分类专属行 VO），无逐项时为空数组 `[]`；前端按 `category` 判别窄化到 5.5～5.11 的对应结构 |

### 5.5 成本逐项行 · HOTEL 住宿（SettlementGroupHotelLineVO）✨

| 字段 | 类型 | 说明 |
|------|------|------|
| `stayDate` | String | 入住日期，`yyyy-MM-dd` |
| `hotelName` | String | 酒店名称 |
| `roomTypeName` | String | 房型名称 |
| `roomCount` | Number | 房间数 |
| `unitPrice` | Number | 单价，两位小数 |
| `plannedCost` | Number | 计划成本，两位小数 |
| `amount` | Number | 核算金额（实际成本），两位小数 |
| `paymentMethod` / `paymentMethodName` | String | 付款方式 code / 中文名 |
| `sourceType` / `sourceTypeName` | String | 来源类型 code / 中文名 |
| `remark` | String | 备注 |
| `voucherUrls` | Array&lt;String&gt; | 凭证 URL 数组 |

### 5.6 成本逐项行 · TICKET 门票（SettlementGroupTicketLineVO）✨

| 字段 | 类型 | 说明 |
|------|------|------|
| `dayDate` | String | 游玩日期，`yyyy-MM-dd` |
| `scenicName` | String | 景区/项目名称 |
| `specName` | String | 规格名称（如 成人票） |
| `ticketCount` | Number | 票数 |
| `ticketUnitPrice` | Number | 门票单价，两位小数 |
| `sellPrice` | Number | 销售价，两位小数 |
| `plannedCost` | Number | 计划成本，两位小数 |
| `amount` | Number | 核算金额（实际成本），两位小数 |
| `paymentMethod` / `paymentMethodName` | String | 付款方式 code / 中文名 |
| `sourceType` / `sourceTypeName` | String | 来源类型 code / 中文名 |
| `remark` | String | 备注 |
| `voucherUrls` | Array&lt;String&gt; | 凭证 URL 数组 |

### 5.7 成本逐项行 · MEAL 餐食（SettlementGroupMealLineVO）✨

| 字段 | 类型 | 说明 |
|------|------|------|
| `mealDate` | String | 用餐日期，`yyyy-MM-dd` |
| `mealName` | String | 餐食名称 |
| `mealType` | String | 餐食类型：`BREAKFAST` / `LUNCH` / `DINNER` / `SELF` |
| `mealTypeName` | String | 餐食类型中文名（字典 `meal_type`） |
| `quantity` | Number | 份数 |
| `unitPrice` | Number | 单价，两位小数 |
| `amount` | Number | 核算金额（实际金额），两位小数 |
| `paymentMethod` / `paymentMethodName` | String | 付款方式 code / 中文名 |
| `sourceType` / `sourceTypeName` | String | 来源类型 code / 中文名；餐食明细无来源时缺省 |
| `remark` | String | 备注 |
| `voucherUrls` | Array&lt;String&gt; | 凭证 URL 数组 |

### 5.8 成本逐项行 · VEHICLE 用车（SettlementGroupVehicleLineVO）✨

> 车务逐日行（VEHICLE_FEE 族）与车辆费用行（EXPENSE 族：油费/过路费等）的**稀疏并集**：每行仅本族字段非空，另一族字段整体缺省。无单价/数量概念，`dailyPrice` 即核算单价列。

| 字段 | 类型 | 说明 |
|------|------|------|
| `serviceDate` | String | [VEHICLE_FEE] 服务日期，`yyyy-MM-dd` |
| `startDate` | String | [VEHICLE_FEE] 服务开始日期，`yyyy-MM-dd` |
| `endDate` | String | [VEHICLE_FEE] 服务结束日期，`yyyy-MM-dd` |
| `vehiclePlate` | String | [VEHICLE_FEE] 车牌号 |
| `vehicleModelName` | String | [VEHICLE_FEE] 车型名称 |
| `driverName` | String | [VEHICLE_FEE] 司机姓名 |
| `dailyPrice` | Number | [VEHICLE_FEE] 日单价（即核算单价列），两位小数 |
| `paymentTypeName` | String | [VEHICLE_FEE] 车务付款类型名称 |
| `amount` | Number | 核算金额，两位小数 |
| `paymentMethod` / `paymentMethodName` | String | 付款方式 code / 中文名 |
| `sourceType` / `sourceTypeName` | String | 来源类型 code / 中文名 |
| `expenseType` | String | [EXPENSE] 车辆费用类型：`FUEL` / `TOLL` / `PARKING` / `RENTAL` / `MAINTENANCE` |
| `expenseTypeName` | String | [EXPENSE] 车辆费用类型中文名（字典 `expense_type`） |
| `projectName` | String | [EXPENSE] 项目名称 |
| `expenseDate` | String | [EXPENSE] 费用发生日期，`yyyy-MM-dd` |
| `remark` | String | 备注 |
| `voucherUrls` | Array&lt;String&gt; | 凭证 URL 数组 |

### 5.9 成本逐项行 · GUIDE 导游 / PHOTOGRAPHER 摄影（SettlementGroupStaffLineVO，两分类共用）✨

| 字段 | 类型 | 说明 |
|------|------|------|
| `serviceDate` | String | 服务日期，`yyyy-MM-dd`；无服务日时缺省 |
| `name` | String | 人员姓名 |
| `serviceType` | String | 服务类型：`GUIDE` / `PHOTOGRAPHER` |
| `serviceTypeName` | String | 服务类型中文名（字典 `staff_role`） |
| `amount` | Number | 核算金额，两位小数 |
| `paymentMethod` / `paymentMethodName` | String | 付款方式 code / 中文名 |
| `sourceType` / `sourceTypeName` | String | 来源类型 code / 中文名；无来源时缺省 |
| `remark` | String | 备注 |
| `voucherUrls` | Array&lt;String&gt; | 凭证 URL 数组 |

### 5.10 成本逐项行 · OTHER_EXPENSE 其他支出（SettlementGroupOtherExpenseLineVO）✨

> 其他费用行（EXPENSE 族）与补贴行（SUBSIDY 族）的**稀疏并集**：每行仅本族字段非空。无单价/数量概念。

| 字段 | 类型 | 说明 |
|------|------|------|
| `expenseDate` | String | 费用发生日期，`yyyy-MM-dd` |
| `projectName` | String | 项目名称 |
| `expenseType` | String | [EXPENSE] 其他费用类型：固定 `OTHER` |
| `expenseTypeName` | String | [EXPENSE] 其他费用类型中文名（字典 `expense_type`） |
| `subsidyType` | String | [SUBSIDY] 补贴类型：`PHONE` / `OVERTIME` |
| `subsidyTypeName` | String | [SUBSIDY] 补贴类型中文名（字典 `subsidy_type`） |
| `amount` | Number | 核算金额（实际金额），两位小数 |
| `paymentMethod` / `paymentMethodName` | String | 付款方式 code / 中文名 |
| `sourceType` / `sourceTypeName` | String | 来源类型 code / 中文名；无来源时缺省 |
| `remark` | String | 备注 |
| `voucherUrls` | Array&lt;String&gt; | 凭证 URL 数组 |

### 5.11 成本逐项行 · INSURANCE 保险（SettlementGroupInsuranceLineVO）✨

| 字段 | 类型 | 说明 |
|------|------|------|
| `productName` | String | 保险产品名称 |
| `bizType` | String | 业务类型：`ORDER` / `DRIVER` |
| `bizTypeName` | String | 业务类型中文名（字典 `insurance_biz_type`，本次新增） |
| `totalPremium` | Number | 保费（即核算金额列），两位小数 |
| `extPolicyNo` | String | 外部保单号 |
| `voucherUrls` | Array&lt;String&gt; | 凭证 URL 数组（电子保单 PDF） |

> 保险行无 `plannedCost` / `sourceType` 字段，不输出。

## 6. 枚举 / 数据字典

### 6.1 `incomeLines[].type`（字典 `settlement_report_line_type`）

| 值 | 中文 | 说明 |
|----|------|------|
| `BASE_ORDER` | 订单应收 | 订单应收行 |
| `OTHER_INCOME` | 其他收入 | 其他收入行 |
| `DISCOUNT` | 优惠 | 优惠行（金额为负） |
| `ACTUAL_REFUND` | 实际退款 | 实际退款行（金额为负） |

### 6.2 `costCategories[].category`（字典 `settlement_category`）

| 值 | 中文 | 对应 lines 行结构 |
|----|------|-------------------|
| `HOTEL` | 住宿 | §5.5 |
| `TICKET` | 门票/游玩项目 | §5.6 |
| `MEAL` | 餐食 | §5.7 |
| `VEHICLE` | 车辆 | §5.8 |
| `GUIDE` | 导游 | §5.9 |
| `PHOTOGRAPHER` | 摄影 | §5.9（与 GUIDE 共用） |
| `OTHER_EXPENSE` | 其他支出 | §5.10 |
| `INSURANCE` | 保险 | §5.11 |

### 6.3 `paymentMethod`（字典 `settlement_payment_method`）

出现于：收入逐项明细、HOTEL / TICKET / MEAL / VEHICLE / 人员 / 其他支出各成本逐项行。

| 值 | 中文 |
|----|------|
| `CASH_PAID` | 现金已付 |
| `COMPANY_PAID` | 公司支付 |
| `SIGNED` | 签单 |

### 6.4 `details[].source`（字典 `settlement_refund_source`，✨ 本次新增字典）

仅 `ACTUAL_REFUND` 下人工返还行透出。

| 值 | 中文 |
|----|------|
| `DRIVER_ONSITE` | 司机现场返还 |
| `COMPANY_COMPENSATION` | 公司赔付 |

### 6.5 `lines[].bizType`（字典 `insurance_biz_type`，✨ 本次新增字典）

仅 INSURANCE 保险行。

| 值 | 中文 |
|----|------|
| `ORDER` | 订单险 |
| `DRIVER` | 司机险 |

### 6.6 `sourceType`（后端枚举 SettlementDetailSourceType）

出现于：收入逐项明细、HOTEL / TICKET / MEAL / VEHICLE / 人员 / 其他支出各成本逐项行。

| 值 | 中文 |
|----|------|
| `MANUAL` | 手工 |
| `HOUSE_ASSIGNMENT` | 配房结果 |
| `SCENIC_ASSIGNMENT` | 景区 |
| `ACTIVITY_ASSIGNMENT` | 游玩项目 |
| `MEAL_ASSIGNMENT` | 餐饮安排 |
| `FLEET` | 车务 |
| `STAFF_ASSIGNMENT` | 人员安排 |
| `ORDER_SURCHARGE` | 订单增费 |
| `SYSTEM` | 系统 |

### 6.7 `lines[].mealType`（字典 `meal_type`）

仅 MEAL 餐食行。

| 值 | 中文 |
|----|------|
| `BREAKFAST` | 早餐 |
| `LUNCH` | 午餐 |
| `DINNER` | 晚餐 |
| `SELF` | 自理 |

### 6.8 `lines[].serviceType`（字典 `staff_role`）

仅 GUIDE / PHOTOGRAPHER 人员行。本接口只会出现 `GUIDE` / `PHOTOGRAPHER` 两个值（字典另有 助理导游/领队/司机/其他，不在本接口出现）。

| 值 | 中文 |
|----|------|
| `GUIDE` | 导游 |
| `PHOTOGRAPHER` | 摄影师 |

### 6.9 `lines[].expenseType`（字典 `expense_type`）

VEHICLE 行（EXPENSE 族）：`FUEL`=油费 / `TOLL`=过路费 / `PARKING`=停车费 / `RENTAL`=租车费 / `MAINTENANCE`=维修保养。
OTHER_EXPENSE 行（EXPENSE 族）：固定 `OTHER`=其他。

### 6.10 `lines[].subsidyType`（字典 `subsidy_type`）

仅 OTHER_EXPENSE 行（SUBSIDY 族）。

| 值 | 中文 |
|----|------|
| `PHONE` | 话补 |
| `OVERTIME` | 加班补贴 |

### 6.11 `reportStatus`

| 值 | 中文 | 说明 |
|----|------|------|
| `GENERATED` | 已生成 | 未核单订单，实时组装 |
| `CONFIRMED` | 已确认 | 已核单（SETTLED）订单，终态快照回放 |

## 7. 错误码

| code | 含义 | 触发场景 |
|------|------|----------|
| 400 | 参数校验失败 | `orderId` 缺失或 < 1 |
| 581007 | 订单不存在 | `orderId` 对应订单不存在或已删除 |
| 581045 | 房务角色无权查看订单详情，房务仅可配房 | 房务管理员 / 房务组长角色调用 |

## 8. 示例（3 组：典型 / 边界 / 异常）

### 8.1 典型成功（已核单订单，逐项明细完整填充）

**请求**：

    GET /v3/admin/order/1956112233445566778/settlement/reports/group
    Authorization: Bearer <admin JWT>
    （无请求体）

**响应**（节选，仅展示本次新增结构所在的 incomeLines / costCategories，顶层汇总字段与变更前一致故省略）：

```json
{
  "code": 200,
  "data": {
    "id": "1957000000000000001",
    "orderId": "1956112233445566778",
    "reportStatus": "CONFIRMED",
    "incomeLines": [
      {
        "type": "BASE_ORDER",
        "typeName": "订单应收",
        "amount": 12800.00,
        "details": [
          {
            "itemName": "订单应收",
            "content": "小红书(孙雷) 王彧琪",
            "unitPrice": 1280.00,
            "headCount": 10,
            "amount": 12800.00
          }
        ]
      },
      {
        "type": "OTHER_INCOME",
        "typeName": "其他收入",
        "amount": 200.00,
        "details": [
          {
            "itemName": "现场加收骑马费",
            "unitPrice": 100.00,
            "quantity": 2,
            "amount": 200.00,
            "paymentMethod": "CASH_PAID",
            "paymentMethodName": "现金已付",
            "sourceType": "ORDER_SURCHARGE",
            "sourceTypeName": "订单增费",
            "remark": "现场加收"
          }
        ]
      },
      {
        "type": "DISCOUNT",
        "typeName": "优惠",
        "amount": -500.00,
        "details": [
          {
            "itemName": "早鸟优惠",
            "amount": -500.00
          }
        ]
      },
      {
        "type": "ACTUAL_REFUND",
        "typeName": "实际退款",
        "amount": -300.00,
        "details": [
          {
            "itemName": "司机现场返还",
            "content": "少住一晚退房差",
            "source": "DRIVER_ONSITE",
            "sourceName": "司机现场返还",
            "amount": -300.00,
            "paymentMethod": "CASH_PAID",
            "paymentMethodName": "现金已付",
            "remark": "现场返还现金"
          }
        ]
      }
    ],
    "costCategories": [
      {
        "category": "HOTEL",
        "categoryName": "住宿",
        "amount": 3600.00,
        "lines": [
          {
            "stayDate": "2026-07-30",
            "hotelName": "草原明珠大酒店",
            "roomTypeName": "标间",
            "roomCount": 3,
            "unitPrice": 400.00,
            "plannedCost": 1200.00,
            "amount": 1200.00,
            "paymentMethod": "CASH_PAID",
            "paymentMethodName": "现金已付",
            "sourceType": "HOUSE_ASSIGNMENT",
            "sourceTypeName": "配房结果",
            "remark": "含早",
            "voucherUrls": ["https://oss/v1.jpg"]
          }
        ]
      },
      {
        "category": "VEHICLE",
        "categoryName": "车辆",
        "amount": 1760.00,
        "lines": [
          {
            "serviceDate": "2026-07-30",
            "startDate": "2026-07-30",
            "endDate": "2026-07-31",
            "vehiclePlate": "蒙A-5376",
            "vehicleModelName": "坦克500",
            "driverName": "司机甲",
            "dailyPrice": 880.00,
            "amount": 880.00,
            "paymentMethod": "CASH_PAID",
            "paymentMethodName": "现金已付",
            "sourceType": "FLEET",
            "sourceTypeName": "车务"
          },
          {
            "expenseType": "FUEL",
            "expenseTypeName": "油费",
            "projectName": "全程油费",
            "expenseDate": "2026-07-31",
            "amount": 880.00,
            "paymentMethod": "COMPANY_PAID",
            "paymentMethodName": "公司支付",
            "sourceType": "FLEET",
            "sourceTypeName": "车务"
          }
        ]
      },
      {
        "category": "GUIDE",
        "categoryName": "导游",
        "amount": 1600.00,
        "lines": [
          {
            "serviceDate": "2026-07-30",
            "name": "导游乙",
            "serviceType": "GUIDE",
            "serviceTypeName": "导游",
            "amount": 1600.00,
            "paymentMethod": "SIGNED",
            "paymentMethodName": "签单",
            "sourceType": "STAFF_ASSIGNMENT",
            "sourceTypeName": "人员安排"
          }
        ]
      },
      {
        "category": "INSURANCE",
        "categoryName": "保险",
        "amount": 150.00,
        "lines": [
          {
            "productName": "保游畅享境内游保险",
            "bizType": "ORDER",
            "bizTypeName": "订单险",
            "totalPremium": 150.00,
            "extPolicyNo": "PY20260730001",
            "voucherUrls": ["https://oss/policy1.pdf"]
          }
        ]
      }
    ]
  },
  "msg": ""
}
```

### 8.2 边界情况（无任何逐项明细 / 金额为 0）

**场景说明**：订单无任何其他收入、优惠、退款，且各成本分类未录入任何逐项 —— `details` / `lines` 返回**空数组** `[]`（不是 null），对应分类 `amount` 可为 `0.00`。所有 null 的可选字段（unitPrice / headCount / paymentMethod / remark / voucherUrls 等）**整体缺省不出现在 JSON 中**。

**请求**：

    GET /v3/admin/order/1956112233445566889/settlement/reports/group
    Authorization: Bearer <admin JWT>
    （无请求体）

**响应**（节选）：

```json
{
  "code": 200,
  "data": {
    "orderId": "1956112233445566889",
    "reportStatus": "GENERATED",
    "incomeLines": [
      { "type": "BASE_ORDER", "typeName": "订单应收", "amount": 12800.00, "details": [
        { "itemName": "订单应收", "unitPrice": 1280.00, "headCount": 10, "amount": 12800.00 }
      ] },
      { "type": "OTHER_INCOME", "typeName": "其他收入", "amount": 0.00, "details": [] },
      { "type": "DISCOUNT", "typeName": "优惠", "amount": 0.00, "details": [] },
      { "type": "ACTUAL_REFUND", "typeName": "实际退款", "amount": 0.00, "details": [] }
    ],
    "costCategories": [
      { "category": "HOTEL", "categoryName": "住宿", "amount": 0.00, "lines": [] },
      { "category": "TICKET", "categoryName": "门票/游玩项目", "amount": 0.00, "lines": [] },
      { "category": "MEAL", "categoryName": "餐食", "amount": 0.00, "lines": [] },
      { "category": "VEHICLE", "categoryName": "车辆", "amount": 0.00, "lines": [] },
      { "category": "GUIDE", "categoryName": "导游", "amount": 0.00, "lines": [] },
      { "category": "PHOTOGRAPHER", "categoryName": "摄影", "amount": 0.00, "lines": [] },
      { "category": "OTHER_EXPENSE", "categoryName": "其他支出", "amount": 0.00, "lines": [] },
      { "category": "INSURANCE", "categoryName": "保险", "amount": 0.00, "lines": [] }
    ]
  },
  "msg": ""
}
```

### 8.3 业务失败（订单不存在 / 房务角色越权）

**场景说明 A**：`orderId` 不存在 → 581007。

**请求**：

    GET /v3/admin/order/999999999/settlement/reports/group
    Authorization: Bearer <admin JWT>
    （无请求体）

**响应**：

```json
{ "code": 581007, "msg": "订单不存在", "data": null }
```

**场景说明 B**：房务管理员角色调用 → 581045。

```json
{ "code": 581045, "msg": "房务角色无权查看订单详情，房务仅可配房", "data": null }
```

## 9. 业务边界

- ✅ **适用场景**：订单存在即可调；未核单订单（`reportStatus=GENERATED`）走实时组装，已核单订单（`reportStatus=CONFIRMED`）走终态快照回放，**两条路径出参结构完全一致**，前端无需区分
- ❌ **不适用场景**：房务角色（ROOM_MANAGER / HOUSE_KEEPER_LEAD）调用 → 581045
- ⚠️ **特殊边界**：
  - 逐项明细**不出已付/未付逐行列**，逐行只有单价/数量/核算金额（`paidCost` / `unpaidCost` 仍是顶层分类维度的合计口径，不在逐项层）
  - VEHICLE / OTHER_EXPENSE 两分类的行是同数组内两族结构稀疏并集（见 §5.8 / §5.10），前端渲染列时按「本族字段是否出现」判别
  - `DISCOUNT` / `ACTUAL_REFUND` 行及其明细金额均为**负数**，前端不要自行取绝对值

## 10. 修改前后对比

### 10.1 字段级对比

| 字段 | 改前 | 改后 |
|------|------|------|
| `incomeLines[].details` | 无此字段 | ✨ 新增 `Array<SettlementGroupIncomeDetailVO>`，无逐项时为 `[]` |
| `costCategories[].lines` | 无此字段 | ✨ 新增 `Array`（分类专属行结构，按 `category` 窄化），无逐项时为 `[]` |
| 顶层汇总字段 / 4 行收入合计 / 8 行成本合计 | 现状 | **不变** |

### 10.2 行为级对比

| 行为 | 改前 | 改后 |
|------|------|------|
| 核算表核对逐项明细 | 只能看到行合计，需跳各分类明细页签逐条对账 | 行内直接展开 `details` / `lines` 逐项 |
| 数据字典 | 无 `insurance_biz_type` / `settlement_refund_source` | ✨ 新增两个字典（保险业务类型 / 人工返还来源） |

## 11. 影响评估 / 回滚

### 11.1 影响评估

- **是否破坏向后兼容**：否。纯出参增量，原有字段名 / 类型 / 结构 / 合计口径零变化；老前端不读 `details` / `lines` 不受影响
- **前端是否必须同步上线**：否。前端按自身排期接入逐项展开即可

### 11.2 回滚方案

- **回滚方式**：revert PR #5786
- **回滚后清理**：无（无 DDL、无缓存、无脏数据；两个字典 `insurance_biz_type` / `settlement_refund_source` 保留无害）

## 12. 注意事项

- **null 字段整体缺省**：所有行 VO 标注了 null 不序列化，可选字段（unitPrice / headCount / quantity / paymentMethod / sourceType / remark / voucherUrls 等）为 null 时**该 key 不出现在 JSON 中**，前端按可选字段处理，不要断言 key 必存在
- `details` / `lines` 无逐项时是**空数组 `[]`** 而不是字段缺省，可直接 `.length` 判空
- **行结构窄化**：`costCategories[].lines` 元素是多态结构，前端必须先按 `category` 判别再取分类专属字段（GUIDE / PHOTOGRAPHER 共用人员行结构）
- **金额符号**：`DISCOUNT` / `ACTUAL_REFUND` 的行金额与明细金额均为负数；成本各行为正数
- **中文名渲染**：`*Name` 字段后端已回填中文名（字典缺值时回退硬编码），可直接展示；如需动态字典渲染，调 `GET /admin/dict/data/{dictType}`，dictType 见 §6 各子节
- 无历史 workaround 需要清理（本能力此前不存在）

## 13. 关联 / 联系人

### 13.1 链接

- **Issue**: [#5781](https://git.1814.love:8443/wx/HL/issues/5781)
- **PR**: [#5786](https://git.1814.love:8443/wx/HL/pulls/5786)
- **Merge commit**: [fdc429bf](https://git.1814.love:8443/wx/HL/commit/fdc429bf8546ce2cbb8c69f4166b153cccb4839c)

### 13.2 联系人

- **后端负责人**: @yaosutu
