文件
hl-api-changelog/changelogs-v2/2026-05/18_§1_订单核心模块-新增接口-管理后台.md
T
yaosutu 1175979e12 docs(§1 订单核心模块): 同步 HL@087c4331 — §1.2 加 teamNo + §6.17 三元组化 + 加非 transition 段落
回应前端 mmg 在 #2 issue 提的 2 处契约空白:

§3.2 §1.2 OrderListItemRespVO
- 字段表 17 → 18 字段,新增 teamNo(订金支付成功时生成;列表"团号"展示用)
- 响应 JSON 示例同步加 teamNo 字段
- 前端不再从 displayOrderNo substr 解析团号

§6.17 transition eventCode
- 9 行平铺表 → 16 条规则三元组(事件 → 前置态 → 目标态)
- 显式标注 CONFIRM 复用 2 种语义:
  · CUSTOMIZING → PENDING_DEPARTURE = 确认锁单
  · REVIEWING → SETTLED = 核单通过 / 确认结算
- FINISH 仅用于 TRAVELLING → REVIEWING(结团,不是结算)
- 新增 §6.17.2「非 transition 业务路径」段落:
  · 核单结算走独立 6 步接口 /settlement/step{1-6}/*,Step 6 submit 内部自动推 REVIEWING → SETTLED,前端不 fire eventCode
  · 退款走独立退款接口
  · 「申请解锁」v3 已砍,前端隐藏对应按钮

§13 关联链接 v5.49 → v5.50(同步 PR #2614 升的设计文档版本号)

关联:
- HL PR: https://git.1814.love:8443/wx/HL/pulls/2614 (merged 087c4331)
- 前端 issue: https://git.1814.love:8443/wx/hl-api-changelog/issues/2
2026-05-19 16:50:34 +08:00

64 KiB
原始文件 Blame 文件历史

【新增接口·管理后台】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 仅含系统自动标签

示例

典型成功 - 请求:

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 客户"]
}

典型成功 - 响应:

{
  "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 指向已满批次)

异常 - 响应:

{ "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

示例

典型 - 请求:

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

典型 - 响应:

{
  "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

示例

典型 - 请求:

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

典型 - 响应:

{
  "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 不属于订单所属公司)

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

异常 - 响应:

{ "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 无权访问该订单

示例

典型 - 请求:

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

典型 - 响应:

{
  "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 无权访问该订单

示例

典型 - 请求:

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

典型 - 响应:

{
  "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 无权访问该订单

示例

典型 - 请求:

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

典型 - 响应(Mock 数据示意):

{
  "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 无权访问该订单

示例

典型 - 请求:

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

典型 - 响应:

{
  "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 无权访问该订单

示例

典型(有退款) - 请求:

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

典型(有退款) - 响应:

{
  "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"
}

边界(无退款) - 请求:(同上路径)

边界 - 响应:

{ "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 无权访问该订单

示例

典型 - 请求:

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

典型 - 响应:

{
  "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 语义:不传 = 不改;传空字符串 = 改成空(区分两者)

示例

典型(转单) - 请求:

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

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

典型 - 响应:

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

异常(转单缺原因 581031) - 请求:

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

{
  "targetConsultantId": 50009876543210
}

异常 - 响应:

{ "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 天) - 请求:

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

典型 - 响应:

{
  "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

示例

典型 - 请求:

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

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

典型 - 响应:

{
  "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 走

示例

典型 - 请求:

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

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

典型 - 响应:

{
  "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 跟踪)

示例

典型(确认锁单) - 请求:

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

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

典型 - 响应:

{
  "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,但订单存在未完善出行人)

异常 - 响应:

{ "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 触发)

示例

典型(未通过) - 请求:

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

典型(未通过) - 响应:

{
  "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"
}

典型(全通过) - 请求:(同上)

典型(全通过) - 响应:

{
  "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
GET / POST / DELETE /v3/admin/order/{id}/settlement/step5/*
POST /v3/admin/order/{id}/settlement/step6/submit
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 扩充本文件。