From 9c93934b70ccfca081102944a47f3baafad3c218 Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期一, 28 九月 2026 16:43:57 +0800
Subject: [PATCH] 实现新威 7.6 的工步与循环数据取数

---
 ruoyi-admin/src/test/java/com/battery/business/web/ConsoleSingleSheetImportDatabaseTest.java |   50 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/ruoyi-admin/src/test/java/com/battery/business/web/ConsoleSingleSheetImportDatabaseTest.java b/ruoyi-admin/src/test/java/com/battery/business/web/ConsoleSingleSheetImportDatabaseTest.java
index 60ca979..79a71f6 100644
--- a/ruoyi-admin/src/test/java/com/battery/business/web/ConsoleSingleSheetImportDatabaseTest.java
+++ b/ruoyi-admin/src/test/java/com/battery/business/web/ConsoleSingleSheetImportDatabaseTest.java
@@ -64,7 +64,7 @@
                 new ClassPathResource("db/migration-final/V8__import_records_without_polling_slots.sql"));
         String deviceTime = "dedupe_key varchar(512) not null, device_time_utc timestamp(3) not null, device_time_raw varchar(64) not null, adapter_timezone_id varchar(64) not null, unique(test_battery_id,source_identity,dedupe_key)";
         jdbc.execute("create table t_test_step_record(step_record_id bigint auto_increment primary key," + common + "," + metrics + "," + deviceTime + ")");
-        jdbc.execute("create table t_test_cycle_record(cycle_record_id bigint auto_increment primary key," + common + ",charge_capacity_ah decimal(30,12),discharge_capacity_ah decimal(30,12),charge_energy_wh decimal(30,12),discharge_energy_wh decimal(30,12),efficiency decimal(30,12)," + deviceTime + ")");
+        jdbc.execute("create table t_test_cycle_record(cycle_record_id bigint auto_increment primary key," + common + ",source_kind varchar(16) default 'DEVICE',charge_capacity_ah decimal(30,12),discharge_capacity_ah decimal(30,12),charge_energy_wh decimal(30,12),discharge_energy_wh decimal(30,12),efficiency decimal(30,12)," + deviceTime + ")");
         var factory = new SqlSessionFactoryBean(); factory.setDataSource(source);
         factory.setTypeAliasesPackage("com.battery.business.domain");
         factory.setMapperLocations(new ClassPathResource("mapper/battery/TTestMapper.xml"));
@@ -107,6 +107,40 @@
         }
         assertEquals("17", mapper.selectPersistedFinalRealtimeRecords(1L).get(0).get("recordno"));
         assertEquals(3, service.selectActions(new TTestDataRevisionAction()).size());
+    }
+
+    /**
+     * 循环记录的来源类别随记录落库并经查询交回:导入的循环来自授权文件,
+     * 由工步层聚合的循环标注为聚合,使界面与导出能区分"推导值"与"设备或文件给的值"。
+     */
+    @Test void cycleSourceKindDistinguishesImportedAndAggregatedRecords()
+    {
+        assertEquals(1, submit("CYCLE", List.of(row())).get("importedCount"));
+        assertEquals("IMPORTED", mapper.selectPersistedFinalCycleRecords(1L).get(0).get("sourcekind"));
+
+        var aggregated = new com.battery.business.domain.TTestCycleRecord();
+        aggregated.setTestId(1L); aggregated.setTestBatteryId(4L); aggregated.setBindingId(5L);
+        aggregated.setAdapterCode("adapter-a"); aggregated.setSourceIdentity("adapter-a:27:1:1:2");
+        aggregated.setSourceRecordId("neware:442:cycle:3");
+        aggregated.setSourceKind(com.battery.device.api.TestDataObservationAdapter.CycleRecord.SOURCE_AGGREGATED);
+        aggregated.setDedupeKey("record:neware:442:cycle:3");
+        aggregated.setAdapterTimezoneId("Asia/Hong_Kong");
+        aggregated.setDeviceTimeUtc(new java.util.Date(1683517331000L));
+        aggregated.setDeviceTimeRaw("2023-05-08 11:42:11");
+        aggregated.setServerReceivedAtUtc(new java.util.Date(1683517331000L));
+        aggregated.setCycleNo(3);
+        aggregated.setChargeCapacityAh(new java.math.BigDecimal("2.375"));
+        aggregated.setDischargeCapacityAh(new java.math.BigDecimal("1.383"));
+        aggregated.setEfficiency(null);
+        aggregated.setContentSha256(new byte[32]);
+        assertEquals(1, mapper.insertCycleRecord(aggregated));
+
+        var rows = mapper.selectPersistedFinalCycleRecords(1L);
+        assertEquals(2, rows.size());
+        var stored = rows.stream().filter(item -> "3".equals(String.valueOf(item.get("cycleno")))).findFirst().orElseThrow();
+        assertEquals("AGGREGATED", stored.get("sourcekind"));
+        // 没有可用充电容量就没有效率:空值不是零。
+        assertNull(stored.get("efficiency"));
     }
 
     @Test void databaseFailureRollsBackEarlierRowsAndTheRevision()
@@ -165,12 +199,24 @@
                 org.mockito.Mockito.mock(com.battery.business.service.ITTestService.class));
         var current = new LinkedHashMap<String, Object>(Map.of("extensionMeasurementsJson", extension.toJSONString()));
         var legacy = new LinkedHashMap<String, Object>(Map.of("extensionMeasurementsJson", "{\"chargePeakVoltage\":1.8,\"dischargeValleyVoltage\":0.8}"));
-        org.mockito.Mockito.when(queryMapper.selectPersistedFinalStepRecords(1L)).thenReturn(List.of(current, legacy));
+        // 设备工步层的四组容量能量是独立事实:查询要交出它们,供方向未确认的工步核对。
+        var deviceStep = new LinkedHashMap<String, Object>(Map.of("extensionMeasurementsJson",
+                "{\"chargeCapacity\":13.888888888889,\"dischargeCapacity\":0,\"chargeEnergy\":25,\"dischargeEnergy\":0}"));
+        org.mockito.Mockito.when(queryMapper.selectPersistedFinalStepRecords(1L)).thenReturn(List.of(current, legacy, deviceStep));
         var result = query.steps(1L);
         assertEquals(new java.math.BigDecimal("1.1709"), result.get(0).get("dischargeMedianVoltage"));
         assertEquals(0.0, ((Number) result.get(0).get("chargeMedianVoltage")).doubleValue());
         assertNull(result.get(1).get("chargeMedianVoltage"));
         assertNull(result.get(1).get("dischargeMedianVoltage"));
+        assertEquals(0, new java.math.BigDecimal("13.888888888889").compareTo(
+                new java.math.BigDecimal(String.valueOf(result.get(2).get("chargeCapacity")))));
+        assertEquals(0, java.math.BigDecimal.ZERO.compareTo(
+                new java.math.BigDecimal(String.valueOf(result.get(2).get("dischargeCapacity")))));
+        assertEquals(0, new java.math.BigDecimal("25.0").compareTo(
+                new java.math.BigDecimal(String.valueOf(result.get(2).get("chargeEnergy")))));
+        assertEquals(0, java.math.BigDecimal.ZERO.compareTo(
+                new java.math.BigDecimal(String.valueOf(result.get(2).get("dischargeEnergy")))));
+        assertNull(result.get(1).get("chargeCapacity"));
 
         imported.put("dischargeMedianVoltage", 1.2);
         assertTrue(assertThrows(RuntimeException.class, () -> submit("STEP", List.of(imported))).getMessage().contains("冲突拒绝"));

--
Gitblit v1.7.1