package com.engine.salary.entity.taxdeclaration.bo; import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.StrUtil; import com.engine.salary.annotation.SalaryFormulaVar; import com.engine.salary.constant.SalaryDefaultTenantConstant; import com.engine.salary.entity.datacollection.AddUpSituation; import com.engine.salary.entity.salaryacct.po.SalaryAcctEmployeePO; import com.engine.salary.entity.salaryacct.po.SalaryAcctRecordPO; import com.engine.salary.entity.salaryacct.po.SalaryAcctResultPO; import com.engine.salary.entity.salarysob.po.SalarySobAddUpRulePO; import com.engine.salary.entity.salarysob.po.SalarySobTaxReportRulePO; import com.engine.salary.entity.taxdeclaration.po.TaxDeclarationPO; import com.engine.salary.entity.taxdeclaration.po.TaxDeclarationValuePO; import com.engine.salary.entity.taxdeclaration.po.TaxReportColumnPO; import com.engine.salary.enums.salaryitem.SalaryDataTypeEnum; import com.engine.salary.enums.salarysob.IncomeCategoryEnum; import com.engine.salary.enums.sicategory.DeleteTypeEnum; import com.engine.salary.enums.taxdeclaration.SourceEnum; import com.engine.salary.util.SalaryDateUtil; import com.engine.salary.util.SalaryEntityUtil; import com.engine.salary.util.db.IdGenerator; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import weaver.general.BaseBean; import java.lang.reflect.Field; import java.math.BigDecimal; import java.util.*; import java.util.stream.Collectors; /** * 通用:一般劳务报酬所得、全年一次性奖金 *

Copyright: Copyright (c) 2023

*

Company: 泛微软件

* * @author qiantao * @version 1.0 **/ public class TaxDeclarationCommon implements TaxDeclarationStrategy { @Override public TaxDeclarationGenerateResult generate(TaxDeclareContext taxDeclareContext, Long employeeId) { // 获取联特绩效账套 BaseBean baseBean = new BaseBean(); String jxSobIdStr = baseBean.getPropValue("ltSalary", "tax_declare_jx_sob_ids"); List jxSobIdList = new ArrayList<>(); if (StringUtils.isNotBlank(jxSobIdStr)) { jxSobIdList = Arrays.stream(jxSobIdStr.split(",")).filter(id -> NumberUtils.isCreatable(id)).map(Long::valueOf).collect(Collectors.toList()); } Date now = new Date(); // 薪资核算结果按照薪资核算人员id聚合分类 Map> salaryAcctResultValueMap = SalaryEntityUtil.group2Map(taxDeclareContext.getSalaryAcctResultValues(), SalaryAcctResultPO::getSalaryAcctEmpId); // 薪资核算人员按照人员id聚合分类 Map> employeeIdKeyMap = SalaryEntityUtil.group2Map(taxDeclareContext.getSalaryAcctEmployees(), SalaryAcctEmployeePO::getEmployeeId); List taxDeclarationValues = Lists.newArrayListWithExpectedSize(employeeIdKeyMap.size()); for (Map.Entry> employeeIdEntry : employeeIdKeyMap.entrySet()) { Map valueMap = Maps.newHashMap(); for (TaxReportColumnPO taxReportColumn : taxDeclareContext.getTaxReportColumns()) { String value = ""; List firstValueList = Lists.newArrayList( "taxFreeIncome", "endowmentInsurance", "medicalInsurance", "unemploymentInsurance", "housingProvidentFund", "addUpChildEducation", "addUpHousingLoanInterest", "addUpHousingRent", "addUpSupportElderly", "addUpContinuingEducation", "addUpInfantCare", "annuity", "commercialHealthInsurance", "taxDeferredEndowmentInsurance", "other", "allowedDonation", "taxDeduction", "description", "addUpAdvanceTax"); List lastValueList = Lists.newArrayList( "addUpIncome", "addUpTaxFreeIncome", "addUpSubtraction", "addUpSpecialDeduction", "addUpOtherDeduction", "addUpAllowedDonation", "addUpTaxableIncome", "taxRate", "quickDeductionFactor", "addUpTaxPayable", "addUpTaxDeduction" ); List mergeValueList = Lists.newArrayList( "income", "refundedOrSupplementedTax" ); //取第一次值 if (firstValueList.contains(taxReportColumn.getReportColumnDataIndex())) { SalaryAcctEmployeePO lastSalaryAcctEmployee = SalaryEntityUtil.findFirst(employeeIdEntry.getValue()); for (SalaryAcctEmployeePO salaryAcctEmployee : employeeIdEntry.getValue()) { SalaryAcctRecordPO salaryAcctRecord = taxDeclareContext.getSalaryAcctRecordMap().get(salaryAcctEmployee.getSalaryAcctRecordId()); SalaryAcctRecordPO lastSalaryAcctRecord = taxDeclareContext.getSalaryAcctRecordMap().get(lastSalaryAcctEmployee.getSalaryAcctRecordId()); if (salaryAcctRecord.getCreateTime().compareTo(lastSalaryAcctRecord.getCreateTime()) < 0) { lastSalaryAcctEmployee = salaryAcctEmployee; } } SalarySobTaxReportRulePO salarySobTaxReportRule = taxDeclareContext.getSalarySobTaxReportRuleMap() .get(lastSalaryAcctEmployee.getSalarySobId() + "-" + taxReportColumn.getReportColumnDataIndex()); List salaryAcctResultValue = salaryAcctResultValueMap.get(lastSalaryAcctEmployee.getId()); if (salarySobTaxReportRule != null && salaryAcctResultValue != null) { value = salaryAcctResultValue.stream() .filter(result -> result.getSalaryItemId().equals(salarySobTaxReportRule.getSalaryItemId())) .findFirst() .orElse(new SalaryAcctResultPO()) .getResultValue(); } value = StrUtil.isNotBlank(value) ? value : Objects.equals(taxReportColumn.getDataType(), SalaryDataTypeEnum.NUMBER.getValue()) ? "0.00" : ""; } //取多次累计值 else if (mergeValueList.contains(taxReportColumn.getReportColumnDataIndex()) && Objects.equals(taxReportColumn.getDataType(), SalaryDataTypeEnum.NUMBER.getValue())) { List employeePOS = employeeIdEntry.getValue(); BigDecimal income = new BigDecimal("0.00"); for (SalaryAcctEmployeePO salaryAcctEmployeePO : employeePOS) { // 跳过绩效账套 if (jxSobIdList.contains(salaryAcctEmployeePO.getSalarySobId())) { continue; } SalarySobTaxReportRulePO incomeRule = taxDeclareContext.getSalarySobTaxReportRuleMap() .get(salaryAcctEmployeePO.getSalarySobId() + "-" + taxReportColumn.getReportColumnDataIndex()); List salaryAcctResultValue = salaryAcctResultValueMap.get(salaryAcctEmployeePO.getId()); if (incomeRule != null && salaryAcctResultValue != null) { String incomeValue = salaryAcctResultValue.stream() .filter(result -> result.getSalaryItemId().equals(incomeRule.getSalaryItemId())) .findFirst() .orElse(new SalaryAcctResultPO()) .getResultValue(); if (StrUtil.isNotBlank(incomeValue) && NumberUtil.isNumber(incomeValue)) { income = income.add(new BigDecimal(incomeValue)); } } } value = income.toPlainString(); } //取最后一次值 else { SalaryAcctEmployeePO lastSalaryAcctEmployee = SalaryEntityUtil.findFirst(employeeIdEntry.getValue()); for (SalaryAcctEmployeePO salaryAcctEmployee : employeeIdEntry.getValue()) { SalaryAcctRecordPO salaryAcctRecord = taxDeclareContext.getSalaryAcctRecordMap().get(salaryAcctEmployee.getSalaryAcctRecordId()); SalaryAcctRecordPO lastSalaryAcctRecord = taxDeclareContext.getSalaryAcctRecordMap().get(lastSalaryAcctEmployee.getSalaryAcctRecordId()); if (salaryAcctRecord.getCreateTime().compareTo(lastSalaryAcctRecord.getCreateTime()) > 0) { lastSalaryAcctEmployee = salaryAcctEmployee; } } SalarySobTaxReportRulePO salarySobTaxReportRule = taxDeclareContext.getSalarySobTaxReportRuleMap() .get(lastSalaryAcctEmployee.getSalarySobId() + "-" + taxReportColumn.getReportColumnDataIndex()); List salaryAcctResultValue = salaryAcctResultValueMap.get(lastSalaryAcctEmployee.getId()); if (salarySobTaxReportRule != null && salaryAcctResultValue != null) { value = salaryAcctResultValue.stream() .filter(result -> result.getSalaryItemId().equals(salarySobTaxReportRule.getSalaryItemId())) .findFirst() .orElse(new SalaryAcctResultPO()) .getResultValue(); } value = StrUtil.isNotBlank(value) ? value : Objects.equals(taxReportColumn.getDataType(), SalaryDataTypeEnum.NUMBER.getValue()) ? "0.00" : ""; } if (new String("income").equals(taxReportColumn.getReportColumnDataIndex()) && Objects.equals(taxReportColumn.getDataType(), SalaryDataTypeEnum.NUMBER.getValue())) { // 还需要取联特绩效本期收入 List employeePOS = employeeIdEntry.getValue(); BigDecimal income = new BigDecimal("0.00"); for (SalaryAcctEmployeePO salaryAcctEmployeePO : employeePOS) { SalarySobTaxReportRulePO incomeRule = taxDeclareContext.getSalarySobTaxReportRuleMap() .get(salaryAcctEmployeePO.getSalarySobId() + "-ltjxincome" ); List salaryAcctResultValue = salaryAcctResultValueMap.get(salaryAcctEmployeePO.getId()); if (incomeRule != null && salaryAcctResultValue != null) { String incomeValue = salaryAcctResultValue.stream() .filter(result -> result.getSalaryItemId().equals(incomeRule.getSalaryItemId())) .findFirst() .orElse(new SalaryAcctResultPO()) .getResultValue(); if (StrUtil.isNotBlank(incomeValue) && NumberUtil.isNumber(incomeValue)) { income = income.add(new BigDecimal(incomeValue)); } } } BigDecimal valueBigDecimal = NumberUtils.isCreatable(value) ? new BigDecimal(value) : new BigDecimal("0.00"); value = valueBigDecimal.add(income).toPlainString(); } valueMap.put(taxReportColumn.getReportColumnDataIndex(), value); } TaxDeclarationValuePO taxDeclarationValue = TaxDeclarationValuePO.builder() .id(IdGenerator.generate()) .taxDeclareRecordId(taxDeclareContext.getTaxDeclaration().getTaxDeclareRecordId()) .taxDeclarationId(taxDeclareContext.getTaxDeclaration().getId()) .employeeType(employeeIdEntry.getValue().get(0).getEmployeeType()) .employeeId(employeeIdEntry.getKey()) .resultValue(valueMap) .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY) .creator(employeeId) .deleteType(DeleteTypeEnum.NOT_DELETED.getValue()) .createTime(now) .updateTime(now) .source(SourceEnum.ACCT.getValue()) .build(); taxDeclarationValues.add(taxDeclarationValue); } // 生成累计数据 List addUpSituations = generateAddUpSituation(taxDeclareContext, salaryAcctResultValueMap, employeeIdKeyMap); return new TaxDeclarationGenerateResult() .setTaxDeclarationValues(taxDeclarationValues) .setAddUpSituations(addUpSituations); } /** * 生成往期累计数据 * * @param taxDeclareContext * @param salaryAcctResultValueMap * @param employeeIdKeyMap * @return */ private List generateAddUpSituation(TaxDeclareContext taxDeclareContext, Map> salaryAcctResultValueMap, Map> employeeIdKeyMap) { List addUpSituations = Lists.newArrayList(); // 只有「工资工资薪金」、「保险营销员佣金收入」、「证券经纪人佣金收入」、「其他连续劳务报酬所得」需要累计计税 TaxDeclarationPO taxDeclaration = taxDeclareContext.getTaxDeclaration(); if (!Objects.equals(taxDeclaration.getIncomeCategory(), IncomeCategoryEnum.WAGES_AND_SALARIES.getValue()) && !Objects.equals(taxDeclaration.getIncomeCategory(), IncomeCategoryEnum.INCOME_FOR_INSURANCE_SALESMAN.getValue()) && !Objects.equals(taxDeclaration.getIncomeCategory(), IncomeCategoryEnum.INCOME_FOR_SECURITIES_BROKER.getValue()) && !Objects.equals(taxDeclaration.getIncomeCategory(), IncomeCategoryEnum.REMUNERATION_FOR_OTHER_CONTINUOUS_LABOR.getValue())) { return addUpSituations; } for (Map.Entry> employeeIdEntry : employeeIdKeyMap.entrySet()) { // 取最后一次薪资核算记录的核算结果作为个税申报表的数据来源 SalaryAcctEmployeePO lastSalaryAcctEmployee = SalaryEntityUtil.findFirst(employeeIdEntry.getValue()); for (SalaryAcctEmployeePO salaryAcctEmployee : employeeIdEntry.getValue()) { SalaryAcctRecordPO salaryAcctRecord = taxDeclareContext.getSalaryAcctRecordMap().get(salaryAcctEmployee.getSalaryAcctRecordId()); SalaryAcctRecordPO lastSalaryAcctRecord = taxDeclareContext.getSalaryAcctRecordMap().get(lastSalaryAcctEmployee.getSalaryAcctRecordId()); if (salaryAcctRecord.getCreateTime().compareTo(lastSalaryAcctRecord.getCreateTime()) > 0) { lastSalaryAcctEmployee = salaryAcctEmployee; } } List salaryAcctResultValue = salaryAcctResultValueMap.get(lastSalaryAcctEmployee.getId()); Map valueMap = Maps.newHashMap(); for (Field declaredField : AddUpSituation.class.getDeclaredFields()) { if (!declaredField.isAnnotationPresent(SalaryFormulaVar.class)) { continue; } SalarySobAddUpRulePO salarySobAddUpRule = taxDeclareContext.getSalarySobAddUpRuleMap() .get(lastSalaryAcctEmployee.getSalarySobId() + "-" + declaredField.getName()); String value = BigDecimal.ZERO.toPlainString(); if (Objects.nonNull(salarySobAddUpRule) && Objects.nonNull(salaryAcctResultValue)) { value = salaryAcctResultValue.stream() .filter(e -> e.getSalaryItemId().equals(salarySobAddUpRule.getSalaryItemId())) .findFirst() .orElse(new SalaryAcctResultPO()) .getResultValue(); } valueMap.put(declaredField.getName(), value); } AddUpSituation addUpSituation = AddUpSituation.builder() .id(IdGenerator.generate()) .employeeId(lastSalaryAcctEmployee.getEmployeeId()) // .employeeType(lastSalaryAcctEmployee.getEmployeeType()) .taxAgentId(lastSalaryAcctEmployee.getTaxAgentId()) .taxYearMonth(taxDeclaration.getTaxCycle()) .year(SalaryDateUtil.date2Year(taxDeclaration.getTaxCycle())) .addUpIncome(valueMap.get("addUpIncome")) .addUpSocialSecurityTotal(valueMap.get("addUpSocialSecurityTotal")) .addUpAccumulationFundTotal(valueMap.get("addUpAccumulationFundTotal")) .addUpEnterpriseAndOther(valueMap.get("addUpEnterpriseAndOther")) .addUpSubtraction(valueMap.get("addUpSubtraction")) .addUpOtherDeduction(valueMap.get("addUpOtherDeduction")) .addUpTaxExemptIncome(valueMap.get("addUpTaxExemptIncome")) .addUpAllowedDonation(valueMap.get("addUpAllowedDonation")) .addUpTaxSavings(valueMap.get("addUpTaxSavings")) .addUpAdvanceTax(valueMap.get("addUpAdvanceTax")) .taxAdjustment(valueMap.get("taxAdjustment")) .addUpTaxableIncome(valueMap.get("addUpTaxableIncome")) // .modifier(taxDeclaration.getCreator()) .creator(taxDeclaration.getCreator()) .createTime(taxDeclaration.getCreateTime()) .updateTime(taxDeclaration.getUpdateTime()) .tenantKey(taxDeclaration.getTenantKey()) .deleteType(taxDeclaration.getDeleteType()) .build(); addUpSituations.add(addUpSituation); } return addUpSituations; } }