InfraredReadingMeterServiceImpl.java 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. package com.zksy.infrared.service.impl;
  2. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  3. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  4. import com.zksy.common.exception.CommonException;
  5. import com.zksy.infrared.domain.CompanyElectric;
  6. import com.zksy.infrared.domain.InfraredReadingMeter;
  7. import com.zksy.infrared.domain.vo.MeterDayDataVo;
  8. import com.zksy.infrared.domain.vo.MeterMonthDataVo;
  9. import com.zksy.infrared.domain.vo.MeterQuarterDataVo;
  10. import com.zksy.infrared.domain.vo.MeterYearDataVo;
  11. import com.zksy.infrared.service.CompanyElectricService;
  12. import com.zksy.infrared.service.InfraredReadingMeterService;
  13. import com.zksy.infrared.mapper.InfraredReadingMeterMapper;
  14. import org.springframework.beans.factory.annotation.Autowired;
  15. import org.springframework.stereotype.Service;
  16. import java.math.BigDecimal;
  17. import java.math.RoundingMode;
  18. import java.time.*;
  19. import java.util.*;
  20. import java.util.stream.Collectors;
  21. /**
  22. * @author Administrator
  23. * @description 针对表【infrared_reading_meter(红外读电表数据)】的数据库操作Service实现
  24. * @createDate 2025-06-06 10:27:47
  25. */
  26. @Service
  27. public class InfraredReadingMeterServiceImpl extends ServiceImpl<InfraredReadingMeterMapper, InfraredReadingMeter>
  28. implements InfraredReadingMeterService {
  29. // 工具方法:生成默认月数据列表
  30. private static final List<BigDecimal> DEFAULT_MONTH_LIST = Collections.nCopies(12, BigDecimal.ZERO);
  31. // 工具方法:生成默认日数据列表
  32. private static final List<BigDecimal> DEFAULT_DAY_LIST = Collections.nCopies(31, BigDecimal.ZERO);
  33. // 工具方法:生成默认季数据列表
  34. private static final List<BigDecimal> DEFAULT_QUARTER_LIST = Collections.nCopies(3, new BigDecimal("0.00"));
  35. @Autowired
  36. private CompanyElectricService companyElectricService;
  37. @Override
  38. public MeterYearDataVo selectByYear(Integer year, String meterNumber) {
  39. if (year == null || year < 0 || year > 9999) {
  40. throw new CommonException("年份无效", 400);
  41. }
  42. LocalDate firstDayOfYear = LocalDate.of(year, 1, 1);
  43. LocalDate lastDayOfYear = LocalDate.of(year, 12, 31);
  44. LocalDateTime startOfDay = firstDayOfYear.atStartOfDay();
  45. LocalDateTime endOfDay = lastDayOfYear.atTime(LocalTime.MAX);
  46. LambdaQueryWrapper<InfraredReadingMeter> wrapper = new LambdaQueryWrapper<>();
  47. wrapper.eq(InfraredReadingMeter::getElectricNumber, meterNumber)
  48. .between(InfraredReadingMeter::getCreateTime, startOfDay, endOfDay)
  49. .orderByAsc(InfraredReadingMeter::getCreateTime);
  50. List<InfraredReadingMeter> list = this.list(wrapper);
  51. if (list == null || list.size() < 2) {
  52. return new MeterYearDataVo(BigDecimal.ZERO, new ArrayList<>(DEFAULT_MONTH_LIST));
  53. }
  54. BigDecimal firstValue = BigDecimal.valueOf(list.get(0).getElectricEnergy());
  55. BigDecimal lastValue = BigDecimal.valueOf(list.get(list.size() - 1).getElectricEnergy());
  56. Map<Integer, List<InfraredReadingMeter>> groupedByMonth = list.stream()
  57. .collect(Collectors.groupingBy(item -> {
  58. LocalDate date = item.getCreateTime().toInstant()
  59. .atZone(ZoneId.systemDefault())
  60. .toLocalDate();
  61. return date.getMonthValue();
  62. }));
  63. List<Integer> months = new ArrayList<>(groupedByMonth.keySet());
  64. Collections.sort(months);
  65. List<BigDecimal> monthDataList = new ArrayList<>(DEFAULT_MONTH_LIST);
  66. for (int i = 0; i < months.size(); i++) {
  67. Integer currentMonth = months.get(i);
  68. List<InfraredReadingMeter> meters = groupedByMonth.get(currentMonth);
  69. if (!meters.isEmpty()) {
  70. BigDecimal start = BigDecimal.valueOf(meters.get(0).getElectricEnergy());
  71. BigDecimal end;
  72. if (i < months.size() - 1) {
  73. Integer nextMonth = months.get(i + 1);
  74. List<InfraredReadingMeter> nextMeters = groupedByMonth.get(nextMonth);
  75. end = !nextMeters.isEmpty()
  76. ? BigDecimal.valueOf(nextMeters.get(0).getElectricEnergy())
  77. : BigDecimal.valueOf(meters.get(meters.size() - 1).getElectricEnergy());
  78. } else {
  79. end = BigDecimal.valueOf(meters.get(meters.size() - 1).getElectricEnergy());
  80. }
  81. monthDataList.set(currentMonth - 1, end.subtract(start));
  82. }
  83. }
  84. return new MeterYearDataVo(lastValue.subtract(firstValue), monthDataList);
  85. }
  86. @Override
  87. public MeterMonthDataVo selectByYearselectByYearAndMonthWithDayData(Integer year, Integer month, String meterNumber) {
  88. if (year == null || month == null || year < 0 || year > 9999 || month < 1 || month > 12) {
  89. throw new CommonException("年份或月份无效", 400);
  90. }
  91. LocalDate firstDayOfMonth = LocalDate.of(year, month, 1);
  92. LocalDate lastDayOfMonth = firstDayOfMonth.withDayOfMonth(firstDayOfMonth.lengthOfMonth());
  93. LocalDateTime startOfDay = firstDayOfMonth.atStartOfDay();
  94. LocalDateTime endOfDay = lastDayOfMonth.atTime(LocalTime.MAX);
  95. LambdaQueryWrapper<InfraredReadingMeter> wrapper = new LambdaQueryWrapper<>();
  96. wrapper.eq(InfraredReadingMeter::getElectricNumber, meterNumber)
  97. .between(InfraredReadingMeter::getCreateTime, startOfDay, endOfDay)
  98. .orderByAsc(InfraredReadingMeter::getCreateTime);
  99. List<InfraredReadingMeter> list = this.list(wrapper);
  100. if (list == null || list.size() < 2) {
  101. return new MeterMonthDataVo(BigDecimal.ZERO, new ArrayList<>(DEFAULT_DAY_LIST));
  102. }
  103. BigDecimal firstValue = BigDecimal.valueOf(list.get(0).getElectricEnergy());
  104. BigDecimal lastValue = BigDecimal.valueOf(list.get(list.size() - 1).getElectricEnergy());
  105. Map<Integer, List<InfraredReadingMeter>> groupedByDay = list.stream()
  106. .collect(Collectors.groupingBy(item -> {
  107. LocalDate date = item.getCreateTime().toInstant()
  108. .atZone(ZoneId.systemDefault())
  109. .toLocalDate();
  110. return date.getDayOfMonth();
  111. }));
  112. List<Integer> days = new ArrayList<>(groupedByDay.keySet());
  113. Collections.sort(days);
  114. List<BigDecimal> dayDataList = new ArrayList<>(DEFAULT_DAY_LIST);
  115. for (int i = 0; i < days.size(); i++) {
  116. Integer currentDay = days.get(i);
  117. List<InfraredReadingMeter> currentMeters = groupedByDay.get(currentDay);
  118. if (!currentMeters.isEmpty()) {
  119. BigDecimal start = BigDecimal.valueOf(currentMeters.get(0).getElectricEnergy());
  120. BigDecimal end;
  121. if (i < days.size() - 1) {
  122. Integer nextDay = days.get(i + 1);
  123. List<InfraredReadingMeter> nextMeters = groupedByDay.get(nextDay);
  124. end = !nextMeters.isEmpty()
  125. ? BigDecimal.valueOf(nextMeters.get(0).getElectricEnergy())
  126. : BigDecimal.valueOf(currentMeters.get(currentMeters.size() - 1).getElectricEnergy());
  127. } else {
  128. end = BigDecimal.valueOf(currentMeters.get(currentMeters.size() - 1).getElectricEnergy());
  129. }
  130. dayDataList.set(currentDay - 1, end.subtract(start));
  131. }
  132. }
  133. return new MeterMonthDataVo(lastValue.subtract(firstValue), dayDataList);
  134. }
  135. @Override
  136. public MeterDayDataVo selectByNewestData(String meterNumber) {
  137. if (meterNumber == null || meterNumber.isEmpty()) {
  138. throw new CommonException("电表编号不能为空", 400);
  139. }
  140. LocalDate today = LocalDate.now();
  141. LocalDateTime startOfDay = today.atStartOfDay();
  142. LocalDateTime endOfDay = today.atTime(LocalTime.MAX);
  143. LambdaQueryWrapper<InfraredReadingMeter> wrapper = new LambdaQueryWrapper<>();
  144. wrapper.eq(InfraredReadingMeter::getElectricNumber, meterNumber)
  145. .between(InfraredReadingMeter::getCreateTime, startOfDay, endOfDay)
  146. .orderByAsc(InfraredReadingMeter::getCreateTime);
  147. List<InfraredReadingMeter> list = this.list(wrapper);
  148. if (list == null || list.size() < 2) {
  149. return new MeterDayDataVo(BigDecimal.ZERO);
  150. }
  151. BigDecimal firstValue = BigDecimal.valueOf(list.get(0).getElectricEnergy());
  152. BigDecimal lastValue = BigDecimal.valueOf(list.get(list.size() - 1).getElectricEnergy());
  153. return new MeterDayDataVo(lastValue.subtract(firstValue));
  154. }
  155. @Override
  156. public MeterYearDataVo selectByCurrentYearData() {
  157. log.warn("按照年统计电表");
  158. int currentYear = LocalDate.now().getYear();
  159. LocalDate firstDayOfYear = LocalDate.of(currentYear, 1, 1);
  160. LocalDate lastDayOfYear = LocalDate.of(currentYear, 12, 31);
  161. LocalDateTime startOfDay = firstDayOfYear.atStartOfDay();
  162. LocalDateTime endOfDay = lastDayOfYear.atTime(LocalTime.MAX);
  163. LambdaQueryWrapper<InfraredReadingMeter> wrapper = new LambdaQueryWrapper<InfraredReadingMeter>()
  164. .between(InfraredReadingMeter::getCreateTime, startOfDay, endOfDay)
  165. .orderByAsc(InfraredReadingMeter::getCreateTime);
  166. List<InfraredReadingMeter> list = this.list(wrapper);
  167. Map<Integer, Map<String, List<InfraredReadingMeter>>> groupedByMonthAndMeter =
  168. list.stream()
  169. // TODO 过滤掉电表号为空、创建时间为空、总电能为空的行
  170. .filter(item -> item.getElectricNumber() != null
  171. && !item.getElectricNumber().isEmpty()
  172. && item.getCreateTime() != null
  173. && item.getElectricEnergy() != null)
  174. .collect(Collectors.groupingBy(
  175. item -> item.getCreateTime()
  176. .toInstant()
  177. .atZone(ZoneId.systemDefault())
  178. .toLocalDate()
  179. .getMonthValue(),
  180. Collectors.groupingBy(InfraredReadingMeter::getElectricNumber)
  181. ));
  182. List<BigDecimal> monthDataList = new ArrayList<>(Collections.nCopies(12, BigDecimal.ZERO));
  183. for(int month=1;month<=12;month++){
  184. Map<String, List<InfraredReadingMeter>> meterData=groupedByMonthAndMeter.getOrDefault(month,Collections.emptyMap());
  185. BigDecimal monthTotal=BigDecimal.ZERO;
  186. for(List<InfraredReadingMeter> meterList:meterData.values()){
  187. if(meterList.size()>=2){
  188. BigDecimal start = BigDecimal.valueOf(meterList.get(0).getElectricEnergy());
  189. BigDecimal end = BigDecimal.valueOf(meterList.get(meterList.size()-1).getElectricEnergy());
  190. monthTotal=monthTotal.add(end.subtract(start));
  191. }
  192. }
  193. monthTotal = monthTotal.setScale(2, RoundingMode.HALF_UP);
  194. monthDataList.set(month-1,monthTotal);
  195. }
  196. BigDecimal totalElectricity = monthDataList.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
  197. totalElectricity = totalElectricity.setScale(2, RoundingMode.HALF_UP);
  198. return new MeterYearDataVo(totalElectricity,monthDataList);
  199. }
  200. @Override
  201. public MeterMonthDataVo selectByCurrentYearselectByCurrentYearAndCurrentMonthWithDayData() {
  202. final List<BigDecimal> defaultDayList = Collections.nCopies(31, new BigDecimal("0.00"));
  203. LocalDate now = LocalDate.now();
  204. int year = now.getYear();
  205. int month = now.getMonthValue();
  206. LocalDate firstDayOfMonth = LocalDate.of(year, month, 1);
  207. LocalDate lastDayOfMonth = firstDayOfMonth.withDayOfMonth(firstDayOfMonth.lengthOfMonth());
  208. LocalDateTime startOfDay = firstDayOfMonth.atStartOfDay();
  209. LocalDateTime endOfDay = lastDayOfMonth.atTime(LocalTime.MAX);
  210. LambdaQueryWrapper<InfraredReadingMeter> wrapper = new LambdaQueryWrapper<>();
  211. wrapper.between(InfraredReadingMeter::getCreateTime, startOfDay, endOfDay)
  212. .orderByAsc(InfraredReadingMeter::getCreateTime);
  213. List<InfraredReadingMeter> list = this.list(wrapper);
  214. if(list==null||list.size()<2){
  215. return new MeterMonthDataVo(new BigDecimal("0.00"),defaultDayList);
  216. }
  217. Map<Integer,Map<String,List<InfraredReadingMeter>>> groupedByDayAndMeter=list.stream()
  218. // TODO 过滤掉电表号为空、创建时间为空、总电能为空的行
  219. .filter(item -> item.getElectricNumber() != null
  220. && !item.getElectricNumber().isEmpty()
  221. && item.getCreateTime() != null
  222. && item.getElectricEnergy() != null)
  223. .collect(Collectors.groupingBy(item->item.getCreateTime()
  224. .toInstant()
  225. .atZone(ZoneId.systemDefault())
  226. .toLocalDate()
  227. .getDayOfMonth(),
  228. Collectors.groupingBy(InfraredReadingMeter::getElectricNumber)));
  229. List<BigDecimal> dayDataList=new ArrayList<>(Collections.nCopies(firstDayOfMonth.lengthOfMonth(),BigDecimal.ZERO));
  230. for(int day=1;day<=firstDayOfMonth.lengthOfMonth();day++){
  231. Map<String, List<InfraredReadingMeter>> meterData = groupedByDayAndMeter.getOrDefault(day, Collections.emptyMap());
  232. BigDecimal dayTotal=BigDecimal.ZERO;
  233. for(List<InfraredReadingMeter> meterList:meterData.values()){
  234. if(meterList.size()>=2){
  235. BigDecimal start = BigDecimal.valueOf(meterList.get(0).getElectricEnergy());
  236. BigDecimal end = BigDecimal.valueOf(meterList.get(meterList.size() - 1).getElectricEnergy());
  237. dayTotal=dayTotal.add(end.subtract(start));
  238. }
  239. }
  240. dayTotal = dayTotal.setScale(2, RoundingMode.HALF_UP);
  241. dayDataList.set(day-1,dayTotal);
  242. }
  243. Map<String, List<InfraredReadingMeter>> groupedByMeter = list.stream()
  244. // TODO 过滤掉电表号为空、创建时间为空、总电能为空的行
  245. .filter(item -> item.getElectricNumber() != null
  246. && !item.getElectricNumber().isEmpty()
  247. && item.getCreateTime() != null
  248. && item.getElectricEnergy() != null)
  249. .collect(Collectors.groupingBy(InfraredReadingMeter::getElectricNumber));
  250. BigDecimal totalElectricity = BigDecimal.ZERO;
  251. for (List<InfraredReadingMeter> meterList : groupedByMeter.values()) {
  252. // 找到当月最早一条数据(优化逻辑)
  253. InfraredReadingMeter firstRecord = meterList.stream()
  254. .min(Comparator.comparing(InfraredReadingMeter::getCreateTime))
  255. .orElse(null);
  256. // 找到当月最晚一条数据(优化逻辑)
  257. InfraredReadingMeter lastRecord = meterList.stream()
  258. .max(Comparator.comparing(InfraredReadingMeter::getCreateTime))
  259. .orElse(null);
  260. if (firstRecord != null && lastRecord != null) {
  261. BigDecimal startEnergy = BigDecimal.valueOf(firstRecord.getElectricEnergy());
  262. BigDecimal endEnergy = BigDecimal.valueOf(lastRecord.getElectricEnergy());
  263. totalElectricity = totalElectricity.add(endEnergy.subtract(startEnergy));
  264. }
  265. }
  266. totalElectricity = totalElectricity.setScale(2, RoundingMode.HALF_UP);
  267. return new MeterMonthDataVo(totalElectricity,dayDataList);
  268. }
  269. @Override
  270. public MeterQuarterDataVo selectByCurrentQuarterData() {
  271. LocalDate now = LocalDate.now();
  272. int year = now.getYear();
  273. int month = now.getMonthValue();
  274. int currentQuarter = (month - 1) / 3 + 1;
  275. int startMonth = (currentQuarter - 1) * 3 + 1;
  276. int endMonth = startMonth + 2;
  277. LocalDate startDate = LocalDate.of(year, startMonth, 1);
  278. LocalDate endDate = LocalDate.of(year, endMonth, YearMonth.of(year, endMonth).lengthOfMonth());
  279. LocalDateTime startDateTime = startDate.atStartOfDay();
  280. LocalDateTime endDateTime = endDate.atTime(LocalTime.MAX);
  281. LambdaQueryWrapper<InfraredReadingMeter> wrapper = new LambdaQueryWrapper<>();
  282. wrapper.between(InfraredReadingMeter::getCreateTime,startDateTime,endDateTime)
  283. .orderByAsc(InfraredReadingMeter::getCreateTime);
  284. List<InfraredReadingMeter> list = this.list(wrapper);
  285. if(list==null||list.size()<2){
  286. return new MeterQuarterDataVo(new BigDecimal("0.00"),DEFAULT_QUARTER_LIST);
  287. }
  288. Map<Integer, Map<String, List<InfraredReadingMeter>>> groupedByMonthAndMeter =
  289. list.stream()
  290. // TODO 过滤掉电表号为空、创建时间为空、总电能为空的行
  291. .filter(item -> item.getElectricNumber() != null
  292. && !item.getElectricNumber().isEmpty()
  293. && item.getCreateTime() != null
  294. && item.getElectricEnergy() != null)
  295. .collect(Collectors.groupingBy(
  296. item -> item.getCreateTime().toInstant()
  297. .atZone(ZoneId.systemDefault())
  298. .toLocalDate()
  299. .getMonthValue(),
  300. Collectors.groupingBy(InfraredReadingMeter::getElectricNumber)
  301. ));
  302. List<BigDecimal> monthDataList=new ArrayList<>(Collections.nCopies(3, new BigDecimal("0.00")));
  303. BigDecimal totalQuarterElectricity = BigDecimal.ZERO;
  304. for(int m=startMonth;m<=endMonth;m++){
  305. Map<String, List<InfraredReadingMeter>> meterData = groupedByMonthAndMeter.getOrDefault(m, Collections.emptyMap());
  306. BigDecimal monthTotal = BigDecimal.ZERO;
  307. for(List<InfraredReadingMeter> meterList:meterData.values()){
  308. if(meterList.size()>=2){
  309. BigDecimal start = BigDecimal.valueOf(meterList.get(0).getElectricEnergy());
  310. BigDecimal end = BigDecimal.valueOf(meterList.get(meterList.size() - 1).getElectricEnergy());
  311. monthTotal=monthTotal.add(end.subtract(start));
  312. }
  313. }
  314. monthTotal = monthTotal.setScale(2, RoundingMode.HALF_UP);
  315. monthDataList.set(m-startMonth,monthTotal);
  316. totalQuarterElectricity = totalQuarterElectricity.add(monthTotal);
  317. }
  318. totalQuarterElectricity = totalQuarterElectricity.setScale(2, RoundingMode.HALF_UP);
  319. return new MeterQuarterDataVo(totalQuarterElectricity,monthDataList);
  320. }
  321. @Override
  322. public List<Map<String, Object>> getDailyAndTotalElectricityAsMap() {
  323. // 确定当日时间范围
  324. LocalDate today = LocalDate.now();
  325. Date startOfDay = Date.from(today.atStartOfDay(ZoneId.systemDefault()).toInstant());
  326. Date endOfDay = Date.from(today.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
  327. // 获取所有有效的电表号(非空且有总电量记录)
  328. LambdaQueryWrapper<InfraredReadingMeter> allMeterQuery = new LambdaQueryWrapper<>();
  329. allMeterQuery.isNotNull(InfraredReadingMeter::getElectricNumber)
  330. .isNotNull(InfraredReadingMeter::getElectricEnergy)
  331. .groupBy(InfraredReadingMeter::getElectricNumber); // 去重获取所有电表号
  332. List<String> allValidMeterNumbers = list(allMeterQuery).stream()
  333. .map(InfraredReadingMeter::getElectricNumber)
  334. .filter(Objects::nonNull)
  335. .filter(num -> !num.trim().isEmpty())
  336. .collect(Collectors.toList());
  337. // 查询当日所有有效记录(用于计算当日用电量)
  338. LambdaQueryWrapper<InfraredReadingMeter> todayQuery = new LambdaQueryWrapper<>();
  339. todayQuery.between(InfraredReadingMeter::getCreateTime, startOfDay, endOfDay)
  340. .isNotNull(InfraredReadingMeter::getElectricNumber)
  341. .isNotNull(InfraredReadingMeter::getElectricEnergy)
  342. .orderByAsc(InfraredReadingMeter::getCreateTime);
  343. List<InfraredReadingMeter> todayRecords = list(todayQuery);
  344. // 按电表号分组存储当日记录
  345. Map<String, List<InfraredReadingMeter>> todayRecordsByMeter = todayRecords.stream()
  346. .collect(Collectors.groupingBy(InfraredReadingMeter::getElectricNumber));
  347. // 查询所有电表的最新总电量记录
  348. LambdaQueryWrapper<InfraredReadingMeter> latestQuery = new LambdaQueryWrapper<>();
  349. latestQuery.isNotNull(InfraredReadingMeter::getElectricNumber)
  350. .isNotNull(InfraredReadingMeter::getElectricEnergy);
  351. List<InfraredReadingMeter> allRecords = list(latestQuery);
  352. // 按电表号分组,取最新记录(创建时间最晚)
  353. Map<String, InfraredReadingMeter> latestRecordsByMeter = allRecords.stream()
  354. .collect(Collectors.groupingBy(InfraredReadingMeter::getElectricNumber,
  355. Collectors.collectingAndThen(
  356. Collectors.maxBy(Comparator.comparing(InfraredReadingMeter::getCreateTime)),
  357. Optional::get)));
  358. // 组装结果(保留两位小数)
  359. List<Map<String, Object>> result = new ArrayList<>();
  360. for (String electricNumber : allValidMeterNumbers) {
  361. Map<String, Object> meterMap = new HashMap<>(4);
  362. meterMap.put("electricNumber", electricNumber);
  363. LambdaQueryWrapper<CompanyElectric> companyElectricQuery = new LambdaQueryWrapper<>();
  364. companyElectricQuery.eq(CompanyElectric::getElectricNumber, electricNumber);
  365. CompanyElectric companyElectric = companyElectricService.getOne(companyElectricQuery);
  366. meterMap.put("companyName", companyElectric == null ? "" : companyElectric.getCompanyName());
  367. // 获取该电表的最新总电量(保留两位小数)
  368. InfraredReadingMeter latestRecord = latestRecordsByMeter.get(electricNumber);
  369. if (latestRecord == null || latestRecord.getElectricEnergy() == null) {
  370. continue; // 排除总电量为空的电表
  371. }
  372. BigDecimal totalElectricity = BigDecimal.valueOf(latestRecord.getElectricEnergy())
  373. .setScale(2, RoundingMode.HALF_UP); // 四舍五入保留两位小数
  374. meterMap.put("totalElectricity", totalElectricity);
  375. // 计算当日用电量(无数据则为0,保留两位小数)
  376. List<InfraredReadingMeter> todayMeterRecords = todayRecordsByMeter.getOrDefault(electricNumber, Collections.emptyList());
  377. BigDecimal dailyElectricity;
  378. if (todayMeterRecords.size() >= 2) {
  379. InfraredReadingMeter first = todayMeterRecords.get(0);
  380. InfraredReadingMeter last = todayMeterRecords.get(todayMeterRecords.size() - 1);
  381. if (first.getElectricEnergy() != null && last.getElectricEnergy() != null) {
  382. double diff = last.getElectricEnergy() - first.getElectricEnergy();
  383. dailyElectricity = BigDecimal.valueOf(diff)
  384. .setScale(2, RoundingMode.HALF_UP);
  385. } else {
  386. dailyElectricity = BigDecimal.ZERO.setScale(2); // 数据异常时设为0.00
  387. }
  388. } else {
  389. dailyElectricity = BigDecimal.ZERO.setScale(2); // 当日无数据或记录不足,设为0.00
  390. }
  391. meterMap.put("dailyElectricity", dailyElectricity);
  392. result.add(meterMap);
  393. }
  394. return result;
  395. }
  396. }