package com.engine.salary.service.impl; import com.engine.common.util.ServiceUtil; import com.engine.core.impl.Service; import com.engine.salary.constant.SalaryDefaultTenantConstant; import com.engine.salary.constant.SzyhApiConstant; import com.engine.salary.entity.employeedeclare.po.EmployeeDeclarePO; import com.engine.salary.entity.salaryacct.bo.SalaryCalcTax; import com.engine.salary.entity.salaryacct.dto.SalaryCalcTaxInfoDTO; import com.engine.salary.entity.salaryacct.param.AbnormalEmployeeListQueryParam; import com.engine.salary.entity.salaryacct.param.SalaryCalcTaxParam; import com.engine.salary.entity.salaryacct.po.*; import com.engine.salary.entity.salarysob.dto.SalarySobTaxRuleDTO; import com.engine.salary.entity.salarysob.po.SalarySobTaxReportRulePO; import com.engine.salary.entity.taxagent.po.TaxAgentPO; import com.engine.salary.entity.taxagent.po.TaxAgentTaxReturnPO; import com.engine.salary.entity.taxdeclaration.po.TaxDeclarationApiConfigPO; import com.engine.salary.entity.taxdeclaration.po.TaxReportColumnPO; import com.engine.salary.entity.taxdeclaration.response.DeclareTaxResponse; import com.engine.salary.enums.salarysob.IncomeCategoryEnum; import com.engine.salary.enums.sicategory.DeleteTypeEnum; import com.engine.salary.exception.SalaryRunTimeException; import com.engine.salary.remote.tax.client.CalculateClient; import com.engine.salary.remote.tax.response.calculate.GetASynIndividualIncomeTaxFeedbackResponse; import com.engine.salary.service.*; import com.engine.salary.util.*; import com.engine.salary.util.db.IdGenerator; import org.apache.commons.collections4.CollectionUtils; import weaver.hrm.User; import java.util.*; public class SalaryCalcTaxServiceImpl extends Service implements SalaryCalcTaxService { private SalaryAcctRecordService getSalaryAcctRecordService(User user) { return ServiceUtil.getService(SalaryAcctRecordServiceImpl.class, user); } private SalaryAcctTaxAgentService getSalaryAcctTaxAgentService(User user) { return ServiceUtil.getService(SalaryAcctTaxAgentServiceImpl.class, user); } private SalaryAcctEmployeeService getSalaryAcctEmployeeService(User user) { return ServiceUtil.getService(SalaryAcctEmployeeServiceImpl.class, user); } private TaxAgentService getTaxAgentService(User user) { return ServiceUtil.getService(TaxAgentServiceImpl.class, user); } private TaxAgentTaxReturnService getTaxAgentTaxReturnService(User user) { return ServiceUtil.getService(TaxAgentTaxReturnServiceImpl.class, user); } private TaxReportColumnService getTaxReportColumnService(User user) { return ServiceUtil.getService(TaxReportColumnServiceImpl.class, user); } private SalarySobTaxReportRuleService getSalarySobTaxReportRuleService(User user) { return ServiceUtil.getService(SalarySobTaxReportRuleServiceImpl.class, user); } private SalarySobTaxRuleService getSalarySobTaxRuleService(User user) { return ServiceUtil.getService(SalarySobTaxRuleServiceImpl.class, user); } private EmployeeDeclareService getEmployeeDeclareService(User user) { return ServiceUtil.getService(EmployeeDeclareServiceImpl.class, user); } private TaxDeclarationApiConfigService getTaxDeclarationApiConfigService(User user) { return ServiceUtil.getService(TaxDeclarationApiConfigServiceImpl.class, user); } private SalaryAcctCalcTaxReqService getSalaryAcctCalcTaxReqService(User user) { return ServiceUtil.getService(SalaryAcctCalcTaxReqServiceImpl.class, user); } private SalaryAcctResultService getSalaryAcctResultService(User user) { return ServiceUtil.getService(SalaryAcctResultServiceImpl.class, user); } @Override public SalaryCalcTaxInfoDTO getCalcTaxInfo(SalaryCalcTaxParam salaryCalcTaxParam) { // 查询薪资核算记录 SalaryAcctRecordPO salaryAcctRecord = getSalaryAcctRecordService(user).getById(salaryCalcTaxParam.getSalaryAcctRecordId()); // 查询供应商信息 TaxDeclarationApiConfigPO apiConfig = getTaxDeclarationApiConfigService(user).getConfig(false); // 查询在线计算个税记录 List salaryAcctCalcTaxReqs = getSalaryAcctCalcTaxReqService(user).listByRecordId(salaryAcctRecord.getId()); boolean enableTaxDeclarationApiConfig = Objects.nonNull(apiConfig) && Objects.equals(apiConfig.getEnableUse(), 1); boolean showCalcTaxButton = enableTaxDeclarationApiConfig && CollectionUtils.isEmpty(salaryAcctCalcTaxReqs); boolean showCalcTaxFeedbackButton = enableTaxDeclarationApiConfig && CollectionUtils.isNotEmpty(salaryAcctCalcTaxReqs); SalaryCalcTaxInfoDTO salaryCalcTaxInfo = new SalaryCalcTaxInfoDTO(); salaryCalcTaxInfo.setEnableTaxDeclarationApiConfig(enableTaxDeclarationApiConfig); salaryCalcTaxInfo.setShowCalcTaxButton(showCalcTaxButton); salaryCalcTaxInfo.setShowCalcTaxFeedbackButton(showCalcTaxFeedbackButton); return salaryCalcTaxInfo; } @Override public void calcTax(SalaryCalcTaxParam salaryCalcTaxParam) { // 查询供应商信息 TaxDeclarationApiConfigPO apiConfig = getTaxDeclarationApiConfigService(user).getConfig(true); if (apiConfig == null) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(160525, "接口流量不足,暂无法使用该功能,请先购买智能算薪接口流量")); } int i = getSalaryAcctEmployeeService(user).countNotDeclareByParam(AbnormalEmployeeListQueryParam.builder().recordId(salaryCalcTaxParam.getSalaryAcctRecordId()).build()); if (i > 0) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(11111, "存在未报送的人员,请先进行人员报送")); } // 查询薪资核算记录 SalaryAcctRecordPO salaryAcctRecord = getSalaryAcctRecordService(user).getById(salaryCalcTaxParam.getSalaryAcctRecordId()); // 查询薪资核算记录关联的个税扣缴义务人 List salaryAcctTaxAgents = getSalaryAcctTaxAgentService(user) .listBySalaryAcctRecordIds(Collections.singleton(salaryAcctRecord.getId())); // 查询薪资核算记录关联的薪资核算人员 List salaryAcctEmployees = getSalaryAcctEmployeeService(user).listBySalaryAcctRecordId(salaryAcctRecord.getId()); // 查询薪资核算记录关联的薪资核算结果 List salaryAcctResultValues = getSalaryAcctResultService(user).listBySalaryAcctRecordIds(Collections.singleton(salaryAcctRecord.getId())); // 查询个税扣缴义务人 Set taxAgentIds = SalaryEntityUtil.properties(salaryAcctTaxAgents, SalaryAcctTaxAgentPO::getTaxAgentId); List taxAgents = getTaxAgentService(user).listByIds(taxAgentIds); // 查询个税扣缴义务人关联的报税信息 List taxAgentTaxReturns = getTaxAgentTaxReturnService(user).getByTaxAgentIds(taxAgentIds); // 查询个税申报表字段 List taxReportColumns = getTaxReportColumnService(user).listAll(); // 查询薪资核算记录关联薪资账套的个税申报配置 List salarySobTaxReportRules = getSalarySobTaxReportRuleService(user) .listBySalarySobIds(Collections.singleton(salaryAcctRecord.getSalarySobId())); // 查询报送人员 List employeeDeclares = getEmployeeDeclareService(user).listBySalaryAcctTaxAgent(salaryAcctTaxAgents); List salaryAcctCalcTaxReqs = new ArrayList<>(); Date now = new Date(); Map params = new HashMap<>(1); Map header = SingnatureData.initHeader(params, apiConfig.getAppKey(), apiConfig.getAppSecret()); String url = apiConfig.getHost() + SzyhApiConstant.CALCULATE_ASYN_INDIVIDUAL_INCOME_TAX; SalaryCalcTax salaryCalcTax = new SalaryCalcTax(salaryAcctRecord, salaryAcctTaxAgents, salaryAcctEmployees, salaryAcctResultValues, taxAgents, taxAgentTaxReturns, taxReportColumns, salarySobTaxReportRules, employeeDeclares); Map> taxAgentIdKeyRequestParam = salaryCalcTax.buildCalcTaxRequestParam(); for (Map.Entry> entry : taxAgentIdKeyRequestParam.entrySet()) { String reqJson = JsonUtil.toJsonString(entry.getValue()); // 请求第三方供应商 String res = HttpUtil.doPost(url, header, reqJson, HttpUtil.JSON_TYPE); DeclareTaxResponse declareTaxResponse = JsonUtil.parseObject(res, DeclareTaxResponse.class); if (Objects.isNull(declareTaxResponse) || Objects.isNull(declareTaxResponse.getHead())) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(156449, "服务异常")); } if (!Objects.equals(declareTaxResponse.getHead().getCode(), SzyhApiConstant.SUCCESS_CODE)) { throw new SalaryRunTimeException(declareTaxResponse.getHead().getMsg()); } SalaryAcctCalcTaxReqPO salaryAcctCalcTaxReq = new SalaryAcctCalcTaxReqPO(); salaryAcctCalcTaxReq.setId(IdGenerator.generate()); salaryAcctCalcTaxReq.setSalaryAcctRecordId(salaryAcctRecord.getId()); salaryAcctCalcTaxReq.setTaxAgentId(entry.getKey()); salaryAcctCalcTaxReq.setRequestId(declareTaxResponse.getBody().getRequestId()); salaryAcctCalcTaxReq.setTenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY); salaryAcctCalcTaxReq.setCreator((long) user.getUID()); salaryAcctCalcTaxReq.setDeleteType(DeleteTypeEnum.NOT_DELETED.getValue()); salaryAcctCalcTaxReq.setCreateTime(now); salaryAcctCalcTaxReq.setUpdateTime(now); salaryAcctCalcTaxReqs.add(salaryAcctCalcTaxReq); } // 批量保存 getSalaryAcctCalcTaxReqService(user).batchSave(salaryAcctCalcTaxReqs); // 记录日志 String operateTypeName = SalaryI18nUtil.getI18nLabel(268191, "在线计算个税"); // 记录日志 // getSalaryAcctResultService(user).writeBatchLog(salaryAcctRecord, Collections.emptyMap(), SalaryLogOperateTypeEnum.CALC_TAX_ONLINE); } @Override public void calcTaxFeedback(SalaryCalcTaxParam salaryCalcTaxParam) { // 查询供应商信息 TaxDeclarationApiConfigPO apiConfig = getTaxDeclarationApiConfigService(user).getConfig(true); if (apiConfig == null) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(160525, "接口流量不足,暂无法使用该功能,请先购买智能算薪接口流量")); } // 查询薪资核算记录 SalaryAcctRecordPO salaryAcctRecord = getSalaryAcctRecordService(user).getById(salaryCalcTaxParam.getSalaryAcctRecordId()); // 查询薪资核算记录关联的薪资核算人员 List salaryAcctEmployees = getSalaryAcctEmployeeService(user).listBySalaryAcctRecordId(salaryAcctRecord.getId()); Map> salaryAcctEmployeeMap = SalaryEntityUtil.group2Map(salaryAcctEmployees, e -> e.getTaxAgentId() + "-" + e.getIncomeCategory()); // 查询薪资核算记录关联的薪资核算结果 List salaryAcctResultValues = getSalaryAcctResultService(user).listBySalaryAcctRecordIds(Collections.singleton(salaryAcctRecord.getId())); Map> salaryAcctResultValueMap = SalaryEntityUtil.list2Map(salaryAcctResultValues, SalaryAcctResultPO::getSalaryAcctEmpId, SalaryAcctResultPO::getSalaryItemId); // 查询薪资核算记录关联的个税扣缴义务人 List salaryAcctTaxAgents = getSalaryAcctTaxAgentService(user) .listBySalaryAcctRecordIds(Collections.singleton(salaryAcctRecord.getId())); Map> salaryAcctTaxAgentMap = SalaryEntityUtil.group2Map(salaryAcctTaxAgents, SalaryAcctTaxAgentPO::getTaxAgentId); // 查询薪资核算记录关联的异步算税请求记录 List salaryAcctCalcTaxReqs = getSalaryAcctCalcTaxReqService(user).listByRecordId(salaryAcctRecord.getId()); if (CollectionUtils.isEmpty(salaryAcctCalcTaxReqs)) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(268184, "请先计算个税再获取反馈")); } // 查询薪资核算记录关联的薪资账套个税字段对应 List salarySobTaxRules = getSalarySobTaxRuleService(user).getSalarySobTaxRuleDTO(salaryAcctRecord.getSalarySobId()); Map salarySobTaxRuleMap = SalaryEntityUtil.convert2Map(salarySobTaxRules, SalarySobTaxRuleDTO::getIncomeCategoryId); // 查询报送人员 List employeeDeclares = getEmployeeDeclareService(user).listBySalaryAcctTaxAgent(salaryAcctTaxAgents); Map> employeeDeclareMap = SalaryEntityUtil.group2Map(employeeDeclares, EmployeeDeclarePO::getTaxAgentId); List resultPOS = new ArrayList<>(); for (SalaryAcctCalcTaxReqPO salaryAcctCalcTaxReq : salaryAcctCalcTaxReqs) { CalculateClient calculateClient = new CalculateClient(salaryAcctCalcTaxReq.getTaxAgentId()); GetASynIndividualIncomeTaxFeedbackResponse feedbackResponse = calculateClient.getASynIndividualIncomeTaxFeedback(salaryAcctCalcTaxReq.getRequestId()); if (Objects.isNull(feedbackResponse) || Objects.isNull(feedbackResponse.getHead())) { throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(156449, "服务异常")); } if (!Objects.equals(feedbackResponse.getHead().getCode(), SzyhApiConstant.SUCCESS_CODE)) { throw new SalaryRunTimeException(feedbackResponse.getHead().getMsg()); } List subSalaryAcctTaxAgents = salaryAcctTaxAgentMap.get(salaryAcctCalcTaxReq.getTaxAgentId()); if (CollectionUtils.isEmpty(subSalaryAcctTaxAgents)) { continue; } List subEmployeeDeclares = employeeDeclareMap.get(salaryAcctCalcTaxReq.getTaxAgentId()); // 获取不同所得项目的个税 for (SalaryAcctTaxAgentPO salaryAcctTaxAgent : subSalaryAcctTaxAgents) { IncomeCategoryEnum incomeCategoryEnum = IncomeCategoryEnum.parseByValue(salaryAcctTaxAgent.getIncomeCategory()); if (incomeCategoryEnum == null) { continue; } SalarySobTaxRuleDTO taxRuleDTO = salarySobTaxRuleMap.get(incomeCategoryEnum.getValue().toString()); Map empIdResult = incomeCategoryEnum.parseGetASynIndividualIncomeTaxFeedbackResponse(feedbackResponse, subEmployeeDeclares, taxRuleDTO); List subSalaryAcctEmployees = salaryAcctEmployeeMap.get(salaryAcctTaxAgent.getTaxAgentId() + "-" + salaryAcctTaxAgent.getIncomeCategory()); if (CollectionUtils.isEmpty(subSalaryAcctEmployees)) { continue; } for (SalaryAcctEmployeePO salaryAcctEmployee : subSalaryAcctEmployees) { Map salaryAcctResultValue = salaryAcctResultValueMap.get(salaryAcctEmployee.getId()); if (salaryAcctResultValue == null) { continue; } SalarySobTaxRuleDTO salarySobTaxRuleDTO = empIdResult.get(salaryAcctEmployee.getEmployeeId()); List taxRules = salarySobTaxRuleDTO.getTaxRules(); taxRules.forEach(rule -> { SalaryAcctResultPO salaryAcctResultPO = salaryAcctResultValue.get(rule.getSalaryItemId()); if (salaryAcctResultPO != null) { salaryAcctResultPO.setResultValue(rule.getValue()); resultPOS.add(salaryAcctResultPO); } }); } } } getSalaryAcctResultService(user).batchUpdate(resultPOS); getSalaryAcctCalcTaxReqService(user).deleteByRecordId(salaryAcctRecord.getId()); // 记录日志 // getSalaryAcctResultService(user).writeBatchLog(salaryAcctRecord, Collections.emptyMap(), SalaryLogOperateTypeEnum.GET_CALC_TAX_FEEDBACK); } }