| New file |
| | |
| | | package com.ruoyi.system.service.impl; |
| | | |
| | | import com.ruoyi.common.core.domain.AjaxResult; |
| | | import com.ruoyi.common.core.domain.entity.SysDept; |
| | | import com.ruoyi.system.domain.VehicleInfo; |
| | | import com.ruoyi.system.domain.VehicleSyncDTO; |
| | | import com.ruoyi.system.mapper.SysDeptMapper; |
| | | import com.ruoyi.system.service.IVehicleInfoService; |
| | | import com.ruoyi.system.service.IVehicleSyncDataService; |
| | | import com.ruoyi.system.service.IVehicleSyncService; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | 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.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 车辆同步服务实现 |
| | | * |
| | | * 职责:将从 SQL Server 查询到的车辆数据同步到 MySQL |
| | | * |
| | | * 数据流向:接收 DTO → 同步到 MySQL |
| | | * |
| | | * @author ruoyi |
| | | * @date 2025-10-20 |
| | | */ |
| | | @Service |
| | | public class VehicleSyncServiceImpl implements IVehicleSyncService |
| | | { |
| | | private static final Logger log = LoggerFactory.getLogger(VehicleSyncServiceImpl.class); |
| | | |
| | | @Autowired |
| | | private IVehicleInfoService vehicleInfoService; |
| | | |
| | | @Autowired |
| | | private SysDeptMapper sysDeptMapper; |
| | | |
| | | |
| | | /** |
| | | * 同步车辆数据到MySQL |
| | | * |
| | | * @param vehicles 从SQL Server查询的车辆列表 |
| | | * @return 同步结果 |
| | | */ |
| | | @Override |
| | | @Transactional |
| | | public AjaxResult syncVehicles(List<VehicleSyncDTO> vehicles) |
| | | { |
| | | if (vehicles == null || vehicles.isEmpty()) |
| | | { |
| | | return AjaxResult.error("车辆数据为空,无法同步"); |
| | | } |
| | | |
| | | try |
| | | { |
| | | log.info("开始同步 {} 条车辆数据到 MySQL...", vehicles.size()); |
| | | |
| | | int insertCount = 0; |
| | | int updateCount = 0; |
| | | int skipCount = 0; |
| | | Map<String, String> errorMessages = new HashMap<>(); |
| | | |
| | | for (VehicleSyncDTO vehicleDTO : vehicles) |
| | | { |
| | | try |
| | | { |
| | | // 提取车牌号(去除括号中的内容) |
| | | String plateNumber = extractPlateNumber(vehicleDTO.getCarLicense()); |
| | | |
| | | if (StringUtils.isBlank(plateNumber)) |
| | | { |
| | | log.warn("车辆 CarID={} 车牌号为空,跳过同步", vehicleDTO.getCarId()); |
| | | skipCount++; |
| | | continue; |
| | | } |
| | | |
| | | // 查询车辆是否存在 |
| | | VehicleInfo existingVehicle = findVehicleByPlateNumber(plateNumber); |
| | | |
| | | // 解析部门信息 |
| | | Long deptId = parseDeptIdFromCarOrdClass(vehicleDTO.getCarOrdClass()); |
| | | |
| | | if (existingVehicle != null) |
| | | { |
| | | // 更新车辆信息 |
| | | existingVehicle.setCarId(vehicleDTO.getCarId()); |
| | | existingVehicle.setDeptId(deptId); |
| | | // 可以选择是否更新其他字段 |
| | | vehicleInfoService.updateVehicleInfo(existingVehicle); |
| | | updateCount++; |
| | | log.debug("更新车辆: {} (CarID={}), 部门ID={}", plateNumber, vehicleDTO.getCarId(), deptId); |
| | | } |
| | | else |
| | | { |
| | | // 新增车辆信息 |
| | | VehicleInfo newVehicle = new VehicleInfo(); |
| | | newVehicle.setVehicleNo(plateNumber); |
| | | newVehicle.setCarId(vehicleDTO.getCarId()); |
| | | newVehicle.setDeptId(deptId); |
| | | newVehicle.setStatus("0"); |
| | | newVehicle.setPlatformCode("LEGACY"); // 标记为旧系统同步 |
| | | newVehicle.setRemark("从旧系统同步,CarID: " + vehicleDTO.getCarId()); |
| | | vehicleInfoService.insertVehicleInfo(newVehicle); |
| | | insertCount++; |
| | | log.debug("新增车辆: {} (CarID={}), 部门ID={}", plateNumber, vehicleDTO.getCarId(), deptId); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | String errorMsg = String.format("同步车辆 CarID=%d 失败: %s", |
| | | vehicleDTO.getCarId(), e.getMessage()); |
| | | log.error(errorMsg, e); |
| | | errorMessages.put("CarID_" + vehicleDTO.getCarId(), errorMsg); |
| | | } |
| | | } |
| | | |
| | | String resultMsg = String.format( |
| | | "车辆同步完成 - 新增: %d, 更新: %d, 跳过: %d, 失败: %d", |
| | | insertCount, updateCount, skipCount, errorMessages.size()); |
| | | |
| | | log.info(resultMsg); |
| | | |
| | | Map<String, Object> result = new HashMap<>(); |
| | | result.put("insertCount", insertCount); |
| | | result.put("updateCount", updateCount); |
| | | result.put("skipCount", skipCount); |
| | | result.put("errorCount", errorMessages.size()); |
| | | result.put("errors", errorMessages); |
| | | |
| | | if (errorMessages.isEmpty()) |
| | | { |
| | | return AjaxResult.success(resultMsg, result); |
| | | } |
| | | else |
| | | { |
| | | return AjaxResult.warn(resultMsg, result); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | log.error("同步车辆数据到 MySQL 失败", e); |
| | | return AjaxResult.error("同步失败: " + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 提取车牌号(去除括号中的内容) |
| | | * 例如:浙A12345(奔驰) -> 浙A12345 |
| | | * |
| | | * @param carLicense 原始车牌号 |
| | | * @return 提取后的车牌号 |
| | | */ |
| | | private String extractPlateNumber(String carLicense) |
| | | { |
| | | if (StringUtils.isBlank(carLicense)) |
| | | { |
| | | return null; |
| | | } |
| | | |
| | | // 去除空格 |
| | | String license = carLicense.trim(); |
| | | |
| | | // 查找左括号位置(支持中文和英文括号) |
| | | int leftBracketIndex = license.indexOf('('); |
| | | int leftBracketIndexCn = license.indexOf('('); |
| | | |
| | | // 取最小的有效括号位置 |
| | | int bracketIndex = -1; |
| | | if (leftBracketIndex >= 0 && leftBracketIndexCn >= 0) |
| | | { |
| | | bracketIndex = Math.min(leftBracketIndex, leftBracketIndexCn); |
| | | } |
| | | else if (leftBracketIndex >= 0) |
| | | { |
| | | bracketIndex = leftBracketIndex; |
| | | } |
| | | else if (leftBracketIndexCn >= 0) |
| | | { |
| | | bracketIndex = leftBracketIndexCn; |
| | | } |
| | | |
| | | // 如果找到括号,截取括号前的部分;否则返回原字符串 |
| | | if (bracketIndex > 0) |
| | | { |
| | | return license.substring(0, bracketIndex).trim(); |
| | | } |
| | | |
| | | return license; |
| | | } |
| | | |
| | | /** |
| | | * 根据车牌号查找车辆(模糊匹配) |
| | | * |
| | | * @param plateNumber 车牌号 |
| | | * @return 车辆信息 |
| | | */ |
| | | private VehicleInfo findVehicleByPlateNumber(String plateNumber) |
| | | { |
| | | // 先尝试精确匹配 |
| | | VehicleInfo vehicle = vehicleInfoService.selectVehicleInfoByPlateNumber(plateNumber); |
| | | |
| | | if (vehicle != null) |
| | | { |
| | | return vehicle; |
| | | } |
| | | |
| | | // 如果精确匹配失败,尝试模糊匹配(查询所有车辆,找到包含该车牌号的) |
| | | VehicleInfo query = new VehicleInfo(); |
| | | List<VehicleInfo> allVehicles = vehicleInfoService.selectVehicleInfoList(query); |
| | | |
| | | for (VehicleInfo v : allVehicles) |
| | | { |
| | | if (StringUtils.isNotBlank(v.getVehicleNo())) |
| | | { |
| | | // 如果数据库中的车牌号包含查询的车牌号,或查询的车牌号包含数据库中的车牌号 |
| | | String dbPlateNumber = extractPlateNumber(v.getVehicleNo()); |
| | | if (plateNumber.contains(dbPlateNumber) || dbPlateNumber.contains(plateNumber)) |
| | | { |
| | | return v; |
| | | } |
| | | } |
| | | } |
| | | |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 从 CarOrdClass 解析部门ID,并转换为分公司ID |
| | | * CarOrdClass格式可能是:ZB、HB.TI等 |
| | | * 需要拆分并在sys_dept中匹配dispatch_order_class字段 |
| | | * |
| | | * @param carOrdClass 车辆单据类型编码 |
| | | * @return 分公司ID,如果未找到返回null |
| | | */ |
| | | private Long parseDeptIdFromCarOrdClass(String carOrdClass) |
| | | { |
| | | if (StringUtils.isBlank(carOrdClass)) |
| | | { |
| | | log.debug("CarOrdClass为空,无法解析部门"); |
| | | return null; |
| | | } |
| | | |
| | | // 拆分CarOrdClass,可能的分隔符:. , 空格 |
| | | String[] codes = carOrdClass.split("[.,\\s]+"); |
| | | |
| | | for (String code : codes) |
| | | { |
| | | if (StringUtils.isBlank(code)) |
| | | { |
| | | continue; |
| | | } |
| | | |
| | | code = code.trim(); |
| | | |
| | | // 查询匹配dispatch_order_class的部门 |
| | | SysDept dept = findDeptByDispatchOrderClass(code); |
| | | if (dept != null) |
| | | { |
| | | log.debug("通过dispatch_order_class='{}' 找到部门: {} (ID={})", |
| | | code, dept.getDeptName(), dept.getDeptId()); |
| | | |
| | | // 将部门ID转换为分公司ID |
| | | Long branchCompanyId = sysDeptMapper.selectBranchCompanyIdByDeptId(dept.getDeptId()); |
| | | if (branchCompanyId != null) |
| | | { |
| | | log.debug("将部门ID {} 转换为分公司ID: {}", dept.getDeptId(), branchCompanyId); |
| | | return branchCompanyId; |
| | | } |
| | | else |
| | | { |
| | | log.warn("部门ID {} 无法转换为分公司ID,可能是总公司或数据异常", dept.getDeptId()); |
| | | return null; |
| | | } |
| | | } |
| | | } |
| | | |
| | | log.warn("未找到匹配CarOrdClass='{}' 的部门", carOrdClass); |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 根据dispatch_order_class查询部门 |
| | | * |
| | | * @param dispatchOrderClass 调度单编码 |
| | | * @return 部门信息 |
| | | */ |
| | | private SysDept findDeptByDispatchOrderClass(String dispatchOrderClass) |
| | | { |
| | | if (StringUtils.isBlank(dispatchOrderClass)) |
| | | { |
| | | return null; |
| | | } |
| | | |
| | | try |
| | | { |
| | | SysDept query = new SysDept(); |
| | | query.setDispatchOrderClass(dispatchOrderClass); |
| | | List<SysDept> depts = sysDeptMapper.selectDeptList(query); |
| | | |
| | | if (depts != null && !depts.isEmpty()) |
| | | { |
| | | // 返回第一个匹配的部门 |
| | | return depts.get(0); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | log.error("查询dispatch_order_class='{}' 的部门失败", dispatchOrderClass, e); |
| | | } |
| | | |
| | | return null; |
| | | } |
| | | } |