package com.engine.salary.entity.salaryacct.bo; import com.cloudstore.eccom.pc.table.WeaTableColumn; import com.engine.salary.annotation.SalaryFormulaVar; import com.engine.salary.constant.SalaryDefaultTenantConstant; import com.engine.salary.entity.datacollection.DataCollectionEmployee; import com.engine.salary.entity.salaryacct.dto.ConsolidatedTaxDetailDTO; import com.engine.salary.entity.salaryacct.dto.SalaryAcctEmployeeInfoDTO; import com.engine.salary.entity.salaryacct.dto.SalaryAcctResultDetailDTO; import com.engine.salary.entity.salaryacct.param.SalaryAcctResultSaveParam; import com.engine.salary.entity.salaryacct.po.*; import com.engine.salary.entity.salaryformula.dto.SalaryFormulaEmployeeDTO; import com.engine.salary.entity.salaryitem.po.SalaryItemPO; import com.engine.salary.entity.salarysob.dto.SalarySobEmpFieldDTO; import com.engine.salary.entity.salarysob.dto.SalarySobItemAggregateDTO; import com.engine.salary.entity.salarysob.dto.SalarySobItemDTO; import com.engine.salary.entity.salarysob.dto.SalarySobItemGroupDTO; import com.engine.salary.entity.salarysob.po.SalarySobEmpFieldPO; import com.engine.salary.entity.salarysob.po.SalarySobItemPO; import com.engine.salary.entity.salarysob.po.SalarySobPO; import com.engine.salary.entity.taxrate.TaxAgent; import com.engine.salary.enums.salaryitem.SalaryDataTypeEnum; import com.engine.salary.util.SalaryEntityUtil; import com.engine.salary.util.SalaryI18nUtil; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import org.springframework.beans.BeanUtils; import java.lang.reflect.Field; import java.util.*; import java.util.stream.Collectors; /** * @description: 薪资核算结果 * @author: xiajun * @modified By: xiajun * @date: Created in 12/6/21 7:05 PM * @version:v1.0 */ public class SalaryAcctResultBO { /** * 数据类型的后悔标识 * 为了展示千分位,薪资核算结果列表、线上线下对比结果列表需要返回给前端列表字段的数据类型,字段索引+后缀标识 */ private static final String DATA_TYPE_SUFFIX = "_type"; /** * 构建薪资核算结果列表的表头 * * @param salarySobItemAggregateDTO * @return */ public static List buildTableColumns4ComparisonResult(SalarySobItemAggregateDTO salarySobItemAggregateDTO, Set excludeSalaryItemIds) { List columns = Lists.newArrayList(); // 员工信息字段 for (SalarySobEmpFieldDTO salarySobEmpFieldDTO : salarySobItemAggregateDTO.getEmpFields()) { columns.add(new WeaTableColumn("150", salarySobEmpFieldDTO.getFieldName(), salarySobEmpFieldDTO.getFieldId())); } // 薪资项目分组下的薪资项目 for (SalarySobItemGroupDTO salarySobItemGroupDTO : salarySobItemAggregateDTO.getItemGroups()) { if (CollectionUtils.isEmpty(salarySobItemGroupDTO.getItems())) { continue; } for (SalarySobItemDTO salarySobItemDTO : salarySobItemGroupDTO.getItems()) { if (excludeSalaryItemIds.contains(salarySobItemDTO.getSalaryItemId())) { continue; } columns.add(new WeaTableColumn("150", salarySobItemDTO.getName(), "" + salarySobItemDTO.getSalaryItemId())); } } // 没有分类的薪资项目 for (SalarySobItemDTO salarySobItemDTO : salarySobItemAggregateDTO.getItems()) { if (excludeSalaryItemIds.contains(salarySobItemDTO.getSalaryItemId())) { continue; } columns.add(new WeaTableColumn("150", salarySobItemDTO.getName(), "" + salarySobItemDTO.getSalaryItemId())); } return columns; } /** * 构建薪资核算结果列表的表头 * * @param salarySobItemAggregateDTO * @return */ public static List buildTableColumns(SalarySobItemAggregateDTO salarySobItemAggregateDTO) { List columns = Lists.newArrayList(); // 员工信息字段 for (SalarySobEmpFieldDTO salarySobEmpFieldDTO : salarySobItemAggregateDTO.getEmpFields()) { columns.add(new WeaTableColumn("150", salarySobEmpFieldDTO.getFieldName(), salarySobEmpFieldDTO.getFieldId())); } // 薪资项目分组下的薪资项目 for (SalarySobItemGroupDTO salarySobItemGroupDTO : salarySobItemAggregateDTO.getItemGroups()) { if (CollectionUtils.isEmpty(salarySobItemGroupDTO.getItems())) { continue; } // Map group = Maps.newHashMap(); // group.put("groupName", salarySobItemGroupDTO.getName()); // group.put("groupId", String.valueOf(salarySobItemGroupDTO.getId())); List childrenColumns = Lists.newArrayList(); for (SalarySobItemDTO salarySobItemDTO : salarySobItemGroupDTO.getItems()) { columns.add(new WeaTableColumn("150", salarySobItemDTO.getName(), "" + salarySobItemDTO.getSalaryItemId())); // childrenColumns.add(new WeaTableColumn("150", salarySobItemDTO.getName(), "" + salarySobItemDTO.getSalaryItemId())); } // group.put("list", childrenColumns); } // 没有分类的薪资项目 for (SalarySobItemDTO salarySobItemDTO : salarySobItemAggregateDTO.getItems()) { columns.add(new WeaTableColumn("150", salarySobItemDTO.getName(), "" + salarySobItemDTO.getSalaryItemId())); } return columns; } /** * 转船成薪资核算结果列表的表格数据 * * @param salaryItems * @param salarySobEmpFields * @param simpleEmployees * @param salaryAcctEmployees * @param salaryAccountingResults * @param taxAgents * @param consolidatedTaxSalaryAcctEmpIds * @return */ public static List> buildTableData(List salaryItems, List salarySobEmpFields, List simpleEmployees, List salaryAcctEmployees, List salaryAccountingResults, List taxAgents, Set consolidatedTaxSalaryAcctEmpIds, Map customParameters) { if (CollectionUtils.isEmpty(salaryAcctEmployees)) { return Collections.emptyList(); } Map employeeMap = SalaryEntityUtil.convert2Map(simpleEmployees, DataCollectionEmployee::getEmployeeId); Map> acctResultMap = SalaryEntityUtil.group2Map(salaryAccountingResults, SalaryAcctResultPO::getEmployeeId); Map taxAgentNameMap = SalaryEntityUtil.convert2Map(taxAgents, TaxAgent::getId, TaxAgent::getName); return salaryAcctEmployees.stream().map(e -> { Map resultValueMap = SalaryEntityUtil.convert2Map(acctResultMap.getOrDefault(e.getEmployeeId(), Collections.emptyList()), SalaryAcctResultPO::getSalaryItemId, SalaryAcctResultPO::getResultValue); // 薪资项目的值 Map map = SalaryEntityUtil.convert2Map(salaryItems, o -> "" + o.getId(), o -> resultValueMap.getOrDefault(o.getId(), StringUtils.EMPTY)); // 薪资项目的字段类型(前端依据这个判断是否需要展示千分位) Map dataTypeMap = SalaryEntityUtil.convert2Map(salaryItems, salaryItemPO -> salaryItemPO.getId() + DATA_TYPE_SUFFIX, SalaryItemPO::getDataType); map.putAll(dataTypeMap); // 人员信息字段的值 Map fieldValueMap = SalaryAcctFormulaBO.convert2FormulaEmployee(employeeMap.get(e.getEmployeeId())); for (SalarySobEmpFieldPO salarySobEmpField : salarySobEmpFields) { map.put(salarySobEmpField.getFieldCode(), fieldValueMap.get(salarySobEmpField.getFieldCode())); // 员工信息字段的字段类型 map.put(salarySobEmpField.getFieldCode() + DATA_TYPE_SUFFIX, SalaryDataTypeEnum.STRING.getValue()); } // 主键id map.put("id", e.getId()); // 个税扣缴义务人 String taxAgentName = taxAgentNameMap.getOrDefault(e.getTaxAgentId(), StringUtils.EMPTY); map.put("taxAgentName", taxAgentName); // 是否属于"合并计税"的标记 map.put("consolidatedTaxation", StringUtils.isNotEmpty(taxAgentName) && consolidatedTaxSalaryAcctEmpIds.contains(e.getId())); // 个税扣缴义务人的字段类型 map.put("taxAgentName" + DATA_TYPE_SUFFIX, SalaryDataTypeEnum.STRING.getValue()); // 公式详情 map.put("customParameters", customParameters); return map; }).collect(Collectors.toList()); } /** * 转转成薪资核算线下对比结果 * * @param salaryItems * @param salarySobEmpFields * @param simpleEmployees * @param salaryAcctEmployees * @param salaryAcctResultPOS * @param excelAcctResultPOS * @param taxAgents * @param consolidatedTaxSalaryAcctEmpIds * @return */ public static List> buildComparisonTableData(List salaryItems, List salarySobEmpFields, List simpleEmployees, List salaryAcctEmployees, List salaryAcctResultPOS, List excelAcctResultPOS, List taxAgents, Map customParameters, Set consolidatedTaxSalaryAcctEmpIds, Set includeSalaryItemIds) { if (CollectionUtils.isEmpty(simpleEmployees)) { return Collections.emptyList(); } Map> excelResultMap = SalaryEntityUtil.group2Map(excelAcctResultPOS, ExcelAcctResultPO::getSalaryAcctEmpId); Map> acctResultMap = SalaryEntityUtil.group2Map(salaryAcctResultPOS, SalaryAcctResultPO::getSalaryAcctEmpId); Map taxAgentNameMap = SalaryEntityUtil.convert2Map(taxAgents, TaxAgent::getId, TaxAgent::getName); Map employeeMap = SalaryEntityUtil.convert2Map(simpleEmployees, DataCollectionEmployee::getEmployeeId); List> resultList = Lists.newArrayListWithExpectedSize(salaryAcctEmployees.size()); for (SalaryAcctEmployeePO salaryAcctEmployee : salaryAcctEmployees) { // 线下值和系统值之间是否存在差异 boolean different = false; Map map = Maps.newHashMap(); // 员工信息字段的值 Map fieldValueMap = SalaryAcctFormulaBO.convert2FormulaEmployee(employeeMap.get(salaryAcctEmployee.getEmployeeId())); for (SalarySobEmpFieldPO salarySobEmpField : salarySobEmpFields) { map.put(salarySobEmpField.getFieldCode(), fieldValueMap.get(salarySobEmpField.getFieldCode())); // 员工信息字段的字段类型 map.put(salarySobEmpField.getFieldCode() + DATA_TYPE_SUFFIX, SalaryDataTypeEnum.STRING.getValue()); } // 系统值 Map acctResultValueMap = SalaryEntityUtil.convert2Map(acctResultMap.getOrDefault(salaryAcctEmployee.getId(), Collections.emptyList()), SalaryAcctResultPO::getSalaryItemId, SalaryAcctResultPO::getResultValue); // 线下值 Map excelResultValueMap = SalaryEntityUtil.convert2Map(excelResultMap.getOrDefault(salaryAcctEmployee.getId(), Collections.emptyList()), ExcelAcctResultPO::getSalaryItemId, ExcelAcctResultPO::getResultValue); // 薪资项目字段的值 for (SalaryItemPO salaryItem : salaryItems) { Map temp = Maps.newHashMap(); // 系统值 String acctResultValue = acctResultValueMap.get(salaryItem.getId()); // 线下值 String excelResultValue = excelResultValueMap.get(salaryItem.getId()); temp.put("acctResultValue", acctResultValue); temp.put("excelResultValue", excelResultValue); map.put(String.valueOf(salaryItem.getId()), temp); // 薪资项目字段的字段类型 map.put(salaryItem.getId() + DATA_TYPE_SUFFIX, salaryItem.getDataType()); SalaryDataTypeEnum dataTypeEnum = SalaryDataTypeEnum.parseByValue(salaryItem.getDataType()); if (dataTypeEnum == SalaryDataTypeEnum.STRING) { if (!StringUtils.equals(acctResultValue, excelResultValue)) { different = true; includeSalaryItemIds.add(salaryItem.getId()); } } else { if (SalaryEntityUtil.empty2Zero(acctResultValue).compareTo(SalaryEntityUtil.empty2Zero(excelResultValue)) != 0) { different = true; includeSalaryItemIds.add(salaryItem.getId()); } } } // 主键id map.put("id", salaryAcctEmployee.getId()); // 个税扣缴义务人 String taxAgentName = taxAgentNameMap.getOrDefault(salaryAcctEmployee.getTaxAgentId(), StringUtils.EMPTY); map.put("taxAgentName", taxAgentName); // 个税扣缴义务人的字段类型 map.put("taxAgentName" + DATA_TYPE_SUFFIX, SalaryDataTypeEnum.STRING.getValue()); // 是否属于"合并计税"的标记 map.put("consolidatedTaxation", StringUtils.isNotEmpty(taxAgentName) && consolidatedTaxSalaryAcctEmpIds.contains(salaryAcctEmployee.getId())); // 薪资项目的公式详情(前端需要展示) map.put("customParameters", customParameters); // 是否存在差异的标记 map.put("different", different); resultList.add(map); } return resultList; } /** * 转换成薪资核算结果详情dto * * @param simpleEmployee * @param taxAgentPO * @param salaryAcctEmployee * @param salarySobEmpFields * @param salarySobItemPOS * @param salaryItems * @param salaryAcctResults * @return */ public static SalaryAcctResultDetailDTO convert2DetailDTO(DataCollectionEmployee simpleEmployee, TaxAgent taxAgentPO, SalaryAcctEmployeePO salaryAcctEmployee, List salarySobEmpFields, List salarySobItemPOS, List salaryItems, List salaryAcctResults) { // 员工信息字段 Map employeeFieldValueMap = SalaryAcctFormulaBO.convert2FormulaEmployee(simpleEmployee); // 个税扣缴义务人 employeeFieldValueMap.put("taxAgentName", Optional.ofNullable(taxAgentPO).map(TaxAgent::getName).orElse(StringUtils.EMPTY)); Map employeeFieldNameMap = buildEmployeeFieldName(); List employeeInfos = salarySobEmpFields.stream() .map(e -> SalaryAcctEmployeeInfoDTO.builder() .fieldName(employeeFieldNameMap.getOrDefault(e.getFieldCode(), StringUtils.EMPTY)) .fieldValue(employeeFieldValueMap.getOrDefault(e.getFieldCode(), StringUtils.EMPTY)) .build()) .collect(Collectors.toList()); // 薪资项目的值 Map resultValueMap = SalaryEntityUtil.convert2Map(salaryAcctResults, SalaryAcctResultPO::getSalaryItemId, SalaryAcctResultPO::getResultValue); Map salaryItemMap = SalaryEntityUtil.convert2Map(salaryItems, SalaryItemPO::getId); // 公式项的值(不根据salaryItemPO的valueType判断是因为薪资项目的valueType属性改变后并不会同步更新薪资账套中的薪资项目的formulaId字段) List formulaItems = salarySobItemPOS.stream() .filter(salarySobItemPO -> salarySobItemPO.getFormulaId() > 0) .map(salarySobItemPO -> convert2SalaryAcctResultDetailItemDTO(salarySobItemPO, salaryItemMap.get(salarySobItemPO.getSalaryItemId()), resultValueMap)) .collect(Collectors.toList()); // 输入/导入项目的值 List inputItems = salarySobItemPOS.stream() .filter(salarySobItemPO -> salarySobItemPO.getFormulaId() <= 0) .map(salarySobItemPO -> convert2SalaryAcctResultDetailItemDTO(salarySobItemPO, salaryItemMap.get(salarySobItemPO.getSalaryItemId()), resultValueMap)) .collect(Collectors.toList()); return SalaryAcctResultDetailDTO.builder() .id(salaryAcctEmployee.getId()) .employeeId(salaryAcctEmployee.getEmployeeId()) .employeeInfos(employeeInfos) .formulaItems(formulaItems) .inputItems(inputItems) .build(); } /** * 转换成薪资核算结果详情dto * * @param salarySobItemPO * @param salaryItemPO * @param resultValueMap * @return */ private static SalaryAcctResultDetailDTO.SalaryAcctResultDetailItemDTO convert2SalaryAcctResultDetailItemDTO(SalarySobItemPO salarySobItemPO, SalaryItemPO salaryItemPO, Map resultValueMap) { // 薪资项目的数据类型 return SalaryAcctResultDetailDTO.SalaryAcctResultDetailItemDTO.builder() .salaryItemId(salarySobItemPO.getSalaryItemId()) .salaryItemName(Optional.ofNullable(salaryItemPO).map(SalaryItemPO::getName).orElse(StringUtils.EMPTY)) .resultValue(resultValueMap.getOrDefault(salarySobItemPO.getSalaryItemId(), StringUtils.EMPTY)) .dataType(Optional.ofNullable(salaryItemPO).map(SalaryItemPO::getDataType).orElse(SalaryDataTypeEnum.NUMBER.getValue())) .build(); } /** * 薪资核算结果保存参数转换成薪资核算结果po * * @param saveParam 前端保存参数 * @param salaryAcctEmployee 薪资核算人员po * @param employeeId 当前登陆人员id * @return */ public static List convert2PO(SalaryAcctResultSaveParam saveParam, SalaryAcctEmployeePO salaryAcctEmployee, Long employeeId) { if (CollectionUtils.isEmpty(saveParam.getItems())) { return Collections.emptyList(); } Date now = new Date(); return saveParam.getItems().stream() .map(e -> SalaryAcctResultPO.builder() // .id(IdGenerator.generate()) .salarySobId(salaryAcctEmployee.getSalarySobId()) .salaryItemId(e.getSalaryItemId()) .salaryAcctRecordId(salaryAcctEmployee.getSalaryAcctRecordId()) .salaryAcctEmpId(salaryAcctEmployee.getId()) .employeeId(salaryAcctEmployee.getEmployeeId()) .taxAgentId(salaryAcctEmployee.getTaxAgentId()) .resultValue(e.getResultValue()) .creator(employeeId) .createTime(now) .updateTime(now) .deleteType(NumberUtils.INTEGER_ZERO) .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY) .build()) .collect(Collectors.toList()); } public static Map buildEmployeeFieldName() { Field[] declaredFields = SalaryFormulaEmployeeDTO.class.getDeclaredFields(); Map employeeFieldNameMap = Maps.newHashMapWithExpectedSize(declaredFields.length); for (Field declaredField : declaredFields) { if (!declaredField.isAnnotationPresent(SalaryFormulaVar.class)) { continue; } SalaryFormulaVar annotation = declaredField.getAnnotation(SalaryFormulaVar.class); employeeFieldNameMap.put(declaredField.getName(), SalaryI18nUtil.getI18nLabel(annotation.labelId(), annotation.defaultLabel())); } return employeeFieldNameMap; } public static ConsolidatedTaxDetailDTO convert2ConsolidatedTaxDetailDTO(DataCollectionEmployee simpleEmployee, TaxAgent taxAgent, List salarySobEmpFields, List salaryItems, List salaryAcctEmployees, List salarySobs, List salaryAcctRecords, List salaryAcctResults) { return ConsolidatedTaxDetailDTO.builder() // .employeeInfo(buildConsolidatedTaxationEmpInfo(simpleEmployee, taxAgent, salarySobEmpFields)) // .salaryAcctResult(buildConsolidatedTaxationAcctResult(salaryItems, salaryAcctEmployees, salarySobs, salaryAcctRecords, salaryAcctResults)) .build(); } /** * 合并计税详情-员工信息 * * @param simpleEmployee * @param salarySobEmpFields * @return */ // private static WeaForm buildConsolidatedTaxationEmpInfo(DataCollectionEmployee simpleEmployee, TaxAgent taxAgent, List salarySobEmpFields) { // Map employeeFieldNameMap = buildEmployeeFieldName(); // Map fieldValueMap = SalaryAcctFormulaBO.convert2FormulaEmployee(simpleEmployee); // fieldValueMap.put("taxAgentName", taxAgent.getName()); // Map data = Maps.newHashMap(); // Map items = Maps.newHashMap(); // List> layout = Lists.newArrayList(); // List temp = Lists.newArrayList(); // for (SalarySobEmpFieldPO field : salarySobEmpFields) { // // 字段属性 // WeaFormItem weaFormItem = new WeaFormItem(WeaFormItemType.INPUT); // weaFormItem.setReadOnly(true); // weaFormItem.setValue(fieldValueMap.getOrDefault(field.getFieldCode(), "")); // items.put(field.getFieldCode(), weaFormItem); // // 字段布局 // if (temp.size() == 3) { // layout.add(new ArrayList<>(temp)); // temp = Lists.newArrayList(); // } // WeaFormLayout weaFormLayout = new WeaFormLayout(field.getFieldCode(), employeeFieldNameMap.getOrDefault(field.getFieldCode(), ""), new String[]{field.getFieldCode()}); // temp.add(weaFormLayout); // // 字段的值 // data.put(field.getFieldCode(), weaFormItem.getValue()); // } // if (CollectionUtils.isNotEmpty(temp)) { // layout.add(new ArrayList<>(temp)); // } // WeaForm weaForm = new WeaForm(); // weaForm.setData(data); // weaForm.setItems(items); // weaForm.setLayout(layout); // return weaForm; // } /** * 合并计税详情-核算结果列表 * * @param salaryItems * @param salaryAcctResults * @return */ // private static WeaTable> buildConsolidatedTaxationAcctResult(List salaryItems, // List salaryAcctEmployees, // List salarySobs, // List salaryAcctRecords, // List salaryAcctResults) { // // 薪资核算人员 // Map salaryAcctEmployeeMap = SalaryEntityUtil.convert2Map(salaryAcctEmployees, SalaryAcctEmployeePO::getId); // // 薪资账套 // Map salarySobNameMap = SalaryEntityUtil.convert2Map(salarySobs, SalarySobPO::getId, SalarySobPO::getName); // // 薪资核算记录 // Map salaryAcctRecordMap = SalaryEntityUtil.convert2Map(salaryAcctRecords, SalaryAcctRecordPO::getId); // // 薪资核算结果 // Map> salaryAcctResultMap = SalaryEntityUtil.group2Map(salaryAcctResults, SalaryAcctResultPO::getSalaryAcctEmpId); // List weaTableColumns = Lists.newArrayList(new WeaTableColumn("核算批次", "salarySobName")); // weaTableColumns.addAll(salaryItems.stream() // .map(e -> new WeaTableColumn(e.getName(), "" + e.getId(), false)) // .collect(Collectors.toList())); // WeaTable> weaTable = new WeaTable<>(); // weaTable.setTableType(WeaTableTypeEnum.NONE); // weaTable.setCurrent(0); // weaTable.setPageSize(salaryAcctResultMap.size()); // weaTable.setTotal(salaryAcctResultMap.size()); // weaTable.setColumns(weaTableColumns); // if (CollectionUtils.isEmpty(salaryAcctResults)) { // return weaTable; // } // List> data = Lists.newArrayList(); // salaryAcctResultMap.forEach((k, v) -> { // // 薪资核算的结果 // Map valueMap = SalaryEntityUtil.convert2Map(v, e -> "" + e.getSalaryItemId(), SalaryAcctResultPO::getResultValue); // // 核算批次 // SalaryAcctEmployeePO salaryAcctEmployeePO = salaryAcctEmployeeMap.get(k); // SalaryAcctRecordPO salaryAcctRecordPO = salaryAcctRecordMap.get(salaryAcctEmployeePO.getSalaryAcctRecordId()); // String salarySobName = salarySobNameMap.getOrDefault(salaryAcctRecordPO.getSalarySobId(), ""); // valueMap.put("salarySobName", "第" + salaryAcctRecordPO.getAcctTimes() + "次(" + salarySobName + ")"); // data.add(valueMap); // }); // weaTable.setData(data); // weaTable.setDisplayData(data); // return weaTable; // } /** * 薪资核算结果临时存储转成薪资核算结果po * * @param temps * @return */ public static List convert2ResultPO(Collection temps) { if (CollectionUtils.isEmpty(temps)) { return Collections.emptyList(); } return temps.stream().map(e -> { SalaryAcctResultPO salaryAcctResult = new SalaryAcctResultPO(); BeanUtils.copyProperties(e, salaryAcctResult); return salaryAcctResult; }).collect(Collectors.toList()); } }