|
|
@@ -8,26 +8,33 @@ import kd.bos.orm.query.QFilter;
|
|
|
import kd.bos.servicehelper.BusinessDataServiceHelper;
|
|
|
import nckd.jxccl.base.common.constant.FormConstant;
|
|
|
import nckd.jxccl.base.common.enums.AppraisalResultEnum;
|
|
|
+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.pm.helper.PerformanceManagerHelper;
|
|
|
import nckd.jxccl.hr.psms.common.PositionStructureConstant;
|
|
|
import nckd.jxccl.hr.psms.common.bo.PositionAppointmentBO;
|
|
|
import nckd.jxccl.hr.psms.helper.PositionStructureHelper;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
+import java.time.LocalDate;
|
|
|
import java.time.LocalDateTime;
|
|
|
+import java.time.ZoneId;
|
|
|
import java.util.Date;
|
|
|
import java.util.LinkedHashMap;
|
|
|
import java.util.Map;
|
|
|
+import java.util.Optional;
|
|
|
+import java.util.StringJoiner;
|
|
|
|
|
|
/**
|
|
|
- * 年度调整服务类。
|
|
|
- * <p>重构目标:逻辑清晰、职责单一、条件判断明确、可维护可测试;保持原始业务逻辑完整性。</p>
|
|
|
- */
|
|
|
+* 年度调整服务类
|
|
|
+* @author W.Y.C
|
|
|
+* @date 2025/10/08 22:12
|
|
|
+* @version 1.0
|
|
|
+*/
|
|
|
public class AnnualAdjustmentService {
|
|
|
|
|
|
|
|
|
@@ -35,22 +42,34 @@ public class AnnualAdjustmentService {
|
|
|
* 生成年度调整记录
|
|
|
* @param person 员工
|
|
|
* @param beginDate 生效日期
|
|
|
- * @return 成功返回 null;失败返回错误信息
|
|
|
+ * @return 成功返回 新的职位档案
|
|
|
* @note 对应SHR:PersonpositionfilecreateViewListHandler#addNewYear_PersonpositionfileInfo(277~815行)
|
|
|
*/
|
|
|
- public DynamicObject addNewYearPersonPositionFileInfo(DynamicObject person, Date beginDate,String remark) {
|
|
|
+ public static DynamicObject addNewYearPersonPositionFileInfo(DynamicObject person, Date beginDate,String remark,PositionAppointmentBO positionAppointment,DynamicObject performanceResult,DynamicObject firstPersonPosFile) {
|
|
|
int executeYear = beginDate != null ? DateUtil.getYear(beginDate) : DateUtil.getYear(new Date());
|
|
|
- //判断当前年是否已执行过年度调整
|
|
|
- DynamicObject[] personPosFileByYear = PositionStructureHelper.getPersonPosFileByPersonAndState(person.getLong(FormConstant.ID_KEY), new String[]{"3"}, null, new QFilter(PositionStructureConstant.NCKD_EXECUTEYEAR, QCP.equals, executeYear));
|
|
|
- if(personPosFileByYear != null && personPosFileByYear.length > 0){
|
|
|
- throw new ValidationException(StrFormatter.format("人员【{}】已存在【{}】年的年度调整!", person.getString(FormConstant.NAME_KEY), executeYear));
|
|
|
- }
|
|
|
|
|
|
// 1、 初始化上下文并加载基础数据。
|
|
|
// 对应SHR:291~339行
|
|
|
- AdjustmentContext ac = initAndLoad(executeYear, person, beginDate);
|
|
|
+ Date adjustDate = beginDate;
|
|
|
+ if (adjustDate != null) {
|
|
|
+ // 如果adjustDate不为空且为年初日期(xxxx-01-01),则转换为当年7月1日
|
|
|
+ LocalDateTime adjustDateTime = DateUtil.toLocalDateTime(adjustDate);
|
|
|
+ if (adjustDateTime.getMonthValue() == 1 && adjustDateTime.getDayOfMonth() == 1) {
|
|
|
+ //前端只选年份,这里默认为XXX-07-01
|
|
|
+ adjustDate = DateUtil.toDate(adjustDateTime.withMonth(7).withDayOfMonth(1));
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ //获取当年07-01的日期
|
|
|
+ /*LocalDate julyFirst = LocalDate.of(DateUtil.getYear(new Date()), 7, 1);
|
|
|
+ adjustDate = Date.from(julyFirst.atStartOfDay(ZoneId.systemDefault()).toInstant());*/
|
|
|
+ adjustDate = new Date();
|
|
|
+ }
|
|
|
+ String adjustDateStr = DateUtil.format(adjustDate,DateUtil.NORM_DATE_PATTERN);
|
|
|
+ AdjustmentContext ac = initAndLoad(executeYear, person, beginDate,adjustDate,positionAppointment,performanceResult,firstPersonPosFile);
|
|
|
ac.remark = remark;
|
|
|
|
|
|
+
|
|
|
+
|
|
|
//2、 判断是否为本年首次调整、考核是否已被使用,并根据规则决定是否使用R排名。
|
|
|
//对应SHR:341~391行
|
|
|
evaluateFirstAndAppraisalUsage(ac);
|
|
|
@@ -68,7 +87,7 @@ public class AnnualAdjustmentService {
|
|
|
|
|
|
// 5、获取技能/职称分
|
|
|
//对应SHR:451~481行
|
|
|
- JobLevelCalculatorService.JobScoreInfo jobScoreInfo = JobLevelCalculatorService.handleJobScores(convertJobSeq, ac.positionAppointment);
|
|
|
+ JobLevelCalculatorService.JobScoreInfo jobScoreInfo = JobLevelCalculatorService.handleJobScores(ac.lastRecordInfo,convertJobSeq, ac.positionAppointment);
|
|
|
ac.data.setJobScoreInfo(jobScoreInfo);
|
|
|
|
|
|
// 6、计算学历得分并生成说明
|
|
|
@@ -76,6 +95,17 @@ public class AnnualAdjustmentService {
|
|
|
ac.diplomaScore = JobLevelCalculatorService.handleDiplomaScore(ac.lastRecordInfo, ac.positionAppointment, jobScoreInfo);
|
|
|
ac.whyDiplomaScore.putAll(jobScoreInfo.whyDiplomaScore);
|
|
|
|
|
|
+ //---------------------------------- 调整日志 begin ----------------------------------
|
|
|
+ ac.whyAdjust1.add(StrFormatter.format("毕业时间小于等于【{}】的最高学历【{}】,学历分【{}】{}",
|
|
|
+ adjustDateStr, ConvertUtil.toStr(jobScoreInfo.diplomaName,"无"), ConvertUtil.toStr(jobScoreInfo.diplomaScore,"无"),jobScoreInfo.isDiplomaChange ? "(变化)":""));
|
|
|
+ ac.whyAdjust1.add(StrFormatter.format("聘任时间小于等于【{}】的职称【{}】,职称等级【{}】,职称等级分【{}】{}",
|
|
|
+ adjustDateStr,ConvertUtil.toStr(jobScoreInfo.rankName,"无"),ConvertUtil.toStr(jobScoreInfo.perProTitleName,"无"),ConvertUtil.toStr(jobScoreInfo.perProTitleScore,"无"),
|
|
|
+ jobScoreInfo.isPerProTitleChange ? "(变化)":""));
|
|
|
+ ac.whyAdjust1.add(StrFormatter.format("聘任时间小于等于【{}】的技能【{}】,技能等级【{}】,技能等级分【{}】{}",
|
|
|
+ adjustDateStr,ConvertUtil.toStr(jobScoreInfo.jobStatusName,"无"),ConvertUtil.toStr(jobScoreInfo.quaLevelName,"无"),ConvertUtil.toStr(jobScoreInfo.quaLevelScore,"无"),
|
|
|
+ jobScoreInfo.isQuaLeveleChange ? "(变化)":""));
|
|
|
+ //---------------------------------- 调整日志 end ----------------------------------
|
|
|
+
|
|
|
// 7、汇总年度积分池与综合分数。
|
|
|
//对应SHR:483~519行
|
|
|
aggregateScores(ac);
|
|
|
@@ -103,9 +133,11 @@ public class AnnualAdjustmentService {
|
|
|
ac.data.getAppraisalResultName()));
|
|
|
}
|
|
|
|
|
|
- JobLevelCalculatorService.JobLevelResult jobLevelResult = JobLevelCalculatorService.calculateJobLevel(person, beginDate, ac.positionAppointment);
|
|
|
- ac.data.getRankingResultInfo().allowanceRankMark = jobLevelResult.rankingResultInfo.allowanceRankMark;
|
|
|
- ac.data.getRankingResultInfo().allowanceRankSel = jobLevelResult.rankingResultInfo.allowanceRankSel;
|
|
|
+ JobLevelCalculatorService.JobLevelResult jobLevelResult = JobLevelCalculatorService.calculateJobLevel(person, beginDate == null ? new Date() : beginDate, ac.positionAppointment);
|
|
|
+ if(jobLevelResult.rankingResultInfo != null) {
|
|
|
+ ac.data.getRankingResultInfo().allowanceRankMark = jobLevelResult.rankingResultInfo.allowanceRankMark;
|
|
|
+ ac.data.getRankingResultInfo().allowanceRankSel = jobLevelResult.rankingResultInfo.allowanceRankSel;
|
|
|
+ }
|
|
|
|
|
|
//10、构建职位档案
|
|
|
return buildPersonPositionFile(ac, jobLevel);
|
|
|
@@ -116,12 +148,15 @@ public class AnnualAdjustmentService {
|
|
|
* 初始化上下文并加载基础数据。
|
|
|
* @param executeYear 执行年份
|
|
|
* @param person 员工
|
|
|
- * @param beginDate 生效日期
|
|
|
+ * @param beginDate 生效日期(可以为空,为空默认为不生效状态)
|
|
|
+ * @param positionAppointment 员工最新任职信息
|
|
|
+ * @param performanceResult 上年度考核结果
|
|
|
+ * @param firstPersonPosFile 初定档案
|
|
|
* @return: nckd.jxccl.hr.psms.business.AnnualAdjustmentService.AdjustmentContext
|
|
|
* @author W.Y.C
|
|
|
* @date: 2025/10/08 21:15
|
|
|
*/
|
|
|
- private AdjustmentContext initAndLoad(Integer executeYear, DynamicObject person, Date beginDate){
|
|
|
+ private static AdjustmentContext initAndLoad(Integer executeYear, DynamicObject person, Date beginDate,Date adjustDate,PositionAppointmentBO positionAppointment,DynamicObject performanceResult,DynamicObject firstPersonPosFile){
|
|
|
AdjustmentContext ac = new AdjustmentContext();
|
|
|
ac.executeYear = executeYear;
|
|
|
ac.nowYear = executeYear;
|
|
|
@@ -133,19 +168,21 @@ public class AnnualAdjustmentService {
|
|
|
int lastYear = executeYear - 1;
|
|
|
LocalDateTime lastYearDateTime = LocalDateTime.of(lastYear, 1, 1, 0, 0);
|
|
|
|
|
|
+ ac.whyAdjust1.add(StrFormatter.format("选择的调整时间:【{}】", DateUtil.format(adjustDate,DateUtil.NORM_DATE_PATTERN)));
|
|
|
+
|
|
|
|
|
|
//对应SHR:291行;utils.YearContributeScoreBillEntryScoreSumBypersonidAndYear
|
|
|
//TODO 1、获取年度贡献积分
|
|
|
//yearscoresuma、yearscoresumb、yearscoresumc、yearscoresumd、yearscoresume、yearscoresumf、yearscoresumg、yearscoresumh、yearscoresumi、allyearscoresum、yearscoresuma
|
|
|
|
|
|
//2、获取上年度考核结果(对应SHR:PersonpositionfileUtils:884~914行)
|
|
|
- DynamicObject performanceResult = PerformanceManagerHelper.getPerformanceResult(ac.personId, lastYearDateTime);
|
|
|
+ // DynamicObject performanceResult = PerformanceManagerHelper.getPerformanceResult(ac.personId, lastYearDateTime);
|
|
|
if(performanceResult == null){
|
|
|
throw new ValidationException(StrFormatter.format("人员【{}】缺少【{}】年考核结果", ac.personName,lastYear));
|
|
|
}
|
|
|
AnnualAdjustmentData data = new AnnualAdjustmentData();
|
|
|
data.setAppraisalResult(performanceResult);
|
|
|
- data.setAppraisalResultNumber(performanceResult.getString(FormConstant.ID_KEY));
|
|
|
+ data.setAppraisalResultNumber(performanceResult.getString(FormConstant.NUMBER_KEY));
|
|
|
data.setAppraisalResultName(performanceResult.getString(FormConstant.NAME_KEY));
|
|
|
data.setAppraisalResultId(performanceResult.getLong(FormConstant.ID_KEY));
|
|
|
data.setAppraisalResultScore(performanceResult.getBigDecimal(FormConstant.NCKD_SCORE));
|
|
|
@@ -153,7 +190,7 @@ public class AnnualAdjustmentService {
|
|
|
|
|
|
//3.获取员工上年度年度R排名(对应SHR:PersonpositionfileUtils:915~945行)
|
|
|
DynamicObject lastPersonPosFile = null;
|
|
|
- JobLevelCalculatorService.RankingResultInfo rankingInfo = JobLevelCalculatorService.getRankingInfo(ac.personId, ac.personName, beginDate);
|
|
|
+ JobLevelCalculatorService.RankingResultInfo rankingInfo = JobLevelCalculatorService.getRankingInfo(ac.personId, ac.personName, beginDate == null ? new Date() : beginDate);
|
|
|
data.setRankingResultInfo(rankingInfo);
|
|
|
|
|
|
//4.查询上一条有效年度调整记录(对应SHR:PersonpositionfileUtils:946~997行)
|
|
|
@@ -164,20 +201,23 @@ public class AnnualAdjustmentService {
|
|
|
.orderDesc(PositionStructureConstant.NCKD_EXECUTEYEAR,PositionStructureConstant.MODIFY_TIME_KEY,PositionStructureConstant.NCKD_BEGINDATE).buildOrderArray());
|
|
|
if(personPosFileByPersonAndState == null || personPosFileByPersonAndState.length < 1){
|
|
|
//没有年度调整记录取初定记录
|
|
|
- lastPersonPosFile = PositionStructureHelper.getFirstRank(ac.personId);
|
|
|
- if(lastPersonPosFile == null){
|
|
|
+ if(firstPersonPosFile == null){
|
|
|
throw new ValidationException(StrFormatter.format("当前无法为【{}】进行调整,因为他/她尚未建立职位档案。请前往“职位及积分初定” -> 进行初定!", ac.personName));
|
|
|
}
|
|
|
+ lastPersonPosFile = firstPersonPosFile;
|
|
|
data.setFirstId(lastPersonPosFile.getLong(FormConstant.ID_KEY));
|
|
|
+ String typeState = lastPersonPosFile.getString(PositionStructureConstant.NCKD_TYPESTATE);
|
|
|
+ ac.whyAdjust1.add(StrFormatter.format("上一条有效职位档案为【{}】档案,初定时间:【{}】;", TypeStateEnum.getByCode(typeState).getName(), DateUtil.format(lastPersonPosFile.getDate(PositionStructureConstant.NCKD_BEGINDATE),DateUtil.NORM_DATE_PATTERN)));
|
|
|
}else{
|
|
|
lastPersonPosFile = personPosFileByPersonAndState[0];
|
|
|
data.setLastId(lastPersonPosFile.getLong(FormConstant.ID_KEY));
|
|
|
+ String typeState = lastPersonPosFile.getString(PositionStructureConstant.NCKD_TYPESTATE);
|
|
|
+ ac.whyAdjust1.add(StrFormatter.format("上一条有效职位档案为【{}】档案,调整时间:【{}】", TypeStateEnum.getByCode(typeState).getName(),DateUtil.format(lastPersonPosFile.getDate(PositionStructureConstant.NCKD_BEGINDATE),DateUtil.NORM_DATE_PATTERN)));
|
|
|
}
|
|
|
if(lastPersonPosFile != null) {
|
|
|
//(firstid、lastsumscore、lastdiplomascore、lastrankscore、lastjobstatusscore、lasthrjobfamilynumber、lastjobgradefid、lastjobgradeindex)
|
|
|
-
|
|
|
-
|
|
|
data.setLastSumScore(lastPersonPosFile.getBigDecimal(PositionStructureConstant.NCKD_SUMSCORE));
|
|
|
+
|
|
|
//lastdiplomascore
|
|
|
//lastrankscore
|
|
|
//lastjobstatusscore
|
|
|
@@ -187,11 +227,43 @@ public class AnnualAdjustmentService {
|
|
|
DynamicObject jobLevel = lastPersonPosFile.getDynamicObject(PositionStructureConstant.NCKD_JOBLEVELHR);
|
|
|
data.setLastJobLevel(jobLevel);
|
|
|
data.setLastJobGradeIndex(jobLevel.getInt(FormConstant.JOBLEVELSEQ));
|
|
|
- data.setLastJobGradeIndex(jobLevel.getInt(FormConstant.JOBLEVELSEQ));
|
|
|
+
|
|
|
+ //---------------------------------- 调整日志 begin ----------------------------------
|
|
|
+ ac.whyAdjust1.add(StrFormatter.format("上一职位序列【{}】", jobSeq.getString(FormConstant.NAME_KEY)));
|
|
|
+ ac.whyAdjust1.add(StrFormatter.format("上一职位档案总积分【{}】", lastPersonPosFile.getBigDecimal(PositionStructureConstant.NCKD_ALLSUMSCORE)));
|
|
|
+ ac.whyAdjust1.add(StrFormatter.format("上一职位档案积分池积分【{}】", data.getLastSumScore()));
|
|
|
+
|
|
|
+ DynamicObject diploma = lastPersonPosFile.getDynamicObject(PositionStructureConstant.NCKD_DIPLOMA);
|
|
|
+ BigDecimal diplomaScore = lastPersonPosFile.getBigDecimal(PositionStructureConstant.NCKD_DIPLOMASCORE);
|
|
|
+ ac.whyAdjust1.add(StrFormatter.format("上一职位档案学历【{}】,学历分【{}】", diploma == null ? "无" : diploma.getString(FormConstant.NAME_KEY), diplomaScore == null ? "无" : diplomaScore));
|
|
|
+
|
|
|
+ String rankName = lastPersonPosFile.getString(PositionStructureConstant.NCKD_RANKNAME);
|
|
|
+ rankName = StringUtils.isEmpty(rankName) ? "无" : rankName;
|
|
|
+ DynamicObject proTitleLevel = lastPersonPosFile.getDynamicObject(PositionStructureConstant.NCKD_PROTITLELEVEL);
|
|
|
+ String ranksScore = lastPersonPosFile.getString(PositionStructureConstant.NCKD_RANKSCORE);
|
|
|
+ ac.whyAdjust1.add(StrFormatter.format("上一职位档案职称【{}】,职称等级【{}】,职称等级分【{}】", rankName,proTitleLevel == null ? "无" : proTitleLevel.getString(FormConstant.NAME_KEY), ranksScore == null ? "无" : ranksScore));
|
|
|
+
|
|
|
+ String jobStatusName = lastPersonPosFile.getString(PositionStructureConstant.NCKD_JOBSTATUSNAME);
|
|
|
+ jobStatusName = StringUtils.isEmpty(jobStatusName) ? "无" : jobStatusName;
|
|
|
+ DynamicObject ocpQualLevel = lastPersonPosFile.getDynamicObject(PositionStructureConstant.NCKD_OCPQUALLEVEL);
|
|
|
+ String jobStatusScore = lastPersonPosFile.getString(PositionStructureConstant.NCKD_JOBSTATUSSCORE);
|
|
|
+ ac.whyAdjust1.add(StrFormatter.format("上一职位档案技能【{}】,技能等级【{}】,技能等级分【{}】", jobStatusName,ocpQualLevel == null ? "无" : ocpQualLevel.getString(FormConstant.NAME_KEY), jobStatusScore == null ? "无" : jobStatusScore));
|
|
|
+ ac.whyAdjust1.add(StrFormatter.format("上一职位档案职级【{}({})】", jobLevel.getString(FormConstant.NAME_KEY),data.getLastJobGradeIndex()));
|
|
|
+ ac.whyAdjust1.add("----------------------------------------------------------");
|
|
|
+ //---------------------------------- 调整日志 end ----------------------------------
|
|
|
+ }
|
|
|
+
|
|
|
+ ac.whyAdjust1.add(StrFormatter.format("上年度【{}】考核结果为【{}】;", lastYear, performanceResult.getString(FormConstant.NAME_KEY)));
|
|
|
+ if(rankingInfo == null) {
|
|
|
+ ac.whyAdjust1.add("无全排名");
|
|
|
+ }else{
|
|
|
+ ac.whyAdjust1.add(StrFormatter.format("上年度【{}】排名单元【{}】,全排名名次【{}】,全排名总人数【{}】,R排名名次【{}】,R排名总人数【{}】;",
|
|
|
+ lastYear, rankingInfo.groupName,rankingInfo.topRank,rankingInfo.allowanceRank,rankingInfo.count,rankingInfo.countR));
|
|
|
}
|
|
|
|
|
|
+
|
|
|
//5.获取员工任职信息(对应SHR:PersonpositionfileUtils:998~1009行)
|
|
|
- PositionAppointmentBO positionAppointment = PositionStructureHelper.positionAppointmentQuery(ac.personId, beginDate == null ? new Date() : beginDate);
|
|
|
+ // PositionAppointmentBO positionAppointment = PositionStructureHelper.positionAppointmentQuery(ac.personId, beginDate == null ? new Date() : beginDate);
|
|
|
DynamicObject perEduExp = positionAppointment.getPerEduExp();
|
|
|
if(perEduExp != null){
|
|
|
data.setDiplomaId(perEduExp.getLong(String.join(".", FormConstant.EDUCATION_KEY, FormConstant.ID_KEY)));
|
|
|
@@ -202,8 +274,8 @@ public class AnnualAdjustmentService {
|
|
|
data.setPersonDepId(empPosOrgRel.getLong(String.join(".",FormConstant.ADMINORG,FormConstant.ID_KEY)));
|
|
|
data.setHrJobFamilyId(empPosOrgRel.getLong(String.join(".", FormConstant.HBPM_POSITIONHR, FormConstant.NCKD_JOBSEQ, FormConstant.ID_KEY)));
|
|
|
data.setHrJobFamilyNumber(empPosOrgRel.getString(String.join(".", FormConstant.HBPM_POSITIONHR, FormConstant.NCKD_JOBSEQ, FormConstant.NUMBER_KEY)));
|
|
|
- data.setPositionId(empPosOrgRel.getLong(String.join(".", FormConstant.HBPM_POSITIONHR, FormConstant.ID_KEY)));
|
|
|
- data.setPositionName(empPosOrgRel.getString(String.join(".", FormConstant.HBPM_POSITIONHR, FormConstant.NAME_KEY)));
|
|
|
+ data.setPositionId(empPosOrgRel.getLong(String.join(".", FormConstant.POSITION_KEY, FormConstant.ID_KEY)));
|
|
|
+ data.setPositionName(empPosOrgRel.getString(String.join(".", FormConstant.POSITION_KEY, FormConstant.NAME_KEY)));
|
|
|
data.setPersonName(empPosOrgRel.getString(String.join(".", FormConstant.EMPLOYEE_KEY, FormConstant.NAME_KEY)));
|
|
|
// data.setHrOrgUnitId();
|
|
|
}else{
|
|
|
@@ -232,10 +304,12 @@ public class AnnualAdjustmentService {
|
|
|
long jobSeq = positionAppointment.getEmpPosOrgRel().getLong(String.join(".", FormConstant.HBPM_POSITIONHR, FormConstant.NCKD_JOBSEQ, FormConstant.ID_KEY));
|
|
|
ac.jobSeq = BusinessDataServiceHelper.loadSingle(jobSeq,FormConstant.HBJM_JOBSEQHR);
|
|
|
|
|
|
+ ac.data = data;
|
|
|
|
|
|
// 对应SHR:307~322行
|
|
|
// 判断R位次存在性
|
|
|
if (ac.data.getRankingResultInfo() == null || ac.data.getRankingResultInfo().allowanceRankPercent == null || ac.data.getRankingResultInfo().topRank == null) {
|
|
|
+ //如果没有排名与R排名,则按保级处理
|
|
|
ac.keep = true;
|
|
|
}
|
|
|
if (ac.data.getRankingResultInfo() == null || ac.data.getRankingResultInfo().allowanceRankPercent == null || ac.data.getRankingResultInfo().allowanceRankPercent <= 0) {
|
|
|
@@ -254,7 +328,6 @@ public class AnnualAdjustmentService {
|
|
|
ac.minusByAppraisal = -2;
|
|
|
ac.whyAdjust.append("【考核结果不合格】降2级");
|
|
|
}
|
|
|
- ac.data = data;
|
|
|
return ac;
|
|
|
}
|
|
|
|
|
|
@@ -265,7 +338,7 @@ public class AnnualAdjustmentService {
|
|
|
* @author W.Y.C
|
|
|
* @date: 2025/10/08 22:12
|
|
|
*/
|
|
|
- private void evaluateFirstAndAppraisalUsage(AdjustmentContext ac) {
|
|
|
+ private static void evaluateFirstAndAppraisalUsage(AdjustmentContext ac) {
|
|
|
|
|
|
DynamicObject nowYearPersonPosFile = PositionStructureHelper.getLatsPersonPosFileByPerson(ac.personId, new QFilter(PositionStructureConstant.NCKD_EXECUTEYEAR, QCP.equals, ac.nowYear));
|
|
|
|
|
|
@@ -278,15 +351,19 @@ public class AnnualAdjustmentService {
|
|
|
throw new ValidationException(StrFormatter.format("人员【{}】,上年考度核结果存在变更,需删除【{}】年度创建的【员工职位档案调整】记录才能继续操作 !", ac.personName,ac.nowYear));
|
|
|
}
|
|
|
LocalDateTime nowYearDateTime = LocalDateTime.of(ac.nowYear, 1, 1, 0, 0);
|
|
|
- ac.useAppraisalresult = JobLevelCalculatorService.useAppraisalResult(ac.personId, DateUtil.toDate(nowYearDateTime));
|
|
|
+ StringBuilder reasons = new StringBuilder();
|
|
|
+ ac.useAppraisalresult = JobLevelCalculatorService.useAppraisalResult(ac.personId, DateUtil.toDate(nowYearDateTime),reasons);
|
|
|
+ ac.useAppraisalResultReasons = reasons;
|
|
|
if (ac.useAppraisalresult && ac.minusByAppraisal != 0) {
|
|
|
ac.whyAdjust.append(" 非").append(ac.nowYear)
|
|
|
.append("年度首次调整,且升降【考核结果】已被使用,不需要考虑R排名,保级处理");
|
|
|
ac.haveRp = false;
|
|
|
ac.keep = true;
|
|
|
}
|
|
|
+ ac.whyAdjust1.add("【非】本年度首次调整,"+reasons.toString());
|
|
|
} else {
|
|
|
ac.whyAdjust.append(" ").append(ac.nowYear).append("年度首次调整,【考核结果】未被使用");
|
|
|
+ ac.whyAdjust1.add("本年度首次调整");
|
|
|
isyearfirstdo = true;
|
|
|
}
|
|
|
|
|
|
@@ -300,7 +377,9 @@ public class AnnualAdjustmentService {
|
|
|
isyearfirstdo = true;
|
|
|
if (ac.minusByAppraisal == 0) {
|
|
|
ac.whyAdjust.append("【考核结果】为保级,");
|
|
|
- Double p = ac.data.getRankingResultInfo().allowanceRankPercent;
|
|
|
+ Double p = Optional.ofNullable(ac.data.getRankingResultInfo())
|
|
|
+ .map(info -> info.allowanceRankPercent)
|
|
|
+ .orElse(null);
|
|
|
if (p == null || p <= 0) {
|
|
|
ac.whyAdjust.append("无R排名");
|
|
|
ac.haveRp = false;
|
|
|
@@ -321,7 +400,7 @@ public class AnnualAdjustmentService {
|
|
|
* @author W.Y.C
|
|
|
* @date: 2025/10/08 23:13
|
|
|
*/
|
|
|
- private void loadLastRecordAndValidateBeginDate(AdjustmentContext ac) {
|
|
|
+ private static void loadLastRecordAndValidateBeginDate(AdjustmentContext ac) {
|
|
|
ac.lastRecordId = ac.data.getLastId() != null && ac.data.getLastId() != 0 ? ac.data.getLastId() : ac.data.getFirstId();
|
|
|
if (ac.lastRecordId == null || ac.lastRecordId == 0) {
|
|
|
throw new ValidationException(StrFormatter.format("人员【{}】,缺少职位及积分初定信息,请先完成初定,第二年再操作年度调整!", ac.personName));
|
|
|
@@ -332,7 +411,7 @@ public class AnnualAdjustmentService {
|
|
|
&& ac.lastRecordInfo != null
|
|
|
&& ac.lastRecordInfo.getDate(PositionStructureConstant.NCKD_BEGINDATE) != null) {
|
|
|
Date lastBegin = ac.lastRecordInfo.getDate(PositionStructureConstant.NCKD_BEGINDATE);
|
|
|
- if (ac.beginDate.before(lastBegin)) {
|
|
|
+ if (ac.beginDate.compareTo(lastBegin) <= 0) {
|
|
|
throw new ValidationException(StrFormatter.format("当前无法为【{}】进行调整,因为最近调整时间为【{}】,不能早于最近一次职位调整时间。", ac.personName,DateUtil.format(lastBegin,DateUtil.NORM_DATE_PATTERN)));
|
|
|
}
|
|
|
}
|
|
|
@@ -346,7 +425,7 @@ public class AnnualAdjustmentService {
|
|
|
* @author W.Y.C
|
|
|
* @date: 2025/10/08 23:46
|
|
|
*/
|
|
|
- private void aggregateScores(AdjustmentContext ac) {
|
|
|
+ private static void aggregateScores(AdjustmentContext ac) {
|
|
|
BigDecimal allyearscoresum =
|
|
|
ac.data.getAllYearScoreSum() == null ? BigDecimal.ZERO : ac.data.getAllYearScoreSum();
|
|
|
System.out.println("上年所有贡献单据分数之和" + allyearscoresum);
|
|
|
@@ -383,7 +462,7 @@ public class AnnualAdjustmentService {
|
|
|
* @author W.Y.C
|
|
|
* @date: 2025/10/10 14:17
|
|
|
*/
|
|
|
- private DynamicObject decideTargetJobGrade(AdjustmentContext ac) {
|
|
|
+ private static DynamicObject decideTargetJobGrade(AdjustmentContext ac) {
|
|
|
|
|
|
//上一条职位档案的职位序列(如果是管理序列,则转换为职能序列)
|
|
|
String newJobSeqNumber = ac.convertJobSeq.getString(FormConstant.NUMBER_KEY);
|
|
|
@@ -407,7 +486,8 @@ public class AnnualAdjustmentService {
|
|
|
* @author W.Y.C
|
|
|
* @date: 2025/10/10 14:18
|
|
|
*/
|
|
|
- private DynamicObject decideWithR(AdjustmentContext ac) {
|
|
|
+ private static DynamicObject decideWithR(AdjustmentContext ac) {
|
|
|
+ //根据[职位序列][积分]和[职称等级/技能等级]获取职位序列最高职级
|
|
|
DynamicObject jobLevel = JobLevelCalculatorService.getJobLevel(ac.convertJobSeq, ac.allSumScore, ac.data.getZgjbNumber(), ac.data.getZyjndjNumber(), 0, Boolean.FALSE,Boolean.FALSE);
|
|
|
if(jobLevel == null){
|
|
|
throw new ValidationException(StrFormatter.format("人员【{}】,职位序列【{}】总积分【{}】职称等级【{}】技能等级【{}】考核结果【{}】没有匹配到符合的职级",
|
|
|
@@ -432,12 +512,15 @@ public class AnnualAdjustmentService {
|
|
|
}
|
|
|
|
|
|
if (newjobgradeindex > jobGradeindex) {
|
|
|
+ //超过职位序列最高职级则退回职位序列最高职级
|
|
|
newjobgradeindex = jobGradeindex;
|
|
|
+ //但超出『积分』和『职称等级、技能等级』的所能定级的最高职级,按
|
|
|
}
|
|
|
} else {
|
|
|
// 考核结果需要升降级则直接执行
|
|
|
newjobgradeindex = ac.data.getLastJobGradeIndex() + ac.minusByAppraisal;
|
|
|
if (jobGradeindex <= newjobgradeindex) {
|
|
|
+ //超过职位序列最高职级则退回职位序列最高职级
|
|
|
newjobgradeindex = jobGradeindex;
|
|
|
}
|
|
|
}
|
|
|
@@ -502,7 +585,7 @@ public class AnnualAdjustmentService {
|
|
|
* @author W.Y.C
|
|
|
* @date: 2025/10/10 14:18
|
|
|
*/
|
|
|
- private DynamicObject decideWithoutR(AdjustmentContext ac) {
|
|
|
+ private static DynamicObject decideWithoutR(AdjustmentContext ac) {
|
|
|
// String JobGrade = "";
|
|
|
DynamicObject jobLevel = null;
|
|
|
|
|
|
@@ -589,7 +672,7 @@ public class AnnualAdjustmentService {
|
|
|
* @author W.Y.C
|
|
|
* @date: 2025/10/10 15:44
|
|
|
*/
|
|
|
- private DynamicObject buildPersonPositionFile(AdjustmentContext ac, DynamicObject jobLevel) {
|
|
|
+ private static DynamicObject buildPersonPositionFile(AdjustmentContext ac, DynamicObject jobLevel) {
|
|
|
|
|
|
DynamicObject newPersonPosFile = BusinessDataServiceHelper.newDynamicObject(
|
|
|
PositionStructureConstant.PERSONPOSFILE_ENTITYID);
|
|
|
@@ -628,27 +711,35 @@ public class AnnualAdjustmentService {
|
|
|
newPersonPosFile.set(PositionStructureConstant.NCKD_LASTPERSONPOSFILE, ac.lastRecordInfo);
|
|
|
newPersonPosFile.set(PositionStructureConstant.NCKD_DIPLOMASCORE, ac.diplomaScore);
|
|
|
newPersonPosFile.set(PositionStructureConstant.NCKD_WHYDIPLOMASCORE, ac.whyDiplomaScore.toString());
|
|
|
- newPersonPosFile.set(PositionStructureConstant.NCKD_RANKSCORE, ac.data.getJobScoreInfo().perProTitleScore);
|
|
|
- newPersonPosFile.set(PositionStructureConstant.NCKD_JOBSTATUSSCORE, ac.data.getJobScoreInfo().quaLevelScore);
|
|
|
+ if(ac.data.getJobScoreInfo() != null) {
|
|
|
+ newPersonPosFile.set(PositionStructureConstant.NCKD_RANKSCORE, ac.data.getJobScoreInfo().perProTitleScore);
|
|
|
+ newPersonPosFile.set(PositionStructureConstant.NCKD_JOBSTATUSSCORE, ac.data.getJobScoreInfo().quaLevelScore);
|
|
|
+ }
|
|
|
newPersonPosFile.set(PositionStructureConstant.NCKD_ALLSUMSCORE, ac.allSumScore);
|
|
|
newPersonPosFile.set(PositionStructureConstant.NCKD_SUMSCORE,ac.sumScore);
|
|
|
- newPersonPosFile.set(PositionStructureConstant.NCKD_BEGINDATE, ac.beginDate);
|
|
|
+ newPersonPosFile.set(PositionStructureConstant.NCKD_ADJUSTTYPE,ac.adjustType);
|
|
|
+ newPersonPosFile.set(PositionStructureConstant.NCKD_ADJUSSTATUS, EnableEnum.NO.getCode());
|
|
|
+ if(ac.beginDate != null){
|
|
|
+ newPersonPosFile.set(PositionStructureConstant.NCKD_BEGINDATE, ac.beginDate);
|
|
|
+ newPersonPosFile.set(PositionStructureConstant.NCKD_ADJUSSTATUS, EnableEnum.YES.getCode());
|
|
|
+ }
|
|
|
newPersonPosFile.set(PositionStructureConstant.NCKD_ADJUSTINT, ac.adjustInt);
|
|
|
newPersonPosFile.set(PositionStructureConstant.NCKD_FIRSTRANK, EnableEnum.NO.getCode());
|
|
|
|
|
|
- newPersonPosFile.set(PositionStructureConstant.NCKD_TOPRANK, ac.data.getRankingResultInfo().topRank);
|
|
|
- newPersonPosFile.set(PositionStructureConstant.NCKD_ALLOWANCERANK, ac.data.getRankingResultInfo().allowanceRank);
|
|
|
- newPersonPosFile.set(PositionStructureConstant.NCKD_TOPRANKPERCENT, ac.data.getRankingResultInfo().topRankPercent);
|
|
|
- newPersonPosFile.set(PositionStructureConstant.NCKD_ALLOWANCERANKMARK, ac.data.getRankingResultInfo().allowanceRankMark);
|
|
|
- newPersonPosFile.set(PositionStructureConstant.NCKD_ALLOWANCERANKSEL, ac.data.getRankingResultInfo().allowanceRankSel);
|
|
|
- newPersonPosFile.set(PositionStructureConstant.NCKD_ALLOWANCERANKPCT, ac.data.getRankingResultInfo().allowanceRankPercent);
|
|
|
+ if(ac.data.getRankingResultInfo() != null) {
|
|
|
+ newPersonPosFile.set(PositionStructureConstant.NCKD_TOPRANK, ac.data.getRankingResultInfo().topRank);
|
|
|
+ newPersonPosFile.set(PositionStructureConstant.NCKD_ALLOWANCERANK, ac.data.getRankingResultInfo().allowanceRank);
|
|
|
+ newPersonPosFile.set(PositionStructureConstant.NCKD_TOPRANKPERCENT, ac.data.getRankingResultInfo().topRankPercent);
|
|
|
+ newPersonPosFile.set(PositionStructureConstant.NCKD_ALLOWANCERANKMARK, ac.data.getRankingResultInfo().allowanceRankMark);
|
|
|
+ newPersonPosFile.set(PositionStructureConstant.NCKD_ALLOWANCERANKSEL, ac.data.getRankingResultInfo().allowanceRankSel);
|
|
|
+ newPersonPosFile.set(PositionStructureConstant.NCKD_ALLOWANCERANKPCT, ac.data.getRankingResultInfo().allowanceRankPercent);
|
|
|
+ }
|
|
|
//上年度考核结果
|
|
|
newPersonPosFile.set(PositionStructureConstant.NCKD_APPRAISALRESULT, ac.data.getAppraisalResult());
|
|
|
newPersonPosFile.set(PositionStructureConstant.NCKD_RESULTSCORE, ac.data.getAppraisalResultScore());
|
|
|
- newPersonPosFile.set(PositionStructureConstant.NCKD_ADJUSTTYPE, ac.adjustType);
|
|
|
|
|
|
newPersonPosFile.set(PositionStructureConstant.NCKD_DISABLE, EnableEnum.NO.getCode());
|
|
|
- newPersonPosFile.set(PositionStructureConstant.NCKD_ISCURRENTNEWEST, EnableEnum.YES.getCode());
|
|
|
+ // newPersonPosFile.set(PositionStructureConstant.NCKD_ISCURRENTNEWEST, EnableEnum.YES.getCode());
|
|
|
newPersonPosFile.set(PositionStructureConstant.STATUS, StatusEnum.C.toString());
|
|
|
newPersonPosFile.set(PositionStructureConstant.ENABLE, EnableEnum.YES.getCode());
|
|
|
newPersonPosFile.set(PositionStructureConstant.NCKD_YEARSCORESUMA, ac.data.getYearscoresuma());
|
|
|
@@ -702,6 +793,9 @@ public class AnnualAdjustmentService {
|
|
|
/** 本年考核是否已使用 */
|
|
|
boolean useAppraisalresult = false;
|
|
|
|
|
|
+ /** 本年考核被使用的原因*/
|
|
|
+ StringBuilder useAppraisalResultReasons;
|
|
|
+
|
|
|
/** 是否本年首次调整 */
|
|
|
boolean isYearFirstDo = false;
|
|
|
|
|
|
@@ -751,5 +845,8 @@ public class AnnualAdjustmentService {
|
|
|
DynamicObject convertJobSeq;
|
|
|
|
|
|
String remark;
|
|
|
+
|
|
|
+ /** 调整说明 */
|
|
|
+ StringJoiner whyAdjust1 = new StringJoiner(StrFormatter.LINE_SEPARATOR);
|
|
|
}
|
|
|
}
|