From c4db0a4526f61758272c92396aa788d84f098102 Mon Sep 17 00:00:00 2001
From: longz <longzhaoz@qq.com>
Date: 星期二, 21 四月 2026 17:04:30 +0800
Subject: [PATCH] 风险规避

---
 backend/src/main/java/com/sinata/appointment/service/PostApprovalOrchestrationService.java |   81 +++++++++++++++++++++++++++++++---------
 1 files changed, 63 insertions(+), 18 deletions(-)

diff --git a/backend/src/main/java/com/sinata/appointment/service/PostApprovalOrchestrationService.java b/backend/src/main/java/com/sinata/appointment/service/PostApprovalOrchestrationService.java
index 2af6630..a4134cb 100644
--- a/backend/src/main/java/com/sinata/appointment/service/PostApprovalOrchestrationService.java
+++ b/backend/src/main/java/com/sinata/appointment/service/PostApprovalOrchestrationService.java
@@ -24,7 +24,11 @@
 import com.sinata.appointment.util.SensitiveDataUtil;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 import java.util.UUID;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -81,6 +85,8 @@
                                 .eq(AppointmentVisitor::getDelFlag, 0)
                                 .eq(AppointmentVisitor::getOrderId, order.getId())
                                 .orderByAsc(AppointmentVisitor::getId));
+        Map<Long, MpVisitor> visitorProfileMap = loadVisitorProfileMap(visitors);
+        Map<Long, QrcodeTicket> existingTicketMap = loadActiveUnusedTicketMap(order.getId(), visitors);
         int validMinutes = getMaxConsecutiveDays() * 24 * 60;
         LocalDateTime generateTime = resolveGenerateTime(order);
         LocalDateTime expireTime = generateTime.plusMinutes(validMinutes);
@@ -90,17 +96,17 @@
 
         int createdCount = 0;
         for (AppointmentVisitor visitor : visitors) {
-            QrcodeTicket existed = findActiveUnusedTicket(order.getId(), visitor.getMpVisitorId());
+            QrcodeTicket existed = existingTicketMap.get(visitor.getMpVisitorId());
             if (existed != null) {
                 log.info(
                         "{} orderId={} mpVisitorId={} reuse ticketId={}",
                         IntegrationConstant.HIKVISION_QRCODE_EVENT,
-                        order.getId(),
-                        visitor.getMpVisitorId(),
-                        existed.getId());
+                    order.getId(),
+                    visitor.getMpVisitorId(),
+                    existed.getId());
                 continue;
             }
-            MpVisitor visitorProfile = loadVisitor(visitor.getMpVisitorId());
+            MpVisitor visitorProfile = visitorProfileMap.get(visitor.getMpVisitorId());
             String ticketUuid = UUID.randomUUID().toString().replace("-", "");
             String visitorIdCardPlain = resolveVisitorIdCardPlain(visitor, visitorProfile);
             String payload =
@@ -125,6 +131,7 @@
             ticket.setGenerateTime(generateTime);
             ticket.setExpireTime(expireTime);
             qrcodeTicketMapper.insert(ticket);
+            existingTicketMap.put(visitor.getMpVisitorId(), ticket);
             createdCount++;
             log.info(
                     "{} raw-payload orderId={} mpVisitorId={} payload={}",
@@ -166,20 +173,58 @@
         }
     }
 
-    private QrcodeTicket findActiveUnusedTicket(Long orderId, Long mpVisitorId) {
-        LambdaQueryWrapper<QrcodeTicket> query =
-                new LambdaQueryWrapper<QrcodeTicket>()
-                        .eq(QrcodeTicket::getDelFlag, 0)
-                        .eq(QrcodeTicket::getOrderId, orderId)
-                        .eq(QrcodeTicket::getTicketStatus, QrcodeTicketStatus.UNUSED)
-                        .orderByDesc(QrcodeTicket::getId)
-                        .last("limit 1");
-        if (mpVisitorId == null) {
-            query.isNull(QrcodeTicket::getMpVisitorId);
-        } else {
-            query.eq(QrcodeTicket::getMpVisitorId, mpVisitorId);
+    private Map<Long, MpVisitor> loadVisitorProfileMap(List<AppointmentVisitor> visitors) {
+        if (visitors == null || visitors.isEmpty()) {
+            return Map.of();
         }
-        return qrcodeTicketMapper.selectOne(query);
+        List<Long> visitorIds =
+                visitors.stream()
+                        .map(AppointmentVisitor::getMpVisitorId)
+                        .filter(Objects::nonNull)
+                        .distinct()
+                        .toList();
+        if (visitorIds.isEmpty()) {
+            return Map.of();
+        }
+        List<MpVisitor> rows =
+                mpVisitorMapper.selectList(
+                        new LambdaQueryWrapper<MpVisitor>()
+                                .eq(MpVisitor::getDelFlag, 0)
+                                .in(MpVisitor::getId, visitorIds));
+        Map<Long, MpVisitor> result = new LinkedHashMap<>();
+        for (MpVisitor row : rows) {
+            result.putIfAbsent(row.getId(), row);
+        }
+        return result;
+    }
+
+    private Map<Long, QrcodeTicket> loadActiveUnusedTicketMap(Long orderId, List<AppointmentVisitor> visitors) {
+        if (orderId == null || visitors == null || visitors.isEmpty()) {
+            return new LinkedHashMap<>();
+        }
+        LinkedHashSet<Long> visitorIds =
+                visitors.stream()
+                        .map(AppointmentVisitor::getMpVisitorId)
+                        .filter(Objects::nonNull)
+                        .collect(java.util.stream.Collectors.toCollection(LinkedHashSet::new));
+        if (visitorIds.isEmpty()) {
+            return new LinkedHashMap<>();
+        }
+        List<QrcodeTicket> rows =
+                qrcodeTicketMapper.selectList(
+                        new LambdaQueryWrapper<QrcodeTicket>()
+                                .eq(QrcodeTicket::getDelFlag, 0)
+                                .eq(QrcodeTicket::getOrderId, orderId)
+                                .eq(QrcodeTicket::getTicketStatus, QrcodeTicketStatus.UNUSED)
+                                .in(QrcodeTicket::getMpVisitorId, visitorIds)
+                                .orderByDesc(QrcodeTicket::getId));
+        Map<Long, QrcodeTicket> result = new LinkedHashMap<>();
+        for (QrcodeTicket row : rows) {
+            if (row.getMpVisitorId() != null) {
+                result.putIfAbsent(row.getMpVisitorId(), row);
+            }
+        }
+        return result;
     }
 
     private LocalDateTime resolveGenerateTime(AppointmentOrder order) {

--
Gitblit v1.7.1