From 96144b97e1761db230c0dc61a837ec55d76210df Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期三, 02 九月 2026 15:50:55 +0800
Subject: [PATCH] 允许离线设备进入接收状态

---
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTestServiceImpl.java                |   14 ++----
 ruoyi-admin/src/test/java/com/ruoyi/system/service/impl/TTestServiceImplTest.java             |   33 ++++++++++++----
 ruoyi-admin/src/test/java/com/ruoyi/system/service/impl/TestDataReceptionServiceImplTest.java |   20 ++++++++++
 ruoyi-system/src/main/resources/mapper/system/TTestMapper.xml                                 |    5 --
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/TTestMapper.java                           |    1 
 5 files changed, 49 insertions(+), 24 deletions(-)

diff --git a/ruoyi-admin/src/test/java/com/ruoyi/system/service/impl/TTestServiceImplTest.java b/ruoyi-admin/src/test/java/com/ruoyi/system/service/impl/TTestServiceImplTest.java
index 561b2de..32c39ad 100644
--- a/ruoyi-admin/src/test/java/com/ruoyi/system/service/impl/TTestServiceImplTest.java
+++ b/ruoyi-admin/src/test/java/com/ruoyi/system/service/impl/TTestServiceImplTest.java
@@ -383,7 +383,6 @@
         when(testMapper.selectReceptionChannelForUpdate(100L)).thenReturn(channel);
         when(testMapper.countCollectorEnabled(8L)).thenReturn(1);
         when(testMapper.selectCollectorChannelCount(8L)).thenReturn(4);
-        when(testMapper.collectorOnline(8L)).thenReturn(true);
         when(testMapper.updateReceptionStarted(eq(10L), any(), anyBoolean(), eq("operator"))).thenReturn(1);
 
         assertEquals(1, testService.startReception(10L, 7L, "operator"));
@@ -406,7 +405,6 @@
         when(testMapper.selectReceptionChannelForUpdate(100L)).thenReturn(channel);
         when(testMapper.countCollectorEnabled(8L)).thenReturn(1);
         when(testMapper.selectCollectorChannelCount(8L)).thenReturn(4);
-        when(testMapper.collectorOnline(8L)).thenReturn(true);
         when(testMapper.updateReceptionStarted(eq(10L), any(), anyBoolean(), eq("operator"))).thenReturn(1);
 
         assertEquals(1, testService.startReception(10L, 7L, "operator"));
@@ -430,7 +428,6 @@
         when(testMapper.selectReceptionChannelForUpdate(100L)).thenReturn(channel);
         when(testMapper.countCollectorEnabled(8L)).thenReturn(1);
         when(testMapper.selectCollectorChannelCount(8L)).thenReturn(4);
-        when(testMapper.collectorOnline(8L)).thenReturn(true);
         when(testMapper.updateReceptionStarted(eq(10L), any(), anyBoolean(), eq("operator"))).thenReturn(1);
 
         assertEquals(1, testService.startReception(10L, 7L, "operator"));
@@ -438,22 +435,41 @@
     }
 
     @Test
-    void startReceptionShouldRejectOfflineSourceWithoutWritingAnything()
+    void startReceptionShouldAllowOfflineSourcesWithoutBlockingReception()
     {
         TTest current = validTest();
         current.setTestId(10L);
         current.setReceptionStatus("NOT_STARTED");
+        current.getBatteries().get(0).getBinding().setBindingId(30L);
         when(testMapper.selectTestByIdForUpdate(10L)).thenReturn(current);
         TDetectionChannel channel = new TDetectionChannel();
         channel.setChannelId(100L);
         channel.setOnlineStatus("OFFLINE");
         when(testMapper.selectReceptionChannelForUpdate(100L)).thenReturn(channel);
+        when(testMapper.countCollectorEnabled(8L)).thenReturn(1);
+        when(testMapper.selectCollectorChannelCount(8L)).thenReturn(4);
+        when(testMapper.updateReceptionStarted(eq(10L), any(), anyBoolean(), eq("operator"))).thenReturn(1);
 
-        ServiceException exception = assertThrows(ServiceException.class,
-                () -> testService.startReception(10L, 7L, "operator"));
+        assertEquals(1, testService.startReception(10L, 7L, "operator"));
+    }
 
-        assertEquals("检测柜通道 100 当前离线或不可观测", exception.getMessage());
-        verify(testMapper, never()).updateReceptionStarted(any(), any(), anyBoolean(), any());
+    @Test
+    void startReceptionShouldAllowOfflineCollectorWithoutBlockingReception()
+    {
+        TTest current = validTest();
+        current.setTestId(10L);
+        current.setReceptionStatus("NOT_STARTED");
+        current.getBatteries().get(0).getBinding().setBindingId(30L);
+        when(testMapper.selectTestByIdForUpdate(10L)).thenReturn(current);
+        TDetectionChannel channel = new TDetectionChannel();
+        channel.setChannelId(100L);
+        channel.setOnlineStatus("ONLINE");
+        when(testMapper.selectReceptionChannelForUpdate(100L)).thenReturn(channel);
+        when(testMapper.countCollectorEnabled(8L)).thenReturn(1);
+        when(testMapper.selectCollectorChannelCount(8L)).thenReturn(4);
+        when(testMapper.updateReceptionStarted(eq(10L), any(), anyBoolean(), eq("operator"))).thenReturn(1);
+
+        assertEquals(1, testService.startReception(10L, 7L, "operator"));
     }
 
     @Test
@@ -471,7 +487,6 @@
         channel.setLastSeenAtUtc(Instant.parse("2026-08-29T12:00:00Z"));
         when(testMapper.selectReceptionChannelForUpdate(100L)).thenReturn(channel);
         when(testMapper.countCollectorEnabled(8L)).thenReturn(1);
-        when(testMapper.collectorOnline(8L)).thenReturn(true);
         when(testMapper.selectCollectorChannelCount(8L)).thenReturn(4);
 
         ServiceException exception = assertThrows(ServiceException.class,
diff --git a/ruoyi-admin/src/test/java/com/ruoyi/system/service/impl/TestDataReceptionServiceImplTest.java b/ruoyi-admin/src/test/java/com/ruoyi/system/service/impl/TestDataReceptionServiceImplTest.java
index 794525c..3992beb 100644
--- a/ruoyi-admin/src/test/java/com/ruoyi/system/service/impl/TestDataReceptionServiceImplTest.java
+++ b/ruoyi-admin/src/test/java/com/ruoyi/system/service/impl/TestDataReceptionServiceImplTest.java
@@ -6,6 +6,7 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -51,6 +52,25 @@
                 any(byte[].class));
     }
 
+    @Test
+    void doesNotWriteSamplesWhenNoSuccessfulRecordsAreAvailable()
+    {
+        TTestMapper mapper = mock(TTestMapper.class);
+        ITTestService tests = mock(ITTestService.class);
+        BtsDevelopmentSimulator simulator = mock(BtsDevelopmentSimulator.class);
+        TTest test = test(Date.from(Instant.parse("2026-09-02T04:00:00Z")));
+        when(mapper.selectReceivingTestIds()).thenReturn(List.of(1L));
+        when(mapper.selectTestByIdForUpdate(1L)).thenReturn(test);
+        when(tests.selectTestById(1L)).thenReturn(test);
+        when(simulator.btsRecords(1, 1)).thenReturn(List.of());
+
+        new TestDataReceptionServiceImpl(mapper, tests, simulator).captureDevelopmentCabinetRecords();
+
+        verify(mapper, never()).insertBtsSample(any(), any(), any(), anyString(), any(), any(Date.class), anyString(),
+                any(Date.class), anyInt(), anyInt(), anyString(), anyString(), isNull(), any(BigDecimal.class),
+                any(BigDecimal.class), any(BigDecimal.class), any(BigDecimal.class), any(byte[].class));
+    }
+
     private static TTest test(Date startedAt)
     {
         TTestChannelBinding binding = new TTestChannelBinding();
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TTestMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TTestMapper.java
index 727dcbd..cc7fff7 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TTestMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TTestMapper.java
@@ -80,7 +80,6 @@
     TDetectionChannel selectReceptionChannelForUpdate(Long channelId);
     int hasReceivingTestForAdapter(@Param("adapterCode") String adapterCode);
     List<TDetectionChannel> selectReceivingChannelsForAdapter(@Param("adapterCode") String adapterCode);
-    boolean collectorOnline(Long collectorId);
     int updateReceptionStarted(@Param("testId") Long testId, @Param("startedAtUtc") Date startedAtUtc,
             @Param("runtimeAttach") boolean runtimeAttach, @Param("updateBy") String updateBy);
     int updateReceptionPaused(@Param("testId") Long testId, @Param("updateBy") String updateBy,
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 13f5179..85e6352 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
@@ -154,6 +154,9 @@
         throw new ServiceException("旧开始入口已停用,请使用原子开始接收接口并提供操作人");
     }
 
+    /**
+     * 建立测试接收边界;来源离线不阻断状态流转,只有成功观测数据才会写入测试事实。
+     */
     @Override
     @Transactional(rollbackFor = Exception.class)
     public int startReception(Long testId, Long operatorId, String updateBy)
@@ -179,14 +182,12 @@
             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 == null || !isEnabled(channel.getStatus()))
+                throw new ServiceException("检测柜通道 " + binding.getChannelId() + " 不存在或未启用");
             // 只有设备事实为运行中时才标记“运行中接入”;设备暂停属于独立设备状态。
             runtimeAttach |= "WORKING".equalsIgnoreCase(channel.getWorkStatus());
             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);
@@ -264,11 +265,6 @@
                 JSON.toJSONString(Map.of("testStatus", "COMPLETED", "receptionStatus", "ENDED",
                         "polling", "STOPPED", "release", "IMMEDIATE")));
         return 1;
-    }
-
-    private boolean isOnline(String status)
-    {
-        return status != null && ("ONLINE".equalsIgnoreCase(status) || "0".equals(status));
     }
 
     private boolean isEnabled(String status)
diff --git a/ruoyi-system/src/main/resources/mapper/system/TTestMapper.xml b/ruoyi-system/src/main/resources/mapper/system/TTestMapper.xml
index 69aa513..608d8c8 100644
--- a/ruoyi-system/src/main/resources/mapper/system/TTestMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/TTestMapper.xml
@@ -560,11 +560,6 @@
           and test_fact.reception_status = 'RECEIVING'
           and test_fact.del_flag = 0 and channel_fact.del_flag = 0 and channel_fact.status = '0'
     </select>
-    <select id="collectorOnline" resultType="boolean">
-        select count(1) &gt; 0 from t_collector
-        where collector_id = #{collectorId} and status = '0' and del_flag = 0
-          and upper(online_status) in ('ONLINE', '1')
-    </select>
     <update id="updateReceptionStarted">
         update t_test
         set test_status = 'RUNNING', reception_status = 'RECEIVING',

--
Gitblit v1.7.1