Эх сурвалжийг харах

Merge remote-tracking branch 'origin/master'

jtd 1 цаг өмнө
parent
commit
11bb3258f2
39 өөрчлөгдсөн 1747 нэмэгдсэн , 307 устгасан
  1. 10 1
      code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/constant/FormConstant.java
  2. 11 0
      code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/utils/DateUtil.java
  3. 118 35
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/business/JobLevelCalculatorService.java
  4. 12 1
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/common/bo/PositionAppointmentBO.java
  5. 8 1
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/helper/PositionFileHelper.java
  6. 3 3
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/initial/NewHireInitialFormPlugin.java
  7. 4 2
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/initial/ServingInitialFormPlugin.java
  8. 34 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/other/ManagerAllowanceListPlugin.java
  9. 97 4
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/performance/PerfRankMgmtFormPlugin.java
  10. 2 4
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/adjust/NewDynamicAdjustmentOperationPlugIn.java
  11. 5 4
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/initial/BaseInitialOperationPlugIn.java
  12. 51 34
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/performance/validate/PerfRankMgmtSaveValidate.java
  13. 13 22
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/report/adjust/UnAdjustedReportReportListDataPlugin.java
  14. 48 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/task/HRDataCleanTask.java
  15. 23 1
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/operate/cycle/PerfManagerSaveOpPlugin.java
  16. 3 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/business/annualincome/AnnualIncomeCalculateService.java
  17. 183 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/business/coordination/SinsurCoordSplitService.java
  18. 23 23
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/business/coordination/api/SinsurCoordBizSaveHandler.java
  19. 111 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/business/file/attach/AdjustSIBaseService.java
  20. 4 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/common/constant/SitConstant.java
  21. 23 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/coordination/SinSurEmpChgCoordBatchEditPluginEx.java
  22. 181 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/file/attach/AdjustSIBaseFormPlugin.java
  23. 56 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/file/attach/SIBaseListEx.java
  24. 66 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/opplugin/web/coordination/SinsurEmpCoordSplitOp.java
  25. 16 4
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/opplugin/web/file/attach/SIBaseSaveOpEx.java
  26. 17 2
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hsas/business/outdata/OutImportTaskGuideExportService.java
  27. 14 25
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hsas/business/outdata/OutImportTaskGuideImportService.java
  28. 40 5
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hsas/business/utils/OutImportTaskUtils.java
  29. 126 119
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hsas/formplugin/web/outdata/bill/OutTempDataViewBillListPlugin.java
  30. 7 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hsas/formplugin/web/outdata/helper/OutImpTemplateHelper.java
  31. 6 2
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/structappr/AbstractStructApprFormPlugin.java
  32. 14 7
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/structappr/EntleaderAnlSalStdFormPlugin.java
  33. 13 7
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/structappr/SubcorpChiefSalStdFormPlugin.java
  34. 5 1
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/structappr/change/AbstractSalaryStdChgFormPlugin.java
  35. 142 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/onlineperf/business/extpoint/OnlinePerfSalaryCalServiceExPlugin.java
  36. 30 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/onlineperf/common/OnlinePerfConstant.java
  37. 108 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/onlineperf/common/OnlinePerfFetchDataService.java
  38. 22 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/onlineperf/plugin/form/OnlinePerfListPlugin.java
  39. 98 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/onlineperf/plugin/operate/UnLockOnlinePerfOpPlugin.java

+ 10 - 1
code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/constant/FormConstant.java

@@ -58,8 +58,10 @@ public class FormConstant {
     public static final String BOS_ORG = "bos_org";
     /** 调动单-实体标识*/
     public static final String HDM_TRANSFERAPPLY = "hdm_transferapply";
+    /** 批量调动单-实体标识*/
+    public static final String HDM_TRANSFERBATCH = "hdm_transferbatch";
     /** 事务变动记录-实体标识 */
-    public static final String HPFS_CHGRECORD_ENTITY = "hpfs_chgrecord";
+    public static final String HPFS_CHGRECORD = "hpfs_chgrecord";
     /** 组织-实体标识 */
     public static final String BOS_ORG_ENTITY = "bos_org";
     /** HR组织 */
@@ -419,4 +421,11 @@ public class FormConstant {
     /** 上级组织 */
     public static final String PARENTORG_KEY = "parentorg";
 
+    /** 变动操作 */
+    public static final String AFFACTION_KEY = "affaction";
+    /** 别名 */
+    public static final String NCKD_ALIAS = "nckd_alias";
+    /** 别名 */
+    public static final String NCKD_ISPARTICIPATE = "nckd_isparticipate";
+
 }

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

@@ -300,6 +300,17 @@ public class DateUtil {
         return dateTime.getMonth();
     }
 
+
+    /**
+     * 获取月份数字(1-12)
+     *
+     * @param date 日期时间对象
+     * @return 月份数字
+     */
+    public static int getMonthValue(Date date) {
+        return getMonthValue(toLocalDateTime(date));
+    }
+
     /**
      * 获取月份数字(1-12)
      *

+ 118 - 35
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/business/JobLevelCalculatorService.java

@@ -35,6 +35,7 @@ import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.time.LocalDateTime;
 import java.util.Arrays;
+import java.util.Comparator;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
@@ -153,7 +154,7 @@ public class JobLevelCalculatorService {
 
         // 9. 处理序列相关信息
         //对应SHR:995~1013
-        JobSeqInfo jobSeqInfo = processJobFamilyInfo(jobSeq, currentPersonPosFile);
+        JobSeqInfo jobSeqInfo = processJobFamilyInfo(jobSeq, currentPersonPosFile,date);
 
         // 10. 处理职称/技能等级积分
         // 对应SHR:1015~1036
@@ -697,16 +698,20 @@ public class JobLevelCalculatorService {
      * 处理序列相关信息
      */
     private static JobSeqInfo processJobFamilyInfo(DynamicObject newJobSeq,
-                                                   DynamicObject currentPersonPosFileByPerson) {
+                                                   DynamicObject currentPersonPosFileByPerson,
+                                                   Date date) {
         JobSeqInfo jobSeqInfo = new JobSeqInfo();
 
         long newJonSeqId = newJobSeq.getLong(FormConstant.ID_KEY);
         String newJonSeqNumber = newJobSeq.getString(FormConstant.NUMBER_KEY);
         // 获取原序列信息
         DynamicObject currentJobSeq = currentPersonPosFileByPerson.getDynamicObject(PositionStructureConstant.NCKD_JOBSEQHR);
+        jobSeqInfo.currentJobSeq = currentJobSeq;
         //如果是管理序列,则按职能序列进行调整
         //对应SHR:986~993行
-        currentJobSeq = handleJobSeq(currentJobSeq);
+        DynamicObject convertJobSeq = handleJobSeq(currentJobSeq);
+        currentJobSeq = convertJobSeq;
+        jobSeqInfo.convertJobSeq = convertJobSeq;
         long currentJonSeqId = currentJobSeq.getLong(FormConstant.ID_KEY);
         String currentJonSeqNumber = currentJobSeq.getString(FormConstant.NUMBER_KEY);
 
@@ -717,7 +722,23 @@ public class JobLevelCalculatorService {
 
         // 判断是否为跨单位调动
         jobSeqInfo.isCrossUnitTransfer = false;
-        // TODO【待修改】-职位体系-这里需要根据具体业务逻辑判断是否为跨单位调动
+        //上一段员工档案开始时间至当前开始时间有没有跨单位调动
+        QFilter filter = QFilterCommonHelper.getBillStatusFilter()
+                .and(String.join(".",FormConstant.BB_EM_TID,FormConstant.ID_KEY),QCP.equals,currentPersonPosFileByPerson.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY)))
+                //跨单位调动
+                .and(String.join(".",FormConstant.AFFACTION_KEY,FormConstant.NUMBER_KEY),QCP.equals,"101060_S")
+                .and(FormConstant.B_EFFECTIVEDATE,QCP.large_equals,currentPersonPosFileByPerson.getDate(PositionStructureConstant.NCKD_BEGINDATE))
+                .and(FormConstant.B_EFFECTIVEDATE,QCP.less_equals,date);
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                //调出公司
+                .addIdNumberName("bcompany")
+                //调入公司
+                .addIdNumberName("acompany");
+        DynamicObjectCollection query = QueryServiceHelper.query("hdm_transferapply", queryFieldBuilder.buildSelect(), new QFilter[]{filter});
+        if(!query.isEmpty()){
+            jobSeqInfo.isCrossUnitTransfer = true;
+        }
+
 
         return jobSeqInfo;
     }
@@ -1604,8 +1625,7 @@ public class JobLevelCalculatorService {
      * @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));
+        DynamicObjectCollection jobLevels = queryJobLevels(jobSeq.getString(FormConstant.NUMBER_KEY), null, 0, 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));
@@ -1624,7 +1644,7 @@ public class JobLevelCalculatorService {
      */
     public static DynamicObject getLowestJobLevel(DynamicObject jobSeq) {
 
-        DynamicObjectCollection jobLevels = queryJobLevels(jobSeq.getString(FormConstant.NUMBER_KEY), null, null,
+        DynamicObjectCollection jobLevels = queryJobLevels(jobSeq.getString(FormConstant.NUMBER_KEY), null,
                 null, String.join(".", FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ));
         DynamicObject jobLevel = !jobLevels.isEmpty() ? jobLevels.get(0) : null;
         if( jobLevel != null) {
@@ -1643,7 +1663,7 @@ public class JobLevelCalculatorService {
      * @date: 2025/09/20 16:52
      */
     public static DynamicObject getMaxJobLevel(DynamicObject jobSeq,BigDecimal score) {
-        DynamicObjectCollection jobLevels = queryJobLevels(jobSeq.getString(FormConstant.NUMBER_KEY), score, null,
+        DynamicObjectCollection jobLevels = queryJobLevels(jobSeq.getString(FormConstant.NUMBER_KEY), score,
                 null, String.join(".", FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ +" desc"));
         DynamicObject jobLevel = !jobLevels.isEmpty() ? jobLevels.get(0) : null;
         if( jobLevel != null) {
@@ -1699,15 +1719,15 @@ public class JobLevelCalculatorService {
             System.out.println("非技能序列使用职称等级,编码【" + likenumber + "】");
         }
 
-        DynamicObjectCollection jobLevels = queryJobLevels(jobSeq.getString(FormConstant.NUMBER_KEY), score, null,
+        DynamicObject jobLevels = getJobLevelByJobSeqAndQualAndScore(jobSeq.getString(FormConstant.NUMBER_KEY), score, null,
                 likenumber, String.join(".", FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ + " desc"));
 
-        if(!jobLevels.isEmpty()){
+        if(jobLevels != null){
             if(downgradeNum != null && downgradeNum > 0) {
                 //降级
                 Map<Integer, DynamicObject> jobLevelMap = getJobLevelByJobSeqMap(jobSeq);
                 //当前分数能达到的最大职级减去需降级数
-                int maxJobLevelSeq = jobLevels.get(0).getInt(FormConstant.JOBLEVELSEQ);
+                int maxJobLevelSeq = jobLevels.getInt(FormConstant.JOBLEVELSEQ);
                 DynamicObject jobLevel = jobLevelMap.get(maxJobLevelSeq - downgradeNum);
                 if (jobLevel == null) {
                     //降级数超出则返回最低职级
@@ -1715,7 +1735,7 @@ public class JobLevelCalculatorService {
                 }
                 return jobLevel;
             }
-            long jobLevelId = jobLevels.get(0).getLong(String.join(".", FormConstant.HBJM_JOBLEVELHR, FormConstant.ID_KEY));
+            long jobLevelId = jobLevels.getLong(String.join(".", FormConstant.HBJM_JOBLEVELHR, FormConstant.ID_KEY));
             return BusinessDataServiceHelper.loadSingle(jobLevelId, FormConstant.HBJM_JOBLEVELHR);
         }else{
             //没有获取到预期的职级则返回最低职级
@@ -1753,7 +1773,7 @@ public class JobLevelCalculatorService {
      * @date: 2025/09/20 16:52
      */
     public static DynamicObject[] getJobLevelByJobSeq(DynamicObject jobSeq) {
-        DynamicObjectCollection jobLevels = queryJobLevels(jobSeq.getString(FormConstant.NUMBER_KEY), null, null,
+        DynamicObjectCollection jobLevels = queryJobLevels(jobSeq.getString(FormConstant.NUMBER_KEY), 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);
@@ -1778,13 +1798,12 @@ public class JobLevelCalculatorService {
      * @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) {
+    private static DynamicObjectCollection queryJobLevels(String jobSeqNumber, BigDecimal score, Integer jobLevelSeq, String orderBy) {
 
         QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                 .addIdNumberNameWithExtras(
@@ -1799,7 +1818,8 @@ public class JobLevelCalculatorService {
                 .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));
+                .and(new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ), QCP.is_notnull, null))
+                .and(new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NCKD_ISPARTICIPATE), QCP.equals, EnableEnum.YES.getCode()));
         if(score != null){
             filter.and(new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NCKD_SCORE), QCP.less_equals, score));
         }
@@ -1811,32 +1831,92 @@ public class JobLevelCalculatorService {
         }
 
         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);
+        return QueryServiceHelper.query(PositionStructureConstant.GETLEVELBYJOBSEQ_QUERY,
+                queryFieldBuilder.buildSelect(),
+                new QFilter[]{filter},
+                orderBy);
+    }
+
+    //根据职位序列、资格级别和分数获取符合条件的职级
+    public static DynamicObject getJobLevelByJobSeqAndQualAndScore(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))
+                .and(new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NCKD_ISPARTICIPATE), QCP.equals, EnableEnum.YES.getCode()));
+        if(jobLevelSeq != null){
+            filter.and(new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ), QCP.less_equals, jobLevelSeq));
         }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);
+            //只查询有效的序号(无职级是-1,避免查出来)
+            filter.and(new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ), QCP.large_than, 0));
         }
-        return query;
+
+        QFilter filter1 = filter.copy();
+        filter1.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()))
+                .and(new QFilter(String.join(".",FormConstant.HBJM_JOBLEVELHR, FormConstant.NCKD_SCORE), QCP.less_equals, score));
+        //获取分数可以达到的职级列表
+        DynamicObjectCollection query1 = QueryServiceHelper.query(PositionStructureConstant.GETLEVELBYJOBSEQ_QUERY,
+                queryFieldBuilder.buildSelect(),
+                new QFilter[]{filter1},
+                orderBy);
+        Map<Integer, List<DynamicObject>> resultMap = query1.stream()
+                .collect(Collectors.groupingBy(
+                        obj -> obj.getInt(String.join(".", FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ)),
+                        LinkedHashMap::new,
+                        Collectors.toList()
+                ))
+                .entrySet()
+                .stream()
+                .sorted(Map.Entry.<Integer, List<DynamicObject>>comparingByKey().reversed())
+                .collect(Collectors.toMap(
+                        Map.Entry::getKey,
+                        Map.Entry::getValue,
+                        (existing, replacement) -> existing,
+                        LinkedHashMap::new
+                ));
+
+        //获取职称级别/技能级别可以达到的最大职级
+        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+"%"));
+        DynamicObjectCollection query = QueryServiceHelper.query(PositionStructureConstant.GETLEVELBYJOBSEQQUERYANDQUAL_QUERY,
+                queryFieldBuilder.buildSelect(),
+                new QFilter[]{filter},
+                orderBy);
+        if(!query.isEmpty()){
+            int max = query.get(0).getInt(String.join(".", FormConstant.HBJM_JOBLEVELHR, FormConstant.JOBLEVELSEQ));
+            //找到 resultMap 中最接近 max 值的职级
+            DynamicObject closestObject = resultMap.entrySet().stream()
+                    .min(Comparator.comparingInt(entry -> Math.abs(entry.getKey() - max)))
+                    .map(Map.Entry::getValue)
+                    .filter(list -> !list.isEmpty())
+                    .map(list -> list.get(0))
+                    .orElse(null);
+            return closestObject;
+        }
+        return null;
     }
 
     // 辅助类定义
@@ -1847,6 +1927,9 @@ public class JobLevelCalculatorService {
         /** 是否为跨单位调动*/
         //对应SHR:isadjusttype_1
         public boolean isCrossUnitTransfer;
+
+        public DynamicObject currentJobSeq;
+        public DynamicObject convertJobSeq;
     }
 
     public static class JobScoreInfo {

+ 12 - 1
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/common/bo/PositionAppointmentBO.java

@@ -27,14 +27,17 @@ public  class PositionAppointmentBO {
      */
     private DynamicObject perOcpQual;
 
+    private Boolean isExcellent;
+
     public PositionAppointmentBO() {
     }
 
-    public PositionAppointmentBO(DynamicObject empPosOrgRel, DynamicObject perEduExp, DynamicObject perProTitle, DynamicObject perOcpQual) {
+    public PositionAppointmentBO(DynamicObject empPosOrgRel, DynamicObject perEduExp, DynamicObject perProTitle, DynamicObject perOcpQual,Boolean isExcellent) {
         this.empPosOrgRel = empPosOrgRel;
         this.perEduExp = perEduExp;
         this.perProTitle = perProTitle;
         this.perOcpQual = perOcpQual;
+        this.isExcellent = isExcellent;
     }
 
     public DynamicObject getEmpPosOrgRel() {
@@ -68,4 +71,12 @@ public  class PositionAppointmentBO {
     public void setPerProTitle(DynamicObject perProTitle) {
         this.perProTitle = perProTitle;
     }
+
+    public Boolean getExcellent() {
+        return isExcellent;
+    }
+
+    public void setExcellent(Boolean excellent) {
+        isExcellent = excellent;
+    }
 }

+ 8 - 1
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/helper/PositionFileHelper.java

@@ -485,7 +485,14 @@ public class PositionFileHelper {
             positionAppointmentBO.setPerOcpQual(perOcpQualDynamicObject.get(0));
         }
 
-
+        //5.是否优秀生
+        QueryFieldBuilder topStudentQueryFieldBuilder = QueryFieldBuilder.create().add(FormConstant.ID_KEY);
+        QFilter topStudentFilter = new QFilter(FormConstant.EMPLOYEE_KEY,QCP.equals,personId)
+                .and("nckd_honortype",QCP.is_notnull,null);
+        DynamicObjectCollection topStudentDynamicObject = QueryServiceHelper.query("nckd_hrpi_topstudent", topStudentQueryFieldBuilder.buildSelect(), new QFilter[]{topStudentFilter});
+        if(!topStudentDynamicObject.isEmpty()){
+            positionAppointmentBO.setExcellent(true);
+        }
         return positionAppointmentBO;
     }
 

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

@@ -121,6 +121,9 @@ public class NewHireInitialFormPlugin extends AbstractFormPlugin implements Plug
                 long quaLevelId = perOcpQual.getLong(String.join(".", FormConstant.QUALEVEL_KEY, FormConstant.ID_KEY));
                 this.getModel().setValue(PositionStructureConstant.NCKD_OCPQUALLEVEL, quaLevelId == 0 ? null : quaLevelId);
             }
+            if(positionAppointMen.getExcellent() != null && positionAppointMen.getExcellent()){
+                this.getModel().setValue(PositionStructureConstant.NCKD_EXCELLENT, true);
+            }
 
             if(affirm){
                 String personName = positionAppointMen.getEmpPosOrgRel().getString(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.NAME_KEY));
@@ -141,9 +144,6 @@ public class NewHireInitialFormPlugin extends AbstractFormPlugin implements Plug
                 this.getModel().setValue(PositionStructureConstant.NCKD_BEGINDATE, beginYear);
             }
         }
-        // TODO 【待修改】优秀生
-        // this.getModel().setValue(PositionStructureConstant.NCKD_EXCELLENT, );
-
 
     }
 

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

@@ -123,8 +123,10 @@ public class ServingInitialFormPlugin extends AbstractFormPlugin implements Plug
                 this.getModel().setValue(PositionStructureConstant.NCKD_JOINCOMDATE, joinComDate);
 
             }
-            // TODO 【待修改】优秀生
-            // this.getModel().setValue(PositionStructureConstant.NCKD_EXCELLENT, );
+
+            if(positionAppointMen.getExcellent() != null && positionAppointMen.getExcellent()){
+                this.getModel().setValue(PositionStructureConstant.NCKD_EXCELLENT, true);
+            }
         }
     }
 

+ 34 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/other/ManagerAllowanceListPlugin.java

@@ -0,0 +1,34 @@
+package nckd.jxccl.hr.psms.plugin.form.other;
+
+import kd.bos.entity.operate.result.IOperateInfo;
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.list.plugin.AbstractListPlugin;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FormConstant;
+
+/**
+* 配置有职位津贴的管理人员
+* 实体标识:nckd_managerallowance
+* @author W.Y.C
+* @date 2025/12/18 21:32
+* @version 1.0
+*/
+public class ManagerAllowanceListPlugin extends AbstractListPlugin implements Plugin {
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
+        if(afterDoOperationEventArgs.getOperationResult() != null){
+            String operateKey = afterDoOperationEventArgs.getOperateKey();
+            if(FormConstant.SUBMIT_OP.equalsIgnoreCase(operateKey)){
+                if(!afterDoOperationEventArgs.getOperationResult().isSuccess()){
+                    for (IOperateInfo iOperateInfo : afterDoOperationEventArgs.getOperationResult().getAllErrorOrValidateInfo()) {
+                        if(iOperateInfo.getMessage().equalsIgnoreCase("只有暂存的数据才允许提交。")){
+                            afterDoOperationEventArgs.getOperationResult().setShowMessage(false);
+                            this.getView().showTipNotification("只有未确认的数据才允许确认。");
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

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

@@ -16,12 +16,17 @@ import kd.bos.entity.datamodel.events.BeforeDeleteRowEventArgs;
 import kd.bos.entity.datamodel.events.BeforeImportEntryEventArgs;
 import kd.bos.entity.datamodel.events.ChangeData;
 import kd.bos.entity.datamodel.events.PropertyChangedArgs;
+import kd.bos.entity.filter.CompareTypeEnum;
+import kd.bos.entity.filter.FilterValue;
+import kd.bos.entity.filter.SimpleFilterRow;
+import kd.bos.entity.property.entryfilter.EntryQueryParam;
 import kd.bos.form.ConfirmCallBackListener;
 import kd.bos.form.ConfirmTypes;
 import kd.bos.form.IClientViewProxy;
 import kd.bos.form.MessageBoxOptions;
 import kd.bos.form.MessageBoxResult;
 import kd.bos.form.container.Wizard;
+import kd.bos.form.control.Control;
 import kd.bos.form.control.EntryGrid;
 import kd.bos.form.control.Steps;
 import kd.bos.form.control.events.StepEvent;
@@ -37,6 +42,7 @@ import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
 import kd.bos.servicehelper.BusinessDataServiceHelper;
 import kd.bos.servicehelper.QueryServiceHelper;
+import kd.hdtc.hrcc.common.enums.FileImportSubTaskDealStatusEnum;
 import kd.hr.hbp.business.servicehelper.HRQueryEntityHelper;
 import nckd.jxccl.base.common.constant.FormConstant;
 import nckd.jxccl.base.common.constant.QueryConstant;
@@ -53,6 +59,8 @@ import nckd.jxccl.hr.psms.common.PositionStructureConstant;
 import nckd.jxccl.hr.psms.helper.PositionFileHelper;
 import org.apache.commons.lang3.StringUtils;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.temporal.ChronoUnit;
@@ -102,6 +110,9 @@ public class PerfRankMgmtFormPlugin extends AbstractFormPlugin implements Wizard
             setStepStatus(1,Steps.PROCESS);
 
             importResultStep();
+
+            //步骤为:导入考核结果时只显示参与排名的人员
+            applyRankingFilter(true);
         }
     }
 
@@ -161,7 +172,7 @@ public class PerfRankMgmtFormPlugin extends AbstractFormPlugin implements Wizard
                         PerfRankMgmtConstant.NCKD_TOPRANK)
                 .anyMatch(prop -> prop.equalsIgnoreCase(name))){
             //排名信息变化计算排名数
-            calcRankCount();
+//            calcRankCount();
         }else if(FormConstant.NCKD_PERSON.equalsIgnoreCase(name)){
             //变更或选择人员重新获取是否享受职位津贴
             ChangeData[] changeSet = e.getChangeSet();
@@ -176,11 +187,55 @@ public class PerfRankMgmtFormPlugin extends AbstractFormPlugin implements Wizard
                 this.getModel().setValue(PerfRankMgmtConstant.NCKD_POSTALLOWANCE, hasAllowance,changeSet[0].getRowIndex());
                 this.getView().updateView(PerfRankMgmtConstant.NCKD_POSTALLOWANCE,changeSet[0].getRowIndex());
             }
-
+        }else if(PerfRankMgmtConstant.NCKD_TOPRANKS.equalsIgnoreCase(name)){
+            //输入总排名
+            ChangeData[] changeSet = e.getChangeSet();
+            Object newValue = changeSet[0].getNewValue();
+            Object oldValue = changeSet[0].getOldValue();
+//            优秀人数、基本合格人数、不合格人数
+            if(!Objects.equals(newValue, oldValue)) {
+                QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                        .addGroup(new String[]{FormConstant.NCKD_ENTRYENTITY}, PerfRankMgmtConstant.NCKD_RATIO)
+                        .addGroup(new String[]{FormConstant.NCKD_ENTRYENTITY, PositionStructureConstant.NCKD_APPRAISALRESULT}, FormConstant.NUMBER_KEY);
+                DynamicObjectCollection query = QueryServiceHelper.query(PerfRankMgmtConstant.RANKRATIOCONF_ENTITYID, queryFieldBuilder.buildSelect(), null);
+                Map<String, BigDecimal> appraisalResultRatioMap = new HashMap<>();
+                query.forEach(dynamicObject -> {
+                    String key = dynamicObject.getString(String.join(".", FormConstant.NCKD_ENTRYENTITY, PositionStructureConstant.NCKD_APPRAISALRESULT, FormConstant.NUMBER_KEY));
+                    BigDecimal value = dynamicObject.getBigDecimal(String.join(".", FormConstant.NCKD_ENTRYENTITY, PerfRankMgmtConstant.NCKD_RATIO));
+                    appraisalResultRatioMap.put(key, value);
+                });
+
+                // 获取配置比例
+                BigDecimal excellentRatio = appraisalResultRatioMap.get(AppraisalResultEnum.EXCELLENT.getCode());
+                BigDecimal qualifiedRatio = appraisalResultRatioMap.get(AppraisalResultEnum.QUALIFIED.getCode());
+                BigDecimal basicallyQualifiedRatio = appraisalResultRatioMap.get(AppraisalResultEnum.BASICALLY_QUALIFIED.getCode());
+                BigDecimal unQualifiedRatio = appraisalResultRatioMap.get(AppraisalResultEnum.UN_QUALIFIED.getCode());
+
+                // 计算各等级的理论人数(四舍五入)
+                int expectedExcellent = calculateExpectedCount(ConvertUtil.toInt(newValue, 0), excellentRatio);
+                int expectedQualified = calculateExpectedCount(ConvertUtil.toInt(newValue, 0), qualifiedRatio);
+                int expectedBasic = calculateExpectedCount(ConvertUtil.toInt(newValue, 0), basicallyQualifiedRatio);
+                int expectedFail = calculateExpectedCount(ConvertUtil.toInt(newValue, 0), unQualifiedRatio);
+
+                this.getModel().setValue(PerfRankMgmtConstant.NCKD_EXCELLENTS, expectedExcellent);
+//                this.getModel().setValue(PerfRankMgmtConstant.NCKD_BASICS, expectedQualified);
+                this.getModel().setValue(PerfRankMgmtConstant.NCKD_BASICS, expectedBasic);
+                this.getModel().setValue(PerfRankMgmtConstant.NCKD_FAILS, expectedFail);
+            }
         }
 
     }
 
+    /**
+     * 计算理论人数(四舍五入)
+     */
+    private int calculateExpectedCount(int totalCount, BigDecimal ratio) {
+        // 将百分比转换为小数进行计算
+        BigDecimal decimalRatio = ratio.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP);
+        BigDecimal expected = decimalRatio.multiply(BigDecimal.valueOf(totalCount));
+        return expected.setScale(0, RoundingMode.HALF_UP).intValue();
+    }
+
     @Override
     public void beforeImportEntry(BeforeImportEntryEventArgs e) {
         super.beforeImportEntry(e);
@@ -477,7 +532,7 @@ public class PerfRankMgmtFormPlugin extends AbstractFormPlugin implements Wizard
 
     private void importResultStep() {
         this.getModel().setValue(PerfRankMgmtConstant.NCKD_STEP,1);
-        this.getView().setVisible(false, FormConstant.NUMBER_KEY, PerfRankMgmtConstant.NCKD_GETRANKLIST);
+        this.getView().setVisible(false, FormConstant.NUMBER_KEY, PerfRankMgmtConstant.NCKD_GETRANKLIST,"nckd_advconbaritemap2","nckd_advconbaritemap3");
         this.getView().setVisible(true, PerfRankMgmtConstant.NCKD_TOPRANKS, PerfRankMgmtConstant.NCKD_ALLOWANCERANKS, PerfRankMgmtConstant.NCKD_FAILS, PerfRankMgmtConstant.NCKD_BASICS, PerfRankMgmtConstant.NCKD_EXCELLENTS, "nckd_advconbaritemap6","nckd_advconbaritemap");
         DynamicObjectCollection entryEntity = this.getModel().getEntryEntity(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
         for (int i = 0; i < entryEntity.size(); i++) {
@@ -487,7 +542,7 @@ public class PerfRankMgmtFormPlugin extends AbstractFormPlugin implements Wizard
 
     private void generatePersonList() {
         this.getModel().setValue(PerfRankMgmtConstant.NCKD_STEP,0);
-        this.getView().setVisible(true, FormConstant.NUMBER_KEY, PerfRankMgmtConstant.NCKD_GETRANKLIST);
+        this.getView().setVisible(true, FormConstant.NUMBER_KEY, PerfRankMgmtConstant.NCKD_GETRANKLIST,"nckd_advconbaritemap2","nckd_advconbaritemap3");
         this.getView().setVisible(false, PerfRankMgmtConstant.NCKD_TOPRANKS, PerfRankMgmtConstant.NCKD_ALLOWANCERANKS, PerfRankMgmtConstant.NCKD_FAILS, PerfRankMgmtConstant.NCKD_BASICS, PerfRankMgmtConstant.NCKD_EXCELLENTS, "nckd_advconbaritemap6","nckd_advconbaritemap");
         DynamicObjectCollection entryEntity = this.getModel().getEntryEntity(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
         for (int i = 0; i < entryEntity.size(); i++) {
@@ -724,6 +779,10 @@ public class PerfRankMgmtFormPlugin extends AbstractFormPlugin implements Wizard
             generatePersonList();
             setStepStatus(0, Steps.PROCESS);
             this.getView().updateView(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
+
+            //步骤为:导入考核结果时只显示参与排名的人员
+            applyRankingFilter(false);
+
         }else{
             //校验有没有保存
             DynamicObject dataEntity = this.getModel().getDataEntity();
@@ -734,9 +793,43 @@ public class PerfRankMgmtFormPlugin extends AbstractFormPlugin implements Wizard
                 importResultStep();
                 setStepStatus(1, Steps.PROCESS);
                 this.getView().updateView(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
+
+                //步骤为:导入考核结果时只显示参与排名的人员
+                applyRankingFilter(true);
             }
         }
         this.getView().updateView(PerfRankMgmtConstant.NCKD_STEP);
 
     }
+
+    /**
+     * 应用排名过滤器
+     * @param onlyRankingParticipants 是否只显示参与排名的人员
+     */
+    private void applyRankingFilter(boolean onlyRankingParticipants) {
+        EntryGrid entryGrid = this.getView().getControl(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
+        List<SimpleFilterRow> filterRowList = new ArrayList<>(1);
+        List<FilterValue> value = new ArrayList<>();
+        
+        if (onlyRankingParticipants) {
+            // 只显示参与排名的人员 (nckd_isranking = 1)
+            FilterValue rankingValue = new FilterValue();
+            rankingValue.setValue("1");
+            value.add(rankingValue);
+        } else {
+            // 显示参与和不参与排名的人员 (nckd_isranking in (0,1))
+            FilterValue notRankingValue = new FilterValue();
+            notRankingValue.setValue("0");
+            value.add(notRankingValue);
+            
+            FilterValue rankingValue = new FilterValue();
+            rankingValue.setValue("1");
+            value.add(rankingValue);
+        }
+        
+        filterRowList.add(new SimpleFilterRow("(", CompareTypeEnum.IN.getId(), "nckd_isranking", ")", "", value));
+        //分录过滤
+        entryGrid.getGridDataByDefaultFilterRow(filterRowList);
+    }
+
 }

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

@@ -224,7 +224,7 @@ public class NewDynamicAdjustmentOperationPlugIn extends AbstractOperationServic
         }
 
         createPersonPosFile(person, positionAppointment, adjustDate, jobLevelResult, latsPersonPosFile, allSumScore, personId, frontendJobLevelId, jobLevelId, remark, personIds, newPersonPosFiles,lastYearPerformanceResultMap);
-        setJobLevelResult(person,jobLevelHr);
+        setJobLevelResult(person,jobLevelResult.jobLevel);
     }
 
     private static void createPersonPosFile(DynamicObject person, PositionAppointmentBO positionAppointment, Date adjustDate,
@@ -269,9 +269,7 @@ 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);
-        //档案里面存储转换后的序列
-        DynamicObject newJob = JobLevelCalculatorService.handleJobSeq(jobSeq);
-        jobSeq.set(FormConstant.ID_KEY, newJob.getLong(FormConstant.ID_KEY));
+        jobSeq.set(FormConstant.ID_KEY, jobSeqId);
         newPersonPosFile.set(PositionStructureConstant.NCKD_JOBSEQHR, jobSeq);
         newPersonPosFile.set(PositionStructureConstant.NCKD_POSITIONHR, position);
         newPersonPosFile.set(PositionStructureConstant.NCKD_RANKNAME, jobLevelResult.jobScoreInfo.rankName);

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

@@ -96,7 +96,7 @@ public abstract class BaseInitialOperationPlugIn extends AbstractOperationServic
         int downgradeNum;
         /** 上年度绩效考核结果枚举 */
         AppraisalResultEnum lastYearAppraisalResultEnum;
-        /** 备注 */
+        /** 是否优秀生 */
         boolean isExcellent;
     }
 
@@ -228,10 +228,11 @@ public abstract class BaseInitialOperationPlugIn extends AbstractOperationServic
             //本次加入集团时间
             data.joinComDate = empPosOrgRel.getDate(String.join(".", FormConstant.HRPI_PERSERLEN, FormConstant.JOINCOMDATE_KEY));
         }
-        // TODO 【待修改】优秀生
-        // data.isExcellent = initialData.getBoolean(PositionStructureConstant.NCKD_EXCELLENT);
-
 
+        data.isExcellent = Boolean.FALSE;
+        if(positionAppointment.getExcellent() != null && positionAppointment.getExcellent()){
+            data.isExcellent = Boolean.TRUE;
+        }
         // 特定字段由子类处理
         extractSpecificFields(data, initialData);
         return data;

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

@@ -1,5 +1,6 @@
 package nckd.jxccl.hr.psms.plugin.operate.performance.validate;
 
+import akka.routing.FromConfig;
 import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.dataentity.entity.DynamicObjectCollection;
 import kd.bos.entity.ExtendedDataEntity;
@@ -113,25 +114,38 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
         // 不合格人数
         int failCount = context.failCount;
 
-        // 获取配置比例
+      /*  // 获取配置比例
         BigDecimal excellentRatio = appraisalResultRatioMap.get(AppraisalResultEnum.EXCELLENT.getCode());
         BigDecimal qualifiedRatio = appraisalResultRatioMap.get(AppraisalResultEnum.QUALIFIED.getCode());
         BigDecimal basicallyQualifiedRatio = appraisalResultRatioMap.get(AppraisalResultEnum.BASICALLY_QUALIFIED.getCode());
-        BigDecimal unQualifiedRatio = appraisalResultRatioMap.get(AppraisalResultEnum.UN_QUALIFIED.getCode());
+        BigDecimal unQualifiedRatio = appraisalResultRatioMap.get(AppraisalResultEnum.UN_QUALIFIED.getCode());*/
 
         // 计算各等级的理论人数(四舍五入)
-        int expectedExcellent = calculateExpectedCount(totalRankCount, excellentRatio);
+       /* int expectedExcellent = calculateExpectedCount(totalRankCount, excellentRatio);
         int expectedQualified = calculateExpectedCount(totalRankCount, qualifiedRatio);
         int expectedBasic = calculateExpectedCount(totalRankCount, basicallyQualifiedRatio);
-        int expectedFail = calculateExpectedCount(totalRankCount, unQualifiedRatio);
-
+        int expectedFail = calculateExpectedCount(totalRankCount, unQualifiedRatio);*/
 
+        DynamicObject data = rowDataEntity.getDataEntity();
+        int topRanks = data.getInt(PerfRankMgmtConstant.NCKD_TOPRANKS);
+        int expectedExcellent = data.getInt(PerfRankMgmtConstant.NCKD_EXCELLENTS);
+        int expectedBasic = data.getInt(PerfRankMgmtConstant.NCKD_BASICS);
+        int expectedFail = data.getInt(PerfRankMgmtConstant.NCKD_FAILS);
+        int expectedQualified = topRanks - expectedExcellent - expectedBasic - expectedFail;
+
+
+
+        // 集团本部不校验
+        DynamicObject adminOrg = data.getDynamicObject(FormConstant.NCKD_ADMINORG);
+        DynamicObject secondOrg = adminOrg.getDynamicObject(FormConstant.NCKD_SECONDORG);
+        if(secondOrg == null || !secondOrg.getString(FormConstant.NUMBER_KEY).contains("0101")){
+            // 校验各等级人数是否在合理范围内(允许±1的差异)
+            /*validateCountRange(AppraisalResultEnum.EXCELLENT.getName(), excellentCount, expectedExcellent, totalRankCount,rowDataEntity);
+            validateCountRange(AppraisalResultEnum.QUALIFIED.getName(), qualifiedCount, expectedQualified, totalRankCount,rowDataEntity);
+            validateCountRange(AppraisalResultEnum.BASICALLY_QUALIFIED.getName(), basicCount, expectedBasic, totalRankCount,rowDataEntity);
+            validateCountRange(AppraisalResultEnum.UN_QUALIFIED.getName(), failCount, expectedFail, totalRankCount,rowDataEntity);*/
+        }
 
-        // 校验各等级人数是否在合理范围内(允许±1的差异)
-        validateCountRange(AppraisalResultEnum.EXCELLENT.getName(), excellentCount, expectedExcellent, totalRankCount,rowDataEntity);
-        validateCountRange(AppraisalResultEnum.QUALIFIED.getName(), qualifiedCount, expectedQualified, totalRankCount,rowDataEntity);
-        validateCountRange(AppraisalResultEnum.BASICALLY_QUALIFIED.getName(), basicCount, expectedBasic, totalRankCount,rowDataEntity);
-        validateCountRange(AppraisalResultEnum.UN_QUALIFIED.getName(), failCount, expectedFail, totalRankCount,rowDataEntity);
 
     }
 
@@ -239,11 +253,10 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
         QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                 .addIdNumberName(PerfRankMgmtConstant.NCKD_PERSON);
         DynamicObjectCollection query = QueryServiceHelper.query(PerfRankMgmtConstant.PERFMANAGER_ENTITYID, queryFieldBuilder.buildSelect(), new QFilter[]{filter});
-        Map<Long, DynamicObject> personMap = query.stream()
+        Map<Long, List<DynamicObject>> personMap = query.stream()
                 .filter(obj -> obj.getLong(String.join(".", PerfRankMgmtConstant.NCKD_PERSON, FormConstant.ID_KEY)) > 0)
-                .collect(Collectors.toMap(
-                        obj -> obj.getLong(String.join(".", PerfRankMgmtConstant.NCKD_PERSON, FormConstant.ID_KEY)),
-                        obj -> obj
+                .collect(Collectors.groupingBy(
+                        obj -> obj.getLong(String.join(".", PerfRankMgmtConstant.NCKD_PERSON, FormConstant.ID_KEY))
                 ));
 //        StringJoiner msgJoiner = new StringJoiner(StrFormatter.LINE_SEPARATOR);
         for (DynamicObject entry : entries) {
@@ -366,26 +379,30 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
      */
     private void checkCountConsistency(DynamicObject data, ValidationContext context,
                                        ExtendedDataEntity rowDataEntity) {
-        int topRanks = data.getInt(PerfRankMgmtConstant.NCKD_TOPRANKS);
-        int allowanceRanks = data.getInt(PerfRankMgmtConstant.NCKD_ALLOWANCERANKS);
-        int fails = data.getInt(PerfRankMgmtConstant.NCKD_FAILS);
-        int basics = data.getInt(PerfRankMgmtConstant.NCKD_BASICS);
-        int excellents = data.getInt(PerfRankMgmtConstant.NCKD_EXCELLENTS);
-
-        if (topRanks != context.totalRankCount) {
-            this.addFatalErrorMessage(rowDataEntity, "总排名人数与实际录入数据不一致;\n");
-        }
-        if (allowanceRanks != context.allowanceRankCount) {
-            this.addFatalErrorMessage(rowDataEntity, "R排名人数与实际录入数据不一致;\n");
-        }
-        if (fails != context.failCount) {
-            this.addFatalErrorMessage(rowDataEntity, "不合格人数与实际录入数据不一致;\n");
-        }
-        if (basics != context.basicCount) {
-            this.addFatalErrorMessage(rowDataEntity, "基本人数与实际录入数据不一致;\n");
-        }
-        if (excellents != context.excellentCount) {
-            this.addFatalErrorMessage(rowDataEntity, "优秀人数与实际录入数据不一致;\n");
+        DynamicObject adminOrg = data.getDynamicObject(FormConstant.NCKD_ADMINORG);
+        DynamicObject secondOrg = adminOrg.getDynamicObject(FormConstant.NCKD_SECONDORG);
+        if(secondOrg == null || !secondOrg.getString(FormConstant.NUMBER_KEY).contains("0101")) {
+            int topRanks = data.getInt(PerfRankMgmtConstant.NCKD_TOPRANKS);
+            int allowanceRanks = data.getInt(PerfRankMgmtConstant.NCKD_ALLOWANCERANKS);
+            int fails = data.getInt(PerfRankMgmtConstant.NCKD_FAILS);
+            int basics = data.getInt(PerfRankMgmtConstant.NCKD_BASICS);
+            int excellents = data.getInt(PerfRankMgmtConstant.NCKD_EXCELLENTS);
+
+            if (topRanks != context.totalRankCount) {
+                this.addFatalErrorMessage(rowDataEntity, "总排名人数与实际录入数据不一致;\n");
+            }
+            if (allowanceRanks != context.allowanceRankCount) {
+                this.addFatalErrorMessage(rowDataEntity, "R排名人数与实际录入数据不一致;\n");
+            }
+            if (fails != context.failCount) {
+                this.addFatalErrorMessage(rowDataEntity, "不合格人数与实际录入数据不一致;\n");
+            }
+            if (basics != context.basicCount) {
+                this.addFatalErrorMessage(rowDataEntity, "基本人数与实际录入数据不一致;\n");
+            }
+            if (excellents != context.excellentCount) {
+                this.addFatalErrorMessage(rowDataEntity, "优秀人数与实际录入数据不一致;\n");
+            }
         }
     }
 

+ 13 - 22
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/report/adjust/UnAdjustedReportReportListDataPlugin.java

@@ -63,12 +63,8 @@ public class UnAdjustedReportReportListDataPlugin extends AbstractReportListData
     private QueryFieldBuilder buildQueryFieldBuilder() {
         return QueryFieldBuilder.create()
                 .add(FormConstant.ID_KEY)
-                .addGroup(new String[]{FormConstant.ASSIGNMENT_ENTITYID}, FormConstant.IS_PRIMARY)
                 .addGroup(new String[]{FormConstant.EMPLOYEE_KEY}, FormConstant.EMP_NUMBER_KEY, FormConstant.NAME_KEY)
                 .addGroup(new String[]{PositionStructureConstant.PERSONPOSFILE_ENTITYID},
-                        FormConstant.USEORG_KEY,
-                        FormConstant.ORG_KEY,
-                        FormConstant.CREATEORG_KEY,
                         PositionStructureConstant.NCKD_POSITIONHR,
                         PositionStructureConstant.NCKD_JOBSEQHR,
                         PositionStructureConstant.NCKD_PROTITLELEVEL,
@@ -77,7 +73,9 @@ public class UnAdjustedReportReportListDataPlugin extends AbstractReportListData
                         PositionStructureConstant.NCKD_ALLSUMSCORE,
                         PositionStructureConstant.NCKD_BEGINDATE,
                         PositionStructureConstant.NCKD_JOBLEVELHR,
-                        PositionStructureConstant.NCKD_PERSON)
+                        PositionStructureConstant.NCKD_PERSON,
+                        PositionStructureConstant.NCKD_DEP)
+                .addGroup(new String[]{PositionStructureConstant.PERSONPOSFILE_ENTITYID,PositionStructureConstant.NCKD_DEP},"belongcompany")
                 .addGroup(new String[]{FormConstant.HRPI_PERPROTITLE}, FormConstant.PROLEVEL_KEY)
                 .addGroup(new String[]{FormConstant.HRPI_PEROCPQUAL}, FormConstant.QUALIFICATION_KEY)
                 .addGroup(new String[]{FormConstant.HRPI_PEREDUEXP}, FormConstant.EDUCATION_KEY)
@@ -87,12 +85,13 @@ public class UnAdjustedReportReportListDataPlugin extends AbstractReportListData
                 .addIdNumberName(FormConstant.POSITION_KEY)
                 .addGroup(new String[]{FormConstant.HBPM_POSITIONHR}, PositionStructureConstant.NCKD_JOBSEQ)
                 .addGroup(new String[]{FormConstant.HBPM_POSITIONHR, PositionStructureConstant.NCKD_JOBSEQ}, FormConstant.NUMBER_KEY)
-                .addIdNumberName(FormConstant.ADMINORG,FormConstant.NCKD_FIRSTORG)
-                .addIdNumberName(FormConstant.ADMINORG,FormConstant.NCKD_SECONDORG)
-                .addIdNumberName(FormConstant.ADMINORG,FormConstant.NCKD_THIRDORG)
-                .addIdNumberName(FormConstant.ADMINORG,FormConstant.NCKD_FOURTHORG)
-                .addIdNumberName(FormConstant.ADMINORG,FormConstant.NCKD_FIFTHORG)
-                .addIdNumberName(FormConstant.ADMINORG,FormConstant.NCKD_SIXTHORG);
+                .addGroup(new String[]{FormConstant.ADMINORG},
+                        FormConstant.NCKD_FIRSTORG,
+                        FormConstant.NCKD_SECONDORG,
+                        FormConstant.NCKD_THIRDORG,
+                        FormConstant.NCKD_FOURTHORG,
+                        FormConstant.NCKD_FIFTHORG,
+                        FormConstant.NCKD_SIXTHORG);
 
     }
 
@@ -104,7 +103,7 @@ public class UnAdjustedReportReportListDataPlugin extends AbstractReportListData
                 PositionStructureConstant.NCKD_ISCURRENTNEWEST), QCP.equals, EnableEnum.YES.getCode())
                 .and(new QFilter(String.join(".", PositionStructureConstant.PERSONPOSFILE_ENTITYID,
                         PositionStructureConstant.NCKD_DISABLE), QCP.equals, EnableEnum.NO.getCode()))
-                .and(new QFilter(String.join(".", FormConstant.ASSIGNMENT_ENTITYID, FormConstant.IS_PRIMARY),
+                .and(new QFilter(String.join(".", FormConstant.ASSIGNMENT, FormConstant.IS_PRIMARY),
                         QCP.equals, EnableEnum.YES.getCode()))
                 .and(new QFilter(FormConstant.IS_PRIMARY, QCP.equals, EnableEnum.YES.getCode()))
                 .and(FormConstant.IS_SEQLATESTRECORD, QCP.equals, EnableEnum.YES.getCode())
@@ -188,9 +187,7 @@ public class UnAdjustedReportReportListDataPlugin extends AbstractReportListData
         joinOr.add(String.join(".", PositionStructureConstant.PERSONPOSFILE_ENTITYID, PositionStructureConstant.NCKD_DIPLOMA) + " <> " +
                 String.join(".", FormConstant.HRPI_PEREDUEXP, FormConstant.EDUCATION_KEY));
         //公司变化
-        joinOr.add(String.join(".", PositionStructureConstant.PERSONPOSFILE_ENTITYID, FormConstant.CREATEORG_KEY) + " <> " + FormConstant.COMPANY_KEY);
-        //部门变化
-        joinOr.add(String.join(".", PositionStructureConstant.PERSONPOSFILE_ENTITYID, FormConstant.USEORG_KEY) + " <> " + FormConstant.ADMINORG);
+        joinOr.add(String.join(".", PositionStructureConstant.PERSONPOSFILE_ENTITYID, FormConstant.NCKD_DEP,"belongcompany") + " <> " + FormConstant.COMPANY_KEY);
         //序列变化
         joinOr.add(String.join(".", PositionStructureConstant.PERSONPOSFILE_ENTITYID, PositionStructureConstant.NCKD_JOBSEQHR) + " <> " +
                 String.join(".", FormConstant.HBPM_POSITIONHR, PositionStructureConstant.NCKD_JOBSEQ));
@@ -226,15 +223,10 @@ public class UnAdjustedReportReportListDataPlugin extends AbstractReportListData
                 ") THEN '技能变化' END", "c");
 
         newDataSet = newDataSet.addField("CASE WHEN " +
-                String.join(".", PositionStructureConstant.PERSONPOSFILE_ENTITYID, FormConstant.CREATEORG_KEY) +
+                String.join(".", PositionStructureConstant.PERSONPOSFILE_ENTITYID, FormConstant.NCKD_DEP,"belongcompany") +
                 " <> " + FormConstant.COMPANY_KEY +
                 " THEN '跨单位变动' END", "d");
 
-        newDataSet = newDataSet.addField("CASE WHEN " +
-                String.join(".", PositionStructureConstant.PERSONPOSFILE_ENTITYID, FormConstant.USEORG_KEY) +
-                " <> " + FormConstant.ADMINORG +
-                " THEN '单位内变动' END", "e");
-
         newDataSet = newDataSet.addField("CASE WHEN " +
                 String.join(".", PositionStructureConstant.PERSONPOSFILE_ENTITYID, PositionStructureConstant.NCKD_JOBSEQHR) +
                 " <> " +
@@ -255,7 +247,6 @@ public class UnAdjustedReportReportListDataPlugin extends AbstractReportListData
                 "CASE WHEN b IS NOT NULL AND b != '' THEN CONCAT(b,',') ELSE '' END," +
                 "CASE WHEN c IS NOT NULL AND c != '' THEN CONCAT(c,',') ELSE '' END," +
                 "CASE WHEN d IS NOT NULL AND d != '' THEN CONCAT(d,',') ELSE '' END," +
-                "CASE WHEN e IS NOT NULL AND e != '' THEN CONCAT(e,',') ELSE '' END," +
                 "CASE WHEN f IS NOT NULL AND f != '' THEN CONCAT(f,',') ELSE '' END" +
                 ")";
     }

+ 48 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/task/HRDataCleanTask.java

@@ -0,0 +1,48 @@
+package nckd.jxccl.hr.task;
+
+import kd.bos.context.RequestContext;
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.db.DB;
+import kd.bos.db.DBRoute;
+import kd.bos.exception.KDException;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.schedule.executor.AbstractTask;
+import kd.sdk.plugin.Plugin;
+
+import java.util.Map;
+
+/**
+ * 后台任务插件
+ * @author Turborao
+ * @Date : 2025/12/16 13:05
+ */
+public class HRDataCleanTask extends AbstractTask implements Plugin {
+
+    private static final Log logger = LogFactory.getLog(HRDataCleanTask.class);
+
+    private static final DBRoute QUEUE_DB_ROUTE = new DBRoute("hr");
+
+    @Override
+    public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
+
+        this.clearOpenQueueLog();
+
+    }
+
+
+    public void clearOpenQueueLog() {
+        try {
+            String strLog = ResManager.loadKDString("HRDataCleanTask-消息队列保留时长 - 状态成功", "HRDataClearLog_1", "bos-open-base", new Object[]{0});
+            logger.info(strLog);
+            String sql = "DELETE FROM tv_nckd_employee_12m_avgqty WHERE fyear*100+fmonth in (select fyear*100+fmonth  from v_nckd_12monthly_series)";
+            DB.execute(QUEUE_DB_ROUTE, sql);
+            String str = ResManager.loadKDString("HRDataCleanTask-队列清理任务执行成功。", "HRDataClearLog_2", "bos-open-base", new Object[0]);
+            logger.info(str);
+        } catch (Exception e) {
+            String str = ResManager.loadKDString("HRDataCleanTask-队列清理定时任务执行失败:%s。", "HRDataClearLog_3", "bos-open-base", new Object[]{e.getMessage()});
+            logger.error(str, e);
+            throw e;
+        }
+    }
+}

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

@@ -28,6 +28,7 @@ import nckd.jxccl.base.common.utils.ConvertUtil;
 import nckd.jxccl.base.common.utils.DateUtil;
 import nckd.jxccl.base.common.utils.QueryFieldBuilder;
 import nckd.jxccl.base.common.utils.StrFormatter;
+import nckd.jxccl.base.hrpi.helper.EmpPosOrgRelHelper;
 import nckd.jxccl.opmc.pm.common.PerfManagerFormConstant;
 import nckd.jxccl.opmc.pm.helper.PerfManagerHelper;
 import org.apache.commons.lang3.StringUtils;
@@ -503,10 +504,13 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
         Boolean isCycleGenerate = ConvertUtil.toBoolean(this.getOption().getVariableValue("cyclegenerate",StringUtils.EMPTY),Boolean.FALSE);
         Boolean isUpdate = ConvertUtil.toBoolean(this.getOption().getVariableValue("isUpdate",StringUtils.EMPTY),Boolean.FALSE);
         List<DynamicObject> updatePerManager = new ArrayList<>();
+
+
         for (DynamicObject dataEntity : e.getDataEntities()) {
             long id = dataEntity.getLong(FormConstant.ID_KEY);
             DynamicObject person = dataEntity.getDynamicObject(FormConstant.NCKD_PERSON);
-            person = person == null ? dataEntity.getDynamicObject(FormConstant.NCKD_EMPPOSORGREL).getDynamicObject(FormConstant.EMPLOYEE_KEY) : person;
+            DynamicObject empPosOrgRel = dataEntity.getDynamicObject(FormConstant.NCKD_EMPPOSORGREL);
+            person = person == null ? empPosOrgRel.getDynamicObject(FormConstant.EMPLOYEE_KEY) : person;
             dataEntity.set(FormConstant.NCKD_PERSON, person);
             LocalDateTime beginYear = DateUtil.toLocalDateTime(dataEntity.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR));
             LocalDateTime endYear = DateUtil.toLocalDateTime(dataEntity.getDate(PerfManagerFormConstant.NCKD_ENDYEAR));
@@ -521,6 +525,24 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
             if(StringUtils.isBlank(name)){
                 dataEntity.set(FormConstant.NAME_KEY, StrFormatter.format("【{}】{}~{}的考核周期",personName,beginYear.getYear(),endYear.getYear()));
             }
+            DynamicObject dep = dataEntity.getDynamicObject(FormConstant.NCKD_DEP);
+            if(dep == null){
+                dataEntity.set(FormConstant.NCKD_DEP, empPosOrgRel.getDynamicObject(FormConstant.ADMINORG));
+            }
+
+            long depId = dataEntity.getLong(String.join(".", FormConstant.NCKD_DEP, FormConstant.ID_KEY));
+            if(depId <= 0){
+                dataEntity.set(FormConstant.NCKD_DEP, empPosOrgRel.getDynamicObject(FormConstant.ADMINORG));
+            }
+            if(dataEntity.containsProperty(FormConstant.CREATEORG_KEY)){
+                dataEntity.set(FormConstant.CREATEORG_KEY, null);
+            }
+            if(dataEntity.containsProperty(FormConstant.USEORG_KEY)){
+                dataEntity.set(FormConstant.USEORG_KEY, null);
+            }
+            if(dataEntity.containsProperty(FormConstant.ORG_KEY)){
+                dataEntity.set(FormConstant.ORG_KEY, null);
+            }
 
 
             /*DynamicObject lastPerfManager = lastPerfManagerMap.get(personId);

+ 3 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/business/annualincome/AnnualIncomeCalculateService.java

@@ -8,6 +8,7 @@ import kd.bos.form.IFormView;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
 import kd.bos.servicehelper.operation.SaveServiceHelper;
+import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
 import nckd.jxccl.sit.hcsi.common.constant.SitConstant;
 
 import java.math.BigDecimal;
@@ -170,6 +171,8 @@ public class AnnualIncomeCalculateService {
 
     public Map<Long, DynamicObject> getSinSurFile() {
         QFilter filter = new QFilter("welfarepayer.id", QCP.equals, welfarePayer.getLong("id"));
+        filter.and(QFilterCommonHelper.getCurrentVersionFilter());
+        filter.and(QFilterCommonHelper.getDataStatusFilter());
         DynamicObjectCollection cols = SitConstant.SINSURFILE_HELPER.queryOriginalCollection("id,employee.id,org.id", new QFilter[]{filter});
         return cols.stream().collect(Collectors.toMap((dyx) -> {
             return dyx.getLong("employee.id");

+ 183 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/business/coordination/SinsurCoordSplitService.java

@@ -0,0 +1,183 @@
+package nckd.jxccl.sit.hcsi.business.coordination;
+
+
+import com.kingdee.bos.framework.core.exception.BizException;
+import kd.bos.dataentity.OperateOption;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.exception.KDBizException;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.org.utils.DynamicObjectUtils;
+import kd.bos.servicehelper.operation.OperationServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import nckd.jxccl.sit.hcsi.common.constant.SitConstant;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Tyx 2025-12-15
+ * 社保变动单拆单帮助类
+ */
+public class SinsurCoordSplitService {
+
+    private static final Log logger = LogFactory.getLog(SinsurCoordSplitService.class);
+    Long billId;
+    DynamicObject bill;
+
+    public SinsurCoordSplitService(Long billId, DynamicObject bill) {
+        this.billId = billId;
+        this.bill = bill;
+    }
+
+    /**
+     * <p> 执行拆单
+     * <p> 根据参保单位判断:
+     * <p> 1.单头和分录参保单位的交集部分 直接调用标品的提交生效
+     * <p> 2.单头和分录参保单位的差集部分 生成新的核定单
+     */
+    public void doSplit () {
+        // DynamicObject bill = SitConstant.COORDVERIFYBILL_HELPER.loadOne(billId);
+        // 单头参保单位
+        Long welfArePayerId = bill.getLong("welfarepayer_r31.id");
+        // 分录
+        DynamicObjectCollection entryCols = bill.getDynamicObjectCollection("nckd_entryentity");
+        // 根据参保单位分组
+        Map<Long, List<DynamicObject>> welfGroupMap = entryCols.stream()
+                .filter(obj -> obj.getLong("nckd_welfarepayer.id") != welfArePayerId)
+                .collect(Collectors.groupingBy(obj -> obj.getLong("nckd_welfarepayer.id")));
+        doCopy(bill, welfGroupMap);
+    }
+
+    /**
+     * 复制单据
+     */
+    public void doCopy(DynamicObject bill, Map<Long, List<DynamicObject>> welfGroupMap) {
+        DynamicObjectCollection newBillCol = new DynamicObjectCollection();
+        for (Long welfId : welfGroupMap.keySet()) {
+            List<DynamicObject> entryList = welfGroupMap.get(welfId);
+            DynamicObject newBill = SitConstant.COORDVERIFYBILL_HELPER.generateEmptyDynamicObject(SitConstant.COORDVERIFYBILL_HELPER.getEntityName());
+            // 忽略字段
+            Set<String> ignoreFields = getIgnoreFields();
+            // 复制
+            DynamicObjectUtils.copy(bill, newBill, ignoreFields);
+            // 复制后处理相关字段
+            newBill.set("dealresult", "0");
+            newBill.set("nckd_issplit", true);
+            newBill.set("sinsurstd_r31", null);
+            newBill.set("nckd_sourcebillid", bill.getLong("id"));
+            // 处理分录数据
+            DynamicObjectCollection entryCols = newBill.getDynamicObjectCollection("nckd_entryentity");
+            entryCols.clear();
+            for (DynamicObject oldEntry : entryList) {
+                DynamicObject newEntry = entryCols.addNew();
+                DynamicObjectUtils.copy(oldEntry, newEntry);
+                newBill.set("welfarepayer_r31", oldEntry.getDynamicObject("nckd_welfarepayer"));
+                newBill.set("welfarepayertheory_r31", oldEntry.getDynamicObject("nckd_welfarepayertheory"));
+            }
+            newBillCol.add(newBill);
+        }
+        if(newBillCol.size() > 0) {
+            // 直接保存 不走校验 需要把参保标准清除掉 但是参保标准是必填字段
+            SitConstant.COORDVERIFYBILL_HELPER.save(newBillCol);
+//            OperationResult result = SaveServiceHelper.saveOperate(SitConstant.COORDVERIFYBILL_HELPER.getEntityName(), newBillCol.stream().toArray(DynamicObject[]::new), OperateOption.create());
+//            if(!result.isSuccess()) {
+//                throw new KDBizException(result.getMessage());
+//            }
+        }
+        // 判断下当前单据是否有需要生效的数据
+        Long welfArePayerId = bill.getLong("welfarepayer_r31.id");
+        DynamicObjectCollection entryCols = bill.getDynamicObjectCollection("nckd_entryentity");
+        List<DynamicObject> welfGroupCurList = entryCols.stream()
+                .filter(obj -> obj.getLong("nckd_welfarepayer.id") == welfArePayerId)
+                .collect(Collectors.toList());
+        // 如果分录中有跟表头参保单位一样的数据 则调用标品的提交生效
+        if(welfGroupCurList.size() > 0) {
+            doSubmitEffect(bill);
+        }
+        // 否则直接反写源单成无需处理
+        else {
+            writeBackSourceBill(bill);
+        }
+    }
+
+    /**
+     * 复制单据时排除的字段
+     * @return
+     */
+    private Set<String> getIgnoreFields() {
+        Set<String> ignoreFields = new HashSet<String>();
+        ignoreFields.add("dealresult");
+        ignoreFields.add("failmsg");
+        ignoreFields.add("sinsurstd_r31");
+        return ignoreFields;
+    }
+
+
+    /**
+     * 调用标品的确认生效
+     *
+     * @param bill
+     * @return
+     */
+    public void doSubmitEffect (DynamicObject bill) {
+        if("0".equals(bill.getString("dealresult")) ) {
+            OperateOption option = OperateOption.create();
+            OperationResult result = OperationServiceHelper.executeOperate("confirmeffect", "hpdi_empcoordverifbill3", new DynamicObject[]{bill}, option);
+            if (!result.isSuccess()) {
+                String errorMessage = result.getAllErrorInfo().stream()
+                        .map(dyx -> dyx.getMessage())
+                        .collect(Collectors.joining(", "));
+                throw new KDBizException(errorMessage);
+            }
+        }
+    }
+
+    /**
+     * 反写源单, 把源单设置成无需处理
+     * @param bill
+     */
+    public void writeBackSourceBill (DynamicObject bill) {
+        bill.set("dealresult", "9");
+    }
+
+    /**
+     * 判断是否需要拆单
+     * @return
+     */
+    public boolean isNeedSplit () {
+        boolean isNeedSplit = true;
+        // DynamicObject bill = getCoordVerifyBillDyn();
+        // 拆分单据直接返回true
+        if(bill.getBoolean("nckd_issplit")) {
+            return false;
+        }
+        // 获取到变动大类
+        DynamicObject ruleParam = bill.getDynamicObject("coordruleparam");
+        String chgNumber = ruleParam.getString("chgevent_z.number");
+        // 非调动的情况下不需要拆单
+        if(!chgNumber.equals("1020_S")) {
+            return false;
+        }
+        // 获取到流动类型
+        String flowType = ruleParam.getString("flowtype_y");
+        // 非流入的情况下不需要拆单
+        if(!flowType.equals("1")) {
+            return false;
+        }
+        return isNeedSplit;
+    }
+
+    /**
+     * 获取社保员工变动处理单数据包
+     * @return
+     */
+    public DynamicObject getCoordVerifyBillDyn () {
+        return SitConstant.COORDVERIFYBILL_HELPER.loadOne(billId);
+    }
+}

+ 23 - 23
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/business/coordination/api/SinsurCoordBizSaveHandler.java

@@ -16,10 +16,8 @@ import kd.hr.hbp.business.coordination.model.CoordBizContext;
 import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
 import nckd.jxccl.sit.hcsi.business.importtaskguide.ImportTaskGuideImportService;
 
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * Tyx 2025-10-28
@@ -64,40 +62,42 @@ public class SinsurCoordBizSaveHandler implements CoordBizSaveHandler {
             Long fileId = sinsurFile.getLong("id");
             // 获取核定单分录数据
             DynamicObjectCollection entryCols = dynamicObject.getDynamicObjectCollection("nckd_entryentity");
-            for (DynamicObject entry : entryCols) {
+
+            // 只处理分录数据中实际参保单位与单头一致的数据
+            Long welfarePayerId = dynamicObject.getLong("welfarepayer_r31.id");
+            List<DynamicObject> list = entryCols.stream().filter(entry -> entry.getLong("nckd_welfarepayer.id") == welfarePayerId).collect(Collectors.toList());
+            for (DynamicObject entry : list) {
                 // 新建数据包
                 DynamicObject dyn = BusinessDataServiceHelper.newDynamicObject(SIBASE_ENTITY);
-                // 设置字段,单独处理下档案,计薪人员,参保单位,其余字段从fieldMap从处理;
+                // 设置字段,单独处理下档案,计薪人员,实际参保单位,理论参保单位】其余字段从fieldMap从处理;
                 dyn.set("sinsurfile", sinsurFile);
                 dyn.set("employee", sinsurFile.getDynamicObject("employee"));
                 dyn.set("welfarepayer", sinsurFile.getDynamicObject("welfarepayer"));
+                dyn.set("nckd_welfarepayertheory", sinsurFile.getDynamicObject("welfarepayertheory"));
                 dyn.set("id", Uuid.create());
                 Iterator it = fieldMap.keySet().iterator();
-                while(it.hasNext()) {
+                while (it.hasNext()) {
                     String key = it.next().toString();
                     dyn.set(fieldMap.get(key), entry.get(key));
                 }
                 sibaseCols.add(dyn);
             }
-            OperationResult result = SaveServiceHelper.saveOperate(SIBASE_ENTITY, sibaseCols.stream().toArray(DynamicObject[]::new), OperateOption.create());
-            // 标品SinSurFileCoordServiceHelper.saveBizObject方法中,判断success写反了,这里暂时反着写,后续等标品调整
-            // TODO
-            if(result.isSuccess()) {
-                returnMap.put("success",false);
+            if (sibaseCols.size() > 0) {
+                OperationResult result = SaveServiceHelper.saveOperate(SIBASE_ENTITY, sibaseCols.stream().toArray(DynamicObject[]::new), OperateOption.create());
+                // 标品SinSurFileCoordServiceHelper.saveBizObject方法中,判断success写反了,这里暂时反着写,后续等标品调整
+                // TODO
+                if (result.isSuccess()) {
+                    returnMap.put("success", false);
+                } else {
+                    throw new KDBizException("-------- 险种基数保存失败:" + result.getMessage());
+                    //returnMap.put("success",true);
+                    //returnMap.put("msg", result.getMessage());
+                }
+                log.info("-------- bizSaveHandler result = " + result + " --------");
             }
             else {
-                throw new KDBizException("-------- 险种基数保存失败:" + result.getMessage());
-                //returnMap.put("success",true);
-                //returnMap.put("msg", result.getMessage());
+                returnMap.put("success", false);
             }
-//            if(result.isSuccess()) {
-//                returnMap.put("success",true);
-//            }
-//            else {
-//                returnMap.put("success",false);
-//                returnMap.put("msg", result.getMessage());
-//            }
-            log.info("-------- bizSaveHandler result = " + result + " --------");
         }
         return returnMap;
     }

+ 111 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/business/file/attach/AdjustSIBaseService.java

@@ -0,0 +1,111 @@
+package nckd.jxccl.sit.hcsi.business.file.attach;
+
+import kd.bos.algo.DataSet;
+import kd.bos.algo.JoinType;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
+import nckd.jxccl.sit.hcsi.common.constant.SitConstant;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class AdjustSIBaseService {
+
+    private static final Log logger = LogFactory.getLog(AdjustSIBaseService.class);
+    DynamicObject welfarePayer;
+    Date year;
+
+    public AdjustSIBaseService(DynamicObject welfarePayer, Date year) {
+        this.welfarePayer = welfarePayer;
+        this.year = year;
+    }
+
+    /**
+     * <p>执行查询方法
+     * <p>1.查询参保单位下所有员工
+     * <p>2.查询员工现在各险种的基数
+     * <p>3.查询员工的年收入证明统计单, 时间 = year, 单据状态 = 已确认
+     *
+     * @return
+     */
+    public DataSet query() {
+        // 查询社保档案 keySet为employee.id
+        Map<Long, DynamicObject> sinsurFileMap = querySinsurFileDyns();
+        List<Long> employeeIds = sinsurFileMap.keySet().stream().collect(Collectors.toList());
+        // 根据employeeIds 查询员工现在各险种的基数
+        DataSet SIBaseDs = querySIBaseDyns(employeeIds);
+        // 查询员工的年收入证明统计单, 时间 = year, 单据状态 = 已确认
+        DataSet incomeBillDs = queryIncomeBillDyns(employeeIds);
+        // 根据employeeIds处理数据
+        return dealData(sinsurFileMap, SIBaseDs, incomeBillDs);
+    }
+
+
+    /**
+     * 处理数据
+     *
+     * @param sinsurFileMap
+     * @param SIBaseDs
+     * @param incomeBillDs
+     * @return
+     */
+    public DataSet dealData(Map<Long, DynamicObject> sinsurFileMap, DataSet SIBaseDs, DataSet incomeBillDs) {
+        String[] leftFields = new String[]{"nckd_employee.id as employeeId", "nckd_totalamount as totalamount"};
+        String[] rightFields = new String[]{"sinsurfile.id as sinsurfileId", "welfaretype.id as welfaretypeId", "paybaseofemployee", "paybaseofcompany", "nckd_sinsurdimension.id as sinsurdimensionId"};
+        return incomeBillDs.join(SIBaseDs, JoinType.INNER).on("nckd_employee.id", "employee.id").select(leftFields, rightFields).finish();
+    }
+
+
+
+    /**
+     * 查询社保档案
+     * @return
+     */
+    public Map<Long, DynamicObject> querySinsurFileDyns() {
+        QFilter filter = new QFilter("welfarepayer.id", QCP.equals, welfarePayer.getLong("id"));
+        filter.and(QFilterCommonHelper.getCurrentVersionFilter());
+        filter.and(QFilterCommonHelper.getDataStatusFilter());
+        DynamicObjectCollection cols = SitConstant.SINSURFILE_HELPER.queryOriginalCollection("id,employee.id,org.id", new QFilter[]{filter});
+        return cols.stream().collect(Collectors.toMap((dyx) -> {
+            return dyx.getLong("employee.id");
+        }, (dyx) -> {
+            return dyx;
+        }, (key1, key2) -> {
+            return key2;
+        }));
+    }
+
+    /**
+     * 查询员工现在各险种的基数
+     *
+     * @param employeeIds
+     * @return
+     */
+    public DataSet querySIBaseDyns(List<Long> employeeIds) {
+        QFilter filter = new QFilter("employee.id", QCP.in, employeeIds);
+        filter.and("iscurrentdata", QCP.equals, "1");
+        filter.and("insured", QCP.equals, true);
+        String selectFields = "sinsurfile.id, employee.id, welfaretype.id, paybaseofemployee, paybaseofcompany, nckd_sinsurdimension.id";
+        return SitConstant.SIBASE_HELPER.queryDataSet("AdjustSIBaseService-querySIBase",selectFields, new QFilter[]{filter});
+    }
+
+    /**
+     * 根据employeeIds+年度查询员工年收入证明统计单数据
+     *
+     * @param employeeIds
+     * @return
+     */
+    private DataSet queryIncomeBillDyns(List<Long> employeeIds) {
+        QFilter filter = new QFilter("nckd_employee.id", QCP.in, employeeIds);
+        filter.and("nckd_year", QCP.equals, year);
+        filter.and("billstatus", QCP.in, new HashSet<>(Arrays.asList("C", "H")));
+        String selectFields = "nckd_employee.id, nckd_totalamount";
+        return SitConstant.SITINCOMEBILL_HELPER.queryDataSet("AdjustSIBaseService-queryIncomeBill", selectFields, new QFilter[]{filter});
+    }
+
+}

+ 4 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/common/constant/SitConstant.java

@@ -8,6 +8,8 @@ import java.util.Map;
 public class SitConstant {
     /*社保档案*/
     public static final HRBaseServiceHelper SINSURFILE_HELPER = new HRBaseServiceHelper("hcsi_sinsurfile");
+    /*险种基数设置*/
+    public static final HRBaseServiceHelper SIBASE_HELPER = new HRBaseServiceHelper("hcsi_sibase");
     /*业务项目*/
     public static final HRBaseServiceHelper BIZITEM_HELPER = new HRBaseServiceHelper("hsbs_bizitem");
     /* 社保核算任务-明细人员 */
@@ -32,6 +34,8 @@ public class SitConstant {
     public static final HRBaseServiceHelper SINSURSTD_HELPER = new HRBaseServiceHelper("sitbs_sinsurstd");
     /* 参保标准维度结果 */
     public static final HRBaseServiceHelper STDDIMRS_HELPER = new HRBaseServiceHelper("sitbs_stddimrs");
+    /* 社保员工变动处理单 */
+    public static final HRBaseServiceHelper COORDVERIFYBILL_HELPER = new HRBaseServiceHelper("hpdi_empcoordverifbill3");
 
     public static final Long PAY_BASE_OF_EMPLOYEE_ID = 1010L;
     public static final String PAY_BASE_OF_EMPLOYEE_KEY = "nckd_paybaseofemployee";

+ 23 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/coordination/SinSurEmpChgCoordBatchEditPluginEx.java

@@ -1,5 +1,6 @@
 package nckd.jxccl.sit.hcsi.formplugin.web.coordination;
 
+import kd.bos.dataentity.OperateOption;
 import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.dataentity.entity.DynamicObjectCollection;
 import kd.bos.dataentity.serialization.SerializationUtils;
@@ -7,6 +8,7 @@ import kd.bos.dataentity.utils.ObjectUtils;
 import kd.bos.entity.EntityMetadataCache;
 import kd.bos.entity.datamodel.IDataModel;
 import kd.bos.entity.datamodel.events.PropertyChangedArgs;
+import kd.bos.entity.operate.result.OperationResult;
 import kd.bos.form.control.EntryGrid;
 import kd.bos.form.events.AfterDoOperationEventArgs;
 import kd.bos.form.events.BeforeDoOperationEventArgs;
@@ -19,6 +21,7 @@ import kd.bos.form.plugin.AbstractFormPlugin;
 import kd.bos.org.utils.DynamicObjectUtils;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.operation.OperationServiceHelper;
 import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
 import kd.hr.hbp.common.util.HRStringUtils;
 import kd.sdk.plugin.Plugin;
@@ -217,6 +220,10 @@ public class SinSurEmpChgCoordBatchEditPluginEx extends AbstractFormPlugin imple
                 this.getView().showTipNotification("请先维护险种基数!");
             }
         }
+        else if(HRStringUtils.equals(operateKey, "donothing_split")) {
+
+        }
+
 
     }
 
@@ -231,6 +238,20 @@ public class SinSurEmpChgCoordBatchEditPluginEx extends AbstractFormPlugin imple
         else if(HRStringUtils.equals(operateKey, "batchsetting")){
             doBatchSetting();
         }
+        else if(HRStringUtils.equals(operateKey, "donothing_split")) {
+            doSplit();
+        }
+    }
+
+    /**
+     * 拆分
+     */
+    private void doSplit() {
+        List<Long> selectIds = this.getSelectIds();
+        List<String> queryFields = this.getQueryFields();
+        HRBaseServiceHelper helper = new HRBaseServiceHelper(this.getEntityNumber());
+        DynamicObject[] billCols = helper.load(String.join(",", queryFields), new QFilter[]{new QFilter("id", "in", this.getSelectIds())});
+        OperationResult result = OperationServiceHelper.executeOperate("donothing_split", this.getEntityNumber(), billCols, OperateOption.create());
     }
 
     /**
@@ -344,6 +365,8 @@ public class SinSurEmpChgCoordBatchEditPluginEx extends AbstractFormPlugin imple
         queryFields.remove("adminorg");
         queryFields.remove("position");
         queryFields.addAll(defaultQueryFields);
+        queryFields.add("nckd_issplit");
+        queryFields.add("nckd_sourcebillid");
         Set<String> fields = this.getEntryFields();
         queryFields.addAll(fields.stream().map(field -> "nckd_entryentity." + field).collect(Collectors.toList()));
         return new ArrayList(queryFields);

+ 181 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/file/attach/AdjustSIBaseFormPlugin.java

@@ -0,0 +1,181 @@
+package nckd.jxccl.sit.hcsi.formplugin.web.file.attach;
+
+import com.kingdee.util.Uuid;
+import kd.bos.algo.DataSet;
+import kd.bos.algo.Row;
+import kd.bos.dataentity.OperateOption;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.utils.ObjectUtils;
+import kd.bos.entity.datamodel.AbstractFormDataModel;
+import kd.bos.entity.datamodel.IDataModel;
+import kd.bos.entity.datamodel.TableValueSetter;
+import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.events.BeforeDoOperationEventArgs;
+import kd.bos.form.operate.FormOperate;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.sit.hcsi.business.file.attach.AdjustSIBaseService;
+import nckd.jxccl.sit.hcsi.common.constant.SitConstant;
+
+import java.util.*;
+
+/**
+ * 动态表单插件
+ */
+public class AdjustSIBaseFormPlugin extends AbstractFormPlugin implements Plugin {
+
+    private static Map<String, String> fieldMap = new HashMap<String, String>();
+    static {
+        fieldMap.put("nckd_welfaretype","welfaretype");
+        fieldMap.put("nckd_paybaseofemployee","paybaseofemployee");
+        fieldMap.put("nckd_paybaseofcompany","paybaseofcompany");
+        fieldMap.put("nckd_startdate","startdate");
+        fieldMap.put("nckd_enddate","enddate");
+        fieldMap.put("nckd_description","description");
+        fieldMap.put("nckd_sinsurdimension","nckd_sinsurdimension");
+    }
+
+    @Override
+    public void registerListener(EventObject e) {
+        super.registerListener(e);
+    }
+
+    @Override
+    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
+        super.beforeDoOperation(args);
+        FormOperate formOperate = (FormOperate)args.getSource();
+        String opKey = formOperate.getOperateKey();
+        switch (opKey) {
+            case "donothing_query":
+                queryVerify(args);
+                break;
+            case "donothing_adjust":
+                adjustVerify(args);
+                break;
+        }
+    }
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
+        super.afterDoOperation(afterDoOperationEventArgs);
+        String opKey = afterDoOperationEventArgs.getOperateKey();
+        switch(opKey) {
+            case "donothing_query":
+                doQuery();
+                break;
+            case "donothing_adjust":
+                if(afterDoOperationEventArgs.getOperationResult().isSuccess()) {
+                    doAdjust();
+                }
+        }
+    }
+
+    /**
+     * 执行查询方法
+     */
+    public void doQuery() {
+        IDataModel model = this.getModel();
+        DynamicObject dyn = model.getDataEntity(true);
+        DynamicObject welfarePayer = dyn.getDynamicObject("nckd_welfarepayer");
+        Date year = dyn.getDate("nckd_year");
+        // 删除分录
+        this.getModel().deleteEntryData("nckd_entryentity");
+
+        AdjustSIBaseService service = new AdjustSIBaseService(welfarePayer, year);
+        DataSet dataSet = service.query();
+        handleData(dataSet);
+    }
+
+    public void handleData(DataSet dataSet) {
+        TableValueSetter setter = new TableValueSetter();
+        int rowIndex = 0;
+        AbstractFormDataModel model = (AbstractFormDataModel) this.getModel();
+        while(dataSet.hasNext()) {
+            Row rowData = dataSet.next();
+            setter.set("nckd_sinsurfile", rowData.getLong("sinsurfileId"), rowIndex);
+            setter.set("nckd_employee", rowData.getLong("employeeId"), rowIndex);
+            setter.set("nckd_welfaretype", rowData.getLong("welfaretypeId"), rowIndex);
+            setter.set("nckd_yearamount", rowData.getBigDecimal("totalamount"), rowIndex);
+            setter.set("nckd_paybaseofemployee", rowData.getBigDecimal("paybaseofemployee"), rowIndex);
+            setter.set("nckd_paybaseofcompany", rowData.getBigDecimal("paybaseofcompany"), rowIndex);
+            setter.set("nckd_sinsurdimension", rowData.getLong("sinsurdimensionId"), rowIndex);
+            rowIndex++;
+        }
+        model.beginInit();
+        model.batchCreateNewEntryRow("nckd_entryentity", setter);
+        model.endInit();
+        this.getView().updateView("nckd_entryentity");
+    }
+
+    /**
+     * 执行调整方法
+     */
+    public void doAdjust() {
+        IDataModel model = this.getModel();
+        DynamicObject dyn = model.getDataEntity(true);
+        DynamicObjectCollection entryCols = dyn.getDynamicObjectCollection("nckd_entryentity");
+        if(entryCols.size() > 0) {
+            DynamicObjectCollection sibaseCols = new DynamicObjectCollection();
+            for(DynamicObject entry : entryCols) {
+                DynamicObject bill = BusinessDataServiceHelper.newDynamicObject(SitConstant.SIBASE_HELPER.getEntityName());
+                bill.set("welfarepayer", dyn.getDynamicObject("nckd_welfarepayer"));
+                bill.set("welfaretype", entry.getDynamicObject("nckd_welfaretype"));
+                bill.set("sinsurfile", entry.getDynamicObject("nckd_sinsurfile"));
+                bill.set("employee", entry.getDynamicObject("nckd_employee"));
+                bill.set("insured", true);
+                bill.set("startdate", entry.getDate("nckd_effectdate"));
+                bill.set("enddate", entry.getDate("nckd_effectdate"));
+                bill.set("nckd_sinsurdimension", entry.getDynamicObject("nckd_sinsurdimension"));
+                bill.set("paybaseofemployee", entry.getBigDecimal("nckd_yearamount"));
+                bill.set("paybaseofcompany", entry.getBigDecimal("nckd_yearamount"));
+                bill.set("id", Uuid.create());
+                sibaseCols.add(bill);
+            }
+            OperationResult result = SaveServiceHelper.saveOperate(SitConstant.SIBASE_HELPER.getEntityName(), sibaseCols.stream().toArray(DynamicObject[]::new), OperateOption.create());
+            if(result.isSuccess()) {
+                this.getView().showTipNotification("调整成功!",3000);
+            }
+            else {
+                this.getView().showMessage("调整出错:" + result.getMessage());
+            }
+        }
+    }
+
+    /**
+     * 查询前校验
+     * @param args
+     */
+    public void queryVerify(BeforeDoOperationEventArgs args) {
+        IDataModel model = this.getModel();
+        Object welfarepayer = model.getValue("nckd_welfarepayer");
+        Object year = model.getValue("nckd_year");
+        if(ObjectUtils.isEmpty(welfarepayer)) {
+            this.getView().showTipNotification("请选择参保单位!",3000);
+            args.setCancel(true);
+        }
+        if(ObjectUtils.isEmpty(year)) {
+            this.getView().showTipNotification("请选择收入年度!", 3000);
+            args.setCancel(true);
+        }
+    }
+
+    /**
+     * 调整前校验
+     * @param args
+     */
+    public void adjustVerify(BeforeDoOperationEventArgs args) {
+        IDataModel model = this.getModel();
+        int rowCount = model.getEntryRowCount("nckd_entryentity");
+        if(rowCount == 0) {
+            this.getView().showTipNotification("不存在调整的数据",3000);
+            args.setCancel(true);
+        }
+    }
+
+
+
+}

+ 56 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/formplugin/web/file/attach/SIBaseListEx.java

@@ -0,0 +1,56 @@
+package nckd.jxccl.sit.hcsi.formplugin.web.file.attach;
+
+import kd.bos.form.CloseCallBack;
+import kd.bos.form.FormShowParameter;
+import kd.bos.form.ShowType;
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.events.BeforeDoOperationEventArgs;
+import kd.bos.form.events.ClosedCallBackEvent;
+import kd.bos.form.operate.FormOperate;
+import kd.bos.list.plugin.AbstractListPlugin;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.sdk.plugin.Plugin;
+
+/**
+ * 标准单据列表插件
+ */
+public class SIBaseListEx extends AbstractListPlugin implements Plugin {
+
+    private static final Log logger = LogFactory.getLog(SIBaseListEx.class);
+
+    @Override
+    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
+        super.beforeDoOperation(args);
+        FormOperate formOperate = (FormOperate)args.getSource();
+        String opKey = formOperate.getOperateKey();
+        switch (opKey) {
+            case "donothing_adjust":
+                this.opeanAdjustPage();
+                break;
+        }
+    }
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
+        super.afterDoOperation(afterDoOperationEventArgs);
+    }
+
+    private void opeanAdjustPage() {
+        FormShowParameter formShowParameter = new FormShowParameter();
+        formShowParameter.setShowTitle(true);
+        formShowParameter.setFormId("nckd_adjustsibase");
+        formShowParameter.getOpenStyle().setShowType(ShowType.Modal);
+        formShowParameter.setCloseCallBack(new CloseCallBack(this, "adjustSIBase"));
+        this.getView().showForm(formShowParameter);
+    }
+
+    @Override
+    public void closedCallBack(ClosedCallBackEvent closedCallBackEvent) {
+        super.closedCallBack(closedCallBackEvent);
+        String actionId = closedCallBackEvent.getActionId();
+        if ("adjustSIBase".equals(actionId)) {
+
+        }
+    }
+}

+ 66 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/opplugin/web/coordination/SinsurEmpCoordSplitOp.java

@@ -0,0 +1,66 @@
+package nckd.jxccl.sit.hcsi.opplugin.web.coordination;
+
+import kd.bos.dataentity.OperateOption;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.PreparePropertysEventArgs;
+import kd.bos.entity.plugin.args.AfterOperationArgs;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.entity.plugin.args.EndOperationTransactionArgs;
+import kd.bos.exception.KDBizException;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.servicehelper.operation.OperationServiceHelper;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.sit.hcsi.business.coordination.SinsurCoordSplitService;
+
+import java.util.stream.Collectors;
+
+/**
+ * 单据操作插件
+ */
+public class SinsurEmpCoordSplitOp extends AbstractOperationServicePlugIn implements Plugin {
+
+    private static final Log logger = LogFactory.getLog(SinsurEmpCoordSplitOp.class);
+
+    @Override
+    public void onPreparePropertys(PreparePropertysEventArgs e) {
+        super.onPreparePropertys(e);
+        e.getFieldKeys().addAll(this.billEntityType.getAllFields().keySet());
+    }
+
+    @Override
+    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+        super.beginOperationTransaction(e);
+    }
+
+    @Override
+    public void endOperationTransaction(EndOperationTransactionArgs e) {
+        super.endOperationTransaction(e);
+    }
+
+    @Override
+    public void afterExecuteOperationTransaction(AfterOperationArgs e) {
+        super.afterExecuteOperationTransaction(e);
+        DynamicObject[] bills = e.getDataEntities();
+        for(DynamicObject bill : bills) {
+            SinsurCoordSplitService service = new SinsurCoordSplitService(bill.getLong("id"), bill);
+            if(service.isNeedSplit()) {
+                service.doSplit();
+            }
+            else {
+                OperateOption option = OperateOption.create();
+                OperationResult result = OperationServiceHelper.executeOperate("confirmeffect", "hpdi_empcoordverifbill3", new DynamicObject[]{bill}, option);
+                logger.info("标品提交生效结果:" + result.isSuccess());
+                if (!result.isSuccess()) {
+                    String errorMessage = result.getAllErrorInfo().stream()
+                            .map(dyx -> dyx.getMessage())
+                            .collect(Collectors.joining(", "));
+                    logger.info("标品提交生效错误:" + errorMessage);
+                    throw new KDBizException(errorMessage);
+                }
+            }
+        }
+    }
+}

+ 16 - 4
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/opplugin/web/file/attach/SIBaseSaveOpEx.java

@@ -1,10 +1,13 @@
 package nckd.jxccl.sit.hcsi.opplugin.web.file.attach;
 
+import com.kingdee.bos.framework.core.exception.BizException;
 import kd.bos.dataentity.OperateOption;
 import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.operate.result.OperationResult;
 import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
 import kd.bos.entity.plugin.PreparePropertysEventArgs;
 import kd.bos.entity.plugin.args.AfterOperationArgs;
+import kd.bos.entity.plugin.args.EndOperationTransactionArgs;
 import kd.bos.logging.Log;
 import kd.bos.logging.LogFactory;
 import kd.bos.servicehelper.operation.SaveServiceHelper;
@@ -23,7 +26,7 @@ import java.util.stream.Collectors;
  */
 public class SIBaseSaveOpEx extends AbstractOperationServicePlugIn implements Plugin {
 
-    private static final Log log = LogFactory.getLog(SIBaseSaveOpEx.class);
+    private static final Log logger = LogFactory.getLog(SIBaseSaveOpEx.class);
 
     @Override
     public void onPreparePropertys(PreparePropertysEventArgs e) {
@@ -32,8 +35,8 @@ public class SIBaseSaveOpEx extends AbstractOperationServicePlugIn implements Pl
     }
 
     @Override
-    public void afterExecuteOperationTransaction(AfterOperationArgs e) {
-        super.afterExecuteOperationTransaction(e);
+    public void endOperationTransaction(EndOperationTransactionArgs e) {
+        super.endOperationTransaction(e);
         DynamicObject[] bills = e.getDataEntities();
         // 根据社保档案ID进行分组:
         Map<Long, List<DynamicObject>> billsMap = Arrays.stream(bills)
@@ -54,8 +57,17 @@ public class SIBaseSaveOpEx extends AbstractOperationServicePlugIn implements Pl
                 String fieldKey = welfAreTypeDyn.getString("nckd_sinsurfilefields");
                 sinsurFileDyn.set(fieldKey, siBase.getLong("nckd_sinsurdimension.id"));
             }
-            SaveServiceHelper.saveOperate("hcsi_sinsurfile", new DynamicObject[]{sinsurFileDyn}, OperateOption.create());
+            OperationResult result = SaveServiceHelper.saveOperate("hcsi_sinsurfile", new DynamicObject[]{sinsurFileDyn}, OperateOption.create());
+            if(!result.isSuccess()) {
+                logger.info("-------- 保存基数设置结果:" + result.getMessage());
+                logger.info("-------- 保存基数设置错误:" + result.getAllErrorOrValidateInfo());
+                throw new BizException("-------- 保存基数设置失败:" + result.getMessage());
+            }
         }
+    }
 
+    @Override
+    public void afterExecuteOperationTransaction(AfterOperationArgs e) {
+        super.afterExecuteOperationTransaction(e);
     }
 }

+ 17 - 2
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hsas/business/outdata/OutImportTaskGuideExportService.java

@@ -220,6 +220,15 @@ public class OutImportTaskGuideExportService {
     }
 
     private void setDataValidation(SXSSFSheet sheet, String[] options, int columnIndex, int firstDataRowIndex) {
+
+        // 检查选项总长度是否超过限制
+        String optionsString = String.join(",", options);
+        if (optionsString.length() > 255) {
+            // 如果超过255字符限制,则不创建下拉列表或采用其他方式处理
+            logger.warn("Dropdown options exceed 255 characters limit, skipping validation for column: " + columnIndex);
+            return;
+        }
+
         // 创建下拉列表约束
         DataValidationHelper validationHelper = sheet.getDataValidationHelper();
         DataValidationConstraint constraint = validationHelper.createExplicitListConstraint(options);
@@ -230,8 +239,14 @@ public class OutImportTaskGuideExportService {
 
         // 创建数据验证
         DataValidation validation = validationHelper.createValidation(constraint, addressList);
-        validation.setSuppressDropDownArrow(true);
-        validation.setShowErrorBox(true);
+
+        // 允许输入列表外的文本
+        validation.setShowErrorBox(false);  // 不显示错误框
+        validation.setEmptyCellAllowed(true); // 允许空值
+
+        // 可选:添加输入提示
+        validation.setShowPromptBox(true);
+        validation.createPromptBox("输入提示", "可选择下拉选项或输入自定义值");
 
         // 添加到工作表
         sheet.addValidationData(validation);

+ 14 - 25
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hsas/business/outdata/OutImportTaskGuideImportService.java

@@ -213,7 +213,7 @@ public class OutImportTaskGuideImportService {
                 temporary.set("modifier", RequestContext.get().getCurrUserId());
                 temporary.set("modifytime", new Date());
                 temporary.set("billstatus", "A");
-                temporary.set("entryentity", OutImportTaskUtils.getItemEntryList(rowMap, columnIndexMap, entryType));
+                temporary.set("entryentity", OutImportTaskUtils.getItemEntryList(rowMap, columnIndexMap, commonColumnIndexMap, entryType));
                 result.add(temporary);
             }
             HRBaseServiceHelper helper = new HRBaseServiceHelper("nckd_outtempdata");
@@ -306,22 +306,16 @@ public class OutImportTaskGuideImportService {
 
     private Map<Integer, List<Map<String, String>>> getColumnIndexMap() {
         List<Map<String, String>> columnHeadList = OutImportTaskUtils.getColumnHeadList(this.tplId, this.importTaskId);
-        Map<Integer, List<Map<String, String>>> columnIndexMap = new HashMap(columnHeadList.size());
-        List<Map<String, String>> tempMapList = null;
-        Iterator var4 = columnHeadList.iterator();
+        Map<Integer, List<Map<String, String>>> columnIndexMap = new HashMap<>(columnHeadList.size());
 
-        while(var4.hasNext()) {
-            Map<String, String> obj = (Map)var4.next();
+        for (Map<String, String> obj : columnHeadList) {
+            // 只处理非固定列(itemType != "0")
             if (!"0".equals(obj.get("itemType"))) {
-                tempMapList = (List) columnIndexMap.get(Integer.valueOf((String) obj.get("columnIndex")));
-                if (tempMapList == null) {
-                    tempMapList = new ArrayList(10);
-                    columnIndexMap.put(Integer.valueOf((String) obj.get("columnIndex")), tempMapList);
-                }
-                ((List) tempMapList).add(obj);
+                // 使用 computeIfAbsent 简化逻辑
+                columnIndexMap.computeIfAbsent(Integer.valueOf(obj.get("columnIndex")),
+                        k -> new ArrayList<>()).add(obj);
             }
         }
-
         return columnIndexMap;
     }
 
@@ -331,22 +325,16 @@ public class OutImportTaskGuideImportService {
      */
     private Map<Integer, List<Map<String, String>>> getCommonColumnIndexMap() {
         List<Map<String, String>> columnHeadList = OutImportTaskUtils.getColumnHeadList(this.tplId, this.importTaskId);
-        Map<Integer, List<Map<String, String>>> columnIndexMap = new HashMap(columnHeadList.size());
-        List<Map<String, String>> tempMapList = null;
-        Iterator var4 = columnHeadList.iterator();
+        Map<Integer, List<Map<String, String>>> columnIndexMap = new HashMap<>(columnHeadList.size());
 
-        while(var4.hasNext()) {
-            Map<String, String> obj = (Map)var4.next();
+        for (Map<String, String> obj : columnHeadList) {
+            // 只处理固定列(itemType == "0")
             if ("0".equals(obj.get("itemType"))) {
-                tempMapList = (List) columnIndexMap.get(Integer.valueOf((String) obj.get("columnIndex")));
-                if (tempMapList == null) {
-                    tempMapList = new ArrayList(10);
-                    columnIndexMap.put(Integer.valueOf((String) obj.get("columnIndex")), tempMapList);
-                }
-                ((List) tempMapList).add(obj);
+                // 使用 computeIfAbsent 简化逻辑
+                columnIndexMap.computeIfAbsent(Integer.valueOf(obj.get("columnIndex")),
+                        k -> new ArrayList<>()).add(obj);
             }
         }
-
         return columnIndexMap;
     }
 
@@ -366,6 +354,7 @@ public class OutImportTaskGuideImportService {
         Iterator var7 = tplFixItemMap.entrySet().iterator();
         while(var7.hasNext()) {
             Map.Entry<Integer, OutImpPresetItem> entry = (Map.Entry)var7.next();
+            if(entry.getValue() == null)  continue;
             excelName = (String)dataHeadMap.get(entry.getKey());
             if (StringUtils.isEmpty(excelName)) {
                 errDataList.add(((OutImpPresetItem)entry.getValue()).getItemName());

+ 40 - 5
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hsas/business/utils/OutImportTaskUtils.java

@@ -119,18 +119,21 @@ public class OutImportTaskUtils {
      */
     private static void addFixValue(Map<String, String> commentMap, Set<Long> itemSet, String itemKey, Map<String, Map<String, String>> itemMap, String itemType) {
         if (itemSet.size() != 0) {
+            //Map<Long, DynamicObject> map = OutImpTemplateHelper.getAllBaseItemMap();
             Map<Long, OutImpPresetItem> map = OutImpTemplateHelper.getPresetItemEnumMap();
             OutImpPresetItem itemEnum = null;
             Map<String, String> tempMap = null;
             Iterator it = itemSet.iterator();
-            while(it.hasNext()) {
-                Long itemId = (Long)it.next();
-                itemEnum = (OutImpPresetItem)map.get(itemId);
+            while (it.hasNext()) {
+                Long itemId = (Long) it.next();
+                itemEnum = map.get(itemId);
+                if(itemEnum == null)
+                    continue;
                 tempMap = new HashMap(16);
                 tempMap.put("name", itemEnum.getItemName());
                 tempMap.put("datatypeid", String.valueOf(itemEnum.getDataTypeId()));
                 tempMap.put("id", String.valueOf(itemId));
-                tempMap.put("key", getFixColumnKeyByItemId(itemId.toString()));
+                tempMap.put("key", itemKey + itemEnum.getItemId());
                 tempMap.put("itemType", itemType);
                 tempMap.put("comment", commentMap.get(itemKey + itemId));
                 itemMap.put(itemKey + itemId, tempMap);
@@ -211,7 +214,7 @@ public class OutImportTaskUtils {
 
     }
 
-    public static DynamicObjectCollection getItemEntryList(Map<Integer, Object> rowMap, Map<Integer, List<Map<String, String>>> columnIndexMap, EntityType entryType) {
+    public static DynamicObjectCollection getItemEntryList(Map<Integer, Object> rowMap, Map<Integer, List<Map<String, String>>> columnIndexMap, Map<Integer, List<Map<String, String>>> commonColumnIndexMap, EntityType entryType) {
         DynamicObjectCollection itemEntryList = new DynamicObjectCollection();
         int sequence = 0;
         for (Map.Entry<Integer, List<Map<String, String>>> entry : columnIndexMap.entrySet()) {
@@ -245,6 +248,38 @@ public class OutImportTaskUtils {
                 }
             }
         }
+        for (Map.Entry<Integer, List<Map<String, String>>> entry : commonColumnIndexMap.entrySet()) {
+            Object itemValue = rowMap.get(entry.getKey());
+            if (itemValue == null) {
+                continue;
+            }
+            for (Map<String, String> itemMap : entry.getValue()) {
+                try {
+                    DynamicObject item = (DynamicObject) entryType.createInstance();
+
+                    item.set("nckd_itemvalue", itemValue);
+                    item.set("nckd_itemtype", itemMap.get("itemType"));
+                    item.set("nckd_itemname", itemMap.get("name"));
+                    item.set("seq", sequence);
+
+                    String id = itemMap.get("id");
+                    if (id != null) {
+                        item.set("nckd_itemid", Long.valueOf(id));
+                    }
+
+                    String datatypeId = itemMap.get("datatypeid");
+                    if (datatypeId != null) {
+                        item.set("nckd_datatype", Long.valueOf(datatypeId));
+                    }
+                    sequence++;
+                    itemEntryList.add(item);
+                } catch (Exception e) {
+                    // 记录错误日志,但继续处理其他条目
+                    System.err.println("Error processing item: " + e.getMessage());
+                }
+            }
+        }
+
         return itemEntryList;
     }
 

+ 126 - 119
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hsas/formplugin/web/outdata/bill/OutTempDataViewBillListPlugin.java

@@ -185,7 +185,7 @@ public class OutTempDataViewBillListPlugin extends AbstractListPlugin implements
                 String name = (String)tempMap.get("name");
                 key = (String)tempMap.get("key");
                 itemType = (String)tempMap.get("itemType");
-                if ("0".equals(itemType)) {
+                if ("999".equals(itemType)) {
                     if (!COMMONCOLUMNSET.contains(key)) {
                         IListColumn tempColumn = (IListColumn)otherFixColumnMap.get(key);
                         if (tempColumn != null) {
@@ -238,40 +238,40 @@ public class OutTempDataViewBillListPlugin extends AbstractListPlugin implements
     }
 
     private void addItemProp(DynamicObjectType mainEntityType, List<Map<String, String>> columnHeadList) {
-        String key = null;
-        Long dataTypeId = null;
-        String name = null;
-        String itemType = null;
-        Iterator it = columnHeadList.iterator();
-
-        while(true) {
-            while(true) {
-                Map temMap;
-                do {
-                    if (!it.hasNext()) {
-                        return;
-                    }
-                    temMap = (Map)it.next();
-                    key = (String)temMap.get("key");
-                    itemType = (String)temMap.get("itemType");
-                } while("0".equals(itemType));
-
-                dataTypeId = Long.valueOf((String)temMap.get("datatypeid"));
-                name = (String)temMap.get("name");
-                if (1030L != dataTypeId && 1010L != dataTypeId && 1020L != dataTypeId) {
-                    if (1050L == dataTypeId) {
-                        DateProp property = new DateProp();
-                        property.setName(key);
-                        property.setDisplayName(new LocaleString(name));
-                        mainEntityType.addProperty(property);
-                    }
-                } else {
-                    TextProp property = new TextProp();
-                    property.setName(key);
-                    property.setDisplayName(new LocaleString(name));
-                    property.setMaxLenth(200);
-                    mainEntityType.addProperty(property);
-                }
+        // 遍历所有列定义
+        for (Map<String, String> columnDef : columnHeadList) {
+            String key = columnDef.get("key");
+            String itemType = columnDef.get("itemType");
+
+            // 只处理非固定列(itemType != "0")
+//            if ("0".equals(itemType)) {
+//                continue;
+//            }
+
+            Long dataTypeId = Long.valueOf(columnDef.get("datatypeid"));
+            String name = columnDef.get("name");
+
+            // 根据数据类型创建相应属性
+            if (dataTypeId == 1050L) {
+                // 日期类型属性
+                DateProp dateProperty = new DateProp();
+                dateProperty.setName(key);
+                dateProperty.setDisplayName(new LocaleString(name));
+                mainEntityType.addProperty(dateProperty);
+            } else if (dataTypeId == 1010L || dataTypeId == 1020L || dataTypeId == 1030L) {
+                // 文本类型属性(包括数值)
+                TextProp textProperty = new TextProp();
+                textProperty.setName(key);
+                textProperty.setDisplayName(new LocaleString(name));
+                textProperty.setMaxLenth(200);
+                mainEntityType.addProperty(textProperty);
+            } else {
+                // 其他文本类型属性
+                TextProp otherProperty = new TextProp();
+                otherProperty.setName(key);
+                otherProperty.setDisplayName(new LocaleString(name));
+                otherProperty.setMaxLenth(200);
+                mainEntityType.addProperty(otherProperty);
             }
         }
     }
@@ -283,111 +283,118 @@ public class OutTempDataViewBillListPlugin extends AbstractListPlugin implements
         @Override
         public DynamicObjectCollection getData(int start, int limit) {
             DynamicObjectCollection list = super.getData(start, limit);
+
+            // 如果是全选操作,直接返回基础数据
             if (this.getQueryBuilder().isSelectedAllRows()) {
                 return list;
-            } else {
-                List<Map<String, String>> columnHeadList = OutTempDataViewBillListPlugin.this.getColumnHeadList();
-                if (SWCHelper.isEmpty(columnHeadList)) {
-                    return list;
-                } else {
-                    OutTempDataViewBillListPlugin.this.addItemProp(list.getDynamicObjectType(), columnHeadList);
-                    List<Long> idList = (List)list.stream().map((objx) -> {
-                        return objx.getLong("id");
-                    }).collect(Collectors.toList());
-                    Map<Long, Map<String, Object>> itemDataMap = this.getItemDataMap(idList);
-                    if (itemDataMap.size() == 0) {
-                        return list;
-                    } else {
-                        Map<String, Object> tempMap = null;
-                        Iterator it = list.iterator();
-                        while(true) {
-                            DynamicObject obj;
-                            do {
-                                do {
-                                    if (!it.hasNext()) {
-                                        return list;
-                                    }
-                                    obj = (DynamicObject)it.next();
-                                    tempMap = (Map)itemDataMap.get(obj.getLong("id"));
-                                } while(tempMap == null);
-                            } while(tempMap.size() == 0);
-
-                            Iterator it1 = tempMap.entrySet().iterator();
-
-                            while(it1.hasNext()) {
-                                Map.Entry<String, Object> entry = (Map.Entry)it1.next();
-                                obj.set((String)entry.getKey(), entry.getValue());
-                            }
-                        }
+            }
+
+            List<Map<String, String>> columnHeadList = OutTempDataViewBillListPlugin.this.getColumnHeadList();
+            if (SWCHelper.isEmpty(columnHeadList)) {
+                return list;
+            }
+
+            // 添加动态属性到实体类型
+            OutTempDataViewBillListPlugin.this.addItemProp(list.getDynamicObjectType(), columnHeadList);
+
+            // 提取ID列表用于查询
+            List<Long> idList = list.stream()
+                    .map(obj -> obj.getLong("id"))
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toList());
+            if (idList.isEmpty()) {
+                return list;
+            }
+            // 获取详细数据映射
+            Map<Long, Map<String, Object>> itemDataMap = this.getItemDataMap(idList);
+            if (itemDataMap.isEmpty()) {
+                return list;
+            }
+            // 将详细数据填充到主列表中
+            for (DynamicObject obj : list) {
+                Long id = obj.getLong("id");
+                Map<String, Object> detailData = itemDataMap.get(id);
+                if (detailData != null && !detailData.isEmpty()) {
+                    for (Map.Entry<String, Object> entry : detailData.entrySet()) {
+                        obj.set(entry.getKey(), entry.getValue());
                     }
                 }
             }
+            return list;
         }
 
         private Map<Long, Map<String, Object>> getItemDataMap(List<Long> idList) {
-            Map<Long, Map<String, Object>> itemDataMap = new HashMap(16);
+            Map<Long, Map<String, Object>> itemDataMap = new HashMap<>(16);
             HRBaseServiceHelper helper = new HRBaseServiceHelper("nckd_outtempdata");
             String fields = "id,entryentity.nckd_itemtype,entryentity.nckd_itemid,entryentity.nckd_datatype,entryentity.nckd_itemvalue";
             QFilter qFilter = new QFilter("id", "in", idList);
             DynamicObjectCollection itemData = helper.queryOriginalCollection(fields, new QFilter[]{qFilter});
-            if (itemData.size() == 0) {
+
+            if (itemData.isEmpty()) {
                 return itemDataMap;
-            } else {
-                Map<String, Object> tempMap = null;
-                long dataTypeId = 0L;
-                String itemValue = null;
-                String columnKey = null;
-                Iterator var12 = itemData.iterator();
-
-                while(true) {
-                    while(true) {
-                        DynamicObject obj;
-                        do {
-                            if (!var12.hasNext()) {
-                                return itemDataMap;
-                            }
-
-                            obj = (DynamicObject)var12.next();
-                            tempMap = (Map)itemDataMap.get(obj.getLong("id"));
-                            if (tempMap == null) {
-                                tempMap = new HashMap(16);
-                                itemDataMap.put(obj.getLong("id"), tempMap);
-                            }
-
-                            dataTypeId = obj.getLong("entryentity.nckd_itemtype");
-                            itemValue = obj.getString("entryentity.nckd_itemvalue");
-                        } while(itemValue == null);
-
-                        columnKey = this.getColumnKey(obj.getString("entryentity.nckd_itemtype"), obj.getLong("entryentity.nckd_itemid"));
-                        if (1020L != dataTypeId && 1010L != dataTypeId) {
-                            if (1050L == dataTypeId) {
-                                try {
-                                    ((Map)tempMap).put(columnKey, DateTimeUtils.parseDate(itemValue, "yyyy-MM-dd"));
-                                } catch (ParseException var15) {
-                                    OutTempDataViewBillListPlugin.logger.error("parse itemValue error", var15);
-                                    throw new KDBizException(ExceptionUtils.getFullStackTrace(var15));
-                                }
-                            } else {
-                                ((Map)tempMap).put(columnKey, itemValue);
-                            }
-                        } else {
-                            ((Map)tempMap).put(columnKey, new BigDecimal(itemValue));
-                        }
-                    }
+            }
+
+            for (DynamicObject obj : itemData) {
+                Long objectId = obj.getLong("id");
+                String itemValue = obj.getString("entryentity.nckd_itemvalue");
+
+                // 跳过空值记录
+                if (itemValue == null) {
+                    continue;
                 }
+
+                // 获取或创建该对象的属性映射
+                Map<String, Object> objectProperties = itemDataMap.computeIfAbsent(objectId, k -> new HashMap<>(16));
+
+                // 获取列键和数据类型
+                String itemType = obj.getString("entryentity.nckd_itemtype");
+                Long itemId = obj.getLong("entryentity.nckd_itemid");
+                String columnKey = this.getColumnKey(itemType, itemId);
+                Long dataTypeId = obj.getLong("entryentity.nckd_datatype");
+
+                // 根据数据类型处理值
+                try {
+                    Object processedValue = this.processValueByDataType(dataTypeId, itemValue);
+                    objectProperties.put(columnKey, processedValue);
+                } catch (ParseException e) {
+                    OutTempDataViewBillListPlugin.logger.error("parse itemValue error", e);
+                    throw new KDBizException(ExceptionUtils.getFullStackTrace(e));
+                }
+            }
+
+            return itemDataMap;
+        }
+
+        /**
+         * 根据数据类型处理值
+         * @param dataTypeId 数据类型ID
+         * @param itemValue 原始值
+         * @return 处理后的值
+         * @throws ParseException 解析异常
+         */
+        private Object processValueByDataType(Long dataTypeId, String itemValue) throws ParseException {
+            if (dataTypeId == null) {
+                return itemValue;
+            }
+
+            if (dataTypeId == 1050L) {
+                // 日期类型
+                return DateTimeUtils.parseDate(itemValue, "yyyy-MM-dd");
+            } else if (dataTypeId == 1010L || dataTypeId == 1020L) {
+                // 数值类型
+                return new BigDecimal(itemValue);
+            } else {
+                // 其他类型作为字符串处理
+                return itemValue;
             }
         }
 
         private String getColumnKey(String itemType, long itemId) {
             String columnKey = "";
-            if ("4".equals(itemType)) {
-                columnKey = "ft" + itemId;
+            if ("0".equals(itemType)) {
+                columnKey = "fix" + itemId;
             } else if ("1".equals(itemType)) {
                 columnKey = "ii" + itemId;
-            } else if ("3".equals(itemType)) {
-                columnKey = "bs" + itemId;
-            } else if ("2".equals(itemType)) {
-                columnKey = "sp" + itemId;
             }
 
             return columnKey;

+ 7 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hsas/formplugin/web/outdata/helper/OutImpTemplateHelper.java

@@ -240,6 +240,13 @@ public class OutImpTemplateHelper {
                 ));
     }
 
+    public static Map<Long, DynamicObject> getAllBaseItemMap() {
+        String fields = "id,number,name,nckd_datatype.id,nckd_ispreset,nckd_presetcomment";
+        QFilter filter = new QFilter("enable", "=", "1");
+        DynamicObjectCollection dyns = SwcConstant.OUTIMPORTITEM_ENTITY.queryOriginalCollection(fields, new QFilter[]{filter});
+        return dyns.stream().collect(Collectors.toMap(item -> item.getLong("id"), item -> item));
+    }
+
 
     static {
 //        String fields = "id,number,name,nckd_datatype.id";

+ 6 - 2
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/structappr/AbstractStructApprFormPlugin.java

@@ -78,7 +78,7 @@ public abstract class AbstractStructApprFormPlugin extends AbstractFormPlugin im
 
         if (MasConstant.NCKD_INSTALLMENTYEARS.equalsIgnoreCase(fieldKey)) {
             if (!Objects.equals(oldValue, newValue)) {
-                initOperateOption(ConvertUtil.toInt(newValue), rowIndex);
+                initOperateOption(ConvertUtil.toInt(newValue,0), rowIndex);
             }
         } else if (Stream.of(MasConstant.NCKD_PAYUNIT, MasConstant.NCKD_LAWENTITY, MasConstant.NCKD_YEAR)
                 .anyMatch(op -> op.equalsIgnoreCase(fieldKey))) {
@@ -203,7 +203,7 @@ public abstract class AbstractStructApprFormPlugin extends AbstractFormPlugin im
      * @param rowIndex         行索引
      */
     protected void initOperateOption(int installmentYears, int rowIndex) {
-        if (rowIndex > -1) {
+            if (rowIndex > -1) {
             for (int i = 1; i <= 10; i++) {
                 this.getView().setEnable(false, rowIndex, MasConstant.NCKD_PAYYEAR + i);
                 this.getView().setEnable(false, rowIndex, MasConstant.NCKD_PAYAMOUNT + i);
@@ -212,6 +212,10 @@ public abstract class AbstractStructApprFormPlugin extends AbstractFormPlugin im
                 this.getView().setEnable(true, rowIndex, MasConstant.NCKD_PAYYEAR + i);
                 this.getView().setEnable(true, rowIndex, MasConstant.NCKD_PAYAMOUNT + i);
             }
+            for (int i = installmentYears+1; i <= 10; i++) {
+                this.getModel().setValue( MasConstant.NCKD_PAYYEAR + i,null,rowIndex);
+                this.getModel().setValue( MasConstant.NCKD_PAYAMOUNT + i,null,rowIndex);
+            }
         }
     }
 

+ 14 - 7
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/structappr/EntleaderAnlSalStdFormPlugin.java

@@ -146,6 +146,7 @@ public class EntleaderAnlSalStdFormPlugin extends AbstractStructApprFormPlugin i
                             String projectCategoryNumber = projectCategory.getString(FormConstant.NUMBER_KEY);
                             if(projectCategoryNumber.equalsIgnoreCase(ProjectCategoryEnum.YEARLY_SALARY.getCode())) {
                                 DynamicObject entry = entryEntities.addNew();
+                                boolean deferredPayItem = dbEntryEntity.getBoolean(MasConstant.NCKD_DEFERREDPAYITEM);
                                 entry.set(MasConstant.NCKD_PROJECTCATEGORY, dbEntryEntity.getDynamicObject(MasConstant.NCKD_PROJECTCATEGORY));
                                 entry.set(MasConstant.NCKD_EMPLOYEE, dbSubCoHeadService.get(MasConstant.NCKD_EMPLOYEE));
                                 entry.set(MasConstant.NCKD_POSNAME, dbSubCoHeadService.get(MasConstant.NCKD_POSNAME));
@@ -156,12 +157,16 @@ public class EntleaderAnlSalStdFormPlugin extends AbstractStructApprFormPlugin i
                                 entry.set(MasConstant.NCKD_MGTLVLDTL, dbSubCoHeadService.get(MasConstant.NCKD_MGTLVLDTL));
                                 entry.set(MasConstant.NCKD_SALNEGOT, dbSubCoHeadService.get(MasConstant.NCKD_SALNEGOT));
                                 entry.set(MasConstant.NCKD_SALARYITEM, dbEntryEntity.get(MasConstant.NCKD_SALARYITEM));
-                                entry.set(MasConstant.NCKD_DEFERREDPAYITEM, dbEntryEntity.getBoolean(MasConstant.NCKD_DEFERREDPAYITEM));
+                                entry.set(MasConstant.NCKD_DEFERREDPAYITEM, deferredPayItem);
                                 //根据【项目分类】获取延期支付比例配置
-                                List<DynamicObject> dbDeferPayRatoConfList = dbDeferPayRatoConfMap.get(projectCategoryNumber);
-                                if(dbDeferPayRatoConfList != null && !dbDeferPayRatoConfList.isEmpty()){
-                                    DynamicObject dbDeferPayRatoConf = dbDeferPayRatoConfList.get(0);
-                                    entry.set(MasConstant.NCKD_INSTALLMENTYEARS, dbDeferPayRatoConf.getInt(MasConstant.NCKD_PAYOUTTIMES));
+                                if(deferredPayItem) {
+                                    List<DynamicObject> dbDeferPayRatoConfList = dbDeferPayRatoConfMap.get(projectCategoryNumber);
+                                    if (dbDeferPayRatoConfList != null && !dbDeferPayRatoConfList.isEmpty()) {
+                                        DynamicObject dbDeferPayRatoConf = dbDeferPayRatoConfList.get(0);
+                                        entry.set(MasConstant.NCKD_INSTALLMENTYEARS, dbDeferPayRatoConf.getInt(MasConstant.NCKD_PAYOUTTIMES));
+                                    }
+                                }else{
+                                    entry.set(MasConstant.NCKD_INSTALLMENTYEARS, 0);
                                 }
                             }
                         }
@@ -171,13 +176,15 @@ public class EntleaderAnlSalStdFormPlugin extends AbstractStructApprFormPlugin i
                 this.getView().showSuccessNotification("数据加载成功!");
             }
             //====================================== 构建分录数据 end ======================================
+
+            getModel().updateEntryCache(entryEntities);
+            getView().updateView(FormConstant.NCKD_ENTRYENTITY);
+
             for (int rowIndex = 0; rowIndex < entryEntities.size(); rowIndex++) {
                 DynamicObject entry = entryEntities.get(rowIndex);
                 int installmentYears = entry.getInt(MasConstant.NCKD_INSTALLMENTYEARS);
                 initOperateOption(installmentYears,rowIndex);
             }
-            getModel().updateEntryCache(entryEntities);
-            getView().updateView(FormConstant.NCKD_ENTRYENTITY);
 
         }
     }

+ 13 - 7
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/structappr/SubcorpChiefSalStdFormPlugin.java

@@ -138,15 +138,20 @@ public class SubcorpChiefSalStdFormPlugin extends AbstractStructApprFormPlugin i
                         //只取分类为"年度薪酬"的数据
                         if(projectCategoryNumber.equalsIgnoreCase(ProjectCategoryEnum.YEARLY_SALARY.getCode())) {
                             DynamicObject entry = entryEntities.addNew();
+                            boolean deferredPayItem = dbEntryEntity.getBoolean(MasConstant.NCKD_DEFERREDPAYITEM);
                             entry.set(MasConstant.NCKD_PROJECTCATEGORY, dbEntryEntity.getDynamicObject(MasConstant.NCKD_PROJECTCATEGORY));
                             entry.set(MasConstant.NCKD_SALARYITEM, dbEntryEntity.getDynamicObject(MasConstant.NCKD_SALARYITEM));
-                            entry.set(MasConstant.NCKD_DEFERREDPAYITEM, dbEntryEntity.getBoolean(MasConstant.NCKD_DEFERREDPAYITEM));
+                            entry.set(MasConstant.NCKD_DEFERREDPAYITEM, deferredPayItem);
 
                             //根据【项目分类】获取延期支付比例配置
-                            List<DynamicObject> dbDeferPayRatoConfList = dbDeferPayRatoConfMap.get(projectCategoryNumber);
-                            if(dbDeferPayRatoConfList != null && !dbDeferPayRatoConfList.isEmpty()){
-                                DynamicObject dbDeferPayRatoConf = dbDeferPayRatoConfList.get(0);
-                                entry.set(MasConstant.NCKD_INSTALLMENTYEARS, dbDeferPayRatoConf.getInt(MasConstant.NCKD_PAYOUTTIMES));
+                            if(deferredPayItem) {
+                                List<DynamicObject> dbDeferPayRatoConfList = dbDeferPayRatoConfMap.get(projectCategoryNumber);
+                                if (dbDeferPayRatoConfList != null && !dbDeferPayRatoConfList.isEmpty()) {
+                                    DynamicObject dbDeferPayRatoConf = dbDeferPayRatoConfList.get(0);
+                                    entry.set(MasConstant.NCKD_INSTALLMENTYEARS, dbDeferPayRatoConf.getInt(MasConstant.NCKD_PAYOUTTIMES));
+                                }
+                            }else{
+                                entry.set(MasConstant.NCKD_INSTALLMENTYEARS, 0);
                             }
                             /*entry.set(MasConstant.NCKD_DEFERREDPAYDESC, dbEntryEntity.getString(MasConstant.NCKD_DEFERREDPAYDESC));
                             entry.set(MasConstant.NCKD_TERMPAYDESC, dbEntryEntity.getString(MasConstant.NCKD_TERMPAYDESC));*/
@@ -157,13 +162,14 @@ public class SubcorpChiefSalStdFormPlugin extends AbstractStructApprFormPlugin i
             }else{
                 this.getView().showTipNotification("未加载到数据,根据【所属二级单位】、【法人组织】及【年度】未加载到对应\"子企业负责人薪酬结构\"数据!");
             }
+
+            getModel().updateEntryCache(entryEntities);
+            getView().updateView(FormConstant.NCKD_ENTRYENTITY);
             for (int rowIndex = 0; rowIndex < entryEntities.size(); rowIndex++) {
                 DynamicObject entry = entryEntities.get(rowIndex);
                 int installmentYears = entry.getInt(MasConstant.NCKD_INSTALLMENTYEARS);
                 initOperateOption(installmentYears,rowIndex);
             }
-            getModel().updateEntryCache(entryEntities);
-            getView().updateView(FormConstant.NCKD_ENTRYENTITY);
 
         }
     }

+ 5 - 1
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/structappr/change/AbstractSalaryStdChgFormPlugin.java

@@ -65,7 +65,7 @@ public abstract class AbstractSalaryStdChgFormPlugin extends AbstractFormPlugin
         
         if (MasConstant.NCKD_INSTALLMENTYEARS.equalsIgnoreCase(fieldKey)) {
             if (!Objects.equals(oldValue, newValue)) {
-                initOperateOption(ConvertUtil.toInt(newValue), rowIndex);
+                initOperateOption(ConvertUtil.toInt(newValue,0), rowIndex);
             }
         } else if (MasConstant.NCKD_APPRSTD.equalsIgnoreCase(fieldKey)) {
             handleApprStdChanged(oldValue, newValue, rowIndex);
@@ -193,6 +193,10 @@ public abstract class AbstractSalaryStdChgFormPlugin extends AbstractFormPlugin
                 this.getView().setEnable(true, rowIndex, MasConstant.NCKD_PAYYEAR + i);
                 this.getView().setEnable(true, rowIndex, MasConstant.NCKD_PAYAMOUNT + i);
             }
+            for (int i = installmentYears+1; i <= 10; i++) {
+                this.getModel().setValue( MasConstant.NCKD_PAYYEAR + i,null,rowIndex);
+                this.getModel().setValue( MasConstant.NCKD_PAYAMOUNT + i,null,rowIndex);
+            }
         }
     }
 

+ 142 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/onlineperf/business/extpoint/OnlinePerfSalaryCalServiceExPlugin.java

@@ -0,0 +1,142 @@
+package nckd.jxccl.swc.onlineperf.business.extpoint;
+
+import com.alibaba.fastjson.JSONObject;
+import kd.bos.dataentity.OperateOption;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.MainEntityType;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.MetadataServiceHelper;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import kd.sdk.swc.hscs.business.extpoint.ISalaryCalExtPlugin;
+import kd.sdk.swc.hscs.common.events.AfterSalaryCalEventArgs;
+import kd.sdk.swc.hscs.common.events.CalRollBackEventArgs;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.utils.DateUtil;
+import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+import nckd.jxccl.swc.constants.SwcConstant;
+import nckd.jxccl.swc.onlineperf.common.OnlinePerfConstant;
+
+import java.math.BigDecimal;
+import java.nio.file.OpenOption;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+* 薪酬计算扩展(处理在线即时考核)
+* @author W.Y.C
+* @date 2025/12/17 21:04
+* @version 1.0
+*/
+public class OnlinePerfSalaryCalServiceExPlugin implements ISalaryCalExtPlugin {
+
+    private static final Log log = LogFactory.getLog(OnlinePerfSalaryCalServiceExPlugin.class);
+
+    /**
+     * 薪资计算完成后逻辑处理场景
+     * @param event 薪资计算完成后事件,其中属性包括:
+     * Long taskId 核算任务ID,用于获取核算任务信息
+     * Long recordId 计算会话ID
+     * Long batchId 核算批次ID
+     * String calType 计算类型("onlyPreTaxCal":仅计算税前, "preTaxCal":计算税前,"afterTaxCal":计算税后,"cal":计算(不开启个税计算开关,税前 和税后一起计算)),计算保存埋点在分段计算时或进来两次,计算税前和计算税后,计算只进来一次,可以通过计算类型进行判断是否需要进行业务处理
+     * List<Long> calPersonIdList 当前批次核算名单Id集合,用于获取需要处理的明细结果信息
+     * boolean isFinished 是否计算完成,判断当前次计算是否完成
+     * String traceId 日志跟踪ID,可用于日志打印
+     */
+    @Override
+    public void afterSalaryCal(AfterSalaryCalEventArgs event) {
+        //锁定在线即时考核
+        processOnlinePerfLock(event.getCalPersonIdList(), true);
+    }
+
+    /**
+     * 计算回滚扩展场景
+     */
+    @Override
+    public void afterCancelCalRollBack(CalRollBackEventArgs event) {
+        //解锁在线即时考核
+        processOnlinePerfLock(event.getCalPersonIdList(), false);
+    }
+
+    /**
+     * 处理在线即时考核锁定状态
+     * @param calPersonIdList 核算人员ID列表
+     * @param isLocked 是否锁定
+     */
+    private void processOnlinePerfLock(List<Long> calPersonIdList, boolean isLocked) {
+        // 构建查询字段
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                .add(FormConstant.ID_KEY)
+                .add("empnumber")
+                .add("name")
+                .add("org")
+                .addGroup(new String[]{"caltask"}, "calcount", "payrolldate")
+                .addGroup(new String[]{"caltask", "calrule"}, FormConstant.ID_KEY)
+                .addGroup(new String[]{FormConstant.EMPLOYEE_KEY}, FormConstant.ID_KEY);
+        
+        QFilter qFilter = new QFilter("id", "in", calPersonIdList);
+        DynamicObject[] load = SwcConstant.CALPERSON_HELPER.load(queryFieldBuilder.buildSelect(), new QFilter[]{qFilter});
+
+        // 如果没有加载到数据则直接返回
+        if(load == null || load.length <= 0) {
+            return;
+        }
+        
+        Map<Long, Long> employeeToCalPersonMap = Arrays.stream(load)
+                .collect(Collectors.toMap(
+                        obj -> obj.getLong(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY)),
+                        obj -> obj.getLong(FormConstant.ID_KEY)
+                ));
+
+        long orgId = load[0].getLong(String.join(".", FormConstant.ORG_KEY, FormConstant.ID_KEY));
+        DynamicObject calTask = load[0].getDynamicObject("caltask");
+        Date date = calTask.getDate("payrolldate");
+        int year = DateUtil.getYear(date);
+        int month = DateUtil.getMonthValue(date);
+        long calRuleId = calTask.getLong(String.join(".", "calrule", FormConstant.ID_KEY));
+        int calCount = calTask.getInt("calcount");
+
+        // 在线即时考核查询构建
+        QueryFieldBuilder onlinePerfQueryFieldBuilder = QueryFieldBuilder.create()
+                .add(FormConstant.ID_KEY)
+                .addIdNumberName(OnlinePerfConstant.NCKD_CALRULE)
+                .addIdNumberName(OnlinePerfConstant.NCKD_ADMINORGUNIT)
+                .add(OnlinePerfConstant.NCKD_PERIODYEAR)
+                .add(OnlinePerfConstant.NCKD_PERIODMONTH)
+                .addIdNumberName(OnlinePerfConstant.NCKD_ENTRYENTITY, FormConstant.NCKD_PERSON)
+                .addIdNumberName(OnlinePerfConstant.NCKD_ENTRYENTITY, OnlinePerfConstant.NCKD_SALARYITEM)
+                .add(OnlinePerfConstant.NCKD_ENTRYENTITY, OnlinePerfConstant.NCKD_NMONEY);
+                
+        QFilter onlinePerfFilter = new QFilter(OnlinePerfConstant.NCKD_PERIODYEAR, QCP.equals, year)
+                .and(OnlinePerfConstant.NCKD_PERIODMONTH, QCP.equals, month)
+                .and(String.join(".", OnlinePerfConstant.NCKD_ADMINORGUNIT, FormConstant.ID_KEY),QCP.equals, orgId)
+                .and(String.join(".", OnlinePerfConstant.NCKD_CALRULE, FormConstant.ID_KEY),QCP.equals, calRuleId)
+                .and(String.join(".", OnlinePerfConstant.NCKD_ENTRYENTITY, OnlinePerfConstant.NCKD_PERSON),QCP.in, employeeToCalPersonMap.keySet());
+                
+        DynamicObjectCollection onlinePerfColl = QueryServiceHelper.query(OnlinePerfConstant.ONLINEPERF_ENTITYID, onlinePerfQueryFieldBuilder.buildSelect(), new QFilter[]{onlinePerfFilter});
+        
+        // 如果查询结果为空则直接返回
+        if(!onlinePerfColl.isEmpty()) {
+
+            List<Long> ids = onlinePerfColl.stream().map(obj -> obj.getLong(FormConstant.ID_KEY)).collect(Collectors.toList());
+            MainEntityType dataEntityType = MetadataServiceHelper.getDataEntityType(OnlinePerfConstant.ONLINEPERF_ENTITYID);
+            DynamicObject[] dbOnlinePerfArray = BusinessDataServiceHelper.load(ids.toArray(), dataEntityType);
+
+            for (DynamicObject dynamicObject : dbOnlinePerfArray) {
+                dynamicObject.set(OnlinePerfConstant.NCKD_ISCALDYNLOCK, isLocked);
+            }
+
+            // 锁定/解锁在线即时考核结果
+            SaveServiceHelper.saveOperate(OnlinePerfConstant.ONLINEPERF_ENTITYID, dbOnlinePerfArray, OperateOption.create());
+        }
+    }
+}

+ 30 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/onlineperf/common/OnlinePerfConstant.java

@@ -0,0 +1,30 @@
+package nckd.jxccl.swc.onlineperf.common;
+
+import nckd.jxccl.base.common.constant.FormConstant;
+
+/**
+ * 在线即时考核常量类
+ *
+ * @author W.Y.C
+ * @version 1.0
+ * @date 2025/12/17 19:38
+ */
+public class OnlinePerfConstant extends FormConstant {
+
+    /** 在线即时考核-实体标识 */
+    public static final String ONLINEPERF_ENTITYID = "nckd_onlineperf";
+    /** 计算规则 */
+    public static final String NCKD_CALRULE = "nckd_calrule";
+    /** 统计年 */
+    public static final String NCKD_PERIODYEAR = "nckd_periodyear";
+    /** 统计月 */
+    public static final String NCKD_PERIODMONTH = "nckd_periodmonth";
+    /** 所属组织 */
+    public static final String NCKD_ADMINORGUNIT = "nckd_adminorgunit";
+    /** 锁定 */
+    public static final String NCKD_ISCALDYNLOCK = "nckd_iscaldynlock";
+    /** 薪酬项目 */
+    public static final String NCKD_SALARYITEM = "nckd_salaryitem";
+    /** 相关金额 */
+    public static final String NCKD_NMONEY = "nckd_nmoney";
+}

+ 108 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/onlineperf/common/OnlinePerfFetchDataService.java

@@ -0,0 +1,108 @@
+package nckd.jxccl.swc.onlineperf.common;
+
+import com.alibaba.fastjson.JSONObject;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.sdk.swc.hscs.common.api.ICustomFetchDataService;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.utils.DateUtil;
+import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+import nckd.jxccl.swc.constants.SwcConstant;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 在线即时考核薪酬函数
+ *
+ * @author W.Y.C
+ * @version 1.0
+ * @date 2025/12/17 14:37
+ */
+public class OnlinePerfFetchDataService implements ICustomFetchDataService {
+
+    @Override
+    public Map<Long, Map<String, Object>> fetchDataCalPerson(List<Long> calPersonIdList, Map<Long, Map<String, Object>> paramsMap, Map<String, Object> extParamMap) {
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                .add(FormConstant.ID_KEY)
+                .add("empnumber")
+                .add("name")
+                .add("org")
+                .addGroup(new String[]{"caltask"}, "calcount", "payrolldate")
+                .addGroup(new String[]{"caltask", "calrule"}, FormConstant.ID_KEY)
+                .addGroup(new String[]{FormConstant.EMPLOYEE_KEY}, FormConstant.ID_KEY);
+        QFilter qFilter = new QFilter("id", "in", calPersonIdList);
+        DynamicObject[] load = SwcConstant.CALPERSON_HELPER.load(queryFieldBuilder.buildSelect(), new QFilter[]{qFilter});
+
+        Map<Long, Map<String, Object>> resultMap = new HashMap<Long, Map<String, Object>>();
+        if(load != null && load.length > 0) {
+            Map<Long, Long> employeeToCalPersonMap = Arrays.stream(load)
+                    .collect(Collectors.toMap(
+                            obj -> obj.getLong(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY)),
+                            obj -> obj.getLong(FormConstant.ID_KEY)
+                    ));
+            long orgId = load[0].getLong(String.join(".", FormConstant.ORG_KEY, FormConstant.ID_KEY));
+            DynamicObject calTask = load[0].getDynamicObject("caltask");
+            Date date = calTask.getDate("payrolldate");
+            int year = DateUtil.getYear(date);
+            int month = DateUtil.getMonthValue(date);
+            long calRuleId = calTask.getLong(String.join(".", "calrule", FormConstant.ID_KEY));
+            int calCount = calTask.getInt("calcount");
+            //在线即时考核
+            QueryFieldBuilder onlinePerfQueryFieldBuilder = QueryFieldBuilder.create()
+                    .add(FormConstant.ID_KEY)
+                    .addIdNumberName(OnlinePerfConstant.NCKD_CALRULE)
+                    .addIdNumberName(OnlinePerfConstant.NCKD_ADMINORGUNIT)
+                    .add(OnlinePerfConstant.NCKD_PERIODYEAR)
+                    .add(OnlinePerfConstant.NCKD_PERIODMONTH)
+                    .addIdNumberName(OnlinePerfConstant.NCKD_ENTRYENTITY, FormConstant.NCKD_PERSON)
+                    .addIdNumberName(OnlinePerfConstant.NCKD_ENTRYENTITY, OnlinePerfConstant.NCKD_SALARYITEM)
+                    .add(OnlinePerfConstant.NCKD_ENTRYENTITY, OnlinePerfConstant.NCKD_NMONEY);
+            QFilter onlinePerfFilter = new QFilter(OnlinePerfConstant.NCKD_PERIODYEAR, QCP.equals, year)
+                    .and(OnlinePerfConstant.NCKD_PERIODMONTH, QCP.equals, month)
+                    .and(String.join(".", OnlinePerfConstant.NCKD_ADMINORGUNIT, FormConstant.ID_KEY),QCP.equals, orgId)
+                    .and(String.join(".", OnlinePerfConstant.NCKD_CALRULE, FormConstant.ID_KEY),QCP.equals, calRuleId)
+                    .and(String.join(".", OnlinePerfConstant.NCKD_ENTRYENTITY, OnlinePerfConstant.NCKD_PERSON),QCP.in, employeeToCalPersonMap.keySet());
+            DynamicObjectCollection onlinePerfColl = QueryServiceHelper.query(OnlinePerfConstant.ONLINEPERF_ENTITYID, onlinePerfQueryFieldBuilder.buildSelect(), new QFilter[]{onlinePerfFilter});
+            Map<Long, List<DynamicObject>> onlinePerfMap = onlinePerfColl.stream()
+                    .collect(Collectors.groupingBy(dynamicObject ->
+                            dynamicObject.getLong(String.join(".", OnlinePerfConstant.NCKD_ENTRYENTITY, OnlinePerfConstant.NCKD_PERSON, FormConstant.ID_KEY))
+                    ));
+            for (Map.Entry<Long, List<DynamicObject>> entrySet : onlinePerfMap.entrySet()) {
+                Long key = entrySet.getKey();
+                List<DynamicObject> value = entrySet.getValue();
+                JSONObject json = new JSONObject();
+                for (DynamicObject onlinePerf : value) {
+                    if(onlinePerf.getLong(String.join(".", OnlinePerfConstant.NCKD_ENTRYENTITY, OnlinePerfConstant.NCKD_SALARYITEM, FormConstant.ID_KEY))>0){
+                        String salaryItemNumber = onlinePerf.getString(String.join(".", OnlinePerfConstant.NCKD_ENTRYENTITY, OnlinePerfConstant.NCKD_SALARYITEM, FormConstant.NUMBER_KEY));
+                        BigDecimal money = onlinePerf.getBigDecimal(String.join(".", OnlinePerfConstant.NCKD_ENTRYENTITY, OnlinePerfConstant.NCKD_NMONEY));
+                        if(money.compareTo(BigDecimal.ZERO) > 0) {
+                            if(calCount == 1) {
+                                json.put(salaryItemNumber, money);
+                            }else{
+                                json.put(salaryItemNumber, BigDecimal.ZERO);
+                            }
+                        }
+                    }
+                }
+                Map<String, Object> result = new HashMap<String, Object>();
+                result.put("resultJson",json.toString());
+                resultMap.put(employeeToCalPersonMap.get(key), result);
+            }
+        }
+        return resultMap;
+    }
+
+    @Override
+    public Map<String, Object> fetchDataCalTask(Long calTaskId, Map<String, Object> paramsMap, Map<String, Object> extParamMap) {
+        return null;
+    }
+}

+ 22 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/onlineperf/plugin/form/OnlinePerfListPlugin.java

@@ -0,0 +1,22 @@
+package nckd.jxccl.swc.onlineperf.plugin.form;
+
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.list.plugin.AbstractListPlugin;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FormConstant;
+
+/**
+ * 标准单据列表插件
+ */
+public class OnlinePerfListPlugin extends AbstractListPlugin implements Plugin {
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
+        if(afterDoOperationEventArgs.getOperationResult() != null && afterDoOperationEventArgs.getOperationResult().isSuccess()){
+            String operateKey = afterDoOperationEventArgs.getOperateKey();
+            if(operateKey.equalsIgnoreCase("unlock")){
+                this.getView().invokeOperation(FormConstant.REFRESH_OP);
+            }
+        }
+    }
+}

+ 98 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/onlineperf/plugin/operate/UnLockOnlinePerfOpPlugin.java

@@ -0,0 +1,98 @@
+package nckd.jxccl.swc.onlineperf.plugin.operate;
+
+import kd.bos.dataentity.OperateOption;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.ExtendedDataEntity;
+import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.AddValidatorsEventArgs;
+import kd.bos.entity.plugin.PreparePropertysEventArgs;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.entity.validate.AbstractValidator;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.utils.DateUtil;
+import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+import nckd.jxccl.base.common.utils.StrFormatter;
+import nckd.jxccl.swc.constants.SwcConstant;
+import nckd.jxccl.swc.onlineperf.common.OnlinePerfConstant;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+* 解锁在线即时考核
+* 实体标识:nckd_onlineperf
+* @author W.Y.C
+* @date 2025/12/17 21:21
+* @version 1.0
+*/
+public class UnLockOnlinePerfOpPlugin extends AbstractOperationServicePlugIn implements Plugin {
+
+    @Override
+    public void onPreparePropertys(PreparePropertysEventArgs e) {
+        e.getFieldKeys().addAll(this.billEntityType.getAllFields().keySet());
+    }
+
+    @Override
+    public void onAddValidators(AddValidatorsEventArgs e) {
+        e.addValidator(new AbstractValidator() {
+            /*已创建	1
+            未计算	2
+            处理中	3
+            计算完成	9
+            已审核	7
+            审批处理中	8
+            审批不通过	5
+            审批通过	4
+            已废弃	6*/
+//            1、2、5、6
+            @Override
+            public void validate() {
+
+                for (ExtendedDataEntity dataEntity : this.getDataEntities()) {
+                    DynamicObject data = dataEntity.getDataEntity();
+                    boolean isCalDynLock = data.getBoolean(OnlinePerfConstant.NCKD_ISCALDYNLOCK);
+                    if(isCalDynLock) {
+                        long calRuleId = data.getLong(String.join(".", OnlinePerfConstant.NCKD_CALRULE, FormConstant.ID_KEY));
+                        int periodYear = data.getInt(OnlinePerfConstant.NCKD_PERIODYEAR);
+                        int periodMonth = data.getInt(OnlinePerfConstant.NCKD_PERIODMONTH);
+                        long orgId = data.getLong(String.join(".", OnlinePerfConstant.NCKD_ADMINORGUNIT, FormConstant.ID_KEY));
+                        LocalDateTime periodDate = LocalDateTime.of(periodYear, periodMonth, 1, 0, 0);
+                        LocalDateTime beginOfMonth = DateUtil.beginOfMonth(periodDate);
+                        LocalDateTime endOfMonth = DateUtil.endOfMonth(periodDate);
+
+                        QFilter qFilter = new QFilter(String.join(".", "calrule", FormConstant.ID_KEY), QCP.equals, calRuleId)
+                                .and("payrolldate", QCP.large_equals, DateUtil.toDate(beginOfMonth))
+                                .and("payrolldate", QCP.less_equals, DateUtil.toDate(endOfMonth))
+                                .and(String.join(".", FormConstant.ORG_KEY, FormConstant.ID_KEY), QCP.equals, orgId)
+                                .and("taskstatus", QCP.not_in, new String[]{"1", "2", "5", "6"});
+
+                        String selectProperties = QueryFieldBuilder.create().add(FormConstant.ID_KEY).add("taskstatus").buildSelect();
+                        DynamicObject[] load = SwcConstant.CALPAYROLLTASK_HELPER.load(selectProperties, new QFilter[]{qFilter});
+                        if (load != null && load.length > 0) {
+                            this.addFatalErrorMessage(dataEntity, "在线即时考核已被应用于薪酬核算,不能解锁");
+                        }
+                    }else{
+                        this.addFatalErrorMessage(dataEntity, "在线即时考核未锁定,不能解锁");
+                    }
+                }
+            }
+        });
+    }
+
+    @Override
+    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+        for (DynamicObject dataEntity : e.getDataEntities()) {
+            dataEntity.set(OnlinePerfConstant.NCKD_ISCALDYNLOCK, false);
+        }
+        SaveServiceHelper.saveOperate(OnlinePerfConstant.ONLINEPERF_ENTITYID, e.getDataEntities(), OperateOption.create());
+    }
+}