hl-api-changelog/changelogs-v2/2026-07/25_5238_核单门票来源类型统一-修改接口-管理后台.md
Mimingguang 120aee2b40
所有检测均成功
changelog-filename-gate / validate (push) Successful in 2s
chore(changelog): 标记前端已实现 #5238
修改原因:hl-ui changelog loop 需要把前端消费进度回写到契约源,避免领取、实现状态与实际交付脱节。

修改内容:将 frontend_status 与已有 legacy frontend 同步为 implemented,记录负责人 hl-ui-codex,并关联 mmg/hl-ui@5a155c42395a7abd66c78789b225d6af86bb7fbd;发布和验收字段保持不变。

实际验证:回写器已校验目标文件、状态单调性、提交范围和 Front Matter 内容,提交只包含当前 changelog。

Frontend-Status: tools/mcp-api-sync/.changelog-repo/changelogs-v2/2026-07/25_5238_核单门票来源类型统一-修改接口-管理后台.md
2026-07-25 11:42:03 +08:00

15 KiB

frontend_status, frontend_owner, frontend_ref, updated_at
frontend_status frontend_owner frontend_ref updated_at
implemented hl-ui-codex mmg/hl-ui@5a155c4239 2026-07-25T03:42:03.625Z

【修改接口·管理后台】核单门票来源类型统一 (#5238)

PR: #5242 | 服务: hl-order-service-v3 | 更新时间: 2026-07-25 10:03

1. 接口背景

核单 Step2 门票/游玩项目页签中,手工补充的门票行此前在查询出参中使用 CUSTOM_ASSIGNMENT。为避免前端按不同 Tab 或来源类型做额外分支,本次将查询出参的手工门票来源统一为 MANUAL,中文名统一为 手工项目;保存接口同步允许直接提交 MANUAL

2. 变更清单

# 接口 方法 路径 变更类型 说明
1 Step 2 查询门票核单明细 GET /v3/admin/order/{orderId}/settlement/step2 修改接口 手工/自定义门票行的 sourceType 统一返回 MANUALsourceTypeName 返回 手工项目
2 Step 2 录门票核单明细 PUT /v3/admin/order/{orderId}/settlement/step2 修改接口 items[].sourceType 新增允许 MANUAL;旧 CUSTOM_ASSIGNMENT 入参继续兼容

3. 接口详情

3.1 Step 2 查询门票核单明细

  • 方法GET
  • 路径/v3/admin/order/{orderId}/settlement/step2
  • 接口名listTicket
  • ApiOperationStep 2 查询门票核单明细
  • 使用场景:进入核单 Step2 门票/游玩项目页签,或保存成功后回读页面明细。
  • 认证:需要管理后台 JWT。
  • 幂等性:幂等,只读查询。
  • 限流:无单接口额外限流。
  • 响应结构dataTicketItemVO[]

3.2 Step 2 录门票核单明细

  • 方法PUT
  • 路径/v3/admin/order/{orderId}/settlement/step2
  • 接口名saveTicket
  • ApiOperationStep 2 录门票核单明细
  • 使用场景:保存核单 Step2 门票/游玩项目明细,包含派生门票行和手工补充门票行。
  • 认证:需要管理后台 JWT。
  • 幂等性:全量替换保存;同一份 items 重复提交后,以最后一次提交结果为准。
  • 限流:无单接口额外限流。
  • 请求体兼容:推荐使用 { "items": [...] };历史数组 body [...] 仍兼容。
  • 响应结构dataSettlementTicketSaveRespVO

4. 接口入参

4.1 路径参数 / Query 参数

接口 字段 类型 必填 说明
GET / PUT orderId string 订单 ID,长整型字符串

两个接口均无 Query 参数。

4.2 GET 请求体字段

GET 无请求体。

4.3 PUT 请求体字段

字段 类型 必填 说明 校验规则
items array 门票/游玩项目明细行数组,全量替换保存 不允许为 null
items[].id string 已存在行 ID;新增行可不传 长整型字符串
items[].sourceType string 来源类型;手工门票推荐传 MANUAL SCENIC_ASSIGNMENT / ACTIVITY_ASSIGNMENT / MANUAL / CUSTOM_ASSIGNMENT
items[].sourceTypeName string 来源类型中文名,仅展示字段;保存时可不传 最大 32 字符
items[].scenicAssignmentId string/null 来源 assignment ID;手工项目传 null 长整型字符串或 null
items[].dayNumber integer/null 行程第几天;保存后以回读值为准 从 1 开始
items[].dayDate string 行程日期 yyyy-MM-dd
items[].scenicName string 景区/游玩项目名称 1-200 字符
items[].specName string/null 规格/票型名称 最大 128 字符
items[].ticketCount integer 实际购票数量;套餐含门票但无额外成本时可填 0 整数
items[].ticketUnitPrice number/null 参考成本单价,单位元 小数
items[].sellPrice number/null 客户成交单价,单位元 >= 0
items[].totalAmount number/null 客户成交小计,单位元 >= 0
items[].plannedCost number 计划成本,单位元 >= 0
items[].actualCost number 实际成本,单位元 >= 0
items[].paymentMethod string 付款方式;不传时按公司付款处理 SIGNED / COMPANY_PAID / CASH_PAID
items[].paymentMethodName string 付款方式中文名,仅展示字段;保存时可不传 最大 32 字符
items[].voucherUrls array 凭证图片 URL 数组 字符串数组
items[].remark string/null 备注 最大 500 字符

5. 出参字段

5.1 GET 响应字段:TicketItemVO[]

字段 类型 说明
code integer 业务状态码,成功为 200
message string 响应消息
success boolean 是否成功
data array 门票/游玩项目明细行数组
data[].id string/null 核单明细行 ID;未持久化派生行可能为 null
data[].sourceType string 来源类型;手工/自定义门票行本次统一返回 MANUAL
data[].sourceTypeName string/null 来源类型中文名;MANUAL 返回 手工项目
data[].scenicAssignmentId string/null 来源 assignment ID;手工项目为 null
data[].dayNumber integer/null 行程第几天
data[].dayDate string 行程日期,yyyy-MM-dd
data[].scenicName string 景区/游玩项目名称
data[].specName string/null 规格/票型名称
data[].ticketCount integer 实际购票数量
data[].ticketUnitPrice number/null 参考成本单价,单位元
data[].sellPrice number/null 客户成交单价,单位元
data[].totalAmount number/null 客户成交小计,单位元
data[].plannedCost number 计划成本,单位元
data[].actualCost number 实际成本,单位元
data[].paymentMethod string/null 付款方式
data[].paymentMethodName string/null 付款方式中文名
data[].voucherUrls array 凭证图片 URL 数组
data[].remark string/null 备注

5.2 PUT 响应字段:SettlementTicketSaveRespVO

字段 类型 说明
code integer 业务状态码,成功为 200
message string 响应消息
success boolean 是否成功
data.addedIds string[] 本次保存新增的核单明细行 ID 列表
data.updatedIds string[] 本次保存更新的核单明细行 ID 列表;当前全量替换语义下通常为空数组
data.deletedIds string[] 本次保存删除的核单明细行 ID 列表;当前返回通常为空数组
data.totalActualCost string 保存后 Step2 实际成本合计,单位元

6. 枚举 / 数据字典

6.1 sourceType

所属字段items[].sourceTypedata[].sourceType | 类型String | PUT 必填:是 | GET 必返:是

中文 说明
SCENIC_ASSIGNMENT 景区 景区派生来源行;查询和保存语义不变
ACTIVITY_ASSIGNMENT 游玩项目 游玩项目派生来源行;查询和保存语义不变
MANUAL 手工项目 本次推荐值;查询手工/自定义门票行统一返回该值,保存接口也允许提交该值
CUSTOM_ASSIGNMENT 手工项目(旧入参兼容) 仅用于兼容旧保存请求;查询响应不再返回该值

6.2 sourceTypeName

所属字段items[].sourceTypeNamedata[].sourceTypeName | 类型String | 必填:否

sourceType sourceTypeName 说明
SCENIC_ASSIGNMENT 景区 景区派生来源行
ACTIVITY_ASSIGNMENT 游玩项目 游玩项目派生来源行
MANUAL 手工项目 手工/自定义门票行统一展示名
CUSTOM_ASSIGNMENT 手工项目 旧保存请求兼容;保存成功后回读为 MANUAL / 手工项目
null / 未知值 null 查询行为不变,不新增兜底文案

6.3 paymentMethod

所属字段items[].paymentMethoddata[].paymentMethod | 类型String | 必填:否

中文 说明
SIGNED 签单 现场签单
COMPANY_PAID 公司付款 公司统一付款;未传 paymentMethod 时按该值处理
CASH_PAID 现付 现场现金/线下现付

7. 错误码

HTTP 状态 / code 含义 触发场景
200 / 200 成功 GET 查询成功或 PUT 保存成功
200 / 401 未授权 缺少有效的管理后台 Authorization
400 / 400 请求参数非法 sourceType 不在 SCENIC_ASSIGNMENT / ACTIVITY_ASSIGNMENT / MANUAL / CUSTOM_ASSIGNMENT 内,或请求体结构不符合要求
200 / 584011 当前核单状态不允许录门票核单 PUT 保存时订单不是可录门票核单的状态

7.1 错误结构

{
  "code": 400,
  "message": "sourceType 必须是 SCENIC_ASSIGNMENT / ACTIVITY_ASSIGNMENT / MANUAL / CUSTOM_ASSIGNMENT 之一",
  "data": null,
  "success": false
}

8. 示例3 组:典型 / 边界 / 异常)

8.1 典型成功GET 返回手工项目为 MANUAL

请求

GET /v3/admin/order/2079576729147338754/settlement/step2
Authorization: Bearer {token}

GET 无请求体。

响应

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": [
    {
      "id": "2080186487600025601",
      "sourceType": "MANUAL",
      "sourceTypeName": "手工项目",
      "scenicAssignmentId": null,
      "dayNumber": 2,
      "dayDate": "2026-07-22",
      "scenicName": "临时补充门票",
      "specName": "成人票",
      "ticketCount": 2,
      "ticketUnitPrice": 30.00,
      "sellPrice": 50.00,
      "totalAmount": 100.00,
      "plannedCost": 60.00,
      "actualCost": 60.00,
      "paymentMethod": "COMPANY_PAID",
      "paymentMethodName": "公司付款",
      "voucherUrls": [],
      "remark": "现场补充"
    }
  ]
}

8.2 边界成功:查询结果原样 PUT

场景说明:前端可把 GET 回来的 MANUAL 行原样放入 items 后提交;保存成功后再次 GET 仍返回 MANUAL / 手工项目

请求

PUT /v3/admin/order/2079576729147338754/settlement/step2
Authorization: Bearer {token}
Content-Type: application/json
{
  "items": [
    {
      "id": "2080186487600025601",
      "sourceType": "MANUAL",
      "sourceTypeName": "手工项目",
      "scenicAssignmentId": null,
      "dayNumber": 2,
      "dayDate": "2026-07-22",
      "scenicName": "临时补充门票",
      "specName": "成人票",
      "ticketCount": 2,
      "ticketUnitPrice": 30.00,
      "sellPrice": 50.00,
      "totalAmount": 100.00,
      "plannedCost": 60.00,
      "actualCost": 60.00,
      "paymentMethod": "COMPANY_PAID",
      "paymentMethodName": "公司付款",
      "voucherUrls": [],
      "remark": "现场补充"
    }
  ]
}

响应

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "addedIds": ["2080186500000000001"],
    "updatedIds": [],
    "deletedIds": [],
    "totalActualCost": "60.00"
  }
}

8.3 业务失败:非法 sourceType

场景说明items[].sourceType 传入未定义值时仍按参数非法处理。

请求

PUT /v3/admin/order/2079576729147338754/settlement/step2
Authorization: Bearer {token}
Content-Type: application/json
{
  "items": [
    {
      "sourceType": "TAB_MANUAL",
      "scenicAssignmentId": null,
      "dayDate": "2026-07-22",
      "scenicName": "临时补充门票",
      "specName": "成人票",
      "ticketCount": 1,
      "ticketUnitPrice": 0,
      "sellPrice": 0,
      "totalAmount": 0,
      "plannedCost": 0,
      "actualCost": 0,
      "paymentMethod": "COMPANY_PAID",
      "voucherUrls": [],
      "remark": null
    }
  ]
}

响应

{
  "code": 400,
  "message": "sourceType 必须是 SCENIC_ASSIGNMENT / ACTIVITY_ASSIGNMENT / MANUAL / CUSTOM_ASSIGNMENT 之一",
  "data": null,
  "success": false
}

9. 业务边界

  • 适用场景:核单 Step2 门票/游玩项目页签查询、保存门票明细时使用。
  • 手工项目保存:新增或编辑手工门票行时,items[].sourceType 推荐传 MANUALscenicAssignmentId 可传 null
  • 旧入参兼容:旧页面继续传 CUSTOM_ASSIGNMENT 仍可保存;保存成功后再次查询会返回 MANUAL
  • 查询结果原样提交GET 返回的 MANUAL 行可原样进入 PUT 的 items
  • 未变化范围SCENIC_ASSIGNMENTACTIVITY_ASSIGNMENT 的查询和保存语义不变;null / 未知来源的查询兜底行为不变。
  • 不适用场景:人员费用、住宿、餐食、其他支出接口没有本次契约变化。

10. 修改前后对比

10.1 字段级对比

字段 修改前 修改后
GET data[].sourceType 手工/自定义门票行返回 CUSTOM_ASSIGNMENT 手工/自定义门票行统一返回 MANUAL
GET data[].sourceTypeName 手工/自定义门票行可能按旧来源展示 手工/自定义门票行统一返回 手工项目
PUT items[].sourceType 允许 SCENIC_ASSIGNMENT / ACTIVITY_ASSIGNMENT / CUSTOM_ASSIGNMENT 允许 SCENIC_ASSIGNMENT / ACTIVITY_ASSIGNMENT / MANUAL / CUSTOM_ASSIGNMENT

10.2 行为级对比

行为 修改前 修改后
查询手工门票行 前端需要识别 CUSTOM_ASSIGNMENT 前端按 MANUAL 识别手工项目
保存手工门票行 前端需要把手工 Tab 转成 CUSTOM_ASSIGNMENT 前端可直接提交 MANUAL
查询结果原样保存 GET 的旧来源值与页面手工 Tab 值可能不一致 GET 结果可原样 PUT
旧请求兼容 CUSTOM_ASSIGNMENT 入参可保存 继续可保存,回读统一为 MANUAL

11. 影响评估 / 回滚

11.1 影响评估

  • 是否破坏向后兼容否。PUT 继续兼容旧 CUSTOM_ASSIGNMENT 入参;GET 只统一手工门票来源的展示值。
  • 前端是否必须同步上线:否。旧保存请求仍可用;但前端可清理 MANUALCUSTOM_ASSIGNMENT 互转逻辑。
  • 影响已有数据:不需要前端处理历史数据;页面以后端返回的 MANUAL 为准。

11.2 回滚方案

  • 如接口回滚,前端需恢复兼容 GET 返回 CUSTOM_ASSIGNMENT 的判断。
  • 回滚后不要把 GET 查询结果中的 sourceType 假定为一定可原样提交。

12. 注意事项

  • 前端不要再按 Tab 名称把手工项目强制转换成 CUSTOM_ASSIGNMENT;新增手工行可以直接传 MANUAL
  • 前端如有 sourceType === "CUSTOM_ASSIGNMENT" 才展示手工项目的判断,需要同步兼容或改为判断 MANUAL
  • CUSTOM_ASSIGNMENT 仅作为旧保存请求兼容值保留,不应再作为新页面查询展示值。
  • sourceTypeName 是展示字段,保存时可不传;保存后以再次查询结果为准。
  • 非法 sourceType 仍会返回参数非法,不新增兜底保存。

13. 关联 / 联系人

13.1 链接

13.2 联系人

  • 后端负责人: @yst