每日总结

屏幕截图 2026-01-06 032105
屏幕截图 2026-01-06 032051
package com.mentalhealth.service;

import com.mentalhealth.entity.Consultant;
import com.mentalhealth.entity.ConsultationSession;
import com.mentalhealth.repository.ConsultationSessionRepository;
import com.mentalhealth.repository.ConsultantRepository;
import com.mentalhealth.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@RequiredArgsConstructor
public class StatisticsService {

private final UserRepository userRepository;
private final ConsultantRepository consultantRepository;
private final ConsultationSessionRepository sessionRepository;

public Map<String, Object> getSystemStatistics() {
    Map<String, Object> stats = new HashMap<>();

    long totalUsers = userRepository.count();
    long totalConsultants = consultantRepository.count();
    long totalSessions = sessionRepository.count();

    // 今日会话统计
    LocalDateTime startOfToday = LocalDate.now().atStartOfDay();
    long todaySessions = sessionRepository.countByScheduledTimeAfter(startOfToday);

    // 本月会话统计
    LocalDateTime startOfMonth = LocalDate.now().withDayOfMonth(1).atStartOfDay();
    long monthlySessions = sessionRepository.countByScheduledTimeAfter(startOfMonth);

    // 各种状态统计
    long pendingSessions = sessionRepository.countByStatus(ConsultationSession.SessionStatus.PENDING);
    long confirmedSessions = sessionRepository.countByStatus(ConsultationSession.SessionStatus.CONFIRMED);
    long inProgressSessions = sessionRepository.countByStatus(ConsultationSession.SessionStatus.IN_PROGRESS);
    long completedSessions = sessionRepository.countByStatus(ConsultationSession.SessionStatus.COMPLETED);
    long cancelledSessions = sessionRepository.countByStatus(ConsultationSession.SessionStatus.CANCELLED);

    // 计算总收入
    Double totalRevenue = calculateTotalRevenue();

    stats.put("totalUsers", totalUsers);
    stats.put("totalConsultants", totalConsultants);
    stats.put("totalSessions", totalSessions);
    stats.put("todaySessions", todaySessions);
    stats.put("monthlySessions", monthlySessions);
    stats.put("pendingSessions", pendingSessions);
    stats.put("confirmedSessions", confirmedSessions);
    stats.put("inProgressSessions", inProgressSessions);
    stats.put("completedSessions", completedSessions);
    stats.put("cancelledSessions", cancelledSessions);
    stats.put("totalRevenue", totalRevenue != null ? totalRevenue : 0);
    stats.put("completionRate", calculateCompletionRate());
    stats.put("cancellationRate", calculateCancellationRate());

    // 获取状态分布
    List<Object[]> statusDistribution = sessionRepository.countSessionsByStatusForSystem();
    Map<String, Long> statusStats = new HashMap<>();
    for (Object[] result : statusDistribution) {
        String status = result[0].toString();
        Long count = (Long) result[1];
        statusStats.put(status, count);
    }
    stats.put("statusDistribution", statusStats);

    return stats;
}

public Map<String, Object> getConsultantStatistics(Long consultantId) {
    Map<String, Object> stats = new HashMap<>();

    Consultant consultant = consultantRepository.findById(consultantId)
            .orElseThrow(() -> new RuntimeException("咨询师不存在"));

    long totalSessions = sessionRepository.countByConsultantId(consultantId);
    long completedSessions = sessionRepository.countByConsultantIdAndStatus(
            consultantId, ConsultationSession.SessionStatus.COMPLETED);
    long pendingSessions = sessionRepository.countByConsultantIdAndStatus(
            consultantId, ConsultationSession.SessionStatus.PENDING);
    long inProgressSessions = sessionRepository.countByConsultantIdAndStatus(
            consultantId, ConsultationSession.SessionStatus.IN_PROGRESS);

    double averageRating = consultant.getRating() != null ? consultant.getRating() : 0.0;

    // 在 Service 层计算平均响应时间
    Double averageResponseTime = calculateAverageResponseTime(consultantId);

    // 修正:使用正确的方法名 - 基于 consultantId 的方法
    Double satisfactionRate = sessionRepository.findAverageRatingByConsultantId(consultantId);

    Double totalRevenue = sessionRepository.findTotalRevenueByConsultant(consultantId);

    // 今日统计
    LocalDateTime startOfToday = LocalDate.now().atStartOfDay();
    long todaySessions = sessionRepository.countByConsultantIdAndScheduledTimeAfter(consultantId, startOfToday);

    // 本月统计
    LocalDateTime startOfMonth = LocalDate.now().withDayOfMonth(1).atStartOfDay();
    long monthlySessions = sessionRepository.countByConsultantIdAndScheduledTimeAfter(consultantId, startOfMonth);

    stats.put("consultantName", consultant.getUser().getUsername());
    stats.put("realName", consultant.getRealName());
    stats.put("experienceYears", consultant.getExperienceYears());
    stats.put("totalSessions", totalSessions);
    stats.put("completedSessions", completedSessions);
    stats.put("pendingSessions", pendingSessions);
    stats.put("inProgressSessions", inProgressSessions);
    stats.put("todaySessions", todaySessions);
    stats.put("monthlySessions", monthlySessions);
    stats.put("averageRating", averageRating);
    stats.put("averageResponseTime", averageResponseTime != null ? Math.round(averageResponseTime) : 0);
    stats.put("satisfactionRate", satisfactionRate != null ? satisfactionRate : 0.0);
    stats.put("totalRevenue", totalRevenue != null ? totalRevenue : 0.0);
    stats.put("completionRate", totalSessions > 0 ?
            (double) completedSessions / totalSessions * 100 : 0);
    stats.put("responseRate", totalSessions > 0 ?
            (double) (completedSessions + inProgressSessions) / totalSessions * 100 : 0);

    // 获取状态分布
    List<Object[]> statusDistribution = sessionRepository.countSessionsByStatusForConsultant(consultantId);
    Map<String, Long> statusStats = new HashMap<>();
    for (Object[] result : statusDistribution) {
        String status = result[0].toString();
        Long count = (Long) result[1];
        statusStats.put(status, count);
    }
    stats.put("statusDistribution", statusStats);

    // 获取热门咨询类型
    List<Object[]> popularTypes = sessionRepository.findPopularConsultationTypesByConsultant(consultantId);
    Map<String, Long> typeStats = new HashMap<>();
    for (Object[] result : popularTypes) {
        String type = result[0].toString();
        Long count = (Long) result[1];
        typeStats.put(type, count);
    }
    stats.put("consultationTypes", typeStats);

    return stats;
}

public Map<String, Object> getUserStatistics(Long userId) {
    Map<String, Object> stats = new HashMap<>();

    // 修正:添加缺失的方法或使用现有方法
    long totalSessions = sessionRepository.countByUserIdAndStatus(userId, ConsultationSession.SessionStatus.COMPLETED);
    long pendingSessions = sessionRepository.countByUserIdAndStatus(userId, ConsultationSession.SessionStatus.PENDING);
    long completedSessions = sessionRepository.countByUserIdAndStatus(userId, ConsultationSession.SessionStatus.COMPLETED);

    // 平均评分(用户给咨询师的评分)
    Double averageGivenRating = sessionRepository.findAverageRatingByUser(userId);

    stats.put("totalSessions", totalSessions);
    stats.put("pendingSessions", pendingSessions);
    stats.put("completedSessions", completedSessions);
    stats.put("averageGivenRating", averageGivenRating != null ? averageGivenRating : 0.0);
    stats.put("consultationFrequency", calculateConsultationFrequency(userId));

    return stats;
}

public Map<String, Object> getMonthlyStatistics(int year, int month) {
    Map<String, Object> stats = new HashMap<>();

    LocalDateTime startOfMonth = LocalDate.of(year, month, 1).atStartOfDay();
    LocalDateTime endOfMonth = startOfMonth.plusMonths(1).minusSeconds(1);

    long monthlySessions = sessionRepository.countByScheduledTimeBetween(startOfMonth, endOfMonth);

    // 修正:传递两个参数(开始时间和结束时间)
    long monthlyCompleted = sessionRepository.countMonthlyCompletedSessions(startOfMonth, endOfMonth);

    double monthlyRevenue = calculateMonthlyRevenue(year, month);

    stats.put("year", year);
    stats.put("month", month);
    stats.put("totalSessions", monthlySessions);
    stats.put("completedSessions", monthlyCompleted);
    stats.put("revenue", monthlyRevenue);
    stats.put("completionRate", monthlySessions > 0 ? (double) monthlyCompleted / monthlySessions * 100 : 0);

    return stats;
}

// 在 Service 层计算平均响应时间
private Double calculateAverageResponseTime(Long consultantId) {
    List<ConsultationSession> sessions = sessionRepository.findByConsultantId(consultantId);

    long totalMinutes = 0;
    int count = 0;

    for (ConsultationSession session : sessions) {
        if (session.getActualStartTime() != null && session.getScheduledTime() != null) {
            java.time.Duration duration = java.time.Duration.between(session.getScheduledTime(), session.getActualStartTime());
            totalMinutes += duration.toMinutes();
            count++;
        }
    }

    return count > 0 ? (double) totalMinutes / count : null;
}

private Double calculateTotalRevenue() {
    // 计算所有咨询师的总收入
    List<Consultant> consultants = consultantRepository.findAll();
    double totalRevenue = 0.0;
    for (Consultant consultant : consultants) {
        Double revenue = sessionRepository.findTotalRevenueByConsultant(consultant.getId());
        if (revenue != null) {
            totalRevenue += revenue;
        }
    }
    return totalRevenue;
}

private double calculateCompletionRate() {
    long totalSessions = sessionRepository.count();
    long completedSessions = sessionRepository.countByStatus(ConsultationSession.SessionStatus.COMPLETED);

    return totalSessions > 0 ? (double) completedSessions / totalSessions * 100 : 0;
}

private double calculateCancellationRate() {
    long totalSessions = sessionRepository.count();
    long cancelledSessions = sessionRepository.countByStatus(ConsultationSession.SessionStatus.CANCELLED);

    return totalSessions > 0 ? (double) cancelledSessions / totalSessions * 100 : 0;
}

private double calculateConsultationFrequency(Long userId) {
    long completedSessions = sessionRepository.countByUserIdAndStatus(userId, ConsultationSession.SessionStatus.COMPLETED);
    // 假设用户注册时间为3个月前(简化处理)
    long monthsSinceRegistration = 3;
    return monthsSinceRegistration > 0 ? (double) completedSessions / monthsSinceRegistration : 0;
}

private double calculateMonthlyRevenue(int year, int month) {
    LocalDateTime startOfMonth = LocalDate.of(year, month, 1).atStartOfDay();
    LocalDateTime endOfMonth = startOfMonth.plusMonths(1).minusSeconds(1);

    // 计算所有咨询师的月度总收入
    List<Consultant> consultants = consultantRepository.findAll();
    double monthlyRevenue = 0.0;
    for (Consultant consultant : consultants) {
        Double revenue = sessionRepository.findMonthlyRevenueByConsultant(
                consultant.getId(), startOfMonth, endOfMonth);
        if (revenue != null) {
            monthlyRevenue += revenue;
        }
    }
    return monthlyRevenue;
}

}
package com.mentalhealth.service;

import com.mentalhealth.dto.;
import com.mentalhealth.entity.
;
import com.mentalhealth.repository.*;
import lombok.RequiredArgsConstructor;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ConsultationService {

private final ConsultationRequestRepository requestRepository;
private final ConsultantRepository consultantRepository;
private final ConsultationSessionRepository sessionRepository;
private final MessageService messageService;
private final UserRepository userRepository;

@Transactional
public ConsultationRequest createConsultationRequest(ConsultationRequestDTO requestDTO) {
    User user = userRepository.findById(requestDTO.getUserId())
            .orElseThrow(() -> new RuntimeException("用户不存在"));

    ConsultationRequest request = new ConsultationRequest();
    request.setUser(user);

    // 修正字段映射:problemDescription -> description
    request.setDescription(requestDTO.getProblemDescription());

    // 修正字段映射:durationMonths -> duration
    request.setDuration(requestDTO.getDurationMonths());

    // 修正字段映射:preferredType -> consultationType
    request.setConsultationType(requestDTO.getPreferredType());

    request.setStatus(ConsultationRequest.RequestStatus.PENDING);
    request.setCreateTime(LocalDateTime.now());

    ConsultationRequest savedRequest = requestRepository.save(request);

    // 智能匹配咨询师
    matchConsultants(savedRequest);

    return savedRequest;
}

private void matchConsultants(ConsultationRequest request) {
    // 基于问题描述和偏好进行智能匹配
    List<Consultant> matchedConsultants = getAvailableConsultants(
            extractExpertiseArea(request.getDescription()), // 使用 getDescription() 而不是 getProblemDescription()
            request.getConsultationType() != null ? request.getConsultationType().name() : null // 使用
                                                                                                // getConsultationType()
    );

    // 发送匹配通知给咨询师
    for (Consultant consultant : matchedConsultants) {
        String messageContent = String.format(
                "系统为您匹配到咨询师:%s,擅长领域:%s",
                consultant.getUser().getUsername(),
                consultant.getExpertiseAreas() != null ? String.join(",", consultant.getExpertiseAreas()) : "未设置");

        messageService.sendSystemMessage(
                consultant.getUser().getId(),
                request.getUser().getId(),
                messageContent);
    }

    // 发送匹配结果通知给用户
    String userMessageContent;
    if (matchedConsultants.isEmpty()) {
        userMessageContent = "您的咨询请求已提交,系统正在为您寻找合适的咨询师,请耐心等待。";
    } else {
        userMessageContent = String.format(
                "系统已为您匹配到%d位合适的咨询师,我们将尽快安排您的咨询。",
                matchedConsultants.size());
    }

    messageService.sendSystemMessage(
            0L, // 系统消息
            request.getUser().getId(),
            userMessageContent);
}

private String extractExpertiseArea(String problemDescription) {
    // 简单的关键词匹配,实际应该使用NLP技术
    if (problemDescription == null)
        return "一般心理问题";
    if (problemDescription.contains("焦虑"))
        return "焦虑";
    if (problemDescription.contains("抑郁"))
        return "抑郁";
    if (problemDescription.contains("婚姻"))
        return "婚姻家庭";
    if (problemDescription.contains("亲子"))
        return "亲子关系";
    return "一般心理问题";
}

/**
 * 根据ID获取咨询师详情
 */
public Consultant getConsultantById(Long id) {
    return consultantRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("咨询师不存在,ID: " + id));
}

/**
 * 获取所有可用咨询师
 */
public List<Consultant> getAllAvailableConsultants() {
    return getAvailableConsultants(null, null);
}

/**
 * 根据专业领域筛选咨询师
 */
public List<Consultant> getConsultantsByExpertise(String expertiseArea) {
    return getAvailableConsultants(expertiseArea, null);
}

/**
 * 获取可用咨询师
 */
public List<Consultant> getAvailableConsultants(String expertiseArea, String preferredType) {
    Specification<Consultant> spec = (root, query, cb) -> {
        List<Predicate> predicates = new ArrayList<>();

        // 只查询已批准的咨询师
        predicates.add(cb.equal(root.get("status"), "APPROVED"));
        predicates.add(cb.isTrue(root.get("available")));

        if (expertiseArea != null && !expertiseArea.isEmpty()) {
            predicates.add(cb.isMember(expertiseArea, root.get("expertiseAreas")));
        }

        // 考虑咨询方式偏好
        if (preferredType != null && !preferredType.isEmpty()) {
            predicates.add(cb.isMember(preferredType, root.get("therapyMethods")));
        }

        return cb.and(predicates.toArray(new Predicate[0]));
    };

    return consultantRepository.findAll(spec);
}

public List<Consultant> searchConsultants(ConsultantSearchDTO searchDTO) {
    Specification<Consultant> spec = Specification.where(null);

    if (searchDTO.getExpertiseArea() != null) {
        spec = spec.and((root, query, cb) -> cb.isMember(searchDTO.getExpertiseArea(), root.get("expertiseAreas")));
    }

    if (searchDTO.getTherapyMethod() != null) {
        spec = spec.and((root, query, cb) -> cb.isMember(searchDTO.getTherapyMethod(), root.get("therapyMethods")));
    }

    if (searchDTO.getKeyword() != null) {
        spec = spec.and(
                (root, query, cb) -> cb.like(root.get("user").get("username"), "%" + searchDTO.getKeyword() + "%"));
    }

    if (searchDTO.getGender() != null) {
        spec = spec.and((root, query, cb) -> cb.equal(root.get("user").get("gender"), searchDTO.getGender()));
    }

    if (searchDTO.getMinExperience() != null) {
        spec = spec.and((root, query, cb) -> cb.greaterThanOrEqualTo(root.get("experienceYears"),
                searchDTO.getMinExperience()));
    }

    if (searchDTO.getMinRating() != null) {
        spec = spec.and((root, query, cb) -> cb.greaterThanOrEqualTo(root.get("rating"), searchDTO.getMinRating()));
    }

    // 只返回已批准且可用的咨询师
    spec = spec.and((root, query, cb) -> cb.equal(root.get("status"), "APPROVED"));
    spec = spec.and((root, query, cb) -> cb.isTrue(root.get("available")));

    return consultantRepository.findAll(spec);
}

@Transactional
public ConsultationSession bookConsultation(BookingDTO bookingDTO) {
    // 验证用户存在
    User user = userRepository.findById(bookingDTO.getUserId())
            .orElseThrow(() -> new RuntimeException("用户不存在"));

    Consultant consultant = consultantRepository.findById(bookingDTO.getConsultantId())
            .orElseThrow(() -> new RuntimeException("咨询师不存在"));

    // 检查咨询师是否已批准且可用
    if (!"APPROVED".equals(consultant.getStatus()) || !Boolean.TRUE.equals(consultant.getAvailable())) {
        throw new RuntimeException("该咨询师暂不可用");
    }

    ConsultationSession session = new ConsultationSession();
    session.setUserId(bookingDTO.getUserId()); // 使用 setUserId 而不是 setUser
    session.setConsultant(consultant); // 设置关联的consultant对象
    session.setConsultantId(consultant.getId()); // 同时显式设置consultantId字段
    session.setType(bookingDTO.getType());
    session.setDuration(bookingDTO.getDuration());
    session.setScheduledTime(bookingDTO.getScheduledTime());
    session.setPrice(calculatePrice(consultant, bookingDTO.getDuration(), bookingDTO.getType()));
    session.setStatus(ConsultationSession.SessionStatus.PENDING);
    session.setCreateTime(LocalDateTime.now());

    ConsultationSession savedSession = sessionRepository.save(session);

    // 发送通知给用户
    String userMessage = String.format("您已成功预约咨询师%s,时间:%s,咨询类型:%s,时长:%d分钟",
            consultant.getUser().getUsername(),
            savedSession.getScheduledTime()
                    .format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")),
            savedSession.getType().getDescription(),
            savedSession.getDuration());
    messageService.sendSystemMessage(0L, user.getId(), userMessage);

    // 发送通知给咨询师
    String consultantMessage = String.format("用户%s已预约您的咨询,时间:%s,咨询类型:%s,时长:%d分钟",
            user.getUsername(),
            savedSession.getScheduledTime()
                    .format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")),
            savedSession.getType().getDescription(),
            savedSession.getDuration());
    messageService.sendSystemMessage(0L, consultant.getUser().getId(), consultantMessage);

    return savedSession;
}

private BigDecimal calculatePrice(Consultant consultant, Integer duration,
        com.mentalhealth.entity.ConsultationType consultationType) {
    // 将 Double 转换为 BigDecimal
    BigDecimal hourlyRate = consultant.getPricePerHour() != null ? BigDecimal.valueOf(consultant.getPricePerHour())
            : BigDecimal.valueOf(100);

    // 不同咨询方式的价格系数,与前端保持一致
    BigDecimal multiplier = BigDecimal.valueOf(1.0);
    if (com.mentalhealth.entity.ConsultationType.TEXT.equals(consultationType)) {
        multiplier = BigDecimal.valueOf(0.8);
    } else if (com.mentalhealth.entity.ConsultationType.VIDEO.equals(consultationType)) {
        multiplier = BigDecimal.valueOf(1.2);
    }

    return hourlyRate.multiply(
            BigDecimal.valueOf(duration).divide(BigDecimal.valueOf(60), 2, BigDecimal.ROUND_HALF_UP))
            .multiply(multiplier);
}

public List<ConsultationSession> getUserConsultationHistory(Long userId, List<String> statusList, String type) {
    List<ConsultationSession> allSessions = sessionRepository.findByUserIdOrderByScheduledTimeDesc(userId);

    // 根据状态过滤
    if (statusList != null && !statusList.isEmpty()) {
        List<ConsultationSession.SessionStatus> statuses = statusList.stream()
                .filter(status -> status != null && !status.isEmpty() && !"all".equals(status))
                .map(status -> {
                    try {
                        return ConsultationSession.SessionStatus.valueOf(status.toUpperCase());
                    } catch (IllegalArgumentException e) {
                        // 忽略无效的状态值
                        return null;
                    }
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        if (!statuses.isEmpty()) {
            allSessions = allSessions.stream()
                    .filter(session -> statuses.contains(session.getStatus()))
                    .collect(Collectors.toList());
        }
    }

    // 根据类型过滤
    if (type != null && !type.isEmpty() && !"all".equals(type)) {
        try {
            ConsultationType consultationType = ConsultationType.valueOf(type.toUpperCase());
            allSessions = allSessions.stream()
                    .filter(session -> session.getType() == consultationType)
                    .collect(Collectors.toList());
        } catch (IllegalArgumentException e) {
            // 忽略无效的类型值
        }
    }

    return allSessions;
}

/**
 * 获取咨询师的咨询记录
 */
public List<ConsultationSession> getConsultantSessions(Long consultantId) {
    return sessionRepository.findByConsultantIdOrderByScheduledTimeDesc(consultantId);
}

@Transactional
public ConsultationSession rateConsultation(Long sessionId, RatingDTO ratingDTO) {
    ConsultationSession session = sessionRepository.findById(sessionId)
            .orElseThrow(() -> new RuntimeException("咨询记录不存在"));

    // 检查会话是否已完成
    if (session.getStatus() != ConsultationSession.SessionStatus.COMPLETED) {
        throw new RuntimeException("只能对已完成的咨询进行评价");
    }

    session.setRating(ratingDTO.getRating());
    session.setUserReview(ratingDTO.getReview());

    // 更新咨询师评分
    updateConsultantRating(session.getConsultantId());

    return sessionRepository.save(session);
}

/**
 * 更新咨询师评分
 */
private void updateConsultantRating(Long consultantId) {
    List<ConsultationSession> sessions = sessionRepository.findByConsultantIdOrderByScheduledTimeDesc(consultantId)
            .stream()
            .filter(session -> session.getRating() != null)
            .collect(Collectors.toList());

    if (!sessions.isEmpty()) {
        double averageRating = sessions.stream()
                .mapToInt(ConsultationSession::getRating)
                .average()
                .orElse(0.0);

        Consultant consultant = consultantRepository.findById(consultantId)
                .orElseThrow(() -> new RuntimeException("咨询师不存在"));
        consultant.setRating(averageRating);
        consultantRepository.save(consultant);
    }
}

/**
 * 取消咨询预约
 */
@Transactional
public ConsultationSession cancelConsultation(Long sessionId, String reason) {
    ConsultationSession session = sessionRepository.findById(sessionId)
            .orElseThrow(() -> new RuntimeException("咨询记录不存在"));

    if (session.getStatus() != ConsultationSession.SessionStatus.PENDING &&
            session.getStatus() != ConsultationSession.SessionStatus.CONFIRMED) {
        throw new RuntimeException("只能取消待确认或已确认的咨询");
    }

    session.setStatus(ConsultationSession.SessionStatus.CANCELLED);

    // 获取用户和咨询师信息来发送通知
    User user = userRepository.findById(session.getUserId())
            .orElseThrow(() -> new RuntimeException("用户不存在"));
    Consultant consultant = consultantRepository.findById(session.getConsultantId())
            .orElseThrow(() -> new RuntimeException("咨询师不存在"));

    // 发送取消通知
    messageService.sendSystemMessage(
            user.getId(),
            consultant.getUser().getId(),
            "咨询预约已取消,原因:" + reason);

    return sessionRepository.save(session);
}

/**
 * 开始咨询会话
 */
@Transactional
public ConsultationSession startConsultation(Long sessionId) {
    ConsultationSession session = sessionRepository.findById(sessionId)
            .orElseThrow(() -> new RuntimeException("咨询记录不存在"));

    session.setStatus(ConsultationSession.SessionStatus.IN_PROGRESS);
    session.setActualStartTime(LocalDateTime.now());

    return sessionRepository.save(session);
}

/**
 * 结束咨询会话
 */
@Transactional
public ConsultationSession completeConsultation(Long sessionId, String summary, String feedback) {
    ConsultationSession session = sessionRepository.findById(sessionId)
            .orElseThrow(() -> new RuntimeException("咨询记录不存在"));

    session.setStatus(ConsultationSession.SessionStatus.COMPLETED);
    session.setEndTime(LocalDateTime.now());
    session.setSummary(summary);
    session.setConsultantFeedback(feedback);

    return sessionRepository.save(session);
}

/**
 * 获取用户的所有咨询请求
 */
public List<ConsultationRequest> getUserConsultationRequests(Long userId) {
    return requestRepository.findByUserId(userId);
}

/**
 * 根据状态获取咨询请求
 */
public List<ConsultationRequest> getConsultationRequestsByStatus(ConsultationRequest.RequestStatus status) {
    return requestRepository.findByStatus(status);
}

/**
 * 获取咨询会话详情
 */
public ConsultationSession getConsultationSession(Long sessionId) {
    return sessionRepository.findById(sessionId)
            .orElseThrow(() -> new RuntimeException("咨询记录不存在"));
}

/**
 * 获取咨询会话详情(包含用户和咨询师信息)
 */
public ConsultationSessionDetailDTO getSessionDetail(Long sessionId) {
    ConsultationSession session = sessionRepository.findById(sessionId)
            .orElseThrow(() -> new RuntimeException("咨询记录不存在"));

    User user = userRepository.findById(session.getUserId())
            .orElseThrow(() -> new RuntimeException("用户不存在"));
    Consultant consultant = consultantRepository.findById(session.getConsultantId())
            .orElseThrow(() -> new RuntimeException("咨询师不存在"));

    ConsultationSessionDetailDTO detailDTO = new ConsultationSessionDetailDTO();
    detailDTO.setSession(session);
    detailDTO.setUser(user);
    detailDTO.setConsultant(consultant);

    return detailDTO;
}

/**
 * 获取咨询师未来指定天数的日程安排
 */
public List<ConsultationSession> getConsultantSchedule(Long consultantId, int days) {
    LocalDateTime now = LocalDateTime.now();
    LocalDateTime endTime = now.plusDays(days);

    return sessionRepository.findByConsultantIdAndScheduledTimeBetweenOrderByScheduledTimeAsc(
            consultantId, now, endTime);
}

/**
 * 获取用户即将开始的预约(当前时间前后10分钟内)
 */
public Optional<ConsultationSession> getUserUpcomingSession(Long userId) {
    LocalDateTime now = LocalDateTime.now();
    LocalDateTime before = now.minusMinutes(10);
    LocalDateTime after = now.plusMinutes(10);

    return sessionRepository.findByUserIdAndScheduledTimeBetweenAndStatusInOrderByScheduledTimeAsc(
            userId, before, after,
            Arrays.asList(ConsultationSession.SessionStatus.PENDING,
                    ConsultationSession.SessionStatus.CONFIRMED))
            .stream().findFirst();
}

}

posted @ 2025-10-30 19:01  李蕊lr  阅读(2)  评论(0)    收藏  举报