去 printTime / dateRange 拆 departDate+returnDate / 顶层补订单号+订单总额+应收总额+应收尾款 / 餐食三布尔改 meals 数组 / 节点加 serviceStandard。多处破坏性,管理后台前端须同步。
12 KiB
12 KiB
打印行程单出参二次调整(去 printTime / 拆日期 / 补订单金额 / 餐食 meals 数组 / 节点服务标准)
接口路径:GET /v3/admin/order/{id}/print-itinerary 服务:hl-order-service-v3 PR:#4692 | Issue:#4691 | 前序:#4683(第一轮增强)/ #4650(首上线)| 合并至:dev-v3 变更类型:修改接口(含破坏性变更)
1. 接口背景
打印行程单(出团行程单·Driver Copy)接口联调后按前端反馈做第二轮出参调整。只改出参,入参不变,零 DDL,无新依赖。
调整目标:
- 打印时间去后端化,改前端本地生成。
- 出团/返回日期拆开,让前端自行拼接展示。
- 补齐订单号 + 订单级金额(总额/应收总额/应收尾款)。
- 餐食含餐字段结构化(三个平铺布尔 → meals 数组,带中文标签)。
- 每个资源点位带上服务标准。
2. 变更清单
| 类型 | 字段路径 | 变更说明 |
|---|---|---|
| 删除字段 | printTime |
打印时间不再由后端返回,前端本地生成 |
| 删除字段 | dateRange |
出行日期范围字符串删除,拆为 departDate + returnDate |
| 新增字段 | departDate |
出团日期(LocalDate) |
| 新增字段 | returnDate |
返回日期(LocalDate) |
| 新增字段 | orderNo |
订单号 |
| 新增字段 | orderAmount |
订单总额(下单冻结原价) |
| 新增字段 | payableTotal |
订单应收总额 |
| 新增字段 | outstandingBalance |
应收尾款(待收) |
| 删除字段 | days[].breakfast / lunch / dinner |
原 Boolean 三字段删除 |
| 新增字段 | days[].meals |
数组,固定早/午/晚三项,each {type,label,included} |
| 新增字段 | days[].nodes[].serviceStandard |
资源服务标准(景点/活动/服务有值,餐厅无恒 null) |
入参无变化,无 DDL,无新依赖。
3. 接口详情
- 方法:GET
- 路径:
/v3/admin/order/{id}/print-itinerary - 鉴权:管理后台 JWT(公司隔离后端从 JWT 校验,前端不传)
- 响应:
Result<PrintItineraryRespVO>
4. 入参
| 位置 | 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| Path | id |
String | 是 | 订单 ID |
本次入参无变化。
5. 出参
5.1 顶层(本次变化字段)
| 字段 | 类型 | 说明 | 变化 |
|---|---|---|---|
orderNo |
String | 订单号 | 新增 |
departDate |
LocalDate(String) | 出团日期 | 新增(原 dateRange 拆分) |
returnDate |
LocalDate(String) | 返回日期 | 新增 |
orderAmount |
BigDecimal(String) | 订单总额(冻结原价;本地数据恒在,不随 feeDetail 降级) | 新增 |
payableTotal |
BigDecimal(String) | 订单应收总额(取消单为 0) | 新增 |
outstandingBalance |
BigDecimal(String) | 应收尾款(待收) | 新增 |
printTime |
打印时间 | 删除 | |
dateRange |
出行日期范围 | 删除 |
其余顶层字段(agencyName / teamNo / productName / paxSummary / driver·guide·leader Name/Phone / consultantName)不变。
5.2 days[] 每日行程(变化字段)
| 字段 | 类型 | 说明 | 变化 |
|---|---|---|---|
meals |
List<MealVO> | 餐食含餐列表,固定早/午/晚三项 | 新增(原 breakfast/lunch/dinner 三布尔删除) |
breakfast / lunch / dinner |
是否含餐 | 删除,并入 meals |
MealVO:
| 字段 | 类型 | 说明 |
|---|---|---|
type |
String | 餐次:BREAKFAST / LUNCH / DINNER |
label |
String | 餐次中文:早餐 / 午餐 / 晚餐 |
included |
Boolean | 是否含餐 |
5.3 days[].nodes[] 点位(新增字段)
| 字段 | 类型 | 说明 |
|---|---|---|
serviceStandard |
String | 资源服务标准;覆盖景点(SCENIC)/活动(ACTIVITY)/服务(SERVICE),餐厅(RESTAURANT)无此字段恒 null;资源未维护/失败为 null |
节点既有字段(nodeName / nodeType / description / startTime / timePeriod / contactPerson / contactPhone / supplierPhone / remark)不变。
6. 枚举 / 数据字典
| 项 | 值 | 说明 |
|---|---|---|
meals[].type |
BREAKFAST / LUNCH / DINNER | 早 / 午 / 晚 |
meals[].included |
true | 含团餐 / 特色餐(底层 HOTEL / SPECIAL) |
meals[].included |
false | 不含 / 自理(底层 NONE / SELF / 空) |
serviceStandard |
有值 | 仅景点 / 活动 / 服务类资源 |
serviceStandard |
null | 餐厅节点,或资源未维护服务标准 |
7. 错误码
本次无新增错误码。接口为纯查询聚合,Feign 依赖失败走降级(费用块整体 null、联系人/服务标准返空串/null),不抛业务错误。
8. 示例
8.1 典型成功(字段全填示范)
{
"code": 200,
"message": "成功",
"data": {
"agencyName": "内蒙古呼籁国际旅行社有限公司",
"orderNo": "HL20260701001",
"teamNo": "26-0554",
"productName": "游牧的森林-短途版",
"departDate": "2026-07-01",
"returnDate": "2026-07-04",
"paxSummary": "2大2小",
"orderAmount": "18000.00",
"payableTotal": "12000.00",
"outstandingBalance": "6000.00",
"driverName": "扎西", "driverPhone": "13700137001",
"guideName": "", "guidePhone": "", "leaderName": "", "leaderPhone": "",
"consultantName": "王骁",
"transports": [
{"direction": "ARRIVAL", "transportType": "FLIGHT", "transportNo": "CA1234", "carrier": "中国国航", "departStation": "北京首都T2", "arriveStation": "海拉尔东山机场", "departTime": "2026-07-01 08:00:00", "arriveTime": "2026-07-01 10:30:00", "pickupRequired": true, "pickupRemark": "T2出口举牌", "remark": null}
],
"customerOverview": {"customerName": "吕思远", "customerPhone": "138****0020", "adultCount": 2, "childCount": 1, "youngChildCount": 1, "babyCount": 1, "tripDays": 4, "customerType": null, "createSource": "CONSULTANT", "customerRemark": "忌海鲜"},
"feeDetail": {"items": [{"name": "成人包价", "unitPrice": "3380.00", "qty": 2, "subtotal": "6760.00"}], "singleRoomSurcharge": "0", "grandTotal": "9540.00", "onsiteBalance": "3540.00"},
"hotels": [
{"dayNumber": 1, "stayDate": "2026-07-01", "hotelName": "海拉尔海棠酒店", "city": "呼伦贝尔市", "roomCategory": "标间", "roomCount": 4, "contactPerson": "海棠-李经理", "contactPhone": "0470-7777777", "settleType": "公司付款", "paymentMode": "月结", "checkInTime": "14:00", "checkOutTime": "12:00"}
],
"emergencyContacts": [{"contactName": "admin", "contactPhone": "13000000001", "role": "房务"}],
"days": [
{
"dayNumber": 1, "dayDate": "2026-07-01", "dayTitle": "海拉尔接机", "week": "周三",
"description": "接机入住自由活动",
"meals": [
{"type": "BREAKFAST", "label": "早餐", "included": true},
{"type": "LUNCH", "label": "午餐", "included": false},
{"type": "DINNER", "label": "晚餐", "included": false}
],
"diningRemark": null,
"gatherPlace": "{\"name\":\"海拉尔东山机场\",\"cityName\":\"呼伦贝尔市\"}",
"dismissalPlace": "{\"name\":\"海拉尔海棠酒店\"}",
"dailyMileage": "200.00",
"nodes": [
{"nodeName": "黑山头", "nodeType": "SCENIC", "description": "以壮美日落闻名", "serviceStandard": "黑山头点位服务标准:1.带队提前30分钟到集合点清点人数;2.按行程完成本点位服务;3.如遇异常及时上报计调。", "startTime": "10:00", "timePeriod": null, "contactPerson": "黑山头-前台", "contactPhone": "0470-8800006", "supplierPhone": "", "remark": null},
{"nodeName": "早餐", "nodeType": "RESTAURANT", "description": "含(酒店)", "serviceStandard": null, "startTime": null, "timePeriod": null, "contactPerson": "", "contactPhone": "", "supplierPhone": "", "remark": null}
]
}
],
"notices": [
{"level": "FORBIDDEN", "title": "严禁事项 · 违者扣全部车费、永不录用", "color": "#DC2626", "icon": "🚫", "items": ["严禁向客人推荐自费项目、带客进购物店;违者扣除本行程全部车费,且永不录用"]},
{"level": "WARNING", "title": "警示事项 · 风险由领队、师傅承担", "color": "#D97706", "icon": "⚠️", "items": ["送站时间不得早于出发时间前 2 小时"]},
{"level": "STANDARD", "title": "流程标准 · 出团必做", "color": "#16A34A", "icon": "✅", "items": ["出发前须核实全程住宿安排"]}
],
"refundNotes": [
{"sourceName": "黑山头", "intro": "退费说明", "items": [{"title": "单项未骑马", "amount": "100", "unitLabel": "/人", "settleScope": "PER_PERSON", "settleScopeLabel": "按人", "remark": null, "effectiveFrom": null, "effectiveTo": null}]}
],
"handoverChecklist": ["出行群已建立并拉入全部出行人"],
"collectReceipt": {"collectAmount": "3540.00"},
"remark": null
},
"success": true
}
8.2 边界(餐厅节点 serviceStandard 恒 null + 未配司机/大交通)
- 餐厅节点
serviceStandard永远 null(resource 模型无此列)。 - 订单未配司机/大交通时
driverName/driverPhone为空串、transports为空数组。 - 无配房 →
hotels空数组;无固化行程 →days空数组。 - 未录代收款 →
outstandingBalance仍按应收派生返回,collectReceipt.collectAmount为 null。
8.3 异常(product-v2 报价 Feign 失败)
feeDetail整块返回null(前端展示"暂无")。- 但顶层
orderAmount/payableTotal/outstandingBalance仍正常返回(本地数据,不受 Feign 影响)。
9. 业务边界
- 顶层订单金额(orderAmount/payableTotal/outstandingBalance)取自订单本地数据,恒返回,不随 feeDetail 的 product-v2 报价 Feign 降级为 null。
- 服务标准与联系人/电话均为查询类软依赖,失败降级不阻断整单。
- 餐厅节点 serviceStandard 恒 null 属预期(resource restaurant 表无 service_standard 列)。
10. 修改前后对比
| 字段 | 修改前 | 修改后 |
|---|---|---|
| 打印时间 | "printTime": "2026-07-01T10:00:00" |
字段删除(前端本地生成) |
| 日期 | "dateRange": "2026-07-01→2026-07-04" |
"departDate": "2026-07-01", "returnDate": "2026-07-04" |
| 订单金额 | 无 | 顶层新增 orderNo / orderAmount / payableTotal / outstandingBalance |
| 餐食 | "breakfast": true, "lunch": false, "dinner": false |
"meals": [{"type":"BREAKFAST","label":"早餐","included":true}, {"type":"LUNCH","label":"午餐","included":false}, {"type":"DINNER","label":"晚餐","included":false}] |
| 节点服务标准 | 无 | days[].nodes[].serviceStandard(景点/活动/服务有值,餐厅 null) |
11. 影响评估 / 回滚
破坏性变更(前端必须同步):
- 删除
printTime→ 前端改本地生成打印时间。 - 删除
dateRange→ 前端改用departDate+returnDate拼接。 - 删除
days[].breakfast/lunch/dinner→ 前端改遍历days[].meals数组(用 label 展示、included 判含餐)。
非破坏(可选接入):顶层订单号/金额、节点 serviceStandard。
回滚:接口层回退到 PR #4683 版本(第一轮增强)。零 DDL,无数据迁移,回滚无副作用。
12. 注意事项
- meals 固定三项、顺序早→午→晚,前端可直接下标或按 type 匹配。
- serviceStandard 是长文本,前端展示注意折行/截断。
- 顶层金额为字符串(防 JS 精度丢失),前端按字符串处理或自行解析。