OfferListHandlerEx.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. package com.kingdee.shr.recuritment.web.handler;
  2. import com.kingdee.bos.BOSException;
  3. import com.kingdee.bos.Context;
  4. import com.kingdee.bos.ctrl.reportone.r1.form.engine.x.util.StringUtil;
  5. import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
  6. import com.kingdee.bos.metadata.entity.*;
  7. import com.kingdee.bos.metadata.query.util.CompareType;
  8. import com.kingdee.eas.common.EASBizException;
  9. import com.kingdee.eas.custom.recuritment.task.BeisenTransferPhaseFacadeFactory;
  10. import com.kingdee.eas.custom.recuritment.task.IBeisenTransferPhaseFacade;
  11. import com.kingdee.shr.base.syssetting.api.bean.BatchMessageTipsBody;
  12. import com.kingdee.shr.base.syssetting.api.bean.BatchMessageTipsHeader;
  13. import com.kingdee.shr.base.syssetting.context.SHRContext;
  14. import com.kingdee.shr.base.syssetting.exception.SHRWebException;
  15. import com.kingdee.shr.base.syssetting.exception.ShrWebBizException;
  16. import com.kingdee.shr.recuritment.*;
  17. import com.kingdee.shr.recuritment.service.offer.SyncResumeToPreServiceEx;
  18. import com.kingdee.util.StringUtils;
  19. import org.apache.log4j.Logger;
  20. import org.springframework.ui.ModelMap;
  21. import javax.servlet.http.HttpServletRequest;
  22. import javax.servlet.http.HttpServletResponse;
  23. import java.util.HashMap;
  24. import java.util.Map;
  25. /**
  26. * @Description offer列表
  27. * @Date 2025/7/8 19:42
  28. * @Created by Heyuan
  29. */
  30. public class OfferListHandlerEx extends OfferListHandler {
  31. private static final Logger logger = Logger.getLogger(OfferListHandlerEx.class);
  32. private Context ctx = SHRContext.getInstance().getContext();
  33. /**
  34. * 终止入职
  35. *
  36. * @param request
  37. * @param response
  38. * @param modelMap
  39. * @throws SHRWebException
  40. */
  41. public void executeSyncBeisenAction(
  42. HttpServletRequest request,
  43. HttpServletResponse response,
  44. ModelMap modelMap
  45. ) throws SHRWebException {
  46. String billIds = this.getBillId(request);
  47. if (org.apache.commons.lang3.StringUtils.isEmpty(billIds)) {
  48. throw new ShrWebBizException("单据id不能为空!");
  49. } else if (billIds.split(",").length > 1) {
  50. throw new ShrWebBizException("只能选中单行!");
  51. }
  52. try {
  53. if (!StringUtils.isEmpty(billIds)) {
  54. //同步录用报批状态至北森
  55. IBeisenTransferPhaseFacade iBeisenTransferPhaseFacade =
  56. BeisenTransferPhaseFacadeFactory.getLocalInstance(ctx);
  57. iBeisenTransferPhaseFacade.syncOfferToBeisen(billIds, 0);
  58. }
  59. } catch (Exception e) {
  60. e.printStackTrace();
  61. throw new ShrWebBizException(e);
  62. }
  63. }
  64. /**
  65. * 终止入职
  66. *
  67. * @param request
  68. * @param response
  69. * @param modelMap
  70. * @throws SHRWebException
  71. */
  72. @Override
  73. public void stopOfferAction(
  74. HttpServletRequest request,
  75. HttpServletResponse response,
  76. ModelMap modelMap
  77. ) throws SHRWebException {
  78. super.stopOfferAction(request, response, modelMap);
  79. String billIds = request.getParameter("billId");
  80. try {
  81. if (!StringUtils.isEmpty(billIds)) {
  82. //同步录用报批状态至北森
  83. IBeisenTransferPhaseFacade iBeisenTransferPhaseFacade =
  84. BeisenTransferPhaseFacadeFactory.getLocalInstance(ctx);
  85. iBeisenTransferPhaseFacade.syncOfferToBeisen(billIds, 0);
  86. }
  87. } catch (Exception e) {
  88. e.printStackTrace();
  89. throw new ShrWebBizException(e);
  90. }
  91. }
  92. /**
  93. * 将指定的录用单据转为标准预备入职状态。
  94. * <p>
  95. * 该方法会根据传入的 billId 参数,批量处理多个录用单据。对每个单据执行以下操作:
  96. * 1. 验证单据是否满足转预备入职条件;
  97. * 2. 若验证通过且未放弃入职,则调用服务将简历同步至标准预备入职;
  98. * 3. 记录每条数据的处理结果(成功或失败);
  99. * 4. 最后尝试将录用状态同步到北森系统。
  100. * </p>
  101. *
  102. * @param request HTTP 请求对象,用于获取请求参数(如 billId)
  103. * @param response HTTP 响应对象,用于输出响应内容
  104. * @param modelMap Spring MVC 的模型映射对象,可用于传递数据到视图层(本方法未使用)
  105. * @throws SHRWebException 当业务处理过程中发生异常时抛出
  106. */
  107. @Override
  108. public void toPrePersonAction(
  109. HttpServletRequest request,
  110. HttpServletResponse response,
  111. ModelMap modelMap
  112. ) throws SHRWebException {
  113. // 获取请求中的 billId 参数
  114. String billIds = request.getParameter("billId");
  115. Context ctx = getContext();
  116. IOffer iOffer;
  117. try {
  118. // 获取 Offer 服务实例
  119. iOffer = OfferFactory.getLocalInstance(ctx);
  120. } catch (BOSException e) {
  121. logger.error(e.getMessage(), e);
  122. throw new SHRWebException("系统错误,请联系管理员");
  123. }
  124. int success = 0;
  125. int failure = 0;
  126. BatchMessageTipsHeader batchMessageTipsHeader = new BatchMessageTipsHeader();
  127. // 如果 billIds 不为空,则按逗号分割并逐个处理
  128. if (org.apache.commons.lang3.StringUtils.isNotEmpty(billIds)) {
  129. String[] ids = billIds.split(",");
  130. for (int i = 0; i < ids.length; ++i) {
  131. BatchMessageTipsBody body = new BatchMessageTipsBody();
  132. body.setId(ids[i]);
  133. Map<String, Object> map = new HashMap();
  134. try {
  135. // 执行校验逻辑
  136. this.checkPass(ids[i], map);
  137. String error = (String) map.get("errorMsg");
  138. // 如果没有错误信息,则继续处理
  139. if (org.apache.commons.lang3.StringUtils.isEmpty(error)) {
  140. // 查询 Offer 信息
  141. OfferInfo offer = iOffer.getOfferInfo("select resumeBaseRec,preEntry.*,preEntry.talent.*,preEntryDate where id = '" + ids[i] + "' ");
  142. // 如果该 Offer 没有被放弃入职
  143. if (!offer.isGiveUpEntry()) {
  144. SyncResumeToPreServiceEx syncResumeToPreServiceEx = new SyncResumeToPreServiceEx();
  145. // 添加标准预备入职记录
  146. syncResumeToPreServiceEx.addNewPreEntryByResume(ctx, offer, false);
  147. }
  148. ++success;
  149. body.setMuitTipsState(Boolean.TRUE);
  150. body.setMuitTipsMessage("操作成功!");
  151. batchMessageTipsHeader.addResult(body);
  152. } else {
  153. // 校验失败,记录失败原因
  154. ++failure;
  155. body.setMuitTipsState(Boolean.FALSE);
  156. body.setMuitTipsMessage(error);
  157. batchMessageTipsHeader.addResult(body);
  158. }
  159. } catch (EASBizException e) {
  160. logger.error(e.getMessage(), e);
  161. ++failure;
  162. body.setMuitTipsState(Boolean.FALSE);
  163. body.setMuitTipsMessage("预入职失败!" + e.getMessage());
  164. batchMessageTipsHeader.addResult(body);
  165. } catch (BOSException e) {
  166. logger.error(e.getMessage(), e);
  167. ++failure;
  168. body.setMuitTipsState(Boolean.FALSE);
  169. body.setMuitTipsMessage("预入职失败!" + e.getMessage());
  170. batchMessageTipsHeader.addResult(body);
  171. } catch (SHRWebException e) {
  172. logger.error(e.getMessage(), e);
  173. ++failure;
  174. body.setMuitTipsState(Boolean.FALSE);
  175. body.setMuitTipsMessage("预入职失败!" + e.getMessage());
  176. batchMessageTipsHeader.addResult(body);
  177. }
  178. }
  179. }
  180. // 设置批量处理结果统计信息
  181. batchMessageTipsHeader.setBillId(billIds);
  182. batchMessageTipsHeader.setFailureCount(failure);
  183. batchMessageTipsHeader.setSuccessCount(success);
  184. // 输出处理结果
  185. this.writeSuccessData(batchMessageTipsHeader);
  186. // 同步录用报批状态至北森系统
  187. try {
  188. if (!StringUtils.isEmpty(billIds)) {
  189. IBeisenTransferPhaseFacade iBeisenTransferPhaseFacade =
  190. BeisenTransferPhaseFacadeFactory.getLocalInstance(ctx);
  191. iBeisenTransferPhaseFacade.syncOfferToBeisen(billIds, 0);
  192. }
  193. } catch (Exception e) {
  194. e.printStackTrace();
  195. throw new ShrWebBizException(e);
  196. }
  197. }
  198. /**
  199. * 检查候选人是否可以进入下一步流程(如简历投递等),主要判断该候选人是否正在被其他职位流程占用。
  200. * 如果候选人当前处于“简历筛选”或其他招聘环节,则不允许重复使用,并提示相关信息。
  201. *
  202. * @param billId 候选人简历的唯一标识ID
  203. * @param map 用于返回错误信息的Map对象,若检查不通过会填充state和errorMsg字段
  204. * @return true表示可以通过,false表示已被占用或存在冲突
  205. * @throws SHRWebException 当业务逻辑异常或系统异常时抛出
  206. */
  207. private boolean checkPass(String billId, Map<String, Object> map) throws SHRWebException {
  208. StringBuffer msgBuffer = new StringBuffer("");
  209. try {
  210. // 获取当前简历在途的应聘记录集合
  211. ResumeBaseRecCollection resumeColl = this.getOnWayResume(billId);
  212. if (resumeColl != null && resumeColl.size() > 0) {
  213. ResumeBaseRecInfo resumeBaseRec = resumeColl.get(0);
  214. // 判断当前简历所处的状态是否为“简历筛选”
  215. if ("简历筛选".equals(resumeBaseRec.getResumeState().getResumeStateType().getName())) {
  216. msgBuffer.append("当前候选人已被:");
  217. String positionName = "";
  218. // 获取职位名称(优先取recuritPosition,其次hrJob)
  219. if (resumeBaseRec.getRecuritPosition() != null) {
  220. positionName = resumeBaseRec.getRecuritPosition().getName();
  221. } else if (resumeBaseRec.getHrJob() != null) {
  222. positionName = resumeBaseRec.getHrJob().getName();
  223. }
  224. msgBuffer.append(positionName);
  225. msgBuffer.append("职位(");
  226. msgBuffer.append(resumeBaseRec.getDepartment().getName());
  227. msgBuffer.append("部门)");
  228. msgBuffer.append("的简历筛选环节所抢,可联系操作人");
  229. // 添加操作人信息
  230. if (resumeBaseRec.getProposer() != null) {
  231. msgBuffer.append(resumeBaseRec.getProposer().getName() + "解锁!");
  232. } else {
  233. msgBuffer.append("解锁!");
  234. }
  235. } else {
  236. // 当前简历处于其他招聘环节
  237. msgBuffer.append("当前候选人正在:");
  238. String positionName = "";
  239. // 获取职位名称(优先取recuritPosition,其次hrJob)
  240. if (resumeBaseRec.getRecuritPosition() != null) {
  241. positionName = resumeBaseRec.getRecuritPosition().getName();
  242. } else if (resumeBaseRec.getHrJob() != null) {
  243. positionName = resumeBaseRec.getHrJob().getName();
  244. }
  245. msgBuffer.append(positionName);
  246. msgBuffer.append("职位(");
  247. msgBuffer.append(resumeBaseRec.getDepartment().getName());
  248. msgBuffer.append("部门)的");
  249. msgBuffer.append(resumeBaseRec.getResumeState().getResumeStateType().getName());
  250. msgBuffer.append("环节应聘!当在该职位上应聘不通过,才可释放使用!");
  251. // 查询最近处理人信息
  252. ApplyRecordCollection applyRecordCollection = ApplyRecordFactory.getRemoteInstance().getApplyRecordCollection("select creator.name where resumeBaseRec ='" + resumeBaseRec.getId() + "' order by createTime desc");
  253. if (null != applyRecordCollection && applyRecordCollection.size() > 0) {
  254. msgBuffer.append("可联系简历当前或者上一处理人:”" + applyRecordCollection.get(0).getCreator().getName() + "“释放");
  255. }
  256. }
  257. // 将错误信息放入map中返回
  258. map.put("state", "error");
  259. map.put("errorMsg", msgBuffer.toString());
  260. return false;
  261. } else {
  262. // 无在途应聘记录,允许继续操作
  263. return true;
  264. }
  265. } catch (EASBizException e) {
  266. logger.error(e.getMessage(), e);
  267. throw new ShrWebBizException(e.getMessage(), e);
  268. } catch (BOSException e) {
  269. logger.error(e.getMessage(), e);
  270. throw new ShrWebBizException(e.getMessage(), e);
  271. }
  272. }
  273. /**
  274. * 获取在途简历信息
  275. *
  276. * @param offerId 申请单ID
  277. * @return 简历基础信息集合
  278. * @throws BOSException 业务对象服务异常
  279. * @throws EASBizException EAS业务异常
  280. */
  281. private ResumeBaseRecCollection getOnWayResume(String offerId) throws BOSException, EASBizException {
  282. ResumeBaseRecCollection resumeColl = null;
  283. SelectorItemCollection sel = new SelectorItemCollection();
  284. sel.add(new SelectorItemInfo("*"));
  285. sel.add(new SelectorItemInfo("resumeBaseRec.*"));
  286. // 根据offerId获取申请单信息
  287. OfferInfo offer = OfferFactory.getRemoteInstance().getOfferInfo(new ObjectUuidPK(offerId), sel);
  288. String ifSimplePerson = offer.getResumeBaseRec().getIfSimplePerson();
  289. if (!StringUtil.isEmpty(ifSimplePerson)) {
  290. // 构造查询条件:相同简单人员标识、已处理状态、排除当前记录
  291. EntityViewInfo evi = new EntityViewInfo();
  292. FilterInfo filter = new FilterInfo();
  293. filter.getFilterItems().add(new FilterItemInfo("ifSimplePerson", ifSimplePerson, CompareType.EQUALS));
  294. filter.getFilterItems().add(new FilterItemInfo("TransactionState", TransactionStateEnum.PROCESSED.getValue(), CompareType.EQUALS));
  295. filter.getFilterItems().add(new FilterItemInfo("id", offer.getResumeBaseRec().getId().toString(), CompareType.NOTEQUALS));
  296. // 设置需要查询的字段
  297. SelectorItemCollection sic = evi.getSelector();
  298. sic.add(new SelectorItemInfo("department.name"));
  299. sic.add(new SelectorItemInfo("recuritPosition.name"));
  300. sic.add(new SelectorItemInfo("hrJob.name"));
  301. sic.add(new SelectorItemInfo("resumeState.resumeStateType.name"));
  302. sic.add(new SelectorItemInfo("proposer.name"));
  303. evi.setFilter(filter);
  304. evi.setSelector(sic);
  305. // 执行查询获取在途简历集合
  306. IResumeBaseRec iResumeBaseRec = ResumeBaseRecFactory.getRemoteInstance();
  307. resumeColl = iResumeBaseRec.getResumeBaseRecCollection(evi);
  308. }
  309. return resumeColl;
  310. }
  311. /**
  312. * 反终止
  313. *
  314. * @param request
  315. * @param response
  316. * @param modelMap
  317. * @throws SHRWebException
  318. */
  319. @Override
  320. public void noStopOfferAction(
  321. HttpServletRequest request,
  322. HttpServletResponse response,
  323. ModelMap modelMap
  324. ) throws SHRWebException {
  325. super.noStopOfferAction(request, response, modelMap);
  326. String billIds = request.getParameter("billId");
  327. try {
  328. if (!StringUtils.isEmpty(billIds)) {
  329. //同步录用报批状态至北森
  330. IBeisenTransferPhaseFacade iBeisenTransferPhaseFacade =
  331. BeisenTransferPhaseFacadeFactory.getLocalInstance(ctx);
  332. iBeisenTransferPhaseFacade.syncOfferToBeisen(billIds, 0);
  333. }
  334. } catch (Exception e) {
  335. e.printStackTrace();
  336. throw new ShrWebBizException(e);
  337. }
  338. }
  339. /**
  340. * 放弃入职
  341. *
  342. * @param request
  343. * @param response
  344. * @param modelMap
  345. * @throws SHRWebException
  346. */
  347. @Override
  348. public void abondonEntryAction(
  349. HttpServletRequest request,
  350. HttpServletResponse response,
  351. ModelMap modelMap
  352. ) throws SHRWebException {
  353. super.abondonEntryAction(request, response, modelMap);
  354. String billIds = request.getParameter("billId");
  355. try {
  356. if (!StringUtils.isEmpty(billIds)) {
  357. //同步录用报批状态至北森
  358. IBeisenTransferPhaseFacade iBeisenTransferPhaseFacade =
  359. BeisenTransferPhaseFacadeFactory.getLocalInstance(ctx);
  360. iBeisenTransferPhaseFacade.syncOfferToBeisen(billIds, 0);
  361. }
  362. } catch (Exception e) {
  363. e.printStackTrace();
  364. throw new ShrWebBizException(e);
  365. }
  366. }
  367. }