package com.engine.salary.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.api.formmode.mybatis.util.SqlProxyHandle;
import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.salary.biz.SalarySendBiz;
import com.engine.salary.biz.SalarySendInfoBiz;
import com.engine.salary.cache.SalaryCacheKey;
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
import com.engine.salary.entity.progress.ProgressDTO;
import com.engine.salary.entity.salaryBill.bo.SalaryBillBO;
import com.engine.salary.entity.salaryBill.bo.SalaryTemplateBO;
import com.engine.salary.entity.salaryBill.dto.SalaryBillSendDTO;
import com.engine.salary.entity.salaryBill.dto.SalarySendInfoListDTO;
import com.engine.salary.entity.salaryBill.dto.SalaryTemplateSalaryItemSetListDTO;
import com.engine.salary.entity.salaryBill.param.SalarySendGrantParam;
import com.engine.salary.entity.salaryBill.param.SalarySendInfoQueryParam;
import com.engine.salary.entity.salaryBill.po.SalarySendInfoPO;
import com.engine.salary.entity.salaryBill.po.SalarySendPO;
import com.engine.salary.entity.salaryBill.po.SalaryTemplatePO;
import com.engine.salary.entity.salaryacct.po.SalaryAcctEmployeePO;
import com.engine.salary.entity.salaryacct.po.SalaryAcctResultPO;
import com.engine.salary.entity.salarysob.po.SalarySobPO;
import com.engine.salary.entity.taxagent.po.TaxAgentPO;
import com.engine.salary.enums.salarybill.MessageChannelEnum;
import com.engine.salary.enums.salarybill.SalarySendStatusEnum;
import com.engine.salary.enums.salarysend.SalarySendGrantTypeEnum;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.mapper.salarybill.SalarySendInfoMapper;
import com.engine.salary.mapper.salarybill.SalarySendMapper;
import com.engine.salary.service.*;
import com.engine.salary.util.JsonUtil;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.SalaryI18nUtil;
import com.google.common.collect.Lists;
import com.weaver.util.threadPool.ThreadPoolUtil;
import com.weaver.util.threadPool.constant.ModulePoolEnum;
import com.weaver.util.threadPool.entity.LocalRunnable;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import weaver.hrm.User;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
* 工资单发放
*
Copyright: Copyright (c) 2022
* Company: 泛微软件
*
* @author qiantao
* @version 1.0
**/
@Slf4j
public class SalaryBillServiceImpl extends Service implements SalaryBillService {
private SalarySendMapper getSalarySendMapper() {
return SqlProxyHandle.getProxy(SalarySendMapper.class);
}
private SalarySendInfoMapper getSalarySendInfoMapper() {
return SqlProxyHandle.getProxy(SalarySendInfoMapper.class);
}
private SalaryTemplateService getSalaryTemplateService(User user) {
return ServiceUtil.getService(SalaryTemplateServiceImpl.class, user);
}
private SalarySendService getSalarySendService(User user) {
return ServiceUtil.getService(SalarySendServiceImpl.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 SalaryAcctEmployeeService getSalaryAcctEmployeeService(User user) {
return ServiceUtil.getService(SalaryAcctEmployeeServiceImpl.class, user);
}
private TaxAgentService getTaxAgentService(User user) {
return ServiceUtil.getService(TaxAgentServiceImpl.class, user);
}
private SalarySendRangeService getSalarySendRangeService(User user) {
return ServiceUtil.getService(SalarySendRangeServiceImpl.class, user);
}
private SalaryAcctRecordService getSalaryAcctRecordService(User user) {
return ServiceUtil.getService(SalaryAcctRecordServiceImpl.class, user);
}
private SalaryEmployeeService getSalaryEmployeeService(User user) {
return ServiceUtil.getService(SalaryEmployeeServiceImpl.class, user);
}
private SalarySendInfoBiz salarySendInfoMapper = new SalarySendInfoBiz();
private SalarySendBiz mapper = new SalarySendBiz();
private SalaryEmployeeService salaryEmployeeService;
private SalarySobItemService salarySobItemService;
private ProgressService getProgressService(User user) {
return ServiceUtil.getService(ProgressServiceImpl.class, user);
}
/**
* 工资单发放 start
**********************************************************************/
@Override
public void grant(SalarySendGrantParam param) {
// 1.检查和获取工资单发放
SalarySendPO salarySend = checkAndGetSalarySend(param.getSalarySendId());
// // 已经冻结不能操作
// if (salarySend.getSendStatus().equals(NumberUtils.INTEGER_ONE)) {
// return;
// }
// 获取默认模板
SalarySobPO salarySob = getSalarySobService(user).getById(salarySend.getSalarySobId());
List salaryTemplates = salarySob == null ? Lists.newArrayList() : getSalaryTemplateService(user).getDefaultTemplates(Arrays.asList(salarySend.getSalarySobId(), salarySob.getId()));
if (CollectionUtils.isEmpty(salaryTemplates)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(100518, "没有默认模板,无法发送"));
}
SalaryTemplatePO salaryTemplate = salaryTemplates.get(0);
// 发送通道
Set sendChannels = SalaryBillBO.buildSendChannels(salaryTemplate);
if (CollectionUtils.isEmpty(sendChannels)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(149767, "工资单模板至少开启一个发送通道"));
}
boolean isReplenish = NumberUtils.INTEGER_ONE.equals(salarySend.getSalaryAcctType());
if (isReplenish && StringUtils.isEmpty(salaryTemplate.getReplenishName())) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(204428, "请完善补发工资单模板设置"));
}
// 2.检查是否正在发送中
ProgressDTO salaryBillProgress = getProgressService(user).getProgress(SalaryCacheKey.SALARY_GRANT_PROGRESS + "_" + param.getSalarySendId());
if (Objects.nonNull(salaryBillProgress) && salaryBillProgress.isStatus()
&& Optional.ofNullable(salaryBillProgress.getProgress()).orElse(BigDecimal.ZERO).compareTo(BigDecimal.ONE) < 0) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(136104, "有其他人员正在发送中,请等待其他人员发送结束后再操作"));
}
// 初始化进度
ProgressDTO initProgress = ProgressDTO.builder()
.title(SalaryI18nUtil.getI18nLabel(136097, "发送中"))
.totalQuantity(NumberUtils.INTEGER_ZERO)
.calculatedQuantity(NumberUtils.INTEGER_ZERO)
.progress(BigDecimal.ZERO)
.status(true)
.message("")
.build();
getProgressService(user).initProgress(SalaryCacheKey.SALARY_GRANT_PROGRESS + "_" + salarySend.getId(), initProgress);
List ids = param.getIds();
if (param.getSalarySendRangeIds() != null) {
//如果传了范围id,则使用范围id发放
ids = getSalarySendRangeService(user)
.getSendInfoIdsBySendId(salarySend.getId(), param.getSalarySendRangeIds(), SalarySendGrantTypeEnum.GRANT);
if (ids.isEmpty()) {// 由于查出来是空的,会导致全部发放,在此进行拦截
throw new SalaryRunTimeException("工资发放范围内没有匹配员工");
}
}
// 异步执行
List finalIds = ids;
LocalRunnable localRunnable = new LocalRunnable() {
@Override
public void execute() {
handleGrant(salarySend, finalIds, salarySob, salaryTemplate);
}
};
ThreadPoolUtil.fixedPoolExecute(ModulePoolEnum.OTHER, "salaryBillGrant", localRunnable);
}
/**
* 处理发送
* 注意:
* 1.IM和云桥通道是发送完成后,只需要在预览时获取核算数据,所以发送时可以忽略获取核算数据;
* 2.邮件通道需要在发送时获取,拼凑成html代码,有图片会转化为base64编码变慢,且图片越大越慢
*
* @param salarySend
* @param ids
* @param salarySob
* @param salaryTemplate
*/
private void handleGrant(SalarySendPO salarySend, List ids, SalarySobPO salarySob, SalaryTemplatePO salaryTemplate) {
try {
TaxAgentPO taxAgentPO = getTaxAgentService(user).getById(salarySob.getTaxAgentId());
// 1.构建发送参数
SalaryBillSendDTO salaryBillSendParam = buildSendParams(salarySend, taxAgentPO.getName(), salaryTemplate);
// 2.获取可发送的列表,此步最耗时,需要解密核算数据
List