Bladeren bron

refactor(infrared-reading-meter-service): 优化电表读数解析和统计逻辑

- 改进电表读数解析精度,使用 BigDecimal 替代 BigInteger
-简化电表数据查询和
林仔 8 maanden geleden
bovenliggende
commit
f267e90acd

+ 14 - 38
infrared-reading-meter-service/src/main/java/com/zksy/infrared/service/impl/InfraredReadingMeterServiceImpl.java

@@ -417,14 +417,9 @@ public class InfraredReadingMeterServiceImpl extends ServiceImpl<InfraredReading
         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()
+                .groupBy(InfraredReadingMeter::getElectricNumber); // 去重获取所有电表号
+        List<String> allValidMeterNumbers = list(allMeterQuery).stream()
+                .map(InfraredReadingMeter::getElectricNumber)
                 .filter(Objects::nonNull)
                 .filter(num -> !num.trim().isEmpty())
                 .collect(Collectors.toList());
@@ -444,10 +439,7 @@ public class InfraredReadingMeterServiceImpl extends ServiceImpl<InfraredReading
         // 查询所有电表的最新总电量记录
         LambdaQueryWrapper<InfraredReadingMeter> latestQuery = new LambdaQueryWrapper<>();
         latestQuery.isNotNull(InfraredReadingMeter::getElectricNumber)
-                .isNotNull(InfraredReadingMeter::getElectricEnergy)
-                .select(InfraredReadingMeter::getElectricNumber,
-                        InfraredReadingMeter::getElectricEnergy,
-                        InfraredReadingMeter::getCreateTime);
+                .isNotNull(InfraredReadingMeter::getElectricEnergy);
         List<InfraredReadingMeter> allRecords = list(latestQuery);
 
         // 按电表号分组,取最新记录(创建时间最晚)
@@ -460,7 +452,7 @@ public class InfraredReadingMeterServiceImpl extends ServiceImpl<InfraredReading
         // 组装结果(保留两位小数)
         List<Map<String, Object>> result = new ArrayList<>();
         for (String electricNumber : allValidMeterNumbers) {
-            Map<String, Object> meterMap = new HashMap<>(5); // 增加容量以存储复位标记
+            Map<String, Object> meterMap = new HashMap<>(4);
             meterMap.put("electricNumber", electricNumber);
 
             LambdaQueryWrapper<CompanyElectric> companyElectricQuery = new LambdaQueryWrapper<>();
@@ -474,46 +466,30 @@ public class InfraredReadingMeterServiceImpl extends ServiceImpl<InfraredReading
                 continue; // 排除总电量为空的电表
             }
             BigDecimal totalElectricity = BigDecimal.valueOf(latestRecord.getElectricEnergy())
-                    .setScale(2, RoundingMode.HALF_UP);
+                    .setScale(2, RoundingMode.HALF_UP); // 四舍五入保留两位小数
             meterMap.put("totalElectricity", totalElectricity);
 
-            // 计算当日用电量(处理电表复位情况
+            // 计算当日用电量(无数据则为0,保留两位小数
             List<InfraredReadingMeter> todayMeterRecords = todayRecordsByMeter.getOrDefault(electricNumber, Collections.emptyList());
-            BigDecimal dailyElectricity = BigDecimal.ZERO.setScale(2);
-            boolean isReset = false; // 标记是否发生电表复位
-
+            BigDecimal dailyElectricity;
             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())
+                    dailyElectricity = BigDecimal.valueOf(diff)
                             .setScale(2, RoundingMode.HALF_UP);
+                } else {
+                    dailyElectricity = BigDecimal.ZERO.setScale(2); // 数据异常时设为0.00
                 }
+            } else {
+                dailyElectricity = BigDecimal.ZERO.setScale(2); // 当日无数据或记录不足,设为0.00
             }
-
             meterMap.put("dailyElectricity", dailyElectricity);
-            meterMap.put("isReset", isReset); // 增加复位标记,方便前端展示
 
             result.add(meterMap);
         }
+
         return result;
     }
 }

+ 3 - 1
infrared-reading-meter-service/src/main/java/com/zksy/infrared/utils/DataParser.java

@@ -49,7 +49,9 @@ public class DataParser {
             }
 
             BigInteger energyValue = new BigInteger(res3, 16);
-            result.setElectricEnergy(energyValue.divide(BigInteger.valueOf(100)).doubleValue());
+            BigDecimal value = new BigDecimal(energyValue);
+            BigDecimal divided = value.divide(new BigDecimal(100),2,RoundingMode.HALF_UP);
+            result.setElectricEnergy(divided.doubleValue());
             result.setCreateTime(new Date());
 
         } catch (NumberFormatException e) {

+ 6 - 0
park-overview-service/src/main/java/com/zksy/park/controller/WaterUsageDataController.java

@@ -9,6 +9,7 @@ import com.zksy.common.enums.BusinessType;
 import com.zksy.common.utils.SearchUtil;
 import com.zksy.park.domain.SmartEmployment;
 import com.zksy.park.domain.WaterUsageData;
+import com.zksy.park.domain.vo.MonthlyWaterStats;
 import com.zksy.park.service.WaterUsageDataService;
 import com.zksy.park.utils.DowntemplateUtil;
 import com.zksy.park.utils.ExcelExportUtil;
@@ -108,6 +109,11 @@ public class WaterUsageDataController {
     public Result getCustomerTrend(@PathVariable Long customerCode) {
         return Result.ok(service.getCustomerTrend(customerCode));
     }
+    @ApiOperation(value = "查询当年月数据")
+    @GetMapping("/yearlyMonthlyStats")
+    public Result getYearlyMonthlyStats() {
+        return Result.ok(service.getYearlyMonthlyStats());
+    }
 
     @GetMapping("/exportExcel")
     @ApiOperation(value = "导出用水信息Excel")

+ 14 - 0
park-overview-service/src/main/java/com/zksy/park/domain/vo/MonthlyWaterStats.java

@@ -0,0 +1,14 @@
+package com.zksy.park.domain.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+@AllArgsConstructor
+public class MonthlyWaterStats {
+    private String month;
+    private Long totalWaterVolume;
+    private BigDecimal totalAmount;
+}

+ 15 - 1
park-overview-service/src/main/java/com/zksy/park/mapper/WaterUsageDataMapper.java

@@ -2,8 +2,13 @@ package com.zksy.park.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.zksy.park.domain.WaterUsageData;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
 import org.mapstruct.Mapper;
 
+import java.util.List;
+import java.util.Map;
+
 /**
 * @author Administrator
 * @description 针对表【wate_usage_data(用水数据)】的数据库操作Mapper
@@ -12,7 +17,16 @@ import org.mapstruct.Mapper;
 */
 @Mapper
 public interface WaterUsageDataMapper extends BaseMapper<WaterUsageData> {
-
+    @Select("SELECT " +
+            "SUBSTRING(statistical_time, 1, 4) AS year, " + // 提取年份,如从“2025年9月”中提取“2025”
+            "SUBSTRING(statistical_time, 6, LENGTH(statistical_time)-5) AS month, " + // 提取月份,如从“2025年9月”中提取“9”
+            "SUM(water_volume) AS total_water_volume, " +
+            "SUM(amount) AS total_amount " +
+            "FROM water_usage_data " +
+            "WHERE SUBSTRING(statistical_time, 1, 4) = #{year} " + // 按提取的年份筛选
+            "GROUP BY SUBSTRING(statistical_time, 1, 4), SUBSTRING(statistical_time, 6, LENGTH(statistical_time)-5) " +
+            "ORDER BY SUBSTRING(statistical_time, 6, LENGTH(statistical_time)-5)")
+    List<Map<String, Object>> getMonthlyStatsByYear(@Param("year") String year);
 }
 
 

+ 2 - 0
park-overview-service/src/main/java/com/zksy/park/service/WaterUsageDataService.java

@@ -3,6 +3,7 @@ package com.zksy.park.service;
 import com.zksy.common.core.domain.Result;
 import com.zksy.park.domain.WaterUsageData;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.zksy.park.domain.vo.MonthlyWaterStats;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletResponse;
@@ -28,4 +29,5 @@ public interface WaterUsageDataService extends IService<WaterUsageData> {
         // 4. 客户用水趋势
         List<Map<String, Object>> getCustomerTrend(Long customerCode);
 
+        List<MonthlyWaterStats> getYearlyMonthlyStats();
 }

+ 41 - 0
park-overview-service/src/main/java/com/zksy/park/service/impl/WaterUsageDataServiceImpl.java

@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.zksy.common.core.domain.Result;
 import com.zksy.park.domain.WaterUsageData;
+import com.zksy.park.domain.vo.MonthlyWaterStats;
 import com.zksy.park.listener.WaterUsageDataListener;
 import com.zksy.park.service.WaterUsageDataService;
 import com.zksy.park.mapper.WaterUsageDataMapper;
@@ -17,11 +18,15 @@ import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
+import java.math.BigDecimal;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
+import java.time.LocalDate;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
 * @author Administrator
@@ -71,6 +76,42 @@ public class WaterUsageDataServiceImpl extends ServiceImpl<WaterUsageDataMapper,
                 .groupBy("statistical_time")
                 .orderByAsc("statistical_time"));
     }
+
+    @Override
+    public List<MonthlyWaterStats> getYearlyMonthlyStats() {
+        // 获取当前年份的字符串形式
+        String currentYear = String.valueOf(LocalDate.now().getYear());
+
+        // 从数据库查询当前年份已有的月度数据
+        List<Map<String, Object>> dbStats = baseMapper.getMonthlyStatsByYear(currentYear);
+
+        // 将查询结果转换为Map便于查找,key为月份(如"9")
+        Map<String, Map<String, Object>> statsMap = dbStats.stream()
+                .collect(Collectors.toMap(
+                        item -> item.get("month").toString(),
+                        item -> item
+                ));
+
+        // 构建12个月的完整数据列表
+        List<MonthlyWaterStats> result = new ArrayList<>();
+        for (int i = 1; i <= 12; i++) {
+            // 月份转为字符串
+            String month = String.valueOf(i);
+
+            // 从查询结果中获取当前月份数据,无数据则用0填充
+            Map<String, Object> monthData = statsMap.getOrDefault(month, new HashMap<>());
+            Long waterVolume = monthData.containsKey("total_water_volume")
+                    ? ((Number) monthData.get("total_water_volume")).longValue()
+                    : 0L;
+            BigDecimal amount = monthData.containsKey("total_amount")
+                    ? (BigDecimal) monthData.get("total_amount")
+                    : BigDecimal.ZERO;
+
+            result.add(new MonthlyWaterStats(month, waterVolume, amount));
+        }
+
+        return result;
+    }
 }