AbstractReportService.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. package com.huaxu.service;
  2. import ch.qos.logback.core.joran.conditional.ElseAction;
  3. import cn.hutool.core.collection.CollectionUtil;
  4. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  5. import com.baomidou.mybatisplus.core.metadata.IPage;
  6. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  7. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  8. import com.huaxu.common.StringUtils;
  9. import com.huaxu.dao.DeviceSceneMapper;
  10. import com.huaxu.dto.*;
  11. import com.huaxu.dto.scene.SceneIdDto;
  12. import com.huaxu.entity.DayReportEntity;
  13. import com.huaxu.entity.DeviceParmEntity;
  14. import com.huaxu.entity.MonitorDataEntity;
  15. import com.huaxu.entity.MonitorDataValueEntity;
  16. import com.huaxu.util.UserUtil;
  17. import org.springframework.beans.factory.annotation.Autowired;
  18. import java.math.BigDecimal;
  19. import java.math.RoundingMode;
  20. import java.text.SimpleDateFormat;
  21. import java.util.*;
  22. import java.util.stream.Collectors;
  23. /**
  24. * 报表业务处理
  25. * @author lihui
  26. * @date 2020-3-26
  27. */
  28. public abstract class AbstractReportService<M extends BaseMapper<T>, T> extends ServiceImpl {
  29. @Autowired
  30. protected SceneService sceneService;
  31. @Autowired
  32. protected DeviceService deviceService;
  33. @Autowired
  34. protected DeviceParmService deviceParmService;
  35. @Autowired
  36. protected DeviceSceneMapper deviceSceneMapper;
  37. /**
  38. * 报表数据处理
  39. * @param queryDto
  40. * @param devices
  41. * @param reportPage
  42. */
  43. public void reportDataHandle(ReportQueryDto queryDto, List<DeviceDto> devices, Page<ReportDto> reportPage, boolean isPipe){
  44. // 组装查询参数
  45. ReportDto reportDto = getQueryReportDto(queryDto, devices, isPipe);
  46. // 设置报表标题
  47. Map<String, Integer> mapsTitle = new LinkedHashMap<>();
  48. Map<String, ReportAttributeDto> mapsAttributeTitle = new LinkedHashMap<>();
  49. // 获取标题
  50. List<ReportTitleDto> reportTitleDtos = getReportTitle(reportDto, mapsTitle, mapsAttributeTitle,0);
  51. // 固定参数项
  52. List<ReportDto> reportList = findReport(reportDto);
  53. // 如果为空,把自定义表头返回回去
  54. if (CollectionUtil.isEmpty(reportPage.getRecords())){
  55. List<ReportDto> reportDtos = new ArrayList<>();
  56. ReportDto reportDto1 = new ReportDto();
  57. reportDto1.setReportTitle(reportTitleDtos);
  58. reportDtos.add(reportDto1);
  59. reportPage.setRecords(reportDtos);
  60. return;
  61. }
  62. int total = 0;
  63. // 单个属性值
  64. for (ReportDto item : reportPage.getRecords()) {
  65. item.setCollectDate(formateCollectDate(queryDto, item));
  66. item.setDeviceIds(devices);
  67. if (total == 0){
  68. item.setReportTitle(reportTitleDtos);
  69. }
  70. // 固定参数项
  71. calcUsage(item, reportList);
  72. Integer parentSceneId = item.getParentSceneId();
  73. item.setParentSceneId(null);
  74. //动态参数项
  75. List<ReportAttributeDto> reportAttributeDtos = this.findAttributeList(item);
  76. item.setParentSceneId(parentSceneId);
  77. Map<String, ReportAttributeDto> mapData = new LinkedHashMap<>();
  78. for (ReportAttributeDto itemData : reportAttributeDtos) {
  79. if (!mapData.containsKey(itemData.getDeviceParmId().toString())){
  80. mapData.put(itemData.getDeviceParmId().toString(), itemData);
  81. }
  82. }
  83. // 获取统计维度的值
  84. item.setDataMapValues(getStatisticalDimensionsValue(mapsTitle, mapData, mapsAttributeTitle));
  85. total ++;
  86. }
  87. }
  88. /**
  89. * 报表数据处理
  90. * @param queryDto
  91. * @param devices
  92. * @param reportPage
  93. */
  94. public void reportHistoryDataHandle(ReportQueryDto queryDto, List<DeviceDto> devices, Page<ReportDto> reportPage, Page<MonitorDataEntity> historyData , boolean isPipe) {
  95. // 组装查询参数
  96. ReportDto reportDto = getQueryReportDto(queryDto, devices, isPipe);
  97. // 设置报表标题
  98. Map<String, Integer> mapsTitle = new LinkedHashMap<>();
  99. Map<String, ReportAttributeDto> mapsAttributeTitle = new LinkedHashMap<>();
  100. // 获取标题
  101. List<ReportTitleDto> reportTitleDtos = getReportTitle(reportDto, mapsTitle, mapsAttributeTitle, 1);
  102. // 如果为空,把自定义表头返回回去
  103. reportPage.setSize(historyData.getSize());
  104. reportPage.setCurrent(historyData.getCurrent());
  105. reportPage.setTotal(historyData.getTotal());
  106. if (CollectionUtil.isEmpty(historyData.getRecords())) {
  107. List<ReportDto> reportDtos = new ArrayList<>();
  108. ReportDto reportDto1 = new ReportDto();
  109. reportDto1.setReportTitle(reportTitleDtos);
  110. reportDtos.add(reportDto1);
  111. reportPage.setRecords(reportDtos);
  112. return;
  113. }
  114. //获取场景名称
  115. String sceneName = "";
  116. if(!isPipe) {
  117. sceneName = sceneService.getById(queryDto.getIds()[0]).getSceneName();
  118. }
  119. int total = 0;
  120. // 单个属性值
  121. List<ReportDto> reportDtos = new LinkedList<>();
  122. for (MonitorDataEntity item : historyData.getRecords()) {
  123. ReportDto reportDtoTemp = new ReportDto();
  124. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  125. reportDtoTemp.setCollectDate(sdf.format(item.getCollectDate()));
  126. reportDtoTemp.setParentSceneName(sceneName);
  127. reportDtoTemp.setDeviceIds(devices);
  128. reportDtoTemp.setDeviceName(item.getDeviceName());
  129. if (total == 0) {
  130. reportDtoTemp.setReportTitle(reportTitleDtos);
  131. }
  132. //动态参数项
  133. Map<String, ReportAttributeDto> mapData = new LinkedHashMap<>();
  134. for (MonitorDataValueEntity itemData : item.getDataValues()) {
  135. if (!mapData.containsKey(itemData.getAttributeId().toString())) {
  136. ReportAttributeDto itemData2 = new ReportAttributeDto();
  137. itemData2.setAttributeName(itemData.getAttributeName());
  138. itemData2.setLatestValue(itemData.getDataValue());
  139. mapData.put(itemData.getAttributeId().toString(), itemData2);
  140. }
  141. }
  142. // 获取统计维度的值
  143. reportDtoTemp.setDataMapValues(getStatisticalDimensionsValue(mapsTitle, mapData, mapsAttributeTitle));
  144. reportDtos.add(reportDtoTemp);
  145. total++;
  146. }
  147. reportPage.setRecords(reportDtos);
  148. }
  149. /**
  150. * 查询场景下的所有设备信息
  151. * @param ids 场景ID
  152. * @return
  153. */
  154. public List<DeviceDto> findDevices(Long[] ids){
  155. List<DeviceDto> devices = new ArrayList<>();
  156. DeviceDto deviceDto = new DeviceDto();
  157. for (Long id : ids) {
  158. deviceDto.setSceneIds(sceneService.findByParentIdsLike(id));
  159. if (deviceDto.getSceneIds().size() > 0){
  160. devices.addAll(deviceService.selectList(deviceDto));
  161. }
  162. }
  163. return devices;
  164. }
  165. /**
  166. * ids转换场景集合对象
  167. * @param ids 场景ID
  168. * @return
  169. */
  170. public List<DeviceDto> devicesToList(Long[] ids){
  171. List<DeviceDto> devices = new ArrayList<>();
  172. for (Long id : ids) {
  173. DeviceDto deviceDto = new DeviceDto();
  174. deviceDto.setId(id);
  175. devices.add(deviceDto);
  176. }
  177. return devices;
  178. }
  179. /**
  180. * 1000汇算
  181. * @param value
  182. * @return
  183. */
  184. public double doubleRoundValue(double value){
  185. return (double) Math.round(value * 1000) / 1000;
  186. }
  187. /**
  188. * @Author lihui
  189. * @Description 单位除以一万,保留3位小数
  190. * @Date 14:18 2021/4/28
  191. * @Param [value]
  192. * @return double
  193. **/
  194. public double doubleDivideValue(double value){
  195. return new BigDecimal(value).divide(BigDecimal.valueOf(10000), 3, RoundingMode.HALF_UP).doubleValue();
  196. }
  197. /**
  198. * 组装参数
  199. * @param queryDto
  200. * @param devices
  201. * @return
  202. */
  203. public ReportDto getQueryReportDto(ReportQueryDto queryDto, List<DeviceDto> devices, boolean isPipe){
  204. ReportDto reportDto = new ReportDto();
  205. reportDto.setYear(queryDto.getYear());
  206. reportDto.setMonth(queryDto.getMonth());
  207. reportDto.setDay(queryDto.getDay());
  208. if (isPipe){
  209. String name = queryDto.getType() == 1 ? "压力" : ((queryDto.getType() == 2) ? "流量" : "水质");
  210. SceneIdDto sceneIdDto = deviceSceneMapper.findSceneId("管网",name, queryDto.getIds()[0]);
  211. if (sceneIdDto != null){
  212. reportDto.setSceneId(sceneIdDto.getSceneId());
  213. }
  214. reportDto.setDeviceIds(devices);
  215. } else {
  216. reportDto.setDeviceIds(devices);
  217. reportDto.setParentSceneIds(queryDto.getIds());
  218. }
  219. reportDto.setUserId(UserUtil.getCurrentUser().getId());
  220. reportDto.setStartTime(queryDto.getStartTime());
  221. reportDto.setEndTime(queryDto.getEndTime());
  222. return reportDto;
  223. }
  224. //根据设备ID查询报表测点信息
  225. protected ReportPageQueryDto getReportPageQuery(ReportQueryDto queryDto, List<DeviceDto> devices, boolean isPipe){
  226. ReportPageQueryDto dto = new ReportPageQueryDto();
  227. dto.setYear(queryDto.getYear());
  228. dto.setMonth(queryDto.getMonth());
  229. dto.setDay(queryDto.getDay());
  230. dto.setTenantId(UserUtil.getCurrentUser().getTenantId());
  231. dto.setDeviceIds(devices);
  232. // 管网和其他有点不一样
  233. if (isPipe){
  234. dto.setType(queryDto.getType());
  235. String name = queryDto.getType() == 1 ? "压力" : ((queryDto.getType() == 2) ? "流量" : "水质");
  236. SceneIdDto sceneIdDto = deviceSceneMapper.findSceneId("管网",name, queryDto.getIds()[0]);
  237. if (sceneIdDto != null){
  238. dto.setSceneId(sceneIdDto.getSceneId());
  239. }
  240. } else {
  241. // 管网不需要场景
  242. dto.setParentSceneIds(queryDto.getIds());
  243. }
  244. dto.setStartTime(queryDto.getStartTime());
  245. dto.setEndTime(queryDto.getEndTime());
  246. return dto;
  247. }
  248. /**
  249. * 获取报表标题
  250. * @param reportDto
  251. * @param mapsTitle
  252. * @param mapsAttributeTitle
  253. * @return
  254. */
  255. public List<ReportTitleDto> getReportTitle(ReportDto reportDto, Map<String, Integer> mapsTitle,
  256. Map<String, ReportAttributeDto> mapsAttributeTitle,int reportType){
  257. // 设置标题
  258. Map<String, ReportTitleDto> deviceChildrenMap = new HashMap<>();
  259. List<ReportAttributeDto> reportAttributeDtos2 = new LinkedList<>();
  260. if(reportType==0) {
  261. reportAttributeDtos2= deviceParmService.findAttributeNameList(reportDto);
  262. }else {
  263. reportAttributeDtos2 = deviceParmService.findHistoryDataAttributeNameList(reportDto);
  264. }
  265. int numCount = 0;
  266. for (ReportAttributeDto reportAttributeDto : reportAttributeDtos2) {
  267. // 判断开关是否开启
  268. if (reportAttributeDto.isShowOnOff()){
  269. setReportTitle(reportAttributeDto, deviceChildrenMap);
  270. mapsAttributeTitle.put(reportAttributeDto.getDeviceParmId().toString(),reportAttributeDto);
  271. }
  272. }
  273. // 转换list返回
  274. List<ReportTitleDto> resultList = deviceChildrenMap.values().stream().collect(Collectors.toList());
  275. for (ReportTitleDto reportTitleDto : resultList) {
  276. List<ReportTitleDto.DeviceChildren> childrenList = reportTitleDto.getDeviceChildren();
  277. for (ReportTitleDto.DeviceChildren children : childrenList) {
  278. mapsTitle.put(children.getParamId(), numCount++);
  279. }
  280. }
  281. return resultList;
  282. }
  283. /**
  284. * 获取统计维度的值
  285. * @param mapsTitle
  286. * @param mapData
  287. * @param mapsAttributeTitle
  288. * @return
  289. */
  290. public List<Map<String, Object>> getStatisticalDimensionsValue( Map<String, Integer> mapsTitle, Map<String, ReportAttributeDto> mapData,
  291. Map<String, ReportAttributeDto> mapsAttributeTitle){
  292. // 判断是否有需要展示的字段
  293. boolean haveShowTitle = false;
  294. List<Map<String, Object>> dataMapValues = new ArrayList<>();
  295. for (String key : mapsTitle.keySet()) {
  296. ReportAttributeDto reportAttributeDto = mapsAttributeTitle.get(key);
  297. // 过滤掉没有开启开关的
  298. if (reportAttributeDto == null || !reportAttributeDto.isShowOnOff()) {
  299. continue;
  300. }
  301. Map<String, Object> map = new LinkedHashMap<>();
  302. map.put("attributeName", mapData.get(key) == null ? key : mapData.get(key).getAttributeName());
  303. if (reportAttributeDto.isShowMaxValue()) {
  304. map.put("maxValue" + mapsTitle.get(key), mapData.get(key) == null || mapData.get(key).getMaxValue() == null ?
  305. "-" : doubleRoundValue(mapData.get(key).getMaxValue()));
  306. haveShowTitle = true;
  307. }
  308. if (reportAttributeDto.isShowMinValue()) {
  309. map.put("minValue" + mapsTitle.get(key), mapData.get(key) == null || mapData.get(key).getMinValue() == null ?
  310. "-" : doubleRoundValue(mapData.get(key).getMinValue()));
  311. haveShowTitle = true;
  312. }
  313. if (reportAttributeDto.isShowSumValue()) {
  314. map.put("sumValue" + mapsTitle.get(key), mapData.get(key) == null || mapData.get(key).getSumValue() == null ?
  315. "-" : doubleRoundValue(mapData.get(key).getSumValue()));
  316. haveShowTitle = true;
  317. }
  318. if (reportAttributeDto.isShowLatestValue()) {
  319. map.put("latestValue" + mapsTitle.get(key), mapData.get(key) == null || mapData.get(key).getLatestValue() == null ?
  320. "-" : doubleRoundValue(mapData.get(key).getLatestValue()));
  321. haveShowTitle = true;
  322. }
  323. if (reportAttributeDto.isShowAvgValue()) {
  324. map.put("avgValue" + mapsTitle.get(key), mapData.get(key) == null || mapData.get(key).getAvgValue() == null ?
  325. "-" : doubleRoundValue(mapData.get(key).getAvgValue()));
  326. haveShowTitle = true;
  327. }
  328. if (!haveShowTitle){
  329. continue;
  330. }
  331. haveShowTitle = false;
  332. dataMapValues.add(map);
  333. }
  334. return dataMapValues;
  335. }
  336. /**
  337. * 设置报表标题
  338. * @param v
  339. * @param deviceChildrenMap
  340. */
  341. private void setReportTitle(ReportAttributeDto v, Map<String, ReportTitleDto> deviceChildrenMap){
  342. String classify = StringUtils.isEmpty(v.getClassify()) ? v.getAttributeName() + v.getDeviceParmId() + "isNull" : v.getClassify();
  343. ReportTitleDto reportTitleDto = deviceChildrenMap.get(classify);
  344. if (reportTitleDto == null) {
  345. reportTitleDto = new ReportTitleDto();
  346. reportTitleDto.setClassify(classify);
  347. }
  348. List<ReportTitleDto.DeviceChildren> deviceChildrenList = reportTitleDto.getDeviceChildren();
  349. if (CollectionUtil.isEmpty(deviceChildrenList)){
  350. deviceChildrenList = new ArrayList<>();
  351. }
  352. String unit = StringUtils.isEmpty(v.getUnit()) ? "" : "("+v.getUnit()+")";
  353. ReportTitleDto.DeviceChildren deviceChildren = new ReportTitleDto.DeviceChildren();
  354. deviceChildren.setName(v.getAttributeName() + unit);
  355. deviceChildren.setParamId(v.getDeviceParmId().toString());
  356. // 检查是否有设置维度
  357. List<ReportTitleDto.StatisticalDimension> statisticalDimensions = new ArrayList<>();
  358. if (v.isShowMaxValue()){
  359. statisticalDimensions.add(getStatisticalDimension("showMaxValue", "最大值"));
  360. }
  361. if (v.isShowMinValue()){
  362. statisticalDimensions.add(getStatisticalDimension("showMinValue", "最小值"));
  363. }
  364. if (v.isShowSumValue()){
  365. statisticalDimensions.add(getStatisticalDimension("showSumValue", "合计值"));
  366. }
  367. if (v.isShowLatestValue()){
  368. statisticalDimensions.add(getStatisticalDimension("showLatestValue", "最新值"));
  369. }
  370. if (v.isShowAvgValue()){
  371. statisticalDimensions.add(getStatisticalDimension("showAvgValue", "平均值"));
  372. }
  373. // 有设置维度,添加相关信息
  374. if (v.isShowMaxValue() || v.isShowMinValue() || v.isShowSumValue() || v.isShowLatestValue()
  375. || v.isShowAvgValue()){
  376. deviceChildren.setDimensionList(statisticalDimensions);
  377. deviceChildrenList.add(deviceChildren);
  378. reportTitleDto.setDeviceChildren(deviceChildrenList);
  379. deviceChildrenMap.put(classify, reportTitleDto);
  380. }
  381. }
  382. /**
  383. * 获取统计维度
  384. * @param key
  385. * @param name
  386. * @return
  387. */
  388. private ReportTitleDto.StatisticalDimension getStatisticalDimension(String key, String name){
  389. ReportTitleDto.StatisticalDimension statisticalDimension = new ReportTitleDto.StatisticalDimension();
  390. statisticalDimension.setDimensionKey(key);
  391. statisticalDimension.setDimensionName(name);
  392. return statisticalDimension;
  393. }
  394. /**
  395. * @Author lihui
  396. * @Description 格式化日期
  397. * @Date 16:38 2021/4/15
  398. * @Param [queryDto, item]
  399. * @return java.lang.String
  400. **/
  401. private String formateCollectDate(ReportQueryDto queryDto, ReportDto item){
  402. // 0日 1月 2年
  403. if (queryDto.getReportType() == 0) {
  404. return item.getYear() + "-" + String.format("%02d", item.getMonth()) + "-" + String.format("%02d", item.getDay()) + " " + String.format("%02d", item.getHour()) + ":00:00";
  405. }
  406. if (queryDto.getReportType() == 1 || queryDto.getReportType() == 3) {
  407. return item.getYear() + "-" + String.format("%02d", item.getMonth()) + "-" + String.format("%02d", item.getDay());
  408. }
  409. if (queryDto.getReportType() == 2) {
  410. return item.getYear() + "-" + String.format("%02d", item.getMonth());
  411. }
  412. return null;
  413. }
  414. /**
  415. * 查询报表
  416. * @param reportDto
  417. * @return
  418. */
  419. abstract List<ReportDto> findReport(ReportDto reportDto);
  420. /**
  421. * 计算值
  422. * @param item
  423. * @param reportDtos
  424. */
  425. abstract void calcUsage(ReportDto item, List<ReportDto> reportDtos);
  426. /**
  427. * 查询属性
  428. * @param item
  429. * @return
  430. */
  431. abstract List<ReportAttributeDto> findAttributeList(ReportDto item);
  432. }