支持根据税款所属期进行申报

This commit is contained in:
钱涛 2025-02-07 16:58:58 +08:00
parent 3394c92964
commit 5916cd63ef
4 changed files with 135 additions and 54 deletions

View File

@ -1,11 +1,13 @@
package com.engine.salary.entity.taxdeclaration.param;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.YearMonth;
import java.util.Date;
/**
* 生成个税申报表参数
@ -42,4 +44,10 @@ public class TaxDeclarationSaveParam {
private String description;
private String salaryMonthStr;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date taxCycle;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date salaryDate;
}

View File

@ -54,7 +54,7 @@ public class AddUpSituationManager extends Service {
// 调用生成申报单接口
YearMonth yearMonth = YearMonth.of(localDate.getYear(), localDate.getMonth());
try {
getTaxDeclarationService().save(TaxDeclarationSaveParam.builder().salaryMonth(yearMonth).taxAgentId(po.getTaxAgentId()).build());
getTaxDeclarationService().save(TaxDeclarationSaveParam.builder().salaryMonth(yearMonth).salaryDate(po.getSalaryMonth()).taxCycle(po.getTaxCycle()).taxAgentId(po.getTaxAgentId()).build());
} catch (Exception e) {
bb.writeLog("错误:" + e);
result = false;

View File

@ -2,9 +2,9 @@ package com.engine.salary.service.impl;
import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.hrmelog.entity.dto.LoggerContext;
import com.engine.salary.common.LocalDateRange;
import com.engine.salary.config.SalaryElogConfig;
import com.engine.hrmelog.entity.dto.LoggerContext;
import com.engine.salary.entity.salaryacct.po.SalaryAcctRecordPO;
import com.engine.salary.entity.salaryacct.po.SalaryAcctResultPO;
import com.engine.salary.entity.salaryitem.po.SalaryItemPO;
@ -22,6 +22,8 @@ import com.engine.salary.mapper.datacollection.AddUpSituationMapper;
import com.engine.salary.mapper.salaryacct.SalaryAcctRecordMapper;
import com.engine.salary.mapper.taxdeclaration.TaxDeclarationMapper;
import com.engine.salary.service.*;
import com.engine.salary.sys.service.SalarySysConfService;
import com.engine.salary.sys.service.impl.SalarySysConfServiceImpl;
import com.engine.salary.util.SalaryDateUtil;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.SalaryI18nUtil;
@ -38,6 +40,8 @@ import java.time.YearMonth;
import java.util.*;
import java.util.stream.Collectors;
import static com.engine.salary.sys.constant.SalarySysConstant.TAX_DECLARATION_DATE_TYPE;
@Slf4j
public class TaxDeclarationServiceImpl extends Service implements TaxDeclarationService {
@ -87,6 +91,13 @@ public class TaxDeclarationServiceImpl extends Service implements TaxDeclaration
return ServiceUtil.getService(SalaryAcctEmployeeServiceImpl.class, user);
}
private SalarySysConfService getSalarySysConfService(User user) {
return ServiceUtil.getService(SalarySysConfServiceImpl.class, user);
}
//是否根据税款所属期进行申报
private final boolean isTaxDeclarationByTaxCycle = "1".equals(getSalarySysConfService(user).getValueByCode(TAX_DECLARATION_DATE_TYPE));
@Override
public List<TaxDeclarationPO> listByTaxCycleAndTaxAgentIds(YearMonth taxCycle, Collection<Long> taxAgentIds) {
if (Objects.isNull(taxCycle) || CollectionUtils.isEmpty(taxAgentIds)) {
@ -180,51 +191,96 @@ public class TaxDeclarationServiceImpl extends Service implements TaxDeclaration
// 查询个税扣缴义务人
List<TaxAgentPO> taxAgentPOS = getTaxAgentService(user).listByIds(taxAgentIds);
Map<Long, String> taxAgentNameMap = SalaryEntityUtil.convert2Map(taxAgentPOS, TaxAgentPO::getId, TaxAgentPO::getName);
List<SalaryAcctRecordPO> salaryAcctRecordPOS;
Date taxCycle;
List<SalaryAcctResultPO> salaryAcctResultPOS;
Set<Long> salaryAcctRecordIds;
//根据税款所属期申报
if (isTaxDeclarationByTaxCycle) {
taxCycle = saveParam.getTaxCycle();
if (Objects.isNull(taxCycle)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(84026, "税款所属期参数错误"));
}
// 薪资所属月的日期范围
LocalDateRange salaryMonthDateRange = SalaryDateUtil.localDate2Range(SalaryDateUtil.localDateToDate(saveParam.getSalaryMonth().atDay(1)));
if (Objects.isNull(salaryMonthDateRange)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(84026, "薪资所属月参数错误"));
}
// 查询税款所属期个税扣缴义务人已经生成过的个税申报表
List<TaxDeclarationPO> taxDeclarationPOS = listByTaxCycle(TaxDeclarationPO.builder().taxCycle(taxCycle).taxAgentIds(taxAgentNameMap.keySet()).build());
// 已经生成过个税申报表不允许再次生成个税申报表
if (CollectionUtils.isNotEmpty(taxDeclarationPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(107986, "{0}在{1}已经生成过个税申报表,不允许再次生成")
.replace("{0}", taxAgentNameMap.get(taxDeclarationPOS.get(0).getTaxAgentId()))
.replace("{1}", SalaryDateUtil.getFormatYearMonth(taxCycle)));
}
// 查询薪资所属月的薪资核算记录
salaryAcctRecordPOS = listByTaxCycle(SalaryAcctRecordPO.builder().taxCycle(taxCycle).build());
// 无薪资核算记录不允许生成个税申报表
if (CollectionUtils.isEmpty(salaryAcctRecordPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98874, "{0}无申报数据").replace("{0}", SalaryDateUtil.getFormatYearMonth(taxCycle)));
}
// 查询薪资核算结果
salaryAcctResultPOS = getSalaryAcctResultService(user)
.listBySalaryAcctRecordIdsAndTaxAgentIds(SalaryEntityUtil.properties(salaryAcctRecordPOS, SalaryAcctRecordPO::getId), taxAgentIds);
// 查询薪资所属月个税扣缴义务人已经生成过的个税申报表
List<TaxDeclarationPO> taxDeclarationPOS = listBySalaryMonthTax(TaxDeclarationPO.builder().salaryMonths(salaryMonthDateRange).taxAgentIds(taxAgentNameMap.keySet()).build());
// 已经生成过个税申报表不允许再次生成个税申报表
if (CollectionUtils.isNotEmpty(taxDeclarationPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(107986, "{0}在{1}已经生成过个税申报表,不允许再次生成")
.replace("{0}", taxAgentNameMap.get(taxDeclarationPOS.get(0).getTaxAgentId()))
.replace("{1}", SalaryDateUtil.getFormatYearMonth(saveParam.getSalaryMonth())));
}
// 查询薪资所属月的薪资核算记录
List<SalaryAcctRecordPO> salaryAcctRecordPOS = listBySalaryMonth(SalaryAcctRecordPO.builder().salaryMonths(salaryMonthDateRange).build());
// 无薪资核算记录不允许生成个税申报表
if (CollectionUtils.isEmpty(salaryAcctRecordPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98874, "{0}无申报数据").replace("{0}", saveParam.getSalaryMonth().toString()));
}
// 查询薪资核算结果
List<SalaryAcctResultPO> salaryAcctResultPOS = getSalaryAcctResultService(user)
.listBySalaryAcctRecordIdsAndTaxAgentIds(SalaryEntityUtil.properties(salaryAcctRecordPOS, SalaryAcctRecordPO::getId), taxAgentIds);
// 无薪资核算结果不允许生成个税申报表
if (CollectionUtils.isEmpty(salaryAcctResultPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(110093, "{0}无可申报数据")
.replace("{0}", SalaryDateUtil.getFormatYearMonth(saveParam.getSalaryMonth())));
}
// 无薪资核算结果不允许生成个税申报表
if (CollectionUtils.isEmpty(salaryAcctResultPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(110093, "{0}无可申报数据")
.replace("{0}", SalaryDateUtil.getFormatYearMonth(saveParam.getSalaryMonth())));
}
salaryAcctRecordIds = SalaryEntityUtil.properties(salaryAcctResultPOS, SalaryAcctResultPO::getSalaryAcctRecordId);
salaryAcctRecordPOS = salaryAcctRecordPOS.stream().filter(salaryAcctRecordPO -> salaryAcctRecordIds.contains(salaryAcctRecordPO.getId())).collect(Collectors.toList());
// 如果存在未归档的也不允许生成个税申报表
boolean notArchived = salaryAcctRecordPOS.stream().anyMatch(salaryAcctRecordPO -> Objects.equals(salaryAcctRecordPO.getStatus(), SalaryAcctRecordStatusEnum.NOT_ARCHIVED.getValue()));
if (notArchived) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98875, "{0}有未归档数据,请全部归档后再申报")
.replace("{0}", SalaryDateUtil.getFormatYearMonth(saveParam.getSalaryMonth())));
}
} else {
//根据薪资所属月申报
// 薪资所属月的日期范围
LocalDateRange salaryMonthDateRange = SalaryDateUtil.localDate2Range(SalaryDateUtil.localDateToDate(saveParam.getSalaryMonth().atDay(1)));
if (Objects.isNull(salaryMonthDateRange)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(84026, "薪资所属月参数错误"));
}
Set<Long> salaryAcctRecordIds = SalaryEntityUtil.properties(salaryAcctResultPOS, SalaryAcctResultPO::getSalaryAcctRecordId);
salaryAcctRecordPOS = salaryAcctRecordPOS.stream().filter(salaryAcctRecordPO -> salaryAcctRecordIds.contains(salaryAcctRecordPO.getId())).collect(Collectors.toList());
// 如果存在未归档的也不允许生成个税申报表
boolean notArchived = salaryAcctRecordPOS.stream().anyMatch(salaryAcctRecordPO -> Objects.equals(salaryAcctRecordPO.getStatus(), SalaryAcctRecordStatusEnum.NOT_ARCHIVED.getValue()));
if (notArchived) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98875, "{0}有未归档数据,请全部归档后再申报")
.replace("{0}", SalaryDateUtil.getFormatYearMonth(saveParam.getSalaryMonth())));
}
// 如果当前薪资所属月下存在不同的税款所属期属于异常业务场景不允许生成个税申报表
Date taxCycle = salaryAcctRecordPOS.get(0).getTaxCycle();
boolean differentTaxCycle = salaryAcctRecordPOS.stream().anyMatch(salaryAcctRecordPO -> salaryAcctRecordPO.getTaxCycle().compareTo(taxCycle) != 0);
if (differentTaxCycle) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98876, "{0}存在不同的税款所属期,无法正常生成个税申报表,请调整账套设置,重新核算后再生成个税申报表")
.replace("{0}", SalaryDateUtil.getFormatYearMonth(saveParam.getSalaryMonth())));
// 查询薪资所属月个税扣缴义务人已经生成过的个税申报表
List<TaxDeclarationPO> taxDeclarationPOS = listBySalaryMonthTax(TaxDeclarationPO.builder().salaryMonths(salaryMonthDateRange).taxAgentIds(taxAgentNameMap.keySet()).build());
// 已经生成过个税申报表不允许再次生成个税申报表
if (CollectionUtils.isNotEmpty(taxDeclarationPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(107986, "{0}在{1}已经生成过个税申报表,不允许再次生成")
.replace("{0}", taxAgentNameMap.get(taxDeclarationPOS.get(0).getTaxAgentId()))
.replace("{1}", SalaryDateUtil.getFormatYearMonth(saveParam.getSalaryMonth())));
}
// 查询薪资所属月的薪资核算记录
salaryAcctRecordPOS = listBySalaryMonth(SalaryAcctRecordPO.builder().salaryMonths(salaryMonthDateRange).build());
// 无薪资核算记录不允许生成个税申报表
if (CollectionUtils.isEmpty(salaryAcctRecordPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98874, "{0}无申报数据").replace("{0}", saveParam.getSalaryMonth().toString()));
}
// 查询薪资核算结果
salaryAcctResultPOS = getSalaryAcctResultService(user)
.listBySalaryAcctRecordIdsAndTaxAgentIds(SalaryEntityUtil.properties(salaryAcctRecordPOS, SalaryAcctRecordPO::getId), taxAgentIds);
// 无薪资核算结果不允许生成个税申报表
if (CollectionUtils.isEmpty(salaryAcctResultPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(110093, "{0}无可申报数据")
.replace("{0}", SalaryDateUtil.getFormatYearMonth(saveParam.getSalaryMonth())));
}
salaryAcctRecordIds = SalaryEntityUtil.properties(salaryAcctResultPOS, SalaryAcctResultPO::getSalaryAcctRecordId);
salaryAcctRecordPOS = salaryAcctRecordPOS.stream().filter(salaryAcctRecordPO -> salaryAcctRecordIds.contains(salaryAcctRecordPO.getId())).collect(Collectors.toList());
// 如果存在未归档的也不允许生成个税申报表
boolean notArchived = salaryAcctRecordPOS.stream().anyMatch(salaryAcctRecordPO -> Objects.equals(salaryAcctRecordPO.getStatus(), SalaryAcctRecordStatusEnum.NOT_ARCHIVED.getValue()));
if (notArchived) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98875, "{0}有未归档数据,请全部归档后再申报")
.replace("{0}", SalaryDateUtil.getFormatYearMonth(saveParam.getSalaryMonth())));
}
// 如果当前薪资所属月下存在不同的税款所属期属于异常业务场景不允许生成个税申报表
taxCycle = salaryAcctRecordPOS.get(0).getTaxCycle();
boolean differentTaxCycle = salaryAcctRecordPOS.stream().anyMatch(salaryAcctRecordPO -> salaryAcctRecordPO.getTaxCycle().compareTo(taxCycle) != 0);
if (differentTaxCycle) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98876, "{0}存在不同的税款所属期,无法正常生成个税申报表,请调整账套设置,重新核算后再生成个税申报表")
.replace("{0}", SalaryDateUtil.getFormatYearMonth(saveParam.getSalaryMonth())));
}
}
// 查询薪资账套
Set<Long> salarySobIds = SalaryEntityUtil.properties(salaryAcctRecordPOS, SalaryAcctRecordPO::getSalarySobId);
@ -273,8 +329,8 @@ public class TaxDeclarationServiceImpl extends Service implements TaxDeclaration
loggerContext.setTargetId(declare.getId().toString());
loggerContext.setTargetName(targetName);
loggerContext.setOperateType(OperateTypeEnum.ADD.getValue());
loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel( 0, "生成个税申报表"));
loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel( 0, "生成个税申报表"));
loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "生成个税申报表"));
loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "生成个税申报表"));
loggerContext.setNewValues(declare);
SalaryElogConfig.taxDeclarationLoggerTemplate.write(loggerContext);
});
@ -315,6 +371,14 @@ public class TaxDeclarationServiceImpl extends Service implements TaxDeclaration
return getSalaryAcctRecordMapper().listSome(po);
}
public List<TaxDeclarationPO> listByTaxCycle(TaxDeclarationPO build) {
return getTaxDeclarationMapper().listSome(build);
}
public List<SalaryAcctRecordPO> listByTaxCycle(SalaryAcctRecordPO po) {
return getSalaryAcctRecordMapper().listSome(po);
}
@Override
public boolean checkByAuthority(TaxDeclarationPO taxDeclarationPO, Long employeeId) {
// 判断是否开启了分权
@ -337,7 +401,7 @@ public class TaxDeclarationServiceImpl extends Service implements TaxDeclaration
@Override
public void withDrawTaxDeclaration(Long taxDeclarationId) {
TaxDeclarationPO po = getTaxDeclarationMapper().getById(taxDeclarationId);
if(Objects.isNull(po)){
if (Objects.isNull(po)) {
throw new SalaryRunTimeException("个税申报表不存在");
}
// 获取当前个税扣缴义务人下的薪资账套
@ -350,22 +414,22 @@ public class TaxDeclarationServiceImpl extends Service implements TaxDeclaration
// 删除个税申报表
getTaxDeclarationMapper().deleteByIdZj(po.getId());
// 修改薪资核算记录状态为已归档
if(CollectionUtils.isNotEmpty(salaryAcctRecordIds)){
getSalaryAcctRecordService(user).updateStatusByIds(salaryAcctRecordIds,SalaryAcctRecordStatusEnum.ARCHIVED);
if (CollectionUtils.isNotEmpty(salaryAcctRecordIds)) {
getSalaryAcctRecordService(user).updateStatusByIds(salaryAcctRecordIds, SalaryAcctRecordStatusEnum.ARCHIVED);
}
// 查询个税扣缴义务人名称
String bar = "_";
TaxAgentPO taxAgentPO = getTaxAgentService(user).getById(po.getTaxAgentId());
String targetName = SalaryDateUtil.getFormatYearMonth(po.getSalaryMonth()) + bar + taxAgentPO.getName() + bar + IncomeCategoryEnum.parseByValue(po.getIncomeCategory()).getDefaultLabel();
String targetName = SalaryDateUtil.getFormatYearMonth(po.getSalaryMonth()) + bar + taxAgentPO.getName() + bar + IncomeCategoryEnum.parseByValue(po.getIncomeCategory()).getDefaultLabel();
// 记录日志
LoggerContext<TaxDeclarationPO> loggerContext = new LoggerContext<>();
loggerContext.setUser(user);
loggerContext.setTargetId(taxDeclarationId.toString());
loggerContext.setTargetName(targetName);
loggerContext.setOperateType(OperateTypeEnum.DELETE.getValue());
loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel( 0, "撤回个税申报表"));
loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel( 0, "撤回个税申报表"));
loggerContext.setOperateTypeName(SalaryI18nUtil.getI18nLabel(0, "撤回个税申报表"));
loggerContext.setOperatedesc(SalaryI18nUtil.getI18nLabel(0, "撤回个税申报表"));
SalaryElogConfig.taxDeclarationLoggerTemplate.write(loggerContext);
}
}

View File

@ -79,7 +79,7 @@ public class SalarySysConstant {
/**
* 个税申报撤回
*/
public static final String WITHDRAW_TAX_DECLARATION ="WITHDRAW_TAX_DECLARATION";
public static final String WITHDRAW_TAX_DECLARATION = "WITHDRAW_TAX_DECLARATION";
/**
* 删除薪资档案
@ -124,7 +124,7 @@ public class SalarySysConstant {
/**
* 首次查看后多少分钟不能查看工资单
*/
public static final String SALARY_BILL_BURNING_AFTER_READING_MIN= "SALARY_BILL_BURNING_AFTER_READING_MIN";
public static final String SALARY_BILL_BURNING_AFTER_READING_MIN = "SALARY_BILL_BURNING_AFTER_READING_MIN";
/**
* 核算固定列头数
@ -215,6 +215,15 @@ public class SalarySysConstant {
*/
public static final String SHOT_EMP_TIME_TYPE = "SHOT_EMP_TIME_TYPE";
//是否采集考勤班次数据,0关闭 1开启
/**
* 是否采集考勤班次数据,0关闭 1开启
*/
public static final String ATTENDANCE_SERIAL_COLLECTION_BTN = "ATTENDANCE_SERIAL_COLLECTION_BTN";
/**
* 报税日期类型薪资所属月/税款所属期
* 0薪资所属月 1税款所属期
* 默认薪资所属月
*/
public static final String TAX_DECLARATION_DATE_TYPE = "TAX_DECLARATION_DATE_TYPE";
}