SyncPersonToBeisenService.java 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. package com.kingdee.eas.custom.beisen.syncperson.service;
  2. import com.alibaba.fastjson.JSONArray;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.kingdee.bos.BOSException;
  5. import com.kingdee.bos.Context;
  6. import com.kingdee.bos.bsf.service.app.IHRMsfService;
  7. import com.kingdee.bos.metadata.entity.*;
  8. import com.kingdee.bos.metadata.query.util.CompareType;
  9. import com.kingdee.eas.base.permission.IUser;
  10. import com.kingdee.eas.base.permission.UserCollection;
  11. import com.kingdee.eas.base.permission.UserFactory;
  12. import com.kingdee.eas.base.permission.UserInfo;
  13. import com.kingdee.eas.basedata.org.AdminOrgUnitInfo;
  14. import com.kingdee.eas.basedata.org.PositionInfo;
  15. import com.kingdee.eas.basedata.person.IPerson;
  16. import com.kingdee.eas.basedata.person.PersonCollection;
  17. import com.kingdee.eas.basedata.person.PersonFactory;
  18. import com.kingdee.eas.basedata.person.PersonInfo;
  19. import com.kingdee.eas.common.EASBizException;
  20. import com.kingdee.eas.custom.beisen.utils.BeisenApiClient;
  21. import com.kingdee.eas.custom.beisen.utils.BeisenParamByPropertiesUtil;
  22. import com.kingdee.eas.hr.ats.AtsUtil;
  23. import com.kingdee.eas.hr.base.*;
  24. import com.kingdee.eas.hr.emp.*;
  25. import com.kingdee.eas.util.app.DbUtil;
  26. import com.kingdee.jdbc.rowset.IRowSet;
  27. import com.kingdee.util.DateTimeUtils;
  28. import org.apache.commons.lang3.StringUtils;
  29. import org.apache.log4j.Logger;
  30. import java.io.IOException;
  31. import java.net.URLEncoder;
  32. import java.nio.charset.StandardCharsets;
  33. import java.sql.SQLException;
  34. import java.util.*;
  35. /**
  36. * @ClassName SyncPersonToBeisenService
  37. * @Description 同步人员信息数据到北森
  38. * @Author 青梧
  39. * @Date 2025/7/17 10:50
  40. * @Version 1.0
  41. **/
  42. public class SyncPersonToBeisenService implements IHRMsfService {
  43. private static Logger logger = Logger.getLogger(SyncPersonToBeisenService.class);
  44. private BeisenApiClient beisenApiClient = null;
  45. public SyncPersonToBeisenService() {
  46. beisenApiClient = BeisenApiClient.getInstance();
  47. }
  48. @Override
  49. public Object process(Context ctx, Map map) throws EASBizException, BOSException {
  50. Integer day = (Integer) map.get("day");
  51. String personId = (String) map.get("personId");
  52. // 获取到所有需要的personid
  53. Set<String> personSet = new HashSet();
  54. // 获取当前日期
  55. Date now = new Date();
  56. // 获取指定天数前的日期
  57. Date dayBefore = getDayBefore(now, day);
  58. FilterInfo filterInfo = new FilterInfo();
  59. FilterItemCollection filterItems = filterInfo.getFilterItems();
  60. filterItems.add(new FilterItemInfo("lastUpdateTime", dayBefore, CompareType.GREATER_EQUALS));
  61. filterItems.add(new FilterItemInfo("lastUpdateTime", now, CompareType.LESS_EQUALS));
  62. SelectorItemCollection sic = new SelectorItemCollection();
  63. sic.add(new SelectorItemInfo("id"));
  64. IPerson iPerson = PersonFactory.getLocalInstance(ctx);
  65. EntityViewInfo entityViewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
  66. PersonCollection personCol = iPerson.getPersonCollection(entityViewInfo);
  67. // 循环获取所有人员id
  68. for (int i = 0; i < personCol.size(); i++) {
  69. PersonInfo personInfo = personCol.get(i);
  70. personSet.add(personInfo.getId().toString());
  71. }
  72. sic = new SelectorItemCollection();
  73. sic.add(new SelectorItemInfo("person.id"));
  74. entityViewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
  75. // 获取员工变动记录的personid
  76. IEmpPosOrgRelation empIns = EmpPosOrgRelationFactory.getLocalInstance(ctx);
  77. EmpPosOrgRelationCollection empCol = empIns.getEmpPosOrgRelationCollection(entityViewInfo);
  78. // 循环获取所有人员id
  79. for (int i = 0; i < empCol.size(); i++) {
  80. EmpPosOrgRelationInfo empPosOrgRelation = empCol.get(i);
  81. String personIdStr = empPosOrgRelation.getPerson().getId().toString();
  82. personSet.add(personIdStr);
  83. }
  84. // 同步到beisen
  85. String s = convertSetToString(personSet);
  86. return _syncPerson(ctx, personId, day);
  87. }
  88. public static String convertSetToString(Set set) {
  89. if (set != null && set.size() > 0) {
  90. Iterator iter = set.iterator();
  91. StringBuffer sql = new StringBuffer();
  92. while (iter.hasNext()) {
  93. // sql.append("'");
  94. sql.append(iter.next());
  95. // sql.append("',");
  96. sql.append(",");
  97. }
  98. sql.deleteCharAt(sql.length() - 1);
  99. return sql.toString();
  100. } else {
  101. return "''";
  102. }
  103. }
  104. /**
  105. * 同步人员信息
  106. *
  107. * @param ctx
  108. * @param personId
  109. * @throws BOSException
  110. * @throws EASBizException
  111. */
  112. protected JSONArray _syncPerson(Context ctx, String personId, int day) {
  113. JSONArray jsonArray = new JSONArray();
  114. FilterInfo filterInfo = new FilterInfo();
  115. FilterItemCollection filterItems = filterInfo.getFilterItems();
  116. Set personIds = new HashSet();
  117. SelectorItemCollection sic = getSelectorItemCollection();
  118. // 如果为空查询所有数据
  119. if (!StringUtils.isEmpty(personId)) {
  120. personIds = AtsUtil.toSet(personId);
  121. logger.error("syncPersonToIot---personIds---" + personIds);
  122. filterItems.add(new FilterItemInfo("person", personIds, CompareType.INCLUDE));
  123. }
  124. try {
  125. BeisenParamByPropertiesUtil beisenParamByProperties = new BeisenParamByPropertiesUtil("/server/properties/beisen/BeiSenConfig.properties");
  126. Map<String, String> config = beisenParamByProperties.getConfig();
  127. logger.error("config---" + config.size());
  128. // 查询所有人的user用户
  129. IUser iUser = UserFactory.getLocalInstance(ctx);
  130. UserCollection userCollection = iUser.getUserCollection();
  131. Map userMap = new HashMap();
  132. for (int i = 0; i < userCollection.size(); i++) {
  133. UserInfo userInfo = userCollection.get(i);
  134. PersonInfo person = userInfo.getPerson();
  135. if (person != null) {
  136. String userName = userInfo.getName();
  137. userMap.put(person.getId(), userName);
  138. }
  139. }
  140. // 查询所有人的直接上级
  141. Map personParentMap = getPersonParent(ctx);
  142. IPersonPosition iPersonPosition = PersonPositionFactory.getLocalInstance(ctx);
  143. EntityViewInfo entityViewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
  144. PersonPositionCollection personPositionCollection = iPersonPosition.getPersonPositionCollection(entityViewInfo);
  145. if (personPositionCollection.isEmpty()) {
  146. jsonArray.add("[" + personId + "]未查询到人员信息数据,请检查参数是否url编码");
  147. }
  148. for (int i = 0; i < personPositionCollection.size(); i++) {
  149. Map msgMap = new HashMap();
  150. JSONObject personJson = new JSONObject();
  151. PersonPositionInfo personPositionInfo = personPositionCollection.get(i);
  152. PersonInfo person = personPositionInfo.getPerson();
  153. // 入职ID
  154. Object bsUserId = person.get("bsUserId");
  155. Object beisenId = person.get("beisenId");
  156. logger.error("bsUserId--" + bsUserId);
  157. logger.error("beisenId--" + beisenId);
  158. String originalId = URLEncoder.encode(person.getId().toString(), StandardCharsets.UTF_8.name());
  159. String nCell = person.getNCell();
  160. String name = person.getName();
  161. msgMap.put("number", person.getNumber());
  162. msgMap.put("name", name);
  163. msgMap.put("originalId", originalId);
  164. msgMap.put("bsUserId", bsUserId);
  165. msgMap.put("beisenId", beisenId);
  166. EmployeeTypeInfo employeeType = person.getEmployeeType();
  167. EmployeeTypeEnum inServiceEnum = employeeType.getInService();
  168. String email = person.getEmail();
  169. if (StringUtils.isEmpty(email)) {
  170. // throw new BOSException(person.getName() + "同步失败:邮箱不能为空,请维护!!");
  171. msgMap.put("message", person.getName() + "同步失败:邮箱不能为空,请维护!!");
  172. jsonArray.add(msgMap);
  173. continue;
  174. }
  175. personJson.put("email", email);// 邮箱
  176. personJson.put("userName", email);// 用户名
  177. personJson.put("name", name);// 姓名
  178. personJson.put("originalId", person.getId().toString());// 来源方用户ID
  179. // 来源(创建更新必填字段) 员工创建时的业务来源。0:其他;1:平台;2:测评;3:招聘;4:360;5:自由注册;6:Tita;7:Tita移动端;1001:PeopleSoft
  180. personJson.put("origin", 1);
  181. personJson.put("mobile", nCell);// 手机号
  182. personJson.put(config.get("EMPLOYEETYPENUMBER"), employeeType.getNumber());// 用工关系状态
  183. AdminOrgUnitInfo personDep = personPositionInfo.getPersonDep();
  184. personJson.put("departmentOriginalId", personDep.getId());// 部门外部标识
  185. personJson.put(config.get("HIREDATE"), DateTimeUtils.format(person.getHireDate()));// 入职日期
  186. Object lineManagerOriginalId = personParentMap.get(personId) == null ? null : URLEncoder.encode(personParentMap.get(personId).toString(), StandardCharsets.UTF_8.name());
  187. personJson.put(config.get("lineManagerOriginalId"), lineManagerOriginalId);// 直线上级外部标识
  188. PositionInfo primaryPosition = personPositionInfo.getPrimaryPosition();
  189. personJson.put(config.get("positionNumber"), primaryPosition.getNumber());// 岗位编码
  190. personJson.put(config.get("positionName"), primaryPosition.getName());// 岗位名称
  191. // 判断是否在北森存在 如果beisenId为空并且是在职状态需要再北森创建员工
  192. if (beisenId == null) {
  193. // 判断是否在职
  194. if (inServiceEnum.getValue() == 2) {
  195. msgMap.put("message", person.getName() + "已离职无需同步北森!!");
  196. jsonArray.add(msgMap);
  197. continue;
  198. }
  199. // 创建员工信息
  200. String staffsPost = config.get("STAFFSPOST");
  201. logger.error("personJson--" + personJson);
  202. JSONObject staffs = beisenApiClient.callApi(staffsPost, personJson);
  203. if (!"200".equals(staffs.getString("code"))) {
  204. msgMap.put("message", "创建员工信息失败,原因:" + staffs.get("message"));
  205. jsonArray.add(msgMap);
  206. continue;
  207. }
  208. String data = staffs.getString("data");
  209. // 更新bsUserId
  210. updatePersonBensenId(ctx, person, data);
  211. msgMap.put("bsUserId", data);
  212. msgMap.put("创建员工信息:", staffs.get("message"));
  213. } else {
  214. // 查询待入职人员信息 通过beisenId 入职员工ID获取入职记录guid和userId
  215. Map<String, String> result = getGuid(config, beisenId);
  216. logger.error("result--" + result);
  217. if (result == null || result.isEmpty()) {
  218. msgMap.put("message", "入职ID[" + beisenId + "]未查询到入职信息!");
  219. jsonArray.add(msgMap);
  220. continue;
  221. }
  222. String userId = result.get("userID");
  223. // 判断userid是否等于shr员工信息维护的北森id,如果不等于通过bsUserId修改北森用户管理的外部Id
  224. logger.error("bsUserId == null" + bsUserId == null);
  225. if (bsUserId == null) {
  226. bsUserId = userId;
  227. }
  228. logger.error(person.getName() + ":" + userId + "--" + bsUserId);
  229. msgMap.put("userID", userId);
  230. if (userId != bsUserId) {
  231. updateBeisenOriginalIdByUserId(msgMap, config, bsUserId);
  232. // 更新bsUserId
  233. updatePersonBensenId(ctx, person, (String) bsUserId);
  234. }
  235. // 通过OriginalId更新员工信息
  236. JSONObject udpatePersonJson = personJson;
  237. // 删除用户名,不修改用户名
  238. udpatePersonJson.remove("userName");
  239. String putbyuserid = config.get("PUTBYUSERID") + "?userId=" + userId;
  240. logger.error("putbyuserid--" + putbyuserid);
  241. logger.error("udpatePersonJson--" + udpatePersonJson);
  242. JSONObject updateStaffs = beisenApiClient.callPutApi(putbyuserid, udpatePersonJson);
  243. msgMap.put("通过userId更新员工信息:", updateStaffs.get("message"));
  244. // 更新bsUserId
  245. updatePersonBensenId(ctx, person, userId);
  246. // 更新待入职人员信息
  247. if (beisenId != null) {
  248. JSONObject updateStaffInfo = new JSONObject();
  249. JSONObject staffInfos = new JSONObject();
  250. staffInfos.put("id", beisenId);
  251. staffInfos.put("name", name);
  252. // staffInfos.put("email", email);
  253. staffInfos.put("mobilePhone", nCell);
  254. staffInfos.put("staffStatus", 1);
  255. updateStaffInfo.put("staffInfos", staffInfos);
  256. logger.error("updateStaffInfo--" + updateStaffInfo);
  257. JSONObject updateStaffRet = beisenApiClient.callApi(config.get("UPDATESTAFFURL"), updateStaffInfo);
  258. msgMap.put("更新待入职人员信息:", updateStaffRet.get("code"));
  259. }
  260. // 通过userId更新员工信息
  261. if (inServiceEnum.getValue() == 2 || inServiceEnum.getValue() == 0) {
  262. // 通过OriginalId设置员工离职
  263. String putSetdimission = config.get("PUTSETDIMISSION") + "=" + originalId;
  264. logger.error("putSetdimission--" + putSetdimission);
  265. JSONObject setdimission = beisenApiClient.callPutApi(putSetdimission, new JSONObject());
  266. msgMap.put("通过OriginalId设置员工离职:", setdimission.get("message"));
  267. // 入职管理设置离职
  268. String recruitOnBoardingPost = config.get("RECRUITONBOARDINGPOST") + "?entryId=" + result.get("guid");
  269. logger.error("recruitOnBoardingPost--" + recruitOnBoardingPost);
  270. JSONObject recruitOnBoarding = beisenApiClient.callApi(recruitOnBoardingPost, new JSONObject());
  271. msgMap.put("入职单设置离职:", recruitOnBoarding.get("message"));
  272. } else if (inServiceEnum.getValue() == 1) {
  273. // 入职管理设置已入职 需求变更无需调用该接口
  274. // 设置员工在职
  275. String putSetinduction = config.get("PUTSETINDUCTION") + "?originalId=" + originalId + "&accountEnable=true";
  276. logger.error("putSetinduction--" + putSetinduction);
  277. JSONObject setinduction = beisenApiClient.callPutApi(putSetinduction, new JSONObject());
  278. msgMap.put("设置员工在职:", setinduction.get("message"));
  279. }
  280. }
  281. jsonArray.add(msgMap);
  282. }
  283. } catch (Exception e) {
  284. e.printStackTrace();
  285. logger.error(e.getMessage());
  286. jsonArray.add(e.getMessage());
  287. // throw new RuntimeException(e);
  288. }
  289. logger.error("jsonArray--" + jsonArray);
  290. return jsonArray;
  291. }
  292. /**
  293. * 通过bsUserId修改北森用户管理的外部Id
  294. *
  295. * @param bsUserId
  296. */
  297. public void updateBeisenOriginalIdByUserId(Map map, Map config, Object bsUserId) throws IOException {
  298. String putbyuserid = config.get("PUTBYUSERID") + "?userId=" + bsUserId;
  299. JSONObject udpatePersonJson = new JSONObject();
  300. udpatePersonJson.put("originalId", "");
  301. udpatePersonJson.put("email", "");
  302. JSONObject json = beisenApiClient.callPutApi(putbyuserid, udpatePersonJson);
  303. map.put("修改北森用户管理的外部Id:", json.get("message"));
  304. }
  305. /**
  306. * @param person
  307. * @throws BOSException
  308. * @throws EASBizException
  309. */
  310. private static void updatePersonBensenId(Context ctx, PersonInfo person, String bsUserId) throws BOSException, EASBizException {
  311. // 员工
  312. IPerson iPerson = PersonFactory.getLocalInstance(ctx);
  313. person.put("bsUserId", bsUserId);
  314. SelectorItemCollection personUpdSic = new SelectorItemCollection();
  315. personUpdSic.add("bsUserId");
  316. iPerson.updatePartial(person, personUpdSic);
  317. }
  318. /**
  319. * 查询待入职人员信息 通过beisenId 入职员工ID获取入职记录guid
  320. *
  321. * @param config
  322. * @param beisenId
  323. * @return
  324. */
  325. public Map getGuid(Map<String, String> config, Object beisenId) {
  326. Map<String, String> result = null;
  327. try {
  328. result = new HashMap<>();
  329. String guid = null;
  330. JSONArray jsonArray = new JSONArray();
  331. jsonArray.add(beisenId);
  332. JSONObject staffInfos = beisenApiClient.callApi(config.get("GETSTAFFINFOS"), jsonArray);
  333. logger.error("staffInfos--" + staffInfos);
  334. if (staffInfos.getInteger("code") == 200) {
  335. JSONArray data = staffInfos.getJSONArray("data");
  336. for (int i = 0; i < data.size(); i++) {
  337. JSONObject dataJson = data.getJSONObject(i);
  338. logger.error("dataJson--" + dataJson);
  339. // entryRecord 入职记录
  340. JSONArray entryRecord = dataJson.getJSONArray("entryRecord");
  341. for (int j = 0; j < entryRecord.size(); j++) {
  342. JSONObject entry = entryRecord.getJSONObject(j);
  343. if (entry.getInteger("status") == 1 || entry.getInteger("status") == 0) {
  344. guid = entry.getString("id");
  345. result.put("guid", guid);
  346. }
  347. }
  348. // 任职记录
  349. Long dataTime = 0l;
  350. JSONArray employmentRecord = dataJson.getJSONArray("employmentRecord");
  351. for (int q = 0; q < employmentRecord.size(); q++) {
  352. JSONObject employment = employmentRecord.getJSONObject(q);
  353. String entryDate = employment.getString("entryDate");
  354. logger.debug("entryDate--" + entryDate);
  355. // 处理entryDate为空的数据必须要保存一条数据,如果不为空则保存最新的一条数据
  356. result.put("userID", employment.getString("userID"));
  357. if (!StringUtils.isEmpty(entryDate) && DateTimeUtils.parseDate(entryDate).getTime() > dataTime) {
  358. result.put("userID", employment.getString("userID"));
  359. }
  360. }
  361. }
  362. }
  363. } catch (Exception e) {
  364. e.printStackTrace();
  365. return null;
  366. }
  367. return result;
  368. }
  369. /**
  370. * 获取指定日期前 x 天的日期的方法。
  371. *
  372. * @param specifiedDay 指定日期
  373. * @param x 天数
  374. * @return 指定日期前 x 天的日期
  375. */
  376. public Date getDayBefore(Date specifiedDay, int x) {
  377. // 获取 Calendar 实例
  378. Calendar c = Calendar.getInstance();
  379. // 设置 Calendar 的时间为指定日期
  380. c.setTime(specifiedDay);
  381. // 将日期向前移动 x 天
  382. c.add(Calendar.DATE, -x);
  383. // 返回移动后的日期
  384. return c.getTime();
  385. }
  386. /**
  387. * 获取所有人的直接上级
  388. *
  389. * @return
  390. */
  391. public Map getPersonParent(Context ctx) throws BOSException, SQLException {
  392. Map personParentMap = new HashMap();
  393. StringBuffer sb = new StringBuffer();
  394. sb.append("select person.fid as personId , personParent.fid as personParentId\n").append("\n");
  395. sb.append("from T_ORG_PositionMember positioonMenber\n").append("\n");
  396. sb.append("left join T_ORG_Position position on position.fid = positioonMenber.FPositionID\n").append("\n");
  397. sb.append("left join T_ORG_Position positionParent on position.fid = positionParent.FPARENTID\n").append("\n");
  398. sb.append("left join T_HR_EmpOrgRelation empOrgRelation on empOrgRelation.FPOSITIONID = positionParent.fid\n").append("\n");
  399. sb.append("left join t_Bd_person person on person.fid = empOrgRelation.FPERSONID and empOrgRelation.FIsSystem='1'\n").append("\n");
  400. sb.append("left join t_Bd_person personParent on personParent.fid = positioonMenber.FPERSONID").append("\n");
  401. IRowSet iRowSet = DbUtil.executeQuery(ctx, sb.toString());
  402. while (iRowSet.next()) {
  403. personParentMap.put(iRowSet.getString("personId"), iRowSet.getString("personParentId"));
  404. }
  405. return personParentMap;
  406. }
  407. /**
  408. * 查询字段
  409. *
  410. * @return
  411. */
  412. public SelectorItemCollection getSelectorItemCollection() {
  413. SelectorItemCollection sic = new SelectorItemCollection();
  414. sic.add("*");
  415. sic.add("person.number");
  416. sic.add("person.name");
  417. sic.add("person.beisenId");
  418. sic.add("person.bsUserId");
  419. sic.add("person.id");
  420. sic.add("person.hireDate");
  421. sic.add("person.nCell");
  422. sic.add("person.gender");
  423. sic.add("person.email");
  424. sic.add("person.employeeType.name");
  425. sic.add("person.employeeType.number");
  426. sic.add("person.employeeType.inService");
  427. sic.add("personDep.name");
  428. sic.add("personDep.number");
  429. sic.add("personDep.id");
  430. sic.add("personDep.parent.id");
  431. sic.add("primaryPosition.name");
  432. sic.add("primaryPosition.number");
  433. return sic;
  434. }
  435. }