package com.estate.expert.admin.service.impl; import com.alibaba.excel.util.StringUtils; import com.estate.expert.admin.domain.business.device.Device; import com.estate.expert.admin.domain.business.device.DeviceType; import com.estate.expert.admin.domain.common.mapper.EntityRefMapper; import com.estate.expert.admin.domain.exam.eval.fuzzy.EvalFuzzyResultRepository; import com.estate.expert.admin.domain.exam.eval.score.EvalScoreResultRepository; import com.estate.expert.admin.domain.exam.record.error.ErrorRecord; import com.estate.expert.admin.domain.exam.record.error.ErrorRecordRepository; import com.estate.expert.admin.domain.exam.record.warning.WarningRecordRepository; import com.estate.expert.admin.domain.exam.task.check.CheckTask; import com.estate.expert.admin.domain.exam.task.check.CheckTaskDto; import com.estate.expert.admin.domain.exam.task.check.CheckTaskRepository; import com.estate.expert.admin.domain.exam.task.check.CheckTaskState; import com.estate.expert.admin.domain.exam.task.pass.ByPassInfoDto; import com.estate.expert.admin.domain.exam.task.pass.ByPassInfoMapper; import com.estate.expert.admin.domain.exam.task.review.ReviewTaskDto; import com.estate.expert.admin.domain.exam.task.review.ReviewTaskMapper; import com.estate.expert.admin.domain.plan.Plan; import com.estate.expert.admin.domain.project.Project; import com.estate.expert.admin.domain.standard.hierachy.HierarchyData; import com.estate.expert.admin.domain.standard.model.device.DeviceModel; import com.estate.expert.admin.domain.standard.model.system.SysModel; import com.estate.expert.admin.domain.standard.problem.Problem; import com.estate.expert.admin.domain.user.User; import com.estate.expert.admin.domain.user.UserDto; import com.estate.expert.admin.enums.BizResultCode; import com.estate.expert.admin.service.*; import com.estate.expert.admin.service.common.CrudServiceBaseImpl; import com.estate.expert.admin.service.expert.DeviceExpertService; import com.estate.expert.admin.service.expert.SysExpertService; import com.estate.expert.admin.service.model.DeviceModelService; import com.estate.expert.admin.service.model.SystemModelService; import com.estate.expert.admin.utils.tree.SimpleTreeRoot; import com.estate.expert.admin.utils.tree.TreeNode; import com.estate.expert.admin.utils.tree.TreeRoot; import com.estate.expert.admin.utils.tree.helper.TreeHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import javax.annotation.Resource; import javax.lang.model.type.NullType; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; /** * 项目检查任务服务实现 * 这里面主要分为几个部分 * 1. 检查任务的增删改查 * 2. 任务的状态变更 * 3. 复查任务的增删改查 * 4. 检查记录创建时的相关数据获取(系统模型、设备模型、团队成员) */ @Service public class CheckTaskServiceImpl extends CrudServiceBaseImpl implements CheckTaskService { private static final Logger log = LoggerFactory.getLogger(CheckTaskServiceImpl.class); @Resource private CheckTaskRepository repository; @Resource private PlanService planService; @Resource private ProjectService projectService; @Resource private SysExpertService sysExpertService; @Resource private DeviceExpertService deviceExpertService; @Resource private DeviceUsageService deviceUsageService; @Resource private SystemModelService systemModelService; @Resource private DeviceModelService deviceModelService; @Resource private ByPassInfoMapper byPassInfoMapper; @Resource private UserService userService; @Resource private ReviewTaskMapper reviewTaskMapper; @Resource private EntityRefMapper entityRefMapper; @Resource private ErrorRecordRepository errorRecordRepository; @Resource private WarningRecordRepository warningRecordRepository; @Resource private ProjectInfoService projectInfoService; @Resource private EvalScoreResultRepository evalScoreResultRepository; @Resource private EvalFuzzyResultRepository evalFuzzyResultRepository; @Override public CheckTaskDto toDto(CheckTask entity) { var dto = super.toDto(entity); dto.setClient(entityRefMapper.toReference(entity.getProject().getClient())); return dto; } @Override public List listAvailableTasks(Integer planId, String keyword) { var plan = planService.get(planId); BizResultCode.PLAN_NOT_FOUND.check(plan == null); var checkTasks = repository.findAllByPlanIdAndDeleted(planId, false); var newTasks = new ArrayList(); var projects = projectService.listByClient(plan.getClient().getId()); for(var project : projects) { var checkTask = createTask(plan, project, checkTasks); if(checkTask != null) { newTasks.add(checkTask); } } checkTasks.addAll(newTasks); if(StringUtils.isNotBlank(keyword)) { checkTasks = checkTasks.stream().filter(task -> task.getProject().getName().contains(keyword)).collect(Collectors.toList()); } return toDto(checkTasks); } @Override public List myTasks(Integer userId, Integer planId) { var checkTasks = repository.listMyTasks(userId, planId); return toDto(checkTasks); } @Override public List myTodoTasks(Integer userId) { var checkTasks = repository.listMyToDoTasks(userId); return toDto(checkTasks); } @Override public List listExistTasks(Integer planId) { return repository.findAllByPlanIdAndDeleted(planId, false); } @Override public CheckTask save(CheckTask entity) { var res = super.save(entity); // 保存任务后更新计划状态 planService.updateState(res.getPlan().getId()); return res; } // 检查计划和项目已经有任务 // 如果没有则创建一个任务 private CheckTask createTask(Plan plan, Project project, List checkTasks) { for(var checkTask : checkTasks) { if(checkTask.getPlan().getId().equals(plan.getId()) && checkTask.getProject().getId().equals(project.getId())) { return null; } } var checkTask = new CheckTask(); checkTask.setId(-Math.abs(UUID.randomUUID().hashCode())); checkTask.setPlan(plan); checkTask.setProject(project); checkTask.setState(CheckTaskState.Init); return checkTask; } @Override public List listClosedTasks(Integer planId) { return repository.listClosedTasks(planId); } @Override public List listClosedTasks(List planIds) { return repository.listClosedTasks(planIds); } @Override public CheckTask add(User creator, CheckTask entity) { var task = repository.getFirstByPlanIdAndProjectIdAndDeleted(entity.getPlan().getId(), entity.getProject().getId(), false); BizResultCode.TASK_ALREADY_EXIST.check(task != null); BizResultCode.DRIVER_CAR_NOT_MATCH.check( entity.getDrivers() != null && entity.getCars() != null && entity.getDrivers().size() != entity.getCars().size()); entity.setState(CheckTaskState.Published); entity.setName(UUID.randomUUID().toString()); return super.add(creator, entity); } @Override public CheckTask edit(CheckTask entity) { BizResultCode.TASK_STATUS_ERROR.check(entity.getState() != CheckTaskState.Init && entity.getState() != CheckTaskState.Rejected && entity.getState() != CheckTaskState.EXECUTING && entity.getState() != CheckTaskState.Published); return super.edit(entity); } @Override public CheckTask edit(CheckTaskDto dto) { // 如果传了projectId和addressInfo,更新项目地址 if (dto.getProjectId() != null && dto.getAddressInfo() != null) { var project = projectService.get(dto.getProjectId()); if (project != null) { project.setAddressInfo(dto.getAddressInfo()); projectService.edit(project); } } return super.edit(dto); } @Override public void close(Integer id) { var checkTask = get(id); BizResultCode.TASK_NOT_FOUND.check(checkTask == null); BizResultCode.TASK_STATUS_ERROR.check(checkTask.getState() != CheckTaskState.EXECUTING && checkTask.getState() != CheckTaskState.Rejected && checkTask.getState() != CheckTaskState.Published); checkTask.setState(CheckTaskState.Finished); //关闭项目的时候,关联项目最后一条信息到检查任务上,不管是谁添加的,用于出报告 checkTask.setProjectInfo(projectInfoService.latest(checkTask.getProject().getId())); save(checkTask); } @Override protected void beforeDelete(CheckTask entity) { // 删除任务的时候,删除所有的检查记录 var systemErrors = errorRecordRepository.listSystemErrors(entity.getId()); var deviceErrors = errorRecordRepository.listDeviceErrors(entity.getId()); systemErrors.addAll(deviceErrors); systemErrors.forEach(errorRecord -> { errorRecord.setDeleted(true); }); if(!systemErrors.isEmpty()) errorRecordRepository.saveAll(systemErrors); // 删除任务的时候,删除所有的正确做法 var warnings = warningRecordRepository.list(entity.getId()); warnings.forEach(warningRecord -> { warningRecord.setDeleted(true); }); if(!warnings.isEmpty()) warningRecordRepository.saveAll(warnings); // 删除任务的时候,删除评分结果 var srs = evalScoreResultRepository.listByCheckTask(entity.getId()); srs.forEach(evalScoreResult -> { evalScoreResult.setDeleted(true); }); if(!srs.isEmpty()) { evalScoreResultRepository.saveAll(srs); } // 删除任务的时候,删除模糊评分结果 var frs = evalFuzzyResultRepository.listByCheckTask(entity.getId()); frs.forEach(evalFuzzyResult -> { evalFuzzyResult.setDeleted(true); }); if(!frs.isEmpty()) evalFuzzyResultRepository.saveAll(frs); } @Override public void deleteAllById(Iterable request) { super.deleteAllById(request); } @Override public void reject(Integer id) { var checkTask = get(id); BizResultCode.TASK_NOT_FOUND.check(checkTask == null); BizResultCode.TASK_STATUS_ERROR.check(checkTask.getState() != CheckTaskState.Finished); checkTask.setState(CheckTaskState.Rejected); save(checkTask); } @Override public ByPassInfoDto getByPassInfo(Integer checkTaskId) { var checkTask = get(checkTaskId); BizResultCode.TASK_NOT_FOUND.check(checkTask == null); return byPassInfoMapper.toDto(checkTask.getByPassInfo()); } @Override public void setByPassInfo(Integer checkTaskId, ByPassInfoDto byPassInfo) { var checkTask = get(checkTaskId); BizResultCode.TASK_NOT_FOUND.check(checkTask == null); BizResultCode.TASK_STATUS_ERROR.check(checkTask.getState() != CheckTaskState.Published && checkTask.getState() != CheckTaskState.Rejected && checkTask.getState() != CheckTaskState.EXECUTING); var oldByPassInfo = checkTask.getByPassInfo(); if(oldByPassInfo != null) { byPassInfoMapper.partialUpdate(byPassInfo, oldByPassInfo); }else{ oldByPassInfo = byPassInfoMapper.toEntity(byPassInfo); checkTask.setByPassInfo(oldByPassInfo); } save(checkTask); } @Override public TreeNode getSystemTree(Integer checkTaskId) { var modelTree = sysExpertService.getModelTree(getSystemModel(checkTaskId)); return buildHierarchyTree(modelTree.root(), null, List.of(2, 3, 4, 6), false,6); } // @Override // public TreeNode getByPassSystemTree(Integer checkTaskId) { // var modelTree = sysExpertService.getModelTree(getSystemModel(checkTaskId)); // return buildHierarchyTree(modelTree.root(), null, List.of(2, 3, 4, 6), true, 6); // } @Override public TreeNode getByPassSystemTree(Integer checkTaskId) { var modelTree = sysExpertService.getModelTree(getSystemModel(checkTaskId)); // 需要过滤掉提过问题的层 var records = errorRecordRepository.listSystemErrors(checkTaskId); var newRoot = pruneTreeWithRecords(modelTree.root(), 6, records); return buildHierarchyTree(newRoot, null, List.of(2, 3, 4, 6), true, 6); } private TreeNode pruneTreeWithRecords(TreeNode root, int leafLevel, List records) { // 先过滤掉所有提过问题的叶子节点 var newRoot = TreeHelper.pruneTree(root, (node) -> { if(node.getDepth() == leafLevel) { for(var record : records) { if(record.getProblem().getHierarchyPath().equals(node.getPath())) { return false; } } } return true; }); var sr = new SimpleTreeRoot<>(newRoot); sr.buildTree(); // 再过滤掉所有没有子节点的节点 newRoot = TreeHelper.pruneTree(newRoot, (node) -> { if(node.getDepth() == leafLevel) { return true; } return !node.getChildren().isEmpty(); }); // 返回树 sr = new SimpleTreeRoot<>(newRoot); sr.buildTree(); return sr.root(); } @Override public List getSystemProblems(Integer checkTaskId, String hierarchyPath) { var model = getSystemModel(checkTaskId); return systemModelService.listProblems(model, hierarchyPath == null ? "/" : hierarchyPath); } @Override public TreeNode getDeviceTree(Integer checkTaskId, DeviceType deviceType) { var modelTree = deviceExpertService.getModelTree(getDeviceModel(checkTaskId)); return buildHierarchyTree(modelTree.root(), deviceType, List.of(2, 4), false,4); } @Override public TreeNode getByPassDeviceTree(Integer checkTaskId, DeviceType deviceType) { var modelTree = deviceExpertService.getModelTree(getDeviceModel(checkTaskId)); var records = errorRecordRepository.listDeviceErrors(checkTaskId); var newRoot = pruneTreeWithRecords(modelTree.root(), 4, records); return buildHierarchyTree(newRoot, deviceType, List.of(1, 2, 3, 4), false,4); } @Override public TreeNode getByPassDeviceTree(Integer checkTaskId) { var checkTask = getCheckTask(checkTaskId); var deviceUsages = deviceUsageService.listUsages(checkTask.getProject().getId(), null); if(deviceUsages.isEmpty()) { return null; } var modelTree = deviceExpertService.getModelTree(getDeviceModel(checkTaskId)); var records = errorRecordRepository.listDeviceErrors(checkTaskId); var treeRoot = new TreeNode(); deviceUsages.forEach(deviceUsage -> { var device = deviceUsage.getDevice(); var dt = buildDeviceHierarchyTree(modelTree, records, device); dt.setId(device.getId()); dt.setName(device.getManufacturerNumber()); treeRoot.addChild(dt); }); return treeRoot; } private TreeNode buildDeviceHierarchyTree(TreeRoot modelTree, List records, Device device){ var sr = records.stream().filter( r -> r.getDevice().getId().equals(device.getId())).toList(); var newRoot = pruneTreeWithRecords(modelTree.root(), 4, sr); var deviceTree = buildHierarchyTree(newRoot, device.getType(), List.of(2, 3, 4), false,4); TreeHelper.travel(deviceTree, (node) -> { node.setPath(String.format("%d%s", device.getId(), node.getPath())); }); return deviceTree; } private TreeNode buildHierarchyTree(TreeNode root, DeviceType deviceType, List levels, boolean mergeName, int levelCnt){ var newRoot = TreeHelper. convertTree(root, (node, newNode) -> { // 对于综合问题树,由于第五层不显示,所以第六层的名称需要加上父节点的名称 if(mergeName && node.getDepth() == 6) { newNode.setName(node.getName() + "[" + node.getParent().getName() + "]"); } return null; }, (node) -> { int depth = node.getDepth(); // 对于设备问题树,如果指定了设备类型,则只显示该设备类型的问题 if(deviceType!=null && depth == 1) { return node.getName().equals(deviceType.getDesc()); } // 如果该分支的深度等于指定的深度,则保留 if(node.getDepth() == levelCnt) return true; return !node.getChildren().isEmpty(); }); return TreeHelper.pruneTreeByLevels(newRoot, levels); } @Override public List getDeviceProblems(Integer checkTaskId, String hierarchyPath) { var model = getDeviceModel(checkTaskId); return deviceModelService.listProblems(model, hierarchyPath); } @Override public Map> getTeamMembers(Integer id) { var checkTask = get(id); BizResultCode.TASK_NOT_FOUND.check(checkTask == null); var result = new LinkedHashMap>(); if(checkTask.getDrivers() != null) { result.put("drivers", userService.toDto(checkTask.getDrivers())); } if(checkTask.getGroupLeaders() != null) { result.put("groupLeaders", userService.toDto(checkTask.getGroupLeaders().stream().toList())); } if(checkTask.getGroupMembers() != null) { result.put("groupMembers", userService.toDto(checkTask.getGroupMembers().stream().toList())); } return result; } private SysModel getSystemModel(Integer checkTaskId) { var checkTask = get(checkTaskId); BizResultCode.TASK_NOT_FOUND.check(checkTask == null); var plan = checkTask.getPlan(); BizResultCode.PLAN_NOT_FOUND.check(plan == null); var expert = plan.getSystemFuzzyExpert(); BizResultCode.EXPERT_NOT_FOUND.check(expert == null); var model = plan.getSystemModel(); BizResultCode.EXPERT_MODEL_NOT_EXIST.check(model == null); return model; } private DeviceModel getDeviceModel(Integer checkTaskId) { var checkTask = get(checkTaskId); BizResultCode.TASK_NOT_FOUND.check(checkTask == null); var plan = checkTask.getPlan(); BizResultCode.PLAN_NOT_FOUND.check(plan == null); var expert = plan.getDeviceFuzzyExpert(); BizResultCode.EXPERT_NOT_FOUND.check(expert == null); var model = plan.getDeviceModel(); BizResultCode.EXPERT_MODEL_NOT_EXIST.check(model == null); return model; } //////////// 复核任务相关 //////////// @Override public ReviewTaskDto getReviewTask(Integer checkTaskId) { var checkTask = get(checkTaskId); BizResultCode.TASK_NOT_FOUND.check(checkTask == null); var reviewTask = checkTask.getReviewTask(); if(reviewTask == null) return null; return reviewTaskMapper.toDto(reviewTask); } private CheckTask getCheckTask(Integer checkTaskId) { var checkTask = get(checkTaskId); BizResultCode.TASK_NOT_FOUND.check(checkTask == null); return checkTask; } @Override public void addReviewTask(User user, Integer checkTaskId, ReviewTaskDto reviewTaskDto) { var checkTask = getCheckTask(checkTaskId); BizResultCode.TASK_STATUS_ERROR.check( checkTask.getState() != CheckTaskState.Finished && checkTask.getState() != CheckTaskState.Reviewed); var reviewTask = checkTask.getReviewTask(); if(reviewTask != null) { reviewTaskMapper.partialUpdate(reviewTaskDto, reviewTask); }else{ var newReviewTask = reviewTaskMapper.toEntity(reviewTaskDto); newReviewTask.setName(UUID.randomUUID().toString()); checkTask.setReviewTask(newReviewTask); } checkTask.getReviewTask().setCreator(user); checkTask.getReviewTask().setCreateTime(LocalDateTime.now()); checkTask.getReviewTask().setUpdateTime(LocalDateTime.now()); checkTask.setState(CheckTaskState.WaitForReview); save(checkTask); } @Override public void editReviewTask(Integer checkTaskId, ReviewTaskDto reviewTaskDto) { var checkTask = getCheckTask(checkTaskId); BizResultCode.TASK_STATUS_ERROR.check( checkTask.getState() != CheckTaskState.WaitForReview && checkTask.getState() != CheckTaskState.Reviewing); var reviewTask = checkTask.getReviewTask(); BizResultCode.REVIEW_TASK_NOT_EXIST.check(reviewTask == null); reviewTaskMapper.partialUpdate(reviewTaskDto, reviewTask); save(checkTask); } @Override public void closeReviewTask(Integer checkTaskId) { var checkTask = getCheckTask(checkTaskId); BizResultCode.TASK_STATUS_ERROR.check( checkTask.getState() != CheckTaskState.Reviewing && checkTask.getState() != CheckTaskState.WaitForReview); var reviewTask = checkTask.getReviewTask(); BizResultCode.REVIEW_TASK_NOT_EXIST.check(reviewTask == null); checkTask.setState(CheckTaskState.Reviewed); save(checkTask); } @Override public void deleteReviewTask(Integer checkTaskId) { var checkTask = getCheckTask(checkTaskId); var reviewTask = checkTask.getReviewTask(); BizResultCode.REVIEW_TASK_NOT_EXIST.check(reviewTask == null); checkTask.setReviewTask(null); checkTask.setState(CheckTaskState.Finished); save(checkTask); } }