package com.xjrsoft.module.job; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.xjrsoft.common.utils.VoToColumnUtil; import com.xjrsoft.common.utils.WeChatUtil; import com.xjrsoft.config.CommonPropertiesConfig; import com.xjrsoft.module.attendance.entity.AttendanceMessageSet; import com.xjrsoft.module.attendance.entity.AttendanceMessageUserRelation; import com.xjrsoft.module.attendance.entity.AttendanceRuleDetails; import com.xjrsoft.module.attendance.service.IAttendanceMessageSetService; import com.xjrsoft.module.attendance.service.IAttendanceRuleCategoryService; import com.xjrsoft.module.concat.service.IXjrUserService; import com.xjrsoft.module.holiday.entity.HolidayDate; import com.xjrsoft.module.holiday.service.IHolidayDateService; import com.xjrsoft.module.organization.dto.WeChatSendMessageDto; import com.xjrsoft.module.organization.entity.UserRoleRelation; import com.xjrsoft.module.organization.service.IWeChatService; import com.xjrsoft.module.outint.entity.StudentOutInRecord; import com.xjrsoft.module.outint.entity.TeacherOutInRecord; import com.xjrsoft.module.outint.service.IStudentOutInRecordService; import com.xjrsoft.module.outint.service.ITeacherOutInRecordService; import com.xjrsoft.module.student.entity.BaseStudent; import com.xjrsoft.module.system.entity.WechatMessageLog; import com.xjrsoft.module.system.service.IWechatMessageLogService; import com.xjrsoft.module.teacher.entity.BaseTeacher; import com.xjrsoft.module.teacher.entity.XjrUser; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; /** * 考勤消息通知,给领导推送每个时段的考勤情况 * @author dzx * @date 2024年6月7日 */ @Component @Slf4j public class AttendanceMessageTask { @Autowired private IAttendanceMessageSetService messageSetService; @Autowired private IAttendanceRuleCategoryService ruleCategoryService; @Autowired private IHolidayDateService holidayDateService; @Autowired private IXjrUserService userService; @Autowired private IStudentOutInRecordService studentOutInRecordService; @Autowired private ITeacherOutInRecordService teachertOutInRecordService; @Autowired private IWeChatService weChatService; @Autowired private CommonPropertiesConfig commonPropertiesConfig; @Autowired private WeChatUtil weChatUtil; @Autowired private IWechatMessageLogService wechatMessageLogService; @Scheduled(cron = "0 */1 * * * ?") public void RefreshConnectionPool() { String active = SpringUtil.getActiveProfile(); if(!"prod".equals(active)){ log.info("非正式环境,无法执行数据推送"); return; } doExecute(); } public void doExecute(){ LocalDateTime now = LocalDateTime.now(); HolidayDate holidayDate = holidayDateService.getOne( new QueryWrapper().lambda() .eq(HolidayDate::getDate, now.toLocalDate()) ); if(holidayDate != null && holidayDate.getWay() != null && holidayDate.getWay() != 0 && holidayDate.getWay() != 2){ log.info("非工作日,不需要提醒"); return; } //查询今天的考勤规则 List ruleDetails = ruleCategoryService.getTodayRules(); List list = messageSetService.list(); //判断是上午还是下午 Integer timePeriod = null; String timePeriodStr = null; if(now.getHour() <= 12){ timePeriod = 1; timePeriodStr = "上午考勤"; }else if(now.getHour() <= 18){ timePeriod = 2; timePeriodStr = "下午考勤"; }else{ timePeriod = 3; timePeriodStr = "晚上考勤"; } DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); int userCount = 0; Set roleTypes = list.stream().map(AttendanceMessageSet::getRoleType).collect(Collectors.toSet()); //查询需要通知的人 for (AttendanceMessageSet messageSet : list) { LocalDateTime recentlyTime = null; String characterKey = "character_string18"; String wechatTemplate = weChatUtil.getAttendanceMsgLateTemplate(); if(messageSet.getMessageCategory() != null && messageSet.getMessageCategory() == 1){ wechatTemplate = weChatUtil.getAttendanceMsgLateTemplate(); characterKey = "character_string18"; //获取最近的时间 recentlyTime = getRecentlyTime(ruleDetails, now); if(recentlyTime.getHour() != now.getHour() && Math.abs(recentlyTime.getMinute() - now.getMinute()) >= 2){ log.info("未到时间,不进行推送"); continue; } long count = wechatMessageLogService.count( new QueryWrapper().lambda() .eq(WechatMessageLog::getSendTime, recentlyTime) .eq(WechatMessageLog::getTemplateId, wechatTemplate) ); if(count > 0){//已经推送过,不再进行推送 log.info("已推送过,不进行推送"); continue; } }else if(messageSet.getMessageCategory() != null && messageSet.getMessageCategory() == 3){ wechatTemplate = weChatUtil.getAttendanceMsgAbsenceTemplate(); recentlyTime = getRecentlyOverTime(ruleDetails, now); characterKey = "character_string36"; if(recentlyTime.getHour() != now.getHour() && Math.abs(recentlyTime.getMinute() - now.getMinute()) >= 2){ log.info("未到时间,不进行推送"); continue; } long count = wechatMessageLogService.count( new QueryWrapper().lambda() .eq(WechatMessageLog::getSendTime, recentlyTime) .eq(WechatMessageLog::getTemplateId, wechatTemplate) ); if(count > 0){//已经推送过,不再进行推送 log.info("已推送过,不进行推送"); continue; } } if(!messageSet.getTimePeriod().contains(timePeriod + "")){ continue; } List userList = userService.list( new MPJLambdaWrapper().distinct() .select(XjrUser::getId) .select(XjrUser.class, x -> VoToColumnUtil.fieldsToColumns(XjrUser.class).contains(x.getProperty())) .leftJoin(UserRoleRelation.class, UserRoleRelation::getUserId, XjrUser::getId) .leftJoin(AttendanceMessageUserRelation.class, AttendanceMessageUserRelation::getUserId, XjrUser::getId) .in(UserRoleRelation::getRoleId, roleTypes) .eq(AttendanceMessageUserRelation::getAttendanceMessageSetId, messageSet.getId()) ); //没有需要通知的,直接跳过 if(userList.isEmpty()){ continue; } if(recentlyTime == null){ continue; } String format = recentlyTime.format(formatter); userCount += userList.size(); if(messageSet.getRoleType() != null && messageSet.getRoleType() == 1){ //教师总人数 long teacherCout = userService.count( new MPJLambdaWrapper() .leftJoin(BaseTeacher.class, BaseTeacher::getUserId, XjrUser::getId) ); //查询进入记录,就是实际到校的人数 List outInRecords = teachertOutInRecordService.list( new MPJLambdaWrapper() .le(TeacherOutInRecord::getRecordTime, recentlyTime) .eq(TeacherOutInRecord::getStatus, 1) .eq("DATE_FORMAT(record_time, '%Y-%m-%d')", recentlyTime.toLocalDate()) ); List collect = outInRecords.stream().map(TeacherOutInRecord::getUserId).collect(Collectors.toList()); WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto(); weChatSendMessageDto.setTemplateId(wechatTemplate); JSONObject paramJson = new JSONObject(); JSONObject thing6 = new JSONObject(); thing6.put("value", "教职工"); paramJson.put("thing6", thing6); JSONObject time11 = new JSONObject(); time11.put("value", format); paramJson.put("time11", time11); JSONObject const23 = new JSONObject(); const23.put("value", timePeriodStr); paramJson.put("const23", const23); //迟到人数或者缺勤人数 JSONObject character_string18 = new JSONObject(); character_string18.put("value", teacherCout - collect.size()); paramJson.put(characterKey, character_string18); JSONObject character_string16 = new JSONObject(); character_string16.put("value", teacherCout); paramJson.put("character_string16", character_string16); weChatSendMessageDto.setContent(paramJson); weChatSendMessageDto.setUrl(StrUtil.format("{}pages/attendance/teacher/index", commonPropertiesConfig.getDomainApp())); for (XjrUser xjrUser : userList) { weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + ""); weChatSendMessageDto.setUserId(xjrUser.getOpenId()); // weChatService.sendTemplateMessage(weChatSendMessageDto); } }else if(messageSet.getRoleType() != null && messageSet.getRoleType() == 2){ //教师总人数 long teacherCout = userService.count( new MPJLambdaWrapper() .leftJoin(BaseStudent.class, BaseStudent::getUserId, XjrUser::getId) ); //查询进入记录,就是实际到校的人数 long outInRecords = studentOutInRecordService.count( new MPJLambdaWrapper() .le(StudentOutInRecord::getRecordTime, recentlyTime) .eq(StudentOutInRecord::getStatus, 1) ); WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto(); weChatSendMessageDto.setTemplateId(wechatTemplate); JSONObject paramJson = new JSONObject(); JSONObject thing6 = new JSONObject(); thing6.put("value", "学生"); paramJson.put("thing6", thing6); JSONObject time11 = new JSONObject(); time11.put("value", format); paramJson.put("time11", time11); JSONObject const23 = new JSONObject(); const23.put("value", timePeriodStr); paramJson.put("const23", const23); JSONObject character_string18 = new JSONObject(); character_string18.put("value", teacherCout - outInRecords); paramJson.put(characterKey, character_string18); JSONObject character_string16 = new JSONObject(); character_string16.put("value", teacherCout); paramJson.put("const3", character_string16); weChatSendMessageDto.setContent(paramJson); weChatSendMessageDto.setUrl(StrUtil.format("{}pages/attendance/class/index", commonPropertiesConfig.getDomainApp())); for (XjrUser xjrUser : userList) { weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + ""); weChatSendMessageDto.setUserId(xjrUser.getOpenId()); // weChatService.sendTemplateMessage(weChatSendMessageDto); } } WechatMessageLog messageLog = new WechatMessageLog(); messageLog.setTemplateId(wechatTemplate); messageLog.setSendTime(recentlyTime); messageLog.setCreateDate(new Date()); messageLog.setContent("消息推送人数:" + userCount); wechatMessageLogService.save(messageLog); } } LocalDateTime getRecentlyTime(List ruleDetails, LocalDateTime now){ List result = new ArrayList<>(); for (AttendanceRuleDetails ruleDetail : ruleDetails) { if(ruleDetail.getIsAllowInOutSchool() != null && ruleDetail.getIsAllowInOutSchool() == 1 && ruleDetail.getIsAttendance() != null && ruleDetail.getIsAttendance() == 1){ if(ruleDetail.getAmStartTime() != null){ LocalDateTime amStartTime = now.with(ruleDetail.getAmStartTime().toLocalTime()); result.add(amStartTime); } if(ruleDetail.getPmStartTime() != null){ LocalDateTime pmStartTime = now.with(ruleDetail.getPmStartTime().toLocalTime()); result.add(pmStartTime); } if(ruleDetail.getEveningStartTime() != null){ LocalDateTime eveningStartTime = now.with(ruleDetail.getEveningStartTime().toLocalTime()); result.add(eveningStartTime); } } } if(result.isEmpty()){ return null; } Map timeMap = new HashMap<>(); for (LocalDateTime localDateTime : result) { long between = ChronoUnit.SECONDS.between(now, localDateTime); timeMap.put(Math.abs(between), localDateTime); } List collect = timeMap.keySet().stream().collect(Collectors.toList()); Collections.sort(collect, Long::compare); return timeMap.get(collect.get(0)); } LocalDateTime getRecentlyOverTime(List ruleDetails, LocalDateTime now){ List result = new ArrayList<>(); for (AttendanceRuleDetails ruleDetail : ruleDetails) { if(ruleDetail.getIsAllowInOutSchool() != null && ruleDetail.getIsAllowInOutSchool() == 1 && ruleDetail.getIsAttendance() != null && ruleDetail.getIsAttendance() == 1){ if(ruleDetail.getAmStartTime() != null){ LocalDateTime amStartTime = now.with(ruleDetail.getAmStartTime().toLocalTime()); if(ruleDetail.getOverMinutes() != null){ amStartTime.plusMinutes(ruleDetail.getOverMinutes()); } result.add(amStartTime); } if(ruleDetail.getPmStartTime() != null){ LocalDateTime pmStartTime = now.with(ruleDetail.getPmStartTime().toLocalTime()); if(ruleDetail.getOverMinutes() != null){ pmStartTime.plusMinutes(ruleDetail.getOverMinutes()); } result.add(pmStartTime); } if(ruleDetail.getEveningStartTime() != null){ LocalDateTime eveningStartTime = now.with(ruleDetail.getEveningStartTime().toLocalTime()); if(ruleDetail.getOverMinutes() != null){ eveningStartTime.plusMinutes(ruleDetail.getOverMinutes()); } result.add(eveningStartTime); } } } if(result.isEmpty()){ return null; } Map timeMap = new HashMap<>(); for (LocalDateTime localDateTime : result) { long between = ChronoUnit.SECONDS.between(now, localDateTime); timeMap.put(Math.abs(between), localDateTime); } List collect = timeMap.keySet().stream().collect(Collectors.toList()); Collections.sort(collect, Long::compare); return timeMap.get(collect.get(0)); } }