浏览代码

feat(hr): 新增查询字段构建器并优化职级计算逻辑

- 在 FormConstant 中新增 PROFESSIONAL_KEY、QUALIFICATION_KEY 和 NCKD_ASSIGNMENT 常量
- 在 JobSeqEnum 中新增 MANAGE 枚举项
- 新增 QueryFieldBuilder 工具类用于构建查询字段和排序条件
- 重构 JobLevelCalculatorService 类,使用 QueryFieldBuilder 替代 StringJoiner- 优化职级获取逻辑,增强空值判断与处理
- 更新绩效排名信息处理流程,提升代码可读性与维护性
-修复学历积分字段引用错误的问题- 补充职称与技能等级名称字段的获取与赋值逻辑
wyc 1 月之前
父节点
当前提交
3ab5067c8a
共有 15 个文件被更改,包括 1113 次插入422 次删除
  1. 6 0
      code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/constant/FormConstant.java
  2. 3 1
      code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/enums/JobSeqEnum.java
  3. 253 0
      code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/utils/QueryFieldBuilder.java
  4. 455 247
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/business/JobLevelCalculatorService.java
  5. 9 1
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/common/PositionStructureConstant.java
  6. 98 142
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/helper/PositionStructureHelper.java
  7. 18 2
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/adjust/NewDynamicAdjustmentDiaLogFormPlugin.java
  8. 94 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/initial/NewHireInitialFormPlugin.java
  9. 91 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/initial/ServingInitialFormPlugin.java
  10. 24 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/initial/UngradedPersonQueryListPlugin.java
  11. 1 1
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/adjust/NewDynamicAdjustmentOperationPlugIn.java
  12. 15 8
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/initial/BaseInitialOperationPlugIn.java
  13. 19 10
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/initial/NewHireInitialOperationPlugIn.java
  14. 12 10
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/initial/ServingInitialOperationPlugIn.java
  15. 15 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/report/adjust/UnAdjustedReportFormPlugin.java

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

@@ -146,8 +146,12 @@ public class FormConstant {
     public static final String POSITION_KEY = "position";
     /** 学历*/
     public static final String EDUCATION_KEY = "education";
+    /** 职称*/
+    public static final String PROFESSIONAL_KEY = "professional";
     /** 职称级别*/
     public static final String PROLEVEL_KEY = "prolevel";
+    /** 技能*/
+    public static final String QUALIFICATION_KEY = "qualification";
     /** 职业资格等级*/
     public static final String QUALEVEL_KEY = "qualevel";
     /** 是否主要 */
@@ -181,6 +185,8 @@ public class FormConstant {
 
     /** 工具栏标识(二开)*/
     public static final String NCKD_TOOLBARAP = "nckd_toolbarap";
+    /** 组织分配*/
+    public static final String NCKD_ASSIGNMENT = "NCKD_ASSIGNMENT";
     /** 人员标识*/
     public static final String NCKD_PERSON = "nckd_person";
     /** 职位序列*/

+ 3 - 1
code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/enums/JobSeqEnum.java

@@ -17,7 +17,9 @@ public enum JobSeqEnum {
     /** 职能序列 */
     FUNCTIONAL("02", "职能序列"),
     /** 技能序列 */
-    SKILL("03", "技能序列");
+    SKILL("03", "技能序列"),
+    /** 管理序列 */
+    MANAGE("03", "技能序列");
 
     private static final Map<String, JobSeqEnum> CODE_MAP = new HashMap<>();
 

+ 253 - 0
code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/utils/QueryFieldBuilder.java

@@ -0,0 +1,253 @@
+package nckd.jxccl.base.common.utils;
+
+import nckd.jxccl.base.common.constant.FormConstant;
+
+import java.util.Arrays;
+import java.util.StringJoiner;
+
+/**
+* 查询字段构建器
+* @author W.Y.C
+* @date 2025/9/27 16:34
+* @version 1.0
+*/
+public class QueryFieldBuilder {
+
+    private final StringJoiner selectJoiner;
+    private final StringJoiner orderJoiner;
+
+
+
+    private QueryFieldBuilder() {
+        this.selectJoiner = new StringJoiner(",");
+        this.orderJoiner = new StringJoiner(",");
+    }
+
+    public static QueryFieldBuilder create() {
+        return new QueryFieldBuilder();
+    }
+
+    // ---------------- SELECT ----------------
+
+    /**
+     * 添加单个字段
+     * 使用方式:
+     * QueryFieldBuilder.create().add(FormConstant.ID_KEY).buildSelect();
+     * 输出结果:
+     * "ID_KEY"
+     * @param parts 字段路径,可单级或多级
+     * @return QueryFieldBuilder
+     * @author W.Y.C
+     * @date: 2025/09/27
+     */
+    public QueryFieldBuilder add(String... parts) {
+        selectJoiner.add(joinParts(parts));
+        return this;
+    }
+
+    /**
+     * 添加多级路径 + 多个子字段
+     * 使用方式:
+     * builder.addGroup(new String[]{"HRPI_PEREDUEXP","EDUCATION_KEY"}, FormConstant.ID_KEY, FormConstant.NAME_KEY);
+     * 输出结果:
+     * "HRPI_PEREDUEXP.EDUCATION_KEY.ID_KEY,HRPI_PEREDUEXP.EDUCATION_KEY.NAME_KEY"
+     * @param prefixParts 多级前缀数组
+     * @param subFields 子字段
+     * @return QueryFieldBuilder
+     * @author W.Y.C
+     * @date: 2025/09/27
+     */
+    public QueryFieldBuilder addGroup(String[] prefixParts, String... subFields) {
+        Arrays.stream(subFields)
+                .forEach(f -> selectJoiner.add(joinParts(concat(prefixParts, f))));
+        return this;
+    }
+
+    /**
+     * 添加固定三件套 ID + NUMBER + NAME
+     * 使用方式:
+     * builder.addIdNumberName(FormConstant.COMPANY_KEY);
+     * 输出结果:
+     * "COMPANY_KEY.ID,COMPANY_KEY.NUMBER,COMPANY_KEY.NAME"
+     * @param prefixParts 字段前缀
+     * @return QueryFieldBuilder
+     * @author W.Y.C
+     * @date: 2025/09/27
+     */
+    public QueryFieldBuilder addIdNumberName(String... prefixParts) {
+        return addGroup(prefixParts,
+                FormConstant.ID_KEY,
+                FormConstant.NUMBER_KEY,
+                FormConstant.NAME_KEY);
+    }
+
+    /**
+     * 添加三件套 ID+NUMBER+NAME 并可扩展其他字段
+     * 使用方式:
+     * builder.addIdNumberNameWithExtras(new String[]{FormConstant.EDUCATION_KEY}, FormConstant.NCKD_SCORE, FormConstant.STARTDATE);
+     * 输出结果:
+     * "EDUCATION_KEY.ID,EDUCATION_KEY.NUMBER,EDUCATION_KEY.NAME,EDUCATION_KEY.NCKD_SCORE,EDUCATION_KEY.STARTDATE"
+     * @param prefixParts 字段前缀
+     * @param extraFields 扩展字段
+     * @return QueryFieldBuilder
+     * @author W.Y.C
+     * @date: 2025/09/27
+     */
+    public QueryFieldBuilder addIdNumberNameWithExtras(String[] prefixParts, String... extraFields) {
+        addIdNumberName(prefixParts);
+        if (extraFields != null && extraFields.length > 0) {
+            addGroup(prefixParts, extraFields);
+        }
+        return this;
+    }
+
+    // ---------------- ORDER ----------------
+
+    /**
+     * 升序排序,支持多级路径
+     * 使用方式:
+     * builder.orderAsc(new String[]{HonorStudentConstant.NCKD_EVALUATIONRULE, FormConstant.RULE_DETAIL}, FormConstant.ID_KEY);
+     * 输出结果:
+     * "NCKD_EVALUATIONRULE.RULE_DETAIL.ID asc"
+     * @param prefixParts 多级前缀数组
+     * @param fieldParts 排序字段
+     * @return QueryFieldBuilder
+     * @author W.Y.C
+     * @date: 2025/09/27
+     */
+    public QueryFieldBuilder orderAsc(String[] prefixParts, String... fieldParts) {
+        orderJoiner.add(joinParts(concat(prefixParts, fieldParts)) + " asc");
+        return this;
+    }
+
+    /**
+     * 升序排序,单级路径
+     * 使用方式:
+     * builder.orderAsc(HonorStudentConstant.NCKD_SUMSCORE);
+     * 输出结果:
+     * "NCKD_SUMSCORE asc"
+     * @param parts 排序字段
+     * @return QueryFieldBuilder
+     * @author W.Y.C
+     * @date: 2025/09/27
+     */
+    public QueryFieldBuilder orderAsc(String... parts) {
+        orderJoiner.add(joinParts(parts) + " asc");
+        return this;
+    }
+
+    /**
+     * 降序排序,支持多级路径
+     * 使用方式:
+     * builder.orderDesc(new String[]{HonorStudentConstant.NCKD_EVALUATIONRULE, FormConstant.RULE_DETAIL}, FormConstant.ID_KEY);
+     * 输出结果:
+     * "NCKD_EVALUATIONRULE.RULE_DETAIL.ID desc"
+     * @param prefixParts 多级前缀
+     * @param fieldParts 排序字段
+     * @return QueryFieldBuilder
+     * @author W.Y.C
+     * @date: 2025/09/27
+     */
+    public QueryFieldBuilder orderDesc(String[] prefixParts, String... fieldParts) {
+        orderJoiner.add(joinParts(concat(prefixParts, fieldParts)) + " desc");
+        return this;
+    }
+
+    /**
+     * 降序排序,单级路径
+     * 使用方式:
+     * builder.orderDesc(HonorStudentConstant.NCKD_SUMSCORE);
+     * 输出结果:
+     * "NCKD_SUMSCORE desc"
+     * @param parts 排序字段
+     * @return QueryFieldBuilder
+     * @author W.Y.C
+     * @date: 2025/09/27
+     */
+    public QueryFieldBuilder orderDesc(String... parts) {
+        orderJoiner.add(joinParts(parts) + " desc");
+        return this;
+    }
+
+    /**
+     * 默认排序,不指定 asc/desc(不指定数据库默认未asc)
+     * 使用方式:
+     * builder.orderBy(new String[]{HonorStudentConstant.USEORG_KEY}, FormConstant.ID_KEY);
+     * 输出结果:
+     * "USEORG_KEY.ID_KEY"
+     * @param prefixParts 多级前缀
+     * @param fieldParts 排序字段
+     * @return QueryFieldBuilder
+     * @author W.Y.C
+     * @date: 2025/09/27
+     */
+    public QueryFieldBuilder orderBy(String[] prefixParts, String... fieldParts) {
+        orderJoiner.add(joinParts(concat(prefixParts, fieldParts)));
+        return this;
+    }
+
+    /**
+     * 默认排序,不指定 asc/desc(不指定数据库默认未asc),单级路径
+     * 使用方式:
+     * builder.orderBy(HonorStudentConstant.USEORG_KEY);
+     * 输出结果:
+     * "USEORG_KEY"
+     * @param parts 排序字段
+     * @return QueryFieldBuilder
+     * @author W.Y.C
+     * @date: 2025/09/27
+     */
+    public QueryFieldBuilder orderBy(String... parts) {
+        orderJoiner.add(joinParts(parts));
+        return this;
+    }
+
+    // ---------------- build ----------------
+
+    /**
+     * 构建 SELECT 字段字符串
+     * 使用方式:
+     * builder.buildSelect();
+     * 输出结果:
+     * "ID_KEY,COMPANY_KEY.ID,COMPANY_KEY.NUMBER,COMPANY_KEY.NAME,..."
+     * @return String
+     * @author W.Y.C
+     * @date: 2025/09/27
+     */
+    public String buildSelect() {
+        return selectJoiner.toString();
+    }
+
+    /**
+     * 构建 ORDER BY 字段字符串
+     * 使用方式:
+     * builder.buildOrder();
+     * 输出结果:
+     * "NCKD_EVALUATIONRULE.ID asc,USEORG_KEY.ID,NCKD_SUMSCORE desc"
+     * @return String
+     * @author W.Y.C
+     * @date: 2025/09/27
+     */
+    public String buildOrder() {
+        return orderJoiner.toString();
+    }
+
+    @Override
+    public String toString() {
+        return "SELECT: " + buildSelect() + "\nORDER: " + buildOrder();
+    }
+
+    // ---------------- 工具方法 ----------------
+
+    /** 拼接多级路径 */
+    private String joinParts(String... parts) {
+        return String.join(".", parts);
+    }
+
+    /** 合并前缀数组 + 字段数组 */
+    private String[] concat(String[] prefixParts, String... subFields) {
+        String[] result = Arrays.copyOf(prefixParts, prefixParts.length + subFields.length);
+        System.arraycopy(subFields, 0, result, prefixParts.length, subFields.length);
+        return result;
+    }
+}

+ 455 - 247
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/business/JobLevelCalculatorService.java

@@ -1,5 +1,7 @@
 package nckd.jxccl.hr.psms.business;
 
+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;
@@ -17,6 +19,7 @@ import nckd.jxccl.base.common.enums.AppraisalResultEnum;
 import nckd.jxccl.base.common.enums.JobSeqEnum;
 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.base.pm.helper.PerformanceManagerHelper;
@@ -27,10 +30,11 @@ import org.apache.commons.lang3.StringUtils;
 
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
+import java.util.Arrays;
 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;
 
 /**
@@ -44,14 +48,6 @@ public class JobLevelCalculatorService {
 
     protected final static Log logger = LogFactory.getLog(JobLevelCalculatorService.class);
 
-    /** 技术序列 */
-    public static final String JS_JOB_SEQ = "01";
-    /** 职能序列 */
-    public static final String ZN_JOB_SEQ = "02";
-    /** 技能序列 */
-    public static final String JN_JOB_SEQ = "03";
-    /** 管理序列 */
-    public static final String GL_JOB_SEQ = "04";
     /** 职称等级与技能等级映射关系*/
     public static final Map<String, String> TechPostLevelNumberTojobstatusNumberMap = new HashMap<>();
 
@@ -168,13 +164,18 @@ public class JobLevelCalculatorService {
                 .add(jobScoreInfo.quaLevelScore);
 
         // 11. 获取序列对应的职级
-        DynamicObjectCollection jobLevelByJobSeq = getJobLevelByJobSeq(jobSeq);
+        DynamicObject[] jobLevelByJobSeq = getJobLevelByJobSeq(jobSeq);
         //对应SHR:jobgradeMap
-        Map<Integer, DynamicObject> jobLevelMap = jobLevelByJobSeq.stream()
-                .collect(Collectors.toMap(
-                        dynamicObject -> dynamicObject.getInt(String.join(".", FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ)),
-                        dynamicObject -> dynamicObject)
-                );
+        Map<Integer, DynamicObject> jobLevelMap = new HashMap<>();
+        if (jobLevelByJobSeq != null) {
+            String jobLevelSeqKey = FormConstant.JOBLEVELSEQ;
+            jobLevelMap = Arrays.stream(jobLevelByJobSeq)
+                    .collect(Collectors.toMap(
+                            dynamicObject -> dynamicObject.getInt(jobLevelSeqKey),
+                            dynamicObject -> dynamicObject,
+                            (existing, replacement) -> existing)
+                    );
+        }
 
         // 12. 根据不同情况计算职级ID
         //对应SHR:JobGradeInfo;1044~1071行
@@ -302,15 +303,19 @@ public class JobLevelCalculatorService {
      * @date: 2025/09/19 14:07
      */
     public static DynamicObject handleJobSeq(DynamicObject jobSeq) {
-        if(GL_JOB_SEQ.equalsIgnoreCase(jobSeq.getString(FormConstant.NUMBER_KEY))){
+        if(JobSeqEnum.MANAGE.getCode().equalsIgnoreCase(jobSeq.getString(FormConstant.NUMBER_KEY))){
             QFilter filter = QFilterCommonHelper.getEnableFilter().and(QFilterCommonHelper.getDataStatusFilter()).and(new QFilter(FormConstant.NUMBER_KEY, QCP.equals, JobSeqEnum.FUNCTIONAL.getCode()));
-            StringJoiner selectFields = new StringJoiner(",");
-            selectFields.add(FormConstant.ID_KEY);
-            selectFields.add(FormConstant.NUMBER_KEY);
-            selectFields.add(FormConstant.NAME_KEY);
-            DynamicObject[] load = BusinessDataServiceHelper.load(FormConstant.HBJM_JOBSEQHR, selectFields.toString(), new QFilter[]{filter});
+            QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                    .addIdNumberName(FormConstant.HBJM_JOBSEQHR);
+
+            DynamicObject[] load = BusinessDataServiceHelper.load(
+                    FormConstant.HBJM_JOBSEQHR,
+                    queryFieldBuilder.buildSelect(),
+                    new QFilter[]{filter}
+            );
+
             if(load.length == 0){
-                throw new ValidationException(StrFormatter.format("管理序列转职能序列错误,未找到编码为【{}】的职能序列。请维护编码为【{}】的职能序列!", ZN_JOB_SEQ,ZN_JOB_SEQ));
+                throw new ValidationException(StrFormatter.format("管理序列转职能序列错误,未找到编码为【{}】的职能序列。请维护编码为【{}】的职能序列!", JobSeqEnum.FUNCTIONAL.getCode(),JobSeqEnum.FUNCTIONAL.getCode()));
             }
             return load[0];
         }else{
@@ -334,173 +339,14 @@ public class JobLevelCalculatorService {
         if (StringUtils.isBlank(proTitleLevelNumber) && (StringUtils.isBlank(ocpQualLevel) || JobSeqEnum.SKILL.getCode().equals(jobSeqNumber))) {
             return true;
         }
-
         // 情况2:技能序列下无技能等级,但有职称等级且职称无对应技能等级
-        return JN_JOB_SEQ.equals(jobSeqNumber) &&
+        return JobSeqEnum.SKILL.getCode().equals(jobSeqNumber) &&
                 StringUtils.isBlank(ocpQualLevel) &&
                 StringUtils.isNotBlank(proTitleLevelNumber) &&
                 TechPostLevelNumberTojobstatusNumberMap.get(proTitleLevelNumber) == null;
     }
 
-    /**
-     * 获取职位序列最低职级
-     * @param jobSeq 职位序列
-     * @return: kd.bos.dataentity.entity.DynamicObject
-     * @author W.Y.C
-     * @date: 2025/09/20 16:52
-     */
-    public static DynamicObject getLowestJobLevel(DynamicObject jobSeq) {
 
-        StringJoiner selectFields = new StringJoiner(",")
-                //职位序列
-                .add(String.join(".",FormConstant.NCKD_JOBSEQ,FormConstant.ID_KEY))
-                .add(String.join(".",FormConstant.NCKD_JOBSEQ,FormConstant.NAME_KEY))
-                .add(String.join(".",FormConstant.NCKD_JOBSEQ,FormConstant.NUMBER_KEY))
-                //职级
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.ID_KEY))
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NAME_KEY))
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NUMBER_KEY))
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ))
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NCKD_COEFFICIENT))
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NCKD_SCORE));
-
-        QFilter filter = new QFilter(String.join(".",FormConstant.NCKD_JOBSEQ), QCP.equals, jobSeq.getLong(FormConstant.ID_KEY))
-                .and(new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ), QCP.is_notnull, null))
-                .and(new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ), QCP.large_than, 0));
-        DynamicObjectCollection query = QueryServiceHelper.query(PositionStructureConstant.JOBSEQTOJOBLEVELQUERY,
-                selectFields.toString(),
-                new QFilter[]{filter},
-                String.join(".", FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ));
-        return !query.isEmpty() ? query.get(0) : null;
-    }
-
-    /**
-     * 获取职位序列和积分最高职级
-     * @param jobSeq 职位序列
-     * @return: kd.bos.dataentity.entity.DynamicObject
-     * @author W.Y.C
-     * @date: 2025/09/20 16:52
-     */
-    public static DynamicObject getMaxJobLevel(DynamicObject jobSeq,BigDecimal score) {
-
-        StringJoiner selectFields = new StringJoiner(",")
-                //职位序列
-                .add(String.join(".",FormConstant.NCKD_JOBSEQ,FormConstant.ID_KEY))
-                .add(String.join(".",FormConstant.NCKD_JOBSEQ,FormConstant.NAME_KEY))
-                .add(String.join(".",FormConstant.NCKD_JOBSEQ,FormConstant.NUMBER_KEY))
-                //职级
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.ID_KEY))
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NAME_KEY))
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NUMBER_KEY))
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ))
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NCKD_COEFFICIENT))
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NCKD_SCORE));
-
-        QFilter filter = new QFilter(String.join(".",FormConstant.NCKD_JOBSEQ), QCP.equals, jobSeq.getLong(FormConstant.ID_KEY))
-                .and(new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ), QCP.is_notnull, null))
-                .and(new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ), QCP.large_than, 0))
-                .and(new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NCKD_SCORE), QCP.less_equals, score));
-
-        DynamicObjectCollection query = QueryServiceHelper.query(PositionStructureConstant.JOBSEQTOJOBLEVELQUERY,
-                selectFields.toString(),
-                new QFilter[]{filter},
-                String.join(".", FormConstant.HBJM_JOBGRADESCMHR, FormConstant.JOBLEVELSEQ +" desc"));
-        return !query.isEmpty() ? query.get(0) : null;
-    }
-
-    /**
-     * 获取职位序列和积分最高职级
-     * @param jobSeq 职位序列
-     * @return: kd.bos.dataentity.entity.DynamicObject
-     * @author W.Y.C
-     * @date: 2025/09/20 16:52
-     */
-    private static DynamicObject getMaxJobLevel(DynamicObject jobSeq,String proTitleLevelNumber,String ocpQualLevelNumber) {
-        jobSeq = handleJobSeq(jobSeq);
-        String jobSeqNumber = jobSeq.getString(FormConstant.NUMBER_KEY);
-        /**
-         * 如果没有职称等级与技能等级,则倒取该序列最低职等 如果没有职称且是非技能序列,则倒取该序列最低职等 如果是技能序列,没有技能等级但有职称等级,但职称等级没有对应的技能等级,则取该序列最低职等
-         */
-        if (StringUtils.isBlank(proTitleLevelNumber) && (StringUtils.isBlank(ocpQualLevelNumber) || !JobSeqEnum.SKILL.getCode().equals(jobSeqNumber))) {
-            return getLowestJobLevel(jobSeq);
-        }
-        else if (JobSeqEnum.SKILL.getCode().equals(jobSeqNumber) && StringUtils.isBlank(ocpQualLevelNumber) && StringUtils.isNotBlank(proTitleLevelNumber) && TechPostLevelNumberTojobstatusNumberMap.get(proTitleLevelNumber) == null) {
-            return getLowestJobLevel(jobSeq);
-        }
-        String likename = "";
-        String likenumber = "";
-        if (JobSeqEnum.SKILL.getCode().equals(jobSeqNumber)) {
-            if (StringUtils.isBlank(ocpQualLevelNumber)) {
-                likenumber = TechPostLevelNumberTojobstatusNumberMap.get(proTitleLevelNumber);
-                likename = "职称等级【" + proTitleLevelNumber + "】对应的技能等级";
-                System.out.println("技能序列但无技能等级,使用职称等级【" + proTitleLevelNumber + "】对应的技能等级,编码【" + likenumber + "】");
-            }
-            else {
-                likenumber = ocpQualLevelNumber;
-                likename = "技能等级";
-                System.out.println("技能序列使用技能等级,编码【" + likenumber + "】");
-            }
-        }
-        else {
-            likenumber = proTitleLevelNumber;
-            likename = "职称等级";
-            System.out.println("非技能序列使用职称等级,编码【" + likenumber + "】");
-        }
-        StringJoiner selectFields = new StringJoiner(",")
-                //职位序列
-                .add(String.join(".", FormConstant.NCKD_JOBSEQ,FormConstant.ID_KEY))
-                .add(String.join(".", FormConstant.NCKD_JOBSEQ,FormConstant.NAME_KEY))
-                .add(String.join(".", FormConstant.NCKD_JOBSEQ,FormConstant.NUMBER_KEY))
-                //职级
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.ID_KEY))
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NAME_KEY))
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NUMBER_KEY))
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ))
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NCKD_COEFFICIENT))
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NCKD_SCORE));
-
-        QFilter filter = new QFilter(String.join(".",FormConstant.NCKD_JOBSEQ), QCP.equals, jobSeq.getLong(FormConstant.ID_KEY))
-                .and(new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ), QCP.is_notnull, null))
-                .and(new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ), QCP.large_than, 0))
-                .and(new QFilter(String.join(".",FormConstant.HBJM_JOBGRADEHR, FormConstant.NCKD_JOBLEVELNUMBER), QCP.like, "%"+likenumber+"%"));
-        DynamicObjectCollection query = QueryServiceHelper.query(PositionStructureConstant.JOBSEQTOJOBLEVELQUERY,
-                selectFields.toString(),
-                new QFilter[]{filter},
-                String.join(".", FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ +" desc"));
-        return !query.isEmpty() ? query.get(0) : null;
-    }
-
-    /**
-     * 获取职位序列对应的职级
-     * @param jobSeq 职位序列
-     * @return: kd.bos.dataentity.entity.DynamicObject
-     * @author W.Y.C
-     * @date: 2025/09/20 16:52
-     */
-    private static DynamicObjectCollection getJobLevelByJobSeq(DynamicObject jobSeq) {
-
-        StringJoiner selectFields = new StringJoiner(",")
-                //职位序列
-                .add(String.join(".",FormConstant.HBJM_JOBGRADESCMHR, FormConstant.NCKD_JOBSEQ,FormConstant.ID_KEY))
-                .add(String.join(".",FormConstant.HBJM_JOBGRADESCMHR, FormConstant.NCKD_JOBSEQ,FormConstant.NAME_KEY))
-                .add(String.join(".",FormConstant.HBJM_JOBGRADESCMHR, FormConstant.NCKD_JOBSEQ,FormConstant.NUMBER_KEY))
-                //职级
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.ID_KEY))
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NAME_KEY))
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NUMBER_KEY))
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ))
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NCKD_COEFFICIENT))
-                .add(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NCKD_SCORE));
-
-        QFilter filter = new QFilter(String.join(".", FormConstant.NCKD_JOBSEQ), QCP.equals, jobSeq.getLong(FormConstant.ID_KEY))
-                .and(new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ), QCP.is_notnull, null))
-                .and(new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ), QCP.large_than, 0));
-        DynamicObjectCollection query = QueryServiceHelper.query(PositionStructureConstant.JOBSEQTOJOBLEVELQUERY,
-                selectFields.toString(),
-                new QFilter[]{filter},
-                String.join(".", FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ));
-        return query;
-    }
 
     /**
      * 检查某个人在特定年份的考核结果是否被使用
@@ -521,19 +367,29 @@ public class JobLevelCalculatorService {
                 .and(new QFilter(PositionStructureConstant.NCKD_DISABLE, QCP.equals, EnableEnum.NO.getCode()))
                 .and(new QFilter(PositionStructureConstant.NCKD_FIRSTRANK,QCP.equals, EnableEnum.YES.getCode()).or(new QFilter(PositionStructureConstant.NCKD_TYPESTATE,QCP.in, new String[]{"3","4"})))
                 .and(rankScore.or(jobScore));
-        StringJoiner selectFields = new StringJoiner(",")
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                 .add(PositionStructureConstant.NCKD_EXECUTEYEAR)
                 .add(PositionStructureConstant.NCKD_FIRSTRANK)
                 .add(PositionStructureConstant.NCKD_ADJUSTTYPE)
-                .add(String.join(".", PositionStructureConstant.NCKD_JOBLEVELHR, FormConstant.JOBLEVELSEQ));
+                .addIdNumberNameWithExtras(
+                        new String[]{PositionStructureConstant.NCKD_JOBLEVELHR},
+                        FormConstant.JOBLEVELSEQ
+                )
+                .orderDesc(PositionStructureConstant.NCKD_EXECUTEYEAR)
+                .orderDesc(PositionStructureConstant.NCKD_BEGINDATE);
 
         int year = DateUtil.getYear(date);
 
-        try(DataSet dataSet = QueryServiceHelper.queryDataSet(JobLevelCalculatorService.class.getName()+"#useAppraisalResult", PositionStructureConstant.PERSONPOSFILE_ENTITYID,
-                selectFields.toString(), new QFilter[]{filer}, "nckd_executeyear desc,nckd_begindate desc")){
-
+        try (AlgoContext context = Algo.newContext()) {
+            DataSet dataSet = QueryServiceHelper.queryDataSet(
+                    JobLevelCalculatorService.class.getName() + "#useAppraisalResult",
+                    PositionStructureConstant.PERSONPOSFILE_ENTITYID,
+                    queryFieldBuilder.buildSelect(),
+                    new QFilter[]{filer},
+                    queryFieldBuilder.buildOrder()
+            );
             // 条件1:如果调整年与初定年相同,则考核结果被使用;返回true
-            if(dataSet
+            if(dataSet.copy()
                     .filter(PositionStructureConstant.NCKD_FIRSTRANK + " = true and " + PositionStructureConstant.NCKD_EXECUTEYEAR + "=" + year)
                     .count(PositionStructureConstant.NCKD_EXECUTEYEAR, false) == 1){
                 return Boolean.TRUE;
@@ -614,7 +470,9 @@ public class JobLevelCalculatorService {
                 return Boolean.TRUE;
             }
 
+
         }
+
         return Boolean.FALSE;
     }
 
@@ -632,13 +490,19 @@ public class JobLevelCalculatorService {
                 .and(new QFilter(PositionStructureConstant.NCKD_DISABLE, QCP.equals, EnableEnum.NO.getCode()))
                 .and(rankScore.or(jobScore))
                 .and(new QFilter(String.join(".", PositionStructureConstant.NCKD_APPRAISALRESULT,FormConstant.NUMBER_KEY), QCP.not_equals, AppraisalResultEnum.NONE.getCode()));
-        StringJoiner selectFields = new StringJoiner(",")
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                 .add(PositionStructureConstant.NCKD_FIRSTRANK)
-                .add(String.join(PositionStructureConstant.NCKD_APPRAISALRESULT,FormConstant.ID_KEY))
-                .add(String.join(PositionStructureConstant.NCKD_APPRAISALRESULT,FormConstant.NUMBER_KEY))
-                .add(String.join(PositionStructureConstant.NCKD_APPRAISALRESULT,FormConstant.NAME_KEY));
+                .addIdNumberName(PositionStructureConstant.NCKD_APPRAISALRESULT)
+                .orderDesc(PositionStructureConstant.NCKD_EXECUTEYEAR)
+                .orderDesc(PositionStructureConstant.NCKD_BEGINDATE);
+
         //对应SHR:PRpersonpositionfileCollection
-        DynamicObjectCollection query = QueryServiceHelper.query(PositionStructureConstant.PERSONPOSFILE_ENTITYID, selectFields.toString(), new QFilter[]{filer}, "nckd_executeyear desc,nckd_begindate desc");
+        DynamicObjectCollection query = QueryServiceHelper.query(
+                PositionStructureConstant.PERSONPOSFILE_ENTITYID,
+                queryFieldBuilder.buildSelect(),
+                new QFilter[]{filer},
+                queryFieldBuilder.buildOrder()
+        );
         //如果没有符合条件的记录,或者只有一条记录且为初定且考核结果为空或为考核结果为“无”,为首次聘任
         if(query.isEmpty()){
             return Boolean.TRUE;
@@ -748,7 +612,7 @@ public class JobLevelCalculatorService {
         String currentDiplomaName = positionAppointment.getString(String.join(".", FormConstant.HRPI_PEREDUEXP, FormConstant.EDUCATION_KEY, FormConstant.NAME_KEY));
         //对应SHR:DiplomaScore
         //人员最新学历的积分
-        BigDecimal currentDiplomaScore = positionAppointment.getBigDecimal(String.join(".", FormConstant.HRPI_PEREDUEXP, FormConstant.EDUCATION_KEY, FormConstant.NAME_KEY));
+        BigDecimal currentDiplomaScore = positionAppointment.getBigDecimal(String.join(".", FormConstant.HRPI_PEREDUEXP, FormConstant.EDUCATION_KEY, FormConstant.NCKD_SCORE));
         //对应SHR:DiplomaScore
         BigDecimal resultScore = currentDiplomaScore;
 
@@ -818,6 +682,7 @@ public class JobLevelCalculatorService {
         BigDecimal newPerProTitleScore = positionAppointment.getBigDecimal(String.join(".", FormConstant.HRPI_PERPROTITLE, FormConstant.PROLEVEL_KEY, FormConstant.NCKD_SCORE));
         //对应SHR:selMap.get("zgjbnumber")
         String newPerProTitleNumber = positionAppointment.getString(String.join(".", FormConstant.HRPI_PERPROTITLE, FormConstant.PROLEVEL_KEY, FormConstant.NUMBER_KEY));
+        String newPerProTitleName = positionAppointment.getString(String.join(".", FormConstant.HRPI_PERPROTITLE, FormConstant.PROLEVEL_KEY, FormConstant.NAME_KEY));
 
         //当前人员最新技能等级
         Long newQuaLevelId = positionAppointment.getLong(String.join(".", FormConstant.HRPI_PEROCPQUAL, FormConstant.QUALEVEL_KEY, FormConstant.ID_KEY));
@@ -825,6 +690,7 @@ public class JobLevelCalculatorService {
         BigDecimal newQuaLevelScore = positionAppointment.getBigDecimal(String.join(".", FormConstant.HRPI_PEROCPQUAL, FormConstant.QUALEVEL_KEY, FormConstant.NCKD_SCORE));
         //对应SHR:selMap.get("zyjndjnumber")
         String newQuaLevelNumber = positionAppointment.getString(String.join(".", FormConstant.HRPI_PEROCPQUAL, FormConstant.QUALEVEL_KEY, FormConstant.NUMBER_KEY));
+        String newQuaLevelName = positionAppointment.getString(String.join(".", FormConstant.HRPI_PEROCPQUAL, FormConstant.QUALEVEL_KEY, FormConstant.NAME_KEY));
 
 
         JobScoreInfo jobScoreInfo = new JobScoreInfo();
@@ -841,7 +707,8 @@ public class JobLevelCalculatorService {
             // 获取当前最新职称等级分
             jobScoreInfo.perProTitleScore = newPerProTitleScore;
             jobScoreInfo.perProTitleId = newPerProTitleId;
-            jobScoreInfo.perProTitleNumber = StringUtils.isNotBlank(newPerProTitleNumber) ? newPerProTitleNumber : "";
+            jobScoreInfo.perProTitleNumber = StringUtils.isNotBlank(newPerProTitleNumber) ? newPerProTitleNumber : StringUtils.EMPTY;
+            jobScoreInfo.perProTitleName = StringUtils.isNotBlank(newPerProTitleName) ? newPerProTitleName : StringUtils.EMPTY;
             jobScoreInfo.isEndGainJobGrade = false;
         } else if (JobSeqEnum.SKILL.getCode().equals(newJobSeqNumber)) {
             if (newQuaLevelScore != null && newQuaLevelScore.compareTo(BigDecimal.ZERO) > 0) {
@@ -849,6 +716,7 @@ public class JobLevelCalculatorService {
                 jobScoreInfo.quaLevelScore = newQuaLevelScore;
                 jobScoreInfo.quaLevelId = newQuaLevelId;
                 jobScoreInfo.quaLevelNumber = StringUtils.isNotBlank(newQuaLevelNumber) ? newQuaLevelNumber: "";
+                jobScoreInfo.quaLevelName = StringUtils.isNotBlank(newQuaLevelName) ? newQuaLevelName: "";
                 jobScoreInfo.isEndGainJobGrade = false;
             }
         }
@@ -864,32 +732,32 @@ public class JobLevelCalculatorService {
     private static DynamicObject calculateJobGradeId(DynamicObject newJobSeq, JobScoreInfo jobScoreInfo,JobFamilyInfo jobFamilyInfo,
                                                           BigDecimal allSumScore, int currentJobLevelIndex, int minusPersonAppraisal, boolean fistPR, JobLevelResult jobLevelResult){
 
-        DynamicObject proTitleLevel = BusinessDataServiceHelper.loadSingle(jobScoreInfo.perProTitleId, FormConstant.HBSS_PROTITLELEVEL);
-        DynamicObject ocpQualLevel = BusinessDataServiceHelper.loadSingle(jobScoreInfo.quaLevelId, FormConstant.HBSS_OCPQUALLEVEL);
+        String perProTitleNumber = jobScoreInfo.perProTitleNumber;
+        String quaLevelNumber = jobScoreInfo.quaLevelNumber;
         JobSeqEnum jobSeqEnum = JobSeqEnum.getByCode(newJobSeq.getString(FormConstant.NUMBER_KEY));
         DynamicObject jobLevel = null;
         if (jobScoreInfo.isEndGainJobGrade) {
             System.out.println("缺少聘任,技能序列必需聘任技能等级,其它序列必需聘任职称等级!");
             //对应SHR:JobGradeid = personpositionfileUtils.endGainJobGrade(ctx, allsumScore, hrjobfamilynumber);
-            jobLevel = getLowestJobLevel(newJobSeq);
+            jobLevel = getJobLevel(newJobSeq, null, null, null, null, Boolean.TRUE,Boolean.FALSE);
             //对应SHR:selMap.put("adjusttype", "7");
             jobLevelResult.adjustType = "7";
         } else if (jobFamilyInfo.isSequenceChange) {
             //对应SHR:JobGradeid = personpositionfileUtils.GainJobGrade(ctx, allsumScore, hrjobfamilynumber, zgjbnumber, zyjndjnumber, 0);
-            jobLevel = PositionStructureHelper.calculateLevel(jobSeqEnum, allSumScore, proTitleLevel, ocpQualLevel, null, 0, Boolean.FALSE,Boolean.FALSE);
+            jobLevel = getJobLevel(newJobSeq, allSumScore, perProTitleNumber, quaLevelNumber, 0, Boolean.FALSE,Boolean.FALSE);
             //序列转换
             jobLevelResult.adjustType = "4";
         } else if (jobFamilyInfo.isCrossUnitTransfer) {
             //对应SHR:JobGradeid = personpositionfileUtils.GainJobGrade(ctx, allsumScore, hrjobfamilynumber, zgjbnumber, zyjndjnumber, 0);
-            jobLevel = PositionStructureHelper.calculateLevel(jobSeqEnum, allSumScore, proTitleLevel, ocpQualLevel, null, 0, Boolean.FALSE,Boolean.FALSE);
+            jobLevel = getJobLevel(newJobSeq, allSumScore, perProTitleNumber, quaLevelNumber, 0, Boolean.FALSE,Boolean.FALSE);
             //保级
             jobLevelResult.adjustType = "1";
         } else if (fistPR) {
             //对应SHR:JobGradeid = personpositionfileUtils.GainJobGrade(ctx, allsumScore, hrjobfamilynumber, zgjbnumber, zyjndjnumber, minuspersonappraisal);
-            jobLevel = PositionStructureHelper.calculateLevel(jobSeqEnum, allSumScore, proTitleLevel, ocpQualLevel, null, minusPersonAppraisal, Boolean.FALSE,Boolean.FALSE);
+            jobLevel = getJobLevel(newJobSeq, allSumScore, perProTitleNumber, quaLevelNumber, minusPersonAppraisal, Boolean.FALSE,Boolean.FALSE);
         } else {
             //对应SHR:JobGradeid = personpositionfileUtils.GainJobGrade(ctx, allsumScore, hrjobfamilynumber, zgjbnumber, zyjndjnumber, minuspersonappraisal < 0 ? minuspersonappraisal : 0);
-            jobLevel = PositionStructureHelper.calculateLevel(jobSeqEnum, allSumScore, proTitleLevel, ocpQualLevel, null, minusPersonAppraisal < 0 ? minusPersonAppraisal : 0, Boolean.FALSE,Boolean.FALSE);
+            jobLevel = getJobLevel(newJobSeq, allSumScore, perProTitleNumber, quaLevelNumber, minusPersonAppraisal < 0 ? minusPersonAppraisal : 0, Boolean.FALSE,Boolean.FALSE);
         }
         int newJobGradeIndex = jobLevel.getInt(FormConstant.JOBLEVELSEQ);
         System.out.println("newjobgradeindex:::" + newJobGradeIndex);
@@ -919,38 +787,53 @@ public class JobLevelCalculatorService {
         groupFilter.and(String.join(".",PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY,PerfRankMgmtConstant.NCKD_PERSON),QCP.equals, personId);
         groupFilter.and(String.join(".",PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY,PerfRankMgmtConstant.NCKD_ISRANKING),QCP.equals,EnableEnum.YES.getCode());
         //获取该员工上年度所在的排名分组
-        DynamicObject[] groupArray = BusinessDataServiceHelper.load(PerfRankMgmtConstant.NCKD_PERFRANKMGMT_ENTITYID, FormConstant.ID_KEY+","+FormConstant.NAME_KEY,
+        DynamicObject[] groupArray = BusinessDataServiceHelper.load(PerfRankMgmtConstant.NCKD_PERFRANKMGMT_ENTITYID, FormConstant.ID_KEY+","+PerfRankMgmtConstant.NCKD_GROUPNAME,
                 new QFilter[]{groupFilter},
-                FormConstant.CREATE_TIME_KEY + " desc " + FormConstant.AUDIT_DATE_KEY + " desc " + FormConstant.MODIFY_TIME_KEY + " desc");
+                FormConstant.CREATE_TIME_KEY + " desc," + FormConstant.AUDIT_DATE_KEY + " desc," + FormConstant.MODIFY_TIME_KEY + " desc");
         //避免一个员工存在多个排名分组中,只取最新排名分组
         Long groupId = null;
         String groupName = null;
         if(groupArray != null && groupArray.length > 0){
             groupId = groupArray[0].getLong(FormConstant.ID_KEY);
-            groupName = groupArray[0].getString(FormConstant.NAME_KEY);
+            groupName = groupArray[0].getString(PerfRankMgmtConstant.NCKD_GROUPNAME);
         }
         if(groupId != null && groupId > 0){
             QFilter perfRankMgmtFilter = new QFilter(FormConstant.ID_KEY,QCP.equals,groupId);
-            StringJoiner selectFields = new StringJoiner(",")
+
+            QueryFieldBuilder selectBuilder = QueryFieldBuilder.create()
                     .add(FormConstant.ID_KEY)
-                    .add(String.join(".",PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY,PerfRankMgmtConstant.NCKD_PERSON,FormConstant.ID_KEY))
-                    .add(String.join(".",PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY,PerfRankMgmtConstant.NCKD_TOPRANK))
-                    .add(String.join(".",PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY,PerfRankMgmtConstant.NCKD_POSTALLOWANCE))
-                    .add(String.join(".",PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY,PerfRankMgmtConstant.NCKD_ALLOWANCERANK))
-                    .add(String.join(".",PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY,PerfRankMgmtConstant.NCKD_APPRAISALRESULT))
-                    .add(String.join(".",PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY,PerfRankMgmtConstant.NCKD_ISRANKING));
+                    .addGroup(
+                            new String[]{PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, PerfRankMgmtConstant.NCKD_PERSON},
+                            FormConstant.ID_KEY
+                    ).addGroup(
+                            new String[]{PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY},
+                            PerfRankMgmtConstant.NCKD_TOPRANK,
+                            PerfRankMgmtConstant.NCKD_POSTALLOWANCE,
+                            PerfRankMgmtConstant.NCKD_ALLOWANCERANK,
+                            PerfRankMgmtConstant.NCKD_APPRAISALRESULT,
+                            PerfRankMgmtConstant.NCKD_ISRANKING
+                    );
+            String selectFields = selectBuilder.buildSelect();
+
+            QueryFieldBuilder orderByBuilder = QueryFieldBuilder.create()
+                    .orderBy(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, PerfRankMgmtConstant.NCKD_TOPRANK)
+                    .orderBy(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, PerfRankMgmtConstant.NCKD_ALLOWANCERANK);
+
+            String orderBy = orderByBuilder.buildOrder();
             //对应SHR:allowancerankpercentSQL()方法
-            try(DataSet dataSet = QueryServiceHelper.queryDataSet(JobLevelCalculatorService.class.getName() + "#processRankingInfo", PerfRankMgmtConstant.NCKD_PERFRANKMGMT_ENTITYID,
-                    selectFields.toString(), new QFilter[]{perfRankMgmtFilter}, PerfRankMgmtConstant.NCKD_TOPRANK + "," + PerfRankMgmtConstant.NCKD_ALLOWANCERANK)){
+            try(AlgoContext context = Algo.newContext()){
+                DataSet dataSet = QueryServiceHelper.queryDataSet(JobLevelCalculatorService.class.getName() + "#processRankingInfo", PerfRankMgmtConstant.NCKD_PERFRANKMGMT_ENTITYID,
+                        selectFields, new QFilter[]{perfRankMgmtFilter},
+                        String.join(".",PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY,PerfRankMgmtConstant.NCKD_TOPRANK) + "," + String.join(".",PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY,PerfRankMgmtConstant.NCKD_ALLOWANCERANK));
                 //获取R排名总人数
                 //对应SHR:countallowancerank
-                int countR = dataSet.filter(String.join(".",PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY,PerfRankMgmtConstant.NCKD_ISRANKING) +" = true and "+String.join(".",PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY,PerfRankMgmtConstant.NCKD_POSTALLOWANCE)+" = true")
+                int countR = dataSet.copy().filter(String.join(".",PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY,PerfRankMgmtConstant.NCKD_ISRANKING) +" = true and "+String.join(".",PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY,PerfRankMgmtConstant.NCKD_POSTALLOWANCE)+" = true")
                         .count(FormConstant.ID_KEY, false);
                 //获取总排名总人数
-                int count = dataSet.filter(String.join(".",PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY,PerfRankMgmtConstant.NCKD_ISRANKING) +" = true")
+                int count = dataSet.copy().filter(String.join(".",PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY,PerfRankMgmtConstant.NCKD_ISRANKING) +" = true")
                         .count(FormConstant.ID_KEY, false);
                 //获取排名
-                DataSet topRankDataSet = dataSet.select(String.join(".", PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, PerfRankMgmtConstant.NCKD_TOPRANK))
+                DataSet topRankDataSet = dataSet.copy().select(String.join(".", PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, PerfRankMgmtConstant.NCKD_TOPRANK)+","+String.join(".", PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, PerfRankMgmtConstant.NCKD_PERSON, FormConstant.ID_KEY))
                         .filter(String.join(".", PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, PerfRankMgmtConstant.NCKD_PERSON, FormConstant.ID_KEY) + " = " + personId);
                 //对应SHR:topRank
                 Integer topRank = null;
@@ -960,7 +843,7 @@ public class JobLevelCalculatorService {
                 }
 
                 //获取R排名
-                DataSet allowanceRankDataSet = dataSet.select(String.join(".", PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, PerfRankMgmtConstant.NCKD_ALLOWANCERANK))
+                DataSet allowanceRankDataSet = dataSet.copy().select(String.join(".", PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, PerfRankMgmtConstant.NCKD_ALLOWANCERANK))
                         .filter(String.join(".", PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, PerfRankMgmtConstant.NCKD_PERSON, FormConstant.ID_KEY) + " = " + personId);
                 //对应SHR:allowancerank
                 Integer allowanceRank = null;
@@ -982,7 +865,7 @@ public class JobLevelCalculatorService {
 
                 RankingResult rankingResult = new RankingResult();
                 //获取R排名最后名次
-                DataSet maxAllowanceRank = dataSet.filter(String.join(".", PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, PerfRankMgmtConstant.NCKD_ISRANKING) + " = true and " + String.join(".", PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, PerfRankMgmtConstant.NCKD_POSTALLOWANCE) + " = true")
+                DataSet maxAllowanceRank = dataSet.copy().filter(String.join(".", PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, PerfRankMgmtConstant.NCKD_ISRANKING) + " = true and " + String.join(".", PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, PerfRankMgmtConstant.NCKD_POSTALLOWANCE) + " = true")
                         .groupBy()
                         .max(String.join(".", PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, PerfRankMgmtConstant.NCKD_ALLOWANCERANK), "maxAllowanceRank").finish();
                 if(maxAllowanceRank.hasNext()){
@@ -1047,6 +930,9 @@ public class JobLevelCalculatorService {
 
         JobSeqEnum jobSeqEnum = JobSeqEnum.getByCode(jobSeq.getString(FormConstant.NUMBER_KEY));
         if(rankingResult == null || rankingResult.countR == null || rankingResult.allowanceRank == null){
+            if(rankingResult == null){
+                rankingResult = new RankingResult();
+            }
             rankingResult.allowanceRankMark = "无";
             rankingResult.allowanceRankSel = "无";
             return jobLevelIndex;
@@ -1182,18 +1068,18 @@ public class JobLevelCalculatorService {
                 .and(new QFilter(PositionStructureConstant.NCKD_DISABLE, QCP.equals, EnableEnum.NO.getCode()))
                 .and(rankScore.or(jobScore))
                 .and(new QFilter(String.join(".", PositionStructureConstant.NCKD_APPRAISALRESULT,FormConstant.NUMBER_KEY), QCP.not_equals, AppraisalResultEnum.NONE.getCode()));
-        StringJoiner selectFields = new StringJoiner(",")
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                 .add(PositionStructureConstant.NCKD_FIRSTRANK)
-                .add(String.join(PositionStructureConstant.NCKD_APPRAISALRESULT,FormConstant.ID_KEY))
-                .add(String.join(PositionStructureConstant.NCKD_APPRAISALRESULT,FormConstant.NUMBER_KEY))
-                .add(String.join(PositionStructureConstant.NCKD_APPRAISALRESULT,FormConstant.NAME_KEY))
-
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBLEVELHR,FormConstant.ID_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBLEVELHR,FormConstant.NAME_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBLEVELHR,FormConstant.NUMBER_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBLEVELHR,FormConstant.JOBLEVELSEQ));
+                .addIdNumberName(PositionStructureConstant.NCKD_APPRAISALRESULT)
+                .addIdNumberNameWithExtras(
+                        new String[]{PositionStructureConstant.NCKD_JOBLEVELHR},
+                        FormConstant.JOBLEVELSEQ
+                )
+                .orderDesc(PositionStructureConstant.NCKD_EXECUTEYEAR)
+                .orderDesc(PositionStructureConstant.NCKD_BEGINDATE);
+
         //对应SHR:PRpersonpositionfileCollection
-        DynamicObjectCollection query = QueryServiceHelper.query(PositionStructureConstant.PERSONPOSFILE_ENTITYID, selectFields.toString(), new QFilter[]{filer}, "nckd_executeyear desc,nckd_begindate desc");
+        DynamicObjectCollection query = QueryServiceHelper.query(PositionStructureConstant.PERSONPOSFILE_ENTITYID, queryFieldBuilder.buildSelect(), new QFilter[]{filer}, queryFieldBuilder.buildOrder());
         if(!query.isEmpty()){
             DynamicObject personPosFile = query.get(0);
             int lastAppointmentJobGradeIndex = personPosFile.getInt(String.join(".", PositionStructureConstant.NCKD_JOBLEVELHR, FormConstant.JOBLEVELSEQ));
@@ -1214,7 +1100,7 @@ public class JobLevelCalculatorService {
                     // 考核结果为保级 所以相 等
                     jobLevelIndex = lastAppointmentJobGradeIndex;
                 }
-                if (fistPR && ((rankingResult.countR == null || rankingResult.countR == 0) || (rankingResult.allowanceRank == null || rankingResult.allowanceRank == 0))) {
+                if (fistPR && ((rankingResult == null || rankingResult.countR == null || rankingResult.countR == 0) || (rankingResult.allowanceRank == null || rankingResult.allowanceRank == 0))) {
                     System.out.println("首次聘任而且无R排名,保持分数算出来的职级");
                 } else {
                     System.out.println("应用R排名结果");
@@ -1259,17 +1145,24 @@ public class JobLevelCalculatorService {
                 .and(new QFilter(PositionStructureConstant.NCKD_DISABLE, QCP.equals, EnableEnum.NO.getCode()))
                 .and(rankScore.or(jobScore))
                 .and(new QFilter(String.join(".", PositionStructureConstant.NCKD_APPRAISALRESULT,FormConstant.NUMBER_KEY), QCP.not_equals, AppraisalResultEnum.NONE.getCode()));
-        StringJoiner selectFields = new StringJoiner(",")
+
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                 .add(PositionStructureConstant.NCKD_FIRSTRANK)
-                .add(String.join(PositionStructureConstant.NCKD_APPRAISALRESULT,FormConstant.ID_KEY))
-                .add(String.join(PositionStructureConstant.NCKD_APPRAISALRESULT,FormConstant.NUMBER_KEY))
-                .add(String.join(PositionStructureConstant.NCKD_APPRAISALRESULT,FormConstant.NAME_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBLEVELHR,FormConstant.ID_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBLEVELHR,FormConstant.NAME_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBLEVELHR,FormConstant.NUMBER_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBLEVELHR,FormConstant.JOBLEVELSEQ));
+                .addIdNumberName(PositionStructureConstant.NCKD_APPRAISALRESULT)
+                .addIdNumberNameWithExtras(
+                        new String[]{PositionStructureConstant.NCKD_JOBLEVELHR},
+                        FormConstant.JOBLEVELSEQ
+                )
+                .orderDesc(PositionStructureConstant.NCKD_EXECUTEYEAR)
+                .orderDesc(PositionStructureConstant.NCKD_BEGINDATE);
+
         //对应SHR:PRpersonpositionfileCollection
-        DynamicObjectCollection query = QueryServiceHelper.query(PositionStructureConstant.PERSONPOSFILE_ENTITYID, selectFields.toString(), new QFilter[]{filer}, "nckd_executeyear desc,nckd_begindate desc");
+        DynamicObjectCollection query = QueryServiceHelper.query(
+                PositionStructureConstant.PERSONPOSFILE_ENTITYID,
+                queryFieldBuilder.buildSelect(),
+                new QFilter[]{filer},
+                queryFieldBuilder.buildOrder());
+
         if (firstPR) {
             System.out.println("前一笔为初定且考核结果为无,按首次聘任处理,所以放开限制");
             // 首次聘任
@@ -1369,8 +1262,11 @@ public class JobLevelCalculatorService {
          */
         //对应SHR:String personMaxjobgradeindexstr = personpositionfileUtils.MaxGainJobGrade(ctx, allsumScore, jobFamilyInfo.processedJobFamilyNumber);
         DynamicObject maxJobLevel = getMaxJobLevel(jobSeq, allsumScore);
+        if(maxJobLevel == null){
+            throw new ValidationException(StrFormatter.format("根据职位序列【{}】和积分【{}】未获取到符合条件的职级,请检查职级配置是否有误!",jobSeq.getString(FormConstant.NAME_KEY),allsumScore));
+        }
         //对应SHR:personMaxjobgradeindex
-        int maxJobLevelIndex = maxJobLevel.getInt(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ));
+        int maxJobLevelIndex = maxJobLevel.getInt(FormConstant.JOBLEVELSEQ);
         // 超出总分能任命最高职职级则该最高职级就是要任命的职级
         if (jobLevelIndex > maxJobLevelIndex) {
             // 总分不足
@@ -1387,8 +1283,19 @@ public class JobLevelCalculatorService {
          */
         /*String Maxjobgradeindexstr = personpositionfileUtils.getMaxJobLevel(ctx, jobFamilyInfo.processedJobFamilyNumber,
                 jobScoreInfo.zgjbnumber, jobScoreInfo.zyjndjnumber);*/
-        DynamicObject maxJobLevel1 = getMaxJobLevel(jobSeq, jobScoreInfo.perProTitleNumber, jobScoreInfo.quaLevelNumber);
-        int maxJobGradeIndex = maxJobLevel1.getInt(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ));
+        DynamicObject maxJobLevel1 = getMaxJobLevel(jobSeq,null,null,jobScoreInfo.perProTitleNumber, jobScoreInfo.quaLevelNumber);
+        if(maxJobLevel1 == null){
+            String levelName = "";
+            if (JobSeqEnum.SKILL.getCode().equals(jobSeq.getString(FormConstant.NUMBER_KEY))) {
+                levelName = StringUtils.isNotBlank(jobScoreInfo.quaLevelName) ? jobScoreInfo.quaLevelName : "";
+            } else {
+                levelName = StringUtils.isNotBlank(jobScoreInfo.perProTitleName) ? jobScoreInfo.perProTitleName : "";
+            }
+            throw new ValidationException(StrFormatter.format("根据职位序列【{}】和职称等级/技能等级【{}】未获取到符合条件的职级,请检查职级配置是否有误!",
+                    jobSeq.getString(FormConstant.NAME_KEY), levelName));
+
+        }
+        int maxJobGradeIndex = maxJobLevel1.getInt(FormConstant.JOBLEVELSEQ);
         // 职级超出职称等级或技能等级能任命最高职职级则该最高职级就是要任命的职级
         if (jobLevelIndex > maxJobGradeIndex) {
             if (StringUtils.isBlank(jobLevelResult.adjustType)) {
@@ -1453,8 +1360,308 @@ public class JobLevelCalculatorService {
     }
 
 
+
+    /**
+     * 判断是否符合三要素
+     * @param jobSeq 序列
+     * @param score 积分
+     * @param proTitleLevel 职称等级
+     * @param ocpQualLevel 技能等级
+     * @param appraisalResultEnum 考核结果
+     * @return: kd.bos.dataentity.entity.DynamicObject
+     * @author W.Y.C
+     * @date: 2025/09/26 11:44
+     */
+    public static boolean checkThreeElementsRequirement(DynamicObject jobSeq, BigDecimal score, DynamicObject proTitleLevel, DynamicObject ocpQualLevel,AppraisalResultEnum appraisalResultEnum){
+        //三要素说明:
+        //1、【技术序列、职能序列】:有聘任的职称等级;【技能序列】:有聘任的技能等级
+        //2、有考核结果
+        //3、积分数能够达到职级
+        String jobSeqNumber = jobSeq.getString(FormConstant.NUMBER_KEY);
+        JobSeqEnum jobSeqEnum = JobSeqEnum.getByCode(jobSeqNumber);
+        boolean isEligibleForJobLevel = Boolean.TRUE;
+        if ((jobSeqEnum == JobSeqEnum.TECHNICALS || jobSeqEnum == JobSeqEnum.FUNCTIONAL) && proTitleLevel == null) {
+            //【技术序列或职能序列】无职称等级
+            isEligibleForJobLevel = Boolean.FALSE;
+        } else if (jobSeqEnum == JobSeqEnum.SKILL && ocpQualLevel == null) {
+            //【技能序列】无技能等级
+            isEligibleForJobLevel = Boolean.FALSE;
+        }
+        if (appraisalResultEnum == null || AppraisalResultEnum.NONE.getCode().equals(appraisalResultEnum.getCode())) {
+            //无考核结果
+            isEligibleForJobLevel = Boolean.FALSE;
+        }
+        if(score.compareTo(new BigDecimal(18)) < 0) {
+            //积分数小于18
+            isEligibleForJobLevel = Boolean.FALSE;
+        }
+        return isEligibleForJobLevel;
+    }
+
+
+    /**
+     * 计算职级
+     * 对应SHR:com.kingdee.shr.customer.web.handler.PersonpositionfileUtils#GainJobGrade 和 com.kingdee.shr.customer.web.handler.PersonpositionfileUtils#endGainJobGrade
+     * @param jobSeq 职位序列(转换过的序列,例如管理序列转职能序列)
+     * @param score 积分数;可为空,为空则不限高;不为空则根据传入的积分限定积分所处的职级
+     * @param proTitleLevelNumber 职称等级编码
+     * @param quaLevelNumber 技能等级编码
+     * @param downgradeNum 降级数(根据绩效计算:基本合格:降1级、不合格:降2级)
+     * @param useMinLevel 是否强制按最低职级定级;如果传入true时则按最低级返回;否则按正常定级
+     * @param useNonLevel 是否强制按无职级定级;如果传入true时则按"无"职级返回;否则按正常定级
+     * @return: kd.bos.dataentity.entity.DynamicObject 返回:匹配的职级(joblevelhr对象)
+     * @author W.Y.C
+     * @date: 2025/09/13 14:21
+     */
+    public static DynamicObject getJobLevel(DynamicObject jobSeq, BigDecimal score, String proTitleLevelNumber, String quaLevelNumber,
+                                            Integer downgradeNum, boolean useMinLevel, boolean useNonLevel) {
+
+        DynamicObject jobLevel = null;
+        if(useNonLevel) {
+            //查询该序列“无职级”的数据并返回
+            return getNonJobLevel(jobSeq);
+        } else if(useMinLevel) {
+            //最低职级
+            return getLowestJobLevel(jobSeq);
+        }else{
+            return getMaxJobLevel(jobSeq, score,downgradeNum, proTitleLevelNumber, quaLevelNumber);
+        }
+    }
+
+    /**
+     * 根据职位序列获取“无”职级
+     * @param jobSeq 职位序列
+     * @return: kd.bos.dataentity.entity.DynamicObject
+     * @author W.Y.C
+     * @date: 2025/09/20 16:52
+     */
+    public static DynamicObject getNonJobLevel(DynamicObject jobSeq){
+        DynamicObjectCollection jobLevels = queryJobLevels(jobSeq.getString(FormConstant.NUMBER_KEY), null, -1,
+                null, String.join(".", FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ));
+        DynamicObject jobLevel = !jobLevels.isEmpty() ? jobLevels.get(0) : null;
+        if( jobLevel != null) {
+            long jobLevelId = jobLevel.getLong(String.join(".", FormConstant.HBJM_JOBLEVELHR, FormConstant.ID_KEY));
+            //返回职级对象
+            return BusinessDataServiceHelper.loadSingle(jobLevelId, FormConstant.HBJM_JOBLEVELHR);
+        }
+        return null;
+    }
+
+    /**
+     * 获取职位序列最低职级
+     * @param jobSeq 职位序列
+     * @return: kd.bos.dataentity.entity.DynamicObject
+     * @author W.Y.C
+     * @date: 2025/09/20 16:52
+     */
+    public static DynamicObject getLowestJobLevel(DynamicObject jobSeq) {
+
+        DynamicObjectCollection jobLevels = queryJobLevels(jobSeq.getString(FormConstant.NUMBER_KEY), null, null,
+                null, String.join(".", FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ));
+        DynamicObject jobLevel = !jobLevels.isEmpty() ? jobLevels.get(0) : null;
+        if( jobLevel != null) {
+            long jobLevelId = jobLevel.getLong(String.join(".", FormConstant.HBJM_JOBLEVELHR, FormConstant.ID_KEY));
+            //返回职级对象
+            return BusinessDataServiceHelper.loadSingle(jobLevelId, FormConstant.HBJM_JOBLEVELHR);
+        }
+        return null;
+    }
+
+    /**
+     * 获取职位序列和积分最高职级
+     * @param jobSeq 职位序列
+     * @return: kd.bos.dataentity.entity.DynamicObject
+     * @author W.Y.C
+     * @date: 2025/09/20 16:52
+     */
+    public static DynamicObject getMaxJobLevel(DynamicObject jobSeq,BigDecimal score) {
+        DynamicObjectCollection jobLevels = queryJobLevels(jobSeq.getString(FormConstant.NUMBER_KEY), score, null,
+                null, String.join(".", FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ +" desc"));
+        DynamicObject jobLevel = !jobLevels.isEmpty() ? jobLevels.get(0) : null;
+        if( jobLevel != null) {
+            long jobLevelId = jobLevel.getLong(String.join(".", FormConstant.HBJM_JOBLEVELHR, FormConstant.ID_KEY));
+            //返回职级对象
+            return BusinessDataServiceHelper.loadSingle(jobLevelId, FormConstant.HBJM_JOBLEVELHR);
+        }
+        return null;
+    }
+
+
+
+    /**
+     * 根据[职位序列][积分]和[职称等级/技能等级]获取职位序列最高职级
+     * @param jobSeq 职位序列
+     * @param score 积分(可为空,为空则不限高)
+     * @param downgradeNum 需降级数(可为空,为空则不降级)
+     * @param proTitleLevelNumber 职称等级
+     * @param ocpQualLevelNumber 技能等级
+     * @return: kd.bos.dataentity.entity.DynamicObject 如没有获取到预期职级则返回最低职级
+     * @author W.Y.C
+     * @date: 2025/09/20 16:52
+     */
+    public static DynamicObject getMaxJobLevel(DynamicObject jobSeq, BigDecimal score, Integer downgradeNum, String proTitleLevelNumber, String ocpQualLevelNumber) {
+        jobSeq = handleJobSeq(jobSeq);
+        String jobSeqNumber = jobSeq.getString(FormConstant.NUMBER_KEY);
+        /**
+         * 如果没有职称等级与技能等级,则倒取该序列最低职等 如果没有职称且是非技能序列,则倒取该序列最低职等 如果是技能序列,没有技能等级但有职称等级,但职称等级没有对应的技能等级,则取该序列最低职等
+         */
+        if (StringUtils.isBlank(proTitleLevelNumber) && (StringUtils.isBlank(ocpQualLevelNumber) || !JobSeqEnum.SKILL.getCode().equals(jobSeqNumber))) {
+            return getLowestJobLevel(jobSeq);
+        }
+        else if (JobSeqEnum.SKILL.getCode().equals(jobSeqNumber) && StringUtils.isBlank(ocpQualLevelNumber) && StringUtils.isNotBlank(proTitleLevelNumber) && TechPostLevelNumberTojobstatusNumberMap.get(proTitleLevelNumber) == null) {
+            return getLowestJobLevel(jobSeq);
+        }
+        String likename = "";
+        String likenumber = "";
+        if (JobSeqEnum.SKILL.getCode().equals(jobSeqNumber)) {
+            if (StringUtils.isBlank(ocpQualLevelNumber)) {
+                likenumber = TechPostLevelNumberTojobstatusNumberMap.get(proTitleLevelNumber);
+                likename = "职称等级【" + proTitleLevelNumber + "】对应的技能等级";
+                System.out.println("技能序列但无技能等级,使用职称等级【" + proTitleLevelNumber + "】对应的技能等级,编码【" + likenumber + "】");
+            }
+            else {
+                likenumber = ocpQualLevelNumber;
+                likename = "技能等级";
+                System.out.println("技能序列使用技能等级,编码【" + likenumber + "】");
+            }
+        }
+        else {
+            likenumber = proTitleLevelNumber;
+            likename = "职称等级";
+            System.out.println("非技能序列使用职称等级,编码【" + likenumber + "】");
+        }
+
+        DynamicObjectCollection jobLevels = queryJobLevels(jobSeq.getString(FormConstant.NUMBER_KEY), score, null,
+                likenumber, String.join(".", FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ + " desc"));
+
+        if(!jobLevels.isEmpty()){
+            if(downgradeNum != null && downgradeNum > 0) {
+                //降级
+                DynamicObject[] jobLevelByJobSeq = getJobLevelByJobSeq(jobSeq);
+                Map<Integer, DynamicObject> jobLevelMap = new HashMap<>();
+                if (jobLevelByJobSeq != null) {
+                    String jobLevelSeqKey = FormConstant.JOBLEVELSEQ;
+                    jobLevelMap = Arrays.stream(jobLevelByJobSeq)
+                            .collect(Collectors.toMap(
+                                    dynamicObject -> dynamicObject.getInt(jobLevelSeqKey),
+                                    dynamicObject -> dynamicObject,
+                                    (existing, replacement) -> existing)
+                            );
+                }
+                //当前分数能达到的最大职级减去需降级数
+                int maxJobLevelSeq = jobLevels.get(0).getInt(FormConstant.JOBLEVELSEQ);
+                DynamicObject jobLevel = jobLevelMap.get(maxJobLevelSeq - downgradeNum);
+                if (jobLevel == null) {
+                    //降级数超出则返回最低职级
+                    return getLowestJobLevel(jobSeq);
+                }
+                return jobLevel;
+            }
+            long jobLevelId = jobLevels.get(0).getLong(String.join(".", FormConstant.HBJM_JOBLEVELHR, FormConstant.ID_KEY));
+            return BusinessDataServiceHelper.loadSingle(jobLevelId, FormConstant.HBJM_JOBLEVELHR);
+        }else{
+            //没有获取到预期的职级则返回最低职级
+            return getLowestJobLevel(jobSeq);
+        }
+    }
+
+    /**
+     * 获取职位序列对应的职级
+     * @param jobSeq 职位序列
+     * @return: kd.bos.dataentity.entity.DynamicObject
+     * @author W.Y.C
+     * @date: 2025/09/20 16:52
+     */
+    public static DynamicObject[] getJobLevelByJobSeq(DynamicObject jobSeq) {
+        DynamicObjectCollection jobLevels = queryJobLevels(jobSeq.getString(FormConstant.NUMBER_KEY), null, null,
+                null, String.join(".", FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ));
+        List<Long> jobLevelIds = jobLevels.stream().map(dynamicObject -> dynamicObject.getLong(String.join(".", FormConstant.HBJM_JOBLEVELHR, FormConstant.ID_KEY))).collect(Collectors.toList());
+        QFilter idInFilter = QFilterCommonHelper.getIdInFilter(jobLevelIds);
+
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                .addIdNumberNameWithExtras(
+                        new String[]{FormConstant.HBJM_JOBLEVELHR},
+                        FormConstant.JOBLEVELSEQ,
+                        FormConstant.NCKD_COEFFICIENT,
+                        FormConstant.NCKD_SCORE
+                );
+
+        return BusinessDataServiceHelper.load(
+                FormConstant.HBJM_JOBLEVELHR,
+                queryFieldBuilder.buildSelect(),
+                new QFilter[]{idInFilter},
+                FormConstant.JOBLEVELSEQ
+        );
+    }
+
+    /**
+     * 根据职位序列、资格条件、积分或序列号筛选职级
+     * @param jobSeqNumber 职位序列编码
+     * @param score 积分
+     * @param jobLevelSeq 职级序号
+     * @param jobLevelNumber 资格编码
+     * @param orderBy 排序
+     * @return: kd.bos.dataentity.entity.DynamicObjectCollection
+     * @author W.Y.C
+     * @date: 2025/09/27 13:49
+     */
+    private static DynamicObjectCollection queryJobLevels(String jobSeqNumber, BigDecimal score, Integer jobLevelSeq, String jobLevelNumber, String orderBy) {
+
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                .addIdNumberNameWithExtras(
+                        new String[]{FormConstant.HBJM_JOBLEVELHR},
+                        FormConstant.JOBLEVELSEQ,
+                        FormConstant.NCKD_COEFFICIENT,
+                        FormConstant.NCKD_SCORE
+                );
+
+
+        QFilter filter = new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR,FormConstant.NCKD_SCORE), QCP.is_notnull, null)
+                .and(new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.IS_CURRENT_VERSION), QCP.equals, EnableEnum.YES.getCode()))
+                .and(new QFilter(String.join( ".",FormConstant.HBJM_JOBLEVELHR,FormConstant.ENABLE), QCP.equals, EnableEnum.YES.getCode()))
+                .and(new QFilter(String.join( ".",FormConstant.HBJM_JOBLEVELHR,FormConstant.STATUS), QCP.equals, StatusEnum.C.toString()))
+                .and(new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ), QCP.is_notnull, null));
+        if(score != null){
+            filter.and(new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NCKD_SCORE), QCP.less_equals, score));
+        }
+        if(jobLevelSeq != null){
+            filter.and(new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ), QCP.less_equals, jobLevelSeq));
+        }else{
+            //只查询有效的序号(无职级是-1,避免查出来)
+            filter.and(new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ), QCP.large_than, 0));
+        }
+
+        DynamicObjectCollection query = null;
+        if(StringUtils.isBlank(jobLevelNumber)){
+            //根据职位序列查询
+            filter.and(new QFilter(String.join(".",FormConstant.NCKD_JOBSEQ,FormConstant.NUMBER_KEY), QCP.equals, jobSeqNumber))
+                    .and(new QFilter(String.join(".",FormConstant.NCKD_JOBSEQ, FormConstant.IS_CURRENT_VERSION), QCP.equals, EnableEnum.YES.getCode()))
+                    .and(new QFilter(String.join( ".",FormConstant.NCKD_JOBSEQ,FormConstant.ENABLE), QCP.equals, EnableEnum.YES.getCode()))
+                    .and(new QFilter(String.join( ".",FormConstant.NCKD_JOBSEQ,FormConstant.STATUS), QCP.equals, StatusEnum.C.toString()));
+            query = QueryServiceHelper.query(PositionStructureConstant.GETLEVELBYJOBSEQ_QUERY,
+                    queryFieldBuilder.buildSelect(),
+                    new QFilter[]{filter},
+                    orderBy);
+        }else{
+            //根据职位序列和资格条件查询
+            filter.and(new QFilter(String.join(".",FormConstant.HBJM_JOBGRADESCMHR,FormConstant.NCKD_JOBSEQ,FormConstant.NUMBER_KEY), QCP.equals, jobSeqNumber))
+                    .and(new QFilter(String.join(".",FormConstant.HBJM_JOBGRADESCMHR,FormConstant.NCKD_JOBSEQ, FormConstant.IS_CURRENT_VERSION), QCP.equals, EnableEnum.YES.getCode()))
+                    .and(new QFilter(String.join( ".",FormConstant.HBJM_JOBGRADESCMHR,FormConstant.NCKD_JOBSEQ,FormConstant.ENABLE), QCP.equals, EnableEnum.YES.getCode()))
+                    .and(new QFilter(String.join( ".",FormConstant.HBJM_JOBGRADESCMHR,FormConstant.NCKD_JOBSEQ,FormConstant.STATUS), QCP.equals, StatusEnum.C.toString()))
+                    .and(new QFilter(String.join(".",FormConstant.IS_CURRENT_VERSION), QCP.equals, EnableEnum.YES.getCode()))
+                    .and(new QFilter(String.join( ".",FormConstant.ENABLE), QCP.equals, EnableEnum.YES.getCode()))
+                    .and(new QFilter(String.join( ".",FormConstant.STATUS), QCP.equals, StatusEnum.C.toString()));
+            filter.and(new QFilter(FormConstant.NCKD_JOBLEVELNUMBER, QCP.like, "%"+jobLevelNumber+"%"));
+            query = QueryServiceHelper.query(PositionStructureConstant.GETLEVELBYJOBSEQQUERYANDQUAL_QUERY,
+                    queryFieldBuilder.buildSelect(),
+                    new QFilter[]{filter},
+                    orderBy);
+        }
+        return query;
+    }
+
     // 辅助类定义
-    private static class JobFamilyInfo {
+    public static class JobFamilyInfo {
         /** 是否为序列转换 */
         //对应SHR:isadjusttype_4
         boolean isSequenceChange;
@@ -1476,6 +1683,10 @@ public class JobLevelCalculatorService {
         String perProTitleNumber;
         /** 技能等级编码 */
         String quaLevelNumber;
+        /** 职称级别名称 */
+        String perProTitleName;
+        /** 技能等级名称 */
+        String quaLevelName;
         /** 是否缺少聘任 */
         boolean isEndGainJobGrade;
     }
@@ -1515,7 +1726,4 @@ public class JobLevelCalculatorService {
         public String adjustMsg;
         public DynamicObject jobLevel;
     }
-}
-
-
-
+}

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

@@ -170,7 +170,15 @@ public class PositionStructureConstant extends FormConstant {
     public static final String NEWDYNAMICADJUDIALOG_ENTITYID = "nckd_newdynamicadjudialog";
     /** 本次加入集团日期 */
     public static final String NCKD_ADJUSTDATE = "nckd_adjustdate";
+    //调动后职级
+    public static final String NCKD_JOBLEVEL = "nckd_joblevel";
+    /** 确认定级 */
+    public static final String OP_CONFIRMADJUST = "confirmadjust";
     /*-------------------------------------- 新建动态调整(弹窗) end --------------------------------------*/
     /**职位序列对应职级查询*/
-    public static final String JOBSEQTOJOBLEVELQUERY = "jobseqtojoblevelquery";
+    public static final String JOBSEQTOJOBLEVEL_QUERY = "jobseqtojoblevelquery";
+    /**根据职位序列查询职级*/
+    public static final String GETLEVELBYJOBSEQ_QUERY = "getlevelbyjobseqquery";
+    /**根据职位序列和资格级别查询职级*/
+    public static final String GETLEVELBYJOBSEQQUERYANDQUAL_QUERY = "getlevelbyjobseqqueryandqualquery";
 }

+ 98 - 142
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/helper/PositionStructureHelper.java

@@ -9,6 +9,7 @@ import kd.bos.servicehelper.BusinessDataServiceHelper;
 import kd.bos.servicehelper.QueryServiceHelper;
 import nckd.jxccl.base.common.constant.FormConstant;
 import nckd.jxccl.base.common.enums.JobSeqEnum;
+import nckd.jxccl.base.common.utils.QueryFieldBuilder;
 import nckd.jxccl.hr.psms.common.PositionStructureConstant;
 
 import java.math.BigDecimal;
@@ -24,50 +25,7 @@ import java.util.StringJoiner;
  */
 public class PositionStructureHelper {
 
-    /**
-     * 计算职级
-     * 对应SHR:com.kingdee.shr.customer.web.handler.PersonpositionfileUtils#GainJobGrade 和 com.kingdee.shr.customer.web.handler.PersonpositionfileUtils#endGainJobGrade
-     * TODO [待补充完成]
-     * @param jobSeq 职位序列
-     * @param score 积分数
-     * @param proTitleLevel 职称等级
-     * @param ocpQualLevel 技能等级
-     * @param appraisalResult 绩效结果
-     * @param downgradeNum 降级数(根据绩效计算:基本合格:降1级、不合格:降2级)
-     * @param useMinLevel 是否强制按最低职级定级
-     * @param useNonLevel 是否强制按无职级定级(当为true时不满足三要素【聘任职称/技能、考核结果、积分】任意一条件时按“无职级”定级)
-     * @return: kd.bos.dataentity.entity.DynamicObject 返回:匹配的职级
-     * @author W.Y.C
-     * @date: 2025/09/13 14:21
-     */
-    public static DynamicObject calculateLevel(JobSeqEnum jobSeq, BigDecimal score, DynamicObject proTitleLevel,DynamicObject ocpQualLevel,
-                                               DynamicObject appraisalResult,int downgradeNum,boolean useMinLevel,boolean useNonLevel) {
-        //三要素说明:
-        //1、【技术序列、职能序列】:有聘任的职称等级;【技能序列】:有聘任的技能等级
-        //2、有考核结果
-        //3、积分数能够达到职级
-        if(useNonLevel) {
-            boolean nonLevel = Boolean.FALSE;
-            if ((jobSeq == JobSeqEnum.TECHNICALS || jobSeq == JobSeqEnum.FUNCTIONAL) && proTitleLevel == null) {
-                //【技术序列或职能序列】无职称等级
-                nonLevel = Boolean.TRUE;
-            } else if (jobSeq == JobSeqEnum.SKILL && ocpQualLevel == null) {
-                //【技能序列】无技能等级
-                nonLevel = Boolean.TRUE;
-            }
-            if (appraisalResult == null) {
-                //无考核结果
-                nonLevel = Boolean.TRUE;
-            }
-            if(score.compareTo(new BigDecimal(18)) < 0){
-                //积分数小于18
-                nonLevel = Boolean.TRUE;
-            }
-            //查询该序列“无职级”的数据并返回
-        }
-        DynamicObject dynamicObject = BusinessDataServiceHelper.loadSingle("2294386972933752832", "hbjm_joblevelhr");
-        return dynamicObject;
-    }
+
 
 
     /**
@@ -106,7 +64,7 @@ public class PositionStructureHelper {
         if(otherFilter != null){
             filer.and(otherFilter);
         }
-        StringJoiner selectFields = new StringJoiner(",")
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                 .add(FormConstant.ID_KEY)
                 .add(PositionStructureConstant.NCKD_BEGINDATE)
                 .add(PositionStructureConstant.NCKD_EXECUTEYEAR)
@@ -115,9 +73,7 @@ public class PositionStructureHelper {
                 .add(PositionStructureConstant.NCKD_DIPLOMASCORE)
                 .add(PositionStructureConstant.NCKD_RANKSCORE)
                 .add(PositionStructureConstant.NCKD_JOBSTATUSSCORE)
-                .add(String.join(".",PositionStructureConstant.NCKD_APPRAISALRESULT,FormConstant.ID_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_APPRAISALRESULT,FormConstant.NAME_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_APPRAISALRESULT,FormConstant.NUMBER_KEY))
+                .addIdNumberName(PositionStructureConstant.NCKD_APPRAISALRESULT)
                 .add(PositionStructureConstant.NCKD_ALLOWANCERANKPCT)
                 .add(PositionStructureConstant.NCKD_ALLOWANCERANKSEL)
                 .add(PositionStructureConstant.NCKD_ALLOWANCERANKMARK)
@@ -125,28 +81,28 @@ public class PositionStructureHelper {
                 .add(PositionStructureConstant.NCKD_SUMSCORE)
                 .add(PositionStructureConstant.NCKD_JOBLEVELHR)
                 .add(PositionStructureConstant.NCKD_RANKNAME)
-                .add(String.join(".",PositionStructureConstant.NCKD_PROTITLELEVEL,FormConstant.ID_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_PROTITLELEVEL,FormConstant.NAME_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_PROTITLELEVEL,FormConstant.NUMBER_KEY))
+                .addIdNumberName(PositionStructureConstant.NCKD_PROTITLELEVEL)
                 .add(PositionStructureConstant.NCKD_JOBSTATUSNAME)
-                .add(String.join(".",PositionStructureConstant.NCKD_OCPQUALLEVEL,FormConstant.ID_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_OCPQUALLEVEL,FormConstant.NAME_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_OCPQUALLEVEL,FormConstant.NUMBER_KEY))
+                .addIdNumberName(PositionStructureConstant.NCKD_OCPQUALLEVEL)
+                .addIdNumberNameWithExtras(
+                        new String[]{PositionStructureConstant.NCKD_JOBLEVELHR},
+                        FormConstant.JOBLEVELSEQ
+                )
+                .addIdNumberNameWithExtras(
+                        new String[]{PositionStructureConstant.NCKD_DIPLOMA},
+                        FormConstant.NCKD_SCORE
+                )
+                .addIdNumberName(PositionStructureConstant.NCKD_JOBSEQHR)
+                .orderDesc(PositionStructureConstant.NCKD_BEGINDATE);
 
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBLEVELHR,FormConstant.ID_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBLEVELHR,FormConstant.NAME_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBLEVELHR,FormConstant.NUMBER_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBLEVELHR,FormConstant.JOBLEVELSEQ))
+        return BusinessDataServiceHelper.load(
+                PositionStructureConstant.PERSONPOSFILE_ENTITYID,
+                queryFieldBuilder.buildSelect(),
+                new QFilter[]{filer},
+                queryFieldBuilder.buildOrder()
+        );
 
-                .add(String.join(".",PositionStructureConstant.NCKD_DIPLOMA,FormConstant.ID_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_DIPLOMA,FormConstant.NAME_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_DIPLOMA,FormConstant.NUMBER_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_DIPLOMA,FormConstant.NCKD_SCORE))
 
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBSEQHR,FormConstant.ID_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBSEQHR,FormConstant.NAME_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBSEQHR,FormConstant.NUMBER_KEY));
-        return BusinessDataServiceHelper.load(PositionStructureConstant.PERSONPOSFILE_ENTITYID, selectFields.toString(), new QFilter[]{filer},PositionStructureConstant.NCKD_BEGINDATE + " desc");
     }
 
     /**
@@ -185,7 +141,7 @@ public class PositionStructureHelper {
         if(otherFilter != null){
             filer.and(otherFilter);
         }
-        StringJoiner selectFields = new StringJoiner(",")
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                 .add(FormConstant.ID_KEY)
                 .add(PositionStructureConstant.NCKD_BEGINDATE)
                 .add(PositionStructureConstant.NCKD_EXECUTEYEAR)
@@ -194,37 +150,36 @@ public class PositionStructureHelper {
                 .add(PositionStructureConstant.NCKD_DIPLOMASCORE)
                 .add(PositionStructureConstant.NCKD_RANKSCORE)
                 .add(PositionStructureConstant.NCKD_JOBSTATUSSCORE)
-                .add(String.join(".",PositionStructureConstant.NCKD_APPRAISALRESULT,FormConstant.ID_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_APPRAISALRESULT,FormConstant.NAME_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_APPRAISALRESULT,FormConstant.NUMBER_KEY))
+                .addIdNumberName(PositionStructureConstant.NCKD_APPRAISALRESULT)
                 .add(PositionStructureConstant.NCKD_ALLOWANCERANKPCT)
                 .add(PositionStructureConstant.NCKD_ALLOWANCERANKSEL)
                 .add(PositionStructureConstant.NCKD_ALLOWANCERANKMARK)
                 .add(PositionStructureConstant.NCKD_ALLSUMSCORE)
+                .add(PositionStructureConstant.NCKD_SUMSCORE)
                 .add(PositionStructureConstant.NCKD_JOBLEVELHR)
                 .add(PositionStructureConstant.NCKD_RANKNAME)
-                .add(String.join(".",PositionStructureConstant.NCKD_PROTITLELEVEL,FormConstant.ID_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_PROTITLELEVEL,FormConstant.NAME_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_PROTITLELEVEL,FormConstant.NUMBER_KEY))
+                .addIdNumberName(PositionStructureConstant.NCKD_PROTITLELEVEL)
                 .add(PositionStructureConstant.NCKD_JOBSTATUSNAME)
-                .add(String.join(".",PositionStructureConstant.NCKD_OCPQUALLEVEL,FormConstant.ID_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_OCPQUALLEVEL,FormConstant.NAME_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_OCPQUALLEVEL,FormConstant.NUMBER_KEY))
-
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBLEVELHR,FormConstant.ID_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBLEVELHR,FormConstant.NAME_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBLEVELHR,FormConstant.NUMBER_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBLEVELHR,FormConstant.JOBLEVELSEQ))
-                //学历
-                .add(String.join(".",PositionStructureConstant.NCKD_DIPLOMA,FormConstant.ID_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_DIPLOMA,FormConstant.NAME_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_DIPLOMA,FormConstant.NUMBER_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_DIPLOMA,FormConstant.NCKD_SCORE))
+                .addIdNumberName(PositionStructureConstant.NCKD_OCPQUALLEVEL)
+                .addIdNumberNameWithExtras(
+                        new String[]{PositionStructureConstant.NCKD_JOBLEVELHR},
+                        FormConstant.JOBLEVELSEQ
+                )
+                // 学历
+                .addIdNumberNameWithExtras(
+                        new String[]{PositionStructureConstant.NCKD_DIPLOMA},
+                        FormConstant.NCKD_SCORE
+                )
+                // 职位序列
+                .addIdNumberName(PositionStructureConstant.NCKD_JOBSEQHR)
+                .orderDesc(PositionStructureConstant.NCKD_BEGINDATE);
 
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBSEQHR,FormConstant.ID_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBSEQHR,FormConstant.NAME_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBSEQHR,FormConstant.NUMBER_KEY));
-        DynamicObject[] load = BusinessDataServiceHelper.load(PositionStructureConstant.PERSONPOSFILE_ENTITYID, selectFields.toString(), new QFilter[]{filer},PositionStructureConstant.NCKD_BEGINDATE + " desc");
+        DynamicObject[] load = BusinessDataServiceHelper.load(
+                PositionStructureConstant.PERSONPOSFILE_ENTITYID,
+                queryFieldBuilder.buildSelect(),
+                new QFilter[]{filer},
+                queryFieldBuilder.buildOrder()
+        );
         return load.length > 0 ? load[0] : null;
 
     }
@@ -240,34 +195,34 @@ public class PositionStructureHelper {
         QFilter filer = new QFilter(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY), QCP.equals, personId)
                 .and(new QFilter(PositionStructureConstant.NCKD_DISABLE, QCP.equals, EnableEnum.NO.getCode()))
                 .and(new QFilter(PositionStructureConstant.NCKD_FIRSTRANK, QCP.equals, EnableEnum.YES.getCode()));
-        StringJoiner selectFields = new StringJoiner(",")
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                 .add(FormConstant.ID_KEY)
                 .add(PositionStructureConstant.NCKD_BEGINDATE)
                 .add(PositionStructureConstant.NCKD_EXECUTEYEAR)
                 .add(PositionStructureConstant.NCKD_TYPESTATE)
                 .add(PositionStructureConstant.NCKD_FIRSTRANK)
-                .add(String.join(".",PositionStructureConstant.NCKD_APPRAISALRESULT,FormConstant.ID_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_APPRAISALRESULT,FormConstant.NAME_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_APPRAISALRESULT,FormConstant.NUMBER_KEY))
+                .addIdNumberName(PositionStructureConstant.NCKD_APPRAISALRESULT)
                 .add(PositionStructureConstant.NCKD_ALLOWANCERANKPCT)
                 .add(PositionStructureConstant.NCKD_ALLOWANCERANKSEL)
                 .add(PositionStructureConstant.NCKD_ALLOWANCERANKMARK)
                 .add(PositionStructureConstant.NCKD_ALLSUMSCORE)
                 .add(PositionStructureConstant.NCKD_JOBLEVELHR)
                 .add(PositionStructureConstant.NCKD_RANKNAME)
-                .add(String.join(".",PositionStructureConstant.NCKD_PROTITLELEVEL,FormConstant.ID_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_PROTITLELEVEL,FormConstant.NAME_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_PROTITLELEVEL,FormConstant.NUMBER_KEY))
+                .addIdNumberName(PositionStructureConstant.NCKD_PROTITLELEVEL)
                 .add(PositionStructureConstant.NCKD_JOBSTATUSNAME)
-                .add(String.join(".",PositionStructureConstant.NCKD_OCPQUALLEVEL,FormConstant.ID_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_OCPQUALLEVEL,FormConstant.NAME_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_OCPQUALLEVEL,FormConstant.NUMBER_KEY))
+                .addIdNumberName(PositionStructureConstant.NCKD_OCPQUALLEVEL)
+                .addIdNumberNameWithExtras(
+                        new String[]{PositionStructureConstant.NCKD_JOBLEVELHR},
+                        FormConstant.JOBLEVELSEQ
+                )
+                .orderDesc(PositionStructureConstant.NCKD_BEGINDATE);
 
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBLEVELHR,FormConstant.ID_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBLEVELHR,FormConstant.NAME_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBLEVELHR,FormConstant.NUMBER_KEY))
-                .add(String.join(".",PositionStructureConstant.NCKD_JOBLEVELHR,FormConstant.JOBLEVELSEQ));
-        DynamicObject[] load = BusinessDataServiceHelper.load(PositionStructureConstant.PERSONPOSFILE_ENTITYID, selectFields.toString(), new QFilter[]{filer},PositionStructureConstant.NCKD_BEGINDATE + " desc");
+        DynamicObject[] load = BusinessDataServiceHelper.load(
+                PositionStructureConstant.PERSONPOSFILE_ENTITYID,
+                queryFieldBuilder.buildSelect(),
+                new QFilter[]{filer},
+                queryFieldBuilder.buildOrder()
+        );
         return load.length > 0 ? load[0] : null;
     }
 
@@ -280,42 +235,42 @@ public class PositionStructureHelper {
      * @date: 2025/09/17 10:27
      */
     public static DynamicObject positionAppointmentQuery(Long personId, Date date) {
-        StringJoiner selectFields = new StringJoiner(",")
-                //所属公司
-                .add(String.join(".", FormConstant.COMPANY_KEY, FormConstant.ID_KEY))
-                .add(String.join(".", FormConstant.COMPANY_KEY, FormConstant.NAME_KEY))
-                .add(String.join(".", FormConstant.COMPANY_KEY, FormConstant.NUMBER_KEY))
-                //行政组织(部门)
-                .add(String.join(".", FormConstant.ADMINORG, FormConstant.ID_KEY))
-                .add(String.join(".", FormConstant.ADMINORG, FormConstant.NAME_KEY))
-                .add(String.join(".", FormConstant.ADMINORG, FormConstant.NUMBER_KEY))
-                //岗位
-                .add(String.join(".", FormConstant.POSITION_KEY, FormConstant.ID_KEY))
-                .add(String.join(".", FormConstant.POSITION_KEY, FormConstant.NAME_KEY))
-                .add(String.join(".", FormConstant.POSITION_KEY, FormConstant.NUMBER_KEY))
-                //职位序列
-                .add(String.join(".", FormConstant.HBPM_POSITIONHR, FormConstant.NCKD_JOBSEQ,FormConstant.ID_KEY))
-                .add(String.join(".", FormConstant.HBPM_POSITIONHR, FormConstant.NCKD_JOBSEQ,FormConstant.NAME_KEY))
-                .add(String.join(".", FormConstant.HBPM_POSITIONHR, FormConstant.NCKD_JOBSEQ,FormConstant.NUMBER_KEY))
-                //学历
-                .add(String.join(".", FormConstant.HRPI_PEREDUEXP, FormConstant.EDUCATION_KEY, FormConstant.ID_KEY))
-                .add(String.join(".", FormConstant.HRPI_PEREDUEXP, FormConstant.EDUCATION_KEY, FormConstant.NAME_KEY))
-                .add(String.join(".", FormConstant.HRPI_PEREDUEXP, FormConstant.EDUCATION_KEY, FormConstant.NUMBER_KEY))
-                .add(String.join(".", FormConstant.HRPI_PEREDUEXP, FormConstant.EDUCATION_KEY, FormConstant.NCKD_SCORE))
-                //职称等级
-                .add(String.join(".", FormConstant.HRPI_PERPROTITLE, FormConstant.PROLEVEL_KEY, FormConstant.ID_KEY))
-                .add(String.join(".", FormConstant.HRPI_PERPROTITLE, FormConstant.PROLEVEL_KEY, FormConstant.NAME_KEY))
-                .add(String.join(".", FormConstant.HRPI_PERPROTITLE, FormConstant.PROLEVEL_KEY, FormConstant.NUMBER_KEY))
-                .add(String.join(".", FormConstant.HRPI_PERPROTITLE, FormConstant.PROLEVEL_KEY, FormConstant.NCKD_SCORE))
-                //技能等级
-                .add(String.join(".", FormConstant.HRPI_PEROCPQUAL, FormConstant.QUALEVEL_KEY, FormConstant.ID_KEY))
-                .add(String.join(".", FormConstant.HRPI_PEROCPQUAL, FormConstant.QUALEVEL_KEY, FormConstant.NAME_KEY))
-                .add(String.join(".", FormConstant.HRPI_PEROCPQUAL, FormConstant.QUALEVEL_KEY, FormConstant.NUMBER_KEY))
-                .add(String.join(".", FormConstant.HRPI_PEROCPQUAL, FormConstant.QUALEVEL_KEY, FormConstant.NCKD_SCORE))
-                //服务年限.本次加入集团日期
-                .add(String.join(".", FormConstant.HRPI_PERSERLEN,FormConstant.JOINCOMDATE_KEY))
-                //服务年限.首次加入集团日期
-                .add(String.join(".", FormConstant.HRPI_PERSERLEN,FormConstant.FIRSTJOINCOMDATE_KEY));
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                .add(FormConstant.ID_KEY)
+                // 组织分配
+                .addGroup(new String[]{FormConstant.ASSIGNMENT}, FormConstant.ID_KEY)
+                // 所属公司
+                .addIdNumberName(FormConstant.COMPANY_KEY)
+                // 行政组织(部门)
+                .addIdNumberName(FormConstant.ADMINORG)
+                // 岗位
+                .addIdNumberName(FormConstant.POSITION_KEY)
+                // 职位序列
+                .addIdNumberName(new String[]{FormConstant.HBPM_POSITIONHR, FormConstant.NCKD_JOBSEQ})
+                // 学历
+                .addIdNumberNameWithExtras(
+                        new String[]{FormConstant.HRPI_PEREDUEXP, FormConstant.EDUCATION_KEY},
+                        FormConstant.NCKD_SCORE
+                )
+                // 职称
+                .addGroup(new String[]{FormConstant.HRPI_PERPROTITLE, FormConstant.PROFESSIONAL_KEY}, FormConstant.NAME_KEY)
+                // 职称等级
+                .addIdNumberNameWithExtras(
+                        new String[]{FormConstant.HRPI_PERPROTITLE, FormConstant.PROLEVEL_KEY},
+                        FormConstant.NCKD_SCORE
+                )
+                // 技能
+                .addGroup(new String[]{FormConstant.HRPI_PEROCPQUAL, FormConstant.QUALIFICATION_KEY}, FormConstant.NAME_KEY)
+                // 技能等级
+                .addIdNumberNameWithExtras(
+                        new String[]{FormConstant.HRPI_PEROCPQUAL, FormConstant.QUALEVEL_KEY},
+                        FormConstant.NCKD_SCORE
+                )
+                // 服务年限
+                .addGroup(new String[]{FormConstant.HRPI_PERSERLEN},
+                        FormConstant.JOINCOMDATE_KEY,
+                        FormConstant.FIRSTJOINCOMDATE_KEY
+                );
 
         //获取时间范围内的任职信息
         QFilter filer = new QFilter(String.join(".", FormConstant.EMPLOYEE_KEY,FormConstant.ID_KEY),QCP.equals,personId)
@@ -332,7 +287,8 @@ public class PositionStructureHelper {
         //TODO 职称聘任时间
         //TODO 技能聘任时间
 
-        DynamicObjectCollection query = QueryServiceHelper.query(PositionStructureConstant.POSITIONAPPOINTMENTQUERY, selectFields.toString(), new QFilter[]{filer});
+        DynamicObjectCollection query = QueryServiceHelper.query(PositionStructureConstant.POSITIONAPPOINTMENTQUERY, queryFieldBuilder.buildSelect(), new QFilter[]{filer});
         return !query.isEmpty() ? query.get(0) : null;
+
     }
 }

+ 18 - 2
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/adjust/NewDynamicAdjustmentDiaLogFormPlugin.java

@@ -4,6 +4,8 @@ import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.entity.datamodel.events.ChangeData;
 import kd.bos.entity.datamodel.events.PropertyChangedArgs;
 import kd.bos.form.FormShowParameter;
+import kd.bos.form.MessageBoxOptions;
+import kd.bos.form.events.AfterDoOperationEventArgs;
 import kd.bos.form.plugin.AbstractFormPlugin;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
@@ -19,6 +21,7 @@ import nckd.jxccl.hr.psms.helper.PositionStructureHelper;
 import java.time.LocalDateTime;
 import java.util.Date;
 import java.util.EventObject;
+import java.util.Map;
 import java.util.Objects;
 import java.util.StringJoiner;
 
@@ -49,8 +52,7 @@ public class NewDynamicAdjustmentDiaLogFormPlugin extends AbstractFormPlugin {
     }
 
     @Override
-    public void propertyChanged(PropertyChangedArgs e) {
-        System.out.println();
+    public void beforePropertyChanged(PropertyChangedArgs e) {
         String fieldKey = e.getProperty().getName();
         ChangeData[] changeSet = e.getChangeSet();
 
@@ -72,6 +74,7 @@ public class NewDynamicAdjustmentDiaLogFormPlugin extends AbstractFormPlugin {
                         }else{
                             DynamicObject jobLevel = getJobLevel(person, adjustDate);
                             this.getModel().setValue(PositionStructureConstant.PERSONPOSFILE_ENTITYID, latsPersonPosFileByPerson);
+                            this.getModel().setValue(PositionStructureConstant.NCKD_JOBLEVEL, jobLevel);
                         }
                     }
                 }
@@ -80,6 +83,7 @@ public class NewDynamicAdjustmentDiaLogFormPlugin extends AbstractFormPlugin {
     }
 
 
+
     public static DynamicObject getJobLevel(DynamicObject person,Date date){
         //移植代码:com.kingdee.shr.customer.web.handler.ContributeScore.PersonpositionfileFluctuationListHandler#selaboutJobGradeAction
         long personId = person.getLong(FormConstant.ID_KEY);
@@ -156,4 +160,16 @@ public class NewDynamicAdjustmentDiaLogFormPlugin extends AbstractFormPlugin {
 
         return jobLevelResult.jobLevel;
     }
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
+        String operateKey = afterDoOperationEventArgs.getOperateKey();
+        boolean success = afterDoOperationEventArgs.getOperationResult() != null && afterDoOperationEventArgs.getOperationResult().isSuccess();
+        if(success && PositionStructureConstant.OP_CONFIRMINITIAL.equalsIgnoreCase(operateKey)){
+            Map<String, String> customData = afterDoOperationEventArgs.getOperationResult().getCustomData();
+            String jobLeveStr = customData.get(PositionStructureConstant.NCKD_JOBLEVELHR);
+            this.getView().returnDataToParent("true");
+            this.getView().showConfirm("提示","新建调整成功,职位档案已生成。",jobLeveStr, MessageBoxOptions.OK,null,null,null,null);
+        }
+    }
 }

+ 94 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/initial/NewHireInitialFormPlugin.java

@@ -1,12 +1,22 @@
 package nckd.jxccl.hr.psms.plugin.form.initial;
 
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.datamodel.events.ChangeData;
+import kd.bos.entity.datamodel.events.PropertyChangedArgs;
+import kd.bos.form.FormShowParameter;
 import kd.bos.form.MessageBoxOptions;
 import kd.bos.form.events.AfterDoOperationEventArgs;
 import kd.bos.form.plugin.AbstractFormPlugin;
 import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.utils.ConvertUtil;
 import nckd.jxccl.hr.psms.common.PositionStructureConstant;
+import nckd.jxccl.hr.psms.helper.PositionStructureHelper;
 
+import java.util.Date;
+import java.util.EventObject;
 import java.util.Map;
+import java.util.Objects;
 
 /**
 * 新入职人员初定(弹窗)-弹窗页面插件
@@ -15,6 +25,89 @@ import java.util.Map;
 * @version 1.0
 */
 public class NewHireInitialFormPlugin extends AbstractFormPlugin implements Plugin {
+
+    @Override
+    public void afterCreateNewData(EventObject e) {
+        FormShowParameter showParameter = this.getView().getFormShowParameter();
+        //获取列表选择的人员
+        Object personId = showParameter.getCustomParam("personId");
+        if(personId != null) {
+            this.getModel().setValue(FormConstant.NCKD_PERSON, personId);
+            this.getView().updateView(FormConstant.NCKD_PERSON);
+
+            initValue(ConvertUtil.toLong(personId),null);
+        }
+    }
+
+    @Override
+    public void propertyChanged(PropertyChangedArgs e) {
+        String fieldKey = e.getProperty().getName();
+        ChangeData[] changeSet = e.getChangeSet();
+
+        //【员工】或【调整日期】发生变更则重新获取员工任职信息
+        if (PositionStructureConstant.NCKD_BEGINDATE.equalsIgnoreCase(fieldKey) || FormConstant.NCKD_PERSON.equalsIgnoreCase(fieldKey)) {
+            if (changeSet != null && changeSet.length > 0) {
+                ChangeData changeData = changeSet[0];
+                Object oldValue = changeData.getOldValue();
+                Object newValue = changeData.getNewValue();
+                if (!Objects.equals(oldValue, newValue)) {
+                    Date beginDate = ConvertUtil.toDate(this.getModel().getValue(PositionStructureConstant.NCKD_BEGINDATE));
+                    DynamicObject person = ConvertUtil.toDynamicObject(this.getModel().getValue(PositionStructureConstant.NCKD_PERSON));
+                    if(person.getDataEntityType() != null) {
+                        initValue(person.getLong(FormConstant.ID_KEY), beginDate);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 初始化表单信息
+     * @param personId 人员ID
+     * @param date 日期
+     * @return: void
+     * @author W.Y.C
+     * @date: 2025/09/25 21:40
+     */
+    private void initValue(Long personId, Date date){
+        if(date == null){
+            date = new Date();
+        }
+        DynamicObject positionAppointMen = PositionStructureHelper.positionAppointmentQuery(personId, date);
+        if(positionAppointMen != null) {
+            //学历
+            long diplomaId = positionAppointMen.getLong(String.join(".", FormConstant.HRPI_PEREDUEXP, FormConstant.EDUCATION_KEY, FormConstant.ID_KEY));
+            this.getModel().setValue(PositionStructureConstant.NCKD_DIPLOMA, diplomaId == 0?null:diplomaId);
+            //岗位
+            long positionId = positionAppointMen.getLong(String.join(".", FormConstant.POSITION_KEY, FormConstant.ID_KEY));
+            this.getModel().setValue(PositionStructureConstant.NCKD_POSITIONHR, positionId == 0 ? null : positionId);
+            //职位序列
+            long jobSeqId = positionAppointMen.getLong(String.join(".", FormConstant.HBPM_POSITIONHR, FormConstant.NCKD_JOBSEQ, FormConstant.ID_KEY));
+            this.getModel().setValue(PositionStructureConstant.NCKD_JOBSEQ, jobSeqId == 0 ? null : jobSeqId);
+            //职称名称
+            this.getModel().setValue(PositionStructureConstant.NCKD_RANKNAME, positionAppointMen.getString(String.join(".", FormConstant.HRPI_PERPROTITLE, FormConstant.PROFESSIONAL_KEY, FormConstant.NAME_KEY)));
+            //职称等级
+            long proLevelId = positionAppointMen.getLong(String.join(".", FormConstant.HRPI_PERPROTITLE, FormConstant.PROLEVEL_KEY, FormConstant.ID_KEY));
+            this.getModel().setValue(PositionStructureConstant.NCKD_PROTITLELEVEL, proLevelId == 0 ? null : proLevelId);
+            //技能名称
+            this.getModel().setValue(PositionStructureConstant.NCKD_JOBSTATUSNAME, positionAppointMen.getString(String.join(".", FormConstant.HRPI_PEROCPQUAL, FormConstant.QUALIFICATION_KEY, FormConstant.NAME_KEY)));
+            //技能等级
+            long quaLevelId = positionAppointMen.getLong(String.join(".", FormConstant.HRPI_PEROCPQUAL, FormConstant.QUALEVEL_KEY, FormConstant.ID_KEY));
+            this.getModel().setValue(PositionStructureConstant.NCKD_OCPQUALLEVEL, quaLevelId == 0 ? null : quaLevelId);
+            //组织分配
+            long assignmentId = positionAppointMen.getLong(String.join(".", FormConstant.ASSIGNMENT, FormConstant.ID_KEY));
+            this.getModel().setValue(PositionStructureConstant.NCKD_ASSIGNMENT, assignmentId == 0 ? null : assignmentId);
+            //任职信息
+            long empPosOrgRelId = positionAppointMen.getLong(FormConstant.ID_KEY);
+            this.getModel().setValue(PositionStructureConstant.NCKD_EMPPOSORGREL, assignmentId == 0 ? null : empPosOrgRelId);
+            //本次加入集团日期
+            Date joinComDate = positionAppointMen.getDate(String.join(".", FormConstant.HRPI_PERSERLEN,FormConstant.JOINCOMDATE_KEY));
+            this.getModel().setValue(PositionStructureConstant.NCKD_JOINCOMDATE, joinComDate);
+            //是否优秀生
+            // this.getModel().setValue(PositionStructureConstant.NCKD_EXCELLENT, );
+        }
+    }
+
     @Override
     public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
         String operateKey = afterDoOperationEventArgs.getOperateKey();
@@ -22,6 +115,7 @@ public class NewHireInitialFormPlugin extends AbstractFormPlugin implements Plug
         if(success && PositionStructureConstant.OP_CONFIRMINITIAL.equalsIgnoreCase(operateKey)){
             Map<String, String> customData = afterDoOperationEventArgs.getOperationResult().getCustomData();
             String jobLeveStr = customData.get(PositionStructureConstant.NCKD_JOBLEVELHR);
+            this.getView().returnDataToParent("true");
             this.getView().showConfirm("提示","初定成功,职位档案已生成。",jobLeveStr, MessageBoxOptions.OK,null,null,null,null);
         }
     }

+ 91 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/initial/ServingInitialFormPlugin.java

@@ -1,12 +1,22 @@
 package nckd.jxccl.hr.psms.plugin.form.initial;
 
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.datamodel.events.ChangeData;
+import kd.bos.entity.datamodel.events.PropertyChangedArgs;
+import kd.bos.form.FormShowParameter;
 import kd.bos.form.MessageBoxOptions;
 import kd.bos.form.events.AfterDoOperationEventArgs;
 import kd.bos.form.plugin.AbstractFormPlugin;
 import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.utils.ConvertUtil;
 import nckd.jxccl.hr.psms.common.PositionStructureConstant;
+import nckd.jxccl.hr.psms.helper.PositionStructureHelper;
 
+import java.util.Date;
+import java.util.EventObject;
 import java.util.Map;
+import java.util.Objects;
 
 /**
 * 在职人员初定(弹窗)-弹窗页面插件
@@ -16,6 +26,85 @@ import java.util.Map;
 */
 public class ServingInitialFormPlugin extends AbstractFormPlugin implements Plugin {
 
+    @Override
+    public void afterCreateNewData(EventObject e) {
+        FormShowParameter showParameter = this.getView().getFormShowParameter();
+        //获取列表选择的人员
+        Object personId = showParameter.getCustomParam("personId");
+        if(personId != null) {
+            this.getModel().setValue(FormConstant.NCKD_PERSON, personId);
+            this.getView().updateView(FormConstant.NCKD_PERSON);
+
+            initValue(ConvertUtil.toLong(personId),null);
+        }
+    }
+
+    @Override
+    public void propertyChanged(PropertyChangedArgs e) {
+        String fieldKey = e.getProperty().getName();
+        ChangeData[] changeSet = e.getChangeSet();
+
+        //【员工】或【调整日期】发生变更则重新获取员工任职信息
+        if (PositionStructureConstant.NCKD_BEGINDATE.equalsIgnoreCase(fieldKey) || FormConstant.NCKD_PERSON.equalsIgnoreCase(fieldKey)) {
+            if (changeSet != null && changeSet.length > 0) {
+                ChangeData changeData = changeSet[0];
+                Object oldValue = changeData.getOldValue();
+                Object newValue = changeData.getNewValue();
+                if (!Objects.equals(oldValue, newValue)) {
+                    Date beginDate = ConvertUtil.toDate(this.getModel().getValue(PositionStructureConstant.NCKD_BEGINDATE));
+                    DynamicObject person = ConvertUtil.toDynamicObject(this.getModel().getValue(PositionStructureConstant.NCKD_PERSON));
+                    if(person.getDataEntityType() != null) {
+                        initValue(person.getLong(FormConstant.ID_KEY), beginDate);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 初始化表单数据
+     * @param personId 人员ID
+     * @param date 日期
+     * @return: void
+     * @author W.Y.C
+     * @date: 2025/09/25 21:39
+     */
+    private void initValue(Long personId,Date date){
+        if(date == null){
+            date = new Date();
+        }
+        DynamicObject positionAppointMen = PositionStructureHelper.positionAppointmentQuery(personId, date);
+        if(positionAppointMen != null) {
+            //学历
+            long diplomaId = positionAppointMen.getLong(String.join(".", FormConstant.HRPI_PEREDUEXP, FormConstant.EDUCATION_KEY, FormConstant.ID_KEY));
+            this.getModel().setValue(PositionStructureConstant.NCKD_DIPLOMA, diplomaId == 0?null:diplomaId);
+            //岗位
+            long positionId = positionAppointMen.getLong(String.join(".", FormConstant.POSITION_KEY, FormConstant.ID_KEY));
+            this.getModel().setValue(PositionStructureConstant.NCKD_POSITIONHR, positionId == 0 ? null : positionId);
+            //职位序列
+            long jobSeqId = positionAppointMen.getLong(String.join(".", FormConstant.HBPM_POSITIONHR, FormConstant.NCKD_JOBSEQ, FormConstant.ID_KEY));
+            this.getModel().setValue(PositionStructureConstant.NCKD_JOBSEQ, jobSeqId == 0 ? null : jobSeqId);
+            //职称名称
+            this.getModel().setValue(PositionStructureConstant.NCKD_RANKNAME, positionAppointMen.getString(String.join(".", FormConstant.HRPI_PERPROTITLE, FormConstant.PROFESSIONAL_KEY, FormConstant.NAME_KEY)));
+            //职称等级
+            long proLevelId = positionAppointMen.getLong(String.join(".", FormConstant.HRPI_PERPROTITLE, FormConstant.PROLEVEL_KEY, FormConstant.ID_KEY));
+            this.getModel().setValue(PositionStructureConstant.NCKD_PROTITLELEVEL, proLevelId == 0 ? null : proLevelId);
+            //技能名称
+            this.getModel().setValue(PositionStructureConstant.NCKD_JOBSTATUSNAME, positionAppointMen.getString(String.join(".", FormConstant.HRPI_PEROCPQUAL, FormConstant.QUALIFICATION_KEY, FormConstant.NAME_KEY)));
+            //技能等级
+            long quaLevelId = positionAppointMen.getLong(String.join(".", FormConstant.HRPI_PEROCPQUAL, FormConstant.QUALEVEL_KEY, FormConstant.ID_KEY));
+            this.getModel().setValue(PositionStructureConstant.NCKD_OCPQUALLEVEL, quaLevelId == 0 ? null : quaLevelId);
+            //组织分配
+            long assignmentId = positionAppointMen.getLong(String.join(".", FormConstant.ASSIGNMENT, FormConstant.ID_KEY));
+            this.getModel().setValue(PositionStructureConstant.NCKD_ASSIGNMENT, assignmentId == 0 ? null : assignmentId);
+            //任职信息
+            long empPosOrgRelId = positionAppointMen.getLong(FormConstant.ID_KEY);
+            this.getModel().setValue(PositionStructureConstant.NCKD_EMPPOSORGREL, assignmentId == 0 ? null : empPosOrgRelId);
+            //是否优秀生
+        // this.getModel().setValue(PositionStructureConstant.NCKD_EXCELLENT, );
+        }
+    }
+
     @Override
     public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
         String operateKey = afterDoOperationEventArgs.getOperateKey();
@@ -23,7 +112,9 @@ public class ServingInitialFormPlugin extends AbstractFormPlugin implements Plug
         if(success && PositionStructureConstant.OP_CONFIRMINITIAL.equalsIgnoreCase(operateKey)){
             Map<String, String> customData = afterDoOperationEventArgs.getOperationResult().getCustomData();
             String jobLeveStr = customData.get(PositionStructureConstant.NCKD_JOBLEVELHR);
+            this.getView().returnDataToParent("true");
             this.getView().showConfirm("提示","初定成功,职位档案已生成。",jobLeveStr, MessageBoxOptions.OK,null,null,null,null);
+
         }
     }
 }

+ 24 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/initial/UngradedPersonQueryListPlugin.java

@@ -2,9 +2,11 @@ package nckd.jxccl.hr.psms.plugin.form.initial;
 
 import kd.bos.common.enums.EnableEnum;
 import kd.bos.entity.datamodel.ListSelectedRowCollection;
+import kd.bos.form.CloseCallBack;
 import kd.bos.form.FormShowParameter;
 import kd.bos.form.ShowType;
 import kd.bos.form.events.BeforeDoOperationEventArgs;
+import kd.bos.form.events.ClosedCallBackEvent;
 import kd.bos.form.events.SetFilterEvent;
 import kd.bos.form.operate.FormOperate;
 import kd.bos.list.plugin.AbstractListPlugin;
@@ -14,7 +16,9 @@ import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
 import kd.sdk.plugin.Plugin;
 import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.hr.hstu.common.HonorStudentConstant;
 import nckd.jxccl.hr.psms.common.PositionStructureConstant;
+import org.apache.commons.lang3.StringUtils;
 
 /**
 * 职位体系-未定级人员列表
@@ -42,12 +46,19 @@ public class UngradedPersonQueryListPlugin extends AbstractListPlugin implements
         FormOperate formOperate = (FormOperate) args.getSource();
         String operateKey = formOperate.getOperateKey();
         ListSelectedRowCollection selectedRows = this.getSelectedRows();
+        if(selectedRows.size() > 1){
+            this.getView().showTipNotification("请选择一条数据,不支持多选!");
+            return;
+        }
         if(PositionStructureConstant.OP_SETTINGJOBGRADE.equals(operateKey)){
             //弹出在职人员初定窗口
             FormShowParameter showParameter = new FormShowParameter();
             showParameter.setFormId(PositionStructureConstant.SERVINGINITIAL_ENTITYID);
             showParameter.getOpenStyle().setShowType(ShowType.Modal);
             showParameter.setCaption("在职人员初定-定级信息确认");
+            showParameter.setSendToClient(true);
+            showParameter.setCustomParam("personId",selectedRows.get(0).getPrimaryKeyValue());
+            showParameter.setCloseCallBack(new CloseCallBack(this, PositionStructureConstant.SERVINGINITIAL_ENTITYID));
             this.getView().showForm(showParameter);
         }else if(PositionStructureConstant.OP_SETTINGJOBGRADENEW.equals(operateKey)){
             //弹出新入职人员初定窗口
@@ -55,7 +66,20 @@ public class UngradedPersonQueryListPlugin extends AbstractListPlugin implements
             showParameter.setFormId(PositionStructureConstant.NEWHIREINITIAL_ENTITYID);
             showParameter.getOpenStyle().setShowType(ShowType.Modal);
             showParameter.setCaption("新入职人员初定-定级信息确认");
+            showParameter.setCustomParam("personId",selectedRows.get(0).getPrimaryKeyValue());
+            showParameter.setCloseCallBack(new CloseCallBack(this, PositionStructureConstant.NEWHIREINITIAL_ENTITYID));
             this.getView().showForm(showParameter);
         }
     }
+    @Override
+    public void closedCallBack(ClosedCallBackEvent closedCallBackEvent) {
+        String actionId = closedCallBackEvent.getActionId();
+        if(StringUtils.equalsAny(actionId,PositionStructureConstant.SERVINGINITIAL_ENTITYID,PositionStructureConstant.NEWHIREINITIAL_ENTITYID)){
+            Object returnData = closedCallBackEvent.getReturnData();
+            if(returnData != null) {
+                //刷新列表
+                this.getView().invokeOperation(FormConstant.REFRESH_OP);
+            }
+        }
+    }
 }

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

@@ -59,7 +59,7 @@ public class NewDynamicAdjustmentOperationPlugIn extends AbstractOperationServic
                         return;
                     }
                     if (adjustDate.after(currentDate)) {
-                        addFatalErrorMessage(rowDataEntity,"初定时间不能晚于当前日期,请检查输入的日期是否正确");
+                        addFatalErrorMessage(rowDataEntity,"调整时间不能晚于当前日期,请检查输入的日期是否正确");
                         return;
                     }
                     DynamicObject person = data.getDynamicObject(FormConstant.NCKD_PERSON);

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

@@ -24,6 +24,7 @@ import java.time.LocalDateTime;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.StringJoiner;
 
 /**
  * 人员初定操作插件基类
@@ -185,15 +186,19 @@ public abstract class BaseInitialOperationPlugIn extends AbstractOperationServic
     protected ScoreData getScoreData(BaseInitialData data, String logPrefix) {
         ScoreData scoreData = new ScoreData();
 
+        StringJoiner selectFields = new StringJoiner(",").add(FormConstant.NAME_KEY)
+                .add(FormConstant.NUMBER_KEY)
+                .add(FormConstant.NCKD_SCORE);
+
         // 学历积分
         scoreData.educationScore = BigDecimal.ZERO;
         if (data.diploma != null) {
             DynamicObject education = QueryServiceHelper.queryOne(FormConstant.HBSS_DIPLOMA,
-                    "name,nckd_score",
+                    selectFields.toString(),
                     new QFilter[]{QFilterCommonHelper.getIdEqFilter(data.diploma.getLong(FormConstant.ID_KEY))});
             if (education != null) {
-                scoreData.educationScore = education.getBigDecimal("nckd_score");
-                logger.info("{}-学历【{}】-积分【{}】", logPrefix, education.getString("name"), scoreData.educationScore);
+                scoreData.educationScore = education.getBigDecimal(FormConstant.NCKD_SCORE);
+                logger.info("{}-学历【{}】-积分【{}】", logPrefix, education.getString(FormConstant.NAME_KEY), scoreData.educationScore);
             } else {
                 logger.warn("{}-未找到学历信息", logPrefix);
             }
@@ -208,21 +213,23 @@ public abstract class BaseInitialOperationPlugIn extends AbstractOperationServic
         scoreData.dbProTitleLevel = null;
         scoreData.dbOcpQualLevel = null;
 
+
+
         if (data.jobSeqEnum != JobSeqEnum.SKILL && data.proTitleLevel != null) {
             // 非技能序列获取职称积分
             scoreData.dbProTitleLevel = QueryServiceHelper.queryOne(FormConstant.HBSS_PROTITLELEVEL,
-                    "name,nckd_score",
+                    selectFields.toString(),
                     new QFilter[]{QFilterCommonHelper.getIdEqFilter(data.proTitleLevel.getLong(FormConstant.ID_KEY))});
             if (scoreData.dbProTitleLevel != null) {
-                scoreData.proTitleScore = scoreData.dbProTitleLevel.getBigDecimal("nckd_score");
+                scoreData.proTitleScore = scoreData.dbProTitleLevel.getBigDecimal(FormConstant.NCKD_SCORE);
             }
         } else if (data.jobSeqEnum == JobSeqEnum.SKILL && data.ocpQualLevel != null) {
             // 技能序列获取技能积分
             scoreData.dbOcpQualLevel = QueryServiceHelper.queryOne(FormConstant.HBSS_OCPQUALLEVEL,
-                    "name,nckd_score",
+                    selectFields.toString(),
                     new QFilter[]{QFilterCommonHelper.getIdEqFilter(data.ocpQualLevel.getLong(FormConstant.ID_KEY))});
             if (scoreData.dbOcpQualLevel != null) {
-                scoreData.perOcpQualScore = scoreData.dbOcpQualLevel.getBigDecimal("nckd_score");
+                scoreData.perOcpQualScore = scoreData.dbOcpQualLevel.getBigDecimal(FormConstant.NCKD_SCORE);
             }
         }
 
@@ -303,7 +310,7 @@ public abstract class BaseInitialOperationPlugIn extends AbstractOperationServic
     protected void setJobLevelResult(DynamicObject person, DynamicObject jobLeve) {
         String jobLeveStr = StrFormatter.format("{}:{}({}级)", 
                 person.getString(FormConstant.NAME_KEY),
-                jobLeve.getString(FormConstant.NAME_KEY), 
+                jobLeve.getString(FormConstant.NAME_KEY),
                 jobLeve.getString(FormConstant.JOBLEVELSEQ));
         
         Map<String, String> customData = this.getOperationResult().getCustomData();

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

@@ -10,6 +10,7 @@ import kd.bos.entity.validate.AbstractValidator;
 import nckd.jxccl.base.common.constant.FormConstant;
 import nckd.jxccl.base.common.utils.DateUtil;
 import nckd.jxccl.base.common.utils.StrFormatter;
+import nckd.jxccl.hr.psms.business.JobLevelCalculatorService;
 import nckd.jxccl.hr.psms.common.PositionStructureConstant;
 import nckd.jxccl.hr.psms.helper.PositionStructureHelper;
 
@@ -48,31 +49,35 @@ public class NewHireInitialOperationPlugIn extends BaseInitialOperationPlugIn {
                         return;
                     }
                     if(newHireInitialData.empPosOrgRel == null){
-                        addFatalErrorMessage(rowDataEntity,"人员无任职信息");
+                        addFatalErrorMessage(rowDataEntity,StrFormatter.format("人员【{}】无任职信息",person.getString(FormConstant.NAME_KEY)));
                         return;
                     }
                     if (beginDate == null) {
-                        addFatalErrorMessage(rowDataEntity,"初定时间不能为空");
+                        addFatalErrorMessage(rowDataEntity,StrFormatter.format("人员【{}】初定时间不能为空",person.getString(FormConstant.NAME_KEY)));
                         return;
                     }
                     DynamicObject positionHr = newHireInitialData.positionHr;
                     DynamicObject jobSeq = newHireInitialData.jobSeq;
                     if(positionHr == null){
-                        addFatalErrorMessage(rowDataEntity,"无岗位,请检查当前员工岗位信息");
+                        addFatalErrorMessage(rowDataEntity,StrFormatter.format("无岗位,请检查当前员工【{}】任职的岗位信息",person.getString(FormConstant.NAME_KEY)));
                         return;
                     }
                     if (jobSeq == null) {
-                        addFatalErrorMessage(rowDataEntity,StrFormatter.format("无职位序列,请检查当前员工岗位【{}】是否有职位序列",positionHr.getString(FormConstant.NAME_KEY)));
+                        addFatalErrorMessage(rowDataEntity,StrFormatter.format("无职位序列,请检查当前员工【{}】任职的岗位【{}】是否有职位序列",person.getString(FormConstant.NAME_KEY),positionHr.getString(FormConstant.NAME_KEY)));
                         return;
                     }
 
                     //------ 3、验证初定时间不能超过当前日期 ------
+                    if(newHireInitialData.joinComDate == null){
+                        addFatalErrorMessage(rowDataEntity,StrFormatter.format("无本次加入集团日期,请检查当前员工【{}】服务年限信息",person.getString(FormConstant.NAME_KEY)));
+                        return;
+                    }
                     if (newHireInitialData.joinComDate.after(beginDate)) {
-                        addFatalErrorMessage(rowDataEntity,"初定时间不能早于本次加入集团日期,本次加入集团时间:"+DateUtil.format(newHireInitialData.joinComDate, DateUtil.NORM_DATE_PATTERN));
+                        addFatalErrorMessage(rowDataEntity,StrFormatter.format("人员【{}】初定时间不能早于本次加入集团日期,本次加入集团时间:【{}】",person.getString(FormConstant.NAME_KEY),DateUtil.format(newHireInitialData.joinComDate, DateUtil.NORM_DATE_PATTERN)));
                         return;
                     }
                     if (beginDate.after(currentDate)) {
-                        addFatalErrorMessage(rowDataEntity,"初定时间不能晚于当前日期,请检查输入的日期是否正确");
+                        addFatalErrorMessage(rowDataEntity,StrFormatter.format("人员【{}】初定时间不能晚于当前日期,请检查输入的日期是否正确",person.getString(FormConstant.NAME_KEY)));
                         return;
                     }
                 }
@@ -132,12 +137,16 @@ public class NewHireInitialOperationPlugIn extends BaseInitialOperationPlugIn {
         BigDecimal sumScore = calculateSumScore(allSumScore, scoreData, logPrefix);
 
         // 计算职级
-        //【三期需求】-不满足三要素(聘任职称/技能、考核结果、积分)按"无职级"初定
         //当考核结果为无时,职级定为最低级
         boolean useMinLevel = data.lastYearAppraisalResultEnum == nckd.jxccl.base.common.enums.AppraisalResultEnum.NONE;
-        DynamicObject jobLeve = PositionStructureHelper.calculateLevel(
-                data.jobSeqEnum, sumScore, scoreData.dbProTitleLevel,
-                scoreData.dbOcpQualLevel,data.lastYearAppraisalResult,data.downgradeNum,useMinLevel,Boolean.TRUE);
+        //【三期需求】-不满足三要素(聘任职称/技能、考核结果、积分)按"无职级"初定
+        String perProTitleNumber = scoreData.dbProTitleLevel != null ? scoreData.dbProTitleLevel.getString(FormConstant.NUMBER_KEY) : null;
+        String quaLevelNumber = scoreData.dbOcpQualLevel != null ? scoreData.dbOcpQualLevel.getString(FormConstant.NUMBER_KEY) : null;
+        boolean threeElementMeet = JobLevelCalculatorService.checkThreeElementsRequirement(data.jobSeq, allSumScore, scoreData.dbProTitleLevel,
+                scoreData.dbOcpQualLevel, data.lastYearAppraisalResultEnum);
+        DynamicObject jobLeve = JobLevelCalculatorService.getJobLevel(
+                data.jobSeq, sumScore, perProTitleNumber,
+                quaLevelNumber,data.downgradeNum,useMinLevel,!threeElementMeet);
         if(jobLeve != null) {
             // 构建职位档案并存入数据库
             createAndSavePersonPosFile(data, scoreData, allSumScore, sumScore, jobLeve, logPrefix, "1");

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

@@ -11,6 +11,7 @@ import nckd.jxccl.base.common.constant.FormConstant;
 import nckd.jxccl.base.common.utils.DateUtil;
 import nckd.jxccl.base.common.utils.StrFormatter;
 import nckd.jxccl.base.pm.helper.PerformanceManagerHelper;
+import nckd.jxccl.hr.psms.business.JobLevelCalculatorService;
 import nckd.jxccl.hr.psms.common.PositionStructureConstant;
 import nckd.jxccl.hr.psms.helper.PositionStructureHelper;
 
@@ -49,26 +50,26 @@ public class ServingInitialOperationPlugIn extends BaseInitialOperationPlugIn {
                         return;
                     }
                     if(servingInitialData.empPosOrgRel == null){
-                        addFatalErrorMessage(rowDataEntity,"人员无任职信息");
+                        addFatalErrorMessage(rowDataEntity,StrFormatter.format("人员【{}】无任职信息",person.getString(FormConstant.NAME_KEY)));
                         return;
                     }
                     if (beginDate == null) {
-                        addFatalErrorMessage(rowDataEntity,"初定时间不能为空");
+                        addFatalErrorMessage(rowDataEntity,StrFormatter.format("人员【{}】初定时间不能为空",person.getString(FormConstant.NAME_KEY)));
                         return;
                     }
                     BigDecimal allSumScore = servingInitialData.allSumScore;
                     if(allSumScore == null || allSumScore.compareTo(BigDecimal.ZERO) == 0){
-                        addFatalErrorMessage(rowDataEntity,"请填写总积分");
+                        addFatalErrorMessage(rowDataEntity,StrFormatter.format("人员【{}】请填写总积分",person.getString(FormConstant.NAME_KEY)));
                         return;
                     }
                     DynamicObject positionHr = servingInitialData.positionHr;
                     DynamicObject jobSeq = servingInitialData.jobSeq;
                     if(positionHr == null){
-                        addFatalErrorMessage(rowDataEntity,"无岗位,请检查当前员工岗位信息");
+                        addFatalErrorMessage(rowDataEntity,StrFormatter.format("无岗位,请检查当前员工【{}】任职的岗位信息",person.getString(FormConstant.NAME_KEY)));
                         return;
                     }
                     if (jobSeq == null) {
-                        addFatalErrorMessage(rowDataEntity,StrFormatter.format("无职位序列,请检查当前员工岗位【{}】是否有职位序列",positionHr.getString(FormConstant.NAME_KEY)));
+                        addFatalErrorMessage(rowDataEntity,StrFormatter.format("无职位序列,请检查当前员工【{}】任职的岗位【{}】是否有职位序列",person.getString(FormConstant.NAME_KEY),positionHr.getString(FormConstant.NAME_KEY)));
                         return;
                     }
 
@@ -80,7 +81,7 @@ public class ServingInitialOperationPlugIn extends BaseInitialOperationPlugIn {
                     }
                     //------ 3、验证初定时间不能超过当前日期 ------
                     if (beginDate.after(currentDate)) {
-                        addFatalErrorMessage(rowDataEntity,"初定时间不能晚于当前日期,请检查输入的日期是否正确");
+                        addFatalErrorMessage(rowDataEntity,StrFormatter.format("员工【{}】初定时间不能晚于当前日期,请检查输入的日期是否正确",person.getString(FormConstant.NAME_KEY)));
                         return;
                     }
 
@@ -142,12 +143,13 @@ public class ServingInitialOperationPlugIn extends BaseInitialOperationPlugIn {
         BigDecimal sumScore = calculateSumScore(data.allSumScore, scoreData, logPrefix);
 
         // 计算职级
-        //【三期需求】-不满足三要素(聘任职称/技能、考核结果、积分)按"无职级"初定
         //当考核结果为无时,职级定为最低级
         boolean useMinLevel = data.lastYearAppraisalResultEnum == nckd.jxccl.base.common.enums.AppraisalResultEnum.NONE;
-        DynamicObject jobLeve = PositionStructureHelper.calculateLevel(
-                data.jobSeqEnum, sumScore, scoreData.dbProTitleLevel,
-                scoreData.dbOcpQualLevel, data.lastYearAppraisalResult, data.downgradeNum,useMinLevel,Boolean.TRUE);
+        String perProTitleNumber = scoreData.dbProTitleLevel != null ? scoreData.dbProTitleLevel.getString(FormConstant.NUMBER_KEY) : null;
+        String quaLevelNumber = scoreData.dbOcpQualLevel != null ? scoreData.dbOcpQualLevel.getString(FormConstant.NUMBER_KEY) : null;
+        DynamicObject jobLeve = JobLevelCalculatorService.getJobLevel(
+                data.jobSeq, sumScore, perProTitleNumber,
+                quaLevelNumber,  data.downgradeNum,useMinLevel,Boolean.FALSE);
 
         if(jobLeve != null) {
             // 构建职位档案并存入数据库

+ 15 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/report/adjust/UnAdjustedReportFormPlugin.java

@@ -1,14 +1,17 @@
 package nckd.jxccl.hr.psms.plugin.report.adjust;
 
 import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.form.CloseCallBack;
 import kd.bos.form.FormShowParameter;
 import kd.bos.form.ShowType;
 import kd.bos.form.control.events.ItemClickEvent;
 import kd.bos.form.control.events.ItemClickListener;
+import kd.bos.form.events.ClosedCallBackEvent;
 import kd.bos.report.ReportList;
 import kd.bos.report.plugin.AbstractReportFormPlugin;
 import nckd.jxccl.base.common.constant.FormConstant;
 import nckd.jxccl.hr.psms.common.PositionStructureConstant;
+import org.apache.commons.lang3.StringUtils;
 
 import java.util.EventObject;
 
@@ -49,6 +52,7 @@ public class UnAdjustedReportFormPlugin extends AbstractReportFormPlugin impleme
                 showParameter.getOpenStyle().setShowType(ShowType.Modal);
                 showParameter.setCaption("新建调整");
                 showParameter.setCustomParam(FormConstant.NCKD_PERSON,rowData.getDynamicObject(FormConstant.NCKD_PERSON).getLong(FormConstant.ID_KEY));
+                showParameter.setCloseCallBack(new CloseCallBack(this, PositionStructureConstant.NEWDYNAMICADJUDIALOG_ENTITYID));
                 this.getView().showForm(showParameter);
             }else if(selectedRowIndexes.length > 1){
                 //多人调整
@@ -61,7 +65,18 @@ public class UnAdjustedReportFormPlugin extends AbstractReportFormPlugin impleme
                 this.getView().showErrorNotification("请选择要调整的员工");
                 return;
             }
+        }
+    }
 
+    @Override
+    public void closedCallBack(ClosedCallBackEvent closedCallBackEvent) {
+        String actionId = closedCallBackEvent.getActionId();
+        if(StringUtils.equalsAny(actionId,PositionStructureConstant.NEWDYNAMICADJUDIALOG_ENTITYID)){
+            Object returnData = closedCallBackEvent.getReturnData();
+            if(returnData != null) {
+                //刷新列表
+                this.getView().invokeOperation(FormConstant.REFRESH_OP);
+            }
         }
     }
 }