package com.example.web.service; import com.example.web.dto.UserProductCartDTO; import com.example.web.entity.UsersManagements; import com.example.web.mapper.SupplyUsersMapper; import com.example.web.mapper.SupplyUsersManagementsMapper; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import java.time.LocalDateTime; import java.util.List; @Service @RequiredArgsConstructor public class SupplyCustomerRecycleService { private static final Logger log = LoggerFactory.getLogger(SupplyCustomerRecycleService.class); @Autowired private SupplyUsersManagementsMapper supplyUsersManagementsMapper; @Autowired private SupplyUsersMapper supplyUsersMapper; // 从配置文件注入回流时间配置 @Value("${app.recycle.unclassified-to-organization-days:30}") private int unclassifiedToOrganizationDays; @Value("${app.recycle.organization-to-department-days:30}") private int organizationToDepartmentDays; /** * 客户回流定时任务 - 每天凌晨2点执行 */ @Scheduled(cron = "0 0 2 * * ?") @Transactional(rollbackFor = Exception.class) public void autoRecycleCustomers() { log.info("🎯 开始执行客户回流任务..."); log.info("📅 回流配置 - 未分级->组织公海池: {}天, 组织->部门公海池: {}天", unclassifiedToOrganizationDays, organizationToDepartmentDays); try { // 1. 未分级客户回流到组织公海池 recycleUnclassifiedToOrganization(); // 2. 组织公海池客户回流到部门公海池 recycleOrganizationToDepartment(); log.info("✅ 客户回流任务执行完成"); } catch (Exception e) { log.error("❌ 客户回流任务执行失败", e); throw e; // 抛出异常确保事务回滚 } } /** * 未分级客户回流到组织公海池 - 修复:保留负责人信息 */ private void recycleUnclassifiedToOrganization() { log.info("🔄 开始处理未分级客户回流..."); LocalDateTime thresholdTime = LocalDateTime.now().minusDays(unclassifiedToOrganizationDays); // 查询超过指定天数未更新的未分级客户 List unclassifiedCustomers = supplyUsersMapper.findUnclassifiedCustomersOlderThan(thresholdTime); log.info("📊 找到 {} 个需要回流的未分级客户 (阈值: {}天前)", unclassifiedCustomers.size(), unclassifiedToOrganizationDays); int recycledCount = 0; for (UserProductCartDTO customer : unclassifiedCustomers) { try { // 🔥 关键修改:先查询当前的负责人信息 UsersManagements currentManager = supplyUsersManagementsMapper.findByUserId(customer.getUserId()); log.info("🔍 客户 {} 当前负责人信息: {}", customer.getUserId(), currentManager != null ? currentManager.getUserName() : "无负责人"); // 更新客户等级为组织公海池 boolean success = supplyUsersMapper.updateCustomerLevel( customer.getUserId(), "organization-sea-pools", LocalDateTime.now() ); if (success) { // 🔥 关键修改:确保负责人信息保留 if (currentManager != null) { // 更新负责人信息的更新时间,但不改变负责人本身 boolean managerUpdated = supplyUsersManagementsMapper.updateManagerUpdateTime( customer.getUserId(), LocalDateTime.now()); log.info("✅ 客户 {} 负责人信息已保留: {}", customer.getUserId(), managerUpdated ? "成功" : "失败"); } recycledCount++; log.info("🔄 客户 {} 从未分级回流到组织公海池, 负责人: {}", customer.getUserId(), currentManager != null ? currentManager.getUserName() : "无"); } } catch (Exception e) { log.error("❌ 回流客户失败: {}", customer.getUserId(), e); } } log.info("✅ 未分级客户回流完成: {} 个客户已回流到组织公海池", recycledCount); } /** * 组织公海池客户回流到部门公海池 - 修复:保留负责人信息 */ private void recycleOrganizationToDepartment() { log.info("🔄 开始处理组织公海池客户回流..."); LocalDateTime thresholdTime = LocalDateTime.now().minusDays(organizationToDepartmentDays); // 查询超过指定天数未更新的组织公海池客户 List organizationCustomers = supplyUsersMapper.findOrganizationSeaPoolsCustomersOlderThan(thresholdTime); log.info("📊 找到 {} 个需要回流的组织公海池客户 (阈值: {}天前)", organizationCustomers.size(), organizationToDepartmentDays); int recycledCount = 0; for (UserProductCartDTO customer : organizationCustomers) { try { // 🔥 关键修改:先查询当前的负责人信息 UsersManagements currentManager = supplyUsersManagementsMapper.findByUserId(customer.getUserId()); log.info("🔍 客户 {} 当前负责人信息: {}", customer.getUserId(), currentManager != null ? currentManager.getUserName() : "无负责人"); // 更新客户等级为部门公海池 boolean success = supplyUsersMapper.updateCustomerLevel( customer.getUserId(), "department-sea-pools", LocalDateTime.now() ); if (success) { // 🔥 关键修改:确保负责人信息保留 if (currentManager != null) { // 更新负责人信息的更新时间,但不改变负责人本身 boolean managerUpdated = supplyUsersManagementsMapper.updateManagerUpdateTime( customer.getUserId(), LocalDateTime.now()); log.info("✅ 客户 {} 负责人信息已保留: {}", customer.getUserId(), managerUpdated ? "成功" : "失败"); } recycledCount++; log.info("🔄 客户 {} 从组织公海池回流到部门公海池, 负责人: {}", customer.getUserId(), currentManager != null ? currentManager.getUserName() : "无"); } } catch (Exception e) { log.error("❌ 回流客户失败: {}", customer.getUserId(), e); } } log.info("✅ 组织公海池客户回流完成: {} 个客户已回流到部门公海池", recycledCount); } /** * 手动触发回流任务(用于测试或手动执行) */ public void manualRecycle() { log.info("🔧 手动触发客户回流任务..."); autoRecycleCustomers(); } /** * 获取当前回流配置信息(用于调试或监控) */ public String getRecycleConfigInfo() { return String.format("回流配置 - 未分级->组织公海池: %d天, 组织->部门公海池: %d天", unclassifiedToOrganizationDays, organizationToDepartmentDays); } /** * 🔥 新增:获取回流客户完整信息(用于前端显示) */ public List getRecycledCustomersWithManagerInfo() { log.info("🔍 获取回流客户完整信息(包含负责人信息)"); // 获取最近回流的客户(例如最近1天内回流的) LocalDateTime sinceTime = LocalDateTime.now().minusDays(1); List recycledCustomers = supplyUsersMapper.findRecentlyRecycledCustomers(sinceTime); // 为每个客户加载负责人信息 for (UserProductCartDTO customer : recycledCustomers) { UsersManagements manager = supplyUsersManagementsMapper.findByUserId(customer.getUserId()); if (manager != null) { // 将负责人信息设置到DTO中(需要扩展UserProductCartDTO或使用其他方式) log.info("✅ 客户 {} 回流后负责人信息: {}", customer.getUserId(), manager.getUserName()); } } log.info("📊 获取到 {} 个回流客户的完整信息", recycledCustomers.size()); return recycledCustomers; } }