Files
Wyndham-RSVN-0918/docs/project/integrations/ohip-parameter-interface-mapping-20260917.md
T
2026-09-18 15:38:52 +08:00

118 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Oracle 业务参数与接口逐项核对
2026-09-18 最新创建规则:GROUP NEW不传TA Record Locator;FIT NEW有Tour Code时应传入TA Record Locator、没有时省略。业务规则和候选映射代码已接入:创建externalReferences以idContext=TA_RECORD_LOCATOR、id=Tour发送;映射依据官方结构+字典推导,沙箱页面落值待验,见[新CR](../requirements/CR-20260918-fit-new-conditional-ta.md)。查询接口 searchHotelReservations/taRecordLocatorList 已存在;不能用查询参数冒充创建写入字段。UPDATE的TA范围未改,FIT后续仍以系统保存的成功历史编号精确定位。
更新:2026-09-18。业务参数与字段已按公开 Oracle 契约及实际转换器逐项对照;平台公开目录复查为 184 项,消费端登记的 18 个非附件操作的方法、路径、查询参数白名单均匹配。此前“5 个核心接口尚未发布”已经关闭,不需要平台重复封装。配置查询接口已发布,但本应用的真实授权、酒店参数取值和真实酒店验收仍分开核实。
此前无TA版本的GROUP/FIT新建、修改、取消及双向转换已通过47参数/3故障;本次FIT NEW有Tour Code的候选映射已另行实现及重跑模拟,原生页面落值仍待验。原服务未更新,旧版记录见[无TA交付](ohip-no-ta-local-test-20260918.md)。
## 1. 业务范围先校正
| 任务 | 本次需要输入/修改的内容 |
| --- | --- |
| GROUP NEW | Tour、日期、Account/Contact、Rate、含早、Market/Source、GC、BTQR、TEN、THB、完整逐晚房型房数 |
| GROUP UPDATE | 按原约定修改日期、完整逐晚房型房数;保留原 Account/Contact、Rate、状态及其他新建默认值 |
| FIT NEW | Name/Country、共享 Guest、Travel Agent、日期、Adult、房型房数、Rate、Market/Source、GC、BTQR、Fixed Rate、Note;有Tour Code时写入TA Record Locator,无则省略(候选映射已接入,页面待验) |
| FIT UPDATE | 从已保存的成功历史编号查清实际 Reservation 集合,修改日期、房型房数、Rate、Note;本次同类型新增房型按已批准范围创建必要的新笔 |
| FIT ↔ GROUP | 逐个取消已确定的旧对象,再按最终类型的新建参数处理 |
| Allotment CANCEL | 查找源 Block、查询关联预订和允许的下一状态;以实际 Block ID、当前/取消状态及取消原因执行取消 |
此前口头把 GROUP 修改也概括为更新 Rate/Note 不准确。现有 CP22 和已确认流程没有该要求;GROUP Note 也未列入既定新建输入。FIT Note 保持员工确认原文;Note 中金额不转为手工房价。餐厅由 Rate Code 表达,不另写 BUALUANG/LEELA 字段;GROUP 另写含早布尔值。
## 2. GROUP 主资料
`postBlock` 新建根为 `blocks.blockInfo[].block`;`putBlock` 修改根为 `blocks[]`;`getBlock` 查询根为 `blocks.blockInfo[].block`。下表路径相对于各自单个 Block。原生接口分别为 POST `/blk/v1/hotels/{hotelId}/block`、PUT/GET `/blk/v1/hotels/{hotelId}/blocks/{blockId}`;Edge 对应 `/api/v1/blocks`、`/api/v1/blocks/{blockID}`。
| 业务参数 | Oracle 字段 | 使用范围 |
| --- | --- | --- |
| Tour / Block Name | `blockDetails.blockName` | 新建;修改前以 `searchBlocks` 的 `blockName` 查找并核对 |
| 入住 / 离店 | `blockDetails.timeSpan.startDate/endDate` | 新建、修改;按官方 Postman/指南使用 `YYYY-MM-DD`;schema 的 maxLength=8 矛盾保留记录 |
| Account / Contact 实际 ID | `blockProfiles.blockProfile[].profileIdList[].id`,配 `type=Profile` | 新建;Agent 与 AgentContact 两个关联 |
| 关联角色 / 主关联 | `blockProfiles.blockProfile[].blockProfileType`、`primary` | Agent / AgentContact,`primary=true`;不是修改 CRM 全局主账户 |
| Rate Code | `reservationDetails.ratePlanCode[].ratePlanCode`,`primary=true` | 新建;本轮同类型 GROUP UPDATE 不重设 |
| Breakfast Included | `reservationDetails.breakfast.breakfastIncluded` | 新建,使用已确认布尔值 |
| TA Record Locator | 本期不提交 | 暂停,不清空已有值 |
| Market=GTT | `blockDetails.marketCode.marketCode` | 新建 |
| Source=TA | `blockDetails.sourceOfSale.sourceCode.sourceCode` | 新建 |
| Reservation Type=GC | `blockDetails.reservationType.reservationType` | 新建 |
| Payment=BTQR | `blockDetails.paymentMethod.code` | 新建 |
| Block Status=TEN | `blockDetails.blockStatus.bookingStatus.status.code` | 新建;普通修改保留原状态 |
| Currency=THB | `blockDetails.currencyCode` | 新建 |
| Hotel / Block ID | `hotelId`;修改时 `blockIdList[].id/type` | 与路径及所选酒店一致,使用查询所得实际 ID |
上述主资料写入与查询接口均在当前公开 Edge 目录。历史GROUP TA字段由 [Oracle BLK 契约](https://github.com/oracle/hospitality-api-docs/blob/4bd129b455bc5e3ab0f900ac47983611e58659b4/rest-api-specs/property/v1/blk.json)明确提供。
## 3. GROUP 每晚房型房数
主资料的 `putBlock` 不负责 Room Grid。写入用 `putBlockAllocation`:PUT `/blk/v1/hotels/{hotelId}/blocks/{blockId}/allocation`;查询用 `getBlockRoomRateGrid`:GET `/blk/v1/hotels/{hotelId}/blocks/{blockId}/roomRateGrid`。
| 参数 | `putBlockAllocation` 请求路径 |
| --- | --- |
| 酒店、Block | `criteria.hotelId`、`criteria.blockId.id/type` |
| 房型 | `criteria.allocationRoomTypes[].roomType` |
| Initial / Actual 类别 | `criteria.allocationRoomTypes[].allocationGridDates[].allocation`,本操作用 `INITIAL/ACTUAL` |
| 单个住宿日 | `criteria.allocationRoomTypes[].allocationGridDates[].roomAllocationInfo[].start/end`,逐日填写相同日期 |
| 该日房数 | 同一个 `roomAllocationInfo[]` 下 `inventory.onePerson/twoPerson/threePerson/fourPerson` |
以住宿夜为单位,不把离店日当住宿夜;输入完整目标数量,旧房型/旧日期需处理的格明确归零。未启用 occupancy split 时按官方流程用 onePerson;启用时需有明确分列数据。查询使用 `roomAllocationCriteria=Initial/Actual`,不能机械照抄写入枚举大小写;还需 startDate、numberOfDays、完整分页。依据实际状态 allowPickup 决定类别,不把所有修改强制当 TEN。
**写入和查询均已发布并接入**:Edge PUT `/api/v1/blocks/{blockID}/allocation`,GET `/api/v1/blocks/{blockID}/room-rate-grid`。Actual 分类与 occupancy split 是独立参数;模拟装配已纠正,不能把 allowPickup=true 当成人数分列开启。依据 [Oracle Room Grid 指南](https://docs.oracle.com/en/industries/hospitality/integration-platform/maeig/t_create_a_block_with_or_without_room_grid.htm)及 BLK 契约。
## 4. FIT 主资料、客档和 Note
`postReservation` 新建根为 `reservations.reservation[]`;`putReservation` 修改根为 `reservations[]`;`getReservation` 查询根为 `reservations.reservation[]`。下表相对于单个 Reservation。原生 POST `/rsv/v1/hotels/{hotelId}/reservations`,PUT/GET 加 `/{reservationId}`;Edge 对应 `/api/v1/reservations` 和 `/{reservationID}`。
| 业务参数 | Oracle 字段 | 适用/证据 |
| --- | --- | --- |
| 入住 / 离店 | `roomStay.arrivalDate/departureDate` | 新建、修改,date |
| 房价住宿区间 | `roomStay.roomRates[].start/end` | 新建、修改;当前实现 end 为离店前一日 |
| 房型 / 房数 | `roomStay.roomRates[].roomType/numberOfUnits` | 新建、修改;不同房型不能误当同一笔的日期分段 |
| Rate Code | `roomStay.roomRates[].ratePlanCode` | 新建、修改;不从 Note 取价格 |
| Adult=2 | `roomStay.guestCounts.adults` 及 `roomStay.roomRates[].guestCounts.adults` | 新建,两层保持一致 |
| Market=X / Source=TA | `roomStay.roomRates[].marketCode/sourceCode` | 新建 |
| Fixed Rate=true | `roomStay.roomRates[].fixedRate` | 新建明确设 true;当前修改保留酒店原值,实际重新定价行为另行验证 |
| Reservation Type=GC | `roomStay.guarantee.guaranteeCode` | 新建;不要写进 sourceCode |
| Payment=BTQR | `reservationPaymentMethods[].paymentMethod` | 新建 |
| 共用 Guest ID | `reservationGuests[].profileInfo.profileIdList[].id`,主客标记 `primary=true` | 新建;同次多笔引用同一实际客档 |
| Travel Agent ID | `reservationProfiles.reservationProfile[].profileIdList[].id` | 新建;角色 `reservationProfileType=TravelAgent`,FIT 不另加 GROUP 的 AgentContact |
| Note 原文 | `comments[].comment.text.value` | 新建、修改;修改另带已核实的 `comments[].id`,保留无关备注 |
| Hotel / Reservation ID | `hotelId`、修改时 `reservationIdList[].id/type` | 取实际酒店及预订 ID |
| Tour / TA Record Locator | FIT NEW有Tour Code时应写入,无则省略;候选创建字段externalReferences[].id/idContext已接入,页面待验 | 查询参数taRecordLocatorList已存在;不能当创建写入字段。按TA_RECORD_LOCATOR类型精确回查,错值/缺失/重复不通过 |
主资料新建、修改、查询和 `searchHotelReservations` 均在公开 Edge 目录。Note 正式 schema 是 `comments[]`,`putReservation` 内嵌 example 却有 `comments.commentInfo`,应保留这个契约差异,不能声称样例也已一致。依据 [Oracle RSV 契约](https://github.com/oracle/hospitality-api-docs/blob/4bd129b455bc5e3ab0f900ac47983611e58659b4/rest-api-specs/property/v1/rsv.json)。
Name 与 Country 的独立建档接口已定位:`postProfile`,POST `/crm/v1/profiles`,字段为 `profileDetails.customer.personName[].surname`、`profileDetails.addresses.addressInfo[].address.country.code`,以及 `profileType=Guest`、`registeredProperty`。Country=CN,不代替 nationality;查询为 `getProfile`。Edge POST `/api/v1/profiles` 和 GET `/api/v1/profiles/{profileID}` 已发布且已接入。内嵌新档也有 Oracle schema,但本项目当前选用先建一次、后续共用的流程,不重复创建同次共享客档。
## 5. Account / Contact 的查询与写入是两步
| 目标 | 查询接口和参数 | 结果/写入 |
| --- | --- | --- |
| 旅行社账户 | `getProfiles`,`profileType=Agent`、`profileName`、`excludeInactive`,完整分页;也有 `searchProfiles` | 读取 `profileSummaries.profileInfo[].profileIdList[].id`,核对名称和类型 |
| 固定联系人及其主账户 | `getProfiles`,`profileType=Contact`、`profileName`、`fetchInstructions=PrimaryAccountInfo` | `profileSummaries.profileInfo[].profile.primaryAccountInfo.profileId.id`,比对已选 Account ID;联系人自身 ID 用于 GROUP 的 AgentContact |
| 其他关系路径 | Oracle 原生 `getProfileRelationships` 或 `getProfile` 的 Relationship fetch | `getProfileRelationships` 已发布为 GET `/api/v1/profiles/{profileID}/relationships`;`getProfile` 的可传参数仍按其独立白名单,不能猜加 fetchInstructions |
因此这一项的接口/字段已经找到了,剩余为实际关系数据验证;若联系人没有主账户关系,不得按名字猜归属。CRM 类型为 Agent,GROUP 关联角色 Agent,FIT 关联角色 TravelAgent,三个位置不能混用。依据 [Oracle CRM 契约](https://github.com/oracle/hospitality-api-docs/blob/4bd129b455bc5e3ab0f900ac47983611e58659b4/rest-api-specs/property/v1/crm.json)。
## 6. 邮件 Excel 保留解析,取消 Oracle Attachments 上传
2026-09-17 用户取消“把本封邮件的 Excel 上传到对应的团队或 FIT 预订”。GROUP/FIT 新建、修改不再执行酒店附件上传、替换、查询核验或删除,也不再以 linkType、附件 ID、命名/描述及原件回查作为本流程前置或成功条件。邮件接收、原件查看和业务解析保留;TA现按最新NEW规则区分GROUP/FIT;邮件/本地Tour Code保留。既有附件研究仅作历史记录。执行代码已移除附件阶段及依赖;本轮另清除了 GROUP UPDATE 残留的非空来源附件条件。
## 7. 取消与类型转换
| 动作 | Oracle 原生接口 | 业务参数路径 |
| --- | --- | --- |
| 取消 FIT 原预订 | `postCancelReservation` POST `/rsv/v1/hotels/{hotelId}/reservations/{reservationId}/cancellations` | `reservations[].hotelId`、`reservationIdList[].id/type`、`reason.code`(可带 description)、`verificationOnly=false` |
| 查 Block 可转状态 | `getNextBlockStatus` GET `/blk/v1/blocks/status` | `hotelId`、`currentStatus`;这是业务允许的下一状态查询,不等同配置维护接口 |
| 取消 Block | `putBlockStatus` PUT `/blk/v1/hotels/{hotelId}/blocks/{blockId}/status` | `changeBlockStatus.hotelId`、`blockId.id/type`、`currentBlockStatus`、`newBlockStatus`、`cancellationDetails.cancellationCode.code`,根 `verificationOnly=false` |
| 取消后核对 | `getReservation` / `getBlock` | 按原实际 ID 查询状态;不能只根据写入 HTTP 返回证明当前已取消 |
三个取消/下一状态业务接口均已发布且接入正式 Factory/Runtime:POST `/api/v1/reservations/{reservationID}/cancellations`(201)、GET `/api/v1/blocks/next-status`、PUT `/api/v1/blocks/{blockID}/status`(200)。FIT 取消原因配置查询 `getCancellationCodes`、Block 取消原因 `getBlockCancellationReasons`、状态目录 `getBlockStatusCodes` 已在 Edge 目录;本轮没有读取酒店实际值。状态/原因的酒店代码是待获取的参数值,不是未知的字段位置。Allotment 取消还需查询关联 Reservation(搜索按实际 Block ID),不能顺带取消住客或 PM。
## 8. 第一层尚未关闭的项目
1. FIT NEW有Tour Code时的TA Record Locator写入恢复为本期需求,候选写入已接入并模拟验证,沙箱页面待验;查询接口已存在。GROUP NEW不传,FIT无Tour Code省略。缺本系统可信历史编号的旧FIT仍不自动修改/取消/转换。
2. 文档冲突已有实施依据:FIT Note 采用正式 schema 与官方 Postman 一致的 `comments[]`;GROUP 日期采用官方指南/Postman 的 `YYYY-MM-DD`。保留矛盾记录,真实运行行为另验,不再称字段未定。
3. 真实环境取值与验收:Account/Contact 实际 ID、可用代码、Block 房量控制、两种取消原因及状态需由受信配置提供。接口都已发布,这些是环境配置/验证事项,不是新增封装缺口。
完整映射已列明,本次已完成独立模拟参数和接口链验证。无TA当前状态和用户步骤见[最新交付](ohip-no-ta-local-test-20260918.md)。现有服务更新、文件上传及酒店操作由用户执行;没有向他人代发询问。