xiangpei
2024-08-23 0b8a348d0b978eeddfa3995b87cd11f7cbdd48a9
ycl-server/src/main/java/com/ycl/task/ContractTask.java
@@ -3,20 +3,22 @@
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mongodb.client.result.DeleteResult;
import com.ycl.platform.domain.entity.ContractRuleRecord;
import com.ycl.platform.domain.entity.Report;
import com.ycl.platform.domain.entity.TMonitor;
import com.ycl.platform.domain.entity.YwPoint;
import com.ycl.platform.domain.entity.*;
import com.ycl.platform.domain.result.HK.PicAccessResult;
import com.ycl.platform.domain.result.HK.SnapshotDataMonitorResult;
import com.ycl.platform.domain.result.UY.RecordMetaDSumResult;
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;
@@ -31,6 +33,7 @@
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
/**
 * 合同考核定时任务
@@ -52,10 +55,14 @@
    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 = "系统生成";
    private static final Integer randomSize = 50;
    /**
     * 合同考核 在线率每日任务检测
@@ -66,9 +73,12 @@
     * 月底计算平均值,根据在线率和合同标准扣减分数
     */
    public void onlineCheck() {
        List<CalculateRuleVO> ruleVos = contractMapper.selectByRuleName(ContractRule.CONTRACT_RULE_Online.getName(), null, new Date());
        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("unitId", unitIds));
        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(
@@ -116,13 +126,275 @@
                    onlineSite++;
                }
            }
            BigDecimal online = new BigDecimal(onlineSite).divide(new BigDecimal(totalSite), 2, RoundingMode.DOWN);
            ContractRuleRecord contractRuleRecord = new ContractRuleRecord();
            contractRuleRecord.setSiteOnline( onlineSite / totalSite);
            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 randomDeductPic() {
        Random random = new Random();
        //给定随机范围
        int number = random.nextInt(randomSize);
        if (number == 0) {
            log.info("开始抽查图片完整状态");
            //准备批量打分的集合
            List<ContractScore> contractScoreList = new ArrayList<>();
            Date date = DateUtils.getDay(2024, 7, 13);
            //查图片完整性规则 获取key为合同id,value为规则的map
            Map<Integer, List<CalculateRuleVO>> contractMap = contractMapper.getCalculateRule(new Date()).stream()
                    .filter(calculateRuleVO -> ContractRule.CONTRACT_RULE_PicComplete.getName().equals(calculateRuleVO.getRuleName()))
                    .collect(Collectors.groupingBy(CalculateRuleVO::getContractId));
            //判断车辆、人脸图片是否可用
            Query query = new Query(Criteria
                    .where("mongoCreateTime").gte(DateUtils.getDayStart(date)).lt(DateUtils.getDayEnd(date)));
            List<PicAccessResult> picAccessResults = mongoTemplate.find(query, PicAccessResult.class);
            List<String> serialNumbers = picAccessResults.stream().map(PicAccessResult::getExternalIndexCode).collect(Collectors.toList());
            QueryWrapper<YwPoint> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("serial_number", serialNumbers);
            //获取公司所运维的设备集合,key为unitId value为设备国标码集合
            Map<Long, List<String>> unitMonitorMap = ywPointMapper.selectList(queryWrapper).stream()
                    .collect(Collectors.groupingBy(YwPoint::getUnitId,
                            Collectors.mapping(
                                    YwPoint::getSerialNumber,
                                    Collectors.toList())));
            contractMap.forEach((contractId, ruleList) -> {
                boolean deduct = false;
                String serialNumber = null;
                //此规则对应的unitId均相等
                CalculateRuleVO ruleVO = ruleList.get(0);
                Integer unitId = ruleVO.getUnitId();
                List<String> monitorList = unitMonitorMap.get(Long.parseLong(unitId + ""));
                for (PicAccessResult picAccessResult : picAccessResults) {
                    //判断是否是该公司运维
                    if (monitorList.contains(picAccessResult.getExternalIndexCode())) {
                        //存在大图不可用数据量,需要扣减
                        if (picAccessResult.getBigDisableCount() > 0) {
                            deduct = true;
                            serialNumber = picAccessResult.getExternalIndexCode();
                            break;
                        }
                    }
                }
                if (deduct) {
                    //需要扣除的分数,此规则只有一条不需要判断范围
                    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(ruleVO.getUnitId() + ""));
                    contractScore.setRuleId(Long.parseLong(ruleVO.getId() + ""));
                    contractScore.setRuleIds("0," + ruleVO.getId());
                    contractScore.setNum(1 + "");
                    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 + "国标码为:" + serialNumber + "时间:" + new Date() + "存在大图不可用数据");
                    contractScoreList.add(contractScore);
                }
            });
            contractScoreService.saveBatch(contractScoreList);
            log.info("结束抽查图片完整状态");
        }
    }
    /**
     * 不定期检查数据 扣除积分
     * 每天一次随机数判断成功就执行
     * 优云取录像
     */
    public void randomDeductVideo() {
        Random random = new Random();
        //给定随机范围
        int number = random.nextInt(randomSize);
        if (number == 0) {
            log.info("开始抽查录像完整状态");
            //准备批量打分的集合
            List<ContractScore> contractScoreList = new ArrayList<>();
            Date date = DateUtils.getDay(2024, 7, 13);
            //查图片完整性规则 获取key为合同id,value为规则的map
            Map<Integer, List<CalculateRuleVO>> contractMap = contractMapper.getCalculateRule(new Date()).stream()
                    .filter(calculateRuleVO -> ContractRule.CONTRACT_RULE_VideoRecord.getName().equals(calculateRuleVO.getRuleName()))
                    .collect(Collectors.groupingBy(CalculateRuleVO::getContractId));
            //取录像数据
            Query query = new Query(Criteria
                    .where("mongoCreateTime").gte(DateUtils.getDayStart(date)).lt(DateUtils.getDayEnd(date)));
            List<RecordMetaDSumResult> recordMetaDSumResults = mongoTemplate.find(query, RecordMetaDSumResult.class);
            List<String> serialNumbers = recordMetaDSumResults.stream().map(RecordMetaDSumResult::getDeviceId).collect(Collectors.toList());
            QueryWrapper<YwPoint> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("serial_number", serialNumbers);
            //获取公司所运维的设备集合,key为unitId value为设备国标码集合
            Map<Long, List<String>> unitMonitorMap = ywPointMapper.selectList(queryWrapper).stream()
                    .collect(Collectors.groupingBy(YwPoint::getUnitId,
                            Collectors.mapping(
                                    YwPoint::getSerialNumber,
                                    Collectors.toList())));
            contractMap.forEach((contractId, ruleList) -> {
                //此规则对应的unitId均相等
                CalculateRuleVO ruleVO = ruleList.get(0);
                Integer unitId = ruleVO.getUnitId();
                List<String> monitorList = unitMonitorMap.get(Long.parseLong(unitId + ""));
                for (RecordMetaDSumResult result : recordMetaDSumResults) {
                    //判断是否是该公司运维
                    if (monitorList.contains(result.getDeviceId())) {
                        //录像状态不完整
                        if (!Objects.equals(result.getRecordStatus(), ApiConstants.UY_RecordStatus_Integrity)) {
                            for (CalculateRuleVO calculateRuleVO : ruleList) {
                                Double max = calculateRuleVO.getMax();
                                Double min = calculateRuleVO.getMin();
                                //判断范围在哪个区间
                                if (checkRange(min, max, BigDecimal.valueOf(result.getMissDuration()))) {
                                    if(calculateRuleVO.getNum() == null){
                                        calculateRuleVO.setNum(1);
                                    }else {
                                        calculateRuleVO.setNum(calculateRuleVO.getNum()+1);
                                    }
                                }
                            }
                        }
                    }
                }
                for (CalculateRuleVO calculateRuleVO : ruleList) {
                    //需要扣除的分数,此规则只有一条不需要判断范围
                    double deductScore = calculateRuleVO.getCalcFraction()*calculateRuleVO.getNum();
                    ContractScore contractScore = new ContractScore();
                    contractScore.setContractId(Long.parseLong(contractId + ""));
                    contractScore.setAuditingStatus(AuditingStatus.PASS);
                    contractScore.setAuditingTime(new Date());
                    contractScore.setAuditingUser(Remark);
                    contractScore.setUnitId(Long.parseLong(calculateRuleVO.getUnitId() + ""));
                    contractScore.setRuleId(Long.parseLong(calculateRuleVO.getId() + ""));
                    contractScore.setRuleIds("0," + calculateRuleVO.getId());
                    contractScore.setNum(calculateRuleVO.getNum() + "");
                    contractScore.setDeductCategory(calculateRuleVO.getDeductCategory().getDesc());
                    contractScore.setScore(new BigDecimal(deductScore));
                    contractScore.setRuleName(calculateRuleVO.getRuleName() + "/" + calculateRuleVO.getRuleCondition());
                    contractScore.setCreateTime(new Date());
                    contractScore.setUpdateTime(new Date());
                    contractScore.setRemark(Remark+calculateRuleVO.getNum()+"路设备违反规则");
                    contractScoreList.add(contractScore);
                }
            });
            contractScoreService.saveBatch(contractScoreList);
            log.info("结束抽查图片完整状态");
        }
    }
}