Răsfoiți Sursa

feat(performance): 新增年度绩效归档与撤销归档功能

- 在绩效管理中增加归档与撤销归档操作支持
- 实现归档状态校验,防止已归档数据被修改
- 添加归档记录实体及常量定义
- 更新表单插件以支持归档相关操作按钮
- 调整调薪跟踪列表插件包路径并增强操作回调逻辑
- 引入事务控制优化推送调薪操作的数据一致性
- 完善错误提示机制提升用户体验
wyc 1 săptămână în urmă
părinte
comite
dc548a5c7c

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

@@ -7,12 +7,14 @@ import kd.bos.dataentity.entity.DynamicObjectCollection;
 import kd.bos.entity.MainEntityType;
 import kd.bos.entity.operate.OperateOptionConst;
 import kd.bos.entity.operate.result.IOperateInfo;
+import kd.bos.entity.operate.result.OperateErrorInfo;
 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.entity.validate.ErrorLevel;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
 import kd.bos.servicehelper.BusinessDataServiceHelper;

+ 11 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/common/PerfManagerFormConstant.java

@@ -64,4 +64,15 @@ public class PerfManagerFormConstant extends FormConstant {
     /** 是否参与排名 */
     public static final String NCKD_ISRANKING = "nckd_isranking";
     /*-------------------------------------- 年度全排名 end --------------------------------------*/
+
+    /*-------------------------------------- 年度绩效归档记录 begin --------------------------------------*/
+    /** 年度绩效归档记录-实体标识 */
+    public static final String PERFARCHIVERECORD_ENTITYID = "nckd_perfarchiverecord";
+    /** 状态 */
+    public static final String NCKD_ARCHIVESTATUS = "nckd_archivestatus";
+    /** 归档 */
+    public static final String ARCHIVE_OP = "archive";
+    /** 撤销归档 */
+    public static final String UNARCHIVE_OP = "unarchive";
+    /*-------------------------------------- 年度绩效归档记录 end --------------------------------------*/
 }

+ 0 - 24
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/SalAdjtTackerListPlugin.java

@@ -1,24 +0,0 @@
-package nckd.jxccl.opmc.pm.plugin.form;
-
-import kd.bos.list.plugin.AbstractListPlugin;
-import kd.sdk.plugin.Plugin;
-import nckd.jxccl.base.common.constant.FormConstant;
-
-import java.util.EventObject;
-
-/**
-* 调薪情况列表插件
-* @author W.Y.C
-* @date 2025/6/9 18:43
-* @version 1.0
-*/
-public class SalAdjtTackerListPlugin extends AbstractListPlugin implements Plugin {
-
-    @Override
-    public void afterBindData(EventObject e) {
-        super.afterBindData(e);
-        this.getView().setVisible(false, FormConstant.SEARCH_DATE_KEY);
-    }
-
-
-}

+ 70 - 1
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/result/AnnualPerfDetailFormPlugin.java

@@ -1,19 +1,40 @@
 package nckd.jxccl.opmc.pm.plugin.form.result;
 
+import kd.bos.dataentity.OperateOption;
+import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.entity.datamodel.ListSelectedRowCollection;
+import kd.bos.entity.operate.result.IOperateInfo;
+import kd.bos.entity.operate.result.OperateErrorInfo;
+import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.entity.report.AbstractReportColumn;
+import kd.bos.entity.validate.ErrorLevel;
 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.events.AfterDoOperationEventArgs;
+import kd.bos.form.events.BeforeDoOperationEventArgs;
 import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.bos.report.ReportList;
+import kd.bos.report.events.SortAndFilterEvent;
+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.ConvertUtil;
+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.common.SalAdjTrackerConstant;
 
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
+import java.util.StringJoiner;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
 * 年度绩效结果明细-插件
@@ -24,16 +45,64 @@ import java.util.stream.Collectors;
 */
 public class AnnualPerfDetailFormPlugin extends AbstractFormPlugin implements Plugin {
 
+
     @Override
     public void afterDoOperation(AfterDoOperationEventArgs e) {
         if(e.getOperationResult() != null && e.getOperationResult().isSuccess()) {
             String operateKey = e.getOperateKey();
             if ("deemedresult".equals(operateKey)) {
-
                 FormShowParameter showParameter = new FormShowParameter();
                 showParameter.setFormId("nckd_updateresult");
                 showParameter.getOpenStyle().setShowType(ShowType.Modal);
                 this.getView().showForm(showParameter);
+            }else if (Stream.of(PerfManagerFormConstant.ARCHIVE_OP, PerfManagerFormConstant.UNARCHIVE_OP)
+                    .anyMatch(op -> op.equalsIgnoreCase(operateKey))) {
+                //获取报表选中的数据
+                ReportList reportList = this.getView().getControl("reportlistap");
+                int[] selectedRows = reportList.getEntryState().getSelectedRows();
+                if(selectedRows != null && selectedRows.length > 0){
+                    List<DynamicObject> saveData = new ArrayList<>(selectedRows.length);
+                    for (int rowIndex : selectedRows) {
+                        // 获取指定行的数据
+                        DynamicObject rowData = reportList.getReportModel().getRowData(rowIndex);
+                        DynamicObject person = rowData.getDynamicObject(FormConstant.NCKD_PERSON);
+                        DynamicObject dynamicObject = EntityHelper.newEntity(PerfManagerFormConstant.PERFMANAGER_ENTITYID);
+                        dynamicObject.set(FormConstant.NCKD_PERSON, person);
+                        saveData.add(dynamicObject);
+                    }
+                    OperateOption operateOption = OperateOption.create();
+                    operateOption.setVariableValue("operateKey", operateKey);
+                    OperationResult result = OperationServiceHelper.executeOperate(
+                            "archiveorunarchive",
+                            "nckd_annualperfdetail",
+                            saveData.toArray(new DynamicObject[0]),
+                            operateOption
+                    );
+                    if (!result.isSuccess()) {
+                        StringJoiner error = new StringJoiner(StrFormatter.LINE_SEPARATOR);
+                        StringJoiner warningError = new StringJoiner(StrFormatter.LINE_SEPARATOR);
+                        for (IOperateInfo operateInfo : result.getAllErrorOrValidateInfo()) {
+                            OperateErrorInfo operateErrorInfo = (OperateErrorInfo)operateInfo;
+                            if(operateErrorInfo.getLevel()  == ErrorLevel.FatalError || operateErrorInfo.getLevel() == ErrorLevel.Error){
+                                error.add(operateErrorInfo.getMessage());
+                            }else{
+                                warningError.add(operateErrorInfo.getMessage());
+                            }
+                        }
+                        if(error.length() > 0){
+                            error.add(warningError.toString());
+                            throw new ValidationException(error.toString());
+                        } else if(warningError.length() > 0){
+                            this.getView().showTipNotification(warningError.toString());
+                        }else{
+                            throw new ValidationException(result.getMessage());
+                        }
+                    }else{
+                        //刷新列表
+                        this.getView().invokeOperation(FormConstant.REFRESH_OP);
+                        this.getView().showConfirm("提示",result.getMessage(), MessageBoxOptions.OK,null,null,null,null);
+                    }
+                }
             }
         }
     }

+ 2 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/result/AnnualPerfDetailReportListDataPlugin.java

@@ -81,6 +81,7 @@ public class AnnualPerfDetailReportListDataPlugin extends AbstractReportListData
 
         // 按分组字段聚合
         GroupbyDataSet groupbyDataSet = withYearFields.groupBy(new String[]{
+                String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY),
                 String.join(".", FormConstant.NCKD_EMPPOSORGREL, FormConstant.EMPLOYEE_KEY, FormConstant.EMP_NUMBER_KEY),
                 String.join(".", FormConstant.NCKD_EMPPOSORGREL, FormConstant.EMPLOYEE_KEY, FormConstant.NAME_KEY),
                 String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ADMINORG, FormConstant.NCKD_FIRSTORG, FormConstant.ID_KEY),
@@ -148,6 +149,7 @@ public class AnnualPerfDetailReportListDataPlugin extends AbstractReportListData
                 .addGroup(new String[]{PerfManagerFormConstant.PERFMANAGERENTRY},PerfManagerFormConstant.NCKD_APPRAISALYEAR)
                 .addGroup(new String[]{PerfManagerFormConstant.PERFMANAGERENTRY},PerfManagerFormConstant.ID_KEY)
                 .addGroup(new String[]{FormConstant.NCKD_EMPPOSORGREL,FormConstant.EMPLOYEE_KEY}, FormConstant.EMP_NUMBER_KEY, FormConstant.NAME_KEY)
+                .addIdNumberName(FormConstant.NCKD_PERSON)
                 .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.POS_STATUS)
                 .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG,FormConstant.NCKD_FIRSTORG)
                 .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG,FormConstant.NCKD_SECONDORG)

+ 30 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/salary/SalAdjtTackerListPlugin.java

@@ -0,0 +1,30 @@
+package nckd.jxccl.opmc.pm.plugin.form.salary;
+
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.list.plugin.AbstractListPlugin;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.opmc.pm.common.SalAdjTrackerConstant;
+
+import java.util.Arrays;
+import java.util.stream.Stream;
+
+/**
+* 调薪情况列表插件
+* @author W.Y.C
+* @date 2025/6/9 18:43
+* @version 1.0
+*/
+public class SalAdjtTackerListPlugin extends AbstractListPlugin implements Plugin {
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
+        String operateKey = afterDoOperationEventArgs.getOperateKey();
+        if (afterDoOperationEventArgs.getOperationResult() != null && afterDoOperationEventArgs.getOperationResult().isSuccess()) {
+            if (Stream.of(SalAdjTrackerConstant.NOPUSHADJUST_OP, SalAdjTrackerConstant.PUSHADJUST_OP)
+                    .anyMatch(op -> op.equalsIgnoreCase(operateKey))) {
+                this.getView().invokeOperation(FormConstant.REFRESH_OP);
+            }
+        }
+    }
+}

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

@@ -58,6 +58,8 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
 
     Map<Long, Date> personBeginYearMap = new HashMap<>();
     private  List<Long> ids = new ArrayList<>();
+    //分录ID
+    private  List<Long> entryIds = new ArrayList<>();
 
     private final static String INTERACTION_SPONORE = PerfManagerSaveOpPlugin.class.getName();
 
@@ -83,7 +85,6 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
                     Date beginYear = data.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR);
                     Date endYear = data.getDate(PerfManagerFormConstant.NCKD_ENDYEAR);
                     String description = data.getString(FormConstant.DESCRIPTION_KEY);
-                    DynamicObjectCollection perfManagerEntry = data.getDynamicObjectCollection(PerfManagerFormConstant.NCKD_PERFMANAGERENTRY);
                     Long personId = person.getLong(FormConstant.ID_KEY);
                     if (beginYear != null) {
                         personBeginYearMap.put(personId, beginYear);
@@ -91,6 +92,13 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
                     if (id > 0) {
                         ids.add(id);
                     }
+                    DynamicObjectCollection perfManagerEntry = data.getDynamicObjectCollection(PerfManagerFormConstant.NCKD_PERFMANAGERENTRY);
+                    if(!perfManagerEntry.isEmpty()){
+                        for (DynamicObject entry : perfManagerEntry) {
+                            long entryId = entry.getLong(FormConstant.ID_KEY);
+                            entryIds.add(entryId);
+                        }
+                    }
 
                     PersonPerfInfo perfInfo = new PersonPerfInfo(person, null,null,
                             data.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR),
@@ -139,6 +147,33 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
                     }
                 }
 
+                //获取已归档人员,已归档人员不能修改考核结果
+                QueryFieldBuilder perfArchiveRecordQueryFieldBuilder = QueryFieldBuilder.create().addIdNumberName(FormConstant.NCKD_PERSON);
+                QFilter perfArchiveRecordFilter = new QFilter(FormConstant.NCKD_PERSON, QCP.in, personBeginYearMap.keySet());
+                //查找已归档的记录(状态为1)
+                perfArchiveRecordFilter = perfArchiveRecordFilter.and(new QFilter(PerfManagerFormConstant.NCKD_ARCHIVESTATUS, QCP.equals, "1"));
+                DynamicObjectCollection perfArchiveRecordQuery = QueryServiceHelper.query(PerfManagerFormConstant.PERFARCHIVERECORD_ENTITYID, perfArchiveRecordQueryFieldBuilder.buildSelect(), new QFilter[]{perfArchiveRecordFilter});
+                // 创建已归档人员ID集合
+                Set<Long> archivedPersonIds = perfArchiveRecordQuery.stream()
+                        .map(obj -> obj.getLong(String.join( ".",FormConstant.NCKD_PERSON,FormConstant.ID_KEY)))
+                        .collect(Collectors.toSet());
+                //加载数据库中考核结果(用于后续判断是否变更)
+                Map<Long,String> entryResultMap = new HashMap<>();
+                if(!archivedPersonIds.isEmpty() && !entryIds.isEmpty()){
+                    QueryFieldBuilder perfManagerEntryQueryFieldBuilder = QueryFieldBuilder.create()
+                            .add(PerfManagerFormConstant.NCKD_PERFMANAGERENTRY,FormConstant.ID_KEY)
+                            .addIdNumberName(PerfManagerFormConstant.NCKD_PERFMANAGERENTRY,PerfManagerFormConstant.NCKD_APPRAISALRESULT);
+                    QFilter perfManagerEntryFilter = new QFilter(String.join( ".",PerfManagerFormConstant.NCKD_PERFMANAGERENTRY,FormConstant.ID_KEY), QCP.in, entryIds);
+                    DynamicObjectCollection query = QueryServiceHelper.query(PerfManagerFormConstant.PERFMANAGER_ENTITYID, perfManagerEntryQueryFieldBuilder.buildSelect(), new QFilter[]{perfManagerEntryFilter});
+                    entryResultMap = query.stream()
+                            .collect(Collectors.toMap(
+                                    obj -> obj.getLong(String.join(".", PerfManagerFormConstant.NCKD_PERFMANAGERENTRY, FormConstant.ID_KEY)),
+                                    obj -> obj.getString(String.join(".", PerfManagerFormConstant.NCKD_PERFMANAGERENTRY, PerfManagerFormConstant.NCKD_APPRAISALRESULT, FormConstant.NUMBER_KEY))
+                            ));
+
+                }
+
+
                 QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                         .addIdNumberName(FormConstant.NCKD_PERSON)
                         .add(PerfManagerFormConstant.NCKD_BEGINYEAR)
@@ -241,6 +276,26 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
                             addFatalErrorMessage(rowDataEntity,
                                     StrFormatter.format("考评结果存在重复的考核年份【{}】,请检查!", duplicateYearsStr));
                         }
+
+                        //如果是更新则需要校验是否更改已归档的考核结果
+                        if(isUpdate && !entryIds.isEmpty() && !entryResultMap.isEmpty()) {
+                            for (DynamicObject entry : entrys) {
+                                long entryId = entry.getLong(FormConstant.ID_KEY);
+                                if(entryId > 0) {
+                                    DynamicObject appraisalResult = entry.getDynamicObject(PerfManagerFormConstant.NCKD_APPRAISALRESULT);
+                                    LocalDateTime appraisalYear = DateUtil.toLocalDateTime(entry.getDate(PerfManagerFormConstant.NCKD_APPRAISALYEAR));
+                                    String appraisalResultNumber = appraisalResult != null ? appraisalResult.getString(FormConstant.NUMBER_KEY) : null;
+                                    String dbAppraisalResultNumber = entryResultMap.get(entryId);
+                                    if (!Objects.equals(appraisalResultNumber, dbAppraisalResultNumber)) {
+                                        addFatalErrorMessage(rowDataEntity,
+                                                StrFormatter.format("人员【{}】考核周期已归档,不能修改【{}】年的考核结果。",
+                                                        personName,
+                                                        appraisalYear.getYear()));
+                                    }
+                                }
+                            }
+                        }
+
                     }
 
                     //规则: 如果年度排名管理中已存在某年度的考核结果,则不允许在人员考评管理中修改该年度的考核结果。

+ 158 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/operate/result/PerfArchiveOrUnArchiveOpPlugin.java

@@ -0,0 +1,158 @@
+package nckd.jxccl.opmc.pm.plugin.operate.result;
+
+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.operate.result.IOperateInfo;
+import kd.bos.entity.operate.result.OperateErrorInfo;
+import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.AddValidatorsEventArgs;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.entity.validate.AbstractValidator;
+import kd.bos.entity.validate.ErrorLevel;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.bos.servicehelper.operation.OperationServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import kd.bos.servicehelper.user.UserServiceHelper;
+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.QueryFieldBuilder;
+import nckd.jxccl.base.common.utils.StrFormatter;
+import nckd.jxccl.base.entity.helper.EntityHelper;
+import nckd.jxccl.opmc.pm.common.PerfManagerFormConstant;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringJoiner;
+import java.util.stream.Collectors;
+
+/**
+* 年度绩效结果明细-归档/撤销归档
+* 实体标识:nckd_annualperfdetail
+* @author W.Y.C
+* @date 2025/11/26 17:15
+* @version 1.0
+*/
+public class PerfArchiveOrUnArchiveOpPlugin extends AbstractOperationServicePlugIn implements Plugin {
+
+    @Override
+    public void onAddValidators(AddValidatorsEventArgs e) {
+        e.addValidator(new AbstractValidator() {
+            @Override
+            public void validate() {
+                String operateKey = this.getOption().getVariableValue("operateKey");
+                Map<Long,Integer> personMap = new HashMap<>();
+                for (ExtendedDataEntity rowDataEntity : getDataEntities()) {
+                    DynamicObject data = rowDataEntity.getDataEntity();
+                    DynamicObject person = data.getDynamicObject(FormConstant.NCKD_PERSON);
+                    personMap.put(person.getLong(FormConstant.ID_KEY),rowDataEntity.getDataEntityIndex());
+                }
+
+                QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create().addIdNumberName(FormConstant.NCKD_PERSON);
+                QFilter qFilter = new QFilter(FormConstant.NCKD_PERSON, QCP.in, personMap.keySet().toArray());
+                //查找已归档的记录(状态为1)
+                qFilter = qFilter.and(new QFilter(PerfManagerFormConstant.NCKD_ARCHIVESTATUS, QCP.equals, "1"));
+
+                DynamicObjectCollection perfArchiveRecordQuery = QueryServiceHelper.query(PerfManagerFormConstant.PERFARCHIVERECORD_ENTITYID, queryFieldBuilder.buildSelect(), new QFilter[]{qFilter});
+                // 创建已归档人员ID集合
+                Set<Long> archivedPersonIds = perfArchiveRecordQuery.stream()
+                        .map(obj -> obj.getLong(String.join( ".",FormConstant.NCKD_PERSON,FormConstant.ID_KEY)))
+                        .collect(Collectors.toSet());
+                // 处理归档操作
+                if(PerfManagerFormConstant.ARCHIVE_OP.equalsIgnoreCase(operateKey)){
+                    for (DynamicObject dynamicObject : perfArchiveRecordQuery) {
+                        DynamicObject person = dynamicObject.getDynamicObject(FormConstant.NCKD_PERSON);
+                        String personName = dynamicObject.getString(String.join( ".",FormConstant.NCKD_PERSON,FormConstant.NAME_KEY));
+                        long personId = dynamicObject.getLong(String.join( ".",FormConstant.NCKD_PERSON,FormConstant.ID_KEY));
+                        this.addWarningMessage(getDataEntities()[personMap.get(personId)], StrFormatter.format("【{}】已归档,忽略此次处理;", personName));
+                    }
+                }
+                // 处理撤销归档操作
+                else if(PerfManagerFormConstant.UNARCHIVE_OP.equalsIgnoreCase(operateKey)){
+                    // 找出在personMap中存在但未归档的人员
+                    personMap.entrySet().stream()
+                            .filter(entry -> !archivedPersonIds.contains(entry.getKey()))
+                            .forEach(entry -> {
+                                Long personId = entry.getKey();
+                                Integer dataIndex = entry.getValue();
+
+                                DynamicObject data = getDataEntities()[dataIndex].getDataEntity();
+                                DynamicObject person = data.getDynamicObject(FormConstant.NCKD_PERSON);
+                                String personName = person.getString(FormConstant.NAME_KEY);
+                                this.addWarningMessage(getDataEntities()[dataIndex], StrFormatter.format("【{}】未归档无需撤销,忽略此次处理;", personName));
+                            });
+                }
+            }
+        });
+    }
+
+    @Override
+    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+        String operateKey = this.getOption().getVariableValue("operateKey");
+        List<DynamicObject> archiveList = new ArrayList<>();
+        List<Long> unArchivePersonList = new ArrayList<>();
+        StringJoiner personNameList = new StringJoiner(StrFormatter.LINE_SEPARATOR);
+        for (DynamicObject dataEntity : e.getDataEntities()) {
+            if(PerfManagerFormConstant.ARCHIVE_OP.equalsIgnoreCase(operateKey)){
+                DynamicObject newPerfArchiveRecord = EntityHelper.newEntity(PerfManagerFormConstant.PERFARCHIVERECORD_ENTITYID);
+                DynamicObject person = dataEntity.getDynamicObject(FormConstant.NCKD_PERSON);
+                newPerfArchiveRecord.set(PerfManagerFormConstant.NCKD_PERSON, person);
+                newPerfArchiveRecord.set(PerfManagerFormConstant.NCKD_ARCHIVESTATUS, "1");
+                newPerfArchiveRecord.set(FormConstant.CREATOR_KEY, UserServiceHelper.getCurrentUserId());
+                archiveList.add(newPerfArchiveRecord);
+                personNameList.add(StrFormatter.format("【{}】归档成功;", person.getString(FormConstant.NAME_KEY)));
+            }else if(PerfManagerFormConstant.UNARCHIVE_OP.equalsIgnoreCase(operateKey)){
+                DynamicObject person = dataEntity.getDynamicObject(FormConstant.NCKD_PERSON);
+                unArchivePersonList.add(person.getLong(FormConstant.ID_KEY));
+                personNameList.add(StrFormatter.format("【{}】撤销归档成功;", person.getString(FormConstant.NAME_KEY)));
+            }
+        }
+        if(!archiveList.isEmpty()){
+            SaveServiceHelper.save(archiveList.toArray(new DynamicObject[0]));
+        }
+        if(!unArchivePersonList.isEmpty()){
+            QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create().add(FormConstant.ID_KEY).add(PerfManagerFormConstant.NCKD_ARCHIVESTATUS);
+            QFilter qFilter = new QFilter(FormConstant.NCKD_PERSON, QCP.in, unArchivePersonList);
+            DynamicObject[] perfArchiveRecordArray = BusinessDataServiceHelper.load(PerfManagerFormConstant.PERFARCHIVERECORD_ENTITYID,queryFieldBuilder.buildSelect(), new QFilter[]{qFilter});
+            for (DynamicObject perfArchiveRecord : perfArchiveRecordArray) {
+                perfArchiveRecord.set(PerfManagerFormConstant.NCKD_ARCHIVESTATUS, "2");
+            }
+            OperationResult result = OperationServiceHelper.executeOperate(
+                    "delete",
+                    "nckd_perfarchiverecord",
+                    perfArchiveRecordArray,
+                    OperateOption.create()
+            );
+            if (!result.isSuccess()) {
+                StringJoiner error = new StringJoiner(StrFormatter.LINE_SEPARATOR);
+                StringJoiner warningError = new StringJoiner(StrFormatter.LINE_SEPARATOR);
+                for (IOperateInfo operateInfo : result.getAllErrorOrValidateInfo()) {
+                    OperateErrorInfo operateErrorInfo = (OperateErrorInfo)operateInfo;
+                    if(operateErrorInfo.getLevel()  == ErrorLevel.FatalError || operateErrorInfo.getLevel() == ErrorLevel.Error){
+                        error.add(operateErrorInfo.getMessage());
+                    }else{
+                        warningError.add(operateErrorInfo.getMessage());
+                    }
+                }
+                if(error.length() > 0){
+                    error.add(warningError.toString());
+                    throw new ValidationException(error.toString());
+                } else if(warningError.length() > 0){
+                    throw new ValidationException(warningError.toString());
+                }else{
+                    throw new ValidationException(result.getMessage());
+                }
+            }
+        }
+        this.getOperationResult().setMessage(personNameList.toString());
+    }
+}

+ 23 - 2
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/operate/salary/PushAdjustOpPlugin.java

@@ -2,11 +2,15 @@ package nckd.jxccl.opmc.pm.plugin.operate.salary;
 
 import kd.bos.context.RequestContext;
 import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.db.tx.TX;
+import kd.bos.db.tx.TXHandle;
 import kd.bos.entity.ExtendedDataEntity;
 import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
 import kd.bos.entity.plugin.AddValidatorsEventArgs;
 import kd.bos.entity.plugin.PreparePropertysEventArgs;
+import kd.bos.entity.plugin.args.AfterOperationArgs;
 import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.entity.plugin.args.EndOperationTransactionArgs;
 import kd.bos.entity.validate.AbstractValidator;
 import kd.bos.servicehelper.BusinessDataServiceHelper;
 import kd.bos.servicehelper.operation.SaveServiceHelper;
@@ -68,12 +72,14 @@ public class PushAdjustOpPlugin extends AbstractOperationServicePlugIn implement
         });
     }
 
+    List<DynamicObject> pushAdjusts = new ArrayList<>();
     @Override
     public void beginOperationTransaction(BeginOperationTransactionArgs e) {
 
         String operateKey = e.getOperationKey();
-        List<DynamicObject> pushAdjusts = new ArrayList<>();
+
         List<DynamicObject> updateAdjusts = new ArrayList<>();
+
         for (DynamicObject dataEntity : e.getDataEntities()) {
             if(SalAdjTrackerConstant.PUSHADJUST_OP.equalsIgnoreCase(operateKey)){
                 //推送调薪
@@ -96,7 +102,8 @@ public class PushAdjustOpPlugin extends AbstractOperationServicePlugIn implement
                  * 必填字段
                  * "billname", "billtype", "org", "billcountry", "salaryadjrsn", "salaryadjscm", "billcurrency", "effectivedate", "exchangeratedate", "exctable"
                  */
-                applyBill.put("billname", "岗位工资动态调整-生成");
+                DynamicObject person = pushAdjust.getDynamicObject(SalAdjTrackerConstant.NCKD_PERFMANAGER).getDynamicObject(FormConstant.NCKD_PERSON);
+                applyBill.put("billname", StrFormatter.format("【{}】的岗位工资动态调整(人员考评)",person.getString(FormConstant.NAME_KEY)));
 
                 Long orgId = RequestContext.get().getOrgId();
 
@@ -150,4 +157,18 @@ public class PushAdjustOpPlugin extends AbstractOperationServicePlugIn implement
             }
         }
     }
+
+    @Override
+    public void afterExecuteOperationTransaction(AfterOperationArgs e) {
+        if(this.getOperationResult() != null && this.getOperationResult().isSuccess()) {
+            if(!pushAdjusts.isEmpty()) {
+                for (DynamicObject pushAdjust : pushAdjusts) {
+                    pushAdjust.set(SalAdjTrackerConstant.NCKD_WAGESTATUS, "2");
+                }
+                SaveServiceHelper.update(pushAdjusts.toArray(new DynamicObject[0]));
+            }
+        }
+
+
+    }
 }