文件
hl-api-changelog/changelogs-v2/2026-05/18_2519_traveler-add.md
T
API Changelog Bot和Claude Opus 4.7 e9117da736 changelog(order-v3): 出行人 4 接口 (#2517/#2518/#2519/#2520)
- #2517 list 路径迁移 /travelers → /traveler/list
- #2518 batch-edit 真实业务+9错误码
- #2519 add 路径迁移+4错误码+@Idempotent+@Lock4j
- #2520 delete 方法+路径迁移+4错误码+整事务

测试服 9443 真测全 ✅

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 19:31:03 +08:00

7.5 KiB

出行人新增: POST /traveler/add 路径迁移 + 真实业务化

服务: hl-order-service-v3 (端口 8084 / 二期) PR: #2536 Issue: #2519 日期: 2026-05-18 影响范围: 管理后台 F27 改人数场景(临时加 1 个出行人) 存放目录: changelogs-v2/2026-05/(二期 v3 专属,带 -v2 后缀) 部署 commit: dev-v3 16e861a7d 测试服已验证: ✅(/@qa 通过 9443 网关 + 真 admin token round-trip)


⚠️ 关键变化

  1. 破坏性路径迁移: 老 POST /v3/admin/order/{id}/travelers → 新 POST /v3/admin/order/{id}/traveler/add(对齐 V5.48 §2.3 命名规范)
  2. 从 Mock 占位变真实业务: 三道校验 + INSERT + UPDATE order_main 人数 + INSERT order_status_log,而不是直接 insert 不校验。
  3. 新增 4 个错误码: 581115 / 581116 / 581117 / 581118
  4. 加幂等 @Idempotent(3s) + 分布式锁 @Lock4j(30s): 防止与 batch-edit / 自身重复提交并发,导致 order_main 人数计数 race。

一、背景

文档 V5.48 §2.3 定义: 当订单实际出行人数 > 创单声明人数(典型场景: 客户带了未声明的孩子)时,定制师 B 端临时加人。后端必须同步 UPDATE order_main.<type>Count,且不允许已结算 / 已取消 / 退款中的订单加人(避免影响财务封账与退款冲账)。


二、变更接口清单

# 接口 方法 老路径 新路径 变更类型
1 单个出行人新增 POST /v3/admin/order/{id}/travelers /v3/admin/order/{id}/traveler/add 破坏性路径迁移 + 真实业务化

三、接口详情

1. 单个出行人新增 POST /v3/admin/order/{id}/traveler/add

VO: TravelerCreateReqVO(请求体) / TravelerVO(响应,16 字段)

入参

字段 位置 类型 必填 说明
id Path Long ✅ 订单 ID
travelerType Body String ✅ ADULT / CHILD / YOUNG_CHILD / BABY
name Body String ❌ 姓名(可后填)
gender Body String ❌ MALE / FEMALE / UNKNOWN
birthday Body LocalDate ❌ 出生日期
idType Body String ❌ ID_CARD / PASSPORT / BIRTH_CERT
idNo Body String ❌ 证件号(明文传,DB 加密)
nationality Body String ❌ 国籍(默认"中国")
race Body String ❌ 民族(默认"汉族")
phone Body String ❌ 出行人手机(明文传)
emergencyContact Body String ❌ 紧急联系人姓名
emergencyPhone Body String ❌ 紧急联系人电话
roomGroupNo Body Integer ❌ 同住分组号

出参 Result<TravelerVO>

与 §2.1 列表接口完全相同的 16 字段 VO(含 id / orderId / travelerType / name / gender / birthday / idType / idNo / nationality / race / phone / emergencyContact / emergencyPhone / roomGroupNo / profileStatus / transportPlanIds)。

请求示例

POST /v3/admin/order/60123456789012/traveler/add
Authorization: Bearer {admin_jwt}

{
  "travelerType": "CHILD",
  "name": "王小明",
  "gender": "MALE",
  "birthday": "2018-06-20",
  "idType": "BIRTH_CERT",
  "idNo": "J012345678",
  "nationality": "中国",
  "race": "汉族",
  "roomGroupNo": 1
}

响应示例

{
  "code": 200,
  "data": {
    "id": 70123456789014,
    "orderId": 60123456789012,
    "travelerType": "CHILD",
    "name": "王小明",
    "gender": "MALE",
    "birthday": "2018-06-20",
    "idType": "BIRTH_CERT",
    "idNo": "J012345678",
    "nationality": "中国",
    "race": "汉族",
    "phone": null,
    "emergencyContact": null,
    "emergencyPhone": null,
    "roomGroupNo": 1,
    "profileStatus": "COMPLETED",
    "transportPlanIds": []
  },
  "msg": "success"
}

错误响应清单(本工单新增段位)

错误码 含义
581100 出行人主段位—— 订单不存在
581102 订单不存在,无法编辑出行人
581115 实际人数已等于声明人数,请先调整订单人数再新增出行人
581116 当前订单状态禁止新增出行人(已结算 / 已取消 / 退款中)
581117 出行人类型与现有同住分组冲突
581118 新增出行人缺少必填字段(travelerType 必填)

错误响应体示例:

{
  "code": 581116,
  "msg": "当前订单状态禁止新增出行人(已结算 / 已取消 / 退款中)",
  "data": null
}

四、契约约束

校验顺序(任一失败整事务回滚)

  1. 订单存在(581102)
  2. 订单状态白名单: 拒绝 SETTLED / CANCELLED / REFUNDING(581116)
  3. 实际 vs 声明人数: count(order_traveler 未软删) >= sum(adultCount + childCount + youngChildCount + babyCount) 时拒绝(581115,要求先调订单人数)
  4. 同住分组冲突(581117,可选字段校验)
  5. 必填: travelerType(581118)

并发控制

  • @Idempotent(timeout=3s): 同订单 3 秒重复提交直接拒绝
  • @Lock4j(expire=30000ms,keys="order:traveler:add:" + #id): 同订单 30 秒锁,防与 batch-edit 并发导致 order_main 人数计数 race

五、数据库行为

  • INSERT 1 行 order_traveler(派生 profile_status)
  • UPDATE order_main.<type>Count +1(按 travelerType 选择: adultCount / childCount / youngChildCount / babyCount)
  • INSERT 1 行 order_status_log,reason="新增出行人",flowStatus 不变(from == to)
travelerType order_main 字段 delta
ADULT adult_count +1
CHILD child_count +1
YOUNG_CHILD young_child_count +1
BABY baby_count +1

六、边界行为

  • 未登录 → 401(网关拦截)
  • 订单不存在 → 581102
  • 订单 status = SETTLED / CANCELLED / REFUNDING → 581116(优先于人数校验)
  • 实际人数已等于声明 → 581115(典型场景: 客户原本说 2 大 1 小现已 2 大 1 小,要先把声明改成 2 大 2 小再加人)
  • travelerType 未识别 → 防御性 return(不报错也不更新人数,实际由前置 @NotBlank 拦截)

七、不影响范围

  • 仅影响: 管理后台 F27 改人数(新增)场景
  • 零影响:
    • 批量编辑 /traveler/batch-edit(#2518 独立接口)
    • 软删 /traveler/{travelerId}/delete(#2520 独立接口)
    • 列表 /traveler/list(只读)
    • mp 端出行人接口
    • 老路径 POST /travelers 已下线,前端调用必须改用 /traveler/add

八、测试环境已验证

POST https://web.test.1814.love:9443/v3/admin/order/60123456789012/traveler/add
  Body: {"travelerType":"CHILD","name":"王小明","birthday":"2018-06-20",...}
  → 200 + TravelerVO(含 id / profileStatus / transportPlanIds) ✓
  → order_main.child_count +1 ✓
  → order_status_log 新增 1 行 reason=新增出行人 ✓
反例:
  - 订单 status=SETTLED → 581116 ✓
  - 实际人数 = 声明人数 → 581115 ✓
  - 老路径 POST /travelers → 404 ✓

九、相关历史 PR

PR Issue 说明 是否仍有效
#1984 - [§2 traveler skeleton] 空骨架 Mock ❌ 被本 PR 真实化覆盖
#2535 #2518 batch-edit 真实业务化(同期工单,共用 581100-581114 段位) ✅ 有效
本 PR #2536 #2519 add 接通真实业务 + 路径迁移 + 4 错误码(581115-581118) ✅ 最新

十、相关文档

  • API SPEC: D:/work2/HL-v3/docs/order-v3/api/API-SPEC-V5.48.html §2.3
  • 关联 Issue: wx/HL#2519
  • 关联 PR: wx/HL#2536