package com.ruoyi.system.service.impl;
|
|
import com.ruoyi.common.config.LegacySystemConfig;
|
import com.ruoyi.system.domain.DispatchOrd;
|
import com.ruoyi.system.domain.SysTask;
|
import com.ruoyi.system.domain.SysTaskEmergency;
|
import com.ruoyi.system.domain.enums.TaskStatus;
|
import com.ruoyi.system.mapper.SysTaskMapper;
|
import com.ruoyi.system.service.IDispatchOrdService;
|
import com.ruoyi.system.service.ISysTaskEmergencyService;
|
import com.ruoyi.system.service.ITaskStatusSyncService;
|
import com.ruoyi.system.utils.TaskStatusConverter;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.util.*;
|
|
/**
|
* 任务状态同步Service业务层处理
|
* 负责从旧系统同步任务状态到新系统
|
*
|
* @author ruoyi
|
* @date 2024-01-16
|
*/
|
@Service
|
public class TaskStatusSyncServiceImpl implements ITaskStatusSyncService {
|
|
private static final Logger log = LoggerFactory.getLogger(TaskStatusSyncServiceImpl.class);
|
|
@Autowired
|
private LegacySystemConfig legacyConfig;
|
|
@Autowired
|
private SysTaskMapper sysTaskMapper;
|
|
@Autowired
|
private ISysTaskEmergencyService sysTaskEmergencyService;
|
|
@Autowired
|
private IDispatchOrdService dispatchOrdService;
|
|
/**
|
* 从旧系统同步单个任务状态到新系统
|
*
|
* @param taskId 任务ID
|
* @return 是否同步成功
|
*/
|
@Override
|
@Transactional
|
public boolean syncTaskStatusFromLegacy(Long taskId) {
|
if (!legacyConfig.isEnabled()) {
|
log.info("旧系统同步已禁用,跳过状态同步,任务ID: {}", taskId);
|
return false;
|
}
|
|
try {
|
// 查询任务信息
|
SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
|
if (task == null) {
|
log.error("任务不存在,任务ID: {}", taskId);
|
return false;
|
}
|
|
// 只同步急救转运任务
|
if (!"EMERGENCY_TRANSFER".equals(task.getTaskType())) {
|
log.info("非急救转运任务,跳过状态同步,任务ID: {}", taskId);
|
return false;
|
}
|
|
// 查询急救转运扩展信息
|
SysTaskEmergency emergency = sysTaskEmergencyService.selectSysTaskEmergencyByTaskId(taskId);
|
if (emergency == null) {
|
log.error("急救转运扩展信息不存在,任务ID: {}", taskId);
|
return false;
|
}
|
|
// 必须已经同步过调度单
|
if (emergency.getLegacyDispatchOrdId() == null || emergency.getLegacyDispatchOrdId() <= 0) {
|
log.warn("调度单未同步,无法同步状态,任务ID: {}", taskId);
|
return false;
|
}
|
|
// 查询旧系统状态(直接查询SQL Server数据库)
|
Integer legacyStatus = dispatchOrdService.selectDispatchOrdStateByID(emergency.getLegacyDispatchOrdId());
|
if (legacyStatus == null) {
|
log.error("查询旧系统状态失败,任务ID: {}, DispatchOrdID: {}", taskId, emergency.getLegacyDispatchOrdId());
|
return false;
|
}
|
|
// 调用内部方法同步状态
|
return syncTaskStatusWithLegacyState(taskId, legacyStatus);
|
|
} catch (Exception e) {
|
log.error("同步任务状态异常,任务ID: {}", taskId, e);
|
return false;
|
}
|
}
|
|
/**
|
* 批量同步已同步调度单的任务状态(从旧系统到新系统)
|
* 使用分页查询,批量查询SQL Server数据库,减少网络请求次数
|
*
|
* @return 成功同步的任务数量
|
*/
|
@Override
|
public int batchSyncTaskStatusFromLegacy() {
|
if (!legacyConfig.isEnabled()) {
|
log.info("旧系统同步已禁用");
|
return 0;
|
}
|
|
try {
|
int totalSuccessCount = 0;
|
int pageSize = 200; // 每页200条
|
int offset = 0;
|
|
while (true) {
|
// 1. 分页查询新系统中需要同步状态的任务(已同步调度单且状态未完成)
|
List<SysTaskEmergency> syncedTasks = sysTaskEmergencyService.selectSyncedTasksForStatusUpdate(offset, pageSize);
|
|
if (syncedTasks == null || syncedTasks.isEmpty()) {
|
log.info("没有更多需要同步状态的任务,offset: {}", offset);
|
break; // 没有更多数据,退出循环
|
}
|
|
log.info("开始同步状态第 {} 页,任务数量: {}", (offset / pageSize) + 1, syncedTasks.size());
|
|
// 2. 提取调度单ID列表
|
List<Long> dispatchOrdIDs = new ArrayList<>();
|
Map<Long, SysTaskEmergency> dispatchIdToTaskMap = new HashMap<>();
|
|
for (SysTaskEmergency emergency : syncedTasks) {
|
Long dispatchOrdId = emergency.getLegacyDispatchOrdId();
|
if (dispatchOrdId != null && dispatchOrdId > 0) {
|
dispatchOrdIDs.add(dispatchOrdId);
|
dispatchIdToTaskMap.put(dispatchOrdId, emergency);
|
}
|
}
|
|
if (dispatchOrdIDs.isEmpty()) {
|
log.warn("本页没有有效的调度单ID");
|
offset += pageSize;
|
continue;
|
}
|
|
// 3. 批量查询旧系统调度单状态(直接查询SQL Server数据库)
|
List<DispatchOrd> dispatchOrds = dispatchOrdService.selectDispatchOrdStatesByIDs(dispatchOrdIDs);
|
|
if (dispatchOrds == null || dispatchOrds.isEmpty()) {
|
log.warn("未查询到旧系统调度单状态");
|
offset += pageSize;
|
continue;
|
}
|
|
// 4. 构建调度单ID到状态的映射
|
Map<Long, Integer> dispatchIdToStateMap = new HashMap<>();
|
for (DispatchOrd dispatchOrd : dispatchOrds) {
|
try {
|
Long dispatchOrdId = Long.parseLong(dispatchOrd.getDispatchOrdID());
|
Integer dispatchOrdState = Integer.parseInt(dispatchOrd.getDispatchOrdState());
|
if (dispatchOrdState != null) {
|
dispatchIdToStateMap.put(dispatchOrdId, dispatchOrdState);
|
}
|
} catch (NumberFormatException e) {
|
log.error("解析调度单ID失败: {}", dispatchOrd.getDispatchOrdID(), e);
|
}
|
}
|
|
// 5. 遍历任务,同步状态
|
int pageSuccessCount = 0;
|
for (Map.Entry<Long, SysTaskEmergency> entry : dispatchIdToTaskMap.entrySet()) {
|
Long dispatchOrdId = entry.getKey();
|
SysTaskEmergency emergency = entry.getValue();
|
|
// 获取旧系统状态
|
Integer legacyStatus = dispatchIdToStateMap.get(dispatchOrdId);
|
if (legacyStatus == null) {
|
log.warn("未找到调度单状态,DispatchOrdID: {}", dispatchOrdId);
|
continue;
|
}
|
|
// 同步单个任务状态
|
boolean result = syncTaskStatusWithLegacyState(emergency.getTaskId(), legacyStatus);
|
if (result) {
|
pageSuccessCount++;
|
}
|
}
|
|
totalSuccessCount += pageSuccessCount;
|
log.info("状态第 {} 页同步完成,总数: {}, 成功: {}",
|
(offset / pageSize) + 1, syncedTasks.size(), pageSuccessCount);
|
|
// 如果本页数据少于每页大小,说明已经是最后一页
|
if (syncedTasks.size() < pageSize) {
|
log.info("已到达最后一页,状态同步结束");
|
break;
|
}
|
|
offset += pageSize; // 下一页
|
}
|
|
log.info("批量同步任务状态完成,总成功数: {}", totalSuccessCount);
|
return totalSuccessCount;
|
|
} catch (Exception e) {
|
log.error("批量同步任务状态异常", e);
|
return 0;
|
}
|
}
|
|
/**
|
* 同步单个任务状态(已知旧系统状态码)
|
* 增加状态对比逻辑:当旧系统状态落后于新系统状态时,不进行同步
|
*
|
* @param taskId 任务ID
|
* @param legacyStatus 旧系统状态码
|
* @return 是否成功
|
*/
|
@Transactional
|
private boolean syncTaskStatusWithLegacyState(Long taskId, Integer legacyStatus) {
|
try {
|
// 查询任务信息
|
SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId);
|
if (task == null) {
|
log.error("任务不存在,任务ID: {}", taskId);
|
return false;
|
}
|
|
// 转换为新系统状态
|
TaskStatus newStatus = TaskStatusConverter.convertFromLegacyStatus(legacyStatus);
|
if (newStatus == null) {
|
log.debug("旧系统状态码 > 10 或无法转换,跳过同步,任务ID: {}, 状态码: {} ({})",
|
taskId, legacyStatus, TaskStatusConverter.getLegacyStatusDescription(legacyStatus));
|
return false;
|
}
|
|
// 检查状态是否变化
|
if (newStatus.getCode().equals(task.getTaskStatus())) {
|
log.debug("任务状态未变化,任务ID: {}, 当前状态: {}", taskId, newStatus.getInfo());
|
return true;
|
}
|
|
// 比较新旧系统状态的优先级,防止状态倒退
|
TaskStatus currentStatus = TaskStatus.getByCode(task.getTaskStatus());
|
if (currentStatus != null && !shouldSyncStatus(currentStatus, newStatus, legacyStatus)) {
|
log.info("【旧系统更新到新系统】 旧系统状态落后于新系统状态,跳过同步,任务ID: {}, 新系统状态: {} ({}), 旧系统状态: {} ({})",
|
taskId, task.getTaskStatus(), currentStatus.getInfo(),
|
newStatus.getCode(), TaskStatusConverter.getLegacyStatusDescription(legacyStatus));
|
return false;
|
}
|
|
// 更新任务状态
|
String oldStatus = task.getTaskStatus();
|
task.setTaskStatus(newStatus.getCode());
|
|
// 根据状态设置时间
|
Date now = new Date();
|
switch (newStatus) {
|
case DEPARTING:
|
case ARRIVED:
|
case IN_PROGRESS:
|
// 如果实际开始时间为空,设置实际开始时间
|
if (task.getActualStartTime() == null) {
|
task.setActualStartTime(now);
|
}
|
break;
|
case COMPLETED:
|
case CANCELLED:
|
// 设置实际结束时间
|
if (task.getActualEndTime() == null) {
|
task.setActualEndTime(now);
|
}
|
// 如果实际开始时间为空,也设置一下
|
if (task.getActualStartTime() == null) {
|
task.setActualStartTime(now);
|
}
|
break;
|
default:
|
break;
|
}
|
|
sysTaskMapper.updateSysTask(task);
|
|
log.info("任务状态同步成功,任务ID: {}, 旧状态: {}, 新状态: {}, 旧系统状态码: {} ({})",
|
taskId, oldStatus, newStatus.getCode(), legacyStatus,
|
TaskStatusConverter.getLegacyStatusDescription(legacyStatus));
|
|
return true;
|
|
} catch (Exception e) {
|
log.error("同步任务状态异常,任务ID: {}", taskId, e);
|
return false;
|
}
|
}
|
|
/**
|
* 判断是否应该同步状态
|
* 规则:旧系统状态码需要大于等于新系统当前状态对应的旧系统状态码
|
* 防止因为时间差导致新系统状态比旧系统更新,而被旧系统的旧状态覆盖
|
*
|
* @param currentStatus 新系统当前状态
|
* @param targetStatus 旧系统转换后的目标状态
|
* @param legacyStatusCode 旧系统状态码
|
* @return true-应该同步,false-不应该同步
|
*/
|
private boolean shouldSyncStatus(TaskStatus currentStatus, TaskStatus targetStatus, Integer legacyStatusCode) {
|
// 获取新系统当前状态对应的旧系统状态码
|
Integer currentLegacyCode = TaskStatusConverter.convertToLegacyStatus(currentStatus);
|
|
if (currentLegacyCode == null) {
|
// 如果当前状态无法转换为旧系统状态码,允许同步
|
log.warn("新系统当前状态无法转换为旧系统状态码,允许同步,当前状态: {}", currentStatus.getCode());
|
return true;
|
}
|
|
// 比较状态码大小
|
// 旧系统状态码 >= 新系统当前状态对应的旧系统状态码,才允许同步
|
// 例如:新系统已经是"出发中"(4),旧系统还是"待处理"(3),则不同步
|
// 新系统是"出发中"(4),旧系统是"已到达"(5)或"出发中"(4),则同步
|
boolean shouldSync = legacyStatusCode >= currentLegacyCode;
|
|
if (!shouldSync) {
|
log.debug("状态对比:旧系统状态码({}) < 新系统当前状态对应码({})",
|
legacyStatusCode, currentLegacyCode);
|
}
|
|
return shouldSync;
|
}
|
}
|