package com.engine.salary.wrapper;
import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.salary.biz.EmployBiz;
import com.engine.salary.common.LocalDateRange;
import com.engine.salary.component.WeaFormOption;
import com.engine.salary.entity.datacollection.AddUpSituation;
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
import com.engine.salary.entity.salaryacct.po.SalaryAcctRecordPO;
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.TaxDeclaration;
import com.engine.salary.entity.taxdeclaration.bo.TaxDeclarationBO;
import com.engine.salary.entity.taxdeclaration.dto.TaxDeclarationFormDTO;
import com.engine.salary.entity.taxdeclaration.dto.TaxDeclarationInfoDTO;
import com.engine.salary.entity.taxdeclaration.dto.TaxDeclarationListDTO;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationListQueryParam;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationSaveParam;
import com.engine.salary.entity.taxdeclaration.po.TaxDeclarationPO;
import com.engine.salary.enums.salaryaccounting.SalaryAcctRecordStatusEnum;
import com.engine.salary.exception.SalaryRunTimeException;
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.service.impl.*;
import com.engine.salary.util.SalaryDateUtil;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.SalaryI18nUtil;
import com.engine.salary.util.db.MapperProxyFactory;
import com.engine.salary.util.page.PageInfo;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.transaction.annotation.Transactional;
import weaver.hrm.User;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
/**
* 个税申报表
*
Copyright: Copyright (c) 2022
* Company: 泛微软件
*
* @author qiantao
* @version 1.0
**/
public class TaxDeclarationWrapper extends Service {
private TaxDeclarationService getTaxDeclarationService(User user) {
return ServiceUtil.getService(TaxDeclarationServiceImpl.class, user);
}
private TaxAgentService getTaxAgentService(User user) {
return ServiceUtil.getService(TaxAgentServiceImpl.class, user);
}
private TaxDeclarationDetailService getTaxDeclarationDetailService(User user) {
return ServiceUtil.getService(TaxDeclarationDetailServiceImpl.class, user);
}
private SalaryAcctRecordService getSalaryAcctRecordService(User user) {
return ServiceUtil.getService(SalaryAcctRecordServiceImpl.class, user);
}
private TaxDeclarationMapper getTaxDeclarationMapper() {
return MapperProxyFactory.getProxy(TaxDeclarationMapper.class);
}
private SalaryAcctRecordMapper getSalaryAcctRecordMapper() {
return MapperProxyFactory.getProxy(SalaryAcctRecordMapper.class);
}
private AddUpSituationMapper getAddUpSituationMapper() {
return MapperProxyFactory.getProxy(AddUpSituationMapper.class);
}
private AddUpSituationService getAddUpSituationService(User user) {
return ServiceUtil.getService(AddUpSituationServiceImpl.class, user);
}
private SalarySobService getSalarySobService(User user) {
return ServiceUtil.getService(SalarySobServiceImpl.class, user);
}
private SalaryAcctResultService getSalaryAcctResultService(User user) {
return ServiceUtil.getService(SalaryAcctResultServiceImpl.class, user);
}
private SalaryItemService getSalaryItemService(User user) {
return (SalaryItemService) ServiceUtil.getService(SalaryItemServiceImpl.class, user);
}
/**
* 个税申报表列表
*
* @param queryParam 列表查询条件
* @param
* @return
*/
public PageInfo listPage(TaxDeclarationListQueryParam queryParam) {
EmployBiz employBiz = new EmployBiz();
// 询个税申报表(分页)
PageInfo page = getTaxDeclarationService(user).listPageByParam(queryParam);
PageInfo dtoPage = new PageInfo(TaxDeclarationListDTO.class);
dtoPage.setPageNum(queryParam.getCurrent());
dtoPage.setPageSize(queryParam.getPageSize());
List list = page.getList();
if (CollectionUtils.isNotEmpty(list)) {
// 查询人员
List employeeIds = SalaryEntityUtil.properties(list, TaxDeclarationPO::getCreator, Collectors.toList());
List employeeComInfos = employBiz.getEmployeeByIdsAll(employeeIds);
// 查询个税扣缴义务人
Set taxAgentIds = SalaryEntityUtil.properties(list, TaxDeclarationPO::getTaxAgentId);
List taxAgentPOS = getTaxDeclarationService(user).countByTaxDeclarationId(taxAgentIds);
// 转换成列表dto
List taxDeclarationListDTOS = TaxDeclarationBO.convert2ListDTO(list, employeeComInfos, taxAgentPOS);
dtoPage.setList(taxDeclarationListDTOS);
}
return dtoPage;
}
public TaxDeclarationFormDTO getForm(Long id) {
TaxDeclarationFormDTO formDTO = new TaxDeclarationFormDTO();
if (Objects.nonNull(id)) {
// 查询个税申报表
TaxDeclaration taxDeclaration = getTaxDeclarationService(user).getById(id);
if (Objects.isNull(taxDeclaration)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98877, "个税申报表不存在或已删除"));
}
// 查询个税扣缴义务人
TaxAgentPO taxAgent = getTaxAgentService(user).getById(id);
//日期转换
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM");
String transformDate = simpleDateFormat.format(taxDeclaration.getSalaryMonth());
// 转换成个税申报表详情dto
formDTO = TaxDeclarationFormDTO.builder().salaryMonth(SalaryDateUtil.String2YearMonth(transformDate)).taxAgentId(taxDeclaration.getTaxAgentId()).taxAgentName(Optional.ofNullable(taxAgent).map(TaxAgentPO::getName).orElse("")).description(taxDeclaration.getDescription()).build();
}
// 转换成前端所需的数据格式
// WeaForm weaForm = SalaryFormatUtil.getInstance().buildForm(TaxDeclarationFormDTO.class, formDTO);
// 查询租户所有的个税扣缴义务人
Collection taxAgentListDTOS = getTaxAgentService(user).listAll();
// 表单中个税扣缴义务人的可选项
List weaFormOptions = Lists.newArrayListWithExpectedSize(taxAgentListDTOS.size());
for (TaxAgentPO taxAgent : taxAgentListDTOS) {
weaFormOptions.add(new WeaFormOption("" + taxAgent.getId(), taxAgent.getName()));
}
// weaForm.getItems().forEach((k, v) -> {
// if (StringUtils.equals("taxAgentId", k)) {
// v.setOptions(weaFormOptions);
// }
// if (StringUtils.equals("salaryMonth", k)) {
// Map otherParams = new HashMap<>();
// otherParams.put("type", "month");
// v.setOtherParams(otherParams);
// }
// });
return formDTO;
}
/**
* 查询个税申报表的基本信息
*
* @param id 个税申报表id
* @return
*/
public TaxDeclarationInfoDTO getTaxDeclarationInfoById(Long id) {
// 查询个税申报表
TaxDeclaration taxDeclaration = getTaxDeclarationService(user).getById(id);
if (Objects.isNull(taxDeclaration)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98877, "个税申报表不存在或已删除"));
}
//日期转换
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM");
String transformDate = simpleDateFormat.format(taxDeclaration.getSalaryMonth());
// 查询个税扣缴义务人
TaxAgentPO taxAgentPO = getTaxAgentService(user).getById(taxDeclaration.getTaxAgentId());
return TaxDeclarationInfoDTO.builder().salaryMonth(SalaryDateUtil.String2YearMonth(transformDate)).taxAgentId(taxDeclaration.getTaxAgentId()).taxAgentName(Optional.ofNullable(taxAgentPO).map(TaxAgentPO::getName).orElse("")).build();
}
/**
* 保存
*
* @param saveParam 保存参数
*/
@Transactional(rollbackFor = Exception.class)
public void save(TaxDeclarationSaveParam saveParam) {
long currentEmployeeId = user.getUID();
// 个税扣缴义务人id
Set taxAgentIds;
Boolean openDevolution = getTaxAgentService(user).isOpenDevolution();
if (BooleanUtils.isFalse(openDevolution)) {
taxAgentIds = SalaryEntityUtil.properties(getTaxAgentService(user).listAll(), TaxAgentPO::getId);
} else {
taxAgentIds = SalaryEntityUtil.properties(getTaxAgentService(user).listAllTaxAgentsAsAdmin(currentEmployeeId), TaxAgentPO::getId);
}
// 检查是否具有权限
if (CollectionUtils.isEmpty(taxAgentIds)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(0, "对不起,您不具备任何个税扣缴义务人的管理权限"));
}
// 查询个税扣缴义务人
List taxAgentPOS = getTaxAgentService(user).listByIds(taxAgentIds);
Map taxAgentNameMap = SalaryEntityUtil.convert2Map(taxAgentPOS, TaxAgentPO::getId, TaxAgentPO::getName);
// 薪资所属月的日期范围
LocalDateRange salaryMonthDateRange = SalaryDateUtil.localDate2Range(SalaryDateUtil.localDateToDate(saveParam.getSalaryMonth().atDay(1)));
if (Objects.isNull(salaryMonthDateRange)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(84026, "薪资所属月参数错误"));
}
// 查询薪资所属月个税扣缴义务人已经生成过的个税申报表
List 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}", saveParam.getSalaryMonth().toString()));
}
// 查询薪资所属月的薪资核算记录
List salaryAcctRecordPOS = listBySalaryMonth(SalaryAcctRecordPO.builder().salaryMonths(salaryMonthDateRange).build());
// 无薪资核算记录,不允许生成个税申报表
if (CollectionUtils.isEmpty(salaryAcctRecordPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98874, "{0}无申报数据").replace("{0}", saveParam.getSalaryMonth().toString()));
}
// 查询薪资核算结果
List salaryAcctResultPOS = getSalaryAcctResultService(user)
.listBySalaryAcctRecordIdsAndTaxAgentIds(SalaryEntityUtil.properties(salaryAcctRecordPOS, SalaryAcctRecordPO::getId), taxAgentIds);
// 无薪资核算结果,不允许生成个税申报表
if (CollectionUtils.isEmpty(salaryAcctResultPOS)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(110093, "{0}无可申报数据")
.replace("{0}", saveParam.getSalaryMonth().toString()));
}
Set 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.ARCHIVED.getValue()));
if (notArchived) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98875, "{0}有未归档数据,请全部归档后再申报")
.replace("{0}", saveParam.getSalaryMonth().toString()));
}
// 如果当前薪资所属月下存在不同的税款所属期,属于异常业务场景,不允许生成个税申报表
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}", saveParam.getSalaryMonth().toString()));
}
// 查询薪资账套
Set salarySobIds = SalaryEntityUtil.properties(salaryAcctRecordPOS, SalaryAcctRecordPO::getSalarySobId);
List salarySobPOS = getSalarySobService(user).listByIds(salarySobIds);
// 查询所有薪资项目
List salaryItemPOS = getSalaryItemService(user).listAll();
// 处理要保存的数据
TaxDeclarationBO.Result result = TaxDeclarationBO.handle(saveParam, taxCycle, user, salaryItemPOS, salarySobPOS, salaryAcctResultPOS);
// 保存个税申报表
if (CollectionUtils.isNotEmpty(result.getNeedInsertTaxDeclarations())) {
getTaxDeclarationMapper().batchInsert(result.getNeedInsertTaxDeclarations());
}
// 保存个税申报表明细
if (CollectionUtils.isNotEmpty(result.getNeedInsertTaxDeclarationDetails())) {
getTaxDeclarationDetailService(user).batchSave(result.getNeedInsertTaxDeclarationDetails());
}
// 保存累计情况
if (CollectionUtils.isNotEmpty(result.getNeedInsertAddUpSituations())) {
getAddUpSituationService(user).deleteByTaxYearMonthAndTaxAgentIds(SalaryDateUtil.localDate2YearMonth(taxCycle), taxAgentIds);
List> partition = Lists.partition((List) result.getNeedInsertAddUpSituations(), 100);
partition.forEach(getAddUpSituationMapper()::insertData);
}
// 更新薪资核算记录的状态
getSalaryAcctRecordService(user).updateStatusByIds(salaryAcctRecordIds, SalaryAcctRecordStatusEnum.DECLARED);
}
public List listBySalaryMonthTax(TaxDeclarationPO build) {
return getTaxDeclarationMapper().listSome(build);
}
public List listBySalaryMonth(SalaryAcctRecordPO po) {
return getSalaryAcctRecordMapper().listSome(po);
}
}