d9e6f3616bdb890c9d9cd6c8a7ea8801e9d0bd87.svn-base 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901
  1. package com.kingdee.eas.custom.facade.abnormal;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import java.sql.SQLException;
  5. import java.util.ArrayList;
  6. import java.util.HashMap;
  7. import java.util.HashSet;
  8. import java.util.List;
  9. import java.util.Map;
  10. import java.util.Map.Entry;
  11. import java.util.Set;
  12. import com.aliyun.odps.utils.StringUtils;
  13. import com.kingdee.bos.*;
  14. import com.kingdee.eas.custom.entity.AbnormaAttendanceDetailInfo;
  15. import com.kingdee.eas.custom.entity.AbnormaAttendanceInfo;
  16. import com.kingdee.eas.custom.entity.AbnormalInfo;
  17. import com.kingdee.eas.custom.utils.SendUtils;
  18. import com.kingdee.eas.mobile.BOSMsgTypeEnum;
  19. import com.kingdee.eas.mobile.MimeTypeEnum;
  20. import com.kingdee.eas.mobile.PriorityEnum;
  21. import com.kingdee.eas.util.app.DbUtil;
  22. import com.kingdee.jdbc.rowset.IRowSet;
  23. import java.time.LocalDate;
  24. import java.time.format.DateTimeFormatter;
  25. // 部门考勤异常预警
  26. public class AbnormalFacadeControllerBean extends AbstractAbnormalFacadeControllerBean {
  27. private static Logger logger = LoggerFactory.getLogger(AbnormalFacadeControllerBean.class);
  28. @Override
  29. public void _abnormalAttendance(Context ctx) throws BOSException {
  30. // 查询考勤异常的统计数据
  31. String attendanceSql ="/*dialect*/SELECT\r\n" +
  32. " temp.attendDate attendDate,\r\n" +
  33. " temp.personId personId,\r\n" +
  34. " thpc.fpersondep orgId,\r\n" +
  35. " temp.abnormalCount abnormalCount,\r\n" +
  36. " temp.reason reason \r\n" +
  37. "FROM\r\n" +
  38. " (\r\n" +
  39. " SELECT DISTINCT\r\n" +
  40. " a.FAttendanceDate attendDate,\r\n" +
  41. " a.FProposer personId,\r\n" +
  42. " a.FAttendanceValue abnormalCount,\r\n" +
  43. " c.fname_l1 reason \r\n" +
  44. " FROM\r\n" +
  45. " T_HR_ATS_AbnormalAttendance a\r\n" +
  46. " LEFT JOIN (\r\n" +
  47. " SELECT\r\n" +
  48. " FProposer,\r\n" +
  49. " SUM ( FAttendanceValue ) AS COUNT \r\n" +
  50. " FROM\r\n" +
  51. " T_HR_ATS_AbnormalAttendance \r\n" +
  52. " WHERE\r\n" +
  53. " FAttendanceDate >= date_trunc ( 'month', CURRENT_DATE - INTERVAL '1 month' ) \r\n" +
  54. " AND FAttendanceDate <= LAST_DAY (\r\n" +
  55. " DATE_TRUNC ( 'month', CURRENT_DATE - INTERVAL '1 month' )) and FStatus= '1' and FOperationStatus= '1' \r\n" +
  56. " GROUP BY\r\n" +
  57. " FProposer \r\n" +
  58. " HAVING\r\n" +
  59. " SUM ( FAttendanceValue ) > 3 \r\n" +
  60. " ) b ON a.FProposer= b.FProposer\r\n" +
  61. " LEFT JOIN T_HR_ATS_AttendanceProject c ON c.fid= a.FattendanceProject \r\n" +
  62. " WHERE\r\n" +
  63. " a.FStatus= '1' \r\n" +
  64. " AND a.FOperationStatus= '1' \r\n" +
  65. " AND a.FAttendanceDate >= date_trunc ( 'month', CURRENT_DATE - INTERVAL '1 month' ) \r\n" +
  66. " AND a.FAttendanceDate <= LAST_DAY (\r\n" +
  67. " DATE_TRUNC ( 'month', CURRENT_DATE - INTERVAL '1 month' )) \r\n" +
  68. " AND b.count > 3 \r\n" +
  69. " ) temp\r\n" +
  70. " LEFT JOIN (\r\n" +
  71. " SELECT\r\n" +
  72. " thpa.fpersonid,\r\n" +
  73. " thpa.fpersondep \r\n" +
  74. " FROM\r\n" +
  75. " T_HR_PersonPosition thpa\r\n" +
  76. " INNER JOIN ( SELECT fpersonid fpersonid, MAX ( fjoindate ) maxDate FROM T_HR_PersonPosition GROUP BY fpersonid ) thpb ON thpa.fjoindate= thpb.maxDate \r\n" +
  77. " AND thpa.fpersonid= thpb.fpersonid \r\n" +
  78. " ) thpc ON thpc.fpersonid= temp.personId";
  79. // String attendanceSql ="/*dialect*/ \r\n" +
  80. // " SELECT DISTINCT\r\n" +
  81. // " a.FAttendanceDate attendDate,\r\n" +
  82. // " a.FProposer personId,\r\n" +
  83. // " a.FAdminOrgUnitId orgId,\r\n" +
  84. // " a.FAttendanceValue abnormalCount,\r\n" +
  85. // " c.fname_l1 reason\r\n" +
  86. // " FROM\r\n" +
  87. // " T_HR_ATS_AbnormalAttendance a\r\n" +
  88. // " LEFT JOIN (\r\n" +
  89. // " SELECT\r\n" +
  90. // " FProposer,\r\n" +
  91. // " SUM(CAST(FAttendanceValue AS INT)) AS COUNT \r\n" +
  92. // " FROM\r\n" +
  93. // " T_HR_ATS_AbnormalAttendance \r\n" +
  94. // " WHERE\r\n" +
  95. // " FAttendanceDate >= '2023-11-01' \r\n" +
  96. // " AND FAttendanceDate <= '2023-11-30' \r\n" +
  97. // " GROUP BY\r\n" +
  98. // " FProposer \r\n" +
  99. // " HAVING\r\n" +
  100. // " SUM(CAST(FAttendanceValue AS INT)) > 3 \r\n" +
  101. // " ) b ON a.FProposer= b.FProposer\r\n" +
  102. // " LEFT JOIN T_HR_ATS_AttendanceProject c ON c.fid= a.FattendanceProject \r\n" +
  103. // " WHERE\r\n" +
  104. // " a.FStatus= '1' \r\n" +
  105. // " AND a.FOperationStatus= '1' \r\n" +
  106. // " AND a.FAttendanceDate >'2023-11-01'\r\n" +
  107. // " AND a.FAttendanceDate <= '2023-11-30' \r\n" +
  108. // " AND b.count > 3 ";
  109. try {
  110. // System.out.print(kqSql);
  111. // 先把部门查出来
  112. logger.info("AbnormalFacadeControllerBean->attendanceSql->{} ",attendanceSql);
  113. IRowSet kqRowSet = DbUtil.executeQuery(ctx, attendanceSql);
  114. Set<String> kqSet = new HashSet<>();
  115. List<AbnormalInfo> dataList=new ArrayList<>();
  116. while (kqRowSet.next()) {
  117. AbnormalInfo info=new AbnormalInfo();
  118. String fAdminOrgUnitId = kqRowSet.getString("orgId");
  119. kqSet.add(fAdminOrgUnitId);
  120. info.setAttendDate(kqRowSet.getString("attendDate"));
  121. info.setPersonId(kqRowSet.getString("personId"));
  122. info.setOrgId(kqRowSet.getString("orgId"));
  123. info.setReason(kqRowSet.getString("reason"));
  124. info.setAbnormalCount(Integer.valueOf(kqRowSet.getString("abnormalCount")));
  125. dataList.add(info);
  126. }
  127. //查询条件的字符串拼接
  128. String processStr = processStr(kqSet);
  129. //部门负责人 key为人员 value部门,多个部门以,分隔
  130. Map<String, String> headMap = getHead(ctx,processStr);
  131. //pvc key为人员 value部门,多个部门以,分隔
  132. Map<String, String> pvcMap = getPvc(ctx,processStr);
  133. // //人员统计数
  134. // Map<String, String> personAndCount = getPersonAndCount(ctx);
  135. //合并部门负责人和pvc key为收件人id,value为部门id集合
  136. Map<String, Set<String>> sendPersonIds = mergerPerson(headMap,pvcMap);
  137. //初始化部门集合
  138. Map<String, String> orgMap = initOrg(ctx);
  139. //初始化人员集合
  140. Map<String, String> personMap = initPerson(ctx);
  141. //发送邮件
  142. sendEmail(ctx,sendPersonIds,dataList,getTitle(getCurrenLastDayDate()),orgMap,personMap);
  143. } catch (SQLException e) {
  144. // TODO 自动生成的 catch 块
  145. e.printStackTrace();
  146. }
  147. }
  148. /**
  149. * 默认查询所有的部门集合
  150. * @param ctx
  151. * @return
  152. * @throws BOSException
  153. * @throws SQLException
  154. */
  155. private Map<String,String> initOrg(Context ctx) throws BOSException, SQLException{
  156. String sql="select fid orgId,fname_l1 orgName from T_ORG_ADMIN";
  157. Map<String, String> orgMap = new HashMap<>();
  158. IRowSet orgRowSet = DbUtil.executeQuery(ctx, sql);
  159. while (orgRowSet.next()) {
  160. orgMap.put(orgRowSet.getString("orgId"), orgRowSet.getString("orgName"));
  161. }
  162. return orgMap;
  163. }
  164. /**
  165. * 默认查询所有的部门集合
  166. * @param ctx
  167. * @return
  168. * @throws BOSException
  169. * @throws SQLException
  170. */
  171. private Map<String,String> initPerson(Context ctx) throws BOSException, SQLException{
  172. String sql="select fid pId,fname_l1 pName from T_BD_PERSON ";
  173. Map<String, String> personMap = new HashMap<>();
  174. IRowSet personRowSet = DbUtil.executeQuery(ctx, sql);
  175. while (personRowSet.next()) {
  176. personMap.put(personRowSet.getString("pId"), personRowSet.getString("pName"));
  177. }
  178. return personMap;
  179. }
  180. // /**
  181. // * 获取人员与统计
  182. // * @return key为人员id value统计数
  183. // * @throws BOSException
  184. // * @throws SQLException
  185. // */
  186. // private Map<String,String> getPersonAndCount(Context ctx) throws BOSException, SQLException{
  187. // String sumSql="/*dialect*/ SELECT\r\n" +
  188. // "FProposer,\r\n" +
  189. // "COUNT ( * ) AS COUNT \r\n" +
  190. // "FROM\r\n" +
  191. // " T_HR_ATS_AbnormalAttendance \r\n" +
  192. // "WHERE\r\n" +
  193. // " FAttendanceDate >= date_trunc ( 'month', CURRENT_DATE - INTERVAL '1 month' ) \r\n" +
  194. // " AND FAttendanceDate <= LAST_DAY (\r\n" +
  195. // " DATE_TRUNC ( 'month', CURRENT_DATE - INTERVAL '1 month' )) \r\n" +
  196. // " AND FStatus = '1' \r\n" +
  197. // " AND FOperationStatus = '1' \r\n" +
  198. // "GROUP BY\r\n" +
  199. // " FProposer \r\n" +
  200. // "HAVING\r\n" +
  201. // " SUM ( FAttendanceValue ) > 3";
  202. //
  203. //// String sumSql="/*dialect*/ SELECT\r\n" +
  204. //// "FProposer,\r\n" +
  205. //// "COUNT ( * ) AS COUNT \r\n" +
  206. //// "FROM\r\n" +
  207. //// " T_HR_ATS_AbnormalAttendance \r\n" +
  208. //// "WHERE\r\n" +
  209. //// " FAttendanceDate >= '2023-11-01' \r\n" +
  210. //// " AND FAttendanceDate <= '2023-11-30' \r\n" +
  211. //// " AND FStatus = '1' \r\n" +
  212. //// " AND FOperationStatus = '1' \r\n" +
  213. //// "GROUP BY\r\n" +
  214. //// " FProposer \r\n" +
  215. //// "HAVING\r\n" +
  216. //// " SUM(CAST(FAttendanceValue AS INT)) > 3";
  217. // Map<String, String> countMap = new HashMap<>();
  218. // IRowSet countRowSet = DbUtil.executeQuery(ctx, sumSql);
  219. // while (countRowSet.next()) {
  220. // countMap.put(countRowSet.getString("FProposer"), countRowSet.getString("count"));
  221. // }
  222. // return countMap;
  223. //
  224. // }
  225. //
  226. /**
  227. * 获取部门负责人
  228. * @param numbers
  229. * @return
  230. * @throws BOSException
  231. * @throws SQLException
  232. */
  233. private Map<String,String> getHead(Context ctx,String processStr) throws BOSException, SQLException{
  234. Map<String,String> resultMap=new HashMap<>();
  235. String sql="SELECT\r\n" +
  236. " a.fid AS oId,\r\n" +
  237. " a.fnumber AS oNumber,\r\n" +
  238. " d.fnumber AS pNumber,\r\n" +
  239. " d.fid AS pId,\r\n" +
  240. " d.fname_L1 AS pNameL1,\r\n" +
  241. " d.fname_L2 AS pNameL2 \r\n" +
  242. "FROM\r\n" +
  243. " T_ORG_Admin a\r\n" +
  244. " LEFT JOIN T_ORG_POSITION b ON a.FResponPositionID= b.fid\r\n" +
  245. " LEFT JOIN (\r\n" +
  246. " SELECT\r\n" +
  247. " ca.fpositionid,\r\n" +
  248. " ca.fpersonid, \r\n" +
  249. " ca.fislatestinaday, \r\n" +
  250. " ca.fadminorgid, \r\n" +
  251. " ca.flastupdatetime \r\n" +
  252. " FROM\r\n" +
  253. " T_HR_EmpOrgRelation ca\r\n" +
  254. " INNER JOIN ( SELECT fpositionid, MAX ( fleffdt ) maxDate FROM T_HR_EmpOrgRelation GROUP BY fpositionid ) cb ON ca.fpositionid= cb.fpositionid \r\n" +
  255. " AND ca.fleffdt= cb.maxDate \r\n" +
  256. " ) c ON c.fpositionid= b.fid\r\n" +
  257. " LEFT JOIN T_BD_Person d ON d.fid= c.fpersonid\r\n" +
  258. " LEFT JOIN T_HR_BDEmployeeType e ON e.fid= d.femployeetypeid \r\n" +
  259. "WHERE\r\n" +
  260. " a.fid IN ("+processStr+") \r\n" +
  261. " AND b.FIsRespPosition= 1 \r\n" +
  262. " AND e.finservice= 1 \r\n" +
  263. " AND b.fdeletedstatus= 1 \r\n"+
  264. " AND c.fislatestinaday=1 \r\n";
  265. logger.info("AbnormalFacadeControllerBean->getHead->sql{} ",sql);
  266. IRowSet rs = DbUtil.executeQuery(ctx, sql.toString());
  267. while(rs.next()) {
  268. String pId = rs.getString("pId");
  269. if(StringUtils.isBlank(pId)) {
  270. continue;
  271. }
  272. if(StringUtils.isNotBlank(resultMap.get(pId))) {
  273. resultMap.put(pId, resultMap.get(pId)+","+rs.getString("oId"));
  274. }else {
  275. resultMap.put(pId, rs.getString("oId"));
  276. }
  277. }
  278. return resultMap;
  279. }
  280. /**
  281. * 获取pvc
  282. * @param ctx
  283. * @param processStr
  284. * @return
  285. * @throws BOSException
  286. * @throws SQLException
  287. */
  288. private Map<String,String> getPvc(Context ctx,String processStr) throws BOSException, SQLException{
  289. Map<String,String> resultMap=new HashMap<>();
  290. String sql="SELECT\r\n" +
  291. " org.fid oId,\r\n" +
  292. " org.fnumber orgNumber,\r\n" +
  293. " org.Fname_l1 orgName,\r\n" +
  294. " bp.fnumber pNumber,\r\n" +
  295. " bp.fid pId,\r\n" +
  296. " bp.Fname_l1 pName\r\n" +
  297. "FROM\r\n" +
  298. " T_WFR_WFROLE wf\r\n" +
  299. " LEFT JOIN T_WFR_PERSONROLE wp ON wp.froleid= wf.fid\r\n" +
  300. " LEFT JOIN T_BD_Person bp ON bp.fid= wp.fpsersonid\r\n" +
  301. " LEFT JOIN T_ORG_Admin org ON org.fid= wp.forgid \r\n" +
  302. "WHERE\r\n" +
  303. " wf.fnumber= '106' and org.fid in("+processStr+")";
  304. logger.info("AbnormalFacadeControllerBean->getPvc->sql{} ",sql);
  305. IRowSet rs = DbUtil.executeQuery(ctx, sql.toString());
  306. while(rs.next()) {
  307. String pId = rs.getString("pId");
  308. if(StringUtils.isBlank(pId)) {
  309. continue;
  310. }
  311. if(StringUtils.isNotBlank(resultMap.get(pId))) {
  312. resultMap.put(pId, resultMap.get(pId)+","+rs.getString("oId"));
  313. }else {
  314. resultMap.put(pId, rs.getString("oId"));
  315. }
  316. }
  317. return resultMap;
  318. }
  319. /**
  320. * 合并部门负责人和pvc
  321. * @return
  322. */
  323. private Map<String,Set<String>> mergerPerson(Map<String, String> headMap,Map<String, String> pvcMap ){
  324. Map<String,Set<String>> map=new HashMap<>();
  325. //key为人员id value为部门id,多个以,分隔
  326. for(Map.Entry<String, String> entry:headMap.entrySet()) {
  327. Set<String> set=new HashSet<>();
  328. String key = entry.getKey();
  329. String headValues = entry.getValue();
  330. if(StringUtils.isBlank(headValues)) {
  331. continue;
  332. }
  333. String[] split = headValues.split(",");
  334. for(String str:split) {
  335. set.add(str);
  336. }
  337. map.put(key, set);
  338. }
  339. //key为人员id value为部门id,多个以,分隔
  340. for(Map.Entry<String, String> entry:pvcMap.entrySet()) {
  341. String key = entry.getKey();
  342. String pvcValues = entry.getValue();
  343. if(StringUtils.isBlank(pvcValues)) {
  344. continue;
  345. }
  346. String[] split = pvcValues.split(",");
  347. Set<String> set = map.get(key);
  348. if(set==null || set.size()==0) {
  349. set=new HashSet<>();
  350. }
  351. for(String str:split) {
  352. set.add(str);
  353. }
  354. map.put(key, set);
  355. }
  356. return map;
  357. }
  358. /**
  359. * 处理字符串
  360. * @param numbers
  361. * @return
  362. */
  363. private String processStr(Set<String> ids) {
  364. String result="";
  365. StringBuilder sb = new StringBuilder();
  366. for (String s : ids) {
  367. sb.append("'").append(s).append("'").append(",");
  368. }
  369. if(sb.length()>0){
  370. sb.deleteCharAt(sb.lastIndexOf(","));
  371. result=sb.toString();
  372. }
  373. return result;
  374. }
  375. /**
  376. * 发送部门负责人邮件
  377. * @throws SQLException
  378. */
  379. private void sendEmail(Context ctx,Map<String, Set<String>> sendPersonIds,List<AbnormalInfo> dataList,String title,Map<String, String> orgMap,Map<String, String> personMap) throws SQLException {
  380. if(sendPersonIds==null) {
  381. return;
  382. }
  383. try {
  384. //遍历所有的接收人 ,并取对应的部门及相关信息
  385. Set<Entry<String,Set<String>>> entrySet = sendPersonIds.entrySet();
  386. for(Map.Entry<String,Set<String>> entry:entrySet) {
  387. //接收人id
  388. String personId = entry.getKey();
  389. //接收人对应的部门id集合
  390. Set<String> deptIds = entry.getValue();
  391. if(deptIds==null || deptIds.size()==0) {
  392. continue;
  393. }
  394. StringBuilder totalContent = new StringBuilder("<html><head></head><body>");
  395. totalContent.append("<span>Dear Sir/Madam,</span><br>\r\n" +
  396. " <span>This is attendance exception report of the last month.</span><br>\r\n" +
  397. " <span>Admin employees who has more than 3 abnormal records per month, it will be recorded in this exception report. It’s suggested to remind your team members to complete the leave application, business trip through Kingdee system by the end of each month to ensure the accuracy of the report.</span><br>\r\n" +
  398. " <span>Should you have any question, please do not hesitate to contact HR "+getHrEmail(ctx)+".</span><br>");
  399. StringBuilder detailContent=new StringBuilder();
  400. totalContent.append(
  401. "<table border=\'1\' cellspacing=\'0\' style=\'border:solid 1px #E8F2F9;font-size=8px;;font-size:10px;\'>");
  402. totalContent.append(
  403. "<tr style=\'background-color: #428BCA; color:#ffffff\'><th>Month月份</th><th>Name姓名</th><th>Department部门</th><th>AbnormalTimes考勤异常次数</th></tr>");
  404. //通过部门拿下面的人
  405. for(String deptId:deptIds) {
  406. //考勤明细数据 key为考勤明细中的姓名 value为对应的考勤异常数据
  407. Map<String, List<AbnormaAttendanceDetailInfo>> detailMap = processDetail(dataList,deptId,orgMap,personMap);
  408. //考勤统计数据 key为姓名 value对应为统计数据
  409. Map<String, AbnormaAttendanceInfo> totalMap = processInfo(detailMap);
  410. if(totalMap==null || detailMap==null) {
  411. continue;
  412. }
  413. //构建统计数据
  414. if(totalMap!=null && totalMap.size()>0) {
  415. Set<Entry<String,AbnormaAttendanceInfo>> totalEntrySet = totalMap.entrySet();
  416. for(Map.Entry<String,AbnormaAttendanceInfo> totalEntry:totalEntrySet) {
  417. AbnormaAttendanceInfo info = totalEntry.getValue();
  418. totalContent.append("<tr>");
  419. totalContent.append("<td>" + getCurrenLastDayDate() + "</td>"); // 第一列
  420. totalContent.append("<td>" + info.getName() + "</td>"); // 第二列
  421. totalContent.append("<td>" + info.getDept() + "</td>"); // 三列
  422. totalContent.append("<td>" + info.getCount() + "</td>"); // 第四列
  423. totalContent.append("</tr>");
  424. }
  425. }
  426. //构建明细数据
  427. if(detailMap!=null && detailMap.size()>0) {
  428. Set<Entry<String,List<AbnormaAttendanceDetailInfo>>> detailEntrySet = detailMap.entrySet();
  429. for(Map.Entry<String,List<AbnormaAttendanceDetailInfo>> detailEntry:detailEntrySet) {
  430. String personName = detailEntry.getKey();
  431. List<AbnormaAttendanceDetailInfo> detailList = detailEntry.getValue();
  432. detailContent.append(
  433. "<p style=\"font-size:10px;\">" + totalMap.get(personName).getName() + " of "+detailList.get(0).getDept()+" had "
  434. + totalMap.get(personName).getCount() + " abnormal records in " + getCurrenLastDayDate() + "</p>");
  435. detailContent.append(
  436. "<table border=\'1\' cellspacing=\'0\' style=\'border:solid 1px #E8F2F9;font-size=8px;;font-size:10px;\'>");
  437. detailContent.append(
  438. "<tr style=\'background-color: #428BCA; color:#ffffff\'><th>Name姓名</th><th>Department部门</th><th>AbnormalDate日期 </th><th>AbnoralReason考勤异常原因</th></tr>");// <th>AbnoralReason考勤异常原因</th>
  439. if(detailList==null || detailList.size()==0) {
  440. continue;
  441. }
  442. for(AbnormaAttendanceDetailInfo info:detailList) {
  443. detailContent.append("<tr>");
  444. detailContent.append("<td>" + info.getName() + "</td>"); // 第一列
  445. detailContent.append("<td>" + info.getDept() + "</td>"); // 第二列
  446. detailContent.append("<td>" + info.getDate().substring(0, 10)
  447. + "</td>"); // 三列
  448. detailContent.append("<td>" + info.getReason()+";"+info.getAbnormalCount() + "</td>"); // 第四列
  449. detailContent.append("</tr>");
  450. }
  451. detailContent.append("</table>");
  452. }
  453. }
  454. }
  455. totalContent.append("</table>");
  456. String content = (totalContent.append(detailContent).append("</body></html>")).toString();
  457. logger.info("GtiitOrgAdminService->sendHead->content{} ",content);
  458. try {
  459. //发送邮件
  460. SendUtils.msgSend(ctx, title, PriorityEnum.HIGHT_VALUE, false, content, personId,
  461. BOSMsgTypeEnum.V_TYPE_EMAIL, null, null, MimeTypeEnum.HTML);
  462. }catch(Exception e) {
  463. logger.info("AbnormalFacadeControllerBean->SendUtils.msgSend->{} ",e);
  464. }finally {
  465. //发送完清理
  466. totalContent=new StringBuilder();
  467. detailContent=new StringBuilder();
  468. }
  469. }
  470. }catch(Exception e) {
  471. logger.info("AbnormalFacadeControllerBean->sendHead->{} ",e);
  472. }
  473. }
  474. /**
  475. * 构建考勤异常明细数据
  476. * @param rowSet
  477. * @param sendPersonIds
  478. * @return
  479. * @throws SQLException
  480. */
  481. private Map<String,List<AbnormaAttendanceDetailInfo>> processDetail(List<AbnormalInfo> dataList,String deptId,Map<String, String> orgMap,Map<String, String> personMap) throws SQLException{
  482. //key为异常明细姓名 value是对应的人员集合
  483. Map<String,List<AbnormaAttendanceDetailInfo>> map=new HashMap<>();
  484. if(dataList==null || StringUtils.isBlank(deptId) ) {
  485. return null;
  486. }
  487. for(AbnormalInfo ab:dataList) {
  488. String orgId = ab.getOrgId();
  489. if(deptId.equals(orgId)) {
  490. String personName = personMap.get(ab.getPersonId());
  491. List<AbnormaAttendanceDetailInfo> list = map.get(personName);
  492. AbnormaAttendanceDetailInfo info=new AbnormaAttendanceDetailInfo();
  493. if(list==null || list.size()==0) {
  494. list=new ArrayList<>();
  495. }
  496. info.setDate(ab.getAttendDate());
  497. info.setName(personMap.get(ab.getPersonId()));
  498. info.setDept(orgMap.get(ab.getOrgId()));
  499. info.setReason(ab.getReason());
  500. info.setPersonId(ab.getPersonId());
  501. info.setAbnormalCount(ab.getAbnormalCount());
  502. list.add(info);
  503. map.put(personName, list);
  504. }
  505. }
  506. return map;
  507. }
  508. /**
  509. * 构建考勤统计数据
  510. * @param detailMap
  511. * @return
  512. */
  513. private Map<String, AbnormaAttendanceInfo> processInfo(Map<String,List<AbnormaAttendanceDetailInfo>> detailMap){
  514. //key为人员姓名 value为对应的人员统计数据
  515. Map<String,AbnormaAttendanceInfo> map=new HashMap<>();
  516. if(detailMap==null ) {
  517. return null;
  518. }
  519. Set<Map.Entry<String,List<AbnormaAttendanceDetailInfo>>> entrySet = detailMap.entrySet();
  520. for(Map.Entry<String,List<AbnormaAttendanceDetailInfo>> entry:entrySet) {
  521. String personName = entry.getKey();
  522. List<AbnormaAttendanceDetailInfo> detailList = entry.getValue();
  523. //考勤统计集合
  524. if(detailList==null || detailList.size()==0) {
  525. continue;
  526. }
  527. for(AbnormaAttendanceDetailInfo detailInfo:detailList) {
  528. AbnormaAttendanceInfo info = map.get(personName);
  529. if(info!=null) {
  530. info.setCount((info.getCount()+detailInfo.getAbnormalCount()));
  531. }else {
  532. info=new AbnormaAttendanceInfo();
  533. info.setName(detailInfo.getName());
  534. info.setDept(detailInfo.getDept());
  535. info.setMonth(getCurrenLastDayDate());
  536. info.setCount(detailInfo.getAbnormalCount());
  537. }
  538. map.put(personName, info);
  539. }
  540. }
  541. return map;
  542. }
  543. /**
  544. * 获取上个月的月份
  545. * @return
  546. */
  547. private String getCurrenLastDayDate() {
  548. // 获取当前日期
  549. LocalDate today = LocalDate.now();
  550. System.out.println("今天的日期是: " + today);
  551. // 获取上个月的第一天
  552. LocalDate firstDayOfLastMonth = today.minusMonths(1);
  553. System.out.println("上个月的第一天是: " + firstDayOfLastMonth);
  554. // 定义日期格式为"yyyy/mm"
  555. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM");
  556. // 将日期格式化为指定格式的字符串
  557. return firstDayOfLastMonth.format(formatter);
  558. }
  559. /**
  560. * 获取title
  561. * @param formattedDate
  562. * @return
  563. */
  564. private String getTitle(String formattedDate) {
  565. String replace = formattedDate.replace("/", "");
  566. return "Attendance Alert Report – "+replace;
  567. }
  568. /**
  569. * 获取HR邮箱地址
  570. * @return
  571. * @throws BOSException
  572. * @throws SQLException
  573. */
  574. private String getHrEmail(Context ctx) throws BOSException, SQLException {
  575. String sql="select fname_l1 name from T_HR_ATS_OverTimeReason where fnumber='GTYJ001'";
  576. IRowSet rs = DbUtil.executeQuery(ctx, sql.toString());
  577. String hrEmial="";
  578. while(rs.next()) {
  579. String name = rs.getString("name");
  580. if(StringUtils.isBlank(name)) {
  581. hrEmial="Carleen(carleen.wu@gtiit.edu.cn,88077081)";
  582. }else {
  583. hrEmial=name;
  584. }
  585. }
  586. return hrEmial;
  587. }
  588. // 拼接html
  589. // public void emailTable(IRowSet bumenRowSet, Set<String> bumenSet, String ReceiverID, Map<String, String> countmap,
  590. // Context ctx) {
  591. // int size = bumenSet.size();
  592. // String pid = null;
  593. // int sum = 0;
  594. // int count = 0;
  595. // try {
  596. // for (String element : bumenSet) {
  597. // // 创建一个map部门负责人作为key set存储人员
  598. // Map<String, Set<String>> darmentMap = new HashMap<>();
  599. // Set<String> darmentSet = new HashSet<>();
  600. // // 存储人员姓名的Set用于拼接html
  601. // Set<String> peronSet = new HashSet<>();
  602. // // map存储人员id和姓名用于拼接html
  603. // Map<String, String> personMap = new HashMap<>();
  604. // bumenRowSet.beforeFirst();
  605. // while (bumenRowSet.next()) {
  606. // String bumperonids = bumenRowSet.getString(ReceiverID);
  607. // // 负责人id作为key 只有负责人id相等才存set,每次for循环进来保证key都只有一个
  608. // if (!StringUtils.isBlank(bumperonids)) {
  609. //
  610. // if (bumperonids.equals(element)) {
  611. // darmentSet.add(bumenRowSet.getString("FProposer"));
  612. // personMap.put(bumenRowSet.getString("FProposer"), bumenRowSet.getString("peronName"));
  613. //
  614. // }
  615. // }
  616. // }
  617. // darmentMap.put(element, darmentSet);
  618. // // 部门负责人id为key,人员为vlue
  619. // Map<String, String> kqMap = new HashMap<>();
  620. // StringBuilder content = new StringBuilder("<html><head></head><body>");
  621. // content.append("<span>Dear Sir/Madan,</span><br>\r\n" +
  622. // " <span>This is attendance exception report of the last month.</span><br>\r\n" +
  623. // " <span>Admin employees who has more than 3 abnormal records per month, it will be recorded in this exception report. It’s suggested to remind your team members to complete the leave application, business trip through Kingdee system by the end of each month to ensure the accuracy of the report.</span><br>\r\n" +
  624. // " <span>Should you have any question, please do not hesitate to contact HR Carleen(carleen.wu@gtiit.edu.cn,88077081).</span><br>");
  625. // boolean isFirst = true;
  626. // boolean two = false;
  627. // bumenRowSet.beforeFirst();
  628. // while (bumenRowSet.next()) {
  629. // // 部门负责人id
  630. // String bumperonid = bumenRowSet.getString(ReceiverID);
  631. // String personid = bumenRowSet.getString("FProposer");
  632. // String darmentID = bumenRowSet.getString("fAdminOrgUnitId");
  633. // if (bumperonid != null) {
  634. //
  635. // // 部门负责人id相同才能进1CV1Xix+Qua9UEeo/uZ6TIDvfe0=
  636. // // 进来的时候bumperonid和element比较,进来之后isFirst设置false 所以不会重复
  637. // if (bumperonid.equals(element)) {
  638. // // 第一次先拼接html
  639. // if (isFirst) {
  640. // count++;
  641. // isFirst = false;
  642. // two = true;
  643. // kqMap.put(bumperonid, personid);
  644. // // 去除set中的元素 去除第一个拼接html的人员
  645. // darmentSet.remove(kqMap.get(bumperonid));
  646. // pid = bumperonid;
  647. // content.append(
  648. // "<table border=\'1\' cellspacing=\'0\' style=\'border:solid 1px #E8F2F9;font-size=8px;;font-size:10px;\'>");
  649. // content.append(
  650. // "<tr style=\'background-color: #428BCA; color:#ffffff\'><th>Month月份</th><th>Name姓名</th><th>Department部门</th><th>AbnormalTimes考勤异常次数</th></tr>");
  651. // content.append("<tr>");
  652. // content.append("<td>" + formattedDate + "</td>"); // 第一列
  653. // content.append("<td>" + bumenRowSet.getString("peronName") + "</td>"); // 第二列
  654. // content.append("<td>" + bumenRowSet.getString("bumenName") + "</td>"); // 三列
  655. // content.append("<td>" + bumenRowSet.getString("count") + "</td>"); // 第四列
  656. // content.append("</tr>");
  657. // peronSet.add(bumenRowSet.getString("peronName"));
  658. // continue;
  659. // }
  660. // // 1CV1Xix+Qua9UEeo/uZ6TIDvfe0=
  661. // // if (kqMap.containsKey(bumperonid)) {
  662. // // String key = kqMap.get(bumperonid);
  663. // // if (!kqMap.get(bumperonid).equals(personid)) {
  664. // // }
  665. // // }
  666. // // 创建一个map统计异常的数据
  667. // // Map<String, String> countMap = new HashMap<>();
  668. // // int tosum=0;
  669. //
  670. // // 判断负责人的id是为map的key
  671. // if (darmentMap.containsKey(bumperonid)) {
  672. // for (String key : darmentMap.keySet()) {
  673. // // 因为负责人id一次循环只有一个 所以只要判断set中是否存在人员id 存在就拼接html
  674. // Set<String> valueSet = darmentMap.get(key);
  675. // // 判断人员是否在set中
  676. // if (valueSet.contains(personid)) {
  677. // content.append("<tr>");
  678. // content.append("<td>" + formattedDate + "</td>"); // 第一列
  679. // content.append("<td>" + bumenRowSet.getString("peronName") + "</td>"); // 第二列
  680. // content.append("<td>" + bumenRowSet.getString("bumenName") + "</td>"); // 三列
  681. // content.append("<td>" + bumenRowSet.getString("count") + "</td>"); // 第四列
  682. // content.append("</tr>");
  683. // // 进来的人员id可能重复,拼接完之后去除set中这个元素
  684. // darmentSet.remove(personid);
  685. // peronSet.add(bumenRowSet.getString("peronName"));
  686. // continue;
  687. // }
  688. //
  689. // }
  690. //
  691. // }
  692. // }
  693. // }
  694. // }
  695. // // 如果上个表有就是true 就需要拼接明细
  696. // if (two) {
  697. //
  698. // content.append("</table>");
  699. // }
  700. // // // 拼接姓名的文字
  701. // //
  702. // // content.append("<p style=\"font-size:10px;\">" + person
  703. // // + "of Human Resources Department had 5 abnormal records in " + formattedDate
  704. // // + "</p>");
  705. // // personset遍历拼接
  706. //
  707. // // 遍历map拿key和统计条数的mapkey比较如果相等就评价html
  708. // for (String personkey : personMap.keySet()) {
  709. //
  710. // String perosnvalue = personMap.get(personkey);
  711. //
  712. // for (String countkey : countmap.keySet()) {
  713. //
  714. // String countvalue = countmap.get(personkey);
  715. // if (personkey.equals(countkey)) {
  716. // // 拼接姓名和统计条数
  717. //
  718. // content.append(
  719. // "<p style=\"font-size:10px;\">" + perosnvalue + "of Human Resources Department had "
  720. // + countvalue + " abnormal records in " + formattedDate + "</p>");
  721. // content.append(
  722. // "<table border=\'1\' cellspacing=\'0\' style=\'border:solid 1px #E8F2F9;font-size=8px;;font-size:10px;\'>");
  723. // content.append(
  724. // "<tr style=\'background-color: #428BCA; color:#ffffff\'><th>Name姓名</th><th>Department部门</th><th>AbnormalDate日期 </th><th>AbnoralReason考勤异常原因</th></tr>");// <th>AbnoralReason考勤异常原因</th>
  725. // String peronname = null;
  726. // String attenDate = null;
  727. // boolean first = true;
  728. // // 再次做个表格拼接 明细
  729. // bumenRowSet.beforeFirst();
  730. // while (bumenRowSet.next()) {
  731. // // 获取负责人id和 负责人id
  732. // String bumperonid = bumenRowSet.getString(ReceiverID);
  733. // String personid = bumenRowSet.getString("FProposer");
  734. // String danceDate = bumenRowSet.getString("FAttendanceDate").substring(0, 10);
  735. // for (Map.Entry<String, String> entry : kqMap.entrySet()) {
  736. // String key = entry.getKey();
  737. // String value = entry.getValue();
  738. // // 判断是否在同一个负责人下,是的话就拼接
  739. // if (!StringUtils.isBlank(bumperonid)) {
  740. // // 数据拼接可能会有重复需要判断做处理
  741. // if (bumperonid.equals(key)) {
  742. // // 第一次进来先拼接 并且人员要相等
  743. // if (first&&personkey.equals(personid)) {
  744. // first = false;
  745. // content.append("<tr>");
  746. // content.append("<td>" + bumenRowSet.getString("peronName") + "</td>"); // 第一列
  747. // content.append("<td>" + bumenRowSet.getString("bumenName") + "</td>"); // 第二列
  748. // content.append("<td>" + bumenRowSet.getString("FAttendanceDate").substring(0, 10)
  749. // + "</td>"); // 三列
  750. // content.append("<td>" + bumenRowSet.getString("lack")
  751. // + bumenRowSet.getString("FAttendanceValue") + "</td>"); // 第四列
  752. // content.append("</tr>");
  753. // peronname = bumenRowSet.getString("FProposer");
  754. // attenDate = bumenRowSet.getString("FAttendanceDate").substring(0, 10);
  755. // break;
  756. // }
  757. // // 判断人员和日期是否相等 相等就是以及拼接过的就需要跳出循环
  758. // if (personid.equals(peronname) && danceDate.equals(attenDate)) {
  759. // break;
  760. // } else if(personkey.equals(personid)){
  761. // content.append("<tr>");
  762. // content.append("<td>" + bumenRowSet.getString("peronName") + "</td>"); // 第一列
  763. // content.append("<td>" + bumenRowSet.getString("bumenName") + "</td>"); // 第二列
  764. // content.append("<td>" + bumenRowSet.getString("FAttendanceDate").substring(0, 10)
  765. // + "</td>"); // 三列
  766. // content.append("<td>" + bumenRowSet.getString("lack")
  767. // + bumenRowSet.getString("FAttendanceValue") + "</td>"); // 第四列
  768. // content.append("</tr>");
  769. // peronname = bumenRowSet.getString("FProposer");
  770. // attenDate = bumenRowSet.getString("FAttendanceDate").substring(0, 10);
  771. // break;
  772. // }
  773. //
  774. // }
  775. // }
  776. //
  777. // }
  778. //
  779. // }
  780. // content.append("</table>");
  781. // break;
  782. // }
  783. //
  784. // }
  785. //
  786. // }
  787. //
  788. // content.append("</body></html>");
  789. // String replace = formattedDate.replace("/", "");
  790. // String title = "Attendance Alert Report – "+replace;
  791. // String contents = null;
  792. // if (two) {
  793. //
  794. // contents = content.toString();
  795. // }
  796. // System.out.println("Html是" + contents);
  797. //
  798. // // MsgUtil.msgSend(ctx, title, PriorityEnum.HIGHT_VALUE, false, contents, pid,
  799. // // BOSMsgTypeEnum.V_TYPE_EMAIL, null, null, MimeTypeEnum.HTML);
  800. // SendUtils.msgSend(ctx, title, PriorityEnum.HIGHT_VALUE, false, contents, pid,
  801. // BOSMsgTypeEnum.V_TYPE_EMAIL, null, null, MimeTypeEnum.HTML);
  802. //
  803. // content = new StringBuilder();
  804. // }
  805. // } catch (SQLException | EASBizException | BOSException e) {
  806. // // TODO 自动生成的 catch 块
  807. // e.printStackTrace();
  808. // }
  809. //
  810. // }
  811. }