weaver-hrm-salary/src/com/engine/salary/entity/salaryacct/bo/CalculateFormulaVarBO.java

807 lines
44 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.engine.salary.entity.salaryacct.bo;
import cn.hutool.core.util.NumberUtil;
import com.engine.kq.service.KQGroupService;
import com.engine.salary.annotation.SalaryFormulaVar;
import com.engine.salary.common.LocalDateRange;
import com.engine.salary.constant.SalaryFormulaFieldConstant;
import com.engine.salary.constant.SalaryItemConstant;
import com.engine.salary.entity.datacollection.AddUpDeduction;
import com.engine.salary.entity.datacollection.AddUpSituation;
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
import com.engine.salary.entity.datacollection.dto.AttendQuoteDataDTO;
import com.engine.salary.entity.datacollection.dto.AttendQuoteDataValueDTO;
import com.engine.salary.entity.datacollection.dto.AttendQuoteFieldListDTO;
import com.engine.salary.entity.datacollection.po.OtherDeductionPO;
import com.engine.salary.entity.salaryacct.po.SalaryAcctEmployeePO;
import com.engine.salary.entity.salaryacct.po.SalaryAcctResultPO;
import com.engine.salary.entity.salaryarchive.dto.SalaryArchiveDataDTO;
import com.engine.salary.entity.salaryarchive.dto.SalaryArchiveItemDataDTO;
import com.engine.salary.entity.salaryarchive.dto.SalaryArchiveTaxAgentDataDTO;
import com.engine.salary.entity.salaryitem.po.SalaryItemPO;
import com.engine.salary.entity.salarysob.dto.SalarySobCycleDTO;
import com.engine.salary.entity.salarysob.po.SalarySobAdjustRulePO;
import com.engine.salary.enums.SalaryCycleTypeEnum;
import com.engine.salary.enums.UserStatusEnum;
import com.engine.salary.enums.salaryformula.SalaryFormulaReferenceEnum;
import com.engine.salary.enums.salaryformula.SalarySQLReferenceEnum;
import com.engine.salary.enums.salarysob.SalarySobAdjustRuleTypeEnum;
import com.engine.salary.mapper.SQLMapper;
import com.engine.salary.util.JsonUtil;
import com.engine.salary.util.SalaryDateUtil;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.db.MapperProxyFactory;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.Data;
import lombok.experimental.Accessors;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import weaver.conn.RecordSet;
import weaver.general.BaseBean;
import weaver.general.Util;
import weaver.hrm.User;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
import static com.engine.salary.util.SalaryDateUtil.DATE_TIME_FORMATTER_PATTERN;
/**
* 薪资核算-将数据转换成公式中的变量
* <p>Copyright: Copyright (c) 2022</p>
* <p>Company: 泛微软件</p>
*
* @author qiantao
* @version 1.0
**/
@Data
@Accessors(chain = true)
public class CalculateFormulaVarBO {
BaseBean bb = new BaseBean();
String salaryDateFormat = bb.getPropValue("hrmSalaryCustom", "salaryDateFormat");
/**
* 员工信息
*/
private List<DataCollectionEmployee> simpleEmployees;
/**
* 薪资档案
*/
private List<SalaryArchiveDataDTO> salaryArchiveData;
/**
* 累计情况
*/
private List<AddUpSituation> addUpSituationPOS;
/**
* 累计专项附加扣除
*/
private List<AddUpDeduction> addUpDeductionPOS;
/**
* 其他扣除
*/
private List<OtherDeductionPO> otherDeductionPOS;
/**
* 社保福利
*/
private List<Map<String, Object>> welfareData;
/**
* 考勤数据
*/
private List<AttendQuoteDataDTO> attendQuoteDataDTOS;
/**
* 薪资核算结果(输入/导入的值)
*/
private List<SalaryAcctResultPO> salaryAcctResultPOS;
/**
* 浮动薪资档案
*/
private List<Map<String, Object>> variableArchiveList;
/**
* 上月核算结果
*/
List<SalaryAcctResultPO> lastMonthResultPOS;
public CalculateFormulaVarBO(List<DataCollectionEmployee> simpleEmployees,
List<SalaryArchiveDataDTO> salaryArchiveData,
List<AddUpSituation> addUpSituationPOS,
List<AddUpDeduction> addUpDeductionPOS,
List<OtherDeductionPO> otherDeductionPOS,
List<Map<String, Object>> welfareData,
List<AttendQuoteDataDTO> attendQuoteDataDTOS,
List<SalaryAcctResultPO> salaryAcctResultPOS,
List<Map<String, Object>> variableArchiveList,
List<SalaryAcctResultPO> lastMonthResultPOS) {
this.simpleEmployees = simpleEmployees;
this.salaryArchiveData = salaryArchiveData;
this.addUpSituationPOS = addUpSituationPOS;
this.addUpDeductionPOS = addUpDeductionPOS;
this.otherDeductionPOS = otherDeductionPOS;
this.welfareData = welfareData;
this.attendQuoteDataDTOS = attendQuoteDataDTOS;
this.salaryAcctResultPOS = salaryAcctResultPOS;
this.variableArchiveList = variableArchiveList;
this.lastMonthResultPOS = lastMonthResultPOS;
}
/**
* 将查询到的数据转换成公式变量
*
* @param salaryAcctCalculateBO 核算参数
* @return
*/
public Map<String, List<FormulaVarValue>> convert2FormulaVar(SalaryAcctCalculateBO salaryAcctCalculateBO, KQGroupService kqGroupService, Integer attendCycleType) {
Map<String, List<FormulaVarValue>> resultMap = Maps.newHashMapWithExpectedSize(salaryAcctCalculateBO.getSalaryAcctEmployeePOS().size());
// 处理薪资核算结果
handleSalaryAcctResult(salaryAcctCalculateBO, resultMap);
// 处理薪资档案
handleSalaryArchiveData(salaryAcctCalculateBO, resultMap, kqGroupService, attendCycleType);
// 处理浮动薪资档案
handleVariableArchiveData(salaryAcctCalculateBO, resultMap);
// 处理往期累计情况
handleAddUpSituation(resultMap);
// 处理累计专项附加扣除
handleAddUpDeduction(resultMap);
// 处理其他扣除
handleOtherDeduction(resultMap);
// 处理社保福利
handleWelfareData(salaryAcctCalculateBO, resultMap);
// 处理考勤数据
handleAttendQuoteData(salaryAcctCalculateBO, resultMap);
//处理核算人员信息
handleSalaryAcctEmployee(salaryAcctCalculateBO, resultMap);
//处理人员信息
handleSimpleEmployees(resultMap);
//处理上月薪资核算结果
handleLastMonthResult(salaryAcctCalculateBO, resultMap);
return resultMap;
}
/**
* 处理核算日期相关信息
*/
private List<FormulaVarValue> handleSalarySobCycleDTO(SalaryAcctCalculateBO salaryAcctCalculateBO) {
SalarySobCycleDTO salarySobCycleDTO = salaryAcctCalculateBO.getSalarySobCycleDTO();
salarySobCycleDTO.setSalaryDate(SalaryDateUtil.toDate(salarySobCycleDTO.getSalaryMonth(), 1));
salarySobCycleDTO.setTaxDate(SalaryDateUtil.toDate(salarySobCycleDTO.getTaxCycle(), 1));
salarySobCycleDTO.setSocialSecurityDate(SalaryDateUtil.toDate(salarySobCycleDTO.getSocialSecurityCycle(), 1));
LocalDateRange salaryCycle = salarySobCycleDTO.getSalaryCycle();
salarySobCycleDTO.setSalaryCycleFromDate(salaryCycle.getFromDate());
salarySobCycleDTO.setSalaryCycleEndDate(salaryCycle.getEndDate());
LocalDateRange attendCycle = salarySobCycleDTO.getAttendCycle();
salarySobCycleDTO.setAttendCycleFromDate(attendCycle.getFromDate());
salarySobCycleDTO.setAttendCycleEndDate(attendCycle.getEndDate());
Map<String, String> map = JsonUtil.parseMap(salarySobCycleDTO, String.class);
List<FormulaVarValue> formulaVarValues = Lists.newArrayList();
Field[] declaredFields = SalarySobCycleDTO.class.getDeclaredFields();
for (Field declaredField : declaredFields) {
if (declaredField.isAnnotationPresent(SalaryFormulaVar.class)) {
String fieldName = declaredField.getName();
String fieldId = SalarySQLReferenceEnum.SALARY_CYCLE.getValue()
+ SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR
+ fieldName;
String fieldValue = map.getOrDefault(fieldName, StringUtils.EMPTY);
//日期值取yyyy-MM-dd
if (StringUtils.isNotBlank(fieldValue) && fieldValue.length() > 10 && SalaryDateUtil.parse(fieldValue, DATE_TIME_FORMATTER_PATTERN) != null) {
fieldValue = fieldValue.substring(0, 10);
}
formulaVarValues.add(new FormulaVarValue().setFieldId(fieldId).setFieldValue(fieldValue));
}
}
return formulaVarValues;
}
/**
* 处理薪资核算结果
*
* @param salaryAcctCalculateBO 薪资核算参数
* @param resultMap 返回结果集
*/
private void handleSalaryAcctResult(SalaryAcctCalculateBO salaryAcctCalculateBO, Map<String, List<FormulaVarValue>> resultMap) {
// key:薪资项目的id、value:薪资项目的code
Map<Long, String> salaryItemCodeMap = SalaryEntityUtil.convert2Map(salaryAcctCalculateBO.getSalaryItemPOS(), SalaryItemPO::getId, SalaryItemPO::getCode);
// key:薪资项目的code、value:薪资项目的id
Map<String, Long> salaryCodeItemMap = SalaryEntityUtil.convert2Map(salaryAcctCalculateBO.getSalaryItemPOS(), SalaryItemPO::getCode, SalaryItemPO::getId);
// key:employeeId_taxAgentId、value:薪资核算结果集合
Map<String, List<SalaryAcctResultPO>> salaryAcctResultMap = SalaryEntityUtil.group2Map(salaryAcctResultPOS,
salaryAcctResultPO -> salaryAcctResultPO.getEmployeeId() + "_" + salaryAcctResultPO.getTaxAgentId());
//
// List<ExpressFormula> expressFormulas = salaryAcctCalculateBO.getExpressFormulas();
// 填充到返回结果集中
salaryAcctResultMap.forEach((key, salaryAcctResultPOS) -> {
List<FormulaVarValue> formulaVarValues = resultMap.computeIfAbsent(key, k -> Lists.newArrayList());
formulaVarValues.addAll(salaryAcctResultPOS.stream()
.map(salaryAcctResultPO -> {
String fieldId = SalaryFormulaReferenceEnum.SALARY_ITEM.getValue()
+ SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR
+ salaryItemCodeMap.getOrDefault(salaryAcctResultPO.getSalaryItemId(), StringUtils.EMPTY);
return new FormulaVarValue().setFieldId(fieldId).setFieldValue(salaryAcctResultPO.getResultValue());
})
.collect(Collectors.toList()));
Map<Long, SalaryAcctResultPO> salaryAcctResultPOMap = SalaryEntityUtil.convert2Map(salaryAcctResultPOS, SalaryAcctResultPO::getSalaryItemId);
formulaVarValues.addAll(salaryAcctCalculateBO.getIssuedFieldIds().stream()
.map(fieldId -> {
String originResultValue = salaryAcctResultPOMap.getOrDefault(
salaryCodeItemMap.get(fieldId), SalaryAcctResultPO.builder().originResultValue("").build())
.getOriginResultValue();
String fieldId2 = SalaryFormulaReferenceEnum.ISSUED.getValue()
+ SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR
+ fieldId;
return new FormulaVarValue().setFieldId(fieldId2).setFieldValue(originResultValue);
}).collect(Collectors.toList()));
});
}
private void handleLastMonthResult(SalaryAcctCalculateBO salaryAcctCalculateBO, Map<String, List<FormulaVarValue>> resultMap) {
// key:薪资项目的id、value:薪资项目的code
Map<Long, String> salaryItemCodeMap = SalaryEntityUtil.convert2Map(salaryAcctCalculateBO.getSalaryItemPOS(), SalaryItemPO::getId, SalaryItemPO::getCode);
// key:employeeId_taxAgentId、value:薪资核算结果集合
Map<String, List<SalaryAcctResultPO>> salaryAcctResultMap = SalaryEntityUtil.group2Map(lastMonthResultPOS,
salaryAcctResultPO -> salaryAcctResultPO.getEmployeeId() + "_" + salaryAcctResultPO.getTaxAgentId());
// 填充到返回结果集中
salaryAcctResultMap.forEach((key, salaryAcctResultPOS) -> {
List<FormulaVarValue> formulaVarValues = resultMap.computeIfAbsent(key, k -> Lists.newArrayList());
formulaVarValues.addAll(salaryAcctResultPOS.stream()
.map(salaryAcctResultPO -> {
String fieldId = SalaryFormulaReferenceEnum.LAST_MONTH_CALC.getValue()
+ SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR
+ salaryItemCodeMap.getOrDefault(salaryAcctResultPO.getSalaryItemId(), StringUtils.EMPTY);
return new FormulaVarValue().setFieldId(fieldId).setFieldValue(salaryAcctResultPO.getResultValue());
})
.collect(Collectors.toList()));
});
}
/**
* 处理薪资档案(会涉及调薪计薪规则)+处理核算日期
*
* @param salaryAcctCalculateBO 薪资核算参数
* @param resultMap 返回结果集
*/
private void handleSalaryArchiveData(SalaryAcctCalculateBO salaryAcctCalculateBO, Map<String, List<FormulaVarValue>> resultMap, KQGroupService kqGroupService,Integer attendCycleType) {
// 调薪计薪规则
Map<Long, SalarySobAdjustRulePO> salarySobAdjustRulePOMap = SalaryEntityUtil.convert2Map(salaryAcctCalculateBO.getSalarySobAdjustRulePOS(),
SalarySobAdjustRulePO::getSalaryItemId);
boolean isSeasonSob = false;
if (attendCycleType != null && (attendCycleType.equals(SalaryCycleTypeEnum.THIS_SEASON.getValue()) || attendCycleType.equals(SalaryCycleTypeEnum.LAST_SEASON.getValue()) )) {
// 联特 是季度账套
isSeasonSob = true;
}
for (SalaryArchiveDataDTO salaryArchiveDataDTO : salaryArchiveData) {
for (SalaryArchiveTaxAgentDataDTO salaryArchiveTaxAgentDataDTO : salaryArchiveDataDTO.getTaxAgents()) {
String key = salaryArchiveDataDTO.getEmployeeId() + "_" + salaryArchiveTaxAgentDataDTO.getTaxAgentId();
List<FormulaVarValue> formulaVarValues = resultMap.computeIfAbsent(key, k -> Lists.newArrayList());
// 将薪资档案的值转换成公式中的变量,填充到返回结果集中
formulaVarValues.addAll(handleSalaryArchiveItemVal(salaryAcctCalculateBO, salaryArchiveTaxAgentDataDTO.getSalaryItemValues(), salarySobAdjustRulePOMap, kqGroupService, salaryArchiveDataDTO.getEmployeeId(), isSeasonSob));
}
}
}
private void handleVariableArchiveData(SalaryAcctCalculateBO salaryAcctCalculateBO, Map<String, List<FormulaVarValue>> resultMap) {
Map<String, Map<String, Object>> variableArchiveMap = SalaryEntityUtil.convert2Map(variableArchiveList, map -> map.getOrDefault("taxAgentIds", "").toString() + "-" + map.getOrDefault("employeeId", "").toString());
// 填充到返回结果集中
for (SalaryAcctEmployeePO salaryAcctEmployeePO : salaryAcctCalculateBO.getSalaryAcctEmployeePOS()) {
List<FormulaVarValue> formulaVarValues = resultMap.computeIfAbsent(salaryAcctEmployeePO.getEmployeeId() + "_" + salaryAcctEmployeePO.getTaxAgentId(),
k -> Lists.newArrayList());
String key = salaryAcctEmployeePO.getTaxAgentId().toString() + "-" + salaryAcctEmployeePO.getEmployeeId().toString();
Map<String, Object> map = variableArchiveMap.getOrDefault(key, Collections.emptyMap());
formulaVarValues.addAll(salaryAcctCalculateBO.getVariableItems().stream().map(field -> {
String fieldId = SalaryFormulaReferenceEnum.VARIABLE_ITEM.getValue()
+ SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR
+ field.getCode();
String value = map.getOrDefault(field.getId() + SalaryItemConstant.VARIABLE_ITEM_DYNAMIC_SUFFIX, StringUtils.EMPTY) == null ? StringUtils.EMPTY
: map.getOrDefault(field.getId() + SalaryItemConstant.VARIABLE_ITEM_DYNAMIC_SUFFIX, StringUtils.EMPTY).toString();
return new FormulaVarValue().setFieldId(fieldId).setFieldValue(value);
}).collect(Collectors.toList()));
}
}
/**
* 根据调薪计薪规则处理薪资档案的调薪,转换成公式编辑器中的变量
*
* @param salaryAcctCalculateBO
* @param salaryArchiveItemDataList
* @param salarySobAdjustRulePOMap
* @return
*/
private List<FormulaVarValue> handleSalaryArchiveItemVal(SalaryAcctCalculateBO salaryAcctCalculateBO,
List<SalaryArchiveItemDataDTO> salaryArchiveItemDataList,
Map<Long, SalarySobAdjustRulePO> salarySobAdjustRulePOMap,
KQGroupService kqGroupService,
Long employeeId,
boolean isSeasonSob) {
// 薪资周期
LocalDateRange salaryCycle = salaryAcctCalculateBO.getSalarySobCycleDTO().getSalaryCycle();
// key:薪资项目的id、value:薪资项目的code
Map<Long, String> salaryItemCodeMap = SalaryEntityUtil.convert2Map(salaryAcctCalculateBO.getSalaryItemPOS(), SalaryItemPO::getId, SalaryItemPO::getCode);
// 将薪资档案的调薪记录按照薪资项目id聚合(同一个薪资项目可能存在多次调薪,按照生效日期对调薪记录排序)
Map<Long, List<SalaryArchiveItemDataDTO>> dataMap = salaryArchiveItemDataList.stream()
.collect(Collectors.groupingBy(SalaryArchiveItemDataDTO::getSalaryItemId,
Collectors.collectingAndThen(Collectors.toList(), salaryArchiveItemDataDTOS -> salaryArchiveItemDataDTOS.stream()
.sorted(Comparator.comparing(salaryArchiveItemDataDTO -> salaryArchiveItemDataDTO.getEffectiveDateRange().getFromDate()))
.collect(Collectors.toList()))));
// 将薪资档案的值转换成公式编辑器中的变量
List<FormulaVarValue> formulaVarValues = Lists.newArrayListWithExpectedSize(dataMap.size());
for (Map.Entry<Long, List<SalaryArchiveItemDataDTO>> entry : dataMap.entrySet()) {
String value;
// 获取薪资项目的调薪规则
SalarySobAdjustRulePO salaryAdjustmentRulePO = salarySobAdjustRulePOMap.get(entry.getKey());
List<SalaryArchiveItemDataDTO> valueList = entry.getValue();
if (CollectionUtils.isNotEmpty(valueList)) {
String firstDateStr = SalaryDateUtil.getFormatLocalDate(valueList.get(0).getEffectiveDateRange().getFromDate());
String salaryCycleFirstStr = SalaryDateUtil.getFormatLocalDate(salaryCycle.getFromDate());
if (isSeasonSob) {
salaryCycleFirstStr = SalaryDateUtil.getFormatLocalDate(salaryAcctCalculateBO.getSalarySobCycleDTO().getAttendCycleFromDate());
}
if (!firstDateStr.equals(salaryCycleFirstStr)) {
LocalDateRange dateRange = LocalDateRange.builder()
.fromDate(isSeasonSob ? salaryAcctCalculateBO.getSalarySobCycleDTO().getAttendCycleFromDate() : salaryCycle.getFromDate())
.endDate(valueList.get(0).getEffectiveDateRange().getFromDate()).build();
SalaryArchiveItemDataDTO zeroDTO = SalaryArchiveItemDataDTO.builder().effectiveDateRange(dateRange).salaryItemId(valueList.get(0).getSalaryItemId()).value("0").build();
valueList.add(0, zeroDTO);
}
}
if (entry.getValue().size() > 2) {
// 如果薪资项目在薪资周期内经历了多次调薪,则默认分段计薪
value = calculateBySalarySobAdjustRule(salaryCycle, SalarySobAdjustRuleTypeEnum.PARTITION, entry.getValue(), kqGroupService, employeeId, isSeasonSob);
} else if (salaryAdjustmentRulePO == null || entry.getValue().size() < 2) {
// 如果薪资项目没有设置调薪计薪规则,默认取薪资周期内薪资档案中最新的值
// 如果薪资项目在薪资周期内没有调薪,默认取薪资周期内薪资档案中最新的值
value = calculateBySalarySobAdjustRule(salaryCycle, SalarySobAdjustRuleTypeEnum.USE_AFTER_ADJUSTMENT, entry.getValue(), kqGroupService, employeeId, isSeasonSob);
} else {
// 如果薪资项目在薪资周期内只有一次调薪,则根据调薪计薪规则处理
SalarySobAdjustRuleTypeEnum adjustRuleTypeEnum = salaryAdjustmentRulePO.getDayOfMonth() < SalaryDateUtil.dateToLocalDate(entry.getValue().get(0).getEffectiveDateRange().getEndDate()).getDayOfMonth()
? SalarySobAdjustRuleTypeEnum.parseByValue(salaryAdjustmentRulePO.getAfterAdjustmentType())
: SalarySobAdjustRuleTypeEnum.parseByValue(salaryAdjustmentRulePO.getBeforeAdjustmentType());
// 根据调薪计薪规则处理薪资档案的调薪
value = calculateBySalarySobAdjustRule(salaryCycle, adjustRuleTypeEnum, entry.getValue(), kqGroupService, employeeId, isSeasonSob);
}
String fieldId = SalaryFormulaReferenceEnum.SALARY_ARCHIVES.getValue()
+ SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR
+ salaryItemCodeMap.getOrDefault(entry.getKey(), StringUtils.EMPTY);
formulaVarValues.add(new FormulaVarValue().setFieldId(fieldId).setFieldValue(value));
}
return formulaVarValues;
}
/**
* 根据调薪计薪规则计算调薪后的值
*
* @param adjustRuleTypeEnum
* @param salaryArchiveItemDataDTOS
* @return
*/
private String calculateBySalarySobAdjustRule(LocalDateRange salaryCycle,
SalarySobAdjustRuleTypeEnum adjustRuleTypeEnum,
List<SalaryArchiveItemDataDTO> salaryArchiveItemDataDTOS,
KQGroupService kqGroupService,
Long employeeId,
boolean isSeasonSob) {
if (Objects.isNull(adjustRuleTypeEnum)) {
return StringUtils.EMPTY;
}
String value;
switch (adjustRuleTypeEnum) {
case AVERAGE:
// 可能存在多次调薪
// = (第一段的值+第二段的值+……)/n
value = String.valueOf(salaryArchiveItemDataDTOS.stream()
.mapToDouble(salaryArchiveItemDataDTO -> SalaryEntityUtil.empty2Zero(salaryArchiveItemDataDTO.getValue()).doubleValue())
.average().orElse(NumberUtils.DOUBLE_ZERO));
break;
case PARTITION:
// 可能存在多次调薪
// = (第一段的值*第一段的自然日+第二段的值*第二段的自然日+……)/薪资所属月自然日
// BigDecimal valueSum = BigDecimal.ZERO;
BigDecimal firstValue = BigDecimal.ZERO;
BigDecimal baseValue = new BigDecimal("21.75");
if (isSeasonSob) {
baseValue = baseValue.multiply(new BigDecimal(3));
}
// 调薪补差金额
BigDecimal needAddValue = new BigDecimal(0);
if (CollectionUtils.isNotEmpty(salaryArchiveItemDataDTOS)) {
firstValue = SalaryEntityUtil.empty2Zero(salaryArchiveItemDataDTOS.get(0).getValue());
}
BaseBean baseBean = new BaseBean();
baseBean.writeLog("ltsize"+salaryArchiveItemDataDTOS.size());
for (int i = 1; i < salaryArchiveItemDataDTOS.size(); i++) {
// 联特二开:调薪前工资+(调薪后工资-调薪前工资)/21.75*(调薪后的应出勤天数+调薪后的法定节假日天数)
SalaryArchiveItemDataDTO dataDTO = salaryArchiveItemDataDTOS.get(i);
// 获取应出勤日期+法定节假日
Double ycq = new Double(0);
String fdjjr = "0";
if (Objects.equals(i, salaryArchiveItemDataDTOS.size() - 1)) {
ycq = getKQYcq(dataDTO.getEffectiveDateRange().getFromDate(), dataDTO.getEffectiveDateRange().getEndDate(), employeeId);
fdjjr = getFdjjr(SalaryDateUtil.getFormatDate(dataDTO.getEffectiveDateRange().getFromDate()), SalaryDateUtil.getFormatDate(dataDTO.getEffectiveDateRange().getEndDate()), employeeId.toString(), kqGroupService);
} else {
// 不是最后一个需要往前挪1天
Date endDate = SalaryDateUtil.localDateToDate(SalaryDateUtil.dateToLocalDate(dataDTO.getEffectiveDateRange().getEndDate()).minusDays(1));
ycq = getKQYcq(dataDTO.getEffectiveDateRange().getFromDate(), endDate, employeeId);
fdjjr = getFdjjr(SalaryDateUtil.getFormatDate(dataDTO.getEffectiveDateRange().getFromDate()), SalaryDateUtil.getFormatDate(endDate), employeeId.toString(), kqGroupService);
}
baseBean.writeLog("lt-ycq" +ycq);
double days = ycq + (NumberUtils.isCreatable(fdjjr) ? Double.valueOf(fdjjr) : 0);
needAddValue = needAddValue.add(SalaryEntityUtil.empty2Zero(dataDTO.getValue()).subtract(firstValue).divide(baseValue, 15, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(days)));
//
// BigDecimal dayDiff = new BigDecimal(SalaryDateUtil.dateToLocalDate(dataDTO.getEffectiveDateRange().getFromDate()).until(SalaryDateUtil.dateToLocalDate(dataDTO.getEffectiveDateRange().getEndDate()), ChronoUnit.DAYS));
// // 最后一段日期范围需要加一
// if (Objects.equals(i, salaryArchiveItemDataDTOS.size() - 1)) {
// dayDiff = dayDiff.add(BigDecimal.ONE);
// }
// valueSum = valueSum.add(SalaryEntityUtil.empty2Zero(dataDTO.getValue()).multiply(dayDiff));
}
// value = valueSum.divide(new BigDecimal(SalaryDateUtil.dateToLocalDate(salaryCycle.getFromDate()).until(SalaryDateUtil.dateToLocalDate(salaryCycle.getEndDate()), ChronoUnit.DAYS)).add(BigDecimal.ONE), 2, RoundingMode.HALF_UP).toPlainString();
baseBean.writeLog("lt-ycq" +needAddValue);
value = firstValue.add(needAddValue).toPlainString();
break;
case USE_BEFORE_ADJUSTMENT:
// = 调薪前工资
value = salaryArchiveItemDataDTOS.get(0).getValue();
break;
case USE_AFTER_ADJUSTMENT:
// = 调薪后工资
value = salaryArchiveItemDataDTOS.get(salaryArchiveItemDataDTOS.size() - 1).getValue();
break;
default:
value = "0";
break;
}
return value;
}
private SQLMapper getSQLMapper() {
return MapperProxyFactory.getProxy(SQLMapper.class);
}
/**
* 获取应出勤时数
* @param fromDate
* @param endDate
* @param userId
*/
private Double getKQYcq(Date fromDate, Date endDate, Long userId) {
BaseBean baseBean = new BaseBean();
double ycq = 0.00;
try {
String sql = "SELECT sum(workdays) as a,sum(attendancemins) FROM kq_format_total WHERE workdays is not null and resourceid = "+userId+" and kqdate >= '" +SalaryDateUtil.getFormatDate(fromDate)+"' and kqdate <= '"+ SalaryDateUtil.getFormatDate(endDate)+"'";
baseBean.writeLog("lt-1" + sql);
List<Map> list = getSQLMapper().runSQL(sql);
baseBean.writeLog("lt-list" +list);
if (CollectionUtils.isNotEmpty(list) && list.get(0) != null) {
Object value = list.get(0).get("a");
if (value != null) {
baseBean.writeLog("lt-value" +value);
ycq = NumberUtils.isCreatable(value.toString()) ? Double.valueOf(value.toString()) : Double.valueOf("0");
}
}
} catch (Exception e) {
baseBean.writeLog("获取应出勤时数出错" + e.getMessage());
return 0.00;
}
return ycq;
}
/**
* 获取法定节假日天数
*/
public String getFdjjr(String fromDate, String toDate, String userId, KQGroupService kqGroupService) {
BaseBean baseBean = new BaseBean();
if (StringUtils.isEmpty(userId) || StringUtils.isEmpty(fromDate) || StringUtils.isEmpty(toDate)) {
baseBean.writeLog("userId or fromDate or toDate is null!" + fromDate + toDate + userId);
return "0";
}
try {
Map<String, Object> params = new HashMap<>();
params.put("viewScope", 3);
params.put("resourceId", userId);
params.put("groupType", 0);
params.put("pageSize", 10);
params.put("pageIndex", 1);
User tmpUser = new User();
tmpUser.setUid(1);
tmpUser.setLoginid("sysadmin");
//获取当前人员的生效考勤组
String activeGroupId = null;
List<Map<String, Object>> dataSource = null;
Map<String, Object> groupInfo = kqGroupService.getGroupMemberList(params, tmpUser);
if (groupInfo != null && groupInfo.size() > 0) {
if (groupInfo.get("dataSource") != null) {
dataSource = (List<Map<String, Object>>) groupInfo.get("dataSource");
if (dataSource != null && dataSource.size() > 0) {
Map<String, Object> dataMap = dataSource.get(0);
activeGroupId = dataMap.get("activeGroupId") + "";
}
}
}
if (activeGroupId == null && activeGroupId.length() > 0) {
baseBean.writeLog("activeGroupId is null:" + params + dataSource);
return "0";
}
// 计算公共假期
RecordSet rs = new RecordSet();
String sql ="select count(1) from kq_HolidaySet where changeType =1 and holidayDate>= '"+ fromDate + "' and holidayDate<= '"+toDate+"' and groupId = "+ activeGroupId;
rs.execute(sql);
int jq =0;
if(rs.next()){
jq = rs.getInt(1);
}
if(jq == -1) {
jq = 0;
}
return String.valueOf(jq);
} catch (Exception e) {
baseBean.writeLog("获取法定节假日天数错误"+e.getMessage());
return "0";
}
}
/**
* 处理累计情况(工资、薪金)
*
* @param resultMap 返回结果集
*/
private void handleAddUpSituation(Map<String, List<FormulaVarValue>> resultMap) {
// key:employeeId_taxAgentId、value:累计情况(工资、薪金)的数据
Map<String, AddUpSituation> addUpSituationPOMap = SalaryEntityUtil.convert2Map(addUpSituationPOS,
addUpSituationPO -> addUpSituationPO.getEmployeeId() + "_" + addUpSituationPO.getTaxAgentId());
// 累计情况(工资、薪金)可选字段
List<String> fieldNames = Lists.newArrayList();
Field[] declaredFields = AddUpSituation.class.getDeclaredFields();
for (Field declaredField : declaredFields) {
if (declaredField.isAnnotationPresent(SalaryFormulaVar.class)) {
fieldNames.add(declaredField.getName());
}
}
// 填充到返回结果集中
addUpSituationPOMap.forEach((key, addUpSituationPO) -> {
List<FormulaVarValue> formulaVarValues = resultMap.computeIfAbsent(key, k -> Lists.newArrayList());
Map<String, String> map = JsonUtil.parseMap(addUpSituationPO, String.class);
formulaVarValues.addAll(fieldNames.stream().map(fieldName -> {
String fieldId = SalaryFormulaReferenceEnum.ADD_UP_SITUATION.getValue()
+ SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR
+ fieldName;
return new FormulaVarValue().setFieldId(fieldId).setFieldValue(map.getOrDefault(fieldName, StringUtils.EMPTY));
}).collect(Collectors.toList()));
});
}
/**
* 处理累计专项附加扣除
*
* @param resultMap 返回结果集
*/
private void handleAddUpDeduction(Map<String, List<FormulaVarValue>> resultMap) {
// key:employeeId_taxAgentId、value:累计专项附加扣除的数据
Map<String, AddUpDeduction> addUpDeductionPOMap = SalaryEntityUtil.convert2Map(addUpDeductionPOS,
addUpDeductionPO -> addUpDeductionPO.getEmployeeId() + "_" + addUpDeductionPO.getTaxAgentId());
// 累计专项附加扣除可选字段
List<String> fieldNames = Lists.newArrayList();
Field[] declaredFields = AddUpDeduction.class.getDeclaredFields();
for (Field declaredField : declaredFields) {
if (declaredField.isAnnotationPresent(SalaryFormulaVar.class)) {
fieldNames.add(declaredField.getName());
}
}
// 填充到返回结果集中
addUpDeductionPOMap.forEach((key, addUpDeductionPO) -> {
List<FormulaVarValue> formulaVarValues = resultMap.computeIfAbsent(key, k -> Lists.newArrayList());
Map<String, String> map = JsonUtil.parseMap(addUpDeductionPO, String.class);
formulaVarValues.addAll(fieldNames.stream().map(fieldName -> {
String fieldId = SalaryFormulaReferenceEnum.ADD_UP_DEDUCTIONS.getValue()
+ SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR
+ fieldName;
return new FormulaVarValue().setFieldId(fieldId).setFieldValue(map.getOrDefault(fieldName, StringUtils.EMPTY));
}).collect(Collectors.toList()));
});
}
/**
* 处理其他扣除
*
* @param resultMap 返回结果集
*/
private void handleOtherDeduction(Map<String, List<FormulaVarValue>> resultMap) {
// key:employeeId_taxAgentId、value:累计专项附加扣除的数据
Map<String, OtherDeductionPO> otherDeductionPOMap = SalaryEntityUtil.convert2Map(otherDeductionPOS,
otherDeductionPO -> otherDeductionPO.getEmployeeId() + "_" + otherDeductionPO.getTaxAgentId());
// 累计专项附加扣除可选字段
List<String> fieldNames = Lists.newArrayList();
Field[] declaredFields = OtherDeductionPO.class.getDeclaredFields();
for (Field declaredField : declaredFields) {
if (declaredField.isAnnotationPresent(SalaryFormulaVar.class)) {
fieldNames.add(declaredField.getName());
}
}
// 填充到返回结果集中
otherDeductionPOMap.forEach((key, otherDeductionPO) -> {
List<FormulaVarValue> formulaVarValues = resultMap.computeIfAbsent(key, k -> Lists.newArrayList());
Map<String, String> map = JsonUtil.parseMap(otherDeductionPO, String.class);
formulaVarValues.addAll(fieldNames.stream().map(fieldName -> {
String fieldId = SalaryFormulaReferenceEnum.OTHER_DEDUCTION.getValue()
+ SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR
+ fieldName;
return new FormulaVarValue().setFieldId(fieldId).setFieldValue(map.getOrDefault(fieldName, StringUtils.EMPTY));
}).collect(Collectors.toList()));
});
}
/**
* 处理社保福利数据
*
* @param resultMap 返回结果集
*/
private void handleWelfareData(SalaryAcctCalculateBO salaryAcctCalculateBO, Map<String, List<FormulaVarValue>> resultMap) {
// 社保福利可选字段
List<String> fieldNames = Lists.newArrayList(salaryAcctCalculateBO.getWelfareColumns().values());
// 社保福利数据
Map<String, List<FormulaVarValue>> tempMap = new HashMap<>();
welfareData.forEach(map -> {
String key = map.getOrDefault("employeeId", StringUtils.EMPTY) + "_" + map.getOrDefault("taxAgentId", StringUtils.EMPTY);
List<FormulaVarValue> formulaVarValues = tempMap.computeIfAbsent(key, k -> Lists.newArrayList());
formulaVarValues.addAll(fieldNames.stream().map(fieldName -> {
String fieldId = SalaryFormulaReferenceEnum.WELFARE.getValue()
+ SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR
+ fieldName;
return new FormulaVarValue().setFieldId(fieldId).setFieldValue(String.valueOf(map.getOrDefault(fieldName, StringUtils.EMPTY)));
}).collect(Collectors.toList()));
});
// 填充到返回结果集中
for (SalaryAcctEmployeePO salaryAcctEmployeePO : salaryAcctCalculateBO.getSalaryAcctEmployeePOS()) {
List<FormulaVarValue> formulaVarValues = resultMap.computeIfAbsent(salaryAcctEmployeePO.getEmployeeId() + "_" + salaryAcctEmployeePO.getTaxAgentId(),
k -> Lists.newArrayList());
formulaVarValues.addAll(tempMap.getOrDefault(salaryAcctEmployeePO.getEmployeeId() + "_" + salaryAcctEmployeePO.getTaxAgentId(), Collections.emptyList()));
}
}
/**
* 处理考勤引用数据
*
* @param salaryAcctCalculateBO
* @param resultMap
*/
private void handleAttendQuoteData(SalaryAcctCalculateBO salaryAcctCalculateBO, Map<String, List<FormulaVarValue>> resultMap) {
// 考勤引用可选字段
Set<Long> fieldNames = SalaryEntityUtil.properties(salaryAcctCalculateBO.getAttendQuoteFieldListDTOS(), AttendQuoteFieldListDTO::getId);
// 考勤引用数据
Map<Long, List<FormulaVarValue>> tempMap = Maps.newHashMapWithExpectedSize(attendQuoteDataDTOS.size());
attendQuoteDataDTOS.forEach(attendQuoteDataDTO -> {
Map<Long, String> attendQuoteDataValueMap = SalaryEntityUtil.convert2Map(attendQuoteDataDTO.getDataValues(), AttendQuoteDataValueDTO::getAttendQuoteFieldId, AttendQuoteDataValueDTO::getDataValue);
Long key = attendQuoteDataDTO.getEmployeeId();
List<FormulaVarValue> formulaVarValues = tempMap.computeIfAbsent(key, k -> Lists.newArrayList());
formulaVarValues.addAll(fieldNames.stream().map(fieldName -> {
String fieldId = SalaryFormulaReferenceEnum.ATTEND.getValue()
+ SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR
+ fieldName;
return new FormulaVarValue().setFieldId(fieldId).setFieldValue(attendQuoteDataValueMap.getOrDefault(fieldName, StringUtils.EMPTY));
}).collect(Collectors.toList()));
});
// 填充到返回结果集中
for (SalaryAcctEmployeePO salaryAcctEmployeePO : salaryAcctCalculateBO.getSalaryAcctEmployeePOS()) {
List<FormulaVarValue> formulaVarValues = resultMap.computeIfAbsent(salaryAcctEmployeePO.getEmployeeId() + "_" + salaryAcctEmployeePO.getTaxAgentId(),
k -> Lists.newArrayList());
formulaVarValues.addAll(tempMap.getOrDefault(salaryAcctEmployeePO.getEmployeeId(), Collections.emptyList()));
}
}
/**
* 处理核算人员信息
*
* @param salaryAcctCalculateBO
* @param resultMap
*/
private void handleSalaryAcctEmployee(SalaryAcctCalculateBO salaryAcctCalculateBO, Map<String, List<FormulaVarValue>> resultMap) {
List<SalaryAcctEmployeePO> salaryAcctEmployeePOS = salaryAcctCalculateBO.getSalaryAcctEmployeePOS();
// key:employeeId_taxAgentId、value:核算人员信息
Map<String, SalaryAcctEmployeePO> salaryAcctEmployeeMap = SalaryEntityUtil.convert2Map(salaryAcctEmployeePOS,
po -> po.getEmployeeId() + "_" + po.getTaxAgentId());
// 核算人员信息可选字段
List<String> fieldNames = Lists.newArrayList();
Field[] declaredFields = SalaryAcctEmployeePO.class.getDeclaredFields();
for (Field declaredField : declaredFields) {
if (declaredField.isAnnotationPresent(SalaryFormulaVar.class)) {
fieldNames.add(declaredField.getName());
}
}
// 填充到返回结果集中
salaryAcctEmployeeMap.forEach((key, po) -> {
List<FormulaVarValue> formulaVarValues = resultMap.computeIfAbsent(key, k -> Lists.newArrayList());
Map<String, String> map = JsonUtil.parseMap(po, String.class);
formulaVarValues.addAll(fieldNames.stream().map(fieldName -> {
String fieldId = SalarySQLReferenceEnum.SALARY_ACCT_EMPLOYEE.getValue()
+ SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR
+ fieldName;
String fieldValue = map.getOrDefault(fieldName, StringUtils.EMPTY);
//判断是否是日期日期值取yyyy-MM-dd
if (StringUtils.isNotBlank(fieldValue) && fieldValue.length() > 10 && SalaryDateUtil.parse(fieldValue, DATE_TIME_FORMATTER_PATTERN) != null) {
fieldValue = fieldValue.substring(0, 10);
}
return new FormulaVarValue().setFieldId(fieldId).setFieldValue(fieldValue);
}).collect(Collectors.toList()));
//将薪资周期转换成公式中的变量,填充到返回结果集中
formulaVarValues.addAll(handleSalarySobCycleDTO(salaryAcctCalculateBO));
});
}
/**
* 处理员工基本信息
*
* @param resultMap
*/
private void handleSimpleEmployees(Map<String, List<FormulaVarValue>> resultMap) {
// key:employeeId_taxAgentId、value:员工信息
Map<String, DataCollectionEmployee> employeeMap = SalaryEntityUtil.convert2Map(simpleEmployees,
po -> po.getEmployeeId() + "");
// 核算人员信息可选字段
List<String> fieldNames = Lists.newArrayList();
Field[] declaredFields = DataCollectionEmployee.class.getDeclaredFields();
for (Field declaredField : declaredFields) {
if (declaredField.isAnnotationPresent(SalaryFormulaVar.class)) {
fieldNames.add(declaredField.getName());
}
}
// 填充到返回结果集中
employeeMap.forEach((key, po) -> {
// 获取po的状态
if (po.getStatus() != null && NumberUtil.isNumber(po.getStatus())) {
po.setStatusName(UserStatusEnum.getDefaultLabelByValue(new Integer(Util.null2s(po.getStatus(), "1"))));
}
List<FormulaVarValue> formulaVarValues = resultMap.computeIfAbsent(key, k -> Lists.newArrayList());
Map<String, String> map = JsonUtil.parseMap(po, String.class);
formulaVarValues.addAll(fieldNames.stream().map(fieldName -> {
String fieldId = SalarySQLReferenceEnum.EMPLOYEE_INFO.getValue()
+ SalaryFormulaFieldConstant.FIELD_ID_SEPARATOR
+ fieldName;
return new FormulaVarValue().setFieldId(fieldId).setFieldValue(map.getOrDefault(fieldName, StringUtils.EMPTY));
}).collect(Collectors.toList()));
});
}
@Data
@Accessors(chain = true)
public static class FormulaVarValue {
/**
* 公式变量id
*/
private String fieldId;
/**
* 公式变量的值
*/
private String fieldValue;
}
}