hl-api-changelog/changelogs-v2/2026-05/18_2519_traveler-add.md
API Changelog Bot 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