fuliqi
2024-08-21 4c277c644a565f8027da8f6d5da9681a5598516a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
package com.ycl.task;
 
 
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mongodb.client.result.DeleteResult;
import com.ycl.platform.domain.entity.*;
import com.ycl.platform.domain.result.HK.SnapshotDataMonitorResult;
import com.ycl.platform.domain.result.UY.VideoOnlineResult;
import com.ycl.platform.domain.vo.CalculateRuleVO;
import com.ycl.platform.domain.vo.ContractVO;
import com.ycl.platform.domain.vo.ReportVO;
import com.ycl.platform.mapper.*;
import com.ycl.platform.service.IContractScoreService;
import com.ycl.utils.DateUtils;
import constant.ApiConstants;
import constant.RedisConstant;
import enumeration.ContractRule;
import enumeration.general.AuditingStatus;
import enumeration.general.RuleDeductCategoryEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
 
import javax.management.monitor.Monitor;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
 
/**
 * 合同考核定时任务
 */
@Slf4j
@Component("contractTask")
public class ContractTask {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private TMonitorMapper monitorMapper;
    @Autowired
    private TContractMapper contractMapper;
    @Autowired
    private YwPointMapper ywPointMapper;
    @Autowired
    private ReportMapper reportMapper;
    @Autowired
    private ContractRuleRecordMapper recordMapper;
    @Autowired
    private IContractScoreService contractScoreService;
 
    private static final Integer Online = 1;
    private static final Integer Offline = -1;
    private static final String AuditStatus_Pass = "1";
    private static final String Remark = "系统生成";
 
    /**
     * 合同考核 在线率每日任务检测
     * 查生效的合同关联的公司,获取unitId集合
     * 根据unitId查询对应点位获取各个公司管理的设备Ids
     * 查询三种设备在线不在线情况,封装为一个map<国标码,在线状态>
     * 计算每日每家公司的在线率存入mysql
     * 月底计算平均值,根据在线率和合同标准扣减分数
     */
    public void onlineCheck() {
        log.info("开始计算合同点位在线率");
        List<CalculateRuleVO> ruleVos = contractMapper.selectByRuleName(ContractRule.CONTRACT_RULE_Online.getName(), null, new Date());
        List<Integer> unitIds = ruleVos.stream().map(CalculateRuleVO::getUnitId).collect(Collectors.toList());
        List<YwPoint> ywPoints = ywPointMapper.selectList(new QueryWrapper<YwPoint>().in("unit_id", unitIds));
        //key是unitId value是设备编码集合
        Map<Long, List<String>> unitMap = ywPoints.stream()
                .collect(Collectors.groupingBy(
                        YwPoint::getUnitId,
                        Collectors.mapping(
                                YwPoint::getSerialNumber,
                                Collectors.toList()
                        )
                ));
        Map<String, Integer> onlineStatusMap = new HashMap<>();
        //查mongo获取设备在线情况
        Date date = DateUtils.getDay(2024, 7, 13);
        //车辆、人脸
        Query query = new Query();
        query.addCriteria(Criteria
                .where("mongoCreateTime").gte(DateUtils.getDayStart(date)).lt(DateUtils.getDayEnd(date)));
        List<SnapshotDataMonitorResult> results = mongoTemplate.find(query, SnapshotDataMonitorResult.class);
        for (SnapshotDataMonitorResult result : results) {
            if (ApiConstants.HK_SnapCount_ResultType_Null != result.getResultType()) {
                onlineStatusMap.put(result.getExternalIndexCode(), Online);
            } else {
                onlineStatusMap.put(result.getExternalIndexCode(), Offline);
            }
        }
        //视频
        Query videoQuery = new Query(Criteria
                .where("mongoCreateTime").gte(DateUtils.getDayStart(date)).lt(DateUtils.getDayEnd(date)));
        List<VideoOnlineResult> videoOnlineResults = mongoTemplate.find(videoQuery, VideoOnlineResult.class);
        for (VideoOnlineResult videoOnlineResult : videoOnlineResults) {
            onlineStatusMap.put(videoOnlineResult.getDeviceId(), videoOnlineResult.getStatus());
        }
        //查询报备列表
        List<String> reportNumbers = reportMapper.selectNumberList(AuditStatus_Pass, DateUtils.getDate());
        //计算每个公司的点位在线率
        List<ContractRuleRecord> ruleRecordList = new ArrayList<>();
        unitMap.forEach((unitId, serialNumberList) -> {
            int totalSite = 0;
            int onlineSite = 0;
            for (String number : serialNumberList) {
                //报备过不纳入计算
                if (!CollectionUtils.isEmpty(reportNumbers) && reportNumbers.contains(number)) continue;
                Integer status = onlineStatusMap.get(number);
                totalSite++;
                if (Online.equals(status)) {
                    onlineSite++;
                }
            }
            BigDecimal online = new BigDecimal(onlineSite).divide(new BigDecimal(totalSite), 2, RoundingMode.DOWN);
            ContractRuleRecord contractRuleRecord = new ContractRuleRecord();
            contractRuleRecord.setSiteOnline(online);
            contractRuleRecord.setCreateTime(new Date());
            contractRuleRecord.setUnitId(unitId);
            ruleRecordList.add(contractRuleRecord);
        });
        //存储结果
        recordMapper.insertBatch(ruleRecordList);
        log.info("结束计算合同点位在线率");
    }
 
    //月底计算在线率分数
    public void calculateOnlineScore() {
        log.info("开始计算合同点位在线率分数");
        //如果是月底,需要统计平均在线率然后进行积分扣除
//        String now = DateUtils.getDate();
        String mouthStart = DateUtils.getMouthStart(new Date());
        String mouthEnd = DateUtils.getMouthEnd(new Date());
//        if (now.equals(mouthEnd)) {
            //查一个月的记录
            List<ContractRuleRecord> ruleMonthRecords = recordMapper.selectMonth(mouthStart, mouthEnd);
            //通过unitId分单位
            Map<Long, List<ContractRuleRecord>> unitMap = ruleMonthRecords.stream().collect(Collectors.groupingBy(ContractRuleRecord::getUnitId));
            //查在线率规则
            List<CalculateRuleVO> ruleVos = contractMapper.selectByRuleName(ContractRule.CONTRACT_RULE_Online.getName(), null, new Date());
            //获取key为合同id,value为在线率规则的map
            Map<Integer, List<CalculateRuleVO>> contractMap = ruleVos.stream().collect(Collectors.groupingBy(CalculateRuleVO::getContractId));
            //准备批量打分的集合
            List<ContractScore> contractScoreList = new ArrayList<>();
            contractMap.forEach((contractId, ruleList) -> {
                //一个合同对应一个单位,因此unitId都相同
                CalculateRuleVO calculateRuleVO = ruleList.get(0);
                Integer unitId = calculateRuleVO.getUnitId();
                List<ContractRuleRecord> ruleRecordList = unitMap.get(Long.parseLong(unitId + ""));
                if (!CollectionUtils.isEmpty(ruleMonthRecords)) {
                    BigDecimal siteOnlineTotal = ruleRecordList.stream().map(ContractRuleRecord::getSiteOnline).reduce(BigDecimal.ZERO, BigDecimal::add);
                    BigDecimal siteOnline = siteOnlineTotal.divide(new BigDecimal(ruleRecordList.size()), 2, RoundingMode.DOWN);
                    for (CalculateRuleVO ruleVO : ruleList) {
                        Double max = ruleVO.getMax();
                        Double min = ruleVO.getMin();
                        //判断范围在哪个区间
                        if (checkRange(min, max, siteOnline.multiply(new BigDecimal(100)))) {
                            //需要扣除的分数
                            Double deductScore = ruleVO.getCalcFraction();
                            ContractScore contractScore = new ContractScore();
                            contractScore.setContractId(Long.parseLong(contractId + ""));
                            contractScore.setAuditingStatus(AuditingStatus.PASS);
                            contractScore.setAuditingTime(new Date());
                            contractScore.setAuditingUser(Remark);
                            contractScore.setUnitId(Long.parseLong(unitId + ""));
                            contractScore.setRuleId(Long.parseLong(ruleVO.getId() + ""));
                            contractScore.setRuleIds("0," + ruleVO.getId());
                            contractScore.setNum(siteOnline + "");
                            contractScore.setDeductCategory(ruleVO.getDeductCategory().getDesc());
                            contractScore.setScore(new BigDecimal(deductScore));
                            contractScore.setRuleName(ruleVO.getRuleName() + "/" + ruleVO.getRuleCondition());
                            contractScore.setCreateTime(new Date());
                            contractScore.setUpdateTime(new Date());
                            contractScore.setRemark(Remark);
                            contractScoreList.add(contractScore);
                        }
                    }
                }
            });
//        }
        contractScoreService.saveBatch(contractScoreList);
        log.info("结束计算合同点位在线率分数");
    }
 
    private boolean checkRange(Double min, Double max, BigDecimal siteOnline) {
        if (siteOnline == null) {
            return false;
        }
        if (max != null && siteOnline.compareTo(new BigDecimal(max)) > 0) {
            return false;
        }
        if (min != null && siteOnline.compareTo(new BigDecimal(min)) < 0) {
            return false;
        }
        return true;
    }
 
}