|
|
@@ -4,6 +4,7 @@ import kd.bos.dataentity.entity.DynamicObject;
|
|
|
import kd.bos.dataentity.entity.DynamicObjectCollection;
|
|
|
import kd.bos.entity.ExtendedDataEntity;
|
|
|
import kd.bos.entity.validate.AbstractValidator;
|
|
|
+import kd.bos.orm.query.QCP;
|
|
|
import kd.bos.orm.query.QFilter;
|
|
|
import kd.bos.servicehelper.QueryServiceHelper;
|
|
|
import nckd.jxccl.base.common.constant.FormConstant;
|
|
|
@@ -11,12 +12,12 @@ import nckd.jxccl.base.common.enums.AppraisalResultEnum;
|
|
|
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.orm.helper.QFilterCommonHelper;
|
|
|
import nckd.jxccl.hr.psms.common.PerfRankMgmtConstant;
|
|
|
import nckd.jxccl.hr.psms.common.PositionStructureConstant;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
import java.math.RoundingMode;
|
|
|
+import java.time.LocalDate;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Collections;
|
|
|
import java.util.HashMap;
|
|
|
@@ -24,6 +25,8 @@ import java.util.HashSet;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.Set;
|
|
|
+import java.util.StringJoiner;
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
* 绩效排名管理保存验证插件
|
|
|
@@ -36,39 +39,53 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
|
|
|
private final Map<String, BigDecimal> appraisalResultRatioMap = new HashMap<>();
|
|
|
@Override
|
|
|
public void validate() {
|
|
|
- QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
|
|
|
- .addGroup(new String[]{FormConstant.NCKD_ENTRYENTITY}, PerfRankMgmtConstant.NCKD_RATIO)
|
|
|
- .addGroup(new String[]{FormConstant.NCKD_ENTRYENTITY, PositionStructureConstant.NCKD_APPRAISALRESULT}, FormConstant.NUMBER_KEY);
|
|
|
- DynamicObjectCollection query = QueryServiceHelper.query(PerfRankMgmtConstant.RANKRATIOCONF_ENTITYID, queryFieldBuilder.buildSelect(), null);
|
|
|
-
|
|
|
- query.forEach(dynamicObject -> {
|
|
|
- String key = dynamicObject.getString(String.join(".",FormConstant.NCKD_ENTRYENTITY, PositionStructureConstant.NCKD_APPRAISALRESULT, FormConstant.NUMBER_KEY));
|
|
|
- BigDecimal value = dynamicObject.getBigDecimal(String.join(".",FormConstant.NCKD_ENTRYENTITY, PerfRankMgmtConstant.NCKD_RATIO));
|
|
|
- appraisalResultRatioMap.put(key, value);
|
|
|
- });
|
|
|
- for (ExtendedDataEntity rowDataEntity : getDataEntities()) {
|
|
|
- if(appraisalResultRatioMap.isEmpty()){
|
|
|
- this.addMessage(rowDataEntity, "没有配置【排名考核结果比例】");
|
|
|
- return;
|
|
|
- }
|
|
|
- DynamicObject data = rowDataEntity.getDataEntity();
|
|
|
- // 年份校验
|
|
|
- if (validateYear(data, rowDataEntity)) {
|
|
|
- // 获取明细数据并验证是否为空
|
|
|
- DynamicObjectCollection entries = data.getDynamicObjectCollection(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
|
|
|
- if (entries.isEmpty()) {
|
|
|
- String operateKey = this.getOperateKey();
|
|
|
- if(!operateKey.equals(FormConstant.SAVE_OP)) {
|
|
|
- this.addMessage(rowDataEntity, "请添加排名名单");
|
|
|
- continue;
|
|
|
- }
|
|
|
+ String invoker = (String)this.getOption().getVariables().get(FormConstant.HR_INVOKER_PARAM_INVOKER);
|
|
|
+ boolean dataMigration = FormConstant.DATA_MIGRATION.equalsIgnoreCase(invoker);
|
|
|
+ if(!dataMigration) {
|
|
|
+ QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
|
|
|
+ .addGroup(new String[]{FormConstant.NCKD_ENTRYENTITY}, PerfRankMgmtConstant.NCKD_RATIO)
|
|
|
+ .addGroup(new String[]{FormConstant.NCKD_ENTRYENTITY, PositionStructureConstant.NCKD_APPRAISALRESULT}, FormConstant.NUMBER_KEY);
|
|
|
+ DynamicObjectCollection query = QueryServiceHelper.query(PerfRankMgmtConstant.RANKRATIOCONF_ENTITYID, queryFieldBuilder.buildSelect(), null);
|
|
|
+
|
|
|
+ query.forEach(dynamicObject -> {
|
|
|
+ String key = dynamicObject.getString(String.join(".", FormConstant.NCKD_ENTRYENTITY, PositionStructureConstant.NCKD_APPRAISALRESULT, FormConstant.NUMBER_KEY));
|
|
|
+ BigDecimal value = dynamicObject.getBigDecimal(String.join(".", FormConstant.NCKD_ENTRYENTITY, PerfRankMgmtConstant.NCKD_RATIO));
|
|
|
+ appraisalResultRatioMap.put(key, value);
|
|
|
+ });
|
|
|
+ for (ExtendedDataEntity rowDataEntity : getDataEntities()) {
|
|
|
+ if (appraisalResultRatioMap.isEmpty()) {
|
|
|
+ this.addFatalErrorMessage(rowDataEntity, "没有配置【排名考核结果比例】");
|
|
|
+ return;
|
|
|
}
|
|
|
+ DynamicObject data = rowDataEntity.getDataEntity();
|
|
|
+ // 年份校验
|
|
|
+ if (validateYear(data, rowDataEntity)) {
|
|
|
+ // 获取明细数据并验证是否为空
|
|
|
+ DynamicObjectCollection entries = data.getDynamicObjectCollection(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY);
|
|
|
+ if (entries.isEmpty()) {
|
|
|
+ String operateKey = this.getOperateKey();
|
|
|
+ // if (!operateKey.equals(FormConstant.SAVE_OP)) {
|
|
|
+ this.addFatalErrorMessage(rowDataEntity, "请添加排名名单");
|
|
|
+ // continue;
|
|
|
+ // }
|
|
|
+ }
|
|
|
+ int step = data.getInt(PerfRankMgmtConstant.NCKD_STEP);
|
|
|
|
|
|
- // 验证明细数据
|
|
|
- ValidationContext context = validateEntries(entries, rowDataEntity);
|
|
|
+ //当步骤为导入考核结果时需校验明细数据
|
|
|
|
|
|
- // 验证统计数据一致性
|
|
|
- validateDataConsistency(data, context, rowDataEntity);
|
|
|
+ // 验证明细数据
|
|
|
+ ValidationContext context = validateEntries(entries, rowDataEntity);
|
|
|
+
|
|
|
+ // 校验人员是否在其他分组中排名
|
|
|
+ validateRepetition(data, rowDataEntity, context);
|
|
|
+
|
|
|
+ // 校验人员是否有对应考核周期
|
|
|
+ validatePerfManager(data,entries,rowDataEntity, context);
|
|
|
+ if(step == 1) {
|
|
|
+ // 验证统计数据一致性
|
|
|
+ validateDataConsistency(data, context, rowDataEntity);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -128,7 +145,7 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
|
|
|
|
|
|
if (difference > allowedDifference) {
|
|
|
|
|
|
- this.addMessage(rowDataEntity,
|
|
|
+ this.addFatalErrorMessage(rowDataEntity,
|
|
|
StrFormatter.format("{}人数与配置比例不符,应为{}人,实际为{}人",
|
|
|
levelName, expectedCount,actualCount));
|
|
|
}
|
|
|
@@ -147,7 +164,7 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
|
|
|
int theYear = data.getInt(PerfRankMgmtConstant.NCKD_THEYEAR);
|
|
|
int currentYear = DateUtil.now().getYear();
|
|
|
if (theYear < 1900 || theYear > currentYear) {
|
|
|
- this.addMessage(rowDataEntity, "年份不合法或超过当前年份");
|
|
|
+ this.addFatalErrorMessage(rowDataEntity, "年份不合法或超过当前年份");
|
|
|
return false;
|
|
|
}
|
|
|
return true;
|
|
|
@@ -169,10 +186,66 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
|
|
|
DynamicObject entry = entries.get(i);
|
|
|
validateEntry(entry, rowDataEntity, i + 1, personIds, context);
|
|
|
}
|
|
|
+ context.personIds = personIds;
|
|
|
+
|
|
|
+ return context;
|
|
|
+ }
|
|
|
|
|
|
+
|
|
|
+ private void validateRepetition(DynamicObject data, ExtendedDataEntity rowDataEntity, ValidationContext context) {
|
|
|
//根据年度校验人员只能在同一个组
|
|
|
+ long id = data.getLong(FormConstant.ID_KEY);
|
|
|
+ int theYear = data.getInt(PerfRankMgmtConstant.NCKD_THEYEAR);
|
|
|
+ QFilter filter = new QFilter(String.join(".", PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, PerfRankMgmtConstant.NCKD_PERSON), QCP.in, context.personIds);
|
|
|
+ if(id > 0){
|
|
|
+ filter.and(FormConstant.ID_KEY, QCP.not_equals, id);
|
|
|
+ }
|
|
|
+ filter.and(PerfRankMgmtConstant.NCKD_THEYEAR,QCP.equals,theYear);
|
|
|
+ QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
|
|
|
+ .add(FormConstant.NAME_KEY)
|
|
|
+ .add(PerfRankMgmtConstant.NCKD_THEYEAR)
|
|
|
+ .addIdNumberName(PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, PerfRankMgmtConstant.NCKD_PERSON);
|
|
|
+ DynamicObjectCollection query = QueryServiceHelper.query(PerfRankMgmtConstant.NCKD_PERFRANKMGMT_ENTITYID, queryFieldBuilder.buildSelect(), new QFilter[]{filter});
|
|
|
+ StringJoiner msgJoiner = new StringJoiner(StrFormatter.LINE_SEPARATOR);
|
|
|
+ for (DynamicObject dynamicObject : query) {
|
|
|
+ String name = dynamicObject.getString(FormConstant.NAME_KEY);
|
|
|
+ String personName = dynamicObject.getString(String.join(".", PerfRankMgmtConstant.NCKD_PERFRANKMGMTENTRY, PerfRankMgmtConstant.NCKD_PERSON,FormConstant.NAME_KEY));
|
|
|
+ msgJoiner.add(StrFormatter.format("人员【{}】已在排名单元【{}】中排名;", personName,name));
|
|
|
+ }
|
|
|
+ if(msgJoiner.length() > 0){
|
|
|
+ this.addFatalErrorMessage(rowDataEntity, msgJoiner.toString());
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- return context;
|
|
|
+
|
|
|
+
|
|
|
+ private void validatePerfManager(DynamicObject data,DynamicObjectCollection entries, ExtendedDataEntity rowDataEntity, ValidationContext context) {
|
|
|
+ //根据年度校验人员只能在同一个组
|
|
|
+ int theYear = data.getInt(PerfRankMgmtConstant.NCKD_THEYEAR);
|
|
|
+ LocalDate startDate = LocalDate.of(theYear, 1, 1);
|
|
|
+ QFilter filter = new QFilter(PerfRankMgmtConstant.NCKD_PERSON, QCP.in, context.personIds);
|
|
|
+ filter.and(PerfRankMgmtConstant.NCKD_BEGINYEAR,QCP.less_equals,startDate);
|
|
|
+ filter.and(PerfRankMgmtConstant.NCKD_ENDYEAR,QCP.large_equals,startDate);
|
|
|
+ QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
|
|
|
+ .addIdNumberName(PerfRankMgmtConstant.NCKD_PERSON);
|
|
|
+ DynamicObjectCollection query = QueryServiceHelper.query(PerfRankMgmtConstant.PERFMANAGER_ENTITYID, queryFieldBuilder.buildSelect(), new QFilter[]{filter});
|
|
|
+ Map<Long, DynamicObject> personMap = query.stream()
|
|
|
+ .filter(obj -> obj.getLong(String.join(".", PerfRankMgmtConstant.NCKD_PERSON, FormConstant.ID_KEY)) > 0)
|
|
|
+ .collect(Collectors.toMap(
|
|
|
+ obj -> obj.getLong(String.join(".", PerfRankMgmtConstant.NCKD_PERSON, FormConstant.ID_KEY)),
|
|
|
+ obj -> obj
|
|
|
+ ));
|
|
|
+ StringJoiner msgJoiner = new StringJoiner(StrFormatter.LINE_SEPARATOR);
|
|
|
+ for (DynamicObject entry : entries) {
|
|
|
+ long person = entry.getDynamicObject(PerfRankMgmtConstant.NCKD_PERSON).getLong(FormConstant.ID_KEY);
|
|
|
+ if (!personMap.containsKey(person)) {
|
|
|
+ String personName = entry.getDynamicObject(PerfRankMgmtConstant.NCKD_PERSON).getString(FormConstant.NAME_KEY);
|
|
|
+ msgJoiner.add(StrFormatter.format("人员【{}】没有【{}】年度的考核周期;", personName,theYear));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(msgJoiner.length() > 0){
|
|
|
+ this.addFatalErrorMessage(rowDataEntity, msgJoiner.toString());
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -191,12 +264,12 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
|
|
|
int rowIndex, Set<Long> personIds, ValidationContext context) {
|
|
|
DynamicObject person = entry.getDynamicObject(PerfRankMgmtConstant.NCKD_PERSON);
|
|
|
if (person == null) {
|
|
|
- this.addMessage(rowDataEntity, StrFormatter.format("第{}行,请选择人员\n", rowIndex));
|
|
|
+ this.addFatalErrorMessage(rowDataEntity, StrFormatter.format("第{}行,请选择人员\n", rowIndex));
|
|
|
} else {
|
|
|
// 人员重复校验
|
|
|
long personId = person.getLong(FormConstant.ID_KEY);
|
|
|
if (personIds.contains(personId)) {
|
|
|
- this.addMessage(rowDataEntity, StrFormatter.format("第{}行,人员【{}】重复;\n", rowIndex, person.getString(FormConstant.NAME_KEY)));
|
|
|
+ this.addFatalErrorMessage(rowDataEntity, StrFormatter.format("第{}行,人员【{}】重复;\n", rowIndex, person.getString(FormConstant.NAME_KEY)));
|
|
|
} else {
|
|
|
personIds.add(personId);
|
|
|
}
|
|
|
@@ -279,19 +352,19 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
|
|
|
int excellents = data.getInt(PerfRankMgmtConstant.NCKD_EXCELLENTS);
|
|
|
|
|
|
if (topRanks != context.totalRankCount) {
|
|
|
- this.addMessage(rowDataEntity, "总排名人数与实际录入数据不一致;\n");
|
|
|
+ this.addFatalErrorMessage(rowDataEntity, "总排名人数与实际录入数据不一致;\n");
|
|
|
}
|
|
|
if (allowanceRanks != context.allowanceRankCount) {
|
|
|
- this.addMessage(rowDataEntity, "R排名人数与实际录入数据不一致;\n");
|
|
|
+ this.addFatalErrorMessage(rowDataEntity, "R排名人数与实际录入数据不一致;\n");
|
|
|
}
|
|
|
if (fails != context.failCount) {
|
|
|
- this.addMessage(rowDataEntity, "不合格人数与实际录入数据不一致;\n");
|
|
|
+ this.addFatalErrorMessage(rowDataEntity, "不合格人数与实际录入数据不一致;\n");
|
|
|
}
|
|
|
if (basics != context.basicCount) {
|
|
|
- this.addMessage(rowDataEntity, "基本人数与实际录入数据不一致;\n");
|
|
|
+ this.addFatalErrorMessage(rowDataEntity, "基本人数与实际录入数据不一致;\n");
|
|
|
}
|
|
|
if (excellents != context.excellentCount) {
|
|
|
- this.addMessage(rowDataEntity, "优秀人数与实际录入数据不一致;\n");
|
|
|
+ this.addFatalErrorMessage(rowDataEntity, "优秀人数与实际录入数据不一致;\n");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -343,14 +416,14 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
|
|
|
// 检查排名字段是否在有效范围内
|
|
|
int topRank = entry.getInt(PerfRankMgmtConstant.NCKD_TOPRANK);
|
|
|
if (topRank < 1 || topRank > totalRankCount) {
|
|
|
- this.addMessage(rowDataEntity,
|
|
|
+ this.addFatalErrorMessage(rowDataEntity,
|
|
|
StrFormatter.format("第{}行,排名{}超出有效范围[1-{}]\n", i + 1, topRank, totalRankCount));
|
|
|
}
|
|
|
if (postAllowance) {
|
|
|
// 检查R排名字段是否在有效范围内
|
|
|
int allowanceRank = entry.getInt(PerfRankMgmtConstant.NCKD_ALLOWANCERANK);
|
|
|
if (allowanceRank < 1 || allowanceRank > totalRankCount) {
|
|
|
- this.addMessage(rowDataEntity,
|
|
|
+ this.addFatalErrorMessage(rowDataEntity,
|
|
|
StrFormatter.format("第{}行,R排名{}超出有效范围[1-{}]\n", i + 1, allowanceRank, totalRankCount));
|
|
|
}
|
|
|
}
|
|
|
@@ -378,7 +451,7 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
|
|
|
Map<Integer, Integer> rankCountMap) {
|
|
|
int rankValue = entry.getInt(rankField);
|
|
|
if (rankValue < 1) {
|
|
|
- this.addMessage(rowDataEntity, StrFormatter.format("人员【{}】已勾选{},{}数不能小于1或为空",
|
|
|
+ this.addFatalErrorMessage(rowDataEntity, StrFormatter.format("人员【{}】已勾选{},{}数不能小于1或为空",
|
|
|
personName, type, rankType));
|
|
|
} else {
|
|
|
rankCountMap.put(rankValue, rankCountMap.getOrDefault(rankValue, 0) + 1);
|
|
|
@@ -431,7 +504,7 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
|
|
|
errorMsg.append("✅ 合规示例:[1,1,1,4] - 排名1重复3次,结束位置应为1+3-1=3,3不在列表中\n");
|
|
|
errorMsg.append("【解决建议】\n");
|
|
|
errorMsg.append("请调整重复排名的数值或移除冲突的排名,确保连续序列结束位置未被占用;\n\n");
|
|
|
- this.addMessage(rowDataEntity, errorMsg.toString());
|
|
|
+ this.addFatalErrorMessage(rowDataEntity, errorMsg.toString());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -511,7 +584,7 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
|
|
|
detailMessage.append(StrFormatter.format("{}【{}】出现{}次;", rankType, rank, count));
|
|
|
}
|
|
|
detailMessage.append("\n");
|
|
|
- this.addMessage(rowDataEntity, detailMessage.toString());
|
|
|
+ this.addFatalErrorMessage(rowDataEntity, detailMessage.toString());
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -533,6 +606,7 @@ public class PerfRankMgmtSaveValidate extends AbstractValidator {
|
|
|
int basicCount = 0;
|
|
|
int excellentCount = 0;
|
|
|
int qualifiedCount = 0;
|
|
|
+ Set<Long> personIds = new HashSet<>();
|
|
|
Set<Integer> rankSet = new HashSet<>(); // 记录已出现的排名
|
|
|
Set<Integer> duplicateRanks = new HashSet<>(); // 记录普通排名中重复的排名
|
|
|
Set<Integer> duplicateRRanks = new HashSet<>(); // 记录R排名中重复的排名
|