# 【新增接口·管理后台】v3 订单核心模块 §1 core

> **更新时间**: 2026-05-18
> **端类型**: 管理后台
> **设计文档版本**: v5.49（API-SPEC / SRS / DETAIL-DESIGN / DATABASE-SCHEMA 4 份 HTML 同步）

---

## 0. 模块全貌

| 子模块 | 含接口 | 接口数 | 状态 |
|---|---|---|---|
| **§1A 订单 CRUD + 详情** | §1.1 创建 / §1.2 列表 / §1.3.1 详情主聚合 / §1.3.2~§1.3.7 6 Tab 子接口 / §1.4 修改 | **10** | ✅ |
| **§1B 取消订单** | §1.5.0 预览 / §1.5.1 出行前 / §1.5.2 出行中 | **3** | ✅ |
| **§1C 状态机 + 锁单** | §1.7 transition / §1.8 confirm-checklist | **2** | ✅ |
| **§1 合计** | — | **15** | ✅ 本次推送 |

---

## 1. 接口背景

订单服务 v3（hl-order-service-v3 全新二期）的订单核心模块 §1 core 提供订单管理基础能力，覆盖定制师 B 端代下单 / 多维度筛选列表 / 订单详情（首屏主聚合 + 6 个 Tab 独立懒加载）/ 非关键字段修改。

本次推送 §1 模块**全 15 个接口**，对应管理后台原型 F8-F20（订单列表+创建+详情主体）、F22-F26（详情各 Tab 单刷新）、F37（修改订单字段）、F30-F32（取消订单弹框+出行前/出行中）、F33-F34（确认锁单 checklist + 状态机操作）。

---

## 2. 变更清单

| # | § | 接口名 | 方法 | 路径 |
|---|---|--------|------|------|
| 1 | 1.1 | 创建订单 | POST | `/v3/admin/order` |
| 2 | 1.2 | 订单列表 | GET | `/v3/admin/order` |
| 3 | 1.3.1 | 订单详情主聚合 | GET | `/v3/admin/order/{id}` |
| 4 | 1.3.2 | 财务 Tab | GET | `/v3/admin/order/{id}/finance` |
| 5 | 1.3.3 | 合同保险 Tab | GET | `/v3/admin/order/{id}/contract-insurance` |
| 6 | 1.3.4 | 行程安排 Tab ⚠️Mock | GET | `/v3/admin/order/{id}/itinerary` |
| 7 | 1.3.5 | 状态记录 Tab | GET | `/v3/admin/order/{id}/status-log` |
| 8 | 1.3.6 | 退款明细 Tab | GET | `/v3/admin/order/{id}/refund` |
| 9 | 1.3.7 | 服务标准 Tab | GET | `/v3/admin/order/{id}/service-standard` |
| 10 | 1.4 | 修改订单字段 | PUT | `/v3/admin/order/{id}` |
| 11 | 1.5.0 | 取消订单预览 | GET | `/v3/admin/order/{id}/cancel-preview` |
| 12 | 1.5.1 | 取消订单（出行前） | POST | `/v3/admin/order/{id}/cancel/pre-trip` |
| 13 | 1.5.2 | 取消订单（出行中） | POST | `/v3/admin/order/{id}/cancel/on-trip` |
| 14 | 1.7 | 状态变更操作（状态机） | POST | `/v3/admin/order/{id}/transition` |
| 15 | 1.8 | 确认锁单前置 Checklist | GET | `/v3/admin/order/{id}/confirm-checklist` |

---

## 3. 接口详情

> 每个接口自包含：使用场景 / 入参 / 出参 / 错误码 / 业务边界 / 示例（请求 + 响应）。
> 跨接口共享枚举集中在 §6；模块整体影响评估在 §11。

---

### 3.1 §1.1 创建订单

**路径**：`POST /v3/admin/order`
**使用场景**：定制师 B 端代下单（电话 / 微信 / 线下渠道）。客户自助下单走 mp 端不在本模块。
**认证**：JWT（admin 角色） | **幂等性**：否 | **限流**：无

#### 入参（`OrderCreateReqVO`，13 字段）

| 字段 | 类型 | 必填 | 说明 | 校验规则 |
|------|------|:----:|------|----------|
| `productId` | Long | ✅ | 产品 ID | `@NotNull` |
| `tierSeq` | Integer | ✅ | 档位序号 | `@NotNull` |
| `departureDate` | LocalDate | ✅ | 出发日期 | `@NotNull` |
| `adultCount` | Integer | ✅ | 成人数 | `@NotNull` `@Min(1)` |
| `childCount` | Integer | ❌ | 儿童数 | `@Min(0)`，默认 0 |
| `youngChildCount` | Integer | ❌ | 幼儿数 | `@Min(0)`，默认 0 |
| `babyCount` | Integer | ❌ | 婴儿数 | `@Min(0)`，默认 0 |
| `customerName` | String | ✅ | 客户姓名 | `@NotBlank` |
| `customerPhone` | String | ✅ | 客户手机（明文传，11 位数字） | `@NotBlank` |
| `customerRemark` | String | ❌ | 客户备注 | `@Size(max=500)` |
| `createSource` | String | ❌ | 创建来源（不传默认 `CONSULTANT`） | 枚举见 §6.1 |
| `groupBatchId` | Long | ❌ | 拼团批次 ID（自由出团传空） | — |
| `roomCount` | Integer | ❌ | 房间数 | `@Min(1)` |
| `tags` | List\<String\> | ❌ | 订单标签名列表 | — |

#### 出参（`Result<OrderCreateRespVO>`，20 字段）

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | String | 订单主键 |
| `orderNo` | String | 订单号，格式 `HL{yyyyMMddHHmmss}{3 位序号}` |
| `displayOrderNo` | String | 展示订单号 = `orderNo + teamNo`；`teamNo` 为空时等同 `orderNo` |
| `orderStatus` | String | 创单后固定 `PENDING_PAY`（枚举见 §6.2） |
| `flowStatus` | String | 创单后固定 `AWAITING_PROFILE`（枚举见 §6.3） |
| `consultantId` | String | 实际绑定的定制师 ID |
| `consultantSource` | String | 定制师来源（枚举见 §6.4） |
| `tags` | List\<String\> | 标签列表（含入参 tags + 系统自动标签） |
| `createdAt` | LocalDateTime | 创单时间 |
| `productName` | String | 产品名称 |
| `tierName` | String | 档位名 |
| `groupBatchName` | String? | 拼团批次名（自由出团时 null） |
| `departureDate` | LocalDate | 出发日 |
| `returnDate` | LocalDate | 返团日 |
| `totalAmount` | BigDecimal | 订单总价（元，2 位小数） |
| `depositAmount` | BigDecimal | 建议定金金额 |
| `depositRatio` | Integer | 定金比例百分比（`DEPOSIT` 模式有值；`FULL` 模式恒为 100） |
| `paymentMode` | String | 支付模式（枚举见 §6.5） |
| `expiryMinutes` | Integer | 支付时限分钟数，默认 1440 |
| `payUrl` | String | 支付页绝对 URL |
| `customerName` | String | 客户姓名（回显） |

#### 错误码

| code | 含义 |
|------|------|
| `510101` | 产品不存在 / 已下架 |
| `510102` | 档位不存在 |
| `510103` | 出发日期早于今天 |
| `510104` | 出发日期超过报名截止 |
| `510105` | 拼团批次不存在 / 已满员 |
| `510106` | 总人数 = 0 |
| `510107` | `createSource` 枚举非法 |
| `510108` | 客户手机格式非法 |
| `510109` | 系统未配置默认定制师 |
| `581013` | 定制师 ID 缺失（admin 端 JWT adminId 缺失） |
| `581014` | 产品域 Feign 调用失败 |
| `581015` | 产品域返回产品不存在 |
| `581020` | MQ 事件发布失败（非主路径，记审计） |
| `581021` | 跨公司访问被拒（公司隔离） |

#### 业务边界

- ✅ **适用**：产品上架；档位有效；出发日期 ≥ 今天；总人数 ≥ 1；客户手机合法
- ❌ **拒绝**：产品下架 / 出发日期过期 / 总人数 0 / 拼团满员 / 客户手机非 11 位
- ⚠️ **可选字段省略**：不传 `createSource` 用默认 `CONSULTANT` / 不传 `roomCount` 返 null / 不传 `tags` 仅含系统自动标签

#### 示例

**典型成功 - 请求**：

```http
POST /v3/admin/order
Authorization: Bearer {admin_jwt}
Content-Type: application/json

{
  "productId": 30001234567,
  "tierSeq": 1,
  "departureDate": "2026-06-01",
  "adultCount": 2,
  "childCount": 1,
  "customerName": "张三",
  "customerPhone": "13800002046",
  "customerRemark": "希望住朝阳房",
  "createSource": "CONSULTANT",
  "groupBatchId": 80001234567890,
  "roomCount": 2,
  "tags": ["VIP 客户"]
}
```

**典型成功 - 响应**：

```json
{
  "code": 200,
  "data": {
    "id": "60123456789012",
    "orderNo": "HL20260518220000001",
    "displayOrderNo": "HL20260518220000001",
    "orderStatus": "PENDING_PAY",
    "flowStatus": "AWAITING_PROFILE",
    "consultantId": "50001234567890",
    "consultantSource": "DEFAULT_ASSIGNED",
    "tags": ["VIP 客户", "含儿童"],
    "createdAt": "2026-05-18T22:00:00",
    "productName": "长白山天池3日深度游",
    "tierName": "经典档",
    "groupBatchName": "第 2 期",
    "departureDate": "2026-06-01",
    "returnDate": "2026-06-03",
    "totalAmount": 8580.00,
    "depositAmount": 2574.00,
    "depositRatio": 30,
    "paymentMode": "DEPOSIT",
    "expiryMinutes": 1440,
    "payUrl": "https://pay.hulalv.com/pay/HL20260518220000001",
    "customerName": "张三"
  },
  "msg": "success"
}
```

**异常（拼团满员 510105） - 请求**：（同上，但 `groupBatchId` 指向已满批次）

**异常 - 响应**：

```json
{ "code": 510105, "data": null, "msg": "拼团批次不存在或已满员" }
```

---

### 3.2 §1.2 订单列表

**路径**：`GET /v3/admin/order`
**使用场景**：定制师 / 主管 / 客服多维度筛选订单
**认证**：JWT（admin 角色） | **分页**：继承 PageParam

#### 入参（`OrderListReqVO extends PageParam`）

| 字段 | 类型 | 必填 | 说明 |
|------|------|:----:|------|
| `page` | Integer | ❌ | 页码，默认 1 |
| `pageSize` | Integer | ❌ | 每页条数，默认 10 |
| `orderStatus` | String | ❌ | 粗状态过滤（传英文枚举值，多值用逗号，见 §6.2） |
| `flowStatus` | String | ❌ | 细状态过滤（传英文枚举值，见 §6.3） |
| `tagNames` | List\<String\> | ❌ | 按标签过滤（多标签为 AND） |
| `keyword` | String | ❌ | 关键字（LIKE 团号 / 客户姓名 / 产品名 / 订单号 任一） |
| `departureDateFrom` | LocalDate | ❌ | 出发日期范围起始 |
| `departureDateTo` | LocalDate | ❌ | 出发日期范围结束 |
| `createSource` | String | ❌ | 来源过滤（枚举见 §6.1） |
| `cancelled` | Boolean | ❌ | 是否含已取消（默认 false） |

#### 出参（`Result<PageResult<OrderListItemRespVO>>`）

`PageResult` 字段：`list: List<OrderListItemRespVO>` / `total: Long` / `page` / `pageSize`

`OrderListItemRespVO`（18 字段）：

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | String | 订单 ID |
| `orderNo` | String | 订单号 |
| `teamNo` | String? | 团号（订金支付成功时生成，创单时为 null）|
| `displayOrderNo` | String | 完整展示订单号 |
| `productName` | String | 产品名（快照） |
| `productCoverImg` | String | 产品封面 URL |
| `tierName` | String | 档位名（快照） |
| `customerName` | String | 客户姓名 |
| `customerPhoneMasked` | String | 客户手机（脱敏 `138****2046`） |
| `peopleSummary` | String | 人数摘要（"2 大 1 小"） |
| `departureDate` | LocalDate? | 出发日（未定时 null） |
| `tripDays` | Integer | 行程天数 |
| `orderStatus` | String | 粗状态（枚举见 §6.2） |
| `flowStatus` | String | 细状态（枚举见 §6.3） |
| `totalAmount` | BigDecimal | 订单金额 |
| `paidAmount` | BigDecimal | 实付金额 |
| `balanceAmount` | BigDecimal | 待付金额 |
| `consultantName` | String | 定制师姓名 |
| `tags` | List\<String\> | 标签列表 |
| `createdAt` | LocalDateTime | 创单时间 |

#### 错误码

参数格式错误走全局 400，无业务错误码。

#### 业务边界

- ✅ **默认行为**：`cancelled` 不传 = 不含已取消订单
- ⚠️ **关键字**：`keyword` 同时 LIKE 4 字段（团号 / 客户姓名 / 产品名 / 订单号）任一命中
- ⚠️ **标签过滤**：`tagNames` 多值是 **AND**（订单必须含全部标签才命中），不是 OR

#### 示例

**典型 - 请求**：

```http
GET /v3/admin/order?page=1&pageSize=10&orderStatus=PENDING_DEPARTURE&tagNames=VIP%20%E5%AE%A2%E6%88%B7
Authorization: Bearer {admin_jwt}
```

**典型 - 响应**：

```json
{
  "code": 200,
  "data": {
    "list": [
      {
        "id": "60123456789012",
        "orderNo": "HL20260510143025001",
        "teamNo": "20260601A",
        "displayOrderNo": "HL20260510143025001-T20260601A",
        "productName": "长白山天池3日深度游",
        "productCoverImg": "https://oss.hulalv.com/p/changbai-cover.jpg",
        "tierName": "经典档",
        "customerName": "张三",
        "customerPhoneMasked": "138****2046",
        "peopleSummary": "2 大 1 小",
        "departureDate": "2026-06-01",
        "tripDays": 3,
        "orderStatus": "PENDING_DEPARTURE",
        "flowStatus": "PENDING_DEPARTURE",
        "totalAmount": 8580.00,
        "paidAmount": 8580.00,
        "balanceAmount": 0.00,
        "consultantName": "李定制",
        "tags": ["VIP 客户", "二次复购"],
        "createdAt": "2026-05-10T14:30:25"
      }
    ],
    "total": 1,
    "page": 1,
    "pageSize": 10
  },
  "msg": "success"
}
```

---

### 3.3 §1.3.1 订单详情主聚合

**路径**：`GET /v3/admin/order/{id}`
**使用场景**：详情页**首屏加载**——一次请求拿到主单 + 标签 + 概览（出行人 / 备注 / 紧急联系人）；Tab 详情按需懒加载（§1.3.2 ~ §1.3.7）
**认证**：JWT + 公司隔离 | **响应规模**：精简，不含 6 Tab 子接口数据

> 📌 **本接口只返回 main / tags / overview 3 个顶层字段**。原 v5.48 设计的"一次返 9 Tab 全部数据"已拆分：finance / itinerary / contractInsurance / serviceStandard / statusLog / refund 移到 §1.3.2 ~ §1.3.7 独立懒加载接口。

#### 入参

| 字段 | 类型 | 必填 | 说明 |
|------|------|:----:|------|
| `id` | Long | ✅ | 订单 ID（path） |

#### 出参（`Result<OrderDetailRespVO>`，3 顶层字段）

| 字段 | 类型 | 说明 |
|------|------|------|
| `main` | OrderMainVO | 订单主单 + 异常态横条 + progressStepper 步骤进度条 |
| `tags` | List\<TagVO\> | 标签列表 |
| `overview` | OverviewVO | Tab 1 概览（出行人 + 备注 + 紧急联系人） |

`OrderMainVO` 关键字段：

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | String | 订单 ID |
| `displayOrderNo` | String | 完整展示订单号 |
| `productName` / `tierName` | String | 产品名 / 档位名（快照） |
| `orderStatus` | String | 粗状态（枚举见 §6.2） |
| `flowStatus` | String | 细状态（枚举见 §6.3） |
| `totalAmount` / `paidAmount` / `balanceAmount` | BigDecimal | 金额三件套 |
| `departureDate` / `returnDate` | LocalDate | 出发日 / 返团日 |
| `tripDays` / `tripNights` | Integer | 行程天数 / 晚数 |
| `adultCount` / `childCount` / `youngChildCount` / `babyCount` | Integer | 4 类人数 |
| `customerName` | String | 客户姓名 |
| `customerPhoneMasked` | String | 客户手机（admin 也脱敏，如 138****2046） |
| `consultantName` | String | 定制师姓名 |
| `confirmedAt` | LocalDateTime? | 确认锁单时间 |
| `exceptionBadges` | Map<String, Boolean> | 异常态横条 9 类标识（见下方）⚠️ 运行时**暂返 null**，OrderInfoConverter 派生逻辑待 Issue 接通子表后实现 |
| `progressStepper` | Object | 步骤进度条（见下方）⚠️ 运行时**暂返 null**，OrderInfoConverter 派生逻辑待 Issue 接通子表后实现 |
| `contractStatus` | String? | [Tab 状态] 合同状态枚举：`NONE/GENERATING/GENERATED/SIGNED/VOIDED/RESIGNING`，直接读主表 contract_status |
| `insuranceStatus` | String? | [Tab 状态] 保险状态枚举：`NONE/ISSUING/ISSUED/CANCELLED/FAILED`，直接读主表 insurance_status |
| `refundStatus` | String | [Tab 状态] 退款汇总状态枚举：`NONE/PROCESSING/COMPLETED`（派生，见 OrderMainRefundStatus） |
| `hasRefund` | Boolean | [Tab 状态] 是否存在退款记录（refundedAmount > 0） |
| `hasServiceStandard` | Boolean | [Tab 状态] 是否存在服务标准快照（EXISTS order_product_snapshot） |
| `hasFinanceDetail` | Boolean | [Tab 状态] 是否有财务明细（discountAmount > 0 OR surchargeAmount > 0，派生无 SQL） |

**`exceptionBadges`** 9 类布尔字段（全 false 表示无异常）：`contractFail` / `insuranceFail` / `refundAbnormal` / `grabTimeout` / `hotelPending` / `vehiclePending` / `travelerIncomplete` / `longUnpaid` / `awaitingCustomerConfirm`

**`progressStepper`**：`currentStage` (String) + `nodes` 数组，每节点 `{key, label, status, subItems?}`
- 节点 key 枚举：`INFO_COMPLETE` / `ASSIGN_PARALLEL` / `CONFIRM` / `DEPARTED` / `RETURNED` / `REVIEW` / `SETTLED`
- 节点 status：`DONE` / `ACTIVE` / `PENDING` / `NOT_APPLICABLE`
- `ASSIGN_PARALLEL` 含 `subItems`：`HOTEL` / `VEHICLE` / `LEADER` / `PHOTOGRAPHER` 子项，每子项 {key, label, subStatus, applicable}；subStatus 枚举同节点 status：DONE / ACTIVE / PENDING / NOT_APPLICABLE

`TagVO`：`name` / `type`（枚举见 §6.15） / `color`

`OverviewVO` 关键字段：

| 字段 | 类型 | 说明 |
|------|------|------|
| `travelers` | List\<TravelerVO\> | 出行人完整集合（复用 traveler 模块 TravelerVO，含证件 / 性别 / 生日 / 民族 / 手机 / 紧急联系人 / 同住分组等，admin 明文） |
| `customerRemark` | String? | 客户备注 |
| `consultantRemark` | String? | 定制师备注 |
| `emergencyContactName` | String? | 紧急联系人姓名 |
| `emergencyContactPhone` | String? | 紧急联系人手机 |

`TravelerVO` 字段口径详见 traveler 模块 §2.1 出行人列表 changelog。

#### 错误码

| code | 含义 |
|------|------|
| `581020` | 订单不存在 |
| `581021` | 无权访问该订单（公司隔离） |

#### 业务边界

- ✅ **首屏一次请求拿全 main + tags + overview**
- ⚠️ 6 Tab 数据**不在本响应**，按需调 §1.3.2 ~ §1.3.7 子接口
- ⚠️ 跨公司访问 → `581021`

#### 示例

**典型 - 请求**：

```http
GET /v3/admin/order/60123456789012
Authorization: Bearer {admin_jwt}
```

**典型 - 响应**：

```json
{
  "code": 200,
  "data": {
    "main": {
      "id": "60123456789012",
      "displayOrderNo": "HL20260510143025001-T20260601A",
      "productName": "长白山天池3日深度游",
      "tierName": "经典档",
      "orderStatus": "PENDING_DEPARTURE",
      "flowStatus": "PENDING_DEPARTURE",
      "totalAmount": 8580.00,
      "paidAmount": 8580.00,
      "balanceAmount": 0.00,
      "departureDate": "2026-06-01",
      "returnDate": "2026-06-03",
      "tripDays": 3,
      "tripNights": 2,
      "adultCount": 2,
      "childCount": 1,
      "youngChildCount": 0,
      "babyCount": 0,
      "customerName": "张三",
      "customerPhoneMasked": "138****2046",
      "consultantName": "李定制",
      "confirmedAt": "2026-05-12T10:25:00",
      "exceptionBadges": {
        "contractFail": false, "insuranceFail": false, "refundAbnormal": false,
        "grabTimeout": false, "hotelPending": false, "vehiclePending": false,
        "travelerIncomplete": false, "longUnpaid": false, "awaitingCustomerConfirm": false
      },
      "progressStepper": {
        "currentStage": "RETURNED",
        "nodes": [
          {"key": "INFO_COMPLETE", "label": "补全信息", "status": "DONE"},
          {"key": "ASSIGN_PARALLEL", "label": null, "status": "DONE", "subItems": [
            {"key": "HOTEL", "label": "配房", "subStatus": "DONE", "applicable": true},
            {"key": "VEHICLE", "label": "配车", "subStatus": "DONE", "applicable": true},
            {"key": "LEADER", "label": "配领队", "subStatus": "DONE", "applicable": true},
            {"key": "PHOTOGRAPHER", "label": "配摄影", "subStatus": "DONE", "applicable": true}
          ]},
          {"key": "CONFIRM",  "label": "确认", "status": "DONE"},
          {"key": "DEPARTED", "label": "出行", "status": "DONE"},
          {"key": "RETURNED", "label": "返团", "status": "ACTIVE"},
          {"key": "REVIEW",   "label": "核单", "status": "PENDING"},
          {"key": "SETTLED",  "label": "结算", "status": "PENDING"}
        ]
      }
    },
    "tags": [
      {"name": "二次复购", "type": "SYSTEM", "color": "#52C41A"},
      {"name": "VIP 客户", "type": "PERSONAL", "color": "#FAAD14"}
    ],
    "overview": {
      "travelers": [
        {
          "id": "70123456789012",
          "orderId": "60123456789012",
          "travelerType": "ADULT",
          "name": "张三",
          "gender": "MALE",
          "birthday": "1985-08-12",
          "idType": "ID_CARD",
          "idNo": "220103198508121234",
          "nationality": "中国",
          "race": "汉族",
          "phone": "13800002046",
          "emergencyContact": "李四",
          "emergencyPhone": "13900008888",
          "roomGroupNo": 1,
          "profileStatus": "COMPLETED",
          "transportPlanIds": ["80012345678901234"]
        }
      ],
      "customerRemark": "希望住朝阳房",
      "consultantRemark": "VIP 客户,已沟通到达接机",
      "emergencyContactName": "李四",
      "emergencyContactPhone": "13900008888"
    }
  },
  "msg": "success"
}
```

**异常（跨公司访问 581021） - 请求**：（admin JWT 不属于订单所属公司）

```http
GET /v3/admin/order/60999999999999
Authorization: Bearer {admin_jwt}
```

**异常 - 响应**：

```json
{ "code": 581021, "data": null, "msg": "无权访问该订单" }
```

---

### 3.4 §1.3.2 财务 Tab（懒加载）

**路径**：`GET /v3/admin/order/{id}/finance`
**使用场景**：详情页财务 Tab 单独刷新（如优惠 / 退款操作完后刷新）
**认证**：JWT + 公司隔离

#### 入参

`id` (path, Long) — 订单 ID

#### 出参（`Result<FinanceVO>`）

| 字段 | 类型 | 说明 |
|------|------|------|
| `totalAmount` | BigDecimal | 订单总额 |
| `paidAmount` | BigDecimal | 实付金额 |
| `balanceAmount` | BigDecimal | 待付金额 |
| `discountAmount` | BigDecimal | 优惠金额汇总 |
| `surchargeAmount` | BigDecimal | 附加费用汇总 |
| `refundAmount` | BigDecimal | 退款金额汇总 |
| `payments` | List\<PaymentVO\> | 支付明细 |
| `discounts` | List\<DiscountVO\> | 优惠明细 |
| `surcharges` | List\<SurchargeVO\> | 附加费用 |

`PaymentVO`：`id` / `payType`（枚举见 §6.6） / `amount` / `paidAt` / `status`（枚举见 §6.7）
`DiscountVO`：`id` / `name` / `amount` / `type`（枚举见 §6.8） / `source`（枚举见 §6.9） / `createdAt`
`SurchargeVO`：`id` / `name` / `amount` / `type` / `source` / `createdAt`

#### 错误码

| code | 含义 |
|------|------|
| `581020` | 订单不存在 |
| `581021` | 无权访问该订单 |

#### 示例

**典型 - 请求**：

```http
GET /v3/admin/order/60123456789012/finance
Authorization: Bearer {admin_jwt}
```

**典型 - 响应**：

```json
{
  "code": 200,
  "data": {
    "totalAmount": 8580.00,
    "paidAmount": 8580.00,
    "balanceAmount": 0.00,
    "discountAmount": 200.00,
    "surchargeAmount": 0.00,
    "refundAmount": 0.00,
    "payments": [
      {"id": 90011, "payType": "DEPOSIT", "amount": 2000.00, "paidAt": "2026-05-10T15:00:00", "status": "SUCCESS"},
      {"id": 90012, "payType": "BALANCE", "amount": 6580.00, "paidAt": "2026-05-15T09:30:00", "status": "SUCCESS"}
    ],
    "discounts": [
      {"id": 95001, "name": "早鸟优惠", "amount": 200.00, "type": "EARLY_BIRD", "source": "MANUAL", "createdAt": "2026-05-10T14:30:00"}
    ],
    "surcharges": []
  },
  "msg": "success"
}
```

---

### 3.5 §1.3.3 合同保险 Tab（懒加载）

**路径**：`GET /v3/admin/order/{id}/contract-insurance`
**使用场景**：合同重签 / 保险重投后单独刷新该 Tab
**响应结构**：`contract` / `insurance` 两个并列子对象（前端 Tab 内上下两栏布局）

#### 入参

`id` (path, Long) — 订单 ID

#### 出参（`Result<ContractInsuranceVO>`）

| 字段 | 类型 | 说明 |
|------|------|------|
| `contract.contractStatus` | String | 合同状态（枚举见 §6.10） |
| `contract.contractSignedAt` | LocalDateTime? | 签约时间 |
| `contract.contractFileUrl` | String? | 合同文件 URL |
| `contract.events[].eventType` | String | 合同事件类型（枚举见 §6.11） |
| `contract.events[].occurredAt` | LocalDateTime | 事件发生时间 |
| `insurance.insuranceStatus` | String | 保险状态（枚举见 §6.12） |
| `insurance.insurancePolicyNo` | String? | 保单号 |
| `insurance.insurancePremium` | BigDecimal? | 保费 |
| `insurance.events[].eventType` | String | 保险事件类型（枚举见 §6.11） |
| `insurance.events[].occurredAt` | LocalDateTime | 事件发生时间 |

#### 错误码

| code | 含义 |
|------|------|
| `581020` | 订单不存在 |
| `581021` | 无权访问该订单 |

#### 示例

**典型 - 请求**：

```http
GET /v3/admin/order/60123456789012/contract-insurance
Authorization: Bearer {admin_jwt}
```

**典型 - 响应**：

```json
{
  "code": 200,
  "data": {
    "contract": {
      "contractStatus": "SIGNED",
      "contractSignedAt": "2026-05-12T11:00:00",
      "contractFileUrl": "https://oss.hulalv.com/contract/HL20260510143025001.pdf",
      "events": [
        {"eventType": "GENERATE", "occurredAt": "2026-05-12T10:55:00"},
        {"eventType": "SIGN", "occurredAt": "2026-05-12T11:00:00"}
      ]
    },
    "insurance": {
      "insuranceStatus": "ACTIVE",
      "insurancePolicyNo": "PICC2026060100123",
      "insurancePremium": 88.00,
      "events": [
        {"eventType": "ISSUE", "occurredAt": "2026-05-12T11:05:00"}
      ]
    }
  },
  "msg": "success"
}
```

---

### 3.6 §1.3.4 行程安排 Tab（懒加载）⚠️ Mock

**路径**：`GET /v3/admin/order/{id}/itinerary`
**使用场景**：调整行程节点 / 房车配置后单独刷新

> ⚠️ **当前数据 Mock**：行程节点 + 房车需求&实配为 Mock 数据，真实化进度见 follow-up Issue。前端可先按字段结构对接，真实化后无需改字段口径。

#### 入参

`id` (path, Long) — 订单 ID

#### 出参（`Result<ItineraryVO>`）

| 字段 | 类型 | 说明 |
|------|------|------|
| `days[].dayIndex` | Integer | 天序 |
| `days[].dayDate` | String | 日期（`yyyy-MM-dd`） |
| `days[].title` | String | 标题 |
| `days[].nodes` | List\<Object\> | 节点列表（结构见 itinerary 模块 §5） |
| `hotelGroup.requirement` | Object | 配房需求（`requirementId / status / roomTypeSummary / claimedBy` 等） |
| `hotelGroup.assignments` | List\<Object\> | 实际配房（`hotelName / stayDate / roomType / roomCount / unitPrice / subtotal`） |
| `vehicleGroup.requirement` | Object | 配车需求（`requirementId / status / vehicleTypeSummary / claimedBy`） |
| `vehicleGroup.assignments` | List\<Object\> | 实际配车（`vehicleType / plate / driverName / dailyFee / totalFee`） |

#### 错误码

| code | 含义 |
|------|------|
| `581020` | 订单不存在 |
| `581021` | 无权访问该订单 |

#### 示例

**典型 - 请求**：

```http
GET /v3/admin/order/60123456789012/itinerary
Authorization: Bearer {admin_jwt}
```

**典型 - 响应**（Mock 数据示意）：

```json
{
  "code": 200,
  "data": {
    "days": [
      {
        "dayIndex": 1,
        "dayDate": "2026-06-01",
        "title": "抵达长春-接机",
        "nodes": [
          {"nodeType": "TRANSPORT", "title": "接机", "startTime": "10:30"},
          {"nodeType": "HOTEL", "title": "入住凯悦酒店", "actualResourceName": "长春凯悦酒店"}
        ]
      }
    ],
    "hotelGroup": {
      "requirement": {
        "requirementId": "70011", "status": "DONE", "version": 2,
        "roomTypeSummary": "1 大床房×2 + 1 标间×1",
        "remark": "希望朝阳房,带浴缸优先",
        "budgetRange": "500-800/晚",
        "claimedBy": "房控-王芳", "claimedAt": "2026-05-11T14:20:00"
      },
      "assignments": [
        {"id": "80011", "hotelName": "长春凯悦酒店", "stayDate": "2026-06-01", "roomType": "大床房", "roomCount": 2, "roomGroupNo": 1, "unitPrice": 680, "subtotal": 1360}
      ]
    },
    "vehicleGroup": {
      "requirement": {
        "requirementId": "70021", "status": "DONE", "version": 1,
        "vehicleTypeSummary": "9 座商务车×1",
        "claimedBy": "车控-李强", "claimedAt": "2026-05-11T15:00:00"
      },
      "assignments": [
        {"id": "80021", "vehicleType": "MPV", "plate": "吉A·888XX", "driverName": "王师傅", "driverPhone": "138****1234", "dailyFee": 1100, "totalDays": 3, "totalFee": 3300}
      ]
    }
  },
  "msg": "success"
}
```

---

### 3.7 §1.3.5 状态记录 Tab（懒加载）

**路径**：`GET /v3/admin/order/{id}/status-log`
**使用场景**：执行状态变更后刷新时间线
**数据来源**：5 张审计表联合（status_log / payment / refund / contract_event / insurance_event）按 `occurredAt desc` 倒序

#### 入参

`id` (path, Long) — 订单 ID

#### 出参（`Result<List<LogTimelineVO>>`）

| 字段 | 类型 | 说明 |
|------|------|------|
| `occurredAt` | LocalDateTime | 发生时间 |
| `operator` | String | 操作人 |
| `action` | String | 操作描述 |
| `fromStatus` | String? | 变更前状态（有状态变更时有值） |
| `toStatus` | String? | 变更后状态 |
| `amount` | BigDecimal? | 涉及金额（支付/退款时有值） |

#### 错误码

| code | 含义 |
|------|------|
| `581020` | 订单不存在 |
| `581021` | 无权访问该订单 |

#### 示例

**典型 - 请求**：

```http
GET /v3/admin/order/60123456789012/status-log
Authorization: Bearer {admin_jwt}
```

**典型 - 响应**：

```json
{
  "code": 200,
  "data": [
    {"occurredAt": "2026-05-12T10:25:00", "operator": "李定制", "action": "确认锁单", "fromStatus": "定制中", "toStatus": "待出行"},
    {"occurredAt": "2026-05-10T15:00:00", "operator": "张三", "action": "支付订金", "amount": 2000.00},
    {"occurredAt": "2026-05-10T14:30:25", "operator": "李定制", "action": "创建订单"}
  ],
  "msg": "success"
}
```

---

### 3.8 §1.3.6 退款明细 Tab（懒加载，条件显示）

**路径**：`GET /v3/admin/order/{id}/refund`
**使用场景**：退款流程节点变更后刷新；前端轮询等待退款到账
**空值约定**：无退款时 `data=null`（前端据此判断是否渲染该 Tab）

#### 入参

`id` (path, Long) — 订单 ID

#### 出参（`Result<RefundDetailVO>` 或 `Result<null>`）

| 字段 | 类型 | 说明 |
|------|------|------|
| `totalRefundAmount` | BigDecimal | 合计退款金额（= `finance.refundAmount`） |
| `applications[].applicationId` | Long | 申请 ID |
| `applications[].status` | String | 进度状态（枚举见 §6.13） |
| `applications[].statusText` | String | 状态描述文案 |
| `applications[].refundAmount` | BigDecimal | 退款金额 |
| `applications[].refundChannel` | String | 退款渠道（"原路退回(支付宝)"） |
| `applications[].approverName` | String? | 审批人 |
| `applications[].approvedAt` | LocalDateTime? | 审批时间 |
| `applications[].estimatedArriveDate` | LocalDate? | 预计到账日期 |
| `applications[].actualArriveDate` | LocalDate? | 实际到账日期 |
| `applications[].progress[].step` | String | 步骤（枚举见 §6.14） |
| `applications[].progress[].label` | String | 步骤展示标签 |
| `applications[].progress[].status` | String | 步骤状态（`DONE` / `ACTIVE` / `PENDING`） |
| `applications[].progress[].occurredAt` | LocalDateTime? | 步骤发生时间 |
| `applications[].items[].itemName` | String | 项目名称 |
| `applications[].items[].reason` | String | 退款原因 |
| `applications[].items[].appliedAt` | LocalDateTime | 申请时间 |
| `applications[].items[].amount` | BigDecimal | 退款金额（负数） |

#### 错误码

| code | 含义 |
|------|------|
| `581020` | 订单不存在 |
| `581021` | 无权访问该订单 |

#### 示例

**典型（有退款） - 请求**：

```http
GET /v3/admin/order/60123456789012/refund
Authorization: Bearer {admin_jwt}
```

**典型（有退款） - 响应**：

```json
{
  "code": 200,
  "data": {
    "totalRefundAmount": 4800.00,
    "applications": [
      {
        "applicationId": 60101,
        "status": "PENDING_PAYOUT",
        "statusText": "财务已审批,等待打款",
        "refundAmount": 4800.00,
        "refundChannel": "原路退回(支付宝)",
        "approverName": "财务 · 周经理",
        "approvedAt": "2026-04-25T14:20:00",
        "estimatedArriveDate": "2026-04-30",
        "actualArriveDate": null,
        "progress": [
          {"step": "APPLY",   "label": "退款申请", "status": "DONE",    "occurredAt": "2026-04-25T11:30:00"},
          {"step": "APPROVE", "label": "财务审批", "status": "DONE",    "occurredAt": "2026-04-25T14:20:00"},
          {"step": "PAYOUT",  "label": "退款打款", "status": "ACTIVE",  "occurredAt": null},
          {"step": "ARRIVED", "label": "到账确认", "status": "PENDING", "occurredAt": null}
        ],
        "items": [
          {"itemName": "主行程退款(同行小孩临时不能出行)", "reason": "同行儿童突发感冒,不参与本次出行", "appliedAt": "2026-04-25T11:30:00", "amount": -4800.00}
        ]
      }
    ]
  },
  "msg": "success"
}
```

**边界（无退款） - 请求**：（同上路径）

**边界 - 响应**：

```json
{ "code": 200, "data": null, "msg": "success" }
```

---

### 3.9 §1.3.7 服务标准 Tab（懒加载，条件显示）

**路径**：`GET /v3/admin/order/{id}/service-standard`
**使用场景**：服务标准 Tab 单独刷新
**数据来源**：产品快照冻结（永不变）
**空值约定**：快照缺失时 `data=null`

#### 入参

`id` (path, Long) — 订单 ID

#### 出参（`Result<ServiceStandardVO>` 或 `Result<null>`）

| 字段 | 类型 | 说明 |
|------|------|------|
| `itinerary` | List\<String\> | 行程天纲（产品快照） |
| `notice.title` | String | 出团注意事项标题 |
| `notice.content` | String | 出团注意事项内容（Markdown） |
| `refundPolicy.policyId` | Long | 退改政策 ID |
| `refundPolicy.policyName` | String | 退改政策名称 |
| `refundPolicy.tiers[].minDays` | Integer | 出发前最小天数 |
| `refundPolicy.tiers[].refundRatio` | Integer | 退款比例（百分比 0-100） |
| `refundPolicy.tiers[].label` | String | 展示文案 |

#### 错误码

| code | 含义 |
|------|------|
| `581020` | 订单不存在 |
| `581021` | 无权访问该订单 |

#### 示例

**典型 - 请求**：

```http
GET /v3/admin/order/60123456789012/service-standard
Authorization: Bearer {admin_jwt}
```

**典型 - 响应**：

```json
{
  "code": 200,
  "data": {
    "itinerary": ["Day1 抵达长春-接机入住", "Day2 长白山天池1日游", "Day3 返程"],
    "notice": {
      "title": "长白山天池 3 日深度游 - 出团注意事项",
      "content": "# 出团必读\n\n1. 高原反应：海拔 2691m，请提前服用红景天\n2. 天气：山顶常年低于 0℃，请备厚外套\n..."
    },
    "refundPolicy": {
      "policyId": 50001,
      "policyName": "标准退改政策",
      "tiers": [
        {"minDays": 15, "refundRatio": 100, "label": "出发前 15 天 100%退"},
        {"minDays": 7, "refundRatio": 80, "label": "出发前 7-14 天 80%退"},
        {"minDays": 3, "refundRatio": 50, "label": "出发前 3-6 天 50%退"},
        {"minDays": 0, "refundRatio": 0, "label": "出发前 2 天内不退"}
      ]
    }
  },
  "msg": "success"
}
```

---

### 3.10 §1.4 修改订单字段

**路径**：`PUT /v3/admin/order/{id}`
**使用场景**：修改订单**非关键字段**（备注 / 紧急联系人 / 客户信息 / 转单），不触发状态机
**关键字段约定**：订单金额 / 状态等不允许在此接口改，需走专用接口
**语义**：PATCH（传哪个改哪个）
**审计**：每次修改写 1 行 `order_status_log`（即使状态未变也记录"字段被改"）

#### 入参（`OrderUpdateReqVO`，PATCH 语义）

| 字段 | 类型 | 必填 | 说明 |
|------|------|:----:|------|
| `customerName` | String | ❌ | 客户姓名 |
| `customerPhone` | String | ❌ | 客户手机 |
| `emergencyContactName` | String | ❌ | 紧急联系人姓名 |
| `emergencyContactPhone` | String | ❌ | 紧急联系人电话 |
| `customerRemark` | String | ❌ | 客户备注 |
| `consultantRemark` | String | ❌ | 定制师备注 |
| `targetConsultantId` | Long | ❌ | 转单目标定制师 ID（仅主管 / 客服角色可传） |
| `transferReason` | String | ❌ | 转单原因（传 `targetConsultantId` 时必填） |

#### 出参（`Result<Boolean>`）

返回 `true` 表示成功，`false` 表示无字段实际变化。

#### 错误码

| code | 含义 |
|------|------|
| `581020` | 订单不存在 |
| `581021` | 无权访问该订单 |
| `581030` | 转单目标定制师不存在 |
| `581031` | 转单原因为空（传 `targetConsultantId` 时） |
| `581032` | 当前角色无转单权限（仅主管 / 客服可转单） |

#### 业务边界

- ✅ **可改字段**：备注 / 紧急联系人 / 客户信息 / 转单（仅主管 / 客服角色）
- ❌ **不可改字段**：订单金额 / 订单状态 / 出发日期 / 出行人数 / 拼团批次 → 需走专用接口
- ⚠️ **转单约束**：传 `targetConsultantId` 必须同时传 `transferReason`
- ⚠️ **PATCH 语义**：不传 = 不改；传空字符串 = 改成空（区分两者）

#### 示例

**典型（转单） - 请求**：

```http
PUT /v3/admin/order/60123456789012
Authorization: Bearer {admin_jwt}
Content-Type: application/json

{
  "targetConsultantId": 50009876543210,
  "transferReason": "客户主动申请更换定制师",
  "consultantRemark": "已联系新定制师"
}
```

**典型 - 响应**：

```json
{ "code": 200, "data": true, "msg": "success" }
```

**异常（转单缺原因 581031） - 请求**：

```http
PUT /v3/admin/order/60123456789012
Authorization: Bearer {admin_jwt}
Content-Type: application/json

{
  "targetConsultantId": 50009876543210
}
```

**异常 - 响应**：

```json
{ "code": 581031, "data": null, "msg": "转单原因为空" }
```

---

### 3.11 §1.5.0 取消订单预览（只读）

**路径**：`GET /v3/admin/order/{id}/cancel-preview`
**使用场景**：定制师点击「取消订单」按钮，弹框打开瞬间调用，展示退款金额 + 扣费 + 退款政策
**认证**：JWT（admin 角色） | **幂等性**：是（只读不入库） | **限流**：无
**金额规则**：严格按订单创建时冻结的 `RefundPolicy` 快照计算，不接受人工覆盖

#### 入参

`id` (path, Long) — 订单 ID

#### 出参（`Result<OrderCancelPreviewRespVO>`）

| 字段 | 类型 | 说明 |
|------|------|------|
| `refundAmount` | BigDecimal | 退款金额（按 RefundPolicy 计算） |
| `paidAmount` | BigDecimal | 客户已付金额 |
| `deductAmount` | BigDecimal | 扣费金额 = `paidAmount - refundAmount` |
| `daysToDeparture` | Integer | 距出发天数（今天 - 出发日；负数表已过出发日） |
| `refundPolicy` | RefundPolicyVO | 退款政策快照（结构同 §3.9 `refundPolicy`） |

#### 错误码

| code | 含义 |
|------|------|
| `581020` | 订单不存在 |
| `581021` | 无权访问该订单 |
| `581050` | 订单状态不允许取消（已取消 / 已完成 / 退款中等） |

#### 业务边界

- ✅ **适用**：订单粗状态 ∈ {PENDING_PAY, PENDING_COMPLETE, CUSTOMIZING, PENDING_DEPARTURE, PENDING_BALANCE}（v3 状态机：CONFIRM event 直接迁到 PENDING_DEPARTURE；尾款重开切到 PENDING_BALANCE）
- ❌ **拒绝**：已取消 / 已完成 / 退款中 → `581050`
- ⚠️ **`daysToDeparture` 负数**：已过出发日，前端应引导走 §3.13 出行中取消（on-trip）而非本接口预览

#### 示例

**典型（出行前 12 天） - 请求**：

```http
GET /v3/admin/order/60123456789012/cancel-preview
Authorization: Bearer {admin_jwt}
```

**典型 - 响应**：

```json
{
  "code": 200,
  "data": {
    "refundAmount": 6864.00,
    "paidAmount": 8580.00,
    "deductAmount": 1716.00,
    "daysToDeparture": 12,
    "refundPolicy": {
      "policyId": 50001,
      "policyName": "标准退改政策",
      "tiers": [
        {"minDays": 15, "refundRatio": 100, "label": "出发前 15 天 100%退"},
        {"minDays": 7,  "refundRatio": 80,  "label": "出发前 7-14 天 80%退"},
        {"minDays": 3,  "refundRatio": 50,  "label": "出发前 3-6 天 50%退"},
        {"minDays": 0,  "refundRatio": 0,   "label": "出发前 2 天内不退"}
      ]
    }
  },
  "msg": "success"
}
```

---

### 3.12 §1.5.1 取消订单 - 出行前（pre-trip）

**路径**：`POST /v3/admin/order/{id}/cancel/pre-trip`
**使用场景**：定制师代客取消出行前订单。走企微 OA 审批 + 通道退款
**认证**：JWT（admin 角色） | **幂等性**：否（提交企微 OA + 创建退款申请） | **限流**：无
**金额规则**：严格按 `RefundPolicy` 计算，不接受人工覆盖（金额由 §3.11 预览给定）

#### 入参（`OrderCancelPreTripReqVO`）

| 字段 | 类型 | 必填 | 说明 | 校验规则 |
|------|------|:----:|------|----------|
| `cancelReason` | String | ✅ | 取消原因（前端可选下拉 + 自由填写） | `@NotBlank` |
| `cancelDetail` | String | ❌ | 详细说明 | — |

#### 出参（`Result<OrderCancelPreTripRespVO>`）

| 字段 | 类型 | 说明 |
|------|------|------|
| `refundApplicationId` | Long | 退款申请 ID（已提企微 OA） |
| `refundAmount` | BigDecimal | 退款金额（按 RefundPolicy 政策计算） |
| `pendingApprovalMsg` | String | 审批中提示文案 |
| `newStatus` | String | 取消后订单状态（如 `退款中`） |

#### 错误码

| code | 含义 |
|------|------|
| `581020` | 订单不存在 |
| `581021` | 无权访问该订单 |
| `581050` | 订单状态不允许取消（已取消 / 已完成 / 退款中） |
| `581051` | 订单已过出发日，需走 §3.13 on-trip 取消 |
| `581052` | 企微 OA 提交失败 |

#### 业务边界

- ✅ **适用**：订单状态可取消 + `daysToDeparture` ≥ 0
- ❌ **拒绝**：出发日过 / 状态不可取消
- ⚠️ **不可重复提交**：同一订单存在 PENDING 退款申请时第二次调用返 `581050`

#### 示例

**典型 - 请求**：

```http
POST /v3/admin/order/60123456789012/cancel/pre-trip
Authorization: Bearer {admin_jwt}
Content-Type: application/json

{
  "cancelReason": "客户临时有事无法出行",
  "cancelDetail": "客户家属突发疾病需照顾"
}
```

**典型 - 响应**：

```json
{
  "code": 200,
  "data": {
    "refundApplicationId": 95001234567890,
    "refundAmount": 6864.00,
    "pendingApprovalMsg": "已提交企微审批，预计 2 小时内完成",
    "newStatus": "退款中"
  },
  "msg": "success"
}
```

---

### 3.13 §1.5.2 取消订单 - 出行中（on-trip）

**路径**：`POST /v3/admin/order/{id}/cancel/on-trip`
**使用场景**：定制师代客取消出行中订单。**仅登记返还金额**，不走支付通道（返还金额在核单 Step 5 自动拉取结算）
**认证**：JWT（admin 角色）

#### 入参（`OrderCancelOnTripReqVO`）

| 字段 | 类型 | 必填 | 说明 | 校验规则 |
|------|------|:----:|------|----------|
| `cancelReason` | String | ✅ | 取消原因 | `@NotBlank` |
| `returnAmount` | BigDecimal | ✅ | 定制师手填的返还金额（不走政策算） | `@NotNull` `@DecimalMin(0, exclusive)` |
| `returnRemark` | String | ✅ | 返还金额备注（说明已用成本扣除项） | `@NotBlank` |

#### 出参（`Result<OrderCancelOnTripRespVO>`）

| 字段 | 类型 | 说明 |
|------|------|------|
| `settlementRefundId` | Long | 返还登记 ID |
| `returnAmount` | BigDecimal | 已登记的返还金额（= 入参回显） |
| `newStatus` | String | 取消后状态（`已取消`） |

#### 错误码

| code | 含义 |
|------|------|
| `581020` | 订单不存在 |
| `581021` | 无权访问该订单 |
| `581053` | 订单未出发，不能走 on-trip 取消 |
| `581054` | 订单已完成，不能取消 |
| `581055` | `returnAmount` 大于 `paidAmount` |

#### 业务边界

- ✅ **适用**：订单粗状态 = `出行中` 或 `已确认` 但已过出发日
- ❌ **拒绝**：未出发 → `581053`；已完成 → `581054`；返还金额超额 → `581055`
- ⚠️ **不走支付通道**：本接口**只登记**返还金额，不发起实退；实退在核单 Step 5 走

#### 示例

**典型 - 请求**：

```http
POST /v3/admin/order/60123456789012/cancel/on-trip
Authorization: Bearer {admin_jwt}
Content-Type: application/json

{
  "cancelReason": "客户中途突发疾病",
  "returnAmount": 2500.00,
  "returnRemark": "已用 2 天住宿+用车+导游，扣除 5880 元"
}
```

**典型 - 响应**：

```json
{
  "code": 200,
  "data": {
    "settlementRefundId": 96001234567890,
    "returnAmount": 2500.00,
    "newStatus": "已取消"
  },
  "msg": "success"
}
```

---

### 3.14 §1.7 状态变更操作（通用状态机）

**路径**：`POST /v3/admin/order/{id}/transition`
**使用场景**：所有由状态机驱动的操作统一走此接口。例如「确认锁单」「关闭订单」「触发尾款支付」等
**认证**：JWT（admin 角色） | **幂等性**：否（写 `order_status_log`）
**副作用**：根据 `eventCode` 触发不同副作用（生成合同 / 投保 / 通知司机等），副作用列表在响应 `triggeredEvents` 中返回

#### 入参（`OrderTransitionReqVO`）

| 字段 | 类型 | 必填 | 说明 | 校验规则 |
|------|------|:----:|------|----------|
| `eventCode` | String | ✅ | 状态机事件代码，9 个：PAY_DEPOSIT / PAY_FULL / CANCEL / CONFIRM / INITIATE_REFUND / SET_PENDING_BALANCE / SET_PENDING_DEPARTURE / DEPART / FINISH（含义见 §6.17） | `@NotBlank` |
| `reason` | String | ❌ | 操作原因（按 event 强制要求时必填） | — |
| `payload` | Map\<String, Object\> | ❌ | 事件相关额外数据（不同 event 含义不同） | — |

#### 出参（`Result<OrderTransitionRespVO>`）

| 字段 | 类型 | 说明 |
|------|------|------|
| `success` | Boolean | 是否成功 |
| `oldStatus` | String | 变更前粗状态 |
| `newStatus` | String | 变更后粗状态 |
| `oldFlowStatus` | String | 变更前细状态 |
| `newFlowStatus` | String | 变更后细状态 |
| `triggeredEvents` | List\<String\> | 副作用事件列表（枚举见 §6.18） |

#### 错误码

| code | 含义 |
|------|------|
| `581020` | 订单不存在 |
| `581021` | 无权访问该订单 |
| `581060` | `eventCode` 枚举非法 |
| `581061` | 当前状态不允许该 event（状态机迁移非法） |
| `581062` | `reason` 必填但未传（如 `CANCEL` event） |
| `581063` | 前置 checklist 未全通过（如 `CONFIRM` event 时需 §3.15 全 ✅） |

#### 业务边界

- ✅ **状态机驱动**：触发条件由后端状态机定义，前端只传 `eventCode`，不需要懂迁移规则
- ⚠️ **`CONFIRM` event 强约束**：调用前必须先调 §3.15 confirm-checklist 且 `allPassed=true`，否则返 `581063`
- ⚠️ **副作用异步**：`triggeredEvents` 中 `ASYNC_*` 前缀的事件是异步执行的，本接口返回时副作用可能未完成（用 status-log Tab §3.7 跟踪）

#### 示例

**典型（确认锁单） - 请求**：

```http
POST /v3/admin/order/60123456789012/transition
Authorization: Bearer {admin_jwt}
Content-Type: application/json

{
  "eventCode": "CONFIRM",
  "reason": "定制师确认所有前置条件已完成",
  "payload": {}
}
```

**典型 - 响应**：

```json
{
  "code": 200,
  "data": {
    "success": true,
    "oldStatus": "CUSTOMIZING",
    "newStatus": "PENDING_DEPARTURE",
    "oldFlowStatus": "PENDING_CONFIRM",
    "newFlowStatus": "PENDING_DEPARTURE",
    "triggeredEvents": ["ASYNC_CONTRACT_GENERATE", "ASYNC_INSURANCE_ISSUE"]
  },
  "msg": "success"
}
```

**异常（checklist 未通过 581063） - 请求**：（同上 `eventCode=CONFIRM`，但订单存在未完善出行人）

**异常 - 响应**：

```json
{ "code": 581063, "data": null, "msg": "前置 checklist 未全通过：出行人信息未完善 1/3" }
```

---

### 3.15 §1.8 确认锁单前置 Checklist

**路径**：`GET /v3/admin/order/{id}/confirm-checklist`
**使用场景**：定制师点击「确认订单」按钮时调用。
- 返回 5 项前置校验明细（决定按钮是否可点）
- 通过时返回"确认行程"弹框预览数据（行程概览 + 自动副作用 + 通知项）
- 不通过时 `preview=null`，前端展示 5 项 `failReason` 列表 + `actionPath` 跳转引导

**认证**：JWT（admin 角色） | **幂等性**：是（只读不入库）

#### 入参

`id` (path, Long) — 订单 ID

#### 出参（`Result<ConfirmChecklistRespVO>`）

| 字段 | 类型 | 说明 |
|------|------|------|
| `allPassed` | Boolean | 是否全部通过（任一项不通过则 false） |
| `items` | List\<ChecklistItemVO\> | 5 项详细结果 |
| `preview` | PreviewVO? | 确认行程弹框预览（仅 `allPassed=true` 时返回） |

`ChecklistItemVO`：
| 字段 | 类型 | 说明 |
|------|------|------|
| `code` | String | 检查项代码（枚举见 §6.19） |
| `passed` | Boolean | 是否通过 |
| `failReason` | String? | 未通过原因（通过时 null） |
| `actionPath` | String? | 引导操作路径（如配房页跳转；通过时 null） |

`PreviewVO`（仅 `allPassed=true` 时存在）：
| 字段 | 类型 | 说明 |
|------|------|------|
| `departureDate` | LocalDate | 出发日期 |
| `totalPeopleCount` | Integer | 总出行人数（4 类相加） |
| `driverName` | String | 司机姓名 |
| `driverPhoneMasked` | String | 司机手机（脱敏） |
| `hotels` | List\<{cityName, hotelName}\> | 酒店列表（按行程城市分组） |
| `contractAutoAction.planName` | String | 合同方案名（产品快照） |
| `contractAutoAction.autoSign` | Boolean | 是否自动发送给客户线上签署 |
| `insuranceAutoAction.planName` | String | 保险产品名 |
| `insuranceAutoAction.peopleCount` | Integer | 投保人数（= `totalPeopleCount`） |
| `insuranceAutoAction.effectiveDescription` | String | 生效时间描述 |
| `notifications.notifyDriver` | Boolean | 是否通知司机 |
| `notifications.notifyHotel` | Boolean | 是否通知酒店确认房态 |
| `notifications.notifyCustomer` | Boolean | 是否向客户发送出行提醒 |
| `notifications.customerChannel` | String | 客户通知渠道（`WX` / `SMS` / `MIXED`） |

#### 错误码

| code | 含义 |
|------|------|
| `581020` | 订单不存在 |
| `581021` | 无权访问该订单 |

#### 业务边界

- ✅ **前置校验**：5 项 checklist 用于阻止用户点【确认订单】按钮在前置条件未满足时
- ⚠️ **`actionPath` 引导**：前端建议按字面值跳转（如 `/admin/order/orders/{id}?tab=overview`），不是后端约定渲染
- ⚠️ **`preview` 条件返回**：`allPassed=false` 时 `preview` 为 null，前端不渲染预览区
- ⚠️ **`preview` 数据是预演**：本接口返回的合同方案 / 保险方案是「点击确认后会执行什么」的预演，**不**意味着已经执行（实际执行由 §3.14 `eventCode=CONFIRM` 触发）

#### 示例

**典型（未通过） - 请求**：

```http
GET /v3/admin/order/60123456789012/confirm-checklist
Authorization: Bearer {admin_jwt}
```

**典型（未通过） - 响应**：

```json
{
  "code": 200,
  "data": {
    "allPassed": false,
    "items": [
      {"code": "TRAVELER_COMPLETE", "passed": false, "failReason": "出行人信息未完善 1/3 (小明缺证件号)", "actionPath": "/admin/order/orders/60123456789012?tab=overview"},
      {"code": "PAYMENT_OK", "passed": true, "failReason": null, "actionPath": null},
      {"code": "HOTEL_DONE", "passed": true, "failReason": null, "actionPath": null},
      {"code": "VEHICLE_DONE", "passed": true, "failReason": null, "actionPath": null},
      {"code": "CONTRACT_TEMPLATE_OK", "passed": true, "failReason": null, "actionPath": null}
    ],
    "preview": null
  },
  "msg": "success"
}
```

**典型（全通过） - 请求**：（同上）

**典型（全通过） - 响应**：

```json
{
  "code": 200,
  "data": {
    "allPassed": true,
    "items": [
      {"code": "TRAVELER_COMPLETE", "passed": true, "failReason": null, "actionPath": null},
      {"code": "PAYMENT_OK", "passed": true, "failReason": null, "actionPath": null},
      {"code": "HOTEL_DONE", "passed": true, "failReason": null, "actionPath": null},
      {"code": "VEHICLE_DONE", "passed": true, "failReason": null, "actionPath": null},
      {"code": "CONTRACT_TEMPLATE_OK", "passed": true, "failReason": null, "actionPath": null}
    ],
    "preview": {
      "departureDate": "2026-05-30",
      "totalPeopleCount": 14,
      "driverName": "扎西师傅",
      "driverPhoneMasked": "1398761****",
      "hotels": [
        {"cityName": "拉萨", "hotelName": "瑞吉度假酒店"},
        {"cityName": "林芝", "hotelName": "悦榕庄"}
      ],
      "contractAutoAction": {
        "planName": "标准跟团方案 v3.2",
        "autoSign": true
      },
      "insuranceAutoAction": {
        "planName": "安联境内旅行险 · 尊享版",
        "peopleCount": 14,
        "effectiveDescription": "出发前 24h 内生效"
      },
      "notifications": {
        "notifyDriver": true,
        "notifyHotel": true,
        "notifyCustomer": true,
        "customerChannel": "WX"
      }
    }
  },
  "msg": "success"
}
```

---

## 6. 枚举 / 数据字典

> 跨接口共享枚举集中列出，按字段分组，标注「使用字段在哪里」。

### 6.1 createSource（订单创建来源）

**使用字段**：§3.1 入参 `createSource` / §3.2 入参 `createSource` 过滤

| 值 | 中文 | 说明 |
|----|------|------|
| `CUSTOMER` | 客户自助 | 客户在小程序自助下单 |
| `CONSULTANT` | 定制师代下单 | 默认值 |
| `OTA` | OTA 渠道 | 携程 / 美团等 OTA 引流 |
| `WALK_IN` | 门店步入 | 线下门店现场下单 |
| `B2B` | B2B 渠道 | 旅行社代下单 |
| `VIP_REPURCHASE` | VIP 复购 | — |
| `REFERRAL` | 老客户转介绍 | — |
| `PROMOTION` | 营销活动 | — |
| `INTERNAL` | 内部测试 | 不计入业绩 |

### 6.2 orderStatus（订单粗状态）

**使用字段**：§3.1 出参 / §3.2 出参 / §3.3 main / §3.2 入参过滤

> 后端 enum：`com.hulalv.order.core.enums.OrderStatus`，共 **9 项**（v5.49 对齐 SRS：退款粗态已移除，退款发起瞬间订单 order_status 直接变为 `CANCELLED`，退款进度由 refund_status 子字段记录）。**API 传/返均为英文枚举值，中文标签前端自己映射**。

| 值 | 中文标签 | 说明 |
|----|------|------|
| `PENDING_PAY` | 待支付 | 创单后默认 |
| `PENDING_COMPLETE` | 待完善 | 订金到账后进入 |
| `CUSTOMIZING` | 定制中 | 出行人 + 房车齐前 |
| `PENDING_DEPARTURE` | 待出行 | 确认锁单后 |
| `PENDING_BALANCE` | 待付尾款 | 重开尾款场景（SET_PENDING_BALANCE 事件迁入） |
| `TRAVELLING` | 出行中 | 已发车 |
| `REVIEWING` | 核单中 | 出行结束待财务核算 |
| `SETTLED` | 已结算 | 财务核算完成 |
| `CANCELLED` | 已取消 | 含退款流程中的订单（refund_status 区分进度） |

### 6.3 flowStatus（订单细状态）

**使用字段**：§3.1 出参 / §3.2 出参 / §3.3 main / §3.2 入参过滤

> 后端 enum：`com.hulalv.order.core.enums.OrderFlowStatus`，共 **15 项**（v5.49 全量重写：原 13 项支付节奏视角已废，现采 SRS v5.48 §0.4 行 636 业务环节视角，与 SRS 中文 1:1 对齐）。flow_status 列只承载流程细节，不喂状态机；粗态见 §6.2。

| 值 | 中文标签 | 说明 |
|----|------|------|
| `AWAITING_PROFILE` | 待补全信息 | 订金到账后默认细态 |
| `AWAITING_HOTEL_SUBMIT` | 待提交房型 | 出行人齐全后等定制师提交房型需求 |
| `AWAITING_HOTEL_CLAIM` | 待抢房 | 房型需求提交后进入抢单池 |
| `HOTEL_IN_PROGRESS` | 房控处理中 | 房控已接单配置中 |
| `HOTEL_NEED_ADJUST` | 房控需调整 | 房控需求调整中 |
| `AWAITING_VEHICLE_SUBMIT` | 待提交用车 | 出行人齐全后等定制师提交用车需求 |
| `VEHICLE_IN_PROGRESS` | 车控处理中 | 车控已接单配置中 |
| `VEHICLE_NEED_ADJUST` | 车控需调整 | 车控需求调整中 |
| `PENDING_CONFIRM` | 待确认 | 房车齐后等定制师确认锁单 |
| `PENDING_DEPARTURE` | 待出行 | 确认锁单后默认细态 |
| `TRAVELLING` | 出行中 | 已发车 |
| `PENDING_REVIEW` | 待核单 | 出行结束等核单 |
| `REVIEWING` | 核单中 | 财务核单中 |
| `SETTLED` | 已结算 | 核单通过 |
| `CANCELLED` | 已取消 | 终态 |

### 6.4 consultantSource（定制师分配来源）

**使用字段**：§3.1 出参 / §3.3 main

> 该字段为字符串而非强枚举类：admin 端硬编码 `MANUAL`；C 端分享下单硬编码 `SHARED`；C 端兜底默认定制师时透传 hl-user-service 派生值（如 `DEFAULT_ASSIGNED` / `ROUND_ROBIN`，由 user-service 决定）。

| 值 | 说明 |
|----|------|
| `MANUAL` | admin 端代下单（JWT adminId 即定制师） |
| `SHARED` | C 端客户扫定制师专属分享码下单 |
| `DEFAULT_ASSIGNED` | C 端兜底：hl-user-service 派发默认定制师 |
| `ROUND_ROBIN` | C 端兜底：hl-user-service 轮询派发（未来扩展） |
| `LINK_BOUND` | （DB comment 保留，当前代码路径未实际写入） |

> ⚠️ 因 user-service 可能新增 source 值，前端**严禁**对该字段穷举判断；展示时未知值兜底为 `MANUAL` 的中文标签即可。

### 6.5 paymentMode（支付模式）

**使用字段**：§3.1 出参

| 值 | 说明 |
|----|------|
| `DEPOSIT` | 定金模式（30% 定金 + 余款） |
| `FULL` | 全款模式（100% 一次付清） |

### 6.6 payType（支付类型）

**使用字段**：§3.4 出参 `payments[].payType`

| 值 | 说明 |
|----|------|
| `DEPOSIT` | 定金 |
| `BALANCE` | 尾款 |

### 6.7 payment status（支付记录状态）

**使用字段**：§3.4 出参 `payments[].status`

| 值 | 说明 |
|----|------|
| `SUCCESS` | 成功 |
| `PENDING` | 处理中 |
| `FAIL` | 失败 |

### 6.8 discount type（优惠类型）

**使用字段**：§3.4 出参 `discounts[].type`

| 值 | 说明 |
|----|------|
| `EARLY_BIRD` | 早鸟优惠 |
| `VIP` | VIP 优惠 |
| `COUPON` | 优惠券 |
| `PROMOTION` | 营销活动优惠 |

### 6.9 discount source（优惠 / 附加费来源）

**使用字段**：§3.4 出参 `discounts[].source` / `surcharges[].source`

| 值 | 说明 |
|----|------|
| `MANUAL` | 手动添加（定制师人工） |
| `AUTO` | 系统自动 |
| `HOTEL_ASSIGN` | 配房环节产生（仅 surcharge） |
| `VEHICLE_ASSIGN` | 配车环节产生（仅 surcharge） |

### 6.10 contractStatus（合同状态）

**使用字段**：§3.5 出参 `contract.contractStatus`

| 值 | 说明 |
|----|------|
| `PENDING` | 待生成 |
| `GENERATED` | 已生成待签 |
| `SIGNED` | 已签约 |
| `VOIDED` | 已作废 |

### 6.11 event type（合同 / 保险事件类型）

**使用字段**：§3.5 出参 `contract.events[].eventType` / `insurance.events[].eventType`

| 值 | 说明 |
|----|------|
| `GENERATE` | 合同生成 |
| `SIGN` | 合同签约 |
| `VOID` | 合同作废 |
| `REOPEN` | 合同重开 |
| `ISSUE` | 保险出单 |
| `CANCEL` | 保险退保 |

### 6.12 insuranceStatus（保险状态）

**使用字段**：§3.5 出参 `insurance.insuranceStatus`

| 值 | 说明 |
|----|------|
| `PENDING` | 待出单 |
| `ACTIVE` | 已生效 |
| `FAILED` | 出单失败 |
| `CANCELLED` | 已退保 |

### 6.13 refund application status（退款申请状态）

**使用字段**：§3.8 出参 `applications[].status`

| 值 | 说明 |
|----|------|
| `PENDING_APPROVE` | 待审批 |
| `PENDING_PAYOUT` | 财务已审批，待打款 |
| `PENDING_ARRIVAL` | 已打款，待到账 |
| `COMPLETED` | 退款完成（已到账） |
| `REJECTED` | 已拒绝 |

### 6.14 refund progress step（退款进度步骤）

**使用字段**：§3.8 出参 `applications[].progress[].step`

| 值 | 说明 |
|----|------|
| `APPLY` | 退款申请 |
| `APPROVE` | 财务审批 |
| `PAYOUT` | 退款打款 |
| `ARRIVED` | 到账确认 |

### 6.15 tag type（标签类型）

**使用字段**：§3.3 出参 `tags[].type`

| 值 | 说明 |
|----|------|
| `SYSTEM` | 系统自动打的标签 |
| `PERSONAL` | 定制师手动打的标签 |
| `MANUAL` | 主管手动打的标签 |

### 6.16 traveler & exception badge（出行人 / 异常态字段）

`OverviewVO.travelers[]` 的 `travelerType` / `idType` / `profileStatus` 等枚举详见 traveler 模块 §2.1 出行人列表 changelog。

`OrderMainVO.exceptionBadges` 9 类布尔标识 / `progressStepper.nodes[].key` / `progressStepper.nodes[].status` 字段含义已在 §3.3 出参说明中列出。

### 6.17 transition eventCode（状态机事件代码）

**使用字段**：§3.14 入参 `eventCode`

> 后端 enum：`com.hulalv.order.core.enums.OrderEvent`，共 **9 个值**。
> 状态机由 `OrderStateMachineConfig` **16 条规则**驱动。

#### 6.17.1 完整规则表（事件 → 前置态 → 目标态）

| 事件 | 前置态（orderStatus） | 目标态（orderStatus） | 业务语义 |
|------|---|---|---|
| `PAY_DEPOSIT` | `PENDING_PAY` | `CUSTOMIZING` | 客户支付订金 |
| `PAY_FULL` | `PENDING_PAY` | `CUSTOMIZING` | 客户支付全款 |
| `CANCEL` | `PENDING_PAY` | `CANCELLED` | 未付款取消 |
| `CONFIRM` ⚠️ | `CUSTOMIZING` | `PENDING_DEPARTURE` | **确认锁单**（语义 ①，需先通过 §3.15 checklist）|
| `SET_PENDING_BALANCE` | `PENDING_DEPARTURE` | `PENDING_BALANCE` | 重新开放尾款 / 调整价格 |
| `DEPART` | `PENDING_DEPARTURE` | `TRAVELLING` | 开始出行 |
| `SET_PENDING_DEPARTURE` | `PENDING_BALANCE` | `PENDING_DEPARTURE` | 尾款补齐 |
| `FINISH` | `TRAVELLING` | `REVIEWING` | 结团（进入核单）|
| `CONFIRM` ⚠️ | `REVIEWING` | `SETTLED` | **核单通过 / 确认结算**（语义 ②）|
| `CANCEL` | `CUSTOMIZING` | `CANCELLED` | 定制中取消 |
| `CANCEL` | `TRAVELLING` | `CANCELLED` | 出行中取消 |
| `INITIATE_REFUND` | `CUSTOMIZING` | `CANCELLED` | 定制中发起退款 |
| `INITIATE_REFUND` | `PENDING_DEPARTURE` | `CANCELLED` | 待出行发起退款 |
| `INITIATE_REFUND` | `PENDING_BALANCE` | `CANCELLED` | 待付尾款发起退款 |
| `INITIATE_REFUND` | `REVIEWING` | `CANCELLED` | 核单中发起退款 |
| `INITIATE_REFUND` | `SETTLED` | `CANCELLED` | 已结算售后退款 |

⚠️ **`CONFIRM` 事件复用 2 种语义**：状态机以「当前粗态 + 事件」找规则，不会冲突，但前端按钮文案要按当前状态判断（CUSTOMIZING 下叫"确认锁单"，REVIEWING 下叫"确认结算"）。

#### 6.17.2 非 transition 业务路径（不走本接口）

下列业务**不走** `POST /v3/admin/order/{id}/transition`，前端按对应独立接口调用：

| 业务 | 独立接口 | 备注 |
|---|---|---|
| **核单结算（6 步）** | `PUT /v3/admin/order/{id}/settlement/step1` ~ `step4`<br>`GET / POST / DELETE /v3/admin/order/{id}/settlement/step5/*`<br>`POST /v3/admin/order/{id}/settlement/step6/submit`<br>`GET /v3/admin/order/{id}/settlement/summary` | Step 6 submit 内部事务自动推 `REVIEWING → SETTLED`，前端**不要**自己 fire `eventCode` |
| **退款发起** | 退款专用接口（详见 refund 模块 changelog） | `INITIATE_REFUND` 是 transition 事件，但前端入口走独立退款按钮 |
| **申请解锁** | **v3 已砍** | 原型 UnlockModal 按钮 v3 不实现；前端隐藏对应按钮 |

### 6.18 transition triggeredEvents（状态机副作用事件）

**使用字段**：§3.14 出参 `triggeredEvents[]`

| 值 | 说明 |
|----|------|
| `ASYNC_CONTRACT_GENERATE` | 异步生成电子合同 |
| `ASYNC_INSURANCE_ISSUE` | 异步出保单 |
| `NOTIFY_DRIVER` | 通知司机 |
| `NOTIFY_HOTEL` | 通知酒店确认房态 |
| `NOTIFY_CUSTOMER` | 向客户发出行提醒 |
| `ASYNC_REFUND_APPLY` | 异步发起退款申请 |

> 副作用异步执行，本接口返回时可能未完成；用 §3.7 status-log Tab 跟踪进度。

### 6.19 checklist item code（确认锁单前置 5 项）

**使用字段**：§3.15 出参 `items[].code`

| 值 | 说明 |
|----|------|
| `TRAVELER_COMPLETE` | 出行人信息完整（姓名 + 证件 + 手机 + 证件类型齐） |
| `PAYMENT_OK` | 支付状态满足（订金或全款到账） |
| `HOTEL_DONE` | 配房完成（hotel_stage = DONE） |
| `VEHICLE_DONE` | 配车完成（vehicle_stage = DONE） |
| `CONTRACT_TEMPLATE_OK` | 合同模板就绪（产品快照含合同方案） |

### 6.20 customerChannel（客户通知渠道）

**使用字段**：§3.15 出参 `preview.notifications.customerChannel`

| 值 | 说明 |
|----|------|
| `WX` | 仅企微 / 微信 |
| `SMS` | 仅短信 |
| `MIXED` | 双通道（企微 + 短信） |

---

## 11. 影响评估

- **是否破坏向后兼容**：否（v3 全新二期，前端 v3 项目仓库首次消费）
- **前端是否必须同步上线**：是
- **本次推送范围**：§1 模块全 15 接口（§1A 10 接口 + §1B 取消 3 接口 + §1C 状态机+锁单 2 接口），覆盖订单核心全生命周期入口

---

## 12. 注意事项

- **§3.6 itinerary 子接口数据 Mock**：当前返回占位数据，前端按字段结构对接即可，真实化后无需改字段口径
- **§3.8 / §3.9 条件显示**：`data=null` 时前端不渲染对应 Tab
- **首屏 vs 单 Tab 刷新**：详情页打开用 §3.3 主聚合（一次拿 main + tags + overview）；Tab 切换 / 单 Tab 操作完按需调 §3.4 ~ §3.9
- **公司隔离 581021**：所有 §1 接口均带跨公司隔离校验，前端无需自行过滤
- **取消订单分支**：出行前走 §3.12 走政策算金额 + 企微 OA 审批；出行中走 §3.13 仅登记返还金额（核单 Step 5 自动拉取实退）；前端按 §3.11 预览的 `daysToDeparture` 决定走哪个入口
- **CONFIRM 锁单**：前端点【确认订单】按钮**必须**先调 §3.15 checklist 拿 `allPassed=true` 再调 §3.14 `eventCode=CONFIRM`，否则后端拒绝（`581063`）

---

## 13. 关联

- **API 设计文档**: `docs/order-v3/api/API-SPEC-V5.50.html` §1.1 ~ §1.4
- **SRS 业务规格**: `docs/order-v3/srs/order-cloud-v3-srs-v5.50.html` §F1 创单 / §1.0i 模型 / §1.3 创单流程
- **数据库 Schema**: `docs/order-v3/database/DATABASE-SCHEMA-V5.50.html` §1.1 order_main / §1.2 order_tag
- **后端负责人**: @yaosutu

---

## 📝 后续追加计划

§1 模块 15 接口全部首推完毕。后续若有接口字段调整 / 错误码新增 / 业务边界变化，通过追加 commit 扩充本文件。
