package com.engine.salary.service.impl; import com.api.formmode.mybatis.util.SqlProxyHandle; import com.engine.common.util.ServiceUtil; import com.engine.core.impl.Service; import com.engine.hrm.biz.OrganizationShowSetBiz; import com.engine.salary.biz.SalarySobRangeBiz; import com.engine.salary.biz.SpecialAddDeductionBiz; import com.engine.salary.config.SalaryElogConfig; import com.engine.salary.elog.entity.dto.LoggerContext; import com.engine.salary.entity.datacollection.DataCollectionEmployee; import com.engine.salary.entity.hrm.DeptInfo; import com.engine.salary.entity.hrm.PositionInfo; import com.engine.salary.entity.hrm.SubCompanyInfo; import com.engine.salary.entity.salarysob.bo.SalarySobRangeBO; import com.engine.salary.entity.salarysob.bo.SalarySobRangeSaveBO; import com.engine.salary.entity.salarysob.dto.SalarySobRangeImportListDTO; import com.engine.salary.entity.salarysob.dto.SalarySobRangeListDTO; import com.engine.salary.entity.salarysob.param.SalarySobRangeImportParam; import com.engine.salary.entity.salarysob.param.SalarySobRangeQueryParam; import com.engine.salary.entity.salarysob.param.SalarySobRangeSaveParam; import com.engine.salary.entity.salarysob.po.SalarySobPO; import com.engine.salary.entity.salarysob.po.SalarySobRangePO; import com.engine.salary.entity.taxagent.dto.TaxAgentManageRangeEmployeeDTO; import com.engine.salary.enums.OperateTypeEnum; import com.engine.salary.enums.UserStatusEnum; import com.engine.salary.enums.salarysob.SalaryEmployeeStatusEnum; import com.engine.salary.enums.salarysob.TargetTypeEnum; import com.engine.salary.exception.SalaryRunTimeException; import com.engine.salary.mapper.salarysob.SalarySobExtRangeMapper; import com.engine.salary.mapper.sys.SalarySysConfMapper; import com.engine.salary.service.SalaryEmployeeService; import com.engine.salary.service.SalarySobRangeService; import com.engine.salary.service.SalarySobService; import com.engine.salary.service.TaxAgentService; import com.engine.salary.sys.entity.po.SalarySysConfPO; import com.engine.salary.util.SalaryEntityUtil; import com.engine.salary.util.SalaryI18nUtil; import com.engine.salary.util.excel.ExcelComment; import com.engine.salary.util.excel.ExcelParseHelper; import com.engine.salary.util.excel.ExcelUtil; import com.engine.salary.util.page.PageInfo; import com.engine.salary.util.page.SalaryPageUtil; import com.engine.salary.util.valid.ValidUtil; 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.Validate; import org.apache.poi.util.IOUtils; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import weaver.file.ImageFileManager; import weaver.general.Util; import weaver.hrm.User; import java.io.InputStream; import java.util.*; import java.util.stream.Collectors; /** * 薪资账套人员范围 *

Copyright: Copyright (c) 2022

*

Company: 泛微软件

* * @author qiantao * @version 1.0 **/ public class SalarySobRangeServiceImpl extends Service implements SalarySobRangeService { private SalarySobRangeBiz salarySobRangeBiz = new SalarySobRangeBiz(); private OrganizationShowSetBiz orgBiz = new OrganizationShowSetBiz(); private SalarySobService getSalarySobService(User user) { return (SalarySobService) ServiceUtil.getService(SalarySobServiceImpl.class, user); } private TaxAgentService getTaxAgentService(User user) { return ServiceUtil.getService(TaxAgentServiceImpl.class, user); } private SalaryEmployeeService getSalaryEmployeeService(User user) { return ServiceUtil.getService(SalaryEmployeeServiceImpl.class, user); } private SalarySysConfMapper getSalarySysConfMapper() { return SqlProxyHandle.getProxy(SalarySysConfMapper.class); } private SalarySobExtRangeMapper getSalarySobExtRangeMapper() { return SqlProxyHandle.getProxy(SalarySobExtRangeMapper.class); } @Override public List listByIds(Collection ids) { if (CollectionUtils.isEmpty(ids)) { return Collections.emptyList(); } return salarySobRangeBiz.listSome(SalarySobRangePO.builder().ids(ids).build()); } @Override public List listBySalarySobIdAndIncludeType(Long salarySobId, Integer includeType) { return salarySobRangeBiz.listSome(SalarySobRangePO.builder().salarySobId(salarySobId).includeType(includeType).build()); } @Override public List listAllSalarySobRange() { return salarySobRangeBiz.listSome(SalarySobRangePO.builder().build()); } @Override public PageInfo listPageByParamAndIncludeType(SalarySobRangeQueryParam queryParam, Integer includeType) { // 查询人员范围 List salarySobRangePOS = listBySalarySobIdAndIncludeType(queryParam.getSalarySobId(), includeType); // 查询人员信息 List employeeIds = salarySobRangePOS.stream() .filter(e -> Objects.equals(e.getTargetType(), TargetTypeEnum.EMPLOYEE.getValue())) .map(SalarySobRangePO::getTargetId) .collect(Collectors.toList()); List empInfos = getSalaryEmployeeService(user).getEmployeeByIds(employeeIds); // 查询部门信息 List deptInfos = salarySobRangePOS.stream() .filter(e -> Objects.equals(e.getTargetType(), TargetTypeEnum.DEPT.getValue())) .map(SalarySobRangePO::getTargetId) .map(id -> { return DeptInfo.builder().id(id).name(orgBiz.getDepartmentShow(String.valueOf(id), "0", "-")).build(); }) .collect(Collectors.toList()); // 查询分部信息 List subCompanyInfos = salarySobRangePOS.stream() .filter(e -> Objects.equals(e.getTargetType(), TargetTypeEnum.SUBCOMPANY.getValue())) .map(SalarySobRangePO::getTargetId) .map(id -> { return SubCompanyInfo.builder().id(id).name(orgBiz.getSubcompanyShow(String.valueOf(id), "0", "-")).build(); }) .collect(Collectors.toList()); // 查询岗位信息 List positionIds = salarySobRangePOS.stream() .filter(e -> Objects.equals(e.getTargetType(), TargetTypeEnum.POSITION.getValue())) .map(SalarySobRangePO::getTargetId) .collect(Collectors.toList()); List positionInfos = getSalaryEmployeeService(user).listPositionInfo(positionIds); // 薪资账套的人员范围po转换成列表dto List salarySobRangeListDTOS = SalarySobRangeBO.convert2ListDTO(salarySobRangePOS, empInfos, deptInfos, subCompanyInfos, positionInfos); // 根据对象名称过滤 if (StringUtils.isNotEmpty(queryParam.getTargetName())) { salarySobRangeListDTOS = salarySobRangeListDTOS.stream() .filter(salarySobRangeListDTO -> salarySobRangeListDTO.getTargetName().contains(queryParam.getTargetName())) .collect(Collectors.toList()); } // 填充总数和当页数据 PageInfo pageInfo = new PageInfo(salarySobRangeListDTOS, SalarySobRangeListDTO.class); pageInfo.setTotal(salarySobRangeListDTOS.size()); pageInfo.setList(SalaryPageUtil.subList(queryParam.getCurrent(), queryParam.getPageSize(), salarySobRangeListDTOS)); pageInfo.setPageNum(queryParam.getCurrent()); pageInfo.setPageSize(queryParam.getPageSize()); return pageInfo; } @Override public void save(SalarySobRangeSaveParam saveParam) { ValidUtil.doValidator(saveParam); // 查询薪资账套 SalarySobPO salarySobPO = getSalarySobService(user).getById(saveParam.getSalarySobId()); if (Objects.isNull(salarySobPO)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98379, "参数错误,薪资账套不存在或者已被删除")); } // 查询已有的人员范围 List salarySobRangePOS = listBySalarySobIdAndIncludeType(saveParam.getSalarySobId(), saveParam.getIncludeType()); // 处理一下本次的保存参数(如果原来添加过对应的人员(/部门/岗位),那么本次不需要新增,只需要更新) SalarySobRangeSaveBO.Result result = SalarySobRangeSaveBO.handle(salarySobRangePOS, saveParam, (long) user.getUID(), false); // 保存 if (CollectionUtils.isNotEmpty(result.getNeedInsertSalarySobRanges())) { salarySobRangeBiz.batchInsert(result.getNeedInsertSalarySobRanges()); } if (CollectionUtils.isNotEmpty(result.getNeedUpdateSalarySobRanges())) { result.getNeedUpdateSalarySobRanges().forEach(e -> salarySobRangeBiz.updateById(e)); } //记录日志 String operateTypeName = Objects.equals(saveParam.getIncludeType(), 1) ? SalaryI18nUtil.getI18nLabel(98601, "关联人员范围新增对象") : SalaryI18nUtil.getI18nLabel(98602, "从范围中排除新增对象"); LoggerContext loggerContext = new LoggerContext<>(); loggerContext.setUser(user); loggerContext.setTargetId("" + salarySobPO.getId()); loggerContext.setTargetName(salarySobPO.getName()); loggerContext.setOperateType(OperateTypeEnum.UPDATE.getValue()); loggerContext.setOperateTypeName(operateTypeName); loggerContext.setOperatedesc(operateTypeName); loggerContext.setNewValues(saveParam); SalaryElogConfig.salarySobLoggerTemplate.write(loggerContext); } @Override public void deleteByIds(Collection ids) { // 查询薪资账套的人员范围 List salarySobRangePOS = listByIds(ids); if (CollectionUtils.isEmpty(salarySobRangePOS)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98604, "数据不存在或已被删除")); } ids = SalaryEntityUtil.properties(salarySobRangePOS, SalarySobRangePO::getId); // 删除薪资账套的人员范围 salarySobRangeBiz.deleteByIds(ids); // 查询薪资账套 // Set salarySobIds = SalaryEntityUtil.properties(salarySobRangePOS, SalarySobRangePO::getSalarySobId); // List salarySobPOS = getSalarySobService(user).listByIds(salarySobIds); // // 是"关联人员范围"还是"从范围中排除" // Integer includeType = salarySobRangePOS.get(0).getIncludeType(); // // todo 记录日志 // String operateTypeName = Objects.equals(includeType, NumberUtils.INTEGER_ONE) ? // SalaryI18nUtil.getI18nLabel(98605, "关联人员范围删除对象") : SalaryI18nUtil.getI18nLabel(98606, "从范围中排除删除对象"); // salarySobPOS.forEach(salarySobPO -> { // LoggerContext loggerContext = new LoggerContext<>(); // loggerContext.setTargetId("" + salarySobPO.getId()); // loggerContext.setTargetName(salarySobPO.getName()); // loggerContext.setOperateType(OperateTypeEnum.DELETE.getValue()); // loggerContext.setOperateTypeName(operateTypeName); // loggerContext.setOperatedesc(operateTypeName); // }); } @Override public void deleteBySalarySobIds(Collection salarySobIds) { salarySobRangeBiz.deleteBySalarySobIds(salarySobIds); } @Override public void updateEmployeeStatuses(SalarySobRangePO item) { salarySobRangeBiz.updateEmployeeStatuses(item); } @Override public XSSFWorkbook downloadTemplateRange() { //获取操作按钮资源 List> rowList = getExcelRowList(); //查询对于人员信息导入筛选的全局配置 SalarySysConfPO salarySysConfPO = getSalarySysConfMapper().getOneByCode("matchEmployeeMode"); String confValue = (salarySysConfPO != null && salarySysConfPO.getConfValue() != null && !"".equals(salarySysConfPO.getConfValue())) ? salarySysConfPO.getConfValue() : "0"; // 注释 List excelComments = Lists.newArrayList(); if (confValue.equals("1")) { // 人员校验规则为工号 excelComments.add(new ExcelComment(3, 0, 4, 2, SalaryI18nUtil.getI18nLabel(100344, "必填"))); } else { excelComments.add(new ExcelComment(0, 0, 1, 2, SalaryI18nUtil.getI18nLabel(100344, "必填"))); } excelComments.add(new ExcelComment(4, 0, 6, 3, SalaryI18nUtil.getI18nLabel(100344, "若不填,默认全部员工状态。指定员工状态格式:试用、正式、临时、试用延期"))); //获取excel return ExcelUtil.genWorkbookV2(rowList, "薪资账套人员范围", excelComments); } @Override public Map importData(SalarySobRangeImportParam importParam) { Boolean openDevolution = getTaxAgentService(user).isOpenDevolution(); long currentEmployeeId = user.getUID(); Map apidatas = new HashMap(); SpecialAddDeductionBiz SpecialAddDeductionBiz = new SpecialAddDeductionBiz(); //查询对于人员信息导入筛选的全局配置 SalarySysConfPO salarySysConfPO = getSalarySysConfMapper().getOneByCode("matchEmployeeMode"); String confValue = (salarySysConfPO != null && salarySysConfPO.getConfValue() != null && !"".equals(salarySysConfPO.getConfValue())) ? salarySysConfPO.getConfValue() : "0"; //检验参数 checkImportParam(importParam); //excel文件id String imageId = Util.null2String(importParam.getImageId()); //薪资账套ID String salarySobIdStr = Util.null2String(importParam.getSalarySobId()); Long salarySobId = SalaryEntityUtil.string2Long(salarySobIdStr); // 查询薪资账套 SalarySobPO salarySobPO = getSalarySobService(user).getById(salarySobId); if (Objects.isNull(salarySobPO)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98379, "参数错误,薪资账套不存在或者已被删除")); } InputStream fileInputStream = null; try { fileInputStream = ImageFileManager.getInputStreamById(Integer.parseInt(imageId)); List salarySobRangeImportLists = ExcelParseHelper.parse2Map(fileInputStream, SalarySobRangeImportListDTO.class, 0, 1, 5, "SpecialAddDeductionTemplate.xlsx"); int total = salarySobRangeImportLists.size(); int index = 0; int successCount = 0; int errorCount = 0; //人员信息 List employees = getSalaryEmployeeService(user).listEmployee(); // 获取所有个税扣缴义务人 Collection taxAgentList = getTaxAgentService(user).listTaxAgentAndEmployeeTree(currentEmployeeId); // 错误excel内容 List errorData = new ArrayList<>(); //合规数据 List eligibleData = new ArrayList<>(); for (int i = 0; i < salarySobRangeImportLists.size(); i++) { SalarySobRangeImportListDTO dto = salarySobRangeImportLists.get(i); //待插入数据库对象 SalarySobRangeSaveParam.SalarySobRangeTargetParam po = new SalarySobRangeSaveParam.SalarySobRangeTargetParam(); po.setTargetType(TargetTypeEnum.EMPLOYEE); //异常点数量 int errorSum = 0; //行号 String rowIndex = String.format("第%s行", i + 2); //相同的姓名 String userName = dto.getUsername(); String deparmentName = dto.getDepartmentName(); String mobile = dto.getMobile(); String workcode = dto.getJobNum(); String employeeStatusStr = dto.getEmployeeStatus(); List employeeSameIds = new ArrayList<>(); //筛选导入人员信息可以在人力资源池中匹配到的人员信息 List emps = getSalaryEmployeeService(user) .matchImportEmployee(employees, userName, deparmentName, mobile, workcode, null); //含在职和离职,选在职数据 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()); } //当人员信息导入筛选的全局配置为"0"时,姓名才是必填项 if (StringUtils.isBlank(userName) && "0".equals(confValue)) { //姓名 不能为空 //错误消息对象 Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowIndex + "姓名不能为空"); errorData.add(errorMessageMap); errorSum += 1; } else if (CollectionUtils.isEmpty(employeeSameIds) || employeeSameIds.size() > 1) { Map errorMessageMap = Maps.newHashMap(); errorMessageMap.put("message", rowIndex + "员工信息不存在或者存在多个员工"); errorData.add(errorMessageMap); errorSum += 1; } else { Long employeeId = CollectionUtils.isNotEmpty(employeeSameIds) && employeeSameIds.size() == 1 ? employeeSameIds.get(0) : null; if (employeeId != null && employeeId > 0) { po.setTargetId(employeeId); } else { //姓名错误,系统内不存在该姓名 Map errorMessageMap = new HashMap<>(); errorMessageMap.put("message", rowIndex + "姓名错误,系统内不存在该姓名"); errorData.add(errorMessageMap); errorSum += 1; } } // 设置员工状态 if (StringUtils.isEmpty(employeeStatusStr)) { SalaryEmployeeStatusEnum[] values = SalaryEmployeeStatusEnum.values(); po.setEmployeeStatus(SalaryEmployeeStatusEnum.values()); } else { Boolean[] haveError = {false}; // 人员状态字符串转换为对应的value SalaryEmployeeStatusEnum[] status = SalaryEmployeeStatusEnum.getEnumsParseByFormatStr(employeeStatusStr, haveError); if (haveError[0]) { Map errorMessageMap = new HashMap<>(); errorMessageMap.put("message", rowIndex + "员工状态不存在,或格式有误。格式为:试用、正式、临时、试用延期"); errorData.add(errorMessageMap); errorSum += 1; } else { po.setEmployeeStatus(status); } } //fixme 分权判断 if (errorSum == 0) { successCount += 1; // 合格数据 eligibleData.add(po); } else { errorCount += 1; // 添加错误数据 } } // 入库 eligibleData = handleImportData(eligibleData); // 查询已有的人员范围 List salarySobRangePOS = listBySalarySobIdAndIncludeType(salarySobId, 1); SalarySobRangeSaveParam saveParam = new SalarySobRangeSaveParam(); saveParam.setTargetParams(eligibleData); // saveParam.setEmployeeStatus( SalaryEmployeeStatusEnum.values()); saveParam.setIncludeType(1); saveParam.setSalarySobId(salarySobId); // 处理一下本次的保存参数(如果原来添加过对应的人员(/部门/岗位),那么本次不需要新增,只需要更新) SalarySobRangeSaveBO.Result result = SalarySobRangeSaveBO.handle(salarySobRangePOS, saveParam, (long) user.getUID(), true); // 保存 if (CollectionUtils.isNotEmpty(result.getNeedInsertSalarySobRanges())) { salarySobRangeBiz.batchInsert(result.getNeedInsertSalarySobRanges()); } if (CollectionUtils.isNotEmpty(result.getNeedUpdateSalarySobRanges())) { result.getNeedUpdateSalarySobRanges().forEach(e -> salarySobRangeBiz.updateById(e)); } apidatas.put("successCount", successCount); apidatas.put("errorCount", errorCount); apidatas.put("errorData", errorData); } finally { IOUtils.closeQuietly(fileInputStream); } return apidatas; } // 处理导入数据 private List handleImportData(List pos) { if (CollectionUtils.isEmpty(pos)) { return Collections.emptyList(); } // 多条相同人的则以第一条为准,如果逆序排列(用于重复的则以最后一条为准)Collections.reverse(pos); // 去重(通过记录的唯一条件(人员id) List finalPos = pos.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(f -> f.getTargetId()))), ArrayList::new)); return finalPos; } private void checkImportParam(SalarySobRangeImportParam importParam) { //excel文件id String imageId = Util.null2String(importParam.getImageId()); if (StringUtils.isBlank(imageId)) { throw new SalaryRunTimeException("文件不存在"); } if (StringUtils.isBlank(importParam.getSalarySobId())) { throw new SalaryRunTimeException("薪资账套ID为空"); } } @Override public Map preview(SalarySobRangeImportParam importParam) { Map apidatas = new HashMap(); //excel文件id String imageId = Util.null2String(importParam.getImageId()); Validate.notBlank(imageId, "imageId为空"); InputStream fileInputStream = null; try { fileInputStream = ImageFileManager.getInputStreamById(Integer.parseInt(imageId)); List salarySobRangeImportList = ExcelParseHelper.parse2Map(fileInputStream, SalarySobRangeImportListDTO.class, 0, 1, 5, "TaxAgentEmployee.xlsx"); apidatas.put("preview", salarySobRangeImportList); } finally { IOUtils.closeQuietly(fileInputStream); } return apidatas; } /** * @return List> * @description 获取excel数据行 * @author Harryxzy * @date 2023/1/9 11:37 */ private List> getExcelRowList() { // 表头 List headers = Lists.newArrayList(); headers.add(SalaryI18nUtil.getI18nLabel(85429, "姓名")); headers.add(SalaryI18nUtil.getI18nLabel(86185, "部门")); headers.add(SalaryI18nUtil.getI18nLabel(86186, "手机号")); headers.add(SalaryI18nUtil.getI18nLabel(86317, "工号")); headers.add(SalaryI18nUtil.getI18nLabel(86318, "员工状态")); List> rowList = new ArrayList<>(); rowList.add(headers); return rowList; } }