From acfb83068486766f63284b479d30f78e3ec17dca Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期六, 05 九月 2026 02:24:48 +0800
Subject: [PATCH] 完成测试生命周期与接收边界

---
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTestServiceImpl.java |   27 ++++++++++++++++++---------
 1 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTestServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTestServiceImpl.java
index e301e8d..22077cd 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTestServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTestServiceImpl.java
@@ -37,8 +37,8 @@
 {
     private static final String WAITING = "WAITING";
     private static final String NOT_STARTED = "NOT_STARTED";
-    private static final Set<String> TEST_STATUSES = Set.of(
-            WAITING, "RUNNING", "PAUSED", "RUNNING_ABNORMAL", "COMPLETION_PENDING", "COMPLETED", "TERMINATED");
+    /** 新流程只允许四种测试状态;历史状态仅在旧数据展示层做兼容映射。 */
+    private static final Set<String> TEST_STATUSES = Set.of(WAITING, "RUNNING", "PAUSED", "COMPLETED");
     private static final Set<String> RECEPTION_STATUSES = Set.of(NOT_STARTED, "RECEIVING", "PAUSED", "ENDED");
     private static final Set<String> THRESHOLD_UNITS = Set.of("A", "V", "Ah", "Wh", "℃");
     private static final Set<String> REQUIRED_COLLECTOR_MEASUREMENTS = Set.of(
@@ -109,7 +109,7 @@
         TTest current = testMapper.selectTestByIdForUpdate(test.getTestId());
         if (current == null) throw new ServiceException("测试不存在");
         loadConfiguration(current);
-        if (!NOT_STARTED.equals(current.getReceptionStatus()))
+        if (!stateMatches(current, WAITING, NOT_STARTED))
             throw new ServiceException("开始接收后不能修改测试配置");
 
         test.setCreatorId(current.getCreatorId());
@@ -149,7 +149,7 @@
         if (operatorId == null) throw new ServiceException("操作人不能为空");
         TTest current = testMapper.selectTestByIdForUpdate(testId);
         if (current == null) throw new ServiceException("测试不存在");
-        if (!NOT_STARTED.equals(current.getReceptionStatus()))
+        if (!stateMatches(current, WAITING, NOT_STARTED))
             throw new ServiceException("当前测试不是未开始接收状态");
         loadConfiguration(current);
         if (current.getBatteries().isEmpty()) throw new ServiceException("测试未配置电池号");
@@ -169,7 +169,8 @@
             if (channel == null || !isEnabled(channel.getStatus()))
                 throw new ServiceException("检测柜通道 " + binding.getChannelId() + " 不存在或未启用");
             // 只有设备事实为运行中时才标记“运行中接入”;设备暂停属于独立设备状态。
-            runtimeAttach |= "WORKING".equalsIgnoreCase(channel.getWorkStatus());
+            runtimeAttach |= "WORKING".equalsIgnoreCase(channel.getWorkStatus())
+                    || "RUNNING".equalsIgnoreCase(channel.getWorkStatus());
             if (battery.getCollectorId() == null || testMapper.countCollectorEnabled(battery.getCollectorId()) == 0)
                 throw new ServiceException("电池号 " + battery.getBatteryNo() + " 的采集器不存在或未启用");
             Integer collectorChannelCount = testMapper.selectCollectorChannelCount(battery.getCollectorId());
@@ -200,7 +201,7 @@
         if (operatorId == null) throw new ServiceException("操作人不能为空");
         TTest current = testMapper.selectTestByIdForUpdate(testId);
         if (current == null) throw new ServiceException("测试不存在");
-        if (!"RECEIVING".equals(current.getReceptionStatus()))
+        if (!stateMatches(current, "RUNNING", "RECEIVING"))
             throw new ServiceException("当前测试不是接收中状态");
 
         Date actionAt = new Date();
@@ -220,7 +221,7 @@
         if (operatorId == null) throw new ServiceException("操作人不能为空");
         TTest current = testMapper.selectTestByIdForUpdate(testId);
         if (current == null) throw new ServiceException("测试不存在");
-        if (!"PAUSED".equals(current.getReceptionStatus()))
+        if (!stateMatches(current, "PAUSED", "PAUSED"))
             throw new ServiceException("当前测试不是暂停接收状态");
         // 加锁查询只返回测试主表,继续接收前重新加载绑定配置以校验来源仍可用。
         loadConfiguration(current);
@@ -240,7 +241,8 @@
         if (operatorId == null) throw new ServiceException("操作人不能为空");
         TTest current = testMapper.selectTestByIdForUpdate(testId);
         if (current == null) throw new ServiceException("测试不存在");
-        if (NOT_STARTED.equals(current.getReceptionStatus()) || "ENDED".equals(current.getReceptionStatus()))
+        if (!(stateMatches(current, "RUNNING", "RECEIVING")
+                || stateMatches(current, "PAUSED", "PAUSED")))
             throw new ServiceException("当前测试不能停止");
         Date actionAt = new Date();
         if (testMapper.updateReceptionStopped(testId, updateBy, actionAt) != 1)
@@ -256,6 +258,13 @@
         return status == null || "0".equals(status);
     }
 
+    /** 生命周期动作必须同时匹配测试状态和接收状态,避免并发请求后两个状态字段互相矛盾。 */
+    private boolean stateMatches(TTest test, String expectedTestStatus, String expectedReceptionStatus)
+    {
+        return expectedReceptionStatus.equals(test.getReceptionStatus())
+                && expectedTestStatus.equals(test.getTestStatus());
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public int deleteTestByIds(Long[] testIds, Long operatorId, String updateBy)
@@ -266,7 +275,7 @@
         {
             TTest current = testMapper.selectTestByIdForUpdate(testId);
             if (current == null) throw new ServiceException("测试不存在");
-            if (!NOT_STARTED.equals(current.getReceptionStatus())) throw new ServiceException("开始接收后不能删除测试");
+            if (!stateMatches(current, WAITING, NOT_STARTED)) throw new ServiceException("开始接收后不能删除测试");
             loadConfiguration(current);
             // 测试整体删除是无痕例外:先清理全部测试绑定和阈值,再删除主记录,不写审计。
             testMapper.deleteTestCollectorChannelsByTestId(testId);

--
Gitblit v1.7.1