Commit 95a0d8a55d1e575e18ec9c362da089a96d123685

Authored by 黄 x
1 parent c13654b6

fix: fix empty data generate excel bug [DEFECT-603]

@@ -124,6 +124,19 @@ public class YtReportFormConfigController extends BaseController { @@ -124,6 +124,19 @@ public class YtReportFormConfigController extends BaseController {
124 private ResponseResult<ReportFormConfigDTO> saveOrUpdate(ReportFormConfigDTO configDTO) 124 private ResponseResult<ReportFormConfigDTO> saveOrUpdate(ReportFormConfigDTO configDTO)
125 throws ThingsboardException, SchedulerException { 125 throws ThingsboardException, SchedulerException {
126 configDTO.setTenantId(getCurrentUser().getCurrentTenantId()); 126 configDTO.setTenantId(getCurrentUser().getCurrentTenantId());
  127 + Long startTs = configDTO.getQueryCondition().getStartTs();
  128 + Long endTs = configDTO.getQueryCondition().getEndTs();
  129 + if (null == startTs || null == endTs) {
  130 + throw new YtDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage());
  131 + }
  132 + if (startTs < 946656000000L || endTs < 946656000000L) {
  133 + throw new YtDataValidationException(
  134 + ErrorMessage.START_TIME_OR_END_TIME_EXCEPTION.getMessage());
  135 + }
  136 + if (startTs > endTs) {
  137 + throw new YtDataValidationException(
  138 + ErrorMessage.START_TIME_NOT_MORE_THAN_END_TIME.getMessage());
  139 + }
127 ReportFormConfigDTO newDTO = reportFormConfigService.saveOrUpdateReportFormConfig(configDTO); 140 ReportFormConfigDTO newDTO = reportFormConfigService.saveOrUpdateReportFormConfig(configDTO);
128 return ResponseResult.success(newDTO); 141 return ResponseResult.success(newDTO);
129 } 142 }
@@ -72,6 +72,7 @@ public enum ErrorMessage { @@ -72,6 +72,7 @@ public enum ErrorMessage {
72 CRON_INVALID(400052,"cron表达式无效"), 72 CRON_INVALID(400052,"cron表达式无效"),
73 EXPORT_CONFIG_NON_EXISTENT(400053,"报表配置不存在或已被删除"), 73 EXPORT_CONFIG_NON_EXISTENT(400053,"报表配置不存在或已被删除"),
74 START_TIME_NOT_MORE_THAN_END_TIME(400054,"开始时间不能大于结束时间"), 74 START_TIME_NOT_MORE_THAN_END_TIME(400054,"开始时间不能大于结束时间"),
  75 + START_TIME_OR_END_TIME_EXCEPTION(400055,"开始时间或结束时间异常"),
75 HAVE_NO_PERMISSION(500002,"没有修改权限"); 76 HAVE_NO_PERMISSION(500002,"没有修改权限");
76 private final int code; 77 private final int code;
77 private String message; 78 private String message;
@@ -26,13 +26,15 @@ public class QueryConditionDTO { @@ -26,13 +26,15 @@ public class QueryConditionDTO {
26 @ApiModelProperty("启用/禁用遥测值到字符串的转换。默认情况下启用转换。设置参数为'true'以禁用转换") 26 @ApiModelProperty("启用/禁用遥测值到字符串的转换。默认情况下启用转换。设置参数为'true'以禁用转换")
27 private boolean useStrictDataTypes; 27 private boolean useStrictDataTypes;
28 28
29 - /** 数据周期:单位毫秒 */  
30 - @ApiModelProperty(value = "开始时间", required = true) 29 + @ApiModelProperty(value = "开始时间:单位毫秒", required = true)
31 @NotNull(message = "开始时间不能为空", groups = AddGroup.class) 30 @NotNull(message = "开始时间不能为空", groups = AddGroup.class)
32 private Long startTs; 31 private Long startTs;
33 32
34 - /** 时间间隔:单位毫秒 */  
35 - @ApiModelProperty(value = "结束时间", required = true) 33 + @ApiModelProperty(value = "结束时间:单位毫秒", required = true)
36 @NotNull(message = "结束时间不能为空", groups = AddGroup.class) 34 @NotNull(message = "结束时间不能为空", groups = AddGroup.class)
37 private Long endTs ; 35 private Long endTs ;
  36 +
  37 + @ApiModelProperty(value = "查询方式:0 周期查询 1自定查询", required = true)
  38 + @NotNull(message = "查询方式不能为空", groups = AddGroup.class)
  39 + private Integer queryMode;
38 } 40 }
@@ -156,7 +156,7 @@ public class YtReportGenerateRecordServiceImpl @@ -156,7 +156,7 @@ public class YtReportGenerateRecordServiceImpl
156 156
157 @Override 157 @Override
158 public void generateExcelUpdateReportRecord( 158 public void generateExcelUpdateReportRecord(
159 - ReportFormConfigDTO formConfigDTO, ExecuteAttributesDTO dto, String recordId,int surplus) { 159 + ReportFormConfigDTO formConfigDTO, ExecuteAttributesDTO dto, String recordId, int surplus) {
160 Long startTs = formConfigDTO.getQueryCondition().getStartTs(); 160 Long startTs = formConfigDTO.getQueryCondition().getStartTs();
161 Long endTs = formConfigDTO.getQueryCondition().getEndTs(); 161 Long endTs = formConfigDTO.getQueryCondition().getEndTs();
162 // 如果报表配置是定时执行,获取当前定时任务的执行时间,并计算新的开始时间、结束时间 162 // 如果报表配置是定时执行,获取当前定时任务的执行时间,并计算新的开始时间、结束时间
@@ -166,19 +166,18 @@ public class YtReportGenerateRecordServiceImpl @@ -166,19 +166,18 @@ public class YtReportGenerateRecordServiceImpl
166 long differenceTs = endTs - startTs; 166 long differenceTs = endTs - startTs;
167 endTs = recordDTO.getExecuteTime().toInstant(ZoneOffset.of("+8")).toEpochMilli(); 167 endTs = recordDTO.getExecuteTime().toInstant(ZoneOffset.of("+8")).toEpochMilli();
168 startTs = endTs - differenceTs; 168 startTs = endTs - differenceTs;
  169 + formConfigDTO.getQueryCondition().setStartTs(startTs);
  170 + formConfigDTO.getQueryCondition().setEndTs(endTs);
169 } 171 }
170 - Long finalStartTs = startTs;  
171 - Long finalEndTs = endTs;  
172 - getTsKvValuesOrGenerateExcel(null, formConfigDTO, finalStartTs, finalEndTs, dto, recordId,surplus); 172 + getTsKvValuesOrGenerateExcel(null, formConfigDTO, dto, recordId, surplus);
173 } 173 }
174 174
175 private void getTsKvValuesOrGenerateExcel( 175 private void getTsKvValuesOrGenerateExcel(
176 final DeferredResult<ResponseEntity> result, 176 final DeferredResult<ResponseEntity> result,
177 ReportFormConfigDTO formConfigDTO, 177 ReportFormConfigDTO formConfigDTO,
178 - Long finalStartTs,  
179 - Long finalEndTs,  
180 ExecuteAttributesDTO dto, 178 ExecuteAttributesDTO dto,
181 - String recordId,int surplus) { 179 + String recordId,
  180 + int surplus) {
182 QueryConditionDTO queryCondition = formConfigDTO.getQueryCondition(); 181 QueryConditionDTO queryCondition = formConfigDTO.getQueryCondition();
183 boolean useStrictDataTypes = queryCondition.isUseStrictDataTypes(); 182 boolean useStrictDataTypes = queryCondition.isUseStrictDataTypes();
184 Long interval = queryCondition.getInterval(); 183 Long interval = queryCondition.getInterval();
@@ -189,6 +188,8 @@ public class YtReportGenerateRecordServiceImpl @@ -189,6 +188,8 @@ public class YtReportGenerateRecordServiceImpl
189 DeviceId entityId = DeviceId.fromString(dto.getDevice()); 188 DeviceId entityId = DeviceId.fromString(dto.getDevice());
190 String reportTenantId = formConfigDTO.getTenantId(); 189 String reportTenantId = formConfigDTO.getTenantId();
191 TenantId tenantId = TenantId.fromUUID(UUID.fromString(reportTenantId)); 190 TenantId tenantId = TenantId.fromUUID(UUID.fromString(reportTenantId));
  191 + Long finalStartTs = queryCondition.getStartTs();
  192 + Long finalEndTs = queryCondition.getEndTs();
192 List<ReadTsKvQuery> queries = 193 List<ReadTsKvQuery> queries =
193 keys.stream() 194 keys.stream()
194 .map( 195 .map(
@@ -200,10 +201,11 @@ public class YtReportGenerateRecordServiceImpl @@ -200,10 +201,11 @@ public class YtReportGenerateRecordServiceImpl
200 queryCondition.setEndTs(finalEndTs); 201 queryCondition.setEndTs(finalEndTs);
201 ObjectNode executeCondition = JacksonUtil.newObjectNode(); 202 ObjectNode executeCondition = JacksonUtil.newObjectNode();
202 executeCondition.replace( 203 executeCondition.replace(
203 - FastIotConstants.CHART_EXECUTE_CONDITION, JacksonUtil.convertValue(queryCondition,JsonNode.class)); 204 + FastIotConstants.CHART_EXECUTE_CONDITION,
  205 + JacksonUtil.convertValue(queryCondition, JsonNode.class));
204 executeCondition.replace( 206 executeCondition.replace(
205 FastIotConstants.CHART_EXECUTE_ATTRIBUTES, 207 FastIotConstants.CHART_EXECUTE_ATTRIBUTES,
206 - JacksonUtil.convertValue(formConfigDTO.getExecuteAttributes(),JsonNode.class)); 208 + JacksonUtil.convertValue(formConfigDTO.getExecuteAttributes(), JsonNode.class));
207 Futures.addCallback( 209 Futures.addCallback(
208 tsService.findAll(tenantId, entityId, queries), 210 tsService.findAll(tenantId, entityId, queries),
209 getTsKvListCallback( 211 getTsKvListCallback(
@@ -213,7 +215,9 @@ public class YtReportGenerateRecordServiceImpl @@ -213,7 +215,9 @@ public class YtReportGenerateRecordServiceImpl
213 dto.getName(), 215 dto.getName(),
214 recordId, 216 recordId,
215 reportTenantId, 217 reportTenantId,
216 - executeCondition,surplus), 218 + executeCondition,
  219 + surplus,
  220 + keys),
217 MoreExecutors.directExecutor()); 221 MoreExecutors.directExecutor());
218 } 222 }
219 223
@@ -237,7 +241,9 @@ public class YtReportGenerateRecordServiceImpl @@ -237,7 +241,9 @@ public class YtReportGenerateRecordServiceImpl
237 String deviceName, 241 String deviceName,
238 String reportGenerateRecordId, 242 String reportGenerateRecordId,
239 String tenantId, 243 String tenantId,
240 - JsonNode executeCondition,int surplus) { 244 + JsonNode executeCondition,
  245 + int surplus,
  246 + List<String> keys) {
241 return new FutureCallback<>() { 247 return new FutureCallback<>() {
242 @Override 248 @Override
243 public void onSuccess(List<TsKvEntry> data) { 249 public void onSuccess(List<TsKvEntry> data) {
@@ -255,7 +261,9 @@ public class YtReportGenerateRecordServiceImpl @@ -255,7 +261,9 @@ public class YtReportGenerateRecordServiceImpl
255 result, 261 result,
256 reportGenerateRecordId, 262 reportGenerateRecordId,
257 tenantId, 263 tenantId,
258 - executeCondition,surplus); 264 + executeCondition,
  265 + surplus,
  266 + keys);
259 } else { 267 } else {
260 response.setResult(new ResponseEntity<>(result, HttpStatus.OK)); 268 response.setResult(new ResponseEntity<>(result, HttpStatus.OK));
261 } 269 }
@@ -282,39 +290,18 @@ public class YtReportGenerateRecordServiceImpl @@ -282,39 +290,18 @@ public class YtReportGenerateRecordServiceImpl
282 Map<String, List<BasicData>> result, 290 Map<String, List<BasicData>> result,
283 String reportGenerateRecordId, 291 String reportGenerateRecordId,
284 String tenantId, 292 String tenantId,
285 - JsonNode executeCondition,int surplus) { 293 + JsonNode executeCondition,
  294 + int surplus,
  295 + List<String> keys) {
286 List<List<String>> heads = new ArrayList<>(); 296 List<List<String>> heads = new ArrayList<>();
287 List<List<Object>> values = new ArrayList<>(); 297 List<List<Object>> values = new ArrayList<>();
288 - int firstKey = 0;  
289 - for (String key : result.keySet()) {  
290 - List<String> headValue = new ArrayList<>();  
291 - headValue.add(deviceName);  
292 - headValue.add(key + "采集值");  
293 - List<String> tsValue = new ArrayList<>();  
294 - tsValue.add(deviceName);  
295 - tsValue.add(key + "采集时间");  
296 - heads.add(headValue);  
297 - heads.add(tsValue);  
298 - List<BasicData> basicData = result.get(key);  
299 - for (int i = 0; i < basicData.size(); i++) {  
300 - BasicData item = basicData.get(i);  
301 - List<Object> listValue;  
302 - if (firstKey == 0) {  
303 - listValue = new ArrayList<>();  
304 - } else {  
305 - listValue = values.get(i);  
306 - }  
307 - Object value = item.getValue();  
308 - listValue.add(value);  
309 - DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");  
310 - Timestamp t = new Timestamp(item.getTs());  
311 - listValue.add(t.toLocalDateTime().format(dtf));  
312 - if (firstKey == 0) {  
313 - values.add(listValue);  
314 - } 298 + if (result.isEmpty()) {
  299 + for (String key : keys) {
  300 + List<BasicData> data = new ArrayList<>();
  301 + result.put(key, data);
315 } 302 }
316 - firstKey++;  
317 } 303 }
  304 + generateExcelHeadAndValues(result, deviceName, heads, values);
318 ByteArrayOutputStream byteArrayOutputStream = 305 ByteArrayOutputStream byteArrayOutputStream =
319 ExcelUtil.noModelWrite(reportFormName, heads, values); 306 ExcelUtil.noModelWrite(reportFormName, heads, values);
320 String fileName = reportFormName + System.currentTimeMillis() + ".xlsx"; 307 String fileName = reportFormName + System.currentTimeMillis() + ".xlsx";
@@ -340,11 +327,48 @@ public class YtReportGenerateRecordServiceImpl @@ -340,11 +327,48 @@ public class YtReportGenerateRecordServiceImpl
340 } else { 327 } else {
341 status = StatusEnum.FAIL.getIndex(); 328 status = StatusEnum.FAIL.getIndex();
342 } 329 }
343 - if(surplus == FastIotConstants.MagicNumber.ONE){ 330 + if (surplus == FastIotConstants.MagicNumber.ONE) {
344 recordDTO.setExecuteStatus(status); 331 recordDTO.setExecuteStatus(status);
345 } 332 }
346 recordDTO.setExecuteCondition(executeCondition); 333 recordDTO.setExecuteCondition(executeCondition);
347 saveOrUpdateReportGenerateRecord(recordDTO); 334 saveOrUpdateReportGenerateRecord(recordDTO);
348 } 335 }
349 } 336 }
  337 +
  338 + private void generateExcelHeadAndValues(
  339 + Map<String, List<BasicData>> result,
  340 + String deviceName,
  341 + List<List<String>> heads,
  342 + List<List<Object>> values) {
  343 + int firstKey = 0;
  344 + for (String key : result.keySet()) {
  345 + List<String> headValue = new ArrayList<>();
  346 + headValue.add(deviceName);
  347 + headValue.add(key + "采集值");
  348 + List<String> tsValue = new ArrayList<>();
  349 + tsValue.add(deviceName);
  350 + tsValue.add(key + "采集时间");
  351 + heads.add(headValue);
  352 + heads.add(tsValue);
  353 + List<BasicData> basicData = result.get(key);
  354 + for (int i = 0; i < basicData.size(); i++) {
  355 + BasicData item = basicData.get(i);
  356 + List<Object> listValue;
  357 + if (firstKey == 0) {
  358 + listValue = new ArrayList<>();
  359 + } else {
  360 + listValue = values.get(i);
  361 + }
  362 + Object value = item.getValue();
  363 + listValue.add(value);
  364 + DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
  365 + Timestamp t = new Timestamp(item.getTs());
  366 + listValue.add(t.toLocalDateTime().format(dtf));
  367 + if (firstKey == 0) {
  368 + values.add(listValue);
  369 + }
  370 + }
  371 + firstKey++;
  372 + }
  373 + }
350 } 374 }