zxl
4 天以前 c83101eb62f5d4906b9c01ceea6b21a37f9e84d8
ycl-server/src/main/java/com/ycl/task/DemeritRecordTask.java
@@ -4,6 +4,7 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.google.common.util.concurrent.AtomicDouble;
import com.ycl.platform.domain.entity.DailyMonitorDemeritRecord;
import com.ycl.platform.domain.entity.DemeritRecord;
import com.ycl.platform.domain.entity.MonitorConstruction;
import com.ycl.platform.domain.entity.Report;
@@ -11,6 +12,7 @@
import com.ycl.platform.mapper.DemeritRecordMapper;
import com.ycl.platform.mapper.IMonitorConstructionMapper;
import com.ycl.platform.mapper.ReportMapper;
import com.ycl.platform.service.IDailyMonitorDemeritRecordService;
import com.ycl.platform.service.IDemeritRecordService;
import com.ycl.utils.DateUtils;
import enumeration.ConstructionTypeEnum;
@@ -54,6 +56,8 @@
    private final IMonitorConstructionMapper monitorConstructionMapper;
    private final IDailyMonitorDemeritRecordService dailyMonitorDemeritRecordService;
    private static final ExecutorService executorService = new ThreadPoolExecutor(16,
            128,
            5000,
@@ -63,6 +67,8 @@
    );
    private final IDemeritRecordService demeritRecordService;
    private final IDailyMonitorDemeritRecordService iDailyMonitorDemeritRecordService;
    private DemeritRecord buildDemeritRecord(String constructionType,BigDecimal demerit,Integer deptId,Date recordTime) {
        DemeritRecord record = new DemeritRecord();
        record.setConstructionType(constructionType);
@@ -71,7 +77,19 @@
        record.setRecordTime(recordTime);
        return record;
    }
    private BigDecimal calculateTotalDeduction(List<RecordMetaDSumResult> records) {
    private DailyMonitorDemeritRecord buildDailyMonitorDemeritRecord(Date recordTime,String deviceId,String constructionType,BigDecimal demerit,Integer deptId,Boolean isReport,String deviceName) {
        DailyMonitorDemeritRecord demeritRecord  = new DailyMonitorDemeritRecord();
        demeritRecord.setRecordTime(recordTime);
        demeritRecord.setDemerit(demerit);
        demeritRecord.setConstructionType(constructionType);
        demeritRecord.setSerialNumber(deviceId);
        demeritRecord.setIsReport(isReport);
        demeritRecord.setDeptId(deptId);
        demeritRecord.setDeviceName(deviceName);
        return demeritRecord;
    }
    private BigDecimal calculateTotalDeduction(List<RecordMetaDSumResult> records,Date recordTime,Integer deptId,List<DailyMonitorDemeritRecord> dailyMonitorDemeritRecords) {
        BigDecimal total = BigDecimal.ZERO; // 单线程循环,无需AtomicReference
        for (RecordMetaDSumResult record : records) {
@@ -94,6 +112,8 @@
            } else {
                deduction = BigDecimal.ZERO;
            }
            dailyMonitorDemeritRecords.add(buildDailyMonitorDemeritRecord(recordTime,record.getDeviceId()
                    ,record.getConstructionType(),deduction,deptId,false,record.getDeviceName()));
            // 累加总扣分(最后统一处理精度,避免中间四舍五入误差)
            total = total.add(deduction);
@@ -143,19 +163,34 @@
        List<MonitorConstruction> monitorConstructionList = new LambdaQueryChainWrapper<>(monitorConstructionMapper)
                .eq(MonitorConstruction::getDeleted, Boolean.FALSE)
                .list();
        List<String> serialNumberList = monitorConstructionList.stream()
                .map(MonitorConstruction::getSerialNumber).collect(Collectors.toList());
        //过滤获得包含了这些标签的设备录像情况集合
        //按编号分组,值为设备对应标签
        Map<String, String> serialTagMap = monitorConstructionList.stream()
                .filter(mc -> mc.getSerialNumber() != null) // 过滤序列号为空的无效数据
                .collect(Collectors.toMap(
                        MonitorConstruction::getSerialNumber,
                        MonitorConstruction::getTag,
                        (oldVal, newVal) -> newVal
                ));
        //过滤掉没有标签的集合 并将标签赋值给录像情况集合
        results = results.stream()
                .filter(result -> {
                    String sn = result.getNo();
                    // 任一字段非空且在集合中即可
                    return (sn != null && serialNumberList.contains(sn));
                    // 过滤条件:序列号非空 + 在标签Map中存在(即有对应标签)
                    boolean isMatch = sn != null && serialTagMap.containsKey(sn);
                    if (isMatch) {
                        // 匹配成功,将标签赋值给result(需确保RecordMetaDSumResult有setTag()方法)
                        String tag = serialTagMap.get(sn);
                        result.setConstructionType(tag); // 关键:赋值标签
                    }
                    return isMatch; // 只保留有标签的result
                })
                .collect(Collectors.toList());
        log.info("剩余考核设备过滤后设备数{}",results.size());
        log.info("有标签的设备记录集合大小:{}",results.size());//这是需要计算扣分的录像数据
        //过滤掉报备的设备
        //查询在当前时间有报备的所有设备,
@@ -169,8 +204,12 @@
        List<Report> list = new LambdaQueryChainWrapper<>(reportMapper)
                .eq(Report::getStatus, 1)
                .ge(Report::getBeginCreateTime, DateUtils.getDayStart(yesterday))
                .le(Report::getEndCreateTime,  DateUtils.getDayEnd(yesterday))
                // getEndCreateTime getEndCreateTime  01 00:00:00 - 30 11:59:59
                .le(Report::getBeginCreateTime,
                        DateUtils.getDayStart(yesterday))
                //>=
                .ge(Report::getEndCreateTime, DateUtils.getDayEnd(yesterday))
                .list();
        log.info("报备记录:{}",list);
@@ -186,19 +225,14 @@
                .map(Report::getSerialNumber).collect(Collectors.toList());
        Set<String> deviceIdSet = new HashSet<>(deviceIds);
        log.info("报备设备数{}",deviceIdSet.size());
        results = results.stream()
                .filter(result -> {
                    // 获取当前对象的deviceId
                    String resultDeviceId = result.getDeviceId();
                    // 过滤条件:deviceId不在集合中(注意处理null值,避免NPE)
                    return resultDeviceId != null && !deviceIdSet.contains(resultDeviceId);
                })
                .collect(Collectors.toList());
        log.info("剩余过滤报备后设备数{}",results.size());
        // 按区域划分 组装成map
        List<DailyMonitorDemeritRecord> dailyMonitorDemeritRecords = new ArrayList<>();
        Date yesterdayBegin = DateUtils.getDayStart(yesterday);
        // 遍历区分对象的报备状态
        // 因为下面会过滤覆盖掉考核设备,需要已报备的设备录像情况信息,
        // 所以此处应该将已报备的设备录像情况信息添加到每日扣分详情记录中并初始化好 后续不在处理直接添加数据库中
        // 将区域信息 放入集合中
        results.forEach(item -> {
            String areaCode = item.getArealayername().substring(0, 6);
            AreaDeptEnum areaDeptEnum = AreaDeptEnum.fromCode(areaCode);
@@ -206,9 +240,42 @@
                item.setArealayerno(areaDeptEnum.getCode());
            }
        });
        results.forEach(result ->{
            String deviceId = result.getDeviceId();
            if (StringUtils.isNotBlank(deviceId)) {
                if (deviceIdSet.contains(deviceId)) {
                    //已报备设备记录
                    AreaDeptEnum areaDeptEnum = AreaDeptEnum.fromCode(result.getArealayerno());
                    if (areaDeptEnum == null) {
                        log.info("区域数据异常,异常区域键值:{}",result.getArealayerno());
                        return;
                    }
                    DailyMonitorDemeritRecord demeritRecord  = buildDailyMonitorDemeritRecord(
                            yesterdayBegin,deviceId,
                            result.getConstructionType(),
                            BigDecimal.ZERO,
                            areaDeptEnum.getDeptId(),
                            true,
                            result.getDeviceName()
                    );
                    dailyMonitorDemeritRecords.add(demeritRecord);
                }
            }
        });
        // 过滤获得未报备集合
        results = results.stream()
                .filter(result -> {
                    String resultDeviceId = result.getDeviceId();
                    return resultDeviceId != null && !deviceIdSet.contains(resultDeviceId);
                })
                .collect(Collectors.toList());
        log.info("剩余过滤报备后设备数{}",results.size());
        //需要添加数据库的数据集合
        List<DemeritRecord> demeritRecords = new ArrayList<>();
        // 按区域划分 组装成map
        Map<String,List<RecordMetaDSumResult>> groupByArealayerno = results.stream()
                .collect(Collectors.groupingBy(RecordMetaDSumResult::getArealayerno));
@@ -290,17 +357,17 @@
                        .collect(Collectors.toList());
                log.info("沿滩二期人脸{}", yan_tan_phase_two_face.size());
                //一二期
                buildAndAddDemeritRecords(phase_one_two, ConstructionTypeEnum.PHASE_ONE_TWO.name(), areaDeptEnum.getDeptId(),yesterday,demeritRecords);
                buildAndAddDemeritRecords(phase_one_two, ConstructionTypeEnum.PHASE_ONE_TWO.name(), areaDeptEnum.getDeptId(),yesterdayBegin,demeritRecords,dailyMonitorDemeritRecords);
                //三期
                buildAndAddDemeritRecords(phase_three, ConstructionTypeEnum.PHASE_THREE.name(), areaDeptEnum.getDeptId(),yesterday,demeritRecords);
                buildAndAddDemeritRecords(phase_three, ConstructionTypeEnum.PHASE_THREE.name(), areaDeptEnum.getDeptId(),yesterdayBegin,demeritRecords,dailyMonitorDemeritRecords);
                //四期
                buildAndAddDemeritRecords(phase_fourth, ConstructionTypeEnum.PHASE_FOURTH.name(), areaDeptEnum.getDeptId(),yesterday,demeritRecords);
                buildAndAddDemeritRecords(phase_fourth, ConstructionTypeEnum.PHASE_FOURTH.name(), areaDeptEnum.getDeptId(),yesterdayBegin,demeritRecords,dailyMonitorDemeritRecords);
                //入川即检
                buildAndAddDemeritRecords(check_enter_sichuan, ConstructionTypeEnum.CHECK_ENTER_SICHUAN.name(), areaDeptEnum.getDeptId(),yesterday,demeritRecords);
                buildAndAddDemeritRecords(check_enter_sichuan, ConstructionTypeEnum.CHECK_ENTER_SICHUAN.name(), areaDeptEnum.getDeptId(),yesterdayBegin,demeritRecords,dailyMonitorDemeritRecords);
                //东部新城
                buildAndAddDemeritRecords(eastern_new_city, ConstructionTypeEnum.EASTERN_NEW_CITY.name(), areaDeptEnum.getDeptId(),yesterday,demeritRecords);
                buildAndAddDemeritRecords(eastern_new_city, ConstructionTypeEnum.EASTERN_NEW_CITY.name(), areaDeptEnum.getDeptId(),yesterdayBegin,demeritRecords,dailyMonitorDemeritRecords);
                //沿滩二期人脸
                buildAndAddDemeritRecords(yan_tan_phase_two_face, ConstructionTypeEnum.YAN_TAN_PHASE_TWO_FACE.name(), areaDeptEnum.getDeptId(),yesterday,demeritRecords);
                buildAndAddDemeritRecords(yan_tan_phase_two_face, ConstructionTypeEnum.YAN_TAN_PHASE_TWO_FACE.name(), areaDeptEnum.getDeptId(),yesterdayBegin,demeritRecords,dailyMonitorDemeritRecords);
            }
        }
@@ -308,32 +375,39 @@
        //处理完数据插入数据库中
        //先删除需要插入时间是否存在数据
        LambdaQueryWrapper<DemeritRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ge(DemeritRecord::getCreateTime,DateUtils.getDayStart(today))
        LambdaQueryWrapper<DemeritRecord> demeritRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
        demeritRecordLambdaQueryWrapper.ge(DemeritRecord::getCreateTime,DateUtils.getDayStart(today))
                        .le(DemeritRecord::getCreateTime,DateUtils.getDayEnd(today));
        demeritRecordService.remove(queryWrapper);
        demeritRecordService.remove(demeritRecordLambdaQueryWrapper);
        demeritRecordService.saveBatch(demeritRecords);
        log.info("结束计算每日扣分记录情况:插入数据量{},数据信息:{}",demeritRecords.size(),demeritRecords);
        //填充设备录像情况扣分详情结果
        LambdaQueryWrapper<DailyMonitorDemeritRecord> dailyMonitorDemeritRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
        dailyMonitorDemeritRecordLambdaQueryWrapper.ge(DailyMonitorDemeritRecord::getCreateTime,DateUtils.getDayStart(today))
                .le(DailyMonitorDemeritRecord::getCreateTime,DateUtils.getDayEnd(today));
        iDailyMonitorDemeritRecordService.remove(dailyMonitorDemeritRecordLambdaQueryWrapper);
        iDailyMonitorDemeritRecordService.saveBatch(dailyMonitorDemeritRecords);
        log.info("结束计算每日扣分记录详情情况:插入数据量{},数据信息:{}",dailyMonitorDemeritRecords.size(),dailyMonitorDemeritRecords);
    }
    public void buildAndAddDemeritRecords(List<RecordMetaDSumResult> constructionByRecordMetaList,
                                          String constructionType,Integer areaDeptId,Date recordTime,
                                          List<DemeritRecord> demeritRecords) {
                                          List<DemeritRecord> demeritRecords,
                                          List<DailyMonitorDemeritRecord> dailyMonitorDemeritRecords) {
        if (CollectionUtils.isNotEmpty(constructionByRecordMetaList)) {
                    BigDecimal deduction = calculateTotalDeduction(constructionByRecordMetaList);
                    BigDecimal deduction = calculateTotalDeduction(constructionByRecordMetaList,recordTime,areaDeptId,dailyMonitorDemeritRecords);
                    DemeritRecord demeritRecord = buildDemeritRecord(
                            constructionType,
                            deduction,
                            areaDeptId,
                            DateUtils.getDayStart(recordTime));
                            recordTime);
                    demeritRecords.add(demeritRecord);
                }else{
                    DemeritRecord demeritRecord = buildDemeritRecord(
                            constructionType,
                            BigDecimal.ZERO,
                            areaDeptId,
                            DateUtils.getDayStart(recordTime));
                            recordTime);
                    demeritRecords.add(demeritRecord);
        }
    }