AttendanceExceptionFacadeControllerBean.java 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  1. package com.kingdee.eas.custom.attendanceexception.task;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.kingdee.bos.metadata.entity.*;
  5. import com.kingdee.eas.basedata.org.AdminOrgUnitCollection;
  6. import com.kingdee.eas.basedata.org.AdminOrgUnitFactory;
  7. import com.kingdee.eas.basedata.org.AdminOrgUnitInfo;
  8. import com.kingdee.eas.basedata.org.IAdminOrgUnit;
  9. import com.kingdee.eas.custom.attendanceexception.*;
  10. import com.kingdee.eas.custom.attendanceexception.bean.SyncAttendanceDataBean;
  11. import com.kingdee.eas.custom.attendanceexception.bizEnum.PushTypeEnum;
  12. import com.kingdee.eas.fi.arap.util.DBUtil;
  13. import com.kingdee.eas.hr.ats.AttendanceFileCollection;
  14. import com.kingdee.eas.hr.ats.AttendanceFileFactory;
  15. import com.kingdee.eas.hr.ats.AttendanceFileInfo;
  16. import com.kingdee.eas.hr.ats.IAttendanceFile;
  17. import com.kingdee.eas.hr.ats.util.AtsDateUtils;
  18. import com.kingdee.jdbc.rowset.IRowSet;
  19. import com.kingdee.shr.base.syssetting.CallStatusEnum;
  20. import com.kingdee.util.DateTimeUtils;
  21. import okhttp3.MediaType;
  22. import okhttp3.OkHttpClient;
  23. import okhttp3.Request;
  24. import okhttp3.RequestBody;
  25. import okhttp3.Response;
  26. import org.apache.commons.lang3.StringUtils;
  27. import org.apache.log4j.Logger;
  28. import com.kingdee.bos.*;
  29. import com.kingdee.eas.common.EASBizException;
  30. import java.io.FileInputStream;
  31. import java.io.IOException;
  32. import java.lang.String;
  33. import java.math.BigDecimal;
  34. import java.sql.SQLException;
  35. import java.text.MessageFormat;
  36. import java.text.SimpleDateFormat;
  37. import java.util.*;
  38. public class AttendanceExceptionFacadeControllerBean extends AbstractAttendanceExceptionFacadeControllerBean {
  39. private static Logger logger = Logger.getLogger(AttendanceExceptionFacadeControllerBean.class);
  40. private Properties propt = new Properties();
  41. //通知员工个人消息模板
  42. //private static final String NOTIFYEMPLOYEEMSGTEMPLATE = "##### <font color=#6192f2>HR系统</font>\\n#### 考勤异常提醒:\\n您在{0}出现考勤异常,请及时处理! \\n###### (如有审批中的假勤单据,请及时催办)";
  43. //通知员工个人消息标题
  44. //private static final String NOTIFYEMPLOYEEMSGTITLE = "【考勤异常提醒】";
  45. //通知员工个人消息模板
  46. //private static final String NOTIFYEMPLOYEECUMULATIVEMSGTEMPLATE = "##### <font color=#6192f2>HR系统</font>\\n#### 员工考勤提醒:\\n您在{0}考勤异常次数已经达到{1}次,请您注意本月考勤 \\n###### (如有审批中的假勤单据,请及时催办)";
  47. //通知员工个人消息标题
  48. //private static final String NOTIFYEMPLOYEECUMULATIVEMSGTITLE = "【员工考勤提醒】";
  49. //通知提醒中心负责人异常消息模板
  50. //private static final String NOTIFYALERTLEADEREXCEPTIONMSGTEMPLATE = "##### <font color=#6192f2>HR系统</font>\\n#### 中心考勤异常周报:\\n#####时间:{0}-{1}\\n#####内容:{2}考勤人数{3}人,考勤异常人数{4}人,迟到{5}人,早退{6}人,旷工{7}人 \\n###### (如有审批中的假勤单据,请及时催办)";
  51. //通知提醒中心负责人异常消息标题
  52. //private static final String NOTIFYALERTLEADEREXCEPTIONMSGTITLE = "【考勤异常周报】";
  53. //来源标识
  54. private static final String SOURCE = "EHR";
  55. public AttendanceExceptionFacadeControllerBean() throws BOSException {
  56. String syncOAConfigPath = System.getProperty("EAS_HOME") + "/server/properties/scy/attendanceException.properties";
  57. try {
  58. propt.load(new FileInputStream(syncOAConfigPath));
  59. } catch (IOException e) {
  60. e.printStackTrace();
  61. String errorMsg = "获取配置文件报错,请检查配置:" + syncOAConfigPath + " " + e.getMessage();
  62. throw new BOSException(errorMsg);
  63. }
  64. }
  65. /**
  66. * 员工个人异常提醒
  67. *
  68. * @param ctx
  69. * @throws BOSException
  70. * @throws EASBizException
  71. */
  72. @Override
  73. protected void _notifyEmployeeException(Context ctx) throws BOSException, EASBizException {
  74. long startTime = System.currentTimeMillis();
  75. if (logger.isInfoEnabled()) {
  76. logger.info("AttendanceExceptionFacadeControllerBean.notifyEmployeeException start");
  77. }
  78. super._notifyEmployeeException(ctx);
  79. IAttendanceExceptionLog iAttendanceExceptionLog = AttendanceExceptionLogFactory.getLocalInstance(ctx);
  80. PushTypeEnum pushTypeEnum = PushTypeEnum.EMPLOYEEREMINDER;
  81. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd E HH:mm:ss");
  82. //昨天
  83. Date preDay = AtsDateUtils.getPreDay(new Date());
  84. logger.error("_notifyEmployeeCumulativeException preDay: " + sdf.format(preDay));
  85. //1.查询异常数据
  86. Map<String, List<SyncAttendanceDataBean>> exceptionData = getAttendanceExceptionData(ctx, preDay, preDay, pushTypeEnum, 0);
  87. String yearMonthDay = DateTimeUtils.format(preDay, "yyyy年MM月dd日");
  88. for (String personNumber : exceptionData.keySet()) {
  89. String msgId = UUID.randomUUID().toString();
  90. AttendanceExceptionLogInfo logInfo = new AttendanceExceptionLogInfo();
  91. logInfo.setMessageId(msgId);
  92. logInfo.setPushType(pushTypeEnum);
  93. try {
  94. //发送异常消息
  95. JSONObject dingMsgBean = new JSONObject();
  96. dingMsgBean.put("msgTempCode", "work_notice_03");
  97. dingMsgBean.put("toAllUser", false);
  98. dingMsgBean.put("userIdList", personNumber);
  99. dingMsgBean.put("source", SOURCE);
  100. JSONObject param = new JSONObject();
  101. //消息id
  102. param.put("msgId", msgId);
  103. //时间
  104. param.put("time", yearMonthDay);
  105. dingMsgBean.put("param", param);
  106. sendAttendanceExceptionMsg(dingMsgBean, logInfo);
  107. //推送异常数据
  108. List<SyncAttendanceDataBean> syncAttendanceDataBeans = exceptionData.get(personNumber);
  109. syncAttendanceDataBeans.stream().forEach(syncAttendanceDataBean -> {
  110. syncAttendanceDataBean.setMsgId(msgId);
  111. });
  112. pushAttendanceExceptionData(syncAttendanceDataBeans, logInfo);
  113. } catch (Exception e) {
  114. logger.error("员工个人异常提醒报错", e);
  115. }
  116. //保存消息记录
  117. iAttendanceExceptionLog.save(logInfo);
  118. }
  119. if (logger.isInfoEnabled()) {
  120. long endTime = System.currentTimeMillis();
  121. float duration = (endTime - startTime) / 1000f;
  122. logger.info(String.format("AttendanceExceptionFacadeControllerBean.notifyEmployeeException end, duration: %fS", duration));
  123. }
  124. }
  125. /**
  126. * 员工考勤异常关怀提醒
  127. *
  128. * @param ctx
  129. * @param exceptionLimit 异常次数上限
  130. * @throws BOSException
  131. * @throws EASBizException
  132. */
  133. @Override
  134. protected void _notifyEmployeeCumulativeException(
  135. Context ctx,
  136. String exceptionLimit
  137. ) throws BOSException, EASBizException {
  138. long startTime = System.currentTimeMillis();
  139. if (logger.isInfoEnabled()) {
  140. logger.info("AttendanceExceptionFacadeControllerBean.notifyEmployeeCumulativeException start");
  141. }
  142. super._notifyEmployeeCumulativeException(ctx, exceptionLimit);
  143. int limit = 5;
  144. if (StringUtils.isNotBlank(exceptionLimit)) {
  145. limit = Integer.parseInt(exceptionLimit);
  146. }
  147. IAttendanceExceptionLog iAttendanceExceptionLog = AttendanceExceptionLogFactory.getLocalInstance(ctx);
  148. PushTypeEnum pushTypeEnum = PushTypeEnum.EMPLOYEEEXCEPTIONALERT;
  149. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd E HH:mm:ss");
  150. Date today = new Date();
  151. //当前月第一天
  152. Date currentFirstDay = AtsDateUtils.getCurrentFirstDay(today);
  153. logger.error("_notifyEmployeeCumulativeException currentFirstDay: " + sdf.format(currentFirstDay));
  154. //昨天
  155. Date preDay = AtsDateUtils.getPreDay(today);
  156. logger.error("_notifyEmployeeCumulativeException preDay: " + sdf.format(preDay));
  157. //查询异常数据
  158. Map<String, List<SyncAttendanceDataBean>> exceptionData = getAttendanceExceptionData(ctx, currentFirstDay, preDay, pushTypeEnum, 0);
  159. String yearMonth = DateTimeUtils.format(today, "yyyy年MM月");
  160. for (String personNumber : exceptionData.keySet()) {
  161. String msgId = UUID.randomUUID().toString();
  162. AttendanceExceptionLogInfo logInfo = new AttendanceExceptionLogInfo();
  163. logInfo.setMessageId(msgId);
  164. logInfo.setPushType(pushTypeEnum);
  165. try {
  166. //发送异常消息
  167. JSONObject dingMsgBean = new JSONObject();
  168. dingMsgBean.put("msgTempCode", "work_notice_02");
  169. dingMsgBean.put("toAllUser", false);
  170. dingMsgBean.put("userIdList", personNumber);
  171. dingMsgBean.put("source", SOURCE);
  172. JSONObject param = new JSONObject();
  173. //消息id
  174. param.put("msgId", msgId);
  175. //时间
  176. param.put("time", yearMonth);
  177. //考勤异常人数
  178. param.put("eorNum", limit);
  179. dingMsgBean.put("param", param);
  180. sendAttendanceExceptionMsg(dingMsgBean, logInfo);
  181. //推送异常数据
  182. List<SyncAttendanceDataBean> syncAttendanceDataBeans = exceptionData.get(personNumber);
  183. syncAttendanceDataBeans.stream().forEach(syncAttendanceDataBean -> {
  184. syncAttendanceDataBean.setMsgId(msgId);
  185. });
  186. pushAttendanceExceptionData(syncAttendanceDataBeans, logInfo);
  187. //写入提醒记录
  188. addRemindRecord(ctx, yearMonth, personNumber);
  189. } catch (Exception e) {
  190. logger.error("提醒员工累计异常报错: " + e.getMessage(), e);
  191. }
  192. //保存消息记录
  193. iAttendanceExceptionLog.save(logInfo);
  194. }
  195. if (logger.isInfoEnabled()) {
  196. long endTime = System.currentTimeMillis();
  197. float duration = (endTime - startTime) / 1000f;
  198. logger.info(String.format("AttendanceExceptionFacadeControllerBean.notifyEmployeeCumulativeException end, duration: %fS", duration));
  199. }
  200. }
  201. /**
  202. * 提醒中心负责人累计异常
  203. *
  204. * @param ctx
  205. * @throws BOSException
  206. * @throws EASBizException
  207. */
  208. @Override
  209. protected void _alertLeaderExceptionTotal(Context ctx) throws BOSException, EASBizException {
  210. long startTime = System.currentTimeMillis();
  211. if (logger.isInfoEnabled()) {
  212. logger.info("AttendanceExceptionFacadeControllerBean.alertLeaderExceptionTotal start");
  213. }
  214. super._alertLeaderExceptionTotal(ctx);
  215. IAttendanceExceptionLog iAttendanceExceptionLog = AttendanceExceptionLogFactory.getLocalInstance(ctx);
  216. //中心负责人关系表
  217. ICenterLeaderRelation iCenterLeaderRelation = CenterLeaderRelationFactory.getLocalInstance(ctx);
  218. //获取中心负责人
  219. Map<String, Set<String>> leaders = iCenterLeaderRelation.getLeaders();
  220. //获取各中心考勤人数
  221. Map<String, Integer> attendanceCountMap = getAttendanceCount(ctx);
  222. //获取中心名称
  223. Map<String, String> orgMap = getOrgMap(ctx);
  224. PushTypeEnum pushTypeEnum = PushTypeEnum.CENTERLEADERREMINDER;
  225. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd E HH:mm:ss");
  226. //获取考勤异常数据,本周周一至周五中心考勤异常数据
  227. Calendar calendar = Calendar.getInstance();
  228. Date endDate = calendar.getTime();
  229. int intWeek = calendar.get(7);
  230. calendar.add(Calendar.DAY_OF_WEEK, 2 - intWeek);
  231. Date monday = calendar.getTime();
  232. logger.error("_alertLeaderExceptionTotal startDate: " + sdf.format(monday));
  233. if (intWeek > 6) {
  234. calendar.add(Calendar.DAY_OF_WEEK, 4);
  235. endDate = calendar.getTime();
  236. }
  237. logger.error("_alertLeaderExceptionTotal endDate: " + sdf.format(endDate));
  238. //1.查询异常数据
  239. Map<String, Map<String, Integer>> exceptionCountMap = new HashMap<>();
  240. Map<String, List<SyncAttendanceDataBean>> exceptionData = getAttendanceExceptionDataForLeader(ctx, monday, endDate, exceptionCountMap);
  241. String mondayFormat = DateTimeUtils.format(monday, "yyyy年MM月dd日");
  242. String endDateFormat = DateTimeUtils.format(endDate, "yyyy年MM月dd日");
  243. for (String centerNumber : exceptionData.keySet()) {
  244. String msgId = UUID.randomUUID().toString();
  245. AttendanceExceptionLogInfo logInfo = new AttendanceExceptionLogInfo();
  246. logInfo.setMessageId(msgId);
  247. logInfo.setPushType(pushTypeEnum);
  248. try {
  249. Set<String> alertUserSet = leaders.get(centerNumber);
  250. String orgName = orgMap.getOrDefault(centerNumber, "中心");
  251. //中心负责人
  252. String alertUsers = convertSetToString(alertUserSet);
  253. if (StringUtils.isBlank(alertUsers)) {
  254. throw new BOSException(orgName + "的负责人为空!");
  255. }
  256. //中心考勤总人数
  257. Integer attendanceCount = attendanceCountMap.getOrDefault(centerNumber, 0);
  258. Map<String, Integer> orgExceptionTimes = exceptionCountMap.get(centerNumber);
  259. //迟到人数
  260. Integer lateEmployees = orgExceptionTimes.getOrDefault("lateEmployees", 0);
  261. //早退人数
  262. Integer earlyLeaveEmployees = orgExceptionTimes.getOrDefault("earlyLeaveEmployees", 0);
  263. //旷工人数
  264. Integer absentEmployees = orgExceptionTimes.getOrDefault("absentEmployees", 0);
  265. //个人原因补卡人数
  266. //Integer personalRecheckCountEmployees = orgExceptionTimes.getOrDefault("personalRecheckCountEmployees", 0);
  267. //异常人数
  268. Integer exceptionEmployees = orgExceptionTimes.getOrDefault("exceptionEmployees", 0);
  269. //消息内容
  270. // String content = MessageFormat.format(NOTIFYALERTLEADEREXCEPTIONMSGTEMPLATE,
  271. // mondayFormat,
  272. // endDateFormat,
  273. // orgName,
  274. // attendanceCount,
  275. // exceptionEmployees,
  276. // lateEmployees,
  277. // earlyLeaveEmployees,
  278. // absentEmployees
  279. // );
  280. //发送异常消息
  281. JSONObject dingMsgBean = new JSONObject();
  282. dingMsgBean.put("msgTempCode", "work_notice_01");
  283. dingMsgBean.put("toAllUser", false);
  284. dingMsgBean.put("userIdList", alertUsers);
  285. dingMsgBean.put("source", SOURCE);
  286. JSONObject param = new JSONObject();
  287. //消息id
  288. param.put("msgId", msgId);
  289. //时间
  290. param.put("time", mondayFormat + "-" + endDateFormat);
  291. //中心考勤人数
  292. param.put("centerNum", attendanceCount);
  293. //考勤异常人数
  294. param.put("eorNum", exceptionEmployees);
  295. //迟到人数
  296. param.put("lateNum", lateEmployees);
  297. //早退人数
  298. param.put("earlyNum", earlyLeaveEmployees);
  299. //旷工人数
  300. param.put("hookyNum", absentEmployees);
  301. dingMsgBean.put("param", param);
  302. sendAttendanceExceptionMsg(dingMsgBean, logInfo);
  303. //推送异常数据
  304. List<SyncAttendanceDataBean> syncAttendanceDataBeans = exceptionData.get(centerNumber);
  305. syncAttendanceDataBeans.stream().forEach(syncAttendanceDataBean -> {
  306. syncAttendanceDataBean.setMsgId(msgId);
  307. });
  308. pushAttendanceExceptionData(syncAttendanceDataBeans, logInfo);
  309. } catch (Exception e) {
  310. logger.error("提醒中心负责人累计异常报错", e);
  311. }
  312. //保存消息记录
  313. iAttendanceExceptionLog.save(logInfo);
  314. }
  315. if (logger.isInfoEnabled()) {
  316. long endTime = System.currentTimeMillis();
  317. float duration = (endTime - startTime) / 1000f;
  318. logger.info(String.format("AttendanceExceptionFacadeControllerBean.alertLeaderExceptionTotal end, duration: %fS", duration));
  319. }
  320. }
  321. /**
  322. * 获取考勤异常数据
  323. *
  324. * @param ctx
  325. * @param startDate 开始日期
  326. * @param endDate 结束日期
  327. * @return
  328. * @throws BOSException
  329. * @throws EASBizException
  330. */
  331. protected Map<String, List<SyncAttendanceDataBean>> getAttendanceExceptionData(
  332. Context ctx,
  333. Date startDate,
  334. Date endDate,
  335. PushTypeEnum pushType,
  336. int limit
  337. ) throws BOSException {
  338. String sql = getSql(startDate, endDate);
  339. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  340. try {
  341. IRowSet iRowSet = DBUtil.executeQuery(ctx, sql);
  342. Map<String, List<SyncAttendanceDataBean>> result = new HashMap<>();
  343. Map<String, Integer> personExceptionTimes = new HashMap<>();
  344. if (!PushTypeEnum.CENTERLEADERREMINDER.equals(pushType)) {
  345. //非中心负责人提醒
  346. while (iRowSet.next()) {
  347. //设置考勤结果和次数
  348. SyncAttendanceDataBean data = setAttendanceResult(iRowSet, sdf);
  349. int times = data.getTimes();
  350. String personNumber = data.getEmployeeId();
  351. //累计员工期间总异常次数
  352. if (personExceptionTimes.containsKey(personNumber)) {
  353. Integer i = personExceptionTimes.get(personNumber);
  354. personExceptionTimes.put(personNumber, i + times);
  355. } else {
  356. personExceptionTimes.put(personNumber, times);
  357. }
  358. if (!result.containsKey(personNumber)) {
  359. result.put(personNumber, new ArrayList<>());
  360. }
  361. result.get(personNumber).add(data);
  362. }
  363. if (PushTypeEnum.EMPLOYEEEXCEPTIONALERT.equals(pushType)) {
  364. String yearMonth = DateTimeUtils.format(startDate, "yyyy年M月");
  365. //获取提醒记录
  366. Set<String> remindRecord = getRemindRecord(ctx, yearMonth);
  367. //员工累计异常提醒
  368. for (Map.Entry<String, Integer> entry : personExceptionTimes.entrySet()) {
  369. if (entry.getValue() < limit || remindRecord.contains(entry.getKey())) {
  370. //移除没有达到预警上限的数据,获取已经提醒过的人员
  371. result.remove(entry.getKey());
  372. }
  373. }
  374. }
  375. }
  376. return result;
  377. } catch (SQLException e) {
  378. logger.error(e.getMessage(), e);
  379. throw new RuntimeException(e);
  380. }
  381. }
  382. /**
  383. * 获取中心考勤异常数据
  384. *
  385. * @param ctx
  386. * @param startDate 开始日期
  387. * @param endDate 结束日期
  388. * @return
  389. * @throws BOSException
  390. * @throws EASBizException
  391. */
  392. protected Map<String, List<SyncAttendanceDataBean>> getAttendanceExceptionDataForLeader(
  393. Context ctx,
  394. Date startDate,
  395. Date endDate,
  396. Map<String, Map<String, Integer>> exceptionCountMap
  397. ) throws BOSException {
  398. String sql = getSql(startDate, endDate);
  399. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  400. Map<String, Map<String, Set<String>>> exceptionData = new HashMap<>();
  401. try {
  402. IRowSet iRowSet = DBUtil.executeQuery(ctx, sql);
  403. Map<String, List<SyncAttendanceDataBean>> result = new HashMap<>();
  404. while (iRowSet.next()) {
  405. //设置考勤结果和次数
  406. SyncAttendanceDataBean data = setAttendanceResult(iRowSet, sdf);
  407. //中心编码
  408. String admintwoNumber = iRowSet.getString("admintwoNumber");
  409. String personNumber = data.getEmployeeId();
  410. Map<String, Boolean> attendanceFlags = new LinkedHashMap<>();
  411. int s19 = iRowSet.getInt("s19");
  412. int s21 = iRowSet.getInt("s21");
  413. BigDecimal s23 = iRowSet.getBigDecimal("s23");
  414. int s113 = iRowSet.getInt("s113");
  415. attendanceFlags.put("lateEmployees", s19 > 0);//迟到
  416. attendanceFlags.put("earlyLeaveEmployees", s21 > 0);//早退
  417. attendanceFlags.put("absentEmployees", s23.compareTo(BigDecimal.ZERO) > 0);//旷工
  418. attendanceFlags.put("personalRecheckCountEmployees", s113 > 0);//个人原因补卡
  419. Map<String, Set<String>> exceptionPersonMap = null;
  420. if (exceptionData.containsKey(admintwoNumber)) {
  421. exceptionPersonMap = exceptionData.get(admintwoNumber);
  422. } else {
  423. exceptionPersonMap = new HashMap<>();
  424. exceptionData.put(admintwoNumber, exceptionPersonMap);
  425. }
  426. Set<String> exceptionEmployees = exceptionPersonMap.get("exceptionEmployees");
  427. if (exceptionEmployees == null) {
  428. exceptionEmployees = new HashSet<>();
  429. exceptionPersonMap.put("exceptionEmployees", exceptionEmployees);
  430. }
  431. exceptionEmployees.add(personNumber);
  432. for (Map.Entry<String, Boolean> entry : attendanceFlags.entrySet()) {
  433. if (entry.getValue()) {
  434. Set<String> set = exceptionPersonMap.get(entry.getKey());
  435. if (set == null) {
  436. set = new HashSet<>();
  437. exceptionPersonMap.put(entry.getKey(), set);
  438. }
  439. set.add(personNumber);
  440. }
  441. }
  442. if (!result.containsKey(admintwoNumber)) {
  443. result.put(admintwoNumber, new ArrayList<>());
  444. }
  445. result.get(admintwoNumber).add(data);
  446. }
  447. for (String orgNumber : exceptionData.keySet()) {
  448. Map<String, Set<String>> orgExceptionData = exceptionData.get(orgNumber);
  449. Map<String, Integer> orgExceptionTimes = new HashMap<>();
  450. //迟到人数
  451. orgExceptionTimes.put("lateEmployees", orgExceptionData.get("lateEmployees").size());
  452. //早退人数
  453. orgExceptionTimes.put("earlyLeaveEmployees", orgExceptionData.get("earlyLeaveEmployees").size());
  454. //旷工人数
  455. orgExceptionTimes.put("absentEmployees", orgExceptionData.get("absentEmployees").size());
  456. //个人原因补卡人数
  457. orgExceptionTimes.put("personalRecheckCountEmployees", orgExceptionData.get("personalRecheckCountEmployees").size());
  458. //异常人数
  459. orgExceptionTimes.put("exceptionEmployees", orgExceptionData.get("exceptionEmployees").size());
  460. exceptionCountMap.put(orgNumber, orgExceptionTimes);
  461. }
  462. return result;
  463. } catch (SQLException e) {
  464. logger.error(e.getMessage(), e);
  465. throw new RuntimeException(e);
  466. }
  467. }
  468. /**
  469. * 设置考勤结果和次数
  470. *
  471. * @param iRowSet
  472. * @param sdf
  473. * @throws SQLException
  474. */
  475. protected SyncAttendanceDataBean setAttendanceResult(IRowSet iRowSet, SimpleDateFormat sdf) throws SQLException {
  476. SyncAttendanceDataBean data = new SyncAttendanceDataBean();
  477. data.setEmployeeId(iRowSet.getString("personNumber"));
  478. data.setEmployeeName(iRowSet.getString("personName"));
  479. Date attenceDate = iRowSet.getDate("attenceDate");
  480. if (attenceDate != null) {
  481. data.setExceptionDate(sdf.format(attenceDate));
  482. }
  483. data.setDepartmentCode(iRowSet.getString("adminOrgNumber"));
  484. data.setDepartmentName(iRowSet.getString("adminOrgName"));
  485. data.setDepartmentManagerCode(iRowSet.getString("adminOrgLongNumber"));
  486. data.setDepartmentSortCode(iRowSet.getString("sortCode"));
  487. data.setDepartmentManagerName(iRowSet.getString("displayName"));
  488. StringBuilder attendanceResult = new StringBuilder();
  489. int times = 0;
  490. Map<String, Boolean> attendanceFlags = new LinkedHashMap<>();
  491. int s19 = iRowSet.getInt("s19");
  492. int s21 = iRowSet.getInt("s21");
  493. BigDecimal s23 = iRowSet.getBigDecimal("s23");
  494. int s113 = iRowSet.getInt("s113");
  495. attendanceFlags.put("迟到", s19 > 0);
  496. attendanceFlags.put("早退", s21 > 0);
  497. attendanceFlags.put("旷工", s23.compareTo(BigDecimal.ZERO) > 0);
  498. attendanceFlags.put("个人原因补卡次数", s113 > 0);
  499. for (Map.Entry<String, Boolean> entry : attendanceFlags.entrySet()) {
  500. if (entry.getValue()) {
  501. times++;
  502. attendanceResult.append(entry.getKey()).append("、");
  503. }
  504. }
  505. // 移除最后一个顿号
  506. if (attendanceResult.length() > 0) {
  507. attendanceResult.setLength(attendanceResult.length() - 1);
  508. }
  509. data.setTimes(times);
  510. data.setAttendanceResult(attendanceResult.toString());
  511. return data;
  512. }
  513. /**
  514. * 获取考勤异常查询sql
  515. *
  516. * @param startDate
  517. * @param endDate
  518. * @return
  519. * @throws BOSException
  520. */
  521. protected String getSql(
  522. Date startDate,
  523. Date endDate
  524. ) throws BOSException {
  525. if (startDate == null || endDate == null) {
  526. logger.error("getAttendanceExceptionData startDate or endDate is null");
  527. throw new BOSException("getAttendanceExceptionData startDate or endDate is null");
  528. }
  529. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  530. StringBuilder sql = new StringBuilder()
  531. .append("select").append("\n")
  532. .append(" person.fid as personId,").append("\n")
  533. .append(" person.fnumber as personNumber,").append("\n")
  534. .append(" person.Fname_l2 as personName,").append("\n")
  535. .append(" attendanceResult.FAttenceDate as attenceDate,").append("\n")
  536. .append(" attendanceResult.s19 as s19,").append("\n")
  537. .append(" attendanceResult.s21 as s21,").append("\n")
  538. .append(" attendanceResult.s23 as s23,").append("\n")
  539. .append(" attendanceResult.s113 as s113,").append("\n")
  540. .append(" adminOrg.fid as adminOrgId,").append("\n")
  541. .append(" adminOrg.fnumber as adminOrgNumber,").append("\n")
  542. .append(" adminOrg.fname_l2 as adminOrgName,").append("\n")
  543. .append(" adminOrg.FLongNumber as adminOrgLongNumber,").append("\n")
  544. .append(" adminOrg.FSortCode as sortCode,").append("\n")
  545. .append(" adminOrg.FDisplayName_L2 as displayName,").append("\n")
  546. .append(" admintwo.fid as admintwoId,").append("\n")
  547. .append(" admintwo.fnumber as admintwoNumber,").append("\n")
  548. .append(" admintwo.Fname_l2 as admintwoName").append("\n")
  549. .append("from").append("\n")
  550. .append(" T_HR_ATS_AttendanceResult attendanceResult").append("\n")
  551. .append(" left join t_bd_person person on person.fid = attendanceResult.FProposerID").append("\n")
  552. .append(" left join T_ORG_admin adminOrg on attendanceResult.FAdminOrgUnitID = adminOrg.fid").append("\n")
  553. .append(" left join T_ORG_admin admintwo on adminOrg.FLevelTwoGroupID = admintwo.fid").append("\n")
  554. .append("where").append("\n")
  555. .append(" attendanceResult.FAttenceDate >= { TS '").append(sdf.format(startDate)).append("' }").append("\n")
  556. .append(" and attendanceResult.FAttenceDate <= { TS '").append(sdf.format(endDate)).append("' }").append("\n")
  557. .append(" and (").append("\n")
  558. .append(" attendanceResult.s19 > 0").append("\n")
  559. .append(" or attendanceResult.s21 > 0").append("\n")
  560. .append(" or attendanceResult.s23 > 0").append("\n")
  561. .append(" or attendanceResult.S113 > 0").append("\n")
  562. .append(" );").append("\n");
  563. if (logger.isInfoEnabled()) {
  564. logger.info(String.format("AttendanceExceptionFacadeControllerBean.getSql: %s", sql.toString()));
  565. }
  566. return sql.toString();
  567. }
  568. /**
  569. * 发送考勤异常消息
  570. *
  571. * @param dingMsgBean
  572. * @param logInfo
  573. * @throws BOSException
  574. */
  575. protected void sendAttendanceExceptionMsg(
  576. JSONObject dingMsgBean,
  577. AttendanceExceptionLogInfo logInfo
  578. ) throws BOSException {
  579. try {
  580. String url = propt.getProperty("sendDingMsgUrl");
  581. if (url == null || url.isEmpty()) {
  582. logger.error("pushAttendanceExceptionData url is null");
  583. throw new BOSException("pushAttendanceExceptionData url is null");
  584. }
  585. logger.error("pushAttendanceExceptionData url: " + url);
  586. if (dingMsgBean == null) {
  587. logger.error("pushAttendanceExceptionData dingMsgBean is null");
  588. throw new BOSException("pushAttendanceExceptionData dingMsgBean is null");
  589. }
  590. String params = dingMsgBean.toJSONString();
  591. logInfo.setMessageRequest(params);
  592. OkHttpClient client = new OkHttpClient();
  593. MediaType mediaType = MediaType.parse("application/json");
  594. RequestBody body = RequestBody.create(mediaType, params);
  595. Request request = new Request.Builder()
  596. .url(url)
  597. .post(body)
  598. .addHeader("Accept", "*/*")
  599. .addHeader("Accept-Encoding", "gzip, deflate, br")
  600. .addHeader("User-Agent", "PostmanRuntime-ApipostRuntime/1.1.0")
  601. .addHeader("Connection", "keep-alive")
  602. .addHeader("Content-Type", "application/json")
  603. .build();
  604. Response response = client.newCall(request).execute();
  605. logger.error("response----" + response.isSuccessful());
  606. if (response.isSuccessful()) {
  607. String resultBody = response.body().string();
  608. logInfo.setMessageResponse(resultBody);
  609. logger.error("resultBody----" + resultBody);
  610. JSONObject result = JSONObject.parseObject(resultBody);
  611. if (result.getBoolean("success")) {
  612. logInfo.setPushStatus(CallStatusEnum.success);
  613. } else {
  614. //推送失败
  615. throw new BOSException(result.getString("msg"));
  616. }
  617. } else {
  618. throw new BOSException("接口请求超时");
  619. }
  620. } catch (Exception e) {
  621. logger.error(e.getMessage(), e);
  622. logInfo.setPushStatus(CallStatusEnum.failure);
  623. logInfo.setPushResult("发送考勤异常消息报错: " + e.getMessage());
  624. throw new BOSException(e);
  625. }
  626. }
  627. /**
  628. * 推送考勤异常数据
  629. *
  630. * @param list
  631. * @param logInfo
  632. * @throws BOSException
  633. */
  634. protected void pushAttendanceExceptionData(
  635. List list,
  636. AttendanceExceptionLogInfo logInfo
  637. ) throws BOSException {
  638. try {
  639. String url = propt.getProperty("syncAttendanceDataUrl");
  640. if (url == null || url.isEmpty()) {
  641. logger.error("pushAttendanceExceptionData url is null");
  642. throw new BOSException("pushAttendanceExceptionData url is null");
  643. }
  644. logger.error("pushAttendanceExceptionData url: " + url);
  645. if (list == null || list.size() <= 0) {
  646. logger.error("pushAttendanceExceptionData list is null");
  647. throw new BOSException("pushAttendanceExceptionData list is null");
  648. }
  649. String params = JSON.toJSONString(list);
  650. logInfo.setDataPushRequest(params);
  651. OkHttpClient client = new OkHttpClient();
  652. MediaType mediaType = MediaType.parse("application/json");
  653. RequestBody body = RequestBody.create(mediaType, params);
  654. Request request = new Request.Builder()
  655. .url(url)
  656. .post(body)
  657. .addHeader("Accept", "*/*")
  658. .addHeader("Accept-Encoding", "gzip, deflate, br")
  659. .addHeader("User-Agent", "PostmanRuntime-ApipostRuntime/1.1.0")
  660. .addHeader("Connection", "keep-alive")
  661. .addHeader("Content-Type", "application/json")
  662. .build();
  663. Response response = client.newCall(request).execute();
  664. if (response.isSuccessful()) {
  665. String resultBody = response.body().string();
  666. logInfo.setDataPushResponse(resultBody);
  667. logger.error("resultBody----" + resultBody);
  668. JSONObject result = JSONObject.parseObject(resultBody);
  669. if (result.getBoolean("success")) {
  670. logInfo.setPushStatus(CallStatusEnum.success);
  671. } else {
  672. //推送失败
  673. throw new BOSException(result.getString("msg"));
  674. }
  675. } else {
  676. throw new BOSException("接口请求超时");
  677. }
  678. } catch (Exception e) {
  679. logger.error(e.getMessage(), e);
  680. logInfo.setPushStatus(CallStatusEnum.failure);
  681. logInfo.setPushResult("推送考勤数据报错: " + e.getMessage());
  682. throw new BOSException(e);
  683. }
  684. }
  685. /**
  686. * set转字符串
  687. *
  688. * @param set
  689. * @return
  690. */
  691. public String convertSetToString(Set set) {
  692. if (set != null && set.size() > 0) {
  693. Iterator iter = set.iterator();
  694. StringBuffer sql = new StringBuffer();
  695. while (iter.hasNext()) {
  696. sql.append(iter.next()).append(",");
  697. }
  698. sql.deleteCharAt(sql.length() - 1);
  699. return sql.toString();
  700. } else {
  701. return "";
  702. }
  703. }
  704. /**
  705. * 获取各个中心考勤总人数
  706. *
  707. * @param ctx
  708. * @return
  709. */
  710. public Map<String, Integer> getAttendanceCount(Context ctx) {
  711. Map<String, Integer> attendanceCountMap = new HashMap<>();
  712. try {
  713. IAttendanceFile iAttendanceFile = AttendanceFileFactory.getLocalInstance(ctx);
  714. FilterInfo filterInfo = new FilterInfo();
  715. FilterItemCollection filterItems = filterInfo.getFilterItems();
  716. filterItems.add(new FilterItemInfo("attendFileState", "1"));
  717. SelectorItemCollection sic = new SelectorItemCollection();
  718. sic.add("adminOrgUnit.levelTwoGroup.number");
  719. EntityViewInfo viewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
  720. AttendanceFileCollection attendanceFileCol = iAttendanceFile.getAttendanceFileCollection(viewInfo);
  721. for (int i = 0; i < attendanceFileCol.size(); i++) {
  722. AttendanceFileInfo attendanceFileInfo = attendanceFileCol.get(i);
  723. String number = attendanceFileInfo.getAdminOrgUnit().getLevelTwoGroup().getNumber();
  724. if (attendanceCountMap.containsKey(number)) {
  725. Integer i1 = attendanceCountMap.get(number);
  726. attendanceCountMap.put(number, i1 + 1);
  727. } else {
  728. attendanceCountMap.put(number, 1);
  729. }
  730. }
  731. } catch (BOSException e) {
  732. logger.error("获取各个中心考勤总人数报错: " + e.getMessage(), e);
  733. throw new RuntimeException(e);
  734. }
  735. return attendanceCountMap;
  736. }
  737. /**
  738. * 获取中心名称
  739. *
  740. * @param ctx
  741. * @return
  742. */
  743. public Map<String, String> getOrgMap(Context ctx) {
  744. Map<String, String> orgMap = new HashMap<>();
  745. try {
  746. IAdminOrgUnit iAdminOrgUnit = AdminOrgUnitFactory.getLocalInstance(ctx);
  747. FilterInfo filterInfo = new FilterInfo();
  748. FilterItemCollection filterItems = filterInfo.getFilterItems();
  749. //组织层级为一级组织
  750. filterItems.add(new FilterItemInfo("unitLayerType", "00000000-0000-0000-0000-00000000000362824988"));
  751. filterItems.add(new FilterItemInfo("isSealUp", "0"));
  752. SelectorItemCollection sic = new SelectorItemCollection();
  753. sic.add("number");
  754. sic.add("name");
  755. EntityViewInfo viewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
  756. AdminOrgUnitCollection adminOrgUnitCol = iAdminOrgUnit.getAdminOrgUnitCollection(viewInfo);
  757. for (int i = 0; i < adminOrgUnitCol.size(); i++) {
  758. AdminOrgUnitInfo adminOrgUnitInfo = adminOrgUnitCol.get(i);
  759. String number = adminOrgUnitInfo.getNumber();
  760. String name = adminOrgUnitInfo.getName();
  761. orgMap.put(number, name);
  762. }
  763. } catch (Exception e) {
  764. logger.error("获取中心名称报错: " + e.getMessage(), e);
  765. throw new RuntimeException(e);
  766. }
  767. return orgMap;
  768. }
  769. /**
  770. * 获取提醒记录
  771. *
  772. * @param ctx
  773. * @param yearMonth
  774. * @return
  775. */
  776. private Set<String> getRemindRecord(Context ctx, String yearMonth) {
  777. Set<String> remindRecordSet = new HashSet<>();
  778. try {
  779. String querySql = "select personNumber from T_Remind_Record where yearMonth=?";
  780. IRowSet iRowSet = DBUtil.executeQuery(ctx, querySql, new Object[]{yearMonth});
  781. while (iRowSet.next()) {
  782. remindRecordSet.add(iRowSet.getString("personNumber"));
  783. }
  784. } catch (Exception e) {
  785. logger.error("获取提醒记录报错: " + e.getMessage(), e);
  786. throw new RuntimeException(e);
  787. }
  788. return remindRecordSet;
  789. }
  790. /**
  791. * 新增提醒记录
  792. *
  793. * @param ctx
  794. * @param yearMonth
  795. */
  796. private void addRemindRecord(Context ctx, String yearMonth, String personNumber) {
  797. try {
  798. String querySql = "insert into T_Remind_Record(yearMonth,personNumber) values (?,?)";
  799. DBUtil.execute(ctx, querySql, new Object[]{yearMonth, personNumber});
  800. } catch (Exception e) {
  801. logger.error("新增提醒记录报错: " + e.getMessage(), e);
  802. throw new RuntimeException("新增提醒记录报错: " + e.getMessage());
  803. }
  804. }
  805. }