收口V4 Trace卡后端契约
This commit is contained in:
@@ -556,6 +556,11 @@ class ReservationV4CommandControllerTest {
|
||||
"mail-v4-command-confirm-unknown-trace-target-room-001",
|
||||
Instant.parse("2026-07-19T01:13:05Z"),
|
||||
null,
|
||||
"GROUP",
|
||||
"GROUP_CODE",
|
||||
"GRP-V4-COMMAND-TRACE-UNKNOWN-ROOM-001",
|
||||
ReservationV4CardType.TRACE_RESERVATION_NOTES.name(),
|
||||
"TRACE_RESERVATION_NOTES",
|
||||
"""
|
||||
{"card_type":"TRACE_RESERVATION_NOTES","event_type":"TRACE_RESERVATION_NOTES","business_fields":{"order_ref":"ORDER-COMMAND","event_type":"TRACE_RESERVATION_NOTES","trace_items":[{"item_type":"EXTRA_BED","text":"Please add one extra bed.","target_room_type_code":"UNKNOWN_ROOM","extra_bed_room_count":1,"department_code":"FO"}]}}
|
||||
""");
|
||||
@@ -572,7 +577,217 @@ class ReservationV4CommandControllerTest {
|
||||
"""))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.error_code").value("V4_FIELD_VALIDATION_FAILED"))
|
||||
.andExpect(jsonPath("$.details[0]").value("business_fields.trace_items.0.target_room_type_code: 房型代码不在第一版目录中。"));
|
||||
.andExpect(jsonPath("$.details[0]").value("trace_items.0.target_room_type_code: 房型代码不在第一版目录中。"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRejectBusinessCardConfirmWhenTraceDepartmentCodeInvalid() throws Exception {
|
||||
SeededOrderTask seeded = seedOrderTaskWithBusinessCard(
|
||||
HOTEL_ID,
|
||||
"mail-v4-command-confirm-invalid-trace-department-001",
|
||||
Instant.parse("2026-07-19T01:13:06Z"),
|
||||
null,
|
||||
"GROUP",
|
||||
"GROUP_CODE",
|
||||
"GRP-V4-COMMAND-TRACE-DEPARTMENT-001",
|
||||
ReservationV4CardType.TRACE_RESERVATION_NOTES.name(),
|
||||
"TRACE_RESERVATION_NOTES",
|
||||
"""
|
||||
{"card_type":"TRACE_RESERVATION_NOTES","event_type":"TRACE_RESERVATION_NOTES","business_fields":{"order_ref":"ORDER-COMMAND","event_type":"TRACE_RESERVATION_NOTES","trace_items":[{"item_type":"GENERAL","text":"Guest requests quiet rooms.","department_code":"SALES"}]}}
|
||||
""");
|
||||
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
|
||||
}
|
||||
"""))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.error_code").value("V4_FIELD_VALIDATION_FAILED"))
|
||||
.andExpect(jsonPath("$.details[0]").value("trace_items.0.department_code: Department Code 只允许 FO、HSK、FO+HSK。"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRejectBusinessCardConfirmWhenTraceExtraBedRoomCountNotPositive() throws Exception {
|
||||
SeededOrderTask seeded = seedOrderTaskWithBusinessCard(
|
||||
HOTEL_ID,
|
||||
"mail-v4-command-confirm-invalid-trace-extra-bed-count-001",
|
||||
Instant.parse("2026-07-19T01:13:07Z"),
|
||||
null,
|
||||
"GROUP",
|
||||
"GROUP_CODE",
|
||||
"GRP-V4-COMMAND-TRACE-EXTRA-BED-COUNT-001",
|
||||
ReservationV4CardType.TRACE_RESERVATION_NOTES.name(),
|
||||
"TRACE_RESERVATION_NOTES",
|
||||
"""
|
||||
{"card_type":"TRACE_RESERVATION_NOTES","event_type":"TRACE_RESERVATION_NOTES","business_fields":{"order_ref":"ORDER-COMMAND","event_type":"TRACE_RESERVATION_NOTES","trace_items":[{"item_type":"EXTRA_BED","target_room_type_code":"TWN","extra_bed_room_count":0,"department_code":"FO+HSK"}]}}
|
||||
""");
|
||||
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
|
||||
}
|
||||
"""))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.error_code").value("V4_FIELD_VALIDATION_FAILED"))
|
||||
.andExpect(jsonPath("$.details[0]").value("trace_items.0.extra_bed_room_count: 加床房间数必须为正整数。"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRejectBusinessCardConfirmWhenTraceExtraBedRoomCountDecimal() throws Exception {
|
||||
SeededOrderTask seeded = seedOrderTaskWithBusinessCard(
|
||||
HOTEL_ID,
|
||||
"mail-v4-command-confirm-decimal-trace-extra-bed-count-001",
|
||||
Instant.parse("2026-07-19T01:13:07Z"),
|
||||
null,
|
||||
"GROUP",
|
||||
"GROUP_CODE",
|
||||
"GRP-V4-COMMAND-TRACE-EXTRA-BED-COUNT-DECIMAL-001",
|
||||
ReservationV4CardType.TRACE_RESERVATION_NOTES.name(),
|
||||
"TRACE_RESERVATION_NOTES",
|
||||
"""
|
||||
{"card_type":"TRACE_RESERVATION_NOTES","event_type":"TRACE_RESERVATION_NOTES","business_fields":{"order_ref":"ORDER-COMMAND","event_type":"TRACE_RESERVATION_NOTES","trace_items":[{"item_type":"EXTRA_BED","target_room_type_code":"TWN","extra_bed_room_count":1.5,"department_code":"FO+HSK"}]}}
|
||||
""");
|
||||
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
|
||||
}
|
||||
"""))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.error_code").value("V4_FIELD_VALIDATION_FAILED"))
|
||||
.andExpect(jsonPath("$.details[0]").value("trace_items.0.extra_bed_room_count: 加床房间数必须为正整数。"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNormalizeTraceStableCodesWhenConfirming() throws Exception {
|
||||
SeededOrderTask seeded = seedOrderTaskWithBusinessCard(
|
||||
HOTEL_ID,
|
||||
"mail-v4-command-confirm-trace-normalize-codes-001",
|
||||
Instant.parse("2026-07-19T01:13:07Z"),
|
||||
null,
|
||||
"GROUP",
|
||||
"GROUP_CODE",
|
||||
"GRP-V4-COMMAND-TRACE-NORMALIZE-CODES-001",
|
||||
ReservationV4CardType.TRACE_RESERVATION_NOTES.name(),
|
||||
"TRACE_RESERVATION_NOTES",
|
||||
"""
|
||||
{"card_type":"TRACE_RESERVATION_NOTES","event_type":"TRACE_RESERVATION_NOTES","business_fields":{"order_ref":"ORDER-COMMAND","event_type":"TRACE_RESERVATION_NOTES","trace_items":[{"item_type":"EXTRA_BED","target_room_type_code":" TWN ","extra_bed_room_count":1,"department_code":" FO+HSK "}]}}
|
||||
""");
|
||||
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": {
|
||||
"trace_items": [
|
||||
{
|
||||
"item_type": "EXTRA_BED",
|
||||
"target_room_type_code": " DBL ",
|
||||
"extra_bed_room_count": 2,
|
||||
"department_code": " FO "
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
"""))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.trace_items[0].target_room_type_code")
|
||||
.value("DBL"))
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.trace_items[0].department_code")
|
||||
.value("FO"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldConfirmTraceCardWithOnlyWhitelistedFields() throws Exception {
|
||||
SeededOrderTask seeded = seedOrderTaskWithBusinessCard(
|
||||
HOTEL_ID,
|
||||
"mail-v4-command-confirm-trace-whitelist-001",
|
||||
Instant.parse("2026-07-19T01:13:08Z"),
|
||||
null,
|
||||
"GROUP",
|
||||
"GROUP_CODE",
|
||||
"GRP-V4-COMMAND-TRACE-WHITELIST-001",
|
||||
ReservationV4CardType.TRACE_RESERVATION_NOTES.name(),
|
||||
"TRACE_RESERVATION_NOTES",
|
||||
"""
|
||||
{
|
||||
"card_type":"TRACE_RESERVATION_NOTES",
|
||||
"event_type":"TRACE_RESERVATION_NOTES",
|
||||
"target_order":{"locator_value":"SHOULD-NOT-PERSIST-TRACE-TARGET"},
|
||||
"business_fields":{
|
||||
"trace_items":[
|
||||
{"item_type":"GENERAL","text":"Original trace","department_code":"FO","content":"SHOULD-NOT-PERSIST-CONTENT"},
|
||||
{"item_type":"EXTRA_BED","target_room_type_code":"TWN","extra_bed_room_count":1,"department_code":"FO+HSK","content":"SHOULD-NOT-PERSIST-EXTRA-CONTENT","attachment_url":"https://oss.example.test/trace-confirm-secret.png"}
|
||||
]
|
||||
}
|
||||
}
|
||||
""");
|
||||
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": {
|
||||
"target_order": {"locator_value": "SHOULD-NOT-PERSIST-SUBMITTED-TARGET"},
|
||||
"trace_items": [
|
||||
{
|
||||
"item_type": "GENERAL",
|
||||
"text": "Updated trace",
|
||||
"department_code": "HSK",
|
||||
"content": "SHOULD-NOT-PERSIST-SUBMITTED-CONTENT"
|
||||
},
|
||||
{
|
||||
"item_type": "EXTRA_BED",
|
||||
"target_room_type_code": "DBL",
|
||||
"extra_bed_room_count": 2,
|
||||
"department_code": "FO",
|
||||
"content": "SHOULD-NOT-PERSIST-SUBMITTED-EXTRA-CONTENT",
|
||||
"attachment_url": "https://oss.example.test/trace-submitted-secret.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
"""))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.trace_items[0].text")
|
||||
.value("Updated trace"))
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.trace_items[0].department_code")
|
||||
.value("HSK"))
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.trace_items[1].target_room_type_code")
|
||||
.value("DBL"))
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.trace_items[1].extra_bed_room_count")
|
||||
.value(2))
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.trace_items[1].department_code")
|
||||
.value("FO"))
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.target_order").doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.trace_items[0].content").doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.trace_items[1].content").doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.trace_items[1].attachment_url").doesNotExist())
|
||||
.andExpect(content().string(not(containsString("SHOULD-NOT-PERSIST"))))
|
||||
.andExpect(content().string(not(containsString("https://oss.example.test"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1266,6 +1481,95 @@ class ReservationV4CommandControllerTest {
|
||||
.value("RM2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldAcceptEditableTraceReviewFieldPointersReturnedByTaskDetail() throws Exception {
|
||||
SeededOrderTask seeded = seedReviewOrderTaskWithBusinessCard(
|
||||
HOTEL_ID,
|
||||
"mail-v4-command-review-trace-pointer-runtime-001",
|
||||
Instant.parse("2026-07-19T01:22:28Z"),
|
||||
990000000000070126L,
|
||||
ReservationV4TargetResolutionStatus.RESOLVED.name(),
|
||||
ReservationV4CardStatus.PENDING_CONFIRM.name(),
|
||||
ReservationV4CardStatus.REVIEW_REQUIRED.name(),
|
||||
ReservationV4CardType.TRACE_RESERVATION_NOTES.name(),
|
||||
"TRACE_RESERVATION_NOTES",
|
||||
"""
|
||||
{
|
||||
"card_type":"TRACE_RESERVATION_NOTES",
|
||||
"event_type":"TRACE_RESERVATION_NOTES",
|
||||
"target_order":{"locator_value":"SHOULD-NOT-PERSIST-TRACE"},
|
||||
"business_fields":{
|
||||
"event_type":"TRACE_RESERVATION_NOTES",
|
||||
"trace_items":[
|
||||
{
|
||||
"item_type":"GENERAL",
|
||||
"text":"Guest requests quiet rooms.",
|
||||
"department_code":"SALES",
|
||||
"content":"SHOULD-NOT-PERSIST-CONTENT"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
""",
|
||||
"""
|
||||
[
|
||||
{
|
||||
"field_path": "trace_items.0.department_code",
|
||||
"field_pointer": "/trace_items/0/department_code",
|
||||
"message": "Department Code 只允许 FO、HSK、FO+HSK。",
|
||||
"detail": "trace_items.0.department_code: Department Code 只允许 FO、HSK、FO+HSK。"
|
||||
}
|
||||
]
|
||||
""");
|
||||
confirmBasicCard(seeded);
|
||||
|
||||
MvcResult detailResult = performAuthorized(mockMvc, adminToken(),
|
||||
get("/api/reservation/order-tasks/{orderTaskId}", seeded.orderTask().id())
|
||||
.param("hotel_id", HOTEL_ID))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn();
|
||||
JsonNode detail = objectMapper.readTree(detailResult.getResponse().getContentAsString());
|
||||
ArrayNode overrides = objectMapper.createArrayNode();
|
||||
for (JsonNode field : detail.path("business_cards").get(0).path("fields")) {
|
||||
if (!field.path("editable").asBoolean(false)
|
||||
|| !"review_resolution.field_overrides".equals(field.path("write_target").asText())) {
|
||||
continue;
|
||||
}
|
||||
String pointer = field.path("field_pointer").asText();
|
||||
ObjectNode override = objectMapper.createObjectNode();
|
||||
override.put("field_pointer", pointer);
|
||||
override.set("value", reviewOverrideValue(pointer));
|
||||
overrides.add(override);
|
||||
}
|
||||
org.assertj.core.api.Assertions.assertThat(overrides)
|
||||
.as("Trace 详情返回的可复核字段必须能直接提交给 review-resolution")
|
||||
.isNotEmpty();
|
||||
org.assertj.core.api.Assertions.assertThat(overrides.toString())
|
||||
.contains("/trace_items/0/text")
|
||||
.contains("/trace_items/0/department_code")
|
||||
.doesNotContain("/business_fields/");
|
||||
|
||||
ObjectNode request = objectMapper.createObjectNode();
|
||||
request.put("version", 0);
|
||||
request.put("reason", "回归验证 Trace 详情页可编辑 pointer 与命令侧白名单一致");
|
||||
request.set("field_overrides", overrides);
|
||||
|
||||
performAuthorized(mockMvc, adminToken(), post(
|
||||
"/api/reservation/order-tasks/{orderTaskId}/cards/{cardId}/review-resolution",
|
||||
seeded.orderTask().id(),
|
||||
seeded.businessCard().id())
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.business_cards[0].card_status").value("CONFIRMED"))
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.trace_items[0].text")
|
||||
.value("UPDATED"))
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.trace_items[0].department_code")
|
||||
.value("FO"))
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.trace_items[0].content").doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].confirmed_payload.target_order").doesNotExist());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldResolveEditableRoomInformationPointerWhenLeafMissingInPayload() throws Exception {
|
||||
SeededOrderTask seeded = seedReviewOrderTaskWithBusinessCard(
|
||||
@@ -2111,6 +2415,12 @@ class ReservationV4CommandControllerTest {
|
||||
if (pointer.endsWith("/room_count")) {
|
||||
return objectMapper.getNodeFactory().numberNode(2);
|
||||
}
|
||||
if (pointer.endsWith("/extra_bed_room_count")) {
|
||||
return objectMapper.getNodeFactory().numberNode(1);
|
||||
}
|
||||
if (pointer.endsWith("/department_code")) {
|
||||
return objectMapper.getNodeFactory().textNode("FO");
|
||||
}
|
||||
if (pointer.endsWith("/group_booking_status")) {
|
||||
return objectMapper.getNodeFactory().textNode("TEN");
|
||||
}
|
||||
|
||||
@@ -789,6 +789,77 @@ class ReservationV4QueryControllerTest {
|
||||
.andExpect(content().string(not(containsString("att-payment-real-external-001"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnStableTraceFieldsAndSafeDisplayPayload() throws Exception {
|
||||
ReservationV4OrderTaskSnapshot orderTask = seedOrderTaskWithBusinessCardType(
|
||||
"mail-v4-query-trace-fields-001",
|
||||
Instant.parse("2026-07-18T02:45:00Z"),
|
||||
"GROUP",
|
||||
"GROUP_CODE",
|
||||
"GRP-V4-TRACE-FIELDS-001",
|
||||
ReservationV4CardType.TRACE_RESERVATION_NOTES.name(),
|
||||
"TRACE_RESERVATION_NOTES",
|
||||
ReservationV4CardStatus.CONFIRMED.name(),
|
||||
ReservationV4CardStatus.PENDING_CONFIRM.name(),
|
||||
"""
|
||||
{
|
||||
"card_type":"TRACE_RESERVATION_NOTES",
|
||||
"event_type":"TRACE_RESERVATION_NOTES",
|
||||
"target_order":{"locator_value":"SHOULD-NOT-LEAK-TRACE"},
|
||||
"business_fields":{
|
||||
"order_ref":"ORDER-TRACE",
|
||||
"event_type":"TRACE_RESERVATION_NOTES",
|
||||
"trace_items":[
|
||||
{
|
||||
"item_type":"GENERAL",
|
||||
"text":"Guest requests quiet rooms.",
|
||||
"content":"SHOULD-NOT-LEAK-CONTENT",
|
||||
"department_code":"FO"
|
||||
},
|
||||
{
|
||||
"item_type":"EXTRA_BED",
|
||||
"content":"SHOULD-NOT-LEAK-EXTRA-BED-CONTENT",
|
||||
"target_room_type_code":"TWN",
|
||||
"extra_bed_room_count":1,
|
||||
"department_code":"FO+HSK",
|
||||
"raw_evidence":"SHOULD-NOT-LEAK-RAW",
|
||||
"attachment_url":"https://oss.example.test/trace-secret.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
""",
|
||||
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.trace_items[0].text")
|
||||
.value("Guest requests quiet rooms."))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.trace_items[1].target_room_type_code")
|
||||
.value("TWN"))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.trace_items[1].extra_bed_room_count")
|
||||
.value(1))
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.business_fields").doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.target_order").doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.trace_items[0].content").doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].display_payload.trace_items[1].content").doesNotExist())
|
||||
.andExpect(jsonPath("$.business_cards[0].fields[?(@.field_pointer=='/trace_items/0/text')].editable")
|
||||
.value(contains(true)))
|
||||
.andExpect(jsonPath("$.business_cards[0].fields[?(@.field_pointer=='/trace_items/0/text')].control_type")
|
||||
.value(contains("textarea")))
|
||||
.andExpect(jsonPath("$.business_cards[0].fields[?(@.field_pointer=='/trace_items/0/department_code')].options_source")
|
||||
.value(contains("reservation_v4_trace_department_fixed")))
|
||||
.andExpect(content().string(containsString(
|
||||
"\"fixed_options\":[{\"value\":\"FO\",\"label\":\"FO\"},{\"value\":\"HSK\",\"label\":\"HSK\"},{\"value\":\"FO+HSK\",\"label\":\"FO+HSK\"}]")))
|
||||
.andExpect(jsonPath("$.business_cards[0].fields[?(@.field_pointer=='/trace_items/1/target_room_type_code')].options_source")
|
||||
.value(contains("reservation_v4_room_type_catalog")))
|
||||
.andExpect(jsonPath("$.business_cards[0].fields[?(@.field_pointer=='/trace_items/1/extra_bed_room_count')].control_type")
|
||||
.value(contains("number")))
|
||||
.andExpect(content().string(not(containsString("SHOULD-NOT-LEAK"))))
|
||||
.andExpect(content().string(not(containsString("https://oss.example.test"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnReadonlyRoomInformationDisplayModelForCancelBooking() throws Exception {
|
||||
Long orderId = 990000000000777002L;
|
||||
|
||||
@@ -1383,10 +1383,64 @@ class SuperAgentTaskResultControllerTest {
|
||||
LIMIT 1
|
||||
""", String.class, source.inboxId());
|
||||
assertThat(traceValidationErrors)
|
||||
.contains("business_fields.trace_items.0.target_room_type_code")
|
||||
.contains("trace_items.0.target_room_type_code")
|
||||
.contains("房型代码不在第一版目录中");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldMarkV4TraceReviewRequiredWhenDepartmentCodeInvalid() throws Exception {
|
||||
SourceMessageCaptureResult source = captureSourceMessage("mail-v4-trace-invalid-department-001");
|
||||
String body = v4CancelTraceRoomingListBody("mail-v4-trace-invalid-department-001")
|
||||
.replace("GRP-V4-CTR-001", "GRP-V4-TRACE-INVALID-DEPARTMENT-001")
|
||||
.replace("\"department_code\": \"FO\"", "\"department_code\": \"SALES\"");
|
||||
|
||||
mockMvc.perform(signedPost(body, "nonce-v4-trace-invalid-department-001"))
|
||||
.andExpect(status().isCreated())
|
||||
.andExpect(jsonPath("$.accepted_count").value(3));
|
||||
|
||||
String traceValidationErrors = jdbcTemplate.queryForObject("""
|
||||
SELECT validation_errors_json
|
||||
FROM workflow_reservation_v4_task_card
|
||||
WHERE source_message_id = ?
|
||||
AND card_type = 'TRACE_RESERVATION_NOTES'
|
||||
AND card_status = 'REVIEW_REQUIRED'
|
||||
AND review_status = 'PENDING'
|
||||
LIMIT 1
|
||||
""", String.class, source.inboxId());
|
||||
assertThat(traceValidationErrors)
|
||||
.contains("trace_items.0.department_code")
|
||||
.contains("Department Code 只允许 FO、HSK、FO+HSK。");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldMarkV4TraceReviewRequiredWhenExtraBedRoomCountInvalid() throws Exception {
|
||||
SourceMessageCaptureResult source = captureSourceMessage("mail-v4-trace-invalid-extra-bed-count-001");
|
||||
String body = v4CancelTraceRoomingListBody("mail-v4-trace-invalid-extra-bed-count-001")
|
||||
.replace("GRP-V4-CTR-001", "GRP-V4-TRACE-INVALID-EXTRA-BED-COUNT-001")
|
||||
.replace("\"item_type\": \"GENERAL\"", "\"item_type\": \"EXTRA_BED\"")
|
||||
.replace("\"text\": \"Guest requests quiet rooms.\"", "\"text\": \"Please add one extra bed.\"")
|
||||
.replace("\"department_code\": \"FO\"", "\"target_room_type_code\": \"TWN\",\n"
|
||||
+ " \"extra_bed_room_count\": 0,\n"
|
||||
+ " \"department_code\": \"FO\"");
|
||||
|
||||
mockMvc.perform(signedPost(body, "nonce-v4-trace-invalid-extra-bed-count-001"))
|
||||
.andExpect(status().isCreated())
|
||||
.andExpect(jsonPath("$.accepted_count").value(3));
|
||||
|
||||
String traceValidationErrors = jdbcTemplate.queryForObject("""
|
||||
SELECT validation_errors_json
|
||||
FROM workflow_reservation_v4_task_card
|
||||
WHERE source_message_id = ?
|
||||
AND card_type = 'TRACE_RESERVATION_NOTES'
|
||||
AND card_status = 'REVIEW_REQUIRED'
|
||||
AND review_status = 'PENDING'
|
||||
LIMIT 1
|
||||
""", String.class, source.inboxId());
|
||||
assertThat(traceValidationErrors)
|
||||
.contains("trace_items.0.extra_bed_room_count")
|
||||
.contains("加床房间数必须为正整数");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCreateV4CancelTraceAndRoomingListTasksInEventOrder() throws Exception {
|
||||
SourceMessageCaptureResult source = captureSourceMessage("mail-v4-cancel-trace-rooming-001");
|
||||
|
||||
Reference in New Issue
Block a user