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 ruleVos = contractMapper.selectByRuleName(ContractRule.CONTRACT_RULE_Online.getName(), null, new Date()); List unitIds = ruleVos.stream().map(CalculateRuleVO::getUnitId).collect(Collectors.toList()); List ywPoints = ywPointMapper.selectList(new QueryWrapper().in("unit_id", unitIds)); //key是unitId value是设备编码集合 Map> unitMap = ywPoints.stream() .collect(Collectors.groupingBy( YwPoint::getUnitId, Collectors.mapping( YwPoint::getSerialNumber, Collectors.toList() ) )); Map 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 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 videoOnlineResults = mongoTemplate.find(videoQuery, VideoOnlineResult.class); for (VideoOnlineResult videoOnlineResult : videoOnlineResults) { onlineStatusMap.put(videoOnlineResult.getDeviceId(), videoOnlineResult.getStatus()); } //查询报备列表 List reportNumbers = reportMapper.selectNumberList(AuditStatus_Pass, DateUtils.getDate()); //计算每个公司的点位在线率 List 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 ruleMonthRecords = recordMapper.selectMonth(mouthStart, mouthEnd); //通过unitId分单位 Map> unitMap = ruleMonthRecords.stream().collect(Collectors.groupingBy(ContractRuleRecord::getUnitId)); //查在线率规则 List ruleVos = contractMapper.selectByRuleName(ContractRule.CONTRACT_RULE_Online.getName(), null, new Date()); //获取key为合同id,value为在线率规则的map Map> contractMap = ruleVos.stream().collect(Collectors.groupingBy(CalculateRuleVO::getContractId)); //准备批量打分的集合 List contractScoreList = new ArrayList<>(); contractMap.forEach((contractId, ruleList) -> { //一个合同对应一个单位,因此unitId都相同 CalculateRuleVO calculateRuleVO = ruleList.get(0); Integer unitId = calculateRuleVO.getUnitId(); List 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.WAIT); 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; } }