From 463e56d2cf2020eb8d6977beec47fc31f24bab19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=92=B1=E6=B6=9B?= <15850646081@163.com> Date: Thu, 28 Dec 2023 18:12:38 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=BC=E5=85=A5=E7=94=B3=E6=8A=A5=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../param/DownloadTemplateParam.java | 26 ++ .../service/TaxDeclarationExcelService.java | 15 ++ .../service/TaxDeclarationValueService.java | 2 + .../impl/TaxDeclarationExcelServiceImpl.java | 254 ++++++++++++++++-- .../impl/TaxDeclarationValueServiceImpl.java | 22 +- .../salary/web/TaxDeclarationController.java | 75 +++--- .../wrapper/TaxDeclareRecordWrapper.java | 12 + 7 files changed, 352 insertions(+), 54 deletions(-) create mode 100644 src/com/engine/salary/entity/taxdeclaration/param/DownloadTemplateParam.java diff --git a/src/com/engine/salary/entity/taxdeclaration/param/DownloadTemplateParam.java b/src/com/engine/salary/entity/taxdeclaration/param/DownloadTemplateParam.java new file mode 100644 index 000000000..d9371b3fd --- /dev/null +++ b/src/com/engine/salary/entity/taxdeclaration/param/DownloadTemplateParam.java @@ -0,0 +1,26 @@ +package com.engine.salary.entity.taxdeclaration.param; + +import com.engine.salary.util.valid.DataCheck; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DownloadTemplateParam { + /** + * 申报表id,下载模板 + */ + @DataCheck(require = true,message = "imageId为空") + Long taxDeclarationId; + + + + /** + * 导入文件id + */ + String imageId; +} diff --git a/src/com/engine/salary/service/TaxDeclarationExcelService.java b/src/com/engine/salary/service/TaxDeclarationExcelService.java index 15d6c81fd..e5e154fe7 100644 --- a/src/com/engine/salary/service/TaxDeclarationExcelService.java +++ b/src/com/engine/salary/service/TaxDeclarationExcelService.java @@ -1,9 +1,12 @@ package com.engine.salary.service; import com.engine.salary.entity.taxdeclaration.param.AbnormalEmployeeListQueryParam; +import com.engine.salary.entity.taxdeclaration.param.DownloadTemplateParam; import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationValueListQueryParam; import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import java.util.Map; + /** * 个税申报表导出 *

Copyright: Copyright (c) 2022

@@ -45,4 +48,16 @@ public interface TaxDeclarationExcelService { * @return */ XSSFWorkbook exportEmployee4Fail(AbnormalEmployeeListQueryParam queryParam); + + XSSFWorkbook downloadTemplate(DownloadTemplateParam param); + /** + * 预览 + */ + Map preview(DownloadTemplateParam importParam); + + /** + * 导入数据 + */ + Map importData(DownloadTemplateParam importParam); + } diff --git a/src/com/engine/salary/service/TaxDeclarationValueService.java b/src/com/engine/salary/service/TaxDeclarationValueService.java index 70bd6f729..969292efb 100644 --- a/src/com/engine/salary/service/TaxDeclarationValueService.java +++ b/src/com/engine/salary/service/TaxDeclarationValueService.java @@ -36,6 +36,7 @@ public interface TaxDeclarationValueService { * @return */ List listByTaxDeclarationIds(Collection taxDeclarationIds); + List listByTaxDeclarationId(Long taxDeclarationIds); /** * 查询个税申报表明细 @@ -59,6 +60,7 @@ public interface TaxDeclarationValueService { * @param taxDeclarationValues */ void batchSave(List taxDeclarationValues); + void batchEdit(List taxDeclarationValues); void save(TaxDeclareRecordDetailSaveParam param); diff --git a/src/com/engine/salary/service/impl/TaxDeclarationExcelServiceImpl.java b/src/com/engine/salary/service/impl/TaxDeclarationExcelServiceImpl.java index 6382be9b4..8aac2c649 100644 --- a/src/com/engine/salary/service/impl/TaxDeclarationExcelServiceImpl.java +++ b/src/com/engine/salary/service/impl/TaxDeclarationExcelServiceImpl.java @@ -1,30 +1,53 @@ package com.engine.salary.service.impl; +import com.api.formmode.mybatis.util.SqlProxyHandle; import com.cloudstore.eccom.pc.table.WeaTableColumn; import com.engine.common.util.ServiceUtil; import com.engine.core.impl.Service; +import com.engine.salary.constant.SalaryDefaultTenantConstant; +import com.engine.salary.entity.datacollection.DataCollectionEmployee; import com.engine.salary.entity.taxdeclaration.dto.AbnormalEmployeeListDTO; import com.engine.salary.entity.taxdeclaration.dto.FailEmployeeListDTO; import com.engine.salary.entity.taxdeclaration.dto.TaxDeclarationValueListDTO; import com.engine.salary.entity.taxdeclaration.param.AbnormalEmployeeListQueryParam; +import com.engine.salary.entity.taxdeclaration.param.DownloadTemplateParam; import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationValueListQueryParam; import com.engine.salary.entity.taxdeclaration.po.*; +import com.engine.salary.enums.UserStatusEnum; +import com.engine.salary.enums.salaryaccounting.EmployeeTypeEnum; +import com.engine.salary.enums.salaryitem.SalaryDataTypeEnum; +import com.engine.salary.enums.salarysob.IncomeCategoryEnum; +import com.engine.salary.enums.sicategory.DeleteTypeEnum; +import com.engine.salary.enums.taxdeclaration.SourceEnum; +import com.engine.salary.mapper.sys.SalarySysConfMapper; import com.engine.salary.service.*; +import com.engine.salary.sys.entity.po.SalarySysConfPO; import com.engine.salary.util.JsonUtil; +import com.engine.salary.util.SalaryEntityUtil; import com.engine.salary.util.SalaryI18nUtil; -import com.engine.salary.util.excel.ExcelHead; +import com.engine.salary.util.excel.ExcelParseHelper; import com.engine.salary.util.excel.ExcelSheetData; +import com.engine.salary.util.excel.ExcelSupport; import com.engine.salary.util.excel.ExcelUtil; 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.lang3.StringUtils; +import org.apache.commons.lang3.Validate; +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.general.Util; import weaver.hrm.User; -import java.lang.reflect.Field; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.io.InputStream; +import java.util.*; +import java.util.stream.Collectors; + +import static com.engine.salary.util.excel.ExcelSupport.EXCEL_TYPE_XLSX; /** * 个税申报表导出 @@ -57,6 +80,19 @@ public class TaxDeclarationExcelServiceImpl extends Service implements TaxDeclar return ServiceUtil.getService(TaxDeclareFailServiceImpl.class, user); } + + private TaxReportColumnService getTaxReportColumnService(User user) { + return ServiceUtil.getService(TaxReportColumnServiceImpl.class, user); + } + + private SalarySysConfMapper getSalarySysConfMapper() { + return SqlProxyHandle.getProxy(SalarySysConfMapper.class); + } + + private SalaryEmployeeService getSalaryEmployeeService(User user) { + return ServiceUtil.getService(SalaryEmployeeServiceImpl.class, user); + } + @Override public XSSFWorkbook exportTaxDeclarationValue(TaxDeclarationValueListQueryParam queryParam) { // 查询个税申报表 @@ -140,7 +176,7 @@ public class TaxDeclarationExcelServiceImpl extends Service implements TaxDeclar // 导出的表头 List headerList = Lists.newArrayList(); List dataIndexList = Lists.newArrayList(); - parseHeader(clazz, headerList, dataIndexList); + ExcelUtil.parseHeader(clazz, headerList, dataIndexList); // 导出的数据 List> rows = Lists.newArrayListWithExpectedSize(dtoList.size()); dtoList.forEach(dto -> { @@ -157,23 +193,195 @@ public class TaxDeclarationExcelServiceImpl extends Service implements TaxDeclar return excelSheetData; } - /** - * 解析表头 - * - * @param clazz - * @param headerList - * @param dataIndexList - * @param - */ - private void parseHeader(Class clazz, List headerList, List dataIndexList) { - Field[] declaredFields = clazz.getDeclaredFields(); - for (Field declaredField : declaredFields) { - if (!declaredField.isAnnotationPresent(ExcelHead.class)) { - continue; - } - ExcelHead annotation = declaredField.getAnnotation(ExcelHead.class); - headerList.add(SalaryI18nUtil.getI18nLabel(annotation.labelId(), annotation.title())); - dataIndexList.add(declaredField.getName()); + @Override + public XSSFWorkbook downloadTemplate(DownloadTemplateParam param) { + TaxDeclarationPO declarationPO = getTaxDeclarationService(user).getById(param.getTaxDeclarationId()); + IncomeCategoryEnum incomeCategoryEnum = IncomeCategoryEnum.parseByValue(declarationPO.getIncomeCategory()); + List taxReportColumnPOS = getTaxReportColumnService(user).listByIncomeCategory(incomeCategoryEnum); + + + List heads = new ArrayList<>(); + heads.add(SalaryI18nUtil.getI18nLabel(85429, "姓名")); + heads.add(SalaryI18nUtil.getI18nLabel(86185, "部门")); + heads.add(SalaryI18nUtil.getI18nLabel(86186, "手机号")); + heads.add(SalaryI18nUtil.getI18nLabel(86317, "工号")); + heads.addAll(SalaryEntityUtil.properties(taxReportColumnPOS, TaxReportColumnPO::getReportColumnName, Collectors.toList())); + + List> rowList = new ArrayList<>(); + rowList.add(heads); + XSSFWorkbook book = ExcelUtil.genWorkbookV2(rowList, incomeCategoryEnum.getDefaultLabel()); + return book; + } + + @Override + public Map preview(DownloadTemplateParam importParam) { + //excel文件id + String imageId = Util.null2String(importParam.getImageId()); + Validate.notBlank(imageId, "imageId为空"); + + InputStream fileInputStream = null; + Map map = new HashMap<>(); + try { + fileInputStream = ImageFileManager.getInputStreamById(Integer.parseInt(importParam.getImageId())); + Sheet sheet = ExcelSupport.parseFile(fileInputStream, 0, EXCEL_TYPE_XLSX); + map.put("headers", ExcelSupport.getSheetHeader(sheet, 0)); + map.put("list", ExcelParseHelper.parse2List(sheet, 1, 0)); + return map; + } finally { + IOUtils.closeQuietly(fileInputStream); } } + + @Override + public Map importData(DownloadTemplateParam param) { + //查询对于人员信息导入筛选的全局配置 + SalarySysConfPO salarySysConfPO = getSalarySysConfMapper().getOneByCode("matchEmployeeMode"); + String confValue = (salarySysConfPO != null && salarySysConfPO.getConfValue() != null && !"".equals(salarySysConfPO.getConfValue())) ? salarySysConfPO.getConfValue() : "0"; + + + // 租户下所有的人员 + List salaryEmployees = getSalaryEmployeeService(user).listAllForReport(); + Map salaryEmployeeMap = SalaryEntityUtil.convert2Map(salaryEmployees, DataCollectionEmployee::getUsername, DataCollectionEmployee::getEmployeeId); + Map emps = SalaryEntityUtil.convert2Map(salaryEmployees, DataCollectionEmployee::getEmployeeId); + + + TaxDeclarationPO declarationPO = getTaxDeclarationService(user).getById(param.getTaxDeclarationId()); + IncomeCategoryEnum incomeCategoryEnum = IncomeCategoryEnum.parseByValue(declarationPO.getIncomeCategory()); + List taxReportColumnPOS = getTaxReportColumnService(user).listByIncomeCategory(incomeCategoryEnum); + Map nameColumnMap = SalaryEntityUtil.convert2Map(taxReportColumnPOS, TaxReportColumnPO::getReportColumnName); + + List taxDeclarationValuePOS = getTaxDeclarationValueService(user).listByTaxDeclarationId(declarationPO.getId()); + Map empDeclarationValueMap = SalaryEntityUtil.convert2Map(taxDeclarationValuePOS, TaxDeclarationValuePO::getEmployeeId); + + // 索引(用于计算进度) + int index = 0; + // 失败的数量 + int failCount = 0; + // 成功的数量 + int successCount = 0; + Date now = new Date(); + + List addList = Lists.newArrayList(); + List editList = Lists.newArrayList(); + + + InputStream fileInputStream = null; + try { + + + fileInputStream = ImageFileManager.getInputStreamById(Integer.parseInt(param.getImageId())); + Sheet sheet = ExcelSupport.parseFile(fileInputStream, 0, EXCEL_TYPE_XLSX); + + // 错误提示信息 + List excelComments = Lists.newArrayList(); + // 存在错误的那行数据 + List> errorDatas = Lists.newArrayList(); + // 表头 + List headers; + headers = ExcelSupport.getSheetHeader(sheet, 0); + List> data = ExcelParseHelper.parse2Map(sheet, 1, 0); + + if (CollectionUtils.isEmpty(headers)) { + throw new RuntimeException("表头为空"); + } + if (CollectionUtils.isEmpty(data)) { + throw new RuntimeException("无数据"); + } + for (int i = 0; i < data.size(); i++) { + + String row = "第" + (i + 2) + "行"; + + boolean isError = false; + Map map = data.get(i); + Long employeeId = 0L; + + String username = (String) map.getOrDefault("姓名", ""); + String deparmentName = (String) map.getOrDefault("部门", ""); + String mobile = (String) map.getOrDefault("手机号", ""); + String workcode = (String) map.getOrDefault("工号", ""); + + if (StringUtils.isEmpty(username) && "0".equals(confValue)) { + isError = true; + Map errorMessageMap = Maps.newHashMap(); + errorMessageMap.put("message", row + SalaryI18nUtil.getI18nLabel(102838, "姓名不能为空")); + excelComments.add(errorMessageMap); + } else { + //筛选导入人员信息可以在人力资源池中匹配到的人员信息 + List employeeSameIds = getSalaryEmployeeService(user).matchImportEmployee(salaryEmployees, username, deparmentName, mobile, workcode, null); + + if (CollectionUtils.isEmpty(employeeSameIds)) { + isError = true; + Map errorMessageMap = Maps.newHashMap(); + errorMessageMap.put("message", row + SalaryI18nUtil.getI18nLabel(100579, "姓名错误,系统内不存在该姓名")); + excelComments.add(errorMessageMap); + } else if (employeeSameIds.size() > 1) { + //存在离职和在职状态取在职状态 + employeeSameIds = employeeSameIds.stream() + .filter(e -> UserStatusEnum.getNormalStatus().contains(e.getStatus())) + .collect(Collectors.toList()); + if (employeeSameIds.size() != 1) { + isError = true; + Map errorMessageMap = Maps.newHashMap(); + errorMessageMap.put("message", row + "员工信息不存在或者存在多个员工"); + excelComments.add(errorMessageMap); + } else { + employeeId = CollectionUtils.isNotEmpty(employeeSameIds) && employeeSameIds.size() == 1 ? employeeSameIds.get(0).getEmployeeId() : null; + } + } else { + employeeId = employeeSameIds.get(0).getEmployeeId(); + } + } + + if (isError) { + failCount++; + errorDatas.add(map); + continue; + } + + successCount++; + + Map valueMap = Maps.newHashMap(); + for (TaxReportColumnPO taxReportColumn : taxReportColumnPOS) { + Object value = map.get(taxReportColumn.getReportColumnName()); + valueMap.put(taxReportColumn.getReportColumnDataIndex(), value != null ? value.toString() : Objects.equals(taxReportColumn.getDataType(), SalaryDataTypeEnum.NUMBER.getValue()) ? "0.00" : ""); + } + + if (empDeclarationValueMap.containsKey(employeeId)) { + TaxDeclarationValuePO taxDeclarationValue =empDeclarationValueMap.get(employeeId); + taxDeclarationValue.setResultValue(valueMap); + taxDeclarationValue.setResultValueJson(JsonUtil.toJsonString(valueMap)); + taxDeclarationValue.setUpdateTime(new Date()); + taxDeclarationValue.setSource(SourceEnum.IMP.getValue()); + editList.add(taxDeclarationValue); + } else { + //新增 + TaxDeclarationValuePO taxDeclarationValue = TaxDeclarationValuePO.builder() + .id(IdGenerator.generate()) + .taxDeclareRecordId(declarationPO.getTaxDeclareRecordId()) + .taxDeclarationId(declarationPO.getId()) + .employeeType(EmployeeTypeEnum.ORGANIZATION.getValue()) + .employeeId(employeeId) + .resultValue(valueMap) + .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY) + .creator(employeeId) + .deleteType(DeleteTypeEnum.NOT_DELETED.getValue()) + .createTime(now) + .updateTime(now) + .source(SourceEnum.IMP.getValue()) + .build(); + addList.add(taxDeclarationValue); + } + } + + getTaxDeclarationValueService(user).batchSave(addList); + getTaxDeclarationValueService(user).batchEdit(editList); + + + } finally { + IOUtils.closeQuietly(fileInputStream); + } + + return null; + } + } diff --git a/src/com/engine/salary/service/impl/TaxDeclarationValueServiceImpl.java b/src/com/engine/salary/service/impl/TaxDeclarationValueServiceImpl.java index b5ddd14b4..80e1c8209 100644 --- a/src/com/engine/salary/service/impl/TaxDeclarationValueServiceImpl.java +++ b/src/com/engine/salary/service/impl/TaxDeclarationValueServiceImpl.java @@ -94,6 +94,12 @@ public class TaxDeclarationValueServiceImpl extends Service implements TaxDeclar return decryptBatch(taxDeclarationValues); } + @Override + public List listByTaxDeclarationId(Long taxDeclarationId) { + List taxDeclarationValues = getTaxDeclarationValueMapper().listSome(TaxDeclarationValuePO.builder().taxDeclarationId(taxDeclarationId).build()); + return decryptBatch(taxDeclarationValues); + } + @Override public List listByTaxDeclarationIdsNoDecrypt(Collection taxDeclarationIds) { return getTaxDeclarationValueMapper().listSome(TaxDeclarationValuePO.builder().taxDeclarationIds(taxDeclarationIds).build()); @@ -144,7 +150,21 @@ public class TaxDeclarationValueServiceImpl extends Service implements TaxDeclar List> partition = Lists.partition(taxDeclarationValues, 100); for (List subTaxDeclarationValues : partition) { subTaxDeclarationValues.forEach(getTaxDeclarationValueMapper()::insertIgnoreNull); -// getTaxDeclarationValueMapper().batchInsert(subTaxDeclarationValues); + } + } + } + + @Override + public void batchEdit(List taxDeclarationValues) { + if (CollectionUtils.isNotEmpty(taxDeclarationValues)) { + // 加密 + taxDeclarationValues.forEach(taxDeclarationValue -> + taxDeclarationValue.setResultValueJson(JsonUtil.toJsonString(taxDeclarationValue.getResultValue()))); + taxDeclarationValues = encryptUtil.encryptList(taxDeclarationValues, TaxDeclarationValuePO.class); + // 分批保存 + List> partition = Lists.partition(taxDeclarationValues, 100); + for (List subTaxDeclarationValues : partition) { + subTaxDeclarationValues.forEach(getTaxDeclarationValueMapper()::updateIgnoreNull); } } } diff --git a/src/com/engine/salary/web/TaxDeclarationController.java b/src/com/engine/salary/web/TaxDeclarationController.java index b6963b187..dc61a0458 100644 --- a/src/com/engine/salary/web/TaxDeclarationController.java +++ b/src/com/engine/salary/web/TaxDeclarationController.java @@ -653,35 +653,50 @@ public class TaxDeclarationController { } } -// @POST -// @Path("/downloadTemplate") -// @Produces(MediaType.APPLICATION_OCTET_STREAM) -// public Response getAll(@Context HttpServletRequest request, @Context HttpServletResponse response,@RequestBody DownloadTemplateParam param) { -// try { -// User user = HrmUserVarify.getUser(request, response); -// -// -// XSSFWorkbook workbook = getTaxDeclareRecordWrapper(user).downloadTemplate(queryParam); -// -// String fileName = "往期累计情况导入模板" + LocalDate.now(); -// -// try { -// fileName = URLEncoder.encode(fileName + ".xlsx", "UTF-8"); -// } catch (UnsupportedEncodingException e) { -// log.error(e.getMessage(), e); -// } -// -// StreamingOutput output = outputStream -> { -// workbook.write(outputStream); -// outputStream.flush(); -// }; -// response.setContentType("application/octet-stream"); -// return Response.ok(output).header("Content-disposition", "attachment;filename=" + fileName).header("Cache-Control", "no-cache").build(); -// -// } catch (Exception e) { -// log.error("往期累计情况导入模板导出异常", e); -// throw e; -// } -// } + @POST + @Path("/downloadTemplate") + @Produces(MediaType.APPLICATION_OCTET_STREAM) + public Response downloadTemplate(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody DownloadTemplateParam param) { + try { + User user = HrmUserVarify.getUser(request, response); + + XSSFWorkbook workbook = getTaxDeclareRecordWrapper(user).downloadTemplate(param); + + String fileName = "申报表导入模板" + LocalDate.now(); + + try { + fileName = URLEncoder.encode(fileName + ".xlsx", "UTF-8"); + } catch (UnsupportedEncodingException e) { + log.error(e.getMessage(), e); + } + + StreamingOutput output = outputStream -> { + workbook.write(outputStream); + outputStream.flush(); + }; + response.setContentType("application/octet-stream"); + return Response.ok(output).header("Content-disposition", "attachment;filename=" + fileName).header("Cache-Control", "no-cache").build(); + + } catch (Exception e) { + log.error("申报表导入模板导出异常", e); + throw e; + } + } + + @POST + @Path("/preview") + @Produces(MediaType.APPLICATION_JSON) + public String preview(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody DownloadTemplateParam importParam) { + User user = HrmUserVarify.getUser(request, response); + return new ResponseResult>(user).run(getTaxDeclareRecordWrapper(user)::preview, importParam); + } + + @POST + @Path("/importData") + @Produces(MediaType.APPLICATION_JSON) + public String importAddUpDeduction(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody DownloadTemplateParam importParam) { + User user = HrmUserVarify.getUser(request, response); + return new ResponseResult>(user).run(getTaxDeclareRecordWrapper(user)::importData, importParam); + } } diff --git a/src/com/engine/salary/wrapper/TaxDeclareRecordWrapper.java b/src/com/engine/salary/wrapper/TaxDeclareRecordWrapper.java index 18c81327d..fed3fbe32 100644 --- a/src/com/engine/salary/wrapper/TaxDeclareRecordWrapper.java +++ b/src/com/engine/salary/wrapper/TaxDeclareRecordWrapper.java @@ -755,4 +755,16 @@ public class TaxDeclareRecordWrapper extends Service { .resultValue(declarationValuePO.getResultValue()) .build(); } + + public XSSFWorkbook downloadTemplate(DownloadTemplateParam param) { + return getTaxDeclarationExcelService(user).downloadTemplate(param); + } + + public Map preview(DownloadTemplateParam param) { + return getTaxDeclarationExcelService(user).preview(param); + } + + public Map importData(DownloadTemplateParam param) { + return getTaxDeclarationExcelService(user).importData(param); + } }