package com.engine.salary.entity.taxdeclaration.bo; import com.engine.salary.constant.SalaryDefaultTenantConstant; import com.engine.salary.constant.TaxDeclarationDataIndexConstant; import com.engine.salary.encrypt.EncryptUtil; 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.taxagent.po.TaxAgentPO; 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.enums.salaryaccounting.EmployeeTypeEnum; 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 com.engine.salary.util.db.IdGenerator; import lombok.Data; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import weaver.hrm.User; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; /** * 个税申报表 *

Copyright: Copyright (c) 2022

*

Company: 泛微软件

* * @author qiantao * @version 1.0 **/ public class TaxDeclarationBO { private static EncryptUtil encryptUtil = new EncryptUtil(); public static List convert2ListDTO(List taxDeclarations, List simpleEmployees, List taxAgents) { if (CollectionUtils.isEmpty(simpleEmployees)) { simpleEmployees = new ArrayList<>(); } Map taxAgentNameMap = SalaryEntityUtil.convert2Map(taxAgents, TaxAgentPO::getId, TaxAgentPO::getName); Map employeeNameMap = SalaryEntityUtil.convert2Map(simpleEmployees, DataCollectionEmployee::getEmployeeId, DataCollectionEmployee::getUsername); return taxDeclarations.stream() .map(taxDeclarationPO -> { IncomeCategoryEnum incomeCategoryEnum = IncomeCategoryEnum.parseByValue(taxDeclarationPO.getIncomeCategory()); return TaxDeclarationListDTO.builder() .id(taxDeclarationPO.getId()) .incomeCategory(Optional.ofNullable(incomeCategoryEnum) .map(o -> SalaryI18nUtil.getI18nLabel(o.getLabelId(), o.getDefaultLabel())) .orElse(StringUtils.EMPTY)) .salaryMonth(taxDeclarationPO.getSalaryMonth()) .taxAgentId(taxDeclarationPO.getTaxAgentId()) .taxAgentName(taxAgentNameMap.getOrDefault(taxDeclarationPO.getTaxAgentId(), "")) .taxCycle(taxDeclarationPO.getTaxCycle()) .operateEmployeeId(taxDeclarationPO.getCreator()) .operateEmployeeName(employeeNameMap.getOrDefault(taxDeclarationPO.getCreator(), "")) .operateTime(SalaryDateUtil.getFormatLocalDateTime(taxDeclarationPO.getCreateTime())) .description(taxDeclarationPO.getDescription()) .opts(taxDeclarationPO.getOpts()) .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, User user, 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()))); // 一个个税扣缴义务人,一种薪资类型生成一张个税申报表 taxAgentIdKeyAcctResultMap.forEach((taxAgentId, incomeCategoryKeyAcctResultPOMap) -> { incomeCategoryKeyAcctResultPOMap.forEach((incomeCategory, salaryAcctResultPOS) -> { // 新增的个税申报表 TaxDeclarationPO taxDeclaration = convert2PO(saveParam, user, taxCycle, taxAgentId, incomeCategory); 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); } if (Objects.equals(incomeCategory, IncomeCategoryEnum.ONETIME_ANNUAL_BONUS.getValue())) { // 生成个税申报表 handleTaxDeclaration4Annual(result, taxDeclaration, salaryAcctResultPOS, salaryItemMap); } }); }); return result; } /** * 生成个税申报表明细(正常工资薪金所得) * * @param result * @param taxDeclaration * @param salaryAcctResults * @param salaryItemMap */ private static void handleTaxDeclaration4Wage(Result result, TaxDeclarationPO taxDeclaration, List salaryAcctResults, Map salaryItemMap) { if (CollectionUtils.isEmpty(salaryAcctResults)) { return; } // 核算结果按照人员id分类 Map> salaryAcctResultPOMap = SalaryEntityUtil.group2Map(salaryAcctResults, salaryAcctResultPO -> EmployeeTypeEnum.ORGANIZATION.getValue() + "_" + salaryAcctResultPO.getEmployeeId()); salaryAcctResultPOMap.forEach((key, salaryAcctResultPOS) -> { String[] keyArray = StringUtils.split(key, "_"); // 员工类型 Integer employeeType = Integer.parseInt(keyArray[0]); // 员工id Long employeeId = Long.parseLong(keyArray[1]); Map valueMap = Maps.newHashMapWithExpectedSize(17); Map> resultMap = SalaryEntityUtil.group2Map(salaryAcctResultPOS, SalaryAcctResultPO::getSalaryItemId); // 本期收入 BigDecimal income = SalaryEntityUtil.reduce(resultMap.get(salaryItemMap.getOrDefault(TaxDeclarationDataIndexConstant.INCOME, 0L)), salaryAcctResultPO -> SalaryEntityUtil.empty2Zero(salaryAcctResultPO.getResultValue())); valueMap.put(TaxDeclarationDataIndexConstant.INCOME, income.toPlainString()); // 本期免税收入 BigDecimal taxFreeIncome = findValue(TaxDeclarationDataIndexConstant.TAX_FREE_INCOME, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.TAX_FREE_INCOME, taxFreeIncome.toPlainString()); // 基本养老保险 BigDecimal endowmentInsurance = findValue(TaxDeclarationDataIndexConstant.ENDOWMENT_INSURANCE, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.ENDOWMENT_INSURANCE, endowmentInsurance.toPlainString()); // 基本医疗保险 BigDecimal medicalInsurance = findValue(TaxDeclarationDataIndexConstant.MEDICAL_INSURANCE, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.MEDICAL_INSURANCE, medicalInsurance.toPlainString()); // 失业保险费 BigDecimal unemploymentInsurance = findValue(TaxDeclarationDataIndexConstant.UNEMPLOYMENT_INSURANCE, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.UNEMPLOYMENT_INSURANCE, unemploymentInsurance.toPlainString()); // 住房公积金 BigDecimal housingProvidentFund = findValue(TaxDeclarationDataIndexConstant.HOUSING_PROVIDENT_FUND, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.HOUSING_PROVIDENT_FUND, housingProvidentFund.toPlainString()); // 累计子女教育 BigDecimal addUpChildEducation = findValue(TaxDeclarationDataIndexConstant.ADD_UP_CHILD_EDUCATION, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.ADD_UP_CHILD_EDUCATION, addUpChildEducation.toPlainString()); // 累计继续教育 BigDecimal addUpContinuingEducation = findValue(TaxDeclarationDataIndexConstant.ADD_UP_CONTINUING_EDUCATION, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.ADD_UP_CONTINUING_EDUCATION, addUpContinuingEducation.toPlainString()); // 累计住房贷款利息 BigDecimal addUpHousingLoanInterest = findValue(TaxDeclarationDataIndexConstant.ADD_UP_HOUSING_LOAN_INTEREST, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.ADD_UP_HOUSING_LOAN_INTEREST, addUpHousingLoanInterest.toPlainString()); // 累计住房租金 BigDecimal addUpHousingRent = findValue(TaxDeclarationDataIndexConstant.ADD_UP_HOUSING_RENT, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.ADD_UP_HOUSING_RENT, addUpHousingRent.toPlainString()); // 累计赡养老人 BigDecimal addUpSupportElderly = findValue(TaxDeclarationDataIndexConstant.ADD_UP_SUPPORT_ELDERLY, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.ADD_UP_SUPPORT_ELDERLY, addUpSupportElderly.toPlainString()); // 累计大病医疗 BigDecimal addUpIllnessMedical = findValue(TaxDeclarationDataIndexConstant.ADD_UP_ILLNESS_MEDICAL, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.ADD_UP_ILLNESS_MEDICAL, addUpIllnessMedical.toPlainString()); // 累计婴幼儿照护 BigDecimal addUpInfantCare = findValue(TaxDeclarationDataIndexConstant.ADD_UP_INFANT_CARE, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.ADD_UP_INFANT_CARE, addUpInfantCare.toPlainString()); // 累计个人养老金 BigDecimal addUpPrivatePension = findValue(TaxDeclarationDataIndexConstant.ADD_UP_PRIVATE_PENSION, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.ADD_UP_PRIVATE_PENSION, addUpPrivatePension.toPlainString()); // 企业(职业)年金 BigDecimal annuity = findValue(TaxDeclarationDataIndexConstant.ANNUITY, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.ANNUITY, annuity.toPlainString()); // 商业健康保险 BigDecimal commercialHealthInsurance = findValue(TaxDeclarationDataIndexConstant.COMMERCIAL_HEALTH_INSURANCE, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.COMMERCIAL_HEALTH_INSURANCE, commercialHealthInsurance.toPlainString()); // 税延养老保险 BigDecimal taxDeferredEndowmentInsurance = findValue(TaxDeclarationDataIndexConstant.TAX_DEFERRED_ENDOWMENT_INSURANCE, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.TAX_DEFERRED_ENDOWMENT_INSURANCE, taxDeferredEndowmentInsurance.toPlainString()); // 其他 BigDecimal other = findValue(TaxDeclarationDataIndexConstant.OTHER, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.OTHER, other.toPlainString()); // 准予扣除的捐赠额 BigDecimal allowedDonation = findValue(TaxDeclarationDataIndexConstant.ALLOWED_DONATION, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.ALLOWED_DONATION, allowedDonation.toPlainString()); // 减免税额 BigDecimal taxDeduction = findValue(TaxDeclarationDataIndexConstant.TAX_DEDUCTION, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.TAX_DEDUCTION, taxDeduction.toPlainString()); // 生成个税申报表详情 result.getNeedInsertTaxDeclarationDetails().addAll(convert2DetailPO(taxDeclaration, employeeType, employeeId, valueMap)); }); } /** * 生成个税申报表明细(劳务报酬所得) * * @param result * @param taxDeclaration * @param salaryAcctResults * @param salaryItemMap */ private static void handleTaxDeclaration4Labor(Result result, TaxDeclarationPO taxDeclaration, List salaryAcctResults, Map salaryItemMap) { if (CollectionUtils.isEmpty(salaryAcctResults)) { return; } // 核算结果按照人员id分类 Map> salaryAcctResultPOMap = SalaryEntityUtil.group2Map(salaryAcctResults, salaryAcctResultPO -> EmployeeTypeEnum.ORGANIZATION.getValue() + "_" + salaryAcctResultPO.getEmployeeId()); salaryAcctResultPOMap.forEach((key, salaryAcctResultPOS) -> { String[] keyArray = StringUtils.split(key, "_"); Integer employeeType = Integer.parseInt(keyArray[0]); Long employeeId = Long.parseLong(keyArray[1]); Map valueMap = Maps.newHashMapWithExpectedSize(7); Map> resultMap = SalaryEntityUtil.group2Map(salaryAcctResultPOS, SalaryAcctResultPO::getSalaryItemId); // 所得项目 String incomeItems = resultMap.getOrDefault(salaryItemMap.getOrDefault(TaxDeclarationDataIndexConstant.INCOME_ITEMS, 0L), Collections.emptyList()).stream() .map(SalaryAcctResultPO::getResultValue) .findAny() .orElse(StringUtils.EMPTY); valueMap.put(TaxDeclarationDataIndexConstant.INCOME_ITEMS, incomeItems); // 收入 BigDecimal laborIncome = findValue(TaxDeclarationDataIndexConstant.LABOR_INCOME, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.LABOR_INCOME, laborIncome.toPlainString()); // 免税收入 BigDecimal laborTaxFreeIncome = findValue(TaxDeclarationDataIndexConstant.LABOR_TAX_FREE_INCOME, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.LABOR_TAX_FREE_INCOME, laborTaxFreeIncome.toPlainString()); // 商业健康保险 BigDecimal commercialHealthInsurance = findValue(TaxDeclarationDataIndexConstant.COMMERCIAL_HEALTH_INSURANCE, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.COMMERCIAL_HEALTH_INSURANCE, commercialHealthInsurance.toPlainString()); // 税延养老保险 BigDecimal taxDeferredEndowmentInsurance = findValue(TaxDeclarationDataIndexConstant.TAX_DEFERRED_ENDOWMENT_INSURANCE, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.TAX_DEFERRED_ENDOWMENT_INSURANCE, taxDeferredEndowmentInsurance.toPlainString()); // 其他 BigDecimal other = findValue(TaxDeclarationDataIndexConstant.OTHER, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.OTHER, other.toPlainString()); // 准予扣除的捐赠额 BigDecimal allowedDonation = findValue(TaxDeclarationDataIndexConstant.ALLOWED_DONATION, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.ALLOWED_DONATION, allowedDonation.toPlainString()); // 生成个税申报表详情 result.getNeedInsertTaxDeclarationDetails().addAll(convert2DetailPO(taxDeclaration, employeeType, employeeId, valueMap)); }); } /** * 生成个税申报表明细(年终奖) * * @param result * @param taxDeclaration * @param salaryAcctResults * @param salaryItemMap */ private static void handleTaxDeclaration4Annual(Result result, TaxDeclarationPO taxDeclaration, List salaryAcctResults, Map salaryItemMap) { if (CollectionUtils.isEmpty(salaryAcctResults)) { return; } // 核算结果按照人员id分类 Map> salaryAcctResultPOMap = SalaryEntityUtil.group2Map(salaryAcctResults, salaryAcctResultPO -> EmployeeTypeEnum.ORGANIZATION.getValue() + "_" + salaryAcctResultPO.getEmployeeId()); salaryAcctResultPOMap.forEach((key, salaryAcctResultPOS) -> { String[] keyArray = StringUtils.split(key, "_"); Integer employeeType = Integer.parseInt(keyArray[0]); Long employeeId = Long.parseLong(keyArray[1]); Map valueMap = Maps.newHashMapWithExpectedSize(7); Map> resultMap = SalaryEntityUtil.group2Map(salaryAcctResultPOS, SalaryAcctResultPO::getSalaryItemId); // 全年一次性奖金额 BigDecimal laborIncome = findValue(TaxDeclarationDataIndexConstant.ANNUAL_INCOME, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.ANNUAL_INCOME, laborIncome.toPlainString()); // 免税收入 BigDecimal laborTaxFreeIncome = findValue(TaxDeclarationDataIndexConstant.ANNUAL_TAX_FREE_INCOME, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.ANNUAL_TAX_FREE_INCOME, laborTaxFreeIncome.toPlainString()); // 其他 BigDecimal other = findValue(TaxDeclarationDataIndexConstant.ANNUAL_OTHER, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.ANNUAL_OTHER, other.toPlainString()); // 准予扣除的捐赠额 BigDecimal allowedDonation = findValue(TaxDeclarationDataIndexConstant.ANNUAL_DONATE_TAX, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.ANNUAL_DONATE_TAX, allowedDonation.toPlainString()); // 减免税额 BigDecimal annualTaxSavings = findValue(TaxDeclarationDataIndexConstant.ANNUAL_TAX_SAVINGS, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.ANNUAL_TAX_SAVINGS, annualTaxSavings.toPlainString()); // 备注 String annualRemark = findStringValue(TaxDeclarationDataIndexConstant.ANNUAL_REMARK, resultMap, salaryItemMap); valueMap.put(TaxDeclarationDataIndexConstant.ANNUAL_REMARK, annualRemark); // 生成个税申报表详情 result.getNeedInsertTaxDeclarationDetails().addAll(convert2DetailPO(taxDeclaration, employeeType, employeeId, valueMap)); }); } /** * 往期累计情况 * * @param result * @param taxDeclaration * @param salaryAcctResults * @param salaryItemMap */ private static void handleAddUpSituation(Result result, TaxDeclarationPO taxDeclaration, List salaryAcctResults, Map salaryItemMap) { if (CollectionUtils.isEmpty(salaryAcctResults)) { return; } // 核算结果按照人员id分类 Map> salaryAcctResultPOMap = SalaryEntityUtil.group2Map(salaryAcctResults, salaryAcctResultPO -> EmployeeTypeEnum.ORGANIZATION.getValue() + "_" + salaryAcctResultPO.getEmployeeId()); salaryAcctResultPOMap.forEach((key, salaryAcctResultPOS) -> { String[] keyArray = key.split("_"); Integer employeeType = Integer.parseInt(keyArray[0]); Long employeeId = Long.parseLong(keyArray[1]); Map> resultMap = SalaryEntityUtil.group2Map(salaryAcctResultPOS, SalaryAcctResultPO::getSalaryItemId); // 累计收入额 BigDecimal addUpIncome = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_INCOME, resultMap, salaryItemMap); // 累计免税收入 BigDecimal addUpTaxFreeIncome = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_TAX_FREE_INCOME, resultMap, salaryItemMap); // 累计减除费用 BigDecimal addUpSubtraction = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_SUBTRACTION, resultMap, salaryItemMap); // 累计社保个人合计 BigDecimal addUpSocialSecurityTotal = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_SOCIAL_SECURITY_TOTAL, resultMap, salaryItemMap); // 累计公积金个人合计 BigDecimal addUpAccumulationFundTotal = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_ACCUMULATION_FUND_TOTAL, resultMap, salaryItemMap); // 累计子女教育 BigDecimal addUpChildEducation = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_CHILD_EDUCATION, resultMap, salaryItemMap); // 累计继续教育 BigDecimal addUpContinuingEducation = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_CONTINUING_EDUCATION, resultMap, salaryItemMap); // 累计住房贷款利息 BigDecimal addUpHousingLoanInterest = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_HOUSING_LOAN_INTEREST, resultMap, salaryItemMap); // 累计住房租金 BigDecimal addUpHousingRent = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_HOUSING_RENT, resultMap, salaryItemMap); // 累计赡养老人 BigDecimal addUpSupportElderly = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_SUPPORT_ELDERLY, resultMap, salaryItemMap); // 累计大病医疗 BigDecimal addUpIllnessMedical = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_ILLNESS_MEDICAL, resultMap, salaryItemMap); // 累计婴幼儿照护 BigDecimal addUpInfantCare = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_INFANT_CARE, resultMap, salaryItemMap); // 累计个人养老金 BigDecimal addUpPrivatePension = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_PRIVATE_PENSION, resultMap, salaryItemMap); // 累计企业(职业)年金及其他福利 BigDecimal addUpEnterpriseAndOther = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_ENTERPRISE_AND_OTHER, resultMap, salaryItemMap); // 累计其他免税扣除 BigDecimal addUpOtherDeduction = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_OTHER_DEDUCTION, resultMap, salaryItemMap); // 累计准予扣除的捐赠额 BigDecimal addUpAllowedDonation = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_ALLOWED_DONATION, resultMap, salaryItemMap); // 累计应纳税所得额 BigDecimal addUpTaxableIncome = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_TAXABLE_INCOME, resultMap, salaryItemMap); // 累计应纳税额 BigDecimal addUpTaxPayable = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_TAX_PAYABLE, resultMap, salaryItemMap); //累计减免税额 BigDecimal addUpTaxDeduction = findAddUpValue(TaxDeclarationDataIndexConstant.ADD_UP_TAX_DEDUCTION, resultMap, salaryItemMap); // 累计已预扣预缴税额 List resultPOS = resultMap.get(salaryItemMap.getOrDefault(TaxDeclarationDataIndexConstant.ADD_UP_ADVANCE_TAX, 0L)); BigDecimal addUpAdvanceTax = resultPOS == null ? BigDecimal.ZERO : resultPOS.stream() .map(salaryAcctResultPO -> SalaryEntityUtil.empty2Zero(salaryAcctResultPO.getResultValue())) .min(BigDecimal::compareTo) .orElse(BigDecimal.ZERO); // 本月(次)应补(退)税额 BigDecimal refundedOrSupplementedTax = SalaryEntityUtil.reduce(resultMap.get(salaryItemMap.getOrDefault(TaxDeclarationDataIndexConstant.REFUNDED_OR_SUPPLEMENTED_TAX, 0L)), salaryAcctResultPO -> SalaryEntityUtil.empty2Zero(salaryAcctResultPO.getResultValue())); // 生成往期累计情况 AddUpSituation accumulatedSituation = AddUpSituation.builder() .employeeId(employeeId) // .employeeType(employeeType) .taxAgentId(taxDeclaration.getTaxAgentId()) .taxYearMonth(taxDeclaration.getTaxCycle()) .year(SalaryDateUtil.date2Year(taxDeclaration.getTaxCycle())) .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()) .addUpIllnessMedical(addUpIllnessMedical.toPlainString()) .addUpInfantCare(addUpInfantCare.toPlainString()) .addUpPrivatePension(addUpPrivatePension.toPlainString()) .addUpOtherDeduction(addUpOtherDeduction.toPlainString()) .addUpTaxExemptIncome(addUpTaxFreeIncome.toPlainString()) .addUpAllowedDonation(addUpAllowedDonation.toPlainString()) .addUpAdvanceTax(addUpAdvanceTax.add(refundedOrSupplementedTax).toPlainString()) .addUpTaxSavings(addUpTaxDeduction.toPlainString()) .creator(taxDeclaration.getCreator()) .createTime(taxDeclaration.getCreateTime()) .updateTime(taxDeclaration.getUpdateTime()) .tenantKey(taxDeclaration.getTenantKey()) .deleteType(NumberUtils.INTEGER_ZERO) .build(); encryptUtil.encrypt(accumulatedSituation, AddUpSituation.class); result.getNeedInsertAddUpSituations().add(accumulatedSituation); }); } // 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) -> { // Long employeeId = k; // Map valueMap = new HashMap<>(); // 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 addUpTaxFreeIncome = findAddUpValue("addUpTaxFreeIncome", resultMap, salaryItemMap); // valueMap.put("addUpTaxFreeIncome", addUpTaxFreeIncome); // // 累计减除费用 // 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 addUpIllnessMedical = findAddUpValue("addUpIllnessMedical", resultMap, salaryItemMap); // valueMap.put("addUpIllnessMedical", addUpIllnessMedical); // // 累计婴幼儿照护 // BigDecimal addUpInfantCare = findAddUpValue("addUpInfantCare", resultMap, salaryItemMap); // valueMap.put("addUpInfantCare", addUpInfantCare); // // 累计其他扣除 // 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 taxDeduction = findValue("taxDeduction", resultMap, salaryItemMap); // valueMap.put("taxDeduction", taxDeduction); // // 应补缴税额 // 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() // .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() // .employeeId(employeeId) // .taxAgentId(taxDeclaration.getTaxAgentId()) // .taxYearMonth(taxDeclaration.getTaxCycle()) // .year(SalaryDateUtil.date2Year(taxDeclaration.getTaxCycle())) // .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()) // .addUpIllnessMedical(addUpIllnessMedical.toPlainString()) // .addUpInfantCare(addUpInfantCare.toPlainString()) // .addUpOtherDeduction(addUpOtherDeduction.toPlainString()) // .addUpTaxExemptIncome(addUpTaxFreeIncome.toPlainString()) // .addUpAllowedDonation(addUpAllowedDonation.toPlainString()) // .addUpAdvanceTax(addUpTaxPayable.toPlainString()) //// .addUpTaxSavings(taxDeduction.toPlainString()) // .creator(taxDeclaration.getCreator()) // .createTime(taxDeclaration.getCreateTime()) // .updateTime(taxDeclaration.getUpdateTime()) // .tenantKey(taxDeclaration.getTenantKey()) // .deleteType(NumberUtils.INTEGER_ZERO) // .build(); // result.getNeedInsertAccumulatedSituations().add(accumulatedSituation); // }); // } private static TaxDeclarationPO convert2PO(TaxDeclarationSaveParam saveParam, User user, Date taxCycle, Long taxAgentId, Integer incomeCategory) { LocalDateTime now = LocalDateTime.now(); if (saveParam.getDescription() == null) { saveParam.setDescription(""); } return TaxDeclarationPO.builder() .id(IdGenerator.generate()) .incomeCategory(incomeCategory) .taxAgentId(taxAgentId) .salaryMonth(SalaryDateUtil.localDateToDate(saveParam.getSalaryMonth().atDay(1))) .taxCycle(taxCycle) .description(saveParam.getDescription()) .creator((long) user.getUID()) .createTime(SalaryDateUtil.localDateTimeToDate(now)) .updateTime(SalaryDateUtil.localDateTimeToDate(now)) .deleteType(0) .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY) .build(); } /** * 根据参数生成个税申报表详情po * * @param taxDeclaration * @param employeeId * @param valueMap * @return */ private static List convert2DetailPO(TaxDeclarationPO taxDeclaration, Integer employeeType, Long employeeId, Map valueMap) { if (MapUtils.isEmpty(valueMap)) { return Collections.emptyList(); } List taxDeclarationDetailPOS = Lists.newArrayListWithExpectedSize(valueMap.size()); valueMap.forEach((fieldCode, fieldValue) -> { TaxDeclarationDetailPO taxDeclarationDetailPO = TaxDeclarationDetailPO.builder() .id(IdGenerator.generate()) .taxDeclarationId(taxDeclaration.getId()) .employeeType(employeeType) .employeeId(employeeId) .fieldCode(fieldCode) .fieldValue(fieldValue) .creator(taxDeclaration.getCreator()) .createTime(taxDeclaration.getCreateTime()) .updateTime(taxDeclaration.getUpdateTime()) .deleteType(NumberUtils.INTEGER_ZERO) .tenantKey(taxDeclaration.getTenantKey()) .build(); taxDeclarationDetailPOS.add(taxDeclarationDetailPO); }); return taxDeclarationDetailPOS; } 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); } private static String findStringValue(String fieldCode, Map> resultMap, Map salaryItemMap) { return resultMap.getOrDefault(salaryItemMap.getOrDefault(fieldCode, 0L), Collections.emptyList()).stream() .map(SalaryAcctResultPO::getResultValue) .filter(Objects::nonNull) .findFirst().orElse(""); } @Data public static class Result { private Collection needInsertTaxDeclarations; private Collection needInsertTaxDeclarationDetails; private Collection needInsertAddUpSituations; public Result() { this.needInsertTaxDeclarations = Lists.newArrayList(); this.needInsertTaxDeclarationDetails = Lists.newArrayList(); this.needInsertAddUpSituations = Lists.newArrayList(); } } }