package com.engine.salary.service.impl; import com.engine.common.util.ServiceUtil; import com.engine.core.impl.Service; import com.engine.salary.biz.*; import com.engine.salary.common.LocalDateRange; import com.engine.salary.constant.SalaryDefaultTenantConstant; import com.engine.salary.constant.SalaryItemConstant; import com.engine.salary.entity.datacollection.DataCollectionEmployee; import com.engine.salary.entity.salaryarchive.bo.SalaryArchiveBO; import com.engine.salary.entity.salaryarchive.dto.SalaryArchiveDataDTO; import com.engine.salary.entity.salaryarchive.dto.SalaryArchiveInitImportDTO; import com.engine.salary.entity.salaryarchive.dto.SalaryArchiveInitImportSameDTO; import com.engine.salary.entity.salaryarchive.dto.SalaryArchiveListDTO; import com.engine.salary.entity.salaryarchive.param.*; import com.engine.salary.entity.salaryarchive.po.SalaryArchiveDimissionPO; import com.engine.salary.entity.salaryarchive.po.SalaryArchiveItemPO; import com.engine.salary.entity.salaryarchive.po.SalaryArchivePO; import com.engine.salary.entity.salaryarchive.po.SalaryArchiveTaxAgentPO; import com.engine.salary.entity.salaryitem.po.SalaryItemPO; import com.engine.salary.entity.taxagent.dto.TaxAgentEmployeeDTO; import com.engine.salary.entity.taxagent.dto.TaxAgentManageRangeEmployeeDTO; import com.engine.salary.entity.taxagent.po.TaxAgentPO; import com.engine.salary.enums.UserStatusEnum; import com.engine.salary.enums.salaryarchive.SalaryArchiveImportTypeEnum; import com.engine.salary.enums.salaryarchive.SalaryArchiveItemAdjustReasonEnum; import com.engine.salary.enums.salaryarchive.SalaryArchiveTaxAgentAdjustReasonEnum; import com.engine.salary.exception.SalaryRunTimeException; import com.engine.salary.mapper.archive.SalaryArchiveMapper; import com.engine.salary.service.SalaryArchiveService; import com.engine.salary.service.TaxAgentService; import com.engine.salary.util.SalaryDateUtil; import com.engine.salary.util.SalaryEntityUtil; import com.engine.salary.util.SalaryI18nUtil; import com.engine.salary.util.db.MapperProxyFactory; import com.engine.salary.util.excel.ExcelComment; import com.engine.salary.util.excel.ExcelParseHelper; import com.engine.salary.util.excel.ExcelSupport; import com.engine.salary.util.excel.ExcelUtil; import com.engine.salary.util.page.PageInfo; import com.engine.salary.util.page.SalaryPageUtil; import com.google.common.base.Joiner; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import dm.jdbc.util.IdGenerator; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang.time.DateUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.util.IOUtils; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import weaver.file.ImageFileManager; import weaver.hrm.User; import java.io.InputStream; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import static com.engine.salary.util.excel.ExcelSupport.EXCEL_TYPE_XLSX; /** * 薪资档案 *

Copyright: Copyright (c) 2022

*

Company: 泛微软件

* * @author qiantao * @version 1.0 **/ @Slf4j public class SalaryArchiveServiceImpl extends Service implements SalaryArchiveService { private SalaryArchiveBiz salaryArchiveMapper = new SalaryArchiveBiz(); private EmployBiz employBiz = new EmployBiz(); private SalaryArchiveItemBiz salaryArchiveItemMapper = new SalaryArchiveItemBiz(); private SalaryArchiveTaxAgentBiz salaryArchiveTaxAgentMapper = new SalaryArchiveTaxAgentBiz(); private SalaryArchiveDimissionBiz salaryArchiveDimissionMapper = new SalaryArchiveDimissionBiz(); private SalaryItemBiz salaryItemMapper = new SalaryItemBiz(); private TaxAgentService getTaxAgentService(User user) { return ServiceUtil.getService(TaxAgentServiceImpl.class, user); } private SalaryArchiveMapper getSalaryArchiveMapper() { return MapperProxyFactory.getProxy(SalaryArchiveMapper.class); } @Override public SalaryArchivePO getById(Long salaryArchiveId) { return salaryArchiveMapper.getById(salaryArchiveId); } @Override public PageInfo listPage(SalaryArchiveQueryParam queryParam) { long currentEmployeeId = user.getUID(); // 1.历史数据处理 handleHistory(currentEmployeeId); Boolean needAuth = getTaxAgentService(user).isNeedAuth(currentEmployeeId); if (needAuth) { Boolean adminEnable = getTaxAgentService(user).isAdminEnable(currentEmployeeId); //不是管理员看不到数据,返回空 if (!adminEnable) { PageInfo pageInfo = SalaryPageUtil.buildPage(queryParam.getCurrent(), queryParam.getPageSize(), SalaryArchiveListDTO.class); return pageInfo; } //获取管理的人员范围 List taxAgentEmployeeDTOS = getTaxAgentService(user).listTaxAgentAndEmployee(currentEmployeeId); Set employeeId = SalaryEntityUtil.properties(taxAgentEmployeeDTOS, TaxAgentEmployeeDTO::getEmployeeId); //获取所有薪资档案 List list = getSalaryArchiveMapper().list(queryParam); List finalAllArchive = list.stream().filter(dto -> employeeId.contains(dto.getEmployeeId())).collect(Collectors.toList()); PageInfo pageInfo = SalaryPageUtil.buildPage(queryParam.getCurrent(), queryParam.getPageSize(), SalaryArchiveListDTO.class); pageInfo.setTotal(finalAllArchive.size()); pageInfo.setList(SalaryPageUtil.subList(queryParam.getCurrent(), queryParam.getPageSize(), finalAllArchive)); return pageInfo; } else { SalaryPageUtil.start(queryParam.getCurrent(), queryParam.getPageSize()); List list = getSalaryArchiveMapper().list(queryParam); PageInfo pageInfo = new PageInfo(list, SalaryArchiveListDTO.class); return pageInfo; } } @Override public List list(SalaryArchiveQueryParam queryParam) { long currentEmployeeId = user.getUID(); Boolean needAuth = getTaxAgentService(user).isNeedAuth(currentEmployeeId); if (needAuth) { Boolean adminEnable = getTaxAgentService(user).isAdminEnable(currentEmployeeId); //不是管理员看不到数据,返回空 if (!adminEnable) { return new ArrayList<>(); } //获取管理的人员范围 List taxAgentEmployeeDTOS = getTaxAgentService(user).listTaxAgentAndEmployee(currentEmployeeId); Set employeeId = SalaryEntityUtil.properties(taxAgentEmployeeDTOS, TaxAgentEmployeeDTO::getEmployeeId); //获取所有薪资档案 List list = getSalaryArchiveMapper().list(queryParam); List finalAllArchive = list.stream().filter(dto -> employeeId.contains(dto.getEmployeeId())).collect(Collectors.toList()); return finalAllArchive; } else { return getSalaryArchiveMapper().list(queryParam); } } /** * 获取薪资档案对应的当前生效的薪资项目 * * @param salaryArchivesIds * @return */ @Override public List getCurrentEffectiveItemList(Collection salaryArchivesIds, Collection salaryItemIds) { if(CollectionUtils.isEmpty(salaryItemIds)){ return Collections.EMPTY_LIST; } List salaryArchiveItems = salaryArchiveItemMapper.getCurrentEffectiveItemList(SalaryArchiveItemQueryParam.builder().salaryArchivesIds(salaryArchivesIds).salaryItemIds(salaryItemIds).effectiveTime(new Date()).build()); return salaryArchiveItems.stream() .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(f -> f.getSalaryArchiveId() + "-" + f.getSalaryItemId()))), ArrayList::new)); } /** * 获取薪资档案对应的当前生效的个税扣缴义务人 * * @param salaryArchivesIds * @return */ @Override public List getCurrentEffectiveTaxAgentList(Collection salaryArchivesIds) { if(CollectionUtils.isEmpty(salaryArchivesIds)){ return Collections.EMPTY_LIST; } List salaryArchiveTaxAgents = salaryArchiveTaxAgentMapper.listByParam(SalaryArchiveTaxAgentQueryParam.builder().salaryArchivesIds(salaryArchivesIds).effectiveTime(new Date()).build()); return salaryArchiveTaxAgents.stream() .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(SalaryArchiveTaxAgentPO::getSalaryArchiveId))), ArrayList::new)); } /** * 构建薪资档案数据 * * @param salaryArchives * @param taxAgentLists * @param salaryItems * @param isPage * @return */ @Override public List> buildSalaryArchiveData(Collection salaryArchives, Collection taxAgentLists, List salaryItems, Boolean isPage) { // 分页用于表格展示,否则用于导出 Collection ids = isPage ? salaryArchives.stream().map(SalaryArchiveListDTO::getId).collect(Collectors.toList()) : CollectionUtils.emptyCollection(); List salaryItemIds = salaryItems.stream().map(SalaryItemPO::getId).collect(Collectors.toList()); // 1.获取薪资档案所对应的当前生效的薪资项目数据 List salaryArchiveItemList = getCurrentEffectiveItemList(ids, salaryItemIds); List> salaryArchiveItemData = salaryArchives.stream().map(m -> { Map map = Maps.newHashMap(); map.put("salaryArchiveId", m.getId()); List salaryArchiveItemValuelList = salaryArchiveItemList.stream().filter(i -> i.getSalaryArchiveId().equals(m.getId())).collect(Collectors.toList()); salaryArchiveItemValuelList.forEach(i -> { map.put(i.getSalaryItemId() + SalaryItemConstant.DYNAMIC_SUFFIX, i.getItemValue()); }); return map; }).collect(Collectors.toList()); //2.获取薪资档案所对应的当前生效的个税扣缴义务人列表 // List taxAgentList = getCurrentEffectiveTaxAgentList(ids); // List> taxAgentData = taxAgentList.stream().map(m -> { // Map map = Maps.newHashMap(); // map.put("salaryArchiveId", m.getSalaryArchiveId()); // map.put("taxAgentId", m.getTaxAgentId()); // Optional optional = taxAgentLists.stream().filter(f -> f.getId().equals(m.getTaxAgentId())).findFirst(); // map.put("taxAgentName", optional.isPresent() ? optional.get().getName() : ""); // map.put("taxAgentEffectiveTime", m.getEffectiveTime()); // return map; // }).collect(Collectors.toList()); Map longTaxAgentPOMap = SalaryEntityUtil.convert2Map(taxAgentLists, TaxAgentPO::getId); // 3.组装数据 List> listMaps = new ArrayList<>(); salaryArchives.forEach(e -> { e.setEmployeeStatus(UserStatusEnum.getDefaultLabelByValue(Integer.parseInt(e.getEmployeeStatus()))); Map map = new LinkedHashMap<>(); map.put("id", e.getId()); map.put("username", e.getUsername()); map.put("employeeId", e.getEmployeeId()); // Optional> optionalTaxAgent = taxAgentData.stream().filter(f -> f.get("salaryArchiveId").toString().equals(e.getId().toString())).findFirst(); TaxAgentPO taxAgentPO = longTaxAgentPOMap.get(e.getTaxAgentId()); map.put("taxAgentName", Optional.ofNullable(taxAgentPO).map(TaxAgentPO::getName).orElse("")); map.put("taxAgentId", Optional.ofNullable(taxAgentPO).map(TaxAgentPO::getId).orElse(0L)); // map.put("taxAgentEffectiveTime", optionalTaxAgent.isPresent() ? optionalTaxAgent.get().get("taxAgentEffectiveTime") : ""); map.put("departmentName", e.getDepartmentName()); map.put("mobile", e.getMobile()); map.put("employeeStatus", e.getEmployeeStatus()); // 薪资项目动态 Optional> optionalItem = salaryArchiveItemData.stream().filter(f -> f.get("salaryArchiveId").toString().equals(e.getId().toString())).findFirst(); optionalItem.ifPresent(map::putAll); listMaps.add(map); }); return listMaps; } @Override public XSSFWorkbook exportList(SalaryArchiveQueryParam queryParam) { long employeeId = user.getUID(); // 1.工作簿名称 String sheetName = SalaryI18nUtil.getI18nLabel(85368, "薪资档案"); // 获取所有可被引用的薪资项目 List salaryItems = salaryItemMapper.getCanAdjustSalaryItems(); String[] header = { SalaryI18nUtil.getI18nLabel(85429, "姓名"), SalaryI18nUtil.getI18nLabel(86184, "个税扣缴义务人"), SalaryI18nUtil.getI18nLabel(86185, "部门"), SalaryI18nUtil.getI18nLabel(86186, "手机号"), SalaryI18nUtil.getI18nLabel(91075, "状态") }; // 2.表头 List headerList = new ArrayList<>(Arrays.asList(header)); for (SalaryItemPO salaryItem : salaryItems) { headerList.add(salaryItem.getName()); } // 获取所有个税扣缴义务人 Collection taxAgentList = getTaxAgentService(user).listAll(); Collection salaryArchives = salaryArchiveMapper.list(queryParam); //分权 Boolean needAuth = getTaxAgentService(user).isNeedAuth(employeeId); if (needAuth) { Boolean adminEnable = getTaxAgentService(user).isAdminEnable(employeeId); if (!adminEnable) { salaryArchives = new ArrayList<>(); } else { //管理范围内的人员 List taxAgentEmployeeDTOS = getTaxAgentService(user).listTaxAgentAndEmployee(employeeId); Set employeeIds = SalaryEntityUtil.properties(taxAgentEmployeeDTOS, TaxAgentEmployeeDTO::getEmployeeId); salaryArchives = salaryArchives.stream().filter(salaryArchive -> employeeIds.contains(salaryArchive.getEmployeeId())).collect(Collectors.toList()); } } List> listMaps = buildSalaryArchiveData(salaryArchives, taxAgentList, salaryItems, Boolean.FALSE); // 组装数据 List> rows = new ArrayList<>(); rows.add(headerList); listMaps.forEach(e -> { List row = new ArrayList<>(); row.add(e.get("username").toString()); row.add(e.get("taxAgentName").toString()); row.add(e.get("departmentName").toString()); row.add(e.get("mobile") == null ? "" : e.get("mobile").toString()); row.add(e.get("employeeStatus").toString()); // 薪资项目数据 for (SalaryItemPO salaryItem : salaryItems) { row.add(e.containsKey(salaryItem.getId() + SalaryItemConstant.DYNAMIC_SUFFIX) ? (e.get(salaryItem.getId() + SalaryItemConstant.DYNAMIC_SUFFIX) == null ? "" : e.get(salaryItem.getId() + SalaryItemConstant.DYNAMIC_SUFFIX).toString()) : ""); } rows.add(row); }); // 3.表数据 return ExcelUtil.genWorkbookV2(rows, sheetName); } @Override public XSSFWorkbook downloadTemplate(SalaryArchiveImportTypeEnum salaryArchiveImportTypeEnum, SalaryArchiveQueryParam queryParam) { long employeeId = user.getUID(); boolean isInit = salaryArchiveImportTypeEnum.getValue().equals(SalaryArchiveImportTypeEnum.INIT.getValue()); boolean isTaxAgentAdjust = salaryArchiveImportTypeEnum.getValue().equals(SalaryArchiveImportTypeEnum.TAXAGENTADJUST.getValue()); boolean isSalaryItemAdjust = salaryArchiveImportTypeEnum.getValue().equals(SalaryArchiveImportTypeEnum.SALARYITEMADJUST.getValue()); String nameI18n = SalaryI18nUtil.getI18nLabel(101601, "薪资档案导入模板"); // 初始化 if (isInit) { nameI18n += "-" + SalaryI18nUtil.getI18nLabel(SalaryArchiveImportTypeEnum.INIT.getLabelId(), SalaryArchiveImportTypeEnum.INIT.getDefaultLabel()); // 调整个税扣缴义务人 } else if (isTaxAgentAdjust) { nameI18n += "-" + SalaryI18nUtil.getI18nLabel(SalaryArchiveImportTypeEnum.TAXAGENTADJUST.getLabelId(), SalaryArchiveImportTypeEnum.TAXAGENTADJUST.getDefaultLabel()); // 调薪 } else if (isSalaryItemAdjust) { nameI18n += "-" + SalaryI18nUtil.getI18nLabel(SalaryArchiveImportTypeEnum.SALARYITEMADJUST.getLabelId(), SalaryArchiveImportTypeEnum.SALARYITEMADJUST.getDefaultLabel()); } // 1.工作簿名称 String sheetName = nameI18n; // 获取所有可被引用的薪资项目 List salaryItems = salaryItemMapper.getCanAdjustSalaryItems(); // 2.表头 List header = Lists.newArrayList(); header.add(SalaryI18nUtil.getI18nLabel(85429, "姓名")); header.add(SalaryI18nUtil.getI18nLabel(86184, "个税扣缴义务人")); header.add(SalaryI18nUtil.getI18nLabel(85904, "生效日期")); if (isTaxAgentAdjust || isSalaryItemAdjust) { header.add(SalaryI18nUtil.getI18nLabel(85431, "调整原因")); } header.add(SalaryI18nUtil.getI18nLabel(86185, "部门")); header.add(SalaryI18nUtil.getI18nLabel(86186, "手机号")); header.add(SalaryI18nUtil.getI18nLabel(91075, "状态")); if (isInit || isSalaryItemAdjust) { for (SalaryItemPO salaryItem : salaryItems) { header.add(salaryItem.getName()); } } // 组装数据 List> rows = new ArrayList<>(); rows.add(header); //模板是否含数据 if (queryParam.getHasData() != null && queryParam.getHasData()) { // 获取所有个税扣缴义务人 Collection taxAgentList = getTaxAgentService(user).listAll(); List salaryArchives = list(queryParam); List> listMaps = buildSalaryArchiveData(salaryArchives, taxAgentList, salaryItems, Boolean.FALSE); listMaps.forEach(e -> { List row = new ArrayList<>(); row.add(e.get("username").toString()); row.add(e.get("taxAgentName").toString()); if (isTaxAgentAdjust || isSalaryItemAdjust) { row.add(isTaxAgentAdjust ? e.get("taxAgentEffectiveTime") : ""); } row.add(""); row.add(e.get("departmentName").toString()); row.add(e.get("mobile") == null ? "" : e.get("mobile").toString()); row.add(e.get("employeeStatus").toString()); // 调薪 if (isInit || isSalaryItemAdjust) { // 薪资项目数据 for (SalaryItemPO salaryItem : salaryItems) { row.add(e.containsKey(salaryItem.getId() + SalaryItemConstant.DYNAMIC_SUFFIX) ? (e.get(salaryItem.getId() + SalaryItemConstant.DYNAMIC_SUFFIX) == null ? "" : e.get(salaryItem.getId() + SalaryItemConstant.DYNAMIC_SUFFIX).toString()) : ""); } } rows.add(row); }); } // 3.表数据 // 4.注释 List excelComments = Lists.newArrayList(); excelComments.add(new ExcelComment(0, 0, 3, 2, SalaryI18nUtil.getI18nLabel(100344, "必填"))); if (isInit || isTaxAgentAdjust) { excelComments.add(new ExcelComment(1, 0, 4, 2, SalaryI18nUtil.getI18nLabel(100344, "必填"))); } excelComments.add(new ExcelComment(2, 0, 5, 2, SalaryI18nUtil.getI18nLabel(100458, "必填,格式样例为'2022-01-01'、'2022/1/1'"))); //调整个税扣缴义务人 if (isTaxAgentAdjust) { excelComments.add(new ExcelComment(3, 0, 6, 2, SalaryI18nUtil.getI18nLabel(100952, "必填,可填写如:调动,变更,入职,离职,其他,初始化"))); // 调薪 } else if (isSalaryItemAdjust) { excelComments.add(new ExcelComment(3, 0, 6, 2, SalaryI18nUtil.getI18nLabel(100953, "必填,可填写如:入职,转正,调薪,调岗调薪,离职,其他,初始化"))); } XSSFWorkbook book = ExcelUtil.genWorkbookV2(rows, sheetName, excelComments); return book; } // @BatchExportHandler("exportSalaryArchive") // public void exportSalaryArchiveHandler() { // BatchCallbackMessage message = BatchExportContext.getBatchCallbackMessage(); // log.info("接受到薪资档案导出的结果:{}", JSONObject.toJSONString(message)); // } @Override public List dimissionSets() { return salaryArchiveDimissionMapper.dimissionSets(); } @Override public String saveDimissionSet(SalaryArchiveDimissionSaveParam saveParam) { Date now = new Date(); List dimissionSets = dimissionSets(); if (CollectionUtils.isNotEmpty(dimissionSets)) { SalaryArchiveDimissionPO po = dimissionSets.get(0); po.setDimissionTimeInterval(saveParam.getDimissionTimeInterval().getValue()); po.setUpdateTime(now); salaryArchiveDimissionMapper.updateById(po); } else { salaryArchiveDimissionMapper.insert(SalaryArchiveDimissionPO .builder() // .id(IdGenerator.generate()) .dimissionTimeInterval(saveParam.getDimissionTimeInterval().getValue()) .createTime(now) .updateTime(now) .creator((long) user.getUID()) .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY) .build() ); } return StringUtils.EMPTY; } @Override public List getSalaryArchiveData(LocalDateRange localDateRange, Collection employeeIds) { return getSalaryArchiveData(localDateRange, employeeIds, Boolean.FALSE); } @Override public List getSalaryArchiveTaxAgentData(LocalDateRange localDateRange, Collection employeeIds) { return getSalaryArchiveData(localDateRange, employeeIds, Boolean.TRUE); } /** * 根据日期范围和人员获取薪资档案数据 * * @param localDateRange * @param employeeIds * @param isOnlyTaxAgent * @return */ private List getSalaryArchiveData(LocalDateRange localDateRange, Collection employeeIds, boolean isOnlyTaxAgent) { // 获取个税扣缴义务人调整数据 List salaryArchiveTaxAgentList = salaryArchiveTaxAgentMapper.listByParam(SalaryArchiveTaxAgentQueryParam.builder().employeeIds(employeeIds).effectiveTime(localDateRange.getEndDate()).build()); List allEmployeeIds = salaryArchiveTaxAgentList.stream().map(SalaryArchiveTaxAgentPO::getEmployeeId).distinct().collect(Collectors.toList()); // 获取所有可被引用的薪资项目 List salaryItems = salaryItemMapper.getCanAdjustSalaryItems(); Collection salaryItemIds = salaryItems.stream().map(SalaryItemPO::getId).collect(Collectors.toList()); // 获取薪资项目调整数据,isOnlyTaxAgent为true时不需要薪资项目数据 List salaryArchiveItemDataList; if (isOnlyTaxAgent || CollectionUtils.isEmpty(salaryItemIds)) { salaryArchiveItemDataList = Lists.newArrayList(); } else { salaryArchiveItemDataList = salaryArchiveItemMapper.listByParam(SalaryArchiveItemQueryParam.builder().salaryItemIds(salaryItemIds).employeeIds(employeeIds).effectiveTime(new Date()).build()); } return SalaryArchiveBO.buildSalaryArchiveData(salaryArchiveTaxAgentList, salaryArchiveItemDataList, localDateRange, allEmployeeIds, isOnlyTaxAgent); } /** * 导入薪资档案 */ public Map importSalaryArchive(SalaryArchiveImportHandleParam param) { //1、参数校验 vaildImportParam(param); String imageId = param.getImageId(); String importType = param.getImportType(); // 2.构建导入需要的数据 SalaryArchiveImportHandleParam importHandleParam = buildImportHandleParam(); InputStream fileInputStream = null; try { fileInputStream = ImageFileManager.getInputStreamById(Integer.parseInt(imageId)); Sheet sheet = ExcelSupport.parseFile(fileInputStream, 0, EXCEL_TYPE_XLSX); List headers = ExcelSupport.getSheetHeader(sheet, 0); //检查导入模板的必填列 checkHeaders(importType, headers); //excel数据 List> data = ExcelParseHelper.parse2Map(sheet, 1); int successCount = 0; int errorCount = 0; // 用于(初始化导入)的相同employeeId时的处理 boolean isInit = importType.equals(SalaryArchiveImportTypeEnum.INIT.getValue()); List initImportData = Lists.newArrayList(); // 用于(调薪和调整个税扣缴义务人)的相同employeeId时取第一条记录,如果是初始化导入则有重复 List allEmployeeIds = Lists.newArrayList(); int effectiveTimeIndex = 0; for (int j = 0; j < headers.size(); j++) { if (headers.get(j).equals(SalaryI18nUtil.getI18nLabel(85904, "生效日期"))) { effectiveTimeIndex = j; break; } } // 错误sheet数据 List> errorData = new ArrayList<>(); // 错误提示 List> excelComments = new ArrayList<>(); for (int i = 0; i < data.size(); i++) { Map map = data.get(i); map.put("index", i + 2); // 3.校验行内容 boolean isError = singleRowCheck(importType, allEmployeeIds, map, headers, effectiveTimeIndex, excelComments, errorCount, importHandleParam); if (isError) { errorCount += 1; // 添加错误数据 errorData.add(map); } else { successCount += 1; } // 初始化导入对重复记录校验 if (isInit) { Map validMap = validInitImportData(isError, i, map, excelComments, errorCount, successCount, errorData, initImportData, importHandleParam); errorCount = Integer.parseInt(validMap.getOrDefault("errorCount", errorCount).toString()); successCount = Integer.parseInt(validMap.getOrDefault("successCount", successCount).toString()); } } // 4.数据入库处理 handleImportData(isInit, importHandleParam); Map apidatas = new HashMap<>(); apidatas.put("successCount", successCount); apidatas.put("errorCount", errorCount); apidatas.put("errorNotice", excelComments); return apidatas; } finally { IOUtils.closeQuietly(fileInputStream); } } @Override public Map preview(SalaryArchiveImportHandleParam param) { //1、参数校验 vaildImportParam(param); Map map = new HashMap<>(); InputStream fileInputStream = null; try { fileInputStream = ImageFileManager.getInputStreamById(Integer.parseInt(param.getImageId())); Sheet sheet = ExcelSupport.parseFile(fileInputStream, 0, EXCEL_TYPE_XLSX); List headers = ExcelSupport.getSheetHeader(sheet, 0); map.put("headers", headers); map.put("list", ExcelParseHelper.parse2List(sheet, 1)); return map; } finally { IOUtils.closeQuietly(fileInputStream); } } private void vaildImportParam(SalaryArchiveImportHandleParam param) { String imageId = param.getImageId(); if (StringUtils.isBlank(imageId)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(100593, "文件id为空")); } String importType = param.getImportType(); SalaryArchiveImportTypeEnum importTypeEnum = SalaryArchiveImportTypeEnum.parseByValue(importType); if (importTypeEnum == null) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(100593, "导入类型不正确")); } } /** * 构建导入处理参数 * * @return */ private SalaryArchiveImportHandleParam buildImportHandleParam() { long employeeId = user.getUID(); // 获取所有可被引用的薪资项目 List salaryItems = salaryItemMapper.getCanAdjustSalaryItems(); Collection salaryItemIds = salaryItems.stream().map(SalaryItemPO::getId).collect(Collectors.toList()); Date now = new Date(); return SalaryArchiveImportHandleParam.builder() .openDevolution(getTaxAgentService(user).isOpenDevolution()) .listTaxAgentAndEmployeeTree(getTaxAgentService(user).listTaxAgentAndEmployeeTree(employeeId)) // 获取租户下所有的人员 .employees(employBiz.listEmployee()) // 获取所有个税扣缴义务人 .taxAgentList(getTaxAgentService(user).listAllTaxAgentsAsAdmin(employeeId)) .salaryItems(salaryItems) // 查询已有的薪资档案基本数据 .salaryArchives(list(SalaryArchiveQueryParam.builder().build())) .salaryItemIds(salaryItemIds) // 查询已生效的薪资项目数据 .effectiveItemList(getEffectiveItemList(salaryItemIds)) // 查询未生效的薪资项目数据 .ineffectiveItemList(getIneffectiveItemList(salaryItemIds)) // 查询已生效的个税扣缴义务人数据 .effectiveTaxAgentList(getEffectiveTaxAgentList()) // 查询未生效的个税扣缴义务人数据 .ineffectiveTaxAgentList(getIneffectiveTaxAgentList()) // 当前时间 .nowTime(now) // 当天 .today(now) // 待保存薪资档案 .salaryArchiveSaves(Lists.newArrayList()) // 待保存薪资档案-个税扣缴义务人 .salaryArchiveTaxAgentSaves(Lists.newArrayList()) // 待保存薪资档案-薪资项目 .salaryArchiveItemSaves(Lists.newArrayList()) // 待删除薪资档案-个税扣缴义务人 .salaryArchiveTaxAgentDelTaxAgentIds(Lists.newArrayList()) // 待删除薪资档案-薪资项目 .salaryArchiveItemDelSalaryItemIds(Lists.newArrayList()) .build(); } /** * 初始化导入数据校验 * 说明:如果一个人的多条记录中有一个错那么就全部弄到错误文档中 * * @param isError * @param rowNo * @param map * @param excelComments * @param errorCount * @param successCount * @param errorData * @param initImportData * @param importHandleParam */ private Map validInitImportData(boolean isError, int rowNo, Map map, List> excelComments, int errorCount, int successCount, List> errorData, List initImportData, SalaryArchiveImportHandleParam importHandleParam) { Long employeeId = Long.valueOf(Optional.ofNullable(map.get("employeeId")).orElse("0").toString()); Optional optionalInitImport = initImportData.stream().filter(f -> f.getEmployeeId().equals(employeeId)).findFirst(); Map validMap = new HashMap<>(); validMap.put("errorCount", errorCount); validMap.put("successCount", successCount); if (employeeId.equals(0L)) { return validMap; } AtomicInteger finalErrorCount = new AtomicInteger(errorCount); AtomicInteger finalSuccessCount = new AtomicInteger(successCount); if (optionalInitImport.isPresent()) { SalaryArchiveInitImportDTO initImport = optionalInitImport.get(); List sames = initImport.getSames(); sames.add(SalaryArchiveInitImportSameDTO.builder() .isError(isError) .rowNo(rowNo) .row(map) .build()); Optional optionalSame = sames.stream().filter(SalaryArchiveInitImportSameDTO::isError).findFirst(); // 只要是其中一行有错误 if (optionalSame.isPresent()) { sames.forEach(e -> { if (!e.isError()) { e.setError(Boolean.TRUE); Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", "该员工的薪资档案记录有误,请检查"); excelComments.add(errorMessageMap); // salaryBatchService.createExcelComment(excelComments, SalaryI18nUtil.getI18nLabel(101723, "该员工的薪资档案记录有误,请检查"), finalErrorCount.get() + 1, finalErrorCount.get() + 1, 0, 0); finalErrorCount.addAndGet(1); errorData.add(e.getRow()); finalSuccessCount.addAndGet(-1); } }); // 如果到目前为止都没错的话,则相互之间检验调整记录 } else { int nums = sames.size(); // 1.生效时间不可重复 List effectiveTimeList = sames.stream().map(m -> Optional.ofNullable(m.getRow().get("effectiveTime")).orElse("").toString()).distinct().collect(Collectors.toList()); // 2.个税扣缴义务人和薪资项目共同决定是否重复 List rowSameList = sames.stream().map(m -> { Map row = m.getRow(); String taxAgent = Optional.ofNullable(row.get("taxAgent")).orElse("").toString(); String salaryItem = Optional.ofNullable(row.get("salaryItemVal")).orElse("").toString(); return taxAgent + salaryItem; }).distinct().collect(Collectors.toList()); if (effectiveTimeList.size() != nums || rowSameList.size() != nums) { sames.forEach(e -> { if (!e.isError()) { e.setError(Boolean.TRUE); Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", "该员工的薪资档案记录有误"); excelComments.add(errorMessageMap); // salaryBatchService.createExcelComment(excelComments, SalaryI18nUtil.getI18nLabel(101723, "该员工的薪资档案记录有误,请检查"), finalErrorCount.get() + 1, finalErrorCount.get() + 1, 0, 0); finalErrorCount.addAndGet(1); errorData.add(e.getRow()); finalSuccessCount.addAndGet(-1); } }); } } initImport.setSames(sames); } else { SalaryArchiveInitImportDTO initImport = new SalaryArchiveInitImportDTO(); initImport.setEmployeeId(employeeId); List sames = Lists.newArrayList(); sames.add(SalaryArchiveInitImportSameDTO.builder() .isError(isError) .rowNo(rowNo) .row(map) .build()); initImport.setSames(sames); initImportData.add(initImport); } // 如果出现错误 if (isError || errorCount != finalErrorCount.get() || successCount != finalSuccessCount.get()) { validMap.put("errorCount", finalErrorCount.get()); validMap.put("successCount", finalSuccessCount.get()); // 将前面添加好的数据给过滤掉 importHandleParam.setSalaryArchiveSaves(importHandleParam.getSalaryArchiveSaves().stream().filter(f -> !f.getEmployeeId().equals(employeeId)).collect(Collectors.toList())); importHandleParam.setSalaryArchiveTaxAgentSaves(importHandleParam.getSalaryArchiveTaxAgentSaves().stream().filter(f -> !f.getEmployeeId().equals(employeeId)).collect(Collectors.toList())); importHandleParam.setSalaryArchiveItemSaves(importHandleParam.getSalaryArchiveItemSaves().stream().filter(f -> !f.getEmployeeId().equals(employeeId)).collect(Collectors.toList())); } return validMap; } /** * 校验单行数据 * * @param importType * @param allEmployeeIds * @param map * @param headers * @param excelComments * @param errorCount * @param importHandleParam * @return */ private boolean singleRowCheck(String importType, List allEmployeeIds, Map map, List headers, int effectiveTimeIndex, List> excelComments, int errorCount, SalaryArchiveImportHandleParam importHandleParam) { boolean isError = false; boolean isInit = importType.equals(SalaryArchiveImportTypeEnum.INIT.getValue()); boolean isTaxAgentAdjust = importType.equals(SalaryArchiveImportTypeEnum.TAXAGENTADJUST.getValue()); boolean isSalaryItemAdjust = importType.equals(SalaryArchiveImportTypeEnum.SALARYITEMADJUST.getValue()); String userNameI18n = SalaryI18nUtil.getI18nLabel(85429, "姓名"); String taxAgentI18n = SalaryI18nUtil.getI18nLabel(86184, "个税扣缴义务人"); String effectiveTimeI18n = SalaryI18nUtil.getI18nLabel(85904, "生效日期"); String adjustReasonI18n = SalaryI18nUtil.getI18nLabel(85431, "调整原因"); String rowindex = "第" + map.get("index") + "行"; // 1.姓名 String userName = Optional.ofNullable(map.get(userNameI18n)).orElse("").toString(); String deparmentName = Optional.ofNullable(map.get(SalaryI18nUtil.getI18nLabel(86185, "部门"))).orElse("").toString(); List emps = importHandleParam.getEmployees().stream() .filter(e -> (StringUtils.isBlank(userName) || Objects.equals(e.getUsername(), userName)) && (StringUtils.isBlank(deparmentName) || Objects.equals(e.getDepartmentName(), deparmentName))) .collect(Collectors.toList()); List employeeSameIds = new ArrayList<>(); if (CollectionUtils.isNotEmpty(emps) && emps.size() > 1) { employeeSameIds = emps.stream() .filter(e -> UserStatusEnum.getNormalStatus().contains(e.getStatus())) .map(DataCollectionEmployee::getEmployeeId) .collect(Collectors.toList()); } if (CollectionUtils.isNotEmpty(emps) && emps.size() == 1) { employeeSameIds = emps.stream() .map(DataCollectionEmployee::getEmployeeId) .collect(Collectors.toList()); } Long employeeId = CollectionUtils.isNotEmpty(employeeSameIds) && employeeSameIds.size() == 1 && employeeSameIds.get(0) > 0 ? employeeSameIds.get(0) : null; // 调薪和调整个税扣缴义务人的存在相同的取第一条 if (employeeId != null && allEmployeeIds.contains(employeeId) && (isTaxAgentAdjust || isSalaryItemAdjust)) { return isError; } if (employeeId != null) { allEmployeeIds.add(employeeId); } // 用于初始化导入数据校验 map.put("employeeId", employeeId); map.put("rowId", employeeId); // 2.生效日期 String effectiveTimeCellVal = Optional.ofNullable(map.get(effectiveTimeI18n)).orElse("").toString().replaceAll(" 00:00:00", ""); // 免得失败后,会追加 00:00:00 map.put(effectiveTimeI18n, effectiveTimeCellVal); map.put("effectiveTime", effectiveTimeCellVal); Date effectiveTime = SalaryDateUtil.checkDay(effectiveTimeCellVal) ? dateStrToLocalDate(effectiveTimeCellVal) : null; // 3.个税扣缴义务人 String taxAgentCellVal = Optional.ofNullable(map.get(taxAgentI18n)).orElse("").toString(); // 用于初始化导入的同一个人的记录校验 map.put("taxAgent", taxAgentCellVal); Optional optionalTaxAgent = importHandleParam.getTaxAgentList().stream().filter(m -> m.getName().equals(taxAgentCellVal)).findFirst(); Long taxAgentId = optionalTaxAgent.map(TaxAgentPO::getId).orElse(null); // 4.调整原因 String adjustReason = ""; if (isTaxAgentAdjust) { // 4.调整原因[个税扣缴义务人] adjustReason = SalaryArchiveTaxAgentAdjustReasonEnum.getValueByDefaultLabel(Optional.ofNullable(map.get(adjustReasonI18n)).orElse("").toString()); } else if (isSalaryItemAdjust) { // 4.调整原因[薪资项目] adjustReason = SalaryArchiveItemAdjustReasonEnum.getValueByDefaultLabel(Optional.ofNullable(map.get(adjustReasonI18n)).orElse("").toString()); } // 构建薪资档案 SalaryArchivePO finalSalaryArchive = buildSalaryArchive(isInit, employeeId, taxAgentId, importHandleParam); for (int j = 0; j < headers.size(); j++) { String key = headers.get(j); String cellVal = Optional.ofNullable(map.get(key)).orElse("").toString(); boolean isEmpty = StringUtils.isEmpty(cellVal) && (userNameI18n.equals(key) // 个税扣缴义务人列判空(初始化导入或调整个税扣缴义务人) || (taxAgentI18n.equals(key) && (isInit || isTaxAgentAdjust)) || effectiveTimeI18n.equals(key) // 调整原因列判空(调薪或调整个税扣缴义务人) || (adjustReasonI18n.equals(key) && (isTaxAgentAdjust || isSalaryItemAdjust))); // 判空 if (userNameI18n.equals(key) && StringUtils.isEmpty(cellVal)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + key + "不能为空"); excelComments.add(errorMessageMap); } // 个税扣缴义务人列判空(初始化导入或调整个税扣缴义务人) if ((taxAgentI18n.equals(key) && (isInit || isTaxAgentAdjust)) && StringUtils.isEmpty(cellVal)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + key + "不能为空"); excelComments.add(errorMessageMap); } if (effectiveTimeI18n.equals(key) && StringUtils.isEmpty(cellVal)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + key + "不能为空"); excelComments.add(errorMessageMap); } // 调整原因列判空(调薪或调整个税扣缴义务人) if ((adjustReasonI18n.equals(key) && (isTaxAgentAdjust || isSalaryItemAdjust)) && StringUtils.isEmpty(cellVal)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + key + "不能为空"); excelComments.add(errorMessageMap); } if (isEmpty) { isError = true; } // 1.姓名列处理 if (!isEmpty && userNameI18n.equals(key)) { if (CollectionUtils.isEmpty(employeeSameIds) || employeeSameIds.size() > 1) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + "员工信息不能为空且不可重复(姓名与部门同时确认唯一)"); excelComments.add(errorMessageMap); isError = true; } else if (employeeId == null) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + "姓名错误,系统内不存在该姓名"); excelComments.add(errorMessageMap); isError = true; // (调薪或调整个税扣缴义务人) } else if (finalSalaryArchive == null && (isTaxAgentAdjust || isSalaryItemAdjust)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + "该人员的薪资档案不存在,请先初始化"); excelComments.add(errorMessageMap); isError = true; } //设置当前的待校验人员id importHandleParam.setEmployeeId(employeeId); } else if (!isEmpty && taxAgentI18n.equals(key) && (isInit || isTaxAgentAdjust)) { // 2.个税扣缴义务人列处理(初始化导入或调整个税扣缴义务人) isError = handleTaxAgent(isError, isInit, effectiveTimeIndex, excelComments, errorCount, j, taxAgentId, effectiveTime, finalSalaryArchive, adjustReason, importHandleParam, map); } else if (!isEmpty && effectiveTimeI18n.equals(key) && effectiveTime == null) { // 3.生效时间处理 Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + "生效日期错误或格式不正确,正确格式示例为'2022-01-01'、'2022/1/1'"); excelComments.add(errorMessageMap); // salaryBatchService.createExcelComment(excelComments, SalaryI18nUtil.getI18nLabel(102497, "生效日期错误或格式不正确,正确格式示例为'2022-01-01'、'2022/1/1'"), errorCount + 1, errorCount + 1, j, j); isError = true; // 4.调整原因列处理(调薪或调整个税扣缴义务人) } else if (!isEmpty && adjustReasonI18n.equals(key) && (isTaxAgentAdjust || isSalaryItemAdjust) && StringUtils.isEmpty(adjustReason)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + "调整原因异常"); excelComments.add(errorMessageMap); isError = true; // 5.薪资项目列处理(初始化导入或调薪) } else { // 薪资项目数据 if (effectiveTime == null || finalSalaryArchive == null || !(isInit || isSalaryItemAdjust)) { continue; } isError = handleSalaryItem(isError, isInit, effectiveTimeIndex, excelComments, errorCount, j, effectiveTime, finalSalaryArchive, adjustReason, importHandleParam, key, cellVal, map); } } return isError; } private SalaryArchivePO buildSalaryArchive(boolean isInit, Long employeeId, Long taxAgentId, SalaryArchiveImportHandleParam importHandleParam) { Optional optionalSA = importHandleParam.getSalaryArchives().stream().filter(p -> p.getEmployeeId().equals(employeeId) && p.getTaxAgentId().equals(taxAgentId)).findFirst(); SalaryArchivePO salaryArchive = null; if (optionalSA.isPresent()) { // 修改档案 SalaryArchiveListDTO sa = optionalSA.get(); salaryArchive = new SalaryArchivePO(); salaryArchive.setId(sa.getId()); salaryArchive.setEmployeeId(sa.getEmployeeId()); salaryArchive.setTaxAgentId(sa.getTaxAgentId()); } else if (employeeId != null && isInit) { // 新增档案 salaryArchive = SalaryArchivePO.builder() .id(IdGenerator.generate()) .employeeId(employeeId) .taxAgentId(taxAgentId) .createTime(importHandleParam.getNowTime()) .updateTime(importHandleParam.getNowTime()) .creator((long) user.getUID()) .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY) .build(); importHandleParam.getSalaryArchiveSaves().add(salaryArchive); } return salaryArchive; } /** * 个税扣缴义务人处理 * * @param isError * @param excelComments * @param errorCount * @param j * @param taxAgentId * @param effectiveTime * @param finalSalaryArchive * @param taxAgentAdjustReason * @param importHandleParam * @return */ private boolean handleTaxAgent(boolean isError, boolean isInit, int effectiveTimeIndex, List> excelComments, int errorCount, int j, Long taxAgentId, Date effectiveTime, SalaryArchivePO finalSalaryArchive, String taxAgentAdjustReason, SalaryArchiveImportHandleParam importHandleParam, Map map) { String rowindex = "第" + map.get("index") + "行"; //分权 Boolean openDevolution = importHandleParam.getOpenDevolution(); Collection taxAgentList = importHandleParam.getTaxAgentList(); Set taxAgents = SalaryEntityUtil.properties(taxAgentList, TaxAgentPO::getId); if (taxAgentId == null) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + "个税扣缴义务人不存在"); excelComments.add(errorMessageMap); isError = true; } else if (!taxAgents.contains(taxAgentId)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + "没有该个税扣缴义务人的权限"); excelComments.add(errorMessageMap); isError = true; } //人员是否在扣缴义务人范围内 if (openDevolution) { Optional taxAgentEmployees = importHandleParam.getListTaxAgentAndEmployeeTree().stream().filter(m -> m.getTaxAgentId().equals(taxAgentId)).findFirst(); Optional optionalTaxAgentEmp = taxAgentEmployees.get().getEmployeeList().stream().filter(f -> f.getEmployeeId().equals(importHandleParam.getEmployeeId())).findFirst(); if (!optionalTaxAgentEmp.isPresent()) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + "该条数据不在个税扣缴义务人人员范围内,不可导入"); excelComments.add(errorMessageMap); isError = true; } } if (effectiveTime != null && finalSalaryArchive != null) { boolean isBeforeError = false; if (!isInit) { // 前后调整校验 // 已生效 List effectiveList = importHandleParam.getEffectiveTaxAgentList().stream().filter(i -> finalSalaryArchive.getId().equals(i.getSalaryArchiveId())).collect(Collectors.toList()); // 当前已生效 SalaryArchiveTaxAgentPO effectiveTaxAgent = CollectionUtils.isNotEmpty(effectiveList) && effectiveList.size() > 0 ? effectiveList.get(0) : null; // 当前已生效的前一次调整 SalaryArchiveTaxAgentPO effectiveBeforeTaxAgent = CollectionUtils.isNotEmpty(effectiveList) && effectiveList.size() > 1 ? effectiveList.get(1) : null; // 未生效 Optional optionalIneffective = importHandleParam.getIneffectiveTaxAgentList().stream().filter(i -> finalSalaryArchive.getId().equals(i.getSalaryArchiveId())).findFirst(); SalaryArchiveTaxAgentPO ineffectiveTaxAgent = optionalIneffective.orElse(null); // 1.检验是否可以调整 if (effectiveTaxAgent != null) { // 当前已经生效的时间 Date currentEffectiveTime = effectiveTaxAgent.getEffectiveTime(); // 1.1 如果早于<当前已生效 if (effectiveTime.before(currentEffectiveTime)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + "个税扣缴义务人生效日期不可早于当前已生效的调整日期"); excelComments.add(errorMessageMap); // salaryBatchService.createExcelComment(excelComments, SalaryI18nUtil.getI18nLabel(100429, "生效日期不可早于当前已生效的调整日期"), errorCount + 1, errorCount + 1, effectiveTimeIndex, effectiveTimeIndex); isError = true; isBeforeError = true; // 1.2 如果等于当前已生效 } else if (effectiveTime.equals(currentEffectiveTime)) { if (effectiveBeforeTaxAgent != null && effectiveBeforeTaxAgent.getTaxAgentId().equals(taxAgentId)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + "个税扣缴义务人调整前后不可相同"); excelComments.add(errorMessageMap); // salaryBatchService.createExcelComment(excelComments, SalaryI18nUtil.getI18nLabel(100432, "调整前后不可相同"), errorCount + 1, errorCount + 1, j, j); isError = true; } if (ineffectiveTaxAgent != null && ineffectiveTaxAgent.getTaxAgentId().equals(taxAgentId)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + "个税扣缴义务人与未生效的调整后不可相同"); excelComments.add(errorMessageMap); // salaryBatchService.createExcelComment(excelComments, SalaryI18nUtil.getI18nLabel(100434, "与未生效的调整后不可相同"), errorCount + 1, errorCount + 1, j, j); isError = true; } // 1.3 如果>已经生效且<=今天 } else if (effectiveTime.after(currentEffectiveTime) && !effectiveTime.after(importHandleParam.getToday())) { if (effectiveTaxAgent.getTaxAgentId().equals(taxAgentId)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + "个税扣缴义务人调整前后不可相同"); excelComments.add(errorMessageMap); // salaryBatchService.createExcelComment(excelComments, SalaryI18nUtil.getI18nLabel(100432, "调整前后不可相同"), errorCount + 1, errorCount + 1, j, j); isError = true; } if (ineffectiveTaxAgent != null && ineffectiveTaxAgent.getTaxAgentId().equals(taxAgentId)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + "个税扣缴义务人与未生效的调整后不可相同"); excelComments.add(errorMessageMap); // salaryBatchService.createExcelComment(excelComments, SalaryI18nUtil.getI18nLabel(100434, "与未生效的调整后不可相同"), errorCount + 1, errorCount + 1, j, j); isError = true; } // 1.4 如果>今天 } else if (effectiveTime.after(importHandleParam.getToday()) && effectiveTaxAgent.getTaxAgentId().equals(taxAgentId)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + "个税扣缴义务人调整前后不可相同"); excelComments.add(errorMessageMap); // salaryBatchService.createExcelComment(excelComments, SalaryI18nUtil.getI18nLabel(100432, "调整前后不可相同"), errorCount + 1, errorCount + 1, j, j); isError = true; } } else if (ineffectiveTaxAgent != null && ineffectiveTaxAgent.getTaxAgentId().equals(taxAgentId)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + "个税扣缴义务人与未生效的调整后不可相同"); excelComments.add(errorMessageMap); // salaryBatchService.createExcelComment(excelComments, SalaryI18nUtil.getI18nLabel(100434, "与未生效的调整后不可相同"), errorCount + 1, errorCount + 1, j, j); isError = true; } // 2.数据处理,有的就先删后增 if (effectiveTaxAgent != null && effectiveTime.equals(effectiveTaxAgent.getEffectiveTime())) { importHandleParam.getSalaryArchiveTaxAgentDelTaxAgentIds().add(effectiveTaxAgent.getId()); } if (ineffectiveTaxAgent != null && effectiveTime.after(importHandleParam.getToday())) { importHandleParam.getSalaryArchiveTaxAgentDelTaxAgentIds().add(ineffectiveTaxAgent.getId()); } } if (!isBeforeError) { importHandleParam.getSalaryArchiveTaxAgentSaves().add(SalaryArchiveTaxAgentPO.builder() // .id(IdGenerator.generate()) .salaryArchiveId(finalSalaryArchive.getId()) .employeeId(finalSalaryArchive.getEmployeeId()) .taxAgentId(taxAgentId) .effectiveTime(effectiveTime) .adjustReason(StringUtils.isEmpty(taxAgentAdjustReason) ? SalaryArchiveTaxAgentAdjustReasonEnum.INIT.getValue() : taxAgentAdjustReason) .operator((long) user.getUID()) .operateTime(importHandleParam.getNowTime()) .createTime(importHandleParam.getNowTime()) .updateTime(importHandleParam.getNowTime()) .creator((long) user.getUID()) .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY) .build()); } } return isError; } /** * 薪资项目处理 * * @param isError * @param excelComments * @param errorCount * @param j * @param effectiveTime * @param finalSalaryArchive * @param salaryItemAdjustReason * @param importHandleParam * @param cellVal * @return */ private boolean handleSalaryItem(boolean isError, boolean isInit, int effectiveTimeIndex, List> excelComments, int errorCount, int j, Date effectiveTime, SalaryArchivePO finalSalaryArchive, String salaryItemAdjustReason, SalaryArchiveImportHandleParam importHandleParam, String key, String cellVal, Map map) { String rowindex = "第" + map.get("index") + "行"; Optional optionalSalaryItem = importHandleParam.getSalaryItems().stream().filter(e -> e.getName().equals(key)).findFirst(); if (optionalSalaryItem.isPresent()) { Long salaryItemId = optionalSalaryItem.get().getId(); boolean isBeforeError = false; if (!isInit) { // 已生效 List effectiveList = importHandleParam.getEffectiveItemList().stream().filter(i -> finalSalaryArchive.getId().equals(i.getSalaryArchiveId()) && i.getSalaryItemId().equals(salaryItemId)).collect(Collectors.toList()); // 当前已生效 SalaryArchiveItemPO effectiveSalaryItem = CollectionUtils.isNotEmpty(effectiveList) && effectiveList.size() > 0 ? effectiveList.get(0) : null; // 当前已生效的前一次调整 SalaryArchiveItemPO effectiveBeforeSalaryItem = CollectionUtils.isNotEmpty(effectiveList) && effectiveList.size() > 1 ? effectiveList.get(1) : null; // 未生效 Optional optionalIneffective = importHandleParam.getIneffectiveItemList().stream().filter(i -> finalSalaryArchive.getId().equals(i.getSalaryArchiveId()) && i.getSalaryItemId().equals(salaryItemId)).findFirst(); SalaryArchiveItemPO ineffectiveSalaryItem = optionalIneffective.orElse(null); // 1.检验是否可以调整 if (effectiveSalaryItem != null) { // 当前已经生效的时间 Date currentEffectiveTime = effectiveSalaryItem.getEffectiveTime(); // 1.1 如果早于<当前已生效 if (effectiveTime.before(currentEffectiveTime)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + key + "生效日期不可早于当前已生效的调整日期"); excelComments.add(errorMessageMap); // salaryBatchService.createExcelComment(excelComments, SalaryI18nUtil.getI18nLabel(100429, "生效日期不可早于当前已生效的调整日期"), errorCount + 1, errorCount + 1, effectiveTimeIndex, effectiveTimeIndex); isError = true; isBeforeError = true; // 1.2 如果等于当前已生效 } else if (effectiveTime.equals(currentEffectiveTime)) { if (effectiveBeforeSalaryItem != null && effectiveBeforeSalaryItem.getItemValue().equals(cellVal)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + key + "调整前后不可相同"); excelComments.add(errorMessageMap); // salaryBatchService.createExcelComment(excelComments, SalaryI18nUtil.getI18nLabel(100432, "调整前后不可相同"), errorCount + 1, errorCount + 1, j, j); isError = true; } if (ineffectiveSalaryItem != null && ineffectiveSalaryItem.getItemValue().equals(cellVal)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + key + "与未生效的调整后不可相同"); excelComments.add(errorMessageMap); // salaryBatchService.createExcelComment(excelComments, SalaryI18nUtil.getI18nLabel(100434, "与未生效的调整后不可相同"), errorCount + 1, errorCount + 1, j, j); isError = true; } // 1.3 如果>已经生效且<=今天 } else if (effectiveTime.after(currentEffectiveTime) && !effectiveTime.after(importHandleParam.getToday())) { if (effectiveSalaryItem.getItemValue().equals(cellVal)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + key + "调整前后不可相同"); excelComments.add(errorMessageMap); // salaryBatchService.createExcelComment(excelComments, SalaryI18nUtil.getI18nLabel(100432, "调整前后不可相同"), errorCount + 1, errorCount + 1, j, j); isError = true; } if (ineffectiveSalaryItem != null && ineffectiveSalaryItem.getItemValue().equals(cellVal)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + key + "与未生效的调整后不可相同"); excelComments.add(errorMessageMap); // salaryBatchService.createExcelComment(excelComments, SalaryI18nUtil.getI18nLabel(100434, "与未生效的调整后不可相同"), errorCount + 1, errorCount + 1, j, j); isError = true; } // 1.4 如果>今天 } else if (effectiveTime.after(importHandleParam.getToday()) && effectiveSalaryItem.getItemValue().equals(cellVal)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + key + "调整前后不可相同"); excelComments.add(errorMessageMap); // salaryBatchService.createExcelComment(excelComments, SalaryI18nUtil.getI18nLabel(100432, "调整前后不可相同"), errorCount + 1, errorCount + 1, j, j); isError = true; } } else if (ineffectiveSalaryItem != null && ineffectiveSalaryItem.getItemValue().equals(cellVal)) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowindex + key + "与未生效的调整后不可相同"); excelComments.add(errorMessageMap); // salaryBatchService.createExcelComment(excelComments, SalaryI18nUtil.getI18nLabel(100434, "与未生效的调整后不可相同"), errorCount + 1, errorCount + 1, j, j); isError = true; } // 2.数据处理 if (effectiveSalaryItem != null && effectiveTime.equals(effectiveSalaryItem.getEffectiveTime())) { importHandleParam.getSalaryArchiveItemDelSalaryItemIds().add(effectiveSalaryItem.getId()); } if (ineffectiveSalaryItem != null && effectiveTime.after(importHandleParam.getToday())) { importHandleParam.getSalaryArchiveItemDelSalaryItemIds().add(ineffectiveSalaryItem.getId()); } } if (!isBeforeError) { importHandleParam.getSalaryArchiveItemSaves().add(SalaryArchiveItemPO.builder() // .id(IdGenerator.generate()) .salaryArchiveId(finalSalaryArchive.getId()) .employeeId(finalSalaryArchive.getEmployeeId()) .effectiveTime(effectiveTime) .adjustReason(StringUtils.isEmpty(salaryItemAdjustReason) ? SalaryArchiveItemAdjustReasonEnum.INIT.getValue() : salaryItemAdjustReason) .salaryItemId(salaryItemId) .itemValue(cellVal) .description("") .operator((long) user.getUID()) .operateTime(importHandleParam.getNowTime()) .createTime(importHandleParam.getNowTime()) .updateTime(importHandleParam.getNowTime()) .creator((long) user.getUID()) .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY) .build()); } // 用于初始化导入,同一个人的多行记录之间的薪资项目是否调整 map.put("salaryItemVal", Optional.ofNullable(map.get("salaryItemVal")).orElse("").toString() + salaryItemId + cellVal); } return isError; } /** * 字符串转日期 * 兼容/和- * * @param effectiveTime * @return */ private Date dateStrToLocalDate(String effectiveTime) { Date localDate = null; try { if (effectiveTime.contains("/")) { SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd"); localDate = format.parse(effectiveTime); } else if (effectiveTime.contains("-")) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); localDate = format.parse(effectiveTime); } } catch (Exception e) { localDate = null; } return localDate; } private List getEffectiveItemList(Collection salaryItemIds) { long currentEmployeeId = user.getUID(); // 没有薪资项目时,给个不存在的,否则加载所有不合理 if (CollectionUtils.isEmpty(salaryItemIds)) { return new ArrayList<>(); } Date truncate = DateUtils.truncate(new Date(), Calendar.DATE); return salaryArchiveItemMapper.getEffectiveSalaryItems(SalaryArchiveItemQueryParam.builder().effectiveTime(truncate).salaryItemIds(salaryItemIds).build()); } private List getIneffectiveItemList(Collection salaryItemIds) { long currentEmployeeId = user.getUID(); // 没有薪资项目时,给个不存在的,否则加载所有不合理 if (CollectionUtils.isEmpty(salaryItemIds)) { return new ArrayList<>(); } Date truncate = DateUtils.truncate(new Date(), Calendar.DATE); return salaryArchiveItemMapper.getIneffectiveSalaryItems(SalaryArchiveItemQueryParam.builder().salaryItemIds(salaryItemIds).effectiveTime(truncate).build()); } private List getEffectiveTaxAgentList() { Date truncate = DateUtils.truncate(new Date(), Calendar.DATE); return salaryArchiveTaxAgentMapper.getEffectiveTaxAgentList(SalaryArchiveTaxAgentQueryParam.builder().effectiveTime(truncate).build()); } private List getIneffectiveTaxAgentList() { Date truncate = DateUtils.truncate(new Date(), Calendar.DATE); return salaryArchiveTaxAgentMapper.getIneffectiveTaxAgentList(SalaryArchiveTaxAgentQueryParam.builder().effectiveTime(truncate).build()); } /** * 检查列头 * * @param importType * @param headers * @return */ private boolean checkHeaders(String importType, List headers) { boolean isValid = true; boolean isInit = importType.equals(SalaryArchiveImportTypeEnum.INIT.getValue()); boolean isTaxAgentAdjust = importType.equals(SalaryArchiveImportTypeEnum.TAXAGENTADJUST.getValue()); boolean isSalaryItemAdjust = importType.equals(SalaryArchiveImportTypeEnum.SALARYITEMADJUST.getValue()); String userNameI18n = SalaryI18nUtil.getI18nLabel(85429, "姓名"); String taxAgentI18n = SalaryI18nUtil.getI18nLabel(86184, "个税扣缴义务人"); String effectiveTimeI18n = SalaryI18nUtil.getI18nLabel(85904, "生效日期"); String adjustReasonI18n = SalaryI18nUtil.getI18nLabel(85431, "调整原因"); List mustHeaders = Lists.newArrayList(); if (isInit) { mustHeaders.add(userNameI18n); mustHeaders.add(taxAgentI18n); mustHeaders.add(effectiveTimeI18n); } else if (isTaxAgentAdjust) { mustHeaders.add(userNameI18n); mustHeaders.add(taxAgentI18n); mustHeaders.add(effectiveTimeI18n); mustHeaders.add(adjustReasonI18n); } else if (isSalaryItemAdjust) { mustHeaders.add(userNameI18n); mustHeaders.add(effectiveTimeI18n); mustHeaders.add(adjustReasonI18n); } // 缺少的必须列 List lackHeaders = mustHeaders.stream().filter(item -> !headers.contains(item)).collect(Collectors.toList()); String errorMsg = ""; String checkHeaderI18n = SalaryI18nUtil.getI18nLabel(101850, "缺少如下列,请检查:"); if (CollectionUtils.isNotEmpty(lackHeaders)) { errorMsg = checkHeaderI18n + Joiner.on(",").join((Iterable) lackHeaders); } // 有错误信息发送 if (StringUtils.isNotEmpty(errorMsg)) { throw new SalaryRunTimeException(errorMsg); } return isValid; } /** * 数据落库处理 * * @param importHandleParam */ private void handleImportData(boolean isInit, SalaryArchiveImportHandleParam importHandleParam) { List salaryArchiveSaves = importHandleParam.getSalaryArchiveSaves(); List salaryArchiveTaxAgentSaves = importHandleParam.getSalaryArchiveTaxAgentSaves(); List salaryArchiveItemSaves = importHandleParam.getSalaryArchiveItemSaves(); List salaryArchiveTaxAgentDelTaxAgentIds = importHandleParam.getSalaryArchiveTaxAgentDelTaxAgentIds(); List salaryArchiveItemDelSalaryItemIds = importHandleParam.getSalaryArchiveItemDelSalaryItemIds(); // 初始化导入 if (isInit) { List salaryArchiveTaxAgentIds = importHandleParam.getSalaryArchiveTaxAgentSaves().stream().map(SalaryArchiveTaxAgentPO::getSalaryArchiveId).distinct().collect(Collectors.toList()); List salaryArchiveItemIds = importHandleParam.getSalaryArchiveItemSaves().stream().map(SalaryArchiveItemPO::getSalaryArchiveId).distinct().collect(Collectors.toList()); List salaryArchiveIds = salaryArchiveTaxAgentIds.stream().filter(salaryArchiveItemIds::contains).collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(salaryArchiveIds)) { List> partitionSalaryArchiveIds = Lists.partition(salaryArchiveIds, 1000); for (List partitions : partitionSalaryArchiveIds) { salaryArchiveTaxAgentMapper.deleteBySalaryArchiveId(partitions); salaryArchiveItemMapper.deleteBySalaryArchiveId(partitions); } } } else { if (CollectionUtils.isNotEmpty(salaryArchiveTaxAgentDelTaxAgentIds)) { salaryArchiveTaxAgentMapper.deleteBatchIds(salaryArchiveTaxAgentDelTaxAgentIds); } if (CollectionUtils.isNotEmpty(salaryArchiveItemDelSalaryItemIds)) { salaryArchiveItemMapper.deleteBatchIds(salaryArchiveItemDelSalaryItemIds); } } // 新增薪资档案 if (CollectionUtils.isNotEmpty(salaryArchiveSaves)) { // 薪资档案 salaryArchiveMapper.batchInsert(salaryArchiveSaves); } // 薪资档案-个税扣缴义务人 if (CollectionUtils.isNotEmpty(salaryArchiveTaxAgentSaves)) { salaryArchiveTaxAgentMapper.batchInsert(salaryArchiveTaxAgentSaves); } // 薪资档案-薪资项目 if (CollectionUtils.isNotEmpty(salaryArchiveItemSaves)) { salaryArchiveItemMapper.batchInsert(salaryArchiveItemSaves); } } /** * 处理历史数据 * 下回发版可删除 */ public void handleHistory(Long currentEmployeeId) { // 待定薪没设置过的默认为正常工资薪金所得 // new LambdaUpdateChainWrapper<>(salaryArchiveMapper) // .eq(SalaryArchivePO::getDeleteType, 0) // .eq(SalaryArchivePO::getTenantKey, tenantKey) // .eq(SalaryArchivePO::getRunStatus, SalaryArchiveStatusEnum.PENDING.getValue()) // .isNull(SalaryArchivePO::getIncomeCategory) // .set(SalaryArchivePO::getIncomeCategory, IncomeCategoryEnum.WAGES_AND_SALARIES.getValue()) // .update(); List salaryArchives = getSalaryArchiveMapper().getHistoryData(); log.info("处理历史数据开始,数据总量==============={}", salaryArchives.size()); if (CollectionUtils.isEmpty(salaryArchives)) { return; } Date today = new Date(); List salaryArchiveTaxAgents = getEffectiveTaxAgentList(); List salaryArchiveItems = salaryArchiveItemMapper.getEffectiveSalaryItems(SalaryArchiveItemQueryParam.builder().effectiveTime(today).build()); List salaryArchiveDelIds = salaryArchives.stream().map(SalaryArchivePO::getId).collect(Collectors.toList()); List salaryArchiveTaxAgentDelIds = salaryArchiveTaxAgents.stream().map(SalaryArchiveTaxAgentPO::getId).collect(Collectors.toList()); List salaryArchiveItemDelIds = salaryArchiveItems.stream().map(SalaryArchiveItemPO::getId).collect(Collectors.toList()); List salaryArchiveAddList = Lists.newArrayList(); List salaryArchiveItemAddList = Lists.newArrayList(); Date endDate = today; for (SalaryArchivePO sa : salaryArchives) { List saTaxAgents = salaryArchiveTaxAgents.stream().filter(t -> t.getSalaryArchiveId().equals(sa.getId())).collect(Collectors.toList()); // 去重获取最新生效的个税口角义务人列表 saTaxAgents = saTaxAgents.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(f -> f.getSalaryArchiveId() + "-" + f.getTaxAgentId()))), ArrayList::new)); List saItemList = salaryArchiveItems.stream().filter(i -> i.getSalaryArchiveId().equals(sa.getId())).collect(Collectors.toList()); for (SalaryArchiveTaxAgentPO st : saTaxAgents) { Date finalEndDate = endDate; List saItems = saItemList.stream().filter(si -> !si.getEffectiveTime().after(finalEndDate)) .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(f -> f.getSalaryArchiveId() + "-" + f.getSalaryItemId()))), ArrayList::new)); SalaryArchivePO newSA = SalaryArchivePO.builder() .id(IdGenerator.generate()) .employeeId(sa.getEmployeeId()) .taxAgentId(st.getTaxAgentId()) // .payStartDate(st.getEffectiveTime()) // .runStatus(SalaryArchiveStatusEnum.FIXED.getValue()) // .modifier(0L) .createTime(today) .updateTime(today) .creator(currentEmployeeId) .deleteType(NumberUtils.INTEGER_ZERO) .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY) .build(); salaryArchiveAddList.add(newSA); saItems.forEach(sf -> { salaryArchiveItemAddList.add(SalaryArchiveItemPO.builder() // .id(IdGenerator.generate()) .salaryArchiveId(newSA.getId()) .employeeId(newSA.getEmployeeId()) .effectiveTime(sf.getEffectiveTime()) .adjustReason(sf.getAdjustReason()) .salaryItemId(sf.getSalaryItemId()) .itemValue(sf.getItemValue()) .description(sf.getDescription()) // 不用设置操作人 .operator(currentEmployeeId) .operateTime(today) .createTime(today) .updateTime(today) .creator(currentEmployeeId) .deleteType(NumberUtils.INTEGER_ZERO) .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY) .build()); }); endDate = st.getEffectiveTime(); } } // 逻辑删除历史数据 List> partition = Lists.partition(salaryArchiveDelIds, 999); for (List part : partition) { salaryArchiveMapper.batchDeleteHistoryData(SalaryArchivePO.builder().ids(part).build()); } List> partitionTA = Lists.partition(salaryArchiveTaxAgentDelIds, 999); for (List part : partitionTA) { salaryArchiveTaxAgentMapper.batchDeleteHistoryData(SalaryArchiveTaxAgentPO.builder().ids(part).build()); } List> partitionItem = Lists.partition(salaryArchiveItemDelIds, 999); for (List part : partitionItem) { salaryArchiveItemMapper.batchDeleteHistoryData(SalaryArchiveItemPO.builder().ids(part).build()); } // 新增迁移数据 if (CollectionUtils.isNotEmpty(salaryArchiveAddList)) { this.salaryArchiveMapper.batchInsert(salaryArchiveAddList); } if (CollectionUtils.isNotEmpty(salaryArchiveItemAddList)) { this.salaryArchiveItemMapper.batchInsert(salaryArchiveItemAddList); } log.info("处理历史数据结束==============="); } }