统一系统时间输出并优化任务列表查询

This commit is contained in:
andy
2026-07-08 15:15:42 +08:00
parent 936a5921b0
commit 8a196f14ed
20 changed files with 308 additions and 79 deletions

View File

@@ -1,6 +1,7 @@
package cn.nianxx.thhotel.workflows.reservation.control;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.matchesPattern;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.not;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
@@ -46,6 +47,7 @@ class ReservationAiQueryControllerTest {
private static final String OBJECT_DETAIL_ENDPOINT = "/api/ai-query/v1/object-detail";
private static final String CLIENT_ID = "superagent-test-client";
private static final String SECRET = "test-superagent-secret";
private static final String UTC_INSTANT_PATTERN = "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?Z$";
@Autowired
private MockMvc mockMvc;
@@ -84,9 +86,13 @@ class ReservationAiQueryControllerTest {
.andExpect(jsonPath("$.data.matched_order_records[0].object_type").value("group_block"))
.andExpect(jsonPath("$.data.matched_order_records[0].order_id").value("920000000000000101"))
.andExpect(jsonPath("$.data.matched_order_records[0].group_code").value("GRP-AIQUERY-001"))
.andExpect(jsonPath("$.data.matched_order_records[0].last_updated_at")
.value(matchesPattern(UTC_INSTANT_PATTERN)))
.andExpect(jsonPath("$.data.pending_or_open_tasks[0].task_id").value("920000000000000301"))
.andExpect(jsonPath("$.data.pending_or_open_tasks[0].source_event_index").value(1))
.andExpect(jsonPath("$.data.pending_or_open_tasks[0].task_status").value("PENDING_CONFIRM"))
.andExpect(jsonPath("$.data.pending_or_open_tasks[0].last_updated_at")
.value(matchesPattern(UTC_INSTANT_PATTERN)))
.andExpect(jsonPath("$.data.active_workflows.length()").value(0))
.andExpect(jsonPath("$.data.terminated_records.length()").value(0))
.andExpect(jsonPath("$.data.target_object_validation.status").value("conflict"))
@@ -275,6 +281,8 @@ class ReservationAiQueryControllerTest {
.andExpect(jsonPath("$.data.block_id").value(nullValue()))
.andExpect(jsonPath("$.data.room_items.length()").value(0))
.andExpect(jsonPath("$.data.rate_code_price").value(nullValue()))
.andExpect(jsonPath("$.data.created_at").value(matchesPattern(UTC_INSTANT_PATTERN)))
.andExpect(jsonPath("$.data.last_updated_at").value(matchesPattern(UTC_INSTANT_PATTERN)))
.andExpect(jsonPath("$.data.can_update").value(true))
.andExpect(jsonPath("$.data.can_cancel").value(true))
.andExpect(jsonPath("$.data.hard_validation_warnings[0].code").value("OPERA_PROJECTION_UNAVAILABLE"));

View File

@@ -1,6 +1,13 @@
package cn.nianxx.thhotel.workflows.reservation.control;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.matchesPattern;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@@ -9,6 +16,8 @@ import cn.nianxx.thhotel.ThHotelApplication;
import cn.nianxx.thhotel.platform.message.common.request.CaptureSourceMessageCommand;
import cn.nianxx.thhotel.platform.message.common.result.SourceMessageCaptureResult;
import cn.nianxx.thhotel.platform.message.service.SourceMessageCaptureService;
import cn.nianxx.thhotel.platform.message.service.SourceMessageQueryService;
import cn.nianxx.thhotel.workflows.reservation.repository.ReservationAiWorkflowRepository;
import java.time.Instant;
import java.util.List;
import org.junit.jupiter.api.Test;
@@ -17,6 +26,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMock
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
import org.springframework.test.web.servlet.MockMvc;
@SpringBootTest(classes = ThHotelApplication.class)
@@ -25,6 +35,7 @@ import org.springframework.test.web.servlet.MockMvc;
class ReservationFrontendQueryControllerTest {
private static final String HOTEL_ID = "HOTEL-TEST";
private static final String UTC_INSTANT_PATTERN = "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?Z$";
@Autowired
private MockMvc mockMvc;
@@ -32,6 +43,12 @@ class ReservationFrontendQueryControllerTest {
@Autowired
private SourceMessageCaptureService captureService;
@MockitoSpyBean
private SourceMessageQueryService sourceMessageQueryService;
@MockitoSpyBean
private ReservationAiWorkflowRepository workflowRepository;
@Autowired
private JdbcTemplate jdbcTemplate;
@@ -52,6 +69,8 @@ class ReservationFrontendQueryControllerTest {
"NEW_BOOKING", "NEW_BOOKING", "PENDING_CONFIRM", 1);
insertTask(secondTaskId, orderId, source.inboxId(), 930000000000000202L, "Update Booking",
"UPDATE_BOOKING", "UPDATE_BOOKING", "PENDING_CONFIRM", 2);
reset(sourceMessageQueryService);
reset(workflowRepository);
mockMvc.perform(get("/api/reservation/tasks")
.param("hotel_id", HOTEL_ID)
@@ -71,6 +90,8 @@ class ReservationFrontendQueryControllerTest {
.andExpect(jsonPath("$.items[0].readonly_reason_code").value("PROCESSABLE"))
.andExpect(jsonPath("$.items[0].source_message_id").value(source.inboxId().toString()))
.andExpect(jsonPath("$.items[0].source_subject").value("Frontend Query List Smoke"))
.andExpect(jsonPath("$.items[0].created_at").value(matchesPattern(UTC_INSTANT_PATTERN)))
.andExpect(jsonPath("$.items[0].updated_at").value(matchesPattern(UTC_INSTANT_PATTERN)))
.andExpect(jsonPath("$.items[1].task_id").value(secondTaskId.toString()))
.andExpect(jsonPath("$.items[1].task_type").value("UPDATE_BOOKING"))
.andExpect(jsonPath("$.items[1].can_process").value(false))
@@ -88,6 +109,8 @@ class ReservationFrontendQueryControllerTest {
.andExpect(jsonPath("$.items[0].source_subject").value("Frontend Query List Smoke"))
.andExpect(jsonPath("$.items[1].source_subject").value("Frontend Query List Smoke"))
.andExpect(jsonPath("$.page.total").value(2));
verify(sourceMessageQueryService, never()).getSummary(anyLong());
verify(workflowRepository, never()).findQueueTasksBefore(anyString(), anyLong(), any());
}
@Test
@@ -107,6 +130,7 @@ class ReservationFrontendQueryControllerTest {
"NEW_BOOKING", "NEW_BOOKING", "COMPLETED", 1);
insertTask(secondTaskId, orderId, source.inboxId(), 930000000000000502L, "Update Booking",
"UPDATE_BOOKING", "UPDATE_BOOKING", "PENDING_CONFIRM", 2);
reset(workflowRepository);
mockMvc.perform(get("/api/reservation/orders/{orderId}", orderId)
.param("hotel_id", HOTEL_ID)
@@ -120,14 +144,18 @@ class ReservationFrontendQueryControllerTest {
.andExpect(jsonPath("$.order.group_code").value("GRP-FRONTEND-DETAIL-001"))
.andExpect(jsonPath("$.order.confirmation_number").value(nullValue()))
.andExpect(jsonPath("$.order.display_name").value("GRP-FRONTEND-DETAIL-001"))
.andExpect(jsonPath("$.order.created_at").value(matchesPattern(UTC_INSTANT_PATTERN)))
.andExpect(jsonPath("$.order.updated_at").value(matchesPattern(UTC_INSTANT_PATTERN)))
.andExpect(jsonPath("$.tasks[0].task_id").value(firstTaskId.toString()))
.andExpect(jsonPath("$.tasks[0].task_status").value("COMPLETED"))
.andExpect(jsonPath("$.tasks[0].readonly_reason_code").value("TASK_FINISHED"))
.andExpect(jsonPath("$.tasks[0].created_at").value(matchesPattern(UTC_INSTANT_PATTERN)))
.andExpect(jsonPath("$.tasks[1].task_id").value(secondTaskId.toString()))
.andExpect(jsonPath("$.tasks[1].task_status").value("PENDING_CONFIRM"))
.andExpect(jsonPath("$.tasks[1].can_process").value(true))
.andExpect(jsonPath("$.tasks[1].readonly_reason_code").value("PROCESSABLE"))
.andExpect(jsonPath("$.warnings.length()").value(0));
verify(workflowRepository, never()).findQueueTasksBefore(anyString(), anyLong(), any());
mockMvc.perform(get("/api/reservation/orders/{orderId}", orderId)
.param("hotel_id", HOTEL_ID)