fuliqi
2024-08-22 f37bacfd573715e20dcd003e2b4000f9713aceff
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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
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.getCalculateRule(new Date()).stream()
                .filter(calculateRuleVO -> ContractRule.CONTRACT_RULE_Online.getName().equals(calculateRuleVO.getRuleName()))
                .collect(Collectors.toList());
        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));
        //查在线率规则 获取key为合同id,value为在线率规则的map
        Map<Integer, List<CalculateRuleVO>> contractMap = contractMapper.getCalculateRule(new Date()).stream()
                .filter(calculateRuleVO -> ContractRule.CONTRACT_RULE_Online.getName().equals(calculateRuleVO.getRuleName()))
                .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;
    }
 
    /**
     *   检测工单表 进行合同积分扣除
     *   查出工单需要扣分的所有规则
     *   查出未扣分且已经审核完成了的工单组成map<unitId,List<WorkOrder>> 工单需要连工单故障表查出多个故障类型
     *   循环工单map,每个工单故障类型查对应的规则,根据规则和工单创建时间和审核通过时间进行扣分
     *   插入合同积分表,修改工单状态为已扣分
     */
    public void workOrderDeduct() {
        //查询生效合同对应所有的规则
        List<CalculateRuleVO> calculateRules = contractMapper.getCalculateRule(new Date());
        Map<String, Map<Integer, List<CalculateRuleVO>>> ruleMap = calculateRules.stream()
                .collect(Collectors.groupingBy(
                        CalculateRuleVO::getRuleName,  // 按规则名称分组
                        Collectors.groupingBy(
                                CalculateRuleVO::getContractId // 每个规则名称内部再按合同ID分组,value为规则集合
                        )
                ));
        //前端感知源治理工作(时钟同步规则、OSD规则、一机一档规则) 获取key为合同id,value为规则的map
        Map<Integer, List<CalculateRuleVO>> monitorRuleMap = ruleMap.get(ContractRule.CONTRACT_RULE_Monitor.getName());
        //存储故障(24小时以内,48小时以内) 获取key为合同id,value为规则的map
        Map<Integer, List<CalculateRuleVO>> storeRuleMap = ruleMap.get(ContractRule.CONTRACT_RULE_Store.getName());
        //点位异常情况处理 获取key为合同id,value为规则的map
        Map<Integer, List<CalculateRuleVO>> siteRuleMap = ruleMap.get(ContractRule.CONTRACT_RULE_Site.getName());
 
    }
    /**
     *  不定期检查数据 扣除积分
     */
    public void randomDeduct() {
 
    }
 
}