longz
2026-04-21 c4db0a4526f61758272c92396aa788d84f098102
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,7 +96,7 @@
        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={}",
@@ -100,7 +106,7 @@
                        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 =
    private Map<Long, MpVisitor> loadVisitorProfileMap(List<AppointmentVisitor> visitors) {
        if (visitors == null || visitors.isEmpty()) {
            return Map.of();
        }
        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)
                        .orderByDesc(QrcodeTicket::getId)
                        .last("limit 1");
        if (mpVisitorId == null) {
            query.isNull(QrcodeTicket::getMpVisitorId);
        } else {
            query.eq(QrcodeTicket::getMpVisitorId, mpVisitorId);
                                .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 qrcodeTicketMapper.selectOne(query);
        }
        return result;
    }
    private LocalDateTime resolveGenerateTime(AppointmentOrder order) {