ScheduleController.java 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. package com.template.controller;
  2. import com.alibaba.fastjson.JSON;
  3. import com.seewo.open.sdk.DefaultSeewoClient;
  4. import com.seewo.open.sdk.SeewoClient;
  5. import com.seewo.open.sdk.auth.Account;
  6. import com.template.common.utils.TimeExchange;
  7. import com.template.config.ScheduleConfig;
  8. import com.template.config.SeewoConfig;
  9. import com.template.model.pojo.SmartAttendance;
  10. import com.template.model.pojo.SmartClass;
  11. import com.template.model.pojo.SmartGrade;
  12. import com.template.model.pojo.SmartUser;
  13. import com.template.model.result.CommonResult;
  14. import com.template.model.seewo.*;
  15. import com.template.services.SmartAttendanceService;
  16. import com.template.services.SmartClassService;
  17. import com.template.services.SmartGradeService;
  18. import com.template.services.SmartUserService;
  19. import org.slf4j.Logger;
  20. import org.slf4j.LoggerFactory;
  21. import org.springframework.beans.factory.annotation.Autowired;
  22. import org.springframework.scheduling.annotation.Async;
  23. import org.springframework.scheduling.annotation.Scheduled;
  24. import org.springframework.stereotype.Component;
  25. import org.springframework.transaction.annotation.Transactional;
  26. import org.springframework.util.StringUtils;
  27. import javax.annotation.Resource;
  28. import java.util.ArrayList;
  29. import java.util.Date;
  30. import java.util.List;
  31. import java.util.Optional;
  32. import java.util.stream.Collectors;
  33. @Component
  34. //@EnableAsync
  35. public class ScheduleController {
  36. private static Logger logger = LoggerFactory.getLogger(ScheduleController.class);
  37. @Resource
  38. private SeewoConfig seewoConfig;
  39. @Resource
  40. private ScheduleConfig scheduleConfig;
  41. @Autowired
  42. private SmartClassService smartClassService;
  43. @Autowired
  44. private SmartGradeService smartGradeService;
  45. @Autowired
  46. private SmartUserService smartUserService;
  47. @Autowired
  48. private SmartAttendanceService smartAttendanceService;
  49. /**
  50. * @Scheduled注解会在默认情况下以单线程的方式执行定时任务。 这个“单线程”指两个方面:
  51. * 如果一个定时任务执行时间大于其任务间隔时间,那么下一次将会等待上一次执行结束后再继续执行。
  52. * 如果多个定时任务在同一时刻执行,任务会依次执行。
  53. * @Async:对某个方法进行异步执行
  54. * @EnableAsync:开启异步支持
  55. */
  56. //定时格式参考:https://blog.csdn.net/java13992394428/article/details/108740453
  57. /**
  58. * 每天八点自动派单
  59. * 周六周日定时器不生效
  60. * 其余时间都是早上八点前捞一遍当前时间以前的单子
  61. * 有合适的维修师傅就把单子派给维修师傅
  62. * 周一到周五早上七点执行:0 0 7 ? * MON-FRI
  63. * 周一到周五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
  64. */
  65. //凌晨两点:0 0 2 * * ?
  66. //每小时执行一次:0 0 */1 * * ?
  67. //每分钟执行一次:0 */1 * * * ?
  68. //周一到周五早上七点执行:0 0 7 ? * MON-FRI
  69. //0 0 22 * * ?
  70. @Async
  71. @Scheduled(cron = "0 0 */1 * * ?")//一个小时
  72. //@Scheduled(cron = "0 */10 * * * ?")//10分钟
  73. @Transactional(rollbackFor = {Exception.class})
  74. public void autoDispatch() throws Exception {
  75. logger.info("1");
  76. Date dateNow = new Date();
  77. logger.info("2");
  78. String getDate = TimeExchange.getDate();
  79. try {
  80. if (scheduleConfig.getIsOpen().equals("1")) {
  81. logger.info("3");
  82. List<SmartAttendance> attendances = new ArrayList<>();
  83. List<Integer> deleteAttendances = new ArrayList<>();
  84. //判断当前月份是九月前还是九月后 九月前就不包括本年
  85. List<String> gradeNames = new ArrayList<>();
  86. Integer nowMonth = Integer.valueOf(TimeExchange.getNowMonth());
  87. if (nowMonth.intValue() >= 9) {
  88. Integer yearNow = Integer.valueOf(TimeExchange.getYear());
  89. gradeNames.add(yearNow + "级");
  90. gradeNames.add((yearNow.intValue() - 1) + "级");
  91. gradeNames.add((yearNow.intValue() - 2) + "级");
  92. } else {
  93. Integer yearNow = Integer.valueOf(TimeExchange.getYear());
  94. gradeNames.add((yearNow.intValue() - 1) + "级");
  95. gradeNames.add((yearNow.intValue() - 2) + "级");
  96. gradeNames.add((yearNow.intValue() - 3) + "级");
  97. }
  98. logger.info("4");
  99. List<Integer> gradeIs = new ArrayList<>();
  100. List<String> gradeIds = new ArrayList<>();
  101. List<SmartGrade> grades = smartGradeService.getSmartGrades(gradeNames);
  102. logger.info("5");
  103. for (SmartGrade data : grades) {
  104. gradeIds.add(data.getId()+"");
  105. gradeIs.add(data.getId());
  106. }
  107. List<SmartUser> students = smartUserService.queryStudentsByGrade(gradeIds);
  108. logger.info("6");
  109. // SmartUser studentData = smartUserService.getSmartById(1088);
  110. // students.add(studentData);
  111. //循环班级的classUid
  112. List<SmartClass> classes = smartClassService.getSmartClasssByGrade(gradeIs);
  113. logger.info("7");
  114. // SmartClass classData = smartClassService.getSmartClassById(204);
  115. // classes.add(classData);
  116. //当天已存在的考勤数据 判断是否重复使用
  117. List<SmartAttendance> attendanceList = smartAttendanceService.queryAttendancesNoleave(TimeExchange.getStartOfDayStr(dateNow), TimeExchange.getEndOfDayStr(dateNow));
  118. logger.info("8");
  119. for (SmartClass data : classes) {
  120. logger.info("循环1");
  121. Optional<SmartGrade> oGrade = grades.stream().filter(e -> e.getId().equals(data.getGradeId())).findFirst();
  122. logger.info("循环2");
  123. //region 获取考勤事件ID
  124. //初始化客户端
  125. SeewoClient seewoClient = new DefaultSeewoClient(new Account(seewoConfig.getAppId(), seewoConfig.getAppSecret()));
  126. logger.info("循环3");
  127. AttendanceRuleListEventByClazzParam param = new AttendanceRuleListEventByClazzParam();
  128. logger.info("循环4");
  129. //响应体,MimeType为 application/json
  130. AttendanceRuleListEventByClazzParam.RequestBody requestBody = AttendanceRuleListEventByClazzParam.RequestBody.builder()
  131. .build();
  132. logger.info("循环5");
  133. param.setRequestBody(requestBody);
  134. logger.info("循环6");
  135. //query
  136. AttendanceRuleListEventByClazzParam.Query query = AttendanceRuleListEventByClazzParam.Query.builder()
  137. .appId(seewoConfig.getAppId())
  138. .schoolUid(seewoConfig.getSchoolId())
  139. .date(getDate)
  140. .classUid(data.getClassUid())
  141. .page(1)
  142. .pageSize(20)
  143. .build();
  144. logger.info("循环7");
  145. requestBody.setQuery(query);
  146. logger.info("循环8");
  147. AttendanceRuleListEventByClazzRequest request = new AttendanceRuleListEventByClazzRequest(param);
  148. logger.info("循环9");
  149. // 该接口需要数据权限,请将授权资源id替换至下方,请妥善保管好授权资源id,避免泄露
  150. // permissionId位置: 控制台 -> 应用详情 -> 我申请的 -> 已通过的接口 -> 调用范围 -> 审批信息 中查看授权资源的「学校id」或「区域id」
  151. request.setPermissionId("");
  152. logger.info("入参:" + request);
  153. //执行请求,如果想获取到com.seewo.open.sdk.HttpResponse对象,请调用 seewoClient.execute 方法
  154. AttendanceRuleListEventByClazzResult result = seewoClient.invoke(request);
  155. logger.info("出参:" + result);
  156. //endregion
  157. //考勤事件ID
  158. List<AttendanceRuleListEventByClazzResult.DataItem> eventItems = new ArrayList<>();
  159. logger.info("循环10");
  160. if (result != null && result.getResponseBody().getCode().equals("000000")) {
  161. logger.info("循环11");
  162. if (result.getResponseBody().getData() != null) {
  163. logger.info("循环12");
  164. eventItems = result.getResponseBody().getData();
  165. logger.info("循环13");
  166. }
  167. }
  168. //endregion
  169. for (AttendanceRuleListEventByClazzResult.DataItem eventId : eventItems) {
  170. logger.info("循环14");
  171. //判断考勤是否开始 用考勤事件的开始时间和当前时间判断 考勤规则开始生效了才拉取
  172. Date eventStartTime = TimeExchange.StringToDate((getDate + " " + eventId.getAttendStartTime() + ":00"), "yyyy-MM-dd HH:mm:ss");
  173. Date nowDate = dateNow;
  174. if (nowDate.compareTo(eventStartTime) < 0) {
  175. continue;
  176. }
  177. logger.info("循环15");
  178. /**
  179. * 定时获取考勤
  180. */
  181. //初始化客户端
  182. //SeewoClient seewoClient = new DefaultSeewoClient(new Account(seewoConfig.getAppId(), seewoConfig.getAppSecret()));
  183. AttendanceServiceListAttendClassRecordsParam kParam = new AttendanceServiceListAttendClassRecordsParam();
  184. logger.info("循环16");
  185. //响应体,MimeType为 application/json
  186. AttendanceServiceListAttendClassRecordsParam.RequestBody kRequestBody = AttendanceServiceListAttendClassRecordsParam.RequestBody.builder()
  187. .build();
  188. logger.info("循环17");
  189. kParam.setRequestBody(kRequestBody);
  190. logger.info("循环18");
  191. //query
  192. AttendanceServiceListAttendClassRecordsParam.Query kQuery = AttendanceServiceListAttendClassRecordsParam.Query.builder()
  193. .eventId(eventId.getRuleId())//考勤事件ID 固定写死
  194. .attendDate(getDate)//考勤日期
  195. .appId(seewoConfig.getAppId())//appid
  196. .grade(oGrade != null && oGrade.isPresent() ? oGrade.get().getGradeNo() : 1)//年级序号
  197. .classUid(data.getClassUid())//班级uid 班级uid与年级序号、班级序号二选一确定具体的班级,如果都填以classUid为准
  198. .schoolUid(seewoConfig.getSchoolId())//学校uid
  199. .attendType(1)//考勤类型 时间考勤(默认):1 课程考勤:2
  200. .build();
  201. logger.info("循环19");
  202. kRequestBody.setQuery(kQuery);
  203. logger.info("循环20");
  204. kParam.setRequestBody(kRequestBody);
  205. logger.info("循环21");
  206. AttendanceServiceListAttendClassRecordsRequest kRequest = new AttendanceServiceListAttendClassRecordsRequest(kParam);
  207. logger.info("入参1:" + kRequest);
  208. //如果想要调用沙箱环境,请通过设置 request 对象的 serverUrl 属性,如:
  209. //request.setServerUrl("https://openapi.test.seewo.com")
  210. //执行请求,如果想获取到com.seewo.open.sdk.HttpResponse对象,请调用 seewoClient.execute 方法
  211. AttendanceServiceListAttendClassRecordsResult kResult = seewoClient.invoke(kRequest);
  212. logger.info("出参1:" + kResult);
  213. if (kResult != null && kResult.getResponseBody().getCode().equals("000000")) {
  214. logger.info("循环22");
  215. List<AttendanceServiceListAttendClassRecordsResult.RecordsItem> items = kResult.getResponseBody().getData().getRecords();
  216. logger.info("循环23");
  217. if (students != null && students.size() > 0 && items != null && items.size() > 0) {
  218. logger.info("循环24");
  219. List<String> uids = items.stream().map(AttendanceServiceListAttendClassRecordsResult.RecordsItem::getUserUid).distinct().collect(Collectors.toList());
  220. logger.info("循环25");
  221. for (String uid : uids) {
  222. logger.info("uid"+uid);
  223. if(!org.springframework.util.StringUtils.hasText(uid)){
  224. logger.info("循环25.5");
  225. continue;
  226. }
  227. logger.info("循环26");
  228. Optional<SmartUser> student = students.stream().filter(e -> e.getXwStudentUid().equals(uid)).findFirst();
  229. logger.info("循环27");
  230. if (student != null && student.isPresent()) {
  231. logger.info("循环28");
  232. List<SmartAttendance> oldAttends = attendanceList.stream().filter(e -> e.getUserId().equals(student.get().getId())
  233. && e.getRuleId() != null && e.getRuleId().equals(eventId.getRuleId())).collect(Collectors.toList());
  234. logger.info("循环29");
  235. List<AttendanceServiceListAttendClassRecordsResult.RecordsItem> newAttends = items.stream().filter(e -> e.getUserUid().equals(student.get().getXwStudentUid())).collect(Collectors.toList());
  236. logger.info("循环30");
  237. if (newAttends != null && newAttends.size() > 0) {
  238. int i = 0;
  239. for (AttendanceServiceListAttendClassRecordsResult.RecordsItem newAttend : newAttends) {
  240. logger.info("循环31");
  241. if (oldAttends.size() > i) {
  242. logger.info("循环32");
  243. SmartAttendance oldData = new SmartAttendance();
  244. logger.info("循环33");
  245. oldData = oldAttends.get(i);
  246. logger.info("循环34");
  247. if (newAttend.getStatus().intValue() != 6) {
  248. logger.info("循环35");
  249. boolean isUpdate = false;
  250. 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");
  251. logger.info("循环36");
  252. if (oldData.getAttendTime().compareTo(AttendTime) != 0) {
  253. oldData.setAttendTime(AttendTime);
  254. isUpdate = true;
  255. }
  256. logger.info("循环37");
  257. if (newAttend.getStatus().intValue() != oldData.getStatus()) {
  258. oldData.setStatus(newAttend.getStatus());
  259. isUpdate = true;
  260. }
  261. logger.info("循环38");
  262. if (!eventId.getRuleId().equals(oldData.getRuleId())) {
  263. oldData.setRuleId(eventId.getRuleId());
  264. isUpdate = true;
  265. }
  266. logger.info("循环39");
  267. if (isUpdate) {
  268. attendances.add(oldData);
  269. }
  270. logger.info("循环40");
  271. } else {
  272. deleteAttendances.add(oldData.getId());
  273. }
  274. } else {
  275. logger.info("循环41");
  276. if (newAttend.getStatus().intValue() != 6) {//请假数据不通过考勤接口拿 因为考勤给的请假数据没有请假原因和请假时长
  277. logger.info("循环42");
  278. SmartAttendance attendance = new SmartAttendance();
  279. attendance.setUserId(student.get().getId());
  280. attendance.setUserUid(newAttend.getUserUid());
  281. attendance.setClassId(student.get().getSchoolClass());
  282. attendance.setClassUid(kResult.getResponseBody().getData().getClassUid());
  283. attendance.setXwUserName(newAttend.getUserName());
  284. attendance.setXwStudentCode(newAttend.getStudentCode());
  285. 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"));
  286. attendance.setStatus(newAttend.getStatus());
  287. attendance.setRuleId(eventId.getRuleId());
  288. logger.info("循环43");
  289. attendances.add(attendance);
  290. logger.info("循环44");
  291. }
  292. }
  293. i++;
  294. }
  295. }
  296. }
  297. }
  298. }
  299. }
  300. }
  301. }
  302. if (attendances.size() > 0) {
  303. smartAttendanceService.saveOrUpdateBatch(attendances);
  304. }
  305. if (deleteAttendances.size() > 0) {
  306. smartAttendanceService.deleteDatasByids(deleteAttendances);
  307. }
  308. }
  309. } catch (
  310. Exception e) {
  311. logger.info("考勤定时任务失败:" + e.getMessage());
  312. throw new Exception("考勤定时任务失败" + e.getMessage());
  313. }
  314. }
  315. }