wlzboy
2025-12-04 af8cab142a6b15c06e131a8474574dd5b00df982
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
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;
    }
}