Browse Source

抄表率统计

lin 4 years ago
parent
commit
5a44056f18

+ 1 - 1
smart-city-intf/src/main/java/com/zcxk/smartcity/data/access/util/HexUtil.java

@@ -232,7 +232,7 @@ public class HexUtil {
     }
 
     /**
-     * 保留小数
+     *
      * @param num
      * @param length
      * @return

+ 13 - 0
smart-city-job/src/main/java/com/zcxk/job/controller/TestController.java

@@ -1,5 +1,6 @@
 package com.zcxk.job.controller;
 
+import com.zcxk.job.service.WaterMeterReadRateService;
 import com.zcxk.job.service.jobhandler.WaterMeterReadJob;
 import com.zcxk.zoniot.smartcity.common.model.MeterReadRecord;
 import com.zcxk.job.repository.MeterReadRecordRepository;
@@ -18,6 +19,8 @@ public class TestController {
     MeterReadRecordRepository meterReadRecordRepository;
     @Autowired
     private WaterMeterReadJob waterMeterReadJob;
+    @Autowired
+    private WaterMeterReadRateService waterMeterReadRateService;
 
     @GetMapping("/test/")
     public String test(){
@@ -39,5 +42,15 @@ public class TestController {
         return "ok";
     }
 
+    @GetMapping("yesterdayReadRateJobHandler")
+    public String yesterdayReadRateJobHandler(){
+        try {
+            waterMeterReadRateService.yesterdayReadRateJobHandler("");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return "ok";
+    }
+
 
 }

+ 11 - 0
smart-city-job/src/main/java/com/zcxk/job/dao/StatMeterReadRateMapper.java

@@ -0,0 +1,11 @@
+package com.zcxk.job.dao;
+
+import com.zcxk.job.dto.ReadRateDTO;
+import java.util.List;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+@Mapper
+public interface StatMeterReadRateMapper {
+    int batchInsert(@Param("tableName") String tableName,@Param("list") List<ReadRateDTO> list);
+}

+ 43 - 0
smart-city-job/src/main/java/com/zcxk/job/dto/ReadRateDTO.java

@@ -0,0 +1,43 @@
+package com.zcxk.job.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+public class ReadRateDTO {
+    @ApiModelProperty(value="统计日期")
+    private Integer statDay;
+
+    @ApiModelProperty(value="站点")
+    private Integer siteId;
+
+    @ApiModelProperty(value="场景,对应了水表类型")
+    private Integer channelId;
+
+    @ApiModelProperty(value="客户")
+    private Integer customerId;
+
+    @ApiModelProperty(value="建筑")
+    private Integer buildingId;
+
+    @ApiModelProperty(value="设备数")
+    private Integer deviceCount;
+
+    @ApiModelProperty(value="应抄数据")
+    private Integer readTimes;
+
+    @ApiModelProperty(value="实抄数据")
+    private Integer realReadTimes;
+
+    @ApiModelProperty(value="未抄数据")
+    private Integer unReadTimes;
+
+    @ApiModelProperty(value="抄表率")
+    private Double readRate;
+
+    private LocalDateTime dateCreate;
+    private LocalDateTime dateUpdate;
+
+}

+ 11 - 0
smart-city-job/src/main/java/com/zcxk/job/service/WaterMeterReadRateService.java

@@ -0,0 +1,11 @@
+package com.zcxk.job.service;
+
+public interface WaterMeterReadRateService {
+    void yesterdayReadRateJobHandler(String param);
+
+    void recent7daysReadRateJobHandler(String param);
+
+    void recent15daysReadRateJobHandler(String param);
+
+    void lastMonthReadRateJobHandler(String param);
+}

+ 242 - 0
smart-city-job/src/main/java/com/zcxk/job/service/impl/WaterMeterReadRateServiceImpl.java

@@ -0,0 +1,242 @@
+package com.zcxk.job.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.xxl.job.core.log.XxlJobLogger;
+import com.zcxk.job.dao.StatMeterReadRateMapper;
+import com.zcxk.job.dto.ReadRateDTO;
+import com.zcxk.job.service.WaterMeterReadRateService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.aggregation.Aggregation;
+import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
+import org.springframework.data.mongodb.core.aggregation.AggregationResults;
+import org.springframework.data.mongodb.core.aggregation.ConditionalOperators;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.TemporalAdjusters;
+import java.util.ArrayList;
+import java.util.List;
+
+
+@Service
+public class WaterMeterReadRateServiceImpl implements WaterMeterReadRateService {
+
+    @Autowired
+    private MongoTemplate mongoTemplate;
+    @Autowired
+    private StatMeterReadRateMapper statMeterReadRateMapper;
+
+    @Override
+    public void yesterdayReadRateJobHandler(String param) {
+        JSONObject obj = JSONObject.parseObject(param);
+        XxlJobLogger.log("obj:{}", obj);
+        Integer statDay = 0;
+        Integer startDate = 0;
+        Integer endDate = 0;
+        if (obj != null) {
+            statDay =  obj.getInteger("statDay");
+            startDate =  obj.getInteger("startDate");
+            endDate =  obj.getInteger("endDate");
+        }
+
+        if (statDay == null || statDay == 0) {
+            statDay = Integer.valueOf(LocalDateTime.now().plusDays(-1).format(DateTimeFormatter.ofPattern("yyyyMMdd")));
+        }
+        if (startDate == null || startDate == 0) {
+            startDate = Integer.valueOf(LocalDateTime.now().plusDays(-1).format(DateTimeFormatter.ofPattern("yyyyMMdd")));
+        }
+        if (endDate == null || endDate == 0) {
+            endDate = Integer.valueOf(LocalDateTime.now().plusDays(-1).format(DateTimeFormatter.ofPattern("yyyyMMdd")));
+        }
+        XxlJobLogger.log("statDay:{},startDate:{},endDate:{}",statDay, startDate, endDate);
+
+        List<ReadRateDTO> results = this.readRateJobHandler(statDay,startDate,endDate);
+        if (results != null && results.size() > 0) {
+            XxlJobLogger.log("结果数量,size:{}", results.size());
+            statMeterReadRateMapper.batchInsert("sc_stat_meter_read_rate_by_building",results);
+        }
+    }
+
+    @Override
+    public void recent7daysReadRateJobHandler(String param) {
+        JSONObject obj = JSONObject.parseObject(param);
+        XxlJobLogger.log("obj:{}", obj);
+        Integer statDay = 0;
+        Integer startDate = 0;
+        Integer endDate = 0;
+        if (obj != null) {
+            statDay =  obj.getInteger("statDay");
+            startDate =  obj.getInteger("startDate");
+            endDate =  obj.getInteger("endDate");
+        }
+
+        if (statDay == null || statDay == 0) {
+            statDay = Integer.valueOf(LocalDateTime.now().plusDays(-1).format(DateTimeFormatter.ofPattern("yyyyMMdd")));
+        }
+        if (startDate == null || startDate == 0) {
+            startDate = Integer.valueOf(LocalDateTime.now().plusDays(-7).format(DateTimeFormatter.ofPattern("yyyyMMdd")));
+        }
+        if (endDate == null || endDate == 0) {
+            endDate = Integer.valueOf(LocalDateTime.now().plusDays(-1).format(DateTimeFormatter.ofPattern("yyyyMMdd")));
+        }
+        XxlJobLogger.log("statDay:{},startDate:{},endDate:{}",statDay, startDate, endDate);
+
+        List<ReadRateDTO> results = this.readRateJobHandler(statDay,startDate,endDate);
+        if (results != null && results.size() > 0) {
+            XxlJobLogger.log("结果数量,size:{}", results.size());
+            statMeterReadRateMapper.batchInsert("sc_stat_meter_read_rate_by_building_7day",results);
+        }
+    }
+
+    @Override
+    public void recent15daysReadRateJobHandler(String param) {
+        JSONObject obj = JSONObject.parseObject(param);
+        XxlJobLogger.log("obj:{}", obj);
+        Integer statDay = 0;
+        Integer startDate = 0;
+        Integer endDate = 0;
+        if (obj != null) {
+            statDay =  obj.getInteger("statDay");
+            startDate =  obj.getInteger("startDate");
+            endDate =  obj.getInteger("endDate");
+        }
+
+        if (statDay == null || statDay == 0) {
+            statDay = Integer.valueOf(LocalDateTime.now().plusDays(-1).format(DateTimeFormatter.ofPattern("yyyyMMdd")));
+        }
+        if (startDate == null || startDate == 0) {
+            startDate = Integer.valueOf(LocalDateTime.now().plusDays(-15).format(DateTimeFormatter.ofPattern("yyyyMMdd")));
+        }
+        if (endDate == null || endDate == 0) {
+            endDate = Integer.valueOf(LocalDateTime.now().plusDays(-1).format(DateTimeFormatter.ofPattern("yyyyMMdd")));
+        }
+        XxlJobLogger.log("statDay:{},startDate:{},endDate:{}",statDay, startDate, endDate);
+
+        List<ReadRateDTO> results = this.readRateJobHandler(statDay,startDate,endDate);
+        if (results != null && results.size() > 0) {
+            XxlJobLogger.log("结果数量,size:{}", results.size());
+            statMeterReadRateMapper.batchInsert("sc_stat_meter_read_rate_by_building_15day",results);
+        }
+    }
+
+    @Override
+    public void lastMonthReadRateJobHandler(String param) {
+        JSONObject obj = JSONObject.parseObject(param);
+        XxlJobLogger.log("obj:{}", obj);
+        Integer statDay = 0;
+        Integer startDate = 0;
+        Integer endDate = 0;
+        if (obj != null) {
+            statDay =  obj.getInteger("statDay");
+            startDate =  obj.getInteger("startDate");
+            endDate =  obj.getInteger("endDate");
+        }
+
+        if (statDay == null || statDay == 0) {
+            statDay = Integer.valueOf(LocalDateTime.now().plusMonths(-1).format(DateTimeFormatter.ofPattern("yyyyMM")));
+        }
+        if (startDate == null || startDate == 0) {
+            startDate = Integer.valueOf(LocalDateTime.now().plusMonths(-1).with(TemporalAdjusters.firstDayOfMonth()).format(DateTimeFormatter.ofPattern("yyyyMMdd")));
+        }
+        if (endDate == null || endDate == 0) {
+            endDate = Integer.valueOf(LocalDateTime.now().plusMonths(-1).with(TemporalAdjusters.lastDayOfMonth()).format(DateTimeFormatter.ofPattern("yyyyMMdd")));
+        }
+        XxlJobLogger.log("statDay:{},startDate:{},endDate:{}",statDay, startDate, endDate);
+
+        List<ReadRateDTO> results = this.readRateJobHandler(statDay,startDate,endDate);
+        if (results != null && results.size() > 0) {
+            XxlJobLogger.log("结果数量,size:{}", results.size());
+            statMeterReadRateMapper.batchInsert("sc_stat_meter_read_rate_by_building_month",results);
+        }
+    }
+
+    protected List<ReadRateDTO> readRateJobHandler(Integer statDay, Integer startDate, Integer endDate){
+        /*
+            db.sc_meter_read_record.aggregate(
+             [
+              {$match:{status:1,readDate:20200619}},
+                {$group:{_id:{
+                        "siteId": "$siteId","channelId": "$channelId","customerId": "$customerId","buildingId": "$buildingId","deviceId": "$deviceId",
+                    },
+                            realReadTimes:{$sum:{
+                         $cond: { if: { $eq: ["$readStatus", "1"] }, then: 1, else: 0 }
+                       }}
+                }},
+                {$group:{_id:{
+                        "siteId": "$_id.siteId","channelId": "$_id.channelId","customerId": "$_id.customerId","buildingId": "$_id.buildingId",
+                    },
+                            total:{$sum:1},
+                            realReadTimes:{$sum:{
+                         $cond: { if: { $ne: ["$realReadTimes", 0] }, then: 1, else: 0 }
+                       }},
+                            unReadTimes:{$sum:{
+                         $cond: { if: { $eq: ["$realReadTimes", 0] }, then: 1, else: 0 }
+                       }}
+                }},
+                { $project : {
+                    siteId : 1 ,
+                    channelId : 1 ,
+                    customerId : 1 ,
+                    buildingId : 1 ,
+                    total : 1 ,
+                    realReadTimes : 1 ,
+                    unReadTimes : 1 ,
+                    readRate : { $divide: [ "$realReadTimes", "$total" ] }
+              }}
+             ]
+             ,{ allowDiskUse: true }
+             )
+         */
+
+
+        List<AggregationOperation> operations = new ArrayList<>();
+        operations.add(Aggregation.match(Criteria.where("status").is(1)));
+        operations.add(Aggregation.match(Criteria.where("readDate").gte(startDate).lte(endDate)));
+        // 1,添加分组条件
+        ConditionalOperators.Cond readTimesCond = ConditionalOperators.when(new Criteria("readStatus").is("1")).then(1).otherwise(0);
+        operations.add(Aggregation.group("siteId","channelId","customerId","buildingId","deviceId")
+                .sum(readTimesCond).as("realReadTimes"));
+        // 2,添加分组条件
+        ConditionalOperators.Cond readTimesCond1 = ConditionalOperators.when(new Criteria("realReadTimes").ne(0)).then(1).otherwise(0);
+        ConditionalOperators.Cond unReadTimesCond1= ConditionalOperators.when(new Criteria("realReadTimes").is(0)).then(1).otherwise(0);
+        operations.add(Aggregation.group("siteId","channelId","customerId","buildingId")
+                .sum(readTimesCond1).as("realReadTimes")
+                .sum(unReadTimesCond1).as("unReadTimes")
+                .count().as("total"));
+
+        operations.add(Aggregation.project("realReadTimes","unReadTimes").
+                and("_id.siteId").as("siteId").
+                and("_id.channelId").as("channelId").
+                and("_id.customerId").as("customerId").
+                and("_id.buildingId").as("buildingId").
+                and("total").as("deviceCount").
+                //and("readTimes").divide("total").as("readRate").
+                        andExclude("_id"));
+        //operations.add(Aggregation.sort(Sort.Direction.DESC, "total"));
+
+        // 3,聚合查询所有信息
+        Aggregation aggregation = Aggregation.newAggregation(operations);
+        // 4,查询结果
+        AggregationResults<ReadRateDTO> aggregationResults = mongoTemplate.aggregate(aggregation, "sc_meter_read_record", ReadRateDTO.class);
+        // 5,获取结果
+        List<ReadRateDTO> results = aggregationResults.getMappedResults();
+        if (results != null && results.size() > 0) {
+            for (ReadRateDTO result : results) {
+                if (result.getDeviceCount() != 0) {
+                    BigDecimal realReadTimes = new BigDecimal(result.getRealReadTimes()* 100);
+                    BigDecimal total = new BigDecimal(result.getDeviceCount());
+                    result.setReadRate(realReadTimes.divide(total,2,BigDecimal.ROUND_HALF_UP).doubleValue());
+                }
+                result.setStatDay(statDay);
+                result.setReadTimes(result.getDeviceCount());
+                result.setDateCreate(LocalDateTime.now());
+                result.setDateUpdate(LocalDateTime.now());
+            }
+        }
+        return results;
+    }
+}

+ 12 - 0
smart-city-job/src/main/java/com/zcxk/job/service/jobhandler/WaterMeterReadJob.java

@@ -14,6 +14,12 @@ public class WaterMeterReadJob {
     @Autowired
     MeterReadRecordService meterReadRecordService;
 
+    /**
+     * 每天生成第二天的抄表记录
+     * @param param
+     * @return
+     * @throws Exception
+     */
     @XxlJob("waterMeterReadJobHandler")
     public ReturnT<String> waterMeterReadJobHandler(String param) throws Exception {
 
@@ -34,6 +40,12 @@ public class WaterMeterReadJob {
         return ReturnT.SUCCESS;
     }
 
+    /**
+     * 补齐昨天未抄的最近有效数据
+     * @param param
+     * @return
+     * @throws Exception
+     */
     @XxlJob("waterMeterUnReadReplenishJobHandler")
     public ReturnT<String> waterMeterUnReadReplenishJobHandler(String param) throws Exception {
 

+ 101 - 0
smart-city-job/src/main/java/com/zcxk/job/service/jobhandler/WaterMeterReadRateJob.java

@@ -0,0 +1,101 @@
+package com.zcxk.job.service.jobhandler;
+
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.handler.annotation.XxlJob;
+import com.zcxk.job.service.WaterMeterReadRateService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class WaterMeterReadRateJob {
+
+    @Autowired
+    private WaterMeterReadRateService waterMeterReadRateService;
+
+    /**
+     * 昨天抄表率
+     * @param param
+     * @return
+     * @throws Exception
+     */
+    @XxlJob("yesterdayReadRateJobHandler")
+    public ReturnT<String> yesterdayReadRateJobHandler(String param) throws Exception {
+
+        /*
+        参数格式如下:
+        {
+            "statDay": 20200619,
+            "startDate": 20200619,
+            "endDate": 20200619
+        }
+         */
+        waterMeterReadRateService.yesterdayReadRateJobHandler(param);
+
+        return ReturnT.SUCCESS;
+    }
+
+    /**
+     * 最近7天抄表率
+     * @param param
+     * @return
+     * @throws Exception
+     */
+    @XxlJob("recent7daysReadRateJobHandler")
+    public ReturnT<String> recent7daysReadRateJobHandler(String param) throws Exception {
+        /*
+        参数格式如下:
+        {
+            "statDay": 20200619,
+            "startDate": 20200619,
+            "endDate": 20200619
+        }
+         */
+        waterMeterReadRateService.recent7daysReadRateJobHandler(param);
+
+        return ReturnT.SUCCESS;
+    }
+
+    /**
+     * 最近15抄表率
+     * @param param
+     * @return
+     * @throws Exception
+     */
+    @XxlJob("recent15daysReadRateJobHandler")
+    public ReturnT<String> recent15daysReadRateJobHandler(String param) throws Exception {
+
+        /*
+        参数格式如下:
+        {
+            "statDay": 20200619,
+            "startDate": 20200619,
+            "endDate": 20200619
+        }
+         */
+        waterMeterReadRateService.recent15daysReadRateJobHandler(param);
+
+        return ReturnT.SUCCESS;
+    }
+
+    /**
+     * 上月抄表率
+     * @param param
+     * @return
+     * @throws Exception
+     */
+    @XxlJob("lastMonthReadRateJobHandler")
+    public ReturnT<String> lastMonthReadRateJobHandler(String param) throws Exception {
+
+        /*
+        参数格式如下:
+        {
+            "statDay": 202006,
+            "startDate": 20200601,
+            "endDate": 20200630
+        }
+         */
+        waterMeterReadRateService.lastMonthReadRateJobHandler(param);
+
+        return ReturnT.SUCCESS;
+    }
+}

+ 37 - 0
smart-city-job/src/main/resources/mapper/StatMeterReadRateMapper.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zcxk.job.dao.StatMeterReadRateMapper">
+  <resultMap id="BaseResultMap" type="com.zcxk.job.dto.ReadRateDTO">
+    <!--@mbg.generated-->
+    <!--@Table sc_stat_meter_read_rate_by_building-->
+    <id column="stat_day" property="statDay" />
+    <id column="site_id" property="siteId" />
+    <id column="channel_id" property="channelId" />
+    <id column="customer_id" property="customerId" />
+    <id column="building_id" property="buildingId" />
+    <result column="device_count" property="deviceCount" />
+    <result column="read_times" property="readTimes" />
+    <result column="real_read_times" property="realReadTimes" />
+    <result column="un_read_times" property="unReadTimes" />
+    <result column="read_rate" property="readRate" />
+    <result column="date_create" property="dateCreate" />
+    <result column="date_update" property="dateUpdate" />
+  </resultMap>
+  <sql id="Base_Column_List">
+    <!--@mbg.generated-->
+    stat_day, site_id, channel_id, customer_id, building_id, device_count, read_times, 
+    real_read_times, un_read_times, read_rate, date_create, date_update
+  </sql>
+  <insert id="batchInsert" parameterType="map">
+    <!--@mbg.generated-->
+    insert into ${tableName}
+    (stat_day, site_id, channel_id, customer_id, building_id, device_count, read_times, 
+      real_read_times, un_read_times, read_rate, date_create, date_update)
+    values
+    <foreach collection="list" item="item" separator=",">
+      (#{item.statDay}, #{item.siteId}, #{item.channelId}, #{item.customerId}, #{item.buildingId}, 
+        #{item.deviceCount}, #{item.readTimes}, #{item.realReadTimes}, #{item.unReadTimes}, 
+        #{item.readRate}, #{item.dateCreate}, #{item.dateUpdate})
+    </foreach>
+  </insert>
+</mapper>