|
@@ -408,83 +408,112 @@ public class InfraredReadingMeterServiceImpl extends ServiceImpl<InfraredReading
|
|
|
}
|
|
}
|
|
|
@Override
|
|
@Override
|
|
|
public List<Map<String, Object>> getDailyAndTotalElectricityAsMap() {
|
|
public List<Map<String, Object>> getDailyAndTotalElectricityAsMap() {
|
|
|
- // 确定当日时间范围(避免跨时区问题,统一用系统默认时区)
|
|
|
|
|
|
|
+ // 确定当日时间范围
|
|
|
LocalDate today = LocalDate.now();
|
|
LocalDate today = LocalDate.now();
|
|
|
Date startOfDay = Date.from(today.atStartOfDay(ZoneId.systemDefault()).toInstant());
|
|
Date startOfDay = Date.from(today.atStartOfDay(ZoneId.systemDefault()).toInstant());
|
|
|
Date endOfDay = Date.from(today.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
|
|
Date endOfDay = Date.from(today.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
|
|
|
|
|
|
|
|
- LambdaQueryWrapper<InfraredReadingMeter> baseQuery = Wrappers.lambdaQuery();
|
|
|
|
|
- baseQuery.isNotNull(InfraredReadingMeter::getElectricNumber) // 过滤无效电表号
|
|
|
|
|
- .isNotNull(InfraredReadingMeter::getElectricEnergy) // 过滤无效电量
|
|
|
|
|
- .ge(InfraredReadingMeter::getElectricEnergy, 0); // 排除负数异常数据
|
|
|
|
|
- List<InfraredReadingMeter> allValidRecords = list(baseQuery);
|
|
|
|
|
|
|
+ // 获取所有有效的电表号(非空且有总电量记录)
|
|
|
|
|
+ LambdaQueryWrapper<InfraredReadingMeter> allMeterQuery = new LambdaQueryWrapper<>();
|
|
|
|
|
+ allMeterQuery.isNotNull(InfraredReadingMeter::getElectricNumber)
|
|
|
|
|
+ .isNotNull(InfraredReadingMeter::getElectricEnergy)
|
|
|
|
|
+ .select(InfraredReadingMeter::getElectricNumber)
|
|
|
|
|
+ .groupBy(InfraredReadingMeter::getElectricNumber);
|
|
|
|
|
+ List<String> allValidMeterNumbers = listObjs(allMeterQuery, obj -> {
|
|
|
|
|
+ if (obj instanceof String) {
|
|
|
|
|
+ return (String) obj;
|
|
|
|
|
+ }
|
|
|
|
|
+ return obj.toString();
|
|
|
|
|
+ }).stream()
|
|
|
|
|
+ .filter(Objects::nonNull)
|
|
|
|
|
+ .filter(num -> !num.trim().isEmpty())
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+
|
|
|
|
|
+ // 查询当日所有有效记录(用于计算当日用电量)
|
|
|
|
|
+ LambdaQueryWrapper<InfraredReadingMeter> todayQuery = new LambdaQueryWrapper<>();
|
|
|
|
|
+ todayQuery.between(InfraredReadingMeter::getCreateTime, startOfDay, endOfDay)
|
|
|
|
|
+ .isNotNull(InfraredReadingMeter::getElectricNumber)
|
|
|
|
|
+ .isNotNull(InfraredReadingMeter::getElectricEnergy)
|
|
|
|
|
+ .orderByAsc(InfraredReadingMeter::getCreateTime);
|
|
|
|
|
+ List<InfraredReadingMeter> todayRecords = list(todayQuery);
|
|
|
|
|
|
|
|
- // 按电表号分组,处理数据(减少循环次数)
|
|
|
|
|
- Map<String, List<InfraredReadingMeter>> recordsByMeter = allValidRecords.stream()
|
|
|
|
|
|
|
+ // 按电表号分组存储当日记录
|
|
|
|
|
+ Map<String, List<InfraredReadingMeter>> todayRecordsByMeter = todayRecords.stream()
|
|
|
.collect(Collectors.groupingBy(InfraredReadingMeter::getElectricNumber));
|
|
.collect(Collectors.groupingBy(InfraredReadingMeter::getElectricNumber));
|
|
|
|
|
|
|
|
- // 批量查询公司信息(解决N+1查询问题,性能提升显著)
|
|
|
|
|
- Set<String> allMeterNumbers = recordsByMeter.keySet();
|
|
|
|
|
- LambdaQueryWrapper<CompanyElectric> companyQuery = Wrappers.lambdaQuery();
|
|
|
|
|
- companyQuery.in(CompanyElectric::getElectricNumber, allMeterNumbers);
|
|
|
|
|
- Map<String, String> meterToCompany = companyElectricService.list(companyQuery).stream()
|
|
|
|
|
- .filter(company -> company.getElectricNumber() != null)
|
|
|
|
|
- .collect(Collectors.toMap(
|
|
|
|
|
- CompanyElectric::getElectricNumber,
|
|
|
|
|
- CompanyElectric::getCompanyName,
|
|
|
|
|
- (oldVal, newVal) -> newVal // 电表号重复时取最新值
|
|
|
|
|
- ));
|
|
|
|
|
-
|
|
|
|
|
- // 组装最终结果
|
|
|
|
|
|
|
+ // 查询所有电表的最新总电量记录
|
|
|
|
|
+ LambdaQueryWrapper<InfraredReadingMeter> latestQuery = new LambdaQueryWrapper<>();
|
|
|
|
|
+ latestQuery.isNotNull(InfraredReadingMeter::getElectricNumber)
|
|
|
|
|
+ .isNotNull(InfraredReadingMeter::getElectricEnergy)
|
|
|
|
|
+ .select(InfraredReadingMeter::getElectricNumber,
|
|
|
|
|
+ InfraredReadingMeter::getElectricEnergy,
|
|
|
|
|
+ InfraredReadingMeter::getCreateTime);
|
|
|
|
|
+ List<InfraredReadingMeter> allRecords = list(latestQuery);
|
|
|
|
|
+
|
|
|
|
|
+ // 按电表号分组,取最新记录(创建时间最晚)
|
|
|
|
|
+ Map<String, InfraredReadingMeter> latestRecordsByMeter = allRecords.stream()
|
|
|
|
|
+ .collect(Collectors.groupingBy(InfraredReadingMeter::getElectricNumber,
|
|
|
|
|
+ Collectors.collectingAndThen(
|
|
|
|
|
+ Collectors.maxBy(Comparator.comparing(InfraredReadingMeter::getCreateTime)),
|
|
|
|
|
+ Optional::get)));
|
|
|
|
|
+
|
|
|
|
|
+ // 组装结果(保留两位小数)
|
|
|
List<Map<String, Object>> result = new ArrayList<>();
|
|
List<Map<String, Object>> result = new ArrayList<>();
|
|
|
- for (Map.Entry<String, List<InfraredReadingMeter>> entry : recordsByMeter.entrySet()) {
|
|
|
|
|
- String electricNumber = entry.getKey();
|
|
|
|
|
- List<InfraredReadingMeter> meterRecords = entry.getValue();
|
|
|
|
|
-
|
|
|
|
|
- Map<String, Object> meterMap = new HashMap<>(4);
|
|
|
|
|
|
|
+ for (String electricNumber : allValidMeterNumbers) {
|
|
|
|
|
+ Map<String, Object> meterMap = new HashMap<>(5); // 增加容量以存储复位标记
|
|
|
meterMap.put("electricNumber", electricNumber);
|
|
meterMap.put("electricNumber", electricNumber);
|
|
|
|
|
|
|
|
- // 关联公司名称(默认空字符串,避免空指针)
|
|
|
|
|
- String companyName = meterToCompany.getOrDefault(electricNumber, "");
|
|
|
|
|
- meterMap.put("companyName", companyName);
|
|
|
|
|
|
|
+ LambdaQueryWrapper<CompanyElectric> companyElectricQuery = new LambdaQueryWrapper<>();
|
|
|
|
|
+ companyElectricQuery.eq(CompanyElectric::getElectricNumber, electricNumber);
|
|
|
|
|
+ CompanyElectric companyElectric = companyElectricService.getOne(companyElectricQuery);
|
|
|
|
|
+ meterMap.put("companyName", companyElectric == null ? "" : companyElectric.getCompanyName());
|
|
|
|
|
|
|
|
- // 计算累计总电量(取该电表最新一条记录的电量)
|
|
|
|
|
- InfraredReadingMeter latestRecord = meterRecords.stream()
|
|
|
|
|
- .max(Comparator.comparing(InfraredReadingMeter::getCreateTime)) // 按时间取最新
|
|
|
|
|
- .orElse(null);
|
|
|
|
|
- BigDecimal totalElectricity = BigDecimal.ZERO.setScale(2);
|
|
|
|
|
- if (latestRecord != null) {
|
|
|
|
|
- totalElectricity = BigDecimal.valueOf(latestRecord.getElectricEnergy())
|
|
|
|
|
- .setScale(2, RoundingMode.HALF_UP); // 四舍五入保留两位小数
|
|
|
|
|
|
|
+ // 获取该电表的最新总电量(保留两位小数)
|
|
|
|
|
+ InfraredReadingMeter latestRecord = latestRecordsByMeter.get(electricNumber);
|
|
|
|
|
+ if (latestRecord == null || latestRecord.getElectricEnergy() == null) {
|
|
|
|
|
+ continue; // 排除总电量为空的电表
|
|
|
}
|
|
}
|
|
|
|
|
+ BigDecimal totalElectricity = BigDecimal.valueOf(latestRecord.getElectricEnergy())
|
|
|
|
|
+ .setScale(2, RoundingMode.HALF_UP);
|
|
|
meterMap.put("totalElectricity", totalElectricity);
|
|
meterMap.put("totalElectricity", totalElectricity);
|
|
|
|
|
|
|
|
- //计算当日用电量
|
|
|
|
|
- List<InfraredReadingMeter> todayRecords = meterRecords.stream()
|
|
|
|
|
- .filter(record -> record.getCreateTime().after(startOfDay)
|
|
|
|
|
- && record.getCreateTime().before(endOfDay)) // 筛选当日记录
|
|
|
|
|
- .sorted(Comparator.comparing(InfraredReadingMeter::getCreateTime)) // 按时间排序
|
|
|
|
|
- .collect(Collectors.toList());
|
|
|
|
|
-
|
|
|
|
|
|
|
+ // 计算当日用电量(处理电表复位情况)
|
|
|
|
|
+ List<InfraredReadingMeter> todayMeterRecords = todayRecordsByMeter.getOrDefault(electricNumber, Collections.emptyList());
|
|
|
BigDecimal dailyElectricity = BigDecimal.ZERO.setScale(2);
|
|
BigDecimal dailyElectricity = BigDecimal.ZERO.setScale(2);
|
|
|
- if (todayRecords.size() >= 2) {
|
|
|
|
|
- InfraredReadingMeter firstRecord = todayRecords.get(0); // 当日第一条记录
|
|
|
|
|
- InfraredReadingMeter lastRecord = todayRecords.get(todayRecords.size() - 1); // 当日最后一条
|
|
|
|
|
- double firstEnergy = firstRecord.getElectricEnergy();
|
|
|
|
|
- double lastEnergy = lastRecord.getElectricEnergy();
|
|
|
|
|
-
|
|
|
|
|
- // 排除异常:若首次电量>末次电量(如电表复位),当日用电量设为0
|
|
|
|
|
- if (lastEnergy >= firstEnergy) {
|
|
|
|
|
- dailyElectricity = BigDecimal.valueOf(lastEnergy - firstEnergy)
|
|
|
|
|
|
|
+ boolean isReset = false; // 标记是否发生电表复位
|
|
|
|
|
+
|
|
|
|
|
+ if (todayMeterRecords.size() >= 2) {
|
|
|
|
|
+ InfraredReadingMeter first = todayMeterRecords.get(0);
|
|
|
|
|
+ InfraredReadingMeter last = todayMeterRecords.get(todayMeterRecords.size() - 1);
|
|
|
|
|
+
|
|
|
|
|
+ if (first.getElectricEnergy() != null && last.getElectricEnergy() != null) {
|
|
|
|
|
+ double diff = last.getElectricEnergy() - first.getElectricEnergy();
|
|
|
|
|
+
|
|
|
|
|
+ // 检测到负数,说明电表复位
|
|
|
|
|
+ if (diff < 0) {
|
|
|
|
|
+ // 复位情况下,当日用电量为最后一次记录的电量值
|
|
|
|
|
+ dailyElectricity = BigDecimal.valueOf(last.getElectricEnergy())
|
|
|
|
|
+ .setScale(2, RoundingMode.HALF_UP);
|
|
|
|
|
+ isReset = true;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ dailyElectricity = BigDecimal.valueOf(diff)
|
|
|
|
|
+ .setScale(2, RoundingMode.HALF_UP);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (todayMeterRecords.size() == 1) {
|
|
|
|
|
+ // 只有一条记录时,直接使用该记录的电量值
|
|
|
|
|
+ InfraredReadingMeter record = todayMeterRecords.get(0);
|
|
|
|
|
+ if (record.getElectricEnergy() != null) {
|
|
|
|
|
+ dailyElectricity = BigDecimal.valueOf(record.getElectricEnergy())
|
|
|
.setScale(2, RoundingMode.HALF_UP);
|
|
.setScale(2, RoundingMode.HALF_UP);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
meterMap.put("dailyElectricity", dailyElectricity);
|
|
meterMap.put("dailyElectricity", dailyElectricity);
|
|
|
|
|
+ meterMap.put("isReset", isReset); // 增加复位标记,方便前端展示
|
|
|
|
|
|
|
|
result.add(meterMap);
|
|
result.add(meterMap);
|
|
|
}
|
|
}
|
|
|
- // 按电表号排序
|
|
|
|
|
- result.sort(Comparator.comparing(map -> (String) map.get("electricNumber")));
|
|
|
|
|
return result;
|
|
return result;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|