| | |
| | | import com.ruoyi.common.core.domain.entity.SysDept; |
| | | import com.ruoyi.common.core.domain.entity.SysUser; |
| | | import com.ruoyi.common.utils.*; |
| | | import com.ruoyi.system.domain.SysTask; |
| | | import com.ruoyi.system.domain.SysTaskEmergency; |
| | | import com.ruoyi.system.domain.VehicleInfo; |
| | | import com.ruoyi.system.domain.enums.TaskStatus; |
| | |
| | | import com.ruoyi.system.mapper.VehicleInfoMapper; |
| | | import com.ruoyi.system.service.ISysUserService; |
| | | import com.ruoyi.system.service.IWechatTaskNotifyService; |
| | | import com.ruoyi.system.service.INotifyTaskService; |
| | | import com.ruoyi.system.service.INotifyDispatchService; |
| | | import com.ruoyi.system.domain.NotifyTask; |
| | | import com.ruoyi.system.utils.TaskStatusConverter; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | |
| | | import java.math.BigDecimal; |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | |
| | | /** |
| | | * 旧系统转运单同步Service业务层处理 |
| | |
| | | @Autowired |
| | | private IWechatTaskNotifyService wechatTaskNotifyService; |
| | | |
| | | @Autowired |
| | | private INotifyTaskService notifyTaskService; |
| | | |
| | | @Autowired |
| | | private INotifyDispatchService notifyDispatchService; |
| | | |
| | | |
| | | |
| | | /** |
| | | * 同步指定日期范围的旧系统转运单到新系统 |
| | | * |
| | | * @param daysAgo 多少天前的数据(如7表示7天前的数据) |
| | | * 优化:将多天范围拆分为逐天循环,每次仅查询1天数据,避免大数据量导致SQL Server超时 |
| | | * |
| | | * @param daysAgo 多少天前的数据(如7表示同步最近7天的数据) |
| | | * @return 成功同步的转运单数量 |
| | | */ |
| | | @Override |
| | | public int syncLegacyTransferOrders(int daysAgo) { |
| | | log.info("开始同步{}天前的旧系统转运单数据", daysAgo); |
| | | |
| | | try { |
| | | // 参数验证 |
| | | if (daysAgo <= 0) { |
| | | log.error("天数参数必须大于0"); |
| | | return 0; |
| | | } |
| | | |
| | | // 计算日期范围 |
| | | Date startDate = DateUtils.addDays(new Date(), -daysAgo); |
| | | String startDateStr = DateUtils.parseDateToStr("yyyy-MM-dd", startDate); |
| | | |
| | | // 从SQL Server查询转运单数据 |
| | | List<Map<String, Object>> transferOrders = legacyTransferSyncMapper.selectTransferOrders(startDateStr); |
| | | |
| | | if (transferOrders == null || transferOrders.isEmpty()) { |
| | | log.info("未查询到{}天前的转运单数据", daysAgo); |
| | | return 0; |
| | | |
| | | // log.info("[转运单同步] 开始同步,范围: 最近{}天", daysAgo); |
| | | int totalSuccessCount = 0; |
| | | int totalDays = daysAgo + 1; |
| | | |
| | | // 按天拆分,每次只同步1天的数据,避免大范围查询超时 |
| | | for (int i = daysAgo; i >= 0; i--) { |
| | | Date dayStart = DateUtils.addDays(new Date(), -i); |
| | | String dayStartStr = DateUtils.parseDateToStr("yyyy-MM-dd", dayStart) + " 00:00:00"; |
| | | String dayEndStr = DateUtils.parseDateToStr("yyyy-MM-dd", dayStart) + " 23:59:59"; |
| | | |
| | | int dayIndex = totalDays - i; |
| | | // log.info("[转运单同步] 处理天 {}/{}: {}", dayIndex, totalDays, dayStartStr); |
| | | int daySuccessCount = syncSingleDayOrders(dayStartStr, dayEndStr); |
| | | totalSuccessCount += daySuccessCount; |
| | | // log.info("[转运单同步] {} 完成,新增同步: {}条,累计: {}条", dayStartStr, daySuccessCount, totalSuccessCount); |
| | | } |
| | | |
| | | log.info("查询到{}条转运单数据,开始同步...", transferOrders.size()); |
| | | |
| | | int successCount = 0; |
| | | int totalCount = transferOrders.size(); |
| | | int processedCount = 0; |
| | | |
| | | for (Map<String, Object> order : transferOrders) { |
| | | processedCount++; |
| | | try { |
| | | Long serviceOrdID = MapValueUtils.getLongValue(order, "ServiceOrdID"); |
| | | Long dispatchOrdID = MapValueUtils.getLongValue(order, "DispatchOrdID"); |
| | | |
| | | // 检查参数有效性 |
| | | if (serviceOrdID==null || serviceOrdID<=0) { |
| | | log.warn("第{}条数据服务单ID为空,跳过处理", processedCount); |
| | | continue; |
| | | } |
| | | |
| | | log.debug("正在处理第{}/{}条转运单: ServiceOrdID={}, DispatchOrdID={}", |
| | | processedCount, totalCount, serviceOrdID, dispatchOrdID); |
| | | |
| | | // 检查是否已同步 |
| | | if (isTransferOrderSynced(serviceOrdID, dispatchOrdID)) { |
| | | log.debug("转运单已同步,跳过: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID); |
| | | //进行更新操作 |
| | | updateTransferOrder(serviceOrdID, dispatchOrdID, order); |
| | | continue; |
| | | } |
| | | |
| | | // 同步单个转运单 |
| | | boolean success = syncSingleTransferOrder(serviceOrdID, dispatchOrdID, order); |
| | | if (success) { |
| | | successCount++; |
| | | } |
| | | |
| | | // 控制同步频率,避免请求过快 |
| | | Thread.sleep(100); |
| | | } catch (InterruptedException ie) { |
| | | log.warn("同步任务被中断"); |
| | | Thread.currentThread().interrupt(); |
| | | break; |
| | | } catch (Exception e) { |
| | | log.error("同步单个转运单失败: ServiceOrdID={}, DispatchOrdID={}", |
| | | MapValueUtils.getStringValue(order, "ServiceOrdID"), |
| | | MapValueUtils.getStringValue(order, "DispatchOrdID"), e); |
| | | } |
| | | } |
| | | |
| | | log.info("同步完成,共处理{}条转运单,成功同步{}条转运单数据", totalCount, successCount); |
| | | return successCount; |
| | | |
| | | |
| | | // log.info("[转运单同步] 全部完成,共新增同步 {}条", totalSuccessCount); |
| | | return totalSuccessCount; |
| | | |
| | | } catch (Exception e) { |
| | | log.error("同步{}天前的旧系统转运单数据异常", daysAgo, e); |
| | | return 0; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 同步单天的转运单数据(Keyset游标分页) |
| | | * |
| | | * @param startDateStr 开始日期字符串(yyyy-MM-dd) |
| | | * @param endDateStr 结束日期字符串(yyyy-MM-dd) |
| | | * @return 成功同步的转运单数量 |
| | | */ |
| | | private int syncSingleDayOrders(String startDateStr, String endDateStr) { |
| | | final int PAGE_SIZE = 5; |
| | | long lastId = 0L; |
| | | int successCount = 0; |
| | | int pageNum = 0; |
| | | int totalProcessed = 0; |
| | | |
| | | try { |
| | | while (true) { |
| | | List<Map<String, Object>> transferOrders = legacyTransferSyncMapper.selectTransferOrders(startDateStr, endDateStr, lastId, PAGE_SIZE); |
| | | |
| | | if (transferOrders == null || transferOrders.isEmpty()) { |
| | | break; |
| | | } |
| | | |
| | | pageNum++; |
| | | int totalCount = transferOrders.size(); |
| | | int processedCount = 0; |
| | | |
| | | // log.info("[转运单同步] {} 第{}页,获取{}.条数据,lastId={}", startDateStr, pageNum, totalCount, lastId); |
| | | |
| | | for (Map<String, Object> order : transferOrders) { |
| | | processedCount++; |
| | | totalProcessed++; |
| | | try { |
| | | Long serviceOrdID = MapValueUtils.getLongValue(order, "ServiceOrdID"); |
| | | Long dispatchOrdID = MapValueUtils.getLongValue(order, "DispatchOrdID"); |
| | | |
| | | if (serviceOrdID == null || serviceOrdID <= 0) { |
| | | log.warn("第{}条数据服务单ID为空,跳过处理", processedCount); |
| | | continue; |
| | | } |
| | | |
| | | // 检查是否已同步 |
| | | if (isTransferOrderSynced(serviceOrdID, dispatchOrdID)) { |
| | | log.debug("[转运单同步] 已存在,执行更新: ServiceOrdID={}", serviceOrdID); |
| | | updateTransferOrder(serviceOrdID, dispatchOrdID, order); |
| | | continue; |
| | | } |
| | | |
| | | // 同步单个转运单 |
| | | log.info("[转运单同步] 新增同步: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID); |
| | | boolean success = syncSingleTransferOrder(serviceOrdID, dispatchOrdID, order); |
| | | if (success) { |
| | | successCount++; |
| | | log.info("[转运单同步] 同步成功: ServiceOrdID={}, 当天新增累计: {}", serviceOrdID, successCount); |
| | | } else { |
| | | log.warn("[转运单同步] 同步失败: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID); |
| | | } |
| | | |
| | | // 控制同步频率,避免请求过快 |
| | | Thread.sleep(100); |
| | | } catch (InterruptedException ie) { |
| | | log.warn("同步任务被中断"); |
| | | Thread.currentThread().interrupt(); |
| | | return successCount; |
| | | } catch (Exception e) { |
| | | log.error("同步单个转运单失败: ServiceOrdID={}, DispatchOrdID={}", |
| | | MapValueUtils.getStringValue(order, "ServiceOrdID"), |
| | | MapValueUtils.getStringValue(order, "DispatchOrdID"), e); |
| | | } |
| | | } |
| | | |
| | | // 更新游标为本页最后一条的 ServiceOrdID |
| | | Map<String, Object> lastOrder = transferOrders.get(transferOrders.size() - 1); |
| | | Long lastServiceOrdID = MapValueUtils.getLongValue(lastOrder, "ServiceOrdID"); |
| | | if (lastServiceOrdID != null && lastServiceOrdID > 0) { |
| | | lastId = lastServiceOrdID; |
| | | } else { |
| | | break; |
| | | } |
| | | |
| | | // 本页未满一页,说明已无更多数据 |
| | | if (totalCount < PAGE_SIZE) { |
| | | break; |
| | | } |
| | | } |
| | | |
| | | // log.info("[转运单同步] {} 分页完成,共处理: {}条,新增同步: {}条", startDateStr, totalProcessed, successCount); |
| | | } catch (Exception e) { |
| | | log.error("同步单天转运单数据异常: date={}", startDateStr, e); |
| | | } |
| | | |
| | | return successCount; |
| | | } |
| | | |
| | | /** |
| | |
| | | // log.info("转运单同步成功: ServiceOrdID={}, DispatchOrdID={}, 创建的任务ID={}", serviceOrdID, dispatchOrdID, result); |
| | | |
| | | try { |
| | | notifyTransferOrderByWechat((long) result, serviceOrdID, dispatchOrdID, serviceOrdNo, ServiceOrd_CC_Time, dept, order); |
| | | // 直接使用方法头部已查询的 emergency 获取 taskId |
| | | Long taskId = emergency.getTaskId(); |
| | | if (taskId != null) { |
| | | notifyTransferOrderByWechat(taskId, serviceOrdID, dispatchOrdID, serviceOrdNo, ServiceOrd_CC_Time, dept, order); |
| | | } else { |
| | | log.warn("更新后找不到taskId,跳过通知: ServiceOrdID={}", serviceOrdID); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("转运单同步成功后发送微信通知失败: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID, e); |
| | | } |
| | |
| | | createTaskVo.setDeptId(deptId); |
| | | |
| | | |
| | | int result = sysTaskService.insertTask(createTaskVo,serviceOrdID,dispatchOrdID, serviceOrdNo, taskCreatorId,createUserName, deptId, ServiceOrd_CC_Time, ServiceOrd_CC_Time); |
| | | Long taskId = sysTaskService.insertTask(createTaskVo,serviceOrdID,dispatchOrdID, serviceOrdNo, taskCreatorId,createUserName, deptId, ServiceOrd_CC_Time, ServiceOrd_CC_Time); |
| | | |
| | | if (result > 0) { |
| | | // log.info("转运单同步成功: ServiceOrdID={}, DispatchOrdID={}, 创建的任务ID={}", serviceOrdID, dispatchOrdID, result); |
| | | if (taskId != null && taskId > 0) { |
| | | // log.info("转运单同步成功: ServiceOrdID={}, DispatchOrdID={}, 创建的任务ID={}", serviceOrdID, dispatchOrdID, taskId); |
| | | |
| | | try { |
| | | notifyTransferOrderByWechat((long) result, serviceOrdID, dispatchOrdID, serviceOrdNo, ServiceOrd_CC_Time, dept, order); |
| | | notifyTransferOrderByWechat(taskId, serviceOrdID, dispatchOrdID, serviceOrdNo, ServiceOrd_CC_Time, dept, order); |
| | | } catch (Exception e) { |
| | | log.error("转运单同步成功后发送微信通知失败: ServiceOrdID={}, DispatchOrdID={}", serviceOrdID, dispatchOrdID, e); |
| | | } |
| | |
| | | } |
| | | } |
| | | createTaskVo.setPatient(patientInfo); |
| | | //1000公里,提取数字 |
| | | //1000公里,提取数字(支持小数) |
| | | String ServiceOrdTraDistance=MapValueUtils.getStringValue(order, "ServiceOrdTraDistance"); |
| | | if(ServiceOrdTraDistance!=null){ |
| | | ServiceOrdTraDistance=ServiceOrdTraDistance.replaceAll("[^0-9]", ""); |
| | | createTaskVo.setDistance(new BigDecimal(ServiceOrdTraDistance)); |
| | | // 保留数字和小数点,移除其他字符 |
| | | ServiceOrdTraDistance=ServiceOrdTraDistance.replaceAll("[^0-9.]", ""); |
| | | // 处理多个小数点的情况,只保留第一个 |
| | | int firstDotIndex = ServiceOrdTraDistance.indexOf('.'); |
| | | if (firstDotIndex != -1) { |
| | | ServiceOrdTraDistance = ServiceOrdTraDistance.substring(0, firstDotIndex + 1) |
| | | + ServiceOrdTraDistance.substring(firstDotIndex + 1).replace(".", ""); |
| | | } |
| | | if (!ServiceOrdTraDistance.isEmpty() && !ServiceOrdTraDistance.equals(".")) { |
| | | createTaskVo.setTransferDistance(new BigDecimal(ServiceOrdTraDistance)); |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | SysDept dept, |
| | | Map<String, Object> order) { |
| | | try { |
| | | // 获取通知接收人列表 |
| | | List<SysUser> receivers = getWechatNotifyUsers(dispatchOrdID, dept); |
| | | if (receivers == null || receivers.isEmpty()) { |
| | | // log.info("旧系统同步转运单无可用微信接收人,taskId={}", taskId); |
| | | // 1. 获取执行人列表 |
| | | List<TaskCreateVO.AssigneeInfo> assignees = queryAssignees(dispatchOrdID); |
| | | if (assignees.isEmpty()) { |
| | | // log.info("旧系统同步转运单无执行人,taskId={}", taskId); |
| | | return; |
| | | } |
| | | |
| | | // 提取接收人 ID 列表 |
| | | List<Long> userIds = new ArrayList<>(); |
| | | for (SysUser user : receivers) { |
| | | if (user != null && user.getUserId() != null) { |
| | | userIds.add(user.getUserId()); |
| | | // 2. 查询任务获取showTaskCode |
| | | SysTask sysTask = sysTaskService.getTaskDetail(taskId); |
| | | String showTaskCode = sysTask != null ? sysTask.getShowTaskCode() : serviceOrdNo; |
| | | |
| | | // 3. 构建通知内容 |
| | | String notifyContent = buildLegacyNotifyContent(showTaskCode, serviceOrdCcTime, order); |
| | | |
| | | // 4. 查询该taskId已有的通知记录,收集已存在的userId集合 |
| | | List<NotifyTask> existingTasks = notifyTaskService.selectByTaskIdAndType(taskId, NotifyTask.NOTIFY_TYPE_TASK_ASSIGN); |
| | | Set<Long> existingUserIds = new HashSet<>(); |
| | | List<NotifyTask> pendingTasks = new ArrayList<>(); |
| | | if (existingTasks != null && !existingTasks.isEmpty()) { |
| | | for (NotifyTask t : existingTasks) { |
| | | existingUserIds.add(t.getUserId()); |
| | | // 将未完成的记录收集给待分发列表 |
| | | if (!NotifyTask.STATUS_COMPLETED.equals(t.getStatus())) { |
| | | pendingTasks.add(t); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 调用统一的微信通知服务 |
| | | int successCount = wechatTaskNotifyService.sendTaskNotifyMessage(taskId, userIds); |
| | | // log.info("旧系统同步转运单微信通知发送完成,taskId={}, 成功={}", taskId, successCount); |
| | | // 5. 只对新执行人创建通知任务 |
| | | List<NotifyTask> notifyTasks = new ArrayList<>(pendingTasks); |
| | | for (TaskCreateVO.AssigneeInfo assignee : assignees) { |
| | | if (assignee == null || assignee.getUserId() == null) { |
| | | continue; |
| | | } |
| | | // 该用户已有通知记录,跳过 |
| | | if (existingUserIds.contains(assignee.getUserId())) { |
| | | // log.info("用户已有通知记录,跳过创建,taskId={}, userId={}", taskId, assignee.getUserId()); |
| | | continue; |
| | | } |
| | | |
| | | SysUser user = sysUserService.selectUserById(assignee.getUserId()); |
| | | if (user == null) { |
| | | log.warn("找不到执行人用户信息,userId={}", assignee.getUserId()); |
| | | continue; |
| | | } |
| | | |
| | | NotifyTask notifyTask = new NotifyTask(); |
| | | notifyTask.setTaskId(taskId); |
| | | notifyTask.setTaskCode(showTaskCode); |
| | | notifyTask.setNotifyType(NotifyTask.NOTIFY_TYPE_TASK_ASSIGN); |
| | | notifyTask.setUserId(user.getUserId()); |
| | | notifyTask.setUserName(user.getNickName()); |
| | | notifyTask.setUserPhone(user.getPhonenumber()); |
| | | notifyTask.setTitle("转运单任务派单通知"); |
| | | notifyTask.setContent(notifyContent); |
| | | notifyTask.setCreateBy("系统同步"); |
| | | |
| | | NotifyTask created = notifyTaskService.createNotifyTask(notifyTask); |
| | | if (created != null) { |
| | | notifyTasks.add(created); |
| | | // log.info("创建通知任务成功,id={}, userId={}", created.getId(), user.getUserId()); |
| | | } |
| | | } |
| | | |
| | | // 6. 分发通知任务 |
| | | if (!notifyTasks.isEmpty()) { |
| | | int successCount = notifyDispatchService.dispatchNotifies(notifyTasks); |
| | | // log.info("旧系统同步转运单通知分发完成,taskId={}, 分发数量={}, 成功数量={}", |
| | | // taskId, notifyTasks.size(), successCount); |
| | | } |
| | | // else { |
| | | // log.info("旧系统同步转运单无需新增通知,taskId={}", taskId); |
| | | // } |
| | | |
| | | // 5. 同时保留原有的微信通知服务(兼容) |
| | | // List<Long> userIds = new ArrayList<>(); |
| | | // for (TaskCreateVO.AssigneeInfo assignee : assignees) { |
| | | // if (assignee != null && assignee.getUserId() != null) { |
| | | // userIds.add(assignee.getUserId()); |
| | | // } |
| | | // } |
| | | // if (!userIds.isEmpty()) { |
| | | // int wxCount = wechatTaskNotifyService.sendTaskNotifyMessage(taskId, userIds); |
| | | // log.info("旧系统同步转运单微信通知发送完成,taskId={}, 成功={}", taskId, wxCount); |
| | | // } |
| | | |
| | | } catch (Exception e) { |
| | | log.error("notifyTransferOrderByWechat发生异常, serviceOrdID={}, dispatchOrdID={}", serviceOrdID, dispatchOrdID, e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 构建旧系统同步转运单的通知内容 |
| | | */ |
| | | private String buildLegacyNotifyContent(String serviceOrdNo, Date serviceOrdCcTime, Map<String, Object> order) { |
| | | StringBuilder content = new StringBuilder(); |
| | | content.append("您有新的转运任务,任务单号:").append(serviceOrdNo); |
| | | |
| | | // 出发时间 |
| | | if (serviceOrdCcTime != null) { |
| | | SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm"); |
| | | content.append(",出发时间:").append(df.format(serviceOrdCcTime)); |
| | | } |
| | | |
| | | // 出发地 |
| | | String departure = MapValueUtils.getStringValue(order, "ServiceOrdTraVia"); |
| | | if (StringUtils.isNotEmpty(departure)) { |
| | | content.append(",出发地:").append(departure); |
| | | } |
| | | |
| | | // 目的地 |
| | | String destination = MapValueUtils.getStringValue(order, "ServiceOrdTraEnd"); |
| | | if (StringUtils.isNotEmpty(destination)) { |
| | | content.append(",目的地:").append(destination); |
| | | } |
| | | |
| | | content.append(",请及时处理。"); |
| | | return content.toString(); |
| | | } |
| | | |
| | | private List<SysUser> getWechatNotifyUsers(Long dispatchOrdID, SysDept dept) { |
| | |
| | | List<SysUser> result = new ArrayList<>(); |
| | | |
| | | List<TaskCreateVO.AssigneeInfo> assignees = queryAssignees(dispatchOrdID); |
| | | if (assignees != null && !assignees.isEmpty()) { |
| | | if (!assignees.isEmpty()) { |
| | | for (TaskCreateVO.AssigneeInfo assigneeInfo : assignees) { |
| | | if (assigneeInfo == null || assigneeInfo.getUserId() == null) { |
| | | continue; |