修复V4复核指针运行时白名单一致性
This commit is contained in:
@@ -34,6 +34,10 @@ import cn.nianxx.thhotel.workflows.reservation.common.enums.ReservationV4TargetR
|
||||
import cn.nianxx.thhotel.workflows.reservation.common.enums.ReservationReviewStatus;
|
||||
import cn.nianxx.thhotel.workflows.reservation.repository.ReservationV4SourceNotificationRepository;
|
||||
import cn.nianxx.thhotel.workflows.reservation.repository.ReservationV4WorkflowRepository;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
@@ -47,6 +51,7 @@ import org.springframework.http.MediaType;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
|
||||
@SpringBootTest(
|
||||
classes = ThHotelApplication.class,
|
||||
@@ -91,6 +96,9 @@ class ReservationV4CommandControllerTest {
|
||||
@Autowired
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
private String adminToken;
|
||||
private String noPermissionToken;
|
||||
|
||||
@@ -1091,6 +1099,86 @@ class ReservationV4CommandControllerTest {
|
||||
.value("/room_information/final_values/room_items/0/room_type_code"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldAcceptEditableReviewFieldPointersReturnedByTaskDetail() throws Exception {
|
||||
SeededOrderTask seeded = seedReviewOrderTaskWithBusinessCard(
|
||||
HOTEL_ID,
|
||||
"mail-v4-command-review-pointer-runtime-001",
|
||||
Instant.parse("2026-07-19T01:22:18Z"),
|
||||
990000000000070116L,
|
||||
ReservationV4TargetResolutionStatus.RESOLVED.name(),
|
||||
ReservationV4CardStatus.PENDING_CONFIRM.name(),
|
||||
ReservationV4CardStatus.REVIEW_REQUIRED.name(),
|
||||
ReservationV4CardType.ROOM_INFORMATION.name(),
|
||||
"UPDATE_BOOKING",
|
||||
"""
|
||||
{
|
||||
"card_type":"ROOM_INFORMATION",
|
||||
"event_type":"UPDATE_BOOKING",
|
||||
"target_order":{"booking_type":"GROUP","locator_type":"GROUP_CODE","locator_value":"GRP-V4-REVIEW-RUNTIME-001"},
|
||||
"business_fields":{
|
||||
"event_type":"UPDATE_BOOKING",
|
||||
"after":{
|
||||
"arrival_date":"2026-08-01",
|
||||
"departure_date":"2026-08-03",
|
||||
"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);
|
||||
|
||||
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("任务详情返回的可复核字段必须能直接提交给 review-resolution")
|
||||
.isNotEmpty();
|
||||
org.assertj.core.api.Assertions.assertThat(overrides.toString())
|
||||
.contains("/room_information/final_values/room_items/0/room_type_code");
|
||||
|
||||
ObjectNode request = objectMapper.createObjectNode();
|
||||
request.put("version", 0);
|
||||
request.put("reason", "回归验证详情页可编辑 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.room_information.final_values.room_items[0].room_type_code")
|
||||
.value("RM2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldResolveRoomInformationReviewWhenDisplayPayloadAlreadyUsesStableModel() throws Exception {
|
||||
SeededOrderTask seeded = seedReviewOrderTaskWithBusinessCard(
|
||||
@@ -1770,6 +1858,34 @@ class ReservationV4CommandControllerTest {
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
|
||||
private JsonNode reviewOverrideValue(String pointer) {
|
||||
if (pointer.endsWith("/group_block_name")) {
|
||||
return objectMapper.getNodeFactory().textNode("GRP-V4-REVIEW-RUNTIME-001");
|
||||
}
|
||||
if (pointer.endsWith("/arrival_date")) {
|
||||
return objectMapper.getNodeFactory().textNode("2026-08-01");
|
||||
}
|
||||
if (pointer.endsWith("/departure_date")) {
|
||||
return objectMapper.getNodeFactory().textNode("2026-08-03");
|
||||
}
|
||||
if (pointer.endsWith("/rate_code")) {
|
||||
return objectMapper.getNodeFactory().textNode("GROUP");
|
||||
}
|
||||
if (pointer.endsWith("/room_type_code")) {
|
||||
return objectMapper.getNodeFactory().textNode("RM2");
|
||||
}
|
||||
if (pointer.endsWith("/room_count")) {
|
||||
return objectMapper.getNodeFactory().numberNode(2);
|
||||
}
|
||||
if (pointer.endsWith("/group_booking_status")) {
|
||||
return objectMapper.getNodeFactory().textNode("TEN");
|
||||
}
|
||||
if (pointer.endsWith("/breakfast_included")) {
|
||||
return objectMapper.getNodeFactory().booleanNode(true);
|
||||
}
|
||||
return objectMapper.getNodeFactory().textNode("UPDATED");
|
||||
}
|
||||
|
||||
private void confirmRoomInformationBusinessCard(SeededOrderTask seeded, String groupBookingStatus) throws Exception {
|
||||
String groupBookingStatusFragment = groupBookingStatus == null
|
||||
? ""
|
||||
|
||||
Reference in New Issue
Block a user