Преглед изворни кода

Merge remote-tracking branch 'origin/master'

jtd пре 4 дана
родитељ
комит
f9e87d5ff8
41 измењених фајлова са 2322 додато и 250 уклоњено
  1. 21 1
      code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/constant/FormConstant.java
  2. 84 0
      code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/entity/helper/EntityHelper.java
  3. 75 1
      code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/hrpi/helper/EmpPosOrgRelHelper.java
  4. 6 6
      code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/swc/helper/AdjFileServiceHelper.java
  5. 1 0
      code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/swc/helper/SWCHelper.java
  6. 17 16
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/plugin/operate/PushAdjustOpPlugin.java
  7. 0 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/ijp/business/.gitkeep
  8. 22 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/ijp/common/AppflgConstant.java
  9. 35 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/ijp/common/IntJobPostConstant.java
  10. 0 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/ijp/mservice/.gitkeep
  11. 119 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/ijp/plugin/form/recgen/IntJobPostFormPlugin.java
  12. 0 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/ijp/plugin/operate/.gitkeep
  13. 0 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/ijp/plugin/other/.gitkeep
  14. 0 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/ijp/plugin/report/.gitkeep
  15. 0 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/ijp/plugin/workflow/.gitkeep
  16. 0 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/ijp/webapi/.gitkeep
  17. 1 0
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/form/performance/PerfRankMgmtFormPlugin.java
  18. 107 76
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/file/PersonPosFileSaveOpPlugin.java
  19. 18 10
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/task/PsmsAdjustSalaryTask.java
  20. 337 0
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/print/EmployeePrintPlugin.java
  21. 118 0
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/print/PerfBatchPrintListPlugin.java
  22. 268 0
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/print/PerfDetailPrintPlugin.java
  23. 22 8
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/print/PrintPerfDetailReportListDataPlugin.java
  24. 64 0
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/print/SelectDatePrintFormPlugin.java
  25. 7 1
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/result/AnnualPerfDetailFormPlugin.java
  26. 116 63
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/operate/cycle/PerfManagerSaveOpPlugin.java
  27. 17 15
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/operate/salary/PushAdjustOpPlugin.java
  28. 12 16
      code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/operate/salary/SalaryAdjOpPlugin.java
  29. 2 3
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/sit/hcsi/opplugin/web/file/attach/SIBaseSaveOpEx.java
  30. 148 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hcdm/common/SwcAdjFileServiceHelper.java
  31. 41 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hcdm/mservice/SwcHCDMService.java
  32. 31 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hcdm/mservice/api/ISwcHCDMService.java
  33. 35 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hcdm/servicehelper/ServiceFactory.java
  34. 171 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hcss/formplugin/IncomeProofBillExPlugin.java
  35. 11 7
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hsbs/formplugin/web/basedata/salarygroup/PerSalaryGroupEdit.java
  36. 2 1
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hscs/business/custfetch/HasPosAllowDataService.java
  37. 8 6
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hscs/business/custfetch/PosSalaryGrade1.java
  38. 337 0
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hscs/common/PositionStructureConstant.java
  39. 1 1
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/init/business/SynPendingSalaryAdjDataServiceImpl.java
  40. 27 18
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/init/plugin/operate/BuildApplyBillOpPlugin.java
  41. 41 1
      code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/utils/SwcUtils.java

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

@@ -91,6 +91,20 @@ public class FormConstant {
     public static final String HSAS_CALPERSON = "hsas_calperson";
     /** 定调薪类型  实体标识 */
     public static final String HSBS_SALARYADJUSTRSN = "hsbs_salaryadjustrsn";
+    /** 定调薪类型  实体标识 */
+    public static final String HSBS_SALARYITEM = "hsbs_salaryitem";
+    /** 单据类型  实体标识 */
+    public static final String BOS_BILLTYPE = "bos_billtype";
+    /** 国家  实体标识 */
+    public static final String BD_COUNTRY = "bd_country";
+    /** 国家  实体标识 */
+    public static final String BD_CURRENCY = "bd_currency";
+    /** 定调薪方案 实体标识 */
+    public static final String HCDM_ADJAPPROVESCM = "hcdm_adjapprovescm";
+    /** 汇率标 实体标识 */
+    public static final String BD_EXRATETABLE = "bd_exratetable";
+    /** 频度 实体标识 */
+    public static final String HSBS_CALFREQUENCY = "hsbs_calfrequency";
     /**
      * 定调薪类型 默认值  用于  定调薪清单处理
      * */
@@ -463,6 +477,10 @@ public class FormConstant {
     public static final String PHONE_KEY = "phone";
     /** 参加工作日期 */
     public static final String NCKD_JOINWORKTIME = "nckd_joinworktime";
+    /** 参加工作日期 */
+    public static final String JOINWORKTIME_KEY = "joinworktime";
+    /** 新法定拟退休日期 */
+    public static final String NCKD_NEWPLANRETDT = "nckd_newplanretdt";
     /** 出生日期 */
     public static final String BIRTHDAY = "birthday";
     /** 性别 */
@@ -479,7 +497,9 @@ public class FormConstant {
 
 
     /** 岗位工资标准(jt002)*/
-    public static final Long STANDARDITEM_ID_KEY = 2321899710350111744L;
+    public static final String POS_STANDARD_ITEM_NUMBER = "jt002";
+    /** 员工调薪(console_20)*/
+    public static final String HCDM_APPLYBILL_BT_ADJ = "hcdm_applybill_BT_ADJ";
 
     /** 全职任职类型编码 */
     public static final String FULLSERVICE_NUMBER = "1010_S";

+ 84 - 0
code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/entity/helper/EntityHelper.java

@@ -1,16 +1,26 @@
 package nckd.jxccl.base.entity.helper;
 
+import com.google.common.collect.Lists;
 import kd.bos.common.enums.EnableEnum;
 import kd.bos.context.RequestContext;
 import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
 import kd.bos.entity.EntityMetadataCache;
 import kd.bos.entity.MainEntityType;
 import kd.bos.entity.constant.StatusEnum;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
 import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.QueryServiceHelper;
 import kd.bos.servicehelper.user.UserServiceHelper;
 import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
 
 import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * 实体(DynamicObject) 帮助类
@@ -75,4 +85,78 @@ public class EntityHelper {
         dynamicObject.set(FormConstant.ENABLE, EnableEnum.YES.getCode());
         return dynamicObject;
     }
+
+
+    /**
+     * 根据编码查询最新的id
+     * @param entityNumber
+     * @param number
+     */
+    public static Long getLatestIdByNumber(String entityNumber, String number) {
+        Map<String, Long> map = getLatestIdByNumber(entityNumber, Lists.newArrayList(number));
+        return !map.isEmpty() ? map.get(number) : null;
+    }
+
+    /**
+     * 根据编码查询最新的id
+     * @param entityNumber
+     * @param number
+     * @return
+     */
+    public static Map<String,Long> getLatestIdByNumber(String entityNumber, List<String> number) {
+        QFilter filter = new QFilter("number", QCP.in, number)
+                .and(QFilterCommonHelper.getCurrentVersionFilter())
+                .and(QFilterCommonHelper.getStatusFilter())
+                .and(QFilterCommonHelper.getEnableFilter());
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                .add(FormConstant.ID_KEY)
+                .add(FormConstant.NUMBER_KEY)
+                .add(FormConstant.MODIFY_TIME_KEY);
+        DynamicObjectCollection query = QueryServiceHelper.query(entityNumber, queryFieldBuilder.buildSelect(), new QFilter[]{filter});
+
+        // 按number分组,取每组的第一条(即最新的记录)
+        return query.stream()
+                .collect(Collectors.groupingBy(
+                        obj -> obj.getString(FormConstant.NUMBER_KEY)
+                ))
+                .entrySet()
+                .stream()
+                .collect(Collectors.toMap(
+                        Map.Entry::getKey,
+                        entry -> entry.getValue().get(0).getLong(FormConstant.ID_KEY) // 取每组第一条记录的ID
+                ));
+    }
+
+    /**
+     * 根据编码查询id
+     * @param entityNumber
+     * @param number
+     */
+    public static Long getIdByNumber(String entityNumber,String number) {
+        Map<String, Long> map = getIdByNumber(entityNumber, Lists.newArrayList(number));
+        return !map.isEmpty() ? map.get(number) : null;
+    }
+
+
+    /**
+     * 根据编码查询id
+     * @param entityNumber
+     * @param number
+     * @return
+     */
+    public static Map<String,Long> getIdByNumber(String entityNumber, List<String> number) {
+        QFilter filter = new QFilter("number", QCP.in, number)
+                .and(QFilterCommonHelper.getStatusFilter())
+                .and(QFilterCommonHelper.getEnableFilter());
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create().add(FormConstant.ID_KEY).add(FormConstant.NUMBER_KEY);
+        DynamicObjectCollection query = QueryServiceHelper.query(entityNumber, queryFieldBuilder.buildSelect(), new QFilter[]{filter});
+        return query.stream()
+                .collect(Collectors.toMap(
+                        obj -> obj.getString(FormConstant.NUMBER_KEY),  // key: number
+                        obj -> obj.getLong(FormConstant.ID_KEY)         // value: id
+                ));
+
+    }
+
+
 }

+ 75 - 1
code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/hrpi/helper/EmpPosOrgRelHelper.java

@@ -102,7 +102,42 @@ public class EmpPosOrgRelHelper {
     }
 
     /**
-     * 根据多个员工ID查询最新的任职经历信息
+     * 根据多个员工ID查询最新的任职经历信息(含不在岗)
+     *
+     * @param employeeIds 员工ID集合
+     * @return 员工的任职经历信息数组
+     * @author W.Y.C
+     * @date: 2025/11/04 16:02
+     */
+    public static Map<Long, DynamicObject> queryEmpPosOrgRelWithOutPostByEmployeesMap(Collection<Long> employeeIds) {
+        DynamicObject[] dynamicObjects = queryEmpPosOrgRelByEmployeesWithOutPost(employeeIds, null);
+        // 按员工ID分组,并取每个员工的最新记录(按开始日期)
+        Map<Long, List<DynamicObject>> grouped = new HashMap<>();
+        for (DynamicObject obj : dynamicObjects) {
+            Long empId = obj.getLong(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY));
+            grouped.computeIfAbsent(empId, k -> new ArrayList<>()).add(obj);
+        }
+
+        // 从每组中选取开始日期最新的记录
+        Map<Long, DynamicObject> result = new HashMap<>();
+        for (Map.Entry<Long, List<DynamicObject>> entry : grouped.entrySet()) {
+            List<DynamicObject> records = entry.getValue();
+            DynamicObject latestRecord = records.stream()
+                    .max((o1, o2) -> {
+                        Date date1 = o1.getDate(FormConstant.STARTDATE);
+                        Date date2 = o2.getDate(FormConstant.STARTDATE);
+                        return date1.compareTo(date2);
+                    })
+                    .orElse(null);
+            result.put(entry.getKey(), latestRecord);
+        }
+
+        return result;
+
+    }
+
+    /**
+     * 根据多个员工ID查询最新的任职经历信息(含不在岗)
      *
      * @param employeeIds 员工ID集合
      * @return 员工的任职经历信息数组
@@ -135,6 +170,7 @@ public class EmpPosOrgRelHelper {
         return result;
 
     }
+
     /**
      * 根据多个员工ID查询最新的任职经历信息(含历史)
      *
@@ -222,6 +258,44 @@ public class EmpPosOrgRelHelper {
         return BusinessDataServiceHelper.load(FormConstant.HRPI_EMPPOSORGREL, selectProperties, new QFilter[]{queryFilter}, order);
     }
 
+    /**
+     * 获取员工最新有效任职经历(含不在岗)
+     * 查询条件包括:
+     * 1. 员工ID在指定范围内
+     * 2. 是最新记录(IS_SEQLATESTRECORD=YES)
+     * 3. 未删除(IS_DELETED=NO)
+     * 4. 是主任职(IS_PRIMARY=YES)
+     *
+     * @param employeeIds 员工ID集合
+     * @param otherFilter 其他查询条件(可选)
+     * @return 员工的任职经历信息数组
+     * @author W.Y.C
+     * @date: 2025/11/04 16:02
+     */
+    public static DynamicObject[] queryEmpPosOrgRelByEmployeesWithOutPost(Collection<Long> employeeIds, QFilter otherFilter) {
+        // 构建基础查询条件
+
+        QFilter queryFilter = new QFilter(FormConstant.EMPLOYEE_KEY, QCP.in, employeeIds)
+                .and(FormConstant.IS_SEQLATESTRECORD, QCP.equals, EnableEnum.YES.getCode())
+                .and(FormConstant.IS_DELETED, QCP.equals, EnableEnum.NO.getCode())
+                .and(FormConstant.IS_PRIMARY, QCP.equals, EnableEnum.YES.getCode())
+                .and(FormConstant.STARTDATE, QCP.less_equals, new Date())
+                .and(FormConstant.ENDDATE, QCP.large_equals, new Date())
+                .and(FormConstant.ISCURRENTDATA, QCP.equals, EnableEnum.YES.getCode());
+
+        // 添加额外查询条件(如果有)
+        if (otherFilter != null) {
+            queryFilter.and(otherFilter);
+        }
+
+        // 构建查询字段和排序规则
+        String selectProperties = selectProperties().buildSelect();
+        String order = selectProperties().buildOrder();
+
+        // 执行查询并返回结果
+        return BusinessDataServiceHelper.load(FormConstant.HRPI_EMPPOSORGREL, selectProperties, new QFilter[]{queryFilter}, order);
+    }
+
     /**
      * 获取员工有效任职经历(含历史)
      * 查询条件包括:

+ 6 - 6
code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/swc/helper/AdjFileServiceHelper.java

@@ -5,7 +5,6 @@ import kd.bos.entity.validate.BillStatus;
 import kd.bos.logging.Log;
 import kd.bos.logging.LogFactory;
 import kd.bos.servicehelper.DispatchServiceHelper;
-import kd.sdk.swc.hcdm.business.helper.HCDMAdjFileServiceHelper;
 import nckd.jxccl.base.common.constant.FormConstant;
 import nckd.jxccl.base.common.utils.ConvertUtil;
 import nckd.jxccl.base.entity.helper.EntityHelper;
@@ -33,12 +32,13 @@ public class AdjFileServiceHelper {
     /**
      * 获取员工某个薪酬项目最新定调薪记录
      * @param personIds 人员id
-     * @param standardItemId 定调薪项目id
+     * @param standardItemNumber 定调薪项目编码
      * @return: java.util.List<nckd.jxccl.base.swc.helper.AdjFileServiceHelper.SalaryAdjustmentResult>
      * @author W.Y.C
      * @date: 2025/12/21 16:06
      */
-    public static List<SalaryAdjustmentResult> getLastDecAdjRecords(List<Long> personIds,Long standardItemId) {
+    public static List<SalaryAdjustmentResult> getLastDecAdjRecords(List<Long> personIds,String standardItemNumber) {
+        Long salaryItemId = EntityHelper.getIdByNumber(FormConstant.HSBS_STANDARDITEM, standardItemNumber);
         //获取员工最新任职
         Map<Long, DynamicObject> empPosOrgRelByEmployeesMap = EmpPosOrgRelHelper.queryEmpPosOrgRelByEmployeesMap(personIds);
         List<Long> allEmpPosOrgRelIds = empPosOrgRelByEmployeesMap.values().stream()
@@ -48,7 +48,7 @@ public class AdjFileServiceHelper {
         List<SalaryAdjustmentResult> salaryAdjustmentResultList = new ArrayList<>();
 
         DynamicObject standardItem = EntityHelper.newEntity(FormConstant.HSBS_STANDARDITEM);
-        standardItem.set(FormConstant.ID_KEY, standardItemId);
+        standardItem.set(FormConstant.ID_KEY, salaryItemId);
         Map<String, Object> adjFileParams = new HashMap<>();
         adjFileParams.put("employees", personIds);
         List<String> status = new ArrayList<>();
@@ -75,7 +75,7 @@ public class AdjFileServiceHelper {
                 // 调薪档案ID
                 dataItem.put("adjfile", adjFileId);
                 // 调薪项目ID
-                dataItem.put("standarditem", standardItemId);
+                dataItem.put("standarditem", salaryItemId);
                 // 查询基准日期
                 dataItem.put("startdate", new Date());
                 // 唯一标识
@@ -86,7 +86,7 @@ public class AdjFileServiceHelper {
             adjRecordParams.put("selprops", "salarystdv.rankentry.rank.id,salarystdv.rankentry.rank.name,salarystdv.rankentry.rank.number,salarystdv.rankentry.rank.index,salarystdv.rankentry.frankindex,company.id,company.name,hcdmorg.id,");
             //查询定调薪记录
             //hcdm_decadjrecor
-            Map<String, Object> lastDecAdjRecordMap = HCDMAdjFileServiceHelper.getLastDecAdjRecords(adjRecordParams);
+            Map<String, Object> lastDecAdjRecordMap = DispatchServiceHelper.invokeService("nckd.jxccl.swc.hcdm.servicehelper", "hcdm", "ISwcHCDMService", "getLastDecAdjRecords", adjRecordParams);
             if (ConvertUtil.toBoolean(lastDecAdjRecordMap.get("success"))) {
                 List<Map> datas = ConvertUtil.toList(lastDecAdjRecordMap.get("data"), ArrayList::new);
                 for (Map data : datas) {

+ 1 - 0
code/base/nckd-jxccl-base-helper/src/main/java/nckd/jxccl/base/swc/helper/SWCHelper.java

@@ -1,5 +1,6 @@
 package nckd.jxccl.base.swc.helper;
 
+import com.google.common.collect.Lists;
 import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.dataentity.entity.DynamicObjectCollection;
 import kd.bos.entity.tree.TreeNode;

+ 17 - 16
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/excells/plugin/operate/PushAdjustOpPlugin.java

@@ -1,25 +1,19 @@
 package nckd.jxccl.hr.excells.plugin.operate;
 
 import com.alibaba.fastjson.JSON;
-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.db.tx.TX;
 import kd.bos.db.tx.TXHandle;
 import kd.bos.entity.EntityMetadataCache;
 import kd.bos.entity.MainEntityType;
-import kd.bos.entity.operate.result.IOperateInfo;
-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.AfterOperationArgs;
 import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
 import kd.bos.entity.validate.BillStatus;
 import kd.bos.logging.Log;
 import kd.bos.logging.LogFactory;
-import kd.bos.servicehelper.BusinessDataServiceHelper;
 import kd.bos.servicehelper.DispatchServiceHelper;
 import kd.bos.servicehelper.operation.SaveServiceHelper;
 import kd.sdk.plugin.Plugin;
@@ -29,9 +23,9 @@ import nckd.jxccl.base.common.exception.ValidationException;
 import nckd.jxccl.base.common.utils.ConvertUtil;
 import nckd.jxccl.base.common.utils.DateUtil;
 import nckd.jxccl.base.common.utils.StrFormatter;
+import nckd.jxccl.base.entity.helper.EntityHelper;
 import nckd.jxccl.base.hrpi.helper.EmpPosOrgRelHelper;
 import nckd.jxccl.hr.excells.common.ExcellsConstant;
-import nckd.jxccl.hr.hstu.common.HonorStudentConstant;
 import nckd.jxccl.hr.psms.common.PositionStructureConstant;
 
 import java.util.ArrayList;
@@ -39,7 +33,6 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.StringJoiner;
 import java.util.stream.Collectors;
 
 /**
@@ -65,6 +58,14 @@ public class PushAdjustOpPlugin extends AbstractOperationServicePlugIn implement
 
     @Override
     public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+        Long salaryItemId = EntityHelper.getIdByNumber(FormConstant.HSBS_STANDARDITEM, "jt007");
+        Long billTypeId = EntityHelper.getIdByNumber(FormConstant.BOS_BILLTYPE, FormConstant.HCDM_APPLYBILL_BT_ADJ);
+        Long countryId = EntityHelper.getIdByNumber(FormConstant.BD_COUNTRY, "001");
+        Long salaryAdjuStrSnId = EntityHelper.getIdByNumber(FormConstant.HSBS_SALARYADJUSTRSN, "youxiusheng");
+        Long currencyId = EntityHelper.getIdByNumber(FormConstant.BD_CURRENCY, "CNY");
+        Long adjApproveScmId = EntityHelper.getLatestIdByNumber(FormConstant.HCDM_ADJAPPROVESCM, "dingtiaoxin");
+        Long exRateTableId = EntityHelper.getIdByNumber(FormConstant.BD_EXRATETABLE, "ERT-01");
+        Long calFrequencyId = EntityHelper.getIdByNumber(FormConstant.HSBS_CALFREQUENCY, "000_m_001");
 
         List<Long> ids = new ArrayList<>();
         List<Long> personIds = new ArrayList<>();
@@ -127,19 +128,19 @@ public class PushAdjustOpPlugin extends AbstractOperationServicePlugIn implement
                 applyBill.put("_uniquecode", data.getLong(FormConstant.ID_KEY));
                 applyBill.put("org", orgId);
                 //定调薪明细字段显示方案   调薪明细字段
-                applyBill.put("billtype", 2215975998602655744L);
+                applyBill.put("billtype", billTypeId);
                 //国家
-                applyBill.put("billcountry", 1000001L);
+                applyBill.put("billcountry", countryId);
                 //定调薪类型(优秀生津贴)
-                applyBill.put("salaryadjrsn", 2352338051369287680L);
+                applyBill.put("salaryadjrsn", salaryAdjuStrSnId);
                 //默认币种
-                applyBill.put("billcurrency", 1L);
+                applyBill.put("billcurrency", currencyId);
                 //定调薪方案
-                applyBill.put("salaryadjscm", 2322515162646457344L);
+                applyBill.put("salaryadjscm", adjApproveScmId);
                 //汇率日期
                 applyBill.put("exchangeratedate", new Date());
                 //汇率表
-                applyBill.put("exctable", 2321965096026258432L);
+                applyBill.put("exctable", exRateTableId);
                 //默认生效日期
                 applyBill.put("effectivedate", data.getDate(FormConstant.CREATE_TIME_KEY));
                 //草稿状态
@@ -155,8 +156,8 @@ public class PushAdjustOpPlugin extends AbstractOperationServicePlugIn implement
                 Map<String, Object> applyBillEntry = new HashMap<>();
                 applyBillEntry.put("adjfile", adjFileId);
                 applyBillEntry.put("employee", employeeId);
-                applyBillEntry.put("standarditem", 2321901326927149056L);    //定调薪项目
-                applyBillEntry.put("frequency", 1095454108284088320L);       //频度  月
+                applyBillEntry.put("standarditem", salaryItemId);    //定调薪项目
+                applyBillEntry.put("frequency", calFrequencyId);       //频度  月
                 applyBillEntry.put("amount", entity.getBigDecimal(FormConstant.NCKD_MONEY));
                 applyBillEntry.put("position", position.getLong(FormConstant.ID_KEY));
                 applyBillEntry.put("reason", entity.getString(ExcellsConstant.NCKD_DESC));

+ 0 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/ijp/business/.gitkeep


+ 22 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/ijp/common/AppflgConstant.java

@@ -0,0 +1,22 @@
+/**
+ * This is a kingdee cosmic template project that is automatically generated by the Kingdee cosmic development assistant plugin. 
+ * If there are any issues during the use process, you can provide feedback to the kingdee developer community website.
+ * Website: https://developer.kingdee.com/developer?productLineId=29
+ * Author: liebin.zheng
+ * Generate Date: 2025-05-26 16:28:10
+ */
+package nckd.jxccl.hr.ijp.common;
+
+/**
+ * hr云init应用-通用常量类<br>
+ * 代码中不能存在硬编码敏感信息,如账号、密码、http外链、ftp外链、邮箱等。<br>
+ * 标识或缓存的常量,需以"KEY_"、"FID_"、"ENTRY_"或"SUBENTRY_"作为变量的前缀。<br>
+ *
+ * @author nckd
+ * @date 2025-05-26 16:28:10
+ */
+public class AppflgConstant {
+	
+	public static final String KEY_APP_NAME = "hr-init";
+
+}

+ 35 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/ijp/common/IntJobPostConstant.java

@@ -0,0 +1,35 @@
+package nckd.jxccl.hr.ijp.common;
+
+import nckd.jxccl.base.common.constant.FormConstant;
+
+/**
+ * 三类人员记录生成常量类
+ *
+ * @author W.Y.C
+ * @version 1.0
+ * @date 2026-01-07 11:44:49
+ */
+public class IntJobPostConstant extends FormConstant {
+    /** 三类人员记录生成-实体标识 */
+    public static final String INTJOBPOST_ENTITYID = "nckd_intjobpost";
+    /** 所属年度 */
+    public static final String NCKD_YEAR = "nckd_year";
+    /** 进入市场时间 */
+    public static final String NCKD_BIZDAY = "nckd_bizday";
+    /** 员工类别 */
+    public static final String NCKD_TALENTTYPE = "nckd_talenttype";
+    /** 单据体 */
+    public static final String NCKD_ENTRYENTITY = "nckd_entryentity";
+    /** 姓名 */
+    public static final String NCKD_EMPLOYEEFIELD = "nckd_employeefield";
+    /** 上上年度考核结果 */
+    public static final String NCKD_BEFORELAST = "nckd_beforelast";
+    /** 上年度考核结果 */
+    public static final String NCKD_APPRAISALRESULT = "nckd_appraisalresult";
+    /** 是否进入市场 */
+    public static final String NCKD_ISENTER = "nckd_isenter";
+    /** 是否手动新增 */
+    public static final String NCKD_ISJOG = "nckd_isjog";
+    /** 获取员工 */
+    public static final String FETCHEMP_OP = "fetchemp";
+}

+ 0 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/ijp/mservice/.gitkeep


+ 119 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/ijp/plugin/form/recgen/IntJobPostFormPlugin.java

@@ -0,0 +1,119 @@
+package nckd.jxccl.hr.ijp.plugin.form.recgen;
+
+import kd.bos.common.enums.EnableEnum;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.EntityMetadataCache;
+import kd.bos.entity.QueryEntityType;
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.hr.hbp.business.servicehelper.HRQueryEntityHelper;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.utils.ConvertUtil;
+import nckd.jxccl.base.common.utils.DateUtil;
+import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
+import nckd.jxccl.hr.ijp.common.IntJobPostConstant;
+import org.apache.commons.lang3.StringUtils;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+* 三类人员记录生成
+* 实体标识:nckd_intjobpost
+* @author W.Y.C
+* @date 2026/1/7 11:41
+* @version 1.0
+*/
+public class IntJobPostFormPlugin extends AbstractFormPlugin implements Plugin {
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs evt) {
+        if(evt.getOperationResult() != null && evt.getOperationResult().isSuccess()){
+            String operateKey = evt.getOperateKey();
+            if(IntJobPostConstant.FETCHEMP_OP.equalsIgnoreCase(operateKey)){
+                String talentType = ConvertUtil.toStr(this.getModel().getValue(IntJobPostConstant.NCKD_TALENTTYPE));
+                DynamicObject org = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(IntJobPostConstant.NCKD_ORG));
+                if(StringUtils.isBlank(talentType)){
+                    this.getView().showTipNotification("请先选择人员类别!");
+                }else if(org == null){
+                    this.getView().showTipNotification("请先选择二级单位!");
+                }else{
+                    if("A".equalsIgnoreCase(talentType)){
+                        getExcellentEmp();
+                    }else if("B".equalsIgnoreCase(talentType)){
+
+                    }else{
+
+                    }
+                }
+            }
+        }
+    }
+
+    //获取优秀生员工
+    //本单位工作(工作信息-进本单位时间)满5年,距法定退休年龄(工作信息-新法定退休日期)超过5年且上年度员工绩效考核为优秀的所有员工
+    private void getExcellentEmp(){
+        DynamicObject org = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(IntJobPostConstant.NCKD_ORG));
+        //前5年
+        LocalDateTime firstFiveYears = DateUtil.minusYears(DateUtil.now(), 5);
+        //后5年
+        LocalDateTime fiveYearsLater = DateUtil.addYears(DateUtil.now(), 5);
+
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                .add(FormConstant.ID_KEY)
+                .add(FormConstant.STARTDATE)
+                .addIdNumberName(FormConstant.ADMINORG)
+                .addIdNumberName(FormConstant.POSITION_KEY)
+                .addGroup(new String[]{FormConstant.EMPLOYEE_KEY}, FormConstant.ID_KEY, FormConstant.NAME_KEY, FormConstant.EMP_NUMBER_KEY)
+                .orderDesc(FormConstant.STARTDATE);
+
+        QFilter qFilter = new QFilter(String.join(".", FormConstant.ADMINORG, FormConstant.NCKD_SECONDORG), QCP.equals, org.getLong(FormConstant.ID_KEY))
+                .and(QFilterCommonHelper.getValidDateFilter(FormConstant.STARTDATE, FormConstant.ENDDATE))
+                //任职类型:上挂/全职任职
+                .and(String.join( ".", FormConstant.POSTYPE, FormConstant.NUMBER_KEY), QCP.in,new String[]{"JTCC_1002", "1010_S"})
+                //在职人员
+                .and(String.join(".", FormConstant.HRPI_EMPENTREL, FormConstant.LABOR_REL_STATUS, FormConstant.IS_HIRED), QCP.equals, EnableEnum.YES.getCode())
+                //进本单位满5年
+                .and(String.join(".", FormConstant.HRPI_EMPENTREL, FormConstant.STARTDATE), QCP.less_equals, DateUtil.toDate(firstFiveYears));
+                //新法定退休日期超过5年条件,或退休日期为空
+        QFilter lanRetDtFilter = new QFilter(String.join(".", FormConstant.HRPI_PERSERLEN, FormConstant.NCKD_NEWPLANRETDT), QCP.is_null,null)
+                .or(String.join(".", FormConstant.HRPI_PERSERLEN, FormConstant.NCKD_NEWPLANRETDT), QCP.large_equals, DateUtil.toDate(fiveYearsLater));
+        qFilter.and(lanRetDtFilter);
+        QueryEntityType queryEntityType = (QueryEntityType) EntityMetadataCache.getDataEntityType("personfilequery");
+        DynamicObjectCollection personList = HRQueryEntityHelper.getInstance().getQueryDyoColl(queryEntityType, queryFieldBuilder.buildSelect(), new QFilter[]{qFilter}, queryFieldBuilder.buildOrder());
+        Map<Long, DynamicObject> personMap = personList.stream()
+                .collect(Collectors.groupingBy(
+                        obj -> obj.getLong(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY))
+                ))
+                .entrySet()
+                .stream()
+                .collect(Collectors.toMap(
+                        Map.Entry::getKey,
+                        entry -> entry.getValue().get(0) // 由于已按日期降序排列,取第一条即为最新
+                ));
+
+        //获取上年和上上年考核结果
+        QueryFieldBuilder perfManagerQueryFieldBuilder = QueryFieldBuilder.create()
+                .addIdNumberName("nckd_appraisalresult")
+                .add("nckd_appraisalyear");
+
+        Date beginDate = DateUtil.beginOfYear(DateUtil.minusYears(DateUtil.nowDate(), 2));
+        Date endDate = DateUtil.endOfYear(DateUtil.minusYears(DateUtil.nowDate(), 1));
+        QFilter perfManagerFilter = new QFilter("nckd_appraisalyear",QCP.large_equals,beginDate)
+                .and("nckd_appraisalyear",QCP.less_equals,endDate)
+                .and(String.join(".", "nckd_perfmanager", FormConstant.NCKD_PERSON), QCP.in, personMap.keySet());
+        DynamicObjectCollection query = QueryServiceHelper.query("nckd_perfmanagerentry", perfManagerQueryFieldBuilder.buildSelect(), new QFilter[]{perfManagerFilter});
+        for (DynamicObject dynamicObject : query) {
+            
+        }
+
+    }
+}

+ 0 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/ijp/plugin/operate/.gitkeep


+ 0 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/ijp/plugin/other/.gitkeep


+ 0 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/ijp/plugin/report/.gitkeep


+ 0 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/ijp/plugin/workflow/.gitkeep


+ 0 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/ijp/webapi/.gitkeep


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

@@ -499,6 +499,7 @@ public class PerfRankMgmtFormPlugin extends AbstractFormPlugin implements Wizard
                 QFilter qFilter = new QFilter(String.join(".",FormConstant.ADMINORG, FormConstant.STRUCTLONGNUMBER), QCP.like, structLongNumber + "%")
                         .and(FormConstant.STARTDATE, QCP.less_equals, targetDate)
                         .and(FormConstant.ENDDATE, QCP.large_equals, targetDate)
+                        //任职类型:上挂全职任职
                         .and(String.join( ".", FormConstant.POSTYPE, FormConstant.NUMBER_KEY), QCP.in,new String[]{"JTCC_1002", "1010_S"});
 
                 //在职人员

+ 107 - 76
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/plugin/operate/file/PersonPosFileSaveOpPlugin.java

@@ -11,14 +11,14 @@ 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.DispatchServiceHelper;
 import kd.bos.servicehelper.QueryServiceHelper;
 import kd.sdk.plugin.Plugin;
-import kd.sdk.swc.hcdm.business.helper.HCDMSalaryStdServiceHelper;
-import kd.sdk.swc.hcdm.common.dto.stdtab.match.StdTableDataMatchParam;
-import kd.sdk.swc.hcdm.common.dto.stdtab.match.StdTableDataMatchResult;
 import nckd.jxccl.base.common.constant.FormConstant;
 import nckd.jxccl.base.common.enums.psms.TypeStateEnum;
+import nckd.jxccl.base.common.utils.ConvertUtil;
 import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+import nckd.jxccl.base.entity.helper.EntityHelper;
 import nckd.jxccl.base.swc.helper.AdjFileServiceHelper;
 import nckd.jxccl.hr.psms.common.PositionStructureConstant;
 
@@ -29,7 +29,6 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 /**
 * 员工职位档案-保存
@@ -46,6 +45,7 @@ public class PersonPosFileSaveOpPlugin extends AbstractOperationServicePlugIn im
 
     @Override
     public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+        logger.info("beginOperationTransaction start: processing {} data entities", e.getDataEntities().length);
 
         //职位津贴=职位系数 X 所在岗级岗位工资一档金额
         List<Long> allPersonIds = new ArrayList<>(e.getDataEntities().length);
@@ -68,92 +68,123 @@ public class PersonPosFileSaveOpPlugin extends AbstractOperationServicePlugIn im
                 }
             }
         }
+        
+        logger.info("Collected person IDs count: {}, job level IDs count: {}", allPersonIds.size(), jobLevelIds.size());
 
         //====================================== 获取当前人员所在定调的岗位标准工资一档金额 begin ======================================
-        Map<Long, BigDecimal> amountMap = new HashMap<>(e.getDataEntities().length);
-        if(!allPersonIds.isEmpty() && !jobLevelIds.isEmpty()) {
-            //获取人员最新岗位工资标准定薪记录
-            List<AdjFileServiceHelper.SalaryAdjustmentResult> salaryAdjustmentResultList = AdjFileServiceHelper.getLastDecAdjRecords(allPersonIds, FormConstant.STANDARDITEM_ID_KEY);
-            if (!salaryAdjustmentResultList.isEmpty()) {
-                //薪酬标准ID
-                List<Long> salaryStIds = salaryAdjustmentResultList.stream().map(result -> result.salaryStDv.getLong(FormConstant.ID_KEY)).collect(Collectors.toList());
-                QFilter filter = new QFilter(FormConstant.ID_KEY, QCP.in, salaryStIds)
-                        .and(String.join(".", "rankentry", "rank", FormConstant.NUMBER_KEY), QCP.equals, "01");
-                //获取标准表中01档的薪档
-                QueryFieldBuilder salaryStandFieldBuilder = QueryFieldBuilder.create()
-                        .add(FormConstant.ID_KEY)
-                        .addIdNumberNameWithExtras(new String[]{"rankentry", "rank"},FormConstant.INDEX_KEY);
-                DynamicObjectCollection salaryStandardColl = QueryServiceHelper.query("hcdm_salarystandard", salaryStandFieldBuilder.buildSelect(), new QFilter[]{filter});
-                Map<Long, DynamicObject> salaryStandardMap = salaryStandardColl.stream()
-                        .collect(Collectors.toMap(
-                                obj -> obj.getLong(FormConstant.ID_KEY),
-                                obj -> obj
-                        ));
+        try {
+            Long salaryItemId = EntityHelper.getIdByNumber(FormConstant.HSBS_STANDARDITEM, FormConstant.POS_STANDARD_ITEM_NUMBER);
+            logger.info("Retrieved salary item ID: {}", salaryItemId);
+            
+            Map<Long, BigDecimal> amountMap = new HashMap<>(e.getDataEntities().length);
+            if (!allPersonIds.isEmpty() && !jobLevelIds.isEmpty()) {
+                logger.info("Processing salary adjustment records for {} person IDs", allPersonIds.size());
+                
+                //获取人员最新岗位工资标准定薪记录
+                List<AdjFileServiceHelper.SalaryAdjustmentResult> salaryAdjustmentResultList = AdjFileServiceHelper.getLastDecAdjRecords(allPersonIds, FormConstant.POS_STANDARD_ITEM_NUMBER);
+                logger.info("Retrieved {} salary adjustment results", salaryAdjustmentResultList.size());
+                
+                if (!salaryAdjustmentResultList.isEmpty()) {
+                    //薪酬标准ID
+                    List<Long> salaryStIds = salaryAdjustmentResultList.stream().map(result -> result.salaryStDv.getLong(FormConstant.ID_KEY)).collect(Collectors.toList());
+                    logger.info("Retrieved salary standard IDs: {}", salaryStIds.size());
+                    
+                    QFilter filter = new QFilter(FormConstant.ID_KEY, QCP.in, salaryStIds)
+                            .and(String.join(".", "rankentry", "rank", FormConstant.NUMBER_KEY), QCP.equals, "01");
+                    //获取标准表中01档的薪档
+                    QueryFieldBuilder salaryStandFieldBuilder = QueryFieldBuilder.create()
+                            .add(FormConstant.ID_KEY)
+                            .addIdNumberNameWithExtras(new String[]{"rankentry", "rank"}, FormConstant.INDEX_KEY);
+                    DynamicObjectCollection salaryStandardColl = QueryServiceHelper.query("hcdm_salarystandard", salaryStandFieldBuilder.buildSelect(), new QFilter[]{filter});
+                    logger.info("Retrieved {} salary standard records", salaryStandardColl.size());
+                    
+                    Map<Long, DynamicObject> salaryStandardMap = salaryStandardColl.stream()
+                            .collect(Collectors.toMap(
+                                    obj -> obj.getLong(FormConstant.ID_KEY),
+                                    obj -> obj
+                            ));
+
+                    if (!salaryStandardMap.isEmpty()) {
+                        logger.info("Created salary standard map with {} entries", salaryStandardMap.size());
+                        List<Map<String,Object>> matchParams = new ArrayList<>();
+                        for (AdjFileServiceHelper.SalaryAdjustmentResult result : salaryAdjustmentResultList) {
+                            Map<String,Object> stdTableDataMatchParam = new HashMap<>();
 
-                if (!salaryStandardMap.isEmpty()) {
-                    List<StdTableDataMatchParam> matchParams = new ArrayList<>();
-                    for (AdjFileServiceHelper.SalaryAdjustmentResult result : salaryAdjustmentResultList) {
-                        StdTableDataMatchParam stdTableDataMatchParam = new StdTableDataMatchParam();
-                        stdTableDataMatchParam.setStdTableId(result.salaryStDv.getLong(FormConstant.ID_KEY));
-                        stdTableDataMatchParam.setStdItemId(FormConstant.STANDARDITEM_ID_KEY);
-                        stdTableDataMatchParam.setGradeId(result.salaryGrade.getLong(FormConstant.ID_KEY));
-                        DynamicObject dynamicObject = salaryStandardMap.get(result.salaryStDv.getLong(FormConstant.ID_KEY));
-                        if(dynamicObject != null) {
-                            long rankId = dynamicObject.getLong(String.join(".", "rankentry", "rank", FormConstant.ID_KEY));
-                            stdTableDataMatchParam.setRankId(rankId);
-                            matchParams.add(stdTableDataMatchParam);
+                            stdTableDataMatchParam.put("stdTableId",result.salaryStDv.getLong(FormConstant.ID_KEY));
+                            stdTableDataMatchParam.put("stdItemId",salaryItemId);
+                            stdTableDataMatchParam.put("gradeId",result.salaryGrade.getLong(FormConstant.ID_KEY));
+                            DynamicObject dynamicObject = salaryStandardMap.get(result.salaryStDv.getLong(FormConstant.ID_KEY));
+                            if (dynamicObject != null) {
+                                long rankId = dynamicObject.getLong(String.join(".", "rankentry", "rank", FormConstant.ID_KEY));
+                                stdTableDataMatchParam.put("rankId",result.salaryGrade.getLong(FormConstant.ID_KEY));
+                                matchParams.add(stdTableDataMatchParam);
+                            }
                         }
-                    }
-                    if(!matchParams.isEmpty()) {
-                        //获取薪酬项目、薪等、薪档对应金额(入参params的数组下标和出参的数组下标一一对应)
-                        List<StdTableDataMatchResult> stdTableDataMatchResults = HCDMSalaryStdServiceHelper.matchStdTableData(matchParams);
-                        for (int i = 0; i < salaryAdjustmentResultList.size(); i++) {
-                            AdjFileServiceHelper.SalaryAdjustmentResult result = salaryAdjustmentResultList.get(i);
-                            if (i < stdTableDataMatchResults.size() && stdTableDataMatchResults.get(i) != null) {
-                                //当前薪等01档的金额
-                                amountMap.put(result.employee.getLong(FormConstant.ID_KEY), stdTableDataMatchResults.get(i).getAmount());
+                        logger.info("Created {} match parameters", matchParams.size());
+                        
+                        if (!matchParams.isEmpty()) {
+                            //获取薪酬项目、薪等、薪档对应金额(入参params的数组下标和出参的数组下标一一对应)
+//                            List<StdTableDataMatchResult> stdTableDataMatchResults = HCDMSalaryStdServiceHelper.matchStdTableData(matchParams);
+                            List<Map<String,Object>> stdTableDataMatchResults = DispatchServiceHelper.invokeService("nckd.jxccl.swc.hcdm.servicehelper", "hcdm", "ISwcHCDMService", "matchStdTableData", matchParams);
+                            logger.info("Retrieved {} standard table match results", stdTableDataMatchResults.size());
+                            
+                            for (int i = 0; i < salaryAdjustmentResultList.size(); i++) {
+                                AdjFileServiceHelper.SalaryAdjustmentResult result = salaryAdjustmentResultList.get(i);
+                                if (i < stdTableDataMatchResults.size() && stdTableDataMatchResults.get(i) != null) {
+                                    //当前薪等01档的金额
+                                    amountMap.put(result.employee.getLong(FormConstant.ID_KEY), ConvertUtil.toBigDecimal(stdTableDataMatchResults.get(i).get("amount")));
+                                }
                             }
+                            logger.info("Populated amount map with {} entries", amountMap.size());
                         }
+                    } else {
+                        logger.warn("未获取薪酬标准表中01档的薪档数据,薪酬标准ID:{}", salaryStIds);
                     }
                 } else {
-                    logger.warn("未获取薪酬标准表中01档的薪档数据,薪酬标准ID:{}",salaryStIds);
+                    logger.warn("未获取到人员岗位工资标准定薪记录,人员ID:{}", allPersonIds);
                 }
-            } else {
-                logger.warn("未获取到人员岗位工资标准定薪记录,人员ID:{}",allPersonIds);
             }
-        }
-        //====================================== 获取当前人员所在定调的岗位标准工资一档金额 end ======================================
-        Map<Long, DynamicObject> jobLevelMap = new HashMap<>(e.getDataEntities().length);
-        if(!jobLevelIds.isEmpty()) {
-            MainEntityType jobLevelEntityType = EntityMetadataCache.getDataEntityType(FormConstant.HBJM_JOBLEVELHR);
-            //重新加载职级信息,避免获取不到系数
-            DynamicObject[] load = BusinessDataServiceHelper.load(jobLevelIds.toArray(new Long[0]), jobLevelEntityType);
-            jobLevelMap = Arrays.stream(load)
-                    .collect(Collectors.toMap(
-                            obj -> obj.getLong(FormConstant.ID_KEY),
-                            obj -> obj
-                    ));
-        }
+            //====================================== 获取当前人员所在定调的岗位标准工资一档金额 end ======================================
+            Map<Long, DynamicObject> jobLevelMap = new HashMap<>(e.getDataEntities().length);
+            if (!jobLevelIds.isEmpty()) {
+                logger.info("Loading job level information for {} IDs", jobLevelIds.size());
+                MainEntityType jobLevelEntityType = EntityMetadataCache.getDataEntityType(FormConstant.HBJM_JOBLEVELHR);
+                //重新加载职级信息,避免获取不到系数
+                DynamicObject[] load = BusinessDataServiceHelper.load(jobLevelIds.toArray(new Long[0]), jobLevelEntityType);
+                jobLevelMap = Arrays.stream(load)
+                        .collect(Collectors.toMap(
+                                obj -> obj.getLong(FormConstant.ID_KEY),
+                                obj -> obj
+                        ));
+                logger.info("Loaded {} job level records", jobLevelMap.size());
+            }
 
-        for (DynamicObject dataEntity : e.getDataEntities()) {
-            long jobLevelId = dataEntity.getLong(String.join(".", PositionStructureConstant.NCKD_JOBLEVELHR, FormConstant.ID_KEY));
-            DynamicObject jobLevel = jobLevelMap.get(jobLevelId);
-            if(jobLevel != null){
-                DynamicObject person = dataEntity.getDynamicObject(FormConstant.NCKD_PERSON);
-                long personId = person.getLong(FormConstant.ID_KEY);
-                //当前岗位工资01档金额
-                BigDecimal amount = amountMap.get(personId);
-                if (amount != null && amount.compareTo(BigDecimal.ZERO) > 0) {
-                    BigDecimal coefficient = jobLevel.getBigDecimal(PositionStructureConstant.NCKD_COEFFICIENT);
-                    if(coefficient.compareTo(BigDecimal.ZERO) > 0) {
-                        dataEntity.set(PositionStructureConstant.NCKD_COEFFICIENT, coefficient);
-                        dataEntity.set(PositionStructureConstant.NCKD_CURRENTPOSTSALARY, amount);
-                        dataEntity.set(PositionStructureConstant.NCKD_POSTALLOWANCE, coefficient.multiply(amount));
+            logger.info("Processing {} data entities for coefficient and salary calculation", e.getDataEntities().length);
+            for (DynamicObject dataEntity : e.getDataEntities()) {
+                long jobLevelId = dataEntity.getLong(String.join(".", PositionStructureConstant.NCKD_JOBLEVELHR, FormConstant.ID_KEY));
+                DynamicObject jobLevel = jobLevelMap.get(jobLevelId);
+                if (jobLevel != null) {
+                    DynamicObject person = dataEntity.getDynamicObject(FormConstant.NCKD_PERSON);
+                    long personId = person.getLong(FormConstant.ID_KEY);
+                    //当前岗位工资01档金额
+                    BigDecimal amount = amountMap.get(personId);
+                    if (amount != null && amount.compareTo(BigDecimal.ZERO) > 0) {
+                        BigDecimal coefficient = jobLevel.getBigDecimal(PositionStructureConstant.NCKD_COEFFICIENT);
+                        if (coefficient.compareTo(BigDecimal.ZERO) > 0) {
+                            dataEntity.set(PositionStructureConstant.NCKD_COEFFICIENT, coefficient);
+                            dataEntity.set(PositionStructureConstant.NCKD_CURRENTPOSTSALARY, amount);
+                            dataEntity.set(PositionStructureConstant.NCKD_POSTALLOWANCE, coefficient.multiply(amount));
+                            logger.info("Updated person ID: {}, coefficient: {}, current post salary: {}, post allowance: {}", 
+                                personId, coefficient, amount, coefficient.multiply(amount));
+                        }
+                    } else {
+                        logger.warn("未获取到员工【{}】最新岗位工资标准定薪记录01档的薪等金额,人员ID:{}", person.getString(FormConstant.NAME_KEY), personId);
                     }
-                } else {
-                    logger.warn("未获取到员工【{}】最新岗位工资标准定薪记录01档的薪等金额,人员ID:", person.getString(FormConstant.NAME_KEY));
                 }
             }
+            logger.info("beginOperationTransaction completed successfully");
+        }catch (Exception e1){
+            logger.error("获取人员岗位工资标准定薪记录01档的薪等金额异常", e1);
         }
     }
 

+ 18 - 10
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/task/PsmsAdjustSalaryTask.java

@@ -30,6 +30,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.entity.helper.EntityHelper;
 import nckd.jxccl.base.swc.helper.AdjFileServiceHelper;
 import nckd.jxccl.hr.psms.common.PositionStructureConstant;
 
@@ -62,7 +63,14 @@ public class PsmsAdjustSalaryTask extends AbstractTask implements Plugin {
     @Override
     public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
         logger.info("开始执行职位体系推送薪酬任务, 参数: {}", JSON.toJSONString(map));
-        
+        Long salaryItemId = EntityHelper.getIdByNumber(FormConstant.HSBS_STANDARDITEM, "jt008");
+        Long billTypeId = EntityHelper.getIdByNumber(FormConstant.BOS_BILLTYPE, FormConstant.HCDM_APPLYBILL_BT_ADJ);
+        Long countryId = EntityHelper.getIdByNumber(FormConstant.BD_COUNTRY, "001");
+        Long salaryAdjuStrSnId = EntityHelper.getIdByNumber(FormConstant.HSBS_SALARYADJUSTRSN, "zhijibiandong");
+        Long currencyId = EntityHelper.getIdByNumber(FormConstant.BD_CURRENCY, "CNY");
+        Long adjApproveScmId = EntityHelper.getLatestIdByNumber(FormConstant.HCDM_ADJAPPROVESCM, "dingtiaoxin");
+        Long exRateTableId = EntityHelper.getIdByNumber(FormConstant.BD_EXRATETABLE, "ERT-01");
+        Long calFrequencyId = EntityHelper.getIdByNumber(FormConstant.HSBS_CALFREQUENCY, "000_m_001");
         //1:为本月数据,2:为上月数据
         Integer type = ConvertUtil.toInt(map.get("type"));
         Date beginDateParam = ConvertUtil.toDate(map.get("beginDateParam"));
@@ -172,7 +180,7 @@ public class PsmsAdjustSalaryTask extends AbstractTask implements Plugin {
         if(!needAdjustSalaryId.isEmpty()){
             logger.info("开始获取人员最新岗位工资标准定薪记录");
             //获取人员最新岗位工资标准定薪记录
-            List<AdjFileServiceHelper.SalaryAdjustmentResult> salaryAdjustmentResultList = AdjFileServiceHelper.getLastDecAdjRecords(needPersonId, FormConstant.STANDARDITEM_ID_KEY);
+            List<AdjFileServiceHelper.SalaryAdjustmentResult> salaryAdjustmentResultList = AdjFileServiceHelper.getLastDecAdjRecords(needPersonId, FormConstant.POS_STANDARD_ITEM_NUMBER);
             Map<Long, List<AdjFileServiceHelper.SalaryAdjustmentResult>> salaryAdjustmentResultMap = salaryAdjustmentResultList.stream()
                     .collect(Collectors.groupingBy(result -> result.employee.getLong(FormConstant.ID_KEY)));
             
@@ -230,19 +238,19 @@ public class PsmsAdjustSalaryTask extends AbstractTask implements Plugin {
                                 applyBill.put("org", orgId);
                             }
                             //定调薪明细字段显示方案   调薪明细字段
-                            applyBill.put("billtype", 2215975998602655744L);
+                            applyBill.put("billtype", billTypeId);
                             //国家
-                            applyBill.put("billcountry", 1000001L);
+                            applyBill.put("billcountry", countryId);
                             //定调薪类型
-                            applyBill.put("salaryadjrsn", 2352338490244480000L);
+                            applyBill.put("salaryadjrsn", salaryAdjuStrSnId);
                             //默认币种
-                            applyBill.put("billcurrency", 1L);
+                            applyBill.put("billcurrency", currencyId);
                             //定调薪方案
-                            applyBill.put("salaryadjscm", 2322515162646457344L);
+                            applyBill.put("salaryadjscm", adjApproveScmId);
                             //汇率日期
                             applyBill.put("exchangeratedate", new Date());
                             //汇率表
-                            applyBill.put("exctable", 2321965096026258432L);
+                            applyBill.put("exctable", exRateTableId);
                             //默认生效日期
                             applyBill.put("effectivedate", date);
                             //草稿状态
@@ -274,8 +282,8 @@ public class PsmsAdjustSalaryTask extends AbstractTask implements Plugin {
                             Long positionId = personPosFile.getLong(String.join(".",PositionStructureConstant.NCKD_POSITIONHR, FormConstant.ID_KEY));
                             applyBillEntry.put("adjfile", salaryAdjustmentResult.adjFileInfo.getLong(FormConstant.ID_KEY));
                             applyBillEntry.put("employee", employeeId);
-                            applyBillEntry.put("standarditem", 2321901533681170432L);    //定调薪项目   职位系数
-                            applyBillEntry.put("frequency", 1095454108284088320L);       //频度  月
+                            applyBillEntry.put("standarditem", salaryItemId);    //定调薪项目   职位系数
+                            applyBillEntry.put("frequency", calFrequencyId);       //频度  月
                             applyBillEntry.put("amount", coefficient);
                             applyBillEntry.put("position", positionId);
                             applyBillEntry.put("joblevel", jobLevel.getLong(FormConstant.ID_KEY));

+ 337 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/print/EmployeePrintPlugin.java

@@ -0,0 +1,337 @@
+package nckd.jxccl.opmc.pm.plugin.form.print;
+
+import kd.bos.algo.Algo;
+import kd.bos.algo.AlgoContext;
+import kd.bos.algo.DataSet;
+import kd.bos.algo.GroupbyDataSet;
+import kd.bos.algo.Row;
+import kd.bos.common.enums.EnableEnum;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.metadata.dynamicobject.DynamicObjectType;
+import kd.bos.entity.plugin.args.CustomPrintDataEntitiesArgs;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.print.core.data.DataRowSet;
+import kd.bos.print.core.data.datasource.CustomDataSource;
+import kd.bos.print.core.data.datasource.MainDataSource;
+import kd.bos.print.core.data.datasource.PrtDataSource;
+import kd.bos.print.core.data.field.CollectionField;
+import kd.bos.print.core.data.field.Field;
+import kd.bos.print.core.data.field.IntegerField;
+import kd.bos.print.core.plugin.AbstractPrintPlugin;
+import kd.bos.print.core.plugin.event.AfterLoadDataEvent;
+import kd.bos.print.core.plugin.event.CustomDataLoadEvent;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.hr.hbp.common.cache.HRAppCache;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.algo.GroupMaxStrFunction;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.exception.ValidationException;
+import nckd.jxccl.base.common.utils.ConvertUtil;
+import nckd.jxccl.base.common.utils.DateUtil;
+import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+* 绩效结果打印
+* @author W.Y.C
+* @date 2026/1/6 15:15
+* @version 1.0
+*/
+public class EmployeePrintPlugin extends AbstractPrintPlugin implements Plugin {
+
+    //记录主数据源
+    private MainDataSource mainDataSource;
+
+    @Override
+    public void loadCustomData(CustomDataLoadEvent evt) {
+        Date printYear = HRAppCache.get("nckd_pm").get("printYear", Date.class);
+
+        // 1. 获取数据源标识
+        CustomDataSource dataSource = evt.getDataSource();
+        if (!"custom".equals(dataSource.getDsName())) {
+            return;
+        }
+
+        // 2. 获取或创建数据结果集
+        List<DataRowSet> customRows = evt.getCustomDataRows();
+
+        // 3. 组装数据(例如:从数据库查询、计算衍生字段等)
+
+        DataRowSet rowSet = new DataRowSet();
+        rowSet.put("year", new IntegerField(DateUtil.getYear(printYear)));
+        int printYearValue = DateUtil.getYear(printYear);
+        rowSet.put("yearIndex", new IntegerField(getYearIndexFromPrintYear(printYearValue)));
+
+        // 4. 将数据添加到结果集
+        customRows.add(rowSet);
+        evt.setDataSource(dataSource);
+    }
+
+    /**
+     * 根据年份获取对应的序号,近5年(以当前年份为基准)的序号分别为5/4/3/2/1
+     * 例如:当前年是2026,printYear 为2025,则序号为5(上年)
+     * @param year 年份
+     * @return 序号,最近的年份序号为5,依次递减
+     */
+    private int getYearIndexFromPrintYear(int year) {
+        int currentYear = LocalDate.now().getYear();
+
+        // 计算最近5年的范围,即从当前年份往前推5年到前1年(不包含当前年)
+        // 例如:当前年是2026年,最近5年是2021-2025,即 [2021, 2022, 2023, 2024, 2025]
+        int startYear = currentYear - 5; // 最早的年份
+        int endYear = currentYear - 1;   // 最近的年份
+
+        // 检查年份是否在最近5年范围内
+        if (year >= startYear && year <= endYear) {
+            // 计算序号:最近的年份(endYear)序号为5,前一年为4,以此类推
+            // 序号 = (year - startYear) + 1
+            // 例如:当前年是2026年,startYear=2021,endYear=2025
+            // 2025 (最近): 2025 - 2021 + 1 = 5 ✓
+            // 2024: 2024 - 2021 + 1 = 4 ✓
+            // 2023: 2023 - 2021 + 1 = 3 ✓
+            // 2022: 2022 - 2021 + 1 = 2 ✓
+            // 2021 (最远): 2021 - 2021 + 1 = 1 ✓
+            return year - startYear + 1;
+        } else {
+            // 如果不在最近5年内,返回0表示超出范围
+            return 0;
+        }
+    }
+
+    @Override
+    public void afterLoadData(AfterLoadDataEvent evt) {
+        PrtDataSource dataSource = evt.getDataSource();
+        if(!(dataSource instanceof MainDataSource)){
+            return;//非主数据源,立即返回
+        }
+        //记录主数据源,用于自定义数据源查询时,获取需要的信息
+        mainDataSource = (MainDataSource) dataSource;
+        Date printYear = HRAppCache.get("nckd_pm").get("printYear", Date.class);
+        Map<Integer, Long> selectPrintPersonIdMap = HRAppCache.get("nckd_pm").get("employeePrintIdMap", Map.class);
+        if(selectPrintPersonIdMap == null){
+            throw new ValidationException("请选择要打印的日期!");
+        }
+        List<String> seqs = ConvertUtil.toList(selectPrintPersonIdMap.keySet(), ArrayList::new);
+        LocalDate now = LocalDate.now();
+        // 获取5年前的年份
+        int fiveYearsAgo = LocalDate.now().minusYears(5).getYear();
+        Date beginDate = DateUtil.toDate(LocalDate.of(fiveYearsAgo, 1, 1));
+
+        int currentYear = LocalDate.now().getYear() - 1; // 不包含今年
+        Date endDate = DateUtil.toDate(LocalDate.of(currentYear, 1, 1));
+
+        Map<String, String> positionMap = new HashMap<>();
+        Map<String, Integer> perfRankMgmtMap = new HashMap<>();
+        try (AlgoContext context = Algo.newContext()) {
+            Collection<Long> personIds = selectPrintPersonIdMap.values();
+            DataSet positionDateSet = getPositions(fiveYearsAgo, currentYear, personIds);
+            if (positionDateSet != null) {
+                while (positionDateSet.hasNext()) {
+                    Row next = positionDateSet.next();
+                    Long personId = next.getLong(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY));
+                    int tempIndex = 1;
+                    for (int year = fiveYearsAgo; year <= currentYear; year++) {
+                        String positionName = next.getString("position_" + tempIndex);
+                        positionMap.put(personId + "nckd_position_" + tempIndex, positionName);
+                        tempIndex++;
+                    }
+                }
+            }
+
+            DataSet perfRankMgmtDataSet = getPerfRankMgmt(personIds, fiveYearsAgo, currentYear);
+            if (perfRankMgmtDataSet != null) {
+                while (perfRankMgmtDataSet.hasNext()) {
+                    Row next = perfRankMgmtDataSet.next();
+                    Long personId = next.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
+                    int tempIndex = 1;
+                    for (int year = fiveYearsAgo; year <= currentYear; year++) {
+                        Integer topran = next.getInteger("perfrank_topran_" + tempIndex);
+                        Integer topranks = next.getInteger("perfrank_topranks_" + tempIndex);
+                        perfRankMgmtMap.put(personId + "nckd_perfrank_topran_" + tempIndex, topran);
+                        perfRankMgmtMap.put(personId + "nckd_perfrank_topranks_" + tempIndex, topranks);
+                        tempIndex++;
+                    }
+                }
+            }
+        }
+
+
+        // 获取当前打印的数据集并准备过滤后的集合
+        // 2. 获取当前打印的数据集
+        List<DataRowSet> dataRowSets = evt.getDataRowSets();
+        List<DataRowSet> filteredDataRowSets = new ArrayList<>();
+
+        for (DataRowSet dataRowSet : dataRowSets) {
+            if (dataRowSet.containerKey("reportEntry")) {
+                CollectionField entryField = (CollectionField) dataRowSet.getField("reportEntry");
+                List<DataRowSet> entryRows = entryField.getValue();
+                List<DataRowSet> filteredEntryRows = new ArrayList<>();
+                for (DataRowSet entryRow : entryRows) {
+                    String seq = ConvertUtil.toStr(entryRow.getField(FormConstant.SEQ_KEY).getValue());
+                    Long personId = selectPrintPersonIdMap.get(seq + "");
+                    // 判断该分录行是否在用户勾选的列表中
+                    if (seqs.contains(seq)) {
+                        for (String fieldKey : entryRow.getFieldKeys()) {
+                            if (fieldKey.startsWith("nckd_position_")) {
+                                String positionName = positionMap.get(personId + fieldKey);
+                                Field field = entryRow.getField(fieldKey);
+                                field.setValue(positionName != null ? positionName : "");
+                                entryRow.put(fieldKey, field);
+                            }
+                            if (fieldKey.startsWith("nckd_perfrank_topran_")) {
+                                Integer perfRankMgmt = perfRankMgmtMap.get(personId + fieldKey);
+                                Field field = entryRow.getField(fieldKey);
+                                field.setValue(perfRankMgmt != null ? perfRankMgmt : 0);
+                                entryRow.put(fieldKey, field);
+                            }
+                            if (fieldKey.startsWith("nckd_perfrank_topranks_")) {
+                                Integer perfRankMgmt = perfRankMgmtMap.get(personId + fieldKey);
+                                Field field = entryRow.getField(fieldKey);
+                                field.setValue(perfRankMgmt != null ? perfRankMgmt : 0);
+                                entryRow.put(fieldKey, field);
+                            }
+                        }
+                        filteredEntryRows.add(entryRow);
+                    }
+
+                }
+                // 用过滤后的分录数据替换原数据
+                if (!filteredEntryRows.isEmpty()) {
+                    DataRowSet newDataRowSet = dataRowSet.deepCopy(); // 深拷贝,避免影响原数据
+                    newDataRowSet.put("reportEntry", new CollectionField(filteredEntryRows));
+                    filteredDataRowSets.add(newDataRowSet);
+                }
+            }
+        }
+
+        // 将过滤后的数据集设置回事件,实现只打印勾选行
+        evt.setDataRowSets(filteredDataRowSets);
+
+    }
+
+
+    private static DataSet getPerfRankMgmt(Collection<Long> personIds, int beginYear, int endYear) {
+        // 年度绩效排名管理
+        QueryFieldBuilder perfRankMgmtFieldBuilder = QueryFieldBuilder.create()
+                .addIdNumberName(FormConstant.NCKD_PERSON)
+                .add("nckd_toprank")
+                .addGroup(new String[]{"nckd_perfrankmgmt"},"nckd_topranks","nckd_theyear");
+        QFilter perfRankMgmtFilter = new QFilter("nckd_isranking", "=", EnableEnum.YES.getCode())
+                .and(FormConstant.NCKD_PERSON, QCP.in, personIds)
+                .and("nckd_perfrankmgmt.nckd_theyear",QCP.large_equals, beginYear)
+                .and("nckd_perfrankmgmt.nckd_theyear",QCP.less_equals, endYear);
+        DataSet perfRankMgmtDataSet = QueryServiceHelper.queryDataSet("PrintPerfDetailReportListDataPlugin_perfRank", "nckd_perfrankmgmtentry", perfRankMgmtFieldBuilder.buildSelect(), new QFilter[]{perfRankMgmtFilter}, perfRankMgmtFieldBuilder.buildOrder(), 10000);
+        int tempIndex = 1;
+        for (int year = beginYear; year <= endYear; year++) {
+            //排名
+            String toprankField = "CASE WHEN nckd_perfrankmgmt.nckd_theyear = "+year+" THEN nckd_toprank ELSE null END";
+            perfRankMgmtDataSet = perfRankMgmtDataSet.addField(toprankField, "perfrankmgmt_topran_temp_" + tempIndex);
+            //总人数
+            String topranksField = "CASE WHEN nckd_perfrankmgmt.nckd_theyear = "+year+" THEN nckd_perfrankmgmt.nckd_topranks ELSE null END";
+            perfRankMgmtDataSet = perfRankMgmtDataSet.addField(topranksField, "perfrankmgmt_topranks_temp_" + tempIndex);
+            tempIndex++;
+        }
+        GroupbyDataSet groupbyDataSet = perfRankMgmtDataSet.groupBy(new String[]{String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY)});
+        tempIndex = 1;
+        for (int year = beginYear; year <= endYear; year++) {
+            groupbyDataSet.max("perfrankmgmt_topran_temp_"+tempIndex, "perfrank_topran_"+tempIndex);
+            groupbyDataSet.max("perfrankmgmt_topranks_temp_"+tempIndex, "perfrank_topranks_"+tempIndex);
+            tempIndex++;
+        }
+        return groupbyDataSet.finish();
+    }
+
+
+    /**
+     * 获取近N年的岗位信息
+     * 用于查询每个员工在指定年份范围内每年年底(12月31日)所在的有效岗位
+     * 当一个员工在同一年有多个有效岗位时,选择结束日期最晚的那个岗位
+     *
+     * @param beginYear 起始年份(包含)
+     * @param endYear   结束年份(包含)
+     * @return 包含每个员工每年岗位信息的数据集
+     */
+    private DataSet getPositions(int beginYear,int endYear,Collection<Long> personIds){
+        // 查询全职任职关系,获取员工、岗位、任职起止时间等信息
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                .add(FormConstant.STARTDATE)  // 任职开始日期
+                .add(FormConstant.ENDDATE)    // 任职结束日期
+                .addIdNumberName(FormConstant.POSITION_KEY)  // 岗位信息(ID、编码、名称)
+                .addIdNumberNameWithExtras(new String[]{FormConstant.EMPLOYEE_KEY},FormConstant.EMP_NUMBER_KEY)  // 员工信息(ID、编码、姓名)+ 工号
+                .orderDesc(FormConstant.EMPLOYEE_KEY,FormConstant.STARTDATE);  // 按员工ID和开始日期降序排列
+        // 筛选条件:只查询全职任职(IS_PRIMARY = YES)
+        QFilter qFilter = new QFilter(FormConstant.IS_PRIMARY,QCP.equals, EnableEnum.YES.getCode());
+        if(!personIds.isEmpty()){
+            qFilter = new QFilter(FormConstant.EMPLOYEE_KEY,QCP.in,personIds.toArray());
+        }
+        DataSet dataSet = QueryServiceHelper.queryDataSet("PrintPerfDetailReportListDataPlugin_EMPREL", FormConstant.HRPI_EMPPOSORGREL, queryFieldBuilder.buildSelect(), new QFilter[]{qFilter}, queryFieldBuilder.buildOrder(), 1000000);
+
+        int tempIndex = 1;
+        // 遍历指定年份范围,为每一年生成对应的岗位查询字段
+        for (int year = beginYear; year <= endYear; year++) {
+            // 获取每年12-31 23:59:59作为目标日期,用于判断该员工当年年底的岗位状态
+            Date targetDate = DateUtil.toDate(LocalDateTime.of(year, 12, 31, 23, 59, 59));
+            String targetDateStr = DateUtil.format(targetDate, DateUtil.NORM_DATE_PATTERN); // 使用日期格式而非日期时间格式
+
+            // 创建复合字段:如果在目标日期员工处于有效任职状态,则生成"结束日期|岗位名称"格式的字符串
+            // 这样使用GroupMaxStrFunction时,会根据结束日期选择最晚的那个任职记录
+            //为什么用“00000000000000|”,不用null。因为当GroupMaxStrFunction进行字符串比较时,有效的日期值(如'20231231235959|经济技术部部长')会比'00000000000000|'大,从而被正确选择
+            String combinedField = "CASE WHEN " + FormConstant.STARTDATE + " <= to_date('" + targetDateStr + "','yyyy-MM-dd') " +
+                    "AND " + FormConstant.ENDDATE + " >= to_date('" + targetDateStr + "','yyyy-MM-dd') " +
+                    "THEN CONCAT(TO_CHAR(" + FormConstant.ENDDATE + ", 'YYYYMMDDHHmmss'), '|', " +
+                    String.join(".", FormConstant.POSITION_KEY, FormConstant.NAME_KEY) + ") ELSE '00000000000000|' END";
+
+            // 添加岗位复合字段(包含结束日期和岗位名称)
+            dataSet = dataSet.addField(combinedField, "position_temp_" + tempIndex);
+
+            // 同时创建仅包含日期部分的字段,用于后续解析时去除日期部分,只保留岗位名称
+            String dateField = "CASE WHEN " + FormConstant.STARTDATE + " <= to_date('" + targetDateStr + "','yyyy-MM-dd') " +
+                    "AND " + FormConstant.ENDDATE + " >= to_date('" + targetDateStr + "','yyyy-MM-dd') " +
+                    "THEN CONCAT(TO_CHAR(" + FormConstant.ENDDATE + ", 'YYYYMMDDHHmmss'),'|') ELSE '00000000000000|' END";
+            dataSet = dataSet.addField(dateField, "position_date_" + tempIndex);
+
+//            dataSet = dataSet.addField("'"+year+"'", "position_year_" + tempIndex);
+            tempIndex++;
+        }
+
+        // 行转列处理:按员工ID分组,使用GroupMaxStrFunction获取每个员工每年结束日期最晚的任职记录
+        tempIndex = 1;
+        GroupMaxStrFunction groupMaxStr = new GroupMaxStrFunction();
+        // 按员工ID进行分组聚合
+        GroupbyDataSet groupbyDataSet = dataSet.groupBy(new String[]{String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY)});
+        // 对每一年的数据进行聚合,获取结束日期最晚的任职记录
+        for (int year = beginYear; year <= endYear; year++) {
+            // 获取岗位复合字段的最大值(即结束日期最晚的记录)
+            groupbyDataSet.agg(new GroupMaxStrFunction(),"position_temp_"+tempIndex, "position_max_"+tempIndex);
+            // 同时获取日期字段的最大值,用于后续解析
+            groupbyDataSet.agg(groupMaxStr,"position_date_"+tempIndex, "position_date_max_"+tempIndex);
+            tempIndex++;
+        }
+        DataSet result = groupbyDataSet.finish();
+
+        // 解析复合字段,提取真正的岗位名称
+        // 通过去除日期部分(YYYYMMDDHHmmss|)来获取原始的岗位名称
+        tempIndex = 1;
+        for (int year = beginYear; year <= endYear; year++) {
+            final int currentYearIndex = year - beginYear + 1;
+            result = result.addField(
+                    // 如果岗位字段有效(不为默认值'00000000000000|'),则去除日期部分,只保留岗位名称
+                    "CASE WHEN position_max_" + tempIndex + " IS NOT NULL AND position_max_" + tempIndex + " != '00000000000000|' THEN " +
+                            "REPLACE(position_max_" + tempIndex + ",position_date_max_"+tempIndex+",'') " +  // 去除日期部分,得到岗位名称
+                            "ELSE null END",
+                    "position_" + tempIndex  // 最终的岗位名称字段
+            );
+            tempIndex++;
+        }
+        return result;
+    }
+}

+ 118 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/print/PerfBatchPrintListPlugin.java

@@ -5,25 +5,51 @@ import com.alibaba.fastjson.JSONObject;
 import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.dataentity.entity.DynamicObjectCollection;
 import kd.bos.dataentity.utils.StringUtils;
+import kd.bos.entity.cache.AppCache;
+import kd.bos.entity.datamodel.ListSelectedRow;
+import kd.bos.entity.datamodel.ListSelectedRowCollection;
 import kd.bos.entity.datamodel.events.PackageDataEvent;
 import kd.bos.entity.report.ReportColumn;
 import kd.bos.entity.report.ReportQueryParam;
 import kd.bos.form.CloseCallBack;
 import kd.bos.form.FormShowParameter;
+import kd.bos.form.IFormView;
 import kd.bos.form.ShowType;
 import kd.bos.form.control.Toolbar;
 import kd.bos.form.control.events.ItemClickEvent;
+import kd.bos.form.events.BeforeDoOperationEventArgs;
 import kd.bos.form.events.ClosedCallBackEvent;
 import kd.bos.form.events.PreOpenFormEventArgs;
+import kd.bos.form.operate.AbstractOperate;
+import kd.bos.form.operate.FormOperate;
+import kd.bos.form.operate.printop.PrintPreview;
+import kd.bos.form.operate.printop.SelectTplPrint;
+import kd.bos.list.IListView;
+import kd.bos.metadata.dao.MetaCategory;
+import kd.bos.metadata.dao.MetadataDao;
+import kd.bos.metadata.form.FormMetadata;
+import kd.bos.mvc.report.ReportView;
+import kd.bos.orm.query.QFilter;
+import kd.bos.print.api.utils.ConfigConstUtil;
+import kd.bos.print.business.utils.OldPrintTemplateUtil;
 import kd.bos.report.ReportList;
 import kd.bos.report.plugin.AbstractReportFormPlugin;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.template.orgctrl.service.PrintTemplateServiceFactory;
+import kd.bos.template.orgctrl.utils.ParamUtils;
+import kd.hr.hbp.common.cache.HRAppCache;
 import kd.sdk.plugin.Plugin;
 import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.utils.ConvertUtil;
 import nckd.jxccl.base.common.utils.DateUtil;
 
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.EventObject;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
 * 人员考评套打列表
@@ -84,6 +110,50 @@ public class PerfBatchPrintListPlugin extends AbstractReportFormPlugin implement
             showParameter.setCustomParam( "personIds", personIds);
             this.getView().showForm(showParameter);
         }
+        if("nckd_employeeprint".equalsIgnoreCase(itemKey)){
+            HRAppCache.get("nckd_pm").remove( "printYear");
+            ReportList reportList = this.getView().getControl(FormConstant.REPORTLISTAP);
+            int[] selectedRowIndexes = reportList.getEntryState().getSelectedRows();
+            List<Long> personIds =  new ArrayList<>();
+            if(selectedRowIndexes == null ||  selectedRowIndexes.length == 0){
+                this.getView().showTipNotification("请选择要打印的员工!");
+                return;
+            }
+            FormShowParameter showParameter = new FormShowParameter();
+            showParameter.setFormId("nckd_selectdateprint");
+            showParameter.getOpenStyle().setShowType(ShowType.Modal);
+            showParameter.setCloseCallBack(new CloseCallBack(this, "nckd_selectdateprint"));
+            showParameter.setCaption("选择打印年份");
+            this.getView().showForm(showParameter);
+        }
+    }
+
+
+    private Map<String, String> getTemplates(String formId) {
+        String id = MetadataDao.getIdByNumber(formId, MetaCategory.Form);// 368
+        FormMetadata fm = (FormMetadata)MetadataDao.readMeta(id, MetaCategory.Form);// 369
+        String oriFormId = MetadataDao.getNumberById(fm.getEntityId());// 370
+        Map<String, String> templateMap = new LinkedHashMap(16);// 371
+        DynamicObject[] dynamicObjects = BusinessDataServiceHelper.load("bos_manageprinttpl", "number, name, enable,type,printtplid", ConfigConstUtil.isNewTenantOfVersion(7) ? new QFilter[]{new QFilter("billformid", "=", oriFormId), new QFilter("type", "!=", "A")} : new QFilter[]{new QFilter("billformid", "=", oriFormId)});// 372 373
+
+        for(DynamicObject obj : dynamicObjects) {// 375
+            DynamicObject printtpObj = obj.getDynamicObject("printtplid");// 376
+            Object tplId = obj.get("printtplid_id");// 377
+            String enable = obj.getString("enable");// 378
+            if (!"0".equals(enable)) {// 379
+                if (printtpObj != null && "B".equals(printtpObj.get("type"))) {// 383
+                    templateMap.put(tplId.toString(), printtpObj.getLocaleString("name").getLocaleValue());// 391
+                } else {
+                    QFilter qFilter = new QFilter("id", "=", tplId);// 384
+                    DynamicObject formMeta = OldPrintTemplateUtil.loadSingleFromCache("id,number,bizappid,basedatafield,modifierid", new QFilter[]{qFilter});// 385
+                    if (formMeta != null) {// 386
+                        templateMap.put(tplId.toString(), formMeta.getLocaleString("name").getLocaleValue());// 389
+                    }
+                }
+            }
+        }
+
+        return templateMap;// 394
     }
 
     @Override
@@ -97,6 +167,23 @@ public class PerfBatchPrintListPlugin extends AbstractReportFormPlugin implement
                 this.getView().showSuccessNotification( "文件印发及盖章时间修改成功");
                 this.getView().invokeOperation(FormConstant.REFRESH_OP);
             }
+        }else if("nckd_selectdateprint".equalsIgnoreCase(actionId)){
+            Object returnData = closedCallBackEvent.getReturnData();
+            if(returnData != null) {
+                HRAppCache.get("nckd_pm").remove( "employeePrintIdMap");
+                Date date = ConvertUtil.toDate(returnData);
+                HRAppCache.get("nckd_pm").put( "printYear", date);
+                ReportList reportList = this.getView().getControl(FormConstant.REPORTLISTAP);
+                int[] selectedRowIndexes = reportList.getEntryState().getSelectedRows();
+                Map<Integer,Long> personIdMap = new HashMap<>();
+                for (int selectedRowIndex : selectedRowIndexes) {
+                    DynamicObject rowData = reportList.getReportModel().getRowData(selectedRowIndex);
+                    personIdMap.put( rowData.getInt("fseq"), rowData.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY)));
+                }
+                HRAppCache.get("nckd_pm").put( "employeePrintIdMap", personIdMap);
+                this.getView().invokeOperation("employeeprint");
+
+            }
         }
     }
 
@@ -114,7 +201,38 @@ public class PerfBatchPrintListPlugin extends AbstractReportFormPlugin implement
             }
 
         }
+    }
 
+    @Override
+    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
+        AbstractOperate operate = (AbstractOperate) args.getSource();
+        HRAppCache.get("nckd_pm").remove( "selectPrintSeq");
+        HRAppCache.get("nckd_pm").remove( "selectPrintPersonIdMap");
+        String operateKey = operate.getOperateKey();
+        if ("selecttplprint".equals(operateKey)) {
+            ReportList reportList = this.getView().getControl(FormConstant.REPORTLISTAP);
+            int[] selectedRowIndexes = reportList.getEntryState().getSelectedRows();
+            Map<Integer,Long> personIdMap = new HashMap<>();
+            List<Integer> seqList = new  ArrayList<>();
+            if(selectedRowIndexes != null && selectedRowIndexes.length > 0) {
+                for (int selectedRowIndex : selectedRowIndexes) {
+                    DynamicObject rowData = reportList.getReportModel().getRowData(selectedRowIndex);
+                    seqList.add(rowData.getInt("fseq"));
+                    personIdMap.put( rowData.getInt("fseq"), rowData.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY)));
+                }
+            }else{
+                int rowCount = reportList.getReportModel().getRowCount();
+                DynamicObjectCollection rowDataColl = reportList.getReportModel().getRowData(1, rowCount, false);
+                for (DynamicObject dynamicObject : rowDataColl) {
+                    long personId = dynamicObject.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
+                    seqList.add(dynamicObject.getInt("fseq"));
+                    personIdMap.put(dynamicObject.getInt("fseq"), personId);
+                }
+            }
+            HRAppCache.get("nckd_pm").put( "selectPrintSeq", seqList);
+            HRAppCache.get("nckd_pm").put( "selectPrintPersonIdMap", personIdMap);
+        }else if( "employeeprint".equals(operateKey)){
 
+        }
     }
 }

+ 268 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/print/PerfDetailPrintPlugin.java

@@ -0,0 +1,268 @@
+package nckd.jxccl.opmc.pm.plugin.form.print;
+
+import kd.bos.algo.Algo;
+import kd.bos.algo.AlgoContext;
+import kd.bos.algo.DataSet;
+import kd.bos.algo.GroupbyDataSet;
+import kd.bos.algo.Row;
+import kd.bos.common.enums.EnableEnum;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.print.core.data.DataRowSet;
+import kd.bos.print.core.data.datasource.CustomDataSource;
+import kd.bos.print.core.data.field.CollectionField;
+import kd.bos.print.core.data.field.Field;
+import kd.bos.print.core.plugin.AbstractPrintPlugin;
+import kd.bos.print.core.plugin.event.AfterLoadDataEvent;
+import kd.bos.print.core.plugin.event.BeforeLoadDataEvent;
+import kd.bos.print.core.plugin.event.CustomDataLoadEvent;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.hr.hbp.common.cache.HRAppCache;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.algo.GroupMaxStrFunction;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.utils.ConvertUtil;
+import nckd.jxccl.base.common.utils.DateUtil;
+import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+* 绩效结果打印
+* @author W.Y.C
+* @date 2026/1/6 15:15
+* @version 1.0
+*/
+public class PerfDetailPrintPlugin extends AbstractPrintPlugin implements Plugin {
+
+    @Override
+    public void afterLoadData(AfterLoadDataEvent evt) {
+        String dsName = evt.getDataSource().getDsName();
+        if(!dsName.contains("custom")) {
+            List<Integer> seqs = HRAppCache.get("nckd_pm").get("selectPrintSeq", List.class);
+            if (seqs == null || seqs.isEmpty()) {
+                return;
+            }
+
+            Map<Integer, Long> selectPrintPersonIdMap = HRAppCache.get("nckd_pm").get("selectPrintPersonIdMap", Map.class);
+            LocalDate now = LocalDate.now();
+            // 获取5年前的年份
+            int fiveYearsAgo = LocalDate.now().minusYears(5).getYear();
+            Date beginDate = DateUtil.toDate(LocalDate.of(fiveYearsAgo, 1, 1));
+
+            int currentYear = LocalDate.now().getYear() - 1; // 不包含今年
+            Date endDate = DateUtil.toDate(LocalDate.of(currentYear, 1, 1));
+
+            Map<String, String> positionMap = new HashMap<>();
+            Map<String, Integer> perfRankMgmtMap = new HashMap<>();
+            try (AlgoContext context = Algo.newContext()) {
+                Collection<Long> personIds = selectPrintPersonIdMap.values();
+                DataSet positionDateSet = getPositions(fiveYearsAgo, currentYear, personIds);
+                if (positionDateSet != null) {
+                    while (positionDateSet.hasNext()) {
+                        Row next = positionDateSet.next();
+                        Long personId = next.getLong(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY));
+                        int tempIndex = 1;
+                        for (int year = fiveYearsAgo; year <= currentYear; year++) {
+                            String positionName = next.getString("position_" + tempIndex);
+                            positionMap.put(personId + "nckd_position_" + tempIndex, positionName);
+                            tempIndex++;
+                        }
+                    }
+                }
+
+                DataSet perfRankMgmtDataSet = getPerfRankMgmt(personIds, fiveYearsAgo, currentYear);
+                if (perfRankMgmtDataSet != null) {
+                    while (perfRankMgmtDataSet.hasNext()) {
+                        Row next = perfRankMgmtDataSet.next();
+                        Long personId = next.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
+                        int tempIndex = 1;
+                        for (int year = fiveYearsAgo; year <= currentYear; year++) {
+                            Integer topran = next.getInteger("perfrank_topran_" + tempIndex);
+                            Integer topranks = next.getInteger("perfrank_topranks_" + tempIndex);
+                            perfRankMgmtMap.put(personId + "nckd_perfrank_topran_" + tempIndex, topran);
+                            perfRankMgmtMap.put(personId + "nckd_perfrank_topranks_" + tempIndex, topranks);
+                            tempIndex++;
+                        }
+                    }
+                }
+            }
+
+
+            // 获取当前打印的数据集并准备过滤后的集合
+            // 2. 获取当前打印的数据集
+            List<DataRowSet> dataRowSets = evt.getDataRowSets();
+            List<DataRowSet> filteredDataRowSets = new ArrayList<>();
+            for (DataRowSet dataRowSet : dataRowSets) {
+
+                CollectionField entryField = (CollectionField) dataRowSet.getField("reportEntry");
+                List<DataRowSet> entryRows = entryField.getValue();
+                List<DataRowSet> filteredEntryRows = new ArrayList<>();
+                for (DataRowSet entryRow : entryRows) {
+                    if (dataRowSet.containerKey("reportEntry")) {
+                        Integer seq = ConvertUtil.toInt(entryRow.getField(FormConstant.SEQ_KEY).getValue());
+                        Long personId = selectPrintPersonIdMap.get(seq + "");
+                        // 判断该分录行是否在用户勾选的列表中
+                        if (seqs.contains(seq)) {
+                            filteredEntryRows.add(entryRow); // 保留被勾选的行
+                        }
+                        for (String fieldKey : entryRow.getFieldKeys()) {
+                            if (fieldKey.startsWith("nckd_position_")) {
+                                String positionName = positionMap.get(personId + fieldKey);
+                                Field field = entryRow.getField(fieldKey);
+                                field.setValue(positionName != null ? positionName : "");
+                                entryRow.put(fieldKey, field);
+                            }
+                            if (fieldKey.startsWith("nckd_perfrank_topran_")) {
+                                Integer perfRankMgmt = perfRankMgmtMap.get(personId + fieldKey);
+                                Field field = entryRow.getField(fieldKey);
+                                field.setValue(perfRankMgmt != null ? perfRankMgmt : 0);
+                                entryRow.put(fieldKey, field);
+                            }
+                            if (fieldKey.startsWith("nckd_perfrank_topranks_")) {
+                                Integer perfRankMgmt = perfRankMgmtMap.get(personId + fieldKey);
+                                Field field = entryRow.getField(fieldKey);
+                                field.setValue(perfRankMgmt != null ? perfRankMgmt : 0);
+                                entryRow.put(fieldKey, field);
+                            }
+                        }
+                    }
+                }
+                // 用过滤后的分录数据替换原数据
+                if (!filteredEntryRows.isEmpty()) {
+                    DataRowSet newDataRowSet = dataRowSet.deepCopy(); // 深拷贝,避免影响原数据
+                    newDataRowSet.put("reportEntry", new CollectionField(filteredEntryRows));
+                    filteredDataRowSets.add(newDataRowSet);
+                }
+
+            }
+            // 将过滤后的数据集设置回事件,实现只打印勾选行
+            evt.setDataRowSets(filteredDataRowSets);
+        }
+    }
+
+
+    private static DataSet getPerfRankMgmt(Collection<Long> personIds, int beginYear, int endYear) {
+        // 年度绩效排名管理
+        QueryFieldBuilder perfRankMgmtFieldBuilder = QueryFieldBuilder.create()
+                .addIdNumberName(FormConstant.NCKD_PERSON)
+                .add("nckd_toprank")
+                .addGroup(new String[]{"nckd_perfrankmgmt"},"nckd_topranks","nckd_theyear");
+        QFilter perfRankMgmtFilter = new QFilter("nckd_isranking", "=", EnableEnum.YES.getCode())
+                .and(FormConstant.NCKD_PERSON, QCP.in, personIds)
+                .and("nckd_perfrankmgmt.nckd_theyear",QCP.large_equals, beginYear)
+                .and("nckd_perfrankmgmt.nckd_theyear",QCP.less_equals, endYear);
+        DataSet perfRankMgmtDataSet = QueryServiceHelper.queryDataSet("PrintPerfDetailReportListDataPlugin_perfRank", "nckd_perfrankmgmtentry", perfRankMgmtFieldBuilder.buildSelect(), new QFilter[]{perfRankMgmtFilter}, perfRankMgmtFieldBuilder.buildOrder(), 10000);
+        int tempIndex = 1;
+        for (int year = beginYear; year <= endYear; year++) {
+            //排名
+            String toprankField = "CASE WHEN nckd_perfrankmgmt.nckd_theyear = "+year+" THEN nckd_toprank ELSE null END";
+            perfRankMgmtDataSet = perfRankMgmtDataSet.addField(toprankField, "perfrankmgmt_topran_temp_" + tempIndex);
+            //总人数
+            String topranksField = "CASE WHEN nckd_perfrankmgmt.nckd_theyear = "+year+" THEN nckd_perfrankmgmt.nckd_topranks ELSE null END";
+            perfRankMgmtDataSet = perfRankMgmtDataSet.addField(topranksField, "perfrankmgmt_topranks_temp_" + tempIndex);
+            tempIndex++;
+        }
+        GroupbyDataSet groupbyDataSet = perfRankMgmtDataSet.groupBy(new String[]{String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY)});
+        tempIndex = 1;
+        for (int year = beginYear; year <= endYear; year++) {
+            groupbyDataSet.max("perfrankmgmt_topran_temp_"+tempIndex, "perfrank_topran_"+tempIndex);
+            groupbyDataSet.max("perfrankmgmt_topranks_temp_"+tempIndex, "perfrank_topranks_"+tempIndex);
+            tempIndex++;
+        }
+        return groupbyDataSet.finish();
+    }
+
+
+    /**
+     * 获取近N年的岗位信息
+     * 用于查询每个员工在指定年份范围内每年年底(12月31日)所在的有效岗位
+     * 当一个员工在同一年有多个有效岗位时,选择结束日期最晚的那个岗位
+     *
+     * @param beginYear 起始年份(包含)
+     * @param endYear   结束年份(包含)
+     * @return 包含每个员工每年岗位信息的数据集
+     */
+    private DataSet getPositions(int beginYear,int endYear,Collection<Long> personIds){
+        // 查询全职任职关系,获取员工、岗位、任职起止时间等信息
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                .add(FormConstant.STARTDATE)  // 任职开始日期
+                .add(FormConstant.ENDDATE)    // 任职结束日期
+                .addIdNumberName(FormConstant.POSITION_KEY)  // 岗位信息(ID、编码、名称)
+                .addIdNumberNameWithExtras(new String[]{FormConstant.EMPLOYEE_KEY},FormConstant.EMP_NUMBER_KEY)  // 员工信息(ID、编码、姓名)+ 工号
+                .orderDesc(FormConstant.EMPLOYEE_KEY,FormConstant.STARTDATE);  // 按员工ID和开始日期降序排列
+        // 筛选条件:只查询全职任职(IS_PRIMARY = YES)
+        QFilter qFilter = new QFilter(FormConstant.IS_PRIMARY,QCP.equals, EnableEnum.YES.getCode());
+        if(!personIds.isEmpty()){
+            qFilter = new QFilter(FormConstant.EMPLOYEE_KEY,QCP.in,personIds.toArray());
+        }
+        DataSet dataSet = QueryServiceHelper.queryDataSet("PrintPerfDetailReportListDataPlugin_EMPREL", FormConstant.HRPI_EMPPOSORGREL, queryFieldBuilder.buildSelect(), new QFilter[]{qFilter}, queryFieldBuilder.buildOrder(), 1000000);
+
+        int tempIndex = 1;
+        // 遍历指定年份范围,为每一年生成对应的岗位查询字段
+        for (int year = beginYear; year <= endYear; year++) {
+            // 获取每年12-31 23:59:59作为目标日期,用于判断该员工当年年底的岗位状态
+            Date targetDate = DateUtil.toDate(LocalDateTime.of(year, 12, 31, 23, 59, 59));
+            String targetDateStr = DateUtil.format(targetDate, DateUtil.NORM_DATE_PATTERN); // 使用日期格式而非日期时间格式
+
+            // 创建复合字段:如果在目标日期员工处于有效任职状态,则生成"结束日期|岗位名称"格式的字符串
+            // 这样使用GroupMaxStrFunction时,会根据结束日期选择最晚的那个任职记录
+            //为什么用“00000000000000|”,不用null。因为当GroupMaxStrFunction进行字符串比较时,有效的日期值(如'20231231235959|经济技术部部长')会比'00000000000000|'大,从而被正确选择
+            String combinedField = "CASE WHEN " + FormConstant.STARTDATE + " <= to_date('" + targetDateStr + "','yyyy-MM-dd') " +
+                    "AND " + FormConstant.ENDDATE + " >= to_date('" + targetDateStr + "','yyyy-MM-dd') " +
+                    "THEN CONCAT(TO_CHAR(" + FormConstant.ENDDATE + ", 'YYYYMMDDHHmmss'), '|', " +
+                    String.join(".", FormConstant.POSITION_KEY, FormConstant.NAME_KEY) + ") ELSE '00000000000000|' END";
+
+            // 添加岗位复合字段(包含结束日期和岗位名称)
+            dataSet = dataSet.addField(combinedField, "position_temp_" + tempIndex);
+
+            // 同时创建仅包含日期部分的字段,用于后续解析时去除日期部分,只保留岗位名称
+            String dateField = "CASE WHEN " + FormConstant.STARTDATE + " <= to_date('" + targetDateStr + "','yyyy-MM-dd') " +
+                    "AND " + FormConstant.ENDDATE + " >= to_date('" + targetDateStr + "','yyyy-MM-dd') " +
+                    "THEN CONCAT(TO_CHAR(" + FormConstant.ENDDATE + ", 'YYYYMMDDHHmmss'),'|') ELSE '00000000000000|' END";
+            dataSet = dataSet.addField(dateField, "position_date_" + tempIndex);
+
+//            dataSet = dataSet.addField("'"+year+"'", "position_year_" + tempIndex);
+            tempIndex++;
+        }
+
+        // 行转列处理:按员工ID分组,使用GroupMaxStrFunction获取每个员工每年结束日期最晚的任职记录
+        tempIndex = 1;
+        GroupMaxStrFunction groupMaxStr = new GroupMaxStrFunction();
+        // 按员工ID进行分组聚合
+        GroupbyDataSet groupbyDataSet = dataSet.groupBy(new String[]{String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY)});
+        // 对每一年的数据进行聚合,获取结束日期最晚的任职记录
+        for (int year = beginYear; year <= endYear; year++) {
+            // 获取岗位复合字段的最大值(即结束日期最晚的记录)
+            groupbyDataSet.agg(new GroupMaxStrFunction(),"position_temp_"+tempIndex, "position_max_"+tempIndex);
+            // 同时获取日期字段的最大值,用于后续解析
+            groupbyDataSet.agg(groupMaxStr,"position_date_"+tempIndex, "position_date_max_"+tempIndex);
+            tempIndex++;
+        }
+        DataSet result = groupbyDataSet.finish();
+
+        // 解析复合字段,提取真正的岗位名称
+        // 通过去除日期部分(YYYYMMDDHHmmss|)来获取原始的岗位名称
+        tempIndex = 1;
+        for (int year = beginYear; year <= endYear; year++) {
+            final int currentYearIndex = year - beginYear + 1;
+            result = result.addField(
+                    // 如果岗位字段有效(不为默认值'00000000000000|'),则去除日期部分,只保留岗位名称
+                    "CASE WHEN position_max_" + tempIndex + " IS NOT NULL AND position_max_" + tempIndex + " != '00000000000000|' THEN " +
+                            "REPLACE(position_max_" + tempIndex + ",position_date_max_"+tempIndex+",'') " +  // 去除日期部分,得到岗位名称
+                            "ELSE null END",
+                    "position_" + tempIndex  // 最终的岗位名称字段
+            );
+            tempIndex++;
+        }
+        return result;
+    }
+}

+ 22 - 8
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/print/PrintPerfDetailReportListDataPlugin.java

@@ -21,6 +21,7 @@ import kd.bos.orm.query.QFilter;
 import kd.bos.servicehelper.QueryServiceHelper;
 import kd.bos.servicehelper.model.PermissionStatus;
 import kd.hr.hbp.business.servicehelper.HRQueryEntityHelper;
+import kd.hr.hbp.common.cache.HRAppCache;
 import kd.sdk.hr.hbp.business.helper.permission.HRPermissionServiceHelper;
 import kd.sdk.plugin.Plugin;
 import nckd.jxccl.base.common.algo.DistinctConcatFunction;
@@ -74,6 +75,8 @@ public class PrintPerfDetailReportListDataPlugin extends AbstractReportListDataP
     @Override
     public DataSet query(ReportQueryParam reportQueryParam, Object o) throws Throwable {
 
+        Map<Integer,Long> selectPrintPersonIdMap = HRAppCache.get("nckd_pm").get("selectPrintPersonIdMap", Map.class);
+
         // 构建查询字段
         QueryFieldBuilder queryFieldBuilder = buildQueryFieldBuilder();
 
@@ -103,7 +106,6 @@ public class PrintPerfDetailReportListDataPlugin extends AbstractReportListDataP
             qFilter.and(new QFilter(FormConstant.ID_KEY, QCP.in, idsOfCurrentBatch));
         }
         qFilter.and(String.join(".", FormConstant.HRPI_EMPPOSORGREL, FormConstant.POS_STATUS,FormConstant.POST_STATE_CLS, FormConstant.NUMBER_KEY),QCP.equals,"1010_S");
-
         // 处理快速过滤条件
         processFastFilter(reportQueryParam, qFilter);
 
@@ -116,7 +118,6 @@ public class PrintPerfDetailReportListDataPlugin extends AbstractReportListDataP
         if(dataRule != null){
             qFilter.and(dataRule);
         }
-
         // 执行基础查询
         QueryEntityType queryEntityType = (QueryEntityType) EntityMetadataCache.getDataEntityType("printperfquery");
         DataSet dataSet = HRQueryEntityHelper.getInstance().getQueryDataSet(queryEntityType,queryFieldBuilder.buildSelect(), new QFilter[]{qFilter}, null);
@@ -127,7 +128,9 @@ public class PrintPerfDetailReportListDataPlugin extends AbstractReportListDataP
             Long personId = next.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
             personIds.add(personId);
         }
-
+        if(personIds.isEmpty()){
+            return dataSet;
+        }
         //过滤调实际结束实际之外的年份分录
         DataSet withYearFields = dataSet.filter("year("+String.join(".", PerfManagerFormConstant.PERFMANAGERENTRY, PerfManagerFormConstant.NCKD_APPRAISALYEAR) +") " +
                 "<= year(CASE WHEN nckd_actendyear is not null THEN nckd_actendyear ELSE "+PerfManagerFormConstant.NCKD_ENDYEAR+" end)");
@@ -137,8 +140,8 @@ public class PrintPerfDetailReportListDataPlugin extends AbstractReportListDataP
         for (int year = fiveYearsAgo; year <= currentYear; year++) {
             withYearFields = withYearFields.addField(
                     "CASE WHEN year(" + String.join(".", PerfManagerFormConstant.PERFMANAGERENTRY, PerfManagerFormConstant.NCKD_APPRAISALYEAR) + ") = " + year + " THEN " + String.join(".", PerfManagerFormConstant.PERFMANAGERENTRY, PerfManagerFormConstant.NCKD_APPRAISALRESULT,FormConstant.ID_KEY)+ " ELSE null END",
-                    "temp_" + tempIndex
-            );
+                    "temp_" + tempIndex);
+            withYearFields = withYearFields.addField(year+"","temp_year_" + tempIndex);
             tempIndex++;
         }
 
@@ -164,11 +167,16 @@ public class PrintPerfDetailReportListDataPlugin extends AbstractReportListDataP
                 String.join(".", PerfManagerFormConstant.DOCSTAMP_ENTITYID, PerfManagerFormConstant.NCKD_STAMPTIME),
                 String.join(".", PerfManagerFormConstant.DOCSTAMP_ENTITYID, PerfManagerFormConstant.NCKD_FILEISSUETIME),
                 String.join(".", PerfManagerFormConstant.HRPI_EMPPOSORGREL, PerfManagerFormConstant.POSITION_KEY, FormConstant.ID_KEY),
+                String.join(".", PerfManagerFormConstant.HRPI_PERSERLEN, PerfManagerFormConstant.FIRSTJOINCOMDATE_KEY),
+                String.join(".", PerfManagerFormConstant.HRPI_PERSERLEN, PerfManagerFormConstant.JOINCOMDATE_KEY),
+                String.join(".", PerfManagerFormConstant.HRPI_PERSERLEN, PerfManagerFormConstant.STARTDATE),
         });
         int tempIndex1 = 1;
         for (int year = fiveYearsAgo; year <= currentYear; year++) {
             groupbyDataSet
                     .max("temp_"+tempIndex1, tempIndex1+"_result");
+            groupbyDataSet
+                    .max("temp_year_"+tempIndex1, "year_"+tempIndex1);
             tempIndex1++;
         }
         //职称/技能使用逗号分拼接
@@ -176,6 +184,7 @@ public class PrintPerfDetailReportListDataPlugin extends AbstractReportListDataP
         groupbyDataSet.agg(new DistinctConcatFunction(),"nckd_hrpi_empskill.nckd_qualiname","qualinames");
 
         DataSet annualPerfDetailQueryDataSet = groupbyDataSet.finish();
+        annualPerfDetailQueryDataSet.print(true);
         String[] mainTableFieldNames = annualPerfDetailQueryDataSet.getRowMeta().getFieldNames();
         // 创建新数组,长度比原数组多1
         String[] newMainTableFieldNames = new String[mainTableFieldNames.length + 1];
@@ -185,8 +194,8 @@ public class PrintPerfDetailReportListDataPlugin extends AbstractReportListDataP
         mainTableFieldNames = newMainTableFieldNames;
         annualPerfDetailQueryDataSet.select(mainTableFieldNames);
 
-//        获取近5年的岗位信息
-        DataSet positionDateSet = getPositions(fiveYearsAgo, currentYear,personIds);
+/*//        获取近5年的岗位信息
+        DataSet positionDateSet = getPositions(fiveYearsAgo, currentYear, personIds);
         String[] pivotFieldNames = positionDateSet.getRowMeta().getFieldNames();
         annualPerfDetailQueryDataSet = annualPerfDetailQueryDataSet.join(positionDateSet, JoinType.LEFT)
                 .on(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY), String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY))
@@ -205,7 +214,11 @@ public class PrintPerfDetailReportListDataPlugin extends AbstractReportListDataP
         pivotFieldNames = filteredFieldNames.toArray(new String[0]);
         return annualPerfDetailQueryDataSet.join(perfRankMgmtDataSet, JoinType.LEFT)
                 .on(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY), String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY))
-                .select(mainTableFieldNames, pivotFieldNames).finish();
+                .select(mainTableFieldNames, pivotFieldNames).finish();*/
+
+
+
+        return annualPerfDetailQueryDataSet;
     }
 
     private static DataSet getPerfRankMgmt(Set<Long> personIds, int beginYear, int endYear) {
@@ -371,6 +384,7 @@ public class PrintPerfDetailReportListDataPlugin extends AbstractReportListDataP
                 .add(String.join(".", FormConstant.NCKD_PERSON, FormConstant.BIRTHDAY))
                 .add(String.join(".", FormConstant.NCKD_PERSON, FormConstant.GENDER,FormConstant.NAME_KEY))
                 .add(String.join(".", FormConstant.HRPI_PEREDUEXP, FormConstant.EDUCATION_KEY,FormConstant.NAME_KEY))
+                .addGroup(new String[]{FormConstant.HRPI_PERSERLEN},FormConstant.FIRSTJOINCOMDATE_KEY,FormConstant.JOINCOMDATE_KEY,FormConstant.STARTDATE)
                 .addIdNumberName(FormConstant.HRPI_EMPENTREL,FormConstant.LABOR_REL_STATUS)
                 .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG,FormConstant.NCKD_FIRSTORG)
                 .addIdNumberName(FormConstant.HRPI_EMPPOSORGREL,FormConstant.ADMINORG,FormConstant.NCKD_SECONDORG)

+ 64 - 0
code/opmc/nckd-jxccl-opmc/src/main/java/nckd/jxccl/opmc/pm/plugin/form/print/SelectDatePrintFormPlugin.java

@@ -0,0 +1,64 @@
+package nckd.jxccl.opmc.pm.plugin.form.print;
+
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.field.DateEdit;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.utils.ConvertUtil;
+import nckd.jxccl.base.common.utils.DateUtil;
+import nckd.jxccl.opmc.pm.common.PerfManagerFormConstant;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.EventObject;
+
+/**
+* 年度调整生效表单插件
+* @author W.Y.C
+* @date 2025/10/15 10:14
+* @version 1.0
+*/
+public class SelectDatePrintFormPlugin extends AbstractFormPlugin implements Plugin {
+
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
+        String operateKey = afterDoOperationEventArgs.getOperateKey();
+        boolean success = afterDoOperationEventArgs.getOperationResult() != null && afterDoOperationEventArgs.getOperationResult().isSuccess();
+        if(success && FormConstant.AFFIRM_OP.equalsIgnoreCase(operateKey)){
+            Object value = this.getModel().getValue("nckd_printdate");
+            this.getView().returnDataToParent(value);
+            this.getView().close();
+        }
+    }
+
+    @Override
+    public void afterBindData(EventObject e) {
+        super.afterBindData(e);
+        // 调用方法,设置日期控件的可选范围
+        setDateFieldLimit();
+    }
+
+    /**
+     * 设置日期字段的可选范围为近5年(例如2026年时,可选2021-2025年)
+     */
+    private void setDateFieldLimit() {
+        // 1. 获取日期控件对象
+        DateEdit dateEdit = this.getView().getControl("nckd_printdate");
+        if (dateEdit == null) {
+            return;
+        }
+
+        // 2. 计算日期范围
+        Calendar calendar = Calendar.getInstance();
+        int currentYear = calendar.get(Calendar.YEAR);
+
+        Date beginYear = DateUtil.minusYears(DateUtil.nowDate(), 5);
+        Date endYear = DateUtil.minusYears(DateUtil.nowDate(), 1);
+        // 3. 设置控件的可选范围
+
+        dateEdit.setMinDate(beginYear);
+        dateEdit.setMaxDate(endYear);
+
+    }
+}

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

@@ -14,8 +14,8 @@ import kd.bos.form.MessageBoxOptions;
 import kd.bos.form.ShowType;
 import kd.bos.form.events.AfterDoOperationEventArgs;
 import kd.bos.form.events.PreOpenFormEventArgs;
-import kd.bos.form.plugin.AbstractFormPlugin;
 import kd.bos.report.ReportList;
+import kd.bos.report.ReportShowParameter;
 import kd.bos.report.plugin.AbstractReportFormPlugin;
 import kd.bos.servicehelper.operation.OperationServiceHelper;
 import kd.sdk.plugin.Plugin;
@@ -116,6 +116,12 @@ public class AnnualPerfDetailFormPlugin extends AbstractReportFormPlugin impleme
                         this.getView().showConfirm("提示",result.getMessage(), MessageBoxOptions.OK,null,null,null,null);
                     }
                 }
+            }else if("printlist".equalsIgnoreCase(operateKey)){
+
+                ReportShowParameter reportShowParameter = new ReportShowParameter();
+                reportShowParameter.setFormId("nckd_printlistrpt");
+                reportShowParameter.getOpenStyle().setShowType(ShowType.MainNewTabPage);
+                this.getView().showForm(reportShowParameter);
             }
         }
     }

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

@@ -262,19 +262,20 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
                                     // 判断周期是否重叠并获取重叠信息,已结束周期使用实际结束时间
                                     String overlapInfo = getCycleOverlapInfo(beginYear, endYear, null, dbBeginYear, dbEndYear, dbActEndYear);
                                     if (StringUtils.isNotBlank(overlapInfo)) {
-                                        /*addFatalErrorMessage(rowDataEntity,
+                                        addFatalErrorMessage(rowDataEntity,
                                                 StrFormatter.format("人员【{}】的考核周期与已有周期在{}重叠,请检查!",
-                                                        personName, overlapInfo));*/
+                                                        personName, overlapInfo));
                                     }
                                 }
-                            }
 
-                            //判断beginYear和dbBeginYear的年份是否相同
-                            if (isSameYear(beginYear, dbBeginYear)) {
-                                /*addFatalErrorMessage(rowDataEntity,
-                                        StrFormatter.format("人员【{}】已经存在周期开始年份【{}】的周期,无需进行创建。",
-                                                personName,
-                                                beginYear.getYear()));*/
+
+                                //判断beginYear和dbBeginYear的年份是否相同
+                                if (isSameYear(beginYear, dbBeginYear)) {
+                                    addFatalErrorMessage(rowDataEntity,
+                                            StrFormatter.format("人员【{}】已经存在周期开始年份【{}】的周期,无需进行创建。",
+                                                    personName,
+                                                    beginYear.getYear()));
+                                }
                             }
                         }
 
@@ -290,34 +291,35 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
 
                     //校验是否存在相同周期开始年的记录 end
                     DynamicObjectCollection entrys = data.getDynamicObjectCollection(PerfManagerFormConstant.NCKD_PERFMANAGERENTRY);
-                    if(entrys != null) {
-                        List<Date> dateList = entrys.stream().map(entry -> entry.getDate(PerfManagerFormConstant.NCKD_APPRAISALYEAR)).collect(Collectors.toList());
-                        if (beginYear != null && endYear != null) {
-                            // 校验考核年份是否在周期内
-                            List<String> outOfRangeYears = entrys.stream()
-                                    .map(entry -> entry.getDate(PerfManagerFormConstant.NCKD_APPRAISALYEAR))
-                                    .filter(Objects::nonNull)
-                                    .filter(date -> !DateUtil.isInRange(DateUtil.toLocalDateTime(date), beginYear, endYear))
-                                    .map(date -> String.valueOf(DateUtil.getYear(DateUtil.toLocalDateTime(date))))
-                                    .distinct()
-                                    .collect(Collectors.toList());
-
-                            if (!outOfRangeYears.isEmpty()) {
-                                String outOfRangeYearsStr = String.join(",", outOfRangeYears);
+                    if(!dataMigration) {
+                        if (entrys != null) {
+                            List<Date> dateList = entrys.stream().map(entry -> entry.getDate(PerfManagerFormConstant.NCKD_APPRAISALYEAR)).collect(Collectors.toList());
+                            if (beginYear != null && endYear != null) {
+                                // 校验考核年份是否在周期内
+                                List<String> outOfRangeYears = entrys.stream()
+                                        .map(entry -> entry.getDate(PerfManagerFormConstant.NCKD_APPRAISALYEAR))
+                                        .filter(Objects::nonNull)
+                                        .filter(date -> !DateUtil.isInRange(DateUtil.toLocalDateTime(date), beginYear, endYear))
+                                        .map(date -> String.valueOf(DateUtil.getYear(DateUtil.toLocalDateTime(date))))
+                                        .distinct()
+                                        .collect(Collectors.toList());
+
+                                if (!outOfRangeYears.isEmpty()) {
+                                    String outOfRangeYearsStr = String.join(",", outOfRangeYears);
+                                    addFatalErrorMessage(rowDataEntity,
+                                            StrFormatter.format("考评年份【{}】不在周期范围内,请检查!", outOfRangeYearsStr));
+                                }
+                            }
+                            // 校验考核年份是否重复
+                            List<String> duplicateYears = getDuplicateYears(dateList);
+                            if (!duplicateYears.isEmpty()) {
+                                String duplicateYearsStr = String.join(",", duplicateYears);
                                 addFatalErrorMessage(rowDataEntity,
-                                        StrFormatter.format("考评年份【{}】不在周期范围内,请检查!", outOfRangeYearsStr));
+                                        StrFormatter.format("考评结果存在重复的考核年份【{}】,请检查!", duplicateYearsStr));
                             }
-                        }
-                        // 校验考核年份是否重复
-                        List<String> duplicateYears = getDuplicateYears(dateList);
-                        if (!duplicateYears.isEmpty()) {
-                            String duplicateYearsStr = String.join(",", duplicateYears);
-                            addFatalErrorMessage(rowDataEntity,
-                                    StrFormatter.format("考评结果存在重复的考核年份【{}】,请检查!", duplicateYearsStr));
-                        }
 
-                        //如果是更新则需要校验是否更改已归档的考核结果
-                        if(isUpdate) {
+                            //如果是更新则需要校验是否更改已归档的考核结果
+                            if (isUpdate) {
 
 
                            /* if(!entryIds.isEmpty() && !entryResultMap.isEmpty()) {
@@ -339,16 +341,17 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
                                     }
                                 }
                             }*/
-                            if(!dbMap.isEmpty()){
-                                DynamicObject dbPerManager = dbMap.get(id);
-                                boolean salaryAdjustGenFlag = dbPerManager.getBoolean(PerfManagerFormConstant.NCKD_SALARYADJUSTGENFLAG);
-                                if(salaryAdjustGenFlag){
-                                    addFatalErrorMessage(rowDataEntity,
-                                            StrFormatter.format("人员【{}】已生成调档,不能修改。",personName));
+                                if (!dbMap.isEmpty()) {
+                                    DynamicObject dbPerManager = dbMap.get(id);
+                                    boolean salaryAdjustGenFlag = dbPerManager.getBoolean(PerfManagerFormConstant.NCKD_SALARYADJUSTGENFLAG);
+                                    if (salaryAdjustGenFlag) {
+                                        addFatalErrorMessage(rowDataEntity,
+                                                StrFormatter.format("人员【{}】已生成调档,不能修改。", personName));
+                                    }
                                 }
                             }
-                        }
 
+                        }
                     }
 
                     if(isUpdate){
@@ -467,32 +470,48 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
 
     @Override
     public void beforeExecuteOperationTransaction(BeforeOperationArgs e) {
-        if(!this.getOperationResult().isSuccess()){
-            e.setCancel(true);
-            return;
+
+        boolean dataMigration;
+        Object invoker = this.getOption().getVariables().get(FormConstant.HR_INVOKER_PARAM_INVOKER);
+        if(ObjectUtils.isEmpty(invoker)){
+            Object invoker1 = this.getOption().getVariables().get("hr_hrdmvalidatetag_of_datasource");
+            Object invoker2 = this.getOption().getVariables().get("hr_hrdmsynctag_of_datasource");
+            if(!ObjectUtils.isEmpty(invoker1) || !ObjectUtils.isEmpty(invoker2)){
+                dataMigration = true;
+            } else {
+                dataMigration = false;
+            }
+        } else{
+            dataMigration = FormConstant.DATA_MIGRATION.equalsIgnoreCase(invoker.toString());
         }
-        String ignoreInteraction = this.getOption().getVariableValue(OperateOptionConst.IGNOREINTERACTION,StringUtils.EMPTY);
-        if(StringUtils.isBlank(ignoreInteraction) || !"true".equalsIgnoreCase(ignoreInteraction)) {
-            StringJoiner confirmMsg = new StringJoiner(",");
-            for (DynamicObject dataEntity : e.getDataEntities()) {
-                long id = dataEntity.getLong(FormConstant.ID_KEY);
-                Date date = dataEntity.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR);
-                long personId = dataEntity.getDynamicObject(FormConstant.NCKD_PERSON).getLong(FormConstant.ID_KEY);
-                QFilter filter = null;
-                if (id > 0) {
-                    filter = new QFilter(FormConstant.ID_KEY, QCP.not_in, id);
+        if(!dataMigration) {
+            if(!this.getOperationResult().isSuccess()){
+                e.setCancel(true);
+                return;
+            }
+            String ignoreInteraction = this.getOption().getVariableValue(OperateOptionConst.IGNOREINTERACTION, StringUtils.EMPTY);
+            if (StringUtils.isBlank(ignoreInteraction) || !"true".equalsIgnoreCase(ignoreInteraction)) {
+                StringJoiner confirmMsg = new StringJoiner(",");
+                for (DynamicObject dataEntity : e.getDataEntities()) {
+                    long id = dataEntity.getLong(FormConstant.ID_KEY);
+                    Date date = dataEntity.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR);
+                    long personId = dataEntity.getDynamicObject(FormConstant.NCKD_PERSON).getLong(FormConstant.ID_KEY);
+                    QFilter filter = null;
+                    if (id > 0) {
+                        filter = new QFilter(FormConstant.ID_KEY, QCP.not_in, id);
+                    }
+                    DynamicObject[] lastPerfManagerArray = PerfManagerHelper.getBeforeBeginYear(date, Collections.singletonList(personId), filter);
+                    for (DynamicObject lastPerfManager : lastPerfManagerArray) {
+                        String personName = lastPerfManager.getDynamicObject(FormConstant.NCKD_PERSON).getString(FormConstant.NAME_KEY);
+                        LocalDateTime beginYear = DateUtil.toLocalDateTime(lastPerfManager.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR));
+                        LocalDateTime endYear = DateUtil.toLocalDateTime(lastPerfManager.getDate(PerfManagerFormConstant.NCKD_ENDYEAR));
+                        confirmMsg.add(StrFormatter.format("{}(周期:{}~{})", personName, beginYear.getYear(), endYear.getYear()));
+                    }
                 }
-                DynamicObject[] lastPerfManagerArray = PerfManagerHelper.getBeforeBeginYear(date, Collections.singletonList(personId), filter);
-                for (DynamicObject lastPerfManager : lastPerfManagerArray) {
-                    String personName = lastPerfManager.getDynamicObject(FormConstant.NCKD_PERSON).getString(FormConstant.NAME_KEY);
-                    LocalDateTime beginYear = DateUtil.toLocalDateTime(lastPerfManager.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR));
-                    LocalDateTime endYear = DateUtil.toLocalDateTime(lastPerfManager.getDate(PerfManagerFormConstant.NCKD_ENDYEAR));
-                    confirmMsg.add(StrFormatter.format("{}(周期:{}~{})", personName, beginYear.getYear(), endYear.getYear()));
+                if (confirmMsg.length() > 0) {
+                    e.cancel = !this.showInteractionMessage(confirmMsg.toString());
                 }
             }
-            if (confirmMsg.length() > 0) {
-                e.cancel = !this.showInteractionMessage(confirmMsg.toString());
-            }
         }
 
     }
@@ -501,6 +520,31 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
         //事务开始之后将其他考核周期设置为非最新
         PerfManagerHelper.markAsNotCurrentNewest(personBeginYearMap.keySet().toArray(new Long[0]));
 
+        boolean dataMigration;
+        Object invoker = this.getOption().getVariables().get(FormConstant.HR_INVOKER_PARAM_INVOKER);
+        if(ObjectUtils.isEmpty(invoker)){
+            Object invoker1 = this.getOption().getVariables().get("hr_hrdmvalidatetag_of_datasource");
+            Object invoker2 = this.getOption().getVariables().get("hr_hrdmsynctag_of_datasource");
+            if(!ObjectUtils.isEmpty(invoker1) || !ObjectUtils.isEmpty(invoker2)){
+                dataMigration = true;
+            } else {
+                dataMigration = false;
+            }
+        } else{
+            dataMigration = FormConstant.DATA_MIGRATION.equalsIgnoreCase(invoker.toString());
+        }
+        Map<Long, DynamicObject> empPosOrgRelMap = new HashMap<>();
+        if(dataMigration){
+            List<Long> personIds = new ArrayList<>();
+            for (DynamicObject dataEntity : e.getDataEntities()) {
+                DynamicObject person = dataEntity.getDynamicObject(FormConstant.NCKD_PERSON);
+                if(person != null){
+                    personIds.add(person.getLong(FormConstant.ID_KEY));
+                }
+            }
+            empPosOrgRelMap = EmpPosOrgRelHelper.queryEmpPosOrgRelWithOutPostByEmployeesMap(personIds);
+        }
+
         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<>();
@@ -509,7 +553,16 @@ public class PerfManagerSaveOpPlugin extends AbstractOperationServicePlugIn impl
         for (DynamicObject dataEntity : e.getDataEntities()) {
             long id = dataEntity.getLong(FormConstant.ID_KEY);
             DynamicObject person = dataEntity.getDynamicObject(FormConstant.NCKD_PERSON);
+            if(dataMigration) {
+                long personId = person.getLong(FormConstant.ID_KEY);
+                DynamicObject empPosOrgRel = empPosOrgRelMap.get(personId);
+                dataEntity.set(FormConstant.NCKD_EMPPOSORGREL,empPosOrgRel);
+            }
             DynamicObject empPosOrgRel = dataEntity.getDynamicObject(FormConstant.NCKD_EMPPOSORGREL);
+            if(empPosOrgRel == null){
+                continue;
+            }
+
             person = person == null ? empPosOrgRel.getDynamicObject(FormConstant.EMPLOYEE_KEY) : person;
             dataEntity.set(FormConstant.NCKD_PERSON, person);
             LocalDateTime beginYear = DateUtil.toLocalDateTime(dataEntity.getDate(PerfManagerFormConstant.NCKD_BEGINYEAR));

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

@@ -3,17 +3,13 @@ package nckd.jxccl.opmc.pm.plugin.operate.salary;
 import com.alibaba.fastjson.JSON;
 import kd.bos.context.RequestContext;
 import kd.bos.dataentity.entity.DynamicObject;
-import kd.bos.db.tx.TX;
-import kd.bos.db.tx.TXHandle;
 import kd.bos.entity.ExtendedDataEntity;
 import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
 import kd.bos.entity.plugin.AddValidatorsEventArgs;
 import kd.bos.entity.plugin.PreparePropertysEventArgs;
 import kd.bos.entity.plugin.args.AfterOperationArgs;
 import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
-import kd.bos.entity.plugin.args.EndOperationTransactionArgs;
 import kd.bos.entity.validate.AbstractValidator;
-import kd.bos.servicehelper.BusinessDataServiceHelper;
 import kd.bos.servicehelper.operation.SaveServiceHelper;
 import kd.sdk.plugin.Plugin;
 import kd.sdk.swc.hcdm.business.helper.HCDMApplyBillServiceHelper;
@@ -21,15 +17,14 @@ import nckd.jxccl.base.common.constant.FormConstant;
 import nckd.jxccl.base.common.exception.ValidationException;
 import nckd.jxccl.base.common.utils.ConvertUtil;
 import nckd.jxccl.base.common.utils.StrFormatter;
+import nckd.jxccl.base.entity.helper.EntityHelper;
 import nckd.jxccl.opmc.pm.common.SalAdjTrackerConstant;
 
-import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.StringJoiner;
 import java.util.UUID;
 
 /**
@@ -76,7 +71,14 @@ public class PushAdjustOpPlugin extends AbstractOperationServicePlugIn implement
     List<DynamicObject> pushAdjusts = new ArrayList<>();
     @Override
     public void beginOperationTransaction(BeginOperationTransactionArgs e) {
-
+        Long salaryItemId = EntityHelper.getIdByNumber(FormConstant.HSBS_STANDARDITEM, FormConstant.POS_STANDARD_ITEM_NUMBER);
+        Long billTypeId = EntityHelper.getIdByNumber(FormConstant.BOS_BILLTYPE, FormConstant.HCDM_APPLYBILL_BT_ADJ);
+        Long countryId = EntityHelper.getIdByNumber(FormConstant.BD_COUNTRY, "001");
+        Long salaryAdjuStrSnId = EntityHelper.getIdByNumber(FormConstant.HSBS_SALARYADJUSTRSN, "kaohe");
+        Long currencyId = EntityHelper.getIdByNumber(FormConstant.BD_CURRENCY, "CNY");
+        Long adjApproveScmId = EntityHelper.getLatestIdByNumber(FormConstant.HCDM_ADJAPPROVESCM, "dingtiaoxin");
+        Long exRateTableId = EntityHelper.getIdByNumber(FormConstant.BD_EXRATETABLE, "ERT-01");
+        Long calFrequencyId = EntityHelper.getIdByNumber(FormConstant.HSBS_CALFREQUENCY, "000_m_001");
         String operateKey = e.getOperationKey();
 
         List<DynamicObject> updateAdjusts = new ArrayList<>();
@@ -114,19 +116,19 @@ public class PushAdjustOpPlugin extends AbstractOperationServicePlugIn implement
                     applyBill.put("_uniquecode", uniquecode);
                     applyBill.put("org", orgId);
                     //定调薪明细字段显示方案   调薪明细字段
-                    applyBill.put("billtype", 2215975998602655744L);
+                    applyBill.put("billtype", billTypeId);
                     //国家
-                    applyBill.put("billcountry", 1000001L);
+                    applyBill.put("billcountry", countryId);
                     //定调薪类型
-                    applyBill.put("salaryadjrsn", 2352337648716103680L);
+                    applyBill.put("salaryadjrsn", salaryAdjuStrSnId);
                     //默认币种
-                    applyBill.put("billcurrency", 1L);
+                    applyBill.put("billcurrency", currencyId);
                     //定调薪方案
-                    applyBill.put("salaryadjscm", 2322515162646457344L);
+                    applyBill.put("salaryadjscm", adjApproveScmId);
                     //汇率日期
                     applyBill.put("exchangeratedate", new Date());
                     //汇率表
-                    applyBill.put("exctable", 2321965096026258432L);
+                    applyBill.put("exctable", exRateTableId);
                     //默认生效日期
                     applyBill.put("effectivedate", new Date());
                     //草稿状态
@@ -142,8 +144,8 @@ public class PushAdjustOpPlugin extends AbstractOperationServicePlugIn implement
                     Long positionId = pushAdjust.getDynamicObject(SalAdjTrackerConstant.NCKD_POSITION).getLong(FormConstant.ID_KEY);
                     applyBillEntry.put("adjfile", adjFileInfo.getLong(FormConstant.ID_KEY));
                     applyBillEntry.put("employee", employeeId);
-                    applyBillEntry.put("standarditem", 2321899710350111744L);    //定调薪项目   岗位工资标准
-                    applyBillEntry.put("frequency", 1095454108284088320L);       //频度  月
+                    applyBillEntry.put("standarditem", salaryItemId);    //定调薪项目   岗位工资标准
+                    applyBillEntry.put("frequency", calFrequencyId);       //频度  月
                     applyBillEntry.put("amount", pushAdjust.getBigDecimal(SalAdjTrackerConstant.NCKD_MONEY));
 //            applyBillEntry.put("nckd_postgrade", salaryfile.getLong("position.nckd_postgrade.id"));  //岗级
                     applyBillEntry.put("position", positionId);

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

@@ -26,14 +26,9 @@ import kd.bos.servicehelper.QueryServiceHelper;
 import kd.bos.servicehelper.operation.OperationServiceHelper;
 import kd.bos.servicehelper.operation.SaveServiceHelper;
 import kd.bos.servicehelper.user.UserServiceHelper;
-import kd.hr.hbp.common.model.AuthorizedOrgResultWithSub;
 import kd.hr.hbp.common.model.OrgSubInfo;
 import kd.sdk.hr.hbp.business.helper.permission.HRPermissionServiceHelper;
 import kd.sdk.plugin.Plugin;
-import kd.sdk.swc.hcdm.business.helper.HCDMAdjFileServiceHelper;
-import kd.sdk.swc.hcdm.business.helper.HCDMSalaryStdServiceHelper;
-import kd.sdk.swc.hcdm.common.dto.stdtab.match.StdTableDataMatchParam;
-import kd.sdk.swc.hcdm.common.dto.stdtab.match.StdTableDataMatchResult;
 import nckd.jxccl.base.common.constant.FormConstant;
 import nckd.jxccl.base.common.enums.AppraisalResultEnum;
 import nckd.jxccl.base.common.exception.ValidationException;
@@ -119,6 +114,7 @@ public class SalaryAdjOpPlugin extends AbstractOperationServicePlugIn implements
                 ));
 
         List<SalaryAdjustmentResult> salaryAdjustmentResultList = new ArrayList<>();
+        Long salaryItemId = EntityHelper.getIdByNumber(FormConstant.HSBS_STANDARDITEM, FormConstant.POS_STANDARD_ITEM_NUMBER);
         for (DynamicObject perfManager : perfManagerList) {
             long id = perfManager.getLong(FormConstant.ID_KEY);
             if(perfManagerToSalaryAdjMap.get(id) == null) {
@@ -215,7 +211,7 @@ public class SalaryAdjOpPlugin extends AbstractOperationServicePlugIn implements
                         .collect(Collectors.toList());
 
                 DynamicObject standardItem = EntityHelper.newEntity(FormConstant.HSBS_STANDARDITEM);
-                standardItem.set(FormConstant.ID_KEY, FormConstant.STANDARDITEM_ID_KEY);
+                standardItem.set(FormConstant.ID_KEY, salaryItemId);
                 Map<String, Object> adjFileParams = new HashMap<>();
                 adjFileParams.put("employees", allPersonIds);
                 List<String> status = new ArrayList<>();
@@ -242,7 +238,7 @@ public class SalaryAdjOpPlugin extends AbstractOperationServicePlugIn implements
                         // 调薪档案ID
                         dataItem.put("adjfile", adjFileId);
                         // 调薪项目ID
-                        dataItem.put("standarditem", FormConstant.STANDARDITEM_ID_KEY);
+                        dataItem.put("standarditem", salaryItemId);
                         // 查询基准日期
                         dataItem.put("startdate", new Date());
                         // 唯一标识
@@ -254,7 +250,7 @@ public class SalaryAdjOpPlugin extends AbstractOperationServicePlugIn implements
                     adjRecordParams.put("data", dataList);
                     adjRecordParams.put("selprops", "salarystdv.rankentry.rank.id,salarystdv.rankentry.rank.name,salarystdv.rankentry.rank.number,salarystdv.rankentry.rank.index,salarystdv.rankentry.frankindex,company.id,company.name,");
                     //查询定调薪记录
-                    Map<String, Object> lastDecAdjRecordMap = HCDMAdjFileServiceHelper.getLastDecAdjRecords(adjRecordParams);
+                    Map<String, Object> lastDecAdjRecordMap = DispatchServiceHelper.invokeService("nckd.jxccl.swc.hcdm.servicehelper", "hcdm", "ISwcHCDMService", "getLastDecAdjRecords", adjRecordParams);
                     if (ConvertUtil.toBoolean(lastDecAdjRecordMap.get("success"))) {
                         List<Map> datas = ConvertUtil.toList(lastDecAdjRecordMap.get("data"), ArrayList::new);
                         for (Map data : datas) {
@@ -365,17 +361,17 @@ public class SalaryAdjOpPlugin extends AbstractOperationServicePlugIn implements
                             }
                             result.salaryRank = newSalaryRank;
                             result.reason += StrFormatter.format(";{}->{}", oldSalaryRank.getString(FormConstant.NAME_KEY), newSalaryRank.getString(FormConstant.NAME_KEY));
-                            List<StdTableDataMatchParam> matchParams = new ArrayList<>();
-                            StdTableDataMatchParam stdTableDataMatchParam = new StdTableDataMatchParam();
-                            stdTableDataMatchParam.setStdTableId(result.salaryStDv.getLong(FormConstant.ID_KEY));
-                            stdTableDataMatchParam.setStdItemId(FormConstant.STANDARDITEM_ID_KEY);
-                            stdTableDataMatchParam.setGradeId(result.oldSalaryGrade.getLong(FormConstant.ID_KEY));
-                            stdTableDataMatchParam.setRankId(newSalaryRank.getLong(FormConstant.ID_KEY));
+                            List<Map<String,Object>> matchParams = new ArrayList<>();
+                            Map<String,Object> stdTableDataMatchParam = new HashMap<>();
+                            stdTableDataMatchParam.put("stdTableId", result.salaryStDv.getLong(FormConstant.ID_KEY));
+                            stdTableDataMatchParam.put("stdItemId", salaryItemId);
+                            stdTableDataMatchParam.put("gradeId", result.oldSalaryGrade.getLong(FormConstant.ID_KEY));
+                            stdTableDataMatchParam.put("rankId", newSalaryRank.getLong(FormConstant.ID_KEY));
                             matchParams.add(stdTableDataMatchParam);
                             //获取薪酬项目、薪等、薪档对应金额
-                            List<StdTableDataMatchResult> stdTableDataMatchResults = HCDMSalaryStdServiceHelper.matchStdTableData(matchParams);
+                            List<Map<String,Object>> stdTableDataMatchResults = DispatchServiceHelper.invokeService("nckd.jxccl.swc.hcdm.servicehelper", "hcdm", "ISwcHCDMService", "matchStdTableData", matchParams);
                             if (!stdTableDataMatchResults.isEmpty()) {
-                                result.amount = stdTableDataMatchResults.get(0).getAmount();
+                                result.amount = ConvertUtil.toBigDecimal(stdTableDataMatchResults.get(0).get("amount"));
                             }
                             msgJoiner.add(StrFormatter.format("【{}】{}", result.personName, result.reason));
                         }

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

@@ -1,6 +1,5 @@
 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;
@@ -8,11 +7,11 @@ 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.exception.KDBizException;
 import kd.bos.logging.Log;
 import kd.bos.logging.LogFactory;
 import kd.bos.servicehelper.operation.SaveServiceHelper;
 import kd.sdk.plugin.Plugin;
-import nckd.jxccl.sit.hcsi.business.coordination.api.SinsurCoordBizSaveHandler;
 import nckd.jxccl.sit.hcsi.common.constant.SitConstant;
 
 import java.util.Arrays;
@@ -61,7 +60,7 @@ public class SIBaseSaveOpEx extends AbstractOperationServicePlugIn implements Pl
             if(!result.isSuccess()) {
                 logger.info("-------- 保存基数设置结果:" + result.getMessage());
                 logger.info("-------- 保存基数设置错误:" + result.getAllErrorOrValidateInfo());
-                throw new BizException("-------- 保存基数设置失败:" + result.getMessage());
+                throw new KDBizException("-------- 保存基数设置失败:" + result.getMessage());
             }
         }
     }

+ 148 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hcdm/common/SwcAdjFileServiceHelper.java

@@ -0,0 +1,148 @@
+package nckd.jxccl.swc.hcdm.common;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.validate.BillStatus;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.servicehelper.DispatchServiceHelper;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.utils.ConvertUtil;
+import nckd.jxccl.base.entity.helper.EntityHelper;
+import nckd.jxccl.base.hrpi.helper.EmpPosOrgRelHelper;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+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/21 16:02
+ */
+public class SwcAdjFileServiceHelper {
+
+    protected final static Log logger = LogFactory.getLog(SwcAdjFileServiceHelper.class);
+
+    /**
+     * 获取员工某个薪酬项目最新定调薪记录
+     * @param personIds 人员id
+     * @param standardItemNumber 定调薪项目编码
+     * @return: java.util.List<nckd.jxccl.base.swc.helper.AdjFileServiceHelper.SalaryAdjustmentResult>
+     * @author W.Y.C
+     * @date: 2025/12/21 16:06
+     */
+    public static List<SalaryAdjustmentResult> getLastDecAdjRecords(List<Long> personIds,String standardItemNumber) {
+        Long salaryItemId = EntityHelper.getIdByNumber(FormConstant.HSBS_STANDARDITEM, standardItemNumber);
+        //获取员工最新任职
+        Map<Long, DynamicObject> empPosOrgRelByEmployeesMap = EmpPosOrgRelHelper.queryEmpPosOrgRelByEmployeesMap(personIds);
+        List<Long> allEmpPosOrgRelIds = empPosOrgRelByEmployeesMap.values().stream()
+                .map(result -> result.getLong(FormConstant.ID_KEY))
+                .collect(Collectors.toList());
+
+        List<SalaryAdjustmentResult> salaryAdjustmentResultList = new ArrayList<>();
+
+        DynamicObject standardItem = EntityHelper.newEntity(FormConstant.HSBS_STANDARDITEM);
+        standardItem.set(FormConstant.ID_KEY, salaryItemId);
+        Map<String, Object> adjFileParams = new HashMap<>();
+        adjFileParams.put("employees", personIds);
+        List<String> status = new ArrayList<>();
+        status.add(BillStatus.C.toString());
+        adjFileParams.put("status", status);
+        //获取人员定薪档案
+        Map<String, Object> adjFileResult = DispatchServiceHelper.invokeBizService("swc", "hcdm", "IAdjFileInfoService", "queryAdjFileBoByEmp", adjFileParams);
+        if (ConvertUtil.toBoolean(adjFileResult.get("success"))) {
+            List<Map> list = ConvertUtil.toList(adjFileResult.get("data"), ArrayList::new);
+            List<Long> adjFileIds = new ArrayList<>();
+            for (Map map : list) {
+                Long id = ConvertUtil.toLong(map.get(FormConstant.ID_KEY));
+                //根据员工任职匹配
+                Long empPosOrgRelId = ConvertUtil.toLong(map.get("empposorgrel_id"));
+                if (allEmpPosOrgRelIds.contains(empPosOrgRelId)) {
+                    adjFileIds.add(id);
+                }
+            }
+            //构建定调薪记录查询条件
+            Map<String, Object> adjRecordParams = new HashMap<>();
+            List<Map<String, Object>> dataList = new ArrayList<>();
+            for (Long adjFileId : adjFileIds) {
+                Map<String, Object> dataItem = new HashMap<>();
+                // 调薪档案ID
+                dataItem.put("adjfile", adjFileId);
+                // 调薪项目ID
+                dataItem.put("standarditem", salaryItemId);
+                // 查询基准日期
+                dataItem.put("startdate", new Date());
+                // 唯一标识
+                dataItem.put("_uniquecode", "unique" + adjFileId);
+                dataList.add(dataItem);
+            }
+            adjRecordParams.put("data", dataList);
+            adjRecordParams.put("selprops", "salarystdv.rankentry.rank.id,salarystdv.rankentry.rank.name,salarystdv.rankentry.rank.number,salarystdv.rankentry.rank.index,salarystdv.rankentry.frankindex,company.id,company.name,hcdmorg.id,");
+            //查询定调薪记录
+            //hcdm_decadjrecor
+            Map<String, Object> lastDecAdjRecordMap = kd.sdk.swc.hcdm.business.helper.HCDMAdjFileServiceHelper.getLastDecAdjRecords(adjRecordParams);
+            if (ConvertUtil.toBoolean(lastDecAdjRecordMap.get("success"))) {
+                List<Map> datas = ConvertUtil.toList(lastDecAdjRecordMap.get("data"), ArrayList::new);
+                for (Map data : datas) {
+                    if (ConvertUtil.toBoolean(data.get("success"))) {
+                        List<DynamicObject> adjRecordList = ConvertUtil.toList(data.get("data"), ArrayList::new);
+                        for (DynamicObject dynamicObject : adjRecordList) {
+                            // 人员
+                            DynamicObject employee = dynamicObject.getDynamicObject("adjfile").getDynamicObject("employee");
+                            SalaryAdjustmentResult salaryAdjustmentResult = new SalaryAdjustmentResult();
+                            //薪酬管理组织
+                            DynamicObject hcdmOrg = dynamicObject.getDynamicObject("hcdmorg");
+                            //薪酬标准表版本
+                            DynamicObject salaryStDv = dynamicObject.getDynamicObject("salarystdv");
+                            //薪等(01岗、02岗)
+                            DynamicObject salaryGrade = dynamicObject.getDynamicObject("salarygrade");
+                            //薪档(1档、2档)
+                            DynamicObject salaryRank = dynamicObject.getDynamicObject("salaryrank");
+                            //金额
+                            BigDecimal amount = dynamicObject.getBigDecimal("amount");
+                            salaryAdjustmentResult.employee = employee;
+                            salaryAdjustmentResult.hcdmOrg = hcdmOrg;
+                            salaryAdjustmentResult.adjFileInfo = dynamicObject.getDynamicObject("adjfile");
+                            salaryAdjustmentResult.salaryStDv = salaryStDv;
+                            salaryAdjustmentResult.standardItem = standardItem;
+                            salaryAdjustmentResult.salaryGrade = salaryGrade;
+                            salaryAdjustmentResult.salaryRank = salaryRank;
+                            salaryAdjustmentResult.amount = amount;
+                            salaryAdjustmentResultList.add(salaryAdjustmentResult);
+                        }
+                    }
+                }
+            } else {
+                logger.error("查询定调薪记录失败");
+            }
+        } else {
+            logger.error("获取人员定薪档案失败");
+        }
+        return salaryAdjustmentResultList;
+    }
+
+
+    public static class SalaryAdjustmentResult {
+        /** 人员ID*/
+        public DynamicObject employee;
+        public DynamicObject hcdmOrg;
+        /**定调薪档案*/
+        public DynamicObject adjFileInfo;
+        /**薪酬标准表*/
+        public DynamicObject salaryStDv;
+        /** 定调薪项目 */
+        public DynamicObject standardItem;
+        /** 薪等(01岗、02岗)*/
+        public DynamicObject salaryGrade;
+        /** 薪档(1档、2档)*/
+        public DynamicObject salaryRank;
+        //金额
+        public BigDecimal amount;
+    }
+}

+ 41 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hcdm/mservice/SwcHCDMService.java

@@ -0,0 +1,41 @@
+package nckd.jxccl.swc.hcdm.mservice;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import kd.sdk.swc.hcdm.business.helper.HCDMAdjFileServiceHelper;
+import kd.sdk.swc.hcdm.business.helper.HCDMSalaryStdServiceHelper;
+import kd.sdk.swc.hcdm.common.dto.stdtab.match.StdTableDataMatchParam;
+import kd.sdk.swc.hcdm.common.dto.stdtab.match.StdTableDataMatchResult;
+import nckd.jxccl.swc.hcdm.mservice.api.ISwcHCDMService;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * 定调薪档案服务
+ * @author W.Y.C
+ * @date 2026/1/7 21:37
+ * @version 1.0
+ */
+public class SwcHCDMService implements ISwcHCDMService {
+    @Override
+    public Map<String, Object> getLastDecAdjRecords(Map<String, Object> param) {
+        return HCDMAdjFileServiceHelper.getLastDecAdjRecords(param);
+    }
+
+    @Override
+    public List<Map<String,Object>> matchStdTableData(List<Map<String,Object>> params) {
+        List<StdTableDataMatchParam> stdTableDataMatchParams = params.stream()
+                .map(m -> JSON.toJavaObject((JSONObject) JSON.toJSON(m), StdTableDataMatchParam.class))
+                .collect(Collectors.toList());
+        List<StdTableDataMatchResult> stdTableDataMatchResults = HCDMSalaryStdServiceHelper.matchStdTableData(stdTableDataMatchParams);
+        List<Map<String,Object>> result = new ArrayList<>();
+        return stdTableDataMatchResults.stream()
+                .filter(Objects::nonNull)
+                .map(r -> (Map<String, Object>) JSON.toJSON(r)) // 返回 JSONObject,兼容 Map
+                .collect(Collectors.toList());
+    }
+}

+ 31 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hcdm/mservice/api/ISwcHCDMService.java

@@ -0,0 +1,31 @@
+package nckd.jxccl.swc.hcdm.mservice.api;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+* 定调薪档案服务
+* @author W.Y.C
+* @date 2026/1/7 21:37
+* @version 1.0
+*/
+public interface ISwcHCDMService {
+
+    /**
+     * 获取上一次定调薪信息
+     * @param param
+     * @return: java.util.Map<java.lang.String, java.lang.Object>
+     * @author W.Y.C
+     * @date: 2026/01/07 21:35
+     */
+    Map<String, Object> getLastDecAdjRecords(Map<String, Object> param);
+
+    /**
+     * 标准表数据匹配::根据标准表、项目、薪等、薪档获取金额、薪点数等信息
+      * @param params
+     * @return: java.util.List<kd.sdk.swc.hcdm.common.dto.stdtab.match.StdTableDataMatchResult>
+     * @author W.Y.C
+     * @date: 2026/01/07 22:12
+     */
+    List<Map<String,Object>> matchStdTableData(List<Map<String,Object>> params);
+}

+ 35 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hcdm/servicehelper/ServiceFactory.java

@@ -0,0 +1,35 @@
+package nckd.jxccl.swc.hcdm.servicehelper;
+
+import kd.bos.dataentity.TypesContainer;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+* 薪酬微服务工厂类
+* @author W.Y.C
+* @date 2026/1/7 21:37
+* @version 1.0
+*/
+public class ServiceFactory {
+
+    private static final Map<String, String> SERVICE_MAP = new HashMap<String, String>() {
+        {
+            this.put("ISwcHCDMService", "nckd.jxccl.swc.hcdm.mservice.SwcHCDMService");
+        }
+    };
+
+    public static <T> T getService(Class<T> clazz) {
+        return (T)getService(clazz.getSimpleName());
+    }
+
+    public static Object getService(String serviceName) {
+        String className = (String)SERVICE_MAP.get(serviceName);
+        if (className == null) {
+            throw new RuntimeException(String.format(Locale.ROOT, "%s service not find", serviceName));
+        } else {
+            return TypesContainer.getOrRegisterSingletonInstance(className);
+        }
+    }
+}

+ 171 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hcss/formplugin/IncomeProofBillExPlugin.java

@@ -0,0 +1,171 @@
+package nckd.jxccl.swc.hcss.formplugin;
+
+import kd.bos.algo.DataSet;
+import kd.bos.dataentity.OperateOption;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.db.DB;
+import kd.bos.db.DBRoute;
+import kd.bos.entity.datamodel.IDataModel;
+import kd.bos.entity.param.CustomParam;
+import kd.bos.form.events.BeforeDoOperationEventArgs;
+import kd.bos.form.operate.FormOperate;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.orm.ORM;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.parameter.SystemParamServiceHelper;
+import kd.sdk.swc.hsas.business.internal.spi.CalResultQueryService;
+import kd.swc.hcss.formplugin.web.AbstractHcssBaseFormPlugin;
+import nckd.jxccl.swc.constants.SwcConstant;
+import nckd.jxccl.swc.utils.SwcUtils;
+
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 自定义收入证明项目列表
+ * 系统服务云-公共设置-系统参数-自定义参数
+ * 参数名称为 INCOMEPROOFBILL_CUSTOMITEMS 收入证明办理单,自定义收入证明项目编码 参数值为  000001,000002
+ * 参数名称为 INCOMEPROOFBILL_SALARYITEMS 收入证明办理单,自定义收入证明获取员工薪酬金额的薪酬项目编码 参数值为  JT_283,JT_477  示例
+ * @author turborao
+ * @date 2025-12-03
+ * @desc
+ */
+public class IncomeProofBillExPlugin extends AbstractHcssBaseFormPlugin {
+
+    private static String IncomeProofBill_CustomItems;
+    private static String IncomeProofBill_SalaryItems;
+    private static final Log logger = LogFactory.getLog(IncomeProofBillExPlugin.class);
+
+    public void initialize() {
+
+        CustomParam customParam = new CustomParam();
+        customParam.getSearchKeySet().add("INCOMEPROOFBILL_CUSTOMITEMS");
+        customParam.getSearchKeySet().add("INCOMEPROOFBILL_SALARYITEMS");
+        Map<String, String> cusTomMap = SystemParamServiceHelper.loadCustomParameterFromCache(customParam);
+        IncomeProofBill_CustomItems  = cusTomMap.get("INCOMEPROOFBILL_CUSTOMITEMS");
+        IncomeProofBill_SalaryItems  = cusTomMap.get("INCOMEPROOFBILL_SALARYITEMS");
+
+    }
+
+
+    @Override
+    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
+
+        FormOperate source = (FormOperate)args.getSource();
+        OperateOption option = source.getOption();
+        String formOp = source.getOperateKey();
+        Long id = this.getModel().getDataEntity().getLong("id");
+        DynamicObject data = this.getModel().getDataEntity();
+        Long empId = data.getLong("employee.id");
+        Date startDate = data.getDate("nckd_startdate");
+        Date endDate = data.getDate("nckd_enddate");
+
+        boolean isExistCustomItems = false;
+        if ("checkapprove".equals(formOp)) {
+            isExistCustomItems = isExistCustomItems(data);
+        }
+
+        super.beforeDoOperation(args);
+
+        /**
+         * 以上需要保留标准产品计算逻辑,
+         * 有自定义收入证明项目时才取数
+         */
+        if(isExistCustomItems){
+            String salaryitem = getSalaryItemsForSql();
+            DynamicObjectCollection salaryDetail = querySalaryDetailByEmp(empId, salaryitem, startDate, endDate);
+            if(salaryDetail.size() > 0){
+                DynamicObject salaryDetailObj = salaryDetail.get(0);
+                BigDecimal amount = salaryDetailObj.getBigDecimal("amount");
+                BigDecimal monthCount = salaryDetailObj.getBigDecimal("monthCount");
+                BigDecimal monthlyAmount = amount.divide(monthCount, 2, BigDecimal.ROUND_HALF_UP);
+                //赋值
+                dealIncomeInfo(amount, monthlyAmount);
+            }
+        }
+    }
+
+
+    /**
+     * 根据薪员工 +日期范围获取薪资明细
+     * @return
+     */
+    public DynamicObjectCollection querySalaryDetailByEmp(Long empId,String salaryitem, Date startDate, Date endDate) {
+        StringBuilder sb = SwcUtils.getSalaryDetailSqlByEmp(empId, salaryitem,startDate, endDate);
+        DataSet dataSet = DB.queryDataSet(this.getClass().getName(), DBRoute.of("swc"), sb.toString());
+        DynamicObjectCollection cols = ORM.create().toPlainDynamicObjectCollection(dataSet);
+        return cols;
+
+    }
+
+    private void dealIncomeInfo(BigDecimal amount, BigDecimal monthlyAmount) {
+        List<String> customItems = getCustomItems();
+        IDataModel model = this.getModel();
+        int rowCount = model.getEntryRowCount("entryentity");
+        String regex = "[^0-9.]";
+        for(int i = 0; i < rowCount; i++) {
+            String revenueFieldNum = model.getValue("frevenuefieldid.number", i).toString();
+            if(revenueFieldNum.equals(customItems.get(0))){
+                model.setValue("calvalue", amount.toString(), i);
+                model.setValue("checkvalue", amount.toString(), i);
+            }
+            if(revenueFieldNum.equals(customItems.get(1))){
+                model.setValue("calvalue", monthlyAmount.toString(), i);
+                model.setValue("checkvalue", monthlyAmount.toString(), i);
+            }
+        }
+    }
+
+
+    /**
+     * 判断 收入证明办理单中是否包含自定义收入证明项目
+     */
+    public boolean isExistCustomItems(DynamicObject data) {
+        List<String> customItems = getCustomItems();
+        // 如果没有自定义项目配置,直接返回 true(或根据业务需求决定)
+        if (customItems.isEmpty()) {
+            return false;
+        }
+        List<String> entryNumbers = new ArrayList<>();
+        DynamicObjectCollection dynamicObjectCollection = data.getDynamicObjectCollection("entryentity");
+        for (DynamicObject dynamicObject : dynamicObjectCollection) {
+            DynamicObject revenueField = dynamicObject.getDynamicObject("revenuefield");
+            String number = revenueField.getString("number");
+            entryNumbers.add(number);
+
+        }
+        for (String customItem : customItems) {
+            if (!entryNumbers.contains(customItem)) {
+                return false;
+            }
+        }
+        return false;
+    }
+
+    public List<String> getCustomItems() {
+        if (IncomeProofBill_CustomItems == null || IncomeProofBill_CustomItems.trim().isEmpty()) {
+            return new java.util.ArrayList<>();
+        }
+        return java.util.Arrays.asList(IncomeProofBill_CustomItems.split(","));
+    }
+
+    public String getSalaryItemsForSql() {
+        if (IncomeProofBill_SalaryItems == null || IncomeProofBill_SalaryItems.trim().isEmpty()) {
+            return "''"; // 返回空字符串的 SQL 格式
+        }
+
+        String[] items = IncomeProofBill_SalaryItems.split(",");
+        List<String> quotedItems = new ArrayList<>();
+
+        for (String item : items) {
+            quotedItems.add("'" + item.trim() + "'");
+        }
+
+        return String.join(",", quotedItems);
+    }
+
+}

+ 11 - 7
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hsbs/formplugin/web/basedata/salarygroup/PerSalaryGroupEdit.java

@@ -1,5 +1,6 @@
 package nckd.jxccl.swc.hsbs.formplugin.web.basedata.salarygroup;
 
+import kd.bos.form.IFormView;
 import kd.bos.form.plugin.AbstractFormPlugin;
 import kd.sdk.plugin.Plugin;
 
@@ -13,13 +14,16 @@ public class PerSalaryGroupEdit extends AbstractFormPlugin implements Plugin {
 
     @Override
     public void afterCreateNewData(EventObject e) {
-        Object employeeIdObj = this.getView().getParentView().getFormShowParameter().getCustomParam("employeeId");
-        if (null != employeeIdObj) {
-            this.getView().getModel().setValue("nckd_employee", Long.parseLong(String.valueOf(employeeIdObj)));
-        }
-        Object salaryFileObj = this.getView().getParentView().getFormShowParameter().getCustomParam("salaryfileId");
-        if (null != salaryFileObj) {
-            this.getView().getModel().setValue("nckd_salaryfile", Long.parseLong(String.valueOf(salaryFileObj)));
+        IFormView parentView = this.getView().getParentView();
+        if(parentView != null) {
+            Object employeeIdObj = this.getView().getParentView().getFormShowParameter().getCustomParam("employeeId");
+            if (null != employeeIdObj) {
+                this.getView().getModel().setValue("nckd_employee", Long.parseLong(String.valueOf(employeeIdObj)));
+            }
+            Object salaryFileObj = this.getView().getParentView().getFormShowParameter().getCustomParam("salaryfileId");
+            if (null != salaryFileObj) {
+                this.getView().getModel().setValue("nckd_salaryfile", Long.parseLong(String.valueOf(salaryFileObj)));
+            }
         }
     }
 }

+ 2 - 1
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/common/HasPosAllowDataService.java → code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hscs/business/custfetch/HasPosAllowDataService.java

@@ -1,4 +1,4 @@
-package nckd.jxccl.hr.psms.common;
+package nckd.jxccl.swc.hscs.business.custfetch;
 
 import kd.bos.common.enums.EnableEnum;
 import kd.bos.dataentity.entity.DynamicObject;
@@ -14,6 +14,7 @@ import nckd.jxccl.base.common.enums.psms.TypeStateEnum;
 import nckd.jxccl.base.common.utils.DateUtil;
 import nckd.jxccl.base.common.utils.QueryFieldBuilder;
 import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
+import nckd.jxccl.swc.hscs.common.PositionStructureConstant;
 
 import java.util.Arrays;
 import java.util.Date;

+ 8 - 6
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/common/PosSalaryGrade1.java → code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hscs/business/custfetch/PosSalaryGrade1.java

@@ -1,4 +1,4 @@
-package nckd.jxccl.hr.psms.common;
+package nckd.jxccl.swc.hscs.business.custfetch;
 
 import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.dataentity.entity.DynamicObjectCollection;
@@ -16,7 +16,8 @@ import nckd.jxccl.base.common.constant.FormConstant;
 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.swc.helper.AdjFileServiceHelper;
+import nckd.jxccl.base.entity.helper.EntityHelper;
+import nckd.jxccl.swc.hcdm.common.SwcAdjFileServiceHelper;
 
 import java.math.BigDecimal;
 import java.util.ArrayList;
@@ -41,6 +42,7 @@ public class PosSalaryGrade1 implements ICustomFetchDataService {
     public Map<Long, Map<String, Object>> fetchDataCalPerson(List<Long> calPersonIdList, Map<Long, Map<String, Object>> paramsMap, Map<String, Object> extParamMap) {
         Map<Long, Map<String, Object>> resultMap = new HashMap<Long, Map<String, Object>>();
 
+        Long salaryItemId = EntityHelper.getIdByNumber(FormConstant.HSBS_STANDARDITEM, FormConstant.POS_STANDARD_ITEM_NUMBER);
         QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
                 .add(FormConstant.ID_KEY)
                 .add(FormConstant.EMP_NUMBER_KEY)
@@ -74,7 +76,7 @@ public class PosSalaryGrade1 implements ICustomFetchDataService {
             if(!employeeToCalPersonMap.isEmpty()) {
                 //获取人员最新岗位工资标准定薪记录
                 List<Long> allPersonIds = ConvertUtil.toList(employeeToCalPersonMap.values());
-                List<AdjFileServiceHelper.SalaryAdjustmentResult> salaryAdjustmentResultList = AdjFileServiceHelper.getLastDecAdjRecords(allPersonIds, FormConstant.STANDARDITEM_ID_KEY);
+                List<SwcAdjFileServiceHelper.SalaryAdjustmentResult> salaryAdjustmentResultList = SwcAdjFileServiceHelper.getLastDecAdjRecords(allPersonIds, FormConstant.POS_STANDARD_ITEM_NUMBER);
                 if (!salaryAdjustmentResultList.isEmpty()) {
                     //薪酬标准ID
                     List<Long> salaryStIds = salaryAdjustmentResultList.stream().map(result -> result.salaryStDv.getLong(FormConstant.ID_KEY)).collect(Collectors.toList());
@@ -93,10 +95,10 @@ public class PosSalaryGrade1 implements ICustomFetchDataService {
 
                     if (!salaryStandardMap.isEmpty()) {
                         List<StdTableDataMatchParam> matchParams = new ArrayList<>();
-                        for (AdjFileServiceHelper.SalaryAdjustmentResult result : salaryAdjustmentResultList) {
+                        for (SwcAdjFileServiceHelper.SalaryAdjustmentResult result : salaryAdjustmentResultList) {
                             StdTableDataMatchParam stdTableDataMatchParam = new StdTableDataMatchParam();
                             stdTableDataMatchParam.setStdTableId(result.salaryStDv.getLong(FormConstant.ID_KEY));
-                            stdTableDataMatchParam.setStdItemId(FormConstant.STANDARDITEM_ID_KEY);
+                            stdTableDataMatchParam.setStdItemId(salaryItemId);
                             stdTableDataMatchParam.setGradeId(result.salaryGrade.getLong(FormConstant.ID_KEY));
                             DynamicObject dynamicObject = salaryStandardMap.get(result.salaryStDv.getLong(FormConstant.ID_KEY));
                             if (dynamicObject != null) {
@@ -109,7 +111,7 @@ public class PosSalaryGrade1 implements ICustomFetchDataService {
                             //获取薪酬项目、薪等、薪档对应金额(入参params的数组下标和出参的数组下标一一对应)
                             List<StdTableDataMatchResult> stdTableDataMatchResults = HCDMSalaryStdServiceHelper.matchStdTableData(matchParams);
                             for (int i = 0; i < salaryAdjustmentResultList.size(); i++) {
-                                AdjFileServiceHelper.SalaryAdjustmentResult result = salaryAdjustmentResultList.get(i);
+                                SwcAdjFileServiceHelper.SalaryAdjustmentResult result = salaryAdjustmentResultList.get(i);
                                 if (i < stdTableDataMatchResults.size() && stdTableDataMatchResults.get(i) != null) {
                                     //当前薪等01档的金额
                                     amountMap.put(result.employee.getLong(FormConstant.ID_KEY), stdTableDataMatchResults.get(i).getAmount());

+ 337 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/hscs/common/PositionStructureConstant.java

@@ -0,0 +1,337 @@
+package nckd.jxccl.swc.hscs.common;
+
+import nckd.jxccl.base.common.constant.FormConstant;
+
+/**
+ * 职位体系常量
+ * @author W.Y.C
+ * @date 2025/9/10 16:09
+ * @version 1.0
+ */
+public class PositionStructureConstant extends FormConstant {
+    /*-------------------------------------- 员工职位档案 begin --------------------------------------*/
+    /** 员工职位档案-实体标识 */
+    public static final String PERSONPOSFILE_ENTITYID = "nckd_personposfile";
+    /** 开始日期 */
+    public static final String NCKD_BEGINDATE = "nckd_begindate";
+    /** 所属序列 */
+    public static final String NCKD_JOBSEQHR = "nckd_jobseqhr";
+    /** 职级 */
+    public static final String NCKD_JOBLEVELHR = "nckd_joblevelhr";
+    /** 是否初次定级 */
+    public static final String NCKD_FIRSTRANK = "nckd_firstrank";
+    /** 学历 */
+    public static final String NCKD_DIPLOMA = "nckd_diploma";
+    /** 岗位 */
+    public static final String NCKD_POSITIONHR = "nckd_positionhr";
+    /** 岗位 */
+    public static final String NCKD_POSITION = "nckd_position";
+    /** 职称名称 */
+    public static final String NCKD_RANKNAME = "nckd_rankname";
+    /** 职称级别 */
+    public static final String NCKD_PROTITLELEVEL = "nckd_protitlelevel";
+    /** 技能名称 */
+    public static final String NCKD_JOBSTATUSNAME = "nckd_jobstatusname";
+    /** 技能等级 */
+    public static final String NCKD_OCPQUALLEVEL = "nckd_ocpquallevel";
+    /** 上年度绩效考核结果 */
+    public static final String NCKD_APPRAISALRESULT = "nckd_appraisalresult";
+    /** 上年度员工职位档案 */
+    public static final String NCKD_LASTPERSONPOSFILE = "nckd_lastpersonposfile";
+    /** 聘任状态 */
+    public static final String NCKD_EMPLOYMENTSTATUS = "nckd_employmentstatus";
+    /** 类型状态(新入职人员初定1;在职人员初定2;年度调整3;职位调动4;管理序列的聘任5;高级职称的聘任6) */
+    public static final String NCKD_TYPESTATE = "nckd_typestate";
+    /** 连续聘任年限 */
+    public static final String NCKD_EMPLOYMENTYEARS = "nckd_employmentyears";
+    /** 上年度绩效考核分数 */
+    public static final String NCKD_RESULTSCORE = "nckd_resultscore";
+    /** 优秀生分 */
+    public static final String NCKD_ORGINSSCORE = "nckd_orginsscore";
+    /** 职称分 */
+    public static final String NCKD_RANKSCORE = "nckd_rankscore";
+    /** 技能分 */
+    public static final String NCKD_JOBSTATUSSCORE = "nckd_jobstatusscore";
+    /** 学历分 */
+    public static final String NCKD_DIPLOMASCORE = "nckd_diplomascore";
+    /** 是否失效 */
+    public static final String NCKD_DISABLE = "nckd_disable";
+    /** 上年度贡献综合评价分 */
+    public static final String NCKD_LYRCONTRIBSCORE = "nckd_lyrcontribscore";
+    /** 任命结束日期 */
+    public static final String NCKD_ENDDATE = "nckd_enddate";
+    /** 任命状态 */
+    public static final String NCKD_APPOINTSTATUS = "nckd_appointstatus";
+    /** 年度 */
+    public static final String NCKD_EXECUTEYEAR = "nckd_executeyear";
+    /** 调整类别(升级2;保级1;降级0;首次聘任3;序列变化4;聘任下调5;总分不足6;无聘任7;无考核结果8) */
+    public static final String NCKD_ADJUSTTYPE = "nckd_adjusttype";
+    /** 年度调整状态 */
+    public static final String NCKD_ADJUSSTATUS = "nckd_adjusstatus";
+    /** 上年度绩效排名R百分比 */
+    public static final String NCKD_ALLOWANCERANKPCT = "nckd_allowancerankpct";
+    /** 年度科研与创新分 */
+    public static final String NCKD_YEARSCORESUMA = "nckd_yearscoresuma";
+    /** 年度专利申报分 */
+    public static final String NCKD_YEARSCORESUMB = "nckd_yearscoresumb";
+    /** 年度论文发表分 */
+    public static final String NCKD_YEARSCORESUMC = "nckd_yearscoresumc";
+    /** 年度技能竞赛分 */
+    public static final String NCKD_YEARSCORESUMD = "nckd_yearscoresumd";
+    /** 年度培训教材分 */
+    public static final String NCKD_YEARSCORESUME = "nckd_yearscoresume";
+    /** 年度技术标准分 */
+    public static final String NCKD_YEARSCORESUMF = "nckd_yearscoresumf";
+    /** 年度管理规范分 */
+    public static final String NCKD_YEARSCORESUMG = "nckd_yearscoresumg";
+    /** 年度师带徒分 */
+    public static final String NCKD_YEARSCORESUMH = "nckd_yearscoresumh";
+    /** 年度培训授课分 */
+    public static final String NCKD_YEARSCORESUMI = "nckd_yearscoresumi";
+    /** 贡献单据分数之和 */
+    public static final String NCKD_ALLYEARSCORESUM = "nckd_allyearscoresum";
+    /** 累计总积分 */
+    public static final String NCKD_ALLSUMSCORE = "nckd_allsumscore";
+    /** 累计的积分池 */
+    public static final String NCKD_SUMSCORE = "nckd_sumscore";
+    /** 年度新增的贡献积分 */
+    public static final String NCKD_ADDYCONTRIBSCORE = "nckd_addycontribscore";
+    /** 升降级数 */
+    public static final String NCKD_ADJUSTINT = "nckd_adjustint";
+    /** 上年度绩效排名R名次 */
+    public static final String NCKD_ALLOWANCERANK = "nckd_allowancerank";
+    /** 上年度排名名次 */
+    public static final String NCKD_TOPRANK = "nckd_toprank";
+    /** 上年度排名百分比 */
+    public static final String NCKD_TOPRANKPERCENT = "nckd_toprankpercent";
+    /** 备注 */
+    public static final String KEY_NCKD_CAUSEREMARK = "nckd_causeremark";
+    /** 学历分计算过程 */
+    public static final String NCKD_WHYDIPLOMASCORE = "nckd_whydiplomascore";
+    /** R排名名次/R排名总人数 */
+    public static final String NCKD_ALLOWANCERANKMARK = "nckd_allowancerankmark";
+    /** R排名百分比 */
+    public static final String NCKD_ALLOWANCERANKSEL = "nckd_allowanceranksel";
+
+    /** 锁定状态 */
+    public static final String NCKD_LOCKSTATUS = "nckd_lockstatus";
+    /** 锁定状态 */
+    public static final String KEY_NCKD_LOCKUSER = "nckd_lockuser";
+    /** 锁定人 */
+    public static final String NCKD_LOCKDATETIME = "nckd_lockdatetime";
+    /** 锁定人 */
+    public static final String NCKD_LEVELKEEPREASON = "nckd_levelkeepreason";
+    /** 锁定时间*/
+    public static final String POSITIONAPPOINTMENTQUERY = "positionappointmentquery";
+
+    /** 系数 */
+    public static final String NCKD_COEFFICIENT = "nckd_coefficient";
+    /** 当前01档岗位工资 */
+    public static final String NCKD_CURRENTPOSTSALARY = "nckd_currentpostsalary";
+    /** 岗位津贴 */
+    public static final String NCKD_POSTALLOWANCE = "nckd_postallowance";
+    /** 是否已推送调薪 */
+    public static final String NCKD_ISSALADJPUSH = "nckd_issaladjpush";
+    /** 调薪推送时间 */
+    public static final String NCKD_SALADJPUSHTIME = "nckd_saladjpushtime";
+    /** 调薪id */
+    public static final String NCKD_SALADJID = "nckd_saladjid";
+    /** 调薪编码 */
+    public static final String NCKD_SALADJNUMBER = "nckd_saladjnumber";
+
+    /*-------------------------------------- 员工职位档案 end --------------------------------------*/
+
+
+    /*-------------------------------------- 职位及积分初定 begin --------------------------------------*/
+    /** 职位及积分初定-实体标识 */
+    public static final String SCOREINITIAL_ENTITYID = "nckd_scoreinitial";
+    /** 页签控件 */
+    public static final String NCKD_TABAP = "nckd_tabap";
+    /** 页签控件-已定级人员 */
+    public static final String NCKD_GRADEDPERSON = "nckd_gradedperson";
+    /** 页签控件-未定级人员 */
+    public static final String NCKD_UNGRADEDPERSON = "nckd_ungradedperson";
+    /*-------------------------------------- 职位及积分初定 end --------------------------------------*/
+
+
+    /*-------------------------------------- 未定级人员列表 begin --------------------------------------*/
+    /** 未定级人员-实体标识 */
+    public static final String UNGRADEDPERSONQUERY_ENTITYID = "ungradedpersonquery";
+    /** 在职人员初定-操作 */
+    public static final String OP_SETTINGJOBGRADE = "settingjobgrade";
+    /** 新入职人员初定-操作 */
+    public static final String OP_SETTINGJOBGRADENEW = "settingjobgradenew";
+    /*-------------------------------------- 未定级人员列表 end --------------------------------------*/
+
+    /*-------------------------------------- 已定级人员列表 begin --------------------------------------*/
+    /** 职位及积分初定-实体标识 */
+    public static final String GRADEDPERSONQUERY_ENTITYID = "gradedpersonquery";
+    /*-------------------------------------- 已定级人员列表 end --------------------------------------*/
+
+
+    /*-------------------------------------- 在职人员初定(弹窗) begin --------------------------------------*/
+    /** 在职人员初定(弹窗)-实体标识 */
+    public static final String SERVINGINITIAL_ENTITYID = "nckd_servinginitial";
+    /** 批量在职人员初定(弹窗)-实体标识 */
+    public static final String SERVINGINITIALBATH_ENTITYID = "nckd_servinginitialbatch";
+    /** 职位序列(根据岗位需要自动带出) */
+    public static final String NCKD_JOBSEQ = "nckd_jobseq";
+    /** 优秀生 */
+    public static final String NCKD_EXCELLENT = "nckd_excellent";
+
+    /*-------------------------------------- 在职人员初定(弹窗) end --------------------------------------*/
+
+
+    /*-------------------------------------- 新入职人员初定(弹窗) begin --------------------------------------*/
+    /** 新入职人员初定(弹窗)-实体标识 */
+    public static final String NEWHIREINITIAL_ENTITYID = "nckd_newhireinitial";
+    /** 批量新入职人员初定(弹窗)-实体标识 */
+    public static final String NEWHIREINITIALBATCH_ENTITYID = "nckd_newhireinitialbatch";
+    /** 本次加入集团日期 */
+    public static final String NCKD_JOINCOMDATE = "nckd_joincomdate";
+    /** 确认定级 */
+    public static final String OP_CONFIRMINITIAL = "confirmInitial";
+    /*-------------------------------------- 新入职人员初定(弹窗) end --------------------------------------*/
+
+    /*-------------------------------------- 新建动态调整(弹窗) begin --------------------------------------*/
+    /** 新建动态调整(弹窗)-实体标识 */
+    public static final String NEWDYNAMICADJUDIALOG_ENTITYID = "nckd_newdynamicadjudialog";
+    /** 批量新建动态调整(弹窗)-实体标识 */
+    public static final String NEWDYNAMICADJUBATCH_ENTITYID = "nckd_newdynamicadjubatch";
+    /** 本次加入集团日期 */
+    public static final String NCKD_ADJUSTDATE = "nckd_adjustdate";
+    //调动后职级
+    public static final String NCKD_JOBLEVEL = "nckd_joblevel";
+    /** 确认定级 */
+    public static final String OP_CONFIRMADJUST = "confirmadjust";
+    /** R排名名次/R排名总人数 */
+    public static final String NCKD_ALLOWANCERANKPERCENT = "nckd_allowancerankpercent";
+    /** 职称等级 */
+    public static final String NCKD_PERPROTITLENAME = "nckd_perprotitlename";
+    /** 技能等级 */
+    public static final String NCKD_QUALEVELNAME = "nckd_qualevelname";
+
+    /*-------------------------------------- 新建动态调整(弹窗) end --------------------------------------*/
+
+    /*-------------------------------------- 年度动态调整(弹窗) begin --------------------------------------*/
+    /** 新建动态调整(弹窗)-实体标识 */
+    public static final String NEWANNUALADJUST_ENTITYID = "nckd_newannualadjust";
+    /** 动态调整-锁定 */
+    public static final String ISLOCKED_OP = "islocked";
+    /** 动态调整-解锁 */
+    public static final String UNLOCKED_OP = "unlocked";
+    /** 动态调整-按年度批量锁定 */
+    public static final String BATCHLOCKYEAR_OP = "batchlockyear";
+    /** 动态调整-按年度批量解锁 */
+    public static final String BATCHUNLOCKYEAR_OP = "batchunlockyear";
+    /*-------------------------------------- 年度动态调整(弹窗) end --------------------------------------*/
+
+    /*-------------------------------------- 年度动态调整-生效(弹窗) begin --------------------------------------*/
+    /** 新建动态调整(弹窗)-实体标识 */
+    public static final String ANNUALEFFECTIVE_ENTITYID = "nckd_annualeffective";
+    public static final String NCKD_MULSELEPERSONPOSFILE = "nckd_mulselepersonposfile";
+    /*-------------------------------------- 年度动态调整-生效(弹窗) end --------------------------------------*/
+
+
+    /*-------------------------------------- 职位及积分初定 begin --------------------------------------*/
+    /** 职位及积分初定-实体标识 */
+    public static final String DYNAMICADJUSTMENT_ENTITYID = "nckd_dynamicadjustment";
+    /** 页签控件-已生成动态调整 */
+    public static final String NCKD_ADJUSTED = "nckd_adjusted";
+    /** 页签控件-未生成动态调整 */
+    public static final String NCKD_UNADJUSTED = "nckd_unadjusted";
+    public static final String ADJUST_QUERY = "adjustquery";
+    public static final String NCKD_UNADJUSTREPORT = "nckd_unadjustreport";
+    /*-------------------------------------- 职位及积分初定 end --------------------------------------*/
+
+    /*-------------------------------------- 年度调整 begin --------------------------------------*/
+    /** 职位及积分初定-实体标识 */
+    public static final String ANNUALADJUSTMENT_ENTITYID = "nckd_annualadjustment";
+    /** 已生成年度调整-实体标识 */
+    public static final String ANNUALADJUST_QUERY = "annualadjustquery";
+    /** 未生成年度调整-实体标识 */
+    public static final String UNANNUALADJUST_QUERY = "unannualadjustquery";
+    /*-------------------------------------- 年度调整 begin --------------------------------------*/
+
+
+    /*-------------------------------------- 年度调整解锁单据 begin --------------------------------------*/
+    /** 年度调整解锁单据-实体标识 */
+    public static final String POSFILEUNLOCK_ENTITYID = "nckd_posfileunlock";
+    /** 单据体 */
+    public static final String NCKD_POSFILEUNLOCKENTRY = "nckd_posfileunlockentry";
+    /** 职位档案 */
+    public static final String NCKD_PERSONPOSFILE = "nckd_personposfile";
+    /** 解锁原因 */
+    public static final String NCKD_REASON = "nckd_reason";
+
+    /*-------------------------------------- 年度调整解锁单据 end --------------------------------------*/
+
+    /*-------------------------------------- 配置有职位津贴的管理人员 begin --------------------------------------*/
+    /** 配置有职位津贴的管理人员-实体标识 */
+    public static final String MANAGERALLOWANCE_ENTITYID = "nckd_managerallowance";
+    /*-------------------------------------- 配置有职位津贴的管理人员 end --------------------------------------*/
+
+
+    /**职位序列对应职级查询*/
+    public static final String JOBSEQTOJOBLEVEL_QUERY = "jobseqtojoblevelquery";
+    /**根据职位序列查询职级*/
+    public static final String GETLEVELBYJOBSEQ_QUERY = "getlevelbyjobseqquery";
+    /**根据职位序列和资格级别查询职级*/
+    public static final String GETLEVELBYJOBSEQQUERYANDQUAL_QUERY = "getlevelbyjobseqqueryandqualquery";
+
+
+    /** 人员考评实体名称 */
+    public static final String PERFMANAGER_ENTITYID = "nckd_perfmanager";
+    /** 人员考评管理分录实体名称 */
+    public static final String PERFMANAGER_ENTRY_ENTITYID = "nckd_perfmanagerentry";
+    /** 分录-考核年份 */
+    public static final String APPRAISAL_YEAR_KEY = "nckd_appraisalyear";
+
+    /*-------------------------------------- 新建任命 begin --------------------------------------*/
+    /** 新建任命-实体标识 */
+    public static final String NEWAPPTPOPUP_ENTITYID = "nckd_newapptpopup";
+    /*-------------------------------------- 新建任命 end --------------------------------------*/
+
+
+    /*-------------------------------------- 职位津贴配置 begin --------------------------------------*/
+    /** 职位津贴配置-实体标识 */
+    public static final String MGRPOSTALLOWCONF_ENTITYID = "nckd_mgrpostallowconf";
+    /** 适用单位 */
+    public static final String NCKD_ORG = "nckd_org";
+    /** 最大职级 */
+    public static final String NCKD_MAXJOBLEVEL = "nckd_maxjoblevel";
+    /** 最小职级 */
+    public static final String NCKD_MINJOBLEVEL = "nckd_minjoblevel";
+    /*-------------------------------------- 职位津贴配置 end --------------------------------------*/
+
+    /** 周期开始年份 */
+    public static final String NCKD_BEGINYEAR = "nckd_beginyear";
+    /** 周期结束年份 */
+    public static final String NCKD_ENDYEAR = "nckd_endyear";
+    /** 人员考评管理分录实体名称 */
+    public static final String NCKD_PERFMANAGERENTRY = "nckd_perfmanagerentry";
+    /** 分录-考核年份 */
+    public static final String NCKD_APPRAISALYEAR = "nckd_appraisalyear";
+
+
+
+    /** 关键行为评价表-实体标识 */
+    public static final String KEYBEHAVEVAL_ENTITYID = "nckd_keybehaveval";
+    /** HR员工 */
+    public static final String NCKD_PERSON = "nckd_person";
+    /** 科研、创新、创效成果 */
+    public static final String NCKD_INNOVATE = "nckd_innovate";
+    /** 科研、创新、创效成果 */
+    public static final String NCKD_APPOINT = "nckd_appoint";
+    /** 工作年限 */
+    public static final String NCKD_WORKYEAR = "nckd_workyear";
+    /** 匹配情况说明 */
+    public static final String NCKD_MATCHCONDDESC = "nckd_matchconddesc";
+    /** 配置关键行为人才标准项目分录 */
+    public static final String NCKD_KEYBEHAVCONFENTRY = "nckd_keybehavconfentry";
+    /** 配置关键行为人才标准项目分录 */
+    public static final String NCKD_RESULT = "nckd_result";
+
+    /** 关键行为项目评价结果-实体标识 */
+    public static final String KEYBEHAVEVALPROJRSLT_ENTITYID = "nckd_keybehavevalprojrslt";
+}

+ 1 - 1
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/init/business/SynPendingSalaryAdjDataServiceImpl.java

@@ -162,7 +162,7 @@ public class SynPendingSalaryAdjDataServiceImpl implements SynPendingSalaryAdjDa
          */
         String selectField1 = "id,billno,b_effectivedate,createtime,bb_em_tid,ba_em_empnumber,bb_po_position.boid,aposition.boid,bb_po_adminorg.boid,aorg.boid,aorg.belongcompany.id";
         QFilter qFilter12 = new QFilter("billstatus", QCP.equals, "C"); // 单据状态 = 已审核
-        QFilter qFilter17 = new QFilter("perchgstatus", QCP.equals, "99");   //同步成功
+        QFilter qFilter17 = new QFilter("perchgstatus", QCP.like, "%99%");   //同步成功
         QFilter qFilter13 = new QFilter("b_effectivedate", QCP.large_equals, daysAgo);  //实际调动日期
         QFilter qFilter14 = new QFilter("b_effectivedate", QCP.less_equals, currentDate);  //实际调动日期
         QFilter qFilter16 = new QFilter("aposition.nckd_paystdplan.name", QCP.equals, "江铜集团岗位绩效工资制");

+ 27 - 18
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/init/plugin/operate/BuildApplyBillOpPlugin.java

@@ -22,6 +22,7 @@ import kd.sdk.swc.hcdm.common.dto.stdtab.match.StdTableGradeRankRangeMatchResult
 import nckd.jxccl.base.common.constant.FormConstant;
 import nckd.jxccl.base.common.utils.ConvertUtil;
 import nckd.jxccl.base.common.utils.DateUtil;
+import nckd.jxccl.base.entity.helper.EntityHelper;
 import nckd.jxccl.base.swc.helper.SWCHelper;
 
 import java.util.*;
@@ -51,35 +52,35 @@ public class BuildApplyBillOpPlugin extends AbstractOperationServicePlugIn imple
      * left join t_bas_billtype_l b on a.fid = b.fid
      * where a.fbillformid  like 'hcdm_applybill'
      */
-    private static final Long changeSalaryBillTypeId = 2215975998602655744L;
+//    private static final Long changeSalaryBillTypeId = 2215975998602655744L;
     /**
      * 定调薪申请单  定调薪明细字段显示方案   员工定薪
      */
-    private static final Long setSalaryBillEntryTypeId = 2215982957338868736L;
+//    private static final Long setSalaryBillEntryTypeId = 2215982957338868736L;
     /**
      * 定调薪项目   岗位工资标准   t_hsbs_standarditem
      */
-    private static final Long salaryStdItemId = 2321899710350111744L;
+//    private static final Long salaryStdItemId = 2321899710350111744L;
     /**
      * 频度  月   t_hsbs_calfrequency
      */
-    private static final Long frequencyItemId = 1095454108284088320L;
+//    private static final Long frequencyItemId = 1095454108284088320L;
     /**
      * 汇率表   通用汇率   T_BD_ExRateTable
      */
-    private static final Long exchangeTableId = 2321965096026258432L;
+//    private static final Long exchangeTableId = 2321965096026258432L;
     /**
      * 国家   中国   T_BD_Country
      */
-    private static final Long countryItemId = 1000001L;
+//    private static final Long countryItemId = 1000001L;
     /**
      * 定调薪方案   t_hcdm_adjapprovescm
      */
-    private static final Long salaryAdjScmItemId = 2322515162646457344L;
+//    private static final Long salaryAdjScmItemId = 2322515162646457344L;
     /**
      * 默认币种   人民币   select * from T_BD_Currency
      */
-    private static final Long currencyItemId = 1L;
+//    private static final Long currencyItemId = 1L;
 
 
 
@@ -126,16 +127,23 @@ public class BuildApplyBillOpPlugin extends AbstractOperationServicePlugIn imple
 
         DynamicObjectCollection salaryTypeDyns = SWCHelper.getSalaryTypeDyns();
 
+        Long salaryItemId = EntityHelper.getIdByNumber(FormConstant.HSBS_STANDARDITEM, FormConstant.POS_STANDARD_ITEM_NUMBER);
+        Long billTypeId = EntityHelper.getIdByNumber(FormConstant.BOS_BILLTYPE, FormConstant.HCDM_APPLYBILL_BT_ADJ);
+        Long countryId = EntityHelper.getIdByNumber(FormConstant.BD_COUNTRY, "001");
+        Long currencyId = EntityHelper.getIdByNumber(FormConstant.BD_CURRENCY, "CNY");
+        Long adjApproveScmId = EntityHelper.getLatestIdByNumber(FormConstant.HCDM_ADJAPPROVESCM, "dingtiaoxin");
+        Long exRateTableId = EntityHelper.getIdByNumber(FormConstant.BD_EXRATETABLE, "ERT-01");
+        Long calFrequencyId = EntityHelper.getIdByNumber(FormConstant.HSBS_CALFREQUENCY, "000_m_001");
         String uniquecode = UUID.randomUUID().toString().replace("-", "");
         applyBill.put("_uniquecode", uniquecode);
         //applyBill.put("org",orgId);
         //applyBill.put("billtype", 2215975998602655744L);   //定调薪明细字段显示方案   调薪明细字段
-        applyBill.put("billcountry", countryItemId);                //国家
+        applyBill.put("billcountry", countryId);                //国家
         //applyBill.put("salaryadjrsn", 2352340656979984384L);  //定调薪类型
-        applyBill.put("billcurrency", currencyItemId);           //默认币种
-        applyBill.put("salaryadjscm", salaryAdjScmItemId);   //定调薪方案
+        applyBill.put("billcurrency", currencyId);           //默认币种
+        applyBill.put("salaryadjscm", adjApproveScmId);   //定调薪方案
         applyBill.put("exchangeratedate", new Date());   //汇率日期
-        applyBill.put("exctable", exchangeTableId);  //汇率表
+        applyBill.put("exctable", exRateTableId);  //汇率表
         applyBill.put("effectivedate", new Date());   //默认生效日期
         applyBill.put("isdraft", "1"); //草稿状态
         applyBill.put("auditstatus", "A"); //审核状态
@@ -156,11 +164,11 @@ public class BuildApplyBillOpPlugin extends AbstractOperationServicePlugIn imple
             //定调薪明细字段显示方案   调薪明细字段
             if(billType.equals("调动单")){
                 //定调薪明细字段显示方案
-                applyBill.put("billtype", changeSalaryBillTypeId);
+                applyBill.put("billtype", billTypeId);
                 //定调薪类型
                 applyBill.put("salaryadjrsn", salaryTypeDyns.get(1).getLong("id"));
             }else if(billType.equals("入职单")){
-                applyBill.put("billtype", setSalaryBillEntryTypeId);
+                applyBill.put("billtype", billTypeId);
                 applyBill.put("salaryadjrsn", salaryTypeDyns.get(0).getLong("id"));
             }
 
@@ -169,8 +177,8 @@ public class BuildApplyBillOpPlugin extends AbstractOperationServicePlugIn imple
 
             applyBillEntry.put("adjfile", salaryfile.getLong("id"));
             applyBillEntry.put("employee", employeeId);
-            applyBillEntry.put("standarditem", salaryStdItemId);    //定调薪项目   岗位工资标准
-            applyBillEntry.put("frequency", frequencyItemId);       //频度  月
+            applyBillEntry.put("standarditem", salaryItemId);    //定调薪项目   岗位工资标准
+            applyBillEntry.put("frequency", calFrequencyId);       //频度  月
             //applyBillEntry.put("amount", BigDecimal.ZERO);
             Long postgradeId = salaryfile.getLong("position.nckd_postgrade.id");
             applyBillEntry.put("nckd_postgrade", postgradeId);  //岗级
@@ -178,7 +186,7 @@ public class BuildApplyBillOpPlugin extends AbstractOperationServicePlugIn imple
             /**
              * 获取标准表
              */
-            Long salaryStandardId = getSalarystandard(salaryfile.getLong("stdscm.id"),salaryStdItemId);
+            Long salaryStandardId = getSalarystandard(salaryfile.getLong("stdscm.id"),salaryItemId);
             /**
              * 获取薪等
              */
@@ -253,6 +261,7 @@ public class BuildApplyBillOpPlugin extends AbstractOperationServicePlugIn imple
      * @return
      */
     public Long getSalaryGradeID(Long postgradeId,Long salarystandardId){
+        Long salaryItemId = EntityHelper.getIdByNumber(FormConstant.HSBS_STANDARDITEM, FormConstant.POS_STANDARD_ITEM_NUMBER);
 
         List<StdTableGradeRankRangeMatchParam> matchParams = new ArrayList<>();
         StdTableGradeRankRangeMatchParam stdTableGradeRankMatchParam = new StdTableGradeRankRangeMatchParam();
@@ -264,7 +273,7 @@ public class BuildApplyBillOpPlugin extends AbstractOperationServicePlugIn imple
         /*
          * 定调薪项目  hsbs_standarditem
          */
-        stdTableGradeRankMatchParam.setStdItemId(salaryStdItemId);
+        stdTableGradeRankMatchParam.setStdItemId(salaryItemId);
         /**
          * 匹配类型 为0 时
          * 定调薪人员属性 key 为  定调薪人员属性配置(hcdm_contrastpropconf)的ID

+ 41 - 1
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/utils/SwcUtils.java

@@ -89,7 +89,7 @@ public class SwcUtils {
                 "left join t_hsas_caltable f on f.fcaltaskid = b.fid and f.fcalpersonid = c.fid\n" +
                 "left join t_hsas_caltableentry g on g.fid = f.fid\n" +
                 "left join t_hsbs_salaryitem h on h.fid = g.fsalaryitemid\n" +
-                "where 1 = 1\n" +
+                "where 1 = 1 and b1.ftaskstatus in ('4','7','8','9') ---计算完成 9--已审核 7--审批处理中 8--审批通过 4 \n" +
                 "  and a.fiscurrentversion = '1'\n" +
                 "  and h.fnumber = 'JT_283'\n");
         sb.append("and b1.fpaydate >= '"+startDateStr+"'\n");
@@ -100,6 +100,46 @@ public class SwcUtils {
         return sb;
     }
 
+    /**
+     *
+     * 根据员工ID获取员工薪资明细
+     * @param empId
+     * @param salaryitem
+     * @param startDate
+     * @param endDate
+     * @return
+     */
+    public static StringBuilder getSalaryDetailSqlByEmp(Long empId,String salaryitem, Date startDate, Date endDate) {
+
+        String startDateStr = dateToStr(startDate, 1);
+        String endDateStr = dateToStr(endDate, 2);
+
+        StringBuilder sb = new StringBuilder();
+        sb.append("/*dialect*/ SELECT  c.femployeeid,d.fname empName,\n" +
+                //"       h.fnumber itemName,\n" +
+                "       d.fempnumber empNumber,\n" +
+                "       count(distinct to_char(b1.fpaydate,'yyyy-MM')) monthCount,\n" +
+                "       sum(g.fcalamountvalue) amount\n" +
+                "from t_hsas_calpayrolltask b \n" +
+                "left join t_hsas_calpayrolltask_a b1 on b1.fid = b.fid \n" +
+                "left join t_hsas_calperson c on c.fcaltaskid = b.fid \n" +
+                "left join t_hrpi_employee d on d.fid = c.femployeeid \n" +
+                "left join t_hrpi_percre e on e.femployeeid = d.fid and e.fcredentialstypeid = '1010'\n" +
+                "left join t_hsas_caltable f on f.fcaltaskid = b.fid and f.fcalpersonid = c.fid \n" +
+                "left join t_hsas_caltableentry g on g.fid = f.fid \n" +
+                "left join t_hsbs_salaryitem h on h.fid = g.fsalaryitemid \n" +
+                "where 1 = 1 and b1.ftaskstatus in ('4','7','8','9')  ---计算完成 9--已审核 7--审批处理中 8--审批通过 4 \n" +
+                "  and a.fiscurrentversion = '1'\n" +
+                "  and h.fnumber in ("+salaryitem+") \n");
+        sb.append("and b1.fpaydate >= '"+startDateStr+"' \n");
+        sb.append("and b1.fpaydate <= '"+endDateStr+"' \n");
+        sb.append("and c.femployeeid in ("+empId+") \n");
+        sb.append("group by c.femployeeid,d.fname, d.fempnumber");
+
+        return sb;
+    }
+
+
     public static List<Long> getExcludePayRollGroupIds(Date startDate) {
         List<Long> excludeGroupIds = new ArrayList<Long>();
         QFilter filter = new QFilter("nckd_calyear", QCP.equals, startDate);