修复V4房型信息展示安全边界
This commit is contained in:
@@ -550,14 +550,17 @@ class ReservationFrontendQueryControllerTest {
|
||||
ReservationV4CardStatus.CONFIRMED.name(), null, "{}");
|
||||
confirmV4TaskCard(roomCard.id(), """
|
||||
{
|
||||
"business_fields": {
|
||||
"arrival_date": "2026-07-26",
|
||||
"departure_date": "2026-07-29",
|
||||
"rate_code": "BAR",
|
||||
"room_items": [
|
||||
{"room_type_code": "RM1", "room_count": 2},
|
||||
{"room_type_code": "RM2", "room_count": 1}
|
||||
]
|
||||
"room_information": {
|
||||
"final_values": {
|
||||
"arrival_date": "2026-07-26",
|
||||
"departure_date": "2026-07-29",
|
||||
"nights": 3,
|
||||
"rate_code": "BAR",
|
||||
"room_items": [
|
||||
{"room_type_code": "RM1", "room_count": 2},
|
||||
{"room_type_code": "RM2", "room_count": 1}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
""", "frontend-query-admin", Instant.parse("2026-07-08T11:20:00Z"));
|
||||
|
||||
@@ -2,6 +2,7 @@ package cn.nianxx.thhotel.workflows.reservation.control;
|
||||
|
||||
import static cn.nianxx.thhotel.support.MockMvcAuthTestSupport.loginToken;
|
||||
import static cn.nianxx.thhotel.support.MockMvcAuthTestSupport.performAuthorized;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
@@ -324,6 +325,209 @@ class ReservationV4CommandControllerTest {
|
||||
.doesNotExist());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldConfirmRoomInformationStableFinalValuesAndDropReadonlySubmittedFields() throws Exception {
|
||||
SeededOrderTask seeded = seedOrderTaskWithBusinessCard(
|
||||
HOTEL_ID,
|
||||
"mail-v4-command-confirm-room-info-stable-001",
|
||||
Instant.parse("2026-07-19T01:13:20Z"),
|
||||
null,
|
||||
"""
|
||||
{
|
||||
"card_type":"ROOM_INFORMATION",
|
||||
"event_type":"NEW_BOOKING",
|
||||
"target_order":{"booking_type":"GROUP","locator_type":"GROUP_CODE","locator_value":"GRP-V4-COMMAND-RI-001"},
|
||||
"business_fields":{
|
||||
"event_type":"NEW_BOOKING",
|
||||
"raw_evidence":"nested raw evidence should not persist",
|
||||
"attachment_url":"https://oss.example.test/nested-command-private.pdf",
|
||||
"pms_raw_response":{"debug":"NESTED-COMMAND-SHOULD-NOT-PERSIST"},
|
||||
"arrival_date":"2026-07-26",
|
||||
"departure_date":"2026-07-29",
|
||||
"rate_code":"GROUP",
|
||||
"room_items":[{"room_type_code":"TWN","room_count":2,"raw_evidence":"NESTED-ROOM-RAW","pms_room_type_code":"NESTED-PMS-SHOULD-NOT-PERSIST"}]
|
||||
}
|
||||
}
|
||||
""");
|
||||
confirmBasicCard(seeded);
|
||||
|
||||
performAuthorized(mockMvc, adminToken(), post("/api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/confirm",
|
||||
seeded.orderTask().id(),
|
||||
seeded.businessCard().id())
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("""
|
||||
{
|
||||
"version": 0,
|
||||
"confirmed_payload": {
|
||||
"room_information": {
|
||||
"final_values": {
|
||||
"group_block_name": "前端修正团队名",
|
||||
"arrival_date": "2026-07-27",
|
||||
"departure_date": "2026-07-30",
|
||||
"nights": 99,
|
||||
"rate_code": "GROUP",
|
||||
"breakfast_included": false,
|
||||
"group_booking_status": "DEF",
|
||||
"room_items": [
|
||||
{
|
||||
"room_type_code": "DBL",
|
||||
"room_count": 3,
|
||||
"pms_room_type_code": "SHOULD-NOT-PERSIST"
|
||||
}
|
||||
],
|
||||
"adult": 2,
|
||||
"target_order": {"locator_value": "SHOULD-NOT-PERSIST"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.room_information.event_type")
|
||||
.value("NEW_BOOKING"))
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.room_information.booking_type")
|
||||
.value("GROUP"))
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.room_information.final_values.group_block_name")
|
||||
.value("前端修正团队名"))
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.room_information.final_values.arrival_date")
|
||||
.value("2026-07-27"))
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.room_information.final_values.nights")
|
||||
.value(3))
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.room_information.final_values.breakfast_included")
|
||||
.value(true))
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.room_information.final_values.group_booking_status")
|
||||
.value("DEF"))
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.room_information.final_values.room_items[0].room_type_code")
|
||||
.value("DBL"))
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.room_information.final_values.room_items[0].room_count")
|
||||
.value(3))
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.room_information.final_values.room_items[0].pms_room_type_code")
|
||||
.doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.room_information.final_values.adult")
|
||||
.doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.room_information.final_values.target_order")
|
||||
.doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.room_information.final_values.raw_evidence")
|
||||
.doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.room_information.final_values.attachment_url")
|
||||
.doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.room_information.final_values.pms_raw_response")
|
||||
.doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.room_information.final_values.room_items[0].raw_evidence")
|
||||
.doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.room_information.final_values.room_items[0].pms_room_type_code")
|
||||
.doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.business_fields").doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.target_order").doesNotExist())
|
||||
.andExpect(content().string(not(containsString("nested raw evidence"))))
|
||||
.andExpect(content().string(not(containsString("https://oss.example.test/nested-command-private.pdf"))))
|
||||
.andExpect(content().string(not(containsString("NESTED-COMMAND-SHOULD-NOT-PERSIST"))))
|
||||
.andExpect(content().string(not(containsString("NESTED-ROOM-RAW"))))
|
||||
.andExpect(content().string(not(containsString("NESTED-PMS-SHOULD-NOT-PERSIST"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRejectRoomInformationConfirmWhenDatesAreInvalid() throws Exception {
|
||||
SeededOrderTask seeded = seedOrderTaskWithBusinessCard(
|
||||
HOTEL_ID,
|
||||
"mail-v4-command-confirm-room-info-invalid-date-001",
|
||||
Instant.parse("2026-07-19T01:13:25Z"),
|
||||
null,
|
||||
"""
|
||||
{
|
||||
"card_type":"ROOM_INFORMATION",
|
||||
"event_type":"NEW_BOOKING",
|
||||
"target_order":{"booking_type":"GROUP","locator_type":"GROUP_CODE","locator_value":"GRP-V4-COMMAND-RI-DATE-001"},
|
||||
"business_fields":{
|
||||
"event_type":"NEW_BOOKING",
|
||||
"arrival_date":"2026-07-26",
|
||||
"departure_date":"2026-07-29",
|
||||
"rate_code":"GROUP",
|
||||
"room_items":[{"room_type_code":"TWN","room_count":2}]
|
||||
}
|
||||
}
|
||||
""");
|
||||
confirmBasicCard(seeded);
|
||||
|
||||
performAuthorized(mockMvc, adminToken(), post("/api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/confirm",
|
||||
seeded.orderTask().id(),
|
||||
seeded.businessCard().id())
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("""
|
||||
{
|
||||
"version": 0,
|
||||
"confirmed_payload": {
|
||||
"room_information": {
|
||||
"final_values": {
|
||||
"arrival_date": "2026-07-30",
|
||||
"departure_date": "2026-07-29",
|
||||
"rate_code": "GROUP",
|
||||
"group_block_name": "GRP-V4-COMMAND-RI-DATE-001",
|
||||
"room_items": [
|
||||
{"room_type_code": "TWN", "room_count": 2}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.error_code").value("V4_FIELD_VALIDATION_FAILED"))
|
||||
.andExpect(jsonPath("$.details[?(@=='room_information.final_values.departure_date: 离店日期不能早于入住日期。')]")
|
||||
.exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRequireBreakfastWhenFitRateCodeCannotDeriveBreakfast() throws Exception {
|
||||
SeededOrderTask seeded = seedOrderTaskWithBusinessCard(
|
||||
HOTEL_ID,
|
||||
"mail-v4-command-confirm-room-info-fit-breakfast-001",
|
||||
Instant.parse("2026-07-19T01:13:30Z"),
|
||||
null,
|
||||
"""
|
||||
{
|
||||
"card_type":"ROOM_INFORMATION",
|
||||
"event_type":"NEW_BOOKING",
|
||||
"target_order":{"booking_type":"FIT","locator_type":"BOOKING_CODE","locator_value":"FIT-V4-COMMAND-RI-001"},
|
||||
"business_fields":{
|
||||
"event_type":"NEW_BOOKING",
|
||||
"guest_name":"LI CHUNHONG",
|
||||
"arrival_date":"2026-07-26",
|
||||
"departure_date":"2026-07-29",
|
||||
"rate_code":"FIT",
|
||||
"room_items":[{"room_type_code":"KING","room_count":1}]
|
||||
}
|
||||
}
|
||||
""");
|
||||
confirmBasicCard(seeded);
|
||||
|
||||
performAuthorized(mockMvc, adminToken(), post("/api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/confirm",
|
||||
seeded.orderTask().id(),
|
||||
seeded.businessCard().id())
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("""
|
||||
{
|
||||
"version": 0,
|
||||
"confirmed_payload": {
|
||||
"room_information": {
|
||||
"final_values": {
|
||||
"arrival_date": "2026-07-26",
|
||||
"departure_date": "2026-07-29",
|
||||
"rate_code": "FIT",
|
||||
"room_items": [
|
||||
{"room_type_code": "KING", "room_count": 1}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.error_code").value("V4_FIELD_VALIDATION_FAILED"))
|
||||
.andExpect(jsonPath("$.details[?(@=='room_information.final_values.breakfast_included: 含早不能为空。')]")
|
||||
.exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRejectRepeatedCardConfirm() throws Exception {
|
||||
SeededOrderTask seeded = seedOrderTask(
|
||||
@@ -538,6 +742,120 @@ class ReservationV4CommandControllerTest {
|
||||
.andExpect(jsonPath("$.business_cards[0].review_resolution.reason").value("修正房型目录"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldResolveRoomInformationReviewWithStablePointer() throws Exception {
|
||||
SeededOrderTask seeded = seedReviewOrderTaskWithBusinessCard(
|
||||
HOTEL_ID,
|
||||
"mail-v4-command-review-room-info-stable-001",
|
||||
Instant.parse("2026-07-19T01:22:06Z"),
|
||||
990000000000070104L,
|
||||
ReservationV4CardStatus.PENDING_CONFIRM.name(),
|
||||
ReservationV4CardStatus.REVIEW_REQUIRED.name(),
|
||||
"""
|
||||
{
|
||||
"card_type":"ROOM_INFORMATION",
|
||||
"event_type":"NEW_BOOKING",
|
||||
"target_order":{"booking_type":"GROUP","locator_type":"GROUP_CODE","locator_value":"GRP-V4-REVIEW-RI-001"},
|
||||
"business_fields":{
|
||||
"event_type":"NEW_BOOKING",
|
||||
"arrival_date":"2026-08-01",
|
||||
"departure_date":"2026-08-03",
|
||||
"rate_code":"GROUP",
|
||||
"room_items":[{"room_type_code":"UNKNOWN_TYPE","room_count":2}]
|
||||
}
|
||||
}
|
||||
""",
|
||||
"""
|
||||
[
|
||||
{
|
||||
"field_path": "room_information.final_values.room_items.0.room_type_code",
|
||||
"field_pointer": "/room_information/final_values/room_items/0/room_type_code",
|
||||
"message": "房型代码不在第一版目录中。",
|
||||
"detail": "room_information.final_values.room_items.0.room_type_code: 房型代码不在第一版目录中。"
|
||||
}
|
||||
]
|
||||
""");
|
||||
confirmBasicCard(seeded);
|
||||
|
||||
performAuthorized(mockMvc, adminToken(), post(
|
||||
"/api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/review-resolution",
|
||||
seeded.orderTask().id(),
|
||||
seeded.businessCard().id())
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("""
|
||||
{
|
||||
"version": 0,
|
||||
"reason": "按稳定 Room Information 模型修正房型",
|
||||
"field_overrides": [
|
||||
{
|
||||
"field_pointer": "/room_information/final_values/room_items/0/room_type_code",
|
||||
"value": "RM2"
|
||||
}
|
||||
]
|
||||
}
|
||||
"""))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.room_information.final_values.room_items[0].room_type_code")
|
||||
.value("RM2"))
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.room_information.final_values.nights")
|
||||
.value(2))
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.business_fields").doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].review_resolution.field_overrides[0].field_pointer")
|
||||
.value("/room_information/final_values/room_items/0/room_type_code"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRejectRoomInformationReviewWhenPointerTargetsDerivedReadonlyField() throws Exception {
|
||||
SeededOrderTask seeded = seedReviewOrderTaskWithBusinessCard(
|
||||
HOTEL_ID,
|
||||
"mail-v4-command-review-room-info-readonly-001",
|
||||
Instant.parse("2026-07-19T01:22:07Z"),
|
||||
990000000000070105L,
|
||||
ReservationV4CardStatus.PENDING_CONFIRM.name(),
|
||||
ReservationV4CardStatus.REVIEW_REQUIRED.name(),
|
||||
"""
|
||||
{
|
||||
"card_type":"ROOM_INFORMATION",
|
||||
"event_type":"NEW_BOOKING",
|
||||
"target_order":{"booking_type":"GROUP","locator_type":"GROUP_CODE","locator_value":"GRP-V4-REVIEW-RI-002"},
|
||||
"business_fields":{
|
||||
"event_type":"NEW_BOOKING",
|
||||
"arrival_date":"2026-08-01",
|
||||
"departure_date":"2026-08-03",
|
||||
"rate_code":"GROUP",
|
||||
"room_items":[{"room_type_code":"TWN","room_count":2}]
|
||||
}
|
||||
}
|
||||
""",
|
||||
"""
|
||||
[
|
||||
{
|
||||
"field_path": "room_information.final_values.nights",
|
||||
"field_pointer": "/room_information/final_values/nights",
|
||||
"message": "Nights 由日期派生,不能人工写入。",
|
||||
"detail": "room_information.final_values.nights: Nights 由日期派生,不能人工写入。"
|
||||
}
|
||||
]
|
||||
""");
|
||||
confirmBasicCard(seeded);
|
||||
|
||||
performAuthorized(mockMvc, adminToken(), post(
|
||||
"/api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/review-resolution",
|
||||
seeded.orderTask().id(),
|
||||
seeded.businessCard().id())
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("""
|
||||
{
|
||||
"version": 0,
|
||||
"field_overrides": [
|
||||
{"field_pointer": "/room_information/final_values/nights", "value": 7}
|
||||
]
|
||||
}
|
||||
"""))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.error_code").value("V4_REVIEW_POINTER_READONLY"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRejectReviewResolutionWhenResolvedOrderTaskRebindsToDifferentOrder() throws Exception {
|
||||
Long currentOrderId = 990000000000070111L;
|
||||
|
||||
@@ -28,6 +28,7 @@ import cn.nianxx.thhotel.workflows.reservation.common.dto.ReservationV4OrderTask
|
||||
import cn.nianxx.thhotel.workflows.reservation.common.dto.ReservationV4SourceNotificationDraft;
|
||||
import cn.nianxx.thhotel.workflows.reservation.common.dto.ReservationV4SourceNotificationSnapshot;
|
||||
import cn.nianxx.thhotel.workflows.reservation.common.dto.ReservationV4TaskCardDraft;
|
||||
import cn.nianxx.thhotel.workflows.reservation.common.dto.ReservationV4TaskCardSnapshot;
|
||||
import cn.nianxx.thhotel.workflows.reservation.common.enums.AiResultType;
|
||||
import cn.nianxx.thhotel.workflows.reservation.common.enums.ReservationAiSystemProcessCategory;
|
||||
import cn.nianxx.thhotel.workflows.reservation.common.enums.ReservationSystemTaskType;
|
||||
@@ -252,9 +253,9 @@ class ReservationV4QueryControllerTest {
|
||||
.value(contains(true)))
|
||||
.andExpect(jsonPath("$.business_cards[0].card_type").value("ROOM_INFORMATION"))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.event_type").value("NEW_BOOKING"))
|
||||
.andExpect(jsonPath("$.business_cards[0].fields[?(@.field_pointer=='/room_items/0/room_type_code')].control_type")
|
||||
.andExpect(jsonPath("$.business_cards[0].fields[?(@.field_pointer=='/room_information/final_values/room_items/0/room_type_code')].control_type")
|
||||
.value(contains("select")))
|
||||
.andExpect(jsonPath("$.business_cards[0].fields[?(@.field_pointer=='/room_items/0/room_count')].control_type")
|
||||
.andExpect(jsonPath("$.business_cards[0].fields[?(@.field_pointer=='/room_information/final_values/room_items/0/room_count')].control_type")
|
||||
.value(contains("number")))
|
||||
.andExpect(jsonPath("$.business_cards[0].ai_payload_json").doesNotExist())
|
||||
.andExpect(jsonPath("$.availability.read_only").value(false))
|
||||
@@ -264,6 +265,273 @@ class ReservationV4QueryControllerTest {
|
||||
.andExpect(content().string(not(containsString("https://private.example.test"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnRoomInformationDisplayModelForNewGroupBooking() throws Exception {
|
||||
ReservationV4OrderTaskSnapshot orderTask = seedOrderTaskWithBusinessPayload(
|
||||
"mail-v4-room-info-new-group-001",
|
||||
Instant.parse("2026-07-18T03:01:00Z"),
|
||||
"GROUP",
|
||||
"GROUP_CODE",
|
||||
"GRP-V4-RI-GROUP-001",
|
||||
"NEW_BOOKING",
|
||||
ReservationV4CardStatus.CONFIRMED.name(),
|
||||
ReservationV4CardStatus.PENDING_CONFIRM.name(),
|
||||
"""
|
||||
{
|
||||
"event_type":"NEW_BOOKING",
|
||||
"target_order":{"booking_type":"GROUP","locator_type":"GROUP_CODE","locator_value":"GRP-V4-RI-GROUP-001"},
|
||||
"raw_evidence":"raw evidence should not leak",
|
||||
"attachment_url":"https://oss.example.test/private-room-info.pdf",
|
||||
"pms_raw_response":{"confirmation_number":"SHOULD-NOT-LEAK"},
|
||||
"business_fields":{
|
||||
"event_type":"NEW_BOOKING",
|
||||
"raw_evidence":"nested raw evidence should not leak",
|
||||
"attachment_url":"https://oss.example.test/nested-private-room-info.pdf",
|
||||
"pms_raw_response":{"debug":"NESTED-SHOULD-NOT-LEAK"},
|
||||
"arrival_date":"2026-07-26",
|
||||
"departure_date":"2026-07-29",
|
||||
"rate_code":"GROUP",
|
||||
"room_items":[{"room_type_code":"TWN","room_count":2,"pms_room_type_code":"NESTED-PMS-SHOULD-NOT-LEAK","raw_evidence":"NESTED-ROOM-RAW"}]
|
||||
}
|
||||
}
|
||||
""",
|
||||
null);
|
||||
|
||||
performAuthorized(mockMvc, adminToken(), get("/api/reservation/order-tasks/{orderTaskId}", orderTask.id())
|
||||
.param("hotel_id", HOTEL_ID))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.event_type")
|
||||
.value("NEW_BOOKING"))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.booking_type")
|
||||
.value("GROUP"))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.final_values.group_block_name")
|
||||
.value("GRP-V4-RI-GROUP-001"))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.final_values.arrival_date")
|
||||
.value("2026-07-26"))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.final_values.departure_date")
|
||||
.value("2026-07-29"))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.final_values.nights")
|
||||
.value(3))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.final_values.rate_code")
|
||||
.value("GROUP"))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.final_values.breakfast_included")
|
||||
.value(true))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.final_values.group_booking_status")
|
||||
.value("TEN"))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.final_values.group_booking_status_label")
|
||||
.value("TEN-Tentative"))
|
||||
.andExpect(jsonPath("$.business_cards[0].fields[?(@.field_pointer=='/room_information/final_values/group_block_name')].editable")
|
||||
.value(contains(true)))
|
||||
.andExpect(jsonPath("$.business_cards[0].fields[?(@.field_pointer=='/room_information/final_values/arrival_date')].control_type")
|
||||
.value(contains("date")))
|
||||
.andExpect(jsonPath("$.business_cards[0].fields[?(@.field_pointer=='/room_information/final_values/rate_code')].options_source")
|
||||
.value(contains("reservation_v4_rate_code_catalog")))
|
||||
.andExpect(jsonPath("$.business_cards[0].fields[?(@.field_pointer=='/room_information/final_values/room_items/0/room_type_code')].options_source")
|
||||
.value(contains("reservation_v4_room_type_catalog")))
|
||||
.andExpect(jsonPath("$.business_cards[0].fields[?(@.field_pointer=='/target_order/locator_value')]")
|
||||
.doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.target_order").doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.business_fields").doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.raw_evidence").doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.attachment_url").doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.pms_raw_response").doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.final_values.raw_evidence").doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.final_values.attachment_url").doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.final_values.pms_raw_response").doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.final_values.room_items[0].pms_room_type_code").doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.final_values.room_items[0].raw_evidence").doesNotExist())
|
||||
.andExpect(content().string(not(containsString("ai_payload_json"))))
|
||||
.andExpect(content().string(not(containsString("raw evidence"))))
|
||||
.andExpect(content().string(not(containsString("nested raw evidence"))))
|
||||
.andExpect(content().string(not(containsString("https://oss.example.test/private-room-info.pdf"))))
|
||||
.andExpect(content().string(not(containsString("https://oss.example.test/nested-private-room-info.pdf"))))
|
||||
.andExpect(content().string(not(containsString("SHOULD-NOT-LEAK"))))
|
||||
.andExpect(content().string(not(containsString("NESTED-SHOULD-NOT-LEAK"))))
|
||||
.andExpect(content().string(not(containsString("NESTED-PMS-SHOULD-NOT-LEAK"))))
|
||||
.andExpect(content().string(not(containsString("NESTED-ROOM-RAW"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnRoomInformationUpdateCurrentProposedFinalAndNightsChangeSummary() throws Exception {
|
||||
Long orderId = 990000000000777001L;
|
||||
seedConfirmedRoomInformationProjection(
|
||||
orderId,
|
||||
"mail-v4-room-info-current-projection-001",
|
||||
Instant.parse("2026-07-18T02:50:00Z"),
|
||||
"""
|
||||
{
|
||||
"room_information":{
|
||||
"final_values":{
|
||||
"group_block_name":"GRP-V4-RI-UPDATE-001",
|
||||
"arrival_date":"2026-07-26",
|
||||
"departure_date":"2026-07-29",
|
||||
"nights":3,
|
||||
"rate_code":"GROUP",
|
||||
"breakfast_included":true,
|
||||
"group_booking_status":"TEN",
|
||||
"room_items":[{"room_type_code":"TWN","room_count":2}]
|
||||
}
|
||||
}
|
||||
}
|
||||
""");
|
||||
ReservationV4OrderTaskSnapshot orderTask = seedOrderTaskWithBusinessPayload(
|
||||
"mail-v4-room-info-update-001",
|
||||
Instant.parse("2026-07-18T03:02:00Z"),
|
||||
orderId,
|
||||
"GROUP",
|
||||
"GROUP_CODE",
|
||||
"GRP-V4-RI-UPDATE-001",
|
||||
"UPDATE_BOOKING",
|
||||
ReservationV4CardStatus.CONFIRMED.name(),
|
||||
ReservationV4CardStatus.PENDING_CONFIRM.name(),
|
||||
"""
|
||||
{
|
||||
"event_type":"UPDATE_BOOKING",
|
||||
"target_order":{"booking_type":"GROUP","locator_type":"GROUP_CODE","locator_value":"GRP-V4-RI-UPDATE-001"},
|
||||
"business_fields":{
|
||||
"event_type":"UPDATE_BOOKING",
|
||||
"after":{
|
||||
"arrival_date":"2026-07-27",
|
||||
"departure_date":"2026-07-31",
|
||||
"rate_code":"BAR",
|
||||
"room_items":[{"room_type_code":"DBL","room_count":3}]
|
||||
}
|
||||
}
|
||||
}
|
||||
""",
|
||||
null);
|
||||
|
||||
performAuthorized(mockMvc, adminToken(), get("/api/reservation/order-tasks/{orderTaskId}", orderTask.id())
|
||||
.param("hotel_id", HOTEL_ID))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.current_values.arrival_date")
|
||||
.value("2026-07-26"))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.proposed_values.arrival_date")
|
||||
.value("2026-07-27"))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.final_values.arrival_date")
|
||||
.value("2026-07-27"))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.final_values.departure_date")
|
||||
.value("2026-07-31"))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.final_values.nights")
|
||||
.value(4))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.final_values.rate_code")
|
||||
.value("GROUP"))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.change_summary[?(@.field=='rate_code')]")
|
||||
.doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.change_summary[?(@.field=='nights')].before")
|
||||
.value(contains(3)))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.change_summary[?(@.field=='nights')].after")
|
||||
.value(contains(4)))
|
||||
.andExpect(jsonPath("$.business_cards[0].fields[?(@.field_pointer=='/room_information/final_values/rate_code')]")
|
||||
.doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].fields[?(@.field_pointer=='/room_information/final_values/room_items/0/room_count')].editable")
|
||||
.value(contains(true)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldOnlyMarkRoomInformationReviewProblemFieldsEditable() throws Exception {
|
||||
ReservationV4OrderTaskSnapshot orderTask = seedOrderTaskWithBusinessPayload(
|
||||
"mail-v4-room-info-review-fields-001",
|
||||
Instant.parse("2026-07-18T03:02:30Z"),
|
||||
"GROUP",
|
||||
"GROUP_CODE",
|
||||
"GRP-V4-RI-REVIEW-FIELDS-001",
|
||||
"NEW_BOOKING",
|
||||
ReservationV4CardStatus.CONFIRMED.name(),
|
||||
ReservationV4CardStatus.REVIEW_REQUIRED.name(),
|
||||
"""
|
||||
{
|
||||
"event_type":"NEW_BOOKING",
|
||||
"target_order":{"booking_type":"GROUP","locator_type":"GROUP_CODE","locator_value":"GRP-V4-RI-REVIEW-FIELDS-001"},
|
||||
"business_fields":{
|
||||
"event_type":"NEW_BOOKING",
|
||||
"arrival_date":"2026-08-01",
|
||||
"departure_date":"2026-08-03",
|
||||
"rate_code":"GROUP",
|
||||
"room_items":[{"room_type_code":"UNKNOWN_TYPE","room_count":2}]
|
||||
}
|
||||
}
|
||||
""",
|
||||
null,
|
||||
"""
|
||||
[
|
||||
{
|
||||
"field_path": "room_information.final_values.room_items.0.room_type_code",
|
||||
"field_pointer": "/room_information/final_values/room_items/0/room_type_code",
|
||||
"message": "房型代码不在第一版目录中。",
|
||||
"detail": "room_information.final_values.room_items.0.room_type_code: 房型代码不在第一版目录中。"
|
||||
}
|
||||
]
|
||||
""");
|
||||
|
||||
performAuthorized(mockMvc, adminToken(), get("/api/reservation/order-tasks/{orderTaskId}", orderTask.id())
|
||||
.param("hotel_id", HOTEL_ID))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.business_cards[0].fields[?(@.field_pointer=='/room_information/final_values/room_items/0/room_type_code')].editable")
|
||||
.value(contains(true)))
|
||||
.andExpect(jsonPath("$.business_cards[0].fields[?(@.field_pointer=='/room_information/final_values/arrival_date')].editable")
|
||||
.value(contains(false)))
|
||||
.andExpect(jsonPath("$.business_cards[0].fields[?(@.field_pointer=='/room_information/final_values/departure_date')].editable")
|
||||
.value(contains(false)))
|
||||
.andExpect(jsonPath("$.business_cards[0].fields[?(@.field_pointer=='/room_information/final_values/rate_code')].editable")
|
||||
.value(contains(false)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnReadonlyRoomInformationDisplayModelForCancelBooking() throws Exception {
|
||||
Long orderId = 990000000000777002L;
|
||||
seedConfirmedRoomInformationProjection(
|
||||
orderId,
|
||||
"mail-v4-room-info-current-projection-002",
|
||||
Instant.parse("2026-07-18T02:55:00Z"),
|
||||
"""
|
||||
{
|
||||
"room_information":{
|
||||
"final_values":{
|
||||
"group_block_name":"GRP-V4-RI-CANCEL-001",
|
||||
"arrival_date":"2026-08-01",
|
||||
"departure_date":"2026-08-05",
|
||||
"nights":4,
|
||||
"rate_code":"GROUP",
|
||||
"breakfast_included":true,
|
||||
"group_booking_status":"DEF",
|
||||
"room_items":[{"room_type_code":"KING","room_count":1}]
|
||||
}
|
||||
}
|
||||
}
|
||||
""");
|
||||
ReservationV4OrderTaskSnapshot orderTask = seedOrderTaskWithBusinessPayload(
|
||||
"mail-v4-room-info-cancel-001",
|
||||
Instant.parse("2026-07-18T03:03:00Z"),
|
||||
orderId,
|
||||
"GROUP",
|
||||
"GROUP_CODE",
|
||||
"GRP-V4-RI-CANCEL-001",
|
||||
"CANCEL_BOOKING",
|
||||
ReservationV4CardStatus.CONFIRMED.name(),
|
||||
ReservationV4CardStatus.PENDING_CONFIRM.name(),
|
||||
"""
|
||||
{
|
||||
"event_type":"CANCEL_BOOKING",
|
||||
"target_order":{"booking_type":"GROUP","locator_type":"GROUP_CODE","locator_value":"GRP-V4-RI-CANCEL-001"},
|
||||
"business_fields":{"event_type":"CANCEL_BOOKING"}
|
||||
}
|
||||
""",
|
||||
null);
|
||||
|
||||
performAuthorized(mockMvc, adminToken(), get("/api/reservation/order-tasks/{orderTaskId}", orderTask.id())
|
||||
.param("hotel_id", HOTEL_ID))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.event_type")
|
||||
.value("CANCEL_BOOKING"))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.current_values.arrival_date")
|
||||
.value("2026-08-01"))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.room_information.final_values.room_items[0].room_type_code")
|
||||
.value("KING"))
|
||||
.andExpect(jsonPath("$.business_cards[0].fields.length()").value(0))
|
||||
.andExpect(jsonPath("$.business_cards[0].availability.confirmable").value(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldExposeReviewCardsAsReviewableButNotConfirmable() throws Exception {
|
||||
ReservationV4OrderTaskSnapshot orderTask = seedReviewRequiredOrderTask(
|
||||
@@ -584,6 +852,157 @@ class ReservationV4QueryControllerTest {
|
||||
Instant receivedAt,
|
||||
String orderRef,
|
||||
String targetLocatorValue) {
|
||||
return seedOrderTaskWithBusinessPayload(
|
||||
source,
|
||||
aiBatchId,
|
||||
receivedAt,
|
||||
orderRef,
|
||||
null,
|
||||
"GROUP",
|
||||
"GROUP_CODE",
|
||||
targetLocatorValue,
|
||||
"NEW_BOOKING",
|
||||
ReservationV4CardStatus.PENDING_CONFIRM.name(),
|
||||
ReservationV4CardStatus.PENDING_CONFIRM.name(),
|
||||
"""
|
||||
{"card_type":"ROOM_INFORMATION","event_type":"NEW_BOOKING","room_items":[{"room_type_code":"TWN","room_count":2}]}
|
||||
""",
|
||||
null);
|
||||
}
|
||||
|
||||
private ReservationV4OrderTaskSnapshot seedOrderTaskWithBusinessPayload(
|
||||
String externalMessageId,
|
||||
Instant receivedAt,
|
||||
String targetBookingType,
|
||||
String targetLocatorType,
|
||||
String targetLocatorValue,
|
||||
String eventType,
|
||||
String basicCardStatus,
|
||||
String businessCardStatus,
|
||||
String businessDisplayPayloadJson,
|
||||
String confirmedPayloadJson) {
|
||||
SourceMessageCaptureResult source = captureSourceMessage(externalMessageId, "V4 Query Business", receivedAt, HOTEL_ID);
|
||||
return seedOrderTaskWithBusinessPayload(
|
||||
source,
|
||||
990000000000001001L + Math.abs(externalMessageId.hashCode()),
|
||||
receivedAt,
|
||||
"order-room-info-" + externalMessageId,
|
||||
null,
|
||||
targetBookingType,
|
||||
targetLocatorType,
|
||||
targetLocatorValue,
|
||||
eventType,
|
||||
basicCardStatus,
|
||||
businessCardStatus,
|
||||
businessDisplayPayloadJson,
|
||||
confirmedPayloadJson);
|
||||
}
|
||||
|
||||
private ReservationV4OrderTaskSnapshot seedOrderTaskWithBusinessPayload(
|
||||
String externalMessageId,
|
||||
Instant receivedAt,
|
||||
String targetBookingType,
|
||||
String targetLocatorType,
|
||||
String targetLocatorValue,
|
||||
String eventType,
|
||||
String basicCardStatus,
|
||||
String businessCardStatus,
|
||||
String businessDisplayPayloadJson,
|
||||
String confirmedPayloadJson,
|
||||
String businessValidationErrorsJson) {
|
||||
SourceMessageCaptureResult source = captureSourceMessage(externalMessageId, "V4 Query Business", receivedAt, HOTEL_ID);
|
||||
return seedOrderTaskWithBusinessPayload(
|
||||
source,
|
||||
990000000000001001L + Math.abs(externalMessageId.hashCode()),
|
||||
receivedAt,
|
||||
"order-room-info-" + externalMessageId,
|
||||
null,
|
||||
targetBookingType,
|
||||
targetLocatorType,
|
||||
targetLocatorValue,
|
||||
eventType,
|
||||
basicCardStatus,
|
||||
businessCardStatus,
|
||||
businessDisplayPayloadJson,
|
||||
confirmedPayloadJson,
|
||||
businessValidationErrorsJson);
|
||||
}
|
||||
|
||||
private ReservationV4OrderTaskSnapshot seedOrderTaskWithBusinessPayload(
|
||||
String externalMessageId,
|
||||
Instant receivedAt,
|
||||
Long orderId,
|
||||
String targetBookingType,
|
||||
String targetLocatorType,
|
||||
String targetLocatorValue,
|
||||
String eventType,
|
||||
String basicCardStatus,
|
||||
String businessCardStatus,
|
||||
String businessDisplayPayloadJson,
|
||||
String confirmedPayloadJson) {
|
||||
SourceMessageCaptureResult source = captureSourceMessage(externalMessageId, "V4 Query Business", receivedAt, HOTEL_ID);
|
||||
return seedOrderTaskWithBusinessPayload(
|
||||
source,
|
||||
990000000000002001L + Math.abs(externalMessageId.hashCode()),
|
||||
receivedAt,
|
||||
"order-room-info-" + externalMessageId,
|
||||
orderId,
|
||||
targetBookingType,
|
||||
targetLocatorType,
|
||||
targetLocatorValue,
|
||||
eventType,
|
||||
basicCardStatus,
|
||||
businessCardStatus,
|
||||
businessDisplayPayloadJson,
|
||||
confirmedPayloadJson);
|
||||
}
|
||||
|
||||
private ReservationV4OrderTaskSnapshot seedOrderTaskWithBusinessPayload(
|
||||
SourceMessageCaptureResult source,
|
||||
Long aiBatchId,
|
||||
Instant receivedAt,
|
||||
String orderRef,
|
||||
Long orderId,
|
||||
String targetBookingType,
|
||||
String targetLocatorType,
|
||||
String targetLocatorValue,
|
||||
String eventType,
|
||||
String basicCardStatus,
|
||||
String businessCardStatus,
|
||||
String businessDisplayPayloadJson,
|
||||
String confirmedPayloadJson) {
|
||||
return seedOrderTaskWithBusinessPayload(
|
||||
source,
|
||||
aiBatchId,
|
||||
receivedAt,
|
||||
orderRef,
|
||||
orderId,
|
||||
targetBookingType,
|
||||
targetLocatorType,
|
||||
targetLocatorValue,
|
||||
eventType,
|
||||
basicCardStatus,
|
||||
businessCardStatus,
|
||||
businessDisplayPayloadJson,
|
||||
confirmedPayloadJson,
|
||||
null);
|
||||
}
|
||||
|
||||
private ReservationV4OrderTaskSnapshot seedOrderTaskWithBusinessPayload(
|
||||
SourceMessageCaptureResult source,
|
||||
Long aiBatchId,
|
||||
Instant receivedAt,
|
||||
String orderRef,
|
||||
Long orderId,
|
||||
String targetBookingType,
|
||||
String targetLocatorType,
|
||||
String targetLocatorValue,
|
||||
String eventType,
|
||||
String basicCardStatus,
|
||||
String businessCardStatus,
|
||||
String businessDisplayPayloadJson,
|
||||
String confirmedPayloadJson,
|
||||
String businessValidationErrorsJson) {
|
||||
LocalDateTime now = LocalDateTime.ofInstant(receivedAt.plusSeconds(10), ZoneOffset.UTC);
|
||||
ReservationV4OrderTaskSnapshot orderTask = workflowRepository.findOrCreateOrderTask(new ReservationV4OrderTaskDraft(
|
||||
HOTEL_ID,
|
||||
@@ -591,9 +1010,9 @@ class ReservationV4QueryControllerTest {
|
||||
aiBatchId,
|
||||
orderRef,
|
||||
1,
|
||||
null,
|
||||
"GROUP",
|
||||
"GROUP_CODE",
|
||||
orderId,
|
||||
targetBookingType,
|
||||
targetLocatorType,
|
||||
targetLocatorValue,
|
||||
ReservationV4TargetResolutionStatus.RESOLVED.name(),
|
||||
ReservationV4OrderTaskStatus.OPEN.name(),
|
||||
@@ -604,16 +1023,61 @@ class ReservationV4QueryControllerTest {
|
||||
{"card_type":"SOURCE_MESSAGE_DISPLAY","source_message":{"subject":"V4 Query Business"}}
|
||||
""");
|
||||
insertCard(orderTask, ReservationV4CardType.BASIC_INFORMATION.name(), null, 0, 20,
|
||||
ReservationV4CardStatus.PENDING_CONFIRM.name(), null, """
|
||||
basicCardStatus, reviewStatusFor(basicCardStatus), """
|
||||
{"card_type":"BASIC_INFORMATION","order_ref":"order-1","basic_information":{"account_code":"QBD_TRAVEL","market_code":"LEISURE","source_code":"TRAVEL_AGENT"}}
|
||||
""");
|
||||
insertCard(orderTask, ReservationV4CardType.ROOM_INFORMATION.name(), "NEW_BOOKING", 1, 30,
|
||||
ReservationV4CardStatus.PENDING_CONFIRM.name(), null, """
|
||||
{"card_type":"ROOM_INFORMATION","event_type":"NEW_BOOKING","room_items":[{"room_type_code":"TWN","room_count":2}]}
|
||||
""");
|
||||
ReservationV4TaskCardSnapshot businessCard = insertCard(
|
||||
orderTask,
|
||||
ReservationV4CardType.ROOM_INFORMATION.name(),
|
||||
eventType,
|
||||
1,
|
||||
30,
|
||||
businessCardStatus,
|
||||
reviewStatusFor(businessCardStatus),
|
||||
businessDisplayPayloadJson,
|
||||
businessValidationErrorsJson);
|
||||
if (confirmedPayloadJson != null) {
|
||||
workflowRepository.confirmTaskCardWithVersion(
|
||||
HOTEL_ID,
|
||||
businessCard.id(),
|
||||
businessCard.version(),
|
||||
confirmedPayloadJson,
|
||||
"v4-query-admin",
|
||||
now);
|
||||
workflowRepository.updateOrderTaskStatus(
|
||||
HOTEL_ID,
|
||||
orderTask.id(),
|
||||
ReservationV4OrderTaskStatus.COMPLETED.name(),
|
||||
now);
|
||||
}
|
||||
return orderTask;
|
||||
}
|
||||
|
||||
private void seedConfirmedRoomInformationProjection(
|
||||
Long orderId,
|
||||
String externalMessageId,
|
||||
Instant receivedAt,
|
||||
String confirmedPayloadJson) {
|
||||
seedOrderTaskWithBusinessPayload(
|
||||
externalMessageId,
|
||||
receivedAt,
|
||||
orderId,
|
||||
"GROUP",
|
||||
"GROUP_CODE",
|
||||
"GRP-V4-RI-PROJECTION",
|
||||
"NEW_BOOKING",
|
||||
ReservationV4CardStatus.CONFIRMED.name(),
|
||||
ReservationV4CardStatus.PENDING_CONFIRM.name(),
|
||||
"""
|
||||
{"card_type":"ROOM_INFORMATION","event_type":"NEW_BOOKING","business_fields":{"event_type":"NEW_BOOKING"}}
|
||||
""",
|
||||
confirmedPayloadJson);
|
||||
}
|
||||
|
||||
private String reviewStatusFor(String cardStatus) {
|
||||
return ReservationV4CardStatus.REVIEW_REQUIRED.name().equals(cardStatus) ? "PENDING" : null;
|
||||
}
|
||||
|
||||
private ReservationV4OrderTaskSnapshot seedReviewRequiredOrderTask(String externalMessageId, Instant receivedAt) {
|
||||
SourceMessageCaptureResult source = captureSourceMessage(externalMessageId, "V4 Query Review", receivedAt, HOTEL_ID);
|
||||
LocalDateTime now = LocalDateTime.ofInstant(receivedAt.plusSeconds(10), ZoneOffset.UTC);
|
||||
@@ -669,7 +1133,7 @@ class ReservationV4QueryControllerTest {
|
||||
LocalDateTime.ofInstant(receivedAt.plusSeconds(20), ZoneOffset.UTC)));
|
||||
}
|
||||
|
||||
private void insertCard(
|
||||
private ReservationV4TaskCardSnapshot insertCard(
|
||||
ReservationV4OrderTaskSnapshot orderTask,
|
||||
String cardType,
|
||||
String eventType,
|
||||
@@ -678,7 +1142,29 @@ class ReservationV4QueryControllerTest {
|
||||
String cardStatus,
|
||||
String reviewStatus,
|
||||
String displayPayloadJson) {
|
||||
workflowRepository.insertTaskCard(new ReservationV4TaskCardDraft(
|
||||
return insertCard(
|
||||
orderTask,
|
||||
cardType,
|
||||
eventType,
|
||||
sourceEventIndex,
|
||||
sortOrder,
|
||||
cardStatus,
|
||||
reviewStatus,
|
||||
displayPayloadJson,
|
||||
null);
|
||||
}
|
||||
|
||||
private ReservationV4TaskCardSnapshot insertCard(
|
||||
ReservationV4OrderTaskSnapshot orderTask,
|
||||
String cardType,
|
||||
String eventType,
|
||||
Integer sourceEventIndex,
|
||||
Integer sortOrder,
|
||||
String cardStatus,
|
||||
String reviewStatus,
|
||||
String displayPayloadJson,
|
||||
String validationErrorsJson) {
|
||||
return workflowRepository.insertTaskCard(new ReservationV4TaskCardDraft(
|
||||
HOTEL_ID,
|
||||
orderTask.id(),
|
||||
orderTask.sourceMessageId(),
|
||||
@@ -693,7 +1179,7 @@ class ReservationV4QueryControllerTest {
|
||||
{"private_url":"https://private.example.test/raw","raw":"must stay internal"}
|
||||
""",
|
||||
displayPayloadJson,
|
||||
null,
|
||||
validationErrorsJson,
|
||||
orderTask.createdAt()));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user