package com.ycl.platform.service.impl; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ycl.exception.ServiceException; import com.ycl.platform.domain.entity.*; import com.ycl.platform.domain.form.*; import com.ycl.platform.domain.query.*; import com.ycl.platform.domain.vo.DistributeWorkOrderVO; import com.ycl.platform.domain.vo.WorkOrderVO; import com.ycl.platform.domain.vo.WorkOrderYwConditionRecordVO; import com.ycl.platform.domain.vo.screen.ScreenWorkOrderVO; import com.ycl.platform.domain.vo.screen.WorkOrderRegionVO; import com.ycl.platform.domain.vo.screen.WorkOrderTotalVO; import com.ycl.platform.mapper.*; import com.ycl.platform.service.NotifyService; import com.ycl.platform.service.WorkOrderAuditingRecordService; import com.ycl.platform.service.WorkOrderService; import com.ycl.platform.service.YwPointService; import com.ycl.system.Result; import com.ycl.system.domain.SysConfig; import com.ycl.system.mapper.SysConfigMapper; import com.ycl.system.model.LoginUser; import com.ycl.system.page.PageUtil; import com.ycl.utils.DateUtils; import com.ycl.utils.SecurityUtils; import com.ycl.utils.redis.RedisCache; import com.ycl.utils.uuid.IdUtils; import enumeration.general.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.*; import java.util.stream.Collectors; /** * 工单 服务实现类 * * @author xp * @since 2024-03-05 */ @Slf4j @Service @RequiredArgsConstructor public class WorkOrderServiceImpl extends ServiceImpl implements WorkOrderService { private final WorkOrderMapper workOrderMapper; private final YwPointService ywPointService; private final WorkOrderAuditingRecordMapper workOrderAuditingRecordMapper; private final WorkOrderAuditingRecordService workOrderAuditingRecordService; private final WorkOrderYwConditionRecordMapper workOrderYwConditionRecordMapper; private final NotifyService notifyService; private final WorkOrderDistributeRecordMapper workOrderDistributeRecordMapper; private final TMonitorMapper monitorMapper; private final SysConfigMapper configMapper; private final String DISTRIBUTE_LOCK_KEY = "distributeLock"; private final static String IMPORTANT = "important"; @Autowired private RedisCache redisCache; @Override @Transactional(rollbackFor = Exception.class) public Boolean addWaitDistribute(List workOrderList) { int total = workOrderList.size(); workOrderList.stream().filter(item -> { return StringUtils.hasText(item.getSerialNumber()) && Objects.nonNull(item.getStatus()) && StringUtils.hasText(item.getErrorType()); }); List serialNumberList = workOrderList.stream().map(WorkOrder::getSerialNumber).collect(Collectors.toList()); // 查出数据库中国标码对应的未完成的工单 List inDatabaseWorkOrderList = new LambdaQueryChainWrapper<>(baseMapper) .select(WorkOrder::getId, WorkOrder::getSerialNumber, WorkOrder::getStatus, WorkOrder::getErrorType) .in(WorkOrder::getSerialNumber, serialNumberList) .ne(WorkOrder::getStatus, WorkOrderStatusEnum.AUDITING_SUCCESS) .list(); Map mapping = inDatabaseWorkOrderList.stream().collect((Collectors.toMap(WorkOrder::getSerialNumber, workOrder -> workOrder))); List waitAddList = new ArrayList<>(48); Integer updateNum = 0; for (WorkOrder workOrder : workOrderList) { WorkOrder databaseWorkOrder = mapping.get(workOrder.getSerialNumber()); if (Objects.nonNull(databaseWorkOrder)) { String errorType = databaseWorkOrder.getErrorType(); if (workOrder.getErrorType().equals(errorType)) { // 如果,国标码、故障类型都一样,则跳过不处理 continue; } else { // 错误类型不一样,就更新错误类型,并且重置工单状态为待处理 errorType = errorType + "," + workOrder.getErrorType(); databaseWorkOrder.setErrorType(errorType); databaseWorkOrder.setStatus(WorkOrderStatusEnum.DISTRIBUTED); baseMapper.updateById(databaseWorkOrder); updateNum++; // 同时新增一个运维处理信息,表明此工单被调整 TODO } } else { waitAddList.add(workOrder); } } if (CollectionUtils.isEmpty(waitAddList)) { return Boolean.TRUE; } List willAddSerialNumber = waitAddList.stream().map(WorkOrder::getSerialNumber).collect(Collectors.toList()); List pointList = new LambdaQueryChainWrapper<>(ywPointService.getBaseMapper()) .select(YwPoint::getUnitId, YwPoint::getSerialNumber, YwPoint::getImportantTag, YwPoint::getImportantTag, YwPoint::getProvinceTag, YwPoint::getImportantCommandImageTag) .in(YwPoint::getSerialNumber, willAddSerialNumber) .list(); Map pointMapping = pointList.stream().collect(Collectors.toMap(YwPoint::getSerialNumber, point -> point)); // 查出重点点位、普通点位的处理时间 SysConfig important = configMapper.checkConfigKeyUnique("important.wordkorder.time"); SysConfig normal = configMapper.checkConfigKeyUnique("normal.wordkorder.alarm.time"); for (WorkOrder workOrder : waitAddList) { YwPoint point = pointMapping.get(workOrder.getSerialNumber()); workOrder.setWorkOrderNo(IdUtils.timeAddRandomNO(5)); workOrder.setUnitId(Math.toIntExact(point.getUnitId())); if (point.getImportantTag() || point.getImportantCommandImageTag()) { workOrder.setProcessingPeriod(Integer.valueOf(important.getConfigValue())); } else { workOrder.setProcessingPeriod(Integer.valueOf(normal.getConfigValue())); } } this.saveBatch(waitAddList); // 如果是直接下发,添加下发记录 if (WorkOrderStatusEnum.DISTRIBUTED.equals(waitAddList.get(0).getStatus())) { List distributedRecordList = waitAddList.stream().map(item -> { WorkOrderDistributeRecord workOrderDistributeRecord = new WorkOrderDistributeRecord(); workOrderDistributeRecord.setWorkOrderId(item.getId()); workOrderDistributeRecord.setDistributeWay(WorkOrderDistributeWayEnum.DIRECT_DISTRIBUTE); workOrderDistributeRecord.setUserId(1L); return workOrderDistributeRecord; }).collect(Collectors.toList()); workOrderDistributeRecordMapper.insertBatch(distributedRecordList); } log.info("传入工单总数: {},实际添加工单数:{}, 实际修改工单数:{}", total, waitAddList.size(), updateNum); return Boolean.TRUE; } /** * 添加 * @param form * @return */ @Override public Result add(WorkOrderForm form) { WorkOrder entity = WorkOrderForm.getEntityByForm(form, null); entity.setWorkOrderNo(IdUtils.timeAddRandomNO(5)); entity.setCreateTime(DateUtils.getNowDate()); entity.setStatus(WorkOrderStatusEnum.WAIT_DISTRIBUTE); if(baseMapper.insert(entity) > 0) { return Result.ok("添加成功"); } return Result.error("添加失败"); } /** * 修改 * @param form * @return */ @Override public Result update(WorkOrderForm form) { WorkOrder entity = baseMapper.selectById(form.getId()); // 为空抛IllegalArgumentException,做全局异常处理 Assert.notNull(entity, "记录不存在"); BeanUtils.copyProperties(form, entity); if (baseMapper.updateById(entity) > 0) { return Result.ok("修改成功"); } return Result.error("修改失败"); } @Override @Transactional(rollbackFor = Exception.class) public Result auditing(WorkOrderAuditingForm form) { WorkOrder workOrder = baseMapper.selectById(form.getId()); // 工单状态 workOrder.setStatus(form.getAuditingResult()); baseMapper.updateById(workOrder); // 添加一条审核记录 WorkOrderAuditingRecord workOrderAuditingRecord = new WorkOrderAuditingRecord(); workOrderAuditingRecord.setWorkOrderId(workOrder.getId()); workOrderAuditingRecord.setAuditingUser(SecurityUtils.getLoginUser().getUserId().intValue()); workOrderAuditingRecord.setResult(form.getAuditingResult().getDesc()); workOrderAuditingRecord.setRemark(form.getAuditingRemark()); workOrderAuditingRecordMapper.insert(workOrderAuditingRecord); // 添加新通知 Notify notify = Notify.genEntityByUnit(NotifyTypeEnum.WORK_ORDER, form.getAuditingResult().getDesc(), workOrder.getUnitId(), UrgentLevelEnum.WARNING, workOrder.getWorkOrderNo()); notifyService.save(notify); // 同步点位状态 if (form.getAuditingResult() == WorkOrderStatusEnum.AUDITING_SUCCESS) { ywPointService.updateRecovery(Arrays.asList(workOrder.getSerialNumber()), 0); } return Result.ok("操作成功"); } @Override @Transactional(rollbackFor = Exception.class) public Result batchAuditing(WorkOrderBatchAuditingForm form) { // 根据故障类型获取列表 List list = new LambdaQueryChainWrapper<>(baseMapper) .in(WorkOrder::getStatus, WorkOrderStatusEnum.YW_HANDLE.getValue()) .in(WorkOrder::getErrorType, form.getErrorTypes()) .select(WorkOrder::getId, WorkOrder::getUnitId, WorkOrder::getWorkOrderNo) .list(); if (list.isEmpty()) { return Result.error("没有工单可以审核"); } List ids = list.stream().map(WorkOrder::getId).collect(Collectors.toList()); // 工单状态 LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper<>(); lambdaUpdateWrapper.in(WorkOrder::getId, ids); lambdaUpdateWrapper.set(WorkOrder::getStatus, form.getAuditingResult()); baseMapper.update(lambdaUpdateWrapper); // 添加多条审核记录 List workOrderAuditingRecords = new ArrayList<>(); for (Integer id : ids) { WorkOrderAuditingRecord workOrderAuditingRecord = new WorkOrderAuditingRecord(); workOrderAuditingRecord.setWorkOrderId(id); workOrderAuditingRecord.setAuditingUser(SecurityUtils.getLoginUser().getUserId().intValue()); workOrderAuditingRecord.setResult(form.getAuditingResult().getDesc()); workOrderAuditingRecord.setRemark(form.getAuditingRemark()); workOrderAuditingRecords.add(workOrderAuditingRecord); } workOrderAuditingRecordService.saveBatch(workOrderAuditingRecords); // 添加新通知 List notifies = new ArrayList<>(); for (WorkOrder workOrder : list) { Notify notify = Notify.genEntityByUnit(NotifyTypeEnum.WORK_ORDER, form.getAuditingResult().getDesc(), workOrder.getUnitId(), UrgentLevelEnum.WARNING, workOrder.getWorkOrderNo()); notifies.add(notify); } notifyService.saveBatch(notifies); return Result.ok("操作成功"); } @Override @Transactional(rollbackFor = Exception.class) public Result ywCondition(WorkOrderYWConditionForm form) { WorkOrder workOrder = baseMapper.selectById(form.getId()); if (Objects.isNull(workOrder)) { throw new ServiceException("工单不存在"); } // 工单状态 workOrder.setStatus(WorkOrderStatusEnum.YW_HANDLE); workOrder.setYwHandleTime(LocalDateTime.now()); baseMapper.updateById(workOrder); // 添加一条运维情况记录 WorkOrderYwConditionRecord workOrderYwConditionRecord = new WorkOrderYwConditionRecord(); workOrderYwConditionRecord.setWorkOrderId(workOrder.getId()); workOrderYwConditionRecord.setCommitUser(SecurityUtils.getLoginUser().getUserId().intValue()); workOrderYwConditionRecord.setYwCondition(form.getYwCondition()); workOrderYwConditionRecord.setYwProofMaterials(form.getYwProofMaterials()); workOrderYwConditionRecordMapper.insert(workOrderYwConditionRecord); return Result.ok("操作成功"); } @Override public Result selectYwConditionByYwId(Integer id) { List ywConditionList = workOrderYwConditionRecordMapper.selectYwConditionByYwId(id); return Result.ok().data(ywConditionList); } @Override public Result selectYwAuditingListByYwId(String id) { return Result.ok().data( new LambdaQueryChainWrapper<>(workOrderAuditingRecordMapper) .eq(WorkOrderAuditingRecord::getWorkOrderId, id) .orderByAsc(WorkOrderAuditingRecord::getCreateTime) .list()); } @Override public Result ywResult(WorkOrderYWResultForm form) { return null; } @Override public Result checkResult(WorkOrderCheckResultForm form) { return null; } /** * 批量删除 * @param ids * @return */ @Override public Result remove(List ids) { if(baseMapper.deleteBatchIds(ids) > 0) { return Result.ok("删除成功"); } return Result.error("删除失败"); } /** * id删除 * @param id * @return */ @Override public Result removeById(String id) { if(baseMapper.deleteById(id) > 0) { return Result.ok("删除成功"); } return Result.error("删除失败"); } /** * 分页查询 * @param query * @return */ @Override public Result page(WorkOrderQuery query) { IPage page = PageUtil.getPage(query, WorkOrderVO.class); baseMapper.page(page, query); return Result.ok().data(page.getRecords()).total(page.getTotal()); } @Override public Result distributePage(DistributeWorkOrderQuery query) { IPage page = PageUtil.getPage(query, WorkOrderVO.class); baseMapper.distributePage(page, query); page.getRecords().stream().forEach(workOrder -> { if (StringUtils.hasText(workOrder.getPointTag()) && workOrder.getPointTag().contains(IMPORTANT)) { workOrder.setImportant(Boolean.TRUE); } }); return Result.ok().data(page).total(page.getTotal()); } @Override @Transactional public Result distributeFast(DistributeWorkOrderVO data) { // 获取当前时间 LocalDateTime now = LocalDateTime.now(ZoneId.systemDefault()); data.setEnd(now); switch (data.getFastWay()) { case LAST_HALF_HOUR: data.setStart(now.minusMinutes(30)); break; case LAST_HOUR: data.setStart(now.minusHours(1)); break; case LAST_TWO_HOUR: data.setStart(now.minusHours(2)); break; case LAST_DAY: data.setStart(now.minusDays(1)); break; } // 查询符合条件的工单 List list = new LambdaQueryChainWrapper<>(baseMapper) .select(WorkOrder::getSerialNumber, WorkOrder::getSerialNumber) .eq(WorkOrder::getStatus, WorkOrderStatusEnum.WAIT_DISTRIBUTE) .eq(Objects.nonNull(data.getUnitId()), WorkOrder::getUnitId, data.getUnitId()) .eq(WorkOrder::getErrorType, data.getErrorType()) .between(WorkOrder::getCreateTime, data.getStart(), data.getEnd()) .orderByDesc(WorkOrder::getCreateTime) .last("limit " + data.getFastNumLimit()) .list(); List ids = list.stream().map(WorkOrder::getId).toList(); List serialNumberList = list.stream().map(WorkOrder::getSerialNumber).toList(); if (ids.isEmpty()) { return Result.error("没有符合条件的工单"); } if (!getDistributeLock()) { return Result.error("此刻有人下发中,为避免冲突,请稍后重试"); } try { new LambdaUpdateChainWrapper<>(baseMapper) .set(WorkOrder::getStatus, WorkOrderStatusEnum.DISTRIBUTED) .in(WorkOrder::getId, ids) .update(); addDistributeRecord(ids, WorkOrderDistributeWayEnum.FAST_DISTRIBUTE); // 同步点位状态 ywPointService.updateRecovery(serialNumberList, 1); return Result.ok("成功下发" + ids.size() + "条工单"); } catch (Exception e) { return Result.error("操作失败"); } finally { distributeUnLock(); } } @Override @Transactional public Result selectedIdsDistribute(DistributeWorkOrderQuery query) { WorkOrderDistributeWayEnum distributeWayEnum = WorkOrderDistributeWayEnum.SELECTED_DISTRIBUTE; if (!getDistributeLock()) { return Result.error("此刻有人下发中,为避免冲突,请稍后重试"); } try { if (query.getIds().isEmpty()) { query.setIds(new LambdaQueryChainWrapper<>(baseMapper) .eq(WorkOrder::getStatus, WorkOrderStatusEnum.WAIT_DISTRIBUTE) .eq(Objects.nonNull(query.getUnitId()), WorkOrder::getUnitId, query.getUnitId()) .select(WorkOrder::getId) .list() .stream() .map(WorkOrder::getId) .collect(Collectors.toList())); distributeWayEnum = WorkOrderDistributeWayEnum.ALL_DISTRIBUTE; } if (query.getIds().isEmpty()) { return Result.error("没有工单待下发"); } new LambdaUpdateChainWrapper<>(baseMapper) .set(WorkOrder::getStatus, WorkOrderStatusEnum.DISTRIBUTED) .in(WorkOrder::getId, query.getIds()) .update(); addDistributeRecord(query.getIds(), distributeWayEnum); // 同步点位状态 List serialNumberList = new LambdaQueryChainWrapper<>(baseMapper).select(WorkOrder::getSerialNumber).in(WorkOrder::getId, query.getIds()).list().stream().map(WorkOrder::getSerialNumber).toList(); ywPointService.updateRecovery(serialNumberList, 1); return Result.ok("成功下发" + query.getIds().size() + "条工单"); } catch (Exception e) { return Result.error("操作失败"); } finally { distributeUnLock(); } } /** * 申请工单下发锁 * @return 工单下发锁申请结果 */ public synchronized Boolean getDistributeLock() { if (Objects.isNull(redisCache.getCacheObject(DISTRIBUTE_LOCK_KEY))) { redisCache.setCacheObject(DISTRIBUTE_LOCK_KEY, "1"); return true; } else { return false; } } /** * 工单下发锁释放 */ public synchronized void distributeUnLock() { redisCache.deleteObject(DISTRIBUTE_LOCK_KEY); } /** * 添加工单下发记录 * @param ids 工单id */ private void addDistributeRecord(List ids, WorkOrderDistributeWayEnum distributeWay) { LoginUser loginUser = SecurityUtils.getLoginUser(); workOrderDistributeRecordMapper.insertBatch( ids.stream() .map(id -> new WorkOrderDistributeRecord(id, loginUser.getUserId(), distributeWay)) .toList() ); } /** * 根据id查找 * @param id * @return */ @Override public Result detail(String id) { WorkOrder entity = baseMapper.selectById(id); Assert.notNull(entity, "记录不存在"); WorkOrderVO vo = WorkOrderVO.getVoByEntity(entity, null); return Result.ok().data(vo); } /** * 列表 * @return */ @Override public Result all() { List entities = baseMapper.selectList(null); List vos = entities.stream() .map( entity -> WorkOrderVO.getVoByEntity(entity, null) ) .collect(Collectors.toList()); return Result.ok().data(vos); } @Override public Result screenWorkOrder(ScreenQuery query) { ScreenWorkOrderVO screen = baseMapper.screenWorkOrder(query); return Result.ok().data(screen); } @Override public Map home(HomeQuery monitorQuery) { Map dataMap = new HashMap<>(); Map data1 = new HashMap<>(); Map data2 = new HashMap<>(); Map data3 = new HashMap<>(); List> home = baseMapper.home(monitorQuery); if (ObjectUtils.isNotEmpty(home)) { for (Map map : home) { if (Objects.nonNull(map.get("dateType")) && StringUtils.hasText(map.get("dateType").toString())) { data1.put(map.get("dateType").toString(), map.get("num1")); data2.put(map.get("dateType").toString(), map.get("num2")); data3.put(map.get("dateType").toString(), map.get("num3")); } } dataMap.put("name", home.get(0).get("name")); } dataMap.put("complete", data1); dataMap.put("waiting", data2); dataMap.put("pending", data3); return dataMap; } @Override public WorkOrderTotalVO workOrderTotal(DashboardQuery dashboardQuery) { return baseMapper.workOrderTotal(dashboardQuery); } @Override public List workOrderRegion(DashboardQuery dashboardQuery) { return baseMapper.workOrderRegion(dashboardQuery); } }