package com.engine.salary.entity.taxdeclaration.bo; import com.engine.salary.entity.datacollection.AddUpSituation; import com.engine.salary.entity.datacollection.DataCollectionEmployee; import com.engine.salary.entity.salaryacct.po.SalaryAcctResultPO; import com.engine.salary.entity.salaryitem.po.SalaryItemPO; import com.engine.salary.entity.salarysob.po.SalarySobPO; import com.engine.salary.entity.taxdeclaration.dto.TaxDeclarationDetailListDTO; import com.engine.salary.entity.taxdeclaration.dto.TaxDeclarationListDTO; import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationSaveParam; import com.engine.salary.entity.taxdeclaration.po.TaxDeclarationDetailPO; import com.engine.salary.entity.taxdeclaration.po.TaxDeclarationPO; import com.engine.salary.entity.taxrate.TaxAgent; import com.engine.salary.enums.salarysob.IncomeCategoryEnum; import com.engine.salary.util.SalaryDateUtil; import com.engine.salary.util.SalaryEntityUtil; import com.engine.salary.util.SalaryI18nUtil; import com.engine.salary.util.page.PageInfo; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import dm.jdbc.util.IdGenerator; import lombok.Data; import org.apache.commons.collections4.CollectionUtils; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; /** * @description: 个税申报表 * @author: xiajun * @modified By: xiajun * @date: Created in 12/15/21 10:01 AM * @version:v1.0 */ public class TaxDeclarationBO { public static List convert2ListDTO(List taxDeclarations, List simpleEmployees, List taxAgents) { if (CollectionUtils.isEmpty(simpleEmployees)) { return Collections.emptyList(); } Map taxAgentNameMap = SalaryEntityUtil.convert2Map(taxAgents, TaxAgent::getId, TaxAgent::getName); Map employeeNameMap = SalaryEntityUtil.convert2Map(simpleEmployees, DataCollectionEmployee::getEmployeeId, DataCollectionEmployee::getUsername); return taxDeclarations.stream().map(e -> TaxDeclarationListDTO.builder() .id(e.getId()) .salaryMonth(e.getSalaryMonth()) .taxAgentId(e.getTaxAgentId()) .taxAgentName(taxAgentNameMap.getOrDefault(e.getTaxAgentId(), "")) .taxCycle(e.getTaxCycle()) .operateEmployeeId(e.getCreator()) .operateEmployeeName(employeeNameMap.getOrDefault(e.getCreator(), "")) .operateTime(SalaryDateUtil.getFormatLocalDateTime(e.getCreateTime())) .description(e.getDescription()) .build()).collect(Collectors.toList()); } public static void buildDetailListDTO(Long taxDeclarationId, PageInfo page, List taxDeclarationDetails, List simpleEmployees) { if (CollectionUtils.isEmpty(taxDeclarationDetails)) { return; } int index = (page.getNextPage() - 1) * page.getSize(); List dtos = Lists.newArrayListWithExpectedSize(simpleEmployees.size()); Map> taxDeclarationDetailMap = SalaryEntityUtil.group2Map(taxDeclarationDetails, TaxDeclarationDetailPO::getEmployeeId); for (DataCollectionEmployee simpleEmployee : simpleEmployees) { Map valueMap = SalaryEntityUtil.convert2Map(taxDeclarationDetailMap.get(simpleEmployee.getEmployeeId()), TaxDeclarationDetailPO::getFieldCode, TaxDeclarationDetailPO::getFieldValue); TaxDeclarationDetailListDTO dto = new TaxDeclarationDetailListDTO(); dto.setId(simpleEmployee.getEmployeeId()); dto.setTaxDeclarationId(taxDeclarationId); dto.setSeq(++index); dto.setEmployeeId(simpleEmployee.getEmployeeId()); dto.setEmployeeName(simpleEmployee.getUsername()); dto.setIdCardType(SalaryI18nUtil.getI18nLabel(101696,"身份证")); dto.setIdCardNo(""); dto.setTaxpayerIdNo(""); dto.setResidentType(SalaryI18nUtil.getI18nLabel(101697,"居民")); dto.setIncomeType(SalaryI18nUtil.getI18nLabel(101698,"工资、薪金")); dto.setIncome(valueMap.getOrDefault("income","")); dto.setFee(valueMap.getOrDefault("fee", "")); dto.setTaxFreeIncome(valueMap.getOrDefault("taxFreeIncome", "")); dto.setSubtraction(valueMap.getOrDefault("subtraction", "")); dto.setEndowmentInsurance(valueMap.getOrDefault("endowmentInsurance", "")); dto.setMedicalInsurance(valueMap.getOrDefault("medicalInsurance","")); dto.setUnemploymentInsurance(valueMap.getOrDefault("unemploymentInsurance","")); dto.setHousingProvidentFund(valueMap.getOrDefault("housingProvidentFund","")); dto.setAnnuity(valueMap.getOrDefault("annuity","")); dto.setCommercialHealthInsurance(valueMap.getOrDefault("commercialHealthInsurance","")); dto.setTaxDeferredEndowmentInsurance(valueMap.getOrDefault("taxDeferredEndowmentInsurance","")); dto.setOriginalValueOfProperty(valueMap.getOrDefault("originalValueOfProperty","")); dto.setDeductedTax(valueMap.getOrDefault("deductedTax","")); dto.setOther(valueMap.getOrDefault("other","")); dto.setAddUpIncome(valueMap.getOrDefault("addUpIncome","")); dto.setAddUpSubtraction(valueMap.getOrDefault("addUpSubtraction","")); dto.setAddUpSpecialDeduction(valueMap.getOrDefault("addUpSpecialDeduction","")); dto.setAddUpChildEducation(valueMap.getOrDefault("addUpChildEducation","")); dto.setAddUpContinuingEducation(valueMap.getOrDefault("addUpContinuingEducation","")); dto.setAddUpHousingLoanInterest(valueMap.getOrDefault("addUpHousingLoanInterest","")); dto.setAddUpHousingRent(valueMap.getOrDefault("addUpHousingRent","")); dto.setAddUpSupportElderly(valueMap.getOrDefault("addUpSupportElderly","")); dto.setAddUpOther(valueMap.getOrDefault("addUpOtherDeduction","")); dto.setLessTaxProportion(valueMap.getOrDefault("lessTaxProportion","")); dto.setAllowedDonation(valueMap.getOrDefault("addUpAllowedDonation","")); dto.setTaxableIncome(valueMap.getOrDefault("addUpTaxableIncome","")); dto.setTaxRate(valueMap.getOrDefault("taxRate","")); dto.setQuickDeductionFactor(valueMap.getOrDefault("quickDeductionFactor","")); dto.setTaxPayable(valueMap.getOrDefault("addUpTaxPayable","")); dto.setTaxSavings(valueMap.getOrDefault("addUpTaxDeduction","")); dto.setTaxWithheld(valueMap.getOrDefault("taxWithheld","")); dto.setRefundedOrSupplementedTax(valueMap.getOrDefault("refundedOrSupplementedTax","")); dtos.add(dto); } page.setList(dtos); } public static Result handle(TaxDeclarationSaveParam saveParam, Date taxCycle, List salaryItems, List salarySobs, List salaryAcctResults ) { Result result = new Result(); if (CollectionUtils.isEmpty(salaryAcctResults)) { return result; } // 薪资项目聚合成map(为了根据code获取id) Map salaryItemMap = SalaryEntityUtil.convert2Map(salaryItems, SalaryItemPO::getCode, SalaryItemPO::getId); // 薪资账套聚合成map(为了根据id获取incomeCategory) Map salarySobPOMap = SalaryEntityUtil.convert2Map(salarySobs, SalarySobPO::getId); // 薪资核算结果按照个税扣缴义务人id、所用薪资账套的incomeCategory聚合成map /* Map>> taxAgentIdKeyAcctResultMap = salaryAcctResults.stream() .collect(Collectors.groupingBy(SalaryAcctResultPO::getTaxAgentId, Collectors.groupingBy(salaryAcctResultPO -> salarySobPOMap.get(salaryAcctResultPO.getSalarySobId()).getIncomeCategory()))); */// 一个个税扣缴义务人,一种薪资类型生成一张个税申报表 Map> taxAgentIdKeyAcctResultMap = SalaryEntityUtil.group2Map(salaryAcctResults, SalaryAcctResultPO::getTaxAgentId); taxAgentIdKeyAcctResultMap.forEach((k, v) -> { // 新增的个税申报表 TaxDeclarationPO taxDeclaration = convert2PO(saveParam, taxCycle, k); result.getNeedInsertTaxDeclarations().add(taxDeclaration); // 处理个税申报明细以及累计情况 handleTaxDeclarationDetail(result, taxDeclaration, v, salaryItemMap); }); /*taxAgentIdKeyAcctResultMap.forEach((taxAgentId, incomeCategoryKeyAcctResultPOMap) -> { incomeCategoryKeyAcctResultPOMap.forEach((incomeCategory, salaryAcctResultPOS) -> { // 新增的个税申报表 TaxDeclarationPO taxDeclaration = convert2PO(saveParam, taxCycle, taxAgentId, incomeCategory, employeeId); result.getNeedInsertTaxDeclarations().add(taxDeclaration); if (Objects.equals(incomeCategory, IncomeCategoryEnum.WAGES_AND_SALARIES.getValue())) { // 生成个税申报表 handleTaxDeclaration4Wage(result, taxDeclaration, salaryAcctResultPOS, salaryItemMap); // 生成往期累计情况 handleAddUpSituation(result, taxDeclaration, salaryAcctResultPOS, salaryItemMap); } if (Objects.equals(incomeCategory, IncomeCategoryEnum.REMUNERATION_FOR_LABOR.getValue())) { // 生成个税申报表 handleTaxDeclaration4Labor(result, taxDeclaration, salaryAcctResultPOS, salaryItemMap); } }); });*/ return result; } private static void handleTaxDeclarationDetail(Result result, TaxDeclarationPO taxDeclaration, List salaryAcctResults, Map salaryItemMap) { if (CollectionUtils.isEmpty(salaryAcctResults)) { return; } // 核算结果按照人员id分类 Map> acctResultMap = SalaryEntityUtil.group2Map(salaryAcctResults, SalaryAcctResultPO::getEmployeeId); acctResultMap.forEach((k, v) -> { Map valueMap = Maps.newHashMapWithExpectedSize(32); Map> resultMap = SalaryEntityUtil.group2Map(v, SalaryAcctResultPO::getSalaryItemId); // 收入 BigDecimal income = SalaryEntityUtil.reduce(resultMap.get(salaryItemMap.getOrDefault("income", 0L)), e -> SalaryEntityUtil.empty2Zero(e.getResultValue())); valueMap.put("income", income); // 费用 BigDecimal fee = BigDecimal.ZERO; valueMap.put("fee", fee); // 免税收入 BigDecimal taxFreeIncome = BigDecimal.ZERO; valueMap.put("taxFreeIncome", taxFreeIncome); // 减除费用 BigDecimal subtraction = findValue("subtraction", resultMap, salaryItemMap); valueMap.put("subtraction", subtraction); // 基本养老保险 BigDecimal endowmentInsurance = findValue("endowmentInsurance", resultMap, salaryItemMap); valueMap.put("endowmentInsurance", endowmentInsurance); // 基本医疗保险 BigDecimal medicalInsurance = findValue("medicalInsurance", resultMap, salaryItemMap); valueMap.put("medicalInsurance", medicalInsurance); // 失业保险 BigDecimal unemploymentInsurance = findValue("unemploymentInsurance", resultMap, salaryItemMap); valueMap.put("unemploymentInsurance", unemploymentInsurance); // 住房公积金 BigDecimal housingProvidentFund = findValue("housingProvidentFund", resultMap, salaryItemMap); valueMap.put("housingProvidentFund", housingProvidentFund); // 年金 BigDecimal annuity = findValue("annuity", resultMap, salaryItemMap); valueMap.put("annuity", annuity); // 商业健康保险 BigDecimal commercialHealthInsurance = findValue("commercialHealthInsurance", resultMap, salaryItemMap); valueMap.put("commercialHealthInsurance", commercialHealthInsurance); // 税延养老保险 BigDecimal taxDeferredEndowmentInsurance = findValue("taxDeferredEndowmentInsurance", resultMap, salaryItemMap); valueMap.put("taxDeferredEndowmentInsurance", taxDeferredEndowmentInsurance); // 财产原值 BigDecimal originalValueOfProperty = findValue("originalValueOfProperty", resultMap, salaryItemMap); valueMap.put("originalValueOfProperty", originalValueOfProperty); // 允许扣除的税费 BigDecimal deductedTax = findValue("deductedTax", resultMap, salaryItemMap); valueMap.put("deductedTax", deductedTax); // 其他 BigDecimal other = findValue("other", resultMap, salaryItemMap); valueMap.put("other", other); // 累计收入 BigDecimal addUpIncome = findAddUpValue("addUpIncome", resultMap, salaryItemMap); valueMap.put("addUpIncome", addUpIncome); // 累计减除费用 BigDecimal addUpSubtraction = findAddUpValue("addUpSubtraction", resultMap, salaryItemMap); valueMap.put("addUpSubtraction", addUpSubtraction); // 累计专项扣除 BigDecimal addUpSpecialDeduction = findAddUpValue("addUpSpecialDeduction", resultMap, salaryItemMap); valueMap.put("addUpSpecialDeduction", addUpSpecialDeduction); // 累计子女教育 BigDecimal addUpChildEducation = findAddUpValue("addUpChildEducation", resultMap, salaryItemMap); valueMap.put("addUpChildEducation", addUpChildEducation); // 累计继续教育 BigDecimal addUpContinuingEducation = findAddUpValue("addUpContinuingEducation", resultMap, salaryItemMap); valueMap.put("addUpContinuingEducation", addUpContinuingEducation); // 累计住房贷款利息 BigDecimal addUpHousingLoanInterest = findAddUpValue("addUpHousingLoanInterest", resultMap, salaryItemMap); valueMap.put("addUpHousingLoanInterest", addUpHousingLoanInterest); // 累计住房租金 BigDecimal addUpHousingRent = findAddUpValue("addUpHousingRent", resultMap, salaryItemMap); valueMap.put("addUpHousingRent", addUpHousingRent); // 累计赡养老人 BigDecimal addUpSupportElderly = findAddUpValue("addUpSupportElderly", resultMap, salaryItemMap); valueMap.put("addUpSupportElderly", addUpSupportElderly); // 累计其他扣除 BigDecimal addUpOtherDeduction = findAddUpValue("addUpOtherDeduction", resultMap, salaryItemMap); valueMap.put("addUpOtherDeduction", addUpOtherDeduction); // 减按计税比例 BigDecimal lessTaxProportion = BigDecimal.ONE; valueMap.put("lessTaxProportion", lessTaxProportion); // 准允扣除的捐赠额 BigDecimal addUpAllowedDonation = findAddUpValue("addUpAllowedDonation", resultMap, salaryItemMap); valueMap.put("addUpAllowedDonation", addUpAllowedDonation); // 应纳税所得额 BigDecimal addUpTaxableIncome = findAddUpValue("addUpTaxableIncome", resultMap, salaryItemMap); valueMap.put("addUpTaxableIncome", addUpTaxableIncome); // 税率 BigDecimal taxRate = findAddUpValue("taxRate", resultMap, salaryItemMap); valueMap.put("taxRate", taxRate); // 速算扣除数 BigDecimal quickDeductionFactor = findAddUpValue("quickDeductionFactor", resultMap, salaryItemMap); valueMap.put("quickDeductionFactor", quickDeductionFactor); // 应纳税额 BigDecimal addUpTaxPayable = findAddUpValue("addUpTaxPayable", resultMap, salaryItemMap); valueMap.put("addUpTaxPayable", addUpTaxPayable); // 减免税额 BigDecimal addUpTaxDeduction = BigDecimal.ZERO; valueMap.put("addUpTaxDeduction", addUpTaxDeduction); // 应补缴税额 BigDecimal refundedOrSupplementedTax = SalaryEntityUtil.reduce(resultMap.get(salaryItemMap.getOrDefault("refundedOrSupplementedTax", 0L)), e -> SalaryEntityUtil.empty2Zero(e.getResultValue())); valueMap.put("refundedOrSupplementedTax", refundedOrSupplementedTax); // 已扣缴税额 BigDecimal taxWithheld = addUpTaxPayable.subtract(refundedOrSupplementedTax); valueMap.put("taxWithheld", taxWithheld); valueMap.forEach((key, value) -> { TaxDeclarationDetailPO detailPO = TaxDeclarationDetailPO.builder() .id(IdGenerator.generate()) .taxDeclarationId(taxDeclaration.getId()) .employeeId(k) .fieldCode(key) .fieldValue(value.toPlainString()) .creator(taxDeclaration.getCreator()) .createTime(taxDeclaration.getCreateTime()) .updateTime(taxDeclaration.getUpdateTime()) .deleteType(0) .tenantKey(taxDeclaration.getTenantKey()) .build(); result.getNeedInsertTaxDeclarationDetails().add(detailPO); }); // 累计社保个人合计 BigDecimal addUpSocialSecurityTotal = findAddUpValue("addUpSocialSecurityTotal", resultMap, salaryItemMap); // 累计公积金个人合计 BigDecimal addUpAccumulationFundTotal = findAddUpValue("addUpAccumulationFundTotal", resultMap, salaryItemMap); // 累计年金及其他福利合计 BigDecimal addUpEnterpriseAndOther = findAddUpValue("addUpEnterpriseAndOther", resultMap, salaryItemMap); // 更新累计情况 AddUpSituation accumulatedSituation = AddUpSituation.builder() .id(IdGenerator.generate()) .employeeId(k) .taxAgentId(taxDeclaration.getTaxAgentId()) .taxYearMonth((taxDeclaration.getSalaryMonth())) .year(taxDeclaration.getSalaryMonth().getYear()) .addUpIncome(addUpIncome.toPlainString()) .addUpSocialSecurityTotal(addUpSocialSecurityTotal.toPlainString()) .addUpAccumulationFundTotal(addUpAccumulationFundTotal.toPlainString()) .addUpEnterpriseAndOther(addUpEnterpriseAndOther.toPlainString()) .addUpSubtraction(addUpSubtraction.toPlainString()) .addUpChildEducation(addUpChildEducation.toPlainString()) .addUpContinuingEducation(addUpContinuingEducation.toPlainString()) .addUpHousingLoanInterest(addUpHousingLoanInterest.toPlainString()) .addUpHousingRent(addUpHousingRent.toPlainString()) .addUpSupportElderly(addUpSupportElderly.toPlainString()) .addUpOtherDeduction(addUpOtherDeduction.toPlainString()) .addUpTaxExemptIncome("0") .addUpAllowedDonation(addUpAllowedDonation.toPlainString()) .addUpAdvanceTax(addUpTaxPayable.toPlainString()) .creator(taxDeclaration.getCreator()) .createTime(taxDeclaration.getCreateTime()) .updateTime(taxDeclaration.getUpdateTime()) .tenantKey(taxDeclaration.getTenantKey()) .deleteType(0) .build(); result.getNeedInsertAccumulatedSituations().add(accumulatedSituation); }); } private static TaxDeclarationPO convert2PO(TaxDeclarationSaveParam saveParam, Date taxCycle, Long taxAgentId) { LocalDateTime now = LocalDateTime.now(); return TaxDeclarationPO.builder() .id(IdGenerator.generate()) .taxAgentId(taxAgentId) .salaryMonth(SalaryDateUtil.localDateToDate(saveParam.getSalaryMonth().atDay(1))) .taxCycle(taxCycle) .description(saveParam.getDescription()) // .creator(employeeId) .createTime(SalaryDateUtil.localDateTimeToDate(now)) .updateTime(SalaryDateUtil.localDateTimeToDate(now)) .deleteType(0) //.tenantKey(tenantKey) .build(); } private static BigDecimal findValue(String fieldCode, Map> resultMap, Map salaryItemMap) { return resultMap.getOrDefault(salaryItemMap.getOrDefault(fieldCode, 0L), Collections.emptyList()).stream() .map(e -> SalaryEntityUtil.empty2Zero(e.getResultValue())) .filter(e -> e.compareTo(BigDecimal.ZERO) > 0) .findAny() .orElse(BigDecimal.ZERO); } private static BigDecimal findAddUpValue(String fieldCode, Map> resultMap, Map salaryItemMap) { return resultMap.getOrDefault(salaryItemMap.getOrDefault(fieldCode, 0L), Collections.emptyList()).stream() .map(e -> SalaryEntityUtil.empty2Zero(e.getResultValue())) .max(Comparator.comparingDouble(BigDecimal::doubleValue)) .orElse(BigDecimal.ZERO); } @Data public static class Result { private Collection needInsertTaxDeclarations; private Collection needInsertTaxDeclarationDetails; private Collection needInsertAccumulatedSituations; public Result() { this.needInsertTaxDeclarations = Lists.newArrayList(); this.needInsertTaxDeclarationDetails = Lists.newArrayList(); this.needInsertAccumulatedSituations = Lists.newArrayList(); } } }