Commit c13654b694e571ee9b4a6941c6b83bb194425545

Authored by 黄 x
1 parent 33b6d592

fix: fix bug [DEFECT-591]

Showing 18 changed files with 252 additions and 85 deletions
... ... @@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.yunteng.utils.tools.YtPageData;
23 23 import org.thingsboard.server.controller.BaseController;
24 24 import org.thingsboard.server.dao.yunteng.service.YtReportFormConfigService;
25 25
  26 +import java.sql.Timestamp;
26 27 import java.util.HashMap;
27 28
28 29 import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant.*;
... ... @@ -45,6 +46,8 @@ public class YtReportFormConfigController extends BaseController {
45 46 @RequestParam(value = "name", required = false) String name,
46 47 @RequestParam(value = "organizationId", required = false) String organizationId,
47 48 @RequestParam(value = "status", required = false) Integer status,
  49 + @RequestParam(value = "startTime", required = false) Long startTime,
  50 + @RequestParam(value = "endTime", required = false) Long endTime,
48 51 @RequestParam(value = ORDER_FILED, required = false) String orderBy,
49 52 @RequestParam(value = ORDER_TYPE, required = false) OrderTypeEnum orderType)
50 53 throws ThingsboardException {
... ... @@ -60,6 +63,14 @@ public class YtReportFormConfigController extends BaseController {
60 63 if (orderType != null) {
61 64 queryMap.put(ORDER_TYPE, orderType.name());
62 65 }
  66 + if (null != startTime && null != endTime) {
  67 + if (startTime > endTime) {
  68 + throw new YtDataValidationException(
  69 + ErrorMessage.START_TIME_NOT_MORE_THAN_END_TIME.getMessage());
  70 + }
  71 + queryMap.put("startTime", new Timestamp(startTime).toLocalDateTime());
  72 + queryMap.put("endTime", new Timestamp(endTime).toLocalDateTime());
  73 + }
63 74 return reportFormConfigService.page(queryMap);
64 75 }
65 76
... ...
1 1 package org.thingsboard.server.controller.yunteng;
2 2
  3 +import com.fasterxml.jackson.databind.JsonNode;
3 4 import io.swagger.annotations.Api;
  5 +import io.swagger.annotations.ApiOperation;
4 6 import lombok.RequiredArgsConstructor;
  7 +import org.springframework.http.ResponseEntity;
5 8 import org.springframework.security.access.prepost.PreAuthorize;
6 9 import org.springframework.validation.annotation.Validated;
7 10 import org.springframework.web.bind.annotation.*;
  11 +import org.thingsboard.common.util.JacksonUtil;
8 12 import org.thingsboard.server.common.data.exception.ThingsboardException;
9 13 import org.thingsboard.server.common.data.yunteng.common.DeleteGroup;
10 14 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
  15 +import org.thingsboard.server.common.data.yunteng.core.exception.YtDataValidationException;
  16 +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
11 17 import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO;
12 18 import org.thingsboard.server.common.data.yunteng.dto.ReportGenerateRecordDTO;
  19 +import org.thingsboard.server.common.data.yunteng.dto.request.ExecuteAttributesDTO;
  20 +import org.thingsboard.server.common.data.yunteng.dto.request.QueryConditionDTO;
13 21 import org.thingsboard.server.common.data.yunteng.enums.OrderTypeEnum;
14 22 import org.thingsboard.server.common.data.yunteng.utils.tools.ResponseResult;
15 23 import org.thingsboard.server.common.data.yunteng.utils.tools.YtPageData;
16 24 import org.thingsboard.server.controller.BaseController;
  25 +import org.thingsboard.server.dao.yunteng.service.YtReportFormConfigService;
17 26 import org.thingsboard.server.dao.yunteng.service.YtReportGenerateRecordService;
18 27
  28 +import java.sql.Timestamp;
  29 +import java.util.ArrayList;
19 30 import java.util.HashMap;
  31 +import java.util.List;
  32 +import java.util.Map;
20 33
21 34 import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant.*;
22 35
... ... @@ -28,18 +41,31 @@ import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant.
28 41 public class YtReportGenerateRecordController extends BaseController {
29 42
30 43 private final YtReportGenerateRecordService reportFormGenerateRecordService;
  44 + private final YtReportFormConfigService ytReportFormConfigService;
31 45
32 46 @GetMapping(params = {PAGE_SIZE, PAGE})
  47 + @ApiOperation("分页")
33 48 public YtPageData<ReportGenerateRecordDTO> page(
34   - @RequestParam(PAGE_SIZE) int pageSize,
35   - @RequestParam(PAGE) int page,
36   - @RequestParam(value = "reportConfigName", required = false) String reportConfigName,
37   - @RequestParam(value = "executeStatus", required = false) Integer executeStatus,
38   - @RequestParam(value = ORDER_FILED, required = false) String orderBy,
39   - @RequestParam(value = ORDER_TYPE, required = false) OrderTypeEnum orderType)
40   - throws ThingsboardException {
  49 + @RequestParam(PAGE_SIZE) int pageSize,
  50 + @RequestParam(PAGE) int page,
  51 + @RequestParam(value = "reportConfigName", required = false) String reportConfigName,
  52 + @RequestParam(value = "executeStatus", required = false) Integer executeStatus,
  53 + @RequestParam(value = "startTime", required = false) Long startTime,
  54 + @RequestParam(value = "endTime", required = false) Long endTime,
  55 + @RequestParam(value = ORDER_FILED, required = false) String orderBy,
  56 + @RequestParam(value = ORDER_TYPE, required = false) OrderTypeEnum orderType)
  57 + throws ThingsboardException {
41 58
42 59 HashMap<String, Object> queryMap = new HashMap<>();
  60 + if (null != startTime && null != endTime) {
  61 + if (startTime > endTime) {
  62 + throw new YtDataValidationException(
  63 + ErrorMessage.START_TIME_NOT_MORE_THAN_END_TIME.getMessage());
  64 + }
  65 +
  66 + queryMap.put("startTime", new Timestamp(startTime).toLocalDateTime());
  67 + queryMap.put("endTime", new Timestamp(endTime).toLocalDateTime());
  68 + }
43 69 queryMap.put(PAGE_SIZE, pageSize);
44 70 queryMap.put(PAGE, page);
45 71 queryMap.put(ORDER_FILED, orderBy);
... ... @@ -53,10 +79,34 @@ public class YtReportGenerateRecordController extends BaseController {
53 79 }
54 80
55 81 @DeleteMapping
  82 + @ApiOperation("删除")
56 83 public ResponseResult<Boolean> deleteReportGenerateRecord(
57   - @Validated({DeleteGroup.class}) @RequestBody DeleteDTO deleteDTO) {
  84 + @Validated({DeleteGroup.class}) @RequestBody DeleteDTO deleteDTO) {
58 85 return reportFormGenerateRecordService.deleteReportGenerateRecord(deleteDTO)
59   - ? ResponseResult.success(FastIotConstants.StateValue.DELETE_SUCCESS)
60   - : ResponseResult.failed(FastIotConstants.StateValue.DELETE_FAILED);
  86 + ? ResponseResult.success(FastIotConstants.StateValue.DELETE_SUCCESS)
  87 + : ResponseResult.failed(FastIotConstants.StateValue.DELETE_FAILED);
  88 + }
  89 +
  90 + @GetMapping("chart/{id}")
  91 + @ApiOperation("获取报表查询条件")
  92 + public ResponseEntity getChartQueryCondition(@PathVariable("id") String id)
  93 + throws ThingsboardException {
  94 +
  95 + Map<String, Object> map = new HashMap<>();
  96 + JsonNode json =
  97 + reportFormGenerateRecordService.getChartQueryCondition(
  98 + id, getCurrentUser().getCurrentTenantId());
  99 + if (json != null) {
  100 + QueryConditionDTO queryConditionDTO =
  101 + JacksonUtil.convertValue(
  102 + json.get(FastIotConstants.CHART_EXECUTE_CONDITION), QueryConditionDTO.class);
  103 + List<ExecuteAttributesDTO> list = new ArrayList<>();
  104 + ytReportFormConfigService.getExecuteConditionAndAttribute(
  105 + json.get(FastIotConstants.CHART_EXECUTE_ATTRIBUTES), list);
  106 +
  107 + map.put(FastIotConstants.CHART_EXECUTE_CONDITION, queryConditionDTO);
  108 + map.put(FastIotConstants.CHART_EXECUTE_ATTRIBUTES, list);
  109 + }
  110 + return ResponseEntity.ok(map);
61 111 }
62 112 }
... ...
... ... @@ -9,6 +9,8 @@ public interface FastIotConstants {
9 9 Integer MOBILE_TYPE = 0;
10 10 Integer PC_TYPE = 1;
11 11 String FIRST_PAGE_NAME = "第 1 页";
  12 + String CHART_EXECUTE_CONDITION = "executeCondition";
  13 + String CHART_EXECUTE_ATTRIBUTES = "executeAttributes";
12 14 class DefaultOrder {
13 15 public static final String CREATE_TIME="create_time";
14 16 }
... ...
... ... @@ -71,6 +71,7 @@ public enum ErrorMessage {
71 71 INVALID_PARAMETER_OR_NOT_MATCH_TENANT(400051,"参数错误或该条数据不属于当前租户"),
72 72 CRON_INVALID(400052,"cron表达式无效"),
73 73 EXPORT_CONFIG_NON_EXISTENT(400053,"报表配置不存在或已被删除"),
  74 + START_TIME_NOT_MORE_THAN_END_TIME(400054,"开始时间不能大于结束时间"),
74 75 HAVE_NO_PERMISSION(500002,"没有修改权限");
75 76 private final int code;
76 77 private String message;
... ...
1 1 package org.thingsboard.server.common.data.yunteng.dto;
  2 +
2 3 import io.swagger.annotations.ApiModel;
3 4 import io.swagger.annotations.ApiModelProperty;
4 5 import lombok.Data;
... ... @@ -38,25 +39,14 @@ public class ReportFormConfigDTO extends TenantDTO {
38 39
39 40 /** 设备:json数组格式 */
40 41 @ApiModelProperty(value = "执行设备及属性", required = true)
41   - @Size(message = "至少需要一个执行设备及属性", min = 1,groups = AddGroup.class)
  42 + @Size(message = "至少需要一个执行设备及属性", min = 1, groups = AddGroup.class)
42 43 private List<ExecuteAttributesDTO> executeAttributes;
43 44
44   -
45 45 /** 数据类型:0历史数据 1聚合数据 */
46 46 @ApiModelProperty(value = "数据类型:0原始数据 1聚合数据", required = true)
47 47 @NotNull(message = "数据类型不能为空", groups = AddGroup.class)
48 48 private Integer dataType;
49 49
50   - /** 数据周期:单位毫秒 */
51   - @ApiModelProperty(value = "开始时间", required = true)
52   - @NotNull(message = "开始时间不能为空", groups = AddGroup.class)
53   - private Long startTs;
54   -
55   - /** 时间间隔:单位毫秒 */
56   - @ApiModelProperty(value = "结束时间", required = true)
57   - @NotNull(message = "结束时间不能为空", groups = AddGroup.class)
58   - private Long endTs ;
59   -
60 50 @ApiModelProperty(value = "查询条件", required = true)
61 51 @NotNull(message = "查询条件不能为空", groups = AddGroup.class)
62 52 private QueryConditionDTO queryCondition;
... ...
1 1 package org.thingsboard.server.common.data.yunteng.dto;
2 2
3 3 import com.fasterxml.jackson.annotation.JsonFormat;
  4 +import com.fasterxml.jackson.databind.JsonNode;
4 5 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
5 6 import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
6 7 import io.swagger.annotations.ApiModelProperty;
... ... @@ -35,6 +36,9 @@ public class ReportGenerateRecordDTO extends TenantDTO {
35 36 @ApiModelProperty(value = "报表导出地址")
36 37 private String reportPath;
37 38
  39 + @ApiModelProperty(value = "执行条件")
  40 + private JsonNode executeCondition;
  41 +
38 42 @ApiModelProperty(value = "定时任务ID")
39 43 private String jobId;
40 44 }
... ...
... ... @@ -13,6 +13,9 @@ public class ChartReportDTO {
13 13 /** 报表查询:结束时间 */
14 14 private Long endTs;
15 15
  16 + /** 报表配置名称 */
  17 + private String reportFormName;
  18 +
16 19 /** 查询返回的数据 */
17 20 private List<ReportDataSourceDTO> data;
18 21 }
... ...
... ... @@ -4,6 +4,9 @@ import io.swagger.annotations.ApiModel;
4 4 import io.swagger.annotations.ApiModelProperty;
5 5 import lombok.Data;
6 6 import org.thingsboard.server.common.data.kv.Aggregation;
  7 +import org.thingsboard.server.common.data.yunteng.common.AddGroup;
  8 +
  9 +import javax.validation.constraints.NotNull;
7 10
8 11 @Data
9 12 @ApiModel(value = "查询条件")
... ... @@ -22,4 +25,14 @@ public class QueryConditionDTO {
22 25
23 26 @ApiModelProperty("启用/禁用遥测值到字符串的转换。默认情况下启用转换。设置参数为'true'以禁用转换")
24 27 private boolean useStrictDataTypes;
  28 +
  29 + /** 数据周期:单位毫秒 */
  30 + @ApiModelProperty(value = "开始时间", required = true)
  31 + @NotNull(message = "开始时间不能为空", groups = AddGroup.class)
  32 + private Long startTs;
  33 +
  34 + /** 时间间隔:单位毫秒 */
  35 + @ApiModelProperty(value = "结束时间", required = true)
  36 + @NotNull(message = "结束时间不能为空", groups = AddGroup.class)
  37 + private Long endTs ;
25 38 }
... ...
1 1 package org.thingsboard.server.dao.util.yunteng;
2 2
3 3 import org.apache.commons.lang3.StringUtils;
  4 +import org.thingsboard.server.common.data.yunteng.dto.ReportFormConfigDTO;
4 5 import org.thingsboard.server.common.data.yunteng.dto.ReportGenerateRecordDTO;
5 6 import org.thingsboard.server.common.data.yunteng.enums.JobGroupEnum;
6 7 import org.thingsboard.server.common.data.yunteng.utils.SpringBeanUtils;
7 8 import org.thingsboard.server.dao.yunteng.entities.SysJob;
  9 +import org.thingsboard.server.dao.yunteng.service.YtReportFormConfigService;
8 10 import org.thingsboard.server.dao.yunteng.service.YtReportGenerateRecordService;
9 11
10 12 import java.lang.reflect.InvocationTargetException;
... ... @@ -27,9 +29,12 @@ public class JobInvokeUtil {
27 29 if (StringUtils.isNotEmpty(sysJob.getSourceId())
28 30 && sysJob.getJobGroup().equals(JobGroupEnum.REPORT.toString())) {
29 31 // 写入报表生成记录
  32 + ReportFormConfigDTO formConfigDTO =
  33 + SpringBeanUtils.getBean(YtReportFormConfigService.class)
  34 + .findReportFormConfigById(sysJob.getSourceId(), sysJob.getTenantId());
30 35 ReportGenerateRecordDTO dto =
31 36 SpringBeanUtils.getBean(YtReportGenerateRecordService.class)
32   - .generateReportRecord(sysJob.getSourceId(), sysJob.getTenantId(), sysJob.getId());
  37 + .generateReportRecord(formConfigDTO, sysJob.getId());
33 38 reportGenerateRecordId = dto.getId();
34 39 }
35 40 List<Object[]> methodParams = getMethodParams(invokeTarget, reportGenerateRecordId);
... ...
... ... @@ -40,22 +40,28 @@ public class ReportTask {
40 40 if (dtoList.size() == FastIotConstants.MagicNumber.ONE) {
41 41 try {
42 42 ExecuteAttributesDTO attributesDTO = dtoList.get(0);
43   - getTsKvForGenerateExcel(formConfigDTO, attributesDTO, reportGenerateRecordId);
  43 + getTsKvForGenerateExcel(
  44 + formConfigDTO, attributesDTO, reportGenerateRecordId, dtoList.size());
44 45
45 46 } catch (Exception e) {
46 47 log.error(e.getMessage());
47 48 }
48 49 } else {
  50 + int surplus = dtoList.size();
49 51 for (ExecuteAttributesDTO dto : dtoList) {
50   - getTsKvForGenerateExcel(formConfigDTO, dto, reportGenerateRecordId);
  52 + getTsKvForGenerateExcel(formConfigDTO, dto, reportGenerateRecordId, surplus);
  53 + surplus--;
51 54 }
52 55 }
53 56 }
54 57 }
55 58
56 59 private void getTsKvForGenerateExcel(
57   - ReportFormConfigDTO formConfigDTO, ExecuteAttributesDTO dto, String reportGenerateRecordId) {
  60 + ReportFormConfigDTO formConfigDTO,
  61 + ExecuteAttributesDTO dto,
  62 + String reportGenerateRecordId,
  63 + int surplus) {
58 64 ytReportGenerateRecordService.generateExcelUpdateReportRecord(
59   - formConfigDTO, dto, reportGenerateRecordId);
  65 + formConfigDTO, dto, reportGenerateRecordId, surplus);
60 66 }
61 67 }
... ...
... ... @@ -36,12 +36,6 @@ public class ReportFormConfig extends TenantBaseEntity {
36 36 /** 数据对比:0原始数据 1聚合数据 */
37 37 private Integer dataType;
38 38
39   - /** 查询开始时间:单位毫秒 */
40   - private Long startTs;
41   -
42   - /** 查询结束时间:单位毫秒 */
43   - private Long endTs ;
44   -
45 39 @TableField(typeHandler = JacksonTypeHandler.class)
46 40 private JsonNode queryCondition;
47 41
... ...
1 1 package org.thingsboard.server.dao.yunteng.entities;
2 2
  3 +import com.baomidou.mybatisplus.annotation.TableField;
3 4 import com.baomidou.mybatisplus.annotation.TableName;
  5 +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
  6 +import com.fasterxml.jackson.databind.JsonNode;
4 7 import lombok.Data;
5 8 import lombok.EqualsAndHashCode;
6 9 import org.thingsboard.server.common.data.yunteng.constant.ModelConstants;
... ... @@ -32,6 +35,10 @@ public class ReportGenerateRecord extends TenantBaseEntity {
32 35 /** 报表导出地址 */
33 36 private String reportPath;
34 37
  38 + /** 执行条件 */
  39 + @TableField(typeHandler = JacksonTypeHandler.class)
  40 + private JsonNode executeCondition;
  41 +
35 42 /** 定时任务ID */
36 43 private String jobId;
37 44 }
... ...
... ... @@ -200,6 +200,10 @@ public class SysJobServiceImpl extends AbstractBaseService<SysJobMapper, SysJob>
200 200 } else {
201 201 SysJob job = baseMapper.selectById(jobDTO.getId());
202 202 SysJob newJob = jobDTO.getEntity(SysJob.class);
  203 + if (null == job) {
  204 + throw new YtDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage());
  205 + }
  206 + newJob.setSourceId(job.getSourceId());
203 207 baseMapper.updateById(newJob);
204 208 updateSchedulerJob(newJob, job.getJobGroup());
205 209 }
... ...
... ... @@ -26,7 +26,6 @@ import org.thingsboard.server.dao.yunteng.service.AbstractBaseService;
26 26 import org.thingsboard.server.dao.yunteng.service.YtReportFormConfigService;
27 27 import org.thingsboard.server.dao.yunteng.service.YtReportGenerateRecordService;
28 28 import org.thingsboard.server.dao.yunteng.service.YtSysJobService;
29   -
30 29 import java.util.*;
31 30 import java.util.stream.Collectors;
32 31
... ... @@ -176,8 +175,8 @@ public class YtReportFromConfigServiceImpl
176 175 if (isNowExecute) {
177 176 if (Objects.equals(reportFormConfig.getStatus(), StatusEnum.ENABLE.getIndex())) {
178 177 // 立即执行报表生成,并创建一条报表执行记录
179   - // 生成Excel,并更新报表执行记录
180   - generateExcelUpdateReportRecord(reportFormConfig.getDTO(ReportFormConfigDTO.class));
  178 + // 生成Excel,并更新报表执行记录;
  179 + generateExcelUpdateReportRecord(getDTOByReportFormConfig(reportFormConfig));
181 180 }
182 181 } else {
183 182 createSysJob(reportFormConfig);
... ... @@ -200,7 +199,7 @@ public class YtReportFromConfigServiceImpl
200 199 if (enableStatus) {
201 200 // 立即执行报表生成,并创建一条报表执行记录
202 201 // 生成Excel,并更新报表执行记录
203   - generateExcelUpdateReportRecord(reportFormConfig.getDTO(ReportFormConfigDTO.class));
  202 + generateExcelUpdateReportRecord(getDTOByReportFormConfig(reportFormConfig));
204 203 }
205 204 } else {
206 205 // 修改cron表达式
... ... @@ -213,7 +212,7 @@ public class YtReportFromConfigServiceImpl
213 212 if (enableStatus) {
214 213 // 立即执行报表生成,并创建一条报表执行记录
215 214 // 生成Excel,并更新报表执行记录
216   - generateExcelUpdateReportRecord(reportFormConfig.getDTO(ReportFormConfigDTO.class));
  215 + generateExcelUpdateReportRecord(getDTOByReportFormConfig(reportFormConfig));
217 216 }
218 217 } else {
219 218 createSysJob(reportFormConfig);
... ... @@ -267,21 +266,10 @@ public class YtReportFromConfigServiceImpl
267 266
268 267 private ReportFormConfigDTO getReportFormConfigDTOByEntity(ReportFormConfig obj) {
269 268 ReportFormConfigDTO dto = new ReportFormConfigDTO();
270   - obj.copyToDTO(dto, "executeAttributes");
  269 + obj.copyToDTO(dto, FastIotConstants.CHART_EXECUTE_ATTRIBUTES);
271 270 JsonNode jsonNode = obj.getExecuteAttributes();
272 271 List<ExecuteAttributesDTO> list = new ArrayList<>();
273   - for (JsonNode node : jsonNode) {
274   - ExecuteAttributesDTO attributesDTO =
275   - JacksonUtil.convertValue(node, ExecuteAttributesDTO.class);
276   - List<String> attributes = new ArrayList<>();
277   - JsonNode attribute = node.get("attributes");
278   - for (JsonNode key : attribute) {
279   - attributes.add(JacksonUtil.convertValue(key, String.class));
280   - }
281   - assert attributesDTO != null;
282   - attributesDTO.setAttributes(attributes);
283   - list.add(attributesDTO);
284   - }
  272 + getExecuteConditionAndAttribute(jsonNode, list);
285 273 QueryConditionDTO queryCondition =
286 274 JacksonUtil.convertValue(obj.getQueryCondition(), QueryConditionDTO.class);
287 275 dto.setExecuteAttributes(list);
... ... @@ -295,12 +283,42 @@ public class YtReportFromConfigServiceImpl
295 283 }
296 284 // 立即执行报表生成,并创建一条报表执行记录
297 285 ReportGenerateRecordDTO recordDTO =
298   - ytReportGenerateRecordService.generateReportRecord(
299   - reportFormConfigDTO.getId(), reportFormConfigDTO.getTenantId(), null);
  286 + ytReportGenerateRecordService.generateReportRecord(reportFormConfigDTO, null);
300 287 // 生成Excel,并更新报表执行记录
  288 + int surplus = reportFormConfigDTO.getExecuteAttributes().size();
301 289 for (ExecuteAttributesDTO dto : reportFormConfigDTO.getExecuteAttributes()) {
302 290 ytReportGenerateRecordService.generateExcelUpdateReportRecord(
303   - reportFormConfigDTO, dto, recordDTO.getId());
  291 + reportFormConfigDTO, dto, recordDTO.getId(), surplus);
  292 + surplus--;
  293 + }
  294 + }
  295 +
  296 + @Override
  297 + public void getExecuteConditionAndAttribute(
  298 + JsonNode attributeJsonNode, List<ExecuteAttributesDTO> list) {
  299 + if (attributeJsonNode.isArray()) {
  300 + for (JsonNode node : attributeJsonNode) {
  301 + ExecuteAttributesDTO attributesDTO =
  302 + JacksonUtil.convertValue(node, ExecuteAttributesDTO.class);
  303 + List<String> attributes = new ArrayList<>();
  304 + JsonNode attribute = node.get("attributes");
  305 + for (JsonNode key : attribute) {
  306 + attributes.add(JacksonUtil.convertValue(key, String.class));
  307 + }
  308 + assert attributesDTO != null;
  309 + attributesDTO.setAttributes(attributes);
  310 + list.add(attributesDTO);
  311 + }
304 312 }
305 313 }
  314 +
  315 + private ReportFormConfigDTO getDTOByReportFormConfig(ReportFormConfig reportFormConfig) {
  316 + ReportFormConfigDTO formConfigDTO = reportFormConfig.getDTO(ReportFormConfigDTO.class);
  317 + List<ExecuteAttributesDTO> list = new ArrayList<>();
  318 + getExecuteConditionAndAttribute(reportFormConfig.getExecuteAttributes(), list);
  319 + formConfigDTO.setExecuteAttributes(list);
  320 + formConfigDTO.setQueryCondition(
  321 + JacksonUtil.convertValue(reportFormConfig.getQueryCondition(), QueryConditionDTO.class));
  322 + return formConfigDTO;
  323 + }
306 324 }
... ...
... ... @@ -2,6 +2,8 @@ package org.thingsboard.server.dao.yunteng.impl;
2 2
3 3 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
4 4 import com.baomidou.mybatisplus.core.metadata.IPage;
  5 +import com.fasterxml.jackson.databind.JsonNode;
  6 +import com.fasterxml.jackson.databind.node.ObjectNode;
5 7 import com.google.common.util.concurrent.FutureCallback;
6 8 import com.google.common.util.concurrent.Futures;
7 9 import com.google.common.util.concurrent.MoreExecutors;
... ... @@ -36,7 +38,6 @@ import org.thingsboard.server.dao.yunteng.entities.ReportGenerateRecord;
36 38 import org.thingsboard.server.dao.yunteng.mapper.ReportGenerateRecordMapper;
37 39 import org.thingsboard.server.dao.yunteng.service.AbstractBaseService;
38 40 import org.thingsboard.server.dao.yunteng.service.YtOrganizationService;
39   -import org.thingsboard.server.dao.yunteng.service.YtReportFormConfigService;
40 41 import org.thingsboard.server.dao.yunteng.service.YtReportGenerateRecordService;
41 42
42 43 import java.io.ByteArrayInputStream;
... ... @@ -58,7 +59,6 @@ public class YtReportGenerateRecordServiceImpl
58 59
59 60 private static final String CONTENT_TYPE =
60 61 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
61   - private final YtReportFormConfigService ytReportFormConfigService;
62 62 private final YtOrganizationService ytOrganizationService;
63 63 private final TimeseriesService tsService;
64 64 private final FileStorageService fileStorageService;
... ... @@ -131,9 +131,7 @@ public class YtReportGenerateRecordServiceImpl
131 131
132 132 @Override
133 133 public ReportGenerateRecordDTO generateReportRecord(
134   - String sourceId, String tenantId, String jobId) {
135   - ReportFormConfigDTO reportFormConfigDTO =
136   - ytReportFormConfigService.findReportFormConfigById(sourceId, tenantId);
  134 + ReportFormConfigDTO reportFormConfigDTO, String jobId) {
137 135 if (null == reportFormConfigDTO) {
138 136 throw new YtDataValidationException(ErrorMessage.EXPORT_CONFIG_NON_EXISTENT.getMessage());
139 137 }
... ... @@ -158,9 +156,29 @@ public class YtReportGenerateRecordServiceImpl
158 156
159 157 @Override
160 158 public void generateExcelUpdateReportRecord(
161   - ReportFormConfigDTO formConfigDTO, ExecuteAttributesDTO dto, String recordId) {
162   - Long startTs = formConfigDTO.getStartTs();
163   - Long endTs = formConfigDTO.getEndTs();
  159 + ReportFormConfigDTO formConfigDTO, ExecuteAttributesDTO dto, String recordId,int surplus) {
  160 + Long startTs = formConfigDTO.getQueryCondition().getStartTs();
  161 + Long endTs = formConfigDTO.getQueryCondition().getEndTs();
  162 + // 如果报表配置是定时执行,获取当前定时任务的执行时间,并计算新的开始时间、结束时间
  163 + if (formConfigDTO.getExecuteWay() == FastIotConstants.MagicNumber.ONE) {
  164 + ReportGenerateRecordDTO recordDTO =
  165 + findReportGenerateRecordById(recordId, formConfigDTO.getTenantId());
  166 + long differenceTs = endTs - startTs;
  167 + endTs = recordDTO.getExecuteTime().toInstant(ZoneOffset.of("+8")).toEpochMilli();
  168 + startTs = endTs - differenceTs;
  169 + }
  170 + Long finalStartTs = startTs;
  171 + Long finalEndTs = endTs;
  172 + getTsKvValuesOrGenerateExcel(null, formConfigDTO, finalStartTs, finalEndTs, dto, recordId,surplus);
  173 + }
  174 +
  175 + private void getTsKvValuesOrGenerateExcel(
  176 + final DeferredResult<ResponseEntity> result,
  177 + ReportFormConfigDTO formConfigDTO,
  178 + Long finalStartTs,
  179 + Long finalEndTs,
  180 + ExecuteAttributesDTO dto,
  181 + String recordId,int surplus) {
164 182 QueryConditionDTO queryCondition = formConfigDTO.getQueryCondition();
165 183 boolean useStrictDataTypes = queryCondition.isUseStrictDataTypes();
166 184 Long interval = queryCondition.getInterval();
... ... @@ -171,15 +189,6 @@ public class YtReportGenerateRecordServiceImpl
171 189 DeviceId entityId = DeviceId.fromString(dto.getDevice());
172 190 String reportTenantId = formConfigDTO.getTenantId();
173 191 TenantId tenantId = TenantId.fromUUID(UUID.fromString(reportTenantId));
174   - final DeferredResult<ResponseEntity> result = new DeferredResult<>();
175   - // 如果报表配置是定时执行,获取当前定时任务的执行时间,并计算新的开始时间、结束时间
176   - if (formConfigDTO.getExecuteWay() == FastIotConstants.MagicNumber.ONE) {
177   - long differenceTs = endTs - startTs;
178   - endTs = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
179   - startTs = endTs - differenceTs;
180   - }
181   - Long finalStartTs = startTs;
182   - Long finalEndTs = endTs;
183 192 List<ReadTsKvQuery> queries =
184 193 keys.stream()
185 194 .map(
... ... @@ -187,7 +196,14 @@ public class YtReportGenerateRecordServiceImpl
187 196 new BaseReadTsKvQuery(
188 197 key, finalStartTs, finalEndTs, interval, limit, agg, orderBy))
189 198 .collect(Collectors.toList());
190   -
  199 + queryCondition.setStartTs(finalStartTs);
  200 + queryCondition.setEndTs(finalEndTs);
  201 + ObjectNode executeCondition = JacksonUtil.newObjectNode();
  202 + executeCondition.replace(
  203 + FastIotConstants.CHART_EXECUTE_CONDITION, JacksonUtil.convertValue(queryCondition,JsonNode.class));
  204 + executeCondition.replace(
  205 + FastIotConstants.CHART_EXECUTE_ATTRIBUTES,
  206 + JacksonUtil.convertValue(formConfigDTO.getExecuteAttributes(),JsonNode.class));
191 207 Futures.addCallback(
192 208 tsService.findAll(tenantId, entityId, queries),
193 209 getTsKvListCallback(
... ... @@ -196,17 +212,32 @@ public class YtReportGenerateRecordServiceImpl
196 212 formConfigDTO.getName(),
197 213 dto.getName(),
198 214 recordId,
199   - reportTenantId),
  215 + reportTenantId,
  216 + executeCondition,surplus),
200 217 MoreExecutors.directExecutor());
201 218 }
202 219
  220 + @Override
  221 + public JsonNode getChartQueryCondition(String id, String tenantId) {
  222 + ReportGenerateRecord record =
  223 + baseMapper.selectOne(
  224 + new LambdaQueryWrapper<ReportGenerateRecord>()
  225 + .eq(ReportGenerateRecord::getTenantId, tenantId)
  226 + .eq(ReportGenerateRecord::getId, id));
  227 + if (null == record) {
  228 + throw new YtDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage());
  229 + }
  230 + return record.getExecuteCondition();
  231 + }
  232 +
203 233 private FutureCallback<List<TsKvEntry>> getTsKvListCallback(
204 234 final DeferredResult<ResponseEntity> response,
205 235 Boolean useStrictDataTypes,
206 236 String reportFormName,
207 237 String deviceName,
208 238 String reportGenerateRecordId,
209   - String tenantId) {
  239 + String tenantId,
  240 + JsonNode executeCondition,int surplus) {
210 241 return new FutureCallback<>() {
211 242 @Override
212 243 public void onSuccess(List<TsKvEntry> data) {
... ... @@ -217,8 +248,17 @@ public class YtReportGenerateRecordServiceImpl
217 248 .computeIfAbsent(entry.getKey(), k -> new ArrayList<>())
218 249 .add(new BasicData(entry.getTs(), value));
219 250 }
220   - response.setResult(new ResponseEntity<>(result, HttpStatus.OK));
221   - generateExcel(deviceName, reportFormName, result, reportGenerateRecordId, tenantId);
  251 + if (null == response) {
  252 + generateExcel(
  253 + deviceName,
  254 + reportFormName,
  255 + result,
  256 + reportGenerateRecordId,
  257 + tenantId,
  258 + executeCondition,surplus);
  259 + } else {
  260 + response.setResult(new ResponseEntity<>(result, HttpStatus.OK));
  261 + }
222 262 }
223 263
224 264 @Override
... ... @@ -241,7 +281,8 @@ public class YtReportGenerateRecordServiceImpl
241 281 String reportFormName,
242 282 Map<String, List<BasicData>> result,
243 283 String reportGenerateRecordId,
244   - String tenantId) {
  284 + String tenantId,
  285 + JsonNode executeCondition,int surplus) {
245 286 List<List<String>> heads = new ArrayList<>();
246 287 List<List<Object>> values = new ArrayList<>();
247 288 int firstKey = 0;
... ... @@ -299,7 +340,10 @@ public class YtReportGenerateRecordServiceImpl
299 340 } else {
300 341 status = StatusEnum.FAIL.getIndex();
301 342 }
302   - recordDTO.setExecuteStatus(status);
  343 + if(surplus == FastIotConstants.MagicNumber.ONE){
  344 + recordDTO.setExecuteStatus(status);
  345 + }
  346 + recordDTO.setExecuteCondition(executeCondition);
303 347 saveOrUpdateReportGenerateRecord(recordDTO);
304 348 }
305 349 }
... ...
1 1 package org.thingsboard.server.dao.yunteng.service;
2 2
  3 +import com.fasterxml.jackson.databind.JsonNode;
3 4 import org.quartz.SchedulerException;
4 5 import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO;
5 6 import org.thingsboard.server.common.data.yunteng.dto.ReportFormConfigDTO;
  7 +import org.thingsboard.server.common.data.yunteng.dto.request.ExecuteAttributesDTO;
6 8 import org.thingsboard.server.common.data.yunteng.utils.tools.YtPageData;
7 9
  10 +import java.util.List;
8 11 import java.util.Map;
9 12
10 13 public interface YtReportFormConfigService {
... ... @@ -19,4 +22,6 @@ public interface YtReportFormConfigService {
19 22 ReportFormConfigDTO findReportFormConfigById(String id,String tenantId);
20 23
21 24 ReportFormConfigDTO findReportFormConfigById(String id);
  25 +
  26 + void getExecuteConditionAndAttribute(JsonNode attributeJsonNode, List<ExecuteAttributesDTO> list);
22 27 }
... ...
1 1 package org.thingsboard.server.dao.yunteng.service;
2 2
  3 +import com.fasterxml.jackson.databind.JsonNode;
3 4 import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO;
4 5 import org.thingsboard.server.common.data.yunteng.dto.ReportFormConfigDTO;
5 6 import org.thingsboard.server.common.data.yunteng.dto.ReportGenerateRecordDTO;
... ... @@ -21,18 +22,26 @@ public interface YtReportGenerateRecordService {
21 22 /**
22 23 * 根据报表配置ID及租户ID生成报表生成记录
23 24 *
24   - * @param sourceId 报表配置ID
25   - * @param tenantId 租户ID
  25 + * @param reportFormConfigDTO 报表配置信息
26 26 * @param jobId 定时任务ID(定时任务执行不能为空)
27 27 * @return 报表生成记录
28 28 */
29   - ReportGenerateRecordDTO generateReportRecord(String sourceId, String tenantId, String jobId);
  29 + ReportGenerateRecordDTO generateReportRecord(
  30 + ReportFormConfigDTO reportFormConfigDTO, String jobId);
30 31
31 32 /**
32 33 * 生成报表记录
  34 + *
33 35 * @param formConfigDTO 报表配置
34 36 * @param dto 执行属性
35 37 * @param recordId recordId 记录ID
  38 + * @param surplus 剩余执行次数
36 39 */
37   - void generateExcelUpdateReportRecord(ReportFormConfigDTO formConfigDTO, ExecuteAttributesDTO dto, String recordId);
  40 + void generateExcelUpdateReportRecord(
  41 + ReportFormConfigDTO formConfigDTO,
  42 + ExecuteAttributesDTO dto,
  43 + String recordId,
  44 + int surplus);
  45 +
  46 + JsonNode getChartQueryCondition(String id, String tenantId);
38 47 }
... ...
... ... @@ -9,8 +9,6 @@
9 9 <result property="executeWay" column="execute_way"/>
10 10 <result property="executeContent" column="execute_content"/>
11 11 <result property="dataType" column="data_type"/>
12   - <result property="startTs" column="start_ts"/>
13   - <result property="endTs" column="end_ts"/>
14 12 <result property="status" column="status"/>
15 13 <result property="remark" column="remark"/>
16 14 <result property="tenantId" column="tenant_id"/>
... ... @@ -26,7 +24,7 @@
26 24
27 25 <sql id="columns">
28 26 config.id,config.name,config.organization_id,config.execute_way,config.execute_content,
29   - config.data_type,config.start_ts,config.end_ts,config.status,config.remark,config.create_time,config.creator,
  27 + config.data_type,config.status,config.remark,config.create_time,config.creator,
30 28 config.updater,config.update_time,config.tenant_id
31 29 </sql>
32 30 <select id="getReportFormConfigPage" resultMap="formConfigDtoMap">
... ... @@ -48,6 +46,9 @@
48 46 #{organizationId}
49 47 </foreach>
50 48 </if>
  49 + <if test="queryMap.startTime !=null and queryMap.endTime !=null">
  50 + AND config.create_time &gt;= #{queryMap.startTime} AND config.create_time &lt; #{queryMap.endTime}
  51 + </if>
51 52 </where>
52 53 </select>
53 54 </mapper>
... ...