Pārlūkot izejas kodu

feat(hr): 实现新入职与在职人员初定导入插件- 新增 ScoreInitialImportPlugin 插件类,支持初定导入模板筛选
-优化 BaseInitialOperationPlugIn,修复数据重复与字段映射问题- 改进 NewHireInitialOperationPlugIn,增强重复人员校验逻辑
- 调整 ServingInitialOperationPlugIn,统一处理在职人员初定流程
- 增加职位序列转换逻辑,确保管理序列按职能序列初定
-修复职级计算中职位序列引用错误的问题

wyc 1 mēnesi atpakaļ
vecāks
revīzija
570ab4414c

+ 76 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/initial/impt/ScoreInitialImportPlugin.java

@@ -0,0 +1,76 @@
+package nckd.jxccl.hr.psms.plugin.form.initial.impt;
+
+import com.google.common.collect.Lists;
+import kd.bos.dataentity.OperateOption;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.hr.hbp.formplugin.web.HRDataBaseList;
+import kd.hr.impt.common.dto.ImportBillData;
+import kd.hr.impt.common.dto.ImptPluginContext;
+import kd.hr.impt.common.plugin.AfterLoadStartPageEventArgs;
+import kd.hr.impt.common.plugin.BeforeCallOperationEventArgs;
+import kd.hr.impt.common.plugin.BeforeShowTemplateSelectListEventArgs;
+import kd.hr.impt.common.plugin.HRImportPlugin;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.hr.psms.common.PositionStructureConstant;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+* 新入职人员初定/在职人员初定导入插件
+* 实体标识:gradedpersonquery
+* @author W.Y.C
+* @date 2025/10/31 14:04
+* @version 1.0
+*/
+public class ScoreInitialImportPlugin extends HRDataBaseList implements HRImportPlugin {
+
+    private static String SETTINGJOBGRADE_TPL = "settingjobgradetpl";
+    private static String SETTINGJOBGRADENEW_TPL = "settingjobgradenewtpl";
+    public ScoreInitialImportPlugin() {
+    }
+
+    //kd.hrmp.hbpm.formplugin.web.impt.PositionReviseHRImportPlugin,校验例子
+    //kd.hr.haos.formplugin.web.impo.OrgBatchHRImportPlugin,校验例子
+
+
+    @Override
+    public void afterLoadStartPage(AfterLoadStartPageEventArgs args) {
+        // 启用串行模式:先校验所有数据,再统一入库
+        // 开启之后如有校验失败,前端会提示:数据校验失败
+        args.setSerialModel(true);
+    }
+
+    @Override
+    public void beforeShowTemplateSelectList(BeforeShowTemplateSelectListEventArgs args) {
+        List<QFilter> fileter = args.getqFilterList();
+        if(fileter == null){
+            fileter = Lists.newArrayList();
+        }
+        //模板列表只显示:新入职人员初定/在职人员初定导入模板
+        fileter.add(new QFilter(FormConstant.NUMBER_KEY, QCP.in, new String[]{SETTINGJOBGRADE_TPL,SETTINGJOBGRADENEW_TPL}));
+        args.setqFilterList(fileter);
+    }
+
+    @Override
+    public void beforeCallOperation(BeforeCallOperationEventArgs args) {
+        String mainEntityId = ((ImportBillData)args.getImportBillDatas().get(0)).getMainEntityId();
+        OperateOption operateOption = (OperateOption)args.getOperateOptions().get(mainEntityId);
+        Map<String, String> submitOPs = args.getSubmitOPs();
+        String targetKey = PositionStructureConstant.NCKD_PERSONPOSFILE.toLowerCase();
+        //删除默认save方法
+        submitOPs.entrySet().removeIf(entry -> entry.getKey().toLowerCase().equals(targetKey));
+
+        ImptPluginContext context = args.getContext();
+        String tplNumber = context.getTplNumber();
+
+        if(tplNumber.equalsIgnoreCase(SETTINGJOBGRADE_TPL)){
+            //调用在职人员初定OP
+            submitOPs.put(PositionStructureConstant.NCKD_PERSONPOSFILE.toLowerCase(),"servinginitial");
+        }else if(tplNumber.equalsIgnoreCase(SETTINGJOBGRADENEW_TPL)){
+            //调用新入职人员初定OP
+            submitOPs.put(PositionStructureConstant.NCKD_PERSONPOSFILE.toLowerCase(),"newhireinitial");
+        }
+    }
+}

+ 8 - 8
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/initial/BaseInitialOperationPlugIn.java

@@ -1,5 +1,6 @@
 package nckd.jxccl.hr.psms.plugin.operate.initial;
 
+import com.google.common.collect.Lists;
 import kd.bos.common.enums.EnableEnum;
 import kd.bos.context.RequestContext;
 import kd.bos.dataentity.entity.DynamicObject;
@@ -43,7 +44,7 @@ public abstract class BaseInitialOperationPlugIn extends AbstractOperationServic
     
     protected final static Log logger = LogFactory.getLog(BaseInitialOperationPlugIn.class);
 
-    public List<BaseInitialData> baseInitialData;
+    public List<BaseInitialData> baseInitialData = Lists.newArrayList();
 
     /**
      * 基本信息数据对象
@@ -71,6 +72,8 @@ public abstract class BaseInitialOperationPlugIn extends AbstractOperationServic
         DynamicObject dep;
         /** 职位序列 */
         DynamicObject jobSeq;
+        /** 职位序列(转换后) */
+        DynamicObject convertJobSeq;
         /** 职位序列-编码 */
         String jobSeqNumber;
         /** 职位序列-名称 */
@@ -116,9 +119,6 @@ public abstract class BaseInitialOperationPlugIn extends AbstractOperationServic
      * @date: 2025/10/12 14:20
      */
     protected List<BaseInitialData> extractBasicInfo(DynamicObject initialData) {
-        if(baseInitialData != null){
-            return baseInitialData;
-        }
         List<BaseInitialData> dataList = new ArrayList<>();
         if(initialData.containsProperty(FormConstant.NCKD_ENTRYENTITY)){
             DynamicObjectCollection dynamicObjectCollection = initialData.getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
@@ -126,14 +126,14 @@ public abstract class BaseInitialOperationPlugIn extends AbstractOperationServic
                 //批量初定
                 BaseInitialData data = getBaseInitialData(dynamicObject);
                 dataList.add(data);
+                baseInitialData.add(data);
             }
         }else{
             BaseInitialData data = getBaseInitialData(initialData);
             dataList.add(data);
+            baseInitialData.add(data);
         }
-
-        baseInitialData = dataList;
-        return baseInitialData;
+        return dataList;
     }
 
     @NotNull
@@ -366,7 +366,7 @@ public abstract class BaseInitialOperationPlugIn extends AbstractOperationServic
         personPosFile.set(PositionStructureConstant.NCKD_FIRSTRANK, EnableEnum.YES.getCode());
         personPosFile.set(PositionStructureConstant.NCKD_BEGINDATE, data.beginDate);
         personPosFile.set(PositionStructureConstant.NCKD_APPRAISALRESULT, data.lastYearAppraisalResult);
-        personPosFile.set(PositionStructureConstant.NCKD_JOBSEQHR, data.jobSeq);
+        personPosFile.set(PositionStructureConstant.NCKD_JOBSEQHR, data.convertJobSeq);
         personPosFile.set(PositionStructureConstant.NCKD_POSITIONHR, data.positionHr);
         /*personPosFile.set(PositionStructureConstant.USEORG_KEY, data.company);
         personPosFile.set(PositionStructureConstant.CREATEORG_KEY, data.dep);

+ 25 - 14
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/initial/NewHireInitialOperationPlugIn.java

@@ -8,6 +8,7 @@ import kd.bos.entity.plugin.args.EndOperationTransactionArgs;
 import kd.bos.entity.plugin.args.RollbackOperationArgs;
 import kd.bos.entity.validate.AbstractValidator;
 import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.exception.ValidationException;
 import nckd.jxccl.base.common.utils.DateUtil;
 import nckd.jxccl.base.common.utils.StrFormatter;
 import nckd.jxccl.hr.psms.business.JobLevelCalculatorService;
@@ -15,9 +16,12 @@ import nckd.jxccl.hr.psms.helper.PositionFileHelper;
 
 import java.math.BigDecimal;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
+import java.util.StringJoiner;
 
 /**
  * 新入职人员初定-确认定级操作OP
@@ -38,26 +42,35 @@ public class NewHireInitialOperationPlugIn extends BaseInitialOperationPlugIn {
                     return;
                 }
                 Date currentDate = new Date();
+                Set<Long> personIds = new HashSet<>();
+                Map<Long,Integer> personDataEntityMap = new HashMap<>();
                 for (ExtendedDataEntity rowDataEntity : getDataEntities()) {
                     DynamicObject data = rowDataEntity.getDataEntity();
                     //提取信息
                     List<BaseInitialData> newHireInitialDataList =  extractBasicInfo(data);
 
+                    int dataEntityIndex = rowDataEntity.getDataEntityIndex();
                     // 检查人员ID重复
-                    Set<Long> personIds = new HashSet<>();
                     for (BaseInitialData newHireInitialData : newHireInitialDataList) {
                         if (newHireInitialData.person != null) {
                             Long personId = newHireInitialData.person.getLong(FormConstant.ID_KEY);
                             if (!personIds.add(personId)) {
+                                Integer i = personDataEntityMap.get(personId);
+                                if(i != null){
+                                    //将上一个重复人员也标记为错误
+                                    addFatalErrorMessage(getDataEntities()[i],
+                                            StrFormatter.format("人员【{}】在列表中重复,请保留一条信息",
+                                                    newHireInitialData.person.getString(FormConstant.NAME_KEY)));
+                                }
                                 addFatalErrorMessage(rowDataEntity,
                                         StrFormatter.format("人员【{}】在列表中重复,请保留一条信息",
                                                 newHireInitialData.person.getString(FormConstant.NAME_KEY)));
                             }
+                            personDataEntityMap.put(personId,dataEntityIndex);
                         }
                     }
-                    if(!this.getValidateResult().isSuccess()){
-                        return;
-                    }
+
+
 
                     for (BaseInitialData newHireInitialData : newHireInitialDataList) {
                         Date beginDate = newHireInitialData.beginDate;
@@ -106,9 +119,7 @@ public class NewHireInitialOperationPlugIn extends BaseInitialOperationPlugIn {
         if(this.getOperationResult().isSuccess()) {
             //对应SHR:com.kingdee.shr.customer.web.handler.ContributeScore.PersonpositionfileListHandler#addNewPersonpositionfileInfo
             logger.info("【职位体系】-新入职人员初定-开始");
-            for (DynamicObject servingInitial : e.getDataEntities()) {
-                processNewHireInitialData(servingInitial);
-            }
+            processNewHireInitialData();
         }
     }
 
@@ -124,13 +135,10 @@ public class NewHireInitialOperationPlugIn extends BaseInitialOperationPlugIn {
 
     /**
      * 处理单个在职人员初定
-     * @param newHireInitial 新入职人员初定数据对象
      */
-    private void processNewHireInitialData(DynamicObject newHireInitial) {
+    private void processNewHireInitialData() {
 
-        //提取信息
-        List<BaseInitialData> dataList =  extractBasicInfo(newHireInitial);
-        for (BaseInitialData data : dataList) {
+        for (BaseInitialData data : baseInitialData) {
 
             String logPrefix = StrFormatter.format("【职位体系】-新入职人员初定-人员【{}({})】",
                     data.person.getString(FormConstant.NAME_KEY),
@@ -159,13 +167,16 @@ public class NewHireInitialOperationPlugIn extends BaseInitialOperationPlugIn {
             // 计算职级
             //当考核结果为无时,职级定为最低级
             boolean useMinLevel = data.lastYearAppraisalResultEnum == nckd.jxccl.base.common.enums.AppraisalResultEnum.NONE;
+            // 如果是管理序列,则按职能序列进行初定
+            data.convertJobSeq = JobLevelCalculatorService.handleJobSeq(data.jobSeq);
             //【三期需求】-不满足三要素(聘任职称/技能、考核结果、积分)按"无职级"初定
             String perProTitleNumber = scoreData.dbProTitleLevel != null ? scoreData.dbProTitleLevel.getString(FormConstant.NUMBER_KEY) : null;
             String quaLevelNumber = scoreData.dbOcpQualLevel != null ? scoreData.dbOcpQualLevel.getString(FormConstant.NUMBER_KEY) : null;
-            boolean threeElementMeet = JobLevelCalculatorService.checkThreeElementsRequirement(data.jobSeq, allSumScore, scoreData.dbProTitleLevel,
+            boolean threeElementMeet = JobLevelCalculatorService.checkThreeElementsRequirement(data.convertJobSeq, allSumScore, scoreData.dbProTitleLevel,
                     scoreData.dbOcpQualLevel, data.lastYearAppraisalResultEnum);
+
             DynamicObject jobLeve = JobLevelCalculatorService.getJobLevel(
-                    data.jobSeq, allSumScore, perProTitleNumber,
+                    data.convertJobSeq, allSumScore, perProTitleNumber,
                     quaLevelNumber,data.downgradeNum,useMinLevel,!threeElementMeet);
             if(jobLeve != null) {
                 // 构建职位档案并存入数据库

+ 23 - 14
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/initial/ServingInitialOperationPlugIn.java

@@ -18,8 +18,10 @@ import nckd.jxccl.hr.psms.helper.PositionFileHelper;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -40,26 +42,33 @@ public class ServingInitialOperationPlugIn extends BaseInitialOperationPlugIn {
                     return;
                 }
                 Date currentDate = new Date();
+
+                Set<Long> personIds = new HashSet<>();
+                Map<Long,Integer> personDataEntityMap = new HashMap<>();
                 for (ExtendedDataEntity rowDataEntity : getDataEntities()) {
                     DynamicObject data = rowDataEntity.getDataEntity();
                     //提取信息
                     List<BaseInitialData> servingInitialDataList = extractBasicInfo(data);
-
+                    int dataEntityIndex = rowDataEntity.getDataEntityIndex();
                     // 检查人员ID重复
-                    Set<Long> personIds = new HashSet<>();
                     for (BaseInitialData servingInitialData : servingInitialDataList) {
                         if (servingInitialData.person != null) {
                             Long personId = servingInitialData.person.getLong(FormConstant.ID_KEY);
                             if (!personIds.add(personId)) {
+                                Integer i = personDataEntityMap.get(personId);
+                                if(i != null){
+                                    //将上一个重复人员也标记为错误
+                                    addFatalErrorMessage(getDataEntities()[i],
+                                            StrFormatter.format("人员【{}】在列表中重复,请保留一条信息",
+                                                    servingInitialData.person.getString(FormConstant.NAME_KEY)));
+                                }
                                 addFatalErrorMessage(rowDataEntity,
                                         StrFormatter.format("人员【{}】在列表中重复,请保留一条信息",
                                                 servingInitialData.person.getString(FormConstant.NAME_KEY)));
-                                return;
                             }
+                            personDataEntityMap.put(personId,dataEntityIndex);
                         }
-                    }
-                    if(!this.getValidateResult().isSuccess()){
-                        return;
+
                     }
 
                     for (BaseInitialData servingInitialData : servingInitialDataList) {
@@ -117,9 +126,8 @@ public class ServingInitialOperationPlugIn extends BaseInitialOperationPlugIn {
         if(this.getOperationResult().isSuccess()) {
             //对应SHR:com.kingdee.shr.customer.web.handler.ContributeScore.PersonpositionfileListHandler#addNewPersonpositionfileInfo_older
             logger.info("【职位体系】-在职人员初定-开始");
-            for (DynamicObject servingInitial : e.getDataEntities()) {
-                processServingInitial(servingInitial);
-            }
+            processServingInitial();
+
         }
     }
 
@@ -135,12 +143,10 @@ public class ServingInitialOperationPlugIn extends BaseInitialOperationPlugIn {
 
     /**
      * 处理单个在职人员初定
-     * @param servingInitial 在职人员初定数据对象
      */
-    private void processServingInitial(DynamicObject servingInitial) {
+    private void processServingInitial() {
         // 提取基本信息
-        List<BaseInitialData> dataList = extractBasicInfo(servingInitial);
-        for (BaseInitialData data : dataList) {
+        for (BaseInitialData data : baseInitialData) {
             String logPrefix = StrFormatter.format("【职位体系】-在职人员初定-人员【{}({})】",
                     data.person.getString(FormConstant.NAME_KEY),
                     data.person.getString(FormConstant.EMP_NUMBER_KEY));
@@ -160,13 +166,16 @@ public class ServingInitialOperationPlugIn extends BaseInitialOperationPlugIn {
             // 计算累计积分池(生涯积分)
             BigDecimal sumScore = calculateSumScore(data.allSumScore, scoreData, logPrefix);
 
+            // 如果是管理序列,则按职能序列进行初定
+            data.convertJobSeq = JobLevelCalculatorService.handleJobSeq(data.jobSeq);
+
             // 计算职级
             //当考核结果为无时,职级定为最低级
             boolean useMinLevel = data.lastYearAppraisalResultEnum == nckd.jxccl.base.common.enums.AppraisalResultEnum.NONE;
             String perProTitleNumber = scoreData.dbProTitleLevel != null ? scoreData.dbProTitleLevel.getString(FormConstant.NUMBER_KEY) : null;
             String quaLevelNumber = scoreData.dbOcpQualLevel != null ? scoreData.dbOcpQualLevel.getString(FormConstant.NUMBER_KEY) : null;
             DynamicObject jobLeve = JobLevelCalculatorService.getJobLevel(
-                    data.jobSeq, data.allSumScore, perProTitleNumber,
+                    data.convertJobSeq, data.allSumScore, perProTitleNumber,
                     quaLevelNumber,  data.downgradeNum,useMinLevel,Boolean.FALSE);
 
             if(jobLeve != null) {