Explorar o código

feat(hr): 新增职位体系推送薪酬功能

- 新增 PsmsAdjustSalaryTask 定时任务类,实现职位体系薪酬推送逻辑
- 在 PositionStructureConstant 中增加调薪相关常量定义
- 修改 PersonPosFileSaveOpPlugin 插件,限制仅特定类型状态才获取薪酬数据
- 调整 AdjFileServiceHelper 支持获取薪酬管理组织信息
- 优化 DateUtil 工具类,补充 beginOfDay 和 endOfDay 方法对 Date 类型的支持
- 改进 PushAdjustOpPlugin 异常处理,增强错误信息提示
wyc hai 1 día
pai
achega
4da7f7a8e0

+ 14 - 2
code/base/nckd-jxccl-base-common/src/main/java/nckd/jxccl/base/common/utils/DateUtil.java

@@ -399,6 +399,16 @@ public class DateUtil {
 
     // ==================== 时间范围处理 ====================
 
+    /**
+     * 获取日期的开始时间(00:00:00)
+     *
+     * @param date 日期时间
+     * @return 当天的开始时间
+     */
+    public static Date beginOfDay(Date date) {
+        return toDate(beginOfDay(toLocalDateTime(date)));
+    }
+
     /**
      * 获取日期的开始时间(00:00:00)
      *
@@ -450,14 +460,16 @@ public class DateUtil {
         return dateTime.withDayOfYear(1).toLocalDate().atStartOfDay();
     }
 
+
+
     /**
      * 获取日期当天的结束时间(23:59:59.999999999)
      *
      * @param date 日期时间
      * @return 当天的结束时间
      */
-    public static LocalDateTime endOfDay(Date date) {
-        return endOfDay(toLocalDateTime(date));
+    public static Date endOfDay(Date date) {
+        return toDate(endOfDay(toLocalDateTime(date)));
     }
 
     /**

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

@@ -83,8 +83,9 @@ public class AdjFileServiceHelper {
                 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,");
+            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);
             if (ConvertUtil.toBoolean(lastDecAdjRecordMap.get("success"))) {
                 List<Map> datas = ConvertUtil.toList(lastDecAdjRecordMap.get("data"), ArrayList::new);
@@ -95,6 +96,8 @@ public class AdjFileServiceHelper {
                             // 人员
                             DynamicObject employee = dynamicObject.getDynamicObject("adjfile").getDynamicObject("employee");
                             SalaryAdjustmentResult salaryAdjustmentResult = new SalaryAdjustmentResult();
+                            //薪酬管理组织
+                            DynamicObject hcdmOrg = dynamicObject.getDynamicObject("hcdmorg");
                             //薪酬标准表版本
                             DynamicObject salaryStDv = dynamicObject.getDynamicObject("salarystdv");
                             //薪等(01岗、02岗)
@@ -104,6 +107,7 @@ public class AdjFileServiceHelper {
                             //金额
                             BigDecimal amount = dynamicObject.getBigDecimal("amount");
                             salaryAdjustmentResult.employee = employee;
+                            salaryAdjustmentResult.hcdmOrg = hcdmOrg;
                             salaryAdjustmentResult.adjFileInfo = dynamicObject.getDynamicObject("adjfile");
                             salaryAdjustmentResult.salaryStDv = salaryStDv;
                             salaryAdjustmentResult.standardItem = standardItem;
@@ -127,6 +131,7 @@ public class AdjFileServiceHelper {
     public static class SalaryAdjustmentResult {
         /** 人员ID*/
         public DynamicObject employee;
+        public DynamicObject hcdmOrg;
         /**定调薪档案*/
         public DynamicObject adjFileInfo;
         /**薪酬标准表*/

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

@@ -124,10 +124,18 @@ public class PositionStructureConstant extends FormConstant {
 
     /** 系数 */
     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 --------------------------------------*/
 

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

@@ -17,6 +17,7 @@ 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.QueryFieldBuilder;
 import nckd.jxccl.base.swc.helper.AdjFileServiceHelper;
 import nckd.jxccl.hr.psms.common.PositionStructureConstant;
@@ -28,6 +29,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
 * 员工职位档案-保存
@@ -49,19 +51,22 @@ public class PersonPosFileSaveOpPlugin extends AbstractOperationServicePlugIn im
         List<Long> allPersonIds = new ArrayList<>(e.getDataEntities().length);
         List<Long> jobLevelIds = new ArrayList<>(e.getDataEntities().length);
         for (DynamicObject dataEntity : e.getDataEntities()) {
-            BigDecimal coefficient = dataEntity.getBigDecimal(PositionStructureConstant.NCKD_COEFFICIENT);
-            BigDecimal currentPostSalary = dataEntity.getBigDecimal(PositionStructureConstant.NCKD_CURRENTPOSTSALARY);
-            BigDecimal postAllowance = dataEntity.getBigDecimal(PositionStructureConstant.NCKD_POSTALLOWANCE);
-            //当职位系数、岗位工资一档金额、岗位津贴为0时才处理,不为空则跳过
-            if((coefficient == null || coefficient.compareTo(BigDecimal.ZERO) <= 0) && (currentPostSalary == null || currentPostSalary.compareTo(BigDecimal.ZERO) <= 0) && (postAllowance == null || postAllowance.compareTo(BigDecimal.ZERO) <= 0)){
-                long personId = dataEntity.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
-                if(personId > 0){
-                    allPersonIds.add(personId);
+            String typeState = dataEntity.getString(PositionStructureConstant.NCKD_TYPESTATE);
+            if(Arrays.asList(TypeStateEnum.NEW_ENTRY.getCode(), TypeStateEnum.IN_SERVICE_LEVEL.getCode(), TypeStateEnum.ANNUAL_ADJUSTMENT.getCode(), TypeStateEnum.POSITION_TRANSFER.getCode()).contains(typeState)){
+                //只有新入职、在职人员初定、年度调整、动态调整才要获取薪酬
+                BigDecimal coefficient = dataEntity.getBigDecimal(PositionStructureConstant.NCKD_COEFFICIENT);
+                BigDecimal currentPostSalary = dataEntity.getBigDecimal(PositionStructureConstant.NCKD_CURRENTPOSTSALARY);
+                BigDecimal postAllowance = dataEntity.getBigDecimal(PositionStructureConstant.NCKD_POSTALLOWANCE);
+                //当职位系数、岗位工资一档金额、岗位津贴为0时才处理,不为空则跳过
+                if((coefficient == null || coefficient.compareTo(BigDecimal.ZERO) <= 0) && (currentPostSalary == null || currentPostSalary.compareTo(BigDecimal.ZERO) <= 0) && (postAllowance == null || postAllowance.compareTo(BigDecimal.ZERO) <= 0)){
+                    long personId = dataEntity.getLong(String.join(".", FormConstant.NCKD_PERSON, FormConstant.ID_KEY));
+                    if(personId > 0){
+                        allPersonIds.add(personId);
+                    }
+                    long jobLevelId = dataEntity.getLong(String.join(".", PositionStructureConstant.NCKD_JOBLEVELHR, FormConstant.ID_KEY));
+                    jobLevelIds.add(jobLevelId);
                 }
-                long jobLevelId = dataEntity.getLong(String.join(".", PositionStructureConstant.NCKD_JOBLEVELHR, FormConstant.ID_KEY));
-                jobLevelIds.add(jobLevelId);
             }
-
         }
 
         //====================================== 获取当前人员所在定调的岗位标准工资一档金额 begin ======================================
@@ -105,6 +110,7 @@ public class PersonPosFileSaveOpPlugin extends AbstractOperationServicePlugIn im
                         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());
                             }
                         }

+ 334 - 1
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/psms/task/PsmsAdjustSalaryTask.java

@@ -1,22 +1,355 @@
 package nckd.jxccl.hr.psms.task;
 
+import com.alibaba.fastjson.JSON;
+import kd.bos.common.enums.EnableEnum;
 import kd.bos.context.RequestContext;
+import kd.bos.dataentity.OperateOption;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.utils.ObjectUtils;
+import kd.bos.entity.EntityMetadataCache;
+import kd.bos.entity.MainEntityType;
+import kd.bos.entity.operate.result.IOperateInfo;
+import kd.bos.entity.operate.result.OperationResult;
 import kd.bos.exception.KDException;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
 import kd.bos.schedule.executor.AbstractTask;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
 import kd.sdk.plugin.Plugin;
+import kd.sdk.swc.hcdm.business.helper.HCDMApplyBillServiceHelper;
+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.AdjustTypeEnum;
+import nckd.jxccl.base.common.enums.psms.TypeStateEnum;
+import nckd.jxccl.base.common.exception.ValidationException;
+import nckd.jxccl.base.common.utils.ConvertUtil;
+import nckd.jxccl.base.common.utils.DateUtil;
+import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+import nckd.jxccl.base.common.utils.StrFormatter;
+import nckd.jxccl.base.entity.helper.EntityHelper;
+import nckd.jxccl.base.swc.helper.AdjFileServiceHelper;
+import nckd.jxccl.hr.psms.common.PositionStructureConstant;
 
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.Optional;
+import java.util.StringJoiner;
+import java.util.UUID;
+import java.util.stream.Collectors;
 
 /**
- * TODO
+ * 职位体系推送薪酬
  *
  * @author W.Y.C
  * @version 1.0
  * @date 2025/12/21 15:01
  */
 public class PsmsAdjustSalaryTask extends AbstractTask implements Plugin {
+
+    private static final Log logger = LogFactory.getLog(PsmsAdjustSalaryTask.class);
+
+
     @Override
     public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
+        //1:为本月数据,2:为上月数据
+        Integer type = ConvertUtil.toInt(map.get("type"));
+        Date beginDateParam = ConvertUtil.toDate(map.get("beginDateParam"));
+        Date endDateParam = ConvertUtil.toDate(map.get("endDateParam"));
+        // 校验日期:要么都为空,要么都不为空
+        if ((beginDateParam == null && endDateParam != null) || (beginDateParam != null && endDateParam == null)) {
+            throw new ValidationException("日期参数错误-开始日期和结束日期必须同时为空或同时不为空");
+        }
+
+        QFilter filter = new QFilter(PositionStructureConstant.NCKD_DISABLE, QCP.equals, EnableEnum.NO.getCode())
+                .and(PositionStructureConstant.NCKD_TYPESTATE, QCP.in, new String[]{TypeStateEnum.NEW_ENTRY.getCode(),TypeStateEnum.IN_SERVICE_LEVEL.getCode(),TypeStateEnum.ANNUAL_ADJUSTMENT.getCode(),TypeStateEnum.POSITION_TRANSFER.getCode()});
+        Date beginDate = null;
+        Date endDate = null;
+        if(beginDateParam != null && endDateParam != null){
+            beginDate = DateUtil.beginOfDay(beginDateParam);
+            endDate = DateUtil.endOfDay(endDateParam);
+        }else{
+            LocalDateTime now = DateUtil.now();
+            if(type == 2){
+                now = DateUtil.minusMonths(now, 1);
+            }else if(type == 1){
+                //本月
+            }else{
+                throw new ValidationException("参数错误-type,只能为1或2");
+            }
+            beginDate = DateUtil.toDate(DateUtil.beginOfMonth(now));
+            endDate = DateUtil.toDate(DateUtil.endOfMonth(now));
+        }
+        filter.and(FormConstant.CREATE_TIME_KEY,QCP.large_equals,beginDate);
+        filter.and(FormConstant.CREATE_TIME_KEY,QCP.less_equals,new Date());
+
+        QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                .add(FormConstant.ID_KEY)
+                .addIdNumberName(FormConstant.NCKD_PERSON)
+                .add(PositionStructureConstant.NCKD_ISSALADJPUSH)
+                .add(PositionStructureConstant.NCKD_BEGINDATE)
+                .add(PositionStructureConstant.CREATE_TIME_KEY)
+                .addIdNumberNameWithExtras(new String[]{PositionStructureConstant.NCKD_JOBLEVELHR},PositionStructureConstant.JOBLEVELSEQ,PositionStructureConstant.NCKD_COEFFICIENT)
+                .addIdNumberName(PositionStructureConstant.NCKD_LASTPERSONPOSFILE,PositionStructureConstant.NCKD_JOBLEVELHR)
+                .orderDesc(FormConstant.CREATE_TIME_KEY);
+        DynamicObjectCollection personPosFileColl = QueryServiceHelper.query(PositionStructureConstant.PERSONPOSFILE_ENTITYID, queryFieldBuilder.buildSelect(), new QFilter[]{filter});
+        // 按人员分组,Map<Long,List<DynamicObject>>
+        Map<Long, List<DynamicObject>> personPosFileMap = personPosFileColl.stream()
+                .collect(Collectors.groupingBy(
+                        obj -> obj.getLong(String.join(".", PositionStructureConstant.NCKD_PERSON, FormConstant.ID_KEY))
+                ));
+        //需要推送调薪的员工档案id
+        List<Long> needAdjustSalaryId = new ArrayList<>();
+        List<Long> needPersonId = new ArrayList<>();
+        List<Long> jobLevelIds = new ArrayList<>();
+        // 处理每个员工的记录
+        for (Map.Entry<Long, List<DynamicObject>> entry : personPosFileMap.entrySet()) {
+            List<DynamicObject> records = entry.getValue();
+            // 在当前员工的所有记录中,找出beginDate~endDate范围内CREATE_TIME_KEY最新的那条记录
+            Date finalBeginDate = beginDate;
+            Date finalEndDate = endDate;
+            Optional<DynamicObject> latestRecordOpt = records.stream()
+                    .filter(record -> {
+                        Date createTime = record.getDate(PositionStructureConstant.CREATE_TIME_KEY);
+                        return createTime != null &&
+                                !createTime.before(finalBeginDate) &&
+                                !createTime.after(finalEndDate);
+                    })
+                    .max(Comparator.comparing(record -> record.getDate(PositionStructureConstant.CREATE_TIME_KEY)));
+
+            // 如果找到了时间范围内的最新记录
+            if (latestRecordOpt.isPresent()) {
+                DynamicObject latestRecord = latestRecordOpt.get();
+                Date latestCreateTime = latestRecord.getDate(PositionStructureConstant.CREATE_TIME_KEY);
+
+                // 检查在latestCreateTime到当前时间范围内,该员工是否有NCKD_ISSALADJPUSH=true的记录(有的话说明当前数据之后已经有推送薪酬了,这条不用推送)
+                boolean hasPushedRecord = records.stream()
+                        .filter(record -> {
+                            Date createTime = record.getDate(PositionStructureConstant.CREATE_TIME_KEY);
+                            return createTime != null &&
+                                    !createTime.before(latestCreateTime);
+                        })
+                        .anyMatch(record -> record.getBoolean(PositionStructureConstant.NCKD_ISSALADJPUSH));
+                // 如果在最新记录时间之后没有推送调薪的记录,则添加到需要推送调薪的列表中
+                if (!hasPushedRecord) {
+                    needAdjustSalaryId.add(latestRecord.getLong(FormConstant.ID_KEY));
+                    needPersonId.add(latestRecord.getLong(String.join(".", PositionStructureConstant.NCKD_PERSON, FormConstant.ID_KEY)));
+                    jobLevelIds.add(latestRecord.getLong(String.join(".", PositionStructureConstant.NCKD_JOBLEVELHR, FormConstant.ID_KEY)));
+                    //上一档案职级
+                    long lastJobLevel = latestRecord.getLong(String.join(".", PositionStructureConstant.NCKD_LASTPERSONPOSFILE, PositionStructureConstant.NCKD_JOBLEVELHR, FormConstant.ID_KEY));
+                    jobLevelIds.add(lastJobLevel);
+                }
+            }
+        }
+
+        if(!needAdjustSalaryId.isEmpty()){
+            //获取人员最新岗位工资标准定薪记录
+            List<AdjFileServiceHelper.SalaryAdjustmentResult> salaryAdjustmentResultList = AdjFileServiceHelper.getLastDecAdjRecords(needPersonId, FormConstant.STANDARDITEM_ID_KEY);
+            Map<Long,AdjFileServiceHelper.SalaryAdjustmentResult> salaryAdjustmentResultMap = new HashMap<>(salaryAdjustmentResultList.size());
+            if (!salaryAdjustmentResultList.isEmpty()) {
+                //薪酬标准ID
+                List<Long> salaryStIds = salaryAdjustmentResultList.stream().map(result -> result.salaryStDv.getLong(FormConstant.ID_KEY)).collect(Collectors.toList());
+                QFilter salaryStandardFilter = 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[]{salaryStandardFilter});
+                Map<Long, DynamicObject> salaryStandardMap = salaryStandardColl.stream()
+                        .collect(Collectors.toMap(
+                                obj -> obj.getLong(FormConstant.ID_KEY),
+                                obj -> obj
+                        ));
+
+                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);
+                            result.salaryRank = EntityHelper.newEntity(FormConstant.HSBS_SALARYRANK, rankId);
+                            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档的金额
+                                result.amount = stdTableDataMatchResults.get(i).getAmount();
+                                salaryAdjustmentResultMap.put(result.employee.getLong(FormConstant.ID_KEY), result);
+                            }
+                        }
+                    }
+                } else {
+                    logger.warn("未获取薪酬标准表中01档的薪档数据,薪酬标准ID:{}",salaryStIds);
+                }
+            } else {
+                logger.warn("未获取到人员岗位工资标准定薪记录,人员ID:{}",needPersonId);
+            }
+
+            if(!salaryAdjustmentResultMap.isEmpty()){
+                Map<Long, DynamicObject> jobLevelMap = new HashMap<>(jobLevelIds.size());
+                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
+                            ));
+                }
+
+                List<DynamicObject> updatePersonPosFile = new ArrayList<>();
+                MainEntityType personPosFileEntityType = EntityMetadataCache.getDataEntityType(PositionStructureConstant.PERSONPOSFILE_ENTITYID);
+                DynamicObject[] personPosFileArray = BusinessDataServiceHelper.load(needAdjustSalaryId.toArray(), personPosFileEntityType);
+                for (DynamicObject personPosFile : personPosFileArray) {
+                    long jobLevelId = personPosFile.getLong(String.join(".", PositionStructureConstant.NCKD_JOBLEVELHR, FormConstant.ID_KEY));
+                    long lastJobLevelId = personPosFile.getLong(String.join(".",PositionStructureConstant.NCKD_LASTPERSONPOSFILE, PositionStructureConstant.NCKD_JOBLEVELHR, FormConstant.ID_KEY));
+                    DynamicObject jobLevel = jobLevelMap.get(jobLevelId);
+                    DynamicObject lastJobLevel = jobLevelMap.get(lastJobLevelId);
+
+                    if(jobLevel != null) {
+                        DynamicObject person = personPosFile.getDynamicObject(FormConstant.NCKD_PERSON);
+                        Date date = personPosFile.getDate(PositionStructureConstant.NCKD_BEGINDATE);
+                        AdjFileServiceHelper.SalaryAdjustmentResult salaryAdjustmentResult = salaryAdjustmentResultMap.get(person.getLong(FormConstant.ID_KEY));
+                        if (salaryAdjustmentResult != null && salaryAdjustmentResult.amount.compareTo(BigDecimal.ZERO) > 0) {
+                            BigDecimal coefficient = jobLevel.getBigDecimal(PositionStructureConstant.NCKD_COEFFICIENT);
+                            BigDecimal finalAmount = BigDecimal.ZERO;
+                            if(coefficient.compareTo(BigDecimal.ZERO) > 0) {
+                                //职位津贴=职位系数 X 所在岗级岗位工资一档金额
+                                finalAmount = coefficient.multiply(salaryAdjustmentResult.amount);
+                            }
+
+
+                            //触发定调薪
+                            Map<String, Object> applyBill = new HashMap<>();
+                            applyBill.put("billname", StrFormatter.format("【{}】的职位体系调整(职位津贴)",person.getString(FormConstant.NAME_KEY)));
+                            Long orgId = RequestContext.get().getOrgId();
+
+                            String uniquecode = UUID.randomUUID().toString().replace("-", "");
+                            applyBill.put("_uniquecode", uniquecode);
+                            if(salaryAdjustmentResult.hcdmOrg != null){
+                                applyBill.put("org", salaryAdjustmentResult.hcdmOrg.getLong(FormConstant.ID_KEY));
+                            }else{
+                                applyBill.put("org", orgId);
+                            }
+
+                            //定调薪明细字段显示方案   调薪明细字段
+                            applyBill.put("billtype", 2215975998602655744L);
+                            //国家
+                            applyBill.put("billcountry", 1000001L);
+                            //定调薪类型
+                            applyBill.put("salaryadjrsn", 2352338490244480000L);
+                            //默认币种
+                            applyBill.put("billcurrency", 1L);
+                            //定调薪方案
+                            applyBill.put("salaryadjscm", 2322515162646457344L);
+                            //汇率日期
+                            applyBill.put("exchangeratedate", new Date());
+                            //汇率表
+                            applyBill.put("exctable", 2321965096026258432L);
+                            //默认生效日期
+                            applyBill.put("effectivedate", date);
+                            //草稿状态
+                            applyBill.put("isdraft", "1");
+                            //审核状态
+                            applyBill.put("auditstatus", "A");
+                            //申请单数据来源   //1:手工新增  2:接口写入
+                            applyBill.put("datasource", "2");
+
+                            String typeStateStr = personPosFile.getString(PositionStructureConstant.NCKD_TYPESTATE);
+                            TypeStateEnum typeState = TypeStateEnum.getByCode(typeStateStr);
+                            String adjustTypeStr = personPosFile.getString(PositionStructureConstant.NCKD_ADJUSTTYPE);
+                            AdjustTypeEnum adjustType = AdjustTypeEnum.getByCode(adjustTypeStr);
+                            String description = StrFormatter.format("【{}】执行【{}】,调整生效时间【{}】,调整类别【{}】,由【{}({})】 -> 【{}({}级)】。系数【{}】",
+                                    DateUtil.format(personPosFile.getDate(FormConstant.CREATE_TIME_KEY),DateUtil.NORM_DATETIME_PATTERN),
+                                    typeState.getName(),
+                                    DateUtil.format(personPosFile.getDate(PositionStructureConstant.NCKD_BEGINDATE),DateUtil.NORM_DATE_PATTERN),
+                                    adjustType != null ? adjustType.getName() : "初定",
+                                    lastJobLevel == null ? "无" : lastJobLevel.getString(FormConstant.NAME_KEY),
+                                    lastJobLevel == null ? "无" : lastJobLevel.getString(FormConstant.JOBLEVELSEQ)+"级",
+                                    jobLevel.getString(FormConstant.NAME_KEY),
+                                    jobLevel.getString(FormConstant.JOBLEVELSEQ),
+                                     coefficient
+                            );
+                            applyBill.put("description", description);
+                            List<Map<String, Object>> applyBillEntryData = new ArrayList<>();
+                            Map<String, Object> applyBillEntry = new HashMap<>();
+                            Long employeeId = person.getLong(FormConstant.ID_KEY);
+                            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("amount", finalAmount);
+                            applyBillEntry.put("position", positionId);
+                            applyBillEntry.put("joblevel", jobLevel.getLong(FormConstant.ID_KEY));
+                            applyBillEntry.put("salarygrade", salaryAdjustmentResult.salaryGrade.getLong(FormConstant.ID_KEY));
+                            applyBillEntry.put("salaryrank", salaryAdjustmentResult.salaryRank.getLong(FormConstant.ID_KEY));
+                            applyBillEntry.put("reason", description);
+                            applyBillEntryData.add(applyBillEntry);
+                            applyBill.put("applybillent", applyBillEntryData);
+                            List<Map<String, Object>> applyBillData = new ArrayList<>();
+                            applyBillData.add(applyBill);
+                            Map<String, Object> papams = new HashMap<>();
+                            papams.put("data", applyBillData);
+                            papams.put("isUseMatchAmount", Boolean.TRUE);
+                            Map<String, Object> result = HCDMApplyBillServiceHelper.saveDraftApplyBill(papams);
+                            if (!ConvertUtil.toBoolean(result.get("success")) || result.get("data") == null || ConvertUtil.toList(result.get("data")).isEmpty()) {
+                                throw new ValidationException("【"+person.getString(FormConstant.NAME_KEY)+"】推送定调薪失败,原因:" + JSON.toJSONString(result));
+                            }else{
+                                personPosFile.set(PositionStructureConstant.NCKD_ISSALADJPUSH, Boolean.TRUE);
+                                personPosFile.set(PositionStructureConstant.NCKD_SALADJPUSHTIME, new Date());
+                                personPosFile.set(PositionStructureConstant.NCKD_SALADJID, ConvertUtil.toMap(ConvertUtil.toList(result.get("data")).get(0)).get("id"));
+                                personPosFile.set(PositionStructureConstant.NCKD_SALADJNUMBER, null);
+
+                                updatePersonPosFile.add(personPosFile);
+                            }
+                        } else {
+                            logger.warn("未获取到员工【{}】最新岗位工资标准定薪记录01档的薪等金额,人员ID:", person.getString(FormConstant.NAME_KEY));
+                        }
+                    }
+                }
 
+                if(!updatePersonPosFile.isEmpty()){
+                    OperationResult operationResult = SaveServiceHelper.saveOperate(PositionStructureConstant.PERSONPOSFILE_ENTITYID, updatePersonPosFile.toArray(new DynamicObject[0]), OperateOption.create());
+                    if (!operationResult.isSuccess()) {
+                        StringJoiner errorMsg = new StringJoiner("\n");
+                        for (IOperateInfo error : operationResult.getAllErrorOrValidateInfo()) {
+                            errorMsg.add(error.getMessage());
+                        }
+                        if (!ObjectUtils.isEmpty(operationResult.getMessage())) {
+                            errorMsg.add(operationResult.getMessage());
+                        }
+                        throw new ValidationException("保存职位档案失败,原因:" + errorMsg.toString());
+                    }
+                }
+            }
+        }else{
+            logger.warn("没有需要推送的调薪数据");
+        }
     }
 }

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

@@ -1,5 +1,6 @@
 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;
@@ -155,8 +156,8 @@ public class PushAdjustOpPlugin extends AbstractOperationServicePlugIn implement
             papams.put("data", applyBillData);
             papams.put("isUseMatchAmount", Boolean.TRUE);
             Map<String, Object> result = HCDMApplyBillServiceHelper.saveDraftApplyBill(papams);
-            if (!ConvertUtil.toBoolean(result.get("success"))) {
-                throw new ValidationException("推送定调薪失败,原因:" + result.get("message").toString());
+            if (!ConvertUtil.toBoolean(result.get("success")) || result.get("data") == null || ConvertUtil.toList(result.get("data")).isEmpty()) {
+                throw new ValidationException("推送定调薪失败,原因:" + JSON.toJSONString(result));
             }
         }
     }