| | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.alibaba.fastjson2.JSONException; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.dao.DuplicateKeyException; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | |
| | | import com.ruoyi.system.domain.TTestCollectorChannel; |
| | | import com.ruoyi.system.domain.TTestPlanStep; |
| | | import com.ruoyi.system.domain.TTestResult; |
| | | import com.ruoyi.system.domain.TTestFieldSnapshot; |
| | | import com.ruoyi.system.domain.TTestWarningThreshold; |
| | | import com.ruoyi.system.domain.TDetectionChannel; |
| | | import com.ruoyi.system.domain.TTestReceptionInterval; |
| | | import com.ruoyi.system.domain.vo.TestConfigurationOptionsVo; |
| | | import com.ruoyi.system.mapper.TTestMapper; |
| | | import com.ruoyi.system.service.ITTestService; |
| | |
| | | @Override |
| | | public int startTest(Long testId, String updateBy) |
| | | { |
| | | throw new ServiceException("开始接收由后续原子动作处理"); |
| | | throw new ServiceException("旧开始入口已停用,请使用原子开始接收接口并提供操作人"); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int startReception(Long testId, Long operatorId, String updateBy) |
| | | { |
| | | if (testId == null) throw new ServiceException("测试ID不能为空"); |
| | | if (operatorId == null) throw new ServiceException("操作人不能为空"); |
| | | TTest current = testMapper.selectTestByIdForUpdate(testId); |
| | | if (current == null) throw new ServiceException("测试不存在"); |
| | | if (!NOT_STARTED.equals(current.getReceptionStatus())) |
| | | throw new ServiceException("当前测试不是未开始接收状态"); |
| | | loadConfiguration(current); |
| | | if (current.getBatteries().isEmpty()) throw new ServiceException("测试未配置电池号"); |
| | | |
| | | Date actionAt = new Date(); |
| | | List<TTestReceptionInterval> intervals = new ArrayList<>(); |
| | | Set<Long> channelIds = new HashSet<>(); |
| | | Set<String> collectorChannels = new HashSet<>(); |
| | | boolean runtimeAttach = false; |
| | | for (TTestBattery battery : current.getBatteries()) |
| | | { |
| | | TTestChannelBinding binding = battery.getBinding(); |
| | | if (binding == null || binding.getChannelId() == null) |
| | | throw new ServiceException("电池号 " + battery.getBatteryNo() + " 未绑定检测柜通道"); |
| | | if (!channelIds.add(binding.getChannelId())) |
| | | throw new ServiceException("检测柜通道重复绑定,无法开始接收"); |
| | | TDetectionChannel channel = testMapper.selectReceptionChannelForUpdate(binding.getChannelId()); |
| | | if (channel == null || !isEnabled(channel.getStatus()) || !isOnline(channel.getOnlineStatus())) |
| | | throw new ServiceException("检测柜通道 " + binding.getChannelId() + " 当前离线或不可观测"); |
| | | if (channel.getLastSeenAtUtc() == null) |
| | | throw new ServiceException("检测柜通道 " + binding.getChannelId() + " 尚未取得成功观测边界"); |
| | | runtimeAttach |= "WORKING".equalsIgnoreCase(channel.getWorkStatus()) |
| | | || "PAUSED".equalsIgnoreCase(channel.getWorkStatus()); |
| | | if (testMapper.selectChannelLeaseForUpdate(binding.getChannelId()) != null) |
| | | throw new ServiceException("检测柜通道 " + binding.getChannelId() + " 已被其他测试占用"); |
| | | if (battery.getCollectorId() == null || testMapper.countCollectorEnabled(battery.getCollectorId()) == 0) |
| | | throw new ServiceException("电池号 " + battery.getBatteryNo() + " 的采集器不存在或未启用"); |
| | | if (!testMapper.collectorOnline(battery.getCollectorId())) |
| | | throw new ServiceException("采集器 " + battery.getCollectorId() + " 当前离线或不可观测"); |
| | | Integer collectorChannelCount = testMapper.selectCollectorChannelCount(battery.getCollectorId()); |
| | | validateCollectorChannels(battery.getCollectorId(), collectorChannelCount == null ? 0 : collectorChannelCount, |
| | | battery.getCollectorChannels(), collectorChannels); |
| | | |
| | | intervals.add(interval(current, binding.getBindingId(), "CABINET_CHANNEL", binding.getChannelId(), null, |
| | | actionAt, Date.from(channel.getLastSeenAtUtc()), runtimeAttach |
| | | ? "运行中接入:采用检测柜最近成功观测边界" : "采用检测柜最近成功观测边界")); |
| | | for (TTestCollectorChannel mapping : mutable(battery.getCollectorChannels())) |
| | | { |
| | | intervals.add(interval(current, binding.getBindingId(), "COLLECTOR_CHANNEL", battery.getCollectorId(), |
| | | mapping.getChannelCode(), actionAt, actionAt, "采集器开始接收确认边界")); |
| | | } |
| | | } |
| | | |
| | | try |
| | | { |
| | | for (TTestBattery battery : current.getBatteries()) |
| | | { |
| | | TTestChannelBinding binding = battery.getBinding(); |
| | | testMapper.insertChannelLease(binding.getChannelId(), testId, binding.getBindingId(), operatorId, actionAt); |
| | | for (TTestCollectorChannel mapping : mutable(battery.getCollectorChannels())) |
| | | testMapper.insertCollectorChannelLease(battery.getCollectorId(), mapping.getChannelCode(), testId, |
| | | binding.getBindingId(), operatorId, actionAt); |
| | | } |
| | | for (TTestReceptionInterval interval : intervals) testMapper.insertReceptionInterval(interval); |
| | | if (testMapper.updateReceptionStarted(testId, actionAt, updateBy) != 1) |
| | | throw new ServiceException("测试状态已变更,请刷新后重试"); |
| | | testMapper.insertTestAudit(testId, "RECEPTION_STARTED", operatorId, updateBy, null, |
| | | JSON.toJSONString(Map.of("receptionStatus", "RECEIVING", "intervalCount", intervals.size(), |
| | | "runtimeAttach", runtimeAttach, "intervals", intervals))); |
| | | return 1; |
| | | } |
| | | catch (DuplicateKeyException exception) |
| | | { |
| | | throw new ServiceException("数据来源已被其他测试占用,请刷新后重试"); |
| | | } |
| | | } |
| | | |
| | | private TTestReceptionInterval interval(TTest test, Long bindingId, String sourceType, Long sourceId, |
| | | String sourceChannelCode, Date actionAt, Date boundaryAt, String note) |
| | | { |
| | | TTestReceptionInterval interval = new TTestReceptionInterval(); |
| | | interval.setTestId(test.getTestId()); |
| | | interval.setBindingId(bindingId); |
| | | interval.setSourceType(sourceType); |
| | | interval.setSourceId(sourceId); |
| | | interval.setSourceChannelCode(sourceChannelCode); |
| | | interval.setActionAtUtc(actionAt); |
| | | interval.setStartBoundaryAtUtc(boundaryAt); |
| | | interval.setBoundaryNote(note); |
| | | interval.setIntervalStatus("OPEN"); |
| | | return interval; |
| | | } |
| | | |
| | | private boolean isOnline(String status) |
| | | { |
| | | return status != null && ("ONLINE".equalsIgnoreCase(status) || "0".equals(status)); |
| | | } |
| | | |
| | | private boolean isEnabled(String status) |
| | | { |
| | | return status == null || "0".equals(status); |
| | | } |
| | | |
| | | @Override |
| | |
| | | private void loadConfiguration(TTest test) |
| | | { |
| | | Long testId = test.getTestId(); |
| | | List<TTestPlanStep> planSteps = mutable(testMapper.selectTestPlanSteps(testId)); |
| | | List<TTestPlanStep> loadedPlanSteps = testMapper.selectTestPlanSteps(testId); |
| | | List<TTestPlanStep> planSteps = loadedPlanSteps == null ? mutable(test.getPlanSteps()) : mutable(loadedPlanSteps); |
| | | for (TTestPlanStep step : planSteps) |
| | | { |
| | | try |
| | |
| | | } |
| | | } |
| | | |
| | | List<TTestBattery> batteries = mutable(testMapper.selectTestBatteries(testId)); |
| | | List<TTestBatteryField> fields = mutable(testMapper.selectTestBatteryFields(testId)); |
| | | List<TTestCollectorChannel> collectorChannels = mutable(testMapper.selectTestCollectorChannels(testId)); |
| | | List<TTestBattery> loadedBatteries = testMapper.selectTestBatteries(testId); |
| | | List<TTestBattery> batteries = loadedBatteries == null || (loadedBatteries.isEmpty() && test.getBatteries() != null |
| | | && !test.getBatteries().isEmpty()) ? mutable(test.getBatteries()) : mutable(loadedBatteries); |
| | | List<TTestBatteryField> loadedFields = testMapper.selectTestBatteryFields(testId); |
| | | List<TTestBatteryField> fields = loadedFields == null ? List.of() : mutable(loadedFields); |
| | | List<TTestCollectorChannel> loadedCollectorChannels = testMapper.selectTestCollectorChannels(testId); |
| | | List<TTestCollectorChannel> collectorChannels = loadedCollectorChannels == null ? List.of() : mutable(loadedCollectorChannels); |
| | | Map<Long, TTestChannelBinding> bindings = new HashMap<>(); |
| | | for (TTestChannelBinding binding : mutable(testMapper.selectTestChannelBindings(testId))) |
| | | List<TTestChannelBinding> loadedBindings = testMapper.selectTestChannelBindings(testId); |
| | | if (loadedBindings == null || (loadedBindings.isEmpty() && batteries.stream().anyMatch(item -> item.getBinding() != null))) |
| | | for (TTestBattery battery : batteries) |
| | | if (battery.getBinding() != null) bindings.put(battery.getRelationId(), battery.getBinding()); |
| | | for (TTestChannelBinding binding : mutable(loadedBindings)) |
| | | bindings.put(binding.getBatteryRelationId(), binding); |
| | | for (TTestBattery battery : batteries) |
| | | { |
| | | battery.setBinding(bindings.get(battery.getRelationId())); |
| | | battery.setFields(fields.stream() |
| | | .filter(field -> battery.getRelationId().equals(field.getRelationId())) |
| | | .toList()); |
| | | battery.setCollectorChannels(collectorChannels.stream() |
| | | .filter(mapping -> battery.getRelationId().equals(mapping.getBatteryRelationId())) |
| | | .toList()); |
| | | if (loadedFields != null && (!loadedFields.isEmpty() || battery.getFields() == null)) |
| | | battery.setFields(fields.stream() |
| | | .filter(field -> battery.getRelationId().equals(field.getRelationId())) |
| | | .toList()); |
| | | if (loadedCollectorChannels != null && (!loadedCollectorChannels.isEmpty() || battery.getCollectorChannels() == null)) |
| | | battery.setCollectorChannels(collectorChannels.stream() |
| | | .filter(mapping -> battery.getRelationId().equals(mapping.getBatteryRelationId())) |
| | | .toList()); |
| | | } |
| | | test.setPlanSteps(planSteps); |
| | | test.setBatteries(batteries); |
| | | test.setBatteryNo(joinBatteryNos(batteries)); |
| | | test.setThresholds(mutable(testMapper.selectTestThresholds(testId))); |
| | | test.setFieldSnapshots(sharedFieldSnapshotService.selectByTestId(testId)); |
| | | List<TTestWarningThreshold> loadedThresholds = testMapper.selectTestThresholds(testId); |
| | | test.setThresholds(loadedThresholds == null ? mutable(test.getThresholds()) : mutable(loadedThresholds)); |
| | | List<TTestFieldSnapshot> loadedSnapshots = sharedFieldSnapshotService.selectByTestId(testId); |
| | | test.setFieldSnapshots(loadedSnapshots == null ? mutable(test.getFieldSnapshots()) : loadedSnapshots); |
| | | } |
| | | |
| | | private void validateBase(TTest test, boolean update) |