package com.template.controller; import com.alibaba.fastjson.JSON; import com.seewo.open.sdk.DefaultSeewoClient; import com.seewo.open.sdk.SeewoClient; import com.seewo.open.sdk.auth.Account; import com.template.common.utils.TimeExchange; import com.template.config.ScheduleConfig; import com.template.config.SeewoConfig; import com.template.model.pojo.SmartAttendance; import com.template.model.pojo.SmartClass; import com.template.model.pojo.SmartGrade; import com.template.model.pojo.SmartUser; import com.template.model.result.CommonResult; import com.template.model.seewo.*; import com.template.services.SmartAttendanceService; import com.template.services.SmartClassService; import com.template.services.SmartGradeService; import com.template.services.SmartUserService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import javax.annotation.Resource; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @Component //@EnableAsync public class ScheduleController { private static Logger logger = LoggerFactory.getLogger(ScheduleController.class); @Resource private SeewoConfig seewoConfig; @Resource private ScheduleConfig scheduleConfig; @Autowired private SmartClassService smartClassService; @Autowired private SmartGradeService smartGradeService; @Autowired private SmartUserService smartUserService; @Autowired private SmartAttendanceService smartAttendanceService; /** * @Scheduled注解会在默认情况下以单线程的方式执行定时任务。 这个“单线程”指两个方面: * 如果一个定时任务执行时间大于其任务间隔时间,那么下一次将会等待上一次执行结束后再继续执行。 * 如果多个定时任务在同一时刻执行,任务会依次执行。 * @Async:对某个方法进行异步执行 * @EnableAsync:开启异步支持 */ //定时格式参考:https://blog.csdn.net/java13992394428/article/details/108740453 /** * 每天八点自动派单 * 周六周日定时器不生效 * 其余时间都是早上八点前捞一遍当前时间以前的单子 * 有合适的维修师傅就把单子派给维修师傅 * 周一到周五早上七点执行:0 0 7 ? * MON-FRI * 周一到周五1、2、3、4、5、6、7、18、19、20、21、22点执行:0 0 1,2,3,4,5,6,7,18,19,20,21,22 ? * MON-FRI */ //凌晨两点:0 0 2 * * ? //每小时执行一次:0 0 */1 * * ? //每分钟执行一次:0 */1 * * * ? //周一到周五早上七点执行:0 0 7 ? * MON-FRI //0 0 22 * * ? @Async @Scheduled(cron = "0 0 */1 * * ?")//一个小时 //@Scheduled(cron = "0 */10 * * * ?")//10分钟 @Transactional(rollbackFor = {Exception.class}) public void autoDispatch() throws Exception { logger.info("1"); Date dateNow = new Date(); logger.info("2"); String getDate = TimeExchange.getDate(); try { if (scheduleConfig.getIsOpen().equals("1")) { logger.info("3"); List attendances = new ArrayList<>(); List deleteAttendances = new ArrayList<>(); //判断当前月份是九月前还是九月后 九月前就不包括本年 List gradeNames = new ArrayList<>(); Integer nowMonth = Integer.valueOf(TimeExchange.getNowMonth()); if (nowMonth.intValue() >= 9) { Integer yearNow = Integer.valueOf(TimeExchange.getYear()); gradeNames.add(yearNow + "级"); gradeNames.add((yearNow.intValue() - 1) + "级"); gradeNames.add((yearNow.intValue() - 2) + "级"); } else { Integer yearNow = Integer.valueOf(TimeExchange.getYear()); gradeNames.add((yearNow.intValue() - 1) + "级"); gradeNames.add((yearNow.intValue() - 2) + "级"); gradeNames.add((yearNow.intValue() - 3) + "级"); } logger.info("4"); List gradeIs = new ArrayList<>(); List gradeIds = new ArrayList<>(); List grades = smartGradeService.getSmartGrades(gradeNames); logger.info("5"); for (SmartGrade data : grades) { gradeIds.add(data.getId()+""); gradeIs.add(data.getId()); } List students = smartUserService.queryStudentsByGrade(gradeIds); logger.info("6"); // SmartUser studentData = smartUserService.getSmartById(1088); // students.add(studentData); //循环班级的classUid List classes = smartClassService.getSmartClasssByGrade(gradeIs); logger.info("7"); // SmartClass classData = smartClassService.getSmartClassById(204); // classes.add(classData); //当天已存在的考勤数据 判断是否重复使用 List attendanceList = smartAttendanceService.queryAttendancesNoleave(TimeExchange.getStartOfDayStr(dateNow), TimeExchange.getEndOfDayStr(dateNow)); logger.info("8"); for (SmartClass data : classes) { logger.info("循环1"); Optional oGrade = grades.stream().filter(e -> e.getId().equals(data.getGradeId())).findFirst(); logger.info("循环2"); //region 获取考勤事件ID //初始化客户端 SeewoClient seewoClient = new DefaultSeewoClient(new Account(seewoConfig.getAppId(), seewoConfig.getAppSecret())); logger.info("循环3"); AttendanceRuleListEventByClazzParam param = new AttendanceRuleListEventByClazzParam(); logger.info("循环4"); //响应体,MimeType为 application/json AttendanceRuleListEventByClazzParam.RequestBody requestBody = AttendanceRuleListEventByClazzParam.RequestBody.builder() .build(); logger.info("循环5"); param.setRequestBody(requestBody); logger.info("循环6"); //query AttendanceRuleListEventByClazzParam.Query query = AttendanceRuleListEventByClazzParam.Query.builder() .appId(seewoConfig.getAppId()) .schoolUid(seewoConfig.getSchoolId()) .date(getDate) .classUid(data.getClassUid()) .page(1) .pageSize(20) .build(); logger.info("循环7"); requestBody.setQuery(query); logger.info("循环8"); AttendanceRuleListEventByClazzRequest request = new AttendanceRuleListEventByClazzRequest(param); logger.info("循环9"); // 该接口需要数据权限,请将授权资源id替换至下方,请妥善保管好授权资源id,避免泄露 // permissionId位置: 控制台 -> 应用详情 -> 我申请的 -> 已通过的接口 -> 调用范围 -> 审批信息 中查看授权资源的「学校id」或「区域id」 request.setPermissionId(""); logger.info("入参:" + request); //执行请求,如果想获取到com.seewo.open.sdk.HttpResponse对象,请调用 seewoClient.execute 方法 AttendanceRuleListEventByClazzResult result = seewoClient.invoke(request); logger.info("出参:" + result); //endregion //考勤事件ID List eventItems = new ArrayList<>(); logger.info("循环10"); if (result != null && result.getResponseBody().getCode().equals("000000")) { logger.info("循环11"); if (result.getResponseBody().getData() != null) { logger.info("循环12"); eventItems = result.getResponseBody().getData(); logger.info("循环13"); } } //endregion for (AttendanceRuleListEventByClazzResult.DataItem eventId : eventItems) { logger.info("循环14"); //判断考勤是否开始 用考勤事件的开始时间和当前时间判断 考勤规则开始生效了才拉取 Date eventStartTime = TimeExchange.StringToDate((getDate + " " + eventId.getAttendStartTime() + ":00"), "yyyy-MM-dd HH:mm:ss"); Date nowDate = dateNow; if (nowDate.compareTo(eventStartTime) < 0) { continue; } logger.info("循环15"); /** * 定时获取考勤 */ //初始化客户端 //SeewoClient seewoClient = new DefaultSeewoClient(new Account(seewoConfig.getAppId(), seewoConfig.getAppSecret())); AttendanceServiceListAttendClassRecordsParam kParam = new AttendanceServiceListAttendClassRecordsParam(); logger.info("循环16"); //响应体,MimeType为 application/json AttendanceServiceListAttendClassRecordsParam.RequestBody kRequestBody = AttendanceServiceListAttendClassRecordsParam.RequestBody.builder() .build(); logger.info("循环17"); kParam.setRequestBody(kRequestBody); logger.info("循环18"); //query AttendanceServiceListAttendClassRecordsParam.Query kQuery = AttendanceServiceListAttendClassRecordsParam.Query.builder() .eventId(eventId.getRuleId())//考勤事件ID 固定写死 .attendDate(getDate)//考勤日期 .appId(seewoConfig.getAppId())//appid .grade(oGrade != null && oGrade.isPresent() ? oGrade.get().getGradeNo() : 1)//年级序号 .classUid(data.getClassUid())//班级uid 班级uid与年级序号、班级序号二选一确定具体的班级,如果都填以classUid为准 .schoolUid(seewoConfig.getSchoolId())//学校uid .attendType(1)//考勤类型 时间考勤(默认):1 课程考勤:2 .build(); logger.info("循环19"); kRequestBody.setQuery(kQuery); logger.info("循环20"); kParam.setRequestBody(kRequestBody); logger.info("循环21"); AttendanceServiceListAttendClassRecordsRequest kRequest = new AttendanceServiceListAttendClassRecordsRequest(kParam); logger.info("入参1:" + kRequest); //如果想要调用沙箱环境,请通过设置 request 对象的 serverUrl 属性,如: //request.setServerUrl("https://openapi.test.seewo.com") //执行请求,如果想获取到com.seewo.open.sdk.HttpResponse对象,请调用 seewoClient.execute 方法 AttendanceServiceListAttendClassRecordsResult kResult = seewoClient.invoke(kRequest); logger.info("出参1:" + kResult); if (kResult != null && kResult.getResponseBody().getCode().equals("000000")) { logger.info("循环22"); List items = kResult.getResponseBody().getData().getRecords(); logger.info("循环23"); if (students != null && students.size() > 0 && items != null && items.size() > 0) { logger.info("循环24"); List uids = items.stream().map(AttendanceServiceListAttendClassRecordsResult.RecordsItem::getUserUid).distinct().collect(Collectors.toList()); logger.info("循环25"); for (String uid : uids) { logger.info("uid"+uid); if(!org.springframework.util.StringUtils.hasText(uid)){ logger.info("循环25.5"); continue; } logger.info("循环26"); Optional student = students.stream().filter(e -> e.getXwStudentUid().equals(uid)).findFirst(); logger.info("循环27"); if (student != null && student.isPresent()) { logger.info("循环28"); List oldAttends = attendanceList.stream().filter(e -> e.getUserId().equals(student.get().getId()) && e.getRuleId() != null && e.getRuleId().equals(eventId.getRuleId())).collect(Collectors.toList()); logger.info("循环29"); List newAttends = items.stream().filter(e -> e.getUserUid().equals(student.get().getXwStudentUid())).collect(Collectors.toList()); logger.info("循环30"); if (newAttends != null && newAttends.size() > 0) { int i = 0; for (AttendanceServiceListAttendClassRecordsResult.RecordsItem newAttend : newAttends) { logger.info("循环31"); if (oldAttends.size() > i) { logger.info("循环32"); SmartAttendance oldData = new SmartAttendance(); logger.info("循环33"); oldData = oldAttends.get(i); logger.info("循环34"); if (newAttend.getStatus().intValue() != 6) { logger.info("循环35"); boolean isUpdate = false; Date AttendTime = StringUtils.hasText(newAttend.getAttendTime()) ? TimeExchange.StringToDate((getDate + " " + newAttend.getAttendTime()), "yyyy-MM-dd HH:mm:ss") : TimeExchange.StringToDate((getDate + " " + eventId.getAttendEndTime() + ":00"), "yyyy-MM-dd HH:mm:ss"); logger.info("循环36"); if (oldData.getAttendTime().compareTo(AttendTime) != 0) { oldData.setAttendTime(AttendTime); isUpdate = true; } logger.info("循环37"); if (newAttend.getStatus().intValue() != oldData.getStatus()) { oldData.setStatus(newAttend.getStatus()); isUpdate = true; } logger.info("循环38"); if (!eventId.getRuleId().equals(oldData.getRuleId())) { oldData.setRuleId(eventId.getRuleId()); isUpdate = true; } logger.info("循环39"); if (isUpdate) { attendances.add(oldData); } logger.info("循环40"); } else { deleteAttendances.add(oldData.getId()); } } else { logger.info("循环41"); if (newAttend.getStatus().intValue() != 6) {//请假数据不通过考勤接口拿 因为考勤给的请假数据没有请假原因和请假时长 logger.info("循环42"); SmartAttendance attendance = new SmartAttendance(); attendance.setUserId(student.get().getId()); attendance.setUserUid(newAttend.getUserUid()); attendance.setClassId(student.get().getSchoolClass()); attendance.setClassUid(kResult.getResponseBody().getData().getClassUid()); attendance.setXwUserName(newAttend.getUserName()); attendance.setXwStudentCode(newAttend.getStudentCode()); attendance.setAttendTime(StringUtils.hasText(newAttend.getAttendTime()) ? TimeExchange.StringToDate((getDate + " " + newAttend.getAttendTime()), "yyyy-MM-dd HH:mm:ss") : TimeExchange.StringToDate((getDate + " " + eventId.getAttendEndTime() + ":00"), "yyyy-MM-dd HH:mm:ss")); attendance.setStatus(newAttend.getStatus()); attendance.setRuleId(eventId.getRuleId()); logger.info("循环43"); attendances.add(attendance); logger.info("循环44"); } } i++; } } } } } } } } if (attendances.size() > 0) { smartAttendanceService.saveOrUpdateBatch(attendances); } if (deleteAttendances.size() > 0) { smartAttendanceService.deleteDatasByids(deleteAttendances); } } } catch ( Exception e) { logger.info("考勤定时任务失败:" + e.getMessage()); throw new Exception("考勤定时任务失败" + e.getMessage()); } } }