From 9c0fd80309b277420c492180ae9f98f779f0f5c8 Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期日, 30 八月 2026 23:29:33 +0800
Subject: [PATCH] 实现设备自然结束与区间补采恢复

---
 ruoyi-system/src/main/resources/mapper/system/TTestMapper.xml |  123 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 122 insertions(+), 1 deletions(-)

diff --git a/ruoyi-system/src/main/resources/mapper/system/TTestMapper.xml b/ruoyi-system/src/main/resources/mapper/system/TTestMapper.xml
index 0c10891..078a111 100644
--- a/ruoyi-system/src/main/resources/mapper/system/TTestMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/TTestMapper.xml
@@ -19,6 +19,9 @@
         <result property="startedAtUtc" column="started_at_utc" />
         <result property="endedAtUtc" column="ended_at_utc" />
         <result property="runtimeAttach" column="runtime_attach" />
+        <result property="backfillStatus" column="backfill_status" />
+        <result property="backfillStartedAtUtc" column="backfill_started_at_utc" />
+        <result property="backfillCompletedAtUtc" column="backfill_completed_at_utc" />
         <result property="delFlag" column="del_flag" />
         <result property="createBy" column="create_by" />
         <result property="createTime" column="create_time" />
@@ -153,7 +156,8 @@
                t.started_at_utc, t.ended_at_utc, t.del_flag,
                t.create_by, t.create_time, t.update_by, t.update_time, t.remark,
                (select count(1) from t_test_battery b where b.test_id = t.test_id and b.del_flag = 0) battery_count,
-               t.runtime_attach runtime_attach
+               t.runtime_attach runtime_attach, t.backfill_status, t.backfill_started_at_utc,
+               t.backfill_completed_at_utc
         from t_test t
         left join sys_user creator on creator.user_id = t.creator_id and creator.del_flag = '0'
         left join sys_user principal on principal.user_id = t.principal_id and principal.del_flag = '0'
@@ -371,6 +375,9 @@
     <select id="selectCollectorChannelCount" resultType="int">
         select channel_count from t_collector where collector_id = #{collectorId} and status = '0' and del_flag = 0
     </select>
+    <select id="selectCollectorCode" resultType="string">
+        select collector_code from t_collector where collector_id = #{collectorId} and status = '0' and del_flag = 0
+    </select>
 
     <select id="selectEnabledUserOptions" resultType="com.ruoyi.system.domain.vo.TestUserOptionVo">
         select user_id userId, user_name userName, nick_name nickName
@@ -430,6 +437,119 @@
           and cabinet.registration_status = 'REGISTERED'
         for update
     </select>
+
+    <select id="selectTestsForNaturalEnd" resultMap="TTestResultMap">
+        <include refid="selectTestBase" />
+        where t.del_flag = 0 and t.reception_status in ('RECEIVING', 'PAUSED')
+        order by t.test_id
+    </select>
+    <select id="selectTestsForBackfill" resultMap="TTestResultMap">
+        <include refid="selectTestBase" />
+        where t.del_flag = 0 and t.reception_status = 'ENDED'
+          and t.test_status in ('COMPLETION_PENDING', 'COMPLETED')
+          and coalesce(t.backfill_status, 'NOT_STARTED') &lt;&gt; 'COMPLETED'
+        order by t.ended_at_utc, t.test_id
+    </select>
+    <resultMap id="TTestBackfillCursorResultMap" type="com.ruoyi.system.domain.TTestBackfillCursor">
+        <id property="cursorId" column="cursor_id" />
+        <result property="testId" column="test_id" />
+        <result property="bindingId" column="binding_id" />
+        <result property="sourceType" column="source_type" />
+        <result property="sourceId" column="source_id" />
+        <result property="sourceChannelCode" column="source_channel_code" />
+        <result property="protocolTestId" column="protocol_test_id" />
+        <result property="nextPosition" column="next_position" />
+        <result property="sourceStatus" column="source_status" />
+        <result property="protocolMetadata" column="protocol_metadata" />
+        <result property="lastError" column="last_error" />
+        <result property="updatedAtUtc" column="updated_at_utc" />
+    </resultMap>
+    <select id="selectBackfillCursorForUpdate" resultMap="TTestBackfillCursorResultMap">
+        select * from t_test_backfill_cursor
+        where test_id = #{testId} and binding_id = #{bindingId}
+          and source_type = #{sourceType} and source_id = #{sourceId}
+          and (source_channel_code = #{sourceChannelCode} or (source_channel_code is null and #{sourceChannelCode} is null))
+        for update
+    </select>
+    <insert id="insertBackfillCursor" parameterType="com.ruoyi.system.domain.TTestBackfillCursor" useGeneratedKeys="true" keyProperty="cursorId">
+        insert into t_test_backfill_cursor
+        (test_id, binding_id, source_type, source_id, source_channel_code, protocol_test_id,
+         next_position, source_status, protocol_metadata, last_error, updated_at_utc)
+        values (#{testId}, #{bindingId}, #{sourceType}, #{sourceId}, #{sourceChannelCode}, #{protocolTestId},
+                #{nextPosition}, #{sourceStatus}, cast(#{protocolMetadata} as json), #{lastError}, #{updatedAtUtc})
+    </insert>
+    <update id="updateBackfillCursor" parameterType="com.ruoyi.system.domain.TTestBackfillCursor">
+        update t_test_backfill_cursor set protocol_test_id = #{protocolTestId}, next_position = #{nextPosition},
+            source_status = #{sourceStatus}, protocol_metadata = cast(#{protocolMetadata} as json),
+            last_error = #{lastError}, updated_at_utc = #{updatedAtUtc}
+        where cursor_id = #{cursorId}
+    </update>
+    <update id="updateTestBackfillStarted">
+        update t_test set test_status = 'COMPLETION_PENDING', backfill_status = 'RUNNING',
+            backfill_started_at_utc = coalesce(backfill_started_at_utc, #{updatedAtUtc}),
+            update_time = #{updatedAtUtc} where test_id = #{testId} and reception_status = 'ENDED'
+    </update>
+    <update id="updateTestBackfillWaiting">
+        update t_test set backfill_status = 'WAITING', update_time = #{updatedAtUtc}, remark = #{error}
+        where test_id = #{testId} and reception_status = 'ENDED'
+    </update>
+    <update id="updateTestBackfillCompleted">
+        update t_test set backfill_status = 'COMPLETED', backfill_completed_at_utc = #{updatedAtUtc},
+            update_time = #{updatedAtUtc} where test_id = #{testId} and reception_status = 'ENDED'
+    </update>
+    <update id="updateTestNaturallyEnded">
+        update t_test set test_status = 'COMPLETION_PENDING', reception_status = 'ENDED',
+            ended_at_utc = #{endedAtUtc}, backfill_status = 'NOT_STARTED', update_time = #{endedAtUtc}
+        where test_id = #{testId} and reception_status in ('RECEIVING', 'PAUSED')
+    </update>
+    <select id="selectSampleContentHash" resultType="string">
+        select hex(content_sha256) from t_test_sample
+        where channel_id = #{channelId} and bts_test_id = #{btsTestId} and seq_id = #{sequenceId}
+    </select>
+    <insert id="insertBtsSample">
+        insert ignore into t_test_sample
+        (test_id, binding_id, channel_id, reception_interval_id, bts_test_id, seq_id, device_time_utc,
+         device_time_raw, received_at_utc, cycle_no, step_no, step_type, test_time_ms, voltage_v,
+         current_a, capacity_ah, energy_wh, content_sha256)
+        values (#{testId}, #{bindingId}, #{channelId}, #{intervalId}, #{btsTestId}, #{sequenceId}, #{deviceTimeUtc},
+                #{deviceTimeRaw}, #{receivedAtUtc}, #{cycleNo}, #{stepNo}, #{stepType}, #{testTimeMs}, #{voltageV},
+                #{currentA}, #{capacityAh}, #{energyWh}, #{contentSha256})
+    </insert>
+    <insert id="insertBtsMeasurement">
+        insert ignore into t_test_sample_measurement
+        (sample_id, metric_code, metric_value, unit, source_type)
+        values (#{sampleId}, #{metricCode}, #{metricValue}, #{unit}, #{sourceType})
+    </insert>
+    <select id="selectBtsSampleId" resultType="long">
+        select sample_id from t_test_sample
+        where channel_id = #{channelId} and bts_test_id = #{btsTestId} and seq_id = #{sequenceId}
+    </select>
+    <insert id="insertCollectorSample">
+        insert ignore into t_test_collector_sample
+        (test_id, binding_id, collector_id, collector_channel_code, sequence_id, device_time_utc,
+         device_time_raw, server_received_at_utc, metric_code, metric_value, unit, content_sha256)
+        values (#{testId}, #{bindingId}, #{collectorId}, #{channelCode}, #{sequenceId}, #{deviceTimeUtc},
+                #{deviceTimeRaw}, #{receivedAtUtc}, #{metricCode}, #{metricValue}, #{unit}, #{contentSha256})
+    </insert>
+    <select id="selectCollectorSampleId" resultType="long">
+        select sample_id from t_test_collector_sample
+        where collector_id = #{collectorId} and collector_channel_code = #{channelCode}
+          and sequence_id = #{sequenceId} and metric_code = #{metricCode}
+    </select>
+    <select id="selectCollectorSampleContentHash" resultType="string">
+        select hex(content_sha256) from t_test_collector_sample
+        where collector_id = #{collectorId} and collector_channel_code = #{channelCode}
+          and sequence_id = #{sequenceId} and metric_code = #{metricCode}
+    </select>
+    <insert id="insertBackfillConflict">
+        insert into t_test_exception
+        (test_id, channel_id, exception_type, exception_status, severity,
+         first_occurred_at_utc, last_occurred_at_utc, occurrence_count, detail)
+        values (#{testId}, #{channelId}, 'HISTORY_CONTENT_CONFLICT', 'OPEN', 'WARNING', utc_timestamp(3),
+                utc_timestamp(3), 1, #{detail})
+        on duplicate key update last_occurred_at_utc = utc_timestamp(3), occurrence_count = occurrence_count + 1,
+            detail = values(detail)
+    </insert>
     <select id="selectChannelLeaseForUpdate" parameterType="Long" resultMap="TTestBindingResultMap">
         select binding.binding_id, binding.test_id, binding.battery_relation_id, binding.channel_id,
                binding.claim_status
@@ -522,6 +642,7 @@
     <update id="updateReceptionStopped">
         update t_test
         set test_status = 'COMPLETED', reception_status = 'ENDED', ended_at_utc = #{endedAtUtc},
+            backfill_status = 'NOT_STARTED',
             update_by = #{updateBy}, update_time = #{endedAtUtc}
         where test_id = #{testId} and reception_status in ('RECEIVING', 'PAUSED') and del_flag = 0
     </update>

--
Gitblit v1.7.1