Ver código fonte

feat(hr): 新增积分项目名次维度支持及有效期过滤

- 在QFilterCommonHelper中新增getValidDateFilter方法,用于获取有效时间范围内的过滤条件
- 修改ContributionHelper中的分数配置逻辑,增加对积分项目名次的支持
- 更新ScoreItemValidScore类结构,添加scoreItemRankId字段及相关构造方法和getter/setter- 调整calculateAvailableScore与determineSumScore方法,实现三级限制(名次>子项>大类)的优先级处理- 扩展getScoreConf方法以支持按不同维度生成配置键值
- 在多个插件类中补充scoreItemRank相关字段的操作逻辑
- 新增ScoreItemConfValidate校验类,防止重复配置相同维度的积分规则- 优化报表插件默认选中全部数据的功能
wyc 1 mês atrás
pai
commit
08e32b0d6c

+ 20 - 0
code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/orm/helper/QFilterCommonHelper.java

@@ -11,6 +11,7 @@ import nckd.jxccl.base.common.constant.FormConstant;
 import nckd.jxccl.base.common.utils.ConvertUtil;
 
 import java.util.Collection;
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -144,4 +145,23 @@ public final class QFilterCommonHelper {
     public static QFilter getIdInFilter(Collection<Long> idList) {
         return new QFilter(FormConstant.ID_KEY, QCP.in, idList);
     }
+
+    /**
+     * 获取有效时间范围内的QFilter实例
+     * 如果结束时间为空,则表示持续有效
+     * @param beginDateProperty 开始时间字段名
+     * @param endDateProperty 结束时间字段名
+     * @return: kd.bos.orm.query.QFilter
+     * @author W.Y.C
+     * @date: 2025/07/07
+     */
+    public static QFilter getValidDateFilter(String beginDateProperty, String endDateProperty) {
+        // 创建组合条件 (beginTime <= currentTime AND (endTime >= currentTime OR endTime IS NULL))
+        Date currentDate = new Date();
+        QFilter beginFilter = new QFilter(beginDateProperty, QCP.less_equals, currentDate);
+        QFilter endFilter = new QFilter(endDateProperty, QCP.large_equals, currentDate);
+        QFilter nullEndFilter = new QFilter(endDateProperty, QCP.is_null, null);
+
+        return beginFilter.and(endFilter.or(nullEndFilter));
+    }
 }

+ 182 - 62
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/helper/ContributionHelper.java

@@ -49,7 +49,7 @@ public class ContributionHelper {
         }
 
         //获取积分项目分数配置
-        Map<Long, BigDecimal> scoreConfMap = getScoreConf();
+        Map<String, BigDecimal> scoreConfMap = getScoreConf();
         //统计人员各项目已累计积分
         Long[] personIdArray = scoreItemValidScoreList.stream()
                 .map(ScoreItemValidScore::getPersonId)
@@ -71,6 +71,7 @@ public class ContributionHelper {
             Long personId = scoreItemValidScore.getPersonId();
             Long scoreItemId = scoreItemValidScore.getScoreItemId();
             Long scoreItemSubId = scoreItemValidScore.getScoreItemSubId();
+            Long scoreItemRankId = scoreItemValidScore.getScoreItemRankId();
 
             //获取该人员的累计积分数据
             List<ScoreItemValidScore> personAccumulateScores = personAccumulateScoreMap.getOrDefault(personId, new ArrayList<>());
@@ -78,23 +79,30 @@ public class ContributionHelper {
             //计算积分项目和具体项目累计分数
             BigDecimal scoreItemSumScore = BigDecimal.ZERO;
             BigDecimal scoreItemSubSumScore = BigDecimal.ZERO;
+            BigDecimal scoreItemRankSumScore = BigDecimal.ZERO;
 
             for (ScoreItemValidScore accumulateScore : personAccumulateScores) {
                 Long tempScoreItemId = accumulateScore.getScoreItemId();
                 Long tempScoreItemSubId = accumulateScore.getScoreItemSubId();
+                Long tempScoreItemRankId = accumulateScore.getScoreItemRankId();
 
                 if (Objects.equals(tempScoreItemId, scoreItemId)) {
                     scoreItemSumScore = scoreItemSumScore.add(accumulateScore.getSumScore());
                     if (Objects.equals(tempScoreItemSubId, scoreItemSubId)) {
-                        scoreItemSubSumScore = accumulateScore.getSumScore();
+                        scoreItemSubSumScore = scoreItemSubSumScore.add(accumulateScore.getSumScore());
+                    }
+                    // 添加名次维度判断
+                    if (Objects.equals(tempScoreItemRankId, scoreItemRankId)) {
+                        scoreItemRankSumScore = scoreItemRankSumScore.add(accumulateScore.getSumScore());
                     }
                 }
             }
 
             //根据配置决定使用哪种累计分数
-            BigDecimal sumScore = determineSumScore(scoreConfMap, scoreItemId, scoreItemSumScore, scoreItemSubSumScore);
+            BigDecimal sumScore = determineSumScore(scoreConfMap, scoreItemId, scoreItemSubId, scoreItemRankId,
+                    scoreItemSumScore, scoreItemSubSumScore, scoreItemRankSumScore);
 
-            BigDecimal validScore = calculateAvailableScore(scoreConfMap, scoreItemId, scoreItemSubId, sumScore);
+            BigDecimal validScore = calculateAvailableScore(scoreConfMap, scoreItemId, scoreItemSubId, scoreItemRankId, sumScore);
             scoreItemValidScore.setValidScore(validScore);
             scoreItemValidScore.setSumScore(sumScore);
         }
@@ -143,6 +151,7 @@ public class ContributionHelper {
                 .add(ContributionConstant.NCKD_YEAR)
                 .addIdNumberName(ContributionConstant.NCKD_SCOREITEM)
                 .addIdNumberName(ContributionConstant.NCKD_SCOREITEMSUB)
+                .addIdNumberName(ContributionConstant.NCKD_SCOREITEMRANK) // 添加积分项目名次字段
                 .addGroup(new String[]{FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_PERSON},FormConstant.ID_KEY)
                 .addGroup(new String[]{FormConstant.NCKD_ENTRYENTITY}, ContributionConstant.NCKD_SCORE, ContributionConstant.NCKD_ORISCORE);
 
@@ -172,11 +181,12 @@ public class ContributionHelper {
                     new QFilter[]{filter}, null, 5000);
 
             DataSet sumDateSet = dateSet.copy()
-                    // 按人员、积分项目、积分项目子项进行分组
+                    // 按人员、积分项目、积分项目子项、积分项目名次进行分组
                     .groupBy(new String[]{String.join(".", ContributionConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_PERSON, FormConstant.ID_KEY),
                             String.join(".", ContributionConstant.NCKD_SCOREITEM, FormConstant.ID_KEY),
                             String.join(".", ContributionConstant.NCKD_SCOREITEM, FormConstant.NUMBER_KEY),
-                            String.join(".", ContributionConstant.NCKD_SCOREITEMSUB, FormConstant.ID_KEY)})
+                            String.join(".", ContributionConstant.NCKD_SCOREITEMSUB, FormConstant.ID_KEY),
+                            String.join(".", ContributionConstant.NCKD_SCOREITEMRANK, FormConstant.ID_KEY)}) // 添加名次分组
                     .sum(String.join(".", ContributionConstant.NCKD_ENTRYENTITY, FormConstant.NCKD_SCORE),"sumScore").finish();
 
             while (sumDateSet.hasNext()) {
@@ -185,9 +195,10 @@ public class ContributionHelper {
                 Long scoreItemId = row.getLong(String.join(".", ContributionConstant.NCKD_SCOREITEM, FormConstant.ID_KEY));
                 String scoreItemNumber = row.getString(String.join(".", ContributionConstant.NCKD_SCOREITEM, FormConstant.NUMBER_KEY));
                 Long scoreItemSubId = row.getLong(String.join(".", ContributionConstant.NCKD_SCOREITEMSUB, FormConstant.ID_KEY));
+                Long scoreItemRankId = row.getLong(String.join(".", ContributionConstant.NCKD_SCOREITEMRANK, FormConstant.ID_KEY)); // 获取名次ID
                 //已获得的累计积分
                 BigDecimal sumScore = row.getBigDecimal("sumScore");
-                ScoreItemValidScore scoreItemValidScore = new ScoreItemValidScore(personId, scoreItemId,scoreItemNumber, scoreItemSubId, sumScore);
+                ScoreItemValidScore scoreItemValidScore = new ScoreItemValidScore(personId, scoreItemId,scoreItemNumber, scoreItemSubId, scoreItemRankId, sumScore);
                 scoreItemValidScoreList.add(scoreItemValidScore);
             }
         }
@@ -227,6 +238,7 @@ public class ContributionHelper {
      * @param scoreConfMap 分数配置映射表,key为配置ID,value为限分数值
      * @param scoreItemId 积分项目ID
      * @param scoreItemSubId 具体积分项目ID
+     * @param scoreItemRankId 积分项目名次ID
      * @param accumulatedScore 已累计总分
      * @return 可获得的有效分数
      *         如果没有任何限制返回null
@@ -235,14 +247,25 @@ public class ContributionHelper {
      * @author W.Y.C
      * @date: 2025/10/26 16:53
      */
-    private static BigDecimal calculateAvailableScore(Map<Long, BigDecimal> scoreConfMap, Long scoreItemId, Long scoreItemSubId, BigDecimal accumulatedScore) {
+    private static BigDecimal calculateAvailableScore(Map<String, BigDecimal> scoreConfMap, Long scoreItemId, Long scoreItemSubId, Long scoreItemRankId, BigDecimal accumulatedScore) {
         // 积分项目限分 - 如果没有找到则不限分
-        BigDecimal scoreItemMaxScore = scoreConfMap.get(scoreItemId);
+        String scoreItemKey = scoreItemId + "";
+        BigDecimal scoreItemMaxScore = scoreConfMap.get(scoreItemKey);
 
         // 具体积分项目限分 - 如果没有找到则不限分
+        String scoreItemSubKey = null;
         BigDecimal scoreItemSubMaxScore = null;
         if (scoreItemSubId != null && scoreItemSubId > 0) {
-            scoreItemSubMaxScore = scoreConfMap.get(scoreItemSubId);
+            scoreItemSubKey = scoreItemId + "-" + scoreItemSubId;
+            scoreItemSubMaxScore = scoreConfMap.get(scoreItemSubKey);
+        }
+
+        // 积分项目名次限分 - 如果没有找到则不限分
+        String scoreItemRankKey = null;
+        BigDecimal scoreItemRankMaxScore = null;
+        if (scoreItemRankId != null && scoreItemRankId > 0) {
+            scoreItemRankKey = scoreItemId + "-" + scoreItemSubId + "-" + scoreItemRankId;
+            scoreItemRankMaxScore = scoreConfMap.get(scoreItemRankKey);
         }
 
         // 处理累计分数的空值
@@ -251,9 +274,19 @@ public class ContributionHelper {
         // 计算实际的最大限制
         BigDecimal actualMaxScore = null;
 
+        // 检查积分项目名次限分是否存在且大于0(最高优先级)
+        if (scoreItemRankMaxScore != null && scoreItemRankMaxScore.compareTo(BigDecimal.ZERO) > 0) {
+            actualMaxScore = scoreItemRankMaxScore;
+        }
+
         // 检查具体积分项目限分是否存在且大于0
         if (scoreItemSubMaxScore != null && scoreItemSubMaxScore.compareTo(BigDecimal.ZERO) > 0) {
-            actualMaxScore = scoreItemSubMaxScore;
+            if (actualMaxScore == null) {
+                actualMaxScore = scoreItemSubMaxScore;
+            } else {
+                // 多重限制,取较小值
+                actualMaxScore = actualMaxScore.min(scoreItemSubMaxScore);
+            }
         }
 
         // 检查积分项目限分是否存在且大于0
@@ -261,7 +294,7 @@ public class ContributionHelper {
             if (actualMaxScore == null) {
                 actualMaxScore = scoreItemMaxScore;
             } else {
-                // 重限制,取较小值
+                // 重限制,取较小值
                 actualMaxScore = actualMaxScore.min(scoreItemMaxScore);
             }
         }
@@ -284,14 +317,25 @@ public class ContributionHelper {
         return availableScore;
     }
 
+    public static void main(String[] args) {
+        List<ScoreItemValidScore> list = new ArrayList<>();
+        list.add(new ScoreItemValidScore(1L, 11L, "1", 111L, 1111L, BigDecimal.valueOf(6)));
+        list.add(new ScoreItemValidScore(1L, 11L, "1", 121L, null, BigDecimal.valueOf(10)));
+        list.add(new ScoreItemValidScore(1L, 11L, "1", 131L, null, BigDecimal.valueOf(10)));
+        list.add(new ScoreItemValidScore(1L, 11L, "1", 141L, null, BigDecimal.valueOf(20)));
+        List<ScoreItemValidScore> scoreItemValidScores = calculateMaxAllowedScore(list);
+        System.out.println();
+    }
+
     /**
      * 计算最多可得的分数
      * 根据累计积分和分数配置映射表,如果超过配置的限制分数则返回限制分最大分数,
-     * 计算每个积分大项在考虑双重限制条件下的最大可获得分数:
-     * 1. 子项限制:每个具体积分项目子项可能有分数上限
-     * 2. 大项限制:整个积分大项可能有总分上限
+     * 计算每个积分大项在考虑三重限制条件下的最大可获得分数:
+     * 1. 名次限制:每个积分项目名次可能有分数上限(最高优先级)
+     * 2. 子项限制:每个具体积分项目子项可能有分数上限
+     * 3. 大项限制:整个积分大项可能有总分上限
      *
-     * @param scoreItemValidScoreList 某个人员所有积分项目的累计积分(personId、scoreItemId、scoreItemSubId、sumScore有值)
+     * @param scoreItemValidScoreList 某个人员所有积分项目的累计积分(personId、scoreItemId、scoreItemSubId、scoreItemRankId、sumScore有值)
      * @return 最多可得的分数列表(按大项维度聚合)
      * @author W.Y.C
      * @date: 2025/10/27
@@ -299,7 +343,11 @@ public class ContributionHelper {
     public static List<ScoreItemValidScore> calculateMaxAllowedScore(List<ScoreItemValidScore> scoreItemValidScoreList) {
 
         //获取积分限分配置
-        Map<Long, BigDecimal> scoreConfMap = ContributionHelper.getScoreConf();
+        Map<String, BigDecimal> scoreConfMap = ContributionHelper.getScoreConf();
+        /*Map<String, BigDecimal> scoreConfMap = Maps.newConcurrentMap();
+         scoreConfMap.put("11-111-1111",new BigDecimal(2));
+         scoreConfMap.put("11-121",new BigDecimal(5));
+         scoreConfMap.put("11",new BigDecimal(20));*/
 
         List<ScoreItemValidScore> result = new ArrayList<>();
 
@@ -312,51 +360,72 @@ public class ContributionHelper {
             List<ScoreItemValidScore> valueList = entry.getValue();
 
             // 获取大项限制分数
-            BigDecimal scoreItemMaxScore = scoreConfMap.get(scoreItemId);
-
-            // 计算大项总分(按子项分组后求和)
-            Map<Long, BigDecimal> subItemSumMap = new HashMap<>();
-            for (ScoreItemValidScore item : valueList) {
-                Long subItemId = item.getScoreItemSubId();
-                BigDecimal score = item.getSumScore() == null ? BigDecimal.ZERO : item.getSumScore();
-                subItemSumMap.merge(subItemId, score, BigDecimal::add);
-            }
+            BigDecimal scoreItemMaxScore = scoreConfMap.get(scoreItemId + "");
 
-            // 计算未受限制的实际总分
-            BigDecimal actualTotalScore = BigDecimal.ZERO;
-            for (BigDecimal subItemScore : subItemSumMap.values()) {
-                actualTotalScore = actualTotalScore.add(subItemScore);
-            }
+            // 按具体项目分组
+            Map<Long, List<ScoreItemValidScore>> groupedBySubItemId = valueList.stream()
+                    .collect(Collectors.groupingBy(ScoreItemValidScore::getScoreItemSubId));
 
-
-            // 计算每个子项的有效分数并求和
             BigDecimal totalAllowedScore = BigDecimal.ZERO;
-            for (Map.Entry<Long, BigDecimal> subEntry : subItemSumMap.entrySet()) {
+            BigDecimal actualTotalScore = BigDecimal.ZERO;
+
+            // 遍历每个具体项目
+            for (Map.Entry<Long, List<ScoreItemValidScore>> subEntry : groupedBySubItemId.entrySet()) {
                 Long subItemId = subEntry.getKey();
-                BigDecimal subItemSumScore = subEntry.getValue();
+                List<ScoreItemValidScore> subItemList = subEntry.getValue();
 
                 // 获取子项限制分数
                 BigDecimal scoreItemSubMaxScore = null;
                 if (subItemId != null && subItemId > 0) {
-                    scoreItemSubMaxScore = scoreConfMap.get(subItemId);
+                    scoreItemSubMaxScore = scoreConfMap.get(scoreItemId + "-" + subItemId);
+                }
+
+                // 按名次分组
+                Map<Long, BigDecimal> rankSumMap = new HashMap<>();
+                for (ScoreItemValidScore item : subItemList) {
+                    Long rankItemId = item.getScoreItemRankId();
+                    BigDecimal score = item.getSumScore() == null ? BigDecimal.ZERO : item.getSumScore();
+                    rankSumMap.merge(rankItemId, score, BigDecimal::add);
+                    actualTotalScore = actualTotalScore.add(score);
                 }
 
-                // 子项限制后的分数(优先考虑子项限制)
-                BigDecimal allowedSubScore = subItemSumScore;
+                BigDecimal subItemAllowedScore = BigDecimal.ZERO;
+
+                // 处理每个名次的分数限制
+                for (Map.Entry<Long, BigDecimal> rankEntry : rankSumMap.entrySet()) {
+                    Long rankItemId = rankEntry.getKey();
+                    BigDecimal rankSumScore = rankEntry.getValue();
+
+                    // 获取名次限制分数
+                    BigDecimal scoreItemRankMaxScore = null;
+                    if (rankItemId != null && rankItemId > 0) {
+                        scoreItemRankMaxScore = scoreConfMap.get(scoreItemId + "-" + subItemId + "-" + rankItemId);
+                    }
+
+                    // 名次限制后的分数
+                    BigDecimal allowedRankScore = rankSumScore;
+                    if (scoreItemRankMaxScore != null && scoreItemRankMaxScore.compareTo(BigDecimal.ZERO) > 0) {
+                        allowedRankScore = rankSumScore.min(scoreItemRankMaxScore);
+                    }
+
+                    subItemAllowedScore = subItemAllowedScore.add(allowedRankScore);
+                }
+
+                // 应用子项限制(如果设置了子项限制)
                 if (scoreItemSubMaxScore != null && scoreItemSubMaxScore.compareTo(BigDecimal.ZERO) > 0) {
-                    allowedSubScore = subItemSumScore.min(scoreItemSubMaxScore);
+                    subItemAllowedScore = subItemAllowedScore.min(scoreItemSubMaxScore);
                 }
 
-                totalAllowedScore = totalAllowedScore.add(allowedSubScore);
+                totalAllowedScore = totalAllowedScore.add(subItemAllowedScore);
             }
 
-            // 如果大项有限制,需要检查是否超过大项限制
+            // 应用大项限制(如果设置了大项限制)
             if (scoreItemMaxScore != null && scoreItemMaxScore.compareTo(BigDecimal.ZERO) > 0) {
                 totalAllowedScore = totalAllowedScore.min(scoreItemMaxScore);
             }
 
             // 创建结果对象,只包含scoreItemId和validScore
-            ScoreItemValidScore resultItem = new ScoreItemValidScore(null, scoreItemId, null);
+            ScoreItemValidScore resultItem = new ScoreItemValidScore(null, scoreItemId, null, null);
             String scoreItemNumber = null;
             if (!valueList.isEmpty() && valueList.get(0) != null) {
                 scoreItemNumber = valueList.get(0).getScoreItemNumber();
@@ -376,45 +445,84 @@ public class ContributionHelper {
      * @param scoreItemId 积分项目ID
      * @param scoreItemSumScore 积分项目累计分数
      * @param scoreItemSubSumScore 积分项目具体项目累计分数
+     * @param scoreItemRankSumScore 积分项目名次累计分数
      * @return 应该使用的累计分数
      */
-    private static BigDecimal determineSumScore(Map<Long, BigDecimal> scoreConfMap, Long scoreItemId,
-                                                BigDecimal scoreItemSumScore, BigDecimal scoreItemSubSumScore) {
-        BigDecimal scoreItemMaxScore = scoreConfMap.get(scoreItemId);
-        if (scoreItemMaxScore != null) {
-            //如果设置积分项目大类分数限制,则取大类的累计积分
-            return scoreItemSumScore;
-        } else {
-            //如果没有设置积分项目大类分数限制,则取小类的累计积分
-            return scoreItemSubSumScore;
+    private static BigDecimal determineSumScore(Map<String, BigDecimal> scoreConfMap, Long scoreItemId, Long scoreItemSubId, Long scoreItemRankId,
+                                                BigDecimal scoreItemSumScore, BigDecimal scoreItemSubSumScore,
+                                                BigDecimal scoreItemRankSumScore) {
+        // 按照优先级判断使用哪个维度的累计分数
+        // 优先级:名次 > 子项 > 大类
+
+        // 如果设置了积分项目名次限制,使用名次的累计积分
+        if (scoreItemRankSumScore != null && scoreItemRankSumScore.compareTo(BigDecimal.ZERO) > 0) {
+            String key = scoreItemId + "-" + scoreItemSubId + "-" + scoreItemRankId;
+            if (scoreConfMap.containsKey(key)) {
+                return scoreItemRankSumScore;
+            }
         }
+
+        // 如果设置了积分项目子项限制,使用子项的累计积分
+        if (scoreItemSubSumScore != null && scoreItemSubSumScore.compareTo(BigDecimal.ZERO) > 0) {
+            String key = scoreItemId + "-" + scoreItemSubId;
+            if (scoreConfMap.containsKey(key)) {
+                return scoreItemSubSumScore;
+            }
+        }
+
+        // 默认使用大类的累计积分
+        return scoreItemSumScore;
+    }
+
+    public static Map<String, BigDecimal> getScoreConf() {
+        return getScoreConf(null);
     }
 
     /**
      * 获取积分配置
-     * @return: java.util.Map<java.lang.Long, java.math.BigDecimal>;key为积分项目子项ID(项目子项为空时key为项目大项),value为积分项目对应的最大分数
+     * @return: java.util.Map<java.lang.String, java.math.BigDecimal>;key:根据配置的完整程度生成不同格式的字符串,
+     *          仅配置积分项目时为"scoreItemId",
+     *          配置积分项目和具体积分项目时为"scoreItemId-scoreItemSubId",
+     *          配置积分项目、具体积分项目和积分项目名次时为"scoreItemId-scoreItemSubId-scoreItemRankId",
+     *          value为积分项目对应的最大分数
      * @author W.Y.C
      * @date: 2025/10/26 13:38
      */
-    public static Map<Long, BigDecimal> getScoreConf() {
+    public static Map<String, BigDecimal> getScoreConf(QFilter otherFilter) {
         //查询积分项目分数配置
         QueryFieldBuilder scoreItemConfFieldBuilder = QueryFieldBuilder.create()
                 .addIdNumberName(FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_SCOREITEM)
                 .addIdNumberName(FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_SCOREITEMSUB)
+                .addIdNumberName(FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_SCOREITEMRANK)
                 .addGroup(new String[]{FormConstant.NCKD_ENTRYENTITY}, ContributionConstant.NCKD_MAXSCORE);
+        QFilter filter = QFilterCommonHelper.getEnableFilter()
+                .and(QFilterCommonHelper.getValidDateFilter(FormConstant.NCKD_STARTDATE,FormConstant.NCKD_ENDDATE));
+        if(otherFilter != null){
+            filter = filter.and(otherFilter);
+        }
 
         DynamicObjectCollection scoreItemConfQuery = QueryServiceHelper.query(ContributionConstant.SCOREITEMCONF_ENTITYID,
                 scoreItemConfFieldBuilder.buildSelect(),
-                new QFilter[]{QFilterCommonHelper.getEnableFilter()});
+                new QFilter[]{filter});
 
-        //scoreMap:key为积分项目子项ID(项目子项为空时key为项目大项),value为积分项目对应的最大分数
-        Map<Long, BigDecimal> scoreMap = scoreItemConfQuery.stream().collect(Collectors.toMap(
+        //scoreMap:key为积分配置维度ID,value为积分项目对应的最大分数
+        //优先级顺序:NCKD_SCOREITEMRANK > NCKD_SCOREITEMSUB > NCKD_SCOREITEM
+        Map<String, BigDecimal> scoreMap = scoreItemConfQuery.stream().collect(Collectors.toMap(
                 item -> {
+                    long scoreItemRankId = item.getLong(String.join(".", FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_SCOREITEMRANK, FormConstant.ID_KEY));
                     long scoreItemSubId = item.getLong(String.join(".", FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_SCOREITEMSUB, FormConstant.ID_KEY));
-                    if (scoreItemSubId <= 0) {
-                        return item.getLong(String.join(".", FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_SCOREITEM, FormConstant.ID_KEY));
+                    long scoreItemId = item.getLong(String.join(".", FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_SCOREITEM, FormConstant.ID_KEY));
+
+                    // 按优先级顺序确定key值
+                    if (scoreItemRankId > 0) {
+                        // 优先使用NCKD_SCOREITEMRANK作为key
+                        return scoreItemId+"-"+scoreItemSubId+"-"+scoreItemRankId;
+                    } else if (scoreItemSubId > 0) {
+                        // 当NCKD_SCOREITEMRANK为空时,使用NCKD_SCOREITEMSUB作为key
+                        return scoreItemId+"-"+scoreItemSubId;
                     } else {
-                        return scoreItemSubId;
+                        // 当NCKD_SCOREITEMRANK和NCKD_SCOREITEMSUB都为空时,使用NCKD_SCOREITEM作为key
+                        return scoreItemId+"";
                     }
                 },
                 item -> item.getBigDecimal(String.join(".", FormConstant.NCKD_ENTRYENTITY, ContributionConstant.NCKD_MAXSCORE)),
@@ -429,6 +537,7 @@ public class ContributionHelper {
         private Long scoreItemId;
         private String scoreItemNumber;
         private Long scoreItemSubId;
+        private Long scoreItemRankId;
         /**本次积分*/
         private BigDecimal currentScore;
         private BigDecimal sumScore;
@@ -437,24 +546,27 @@ public class ContributionHelper {
         //没有业务含义,只用来记录分录索引号;
         private int rowIndex;
 
-        public ScoreItemValidScore(Long personId, Long scoreItemId, Long scoreItemSubId) {
+        public ScoreItemValidScore(Long personId, Long scoreItemId, Long scoreItemSubId, Long scoreItemRankId) {
             this.personId = personId;
             this.scoreItemId = scoreItemId;
             this.scoreItemSubId = scoreItemSubId;
+            this.scoreItemRankId = scoreItemRankId;
         }
 
-        public ScoreItemValidScore(Long personId, Long scoreItemId,String scoreItemNumber, Long scoreItemSubId, BigDecimal sumScore) {
+        public ScoreItemValidScore(Long personId, Long scoreItemId,String scoreItemNumber, Long scoreItemSubId, Long scoreItemRankId, BigDecimal sumScore) {
             this.personId = personId;
             this.scoreItemId = scoreItemId;
             this.scoreItemNumber = scoreItemNumber;
             this.scoreItemSubId = scoreItemSubId;
+            this.scoreItemRankId = scoreItemRankId;
             this.sumScore = sumScore;
         }
 
-        public ScoreItemValidScore(Long personId, Long scoreItemId, Long scoreItemSubId, BigDecimal sumScore, BigDecimal validScore) {
+        public ScoreItemValidScore(Long personId, Long scoreItemId, Long scoreItemSubId, Long scoreItemRankId, BigDecimal sumScore, BigDecimal validScore) {
             this.personId = personId;
             this.scoreItemId = scoreItemId;
             this.scoreItemSubId = scoreItemSubId;
+            this.scoreItemRankId = scoreItemRankId;
             this.sumScore = sumScore;
             this.validScore = validScore;
         }
@@ -490,6 +602,14 @@ public class ContributionHelper {
             this.scoreItemSubId = scoreItemSubId;
         }
 
+        public Long getScoreItemRankId() {
+            return scoreItemRankId;
+        }
+
+        public void setScoreItemRankId(Long scoreItemRankId) {
+            this.scoreItemRankId = scoreItemRankId;
+        }
+
         public BigDecimal getSumScore() {
             return sumScore;
         }

+ 7 - 2
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/contribution/ContribBillFormPlugin.java

@@ -98,6 +98,7 @@ public class ContribBillFormPlugin extends AbstractFormPlugin implements Plugin,
                 || ContributionConstant.NCKD_PERSON.equalsIgnoreCase(fieldKey)
                 || ContributionConstant.NCKD_SCOREITEMSUB.equalsIgnoreCase(fieldKey)
                 || ContributionConstant.NCKD_SCOREITEM.equalsIgnoreCase(fieldKey)
+                || ContributionConstant.NCKD_SCOREITEMRANK.equalsIgnoreCase(fieldKey)
                 || ContributionConstant.NCKD_ORISCORE.equalsIgnoreCase(fieldKey);
     }
 
@@ -114,6 +115,7 @@ public class ContribBillFormPlugin extends AbstractFormPlugin implements Plugin,
         Date date = ConvertUtil.toDate(this.getModel().getValue(ContributionConstant.NCKD_YEAR));
         DynamicObject scoreItem = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_SCOREITEM));
         DynamicObject scoreItemSub = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_SCOREITEMSUB));
+        DynamicObject scoreItemRank = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_SCOREITEMRANK));
         DynamicObject person = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_PERSON, rowIndex));
         BigDecimal oriScore = ConvertUtil.toBigDecimal(this.getModel().getValue(ContributionConstant.NCKD_ORISCORE, rowIndex));
 
@@ -123,7 +125,8 @@ public class ContribBillFormPlugin extends AbstractFormPlugin implements Plugin,
             ContributionHelper.ScoreItemValidScore scoreItemValidScore = new ContributionHelper.ScoreItemValidScore(
                     person.getLong(FormConstant.ID_KEY),
                     scoreItem.getLong(FormConstant.ID_KEY),
-                    scoreItemSub.getLong(FormConstant.ID_KEY));
+                    scoreItemSub.getLong(FormConstant.ID_KEY),
+                    scoreItemRank != null ? scoreItemRank.getLong(FormConstant.ID_KEY) : null);
             scoreItemValidScore.setCurrentScore(oriScore);
             ContributionHelper.getScoreItemValidScore(scoreItemValidScore, date, id);
             this.getModel().setValue(ContributionConstant.NCKD_SCORE, scoreItemValidScore.getValidScore(), rowIndex);
@@ -144,6 +147,7 @@ public class ContribBillFormPlugin extends AbstractFormPlugin implements Plugin,
         Date date = ConvertUtil.toDate(this.getModel().getValue(ContributionConstant.NCKD_YEAR));
         DynamicObject scoreItem = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_SCOREITEM));
         DynamicObject scoreItemSub = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_SCOREITEMSUB));
+        DynamicObject scoreItemRank = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(ContributionConstant.NCKD_SCOREITEMRANK));
 
         if (date != null && scoreItem != null && scoreItemSub != null) {
             //重置分录所有分录的"录用积分"字段
@@ -158,7 +162,8 @@ public class ContribBillFormPlugin extends AbstractFormPlugin implements Plugin,
                     ContributionHelper.ScoreItemValidScore scoreItemValidScore = new ContributionHelper.ScoreItemValidScore(
                             person.getLong(FormConstant.ID_KEY),
                             scoreItem.getLong(FormConstant.ID_KEY),
-                            scoreItemSub.getLong(FormConstant.ID_KEY));
+                            scoreItemSub.getLong(FormConstant.ID_KEY),
+                            scoreItemRank != null ? scoreItemRank.getLong(FormConstant.ID_KEY) : null);
                     scoreItemValidScore.setCurrentScore(oriScore);
                     scoreItemValidScore.setRowIndex(i);
                     scoreItemValidScoreList.add(scoreItemValidScore);

+ 9 - 4
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/contribution/ScoreItemConfFormPlugin.java

@@ -28,9 +28,14 @@ public class ScoreItemConfFormPlugin extends AbstractFormPlugin implements Plugi
         super.registerListener(e);
 
         // 为分录中的A字段添加值变化监听
-        BasedataEdit bFieldEdit = this.getView().getControl(ContributionConstant.NCKD_SCOREITEMSUB);
-        if (bFieldEdit != null) {
-            bFieldEdit.addBeforeF7SelectListener(this);
+        BasedataEdit scoreItemSubEdit = this.getView().getControl(ContributionConstant.NCKD_SCOREITEMSUB);
+        if (scoreItemSubEdit != null) {
+            scoreItemSubEdit.addBeforeF7SelectListener(this);
+        }
+
+        BasedataEdit scoreItemRankEdit = this.getView().getControl(ContributionConstant.NCKD_SCOREITEMRANK);
+        if (scoreItemRankEdit != null) {
+            scoreItemRankEdit.addBeforeF7SelectListener(this);
         }
     }
 
@@ -41,7 +46,7 @@ public class ScoreItemConfFormPlugin extends AbstractFormPlugin implements Plugi
 
         //基础资料联动
         // 仅处理B字段的F7事件
-        if (ContributionConstant.NCKD_SCOREITEMSUB.equalsIgnoreCase(fieldKey)) {
+        if (ContributionConstant.NCKD_SCOREITEMSUB.equalsIgnoreCase(fieldKey) || ContributionConstant.NCKD_SCOREITEMRANK.equalsIgnoreCase(fieldKey)) {
             // 获取当前分录行的行号
             int currentRow = e.getRow();
 

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

@@ -256,7 +256,9 @@ public class NewDynamicAdjustmentOperationPlugIn extends AbstractOperationServic
         position.set(FormConstant.ID_KEY, positionId);
         Long jobSeqId = empPosOrgRel.getLong(String.join(".", FormConstant.HBPM_POSITIONHR, FormConstant.NCKD_JOBSEQ, FormConstant.ID_KEY));
         DynamicObject jobSeq = BusinessDataServiceHelper.newDynamicObject(FormConstant.HBJM_JOBSEQHR);
-        jobSeq.set(FormConstant.ID_KEY, jobSeqId);
+        //档案里面存储转换后的序列
+        DynamicObject newJob = JobLevelCalculatorService.handleJobSeq(jobSeq);
+        jobSeq.set(FormConstant.ID_KEY, newJob.getLong(FormConstant.ID_KEY));
         newPersonPosFile.set(PositionStructureConstant.NCKD_JOBSEQHR, jobSeq);
         newPersonPosFile.set(PositionStructureConstant.NCKD_POSITIONHR, position);
         newPersonPosFile.set(PositionStructureConstant.NCKD_RANKNAME, jobLevelResult.jobScoreInfo.rankName);

+ 4 - 1
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/contribution/ContribBillOpPlugin.java

@@ -16,6 +16,7 @@ import kd.bos.entity.validate.ErrorLevel;
 import kd.bos.form.MessageBoxResult;
 import kd.sdk.plugin.Plugin;
 import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.utils.ConvertUtil;
 import nckd.jxccl.base.common.utils.StrFormatter;
 import nckd.jxccl.hr.psms.common.ContributionConstant;
 import nckd.jxccl.hr.psms.helper.ContributionHelper;
@@ -60,6 +61,7 @@ public class ContribBillOpPlugin extends AbstractOperationServicePlugIn implemen
                             Date date = data.getDate(ContributionConstant.NCKD_YEAR);
                             DynamicObject scoreItem = data.getDynamicObject(ContributionConstant.NCKD_SCOREITEM);
                             DynamicObject scoreItemSub = data.getDynamicObject(ContributionConstant.NCKD_SCOREITEMSUB);
+                            DynamicObject scoreItemRank = data.getDynamicObject(ContributionConstant.NCKD_SCOREITEMRANK);
                             List<ContributionHelper.ScoreItemValidScore> scoreItemValidScoreList = new ArrayList<>(entryEntity.size());
                             for (DynamicObject entry : entryEntity) {
                                 DynamicObject person = entry.getDynamicObject(ContributionConstant.NCKD_PERSON);
@@ -67,7 +69,8 @@ public class ContribBillOpPlugin extends AbstractOperationServicePlugIn implemen
                                 ContributionHelper.ScoreItemValidScore scoreItemValidScore = new ContributionHelper.ScoreItemValidScore(
                                         person.getLong(FormConstant.ID_KEY),
                                         scoreItem.getLong(FormConstant.ID_KEY),
-                                        scoreItemSub.getLong(FormConstant.ID_KEY));
+                                        scoreItemSub.getLong(FormConstant.ID_KEY),
+                                        scoreItemRank != null ? scoreItemRank.getLong(FormConstant.ID_KEY) : null);
                                 scoreItemValidScore.setCurrentScore(oriScore);
                                 scoreItemValidScoreList.add(scoreItemValidScore);
                             }

+ 102 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/contribution/validate/ScoreItemConfValidate.java

@@ -0,0 +1,102 @@
+package nckd.jxccl.hr.psms.plugin.operate.contribution.validate;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.ExtendedDataEntity;
+import kd.bos.entity.validate.AbstractValidator;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.utils.StrFormatter;
+import nckd.jxccl.hr.psms.common.ContributionConstant;
+import nckd.jxccl.hr.psms.helper.ContributionHelper;
+import org.apache.commons.lang3.StringUtils;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.Map;
+import java.util.Objects;
+import java.util.StringJoiner;
+import java.util.stream.Collectors;
+
+/**
+ * 动态表单插件
+ */
+/**
+* 积分项目分数配置校验
+* 实体标识:nckd_scoreitemconf
+* @author W.Y.C
+* @date 2025/11/2 13:02
+* @version 1.0
+*/
+public class ScoreItemConfValidate extends AbstractValidator {
+
+    @Override
+    public void validate() {
+
+        //查询其他有效日期内的数据
+
+        for (ExtendedDataEntity dataEntity : this.getDataEntities()) {
+            DynamicObject data = dataEntity.getDataEntity();
+            long id = data.getLong(FormConstant.ID_KEY);
+            Date startDate = data.getDate(FormConstant.NCKD_STARTDATE);
+            Date endDate = data.getDate(FormConstant.NCKD_ENDDATE);
+
+            QFilter filter = new QFilter(FormConstant.ID_KEY, QCP.not_equals,id);
+            Map<String, BigDecimal> scoreConfMap = ContributionHelper.getScoreConf(filter);
+
+            //判定是否在有效期内,endDate为空时,默认为不失效
+            // if (startDate != null && (endDate == null || !endDate.before(new Date()))) {
+                //校验有效时间范围内有没有重复配置
+                DynamicObjectCollection dynamicObjectCollection = data.getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
+                Map<String, DynamicObject> scoreMap = dynamicObjectCollection.stream()
+                .filter(Objects::nonNull)
+                .collect(Collectors.toMap(
+                        item -> {
+                            DynamicObject scoreItem = item.getDynamicObject(ContributionConstant.NCKD_SCOREITEM);
+                            DynamicObject scoreItemSub = item.getDynamicObject(ContributionConstant.NCKD_SCOREITEMSUB);
+                            DynamicObject scoreItemRank = item.getDynamicObject(ContributionConstant.NCKD_SCOREITEMRANK);
+
+                            long scoreItemId = (scoreItem != null) ? scoreItem.getLong(FormConstant.ID_KEY) : 0L;
+                            long scoreItemSubId = (scoreItemSub != null) ? scoreItemSub.getLong(FormConstant.ID_KEY) : 0L;
+                            long scoreItemRankId = (scoreItemRank != null) ? scoreItemRank.getLong(FormConstant.ID_KEY) : 0L;
+
+                            if (scoreItemRankId > 0) {
+                                return scoreItemId + "-" + scoreItemSubId + "-" + scoreItemRankId;
+                            } else if (scoreItemSubId > 0) {
+                                return scoreItemId + "-" + scoreItemSubId;
+                            } else {
+                                return String.valueOf(scoreItemId);
+                            }
+                        },
+                        item -> item,
+                        (existing, replacement) -> existing
+                ));
+                for (Map.Entry<String, DynamicObject> entry : scoreMap.entrySet()) {
+                    String key = entry.getKey();
+                    DynamicObject dynamicObject = entry.getValue();
+                    if(scoreConfMap.get(key) != null){
+                        DynamicObject scoreItem = dynamicObject.getDynamicObject(ContributionConstant.NCKD_SCOREITEM);
+                        DynamicObject scoreItemSub = dynamicObject.getDynamicObject(ContributionConstant.NCKD_SCOREITEMSUB);
+                        DynamicObject scoreItemRank = dynamicObject.getDynamicObject(ContributionConstant.NCKD_SCOREITEMRANK);
+
+                        String scoreItemName = (scoreItem != null) ? scoreItem.getString(FormConstant.NAME_KEY) : null;
+                        String scoreItemSubName = (scoreItemSub != null) ? scoreItemSub.getString(FormConstant.NAME_KEY) : null;
+                        String scoreItemRankName = (scoreItemRank != null) ? scoreItemRank.getString(FormConstant.NAME_KEY) : null;
+                        StringJoiner joiner = new StringJoiner("-");
+                        if (StringUtils.isNotEmpty(scoreItemName)) {
+                            joiner.add(scoreItemName);
+                        }
+                        if (StringUtils.isNotEmpty(scoreItemSubName)) {
+                            joiner.add(scoreItemSubName);
+                        }
+                        if (StringUtils.isNotEmpty(scoreItemRankName)) {
+                            joiner.add(scoreItemRankName);
+                        }
+                        this.addErrorMessage(dataEntity, StrFormatter.format("【{}】已存在生效中的配置。不能重复配置", joiner.toString()));
+                    }
+                }
+            // }
+        }
+    }
+}

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

@@ -1,6 +1,7 @@
 package nckd.jxccl.hr.psms.plugin.report.adjust;
 
 import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.report.ReportQueryParam;
 import kd.bos.form.CloseCallBack;
 import kd.bos.form.FormShowParameter;
 import kd.bos.form.ShowType;
@@ -44,6 +45,12 @@ public class UnAdjustedReportFormPlugin extends AbstractReportFormPlugin impleme
         this.addItemClickListeners(FormConstant.TOOLBARAP);
     }
 
+    @Override
+    public void beforeQuery(ReportQueryParam queryParam) {
+        ReportList reportList = this.getControl("reportlistap");
+        reportList.setSelectedAll(true);
+    }
+
     @Override
     public void itemClick(ItemClickEvent evt) {
         String itemKey = evt.getItemKey();