From a04222c873e5e55f48c8d33b5c0bc46fa524ac8d Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期四, 08 十月 2026 13:20:39 +0800
Subject: [PATCH] 界面显示号改为来源自报,并给出无歧义的来源定位

---
 ruoyi-admin/src/test/java/com/battery/business/runtime/PushIngestLandingMigrationContractTest.java |   30 ++++++++++++++++++++++++++++++
 1 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/ruoyi-admin/src/test/java/com/battery/business/runtime/PushIngestLandingMigrationContractTest.java b/ruoyi-admin/src/test/java/com/battery/business/runtime/PushIngestLandingMigrationContractTest.java
index 8199694..fe58e3f 100644
--- a/ruoyi-admin/src/test/java/com/battery/business/runtime/PushIngestLandingMigrationContractTest.java
+++ b/ruoyi-admin/src/test/java/com/battery/business/runtime/PushIngestLandingMigrationContractTest.java
@@ -35,6 +35,7 @@
 public class PushIngestLandingMigrationContractTest
 {
     private static final String PATH = "db/migration-final/V24__push_ingest_landing_table.sql";
+    private static final String VENDOR_CHANNEL_NO_PATH = "db/migration-final/V25__ingest_vendor_channel_no.sql";
     private static final String ADAPTER = "j22";
     private static final Instant RECEIVED_AT = Instant.parse("2026-09-27T09:20:00Z");
 
@@ -50,7 +51,9 @@
         jdbc = new JdbcTemplate(source);
         // H2 无 MySQL 的 HEX();测试中补一个等价别名,生产 SQL 仍在 MySQL 上验证。
         jdbc.execute("create alias HEX for 'com.battery.business.runtime.PushIngestLandingMigrationContractTest.hexOf'");
+        // 按顺序跑落地表相关的迁移,使内存库结构与生产库一致(V24 建表、V25 加来源通道号列)。
         ScriptUtils.executeSqlScript(keepAlive, new ClassPathResource(PATH));
+        ScriptUtils.executeSqlScript(keepAlive, new ClassPathResource(VENDOR_CHANNEL_NO_PATH));
 
         SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
         factory.setDataSource(source);
@@ -78,6 +81,33 @@
                 "select count(*) from t_device_ingest_record where voltage_v is null", Integer.class));
     }
 
+    /**
+     * 来源自己的通道叫法那条迁移:只加一个可空列,不写入任何数据;
+     * 老行读出来是空(界面回退到「单元-通道」),新行可以带上来源软件里显示的通道号。
+     */
+    @Test
+    void vendorChannelNoMigrationOnlyAddsANullableColumn()
+    {
+        String migration = resource(VENDOR_CHANNEL_NO_PATH);
+        assertTrue(migration.contains("ADD COLUMN vendor_channel_no INT NULL"));
+        assertFalse(migration.matches("(?s).*(INSERT|UPDATE|DELETE|DROP)\\b.*"));
+
+        jdbc.update("insert into t_device_ingest_record(adapter_code, payload_kind, record_key, payload_json,"
+                + " content_sha256, received_at_utc) values(?,?,?,?,?,?)", ADAPTER, "TOPOLOGY", "topology:26",
+                "{\"channel\":26}", new byte[32], Timestamp.from(RECEIVED_AT));
+        // 迁移在 setUp 里已按顺序执行过(V24 建表、V25 加列),这里只核对列的行为。
+        assertNull(jdbc.queryForObject(
+                "select vendor_channel_no from t_device_ingest_record where record_key = 'topology:26'",
+                Integer.class));
+        jdbc.update("update t_device_ingest_record set vendor_channel_no = ? where record_key = ?", 27,
+                "topology:26");
+        assertEquals(27, jdbc.queryForObject(
+                "select vendor_channel_no from t_device_ingest_record where record_key = 'topology:26'",
+                Integer.class));
+        // 展示列不参与身份:唯一键仍只由来源行身份决定。
+        assertEquals(1, jdbc.queryForObject("select count(*) from t_device_ingest_record", Integer.class));
+    }
+
     @Test
     void repeatedPushIsIgnoredBySourceRowIdentityAndDifferentContentIsKept()
     {

--
Gitblit v1.7.1