Переглянути джерело

Merge branch 'refs/heads/feat-opmc-pm_1.0'

wyc 1 тиждень тому
батько
коміт
c68e960f30
17 змінених файлів з 985 додано та 332 видалено
  1. 25 0
      code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/constant/FormConstant.java
  2. 10 0
      code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/utils/DateUtil.java
  3. 21 1
      code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/hrpi/helper/EmpPosOrgRelHelper.java
  4. 18 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/common/PerfRankMgmtConstant.java
  5. 1 2
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/common/PositionStructureConstant.java
  6. 77 4
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/performance/PerfrankMgmtFormPlugin.java
  7. 8 2
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/adjust/NewDynamicAdjustmentOperationPlugIn.java
  8. 151 2
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/performance/PerfRankMgmtSaveOpPlugin.java
  9. 120 46
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/performance/validate/PerfRankMgmtSaveValidate.java
  10. 3 2
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/common/PerfManagerFormConstant.java
  11. 16 5
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/helper/PerfManagerHelper.java
  12. 248 61
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/cycle/BatchEvalCycleFormPlugin.java
  13. 35 31
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/cycle/PerfManagerListPlugin.java
  14. 29 9
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/operate/cycle/CycleGenerateOpPlugin.java
  15. 1 1
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/operate/cycle/PerfManagerDeleteOpPlugin.java
  16. 131 75
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/operate/cycle/PerfManagerSaveOpPlugin.java
  17. 91 91
      code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/task/SyncPunchCardTask.java

+ 25 - 0
code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/constant/FormConstant.java

@@ -8,6 +8,11 @@ package nckd.jxccl.base.common.constant;
  */
 public class FormConstant {
 
+    /** 数迁参数 */
+    public static final String HR_INVOKER_PARAM_INVOKER = "hrInvokerParam#invoker";
+    public static final String DATA_MIGRATION = "dataMigration";
+
+
     //====================================== 标品实体标识(需要小写) ======================================
     /**学历-实体标识*/
     public static final String HBSS_DIPLOMA = "hbss_diploma";
@@ -101,6 +106,8 @@ public class FormConstant {
     public static final String CHKINCLUDECHILD = "chkincludechild";
     /** 单据体 */
     public static final String NCKD_ENTRYENTITY = "nckd_entryentity";
+    /** 向导控件 */
+    public static final String NCKD_WIZARDAP = "nckd_wizardap";
 
     //====================================== 通用字段 ======================================
     /** BOID标识 */
@@ -264,5 +271,23 @@ public class FormConstant {
     public static final String NCKD_ISCURRENTNEWEST = "nckd_iscurrentnewest";
     /** 部门*/
     public static final String NCKD_DEP = "nckd_dep";
+    /** 任职经历 */
+    public static final String NCKD_EMPPOSORGREL = "nckd_empposorgrel";
+
+    /** 一级组织 */
+    public static final String NCKD_FIRSTORG = "nckd_firstorg";
+    /** 二级组织 */
+    public static final String NCKD_SECONDORG = "nckd_secondorg";
+    /** 三级组织 */
+    public static final String NCKD_THIRDORG = "nckd_thirdorg";
+    /** 四级组织 */
+    public static final String NCKD_FOURTHORG = "nckd_fourthorg";
+    /** 五级组织 */
+    public static final String NCKD_FIFTHORG = "nckd_fifthorg";
+    /** 六级组织 */
+    public static final String NCKD_SIXTHORG = "nckd_sixthorg";
+    /** 工作性质 */
+    public static final String NCKD_WORKNATURE = "nckd_worknature";
+
 
 }

+ 10 - 0
code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/utils/DateUtil.java

@@ -57,6 +57,16 @@ public class DateUtil {
         return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
     }
 
+    /**
+     * 转换为Date对象
+     *
+     * @param localDate LocalDate
+     * @return 对应的Date对象
+     */
+    public static Date toDate(LocalDate localDate) {
+        return  Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
+    }
+
     /**
      * 转换为LocalDateTime对象
      *

+ 21 - 1
code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/hrpi/helper/EmpPosOrgRelHelper.java

@@ -20,8 +20,28 @@ import java.util.Collection;
  * @date 2025/11/4 15:33
  * @version 1.0
  */
-public class EmpPosOrgRelHelper implements Plugin {
+public class EmpPosOrgRelHelper {
 
+    //根据id查询任职经历
+    public static DynamicObject[] queryEmpPosOrgRelById(Collection<Long> ids) {
+        // 构建基础查询条件
+        QFilter queryFilter = new QFilter(FormConstant.ID_KEY, QCP.in, ids);
+
+        // 构建查询字段和排序规则
+        QueryFieldBuilder queryFieldBuilder = selectProperties();
+        queryFieldBuilder.addIdNumberName(FormConstant.POSITION_KEY,FormConstant.NCKD_WORKNATURE);
+        queryFieldBuilder.addIdNumberName(FormConstant.ADMINORG,FormConstant.NCKD_FIRSTORG);
+        queryFieldBuilder.addIdNumberName(FormConstant.ADMINORG,FormConstant.NCKD_SECONDORG);
+        queryFieldBuilder.addIdNumberName(FormConstant.ADMINORG,FormConstant.NCKD_THIRDORG);
+        queryFieldBuilder.addIdNumberName(FormConstant.ADMINORG,FormConstant.NCKD_FOURTHORG);
+        queryFieldBuilder.addIdNumberName(FormConstant.ADMINORG,FormConstant.NCKD_FIFTHORG);
+        queryFieldBuilder.addIdNumberName(FormConstant.ADMINORG,FormConstant.NCKD_SIXTHORG);
+        String selectProperties = queryFieldBuilder.buildSelect();
+        String order = selectProperties().buildOrder();
+
+        // 执行查询并返回结果
+        return BusinessDataServiceHelper.load(FormConstant.HRPI_EMPPOSORGREL, selectProperties, new QFilter[]{queryFilter}, order);
+    }
     /**
      * 根据员工ID查询最新的任职经历信息
      *

+ 18 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/common/PerfRankMgmtConstant.java

@@ -48,6 +48,8 @@ public class PerfRankMgmtConstant extends FormConstant {
     public static final String NCKD_GETRANKLIST = "nckd_getranklist";
     /** 获取排名名单-OP */
     public static final String GETRANKLIST_OP = "getranklist";
+    /** 步骤 */
+    public static final String NCKD_STEP = "nckd_step";
 
 
 
@@ -78,4 +80,20 @@ public class PerfRankMgmtConstant extends FormConstant {
     /** 降级百分比阈值 */
     public static final String NCKD_DOWNGRADETHRESHOLD = "nckd_downgradethreshold";
     /*-------------------------------------- 升保降级条件配置 begin --------------------------------------*/
+
+
+    /*-------------------------------------- 考核周期(人员考评) begin --------------------------------------*/
+    /** 周期开始年份 */
+    public static final String NCKD_BEGINYEAR = "nckd_beginyear";
+    /** 周期结束年份 */
+    public static final String NCKD_ENDYEAR = "nckd_endyear";
+    /** 人员考评管理实体名称 */
+    public static final String PERFMANAGER_ENTITYID = "nckd_perfmanager";
+    /** 人员考评管理分录实体名称 */
+    public static final String NCKD_PERFMANAGERENTRY = "nckd_perfmanagerentry";
+    /** 分录-考核年份 */
+    public static final String NCKD_APPRAISALYEAR = "nckd_appraisalyear";
+    /** 分录-是否来源全排名 */
+    public static final String NCKD_ISALLRANKSOURCE = "nckd_isallranksource";
+    /*-------------------------------------- 考核周期(人员考评) end --------------------------------------*/
 }

+ 1 - 2
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/common/PositionStructureConstant.java

@@ -160,8 +160,7 @@ public class PositionStructureConstant extends FormConstant {
     public static final String NCKD_JOBSEQ = "nckd_jobseq";
     /** 优秀生 */
     public static final String NCKD_EXCELLENT = "nckd_excellent";
-    /** 任职经历 */
-    public static final String NCKD_EMPPOSORGREL = "nckd_empposorgrel";
+
     /*-------------------------------------- 在职人员初定(弹窗) end --------------------------------------*/
 
 

+ 77 - 4
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/performance/PerfrankMgmtFormPlugin.java

@@ -21,17 +21,18 @@ import kd.bos.form.ConfirmTypes;
 import kd.bos.form.IClientViewProxy;
 import kd.bos.form.MessageBoxOptions;
 import kd.bos.form.MessageBoxResult;
+import kd.bos.form.container.Wizard;
+import kd.bos.form.control.Steps;
 import kd.bos.form.events.AfterDoOperationEventArgs;
 import kd.bos.form.events.BeforeDoOperationEventArgs;
 import kd.bos.form.events.MessageBoxClosedEvent;
 import kd.bos.form.operate.FormOperate;
+import kd.bos.form.plugin.AbstractFormPlugin;
 import kd.bos.logging.Log;
 import kd.bos.logging.LogFactory;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
-import kd.bos.plugin.sample.dynamicform.pcform.form.template.ConfirmCallBack;
 import kd.bos.servicehelper.QueryServiceHelper;
-import kd.sdk.plugin.Plugin;
 import nckd.jxccl.base.common.constant.FormConstant;
 import nckd.jxccl.base.common.constant.SystemQueryConstant;
 import nckd.jxccl.base.common.enums.AppraisalResultEnum;
@@ -39,9 +40,11 @@ import nckd.jxccl.base.common.enums.psms.JobSeqEnum;
 import nckd.jxccl.base.common.utils.ConvertUtil;
 import nckd.jxccl.base.common.utils.DateUtil;
 import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+import nckd.jxccl.base.hrpi.helper.EmpPosOrgRelHelper;
 import nckd.jxccl.hr.psms.common.PerfRankMgmtConstant;
 import nckd.jxccl.hr.psms.common.PositionStructureConstant;
 import nckd.jxccl.hr.psms.helper.PositionFileHelper;
+import org.apache.commons.lang3.StringUtils;
 
 import java.time.temporal.ChronoUnit;
 import java.util.Arrays;
@@ -62,7 +65,7 @@ import java.util.stream.Stream;
 * @date 2025/10/20 15:11
 * @version 1.0
 */
-public class PerfrankMgmtFormPlugin extends ConfirmCallBack implements Plugin {
+public class PerfrankMgmtFormPlugin extends AbstractFormPlugin {
 
     private static final Log logger = LogFactory.getLog(PerfrankMgmtFormPlugin.class);
 
@@ -73,6 +76,13 @@ public class PerfrankMgmtFormPlugin extends ConfirmCallBack implements Plugin {
         sortEntry();
         // 该单据不需要审批,默认为暂存状态
         this.getModel().setValue(FormConstant.STATUS, StatusEnum.A.toString());
+        String step = ConvertUtil.toStr(this.getModel().getValue(PerfRankMgmtConstant.NCKD_STEP));
+        if("1".equals(step)){
+            setStepStatus(0,Steps.FINISH);
+            setStepStatus(1,Steps.PROCESS);
+
+            importResultStep();
+        }
     }
 
     @Override
@@ -249,6 +259,7 @@ public class PerfrankMgmtFormPlugin extends ConfirmCallBack implements Plugin {
                     //在职人员
                     qFilter.and(String.join(".", FormConstant.HRPI_EMPENTREL, FormConstant.LABOR_REL_STATUS, FormConstant.IS_HIRED), QCP.equals, EnableEnum.YES.getCode());
                     QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                            .addGroup(new String[]{FormConstant.HRPI_EMPPOSORGREL}, FormConstant.ID_KEY)
                             //用工关系状态.编码(1005_S	在职-试用中、1010_S	在职、1020_S	离职、1030_S	已退休),istrial:是否试用,ishired:是否在职
                             .addGroup(new String[]{FormConstant.HRPI_EMPENTREL, FormConstant.LABOR_REL_STATUS}, FormConstant.NUMBER_KEY, FormConstant.NAME_KEY, FormConstant.IS_TRIAL, FormConstant.IS_HIRED)
                             //任职状态分类(1010_S:在岗,1030_S:不在岗)
@@ -279,18 +290,38 @@ public class PerfrankMgmtFormPlugin extends ConfirmCallBack implements Plugin {
                         Map<Long, Boolean> entitledToAllowance = isEntitledToAllowance(personIds, now);
 
                         // -------------------------------- 4、加载数据到分录 --------------------------------
+                        //预加载任职经历
+                        List<Long> ids = personList.stream()
+                                .map(person -> person.getLong(String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ID_KEY)))
+                                .collect(Collectors.toList());
+                        DynamicObject[] empPosOrgRelArray = EmpPosOrgRelHelper.queryEmpPosOrgRelById(ids);
+                        Map<Long, DynamicObject> empPosOrgRelMap = Arrays.stream(empPosOrgRelArray)
+                                .filter(Objects::nonNull)
+                                .collect(Collectors.toMap(
+                                        obj -> obj.getLong(FormConstant.ID_KEY),
+                                        obj -> obj,
+                                        (existing, replacement) -> existing
+                                ));
                         for (DynamicObject person : personList) {
                             DynamicObject entryCol = entryEntityCols.addNew();
                             long personId = person.getLong(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY));
+                            long empPosOrgRelId = person.getLong(String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ID_KEY));
                             String personName = person.getString(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.NAME_KEY));
                             String personNumber = person.getString(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.EMP_NUMBER_KEY));
 
+                            DynamicObject empPosOrgRel = empPosOrgRelMap.get(empPosOrgRelId);
+                            entryCol.set(FormConstant.NCKD_EMPPOSORGREL, empPosOrgRel);
+
+
                             DynamicObjectType type = EntityMetadataCache.getDataEntityType(FormConstant.HRPI_EMPLOYEE);
                             DynamicObject personObj = (DynamicObject) type.createInstance();
                             personObj.set(FormConstant.ID_KEY, personId);
                             personObj.set(FormConstant.NAME_KEY, personName);
                             personObj.set(FormConstant.EMP_NUMBER_KEY, personNumber);
                             entryCol.set(FormConstant.NCKD_PERSON, personObj);
+
+
+
                             //是否试用
                             boolean isTrial = person.getBoolean(String.join(".", FormConstant.HRPI_EMPENTREL, FormConstant.LABOR_REL_STATUS, FormConstant.IS_TRIAL));
                             //入职日期
@@ -312,13 +343,27 @@ public class PerfrankMgmtFormPlugin extends ConfirmCallBack implements Plugin {
                             entryCol.set(PerfRankMgmtConstant.NCKD_POSTALLOWANCE, hasAllowance);
 
                         }
+                        this.getModel().updateEntryCache(entryEntityCols);
+                        this.getView().updateView(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
                         this.getView().showSuccessNotification("名单获取完成");
                     } else {
                         this.getView().showTipNotification("未获取到人员");
                     }
                 }
+            /* }*/
+        }else if(PerfRankMgmtConstant.SAVE_OP.equalsIgnoreCase(itemKey)){
+            if(afterDoOperationEventArgs.getOperationResult() != null && afterDoOperationEventArgs.getOperationResult().isSuccess()){
+                String wizadap = this.getView().getPageCache().get(FormConstant.NCKD_WIZARDAP);
+                if(StringUtils.isBlank(wizadap) || "0".equals(wizadap)){
+                    setStepStatus(0,Steps.FINISH);
+                    setStepStatus(1,Steps.PROCESS);
+                    //控制显示隐藏
+                    importResultStep();
+                }else {
+                    this.getView().showSuccessNotification("同步考核周期成功。");
+                }
             }
-       /* }*/
+        }
         if(Arrays.asList(FormConstant.DELETEENTRY_OP, PerfRankMgmtConstant.GETRANKLIST_OP).contains(itemKey)){
             sortEntry();
             calcRankCount();
@@ -326,6 +371,16 @@ public class PerfrankMgmtFormPlugin extends ConfirmCallBack implements Plugin {
         // this.getView().setStatus(OperationStatus.EDIT);
     }
 
+    private void importResultStep() {
+        this.getModel().setValue(PerfRankMgmtConstant.NCKD_STEP,1);
+        this.getView().setVisible(false, FormConstant.NUMBER_KEY, FormConstant.NAME_KEY, FormConstant.NCKD_ADMINORG, PerfRankMgmtConstant.NCKD_THEYEAR, PerfRankMgmtConstant.NCKD_GETRANKLIST);
+        this.getView().setVisible(true, PerfRankMgmtConstant.NCKD_TOPRANKS, PerfRankMgmtConstant.NCKD_ALLOWANCERANKS, PerfRankMgmtConstant.NCKD_FAILS, PerfRankMgmtConstant.NCKD_BASICS, PerfRankMgmtConstant.NCKD_EXCELLENTS, "nckd_advconbaritemap6");
+        DynamicObjectCollection entryEntity = this.getModel().getEntryEntity(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
+        for (int i = 0; i < entryEntity.size(); i++) {
+            this.getView().setEnable(Boolean.FALSE, i, FormConstant.NCKD_EMPPOSORGREL);
+        }
+    }
+
     /**
      * 判断人员是否享受职位津贴
      * @param personIds 人员ID列表
@@ -528,4 +583,22 @@ public class PerfrankMgmtFormPlugin extends ConfirmCallBack implements Plugin {
         //优秀人数
         this.getModel().setValue(PerfRankMgmtConstant.NCKD_EXCELLENTS, excellentCount);
     }
+
+
+    /**
+     * 设置步骤状态
+     * @param step 步骤索引(从0开始)
+     * @param stepStatus 步骤状态 {@link Steps}
+     * @return: void
+     * @author W.Y.C
+     * @date: 2025/06/14 20:12
+     */
+    private void setStepStatus(int step,String stepStatus) {
+        Wizard wizard = this.getControl(FormConstant.NCKD_WIZARDAP);
+        Map<String, Object> currentStepMap = new HashMap<>();
+        currentStepMap.put("currentStep", step);
+        currentStepMap.put("currentStatus", stepStatus);
+        wizard.setWizardCurrentStep(currentStepMap);
+        this.getView().getPageCache().put(FormConstant.NCKD_WIZARDAP, step+"");
+    }
 }

+ 8 - 2
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/adjust/NewDynamicAdjustmentOperationPlugIn.java

@@ -9,6 +9,7 @@ import kd.bos.entity.ExtendedDataEntity;
 import kd.bos.entity.constant.StatusEnum;
 import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
 import kd.bos.entity.plugin.AddValidatorsEventArgs;
+import kd.bos.entity.plugin.args.BeforeOperationArgs;
 import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
 import kd.bos.entity.validate.AbstractValidator;
 import kd.bos.logging.Log;
@@ -148,10 +149,15 @@ public class NewDynamicAdjustmentOperationPlugIn extends AbstractOperationServic
     }
 
     @Override
-    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+    public void beforeExecuteOperationTransaction(BeforeOperationArgs e) {
         if(!this.getOperationResult().isSuccess()){
-            return;
+            e.setCancel(true);
         }
+    }
+
+    @Override
+    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+
         logger.info("【职位体系】-动态调整-开始");
         List<Long> personIds = new ArrayList<>(e.getDataEntities().length);
         List<DynamicObject> newPersonPosFiles = new ArrayList<>(e.getDataEntities().length);

+ 151 - 2
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/performance/PerfRankMgmtSaveOpPlugin.java

@@ -1,10 +1,46 @@
 package nckd.jxccl.hr.psms.plugin.operate.performance;
 
+import kd.bos.common.enums.EnableEnum;
+import kd.bos.dataentity.OperateOption;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.ExtendedDataEntity;
+import kd.bos.entity.MainEntityType;
+import kd.bos.entity.operate.OperateOptionConst;
+import kd.bos.entity.operate.result.IOperateInfo;
+import kd.bos.entity.operate.result.OperationResult;
 import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
 import kd.bos.entity.plugin.AddValidatorsEventArgs;
+import kd.bos.entity.plugin.PreparePropertysEventArgs;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
 import kd.bos.entity.plugin.args.EndOperationTransactionArgs;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.MetadataServiceHelper;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.bos.servicehelper.operation.OperationServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
 import kd.sdk.plugin.Plugin;
+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.QueryFieldBuilder;
+import nckd.jxccl.base.common.utils.StrFormatter;
+import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
+import nckd.jxccl.hr.hstu.common.HonorStudentConstant;
+import nckd.jxccl.hr.psms.common.PerfRankMgmtConstant;
 import nckd.jxccl.hr.psms.plugin.operate.performance.validate.PerfRankMgmtSaveValidate;
+import org.apache.commons.lang3.StringUtils;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.StringJoiner;
+import java.util.stream.Collectors;
 
 /**
 * 年度绩效排名管理-保存插件
@@ -14,15 +50,128 @@ import nckd.jxccl.hr.psms.plugin.operate.performance.validate.PerfRankMgmtSaveVa
 */
 public class PerfRankMgmtSaveOpPlugin extends AbstractOperationServicePlugIn implements Plugin {
 
+    @Override
+    public void onPreparePropertys(PreparePropertysEventArgs e) {
+        e.getFieldKeys().addAll(this.billEntityType.getAllFields().keySet());
+    }
+
     @Override
     public void onAddValidators(AddValidatorsEventArgs e) {
         e.addValidator(new PerfRankMgmtSaveValidate());
     }
 
+    @Override
+    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+        for (DynamicObject dataEntity : e.getDataEntities()) {
+            DynamicObjectCollection entryList = dataEntity.getDynamicObjectCollection(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
+            for (DynamicObject entry : entryList) {
+                DynamicObject person = entry.getDynamicObject(FormConstant.NCKD_PERSON);
+                if(person == null){
+                    DynamicObject empPosOrgRel = entry.getDynamicObject(FormConstant.NCKD_EMPPOSORGREL);
+                    entry.set(FormConstant.NCKD_PERSON, empPosOrgRel.getDynamicObject(FormConstant.EMPLOYEE_KEY));
+                }
+            }
+
+        }
+
+    }
 
     @Override
     public void endOperationTransaction(EndOperationTransactionArgs e) {
-        //TODO 【待修改】-职位体系-全排名同步到考核周期
-        super.endOperationTransaction(e);
+        //先查询人员对应考核周期
+        for (DynamicObject data : e.getDataEntities()) {
+            int theYear = data.getInt(PerfRankMgmtConstant.NCKD_THEYEAR);
+            int step = data.getInt(PerfRankMgmtConstant.NCKD_STEP);
+            //当步骤为1时同步考核周期结果
+            if(step == 1) {
+                DynamicObjectCollection entryList = data.getDynamicObjectCollection(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
+
+                List<Long> personIds = entryList.stream()
+                        .map(entry -> entry.getDynamicObject(FormConstant.NCKD_PERSON))
+                        .filter(Objects::nonNull)
+                        .map(person -> person.getLong(FormConstant.ID_KEY))
+                        .filter(id -> id > 0)
+                        .collect(Collectors.toList());
+
+                Map<Long, DynamicObject> personAppraisalMap = entryList.stream()
+                        .filter(entry -> Objects.nonNull(entry.getDynamicObject(FormConstant.NCKD_PERSON)))
+                        .filter(entry -> Objects.nonNull(entry.getDynamicObject(PerfRankMgmtConstant.NCKD_APPRAISALRESULT)))
+                        .collect(Collectors.toMap(
+                                entry -> entry.getDynamicObject(FormConstant.NCKD_PERSON).getLong(FormConstant.ID_KEY),
+                                entry -> entry.getDynamicObject(PerfRankMgmtConstant.NCKD_APPRAISALRESULT)
+                        ));
+
+                //获取考核周期
+                List<Long> perfManagerIds = findPerfManager(theYear, personIds);
+
+                QFilter filter = QFilterCommonHelper.getIdInFilter(perfManagerIds);
+                MainEntityType dataEntityType = MetadataServiceHelper.getDataEntityType(PerfRankMgmtConstant.PERFMANAGER_ENTITYID);
+                DynamicObject[] perfManagerArray = BusinessDataServiceHelper.load(perfManagerIds.toArray(new Long[0]), dataEntityType);
+                LocalDate appraisalYearLocalDate = LocalDate.of(theYear, 1, 1);
+                Date appraisalYearDate = DateUtil.toDate(appraisalYearLocalDate);
+
+                for (DynamicObject perfManager : perfManagerArray) {
+                    DynamicObject person = perfManager.getDynamicObject(FormConstant.NCKD_PERSON);
+                    long personId = person.getLong(FormConstant.ID_KEY);
+                    DynamicObjectCollection perfManagerEntryColl = perfManager.getDynamicObjectCollection(PerfRankMgmtConstant.NCKD_PERFMANAGERENTRY);
+                    boolean isExist = false;
+                    for (DynamicObject perfManagerEntry : perfManagerEntryColl) {
+                        LocalDateTime appraisalYear = DateUtil.toLocalDateTime(perfManagerEntry.getDate(PerfRankMgmtConstant.NCKD_APPRAISALYEAR));
+                        int year = appraisalYear.getYear();
+                        if(year == theYear){
+                            perfManagerEntry.set(PerfRankMgmtConstant.NCKD_APPRAISALRESULT, personAppraisalMap.get(personId));
+                            isExist = true;
+                            break;
+                        }
+                    }
+                    if(!isExist){
+                        DynamicObject perfManagerEntry = perfManagerEntryColl.addNew();
+                        perfManagerEntry.set(PerfRankMgmtConstant.NCKD_APPRAISALYEAR,appraisalYearDate);
+                        perfManagerEntry.set(PerfRankMgmtConstant.NCKD_APPRAISALRESULT, personAppraisalMap.get(personId));
+                        perfManagerEntry.set(PerfRankMgmtConstant.NCKD_ISALLRANKSOURCE, EnableEnum.YES.getCode());
+                    }
+                }
+                OperationResult operationResult = SaveServiceHelper.saveOperate(FormConstant.SAVE_OP, PerfRankMgmtConstant.PERFMANAGER_ENTITYID, perfManagerArray, OperateOption.create());
+                if (!operationResult.isSuccess()) {
+                    StringJoiner errorMsgJoiner = new StringJoiner(StrFormatter.LINE_SEPARATOR);
+                    for (IOperateInfo error : operationResult.getAllErrorOrValidateInfo()) {
+                        errorMsgJoiner.add(error.getMessage());
+                    }
+                    String errorMsg = errorMsgJoiner.toString();
+                    if(StringUtils.isBlank(errorMsg)){
+                        errorMsg = operationResult.getMessage();
+                    }
+                    throw new ValidationException("同步考核周期失败,原因:"+errorMsg);
+                }
+
+            }
+        }
+    }
+
+
+
+
+
+    /**
+     * 根据人员和年度查询人员考核周期
+     * @param theYear 年份
+     * @param personIds 人员ID
+     * @return: java.util.List<java.lang.Long>
+     * @author W.Y.C
+     * @date: 2025/11/12 22:10
+     */
+    private List<Long> findPerfManager(int theYear,List<Long> personIds) {
+        //根据年度校验人员只能在同一个组
+        LocalDate startDate = LocalDate.of(theYear, 1, 1);
+        QFilter filter = new QFilter(PerfRankMgmtConstant.NCKD_PERSON, QCP.in, personIds);
+        filter.and(PerfRankMgmtConstant.NCKD_BEGINYEAR,QCP.less_equals,startDate);
+        filter.and(PerfRankMgmtConstant.NCKD_ENDYEAR,QCP.large_equals,startDate);
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                .add(FormConstant.ID_KEY);
+        DynamicObjectCollection query = QueryServiceHelper.query(PerfRankMgmtConstant.PERFMANAGER_ENTITYID, queryFieldBuilder.buildSelect(), new QFilter[]{filter});
+        List<Long> ids = query.stream()
+                .map(obj -> obj.getLong(FormConstant.ID_KEY))
+                .collect(Collectors.toList());
+        return ids;
     }
 }

+ 120 - 46
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/performance/validate/PerfRankMgmtSaveValidate.java

@@ -4,6 +4,7 @@ import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.dataentity.entity.DynamicObjectCollection;
 import kd.bos.entity.ExtendedDataEntity;
 import kd.bos.entity.validate.AbstractValidator;
+import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
 import kd.bos.servicehelper.QueryServiceHelper;
 import nckd.jxccl.base.common.constant.FormConstant;
@@ -11,12 +12,12 @@ import nckd.jxccl.base.common.enums.AppraisalResultEnum;
 import nckd.jxccl.base.common.utils.DateUtil;
 import nckd.jxccl.base.common.utils.QueryFieldBuilder;
 import nckd.jxccl.base.common.utils.StrFormatter;
-import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
 import nckd.jxccl.hr.psms.common.PerfRankMgmtConstant;
 import nckd.jxccl.hr.psms.common.PositionStructureConstant;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.time.LocalDate;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -24,6 +25,8 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.StringJoiner;
+import java.util.stream.Collectors;
 
 /**
 * 绩效排名管理保存验证插件
@@ -36,39 +39,53 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
     private final Map<String, BigDecimal> appraisalResultRatioMap = new HashMap<>();
     @Override
     public void validate() {
-        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
-                .addGroup(new String[]{FormConstant.NCKD_ENTRYENTITY}, PerfRankMgmtConstant.NCKD_RATIO)
-                .addGroup(new String[]{FormConstant.NCKD_ENTRYENTITY, PositionStructureConstant.NCKD_APPRAISALRESULT}, FormConstant.NUMBER_KEY);
-        DynamicObjectCollection query = QueryServiceHelper.query(PerfRankMgmtConstant.RANKRATIOCONF_ENTITYID, queryFieldBuilder.buildSelect(), null);
-
-        query.forEach(dynamicObject -> {
-            String key = dynamicObject.getString(String.join(".",FormConstant.NCKD_ENTRYENTITY, PositionStructureConstant.NCKD_APPRAISALRESULT, FormConstant.NUMBER_KEY));
-            BigDecimal value = dynamicObject.getBigDecimal(String.join(".",FormConstant.NCKD_ENTRYENTITY, PerfRankMgmtConstant.NCKD_RATIO));
-            appraisalResultRatioMap.put(key, value);
-        });
-        for (ExtendedDataEntity rowDataEntity : getDataEntities()) {
-            if(appraisalResultRatioMap.isEmpty()){
-                this.addMessage(rowDataEntity, "没有配置【排名考核结果比例】");
-                return;
-            }
-            DynamicObject data = rowDataEntity.getDataEntity();
-            // 年份校验
-            if (validateYear(data, rowDataEntity)) {
-                // 获取明细数据并验证是否为空
-                DynamicObjectCollection entries = data.getDynamicObjectCollection(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
-                if (entries.isEmpty()) {
-                    String operateKey = this.getOperateKey();
-                    if(!operateKey.equals(FormConstant.SAVE_OP)) {
-                        this.addMessage(rowDataEntity, "请添加排名名单");
-                        continue;
-                    }
+        String invoker = (String)this.getOption().getVariables().get(FormConstant.HR_INVOKER_PARAM_INVOKER);
+        boolean dataMigration = FormConstant.DATA_MIGRATION.equalsIgnoreCase(invoker);
+        if(!dataMigration) {
+            QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                    .addGroup(new String[]{FormConstant.NCKD_ENTRYENTITY}, PerfRankMgmtConstant.NCKD_RATIO)
+                    .addGroup(new String[]{FormConstant.NCKD_ENTRYENTITY, PositionStructureConstant.NCKD_APPRAISALRESULT}, FormConstant.NUMBER_KEY);
+            DynamicObjectCollection query = QueryServiceHelper.query(PerfRankMgmtConstant.RANKRATIOCONF_ENTITYID, queryFieldBuilder.buildSelect(), null);
+
+            query.forEach(dynamicObject -> {
+                String key = dynamicObject.getString(String.join(".", FormConstant.NCKD_ENTRYENTITY, PositionStructureConstant.NCKD_APPRAISALRESULT, FormConstant.NUMBER_KEY));
+                BigDecimal value = dynamicObject.getBigDecimal(String.join(".", FormConstant.NCKD_ENTRYENTITY, PerfRankMgmtConstant.NCKD_RATIO));
+                appraisalResultRatioMap.put(key, value);
+            });
+            for (ExtendedDataEntity rowDataEntity : getDataEntities()) {
+                if (appraisalResultRatioMap.isEmpty()) {
+                    this.addFatalErrorMessage(rowDataEntity, "没有配置【排名考核结果比例】");
+                    return;
                 }
+                DynamicObject data = rowDataEntity.getDataEntity();
+                // 年份校验
+                if (validateYear(data, rowDataEntity)) {
+                    // 获取明细数据并验证是否为空
+                    DynamicObjectCollection entries = data.getDynamicObjectCollection(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
+                    if (entries.isEmpty()) {
+                        String operateKey = this.getOperateKey();
+                        // if (!operateKey.equals(FormConstant.SAVE_OP)) {
+                            this.addFatalErrorMessage(rowDataEntity, "请添加排名名单");
+                            // continue;
+                        // }
+                    }
+                    int step = data.getInt(PerfRankMgmtConstant.NCKD_STEP);
 
-                // 验证明细数据
-                ValidationContext context = validateEntries(entries, rowDataEntity);
+                    //当步骤为导入考核结果时需校验明细数据
 
-                // 验证统计数据一致性
-                validateDataConsistency(data, context, rowDataEntity);
+                    // 验证明细数据
+                    ValidationContext context = validateEntries(entries, rowDataEntity);
+
+                    // 校验人员是否在其他分组中排名
+                    validateRepetition(data, rowDataEntity, context);
+
+                    // 校验人员是否有对应考核周期
+                    validatePerfManager(data,entries,rowDataEntity, context);
+                    if(step == 1) {
+                        // 验证统计数据一致性
+                        validateDataConsistency(data, context, rowDataEntity);
+                    }
+                }
             }
         }
     }
@@ -128,7 +145,7 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
 
         if (difference > allowedDifference) {
 
-            this.addMessage(rowDataEntity,
+            this.addFatalErrorMessage(rowDataEntity,
                     StrFormatter.format("{}人数与配置比例不符,应为{}人,实际为{}人",
                             levelName, expectedCount,actualCount));
         }
@@ -147,7 +164,7 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
         int theYear = data.getInt(PerfRankMgmtConstant.NCKD_THEYEAR);
         int currentYear = DateUtil.now().getYear();
         if (theYear < 1900 || theYear > currentYear) {
-            this.addMessage(rowDataEntity, "年份不合法或超过当前年份");
+            this.addFatalErrorMessage(rowDataEntity, "年份不合法或超过当前年份");
             return false;
         }
         return true;
@@ -169,10 +186,66 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
             DynamicObject entry = entries.get(i);
             validateEntry(entry, rowDataEntity, i + 1, personIds, context);
         }
+        context.personIds = personIds;
+
+        return context;
+    }
 
+
+    private void validateRepetition(DynamicObject data, ExtendedDataEntity rowDataEntity, ValidationContext context) {
         //根据年度校验人员只能在同一个组
+        long id = data.getLong(FormConstant.ID_KEY);
+        int theYear = data.getInt(PerfRankMgmtConstant.NCKD_THEYEAR);
+        QFilter filter = new QFilter(String.join(".", PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, PerfRankMgmtConstant.NCKD_PERSON), QCP.in, context.personIds);
+        if(id > 0){
+            filter.and(FormConstant.ID_KEY, QCP.not_equals, id);
+        }
+        filter.and(PerfRankMgmtConstant.NCKD_THEYEAR,QCP.equals,theYear);
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                .add(FormConstant.NAME_KEY)
+                .add(PerfRankMgmtConstant.NCKD_THEYEAR)
+                .addIdNumberName(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, PerfRankMgmtConstant.NCKD_PERSON);
+        DynamicObjectCollection query = QueryServiceHelper.query(PerfRankMgmtConstant.NCKD_PERFRANKMGMT_ENTITYID, queryFieldBuilder.buildSelect(), new QFilter[]{filter});
+        StringJoiner msgJoiner = new StringJoiner(StrFormatter.LINE_SEPARATOR);
+        for (DynamicObject dynamicObject : query) {
+            String name = dynamicObject.getString(FormConstant.NAME_KEY);
+            String personName = dynamicObject.getString(String.join(".", PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, PerfRankMgmtConstant.NCKD_PERSON,FormConstant.NAME_KEY));
+            msgJoiner.add(StrFormatter.format("人员【{}】已在排名单元【{}】中排名;", personName,name));
+        }
+        if(msgJoiner.length() > 0){
+            this.addFatalErrorMessage(rowDataEntity, msgJoiner.toString());
+        }
+    }
 
-        return context;
+
+
+    private void validatePerfManager(DynamicObject data,DynamicObjectCollection entries, ExtendedDataEntity rowDataEntity, ValidationContext context) {
+        //根据年度校验人员只能在同一个组
+        int theYear = data.getInt(PerfRankMgmtConstant.NCKD_THEYEAR);
+        LocalDate startDate = LocalDate.of(theYear, 1, 1);
+        QFilter filter = new QFilter(PerfRankMgmtConstant.NCKD_PERSON, QCP.in, context.personIds);
+        filter.and(PerfRankMgmtConstant.NCKD_BEGINYEAR,QCP.less_equals,startDate);
+        filter.and(PerfRankMgmtConstant.NCKD_ENDYEAR,QCP.large_equals,startDate);
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                .addIdNumberName(PerfRankMgmtConstant.NCKD_PERSON);
+        DynamicObjectCollection query = QueryServiceHelper.query(PerfRankMgmtConstant.PERFMANAGER_ENTITYID, queryFieldBuilder.buildSelect(), new QFilter[]{filter});
+        Map<Long, DynamicObject> personMap = query.stream()
+                .filter(obj -> obj.getLong(String.join(".", PerfRankMgmtConstant.NCKD_PERSON, FormConstant.ID_KEY)) > 0)
+                .collect(Collectors.toMap(
+                        obj -> obj.getLong(String.join(".", PerfRankMgmtConstant.NCKD_PERSON, FormConstant.ID_KEY)),
+                        obj -> obj
+                ));
+        StringJoiner msgJoiner = new StringJoiner(StrFormatter.LINE_SEPARATOR);
+        for (DynamicObject entry : entries) {
+            long person = entry.getDynamicObject(PerfRankMgmtConstant.NCKD_PERSON).getLong(FormConstant.ID_KEY);
+            if (!personMap.containsKey(person)) {
+                String personName = entry.getDynamicObject(PerfRankMgmtConstant.NCKD_PERSON).getString(FormConstant.NAME_KEY);
+                msgJoiner.add(StrFormatter.format("人员【{}】没有【{}】年度的考核周期;", personName,theYear));
+            }
+        }
+        if(msgJoiner.length() > 0){
+            this.addFatalErrorMessage(rowDataEntity, msgJoiner.toString());
+        }
     }
 
     /**
@@ -191,12 +264,12 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
                                int rowIndex, Set<Long> personIds, ValidationContext context) {
         DynamicObject person = entry.getDynamicObject(PerfRankMgmtConstant.NCKD_PERSON);
         if (person == null) {
-            this.addMessage(rowDataEntity, StrFormatter.format("第{}行,请选择人员\n", rowIndex));
+            this.addFatalErrorMessage(rowDataEntity, StrFormatter.format("第{}行,请选择人员\n", rowIndex));
         } else {
             // 人员重复校验
             long personId = person.getLong(FormConstant.ID_KEY);
             if (personIds.contains(personId)) {
-                this.addMessage(rowDataEntity, StrFormatter.format("第{}行,人员【{}】重复;\n", rowIndex, person.getString(FormConstant.NAME_KEY)));
+                this.addFatalErrorMessage(rowDataEntity, StrFormatter.format("第{}行,人员【{}】重复;\n", rowIndex, person.getString(FormConstant.NAME_KEY)));
             } else {
                 personIds.add(personId);
             }
@@ -279,19 +352,19 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
         int excellents = data.getInt(PerfRankMgmtConstant.NCKD_EXCELLENTS);
 
         if (topRanks != context.totalRankCount) {
-            this.addMessage(rowDataEntity, "总排名人数与实际录入数据不一致;\n");
+            this.addFatalErrorMessage(rowDataEntity, "总排名人数与实际录入数据不一致;\n");
         }
         if (allowanceRanks != context.allowanceRankCount) {
-            this.addMessage(rowDataEntity, "R排名人数与实际录入数据不一致;\n");
+            this.addFatalErrorMessage(rowDataEntity, "R排名人数与实际录入数据不一致;\n");
         }
         if (fails != context.failCount) {
-            this.addMessage(rowDataEntity, "不合格人数与实际录入数据不一致;\n");
+            this.addFatalErrorMessage(rowDataEntity, "不合格人数与实际录入数据不一致;\n");
         }
         if (basics != context.basicCount) {
-            this.addMessage(rowDataEntity, "基本人数与实际录入数据不一致;\n");
+            this.addFatalErrorMessage(rowDataEntity, "基本人数与实际录入数据不一致;\n");
         }
         if (excellents != context.excellentCount) {
-            this.addMessage(rowDataEntity, "优秀人数与实际录入数据不一致;\n");
+            this.addFatalErrorMessage(rowDataEntity, "优秀人数与实际录入数据不一致;\n");
         }
     }
 
@@ -343,14 +416,14 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
                 // 检查排名字段是否在有效范围内
                 int topRank = entry.getInt(PerfRankMgmtConstant.NCKD_TOPRANK);
                 if (topRank < 1 || topRank > totalRankCount) {
-                    this.addMessage(rowDataEntity,
+                    this.addFatalErrorMessage(rowDataEntity,
                             StrFormatter.format("第{}行,排名{}超出有效范围[1-{}]\n", i + 1, topRank, totalRankCount));
                 }
                 if (postAllowance) {
                     // 检查R排名字段是否在有效范围内
                     int allowanceRank = entry.getInt(PerfRankMgmtConstant.NCKD_ALLOWANCERANK);
                     if (allowanceRank < 1 || allowanceRank > totalRankCount) {
-                        this.addMessage(rowDataEntity,
+                        this.addFatalErrorMessage(rowDataEntity,
                                 StrFormatter.format("第{}行,R排名{}超出有效范围[1-{}]\n", i + 1, allowanceRank, totalRankCount));
                     }
                 }
@@ -378,7 +451,7 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
                                        Map<Integer, Integer> rankCountMap) {
         int rankValue = entry.getInt(rankField);
         if (rankValue < 1) {
-            this.addMessage(rowDataEntity, StrFormatter.format("人员【{}】已勾选{},{}数不能小于1或为空",
+            this.addFatalErrorMessage(rowDataEntity, StrFormatter.format("人员【{}】已勾选{},{}数不能小于1或为空",
                     personName, type, rankType));
         } else {
             rankCountMap.put(rankValue, rankCountMap.getOrDefault(rankValue, 0) + 1);
@@ -431,7 +504,7 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
             errorMsg.append("✅ 合规示例:[1,1,1,4] - 排名1重复3次,结束位置应为1+3-1=3,3不在列表中\n");
             errorMsg.append("【解决建议】\n");
             errorMsg.append("请调整重复排名的数值或移除冲突的排名,确保连续序列结束位置未被占用;\n\n");
-            this.addMessage(rowDataEntity, errorMsg.toString());
+            this.addFatalErrorMessage(rowDataEntity, errorMsg.toString());
         }
     }
 
@@ -511,7 +584,7 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
                     detailMessage.append(StrFormatter.format("{}【{}】出现{}次;", rankType, rank, count));
                 }
                 detailMessage.append("\n");
-                this.addMessage(rowDataEntity, detailMessage.toString());
+                this.addFatalErrorMessage(rowDataEntity, detailMessage.toString());
             }
         }
     }
@@ -533,6 +606,7 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
         int basicCount = 0;
         int excellentCount = 0;
         int qualifiedCount = 0;
+        Set<Long> personIds = new HashSet<>();
         Set<Integer> rankSet = new HashSet<>();  // 记录已出现的排名
         Set<Integer> duplicateRanks = new HashSet<>();  // 记录普通排名中重复的排名
         Set<Integer> duplicateRRanks = new HashSet<>();  // 记录R排名中重复的排名

+ 3 - 2
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/common/PerfManagerFormConstant.java

@@ -14,6 +14,8 @@ public class PerfManagerFormConstant extends FormConstant {
     public static final String PERFMANAGER_ENTITYID = "nckd_perfmanager";
     /** 周期开始年份 */
     public static final String NCKD_BEGINYEAR = "nckd_beginyear";
+    /** 周期结束年份 */
+    public static final String NCKD_ENDYEAR = "nckd_endyear";
     /** 实际周期结束年份 */
     public static final String NCKD_ACTENDYEAR = "nckd_actendyear";
     /** 人员考评向导页面标识*/
@@ -26,8 +28,7 @@ public class PerfManagerFormConstant extends FormConstant {
     public static final String NCKD_THIRDYEARRESULT = "nckd_thirdyearresult";
     /** 调薪说明 */
     public static final String NCKD_WAGEEXPLAIN = "nckd_wageexplain";
-    /** 周期结束年份 */
-    public static final String NCKD_ENDYEAR = "nckd_endyear";
+
     /** 周期状态 */
     public static final String NCKD_THESTATUS = "nckd_thestatus";
     /** 锁定人 */

+ 16 - 5
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/helper/PerfManagerHelper.java

@@ -2,12 +2,15 @@ package nckd.jxccl.opmc.pm.helper;
 
 import kd.bos.common.enums.EnableEnum;
 import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.MainEntityType;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
 import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.MetadataServiceHelper;
 import kd.bos.servicehelper.operation.SaveServiceHelper;
 import nckd.jxccl.base.common.constant.FormConstant;
 import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
 import nckd.jxccl.opmc.pm.common.PerfManagerFormConstant;
 
 import java.util.ArrayList;
@@ -36,6 +39,13 @@ public class PerfManagerHelper {
         return getNewestPerfManagerByPerson(personIds,null);
     }
 
+    public static DynamicObject[] getById(Collection<Long> ids) {
+        QFilter filter = QFilterCommonHelper.getIdInFilter(ids);
+        MainEntityType dataEntityType = MetadataServiceHelper.getDataEntityType(PerfManagerFormConstant.PERFMANAGER_ENTITYID);
+
+        return BusinessDataServiceHelper.load(ids.toArray(new Long[0]),dataEntityType);
+    }
+
 
     /**
      * 根据人员获取当前最新的考核周期(“是否当前最新记录 = true” 并且  “周期状态 = 1”)
@@ -48,6 +58,7 @@ public class PerfManagerHelper {
     public static DynamicObject[] getNewestPerfManagerByPerson(Collection<Long> personIds,QFilter otherFilter) {
         QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                 .add(FormConstant.ID_KEY)
+                .addIdNumberName(FormConstant.NCKD_EMPPOSORGREL)
                 .addIdNumberName(FormConstant.NCKD_PERSON)
                 .addIdNumberName(PerfManagerFormConstant.NCKD_FIRSTYEARRESULT)
                 .addIdNumberName(PerfManagerFormConstant.NCKD_SECONDYEARRESULT)
@@ -58,8 +69,8 @@ public class PerfManagerHelper {
                 .add(PerfManagerFormConstant.NCKD_WHYEND)
                 .add(PerfManagerFormConstant.NCKD_THESTATUS)
                 .add(PerfManagerFormConstant.NCKD_ISCURRENTNEWEST)
-                .addIdNumberName(new String[]{PerfManagerFormConstant.NCKD_PERFMANAGERENTRY,PerfManagerFormConstant.NCKD_APPRAISALRESULT})
-                .addIdNumberName(new String[]{PerfManagerFormConstant.NCKD_PERFMANAGERENTRY,PerfManagerFormConstant.NCKD_APPRAISALYEAR});
+                .addIdNumberName(PerfManagerFormConstant.NCKD_PERFMANAGERENTRY,PerfManagerFormConstant.NCKD_APPRAISALRESULT)
+                .addGroup(new String[]{PerfManagerFormConstant.NCKD_PERFMANAGERENTRY},PerfManagerFormConstant.NCKD_APPRAISALRESULT,PerfManagerFormConstant.NCKD_APPRAISALYEAR,PerfManagerFormConstant.NCKD_ISALLRANKSOURCE);
 
         QFilter filter = new QFilter(PerfManagerFormConstant.NCKD_ISCURRENTNEWEST, QCP.equals, EnableEnum.YES.getCode())
                 .and(new QFilter(PerfManagerFormConstant.NCKD_THESTATUS, QCP.equals, EnableEnum.YES.getCode()))
@@ -81,7 +92,7 @@ public class PerfManagerHelper {
      */
     public static List<DynamicObject> getNewestPerfManagerByPersonAndBeginYear(Collection<Long> personIds,QFilter otherFilter) {
         QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
-                .addIdNumberName()
+                .add(FormConstant.ID_KEY)
                 .addIdNumberName(FormConstant.NCKD_PERSON)
                 .addIdNumberName(PerfManagerFormConstant.NCKD_FIRSTYEARRESULT)
                 .addIdNumberName(PerfManagerFormConstant.NCKD_SECONDYEARRESULT)
@@ -93,8 +104,8 @@ public class PerfManagerHelper {
                 .add(PerfManagerFormConstant.NCKD_THESTATUS)
                 .add(PerfManagerFormConstant.NCKD_ISCURRENTNEWEST)
                 .add(PerfManagerFormConstant.CREATE_TIME_KEY)
-                .addIdNumberName(new String[]{PerfManagerFormConstant.NCKD_PERFMANAGERENTRY,PerfManagerFormConstant.NCKD_APPRAISALRESULT})
-                .addIdNumberName(new String[]{PerfManagerFormConstant.NCKD_PERFMANAGERENTRY,PerfManagerFormConstant.NCKD_APPRAISALYEAR})
+                .addIdNumberName(PerfManagerFormConstant.NCKD_PERFMANAGERENTRY,PerfManagerFormConstant.NCKD_APPRAISALRESULT)
+                .addGroup(new String[]{PerfManagerFormConstant.NCKD_PERFMANAGERENTRY},PerfManagerFormConstant.NCKD_APPRAISALRESULT,PerfManagerFormConstant.NCKD_APPRAISALYEAR,PerfManagerFormConstant.NCKD_ISALLRANKSOURCE)
                 .orderDesc(PerfManagerFormConstant.NCKD_BEGINYEAR);
 
         QFilter filter = new QFilter(PerfManagerFormConstant.NCKD_PERSON, QCP.in, personIds);

+ 248 - 61
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/cycle/BatchEvalCycleFormPlugin.java

@@ -9,9 +9,10 @@ import kd.bos.entity.operate.result.IOperateInfo;
 import kd.bos.entity.operate.result.OperationResult;
 import kd.bos.form.ConfirmCallBackListener;
 import kd.bos.form.ConfirmTypes;
+import kd.bos.form.FormShowParameter;
 import kd.bos.form.MessageBoxOptions;
 import kd.bos.form.MessageBoxResult;
-import kd.bos.form.control.Control;
+import kd.bos.form.events.AfterDoOperationEventArgs;
 import kd.bos.form.events.MessageBoxClosedEvent;
 import kd.bos.form.plugin.AbstractFormPlugin;
 import kd.bos.org.utils.DynamicObjectUtils;
@@ -25,16 +26,22 @@ import nckd.jxccl.base.common.utils.StrFormatter;
 import nckd.jxccl.base.entity.helper.EntityHelper;
 import nckd.jxccl.opmc.pm.common.PerfManagerFormConstant;
 import nckd.jxccl.opmc.pm.helper.PerfManagerHelper;
+import org.apache.commons.lang3.StringUtils;
 
 import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
 import java.util.EventObject;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.StringJoiner;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 
 /**
@@ -47,54 +54,120 @@ import java.util.stream.Collectors;
 public class BatchEvalCycleFormPlugin extends AbstractFormPlugin implements Plugin {
 
     @Override
-    public void registerListener(EventObject e) {
-        this.addClickListeners(FormConstant.BTN_OK_OP);
-    }
-
+    public void afterCreateNewData(EventObject e) {
+        // 获取当前页面的FormShowParameter对象
+        FormShowParameter showParameter = this.getView().getFormShowParameter();
+        //获取列表选择的人员
+        String isAddOrUpdate = ConvertUtil.toStr(showParameter.getCustomParam("nckd_isaddorupdate"));
+        if("2".equalsIgnoreCase(isAddOrUpdate)) {
+            //批量修改
+            this.getModel().setValue("nckd_isaddorupdate", isAddOrUpdate);
+            this.getView().updateView("nckd_isaddorupdate");
 
-    @Override
-    public void click(EventObject evt) {
-
-        super.click(evt);
-        Control source = (Control)evt.getSource();
-        if(FormConstant.BTN_OK_OP.equalsIgnoreCase(source.getKey())){
-            DynamicObjectCollection perfManagerList = this.getModel().getEntryEntity(FormConstant.NCKD_ENTRYENTITY);
-            Set<Long> personIds = new HashSet<>(perfManagerList.size());
-            //转换为考核周期实体
-            for (DynamicObject dynamicObject : perfManagerList) {
-                DynamicObject person = dynamicObject.getDynamicObject(FormConstant.NCKD_PERSON);
-                personIds.add(person.getLong(FormConstant.ID_KEY));
+            List<Long> selectedRows = ConvertUtil.toList(showParameter.getCustomParam("selectedRows"));
+            int max = Math.max(selectedRows.size() - 1, 0);
+            if(max > 0) {
+                this.getModel().batchCreateNewEntryRow(FormConstant.NCKD_ENTRYENTITY, max);
             }
+            DynamicObject[] perfManagerList = PerfManagerHelper.getById(selectedRows);
+            AtomicInteger index = new AtomicInteger(0);
+            for (DynamicObject perfManager : perfManagerList) {
+                int i = index.getAndIncrement();
+                Date beginYear = perfManager.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR);
+                Date endYear = perfManager.getDate(PerfManagerFormConstant.NCKD_ENDYEAR);
+                this.getModel().setValue(PerfManagerFormConstant.PERFMANAGER_ENTITYID,perfManager, i);
+                this.getModel().setValue(PerfManagerFormConstant.NCKD_EMPPOSORGREL,perfManager.getDynamicObject(PerfManagerFormConstant.NCKD_EMPPOSORGREL), i);
+                this.getModel().setValue(PerfManagerFormConstant.NCKD_PERSON,perfManager.getDynamicObject(PerfManagerFormConstant.NCKD_PERSON), i);
+                this.getModel().setValue(PerfManagerFormConstant.NCKD_BEGINYEAR,beginYear, i);
+                this.getModel().setValue(PerfManagerFormConstant.NCKD_ENDYEAR,endYear, i);
+                this.getModel().setValue(PerfManagerFormConstant.DESCRIPTION_KEY,perfManager.getString(FormConstant.DESCRIPTION_KEY), i);
 
-            //最新上一考核周期
-            DynamicObject[] newestPerfManagerByPerson = PerfManagerHelper.getNewestPerfManagerByPerson(personIds);
-            Map<Long, DynamicObject> lastPerfManagerMap; lastPerfManagerMap = Arrays.stream(newestPerfManagerByPerson)
-                    .collect(Collectors.toMap(
-                            perfManager -> perfManager.getDynamicObject(FormConstant.NCKD_PERSON).getLong(FormConstant.ID_KEY),
-                            perfManager -> perfManager,
-                            (existing, replacement) -> existing
-                    ));
-            StringJoiner confirMmsg = new StringJoiner(",");
-            for (DynamicObject lastPerfManager : lastPerfManagerMap.values()) {
-                String personName = lastPerfManager.getDynamicObject(FormConstant.NCKD_PERSON).getString(FormConstant.NAME_KEY);
-                LocalDateTime beginYear = DateUtil.toLocalDateTime(lastPerfManager.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR));
-                LocalDateTime endYear = DateUtil.toLocalDateTime(lastPerfManager.getDate(PerfManagerFormConstant.NCKD_ENDYEAR));
-                confirMmsg.add(StrFormatter.format("{}(周期:{}~{})", personName, beginYear.getYear(), endYear.getYear()));
-            }
-            if(confirMmsg.length() > 0){
-                // 创建回调监听器,指定回调ID和处理此回调的插件(this)
-                ConfirmCallBackListener confirmCallBacks = new ConfirmCallBackListener(PerfManagerFormConstant.BATCHEVALCYCLE_ENTITYID, this);
-                // 弹出确认框
-                this.getView().showConfirm(StrFormatter.format("检测到本次新增的人员中存在【未结束】的考核周期,新周期新增成功后会自动结束上一周期,请确认是否继续。{}", confirMmsg),
-                        MessageBoxOptions.OKCancel,
-                        ConfirmTypes.Default,
-                        confirmCallBacks);
-            }else{
-                executeOperateSave();
+                DynamicObjectCollection entrys = perfManager.getDynamicObjectCollection(PerfManagerFormConstant.NCKD_PERFMANAGERENTRY);
+                for (DynamicObject entry : entrys) {
+                    boolean isAllRankSource = entry.getBoolean(PerfManagerFormConstant.NCKD_ISALLRANKSOURCE);
+                    Date appraisalYear = entry.getDate(PerfManagerFormConstant.NCKD_APPRAISALYEAR);
+
+                    if (isAllRankSource && appraisalYear != null) {
+                        LocalDateTime appraisalLocalDate = DateUtil.toLocalDateTime(appraisalYear);
+                        LocalDateTime beginLocalDate = DateUtil.toLocalDateTime(beginYear);
+
+                        // 计算是第几年(分录中的年份-(周期开始时间 + 1))
+                        long yearsDiff = appraisalLocalDate.getYear() - beginLocalDate.getYear() + 1;
+                        // 根据年份差异禁用对应的考核结果字段
+                        switch ((int) yearsDiff) {
+                            case 1:
+                                this.getView().setEnable(Boolean.FALSE, i, PerfManagerFormConstant.NCKD_FIRSTYEARRESULT);
+                                break;
+                            case 2:
+                                this.getView().setEnable(Boolean.FALSE, i, PerfManagerFormConstant.NCKD_SECONDYEARRESULT);
+                                break;
+                            case 3:
+                                this.getView().setEnable(Boolean.FALSE, i, PerfManagerFormConstant.NCKD_THIRDYEARRESULT);
+                                break;
+                        }
+                    }
+                }
+
+                this.getModel().setValue(PerfManagerFormConstant.NCKD_FIRSTYEARRESULT,perfManager.getDynamicObject(PerfManagerFormConstant.NCKD_FIRSTYEARRESULT), i);
+                this.getModel().setValue(PerfManagerFormConstant.NCKD_SECONDYEARRESULT,perfManager.getDynamicObject(PerfManagerFormConstant.NCKD_SECONDYEARRESULT), i);
+                this.getModel().setValue(PerfManagerFormConstant.NCKD_THIRDYEARRESULT,perfManager.getDynamicObject(PerfManagerFormConstant.NCKD_THIRDYEARRESULT), i);
             }
 
+            this.getView().updateView(FormConstant.NCKD_ENTRYENTITY);
         }
+    }
+
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs e) {
+        if(e.getOperationResult() != null && e.getOperationResult().isSuccess()){
+            String operateKey = e.getOperateKey();
+            if(FormConstant.CONFIRM_OP.equalsIgnoreCase(operateKey)){
+                String isAddOrUpdate = ConvertUtil.toStr(this.getModel().getValue("nckd_isaddorupdate"));
+                boolean isUpdate = "2".equalsIgnoreCase(isAddOrUpdate);
+
+                DynamicObjectCollection perfManagerList = this.getModel().getEntryEntity(FormConstant.NCKD_ENTRYENTITY);
+                Set<Long> personIds = new HashSet<>(perfManagerList.size());
+                //转换为考核周期实体
+                for (DynamicObject dynamicObject : perfManagerList) {
+                    DynamicObject person = dynamicObject.getDynamicObject(FormConstant.NCKD_PERSON);
+                    personIds.add(person.getLong(FormConstant.ID_KEY));
+                }
+                if(isUpdate){
+                    //修改
+                    executeOperateSave();
+                }else{
+                    //新增
+                    //最新上一考核周期
+                    DynamicObject[] newestPerfManagerByPerson = PerfManagerHelper.getNewestPerfManagerByPerson(personIds);
+                    Map<Long, DynamicObject> lastPerfManagerMap; lastPerfManagerMap = Arrays.stream(newestPerfManagerByPerson)
+                            .collect(Collectors.toMap(
+                                    perfManager -> perfManager.getDynamicObject(FormConstant.NCKD_PERSON).getLong(FormConstant.ID_KEY),
+                                    perfManager -> perfManager,
+                                    (existing, replacement) -> existing
+                            ));
+                    StringJoiner confirMmsg = new StringJoiner(",");
+                    for (DynamicObject lastPerfManager : lastPerfManagerMap.values()) {
+                        String personName = lastPerfManager.getDynamicObject(FormConstant.NCKD_PERSON).getString(FormConstant.NAME_KEY);
+                        LocalDateTime beginYear = DateUtil.toLocalDateTime(lastPerfManager.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR));
+                        LocalDateTime endYear = DateUtil.toLocalDateTime(lastPerfManager.getDate(PerfManagerFormConstant.NCKD_ENDYEAR));
+                        confirMmsg.add(StrFormatter.format("{}(周期:{}~{})", personName, beginYear.getYear(), endYear.getYear()));
+                    }
+                    if(confirMmsg.length() > 0){
+                        // 创建回调监听器,指定回调ID和处理此回调的插件(this)
+                        ConfirmCallBackListener confirmCallBacks = new ConfirmCallBackListener(PerfManagerFormConstant.BATCHEVALCYCLE_ENTITYID, this);
+                        // 弹出确认框
+                        this.getView().showConfirm(StrFormatter.format("检测到本次新增的人员中存在【未结束】的考核周期,新周期新增成功后会自动结束上一周期,并将上一周期结束时间更新为当前新周期开始年前一年。请确认是否继续。{}", confirMmsg),
+                                MessageBoxOptions.OKCancel,
+                                ConfirmTypes.Default,
+                                confirmCallBacks);
+                    }else{
+                        executeOperateSave();
+                    }
+                }
 
+            }
+        }
     }
 
     @Override
@@ -102,50 +175,164 @@ public class BatchEvalCycleFormPlugin extends AbstractFormPlugin implements Plug
         // 判断回调ID和用户点击的按钮
         if (PerfManagerFormConstant.BATCHEVALCYCLE_ENTITYID.equals(messageBoxClosedEvent.getCallBackId())
                 && messageBoxClosedEvent.getResult() == MessageBoxResult.Yes) {
-
             executeOperateSave();
         }
     }
 
     private void executeOperateSave() {
-        DynamicObject createorg = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(FormConstant.CREATEORG_KEY));
-        DynamicObject useorg = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(FormConstant.USEORG_KEY));
-        DynamicObject org = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(FormConstant.ORG_KEY));
 
+        String isAddOrUpdate = ConvertUtil.toStr(this.getModel().getValue("nckd_isaddorupdate"));
+        boolean isUpdate = "2".equalsIgnoreCase(isAddOrUpdate);
         DynamicObjectCollection perfManagerList = this.getModel().getEntryEntity(FormConstant.NCKD_ENTRYENTITY);
-        Set<Long> personIds = new HashSet<>(perfManagerList.size());
-        List<DynamicObject> savePerfManager = new ArrayList<>();
+        List<Long> perfManagerIds = Collections.emptyList();
+        Map<Long, DynamicObject> perfManagerMap = null;
+        if(isUpdate){
+            perfManagerIds = perfManagerList.stream()
+                    .map(dynamicObject -> dynamicObject.getDynamicObject(PerfManagerFormConstant.PERFMANAGER_ENTITYID))
+                    .filter(Objects::nonNull)
+                    .map(perfManager -> perfManager.getLong(FormConstant.ID_KEY))
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toList());
+            DynamicObject[] byId = PerfManagerHelper.getById(perfManagerIds);
+            perfManagerMap = Arrays.stream(byId)
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toMap(
+                            perfManager -> perfManager.getLong(FormConstant.ID_KEY),
+                            perfManager -> perfManager,
+                            (existing, replacement) -> existing
+                    ));
+        }
+        List<DynamicObject> savePerfManagerList = new ArrayList<>();
+
         //转换为考核周期实体
         for (DynamicObject dynamicObject : perfManagerList) {
             DynamicObject person = dynamicObject.getDynamicObject(FormConstant.NCKD_PERSON);
             String personName = person.getString(FormConstant.NAME_KEY);
             LocalDateTime beginYear = DateUtil.toLocalDateTime(dynamicObject.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR));
             LocalDateTime endYear = DateUtil.toLocalDateTime(dynamicObject.getDate(PerfManagerFormConstant.NCKD_ENDYEAR));
-            DynamicObject newPerfManager = EntityHelper.newAvailableBasicEntity(PerfManagerFormConstant.PERFMANAGER_ENTITYID);
-            DynamicObjectUtils.copy(dynamicObject, newPerfManager);
-            newPerfManager.set(PerfManagerFormConstant.CREATEORG_KEY, createorg);
-            newPerfManager.set(PerfManagerFormConstant.USEORG_KEY, useorg);
-            newPerfManager.set(PerfManagerFormConstant.ORG_KEY, org);
-            newPerfManager.set(PerfManagerFormConstant.CTRLSTRATEGY_KEY, CtrlStrategyEnum.GLOBAL_SHARE.getCtrlStrategy());
-            newPerfManager.set(FormConstant.NAME_KEY, StrFormatter.format("【{}】{}~{}的考核周期",personName,beginYear.getYear(),endYear.getYear()));
-            savePerfManager.add(newPerfManager);
-            personIds.add(person.getLong(FormConstant.ID_KEY));
+            String description = dynamicObject.getString(PerfManagerFormConstant.DESCRIPTION_KEY);
+            DynamicObject savePerfManager = null;
+            if(isUpdate){
+                //修改
+                DynamicObject perfManager = dynamicObject.getDynamicObject(PerfManagerFormConstant.PERFMANAGER_ENTITYID);
+                long id = perfManager.getLong(FormConstant.ID_KEY);
+                DynamicObject dbPerfManager = perfManagerMap.get(id);
+
+
+                dbPerfManager.set(PerfManagerFormConstant.DESCRIPTION_KEY, description);
+                LocalDateTime dbBeginYear = DateUtil.toLocalDateTime(dbPerfManager.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR));
+                LocalDateTime dbEndYear = DateUtil.toLocalDateTime(dbPerfManager.getDate(PerfManagerFormConstant.NCKD_ENDYEAR));
+
+                boolean isCycleRangeChange = Boolean.FALSE;
+                DynamicObjectCollection dbPerfManagerEntry = dbPerfManager.getDynamicObjectCollection(PerfManagerFormConstant.NCKD_PERFMANAGERENTRY);
+                if(!Objects.equals(dbBeginYear, beginYear)){
+                    isCycleRangeChange = true;
+                    dbPerfManager.set(PerfManagerFormConstant.NCKD_BEGINYEAR, DateUtil.toDate(beginYear));
+                }
+                if(!Objects.equals(dbEndYear, endYear)){
+                    isCycleRangeChange = true;
+                    dbPerfManager.set(PerfManagerFormConstant.NCKD_ENDYEAR, DateUtil.toDate(endYear));
+                }
+                Iterator<DynamicObject> iterator = dbPerfManagerEntry.iterator();
+                while (iterator.hasNext()) {
+                    DynamicObject entry = iterator.next();
+                    Date appraisalYear = entry.getDate(PerfManagerFormConstant.NCKD_APPRAISALYEAR);
+                    if (appraisalYear != null) {
+                        LocalDateTime appraisalLocalDate = DateUtil.toLocalDateTime(appraisalYear);
+                        long yearsDiff = appraisalLocalDate.getYear() - dbBeginYear.getYear();
+                        // 判断年份是否在范围外
+                        if (appraisalLocalDate.getYear() < beginYear.getYear() || appraisalLocalDate.getYear() > endYear.getYear()) {
+                            // 删除不在范围内的考核结果记录
+                            iterator.remove();
+                        }
+                    }
+                }
+
+                // 考核结果写回到分录,save操作的时候会将分录的结果写回到表头
+                DynamicObject firstYearResult = dynamicObject.getDynamicObject(PerfManagerFormConstant.NCKD_FIRSTYEARRESULT);
+                DynamicObject secondYearResult = dynamicObject.getDynamicObject(PerfManagerFormConstant.NCKD_SECONDYEARRESULT);
+                DynamicObject thirdYearResult = dynamicObject.getDynamicObject(PerfManagerFormConstant.NCKD_THIRDYEARRESULT);
+
+                DynamicObject dbFirstYearResult = dbPerfManager.getDynamicObject(PerfManagerFormConstant.NCKD_FIRSTYEARRESULT);
+                DynamicObject dbSecondYearResult = dbPerfManager.getDynamicObject(PerfManagerFormConstant.NCKD_SECONDYEARRESULT);
+                DynamicObject dbThirdYearResult = dbPerfManager.getDynamicObject(PerfManagerFormConstant.NCKD_THIRDYEARRESULT);
+
+                // 判断跟数据库的有没有变化,有变化才写回到分录
+               /* Long firstYearResultId = firstYearResult != null ? firstYearResult.getLong(FormConstant.ID_KEY) : null;
+                Long dbFirstYearResultId = dbFirstYearResult != null ? dbFirstYearResult.getLong(FormConstant.ID_KEY) : null;
+                if (!Objects.equals(firstYearResultId, dbFirstYearResultId) || isCycleRangeChange) {
+                    updateAppraisalResult(dbPerfManagerEntry, beginYear, firstYearResult, 0);
+                }
+
+                Long secondYearResultId = secondYearResult != null ? secondYearResult.getLong(FormConstant.ID_KEY) : null;
+                Long dbSecondYearResultId = dbSecondYearResult != null ? dbSecondYearResult.getLong(FormConstant.ID_KEY) : null;
+                if (!Objects.equals(secondYearResultId, dbSecondYearResultId) || isCycleRangeChange) {
+                    updateAppraisalResult(dbPerfManagerEntry, beginYear, secondYearResult, 1);
+                }
+
+                Long thirdYearResultId = thirdYearResult != null ? thirdYearResult.getLong(FormConstant.ID_KEY) : null;
+                Long dbThirdYearResultId = dbThirdYearResult != null ? dbThirdYearResult.getLong(FormConstant.ID_KEY) : null;
+                if (!Objects.equals(thirdYearResultId, dbThirdYearResultId) || isCycleRangeChange) {
+                    updateAppraisalResult(dbPerfManagerEntry, beginYear, thirdYearResult, 2);
+                }*/
+                savePerfManager = dbPerfManager;
+            }else{
+                //新增
+                savePerfManager = EntityHelper.newAvailableBasicEntity(PerfManagerFormConstant.PERFMANAGER_ENTITYID);
+                DynamicObjectUtils.copy(dynamicObject, savePerfManager);
+                savePerfManager.set(PerfManagerFormConstant.CTRLSTRATEGY_KEY, CtrlStrategyEnum.GLOBAL_SHARE.getCtrlStrategy());
+                savePerfManager.set(FormConstant.NAME_KEY, StrFormatter.format("【{}】{}~{}的考核周期",personName,beginYear.getYear(),endYear.getYear()));
+            }
+            savePerfManagerList.add(savePerfManager);
         }
 
         OperateOption option = OperateOption.create();
         option.setVariableValue(OperateOptionConst.IGNOREINTERACTION, Boolean.TRUE+"");
-        OperationResult operationResult =  OperationServiceHelper.executeOperate(FormConstant.SAVE_OP, PerfManagerFormConstant.PERFMANAGER_ENTITYID, savePerfManager.toArray(new DynamicObject[0]), option);
+        //告诉OP此次操作类型
+        option.setVariableValue("isUpdate", isUpdate+"");
+        OperationResult operationResult =  OperationServiceHelper.executeOperate(FormConstant.SAVE_OP, PerfManagerFormConstant.PERFMANAGER_ENTITYID, savePerfManagerList.toArray(new DynamicObject[0]), option);
 
         if (!operationResult.isSuccess()) {
-            StringJoiner errorMsg = new StringJoiner(StrFormatter.LINE_SEPARATOR);
+            StringJoiner errorMsgJoiner = new StringJoiner(StrFormatter.LINE_SEPARATOR);
             for (IOperateInfo error : operationResult.getAllErrorOrValidateInfo()) {
-                errorMsg.add(error.getMessage());
+                errorMsgJoiner.add(error.getMessage());
             }
-            throw new ValidationException(errorMsg.toString());
+            String errorMsg = errorMsgJoiner.toString();
+            if(StringUtils.isBlank(errorMsg)){
+                errorMsg = operationResult.getMessage();
+            }
+            throw new ValidationException(errorMsg);
         }else{
             this.getView().getParentView().showSuccessNotification("保存成功");
             this.getView().getParentView().invokeOperation(FormConstant.REFRESH_OP);
             this.getView().close();
         }
     }
+
+
+    private void updateAppraisalResult(DynamicObjectCollection perfManagerEntry,
+                                       LocalDateTime beginYear,
+                                       DynamicObject result,
+                                       int yearOffset) {
+        boolean isExist = false;
+        for (DynamicObject entry : perfManagerEntry) {
+            Date appraisalYear = entry.getDate(PerfManagerFormConstant.NCKD_APPRAISALYEAR);
+            if (appraisalYear != null) {
+                LocalDateTime appraisalLocalDate = DateUtil.toLocalDateTime(appraisalYear);
+                long yearsDiff = appraisalLocalDate.getYear() - beginYear.getYear();
+                if (yearsDiff == yearOffset) {
+                    entry.set(PerfManagerFormConstant.NCKD_APPRAISALRESULT, result);
+                    isExist = true;
+                    break;
+                }
+            }
+        }
+
+        if (!isExist) {
+            DynamicObject entry = perfManagerEntry.addNew();
+            entry.set(PerfManagerFormConstant.NCKD_APPRAISALYEAR,
+                    DateUtil.toDate(DateUtil.addYears(beginYear, yearOffset)));
+            entry.set(PerfManagerFormConstant.NCKD_APPRAISALRESULT, result);
+        }
+    }
 }

+ 35 - 31
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/cycle/PerfManagerListPlugin.java

@@ -1,55 +1,29 @@
 package nckd.jxccl.opmc.pm.plugin.form.cycle;
 
-import kd.bos.algo.Algo;
-import kd.bos.algo.AlgoContext;
-import kd.bos.algo.DataSet;
-import kd.bos.algo.Row;
-import kd.bos.common.enums.EnableEnum;
-import kd.bos.consts.PermItemConst;
-import kd.bos.context.RequestContext;
 import kd.bos.dataentity.OperateOption;
 import kd.bos.dataentity.entity.DynamicObject;
-import kd.bos.dataentity.entity.DynamicObjectCollection;
-import kd.bos.entity.EntityMetadataCache;
-import kd.bos.entity.QueryEntityType;
+import kd.bos.entity.datamodel.ListSelectedRowCollection;
 import kd.bos.entity.operate.OperateOptionConst;
-import kd.bos.entity.operate.result.IOperateInfo;
 import kd.bos.entity.operate.result.OperationResult;
-import kd.bos.ext.hr.service.query.QueryEntityHelper;
 import kd.bos.form.CloseCallBack;
 import kd.bos.form.FormShowParameter;
 import kd.bos.form.MessageBoxOptions;
 import kd.bos.form.ShowType;
+import kd.bos.form.StyleCss;
 import kd.bos.form.control.events.ItemClickEvent;
+import kd.bos.form.events.AfterDoOperationEventArgs;
 import kd.bos.form.events.BeforeDoOperationEventArgs;
-import kd.bos.form.events.ClosedCallBackEvent;
 import kd.bos.form.operate.FormOperate;
 import kd.bos.list.plugin.AbstractListPlugin;
-import kd.bos.orm.query.QCP;
-import kd.bos.orm.query.QFilter;
 import kd.bos.servicehelper.operation.OperationServiceHelper;
-import kd.hr.hbp.common.model.AuthorizedOrgResultWithSub;
-import kd.hr.hbp.common.model.OrgSubInfo;
-import kd.sdk.hr.hbp.business.helper.permission.HRPermissionServiceHelper;
 import kd.sdk.plugin.Plugin;
 import nckd.jxccl.base.common.constant.FormConstant;
-import nckd.jxccl.base.common.constant.SystemQueryConstant;
-import nckd.jxccl.base.common.enums.AppraisalResultEnum;
 import nckd.jxccl.base.common.exception.ValidationException;
-import nckd.jxccl.base.common.utils.DateUtil;
-import nckd.jxccl.base.common.utils.QueryFieldBuilder;
-import nckd.jxccl.base.common.utils.StrFormatter;
+import nckd.jxccl.base.common.utils.ConvertUtil;
 import nckd.jxccl.base.entity.helper.EntityHelper;
 import nckd.jxccl.opmc.pm.common.PerfManagerFormConstant;
-import nckd.jxccl.opmc.pm.plugin.operate.cycle.PerfManagerSaveOpPlugin;
 
-import java.time.LocalDateTime;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
-import java.util.StringJoiner;
 import java.util.stream.Collectors;
 
 /**
@@ -65,7 +39,6 @@ public class PerfManagerListPlugin extends AbstractListPlugin implements Plugin
     public void itemClick(ItemClickEvent evt) {
         String itemKey = evt.getItemKey();
         if ("nckd_new".equals(itemKey)) {
-            //弹出【批量】在职人员初定窗口
             FormShowParameter showParameter = new FormShowParameter();
             showParameter.setFormId(PerfManagerFormConstant.BATCHEVALCYCLE_ENTITYID);
             showParameter.getOpenStyle().setShowType(ShowType.Modal);
@@ -80,6 +53,7 @@ public class PerfManagerListPlugin extends AbstractListPlugin implements Plugin
     public void beforeDoOperation(BeforeDoOperationEventArgs args) {
         String operateKey = ((FormOperate) args.getSource()).getOperateKey();
         if (operateKey.equals("list_cyclegenerate")) {
+            //周期生成
             OperateOption option = OperateOption.create();
             option.setVariableValue(OperateOptionConst.IGNOREINTERACTION, Boolean.TRUE+"");
             DynamicObject perfManager = EntityHelper.newEntity(PerfManagerFormConstant.PERFMANAGER_ENTITYID);
@@ -100,4 +74,34 @@ public class PerfManagerListPlugin extends AbstractListPlugin implements Plugin
             }
         }
     }
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs e) {
+        if(e.getOperationResult() != null && e.getOperationResult().isSuccess()) {
+            String operateKey = e.getOperateKey();
+            if ("batchupdate".equals(operateKey)) {
+
+                this.getView().setVisible(Boolean.FALSE, "nckd_advconbaritemap","nckd_advconbaritemap1");
+                ListSelectedRowCollection selectedRows = this.getSelectedRows();
+                FormShowParameter showParameter = new FormShowParameter();
+                showParameter.setFormId(PerfManagerFormConstant.BATCHEVALCYCLE_ENTITYID);
+                showParameter.getOpenStyle().setShowType(ShowType.Modal);
+                showParameter.setCaption("批量修改考核周期");
+                showParameter.setSendToClient(true);
+                showParameter.setCloseCallBack(new CloseCallBack(this, PerfManagerFormConstant.BATCHEVALCYCLE_ENTITYID));
+                showParameter.setCustomParam("nckd_isaddorupdate","2");
+                if(!selectedRows.isEmpty()) {
+                    List<Long> selectedIds = selectedRows.stream()
+                            .map(row -> ConvertUtil.toLong(row.getPrimaryKeyValue()))
+                            .collect(Collectors.toList());
+                    showParameter.setCustomParam("selectedRows", selectedIds);
+                }
+                StyleCss styleCss = new StyleCss();
+               /* styleCss.setWidth("1100");
+                styleCss.setHeight("600");*/
+                showParameter.getOpenStyle().setInlineStyleCss(styleCss);
+                this.getView().showForm(showParameter);
+            }
+        }
+    }
 }

+ 29 - 9
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/operate/cycle/CycleGenerateOpPlugin.java

@@ -1,6 +1,5 @@
 package nckd.jxccl.opmc.pm.plugin.operate.cycle;
 
-import com.google.common.collect.Maps;
 import kd.bos.algo.Algo;
 import kd.bos.algo.AlgoContext;
 import kd.bos.algo.DataSet;
@@ -19,7 +18,6 @@ import kd.bos.entity.operate.result.IOperateInfo;
 import kd.bos.entity.operate.result.OperationResult;
 import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
 import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
-import kd.bos.entity.plugin.args.RollbackOperationArgs;
 import kd.bos.ext.hr.service.query.QueryEntityHelper;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
@@ -99,6 +97,7 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
         for (PerfManagerSaveOpPlugin.PersonPerfInfo value : pendingCyclePersonnelMap.values()) {
             DynamicObject newPerfManager = EntityHelper.newAvailableBasicEntity(PerfManagerFormConstant.PERFMANAGER_ENTITYID);
             String personName = value.getPerson().getString(FormConstant.NAME_KEY);
+            newPerfManager.set(FormConstant.NCKD_EMPPOSORGREL, value.getEmpPosOrgRel());
             newPerfManager.set(FormConstant.NCKD_PERSON, value.getPerson());
             newPerfManager.set(PerfManagerFormConstant.NCKD_BEGINYEAR, DateUtil.toDate(value.getBeginYear()));
             newPerfManager.set(PerfManagerFormConstant.NCKD_ENDYEAR, DateUtil.toDate(value.getEndYear()));
@@ -151,8 +150,8 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
      */
     public static Map<Long, PerfManagerSaveOpPlugin.PersonPerfInfo> getPendingCyclePersonnel() {
         LocalDateTime now = DateUtil.beginOfYear(DateUtil.now());
-        LocalDateTime lastDate = now;
-        // LocalDateTime lastDate = DateUtil.minusYears(now, 1);
+        // LocalDateTime lastDate = now;
+        LocalDateTime lastDate = DateUtil.minusYears(now, 1);
         LocalDateTime lastBegin = DateUtil.beginOfYear(lastDate);
         LocalDateTime lastEnd = DateUtil.endOfYear(lastDate);
 
@@ -231,7 +230,8 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
      */
     private static DynamicObjectCollection queryNewHirePersons(QFilter filter) {
         QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
-                .addIdNumberName(FormConstant.HRPI_EMPLOYEE);
+                .addIdNumberName(FormConstant.HRPI_EMPLOYEE)
+                .addGroup(new String[]{FormConstant.HRPI_EMPPOSORGREL},FormConstant.ID_KEY);
         QueryEntityType queryEntityType = (QueryEntityType) EntityMetadataCache.getDataEntityType(SystemQueryConstant.HSPM_ASSIGNMENTQUERY);
         return QueryEntityHelper.getInstance().getQueryDyoColl(queryEntityType, queryFieldBuilder.buildSelect(), new QFilter[]{filter}, null);
     }
@@ -245,6 +245,7 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
             List<Long> orgIds = extractOrgIds(userAdminOrgWithSub.getHasPermOrgsWithSub());
             perfManagerFilter.and(String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ADMINORG), QCP.in, orgIds);
         }
+        perfManagerFilter.and(String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.IS_SEQLATESTRECORD), QCP.equals,EnableEnum.YES.getCode());
         return perfManagerFilter;
     }
 
@@ -258,6 +259,7 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
                 .add(PerfManagerFormConstant.NCKD_BEGINYEAR)
                 .add(PerfManagerFormConstant.NCKD_ENDYEAR)
                 .addIdNumberName(FormConstant.NCKD_PERSON)
+                .addGroup(new String[]{FormConstant.HRPI_EMPPOSORGREL},FormConstant.ID_KEY)
                 .addGroup(new String[]{PerfManagerFormConstant.PERFMANAGERENTRY}, FormConstant.ID_KEY, PerfManagerFormConstant.NCKD_APPRAISALYEAR)
                 .addIdNumberName(PerfManagerFormConstant.PERFMANAGERENTRY, PerfManagerFormConstant.NCKD_APPRAISALRESULT);
     }
@@ -282,14 +284,18 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
                                                  LocalDateTime now) {
         for (DynamicObject person : newHirePersonList) {
             long personId = person.getLong(String.join(".", FormConstant.HRPI_EMPLOYEE, FormConstant.ID_KEY));
+            long empPosOrgRelId = person.getLong(String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ID_KEY));
             // 判断是否已有周期,如果有则不生成
             if (!personIds.contains(personId)) {
+                DynamicObject empPosOrgRel = EntityHelper.newEntity(FormConstant.HRPI_EMPPOSORGREL);
+                empPosOrgRel.set(FormConstant.ID_KEY, empPosOrgRelId);
+
                 String personName = person.getString(String.join(".", FormConstant.HRPI_EMPLOYEE, FormConstant.NAME_KEY));
                 DynamicObject cyclePerson = EntityHelper.newEntity(FormConstant.HRPI_EMPLOYEE);
                 cyclePerson.set(FormConstant.ID_KEY, personId);
                 cyclePerson.set(FormConstant.NAME_KEY, personName);
                 PerfManagerSaveOpPlugin.PersonPerfInfo personPerfInfo = new PerfManagerSaveOpPlugin.PersonPerfInfo(
-                        cyclePerson, DateUtil.toDate(now), DateUtil.toDate(DateUtil.addYears(now, 2)), "周期生成(新入职)");
+                        cyclePerson,empPosOrgRel, DateUtil.toDate(now), DateUtil.toDate(DateUtil.addYears(now, 2)), "周期生成(新入职)");
                 personPerfInfo.setWhyEnd("新入职员工");
                 personPerfInfoMap.put(personId, personPerfInfo);
             }
@@ -315,17 +321,21 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
             Row next = lastYearFailFilter.next();
             Long id = next.getLong(FormConstant.ID_KEY);
             Long personId = next.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
+            Long empPosOrgRelId = next.getLong(String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ID_KEY));
             String personName = next.getString(String.join(".", FormConstant.NCKD_PERSON, FormConstant.NAME_KEY));
             String appraisalResult = next.getString(String.join(".", PerfManagerFormConstant.PERFMANAGERENTRY,
                     PerfManagerFormConstant.NCKD_APPRAISALRESULT, FormConstant.NUMBER_KEY));
             Date endYear = next.getDate(PerfManagerFormConstant.NCKD_ENDYEAR);
 
+            DynamicObject empPosOrgRel = EntityHelper.newEntity(FormConstant.HRPI_EMPPOSORGREL);
+            empPosOrgRel.set(FormConstant.ID_KEY, empPosOrgRelId);
+
             DynamicObject person = EntityHelper.newEntity(FormConstant.HRPI_EMPLOYEE);
             person.set(FormConstant.ID_KEY, personId);
             person.set(FormConstant.NAME_KEY, personName);
 
             PerfManagerSaveOpPlugin.PersonPerfInfo personPerfInfo = new PerfManagerSaveOpPlugin.PersonPerfInfo(
-                    person, DateUtil.toDate(now), DateUtil.toDate(DateUtil.addYears(now, 2)), "周期生成");
+                    person,empPosOrgRel, DateUtil.toDate(now), DateUtil.toDate(DateUtil.addYears(now, 2)), "周期生成");
             personPerfInfo.setId(id);
 
             LocalDateTime endYearLocalDateTime = DateUtil.toLocalDateTime(endYear);
@@ -361,11 +371,13 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
         Map<Long, String> personIdAndPersonNameMap = new HashMap<>();
         Map<Long, Long> personIdAndIdMap = new HashMap<>();
         Map<Long, Date> personIdAndEndDateMap = new HashMap<>();
+        Map<Long, Long> personIdAndEmpPosOrgRelMap = new HashMap<>();
 
         while (lastYearNoPerfFilter.hasNext()) {
             Row next = lastYearNoPerfFilter.next();
             Long id = next.getLong(FormConstant.ID_KEY);
             Long personId = next.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
+            Long empPosOrgRelId = next.getLong(String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ID_KEY));
             String personName = next.getString(String.join(".", FormConstant.NCKD_PERSON, FormConstant.NAME_KEY));
             String appraisalResultNumber = next.getString(String.join(".", PerfManagerFormConstant.PERFMANAGERENTRY,
                     PerfManagerFormConstant.NCKD_APPRAISALRESULT, FormConstant.NUMBER_KEY));
@@ -379,6 +391,7 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
                 personIdAndPersonNameMap.put(personId, personName);
                 personIdAndIdMap.put(personId, id);
                 personIdAndEndDateMap.put(personId, endYear);
+                personIdAndEmpPosOrgRelMap.put(personId, empPosOrgRelId);
             }
         }
 
@@ -390,12 +403,15 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
 
         for (Long filteredPersonId : filteredPersonIds) {
             String personName = personIdAndPersonNameMap.get(filteredPersonId);
+            DynamicObject empPosOrgRel = EntityHelper.newEntity(FormConstant.HRPI_EMPPOSORGREL);
+            empPosOrgRel.set(FormConstant.ID_KEY, personIdAndEmpPosOrgRelMap.get(filteredPersonId));
+
             DynamicObject person = EntityHelper.newEntity(FormConstant.HRPI_EMPLOYEE);
             person.set(FormConstant.ID_KEY, filteredPersonId);
             person.set(FormConstant.NAME_KEY, personName);
 
             PerfManagerSaveOpPlugin.PersonPerfInfo personPerfInfo = new PerfManagerSaveOpPlugin.PersonPerfInfo(
-                    person, DateUtil.toDate(now), DateUtil.toDate(DateUtil.addYears(now, 2)), "周期生成");
+                    person,empPosOrgRel, DateUtil.toDate(now), DateUtil.toDate(DateUtil.addYears(now, 2)), "周期生成");
             personPerfInfo.setId(personIdAndIdMap.get(filteredPersonId));
             personPerfInfo.setWhyEnd("上年度无绩效结果");
 
@@ -423,16 +439,20 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
             Row next = yearEvalEndFilter.next();
             Long id = next.getLong(FormConstant.ID_KEY);
             Long personId = next.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
+            Long empPosOrgRelId = next.getLong(String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ID_KEY));
             String personName = next.getString(String.join(".", FormConstant.NCKD_PERSON, FormConstant.NAME_KEY));
             Date endYear = next.getDate(PerfManagerFormConstant.NCKD_ENDYEAR);
 
             if (personPerfInfoMap.get(personId) == null) {
+                DynamicObject empPosOrgRel = EntityHelper.newEntity(FormConstant.HRPI_EMPPOSORGREL);
+                empPosOrgRel.set(FormConstant.ID_KEY, empPosOrgRelId);
+
                 DynamicObject person = EntityHelper.newEntity(FormConstant.HRPI_EMPLOYEE);
                 person.set(FormConstant.ID_KEY, personId);
                 person.set(FormConstant.NAME_KEY, personName);
 
                 PerfManagerSaveOpPlugin.PersonPerfInfo personPerfInfo = new PerfManagerSaveOpPlugin.PersonPerfInfo(
-                        person, DateUtil.toDate(now), DateUtil.toDate(DateUtil.addYears(now, 2)), "周期生成");
+                        person,empPosOrgRel, DateUtil.toDate(now), DateUtil.toDate(DateUtil.addYears(now, 2)), "周期生成");
                 personPerfInfo.setId(id);
                 personPerfInfo.setWhyEnd("三年考评周期结束(周期生成)");
 

+ 1 - 1
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/operate/cycle/PerfManagerDeleteOpPlugin.java

@@ -43,7 +43,7 @@ public class PerfManagerDeleteOpPlugin extends AbstractOperationServicePlugIn im
                     DynamicObject data = rowDataEntity.getDataEntity();
                     boolean isCurrentNewest = data.getBoolean(PerfManagerFormConstant.NCKD_ISCURRENTNEWEST);
                     if(!isCurrentNewest){
-                        addMessage(rowDataEntity,"不能删除历史周期,只能删除最新考核周期");
+                        // addMessage(rowDataEntity,"不能删除历史周期,只能删除最新考核周期");
                     }
                     String theStatus = data.getString(PerfManagerFormConstant.NCKD_THESTATUS);
                     if(!"1".equalsIgnoreCase(theStatus)){

+ 131 - 75
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/operate/cycle/PerfManagerSaveOpPlugin.java

@@ -23,6 +23,7 @@ import kd.bos.servicehelper.QueryServiceHelper;
 import kd.bos.servicehelper.operation.SaveServiceHelper;
 import kd.sdk.plugin.Plugin;
 import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.utils.ConvertUtil;
 import nckd.jxccl.base.common.utils.DateUtil;
 import nckd.jxccl.base.common.utils.QueryFieldBuilder;
 import nckd.jxccl.base.common.utils.StrFormatter;
@@ -32,7 +33,6 @@ import org.apache.commons.lang3.StringUtils;
 
 import java.time.LocalDateTime;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
@@ -51,11 +51,10 @@ import java.util.stream.Collectors;
  */
 public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn implements Plugin {
 
-    private List<PersonPerfInfo> personPerfInfos = new ArrayList<>();
 
-    private Map<Long, DynamicObject> lastPerfManagerMap;
+    private Map<Long, DynamicObject> lastPerfManagerMap = new HashMap<>();
 
-    private  List<Long> personIds;
+    private  List<Long> personIds = new ArrayList<>();
     private  List<Long> ids = new ArrayList<>();
 
     private final static String INTERACTION_SPONORE = PerfManagerSaveOpPlugin.class.getName();
@@ -77,66 +76,67 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
                     Date endYear = data.getDate(PerfManagerFormConstant.NCKD_ENDYEAR);
                     String description = data.getString(FormConstant.DESCRIPTION_KEY);
                     DynamicObjectCollection perfManagerEntry = data.getDynamicObjectCollection(PerfManagerFormConstant.NCKD_PERFMANAGERENTRY);
-                    PersonPerfInfo personPerfInfo = new PersonPerfInfo(person, beginYear, endYear, description, dataEntityIndex, perfManagerEntry);
-                    if(id > 0){
-                        personPerfInfo.setId(id);
-                        ids.add(id);
-                    }
-                    personPerfInfos.add(personPerfInfo);
+                    personIds.add(person.getLong(FormConstant.ID_KEY));
+                    ids.add(id);
                 }
 
                 QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                         .addIdNumberName(FormConstant.NCKD_PERSON)
                         .add(PerfManagerFormConstant.NCKD_BEGINYEAR)
                         .add(PerfManagerFormConstant.NCKD_ENDYEAR);
-                personIds = personPerfInfos.stream()
-                        .map(personPerfInfo -> personPerfInfo.getPerson().getLong(FormConstant.ID_KEY))
-                        .collect(Collectors.toList());
-                QFilter filter = new QFilter(FormConstant.NCKD_PERSON, QCP.in, personIds)
-                        .and(PerfManagerFormConstant.NCKD_THESTATUS,QCP.equals,"1");
-                if(!ids.isEmpty()){
+                QFilter filter = new QFilter(FormConstant.NCKD_PERSON, QCP.in, personIds);
+                if(!ids.isEmpty()) {
                     filter = filter.and(new QFilter(FormConstant.ID_KEY, QCP.not_in, ids));
                 }
+                //根据人员查询出当前自己之外的其他考核周期
                 DynamicObjectCollection query = QueryServiceHelper.query(PerfManagerFormConstant.PERFMANAGER_ENTITYID, queryFieldBuilder.buildSelect(), new QFilter[]{filter});
-
-                //开始校验 - 优化后的代码
+                //按人员分组
                 Map<Long, List<DynamicObject>> groupedQueryResults = query.stream()
                         .collect(Collectors.groupingBy(
                                 dynamicObject -> dynamicObject.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY))
                         ));
-
-                for (PersonPerfInfo personPerfInfo : personPerfInfos) {
-
-                    long personId = personPerfInfo.getPerson().getLong(FormConstant.ID_KEY);
-                    LocalDateTime beginYear = personPerfInfo.getBeginYear();
-                    LocalDateTime endYear = personPerfInfo.getEndYear();
+                for (ExtendedDataEntity rowDataEntity : getDataEntities()) {
+                    DynamicObject data = rowDataEntity.getDataEntity();
+                    DynamicObject person = data.getDynamicObject(FormConstant.NCKD_PERSON);
+                    long personId = person.getLong(FormConstant.ID_KEY);
+                    String personName = person.getString(FormConstant.NAME_KEY);
+                    LocalDateTime beginYear = ConvertUtil.toLocalDateTime(data.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR));
+                    LocalDateTime endYear = ConvertUtil.toLocalDateTime(data.getDate(PerfManagerFormConstant.NCKD_ENDYEAR));
 
                     // 判断beginYear和endYear是不是间隔3年,例如:开始2025年,结束必须为2027年
                     if (beginYear != null && endYear != null) {
                         int beginYearValue = beginYear.getYear();
                         int endYearValue = endYear.getYear();
                         if (endYearValue - beginYearValue != 2) {
-                            addFatalErrorMessage(getDataEntities()[personPerfInfo.getDataEntityIndex()],
+                            addFatalErrorMessage(rowDataEntity,
                                     StrFormatter.format("周期开始年份【{}】与结束年份【{}】必须间隔3年,请检查!",
                                             beginYearValue, endYearValue));
                         }
                     }
 
-
                     //校验是否存在相同周期开始年的记录 begin
                     List<DynamicObject> personRecords = groupedQueryResults.getOrDefault(personId, Collections.emptyList());
                     for (DynamicObject dynamicObject : personRecords) {
                         LocalDateTime dbBeginYear = DateUtil.toLocalDateTime(dynamicObject.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR));
                         //判断beginYear和dbBeginYear的年份是否相同
                         if (isSameYear(beginYear, dbBeginYear)) {
-                            addFatalErrorMessage(getDataEntities()[personPerfInfo.getDataEntityIndex()],
+                            addFatalErrorMessage(rowDataEntity,
                                     StrFormatter.format("人员【{}】已经存在周期开始年份【{}】的周期,无需进行创建。",
-                                            personPerfInfo.getPerson().getString(FormConstant.NAME_KEY),
+                                            personName,
                                             beginYear.getYear()));
                         }
+                        //当前周期必须大于之前周期的开始时间
+                        /*if (beginYear != null && beginYear.isBefore(dbBeginYear)) {
+                            addFatalErrorMessage(rowDataEntity,
+                                    StrFormatter.format("人员【{}】当前周期开始时间【{}】必须大于之前周期开始时间【{}】。",
+                                            personName,
+                                            beginYear.getYear(),
+                                            dbBeginYear.getYear()));
+                        }*/
                     }
+
                     //校验是否存在相同周期开始年的记录 end
-                    DynamicObjectCollection entrys = personPerfInfo.getEntrys();
+                    DynamicObjectCollection entrys = data.getDynamicObjectCollection(PerfManagerFormConstant.NCKD_PERFMANAGERENTRY);
                     if(entrys != null) {
                         List<Date> dateList = entrys.stream().map(entry -> entry.getDate(PerfManagerFormConstant.NCKD_APPRAISALYEAR)).collect(Collectors.toList());
                         if (beginYear != null && endYear != null) {
@@ -151,7 +151,7 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
 
                             if (!outOfRangeYears.isEmpty()) {
                                 String outOfRangeYearsStr = String.join(",", outOfRangeYears);
-                                addFatalErrorMessage(getDataEntities()[personPerfInfo.getDataEntityIndex()],
+                                addFatalErrorMessage(rowDataEntity,
                                         StrFormatter.format("考评年份【{}】不在周期范围内,请检查!", outOfRangeYearsStr));
                             }
                         }
@@ -159,11 +159,13 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
                         List<String> duplicateYears = getDuplicateYears(dateList);
                         if (!duplicateYears.isEmpty()) {
                             String duplicateYearsStr = String.join(",", duplicateYears);
-                            addFatalErrorMessage(getDataEntities()[personPerfInfo.getDataEntityIndex()],
+                            addFatalErrorMessage(rowDataEntity,
                                     StrFormatter.format("考评结果存在重复的考核年份【{}】,请检查!", duplicateYearsStr));
                         }
                     }
 
+                    //规则: 如果年度排名管理中已存在某年度的考核结果,则不允许在人员考评管理中修改该年度的考核结果。
+                    //规则: 对于已处理的调薪情况,不允许修改或删除相关的年度考核结果。
                 }
             }
 
@@ -175,6 +177,10 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
 
     @Override
     public void beforeExecuteOperationTransaction(BeforeOperationArgs e) {
+        if(!this.getOperationResult().isSuccess()){
+            e.setCancel(true);
+            return;
+        }
         //最新上一考核周期
         QFilter filter = null;
         if(!ids.isEmpty()) {
@@ -190,10 +196,6 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
 
         String ignoreInteraction = this.getOption().getVariableValue(OperateOptionConst.IGNOREINTERACTION, "");
         if(!"true".equalsIgnoreCase(ignoreInteraction)){
-            personIds = personPerfInfos.stream()
-                    .map(personPerfInfo -> personPerfInfo.getPerson().getLong(FormConstant.ID_KEY))
-                    .collect(Collectors.toList());
-
             StringJoiner confirMmsg = new StringJoiner(",");
             for (DynamicObject lastPerfManager : lastPerfManagerMap.values()) {
                 String personName = lastPerfManager.getDynamicObject(FormConstant.NCKD_PERSON).getString(FormConstant.NAME_KEY);
@@ -208,7 +210,7 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
 
     }
     @Override
-    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+        public void beginOperationTransaction(BeginOperationTransactionArgs e) {
         //事务开始之后将其他考核周期设置为非最新
         PerfManagerHelper.markAsNotCurrentNewest(personIds.toArray(new Long[0]));
 
@@ -226,18 +228,90 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
             }
             //上一周期标记为“已结束”并设置“实际结束时间” begin
             DynamicObject lastPerfManager = lastPerfManagerMap.get(personId);
-            if(lastPerfManager != null && "1".equalsIgnoreCase(lastPerfManager.getString(PerfManagerFormConstant.NCKD_THESTATUS))) {
-                lastPerfManager.set(PerfManagerFormConstant.NCKD_THESTATUS, "3");
-                LocalDateTime localDateTime = DateUtil.minusYears(beginYear, 1);
-                lastPerfManager.set(PerfManagerFormConstant.NCKD_ACTENDYEAR, DateUtil.toDate(localDateTime));
-                dataEntity.set(PerfManagerFormConstant.NCKD_LASTPERFMANAGER, lastPerfManagerMap.get(personId));
+            if(lastPerfManager != null) {
+                if("1".equalsIgnoreCase(lastPerfManager.getString(PerfManagerFormConstant.NCKD_THESTATUS))) {
+                    lastPerfManager.set(PerfManagerFormConstant.NCKD_THESTATUS, "3");
+                    LocalDateTime localDateTime = DateUtil.minusYears(beginYear, 1);
+                    lastPerfManager.set(PerfManagerFormConstant.NCKD_ACTENDYEAR, DateUtil.toDate(localDateTime));
+                    dataEntity.set(PerfManagerFormConstant.NCKD_LASTPERFMANAGER, lastPerfManagerMap.get(personId));
+                }
+
+                LocalDateTime lastBeginYear = DateUtil.toLocalDateTime(lastPerfManager.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR));
+                LocalDateTime lastEndYear = DateUtil.toLocalDateTime(lastPerfManager.getDate(PerfManagerFormConstant.NCKD_ENDYEAR));
+                if(!Objects.equals(lastBeginYear, beginYear) || !Objects.equals(lastEndYear, endYear)) {
+                    //当周期范围发生变化,需要保障数据连续性:若新旧考评周期存在重叠年份,且该年份在旧周期中已存在来源于【年度绩效排名】的考核结果,则新周期将自动继承该结果。
+                    DynamicObjectCollection lastPerfManagerEntrys = lastPerfManager.getDynamicObjectCollection(PerfManagerFormConstant.NCKD_PERFMANAGERENTRY);
+                    DynamicObjectCollection perfManagerEntrys = dataEntity.getDynamicObjectCollection(PerfManagerFormConstant.NCKD_PERFMANAGERENTRY);
+                    for (DynamicObject lastPerfManagerEntry : lastPerfManagerEntrys) {
+                        Date lastAppraisalYear = lastPerfManagerEntry.getDate(PerfManagerFormConstant.NCKD_APPRAISALYEAR);
+                        DynamicObject appraisalResult = lastPerfManagerEntry.getDynamicObject(PerfManagerFormConstant.NCKD_APPRAISALRESULT);
+                        if (lastAppraisalYear != null && appraisalResult != null) {
+                            boolean isAllRankSource = lastPerfManagerEntry.getBoolean(PerfManagerFormConstant.NCKD_ISALLRANKSOURCE);
+                            if (isAllRankSource) {
+                                LocalDateTime lastAppraisalYearLocalDateTime = DateUtil.toLocalDateTime(lastAppraisalYear);
+                                //判断appraisalYearLocalDateTime是不是在beginYear和endYear之间
+                                if (DateUtil.isInRange(lastAppraisalYearLocalDateTime, beginYear, endYear)) {
+                                    boolean isExist = false;
+                                    for (DynamicObject perfManager : perfManagerEntrys) {
+                                        Date appraisalYear = perfManager.getDate(PerfManagerFormConstant.NCKD_APPRAISALYEAR);
+                                        if(appraisalYear != null){
+                                            //如果分录存在相同年份则更新
+                                            LocalDateTime appraisalYearLocalDateTime = DateUtil.toLocalDateTime(appraisalYear);
+                                            if(appraisalYearLocalDateTime.getYear() == lastAppraisalYearLocalDateTime.getYear()){
+                                                perfManager.set(PerfManagerFormConstant.NCKD_APPRAISALRESULT, appraisalResult);
+                                                isExist = true;
+                                            }
+                                        }
+                                    }
+                                    if(!isExist) {
+                                        //分录不存在当前年份,则添加
+                                        DynamicObject dynamicObject = perfManagerEntrys.addNew();
+                                        dynamicObject.set(PerfManagerFormConstant.NCKD_APPRAISALYEAR, lastAppraisalYear);
+                                        dynamicObject.set(PerfManagerFormConstant.NCKD_APPRAISALRESULT, appraisalResult);
+                                        dynamicObject.set(PerfManagerFormConstant.NCKD_ISALLRANKSOURCE, true);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
             }
             //上一周期标记为“已结束”并设置“实际结束时间” end
-        }
-
 
-        DynamicObject[] lastPerfManagerArray = lastPerfManagerMap.values().toArray(new DynamicObject[0]);
-        SaveServiceHelper.update(lastPerfManagerArray);
+            dataEntity.set(PerfManagerFormConstant.NCKD_FIRSTYEARRESULT, null);
+            dataEntity.set(PerfManagerFormConstant.NCKD_SECONDYEARRESULT, null);
+            dataEntity.set(PerfManagerFormConstant.NCKD_THIRDYEARRESULT, null);
+            DynamicObjectCollection entrys = dataEntity.getDynamicObjectCollection(PerfManagerFormConstant.NCKD_PERFMANAGERENTRY);
+            for (DynamicObject entry : entrys) {
+                boolean isAllRankSource = entry.getBoolean(PerfManagerFormConstant.NCKD_ISALLRANKSOURCE);
+                Date appraisalYear = entry.getDate(PerfManagerFormConstant.NCKD_APPRAISALYEAR);
+                DynamicObject appraisalResult = entry.getDynamicObject(PerfManagerFormConstant.NCKD_APPRAISALRESULT);
+
+                if (appraisalYear != null && appraisalResult != null) {
+                    LocalDateTime appraisalLocalDate = DateUtil.toLocalDateTime(appraisalYear);
+                    LocalDateTime beginLocalDate = beginYear;
+
+                    // 计算是第几年(分录中的年份-(周期开始时间 + 1))
+                    long yearsDiff = appraisalLocalDate.getYear() - beginLocalDate.getYear() + 1;
+                    // 根据年份差异设置表头对应的考核结果字段
+                    switch ((int) yearsDiff) {
+                        case 1:
+                            dataEntity.set(PerfManagerFormConstant.NCKD_FIRSTYEARRESULT, appraisalResult);
+                            break;
+                        case 2:
+                            dataEntity.set(PerfManagerFormConstant.NCKD_SECONDYEARRESULT, appraisalResult);
+                            break;
+                        case 3:
+                            dataEntity.set(PerfManagerFormConstant.NCKD_THIRDYEARRESULT, appraisalResult);
+                            break;
+                    }
+                }
+            }
+        }
+        if(lastPerfManagerMap != null && !lastPerfManagerMap.values().isEmpty()) {
+            DynamicObject[] lastPerfManagerArray = lastPerfManagerMap.values().toArray(new DynamicObject[0]);
+            SaveServiceHelper.update(lastPerfManagerArray);
+        }
     }
 
     @Override
@@ -260,7 +334,7 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
         InteractionContext interactionContext = new InteractionContext();
         interactionContext.setSimpleMessage("存在【未结束】的考核周期");
         OperateErrorInfo errorInfo = new OperateErrorInfo();
-        errorInfo.setMessage(StrFormatter.format("检测到本次新增的人员中存在【未结束】的考核周期,新周期新增成功后会自动结束上一周期。{}", confirMmsg));
+        errorInfo.setMessage(StrFormatter.format("检测到本次新增的人员中存在【未结束】的考核周期,新周期新增成功后会自动结束上一周期,并将上一周期结束时间更新为当前新周期开始年前一年。{}", confirMmsg));
         errorInfo.setLevel(ErrorLevel.Warning);
 
         Map<String, String> custInfos = new HashMap<>();
@@ -297,34 +371,35 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
     public static class PersonPerfInfo {
         private  Long id;
         private final DynamicObject person;
+        private final DynamicObject empPosOrgRel;
         private final LocalDateTime beginYear;
         private final LocalDateTime endYear;
         private final String description;
         private int dataEntityIndex;
         private DynamicObjectCollection entrys;
-        private DynamicObject useorg;
-        private DynamicObject org;
-        private DynamicObject createorg;
         private String whyEnd;
         private LocalDateTime actEndYear;
 
-        public PersonPerfInfo(DynamicObject person, Date beginYear, Date endYear, String description) {
+        public PersonPerfInfo(DynamicObject person,DynamicObject empPosOrgRel, Date beginYear, Date endYear, String description) {
             this.person = person;
+            this.empPosOrgRel = empPosOrgRel;
             this.beginYear = DateUtil.toLocalDateTime(beginYear);
             this.endYear = DateUtil.toLocalDateTime(endYear);
             this.description = description;
         }
 
-        public PersonPerfInfo(DynamicObject person, Date beginYear, Date endYear, String description, int dataEntityIndex) {
+        public PersonPerfInfo(DynamicObject person, DynamicObject empPosOrgRel, Date beginYear, Date endYear, String description, int dataEntityIndex) {
             this.person = person;
+            this.empPosOrgRel = empPosOrgRel;
             this.beginYear = DateUtil.toLocalDateTime(beginYear);
             this.endYear = DateUtil.toLocalDateTime(endYear);
             this.description = description;
             this.dataEntityIndex = dataEntityIndex;
         }
 
-        public PersonPerfInfo(DynamicObject person, Date beginYear, Date endYear, String description, int dataEntityIndex, DynamicObjectCollection entrys) {
+        public PersonPerfInfo(DynamicObject person, DynamicObject empPosOrgRel, Date beginYear, Date endYear, String description, int dataEntityIndex, DynamicObjectCollection entrys) {
             this.person = person;
+            this.empPosOrgRel = empPosOrgRel;
             this.beginYear = DateUtil.toLocalDateTime(beginYear);
             this.endYear = DateUtil.toLocalDateTime(endYear);
             this.description = description;
@@ -352,33 +427,14 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
             return person;
         }
 
-        public DynamicObjectCollection getEntrys() {
-            return entrys;
-        }
-
-        public DynamicObject getCreateorg() {
-            return createorg;
+        public DynamicObject getEmpPosOrgRel() {
+            return empPosOrgRel;
         }
 
-        public void setCreateorg(DynamicObject createorg) {
-            this.createorg = createorg;
-        }
-
-        public DynamicObject getOrg() {
-            return org;
-        }
-
-        public void setOrg(DynamicObject org) {
-            this.org = org;
-        }
-
-        public DynamicObject getUseorg() {
-            return useorg;
+        public DynamicObjectCollection getEntrys() {
+            return entrys;
         }
 
-        public void setUseorg(DynamicObject useorg) {
-            this.useorg = useorg;
-        }
 
         public Long getId() {
             return id;

+ 91 - 91
code/wtc/nckd-jxccl-wtc/src/main/java/nckd/jxccl/wtc/task/SyncPunchCardTask.java

@@ -1,92 +1,92 @@
-package nckd.jxccl.wtc.task;
-
-import com.alibaba.fastjson.JSON;
-import com.hikvision.artemis.sdk.ArtemisHttpUtil;
-import com.hikvision.artemis.sdk.config.ArtemisConfig;
-import kd.bos.context.RequestContext;
-import kd.bos.entity.param.CustomParam;
-import kd.bos.exception.KDException;
-import kd.bos.schedule.executor.AbstractTask;
-import kd.bos.servicehelper.parameter.SystemParamServiceHelper;
-import kd.sdk.plugin.Plugin;
-import nckd.jxccl.wtc.utils.SyncPunchCardHelper;
-import com.alibaba.fastjson.JSONArray;
-import com.alibaba.fastjson.JSONObject;
-
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 后台任务插件
- */
-public class SyncPunchCardTask extends AbstractTask implements Plugin {
-    private static final String ARTEMIS_PATH = "/artemis";
-    static final String getCamsApi = ARTEMIS_PATH + "/api/acs/v2/door/events";
-    static Map<String, String> path = new HashMap<String, String>(2) {
-        {
-            put("https://", getCamsApi);
-        }
-    };
-
-    public void initConfig() {
-        CustomParam customParam = new CustomParam();
-        customParam.getSearchKeySet().add("PUNCH_CARD_HOST");
-        customParam.getSearchKeySet().add("PUNCH_CARD_APP_KEY");
-        customParam.getSearchKeySet().add("PUNCH_CARD_APP_SECRET");
-        Map<String, String> cusTomMap = SystemParamServiceHelper.loadCustomParameterFromCache(customParam);
-        ArtemisConfig.host  = cusTomMap.get("PUNCH_CARD_HOST");
-        ArtemisConfig.appKey = cusTomMap.get("PUNCH_CARD_APP_KEY");
-        ArtemisConfig.appSecret = cusTomMap.get("PUNCH_CARD_APP_SECRET");
-    }
-
-    @Override
-    public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
-        try {
-            initConfig();
-            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
-            Calendar date = Calendar.getInstance();
-            System.out.println(sdf.format(date.getTime()));
-            String endTime = sdf.format(date.getTime()) + "T23:59:59+08:00";
-            Integer days = Integer.valueOf(map.get("days").toString());
-            date.set(Calendar.DATE, date.get(Calendar.DATE) - days);
-            System.out.println(sdf.format(date.getTime()));
-            String startTime = sdf.format(date.getTime()) + "T00:00:00+08:00";
-            getAllCards(startTime, endTime);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static void getAllCards(String startTime, String endTime) {
-        JSONObject firstPageJson = getOnePageCard(startTime, endTime, 1);
-        JSONArray firstPageListJson = firstPageJson.getJSONArray("list");
-        // 保存第一页
-        SyncPunchCardHelper.savePunchCardData(firstPageListJson);
-        Integer totalPage = firstPageJson.getInteger("totalPage");
-        if (totalPage <= 1) {
-            return;
-        }
-        // 从第二页开始保存
-        for(int i=2; i<=totalPage; i++) {
-            JSONObject pageJson = getOnePageCard(startTime, endTime, i);
-            JSONArray pageListJson = pageJson.getJSONArray("list");
-            SyncPunchCardHelper.savePunchCardData(pageListJson);
-        }
-    }
-
-    public static JSONObject getOnePageCard(String startTime, String endTime, int pageNo) {
-        JSONObject jsonBody = new JSONObject();
-        jsonBody.put("pageNo", pageNo);
-        jsonBody.put("pageSize", 1000);
-        jsonBody.put("startTime", startTime);
-        jsonBody.put("endTime", endTime);
-        jsonBody.put("userId", "admin");
-        String body = jsonBody.toString();
-        String result = ArtemisHttpUtil.doPostStringArtemis(path, body, null, null, "application/json", null);
-        JSONObject jsonData = JSON.parseObject(result).getJSONObject("data");
-        return jsonData;
-    }
-
+package nckd.jxccl.wtc.task;
+
+import com.alibaba.fastjson.JSON;
+import com.hikvision.artemis.sdk.ArtemisHttpUtil;
+import com.hikvision.artemis.sdk.config.ArtemisConfig;
+import kd.bos.context.RequestContext;
+import kd.bos.entity.param.CustomParam;
+import kd.bos.exception.KDException;
+import kd.bos.schedule.executor.AbstractTask;
+import kd.bos.servicehelper.parameter.SystemParamServiceHelper;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.wtc.utils.SyncPunchCardHelper;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 后台任务插件
+ */
+public class SyncPunchCardTask extends AbstractTask implements Plugin {
+    private static final String ARTEMIS_PATH = "/artemis";
+    static final String getCamsApi = ARTEMIS_PATH + "/api/acs/v2/door/events";
+    static Map<String, String> path = new HashMap<String, String>(2) {
+        {
+            put("https://", getCamsApi);
+        }
+    };
+
+    public void initConfig() {
+        CustomParam customParam = new CustomParam();
+        customParam.getSearchKeySet().add("PUNCH_CARD_HOST");
+        customParam.getSearchKeySet().add("PUNCH_CARD_APP_KEY");
+        customParam.getSearchKeySet().add("PUNCH_CARD_APP_SECRET");
+        Map<String, String> cusTomMap = SystemParamServiceHelper.loadCustomParameterFromCache(customParam);
+        ArtemisConfig.host  = cusTomMap.get("PUNCH_CARD_HOST");
+        ArtemisConfig.appKey = cusTomMap.get("PUNCH_CARD_APP_KEY");
+        ArtemisConfig.appSecret = cusTomMap.get("PUNCH_CARD_APP_SECRET");
+    }
+
+    @Override
+    public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
+        try {
+            initConfig();
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+            Calendar date = Calendar.getInstance();
+            System.out.println(sdf.format(date.getTime()));
+            String endTime = sdf.format(date.getTime()) + "T23:59:59+08:00";
+            Integer days = Integer.valueOf(map.get("days").toString());
+            date.set(Calendar.DATE, date.get(Calendar.DATE) - days);
+            System.out.println(sdf.format(date.getTime()));
+            String startTime = sdf.format(date.getTime()) + "T00:00:00+08:00";
+            getAllCards(startTime, endTime);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static void getAllCards(String startTime, String endTime) {
+        JSONObject firstPageJson = getOnePageCard(startTime, endTime, 1);
+        JSONArray firstPageListJson = firstPageJson.getJSONArray("list");
+        // 保存第一页
+        SyncPunchCardHelper.savePunchCardData(firstPageListJson);
+        Integer totalPage = firstPageJson.getInteger("totalPage");
+        if (totalPage <= 1) {
+            return;
+        }
+        // 从第二页开始保存
+        for(int i=2; i<=totalPage; i++) {
+            JSONObject pageJson = getOnePageCard(startTime, endTime, i);
+            JSONArray pageListJson = pageJson.getJSONArray("list");
+            SyncPunchCardHelper.savePunchCardData(pageListJson);
+        }
+    }
+
+    public static JSONObject getOnePageCard(String startTime, String endTime, int pageNo) {
+        JSONObject jsonBody = new JSONObject();
+        jsonBody.put("pageNo", pageNo);
+        jsonBody.put("pageSize", 1000);
+        jsonBody.put("startTime", startTime);
+        jsonBody.put("endTime", endTime);
+        jsonBody.put("userId", "admin");
+        String body = jsonBody.toString();
+        String result = ArtemisHttpUtil.doPostStringArtemis(path, body, null, null, "application/json", null);
+        JSONObject jsonData = JSON.parseObject(result).getJSONObject("data");
+        return jsonData;
+    }
+
 }