package com.engine.salary.service.impl; import cn.hutool.core.util.NumberUtil; import com.cloudstore.eccom.pc.table.WeaTableColumn; import com.engine.common.util.ServiceUtil; import com.engine.core.impl.Service; import com.engine.salary.component.SalaryWeaTable; import com.engine.salary.config.SalaryElogConfig; import com.engine.salary.constant.SalaryDefaultTenantConstant; import com.engine.hrmelog.entity.dto.LoggerContext; import com.engine.salary.encrypt.EncryptUtil; import com.engine.salary.entity.datacollection.DataCollectionEmployee; import com.engine.salary.entity.employeedeclare.po.EmployeeDeclarePO; import com.engine.salary.entity.extemp.po.ExtEmpPO; import com.engine.salary.entity.salaryarchive.dto.SalaryArchiveListDTO; import com.engine.salary.entity.taxagent.po.TaxAgentPO; import com.engine.salary.entity.taxdeclaration.bo.TaxDeclarationValueList; import com.engine.salary.entity.taxdeclaration.dto.ContrastListDTO; import com.engine.salary.entity.taxdeclaration.dto.TaxDeclarationValueListDTO; import com.engine.salary.entity.taxdeclaration.param.ContrastQueryParam; import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationValueListQueryParam; import com.engine.salary.entity.taxdeclaration.param.TaxDeclareRecordDetailSaveParam; import com.engine.salary.entity.taxdeclaration.po.*; import com.engine.salary.enums.OperateTypeEnum; 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.exception.SalaryRunTimeException; import com.engine.salary.mapper.taxdeclaration.TaxDeclarationValueMapper; import com.engine.salary.mapper.taxdeclaration.TaxDeclareRecordMapper; import com.engine.salary.remote.tax.client.DeclareClient; import com.engine.salary.remote.tax.response.declare.GetDeclareTaxResultFeedbackResponse; import com.engine.salary.service.*; import com.engine.salary.util.*; import com.engine.salary.util.db.IdGenerator; import com.engine.salary.util.db.MapperProxyFactory; import com.engine.salary.util.excel.ExcelUtilPlus; import com.engine.salary.util.page.PageInfo; import com.engine.salary.util.page.SalaryPageUtil; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.wbi.core.entity.WeaResultMsg; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.beans.BeanUtils; import weaver.general.Util; import weaver.hrm.User; import java.math.BigDecimal; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; /** * 个税申报表 *

Copyright: Copyright (c) 2023

*

Company: 泛微软件

* * @author qiantao * @version 1.0 **/ @Slf4j public class TaxDeclarationValueServiceImpl extends Service implements TaxDeclarationValueService { public EncryptUtil encryptUtil = new EncryptUtil(); private TaxDeclarationValueMapper getTaxDeclarationValueMapper() { return MapperProxyFactory.getProxy(TaxDeclarationValueMapper.class); } private TaxDeclareRecordMapper getTaxDeclareRecordMapper() { return MapperProxyFactory.getProxy(TaxDeclareRecordMapper.class); } private TaxDeclareStatusService getTaxDeclareStatusService(User user) { return ServiceUtil.getService(TaxDeclareStatusServiceImpl.class, user); } private SalaryEmployeeService getSalaryEmployeeService(User user) { return ServiceUtil.getService(SalaryEmployeeServiceImpl.class, user); } private ExtEmpService getExtEmpService(User user) { return ServiceUtil.getService(ExtEmpServiceImpl.class, user); } private EmployeeDeclareService getEmployeeDeclareService(User user) { return ServiceUtil.getService(EmployeeDeclareServiceImpl.class, user); } private TaxReportColumnService getTaxReportColumnService(User user) { return ServiceUtil.getService(TaxReportColumnServiceImpl.class, user); } private TaxDeclarationService getTaxDeclarationService(User user) { return ServiceUtil.getService(TaxDeclarationServiceImpl.class, user); } private TaxAgentService getTaxAgentService(User user) { return ServiceUtil.getService(TaxAgentServiceImpl.class, user); } @Override public PageInfo listPageByTaxDeclarationIds(TaxDeclarationValueListQueryParam queryParam, Collection taxDeclarationIds, String keyword) { List taxDeclarationValuePOS = getTaxDeclarationValueMapper().listSome(TaxDeclarationValuePO.builder().taxDeclarationIds(taxDeclarationIds).build()); // 根据关键词查人员信息 if (StringUtils.isNotBlank(keyword)) { List employeeList = getSalaryEmployeeService(user).listByKeyword(keyword); List empIds = employeeList.stream().map(DataCollectionEmployee::getEmployeeId).collect(Collectors.toList()); taxDeclarationValuePOS = taxDeclarationValuePOS.stream().filter(po -> empIds.contains(po.getEmployeeId())).collect(Collectors.toList()); } taxDeclarationValuePOS = decryptBatch(taxDeclarationValuePOS); return SalaryPageUtil.buildPage(queryParam.getCurrent(), queryParam.getPageSize(), taxDeclarationValuePOS, TaxDeclarationValuePO.class); } @Override public List listByTaxDeclarationIds(Collection taxDeclarationIds) { List taxDeclarationValues = getTaxDeclarationValueMapper().listSome(TaxDeclarationValuePO.builder().taxDeclarationIds(taxDeclarationIds).build()); 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()); } @Override public TaxDeclarationValueListDTO convert2List(TaxDeclarationPO taxDeclaration, List taxDeclarationValues) { // 查询个税申报表表头 IncomeCategoryEnum incomeCategoryEnum = SalaryEnumUtil.enumMatchByValue(taxDeclaration.getIncomeCategory(), IncomeCategoryEnum.class); List taxReportColumns = getTaxReportColumnService(user).listByIncomeCategory(incomeCategoryEnum, 0); // 人员id Set employeeIds = SalaryEntityUtil.properties(taxDeclarationValues, TaxDeclarationValuePO::getEmployeeId); // 查询报送的人员 List employeeDeclares = getEmployeeDeclareService(user).listByTaxCycleAndTaxAgentIdAndEmployeeIds(taxDeclaration.getTaxCycle(), taxDeclaration.getTaxAgentId(), employeeIds); // 查询人员信息 List simpleEmployeeIds = taxDeclarationValues.stream().filter(taxDeclarationValue -> taxDeclarationValue.getEmployeeType() == null || Objects.equals(taxDeclarationValue.getEmployeeType(), EmployeeTypeEnum.ORGANIZATION.getValue())).map(TaxDeclarationValuePO::getEmployeeId).distinct().collect(Collectors.toList()); List simpleEmployees = getSalaryEmployeeService(user).getEmployeeByIds(simpleEmployeeIds); // 查询人员薪资(身份证号码等) List simpleUserInfos = getSalaryEmployeeService(user).getEmployeeByIds(simpleEmployeeIds); // 查询外部人员 List extEmployeeIds = taxDeclarationValues.stream().filter(taxDeclarationValue -> Objects.equals(taxDeclarationValue.getEmployeeType(), EmployeeTypeEnum.EXT_EMPLOYEE.getValue())).map(TaxDeclarationValuePO::getEmployeeId).collect(Collectors.toList()); List extEmployees = getExtEmpService(user).getExtEmpByIds(extEmployeeIds); // 列表表头 List weaTableColumns = TaxDeclarationValueList.buildTableColumns(taxReportColumns); // 列表数据 List> data = TaxDeclarationValueList.buildTableData(incomeCategoryEnum, taxReportColumns, taxDeclarationValues, employeeDeclares, simpleEmployees, simpleUserInfos, extEmployees, false); return new TaxDeclarationValueListDTO().setColumns(weaTableColumns).setData(data); } @Override public void batchSave(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()::insertIgnoreNull); } } } @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); } } } @Override public void save(TaxDeclareRecordDetailSaveParam param) { TaxDeclarationPO taxDeclaration = getTaxDeclarationService(user).getById(param.getTaxDeclarationId()); if (taxDeclaration == null) { throw new SalaryRunTimeException("个税申报表不存在!"); } Long taxDeclareRecordId = taxDeclaration.getTaxDeclareRecordId(); TaxDeclareRecordPO declareRecordPO = getTaxDeclareRecordMapper().getById(taxDeclareRecordId); if (declareRecordPO == null) { throw new SalaryRunTimeException("个税申报记录不存在!"); } TaxDeclarationValuePO po = TaxDeclarationValuePO.builder().id(IdGenerator.generate()).taxDeclarationId(param.getTaxDeclarationId()).taxDeclareRecordId(taxDeclareRecordId).employeeId(param.getEmployeeId()).employeeType(param.getEmployeeType()).resultValue(param.getTaxReportColumnValues()).resultValueJson(JsonUtil.toJsonString(param.getTaxReportColumnValues())).createTime(new Date()).updateTime(new Date()).source(SourceEnum.ADD.getValue()).creator((long) user.getUID()).deleteType(0).tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY).build(); TaxDeclarationValuePO po4log = new TaxDeclarationValuePO(); BeanUtils.copyProperties(po,po4log); encryptUtil.encrypt(po, TaxDeclarationValuePO.class); getTaxDeclarationValueMapper().insertIgnoreNull(po); // 记录日志 TaxAgentPO taxAgent = getTaxAgentService(user).getById(taxDeclaration.getTaxAgentId()); LoggerContext loggerContext = new LoggerContext<>(); loggerContext.setUser(user); loggerContext.setTargetId(po.getTaxDeclareRecordId().toString()); loggerContext.setTargetName(SalaryI18nUtil.getI18nLabel(0, "个税扣缴义务人「{0}」,税款所属期「{1}」,人员id「{3}」") .replace("{0}", taxAgent.getName()) .replace("{1}", SalaryDateUtil.getFormatYearMonth(declareRecordPO.getTaxCycle())) .replace("{2}", po.getEmployeeId().toString())); loggerContext.setOperateType(OperateTypeEnum.ADD.getValue()); loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel( 0, "新增人员")); loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel( 0, "新增人员")); loggerContext.setNewValues(po4log); SalaryElogConfig.taxDeclarationLoggerTemplate.write(loggerContext); //新增年终奖 if (IncomeCategoryEnum.ONETIME_ANNUAL_BONUS.getValue().equals(taxDeclaration.getIncomeCategory())) { autoAddWagesDeclare(declareRecordPO); } } @Override public void edit(TaxDeclareRecordDetailSaveParam param) { TaxDeclarationValuePO po = getById(param.getId()); TaxDeclarationValuePO oldPo = new TaxDeclarationValuePO(); BeanUtils.copyProperties(po, oldPo); po.setResultValue(param.getTaxReportColumnValues()); po.setResultValueJson(JsonUtil.toJsonString(param.getTaxReportColumnValues())); po.setUpdateTime(new Date()); po.setSource(SourceEnum.EDIT.getValue()); encryptUtil.encrypt(po, TaxDeclarationValuePO.class); getTaxDeclarationValueMapper().updateIgnoreNull(po); TaxDeclarationValuePO po4log = getTaxDeclarationValueMapper().getById(po.getId()); // 记录日志 TaxDeclareRecordPO taxDeclareRecordPO = getTaxDeclareRecordMapper().getById(po.getTaxDeclareRecordId()); TaxAgentPO taxAgent = getTaxAgentService(user).getById(taxDeclareRecordPO.getTaxAgentId()); LoggerContext loggerContext = new LoggerContext<>(); loggerContext.setUser(user); loggerContext.setTargetId(po.getTaxDeclareRecordId().toString()); loggerContext.setTargetName(SalaryI18nUtil.getI18nLabel(0, "个税扣缴义务人「{0}」税款所属期「{1}」人员id「{3}」") .replace("{0}", taxAgent.getName()) .replace("{1}", SalaryDateUtil.getFormatYearMonth(taxDeclareRecordPO.getTaxCycle())) .replace("{2}", po.getEmployeeId().toString())); loggerContext.setOperateType(OperateTypeEnum.UPDATE.getValue()); loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel( 0, "修改个税申报数据")); loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel( 0, "修改个税申报数据")); loggerContext.setOldValues(oldPo); loggerContext.setNewValues(po4log); SalaryElogConfig.taxDeclarationLoggerTemplate.write(loggerContext); } @Override public TaxDeclarationValuePO getById(Long id) { TaxDeclarationValuePO po = getTaxDeclarationValueMapper().getById(id); if (po == null) { throw new SalaryRunTimeException("个税申报明细不存在!"); } encryptUtil.decrypt(po, TaxDeclarationValuePO.class); po.setResultValue(JsonUtil.parseMap(po.getResultValueJson(), String.class)); return po; } @Override public void deleteByTaxDeclareRecordIds(Collection taxDeclareRecordIds) { if (CollectionUtils.isEmpty(taxDeclareRecordIds)) { return; } getTaxDeclarationValueMapper().deleteBytaxDeclareRecordIds(taxDeclareRecordIds); } private List decryptBatch(List taxDeclarationValues) { if (CollectionUtils.isEmpty(taxDeclarationValues)) { return Collections.emptyList(); } // 解密 taxDeclarationValues = encryptUtil.decryptList(taxDeclarationValues, TaxDeclarationValuePO.class); taxDeclarationValues.forEach(salaryAcctResultValue -> { salaryAcctResultValue.setResultValue(JsonUtil.parseMap(salaryAcctResultValue.getResultValueJson(), String.class)); }); return taxDeclarationValues; } @Override public void autoAddWagesDeclare(TaxDeclareRecordPO taxDeclareRecord) { Long taxDeclareRecordId = taxDeclareRecord.getId(); Date now = new Date(); //非正常薪资的人员 List notWagesEmpIds = getTaxDeclarationValueMapper().queryNotWagesEmpIds(taxDeclareRecordId); if (CollectionUtils.isEmpty(notWagesEmpIds)) { return; } //正常薪资人员 List wagesEmpIds = getTaxDeclarationValueMapper().queryWagesEmpIds(taxDeclareRecordId); //比较差异 List autoAddIds = notWagesEmpIds.stream().filter(id -> !wagesEmpIds.contains(id)).collect(Collectors.toList()); if (CollectionUtils.isEmpty(autoAddIds)) { return; } //正常薪资的表头 List taxReportColumns = getTaxReportColumnService(user).listByIncomeCategory(IncomeCategoryEnum.WAGES_AND_SALARIES, 0); Map valueMap = Maps.newHashMap(); for (TaxReportColumnPO taxReportColumn : taxReportColumns) { String value = Objects.equals(taxReportColumn.getDataType(), SalaryDataTypeEnum.NUMBER.getValue()) ? "0.00" : ""; valueMap.put(taxReportColumn.getReportColumnDataIndex(), value); } //当前申报表是否含正常申报 List list = getTaxDeclarationService(user).listByTaxDeclareRecordId(taxDeclareRecordId, IncomeCategoryEnum.WAGES_AND_SALARIES.getValue()); TaxDeclarationPO taxDeclarationPO; if (CollectionUtils.isNotEmpty(list)) { if (list.size() > 1) { throw new SalaryRunTimeException("存在多条正常工资薪金申报表数据"); } taxDeclarationPO = list.get(0); } else { taxDeclarationPO = TaxDeclarationPO.builder().id(IdGenerator.generate()).taxDeclareRecordId(taxDeclareRecordId).incomeCategory(IncomeCategoryEnum.WAGES_AND_SALARIES.getValue()).taxAgentId(taxDeclareRecord.getTaxAgentId()).salaryMonth(taxDeclareRecord.getSalaryMonth()).taxCycle(taxDeclareRecord.getTaxCycle()).description(taxDeclareRecord.getRemark()).controlView(0).creator((long) user.getUID()).createTime(now).updateTime(now).deleteType(DeleteTypeEnum.NOT_DELETED.getValue()).tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY).build(); List taxList = new ArrayList<>(); getTaxDeclarationService(user).saveBatch(taxList); } //组装数据,自动补足 List autoAddValuePOs = autoAddIds.stream().map((empId -> { TaxDeclarationValuePO taxDeclarationValue = TaxDeclarationValuePO.builder().id(IdGenerator.generate()).taxDeclareRecordId(taxDeclarationPO.getTaxDeclareRecordId()).taxDeclarationId(taxDeclarationPO.getId()).employeeType(0).employeeId(empId).resultValue(valueMap).tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY).creator((long) user.getUID()).deleteType(DeleteTypeEnum.NOT_DELETED.getValue()).createTime(now).updateTime(now).source(SourceEnum.AUTO.getValue()).build(); return taxDeclarationValue; })).collect(Collectors.toList()); batchSave(autoAddValuePOs); } @Override public void deleteById(Long deleteId) { getTaxDeclarationValueMapper().deleteByIds(Collections.singletonList(deleteId)); } }