Commit a17fd9aa authored by fangxinjiang's avatar fangxinjiang

项目配置新增同步合同及商险待续签数据-fxj

parent 1bbada55
......@@ -28,6 +28,8 @@ import com.yifu.cloud.plus.v1.yifu.archives.vo.TAutoMainRelExportVo;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TAutoMainRelRestrictVo;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TAutoMainRelSearchVo;
import com.yifu.cloud.plus.v1.yifu.archives.vo.ProjectAutoSetParam;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.ErrorMessage;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser;
......@@ -133,7 +135,16 @@ public class TAutoMainRelController {
@SysLog("新增项目配置表" )
@PostMapping("/save")
public R<Boolean> save(@RequestBody TAutoMainRelAddVo entity) {
return tAutoMainRelService.saveAsso(entity);
R<Boolean> result = tAutoMainRelService.saveAsso(entity);
// ✅ 如果保存成功,异步刷新续签数据(不阻塞主流程)
if (null != result
&& result.getCode() == CommonConstants.SUCCESS.intValue()
&& Common.isNotNull(entity.getAutoMainRel())) {
tAutoMainRelService.asyncRefreshRenewalDataAfterSave(entity.getAutoMainRel());
}
return result;
}
/**
......
......@@ -252,8 +252,8 @@ public class TEmpContractAlertController {
}
/**
* 定时任务生成合同续签代码信息
* @return R<List>
* 定时任务生成合同续签代码信息(支持按项目过滤)
* @return R<Boolean>
* @Author FXJ
* @Date 2022-07-4
**/
......@@ -261,7 +261,7 @@ public class TEmpContractAlertController {
@PostMapping("/taskCreateContractAlert")
@Inner
public R taskCreateContractAlert() {
return tEmpContractAlertService.taskCreateContractAlert();
return tEmpContractAlertService.taskCreateContractAlert(null);
}
/**
......
......@@ -60,7 +60,7 @@ public interface TEmpContractAlertMapper extends BaseMapper<TEmpContractAlert> {
List<TEmpContractAlertExportVo> listExport(@Param("tEmpContractAlert") ContractAlertSearchVo searchVo);
void updateProcessStatus();
void updateProcessStatus(@Param("deptNo") String deptNo);
List<ContractAlertConfirmVo> getAutoRenewForConfirm(@Param("tEmpContractAlert")ContractAlertSearchVo tEmpContractAlert);
......
......@@ -96,4 +96,10 @@ public interface TAutoMainRelService extends IService<TAutoMainRel> {
* @param entity 项目配置实体
*/
void generateAutoConfigItems(TAutoMainRel entity);
/**
* 项目配置保存后异步刷新续签数据(仅新增时触发)
* @param tAutoMainRel 项目配置对象
*/
void asyncRefreshRenewalDataAfterSave(TAutoMainRel tAutoMainRel);
}
......@@ -56,12 +56,13 @@ public interface TEmpContractAlertService extends IService<TEmpContractAlert> {
void listExport(HttpServletResponse response, ContractAlertSearchVo searchVo);
/**
* 定时任务生成合同续签代码信息
* @return R<List>
* 定时任务生成合同续签代码信息(支持按项目过滤)
* @param deptNo 项目编码(可选,为null时全局刷新)
* @return R<Boolean>
* @Author FXJ
* @Date 2022-07-4
**/
R<Boolean> taskCreateContractAlert();
R<Boolean> taskCreateContractAlert(String deptNo);
boolean changeFeedBackAll(ChangeFeedBackAllVo changeFeedBackAllVo);
......
......@@ -32,6 +32,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yifu.cloud.plus.v1.yifu.archives.entity.*;
import com.yifu.cloud.plus.v1.yifu.archives.mapper.*;
import com.yifu.cloud.plus.v1.yifu.archives.service.TAutoMainRelService;
import com.yifu.cloud.plus.v1.yifu.archives.service.TEmpContractAlertService;
import com.yifu.cloud.plus.v1.yifu.archives.vo.*;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.ServiceNameConstants;
......@@ -40,6 +41,7 @@ import com.yifu.cloud.plus.v1.yifu.common.core.util.equator.HrEquator;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.ArchivesDaprUtil;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.SocialDaprUtils;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.InsuranceDaprUtil;
import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
import com.yifu.cloud.plus.v1.yifu.insurances.vo.AutoDeptDetailVO;
import com.yifu.cloud.plus.v1.yifu.insurances.vo.AutoDeptVO;
......@@ -48,6 +50,7 @@ import com.yifu.cloud.plus.v1.yifu.social.vo.SysBaseSetInfoVo;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
......@@ -122,6 +125,18 @@ public class TAutoMainRelServiceImpl extends ServiceImpl<TAutoMainRelMapper, TAu
@Autowired
private SocialDaprUtils socialDaprUtils;
// ✅ 合同续签服务(同模块,直接注入)
@Autowired
private TEmpContractAlertService empContractAlertService;
// ✅ 商险续签服务(跨模块,通过Dapr调用)
@Autowired
private InsuranceDaprUtil insuranceDaprUtil;
// ✅ 刷新日志Mapper
@Autowired
private TAutoMainRelRefreshLogMapper refreshLogMapper;
public static final String itemsLabel = "label,description,disable";
public static final String itemsLabelRepeat = "同一项目岗位名称不可重复";
......@@ -1798,7 +1813,9 @@ private R<Boolean> checkItemRepeat(List<SysAutoDictItem> autoDictItems, Map<Stri
if (Common.isEmpty(entity)) {
return R.failed(CommonConstants.PARAM_INFO_ERROR);
}
// 保存旧数据用于日志记录
TAutoMainRel oldEntity = new TAutoMainRel();
BeanUtils.copyProperties(entity, oldEntity);
boolean hasChange = false;
// 获取当前要设置的值(使用VO中的值,如果为null则使用实体当前值)
......@@ -1871,6 +1888,33 @@ private R<Boolean> checkItemRepeat(List<SysAutoDictItem> autoDictItems, Map<Stri
entity.setRuleUpdatePerson(user.getNickname());
entity.setRuleUpdateTime(DateUtil.getCurrentDateTime());
baseMapper.updateById(entity);
// 记录变更日志
Map<String,String> diffKeyMap = new HashMap<>();
Map<String,Object> oldMap = new HashMap<>();
Map<String,Object> newMap = new HashMap<>();
// 添加有变化的字段到差异映射
if (!oldEntity.getAutoFlag().equals(entity.getAutoFlag())) {
diffKeyMap.put("autoFlag", "autoFlag");
}
if (!oldEntity.getRestrictArchive().equals(entity.getRestrictArchive())) {
diffKeyMap.put("restrictArchive", "restrictArchive");
}
if (!oldEntity.getRestrictInsurance().equals(entity.getRestrictInsurance())) {
diffKeyMap.put("restrictInsurance", "restrictInsurance");
}
if (!oldEntity.getRestrictContract().equals(entity.getRestrictContract())) {
diffKeyMap.put("restrictContract", "restrictContract");
}
if (!oldEntity.getRestrictSocialFund().equals(entity.getRestrictSocialFund())) {
diffKeyMap.put("restrictSocialFund", "restrictSocialFund");
}
oldMap.put("oldAutoMainRel", oldEntity);
newMap.put("newAutoMainRel", entity);
insertLog(entity, diffKeyMap, oldMap, newMap);
log.info("更新限制项, 项目配置ID: {}, 用户: {}", vo.getId(), user.getNickname());
}
......@@ -1962,7 +2006,9 @@ private R<Boolean> checkItemRepeat(List<SysAutoDictItem> autoDictItems, Map<Stri
"项目编码不存在: " + excel.getDeptNo(),excel));
return;
}
// 保存旧数据用于日志记录
TAutoMainRel oldEntity = new TAutoMainRel();
BeanUtils.copyProperties(entity, oldEntity);
// 获取当前要设置的值(使用Excel中的值,如果为null则使用实体当前值)
String newAutoFlag = Common.isNotNull(excel.getAutoFlag()) ? excel.getAutoFlag() : entity.getAutoFlag();
String newRestrictArchive = excel.getRestrictArchive();
......@@ -2041,10 +2087,38 @@ private R<Boolean> checkItemRepeat(List<SysAutoDictItem> autoDictItems, Map<Stri
}
if (hasChange) {
entity.setUpdateBy(user.getId());
entity.setRuleUpdatePerson(user.getNickname());
entity.setRuleUpdateTime(DateUtil.getCurrentDateTime());
baseMapper.updateById(entity);
// 记录变更日志
Map<String,String> diffKeyMap = new HashMap<>();
Map<String,Object> oldMap = new HashMap<>();
Map<String,Object> newMap = new HashMap<>();
// 添加有变化的字段到差异映射
if (!oldEntity.getAutoFlag().equals(entity.getAutoFlag())) {
diffKeyMap.put("autoFlag", "autoFlag");
}
if (!oldEntity.getRestrictArchive().equals(entity.getRestrictArchive())) {
diffKeyMap.put("restrictArchive", "restrictArchive");
}
if (!oldEntity.getRestrictInsurance().equals(entity.getRestrictInsurance())) {
diffKeyMap.put("restrictInsurance", "restrictInsurance");
}
if (!oldEntity.getRestrictContract().equals(entity.getRestrictContract())) {
diffKeyMap.put("restrictContract", "restrictContract");
}
if (!oldEntity.getRestrictSocialFund().equals(entity.getRestrictSocialFund())) {
diffKeyMap.put("restrictSocialFund", "restrictSocialFund");
}
oldMap.put("oldAutoMainRel", oldEntity);
newMap.put("newAutoMainRel", entity);
insertLog(entity, diffKeyMap, oldMap, newMap);
log.info("更新限制项, 项目编码: {}, 用户: {}", excel.getDeptNo(), user.getNickname());
}
}
......@@ -2086,4 +2160,103 @@ private R<Boolean> checkItemRepeat(List<SysAutoDictItem> autoDictItems, Map<Stri
// 公积金规则配置
entity.setAutoConfigFund(Common.isNotNull(addVo.getFundRuleInfo()) ? CommonConstants.ONE_STRING : CommonConstants.ZERO_STRING);
}
/**
* 项目配置保存后异步刷新续签数据(仅新增时触发)
* @param tAutoMainRel 项目配置对象
*/
@Override
@Async("renewalRefreshExecutor") // 使用专用线程池
public void asyncRefreshRenewalDataAfterSave(TAutoMainRel tAutoMainRel) {
String deptNo = tAutoMainRel.getDeptNo();
String logId = UUID.randomUUID().toString().replace("-", "");
long startTime = System.currentTimeMillis();
log.info("开始异步刷新项目配置续签数据,项目编码: {}, 配置ID: {}, 日志ID: {}",
deptNo, tAutoMainRel.getId(), logId);
// 记录刷新开始日志
saveRefreshLog(logId, tAutoMainRel, "START", null, 0L);
List<String> errorMessages = new ArrayList<>();
try {
// ========== 1. 刷新合同续签待办(同模块调用)==========
try {
// ✅ 直接调用同模块的定时任务方法
// 注意:续签记录由 TEmpContractAlertServiceImpl 内部记录,此处无需重复记录
R<Boolean> result = empContractAlertService.taskCreateContractAlert(deptNo);
if (null != result
&& null != result.getData()
&& result.getData().booleanValue()) {
log.info("合同续签刷新完成,项目编码: {}", deptNo);
} else {
errorMessages.add("合同续签刷新失败: " + result.getMsg());
}
} catch (Exception e) {
String errorMsg = "合同续签刷新异常: " + e.getMessage();
log.error(errorMsg, e);
errorMessages.add(errorMsg);
}
// ========== 2. 刷新商险续签待办(跨模块Dapr调用)==========
try {
// ✅ 通过 Dapr 跨模块调用商险服务
// 注意:续签记录由 yifu-insurances 模块内部记录,此处无需重复记录
R<Boolean> result = insuranceDaprUtil.createInsuranceAlertByDeptNo(deptNo);
if (null != result
&& null != result.getData()
&& result.getData().booleanValue()) {
log.info("商险续签刷新完成,项目编码: {}", deptNo);
} else {
errorMessages.add("商险续签刷新失败: " + result.getMsg());
log.warn("商险续签刷新返回失败,项目编码: {}, 错误: {}", deptNo, result.getMsg());
}
} catch (Exception e) {
String errorMsg = "商险续签刷新异常: " + e.getMessage();
log.error(errorMsg, e);
errorMessages.add(errorMsg);
}
// ========== 3. 记录刷新结果 ==========
long duration = System.currentTimeMillis() - startTime;
String resultMsg;
if (!errorMessages.isEmpty()) {
resultMsg = "错误: " + String.join("; ", errorMessages);
saveRefreshLog(logId, tAutoMainRel, "ERROR", resultMsg, duration);
} else {
resultMsg = "合同和商险续签刷新成功";
saveRefreshLog(logId, tAutoMainRel, "SUCCESS", resultMsg, duration);
}
// ========== 4. 超时告警 ==========
if (duration > 30000) { // 超过30秒
log.warn("项目配置刷新耗时过长,项目编码: {}, 耗时: {}ms", deptNo, duration);
}
} catch (Exception e) {
long duration = System.currentTimeMillis() - startTime;
saveRefreshLog(logId, tAutoMainRel, "EXCEPTION", e.getMessage(), duration);
}
}
/**
* 保存刷新日志(仅记录刷新任务本身的执行情况)
*/
private void saveRefreshLog(String logId, TAutoMainRel config, String status,
String result, Long duration) {
TAutoMainRelRefreshLog log = new TAutoMainRelRefreshLog();
log.setId(logId);
log.setConfigId(config.getId());
log.setDeptNo(config.getDeptNo());
log.setStatus(status); // START/SUCCESS/ERROR/EXCEPTION
log.setResult(result);
log.setDuration(duration);
// ✅ BaseEntity的字段(createName, createBy, createTime, updateBy, updateTime)由MyBatis Plus自动填充
refreshLogMapper.insert(log);
}
}
\ No newline at end of file
......@@ -380,16 +380,17 @@ public class TEmpContractAlertServiceImpl extends ServiceImpl<TEmpContractAlertM
return wrapper;
}
/**
* 定时任务生成合同续签代码信息
* @return R<List>
* 定时任务生成合同续签代码信息(支持按项目过滤)
* @param deptNo 项目编码(可选,为null时全局刷新)
* @return R<Boolean>
* @Author FXJ
* @Date 2022-07-4
**/
@Override
public R<Boolean> taskCreateContractAlert() {
// 获取合同为在档、员工类型为“0外包”、“1派遣”、最近一次合同审核通过、过期或离过期还有3个月的数据
List<TEmployeeContractInfo> alertList = contractInfoMapper.selectList(Wrappers.<TEmployeeContractInfo>query()
.lambda().eq(TEmployeeContractInfo::getAuditStatus, CommonConstants.TWO_STRING)
public R<Boolean> taskCreateContractAlert(String deptNo) {
// 构建查询条件
LambdaQueryWrapper<TEmployeeContractInfo> wrapper = Wrappers.<TEmployeeContractInfo>query().lambda()
.eq(TEmployeeContractInfo::getAuditStatus, CommonConstants.TWO_STRING)
.isNotNull(TEmployeeContractInfo::getAuditTimeLast)
.eq(TEmployeeContractInfo::getInUse,CommonConstants.ZERO_STRING)
.eq(TEmployeeContractInfo::getContractType,CommonConstants.ONE_STRING)
......@@ -399,21 +400,46 @@ public class TEmpContractAlertServiceImpl extends ServiceImpl<TEmpContractAlertM
.le(TEmployeeContractInfo::getContractEnd,DateUtil.dateIncreaseByDay(
DateUtil.dateIncreaseByMonth(DateUtil.getCurrentDateTime(),
CommonConstants.dingleDigitIntArray[3]), CommonConstants.dingleDigitIntArray[1]))
.eq(TEmployeeContractInfo::getDeleteFlag, CommonConstants.ZERO_STRING));
// 获取所有未审核通过的合同数据
List<TEmployeeContractInfo> notAccessList = contractInfoMapper.selectList(Wrappers.<TEmployeeContractInfo>query().lambda()
.eq(TEmployeeContractInfo::getDeleteFlag, CommonConstants.ZERO_STRING);
// ✅ 如果传入了项目编码,则按项目过滤
if (Common.isNotNull(deptNo)) {
wrapper.eq(TEmployeeContractInfo::getDeptNo, deptNo);
log.info("按项目刷新合同续签待办,项目编码: {}", deptNo);
} else {
log.info("全局刷新合同续签待办");
}
// 获取符合条件的合同列表
List<TEmployeeContractInfo> alertList = contractInfoMapper.selectList(wrapper);
// 获取所有未审核通过的合同数据(支持按项目过滤)
LambdaQueryWrapper<TEmployeeContractInfo> notAccessWrapper = Wrappers.<TEmployeeContractInfo>query().lambda()
.and(obj->obj.eq(TEmployeeContractInfo::getAuditStatus,CommonConstants.ZERO_STRING)
.or().eq(TEmployeeContractInfo::getAuditStatus,CommonConstants.ONE_STRING)
.or().eq(TEmployeeContractInfo::getAuditStatus,CommonConstants.FOUR_STRING))
.eq(TEmployeeContractInfo::getWorkFlag,CommonConstants.ZERO_STRING)
.eq(TEmployeeContractInfo::getDeleteFlag,CommonConstants.ZERO_STRING));
.eq(TEmployeeContractInfo::getDeleteFlag,CommonConstants.ZERO_STRING);
if (Common.isNotNull(deptNo)) {
notAccessWrapper.eq(TEmployeeContractInfo::getDeptNo, deptNo);
}
List<TEmployeeContractInfo> notAccessList = contractInfoMapper.selectList(notAccessWrapper);
Map<String,TEmpContractAlert> alertMap = new HashMap<>();
Map<String,TEmpContractAlert> existMap = new HashMap<>();
initExistMap(existMap);
initExistMap(existMap, deptNo);
if (Common.isNotNull(alertList)) {
List<TSettleDomain> projects = settleDomainMapper.selectList(Wrappers.<TSettleDomain>query().lambda()
.eq(TSettleDomain::getDeleteFlag,CommonConstants.ZERO_STRING));
List<TAutoMainRel> ruleInfos = autoMainRelMapper.selectList(Wrappers.<TAutoMainRel>query().lambda());
// 如果项目编码不为空,查询对应项目的数据;否则查询所有数据
LambdaQueryWrapper<TSettleDomain> projectWrapper = Wrappers.<TSettleDomain>query().lambda()
.eq(TSettleDomain::getDeleteFlag, CommonConstants.ZERO_STRING);
if (Common.isNotNull(deptNo)) {
projectWrapper.eq(TSettleDomain::getDepartNo, deptNo);
}
List<TSettleDomain> projects = settleDomainMapper.selectList(projectWrapper);
LambdaQueryWrapper<TAutoMainRel> ruleWrapper = Wrappers.<TAutoMainRel>query().lambda();
if (Common.isNotNull(deptNo)) {
ruleWrapper.eq(TAutoMainRel::getDeptNo, deptNo);
}
List<TAutoMainRel> ruleInfos = autoMainRelMapper.selectList(ruleWrapper);
//判空、判重,处理重复键和null值
Map<String,TSettleDomain> projectMap= null;
if (Common.isNotNull(projects)){
......@@ -462,18 +488,29 @@ public class TEmpContractAlertServiceImpl extends ServiceImpl<TEmpContractAlertM
}
}
}
baseMapper.truncate();
// 如果项目编码不为空 删除对应项目的提醒数据 否则全部删除
if (Common.isNotNull(deptNo)) {
baseMapper.delete(Wrappers.<TEmpContractAlert>query().lambda()
.eq(TEmpContractAlert::getProjectNo,deptNo));
}else {
baseMapper.truncate();
}
if (Common.isNotNull(alertMap)){
this.saveBatch(alertMap.values());
}
//更新自动化的所有的合同办理状态
baseMapper.updateProcessStatus();
//更新自动化的所有的合同办理状态--这里如果项目编码不为空要传参
baseMapper.updateProcessStatus(deptNo);
return R.ok();
}
private void initExistMap(Map<String, TEmpContractAlert> existMap) {
List<TEmpContractAlert> exists = baseMapper.selectList(Wrappers.<TEmpContractAlert>query());
private void initExistMap(Map<String, TEmpContractAlert> existMap, String deptNo) {
LambdaQueryWrapper<TEmpContractAlert> wrapper = Wrappers.<TEmpContractAlert>query().lambda();
// 如果项目编码不为空,只查询对应项目的已存在记录
if (Common.isNotNull(deptNo)) {
wrapper.eq(TEmpContractAlert::getProjectNo, deptNo);
}
List<TEmpContractAlert> exists = baseMapper.selectList(wrapper);
if (Common.isNotNull(exists)){
for (TEmpContractAlert alert:exists){
existMap.put(alert.getContractId(),alert);
......
......@@ -422,9 +422,12 @@
WHEN b.process_status = '9' THEN '2'
WHEN b.process_status IN ('6', '8', '2', '4') THEN '1'
ELSE a.HANDLE_STATUS -- 保持不变
END
END
WHERE a.AUTO_FLAG = '0'
AND b.process_status IN ('9', '6', '8', '2', '4') -- 只处理这些状态
<if test="deptNo != null and deptNo.trim() != ''">
AND a.PROJECT_NO = #{deptNo}
</if>
</update>
<!--tEmpContractAlert简单分页查询-->
......
......@@ -2,6 +2,7 @@ package com.yifu.cloud.plus.v1.yifu.common.core.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
......@@ -21,7 +22,6 @@ import java.util.concurrent.ThreadPoolExecutor;
@Slf4j
public class AsyncConfig implements AsyncConfigurer {
// todo 幂等性如何保证
@Override
public Executor getAsyncExecutor() {
//定义线程池
......@@ -69,4 +69,58 @@ public class AsyncConfig implements AsyncConfigurer {
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
/**
* 续签刷新专用线程池(集群环境固定配置)
*
* 配置说明:
* - 集群环境中 Runtime.getRuntime().availableProcessors() 获取的是容器CPU核数,不准确
* - 采用固定值配置,按 CPU核数=2 计算
* - 核心线程数 = 2 + 1 = 3(IO密集型任务)
* - 最大线程数 = 3 × 2 = 6
* - 队列容量 = 50(平衡内存和缓冲)
*/
@Bean("renewalRefreshExecutor")
public Executor renewalRefreshExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// ✅ 集群环境固定配置(按CPU核数=2计算)
int corePoolSize = 3; // CPU核数(2) + 1
int maxPoolSize = 6; // 核心线程数 × 2
int queueCapacity = 50; // 队列容量
// 核心线程数:3(适合IO密集型任务)
executor.setCorePoolSize(corePoolSize);
// 最大线程数:6(应对突发流量)
executor.setMaxPoolSize(maxPoolSize);
// 队列容量:50(平衡内存使用和任务缓冲)
executor.setQueueCapacity(queueCapacity);
// 线程名前缀:便于日志追踪
executor.setThreadNamePrefix("renewal-refresh-");
// 线程存活时间:60秒
executor.setKeepAliveSeconds(60);
// 允许核心线程超时回收(节省资源)
executor.setAllowCoreThreadTimeOut(true);
// 拒绝策略:由调用线程执行,避免任务丢失
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
// 等待时间:60秒
executor.setAwaitTerminationSeconds(60);
executor.initialize();
log.info("续签刷新线程池初始化完成(集群固定配置) - 核心线程: {}, 最大线程: {}, 队列容量: {}",
corePoolSize, maxPoolSize, queueCapacity);
return executor;
}
}
......@@ -288,4 +288,28 @@ public class InsuranceDaprUtil {
return res;
}
/**
* @Description: 按项目生成商险续签待办(供项目配置新增时调用)
* @Author: system
* @Date: 2026-05-19
* @param deptNo 项目编码
* @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R<java.lang.Boolean>
**/
public R<Boolean> createInsuranceAlertByDeptNo(String deptNo) {
BaseSearchVO paramVo = new BaseSearchVO();
paramVo.setDeptNo(deptNo);
R<Boolean> res = HttpDaprUtil.invokeMethodPost(
daprInsurancesProperties.getAppUrl(),
daprInsurancesProperties.getAppId(),
"/tinsurancewarn/inner/createInsuranceAlert",
paramVo,
Boolean.class,
SecurityConstants.FROM_IN
);
if (Common.isEmpty(res)) {
return R.failed("按项目生成商险续签待办失败!");
}
return res;
}
}
......@@ -6,6 +6,7 @@ import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.ErrorMessage;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.BaseSearchVO;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.MenuUtil;
import com.yifu.cloud.plus.v1.yifu.common.log.annotation.SysLog;
......@@ -209,8 +210,9 @@ public class TInsurancesWarnController {
@Operation(description = "每天刷新商险到期提醒信息")
@Inner
@PostMapping("/inner/createInsuranceAlert")
public void createInsuranceAlert() {
insuranceWarnService.createInsuranceAlert();
public void createInsuranceAlert(@RequestBody(required = false) BaseSearchVO paramVo) {
String deptNo = Common.isNotNull(paramVo) ? paramVo.getDeptNo() : null;
insuranceWarnService.createInsuranceAlert(deptNo);
}
/**
......
......@@ -37,10 +37,26 @@ public interface TInsuranceWarnMapper extends BaseMapper<TInsuranceAlert> {
*/
List<TInsuranceAlert> selectInsuranceAlert();
/**
* 按项目查询商险到期提醒信息
*
* @param deptNo 项目编码
* @return {@link List < TInsuranceAlert >}
*/
List<TInsuranceAlert> selectInsuranceAlertByDeptNo(@Param("deptNo") String deptNo);
List<InsuranceAlertWx> getInsuranceAlertToWx();
List<TInsuranceAlert> selectInsuranceAlertIgnore();
/**
* 按项目查询已忽略的商险提醒数据
*
* @param deptNo 项目编码
* @return {@link List < TInsuranceAlert >}
*/
List<TInsuranceAlert> selectInsuranceAlertIgnoreByDeptNo(@Param("deptNo") String deptNo);
// 查找ID与状态,用作忽略等
List<TInsuranceAlert> selectInsuranceAlertList(@Param("idList") List<String> idList);
// 查找ID与状态,用作确认等(与忽略不同的地方:返回的ID不同,更新不同的表数据
......
......@@ -26,7 +26,8 @@ public interface TInsuranceWarnService extends IService<TInsuranceAlert> {
// 商险待续保导出
void exportTInsuranceAlert(TInsuranceAlertSearchVo searchVo, HttpServletResponse response);
void createInsuranceAlert();
// 生成商险续签待办(支持按项目过滤)
void createInsuranceAlert(String deptNo);
void pushInsuranceAlertToWx();
......
......@@ -3,6 +3,7 @@ package com.yifu.cloud.plus.v1.yifu.insurances.service.insurance.impl;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
......@@ -181,12 +182,27 @@ public class TInsuranceWarnServiceImpl extends ServiceImpl<TInsuranceWarnMapper,
}
@Override
public void createInsuranceAlert() {
//批量删除所有未忽略的提醒数据
baseMapper.delete(Wrappers.<TInsuranceAlert>query().lambda()
.eq(TInsuranceAlert::getExpireIgnoreFlag, CommonConstants.ONE_STRING));
//批量生成或者更新商险到期提醒数据
List<TInsuranceAlert> list = baseMapper.selectInsuranceAlert();
public void createInsuranceAlert(String deptNo) {
// 批量删除所有未忽略的提醒数据
LambdaQueryWrapper<TInsuranceAlert> deleteWrapper = Wrappers.<TInsuranceAlert>query().lambda()
.eq(TInsuranceAlert::getExpireIgnoreFlag, CommonConstants.ONE_STRING);
// ✅ 如果传入了项目编码,则只删除该项目的数据
if (Common.isNotNull(deptNo)) {
deleteWrapper.eq(TInsuranceAlert::getDeptNo, deptNo);
}
baseMapper.delete(deleteWrapper);
// 批量生成或者更新商险到期提醒数据
List<TInsuranceAlert> list;
if (Common.isNotNull(deptNo)) {
// ✅ 按项目查询(需要新增查询方法)
list = baseMapper.selectInsuranceAlertByDeptNo(deptNo);
} else {
// 全局查询(原逻辑)
list = baseMapper.selectInsuranceAlert();
}
//获取所有在用的(未删除未锁定)MVP的用户信息
String userIds;
R<Set<String>> onlineSetTemp;
......@@ -295,13 +311,25 @@ public class TInsuranceWarnServiceImpl extends ServiceImpl<TInsuranceWarnMapper,
}
//批量删除已忽略且人员离职的数据
List<TInsuranceAlert> listIgnore = baseMapper.selectInsuranceAlertIgnore();
List<TInsuranceAlert> listIgnore;
if (Common.isNotNull(deptNo)) {
// ✅ 按项目查询已忽略的提醒数据
listIgnore = baseMapper.selectInsuranceAlertIgnoreByDeptNo(deptNo);
} else {
// 全局查询(原逻辑)
listIgnore = baseMapper.selectInsuranceAlertIgnore();
}
onlineSetTemp = new R<>();
onlineSetTemp = getSetR(listIgnore, onlineSetTemp);
if (Common.isNotKong(onlineSetTemp.getData())){
//批量删除已忽略且人员离职的数据
baseMapper.delete(Wrappers.<TInsuranceAlert>query().lambda()
.in(TInsuranceAlert::getEmpIdcardNo, onlineSetTemp.getData()));
LambdaQueryWrapper<TInsuranceAlert> deleteIgnoreWrapper = Wrappers.<TInsuranceAlert>query().lambda()
.in(TInsuranceAlert::getEmpIdcardNo, onlineSetTemp.getData());
// ✅ 如果传入了项目编码,则只删除该项目的数据
if (Common.isNotNull(deptNo)) {
deleteIgnoreWrapper.eq(TInsuranceAlert::getDeptNo, deptNo);
}
baseMapper.delete(deleteIgnoreWrapper);
}
}
......
......@@ -584,6 +584,119 @@
AND a.IS_EFFECT = 0
</select>
<!-- 按项目查询商险到期提醒 -->
<select id="selectInsuranceAlertByDeptNo" resultMap="BaseResultMap">
SELECT
a.ID,
a.EMP_NAME,
a.EMP_IDCARD_NO,
a.DEPT_NO,
a.DEPT_NAME,
a.POST,
a.INSURANCE_COMPANY_NAME,
a.INSURANCE_TYPE_NAME,
a.INSURANCE_CITY_NAME,
a.INSURANCE_HANDLE_CITY_NAME,
a.INSURANCE_HANDLE_PROVINCE_NAME,
a.INSURANCE_PROVINCE_NAME,
a.BUY_STANDARD,
a.UNIT_NAME,
a.UNIT_NO,
a.SETTLE_TYPE,
a.POLICY_EFFECT,
a.EXPIRE_REMARK,
a.EXPIRE_IGNORE_FLAG,
a.SETTLE_MONTH,
a.POLICY_START,
a.POLICY_END,
a.ACTUAL_PREMIUM,
a.ESTIMATE_PREMIUM,
a.INVOICE_NO,
a.MEDICAL_QUOTA,
a.DIE_DISABLE_QUOTA,
a.DEPT_ID,
a.POLICY_NO,
IF( a.POLICY_END >= curdate(), 0, 1 ) IS_OVERDUE,
a.REMARK,
a.CREATE_BY,
a.DELETE_FLAG,
a.CREATE_NAME,
a.CREATE_TIME,
a.UPDATE_BY,
a.UPDATE_TIME,
a.IS_EFFECT,
a.CREATE_USER_DEPT_NAME
,d.ID INSURANCES_PRE_RENEW_DETAIL_ID
,a.BUY_TYPE
,ep.config_id
,ep.config_name
,a.IS_ADRESS,a.REPLACE_TAG
FROM
t_insurance_detail a
INNER JOIN (
SELECT
h.endTime,
max( l.POLICY_START ) POLICY_START,
l.EMP_IDCARD_NO,
l.INSURANCE_COMPANY_NAME,
l.INSURANCE_TYPE_NAME
FROM
(
SELECT
b.EMP_IDCARD_NO,
max( b.POLICY_END ) endTime
FROM
t_insurance_detail b
WHERE
b.POLICY_START BETWEEN date_sub( date_add( curdate(), INTERVAL 1 DAY ), INTERVAL 1 YEAR )
AND curdate()
AND b.IS_EFFECT = 0
AND b.DELETE_FLAG = '0'
AND b.DEPT_NO = #{deptNo}
AND NOT EXISTS (
SELECT
1
FROM
t_insurance_detail ea
WHERE
ea.POLICY_START >= date_sub( date_add( curdate(), INTERVAL 1 DAY ), INTERVAL 1 YEAR )
AND ea.IS_EFFECT = 0
AND ea.DELETE_FLAG = '0'
AND ea.POLICY_END >= date_add( curdate(), INTERVAL 1 MONTH )
AND ea.EMP_IDCARD_NO = b.EMP_IDCARD_NO
AND ea.INSURANCE_COMPANY_NAME = b.INSURANCE_COMPANY_NAME
AND ea.INSURANCE_TYPE_NAME = b.INSURANCE_TYPE_NAME
)
GROUP BY
b.EMP_IDCARD_NO,
b.INSURANCE_COMPANY_NAME,
b.INSURANCE_TYPE_NAME
) h
INNER JOIN t_insurance_detail l ON h.EMP_IDCARD_NO = l.EMP_IDCARD_NO
AND l.DELETE_FLAG = '0'
AND h.endTime = l.POLICY_END
AND l.POLICY_START BETWEEN date_sub( date_add( curdate(), INTERVAL 1 DAY ), INTERVAL 1 YEAR )
AND curdate()
WHERE
l.EXPIRE_IGNORE_FLAG = '1'
GROUP BY
l.EMP_IDCARD_NO,
l.INSURANCE_COMPANY_NAME,
l.INSURANCE_TYPE_NAME,
l.POLICY_END
) ll ON ll.EMP_IDCARD_NO = a.EMP_IDCARD_NO
AND ll.POLICY_START = a.POLICY_START
AND ll.endTime = a.POLICY_END
AND ll.INSURANCE_COMPANY_NAME = a.INSURANCE_COMPANY_NAME
AND ll.INSURANCE_TYPE_NAME = a.INSURANCE_TYPE_NAME
LEFT JOIN t_insurance_pre_renew_detail d on d.INSURANCES_ID = a.id
LEFT JOIN t_employee_insurance_pre ep on ep.INSURANCES_ID = a.id
where a.DELETE_FLAG = '0'
AND a.EXPIRE_IGNORE_FLAG = '1'
AND a.IS_EFFECT = 0
AND a.DEPT_NO = #{deptNo}
</select>
<resultMap id="PushWxResultMap" type="com.yifu.cloud.plus.v1.yifu.insurances.vo.InsuranceAlertWx">
<result property="projectName" column="DEPT_NAME" jdbcType="VARCHAR"/>
<result property="deptNo" column="DEPT_NO" jdbcType="VARCHAR"/>
......@@ -607,6 +720,18 @@
where a.DELETE_FLAG = '0' and a.EXPIRE_IGNORE_FLAG = '0'
</select>
<!-- 按项目查询已忽略的商险提醒数据 -->
<select id="selectInsuranceAlertIgnoreByDeptNo" resultMap="BaseResultMap">
SELECT
a.ID,
a.EMP_NAME,
a.EMP_IDCARD_NO
FROM
t_insurance_alert a
where a.DELETE_FLAG = '0' and a.EXPIRE_IGNORE_FLAG = '0'
AND a.DEPT_NO = #{deptNo}
</select>
<select id="selectInsuranceAlertList" resultMap="BaseResultMap">
SELECT
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment