Просмотр исходного кода

feat(pm): 新增定调薪项目及考核结果枚举值

- 在FormConstant中新增HSBS_STANDARDITEM常量,用于标识定调薪项目
- 在AppraisalResultEnum中新增三个枚举值:DEEMED_EXCELLENT、DEEMED_UNQUALIFIED、DEEMED_BASICALLY_QUALIFIED
- 在PerfManagerHelper中新增对NCKD_WHYEND和NCKD_ACTENDYEAR字段的处理逻辑
- 在BatchEvalCycleFormPlugin中新增部门信息设置逻辑
- 在AnnualPerfDetailReportListDataPlugin中优化数据查询逻辑和报表列显示控制
- 新增SalaryAdjOpPlugin插件用于处理调薪操作
- 在PerfmanagerQueryListPlugin中新增薪资调整操作处理逻辑
- 在CycleGenerateOpPlugin和PerfManagerSaveOpPlugin中新增管理员组织相关处理逻辑
wyc 1 день назад
Родитель
Сommit
f5e665856d

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

@@ -50,6 +50,8 @@ public class FormConstant {
     public static final String HRPI_EMPENTREL = "hrpi_empentrel";
     /** 员工-实体标识*/
     public static final String HRPI_EMPLOYEE = "hrpi_employee";
+    /** 定调薪项目-实体标识*/
+    public static final String HSBS_STANDARDITEM = "hsbs_standarditem";
 
 
     //====================================== 标品op ======================================

+ 7 - 1
code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/enums/AppraisalResultEnum.java

@@ -26,7 +26,13 @@ public enum AppraisalResultEnum {
     /** 无考核定级 */
     NO_ASSESSMENT_GRADE("07", "无考核定级"),
     /** 良好 */
-    GOOD("08", "良好");
+    GOOD("08", "良好"),
+    /** 视同优秀*/
+    DEEMED_EXCELLENT("09", "视同优秀"),
+    /** 视同不合格*/
+    DEEMED_UNQUALIFIED("10", "视同不合格"),
+    /** 视同基本合格*/
+    DEEMED_BASICALLY_QUALIFIED("11", "视同基本合格");
 
     private static final Map<String, AppraisalResultEnum> CODE_MAP = new HashMap<>();
 

+ 2 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/helper/PerfManagerHelper.java

@@ -322,6 +322,8 @@ public class PerfManagerHelper {
             if(theStatus.equalsIgnoreCase("3")){
                 //结束状态标记为正常
                 dynamicObject.set(PerfManagerFormConstant.NCKD_THESTATUS, EnableEnum.YES.getCode());
+                dynamicObject.set(PerfManagerFormConstant.NCKD_WHYEND,null);
+                dynamicObject.set(PerfManagerFormConstant.NCKD_ACTENDYEAR,null);
             }
             updatePerfManagerColl[i] = dynamicObject;
         }

+ 36 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/PerfmanagerQueryListPlugin.java

@@ -1,10 +1,22 @@
 package nckd.jxccl.opmc.pm.plugin.form;
 
+import kd.bos.dataentity.OperateOption;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.operate.OperateOptionConst;
+import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.form.MessageBoxOptions;
 import kd.bos.form.ShowType;
 import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.events.BeforeDoOperationEventArgs;
+import kd.bos.form.operate.FormOperate;
 import kd.bos.list.plugin.AbstractListPlugin;
 import kd.bos.report.ReportShowParameter;
+import kd.bos.servicehelper.operation.OperationServiceHelper;
 import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.exception.ValidationException;
+import nckd.jxccl.base.entity.helper.EntityHelper;
+import nckd.jxccl.opmc.pm.common.PerfManagerFormConstant;
 
 /**
 * 人员考评列表
@@ -15,6 +27,30 @@ import kd.sdk.plugin.Plugin;
 */
 public class PerfmanagerQueryListPlugin extends AbstractListPlugin implements Plugin {
 
+    @Override
+    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
+        String operateKey = ((FormOperate) args.getSource()).getOperateKey();
+        if(operateKey.equals("salaryadj")){
+            //调档
+            OperateOption option = OperateOption.create();
+            option.setVariableValue(OperateOptionConst.IGNOREINTERACTION, Boolean.TRUE+"");
+            DynamicObject perfManager = EntityHelper.newEntity(PerfManagerFormConstant.PERFMANAGER_ENTITYID);
+            OperationResult operationResult =  OperationServiceHelper.executeOperate("salaryadj", PerfManagerFormConstant.PERFMANAGER_ENTITYID, new DynamicObject[]{perfManager}, option);
+            if (!operationResult.isSuccess()) {
+                int messageType = operationResult.getMessageType();
+                if (messageType == 1) {
+                    this.getView().showTipNotification(operationResult.getMessage());
+                } else {
+                    String message = operationResult.getMessage();
+                    throw new ValidationException(message);
+                }
+            }else{
+                //刷新列表
+                this.getView().invokeOperation(FormConstant.REFRESH_OP);
+                this.getView().showConfirm("提示",operationResult.getMessage(), MessageBoxOptions.OK,null,null,null,null);
+            }
+        }
+    }
 
     @Override
     public void afterDoOperation(AfterDoOperationEventArgs e) {

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

@@ -295,6 +295,8 @@ public class BatchEvalCycleFormPlugin extends AbstractFormPlugin implements Plug
                 savePerfManager.set(PerfManagerFormConstant.CREATEORG_KEY, createOrg);
                 savePerfManager.set(PerfManagerFormConstant.ORG_KEY, org);
                 savePerfManager.set(PerfManagerFormConstant.USEORG_KEY, useOrg);
+                DynamicObject empPosOrgRel = savePerfManager.getDynamicObject(FormConstant.NCKD_EMPPOSORGREL);
+                savePerfManager.set(PerfManagerFormConstant.NCKD_DEP, empPosOrgRel.getDynamicObject(FormConstant.ADMINORG));
             }
             savePerfManagerList.add(savePerfManager);
         }

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

@@ -1,6 +1,7 @@
 package nckd.jxccl.opmc.pm.plugin.form.result;
 
 import kd.bos.algo.DataSet;
+import kd.bos.algo.GroupbyDataSet;
 import kd.bos.dataentity.entity.LocaleString;
 import kd.bos.entity.EntityMetadataCache;
 import kd.bos.entity.QueryEntityType;
@@ -34,16 +35,17 @@ public class AnnualPerfDetailReportListDataPlugin extends AbstractReportListData
         // 构建查询字段
         QueryFieldBuilder queryFieldBuilder = buildQueryFieldBuilder();
 
-
+        LocalDate now = LocalDate.now();
         // 获取5年前的年份
-        int fiveYearsAgo = LocalDate.now().minusYears(5).getYear();
+        int fiveYearsAgo = LocalDate.now().minusYears(now.getYear() - 2018).getYear();
         Date beginDate = DateUtil.toDate(LocalDate.of(fiveYearsAgo, 1, 1));
 
         int currentYear = LocalDate.now().getYear() - 1; // 不包含今年
         Date endDate = DateUtil.toDate(LocalDate.of(currentYear, 1, 1));
         //查询最近5年的数据
-        QFilter qFilter = new QFilter(PerfManagerFormConstant.NCKD_BEGINYEAR, QCP.less_equals, endDate)
-                .and(new QFilter(PerfManagerFormConstant.NCKD_ENDYEAR, QCP.large_equals, beginDate));
+        /*QFilter qFilter = new QFilter(PerfManagerFormConstant.NCKD_BEGINYEAR, QCP.less_equals, endDate)
+                .and(new QFilter(PerfManagerFormConstant.NCKD_ENDYEAR, QCP.large_equals, beginDate));*/
+        QFilter qFilter = QFilter.of("1=1");
 
         // 处理快速过滤条件
         processFastFilter(reportQueryParam, qFilter);
@@ -53,7 +55,7 @@ public class AnnualPerfDetailReportListDataPlugin extends AbstractReportListData
 
         // 执行基础查询
         QueryEntityType queryEntityType = (QueryEntityType) EntityMetadataCache.getDataEntityType("annualperfdetailquery");
-        DataSet dataSet = QueryEntityHelper.getInstance().getQueryDataSet(queryEntityType,queryFieldBuilder.buildSelect(), new QFilter[]{qFilter}, null);
+        DataSet dataSet = QueryEntityHelper.getInstance().getQueryDataSet(queryEntityType,queryFieldBuilder.buildSelect(), null, null);
 
         dataSet.print( true);
 
@@ -74,33 +76,36 @@ public class AnnualPerfDetailReportListDataPlugin extends AbstractReportListData
         withYearFields.print(true);
 
         // 按分组字段聚合
-        DataSet result = withYearFields.groupBy(new String[]{
-                        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),
-                        String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ADMINORG, FormConstant.NCKD_SECONDORG,FormConstant.ID_KEY),
-                        String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ADMINORG, FormConstant.NCKD_THIRDORG,FormConstant.ID_KEY),
-                        String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ADMINORG, FormConstant.NCKD_FOURTHORG,FormConstant.ID_KEY),
-                        String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ADMINORG, FormConstant.NCKD_FIFTHORG,FormConstant.ID_KEY),
-                        String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ADMINORG, FormConstant.NCKD_SIXTHORG,FormConstant.ID_KEY),
-                        String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.POS_STATUS,FormConstant.ID_KEY),
-                        String.join(".", "last_perfmanager", PerfManagerFormConstant.NCKD_BEGINYEAR),
-                        String.join(".", "last_perfmanager", PerfManagerFormConstant.NCKD_ENDYEAR)
-                })
-                .max("temp_1", "1_result")
-                .max("temp_2", "2_result")
-                .max("temp_3", "3_result")
-                .max("temp_4", "4_result")
-                .max("temp_5", "5_result")
-                .finish();
+        GroupbyDataSet groupbyDataSet = withYearFields.groupBy(new String[]{
+                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),
+                String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ADMINORG, FormConstant.NCKD_SECONDORG, FormConstant.ID_KEY),
+                String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ADMINORG, FormConstant.NCKD_THIRDORG, FormConstant.ID_KEY),
+                String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ADMINORG, FormConstant.NCKD_FOURTHORG, FormConstant.ID_KEY),
+                String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ADMINORG, FormConstant.NCKD_FIFTHORG, FormConstant.ID_KEY),
+                String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.ADMINORG, FormConstant.NCKD_SIXTHORG, FormConstant.ID_KEY),
+                String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.POS_STATUS, FormConstant.ID_KEY),
+//                String.join(".", FormConstant.NCKD_EMPPOSORGREL, FormConstant.POSITION_KEY, FormConstant.ID_KEY),
+                String.join(".", "last_perfmanager", PerfManagerFormConstant.NCKD_BEGINYEAR),
+                String.join(".", "last_perfmanager", PerfManagerFormConstant.NCKD_ENDYEAR)
+        });
+        int tempIndex1 = 1;
+        for (int year = fiveYearsAgo; year <= currentYear; year++) {
+            groupbyDataSet
+                    .max("temp_"+tempIndex1, tempIndex1+"_result");
+            tempIndex1++;
+        }
+
+        DataSet result = groupbyDataSet.finish();
         result.print( true);
         return result;
     }
 
     @Override
     public List<AbstractReportColumn> getColumns(List<AbstractReportColumn> columns) throws Throwable {
-        // 获取5年前的年份
-        int fiveYearsAgo = LocalDate.now().minusYears(5).getYear();
+        LocalDate now = LocalDate.now();
+        int fiveYearsAgo = LocalDate.now().minusYears(now.getYear()-2018).getYear();
         int currentYear = LocalDate.now().getYear() - 1; // 不包含今年
 
         for (AbstractReportColumn column : columns) {
@@ -114,7 +119,10 @@ public class AnnualPerfDetailReportListDataPlugin extends AbstractReportListData
                         int yearIndex = Integer.parseInt(fieldKey.replace("nckd_year", ""));
                         // 设置对应年份的标题
                         int displayYear = fiveYearsAgo + yearIndex - 1;
-                        rColumn.setCaption(new LocaleString(displayYear + "年"));
+                        if(displayYear <= currentYear) {
+                            rColumn.setCaption(new LocaleString(displayYear + "年"));
+                            rColumn.setHide(false);
+                        }
                     } catch (NumberFormatException ignored) {
                     }
                 }
@@ -143,6 +151,7 @@ public class AnnualPerfDetailReportListDataPlugin extends AbstractReportListData
                 .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG,FormConstant.NCKD_FOURTHORG)
                 .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG,FormConstant.NCKD_FIFTHORG)
                 .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG,FormConstant.NCKD_SIXTHORG)
+//                .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.POSITION_KEY)
                 .addGroup(new String[]{"last_perfmanager"},
                         PerfManagerFormConstant.NCKD_BEGINYEAR,
                         PerfManagerFormConstant.NCKD_ENDYEAR);

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

@@ -95,6 +95,7 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
             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_DEP, value.getAdminOrg());
             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()));
@@ -230,7 +231,8 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
     private static DynamicObjectCollection queryNewHirePersons(QFilter filter) {
         QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                 .addIdNumberName(FormConstant.HRPI_EMPLOYEE)
-                .addGroup(new String[]{FormConstant.HRPI_EMPPOSORGREL},FormConstant.ID_KEY);
+                .addGroup(new String[]{FormConstant.HRPI_EMPPOSORGREL},FormConstant.ID_KEY)
+                .addGroup(new String[]{FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG},FormConstant.ID_KEY);
         QueryEntityType queryEntityType = (QueryEntityType) EntityMetadataCache.getDataEntityType(QueryConstant.PERSON_QUERY);
         return QueryEntityHelper.getInstance().getQueryDyoColl(queryEntityType, queryFieldBuilder.buildSelect(), new QFilter[]{filter}, null);
     }
@@ -259,6 +261,7 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
                 .add(PerfManagerFormConstant.NCKD_ENDYEAR)
                 .addIdNumberName(FormConstant.NCKD_PERSON)
                 .addGroup(new String[]{FormConstant.HRPI_EMPPOSORGREL},FormConstant.ID_KEY)
+                .addGroup(new String[]{FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG},FormConstant.ID_KEY)
                 .addGroup(new String[]{PerfManagerFormConstant.PERFMANAGERENTRY}, FormConstant.ID_KEY, PerfManagerFormConstant.NCKD_APPRAISALYEAR)
                 .addIdNumberName(PerfManagerFormConstant.PERFMANAGERENTRY, PerfManagerFormConstant.NCKD_APPRAISALRESULT);
     }
@@ -284,17 +287,21 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
         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));
+            long adminOrgId = person.getLong(String.join(".", FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG, FormConstant.ID_KEY));
             // 判断是否已有周期,如果有则不生成
             if (!personIds.contains(personId)) {
                 DynamicObject empPosOrgRel = EntityHelper.newEntity(FormConstant.HRPI_EMPPOSORGREL);
                 empPosOrgRel.set(FormConstant.ID_KEY, empPosOrgRelId);
 
+                DynamicObject adminOrg = EntityHelper.newEntity(FormConstant.ADMINORGHR_ENTITYID);
+                adminOrg.set(FormConstant.ID_KEY, adminOrgId);
+
                 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,empPosOrgRel, DateUtil.toDate(now), DateUtil.toDate(DateUtil.addYears(now, 2)), "周期生成(新入职)");
+                        cyclePerson,empPosOrgRel,adminOrg, DateUtil.toDate(now), DateUtil.toDate(DateUtil.addYears(now, 2)), "周期生成(新入职)");
                 personPerfInfo.setWhyEnd("新入职员工");
                 personPerfInfoMap.put(personId, personPerfInfo);
             }
@@ -321,6 +328,7 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
             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));
+            Long adminOrgId = next.getLong(String.join(".", FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG, 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));
@@ -329,12 +337,15 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
             DynamicObject empPosOrgRel = EntityHelper.newEntity(FormConstant.HRPI_EMPPOSORGREL);
             empPosOrgRel.set(FormConstant.ID_KEY, empPosOrgRelId);
 
+            DynamicObject adminOrg = EntityHelper.newEntity(FormConstant.ADMINORGHR_ENTITYID);
+            adminOrg.set(FormConstant.ID_KEY, adminOrgId);
+
             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,empPosOrgRel, DateUtil.toDate(now), DateUtil.toDate(DateUtil.addYears(now, 2)), "周期生成");
+                    person,empPosOrgRel,adminOrg ,DateUtil.toDate(now), DateUtil.toDate(DateUtil.addYears(now, 2)), "周期生成");
             personPerfInfo.setId(id);
 
             LocalDateTime endYearLocalDateTime = DateUtil.toLocalDateTime(endYear);
@@ -371,12 +382,14 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
         Map<Long, Long> personIdAndIdMap = new HashMap<>();
         Map<Long, Date> personIdAndEndDateMap = new HashMap<>();
         Map<Long, Long> personIdAndEmpPosOrgRelMap = new HashMap<>();
+        Map<Long, Long> personIdAndAdminOrgMap = 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));
+            Long adminOrgId = next.getLong(String.join(".", FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG, 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));
@@ -391,6 +404,7 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
                 personIdAndIdMap.put(personId, id);
                 personIdAndEndDateMap.put(personId, endYear);
                 personIdAndEmpPosOrgRelMap.put(personId, empPosOrgRelId);
+                personIdAndAdminOrgMap.put(personId, adminOrgId);
             }
         }
 
@@ -405,12 +419,15 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
             DynamicObject empPosOrgRel = EntityHelper.newEntity(FormConstant.HRPI_EMPPOSORGREL);
             empPosOrgRel.set(FormConstant.ID_KEY, personIdAndEmpPosOrgRelMap.get(filteredPersonId));
 
+            DynamicObject adminOrg = EntityHelper.newEntity(FormConstant.ADMINORGHR_ENTITYID);
+            adminOrg.set(FormConstant.ID_KEY, personIdAndAdminOrgMap.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,empPosOrgRel, DateUtil.toDate(now), DateUtil.toDate(DateUtil.addYears(now, 2)), "周期生成");
+                    person,empPosOrgRel,adminOrg, DateUtil.toDate(now), DateUtil.toDate(DateUtil.addYears(now, 2)), "周期生成");
             personPerfInfo.setId(personIdAndIdMap.get(filteredPersonId));
             personPerfInfo.setWhyEnd("上年度无绩效结果");
 
@@ -439,6 +456,7 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
             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));
+            Long adminOrgId = next.getLong(String.join(".", FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG, FormConstant.ID_KEY));
             String personName = next.getString(String.join(".", FormConstant.NCKD_PERSON, FormConstant.NAME_KEY));
             Date endYear = next.getDate(PerfManagerFormConstant.NCKD_ENDYEAR);
 
@@ -446,12 +464,15 @@ public class CycleGenerateOpPlugin extends AbstractOperationServicePlugIn implem
                 DynamicObject empPosOrgRel = EntityHelper.newEntity(FormConstant.HRPI_EMPPOSORGREL);
                 empPosOrgRel.set(FormConstant.ID_KEY, empPosOrgRelId);
 
+                DynamicObject adminOrg = EntityHelper.newEntity(FormConstant.ADMINORGHR_ENTITYID);
+                adminOrg.set(FormConstant.ID_KEY, adminOrgId);
+
                 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,empPosOrgRel, DateUtil.toDate(now), DateUtil.toDate(DateUtil.addYears(now, 2)), "周期生成");
+                        person,empPosOrgRel,adminOrg, DateUtil.toDate(now), DateUtil.toDate(DateUtil.addYears(now, 2)), "周期生成");
                 personPerfInfo.setId(id);
                 personPerfInfo.setWhyEnd("三年考评周期结束(周期生成)");
 

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

@@ -82,7 +82,7 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
                         ids.add(id);
                     }
 
-                    PersonPerfInfo perfInfo = new PersonPerfInfo(person, null,
+                    PersonPerfInfo perfInfo = new PersonPerfInfo(person, null,null,
                             data.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR),
                             data.getDate(PerfManagerFormConstant.NCKD_ENDYEAR),
                             data.getString(FormConstant.DESCRIPTION_KEY),
@@ -644,6 +644,7 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
         private  Long id;
         private final DynamicObject person;
         private final DynamicObject empPosOrgRel;
+        private final DynamicObject adminOrg;
         private final LocalDateTime beginYear;
         private final LocalDateTime endYear;
         private final String description;
@@ -652,26 +653,30 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
         private String whyEnd;
         private LocalDateTime actEndYear;
 
-        public PersonPerfInfo(DynamicObject person,DynamicObject empPosOrgRel, Date beginYear, Date endYear, String description) {
+
+        public PersonPerfInfo(DynamicObject person,DynamicObject empPosOrgRel,DynamicObject adminOrg, Date beginYear, Date endYear, String description) {
             this.person = person;
             this.empPosOrgRel = empPosOrgRel;
+            this.adminOrg = adminOrg;
             this.beginYear = DateUtil.toLocalDateTime(beginYear);
             this.endYear = DateUtil.toLocalDateTime(endYear);
             this.description = description;
         }
 
-        public PersonPerfInfo(DynamicObject person, DynamicObject empPosOrgRel, Date beginYear, Date endYear, String description, int dataEntityIndex) {
+        public PersonPerfInfo(DynamicObject person, DynamicObject empPosOrgRel,DynamicObject adminOrg, Date beginYear, Date endYear, String description, int dataEntityIndex) {
             this.person = person;
             this.empPosOrgRel = empPosOrgRel;
+            this.adminOrg = adminOrg;
             this.beginYear = DateUtil.toLocalDateTime(beginYear);
             this.endYear = DateUtil.toLocalDateTime(endYear);
             this.description = description;
             this.dataEntityIndex = dataEntityIndex;
         }
 
-        public PersonPerfInfo(DynamicObject person, DynamicObject empPosOrgRel, Date beginYear, Date endYear, String description, int dataEntityIndex, DynamicObjectCollection entrys) {
+        public PersonPerfInfo(DynamicObject person, DynamicObject empPosOrgRel,DynamicObject adminOrg, Date beginYear, Date endYear, String description, int dataEntityIndex, DynamicObjectCollection entrys) {
             this.person = person;
             this.empPosOrgRel = empPosOrgRel;
+            this.adminOrg = adminOrg;
             this.beginYear = DateUtil.toLocalDateTime(beginYear);
             this.endYear = DateUtil.toLocalDateTime(endYear);
             this.description = description;
@@ -707,7 +712,9 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
             return entrys;
         }
 
-
+        public DynamicObject getAdminOrg() {
+            return adminOrg;
+        }
         public Long getId() {
             return id;
         }

+ 436 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/operate/salary/SalaryAdjOpPlugin.java

@@ -0,0 +1,436 @@
+package nckd.jxccl.opmc.pm.plugin.operate.salary;
+
+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.entity.DynamicObject;
+import kd.bos.entity.EntityMetadataCache;
+import kd.bos.entity.QueryEntityType;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.entity.validate.BillStatus;
+import kd.bos.ext.hr.service.query.QueryEntityHelper;
+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.servicehelper.DispatchServiceHelper;
+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 kd.sdk.swc.hcdm.business.helper.HCDMAdjFileServiceHelper;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.enums.AppraisalResultEnum;
+import nckd.jxccl.base.common.exception.ValidationException;
+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.entity.helper.EntityHelper;
+import nckd.jxccl.opmc.pm.common.PerfManagerFormConstant;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+* 生成调薪
+* 实体标识:nckd_saladjtracker
+* @author W.Y.C
+* @date 2025/11/24 13:14
+* @version 1.0
+*/
+public class SalaryAdjOpPlugin extends AbstractOperationServicePlugIn implements Plugin {
+
+    private static final Log logger = LogFactory.getLog(SalaryAdjOpPlugin.class);
+
+    // 调薪类型常量
+    /**不及格降档*/
+    private static final int TYPE_DEMOTE_FOR_FAIL = -1;
+    /**及格升档*/
+    private static final int TYPE_NO_CHANGE = 0;         // 不升不降档
+    /**双优升档*/
+    private static final int TYPE_PROMOTE_FOR_TWO_EXCELLENT = 1;  // 双优升档
+    /**三及格升档*/
+    private static final int TYPE_PROMOTE_FOR_THREE_PASS = 2;     // 三及格升档
+    /**双优以及三及格升档*/
+    private static final int TYPE_PROMOTE_FOR_TWO_EXCELLENT_AND_THREE_PASS = 3; // 双优以及三及格
+    /**连续两年考核结果为优秀且另一年考核结果为合格及以上*/
+    private static final int TYPE_PROMOTE_FOR_TWO_EXCELLENT_AND_THREE_PASS_FOR_TWO_YEARS = 4;
+    /** 岗位工资标准(jt002)*/
+    private static final Long standardItemId = 2321899710350111744L;
+
+
+    int passYear = 2018;
+
+    @Override
+    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+
+
+        Long currUserId = RequestContext.get().getCurrUserId();
+        // 只处理权限范围内的人员
+        AuthorizedOrgResultWithSub userAdminOrgWithSub = HRPermissionServiceHelper.getUserAdminOrgsWithSub(
+                currUserId, "nckd_pm", PerfManagerFormConstant.PERFMANAGER_ENTITYID,
+                PermItemConst.ITEM_VIEW, "hrpi_empposorgrel.adminorg", new HashMap<>());
+        // 构建考核周期查询条件
+        QFilter perfManagerFilter = buildPerfManagerFilter(userAdminOrgWithSub);
+        QueryFieldBuilder perfManagerQueryFieldBuilder = buildPerfManagerQueryFieldBuilder();
+        QueryEntityType perfManagerQueryEntityType = (QueryEntityType) EntityMetadataCache.getDataEntityType("nckd_perfmanager_query");
+
+        Map<Long,SalaryAdjustmentResult> salaryAdjustmentResultMap = new HashMap<>();
+        try (AlgoContext context = Algo.newContext()) {
+            // 查询权限范围内的考核周期
+            DataSet queryDataSet = QueryEntityHelper.getInstance().getQueryDataSet(
+                    perfManagerQueryEntityType, perfManagerQueryFieldBuilder.buildSelectLowerCase(),
+                    new QFilter[]{perfManagerFilter}, perfManagerQueryFieldBuilder.buildOrder());
+            queryDataSet.print(true);
+            while (queryDataSet.hasNext()) {
+                Row next = queryDataSet.next();
+                //对应:Personappraisaladminid
+                long id = next.getLong(FormConstant.ID_KEY);
+                long personId = next.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
+                LocalDateTime beginDate = DateUtil.toLocalDateTime(next.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR));
+                int beginYear = beginDate.getYear();
+                LocalDateTime endDate = DateUtil.toLocalDateTime(next.getDate(PerfManagerFormConstant.NCKD_ENDYEAR));
+                int endYear = endDate.getYear();
+                Date actEndDate = next.getDate(PerfManagerFormConstant.NCKD_ACTENDYEAR);
+                LocalDateTime actEndLocalDateTime = actEndDate != null ? DateUtil.toLocalDateTime(actEndDate) : endDate;
+                int actEndYear = actEndLocalDateTime.getYear();
+                String theStatus = next.getString(PerfManagerFormConstant.NCKD_THESTATUS);
+                if (actEndYear <= passYear) {
+                    logger.info(">>>周期开始时间在上线前!PASS!!");
+                    continue;
+                }
+                if (theStatus != null && !"1".equals(theStatus)) {
+                    logger.info(">>>周期状态非正常!PASS!!");
+                    continue;
+                }
+                int nowYear = Calendar.getInstance().get(Calendar.YEAR);
+                if (nowYear < beginYear) {
+                    logger.info(">>>还未到周期开始时间!PASS!!");
+                    continue;
+                }
+                //第一年考核结果
+                String firstYearResultNumber = next.getString(String.join(".", PerfManagerFormConstant.NCKD_FIRSTYEARRESULT, FormConstant.NUMBER_KEY));
+                AppraisalResultEnum firstYearResult = AppraisalResultEnum.getByCode(firstYearResultNumber);
+                //第二年考核结果
+                String secondYearResultNumber = next.getString(String.join(".", PerfManagerFormConstant.NCKD_SECONDYEARRESULT, FormConstant.NUMBER_KEY));
+                AppraisalResultEnum secondYearResult = AppraisalResultEnum.getByCode(secondYearResultNumber);
+                //第三年考核结果
+                String thirdYearResultNumber = next.getString(String.join(".", PerfManagerFormConstant.NCKD_THIRDYEARRESULT, FormConstant.NUMBER_KEY));
+                AppraisalResultEnum thirdYearResult = AppraisalResultEnum.getByCode(thirdYearResultNumber);
+                
+                // 计算调薪档次
+                SalaryAdjustmentResult result = calculateSalaryAdjustmentLevel(firstYearResult, secondYearResult, thirdYearResult, beginYear, endYear);
+                logger.info("人员ID: {} 的调薪档次为: {},调薪类型: {},调薪说明: {}", personId, result.level, result.type, result.reason);
+                if(result.level > 0){
+                    salaryAdjustmentResultMap.put(personId, result);
+                }
+            }
+        }
+//        if(!salaryAdjustmentResultMap.isEmpty()){
+        DynamicObject standardItem = EntityHelper.newEntity(FormConstant.HSBS_STANDARDITEM);
+        standardItem.set(FormConstant.ID_KEY, standardItemId);
+        List<Long> personIds = new ArrayList<>();
+            personIds.add(2311775636290546688L);
+            personIds.add(2313784485549715456L);
+            personIds.add(2313784485549715456L);
+            personIds.add(2313986306029400064L);
+            personIds.add(2313986306029400064L);
+            personIds.add(2313985716754853888L);
+            personIds.add(2313985716754853888L);
+            personIds.add(2324801894234460160L);
+            personIds.add(2321890608861426688L);
+            personIds.add(2321890608861426688L);
+            personIds.add(2324801894234460160L);
+            personIds.add(2311773642125487104L);
+            personIds.add(2311773642125487104L);
+            personIds.add(2311775067064774656L);
+            personIds.add(2311775636290546688L);
+            personIds.add(2311775067064774656L);
+            personIds.add(2329770917598607370L);
+            personIds.add(2330584474036731904L);
+            personIds.add(2329770917598607370L);
+            personIds.add(2329770917598607370L);
+            personIds.add(2330584474036731904L);
+            personIds.add(2330584474036731904L);
+            personIds.add(2313985716754853888L);
+            personIds.add(2313985716754853888L);
+            Map<String, Object> params = new HashMap<>();
+            params.put("employees", personIds);
+            List<String> status = new ArrayList<>();
+            status.add(BillStatus.C.toString());
+            params.put("status", status);
+            //获取人员定薪档案
+            Map<String, Object> result = DispatchServiceHelper.invokeBizService("swc", "hcdm", "IAdjFileInfoService", "queryAdjFileBoByEmp", params);
+            if(ConvertUtil.toBoolean(result.get("success"))){
+                List<Map> list = ConvertUtil.toList(result.get("data"), ArrayList::new);
+                List<Long> adjFileIds = new ArrayList<>();
+                for (Map map : list) {
+                    Long id = ConvertUtil.toLong(map.get(FormConstant.ID_KEY));
+                    adjFileIds.add(id);
+                }
+                System.out.println();
+                Map<String, Object> param = new HashMap<>();
+                List<Map<String, Object>> dataList = new ArrayList<>();
+                for (Long adjFileId : adjFileIds) {
+                    Map<String, Object> dataItem = new HashMap<>();
+                    // 调薪档案ID
+                    dataItem.put("adjfile", adjFileId);
+                    // 调薪项目ID
+                    dataItem.put("standarditem", standardItemId);
+                    // 查询基准日期
+                    dataItem.put("startdate", new Date());
+                    // 唯一标识
+                    dataItem.put("_uniquecode", "unique"+adjFileId);
+                    dataList.add(dataItem);
+                }
+
+                param.put("data", dataList);
+                //查询定调薪记录
+                Map<String, Object> lastDecAdjRecords = HCDMAdjFileServiceHelper.getLastDecAdjRecords(param);
+                if(ConvertUtil.toBoolean(lastDecAdjRecords.get("success"))){
+                    List<Map> datas = ConvertUtil.toList(lastDecAdjRecords.get("data"), ArrayList::new);
+                    for (Map data : datas) {
+                        if(ConvertUtil.toBoolean(data.get("success"))){
+                            List<DynamicObject> adjRecordList = ConvertUtil.toList(data.get("data"), ArrayList::new);
+                            for (DynamicObject dynamicObject : adjRecordList) {
+                                //薪等(01岗、02岗)
+                                DynamicObject salaryGrade = dynamicObject.getDynamicObject("salarygrade");
+                                //薪档(1档、2档)
+                                DynamicObject salaryRank = dynamicObject.getDynamicObject("salaryrank");
+                                // 人员
+                                DynamicObject employee = dynamicObject.getDynamicObject("adjfile").getDynamicObject("employee");
+                                //金额
+                                BigDecimal amount = dynamicObject.getBigDecimal("amount");
+                                SalaryAdjustmentResult salaryAdjustmentResult = salaryAdjustmentResultMap.get(employee.getLong(FormConstant.ID_KEY));
+                                salaryAdjustmentResult.oldStandardItem = standardItem;
+                                salaryAdjustmentResult.oldSalaryGrade = salaryGrade;
+                                salaryAdjustmentResult.oldSalaryRank = salaryRank;
+                                salaryAdjustmentResult.oldAmount = amount;
+                            }
+                        }
+                    }
+                }else{
+                    logger.error("查询定调薪记录失败");
+                    throw new ValidationException("查询定调薪记录失败");
+                }
+            }else{
+                logger.error("获取人员定薪档案失败");
+                throw new ValidationException("获取人员定薪档案失败");
+            }
+
+
+//        }
+
+    }
+
+    /**
+     * 根据三年的考核结果计算调薪档次
+     * 1. 考核结果三年合格及以上-上调一档;
+     * 2. 考核结果连续两年优秀-上调一档;
+     * 3. 考核结果为不合格-下降一档;
+     * 4. 连续两年考核结果为优秀且另一年考核结果为合格及以上-上调两档;
+     *
+     * @param firstYear  第一年考核结果
+     * @param secondYear 第二年考核结果
+     * @param thirdYear  第三年考核结果
+     * @param beginYear  考核周期开始年份
+     * @param endYear    考核周期结束年份
+     * @return 调薪结果对象,包含调薪档次和说明
+     */
+    private SalaryAdjustmentResult calculateSalaryAdjustmentLevel(AppraisalResultEnum firstYear, AppraisalResultEnum secondYear, AppraisalResultEnum thirdYear, int beginYear, int endYear) {
+        // 定义考核等级常量组
+        final Set<AppraisalResultEnum> EXCELLENT_LEVELS = new HashSet<>(Arrays.asList(AppraisalResultEnum.EXCELLENT, AppraisalResultEnum.DEEMED_EXCELLENT));
+        final Set<AppraisalResultEnum> QUALIFIED_LEVELS = new HashSet<>(Arrays.asList(AppraisalResultEnum.EXCELLENT, AppraisalResultEnum.DEEMED_EXCELLENT,
+                AppraisalResultEnum.QUALIFIED, AppraisalResultEnum.DEEMED_QUALIFIED, AppraisalResultEnum.NONE));
+        final Set<AppraisalResultEnum> UNQUALIFIED_LEVELS = new HashSet<>(Arrays.asList(AppraisalResultEnum.UN_QUALIFIED, AppraisalResultEnum.DEEMED_UNQUALIFIED));
+
+
+        // 判断各年份是否存在并获取相应值
+        boolean isFirstYearPresent = isFirstYearPresent(firstYear);
+        boolean isSecondYearPresent = isSecondYearPresent(secondYear);
+        boolean isThirdYearPresent = isThirdYearPresent(thirdYear);
+
+        // 判断是否为优秀(包括视同优秀)
+        boolean isFirstYearExcellent = isFirstYearPresent && EXCELLENT_LEVELS.contains(firstYear);
+        boolean isSecondYearExcellent = isSecondYearPresent && EXCELLENT_LEVELS.contains(secondYear);
+        boolean isThirdYearExcellent = isThirdYearPresent && EXCELLENT_LEVELS.contains(thirdYear);
+
+        // 判断是否为合格及以上(包括合格、视同合格、无、优秀、视同优秀)
+        boolean isFirstYearQualifiedOrAbove = isFirstYearPresent && QUALIFIED_LEVELS.contains(firstYear);
+        boolean isSecondYearQualifiedOrAbove = isSecondYearPresent && QUALIFIED_LEVELS.contains(secondYear);
+        boolean isThirdYearQualifiedOrAbove = isThirdYearPresent && QUALIFIED_LEVELS.contains(thirdYear);
+
+        // 判断是否为不合格(包括视同不合格)
+        boolean isFirstYearUnqualified = isFirstYearPresent && UNQUALIFIED_LEVELS.contains(firstYear);
+        boolean isSecondYearUnqualified = isSecondYearPresent && UNQUALIFIED_LEVELS.contains(secondYear);
+        boolean isThirdYearUnqualified = isThirdYearPresent && UNQUALIFIED_LEVELS.contains(thirdYear);
+
+        // 获取每年的具体考核结果名称
+        String firstYearResultName = isFirstYearPresent ? firstYear.getName() : "无";
+        String secondYearResultName = isSecondYearPresent ? secondYear.getName() : "无";
+        String thirdYearResultName = isThirdYearPresent ? thirdYear.getName() : "无";
+
+        // 计算具体的年份
+        int firstYearValue = beginYear;
+        int secondYearValue = beginYear + 1;
+        int thirdYearValue = beginYear + 2;
+
+        int type = TYPE_NO_CHANGE;    // 调薪类型
+        int level = 0;   // 调薪档次
+        String reason = String.format("未满足调薪条件(%d年:%s,%d年:%s,%d年:%s)",
+                firstYearValue, firstYearResultName, secondYearValue, secondYearResultName, thirdYearValue, thirdYearResultName); // 调薪原因
+
+        // 规则3: 考核结果为不合格-下降一档(最高优先级)
+        if (isFirstYearUnqualified || isSecondYearUnqualified || isThirdYearUnqualified) {
+            reason = String.format("考核结果【不合格】【降一档】(%d年:%s,%d年:%s,%d年:%s)",
+                    firstYearValue, firstYearResultName, secondYearValue, secondYearResultName, thirdYearValue, thirdYearResultName);
+            type = TYPE_DEMOTE_FOR_FAIL;
+            level = -1;
+        } else {
+            // 规则4: 连续两年考核结果为优秀且另一年考核结果为合格及以上-上调两档(次高优先级)
+            // 检查所有可能的连续两年优秀的情况
+            if ((isFirstYearExcellent && isSecondYearExcellent && isThirdYearQualifiedOrAbove) ||
+                    (isFirstYearQualifiedOrAbove && isSecondYearExcellent && isThirdYearExcellent)) {
+                reason = String.format("连续两年考核结果为【优秀】且另一年考核结果为【合格及以上】【升两档】(%d年:%s,%d年:%s,%d年:%s)",
+                        firstYearValue, firstYearResultName, secondYearValue, secondYearResultName, thirdYearValue, thirdYearResultName);
+                type = TYPE_PROMOTE_FOR_TWO_EXCELLENT_AND_THREE_PASS_FOR_TWO_YEARS;
+                level = 2;
+            }
+            // 规则2: 考核结果连续两年优秀-上调一档(只要连续两年优秀就可以上调,不需要三年都存在)
+            if ((isFirstYearExcellent && isSecondYearExcellent) ||
+                    (isSecondYearExcellent && isThirdYearExcellent)) {
+                reason = String.format("连续两年考核结果为【优秀】【升一档】(%d年:%s,%d年:%s,%d年:%s)",
+                        firstYearValue, firstYearResultName, secondYearValue, secondYearResultName, thirdYearValue, thirdYearResultName);
+                type = TYPE_PROMOTE_FOR_TWO_EXCELLENT;
+                level = 1;
+            }
+            // 规则1: 考核结果三年合格及以上-上调一档(较低优先级)
+            if (isFirstYearQualifiedOrAbove && isSecondYearQualifiedOrAbove && isThirdYearQualifiedOrAbove) {
+                reason = String.format("三年考核结果均为【合格】【升一档】(%d年:%s,%d年:%s,%d年:%s)",
+                        firstYearValue, firstYearResultName, secondYearValue, secondYearResultName, thirdYearValue, thirdYearResultName);
+                // 特殊处理:如果是因为连续两年优秀上调一档,并且同时满足三年合格及以上,则更新类型
+                if(type == TYPE_PROMOTE_FOR_TWO_EXCELLENT){
+                    reason = String.format("连续两年考核结果【优秀】且三年【合格及以上】【升一档】(%d年:%s,%d年:%s,%d年:%s)",
+                            firstYearValue, firstYearResultName, secondYearValue, secondYearResultName, thirdYearValue, thirdYearResultName);
+                    type = TYPE_PROMOTE_FOR_TWO_EXCELLENT_AND_THREE_PASS;
+                }else{
+                    type = TYPE_PROMOTE_FOR_THREE_PASS;
+                }
+                level = 1;
+            }
+        }
+        return new SalaryAdjustmentResult(type, level, reason);
+    }
+
+    /**
+     * 检查第一年考核结果是否存在
+     */
+    private boolean isFirstYearPresent(AppraisalResultEnum firstYear) {
+        return firstYear != null;
+    }
+
+    /**
+     * 检查第二年考核结果是否存在
+     */
+    private boolean isSecondYearPresent(AppraisalResultEnum secondYear) {
+        return secondYear != null;
+    }
+
+    /**
+     * 检查第三年考核结果是否存在
+     */
+    private boolean isThirdYearPresent(AppraisalResultEnum thirdYear) {
+        return thirdYear != null;
+    }
+
+
+    /**
+     * 构建考核周期查询条件
+     */
+    private static QFilter buildPerfManagerFilter(AuthorizedOrgResultWithSub userAdminOrgWithSub) {
+        QFilter perfManagerFilter = QFilter.of("1=1");
+        if (!userAdminOrgWithSub.isHasAllOrgPerm()) {
+            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());
+        perfManagerFilter.and(PerfManagerFormConstant.NCKD_THESTATUS, QCP.equals, EnableEnum.YES.getCode());
+        perfManagerFilter.and(PerfManagerFormConstant.NCKD_PERSON, QCP.equals, "2348152690355230726");
+        return perfManagerFilter;
+    }
+
+    /**
+     * 构建考核周期查询字段
+     */
+    private static QueryFieldBuilder buildPerfManagerQueryFieldBuilder() {
+        return QueryFieldBuilder.create()
+                .add(FormConstant.ID_KEY)
+                .add(PerfManagerFormConstant.NCKD_ISCURRENTNEWEST)
+                .add(PerfManagerFormConstant.NCKD_BEGINYEAR)
+                .add(PerfManagerFormConstant.NCKD_ENDYEAR)
+                .add(PerfManagerFormConstant.NCKD_ACTENDYEAR)
+                .add(PerfManagerFormConstant.NCKD_THESTATUS)
+                .addIdNumberName(FormConstant.NCKD_PERSON)
+                .addIdNumberName(PerfManagerFormConstant.NCKD_FIRSTYEARRESULT)
+                .addIdNumberName(PerfManagerFormConstant.NCKD_SECONDYEARRESULT)
+                .addIdNumberName(PerfManagerFormConstant.NCKD_THIRDYEARRESULT);
+    }
+    /**
+     * 提取组织ID列表
+     */
+    private static List<Long> extractOrgIds(List<OrgSubInfo> orgSubInfos) {
+        return orgSubInfos.stream()
+                .map(OrgSubInfo::getOrgId)
+                .collect(Collectors.toList());
+    }
+
+    
+    // 调薪结果类
+    class SalaryAdjustmentResult {
+        /** 调薪类型*/
+        int type;
+        /** 调薪档次*/
+        int level;
+        /** 调薪原因*/
+        String reason;
+        /** 原定调薪项目 */
+        DynamicObject oldStandardItem;
+        /** 原薪等(01岗、02岗)*/
+        DynamicObject oldSalaryGrade;
+        /** 原薪档(1档、2档)*/
+        DynamicObject oldSalaryRank;
+        //金额
+        BigDecimal oldAmount;
+        /** 定调薪项目 */
+        DynamicObject standardItem;
+        /** 薪等(01岗、02岗)*/
+        DynamicObject salaryGrade;
+        /** 薪档(1档、2档)*/
+        DynamicObject salaryRank;
+        //金额
+        BigDecimal amount;
+        
+        SalaryAdjustmentResult(int type, int level, String reason) {
+            this.type = type;
+            this.level = level;
+            this.reason = reason;
+        }
+    }
+}