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();
}
}
}