| | |
| | | assertEquals(1, service.selectActions(new TTestDataRevisionAction()).size()); |
| | | } |
| | | |
| | | @Test void workbookImportsThreeSheetsWithOneRevisionAndSkipsRetry() |
| | | @Test void workbookImportsThreeSheetsWithSeparateRevisionsAndSkipsRetry() |
| | | { |
| | | var sheets = Map.of("REALTIME", List.of(row(), row()), "STEP", List.of(row()), "CYCLE", List.of(row())); |
| | | var result = submitWorkbook(sheets); |
| | |
| | | assertEquals(1, service.selectActions(query).size()); |
| | | } |
| | | var actions = service.selectActions(new TTestDataRevisionAction()); |
| | | assertEquals(1, actions.size()); |
| | | assertEquals("ALL", actions.get(0).getDataType()); |
| | | assertEquals(3, actions.size()); |
| | | assertEquals(3, ((List<?>) result.get("actionIds")).size()); |
| | | assertEquals(java.util.Set.of("REALTIME", "STEP", "CYCLE"), actions.stream().map(TTestDataRevisionAction::getDataType).collect(java.util.stream.Collectors.toSet())); |
| | | for (var revision : actions) |
| | | { |
| | | String label = switch (revision.getDataType()) { case "REALTIME" -> "实时"; case "STEP" -> "工步"; default -> "循环"; }; |
| | | assertEquals("导入1条" + label + "数据", revision.getScopeSummary()); |
| | | assertEquals(1L, service.selectActionById(revision.getActionId()).getAffectedRecordCount()); |
| | | } |
| | | assertEquals("三页验收", actions.get(0).getReason()); |
| | | var retry = submitWorkbook(sheets); |
| | | assertEquals(0, retry.get("importedCount")); |
| | | assertEquals(4, retry.get("skippedCount")); |
| | | assertNull(retry.get("actionId")); |
| | | assertEquals(1, service.selectActions(new TTestDataRevisionAction()).size()); |
| | | assertEquals(List.of(), retry.get("actionIds")); |
| | | assertEquals(3, service.selectActions(new TTestDataRevisionAction()).size()); |
| | | } |
| | | |
| | | private com.ruoyi.common.core.domain.AjaxResult submitWorkbook(Map<String, List<Map<String, Object>>> sheets) |
| | |
| | | jdbc.execute("alter table t_test_cycle_record add check (discharge_energy_wh <> 999)"); |
| | | assertThrows(RuntimeException.class, () -> submitWorkbook(Map.of("REALTIME", List.of(row()), "STEP", List.of(row()), "CYCLE", List.of(cycle)))); |
| | | assertWorkbookEmpty(); |
| | | } |
| | | |
| | | @Test void workbookRevisionFailureRollsBackEarlierRevisionsAndAllData() |
| | | { |
| | | jdbc.execute("alter table t_test_data_revision_action add check (data_type <> 'CYCLE')"); |
| | | assertThrows(RuntimeException.class, () -> submitWorkbook(Map.of("REALTIME", List.of(row()), "STEP", List.of(row()), "CYCLE", List.of(row())))); |
| | | assertWorkbookEmpty(); |
| | | } |
| | | |
| | | @Test void partiallyRepeatedWorkbookRecordsActualPerTypeCounts() |
| | | { |
| | | submit("REALTIME", List.of(row())); |
| | | var result = submitWorkbook(Map.of("REALTIME", List.of(row()), "STEP", List.of(row()), "CYCLE", List.of(row()))); |
| | | assertEquals(2, result.get("importedCount")); |
| | | assertEquals(1, result.get("skippedCount")); |
| | | assertEquals(3, ((List<?>) result.get("actionIds")).size()); |
| | | var realtime = new TTestDataRevisionAction(); realtime.setDataType("REALTIME"); |
| | | var revisions = service.selectActions(realtime); |
| | | assertEquals(2, revisions.size()); |
| | | assertEquals("导入0条实时数据", revisions.get(0).getScopeSummary()); |
| | | assertEquals(0L, service.selectActionById(revisions.get(0).getActionId()).getAffectedRecordCount()); |
| | | var invalid = new TTestDataRevisionAction(); invalid.setDataType("ALL"); |
| | | assertThrows(RuntimeException.class, () -> service.selectActions(invalid)); |
| | | } |
| | | |
| | | @Test void workbookMissingEmptyInvalidOrConflictingSheetNeverWritesAnySheet() |
| | |
| | | void suppliedPartyWorkbookImportsAllRowsAndSkipsEveryRetry() throws Exception |
| | | { |
| | | var sample = JSON.parseObject(java.nio.file.Files.readString(java.nio.file.Path.of(System.getenv("TICKET03_SAMPLE_JSON")))); |
| | | Map<String, List<Map<String, Object>>> sheets = new LinkedHashMap<>(); |
| | | for (String type : List.of("REALTIME", "STEP", "CYCLE")) sheets.put(type, (List) sample.getJSONArray(type).toJavaList(Map.class)); |
| | | assertEquals(7767, submitWorkbook(sheets).get("importedCount")); |
| | | assertEquals(7767, submitWorkbook(sheets).get("skippedCount")); |
| | | for (String type : List.of("REALTIME", "STEP", "CYCLE")) |
| | | { |
| | | List<Map<String, Object>> rows = (List) sample.getJSONArray(type).toJavaList(Map.class); |
| | | int count = switch (type) { case "REALTIME" -> 7605; case "STEP" -> 129; default -> 33; }; |
| | | assertEquals(count, submit(type, rows).get("importedCount")); |
| | | assertEquals(count, mapper.selectImportDataRecords(1L, type).size()); |
| | | assertEquals(count, submit(type, rows).get("skippedCount")); |
| | | if ("STEP".equals(type)) |
| | | var query = new TTestDataRevisionAction(); query.setDataType(type); |
| | | var actions = service.selectActions(query); |
| | | assertEquals(1, actions.size()); |
| | | assertEquals((long) count, service.selectActionById(actions.get(0).getActionId()).getAffectedRecordCount()); |
| | | String label = switch (type) { case "REALTIME" -> "实时"; case "STEP" -> "工步"; default -> "循环"; }; |
| | | assertEquals("导入" + count + "条" + label + "数据", actions.get(0).getScopeSummary()); |
| | | if ("STEP".equals(type) || "REALTIME".equals(type)) |
| | | { |
| | | var persisted = mapper.selectImportDataRecords(1L, type).stream().collect(java.util.stream.Collectors.toMap( |
| | | record -> record.get("source_record_id").toString(), record -> record)); |
| | | for (var input : rows) |
| | | { |
| | | var stored = JSON.parseObject(persisted.get(input.get("recordNo").toString()).get("extension_measurements_json").toString()); |
| | | for (String field : List.of("chargeMedianVoltage", "dischargeMedianVoltage")) |
| | | for (String field : "STEP".equals(type) ? List.of("stepDuration", "chargeMedianVoltage", "dischargeMedianVoltage") : List.of("relativeTimeSeconds")) |
| | | if (input.get(field) == null) assertNull(stored.get(field)); |
| | | else assertEquals(0, new java.math.BigDecimal(input.get(field).toString()).compareTo(stored.getBigDecimal(field)), field); |
| | | } |
| | |
| | | assertEquals(3, service.selectActions(new TTestDataRevisionAction()).size()); |
| | | } |
| | | |
| | | @Test void realtimeRelativeTimeSurvivesImportQueryAndDuplicateValidation() |
| | | { |
| | | var input = row(); input.put("relativeTimeSeconds", 3752.125); |
| | | submit("REALTIME", List.of(input)); |
| | | var stored = mapper.selectImportDataRecords(1L, "REALTIME").get(0); |
| | | assertNotNull(stored.get("extension_measurements_json")); |
| | | var extension = JSON.parseObject(stored.get("extension_measurements_json").toString()); |
| | | assertEquals(0, new java.math.BigDecimal("3752.125").compareTo(extension.getBigDecimal("relativeTimeSeconds"))); |
| | | var queryMapper = org.mockito.Mockito.mock(TTestMapper.class); |
| | | var query = new com.battery.business.service.impl.TestDataQueryServiceImpl(queryMapper, |
| | | org.mockito.Mockito.mock(com.battery.business.service.ITTestService.class)); |
| | | var current = new LinkedHashMap<String, Object>(); current.put("extensionMeasurementsJson", extension.toJSONString()); |
| | | var legacy = new LinkedHashMap<String, Object>(); |
| | | org.mockito.Mockito.when(queryMapper.selectPersistedFinalRealtimeRecords(1L)).thenReturn(List.of(current, legacy)); |
| | | assertEquals(new java.math.BigDecimal("3752.125"), query.records(1L).get(0).get("relativeTimeSeconds")); |
| | | assertNull(query.records(1L).get(1).get("relativeTimeSeconds")); |
| | | assertEquals(1, submit("REALTIME", List.of(input)).get("skippedCount")); |
| | | input.put("relativeTimeSeconds", 3752.126); |
| | | assertThrows(RuntimeException.class, () -> submit("REALTIME", List.of(input))); |
| | | } |
| | | |
| | | private Map<String, Object> row() |
| | | { |
| | | var row = new LinkedHashMap<String, Object>(Map.of("recordNo", "17", "batteryNo", "BAT-1", "recordedAt", 1683517331000L, |