diff --git a/server/src/main/java/cn/nianxx/thhotel/workflows/reservation/service/impl/ReservationSourceMessageRelatedContextProvider.java b/server/src/main/java/cn/nianxx/thhotel/workflows/reservation/service/impl/ReservationSourceMessageRelatedContextProvider.java index 3e865a5..a134303 100644 --- a/server/src/main/java/cn/nianxx/thhotel/workflows/reservation/service/impl/ReservationSourceMessageRelatedContextProvider.java +++ b/server/src/main/java/cn/nianxx/thhotel/workflows/reservation/service/impl/ReservationSourceMessageRelatedContextProvider.java @@ -7,6 +7,7 @@ import cn.nianxx.thhotel.platform.message.service.SourceMessageRelatedContextPro import cn.nianxx.thhotel.workflows.reservation.common.dto.ReservationAiQueryOrderSnapshot; import cn.nianxx.thhotel.workflows.reservation.common.dto.ReservationAiQueryTaskSnapshot; import cn.nianxx.thhotel.workflows.reservation.common.enums.ReservationOrderKeyType; +import cn.nianxx.thhotel.workflows.reservation.common.enums.ReservationOrderVisibility; import cn.nianxx.thhotel.workflows.reservation.repository.ReservationAiWorkflowRepository; import java.util.LinkedHashMap; import java.util.List; @@ -54,16 +55,27 @@ public class ReservationSourceMessageRelatedContextProvider implements SourceMes List tasks) { Map ordersById = new LinkedHashMap<>(); workflowRepository.findAiQueryOrdersBySourceMessageIds(hotelId, List.of(sourceMessageId)) + .stream() + .filter(this::isVisibleBusinessOrder) .forEach(order -> ordersById.put(order.id(), order)); List taskOrderIds = tasks.stream() .map(ReservationAiQueryTaskSnapshot::orderId) .distinct() .toList(); workflowRepository.findAiQueryOrdersByIds(hotelId, taskOrderIds) + .stream() + .filter(this::isVisibleBusinessOrder) .forEach(order -> ordersById.put(order.id(), order)); return ordersById; } + /** + * 邮件会话只展示真实业务订单,S000/S999 等隐藏技术订单只通过任务摘要可见。 + */ + private boolean isVisibleBusinessOrder(ReservationAiQueryOrderSnapshot order) { + return order != null && !ReservationOrderVisibility.HIDDEN_SYSTEM.name().equals(order.orderVisibility()); + } + /** * 转换订单快照为 SourceMessage 会话可展示的关联订单摘要。 */ diff --git a/server/src/test/java/cn/nianxx/thhotel/platform/message/control/SourceMessageControllerTest.java b/server/src/test/java/cn/nianxx/thhotel/platform/message/control/SourceMessageControllerTest.java index 26f9416..1ecbabe 100644 --- a/server/src/test/java/cn/nianxx/thhotel/platform/message/control/SourceMessageControllerTest.java +++ b/server/src/test/java/cn/nianxx/thhotel/platform/message/control/SourceMessageControllerTest.java @@ -197,6 +197,28 @@ class SourceMessageControllerTest { org.assertj.core.api.Assertions.assertThat(auditCount).isEqualTo(2L); } + @Test + void shouldHideSystemOrderFromConversationRelatedOrders() throws Exception { + SourceMessageCaptureResult sourceMessage = captureService.capture(conversationCommand( + "mail-conversation-hidden-order-001", + "conversation-hidden-order-001", + "Information only message.", + "

Information only message.

", + List.of())); + Long orderId = 940000000000000401L; + Long transitionId = 940000000000000501L; + Long taskId = 940000000000000601L; + insertHiddenRelatedOrder(orderId, sourceMessage.inboxId()); + insertRelatedTransition(transitionId, sourceMessage.inboxId(), "TMP-HIDDEN-CONVERSATION-001"); + insertRelatedTask(taskId, orderId, sourceMessage.inboxId(), transitionId); + + mockMvc.perform(get("/api/source-messages/{sourceMessageId}/conversation", sourceMessage.inboxId())) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.messages[0].related_orders.length()").value(0)) + .andExpect(jsonPath("$.messages[0].related_tasks[0].task_id").value(taskId.toString())) + .andExpect(content().string(not(containsString("TMP-HIDDEN-CONVERSATION-001")))); + } + private CaptureSourceMessageCommand command( String externalMessageId, String externalConversationId, @@ -275,6 +297,18 @@ class SourceMessageControllerTest { """, orderId, groupCode, groupCode, "TMP-" + orderId, groupCode, sourceMessageId); } + private void insertHiddenRelatedOrder(Long orderId, Long sourceMessageId) { + jdbcTemplate.update(""" + INSERT INTO workflow_reservation_order ( + id, hotel_id, order_key_type, order_business_key, active_business_key, + temporary_order_code, order_status, order_visibility, business_key_source, display_name, + source_message_id, version, created_at, updated_at + ) + VALUES (?, 'HOTEL-TEST', 'TEMPORARY', NULL, NULL, ?, 'TEMPORARY', + 'HIDDEN_SYSTEM', 'AI_CANDIDATE', ?, ?, 0, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) + """, orderId, "TMP-HIDDEN-CONVERSATION-001", "TMP-HIDDEN-CONVERSATION-001", sourceMessageId); + } + private void insertRelatedTransition(Long transitionId, Long sourceMessageId, String groupCode) { jdbcTemplate.update(""" INSERT INTO workflow_reservation_ai_transition (