Commit 2e3d1749 authored by hongguangwu's avatar hongguangwu

Merge remote-tracking branch 'origin/MVP1.7.23' into MVP1.7.23

parents a4f1c8ea 94046792
......@@ -209,4 +209,10 @@ public class EmployeeRegistrationPre extends BaseEntity {
*/
@Schema(description = "是否已确认离职: 0 是 1 ")
private String isLeave;
@Schema(description = "接收终端:0-移动端,1-PC端")
private String receiveTerminal;
@Schema(description = "接收方式:0-单个接收,1-批量接收")
private String receiveType;
}
......@@ -99,7 +99,7 @@ public class TAutoMainRel extends BaseEntity {
private String postFlag;
/**
* 是否仅使用自动化入口 0 是 1否
* 是否仅使用自动化入口 0 是 1否 解释为 0限制 1不限制
*/
@ExcelAttribute(name = "是否仅使用自动化入口", maxLength = 1)
@Schema(description = "是否仅使用自动化入口 0 是 1否")
......@@ -126,4 +126,86 @@ public class TAutoMainRel extends BaseEntity {
@TableField(exist = false)
private String csLoginName;
// ==================== 限制项字段(控制是否限制某服务项目) ====================
/**
* 是否限制档案:0-不限制,1-限制
*/
@ExcelAttribute(name = "是否限制档案", maxLength = 1)
@Schema(description = "是否限制档案:0-不限制,1-限制")
private String restrictArchive;
/**
* 是否限制商险:0-不限制,1-限制
*/
@ExcelAttribute(name = "是否限制商险", maxLength = 1)
@Schema(description = "是否限制商险:0-不限制,1-限制")
private String restrictInsurance;
/**
* 是否限制合同:0-不限制,1-限制
*/
@ExcelAttribute(name = "是否限制合同", maxLength = 1)
@Schema(description = "是否限制合同:0-不限制,1-限制")
private String restrictContract;
/**
* 是否限制社保公积金:0-不限制,1-限制
*/
@ExcelAttribute(name = "是否限制社保公积金", maxLength = 1)
@Schema(description = "是否限制社保公积金:0-不限制,1-限制")
private String restrictSocialFund;
// ==================== 自动化配置项字段(5个独立字段,由后端根据项目配置的服务项目自动计算) ====================
/**
* 是否配置档案:0-否,1-是
*/
@ExcelAttribute(name = "是否配置档案", maxLength = 1)
@Schema(description = "是否配置档案:0-否,1-是")
private String autoConfigArchive;
/**
* 是否配置合同:0-否,1-是
*/
@ExcelAttribute(name = "是否配置合同", maxLength = 1)
@Schema(description = "是否配置合同:0-否,1-是")
private String autoConfigContract;
/**
* 是否配置商险:0-否,1-是
*/
@ExcelAttribute(name = "是否配置商险", maxLength = 1)
@Schema(description = "是否配置商险:0-否,1-是")
private String autoConfigInsurance;
/**
* 是否配置社保:0-否,1-是
*/
@ExcelAttribute(name = "是否配置社保", maxLength = 1)
@Schema(description = "是否配置社保:0-否,1-是")
private String autoConfigSocial;
/**
* 是否配置公积金:0-否,1-是
*/
@ExcelAttribute(name = "是否配置公积金", maxLength = 1)
@Schema(description = "是否配置公积金:0-否,1-是")
private String autoConfigFund;
// ==================== 非数据库字段(用于列表显示) ====================
/**
* 限制项显示(拼接后的服务项目名称,如"社保,公积金")
* 非数据库字段,查询时动态生成
*/
@TableField(exist = false)
@Schema(description = "限制项显示(拼接后的服务项目名称)")
private String restrictItemsDisplay;
/**
* 自动化配置项显示(拼接后的服务项目名称,如"档案、商险、社保")
* 非数据库字段,查询时动态生成
*/
@TableField(exist = false)
@Schema(description = "自动化配置项显示(拼接后的服务项目名称)")
private String autoConfigItemsDisplay;
}
\ No newline at end of file
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the yifu4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.yifu.cloud.plus.v1.yifu.archives.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.yifu.cloud.plus.v1.yifu.common.mybatis.base.BaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 项目配置刷新日志表
*
* @author system
* @date 2026-05-19
*/
@Data
@TableName("t_auto_main_rel_refresh_log")
@Schema(description = "项目配置刷新日志表")
public class TAutoMainRelRefreshLog extends BaseEntity {
/**
* 主键
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "主键")
private String id;
/**
* 项目配置ID
*/
@Schema(description = "项目配置ID")
private String configId;
/**
* 项目编码
*/
@Schema(description = "项目编码")
private String deptNo;
/**
* 状态: START/SUCCESS/ERROR/EXCEPTION
*/
@Schema(description = "状态: START/SUCCESS/ERROR/EXCEPTION")
private String status;
/**
* 刷新结果描述
*/
@Schema(description = "刷新结果描述")
private String result;
/**
* 刷新耗时(毫秒)
*/
@Schema(description = "刷新耗时(毫秒)")
private Long duration;
}
......@@ -392,4 +392,13 @@ public class TEmployeeContractPre extends BaseEntity {
@Schema(description = "发薪日")
private String salaryDay;
@Schema(description = "劳务费可修改标识:0-可修改,1-不可修改")
private String laborFeeModifyFlag;
@Schema(description = "计时工资可修改标识:0-可修改,1-不可修改")
private String hourlyWageModifyFlag;
@Schema(description = "计件工资可修改标识:0-可修改,1-不可修改")
private String pieceWageModifyFlag;
}
......@@ -180,4 +180,9 @@ public class EmployeeRegistrationPreVo implements Serializable {
@TableField(exist = false)
private Boolean fundUpdateFlag;
@Schema(description = "接收终端:0-移动端,1-PC端")
private String receiveTerminal;
@Schema(description = "接收方式:0-单个接收,1-批量接收")
private String receiveType;
}
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the yifu4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.yifu.cloud.plus.v1.yifu.archives.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 项目自动化配置查询参数
*
* @author fxj
* @date 2025-05-18
*/
@Data
@Schema(description = "项目自动化配置查询参数")
public class ProjectAutoSetParam implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 项目编码列表
*/
@Schema(description = "项目编码列表")
private List<String> departNos;
/**
* 类型:0 档案 1 合同 2 商险 3 社保公积金 4 薪酬
*/
@Schema(description = "类型:0 档案 1 合同 2 商险 3 社保公积金 4 薪酬")
private String type;
}
......@@ -53,9 +53,9 @@ public class TAutoMainRelAddVo implements Serializable {
//社保规则明细表
private List<TAutoSocialRuleRel> socialRuleRels;
//社保规则主表
//公积金规则主表
private TAutoFundRuleInfo fundRuleInfo;
//社保规则明细表
//公积金规则明细表
private List<TAutoFundRuleRel> fundRuleRels;
}
......@@ -92,6 +92,28 @@ public class TAutoMainRelExportVo implements Serializable {
@Schema(description = "规则最新更新人")
private String ruleUpdatePerson;
/**
* 是否仅使用自动化入口
*/
@HeadFontStyle(fontHeightInPoints = 11)
@ExcelProperty("是否仅使用自动化入口")
@Schema(description = "是否仅使用自动化入口")
@ExcelAttribute(name = "是否仅使用自动化入口", readConverterExp = "0=是,1=否")
private String autoFlag;
// ==================== 非数据库字段(用于列表显示) ====================
/**
* 限制项显示(拼接后的服务项目名称,如"社保,公积金")
* 非数据库字段,查询时动态生成
*/
@TableField(exist = false)
@Schema(description = "限制项显示(拼接后的服务项目名称)")
private String restrictItemsDisplay;
// ==================== 自动化配置项显示字段 ====================
@HeadFontStyle(fontHeightInPoints = 11)
@ExcelProperty("自动化配置项")
@Schema(description = "自动化配置项列表(记录配置了哪些服务项目)")
private String autoConfigItemsDisplay;
}
\ No newline at end of file
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*/
package com.yifu.cloud.plus.v1.yifu.archives.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.ExcelAttribute;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.RowIndex;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 项目配置限制项批量导入VO
*/
@Data
@Schema(description = "项目配置限制项批量导入")
public class TAutoMainRelRestrictImportVo extends RowIndex {
@ExcelProperty("项目编码(必填)")
@Schema(description = "项目编码")
@ExcelAttribute(name = "项目编码", isNotEmpty = true, errorInfo = "项目编码不能为空", maxLength = 50)
private String deptNo;
@ExcelProperty("项目名称")
@Schema(description = "项目名称")
private String departName;
@ExcelProperty("是否限制(0限制/1不限制)")
@Schema(description = "是否限制:0-限制(仅自动化入口),1-不限制")
@ExcelAttribute(name = "是否限制",isNotEmpty = true, errorInfo = "是否限制不能为空", readConverterExp = "0=限制,1=不限制")
private String autoFlag;
@ExcelProperty("是否限制档案(0不限制/1限制)")
@Schema(description = "是否限制档案")
@ExcelAttribute(name = "是否限制档案", readConverterExp = "0=不限制,1=限制")
private String restrictArchive;
@ExcelProperty("是否限制商险(0不限制/1限制)")
@Schema(description = "是否限制商险")
@ExcelAttribute(name = "是否限制商险", readConverterExp = "0=不限制,1=限制")
private String restrictInsurance;
@ExcelProperty("是否限制合同(0不限制/1限制)")
@Schema(description = "是否限制合同")
@ExcelAttribute(name = "是否限制合同", readConverterExp = "0=不限制,1=限制")
private String restrictContract;
@ExcelProperty("是否限制社保公积金(0不限制/1限制)")
@Schema(description = "是否限制社保公积金")
@ExcelAttribute(name = "是否限制社保公积金", readConverterExp = "0=不限制,1=限制")
private String restrictSocialFund;
}
\ No newline at end of file
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*/
package com.yifu.cloud.plus.v1.yifu.archives.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* 项目配置限制项VO
* 用于单个限制接口新增和更新限制项
*/
@Data
@Schema(description = "项目配置限制项")
public class TAutoMainRelRestrictVo {
@NotBlank(message = "项目ID不能为空")
@Schema(description = "项目配置ID")
private String id;
/**
* 是否仅使用自动化入口(限制标志):0-限制(仅自动化入口),1-不限制
*/
@Schema(description = "是否仅使用自动化入口:0-限制(仅自动化入口),1-不限制")
private String autoFlag;
@Schema(description = "是否限制档案:0-不限制,1-限制")
private String restrictArchive;
@Schema(description = "是否限制商险:0-不限制,1-限制")
private String restrictInsurance;
@Schema(description = "是否限制合同:0-不限制,1-限制")
private String restrictContract;
@Schema(description = "是否限制社保公积金:0-不限制,1-限制")
private String restrictSocialFund;
}
\ No newline at end of file
......@@ -52,7 +52,21 @@ private int limitStart;
* @Author fxj
* 查询数据止
**/
@Schema(description = "查询limit 数据条数")
private int limitEnd;
@Schema(description = "查询limit 数据条数")
private int limitEnd;
/**
* 是否仅使用自动化入口(多选查询)
*/
@Schema(description = "是否仅使用自动化入口(多选查询)")
private java.util.List<String> autoFlagList;
// ==================== 限制项字段(多选查询) ====================
@Schema(description = "限制项(多选查询,如\"档案\"、\"商险\")")
private java.util.List<String> restrictItemsList;
// ==================== 自动化配置项字段(多选查询) ====================
@Schema(description = "自动化配置项(多选查询,如\"档案\"、\"商险\"、\"社保\"、\"公积金\")")
private java.util.List<String> autoConfigItemsList;
}
\ No newline at end of file
......@@ -581,4 +581,13 @@ public class TEmployeeContractPreVo extends RowIndex implements Serializable {
@Schema(description = "发薪日")
private String salaryDay;
@Schema(description = "劳务费可修改标识:0-可修改,1-不可修改")
private String laborFeeModifyFlag;
@Schema(description = "计时工资可修改标识:0-可修改,1-不可修改")
private String hourlyWageModifyFlag;
@Schema(description = "计件工资可修改标识:0-可修改,1-不可修改")
private String pieceWageModifyFlag;
}
......@@ -25,7 +25,11 @@ import com.yifu.cloud.plus.v1.yifu.archives.service.TAutoMainRelService;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TAutoMainRelAddVo;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TAutoMainRelDetailVo;
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;
......@@ -131,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;
}
/**
......@@ -190,12 +203,13 @@ public class TAutoMainRelController {
/**
* @Author fxj
* @Description 远程接口获取项目对应商险的自动化配置信息,有商险自动化且配置为启用的
* @param param 查询参数对象
* @Date 11:20 2025/9/17
**/
@Inner
@PostMapping("/inner/getProjectAutoSetMap")
public Map<String,String> getProjectAutoSetMap(@RequestBody List<String> departNos) {
return tAutoMainRelService.getProjectAutoSetMap(departNos);
public Map<String,String> getProjectAutoSetMap(@RequestBody ProjectAutoSetParam param) {
return tAutoMainRelService.getProjectAutoSetMap(param.getDepartNos(), param.getType());
}
/**
......@@ -223,4 +237,31 @@ public class TAutoMainRelController {
return tAutoMainRelService.getAutoDeptMap();
}
// ==================== 限制项相关接口 ====================
/**
* 单个更新限制项
* @param vo 限制项VO
* @return 更新结果
*/
@Operation(summary = "单个更新限制项", description = "更新单个项目配置的限制项")
@SysLog("单个更新限制项")
@PostMapping("/updateRestrict")
public R<Boolean> updateRestrict(@RequestBody TAutoMainRelRestrictVo vo) {
return tAutoMainRelService.updateRestrict(vo);
}
/**
* 批量更新限制项(通过上传限制项文件)
* @param file Excel文件
* @return 导入结果
*/
@SneakyThrows
@Operation(summary = "批量更新限制项", description = "上传Excel文件批量更新项目配置限制项")
@SysLog("批量更新限制项")
@PostMapping("/uploadRestrictConfig")
public R<List<ErrorMessage>> uploadRestrictConfig(@RequestParam("file") MultipartFile file) {
return tAutoMainRelService.uploadRestrictConfig(file.getInputStream());
}
}
......@@ -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);
}
/**
......
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the yifu4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.yifu.cloud.plus.v1.yifu.archives.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yifu.cloud.plus.v1.yifu.archives.entity.TAutoMainRelRefreshLog;
import org.apache.ibatis.annotations.Mapper;
/**
* 项目配置刷新日志表
*
* @author system
* @date 2026-05-19
*/
@Mapper
public interface TAutoMainRelRefreshLogMapper extends BaseMapper<TAutoMainRelRefreshLog> {
}
......@@ -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);
......
......@@ -22,10 +22,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yifu.cloud.plus.v1.yifu.archives.entity.TAutoContractScheme;
import com.yifu.cloud.plus.v1.yifu.archives.entity.TAutoMainRel;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TAutoMainRelAddVo;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TAutoMainRelDetailVo;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TAutoMainRelExportVo;
import com.yifu.cloud.plus.v1.yifu.archives.vo.TAutoMainRelSearchVo;
import com.yifu.cloud.plus.v1.yifu.archives.vo.*;
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.insurances.vo.AutoDeptVO;
......@@ -65,10 +62,44 @@ public interface TAutoMainRelService extends IService<TAutoMainRel> {
IPage<TAutoContractScheme> getContractSchemePage(Page<TAutoContractScheme> page, TAutoContractScheme search);
Map<String, String> getProjectAutoSetMap(List<String> departNos);
/**
* @Author fxj
* @Description 远程接口获取项目对应商险的自动化配置信息,有商险自动化且配置'是否仅使用自动化入口' 为是的需要强制限制
* @param type 0 档案 1 合同 2 商险 3 社保公积金 4 薪酬
* @Date 11:26 2025/9/17
**/
Map<String, String> getProjectAutoSetMap(List<String> departNos, String type);
// 获取全量自动化项目,value里是续保周期
AutoDeptVO getAutoDeptMap();
R<Boolean> updateAutoFlagById(String id, String autoFlag);
// ==================== 限制项相关方法 ====================
/**
* 单个更新限制项
* @param vo 限制项VO
* @return 更新结果
*/
R<Boolean> updateRestrict(TAutoMainRelRestrictVo vo);
/**
* 批量更新限制项(通过上传限制项文件)
* @param file Excel文件
* @return 导入结果(包含错误信息)
*/
R<List<ErrorMessage>> uploadRestrictConfig(InputStream file);
/**
* 自动计算自动化配置项
* 根据项目配置了哪些服务项目,设置5个自动化配置项字段值
* @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);
......
......@@ -20,6 +20,7 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ArrayUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
......@@ -31,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;
......@@ -39,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;
......@@ -47,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;
......@@ -121,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 = "同一项目岗位名称不可重复";
......@@ -421,6 +437,9 @@ public class TAutoMainRelServiceImpl extends ServiceImpl<TAutoMainRelMapper, TAu
return PARAM_IS_NOT_ERROR;
}
//自动计算自动化配置项(设置5个独立字段)- 根据TAutoMainRelAddVo中的属性设置
generateAutoConfigItems(entity, autoMainRel);
//新增主表
autoMainRel.setRuleUpdatePerson(user.getNickname());
autoMainRel.setRuleUpdateTime(DateUtil.getCurrentDateTime());
......@@ -1013,6 +1032,9 @@ public class TAutoMainRelServiceImpl extends ServiceImpl<TAutoMainRelMapper, TAu
}
}
//自动计算自动化配置项(设置5个独立字段)- 根据TAutoMainRelAddVo中的属性设置
generateAutoConfigItems(entity, autoMainRel);
// 更新主表
autoMainRel.setRuleUpdatePerson(user.getNickname());
autoMainRel.setRuleUpdateTime(DateUtil.getCurrentDateTime());
......@@ -1506,17 +1528,31 @@ private R<Boolean> checkItemRepeat(List<SysAutoDictItem> autoDictItems, Map<Stri
/**
* @Author fxj
* @Description 远程接口获取项目对应商险的自动化配置信息,有商险自动化且配置'是否仅使用自动化入口' 为是的需要强制限制
* @param type 0 档案 1 合同 2 商险 3 社保公积金 4 薪酬
* @Date 11:26 2025/9/17
**/
@Override
public Map<String, String> getProjectAutoSetMap(List<String> departNos) {
public Map<String, String> getProjectAutoSetMap(List<String> departNos,String type) {
Map<String,String> map = new HashMap<>();
//如果配置了'是否仅使用自动化入口' 为是的需要强制限制
List<TAutoMainRel> list = baseMapper.selectList(Wrappers.<TAutoMainRel>query().lambda());
if(Common.isNotNull(list)){
List<TAutoMainRel> list = baseMapper.selectList(Wrappers.<TAutoMainRel>query().lambda()
.in(TAutoMainRel::getDeptNo,departNos));
if(Common.isNotNull(list) && Common.isNotNull(type)){
for(TAutoMainRel vo :list){
if(CommonConstants.ZERO_STRING.equals(vo.getAutoFlag())){
if(type.equals(CommonConstants.TWO_STRING)
&& CommonConstants.ONE_STRING.equals(vo.getRestrictInsurance())){
map.put(vo.getDeptNo(),vo.getDeptNo());
}else if (type.equals(CommonConstants.ONE_STRING)
&& CommonConstants.ONE_STRING.equals(vo.getRestrictContract())){
map.put(vo.getDeptNo(),vo.getDeptNo());
} else if (type.equals(CommonConstants.THREE_STRING)
&& CommonConstants.ONE_STRING.equals(vo.getRestrictSocialFund())){
map.put(vo.getDeptNo(),vo.getDeptNo());
} else if (type.equals(CommonConstants.ZERO_STRING)
&& CommonConstants.ONE_STRING.equals(vo.getRestrictArchive())){
map.put(vo.getDeptNo(),vo.getDeptNo());
}
}
}
}
......@@ -1752,4 +1788,488 @@ private R<Boolean> checkItemRepeat(List<SysAutoDictItem> autoDictItems, Map<Stri
}
return R.failed();
}
// ==================== 限制项相关方法 ====================
/**
* 单个更新限制项
* @param vo 限制项VO
* @return 更新结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public R<Boolean> updateRestrict(TAutoMainRelRestrictVo vo) {
YifuUser user = SecurityUtils.getUser();
if (Common.isEmpty(user)) {
return R.failed(CommonConstants.USER_FAIL);
}
// 参数校验
if (Common.isEmpty(vo) || Common.isEmpty(vo.getId()) || Common.isEmpty(vo.getAutoFlag())) {
return R.failed(CommonConstants.PARAM_IS_NOT_ERROR);
}
TAutoMainRel entity = baseMapper.selectById(vo.getId());
if (Common.isEmpty(entity)) {
return R.failed(CommonConstants.PARAM_INFO_ERROR);
}
// 保存旧数据用于日志记录
TAutoMainRel oldEntity = new TAutoMainRel();
BeanUtils.copyProperties(entity, oldEntity);
boolean hasChange = false;
// 获取当前要设置的值(使用VO中的值,如果为null则使用实体当前值)
String newAutoFlag = vo.getAutoFlag();
String newRestrictArchive = vo.getRestrictArchive();
String newRestrictInsurance = vo.getRestrictInsurance();
String newRestrictContract = vo.getRestrictContract();
String newRestrictSocialFund = vo.getRestrictSocialFund();
// 业务规则:如果是否限制为"是"(0),各限制分项不能为空,且至少有一项为限制(1)
if (CommonConstants.ZERO_STRING.equals(newAutoFlag)) {
// 限制分项不能为空校验
if (Common.isEmpty(newRestrictArchive)) {
return R.failed("是否限制为是时,限制档案不能为空");
}
if (Common.isEmpty(newRestrictInsurance)) {
return R.failed("是否限制为是时,限制商险不能为空");
}
if (Common.isEmpty(newRestrictContract)) {
return R.failed("是否限制为是时,限制合同不能为空");
}
if (Common.isEmpty(newRestrictSocialFund)) {
return R.failed("是否限制为是时,限制社保公积金不能为空");
}
// 限制项至少有一项为限制(1)
if (!CommonConstants.ONE_STRING.equals(newRestrictArchive)
&& !CommonConstants.ONE_STRING.equals(newRestrictInsurance)
&& !CommonConstants.ONE_STRING.equals(newRestrictContract)
&& !CommonConstants.ONE_STRING.equals(newRestrictSocialFund)) {
return R.failed("是否限制为是时,限制项至少要有一项为限制");
}
}
// 业务规则:如果是否限制为"否"(1),所有限制项自动设为不限制(0)
if (CommonConstants.ONE_STRING.equals(newAutoFlag)) {
newRestrictArchive = CommonConstants.ZERO_STRING;
newRestrictInsurance = CommonConstants.ZERO_STRING;
newRestrictContract = CommonConstants.ZERO_STRING;
newRestrictSocialFund = CommonConstants.ZERO_STRING;
}
// 更新是否仅使用自动化入口字段
if (!newAutoFlag.equals(entity.getAutoFlag())) {
entity.setAutoFlag(newAutoFlag);
hasChange = true;
}
// 更新限制档案字段
if (!newRestrictArchive.equals(entity.getRestrictArchive())) {
entity.setRestrictArchive(newRestrictArchive);
hasChange = true;
}
// 更新限制商险字段
if (!newRestrictInsurance.equals(entity.getRestrictInsurance())) {
entity.setRestrictInsurance(newRestrictInsurance);
hasChange = true;
}
// 更新限制合同字段
if (!newRestrictContract.equals(entity.getRestrictContract())) {
entity.setRestrictContract(newRestrictContract);
hasChange = true;
}
// 更新限制社保公积金字段
if (!newRestrictSocialFund.equals(entity.getRestrictSocialFund())) {
entity.setRestrictSocialFund(newRestrictSocialFund);
hasChange = true;
}
if (hasChange) {
entity.setUpdateBy(user.getId());
entity.setRuleUpdatePerson(user.getNickname());
entity.setRuleUpdateTime(DateUtil.getCurrentDateTime());
baseMapper.updateById(entity);
// 记录变更日志 - 整合所有限制项到 autoMailRel
Map<String,String> diffKeyMap = new HashMap<>();
Map<String,Object> oldMap = new HashMap<>();
Map<String,Object> newMap = new HashMap<>();
// 收集所有变化的字段名
List<String> changedFields = new ArrayList<>();
if (!oldEntity.getAutoFlag().equals(entity.getAutoFlag())) {
changedFields.add("autoFlag");
}
if (!oldEntity.getRestrictArchive().equals(entity.getRestrictArchive())) {
changedFields.add("restrictArchive");
}
if (!oldEntity.getRestrictInsurance().equals(entity.getRestrictInsurance())) {
changedFields.add("restrictInsurance");
}
if (!oldEntity.getRestrictContract().equals(entity.getRestrictContract())) {
changedFields.add("restrictContract");
}
if (!oldEntity.getRestrictSocialFund().equals(entity.getRestrictSocialFund())) {
changedFields.add("restrictSocialFund");
}
// 将变化的字段名用逗号分隔
if (!changedFields.isEmpty()) {
diffKeyMap.put("autoMailRel", String.join(",", changedFields));
oldMap.put("oldAutoMailRel", oldEntity);
newMap.put("newAutoMailRel", entity);
insertLog(entity, diffKeyMap, oldMap, newMap);
}
log.info("更新限制项, 项目配置ID: {}, 用户: {}", vo.getId(), user.getNickname());
}
return R.ok(true, CommonConstants.UPDATE_SUCCESS);
}
/**
* 批量更新限制项(通过上传限制项文件)
*/
@Override
@Transactional(rollbackFor = Exception.class)
public R<List<ErrorMessage>> uploadRestrictConfig(InputStream inputStream) {
YifuUser user = SecurityUtils.getUser();
if (Common.isEmpty(user)) {
return R.failed(CommonConstants.USER_FAIL);
}
List<ErrorMessage> errorMessageList = new ArrayList<>();
List<TAutoMainRelRestrictImportVo> excelVOList = new ArrayList<>();
try {
EasyExcel.read(inputStream, TAutoMainRelRestrictImportVo.class,
new com.alibaba.excel.event.AnalysisEventListener<TAutoMainRelRestrictImportVo>() {
@Override
public void invoke(TAutoMainRelRestrictImportVo data, AnalysisContext context) {
data.setRowIndex(context.readRowHolder().getRowIndex() + 1);
excelVOList.add(data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
}
}).sheet().doRead();
ExcelUtil<TAutoMainRelRestrictImportVo> excelUtil = new ExcelUtil<>(TAutoMainRelRestrictImportVo.class);
// 用于记录已处理过的项目编码,检测重复
Set<String> processedDeptNos = new HashSet<>();
for (TAutoMainRelRestrictImportVo excel : excelVOList) {
int rowNum = excel.getRowIndex();
ErrorMessage errorMessage = excelUtil.checkEntity(excel, rowNum);
if (Common.isNotNull(errorMessage)) {
errorMessageList.add(errorMessage);
continue;
}
// 校验重复项目编码:第一个更新成功,其他提示已重复
String deptNo = excel.getDeptNo();
if (processedDeptNos.contains(deptNo)) {
errorMessageList.add(new ErrorMessage(rowNum, "项目编码重复: " + deptNo,excel));
continue;
}
processedDeptNos.add(deptNo);
try {
importRestrictConfig(excel, user, errorMessageList);
} catch (Exception e) {
log.error("处理第{}行数据失败", rowNum, e);
errorMessageList.add(new ErrorMessage(rowNum, "处理失败: " + e.getMessage(),excel));
}
}
} catch (Exception e) {
log.error("读取Excel文件失败", e);
return R.failed("读取Excel文件失败: " + e.getMessage());
}
if (errorMessageList.isEmpty()) {
return R.ok();
}
// 按行号正序排序
errorMessageList.sort(Comparator.comparingInt(ErrorMessage::getLineNum));
return R.ok(errorMessageList);
}
/**
* 导入单条限制项
*/
private void importRestrictConfig(TAutoMainRelRestrictImportVo excel, YifuUser user,
List<ErrorMessage> errorMessageList) {
TAutoMainRel entity = baseMapper.selectOne(Wrappers.<TAutoMainRel>query()
.lambda().eq(TAutoMainRel::getDeptNo, excel.getDeptNo())
.last(CommonConstants.LAST_ONE_SQL));
if (Common.isEmpty(entity)) {
errorMessageList.add(new ErrorMessage(excel.getRowIndex(),
"项目编码不存在: " + 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();
String newRestrictInsurance = excel.getRestrictInsurance();
String newRestrictContract = excel.getRestrictContract();
String newRestrictSocialFund = excel.getRestrictSocialFund();
// 业务规则:如果是否限制为"是"(0),各限制分项不能为空,且至少有一项为限制(1)
if (CommonConstants.ZERO_STRING.equals(newAutoFlag)) {
// 限制分项不能为空校验
if (Common.isEmpty(newRestrictArchive)) {
errorMessageList.add(new ErrorMessage(excel.getRowIndex(),
"是否限制为是时,限制档案不能为空",excel));
return;
}
if (Common.isEmpty(newRestrictInsurance)) {
errorMessageList.add(new ErrorMessage(excel.getRowIndex(),
"是否限制为是时,限制商险不能为空",excel));
return;
}
if (Common.isEmpty(newRestrictContract)) {
errorMessageList.add(new ErrorMessage(excel.getRowIndex(),
"是否限制为是时,限制合同不能为空",excel));
return;
}
if (Common.isEmpty(newRestrictSocialFund)) {
errorMessageList.add(new ErrorMessage(excel.getRowIndex(),
"是否限制为是时,限制社保公积金不能为空",excel));
return;
}
// 限制项至少有一项为限制(1)
if (!CommonConstants.ONE_STRING.equals(newRestrictArchive)
&& !CommonConstants.ONE_STRING.equals(newRestrictInsurance)
&& !CommonConstants.ONE_STRING.equals(newRestrictContract)
&& !CommonConstants.ONE_STRING.equals(newRestrictSocialFund)) {
errorMessageList.add(new ErrorMessage(excel.getRowIndex(),
"是否限制为是时,限制项至少要有一项为限制",excel));
return;
}
}
// 业务规则:如果是否限制为"否"(1),所有限制项自动设为不限制(0)
if (CommonConstants.ONE_STRING.equals(newAutoFlag)) {
newRestrictArchive = CommonConstants.ZERO_STRING;
newRestrictInsurance = CommonConstants.ZERO_STRING;
newRestrictContract = CommonConstants.ZERO_STRING;
newRestrictSocialFund = CommonConstants.ZERO_STRING;
}
boolean hasChange = false;
// 更新是否限制字段
if (!newAutoFlag.equals(entity.getAutoFlag())) {
entity.setAutoFlag(newAutoFlag);
hasChange = true;
}
// 更新限制档案字段
if (!newRestrictArchive.equals(entity.getRestrictArchive())) {
entity.setRestrictArchive(newRestrictArchive);
hasChange = true;
}
// 更新限制商险字段
if (!newRestrictInsurance.equals(entity.getRestrictInsurance())) {
entity.setRestrictInsurance(newRestrictInsurance);
hasChange = true;
}
// 更新限制合同字段
if (!newRestrictContract.equals(entity.getRestrictContract())) {
entity.setRestrictContract(newRestrictContract);
hasChange = true;
}
// 更新限制社保公积金字段
if (!newRestrictSocialFund.equals(entity.getRestrictSocialFund())) {
entity.setRestrictSocialFund(newRestrictSocialFund);
hasChange = true;
}
if (hasChange) {
entity.setUpdateBy(user.getId());
entity.setRuleUpdatePerson(user.getNickname());
entity.setRuleUpdateTime(DateUtil.getCurrentDateTime());
baseMapper.updateById(entity);
// 记录变更日志 - 整合所有限制项到 autoMailRel
Map<String,String> diffKeyMap = new HashMap<>();
Map<String,Object> oldMap = new HashMap<>();
Map<String,Object> newMap = new HashMap<>();
// 收集所有变化的字段名
List<String> changedFields = new ArrayList<>();
if (!oldEntity.getAutoFlag().equals(entity.getAutoFlag())) {
changedFields.add("autoFlag");
}
if (!oldEntity.getRestrictArchive().equals(entity.getRestrictArchive())) {
changedFields.add("restrictArchive");
}
if (!oldEntity.getRestrictInsurance().equals(entity.getRestrictInsurance())) {
changedFields.add("restrictInsurance");
}
if (!oldEntity.getRestrictContract().equals(entity.getRestrictContract())) {
changedFields.add("restrictContract");
}
if (!oldEntity.getRestrictSocialFund().equals(entity.getRestrictSocialFund())) {
changedFields.add("restrictSocialFund");
}
// 将变化的字段名用逗号分隔
if (!changedFields.isEmpty()) {
diffKeyMap.put("autoMailRel", String.join(",", changedFields));
oldMap.put("oldAutoMailRel", oldEntity);
newMap.put("newAutoMailRel", entity);
insertLog(entity, diffKeyMap, oldMap, newMap);
}
log.info("更新限制项, 项目编码: {}, 用户: {}", excel.getDeptNo(), user.getNickname());
}
}
/**
* 自动计算自动化配置项(旧版本,兼容原有调用)
* 根据项目配置了哪些服务项目,设置5个自动化配置项字段值
*/
@Override
public void generateAutoConfigItems(TAutoMainRel entity) {
entity.setAutoConfigArchive(entity.getRestrictArchive());
entity.setAutoConfigContract(entity.getRestrictContract());
entity.setAutoConfigInsurance(entity.getRestrictInsurance());
if (CommonConstants.ONE_STRING.equals(entity.getRestrictSocialFund())) {
entity.setAutoConfigSocial(CommonConstants.ONE_STRING);
entity.setAutoConfigFund(CommonConstants.ONE_STRING);
} else {
entity.setAutoConfigSocial(CommonConstants.ZERO_STRING);
entity.setAutoConfigFund(CommonConstants.ZERO_STRING);
}
}
/**
* 自动计算自动化配置项(新版本)
* 根据TAutoMainRelAddVo中的属性设置自动化配置项:只有属性对应有值,是否配置就是1-是,否则就是0-否
* @param addVo 项目配置新增/更新VO
* @param entity 项目配置实体
*/
public void generateAutoConfigItems(TAutoMainRelAddVo addVo, TAutoMainRel entity) {
// 档案管理规则配置
entity.setAutoConfigArchive(Common.isNotNull(addVo.getAutoEmpRuleInfo()) ? CommonConstants.ONE_STRING : CommonConstants.ZERO_STRING);
// 商险规则配置
entity.setAutoConfigInsurance(Common.isNotNull(addVo.getAutoInsurRuleInfo()) ? CommonConstants.ONE_STRING : CommonConstants.ZERO_STRING);
// 员工合同签订规则配置
entity.setAutoConfigContract(Common.isNotNull(addVo.getContractRuleInfo()) ? CommonConstants.ONE_STRING : CommonConstants.ZERO_STRING);
// 社保规则配置
entity.setAutoConfigSocial(Common.isNotNull(addVo.getSocialRuleInfo()) ? CommonConstants.ONE_STRING : CommonConstants.ZERO_STRING);
// 公积金规则配置
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);
logId = UUID.randomUUID().toString().replace("-", "");
saveRefreshLog(logId, tAutoMainRel, "ERROR", resultMsg, duration);
} else {
resultMsg = "合同和商险续签刷新成功";
logId = UUID.randomUUID().toString().replace("-", "");
saveRefreshLog(logId, tAutoMainRel, "SUCCESS", resultMsg, duration);
}
// ========== 4. 超时告警 ==========
if (duration > 30000) { // 超过30秒
log.warn("项目配置刷新耗时过长,项目编码: {}, 耗时: {}ms", deptNo, duration);
}
} catch (Exception e) {
long duration = System.currentTimeMillis() - startTime;
logId = UUID.randomUUID().toString().replace("-", "");
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
}
}
}
// 如果项目编码不为空 删除对应项目的提醒数据 否则全部删除
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();
return R.ok();
//更新自动化的所有的合同办理状态--这里如果项目编码不为空要传参
baseMapper.updateProcessStatus(deptNo);
return R.ok(true);
}
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);
......
......@@ -48,6 +48,7 @@ import com.yifu.cloud.plus.v1.yifu.common.core.vo.BaseSearchVO;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.BaseServiceParamListVO;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser;
import com.yifu.cloud.plus.v1.yifu.common.dapr.config.DaprSocialProperties;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.ArchivesDaprUtil;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.CspDaprUtils;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.HttpDaprUtil;
import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
......@@ -76,6 +77,7 @@ import java.math.RoundingMode;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Arrays;
import java.util.*;
/**
......@@ -126,6 +128,18 @@ public class TEmployeeContractInfoServiceImpl extends ServiceImpl<TEmployeeContr
private final CspDaprUtils cspDaprUtil;
private final TAutoMainRelService tAutoMainRelService;
/**
* @Description: 检测是否有某个角色权限(超管放行)
* @Author: AI Assistant
* @Date: 2026/5/19
* @return: boolean
**/
private boolean isSuperAdmin(YifuUser user) {
// 使用工具类方法进行超管判断
return SecurityUtils.isSuperAdmin(user);
}
/**
* 员工合同信息表简单分页查询
*
......@@ -168,6 +182,25 @@ public class TEmployeeContractInfoServiceImpl extends ServiceImpl<TEmployeeContr
if (Common.isEmpty(tEmployeeContractInfo.getEmpId()) || Common.isEmpty(tEmployeeContractInfo.getSettleDomain())) {
return R.failed(EmployeeConstants.EMPID_NOT_EMPTY);
}
YifuUser user = SecurityUtils.getUser();
if (user == null || Common.isEmpty(user.getId())) {
return R.failed(CommonConstants.USER_FAIL);
}
TSettleDomain domain = tSettleDomainService.getById(tEmployeeContractInfo.getSettleDomain());
if (Common.isNotNull(user) && !CommonConstants.ZERO_STRING.equals(user.getSystemFlag()) && null != domain) {
// 超管放行,不进行自动化限制检查
if (!isSuperAdmin(user)) {
String deptNo = domain.getDepartNo();
if (Common.isNotNull(deptNo)) {
Map<String, String> res = tAutoMainRelService.getProjectAutoSetMap(Arrays.asList(deptNo), CommonConstants.ONE_STRING);
if (Common.isNotNull(res) && res.containsKey(deptNo)) {
return R.failed("该项目已纳入自动化,请至作业自动化模块操作");
}
}
}
}
return this.setBaseInfo(tEmployeeContractInfo, null);
} catch (Exception e) {
log.error("员工合同保存异常:" + e.getMessage());
......@@ -1373,6 +1406,10 @@ public class TEmployeeContractInfoServiceImpl extends ServiceImpl<TEmployeeContr
public R<List<ErrorMessage>> batchImport(InputStream inputStream) {
List<ErrorMessage> errorMessageList = new ArrayList<>();
ExcelUtil<EmployeeContractVO> util1 = new ExcelUtil<>(EmployeeContractVO.class);
YifuUser user = SecurityUtils.getUser();
if (user == null || Common.isEmpty(user.getId())) {
return R.failed(CommonConstants.USER_FAIL);
}
// 写法2:
// 匿名内部类 不用额外写一个DemoDataListener
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
......@@ -1387,6 +1424,10 @@ public class TEmployeeContractInfoServiceImpl extends ServiceImpl<TEmployeeContr
*临时存储
*/
private List<EmployeeContractVO> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
/**
* 项目编码自动化校验缓存,key: deptNo, value: true-已纳入自动化, false-未纳入
*/
private Map<String, Boolean> autoCheckCache = new HashMap<>();
@Override
public void invoke(EmployeeContractVO data, AnalysisContext context) {
......@@ -1397,6 +1438,31 @@ public class TEmployeeContractInfoServiceImpl extends ServiceImpl<TEmployeeContr
if (Common.isNotNull(errorMessage)) {
errorMessageList.add(errorMessage);
} else {
// 导入时的自动化校验
String deptNo = data.getDeptNo();
if (Common.isNotNull(deptNo) && !isSuperAdmin(user)) {
// 先从缓存中获取
Boolean isAuto = autoCheckCache.get(deptNo);
if (isAuto == null) {
// 缓存中没有,查询数据库
TSettleDomain domain = tSettleDomainService.getOne(Wrappers.<TSettleDomain>query().lambda()
.eq(TSettleDomain::getDepartNo, deptNo)
.eq(TSettleDomain::getDeleteFlag, CommonConstants.ZERO_STRING)
.eq(TSettleDomain::getStopFlag, CommonConstants.ZERO_STRING));
if (Common.isNotNull(domain)) {
Map<String, String> res = tAutoMainRelService.getProjectAutoSetMap(Arrays.asList(deptNo), CommonConstants.ONE_STRING);
isAuto = Common.isNotNull(res) && res.containsKey(deptNo);
} else {
isAuto = false;
}
autoCheckCache.put(deptNo, isAuto);
}
if (isAuto) {
errorMessageList.add(new ErrorMessage(data.getRowIndex(), "该项目已纳入自动化,请至作业自动化模块操作"));
return;
}
}
cachedDataList.add(data);
}
if (cachedDataList.size() >= BATCH_COUNT) {
......
......@@ -801,7 +801,7 @@ public class TEmployeeContractPreServiceImpl extends ServiceImpl<TEmployeeContra
@Override
public Boolean checkContractPreIsExit(EmpProjectStatusVo vo) {
TEmployeeContractPre contractPre = baseMapper.selectOne(Wrappers.<TEmployeeContractPre>query().lambda()
/*TEmployeeContractPre contractPre = baseMapper.selectOne(Wrappers.<TEmployeeContractPre>query().lambda()
.eq(TEmployeeContractPre::getEmpIdcard, vo.getEmpIdcard())
.eq(TEmployeeContractPre::getDeptNo, vo.getDeptNo())
.ne(TEmployeeContractPre::getProcessStatus, CommonConstants.TEN_STRING)
......@@ -823,16 +823,16 @@ public class TEmployeeContractPreServiceImpl extends ServiceImpl<TEmployeeContra
}
} else {
return false;
}
}*/
// 新逻辑 v1.7.23 按身份证+项目查询合同:如果找到审核通过的可用的合同就不允许进入。
/*TEmployeeContractInfo contractInfo = contractInfoService.getOne(Wrappers.<TEmployeeContractInfo>query()
TEmployeeContractInfo contractInfo = contractInfoService.getOne(Wrappers.<TEmployeeContractInfo>query()
.lambda().eq(TEmployeeContractInfo::getEmpIdcard, vo.getEmpIdcard())
.eq(TEmployeeContractInfo::getDeptNo,vo.getDeptNo())
.eq(TEmployeeContractInfo::getAuditStatus,CommonConstants.TWO_STRING)
.eq(TEmployeeContractInfo::getDeleteFlag, CommonConstants.ZERO_INT)
.eq(TEmployeeContractInfo::getInUse, CommonConstants.ZERO_STRING)
.last(CommonConstants.LAST_ONE_SQL));
return Common.isNotNull(contractInfo);*/
return Common.isNotNull(contractInfo);
}
//发送企业微信待办
......
......@@ -179,6 +179,10 @@ public class TEmployeePreLogServiceImpl extends ServiceImpl<TEmployeePreLogMappe
IGNORE_FIELD.add("isLeave");
IGNORE_FIELD.add("isRefuse");
IGNORE_FIELD.add("configId");
// 接收终端和接收方式
IGNORE_FIELD.add("receiveTerminal");
IGNORE_FIELD.add("receiveType");
}
private static final List<String> PRE_IGNORE_FIELD = new ArrayList<>();
......@@ -226,6 +230,10 @@ public class TEmployeePreLogServiceImpl extends ServiceImpl<TEmployeePreLogMappe
CONTRACT_IGNORE_FIELD.add("isLeave");
CONTRACT_IGNORE_FIELD.add("isRefuse");
CONTRACT_IGNORE_FIELD.add("configId");
// 工资可修改标识
CONTRACT_IGNORE_FIELD.add("laborFeeModifyFlag");
CONTRACT_IGNORE_FIELD.add("hourlyWageModifyFlag");
CONTRACT_IGNORE_FIELD.add("pieceWageModifyFlag");
}
private static final List<String> SOCIAL_IGNORE_FIELD = new ArrayList<>();
......
......@@ -36,6 +36,17 @@
<result property="updateTime" column="UPDATE_TIME"/>
<result property="postFlag" column="POST_FLAG"/>
<result property="autoFlag" column="AUTO_FLAG"/>
<result property="restrictArchive" column="RESTRICT_ARCHIVE"/>
<result property="restrictInsurance" column="RESTRICT_INSURANCE"/>
<result property="restrictContract" column="RESTRICT_CONTRACT"/>
<result property="restrictSocialFund" column="RESTRICT_SOCIAL_FUND"/>
<result property="autoConfigArchive" column="AUTO_CONFIG_ARCHIVE"/>
<result property="autoConfigContract" column="AUTO_CONFIG_CONTRACT"/>
<result property="autoConfigInsurance" column="AUTO_CONFIG_INSURANCE"/>
<result property="autoConfigSocial" column="AUTO_CONFIG_SOCIAL"/>
<result property="autoConfigFund" column="AUTO_CONFIG_FUND"/>
<result property="restrictItemsDisplay" column="RESTRICT_ITEMS_DISPLAY"/>
<result property="autoConfigItemsDisplay" column="AUTO_CONFIG_ITEMS_DISPLAY"/>
</resultMap>
<sql id="Base_Column_List">
a.ID,
......@@ -87,6 +98,35 @@
<if test="tAutoMainRel.authSql != null and tAutoMainRel.authSql.trim() != ''">
${tAutoMainRel.authSql}
</if>
<!-- 限制项多选查询(含其中一项就匹配) -->
<if test="tAutoMainRel.restrictItemsList != null and tAutoMainRel.restrictItemsList.size() > 0">
AND (
<foreach collection="tAutoMainRel.restrictItemsList" item="item" separator=" OR ">
<choose>
<when test="item == '档案'">a.RESTRICT_ARCHIVE = '1'</when>
<when test="item == '商险'">a.RESTRICT_INSURANCE = '1'</when>
<when test="item == '合同'">a.RESTRICT_CONTRACT = '1'</when>
<when test="item == '社保公积金'">a.RESTRICT_SOCIAL_FUND = '1'</when>
</choose>
</foreach>
)
</if>
<!-- 自动化配置项多选查询(含其中一项就匹配) -->
<if test="tAutoMainRel.autoConfigItemsList != null and tAutoMainRel.autoConfigItemsList.size() > 0">
AND (
<foreach collection="tAutoMainRel.autoConfigItemsList" item="item" separator=" OR ">
<choose>
<when test="item == '档案'">a.AUTO_CONFIG_ARCHIVE = '1'</when>
<when test="item == '合同'">a.AUTO_CONFIG_CONTRACT = '1'</when>
<when test="item == '商险'">a.AUTO_CONFIG_INSURANCE = '1'</when>
<when test="item == '社保'">a.AUTO_CONFIG_SOCIAL = '1'</when>
<when test="item == '公积金'">a.AUTO_CONFIG_FUND = '1'</when>
</choose>
</foreach>
)
</if>
</if>
</sql>
<!--tAutoMainRel简单分页查询-->
......@@ -100,9 +140,47 @@
a.CREATE_NAME,
a.CREATE_TIME,
a.UPDATE_BY,
a.UPDATE_TIME,a.post_flag
,b.DEPART_NAME,IFNULL(b.cs_name,'') csUserName,b.DEPART_NO dept_NO,IF(b.STOP_FLAG='0','是','否') STOP_FLAG
,a.AUTO_FLAG
a.UPDATE_TIME,
a.post_flag,
a.AUTO_FLAG,
a.RESTRICT_ARCHIVE,
a.RESTRICT_INSURANCE,
a.RESTRICT_CONTRACT,
a.RESTRICT_SOCIAL_FUND,
a.AUTO_CONFIG_ARCHIVE,
a.AUTO_CONFIG_CONTRACT,
a.AUTO_CONFIG_INSURANCE,
a.AUTO_CONFIG_SOCIAL,
a.AUTO_CONFIG_FUND,
-- 限制项显示字段
CASE
WHEN a.RESTRICT_ARCHIVE = '1' OR a.RESTRICT_INSURANCE = '1' OR
a.RESTRICT_CONTRACT = '1' OR a.RESTRICT_SOCIAL_FUND = '1'
THEN CONCAT_WS(',',
CASE WHEN a.RESTRICT_ARCHIVE = '1' THEN '档案' ELSE NULL END,
CASE WHEN a.RESTRICT_INSURANCE = '1' THEN '商险' ELSE NULL END,
CASE WHEN a.RESTRICT_CONTRACT = '1' THEN '合同' ELSE NULL END,
CASE WHEN a.RESTRICT_SOCIAL_FUND = '1' THEN '社保公积金' ELSE NULL END
)
ELSE NULL
END as RESTRICT_ITEMS_DISPLAY,
-- 自动化配置项显示字段
CASE
WHEN a.AUTO_CONFIG_ARCHIVE = '1' OR a.AUTO_CONFIG_CONTRACT = '1' OR
a.AUTO_CONFIG_INSURANCE = '1' OR a.AUTO_CONFIG_SOCIAL = '1' OR a.AUTO_CONFIG_FUND = '1'
THEN CONCAT_WS('、',
CASE WHEN a.AUTO_CONFIG_ARCHIVE = '1' THEN '档案' ELSE NULL END,
CASE WHEN a.AUTO_CONFIG_CONTRACT = '1' THEN '合同' ELSE NULL END,
CASE WHEN a.AUTO_CONFIG_INSURANCE = '1' THEN '商险' ELSE NULL END,
CASE WHEN a.AUTO_CONFIG_SOCIAL = '1' THEN '社保' ELSE NULL END,
CASE WHEN a.AUTO_CONFIG_FUND = '1' THEN '公积金' ELSE NULL END
)
ELSE NULL
END as AUTO_CONFIG_ITEMS_DISPLAY,
b.DEPART_NAME,
IFNULL(b.cs_name,'') csUserName,
b.DEPART_NO dept_NO,
IF(b.STOP_FLAG='0','是','否') STOP_FLAG
FROM t_auto_main_rel a
left join t_settle_domain b on a.DEPT_ID = b.id
<where>
......@@ -114,6 +192,13 @@
<if test="tAutoMainRel.csUserName != null and tAutoMainRel.csUserName.trim() != ''">
AND b.cs_name like concat('%',#{tAutoMainRel.csUserName} ,'%')
</if>
<!-- 是否仅使用自动化入口(多选) -->
<if test="tAutoMainRel.autoFlagList != null and tAutoMainRel.autoFlagList.size() > 0">
AND a.AUTO_FLAG IN
<foreach collection="tAutoMainRel.autoFlagList" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</if>
</if>
<include refid="tAutoMainRel_where"/>
order by a.CREATE_TIME desc
......@@ -163,7 +248,37 @@
b.DEPART_NAME,
IFNULL(b.cs_name,'') csUserName,
b.DEPART_NO dept_NO,
IF(b.STOP_FLAG='0','是','否') STOP_FLAG
IF(b.STOP_FLAG='0','是','否') STOP_FLAG,
a.AUTO_FLAG,
a.RESTRICT_ARCHIVE,
a.RESTRICT_INSURANCE,
a.RESTRICT_CONTRACT,
a.RESTRICT_SOCIAL_FUND,
-- 限制项显示(拼接服务项目名称)
CASE
WHEN a.RESTRICT_ARCHIVE = '1' OR a.RESTRICT_CONTRACT = '1' OR
a.RESTRICT_INSURANCE = '1' OR a.RESTRICT_SOCIAL_FUND = '1'
THEN CONCAT_WS('、',
CASE WHEN a.RESTRICT_ARCHIVE = '1' THEN '档案' ELSE NULL END,
CASE WHEN a.RESTRICT_CONTRACT = '1' THEN '合同' ELSE NULL END,
CASE WHEN a.RESTRICT_INSURANCE = '1' THEN '商险' ELSE NULL END,
CASE WHEN a.RESTRICT_SOCIAL_FUND = '1' THEN '社保公积金' ELSE NULL END
)
ELSE NULL
END as RESTRICT_ITEMS_DISPLAY,
-- 自动化配置项显示(拼接服务项目名称)
CASE
WHEN a.AUTO_CONFIG_ARCHIVE = '1' OR a.AUTO_CONFIG_CONTRACT = '1' OR
a.AUTO_CONFIG_INSURANCE = '1' OR a.AUTO_CONFIG_SOCIAL = '1' OR a.AUTO_CONFIG_FUND = '1'
THEN CONCAT_WS('、',
CASE WHEN a.AUTO_CONFIG_ARCHIVE = '1' THEN '档案' ELSE NULL END,
CASE WHEN a.AUTO_CONFIG_CONTRACT = '1' THEN '合同' ELSE NULL END,
CASE WHEN a.AUTO_CONFIG_INSURANCE = '1' THEN '商险' ELSE NULL END,
CASE WHEN a.AUTO_CONFIG_SOCIAL = '1' THEN '社保' ELSE NULL END,
CASE WHEN a.AUTO_CONFIG_FUND = '1' THEN '公积金' ELSE NULL END
)
ELSE NULL
END as AUTO_CONFIG_ITEMS_DISPLAY
FROM t_auto_main_rel a
left join t_settle_domain b on a.DEPT_ID = b.id
<where>
......
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Copyright (c) 2018-2025, lengleng All rights reserved.
~
~ Redistribution and use in source and binary forms, with or without
~ modification, are permitted provided that the following conditions are met:
~
~ Redistributions of source code must retain the above copyright notice,
~ this list of conditions and the following disclaimer.
~ Redistributions in binary form must reproduce the above copyright
~ notice, this list of conditions and the following disclaimer in the
~ documentation and/or other materials provided with the distribution.
~ Neither the name of the yifu4cloud.com developer nor the names of its
~ contributors may be used to endorse or promote products derived from
~ this software without specific prior written permission.
~ Author: lengleng (wangiegie@gmail.com)
~
-->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yifu.cloud.plus.v1.yifu.archives.mapper.TAutoMainRelRefreshLogMapper">
<resultMap id="tAutoMainRelRefreshLogMap" type="com.yifu.cloud.plus.v1.yifu.archives.entity.TAutoMainRelRefreshLog">
<id property="id" column="ID"/>
<result property="configId" column="CONFIG_ID"/>
<result property="deptNo" column="DEPT_NO"/>
<result property="status" column="STATUS"/>
<result property="result" column="RESULT"/>
<result property="duration" column="DURATION"/>
<!-- BaseEntity 字段 -->
<result property="createName" column="CREATE_NAME"/>
<result property="createBy" column="CREATE_BY"/>
<result property="createTime" column="CREATE_TIME"/>
<result property="updateBy" column="UPDATE_BY"/>
<result property="updateTime" column="UPDATE_TIME"/>
</resultMap>
<sql id="Base_Column_List">
a.ID,
a.CONFIG_ID,
a.DEPT_NO,
a.STATUS,
a.RESULT,
a.DURATION,
a.CREATE_NAME,
a.CREATE_BY,
a.CREATE_TIME,
a.UPDATE_BY,
a.UPDATE_TIME
</sql>
</mapper>
......@@ -425,6 +425,9 @@
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;
}
}
......@@ -38,10 +38,14 @@ public class ArchivesDaprUtil {
/**
* @Author fxj
* @Description 获取项目自动化设置信息,只返回配置了自动化且商险自动化为是的信息
* @param type 0 档案 1 合同 2 商险 3 社保公积金 4 薪酬
* @Date 11:16 2025/9/17
**/
public R<Map<String,String>> getProjectAutoSetMap(List<String> departNos){
R<Map> res = HttpDaprUtil.invokeMethodPost(daprArchivesProperties.getAppUrl(),daprArchivesProperties.getAppId(),"/tautomainrel/inner/getProjectAutoSetMap" , JSON.toJSONString(departNos), Map.class, SecurityConstants.FROM_IN);
public R<Map<String,String>> getProjectAutoSetMap(List<String> departNos, String type){
ProjectAutoSetParam param = new ProjectAutoSetParam();
param.setDepartNos(departNos);
param.setType(type);
R<Map> res = HttpDaprUtil.invokeMethodPost(daprArchivesProperties.getAppUrl(),daprArchivesProperties.getAppId(),"/tautomainrel/inner/getProjectAutoSetMap" , JSON.toJSONString(param), Map.class, SecurityConstants.FROM_IN);
if (Common.isEmpty(res)){
return R.failed("获取项目商险自动化信息失败!");
}
......
......@@ -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(),
"/insuranceWarn/inner/createInsuranceAlert",
paramVo,
Boolean.class,
SecurityConstants.FROM_IN
);
if (Common.isEmpty(res)) {
return R.failed("按项目生成商险续签待办失败!");
}
return res;
}
}
......@@ -17,6 +17,7 @@
package com.yifu.cloud.plus.v1.yifu.common.security.util;
import cn.hutool.core.util.StrUtil;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.ClientNameConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.SecurityConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser;
......@@ -99,4 +100,29 @@ public class SecurityUtils {
return false;
}
}
/**
* @Description: 检测用户是否为超管(超管放行)
* 超管角色ID:1L 或 SSC开发组角色ID:1668092146875969537L
* @Author: AI Assistant
* @Date: 2026/5/19
* @param user 用户信息
* @return: boolean true-是超管,false-不是超管
**/
public boolean isSuperAdmin(YifuUser user) {
if (user == null || user.getClientRoleMap() == null) {
return false;
}
List<Long> roleList = user.getClientRoleMap().get(ClientNameConstants.CLIENT_MVP);
if (roleList == null || roleList.isEmpty()) {
return false;
}
// SSC开发组-1668092146875969537L 超管1
for (Long role : roleList) {
if (role == 1668092146875969537L || role == 1L) {
return true;
}
}
return false;
}
}
......@@ -900,6 +900,16 @@ public class EmployeeRegistrationServiceImpl extends ServiceImpl<EmployeeRegistr
logService.saveLog(registration.getId(), CommonConstants.ZERO_STRING, RegistConstants.CONFIRM_SUBMIT, LocalDateTime.now(),
user.getNickname(), null);
try {
// 设置接收终端和接收方式
if (Common.isNotNull(preVo)) {
// 默认PC端单个接收,前端可传值覆盖
if (Common.isEmpty(preVo.getReceiveTerminal())) {
preVo.setReceiveTerminal(CommonConstants.ONE_STRING); // 1-PC端
}
if (Common.isEmpty(preVo.getReceiveType())) {
preVo.setReceiveType(CommonConstants.ZERO_STRING); // 0-单个接收
}
}
List<String> cardDeptList = new ArrayList<>();
List<String> curIdList = new ArrayList<>();
String cardDeptKey = registration.getEmpIdcard() + CommonConstants.DOWN_LINE_STRING + registration.getDeptNo();
......@@ -1745,6 +1755,14 @@ public class EmployeeRegistrationServiceImpl extends ServiceImpl<EmployeeRegistr
logService.saveLog(registration.getId(), CommonConstants.ZERO_STRING, RegistConstants.CONFIRM_SUBMIT, LocalDateTime.now(),
user.getNickname(), null);
try {
// 设置接收终端和接收方式(批量接收)
if (Common.isNotNull(preVo)) {
// 默认PC端批量接收,前端可传值覆盖
if (Common.isEmpty(preVo.getReceiveTerminal())) {
preVo.setReceiveTerminal(CommonConstants.ONE_STRING); // 1-PC端
}
preVo.setReceiveType(CommonConstants.ONE_STRING); // 1-批量接收
}
historyId = historyIdMap.get(cardDeptKey);
if (Common.isNotNull(historyId)) {
// 历史数据归档
......@@ -2134,24 +2152,12 @@ public class EmployeeRegistrationServiceImpl extends ServiceImpl<EmployeeRegistr
if (Common.isEmpty(checkRes) || checkRes.getCode() != CommonConstants.SUCCESS){
return checkRes.getMsg();
}
EmployeeRegistration exit = null;
//该人员入职/离职数据已登记,请勿重复操作
if (CommonConstants.TWO_STRING.equals(registration.getFeedbackType())){
exit = baseMapper.selectOne(Wrappers.<EmployeeRegistration>query().lambda()
EmployeeRegistration exit = baseMapper.selectOne(Wrappers.<EmployeeRegistration>query().lambda()
.eq(EmployeeRegistration::getEmpIdcard, registration.getEmpIdcard())
.eq(EmployeeRegistration::getDeptNo, registration.getDeptNo())
.eq(EmployeeRegistration::getFeedbackType, registration.getFeedbackType())
.in(EmployeeRegistration::getProcessStatus, CommonConstants.processStatus)
.last(CommonConstants.LAST_ONE_SQL));
} else {
// v1.7.23 新增:已处理 也要拒绝入职
exit = baseMapper.selectOne(Wrappers.<EmployeeRegistration>query().lambda()
.eq(EmployeeRegistration::getEmpIdcard, registration.getEmpIdcard())
.eq(EmployeeRegistration::getDeptNo, registration.getDeptNo())
.eq(EmployeeRegistration::getFeedbackType, registration.getFeedbackType())
.in(EmployeeRegistration::getProcessStatus, Stream.of("0","1","2").collect(Collectors.toList()))
.last(CommonConstants.LAST_ONE_SQL));
}
if (Common.isNotNull(exit)) {
return RegistConstants.REGIST_SAME_CHECK;
}
......@@ -3194,7 +3200,7 @@ public class EmployeeRegistrationServiceImpl extends ServiceImpl<EmployeeRegistr
.eq(EmployeeRegistration::getEmpIdcard, insert.getEmpIdcard())
.eq(EmployeeRegistration::getDeptNo, insert.getDeptNo())
.eq(EmployeeRegistration::getFeedbackType, insert.getFeedbackType())
.in(EmployeeRegistration::getProcessStatus, Stream.of("0","1","2").collect(Collectors.toList()))
.in(EmployeeRegistration::getProcessStatus, Stream.of("0","1").collect(Collectors.toList()))
.last(CommonConstants.LAST_ONE_SQL));
}
if (Common.isNotNull(exit)) {
......@@ -3350,7 +3356,12 @@ public class EmployeeRegistrationServiceImpl extends ServiceImpl<EmployeeRegistr
archiveDetail.setPreId(empPreId);
archiveDetail.setPreLogId(logId);
archiveDetail.setOldInfo(null); // old对象为空
archiveDetail.setNewInfo(JSON.toJSONString(preVo,JSON_FEATURES));
// 创建副本,排除不记录日志的字段
EmployeeRegistrationPreVo logPreVo = new EmployeeRegistrationPreVo();
BeanUtils.copyProperties(preVo, logPreVo);
logPreVo.setReceiveTerminal(null);
logPreVo.setReceiveType(null);
archiveDetail.setNewInfo(JSON.toJSONString(logPreVo,JSON_FEATURES));
archiveDetail.setDifferenceInfo(null);
archiveDetail.setCreateBy(user.getId());
archiveDetail.setCreateName(user.getNickname());
......@@ -3438,7 +3449,13 @@ public class EmployeeRegistrationServiceImpl extends ServiceImpl<EmployeeRegistr
contractDetail.setPreId(empPreId);
contractDetail.setPreLogId(logId);
contractDetail.setOldInfo(null);
contractDetail.setNewInfo(JSON.toJSONString(employeeContractPreVo,JSON_FEATURES));
// 创建合同对象副本,排除不记录日志的字段
TEmployeeContractPreVo logContractVo = new TEmployeeContractPreVo();
BeanUtils.copyProperties(employeeContractPreVo, logContractVo);
logContractVo.setLaborFeeModifyFlag(null);
logContractVo.setHourlyWageModifyFlag(null);
logContractVo.setPieceWageModifyFlag(null);
contractDetail.setNewInfo(JSON.toJSONString(logContractVo,JSON_FEATURES));
contractDetail.setDifferenceInfo(null);
contractDetail.setCreateBy(user.getId());
contractDetail.setCreateName(user.getNickname());
......
......@@ -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,14 @@ public class TInsurancesWarnController {
@Operation(description = "每天刷新商险到期提醒信息")
@Inner
@PostMapping("/inner/createInsuranceAlert")
public void createInsuranceAlert() {
insuranceWarnService.createInsuranceAlert();
public Boolean createInsuranceAlert(@RequestBody(required = false) BaseSearchVO paramVo) {
try {
String deptNo = Common.isNotNull(paramVo) ? paramVo.getDeptNo() : null;
insuranceWarnService.createInsuranceAlert(deptNo);
return true;
}catch (Exception e){
return false;
}
}
/**
......
......@@ -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();
......
......@@ -3876,7 +3876,7 @@ public class TInsuranceDetailServiceImpl extends ServiceImpl<TInsuranceDetailMap
departNos = paramList.stream().map(InsuranceAddParam::getDeptNo).collect(Collectors.toList());
}
if (Common.isNotNull(departNos)){
R<Map<String, String>> resR = archivesDaprUtil.getProjectAutoSetMap(departNos);
R<Map<String, String>> resR = archivesDaprUtil.getProjectAutoSetMap(departNos, CommonConstants.TWO_STRING);
if (Common.isNotNull(resR) && Common.isNotNull(resR.getData())){
insurAutoMap = resR.getData();
}else {
......@@ -3893,7 +3893,7 @@ public class TInsuranceDetailServiceImpl extends ServiceImpl<TInsuranceDetailMap
departNos = paramList.stream().map(InsuranceBatchParam::getDeptNo).collect(Collectors.toList());
}
if (Common.isNotNull(departNos)){
R<Map<String, String>> resR = archivesDaprUtil.getProjectAutoSetMap(departNos);
R<Map<String, String>> resR = archivesDaprUtil.getProjectAutoSetMap(departNos, CommonConstants.TWO_STRING);
if (Common.isNotNull(resR) && Common.isNotNull(resR.getData())){
insurAutoMap = resR.getData();
}else {
......@@ -3909,7 +3909,7 @@ public class TInsuranceDetailServiceImpl extends ServiceImpl<TInsuranceDetailMap
departNos = paramList.stream().map(InsuranceReplaceParam::getReplaceDeptNo).collect(Collectors.toList());
}
if (Common.isNotNull(departNos)){
R<Map<String, String>> resR = archivesDaprUtil.getProjectAutoSetMap(departNos);
R<Map<String, String>> resR = archivesDaprUtil.getProjectAutoSetMap(departNos, CommonConstants.TWO_STRING);
if (Common.isNotNull(resR) && Common.isNotNull(resR.getData())){
insurAutoMap = resR.getData();
}else {
......
......@@ -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
......
......@@ -67,6 +67,15 @@ public class SalaryAccountExportVo{
@ExcelProperty("项目编码")
private String deptNo;
/**
* 封面抬头
*/
@ExcelAttribute(name = "封面抬头", maxLength = 50)
@Length(max = 50, message = "封面抬头不能超过50个字符")
@HeadFontStyle(fontHeightInPoints = 11)
@ExcelProperty("封面抬头")
private String invoiceTitle;
/**
* 员工姓名
*/
......
......@@ -1805,6 +1805,7 @@
SELECT
a.DEPT_NAME,
a.DEPT_NO,
a.INVOICE_TITLE,
a.EMP_NAME,
a.EMP_IDCARD,
a.EMP_PHONE,
......
......@@ -55,6 +55,7 @@ import javax.servlet.http.HttpServletResponse;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 派单信息记录表
......@@ -512,9 +513,31 @@ public class TDispatchInfoController {
@PostMapping("/reduceSocialAndFund")
public R<List<ErrorMessage>> reduceSocialAndFund(@RequestBody TDispatchReduceVo excelVOList,
@RequestParam(required = false) String orderId) {
YifuUser user = SecurityUtils.getUser();
if (Common.isEmpty(user)){
return R.failed(CommonConstants.USER_FAIL);
}
// 自动化校验:检查项目是否纳入自动化(管理员除外)
String deptNo = excelVOList.getDepartNo();
if (Common.isNotNull(deptNo)) {
// 判断是否为管理员:超管ID为1 或 SSC开发组角色
boolean isAdmin = SecurityUtils.isSuperAdmin(user);
if (!isAdmin) {
R<Map<String, String>> resR = HttpDaprUtil.invokeMethodPost(daprArchivesProperties.getAppUrl()
, daprArchivesProperties.getAppId(), "/tautomainrel/inner/getProjectAutoSetMap"
, "{\"departNos\":[\"" + deptNo + "\"],\"type\":\"3\"}", Map.class, SecurityConstants.FROM_IN);
if (Common.isNotNull(resR) && Common.isNotNull(resR.getData()) && resR.getData().containsKey(deptNo)) {
List<ErrorMessage> errorMessageList = new ArrayList<>();
errorMessageList.add(new ErrorMessage(CommonConstants.ONE_INT, "该项目已纳入自动化,请至作业自动化模块操作"));
return R.failed(errorMessageList);
}
}
}
List<TDispatchReduceVo> list = new ArrayList<>();
list.add(excelVOList);
YifuUser user = SecurityUtils.getUser();
List<ErrorMessage> errorMessageList = new ArrayList<>();
tDispatchInfoService.batchReduceDispatch(list, errorMessageList, user, orderId,null);
return R.ok(errorMessageList);
......
......@@ -414,6 +414,10 @@ public class TDispatchInfoServiceImpl extends ServiceImpl<TDispatchInfoMapper, T
if (Common.isEmpty(user)) {
R.failed(CommonConstants.USER_FAIL);
}
// 判断是否为管理员:使用工具类方法(超管放行)
boolean isAdmin = SecurityUtils.isSuperAdmin(user);
List<ErrorMessage> errorMessageList = new ArrayList<>();
ExcelUtil<TDispatchImportVo> util1 = new ExcelUtil<>(TDispatchImportVo.class);
Map<String, String> idCardMap = new HashMap<>();
......@@ -429,6 +433,10 @@ public class TDispatchInfoServiceImpl extends ServiceImpl<TDispatchInfoMapper, T
*临时存储
*/
private List<TDispatchImportVo> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
/**
* 项目编码自动化校验缓存,key: deptNo, value: true-已纳入自动化, false-未纳入
*/
private Map<String, Boolean> autoCheckCache = new HashMap<>();
@Override
public void invoke(TDispatchImportVo data, AnalysisContext context) {
......@@ -439,6 +447,24 @@ public class TDispatchInfoServiceImpl extends ServiceImpl<TDispatchInfoMapper, T
if (Common.isNotNull(errorMessage)) {
errorMessageList.add(errorMessage);
} else {
// 导入时的自动化校验(管理员除外)
if (!isAdmin) {
String deptNo = data.getSettleDomainCode();
if (Common.isNotNull(deptNo)) {
// 先从缓存中获取
Boolean isAuto = autoCheckCache.get(deptNo);
if (isAuto == null) {
// 缓存中没有,查询数据库
R<Map<String, String>> resR = archivesDaprUtil.getProjectAutoSetMap(Arrays.asList(deptNo), CommonConstants.THREE_STRING);
isAuto = Common.isNotNull(resR) && Common.isNotNull(resR.getData()) && resR.getData().containsKey(deptNo);
autoCheckCache.put(deptNo, isAuto);
}
if (isAuto) {
errorMessageList.add(new ErrorMessage(data.getRowIndex(), "该项目已纳入自动化,请至作业自动化模块操作"));
return;
}
}
}
cachedDataList.add(data);
}
if (cachedDataList.size() >= BATCH_COUNT) {
......@@ -3169,6 +3195,10 @@ public class TDispatchInfoServiceImpl extends ServiceImpl<TDispatchInfoMapper, T
if (Common.isEmpty(user)) {
R.failed(CommonConstants.USER_FAIL);
}
// 判断是否为管理员:使用工具类方法(超管放行)
boolean isAdmin = SecurityUtils.isSuperAdmin(user);
List<ErrorMessage> errorMessageList = new ArrayList<>();
ExcelUtil<TDispatchReduceVo> util1 = new ExcelUtil<>(TDispatchReduceVo.class);
// 写法2:
......@@ -3184,6 +3214,10 @@ public class TDispatchInfoServiceImpl extends ServiceImpl<TDispatchInfoMapper, T
*临时存储
*/
private List<TDispatchReduceVo> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
/**
* 项目编码自动化校验缓存,key: deptNo, value: true-已纳入自动化, false-未纳入
*/
private Map<String, Boolean> autoCheckCache = new HashMap<>();
@Override
public void invoke(TDispatchReduceVo data, AnalysisContext context) {
......@@ -3194,6 +3228,24 @@ public class TDispatchInfoServiceImpl extends ServiceImpl<TDispatchInfoMapper, T
if (Common.isNotNull(errorMessage)) {
errorMessageList.add(errorMessage);
} else {
// 导入时的自动化校验(管理员除外)
if (!isAdmin) {
String deptNo = data.getDepartNo();
if (Common.isNotNull(deptNo)) {
// 先从缓存中获取
Boolean isAuto = autoCheckCache.get(deptNo);
if (isAuto == null) {
// 缓存中没有,查询数据库
R<Map<String, String>> resR = archivesDaprUtil.getProjectAutoSetMap(Arrays.asList(deptNo), CommonConstants.THREE_STRING);
isAuto = Common.isNotNull(resR) && Common.isNotNull(resR.getData()) && resR.getData().containsKey(deptNo);
autoCheckCache.put(deptNo, isAuto);
}
if (isAuto) {
errorMessageList.add(new ErrorMessage(data.getRowIndex(), "该项目已纳入自动化,请至作业自动化模块操作"));
return;
}
}
}
cachedDataList.add(data);
}
if (cachedDataList.size() >= BATCH_COUNT) {
......@@ -6913,6 +6965,22 @@ public class TDispatchInfoServiceImpl extends ServiceImpl<TDispatchInfoMapper, T
if (null == user || null == user.getId()) {
return R.failed(CommonConstants.USER_FAIL);
}
// 自动化校验:检查项目是否纳入自动化(使用工具类方法,超管放行)
boolean isAdmin = SecurityUtils.isSuperAdmin(user);
if (!isAdmin) {
String deptNo = importVo.getSettleDomainCode();
if (Common.isNotNull(deptNo)) {
R<Map<String, String>> resR = archivesDaprUtil.getProjectAutoSetMap(Arrays.asList(deptNo), CommonConstants.THREE_STRING);
if (Common.isNotNull(resR) && Common.isNotNull(resR.getData()) && resR.getData().containsKey(deptNo)) {
List<ErrorMessage> errorMessageList = new ArrayList<>();
errorMessageList.add(new ErrorMessage(CommonConstants.ONE_INT, "该项目已纳入自动化,请至作业自动化模块操作"));
return R.failed(errorMessageList);
}
}
}
List<ErrorMessage> errorMessageList = new ArrayList<>();
HashMap<String, SysArea> areaMap = new HashMap<>();
HashMap<String, SysArea> areaIdMap = new HashMap<>();
......
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