302 lines
19 KiB
Java
302 lines
19 KiB
Java
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;
|
|
|
|
/**
|
|
* 通用:一般劳务报酬所得、全年一次性奖金
|
|
* <p>Copyright: Copyright (c) 2023</p>
|
|
* <p>Company: 泛微软件</p>
|
|
*
|
|
* @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<Long> 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<Long, List<SalaryAcctResultPO>> salaryAcctResultValueMap = SalaryEntityUtil.group2Map(taxDeclareContext.getSalaryAcctResultValues(), SalaryAcctResultPO::getSalaryAcctEmpId);
|
|
// 薪资核算人员按照人员id聚合分类
|
|
Map<Long, List<SalaryAcctEmployeePO>> employeeIdKeyMap = SalaryEntityUtil.group2Map(taxDeclareContext.getSalaryAcctEmployees(), SalaryAcctEmployeePO::getEmployeeId);
|
|
|
|
List<TaxDeclarationValuePO> taxDeclarationValues = Lists.newArrayListWithExpectedSize(employeeIdKeyMap.size());
|
|
for (Map.Entry<Long, List<SalaryAcctEmployeePO>> employeeIdEntry : employeeIdKeyMap.entrySet()) {
|
|
|
|
Map<String, String> valueMap = Maps.newHashMap();
|
|
for (TaxReportColumnPO taxReportColumn : taxDeclareContext.getTaxReportColumns()) {
|
|
String value = "";
|
|
|
|
List<String> firstValueList = Lists.newArrayList(
|
|
"taxFreeIncome",
|
|
"endowmentInsurance",
|
|
"medicalInsurance",
|
|
"unemploymentInsurance",
|
|
"housingProvidentFund",
|
|
"addUpChildEducation",
|
|
"addUpHousingLoanInterest",
|
|
"addUpHousingRent",
|
|
"addUpSupportElderly",
|
|
"addUpContinuingEducation",
|
|
"addUpInfantCare",
|
|
"annuity",
|
|
"commercialHealthInsurance",
|
|
"taxDeferredEndowmentInsurance",
|
|
"other",
|
|
"allowedDonation",
|
|
"taxDeduction",
|
|
"description",
|
|
"addUpAdvanceTax");
|
|
|
|
List<String> lastValueList = Lists.newArrayList(
|
|
"addUpIncome",
|
|
"addUpTaxFreeIncome",
|
|
"addUpSubtraction",
|
|
"addUpSpecialDeduction",
|
|
"addUpOtherDeduction",
|
|
"addUpAllowedDonation",
|
|
"addUpTaxableIncome",
|
|
"taxRate",
|
|
"quickDeductionFactor",
|
|
"addUpTaxPayable",
|
|
"addUpTaxDeduction"
|
|
);
|
|
|
|
List<String> 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<SalaryAcctResultPO> 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<SalaryAcctEmployeePO> 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<SalaryAcctResultPO> 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<SalaryAcctResultPO> 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<SalaryAcctEmployeePO> employeePOS = employeeIdEntry.getValue();
|
|
BigDecimal income = new BigDecimal("0.00");
|
|
for (SalaryAcctEmployeePO salaryAcctEmployeePO : employeePOS) {
|
|
SalarySobTaxReportRulePO incomeRule = taxDeclareContext.getSalarySobTaxReportRuleMap()
|
|
.get(salaryAcctEmployeePO.getSalarySobId() + "-ltjxincome" );
|
|
List<SalaryAcctResultPO> 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<AddUpSituation> addUpSituations = generateAddUpSituation(taxDeclareContext, salaryAcctResultValueMap, employeeIdKeyMap);
|
|
return new TaxDeclarationGenerateResult()
|
|
.setTaxDeclarationValues(taxDeclarationValues)
|
|
.setAddUpSituations(addUpSituations);
|
|
}
|
|
|
|
/**
|
|
* 生成往期累计数据
|
|
*
|
|
* @param taxDeclareContext
|
|
* @param salaryAcctResultValueMap
|
|
* @param employeeIdKeyMap
|
|
* @return
|
|
*/
|
|
private List<AddUpSituation> generateAddUpSituation(TaxDeclareContext taxDeclareContext,
|
|
Map<Long, List<SalaryAcctResultPO>> salaryAcctResultValueMap,
|
|
Map<Long, List<SalaryAcctEmployeePO>> employeeIdKeyMap) {
|
|
List<AddUpSituation> 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<Long, List<SalaryAcctEmployeePO>> 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<SalaryAcctResultPO> salaryAcctResultValue = salaryAcctResultValueMap.get(lastSalaryAcctEmployee.getId());
|
|
Map<String, String> 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;
|
|
}
|
|
}
|