Merge pull request 'AD用户状态同步ehr员工状态' (#4) from nflg-bom-transition-lhj0801 into feature/DM/nflg-bom-transition
Reviewed-on: http://192.168.0.40:3000/root/nflg_project/pulls/4
This commit is contained in:
commit
0ff9cfe794
|
|
@ -17,6 +17,7 @@ import com.nflg.product.material.pojo.vo.AuthorityMenuVO;
|
|||
import com.nflg.product.material.pojo.vo.AuthorityUserVO;
|
||||
import com.nflg.product.material.service.AuthorityPowerService;
|
||||
import com.nflg.product.material.service.AuthorityUserService;
|
||||
import com.nflg.product.material.service.EhrService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import nflg.product.common.constant.STATE;
|
||||
|
|
@ -174,6 +175,10 @@ public class AuthorityUserApi extends BaseApi {
|
|||
return ResultVO.success(authorityUserService.updateById(user));
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("syncEhrEmployee")
|
||||
@ApiOperation("同步ehr员工的状态")
|
||||
public ResultVO<String> syncEhrEmployee(){
|
||||
return ResultVO.success(authorityUserService.syncEhrEmployee());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@ public class SaticScheduleTask {
|
|||
@Resource
|
||||
private MaterialUpdateBillService materialUpdateBillService;
|
||||
|
||||
@Resource
|
||||
private AuthorityUserService authorityUserService;
|
||||
|
||||
/**
|
||||
* 更新AD(每天6点)
|
||||
*/
|
||||
|
|
@ -149,4 +152,12 @@ public class SaticScheduleTask {
|
|||
public void doQueryCurrentTwoYearsUsage() throws Exception {
|
||||
materialMainService.doQueryCurrentTwoYearsUsage();
|
||||
}
|
||||
|
||||
/**
|
||||
* 每周六 同步ehr用户人员状态,离职的更新为未启用
|
||||
*/
|
||||
@Scheduled(cron = "${ehr.sync.employee.state.time:0 0 9 ? * SAT}")
|
||||
public void syncEhrEmployee() {
|
||||
authorityUserService.syncEhrEmployee();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
package com.nflg.product.material.pojo.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* packageName com.nflg.product.material.pojo.dto
|
||||
*
|
||||
* @author luohj
|
||||
* @className EhrEmployeeDTO
|
||||
* @date 2024/8/1 0001
|
||||
* @description ehr 员工信息
|
||||
*/
|
||||
@Data
|
||||
public class EhrEmployeeDTO implements Serializable {
|
||||
|
||||
@ApiModelProperty("员工ID")
|
||||
private String EmpID;
|
||||
|
||||
@ApiModelProperty("员工编号")
|
||||
private String EmpNo;
|
||||
|
||||
@ApiModelProperty("员工姓名")
|
||||
private String EmpName;
|
||||
|
||||
@ApiModelProperty("所属部门ID")
|
||||
private String DeptId;
|
||||
|
||||
@ApiModelProperty("所属部门编号")
|
||||
private String DEPTCODE;
|
||||
|
||||
@ApiModelProperty("员工状态 0启用1停用")
|
||||
private String DISABLE;
|
||||
|
||||
@ApiModelProperty("人员类别 1在职5离职")
|
||||
private String A0191;
|
||||
|
||||
@ApiModelProperty("手机号码")
|
||||
private String CELLPHONE;
|
||||
|
||||
@ApiModelProperty("岗位ID")
|
||||
private String POSITIONID;
|
||||
|
||||
@ApiModelProperty("身份证号")
|
||||
private String IDCARDNO;
|
||||
|
||||
@ApiModelProperty("性别")
|
||||
private String SEX;
|
||||
|
||||
@ApiModelProperty("最后修改日期")
|
||||
private Date LASTMODIFYTIME;
|
||||
|
||||
@ApiModelProperty("开户银行")
|
||||
private String A0136;
|
||||
|
||||
@ApiModelProperty("银行代码")
|
||||
private String YHDM;
|
||||
|
||||
@ApiModelProperty("银行账号")
|
||||
private String A0137;
|
||||
|
||||
@ApiModelProperty("银行国家代码")
|
||||
private String YHGJDM;
|
||||
|
||||
@ApiModelProperty("职级")
|
||||
private String GWZJ;
|
||||
|
||||
@ApiModelProperty("序列")
|
||||
private String RYXL;
|
||||
|
||||
@ApiModelProperty("是否结算加班费")
|
||||
private String A01190;
|
||||
|
||||
@ApiModelProperty("入职日期")
|
||||
private String A0141;
|
||||
|
||||
@ApiModelProperty("成本中心编码")
|
||||
private String COSTNO;
|
||||
|
||||
@ApiModelProperty("成本中心")
|
||||
private String COSTNAME;
|
||||
|
||||
@ApiModelProperty("第一次合同签订时间")
|
||||
private Date HT_BEGIN_DATE;
|
||||
}
|
||||
|
|
@ -3,10 +3,13 @@ package com.nflg.product.material.service;
|
|||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.lang.TypeReference;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.XmlUtil;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.nflg.product.base.core.conmon.util.DESUtil;
|
||||
import com.nflg.product.base.core.vo.PageVO;
|
||||
import com.nflg.product.material.mapper.master.AuthorityPowerMapper;
|
||||
|
|
@ -14,23 +17,30 @@ import com.nflg.product.material.mapper.master.AuthorityPowerPermissionMapper;
|
|||
import com.nflg.product.material.mapper.master.AuthorityRoleMapper;
|
||||
import com.nflg.product.material.mapper.master.AuthorityUserMapper;
|
||||
import com.nflg.product.material.pojo.dto.AuthorityUserDTO;
|
||||
import com.nflg.product.material.pojo.dto.EhrEmployeeDTO;
|
||||
import com.nflg.product.material.pojo.dto.SaveUserMemuPermissionDTO;
|
||||
import com.nflg.product.material.pojo.dto.UserRoleDTO;
|
||||
import com.nflg.product.material.pojo.entity.AuthorityPowerPermissionEntity;
|
||||
import com.nflg.product.material.pojo.entity.AuthorityUserEntity;
|
||||
import com.nflg.product.material.pojo.query.AuthorityUserQuery;
|
||||
import com.nflg.product.material.pojo.vo.AuthorityUserVO;
|
||||
import com.nflg.product.material.util.HttpUtils;
|
||||
import com.nflg.product.material.util.ListCommonUtil;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.dom4j.DocumentHelper;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
|
|
@ -58,6 +68,8 @@ public class AuthorityUserService extends ServiceImpl<AuthorityUserMapper, Autho
|
|||
@Resource
|
||||
AuthorityRoleMapper authorityRoleMapper;
|
||||
|
||||
@Resource
|
||||
EhrService ehrService;
|
||||
/**
|
||||
* 分页查询所有数据
|
||||
*
|
||||
|
|
@ -199,5 +211,37 @@ public class AuthorityUserService extends ServiceImpl<AuthorityUserMapper, Autho
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步ehr用户人员状态,离职的更新为未启用
|
||||
* 将来源为AD域同步的用户,与ehr数据更新状态
|
||||
*/
|
||||
public String syncEhrEmployee(){
|
||||
String res = "";
|
||||
//获取AD域同步的用户,状态是启用中的集合,判断在ehr中是否已经离职了
|
||||
List<AuthorityUserEntity> userList = this.list(Wrappers.<AuthorityUserEntity>lambdaQuery()
|
||||
.eq(AuthorityUserEntity::getUserSource,1)
|
||||
.eq(AuthorityUserEntity::getEnableState,1));
|
||||
if(userList.isEmpty()){
|
||||
return "正常AD用户数量为0";
|
||||
}
|
||||
String sessionId = ehrService.getSessionId();
|
||||
List<EhrEmployeeDTO> empList = ehrService.empList(sessionId);
|
||||
if(empList.isEmpty()){
|
||||
return "员工数量为0";
|
||||
}
|
||||
//离职员工编号集合
|
||||
List<String> empNoList = empList.stream().filter(emp -> Objects.equals("1",emp.getDISABLE()) || Objects.equals("5",emp.getA0191()))
|
||||
.map(emp -> emp.getEmpNo().toUpperCase()).collect(Collectors.toList());
|
||||
List<AuthorityUserEntity> disableList = userList.stream()
|
||||
.filter(user -> empNoList.contains(user.getUserCode().toUpperCase()))
|
||||
.map(user -> {
|
||||
user.setEnableState(0);
|
||||
return user;
|
||||
}).collect(Collectors.toList());
|
||||
if(!disableList.isEmpty()){
|
||||
this.updateBatchById(disableList);
|
||||
}
|
||||
return String.format("正常AD用户数:%d,员工数:%d,离职数:%d,更新记录:%d",userList.size(),empList.size(),empNoList.size(),disableList.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,138 @@
|
|||
package com.nflg.product.material.service;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.XmlUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.nflg.product.material.pojo.dto.EhrEmployeeDTO;
|
||||
import com.nflg.product.material.util.CompletableFutureUtil;
|
||||
import com.nflg.product.material.util.HttpUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentHelper;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* packageName com.nflg.product.material.service
|
||||
*
|
||||
* @author luohj
|
||||
* @className EhrService
|
||||
* @date 2024/8/1 0001
|
||||
* @description ehr 相关接口
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
@RefreshScope
|
||||
public class EhrService {
|
||||
|
||||
private static HttpUtils httpUtils = new HttpUtils();
|
||||
|
||||
@Value("${ehr.url:http://192.168.163.30:8088/hr/DataInterface/WebService.asmx}")
|
||||
private String ehrUrl;
|
||||
@Value("${ehr.user:nflj}")
|
||||
private String ehrUser;
|
||||
@Value("${ehr.pwd:nfljadmin}")
|
||||
private String ehrPwd;
|
||||
|
||||
/**
|
||||
* 获取ehr sessionId
|
||||
* @return
|
||||
*/
|
||||
public String getSessionId(){
|
||||
String sessionId = "";
|
||||
Map<String,String> mp = Maps.newHashMap();
|
||||
mp.put("S1",ehrUser);
|
||||
mp.put("S2",ehrPwd);
|
||||
try {
|
||||
String re = httpUtils.doformPost(ehrUrl + "/Login",mp);
|
||||
Document d = DocumentHelper.parseText(re);
|
||||
sessionId = d.getRootElement().getStringValue();
|
||||
} catch (Exception e) {
|
||||
log.error("ehr 登录异常: {}",e.getMessage());
|
||||
}
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取ehr 员工总数
|
||||
* @param sessionId
|
||||
* @return
|
||||
*/
|
||||
public Integer empTotal(String sessionId){
|
||||
int total = -1;
|
||||
Map<String,String> mp2 = Maps.newHashMap();
|
||||
mp2.put("SessionID",sessionId);
|
||||
mp2.put("NewOnly","0");
|
||||
mp2.put("Time","");
|
||||
String re2 = null;
|
||||
try {
|
||||
re2 = httpUtils.doPost(ehrUrl + "/EmpBeginGetEmployee",mp2);
|
||||
Document d2 = DocumentHelper.parseText(re2);
|
||||
total =Integer.valueOf(d2.getRootElement().getStringValue());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* ehr 员工列表
|
||||
* @param sessionId
|
||||
* @return
|
||||
*/
|
||||
public List<EhrEmployeeDTO> empList(String sessionId){
|
||||
int total = empTotal(sessionId);
|
||||
List<EhrEmployeeDTO> ehrEmployeeList =Lists.newArrayList();
|
||||
//每批次数量 1222 6 22 7
|
||||
int batch = 200;
|
||||
if(total <= 0){
|
||||
return ehrEmployeeList;
|
||||
}
|
||||
int mul = total / batch;
|
||||
int rem = total % batch;
|
||||
int cnt = mul + (rem > 0 ? 1: 0);
|
||||
List<CompletableFuture<List<EhrEmployeeDTO>>> taskList = Lists.newArrayList();
|
||||
for (int i = 1; i <= cnt; i++) {
|
||||
int finalI = i;
|
||||
CompletableFuture<List<EhrEmployeeDTO>> future = CompletableFuture.supplyAsync(() -> {
|
||||
Map<String,String> mp3 = Maps.newHashMap();
|
||||
mp3.put("SessionID",sessionId);
|
||||
mp3.put("from",String.valueOf( (finalI -1)*batch + 1 ));
|
||||
mp3.put("to",String.valueOf( (finalI * batch) > total ? total: (finalI * batch) ));
|
||||
try {
|
||||
String re3 = httpUtils.doPost(ehrUrl + "/GetSegment",mp3);
|
||||
Document d3 = DocumentHelper.parseText(re3);
|
||||
String r3 = d3.getRootElement().getStringValue();
|
||||
Map<String, Object> m3 = XmlUtil.xmlToMap(r3);
|
||||
return Convert.toList(EhrEmployeeDTO.class,m3.get("Table"));
|
||||
} catch (Exception e) {
|
||||
log.error("eHr获取人员信息异常:{},{}",sessionId,e.getMessage());
|
||||
}
|
||||
return Lists.newArrayList();
|
||||
});
|
||||
taskList.add(future);
|
||||
}
|
||||
try {
|
||||
|
||||
CompletableFuture<Void> allTask = CompletableFuture.allOf(taskList.stream().map(CompletableFutureUtil::executeActionAsync).toArray(CompletableFuture[]::new));
|
||||
allTask.get();
|
||||
taskList.forEach(t -> ehrEmployeeList.addAll(t.join()));
|
||||
|
||||
//清除缓存
|
||||
Map<String,String> mp4 = Maps.newHashMap();
|
||||
mp4.put("SessionID",sessionId);
|
||||
httpUtils.doPost(ehrUrl + "/ClearCache",mp4);
|
||||
} catch (Exception e) {
|
||||
log.error("eHr获取人员信息异常:{}",e.getMessage());
|
||||
}
|
||||
|
||||
return ehrEmployeeList;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package com.nflg.product.material.util;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* packageName com.nflg.product.material.util
|
||||
*
|
||||
* @author luohj
|
||||
* @className CompletableFutureUtil
|
||||
* @date 2024/8/1 0001
|
||||
* @description TODO
|
||||
*/
|
||||
@Slf4j
|
||||
public class CompletableFutureUtil {
|
||||
private static final int MAX_RETRIES = 3;
|
||||
|
||||
|
||||
public static <T> List<T> getAllCompleted(List<CompletableFuture<T>> futuresList) throws Exception {
|
||||
CompletableFuture<Void> allFuturesResult = CompletableFuture
|
||||
.allOf(futuresList.stream().map(CompletableFutureUtil::executeActionAsync).toArray(CompletableFuture[]::new));
|
||||
allFuturesResult.get();
|
||||
return futuresList
|
||||
.stream()
|
||||
.map(CompletableFuture::join)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static <T> CompletableFuture<T> executeActionAsync(CompletableFuture<T> action) {
|
||||
return action
|
||||
.thenApply(CompletableFuture::completedFuture)
|
||||
.exceptionally(t -> retry(t, action, 0))
|
||||
.thenCompose(Function.identity());
|
||||
}
|
||||
|
||||
private static <T> CompletableFuture<T> retry(Throwable first, CompletableFuture<T> action, int retry) {
|
||||
if (retry >= MAX_RETRIES) {
|
||||
return CompletableFutureUtil.failedFuture(first);
|
||||
}
|
||||
return action
|
||||
.thenApply(CompletableFuture::completedFuture)
|
||||
.exceptionally(t -> {
|
||||
// first.addSuppressed(t);
|
||||
log.info("任务:{} , 重试:{}", action, retry);
|
||||
return retry(first, action, retry + 1); })
|
||||
.thenCompose(Function.identity());
|
||||
}
|
||||
|
||||
public static <T> CompletableFuture<T> failedFuture(Throwable t) {
|
||||
final CompletableFuture<T> cf = new CompletableFuture<>();
|
||||
cf.completeExceptionally(t);
|
||||
return cf;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue