新增IAM用户同步功能,包含用户信息实体、请求和响应DTO,更新用户服务以支持同步IAM用户到主表。

This commit is contained in:
刘倡
2025-07-24 14:28:46 +08:00
parent e1930e0f52
commit f1efffdd32
10 changed files with 404 additions and 70 deletions

View File

@ -1,7 +1,10 @@
package com.coscoshipping.ebtp.system.category.maintenance.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.chinaunicom.mall.ebtp.common.base.entity.BaseEntity;
import com.chinaunicom.mall.ebtp.common.config.CustomLocalDateTimeTypeHandler;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ -10,9 +13,11 @@ import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 实体类 CoscoCategoryMaintenance
*
* @author sunyu
* @date 2025-5-27
*/
@ -20,69 +25,81 @@ import java.io.Serializable;
@Accessors(chain = true)
@ApiModel
@TableName(value = "cosco_category_maintenance", autoResultMap = true)
public class CoscoCategoryMaintenance extends BaseEntity implements Serializable {
public class CoscoCategoryMaintenance implements Serializable {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ApiModelProperty(value = "主键ID")
private Long id;
/**
* 主键ID
*/
@ApiModelProperty(value = "主键ID")
private Long id;
/**
* 版本id
*/
@ApiModelProperty(value = "版本id")
private Long versionId;
/**
* 版本id
*/
@ApiModelProperty(value = "版本id")
private Long versionId;
/**
* 父id
*/
@ApiModelProperty(value = "父id")
private Long parentId;
/**
* 父id
*/
@ApiModelProperty(value = "父id")
private Long parentId;
/**
* 路径
*/
@ApiModelProperty(value = "路径")
private String path;
/**
* 路径
*/
@ApiModelProperty(value = "路径")
private String path;
/**
* 品类名称
*/
@ApiModelProperty(value = "品类名称")
private String categoryName;
/**
* 品类名称
*/
@ApiModelProperty(value = "品类名称")
private String categoryName;
/**
* 编码
*/
@ApiModelProperty(value = "编码")
private String code;
/**
* 编码
*/
@ApiModelProperty(value = "编码")
private String code;
/**
* 状态1启用 0停用
*/
@ApiModelProperty(value = "状态1启用 0停用")
private Integer status;
/**
* 状态1启用 0停用
*/
@ApiModelProperty(value = "状态1启用 0停用")
private Integer status;
/**
* 创建者
*/
@TableField(fill = FieldFill.INSERT)
@ApiModelProperty("创建者")
private String createBy;
/**
* 创建时间
*/
@ApiModelProperty(value = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private java.time.LocalDateTime createDate;
/**
* 更新时间
*/
@ApiModelProperty(value = "更新时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private java.time.LocalDateTime updateDate;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT, typeHandler = CustomLocalDateTimeTypeHandler.class)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("创建时间")
private LocalDateTime createDate;
/**
* 更新者
*/
@TableField(fill = FieldFill.UPDATE)
@ApiModelProperty("更新者")
private String updateBy;
/**
* 更新时间
*/
@TableField(fill = FieldFill.UPDATE, typeHandler = CustomLocalDateTimeTypeHandler.class)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("更新时间")
private LocalDateTime updateDate;
}

View File

@ -1,9 +1,8 @@
package com.coscoshipping.ebtp.system.category.version.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.*;
import com.chinaunicom.mall.ebtp.common.base.entity.BaseEntity;
import com.chinaunicom.mall.ebtp.common.config.CustomLocalDateTimeTypeHandler;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ -12,6 +11,7 @@ import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 实体类 CoscoCategoryVersion
@ -22,7 +22,7 @@ import java.io.Serializable;
@Accessors(chain = true)
@ApiModel
@TableName(value = "cosco_category_version", autoResultMap = true)
public class CoscoCategoryVersion extends BaseEntity implements Serializable {
public class CoscoCategoryVersion implements Serializable {
private static final long serialVersionUID = 1L;
@ -57,23 +57,36 @@ public class CoscoCategoryVersion extends BaseEntity implements Serializable {
@ApiModelProperty(value = "状态1启用 0停用")
private String label;
/**
* 创建者
*/
@TableField(fill = FieldFill.INSERT)
@ApiModelProperty("创建者")
private String createBy;
/**
* 创建时间
*/
@ApiModelProperty(value = "创建时间")
* 创建时间
*/
@TableField(fill = FieldFill.INSERT, typeHandler = CustomLocalDateTimeTypeHandler.class)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private java.time.LocalDateTime createDate;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("创建时间")
private LocalDateTime createDate;
/**
* 更新时间
*/
@ApiModelProperty(value = "更新时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private java.time.LocalDateTime updateDate;
* 更新
*/
@TableField(fill = FieldFill.UPDATE)
@ApiModelProperty("更新者")
private String updateBy;
/**
* 更新时间
*/
@TableField(fill = FieldFill.UPDATE, typeHandler = CustomLocalDateTimeTypeHandler.class)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("更新时间")
private LocalDateTime updateDate;
}

View File

@ -4,16 +4,22 @@ package com.coscoshipping.ebtp.system.faceCompare.feign;
import com.chinaunicom.mall.ebtp.common.base.entity.BaseResponse;
import com.coscoshipping.ebtp.system.faceCompare.entity.CrypBean;
import com.coscoshipping.ebtp.system.faceCompare.feign.fallBack.ExtendFeignClientFallback;
import com.coscoshipping.ebtp.system.user.entity.dto.IamApiRequestDTO;
import com.coscoshipping.ebtp.system.user.entity.dto.IamApiResponseDTO;
import com.coscoshipping.ebtp.system.userinfo.entity.AuthCodeVo;
import io.swagger.annotations.ApiOperation;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
//,url="http://10.242.31.158:8100/biz-service-ebtp-extend")
@FeignClient(value = "${mconfig.feign.name.extend}",fallbackFactory = ExtendFeignClientFallback.class)
@FeignClient(value = "${mconfig.feign.name.extend}", fallbackFactory = ExtendFeignClientFallback.class)
public interface ExtendFeignClient {
/**
* 直接返回结果的天擎通用方法
*
* @param bean 参数
* @return
*/
@ -22,6 +28,7 @@ public interface ExtendFeignClient {
/**
* 短信验证码发送接口
*
* @param vo
* @return
*/
@ -30,9 +37,15 @@ public interface ExtendFeignClient {
/**
* 短信验证码验证接口
*
* @param vo
* @return
*/
@PostMapping("/v1/bizshortmessage/check/authCode")
public BaseResponse<Boolean> authCodeCheck(AuthCodeVo vo);
@ApiOperation("获取人员列表接口")
@PostMapping("/iam/api/users")
public IamApiResponseDTO getUsers(IamApiRequestDTO userRequestDTO);
}

View File

@ -3,6 +3,8 @@ package com.coscoshipping.ebtp.system.faceCompare.feign.fallBack;
import com.chinaunicom.mall.ebtp.common.base.entity.BaseResponse;
import com.coscoshipping.ebtp.system.faceCompare.entity.CrypBean;
import com.coscoshipping.ebtp.system.faceCompare.feign.ExtendFeignClient;
import com.coscoshipping.ebtp.system.user.entity.dto.IamApiRequestDTO;
import com.coscoshipping.ebtp.system.user.entity.dto.IamApiResponseDTO;
import com.coscoshipping.ebtp.system.userinfo.entity.AuthCodeVo;
import feign.hystrix.FallbackFactory;
import lombok.extern.slf4j.Slf4j;
@ -44,6 +46,11 @@ public class ExtendFeignClientFallback implements FallbackFactory<ExtendFeignCli
return null;
}
@Override
public IamApiResponseDTO getUsers(IamApiRequestDTO userRequestDTO) {
return null;
}
};
}

View File

@ -3,6 +3,10 @@ package com.coscoshipping.ebtp.system.user.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chinaunicom.mall.ebtp.common.base.entity.BaseResponse;
import com.coscoshipping.ebtp.system.faceCompare.feign.ExtendFeignClient;
import com.coscoshipping.ebtp.system.user.entity.IamApiUser;
import com.coscoshipping.ebtp.system.user.entity.dto.IamApiRequestDTO;
import com.coscoshipping.ebtp.system.user.entity.dto.IamApiResponseDTO;
import com.coscoshipping.ebtp.system.user.entity.dto.SysInnerUserInfo;
import com.coscoshipping.ebtp.system.user.entity.vo.SysUserVO;
import org.springframework.web.bind.annotation.*;
@ -31,6 +35,9 @@ public class SysUserController {
@Resource
private SysUserService iSysUserService;
@Resource
private ExtendFeignClient extendFeignClient;
/**
* 插入新数据
*
@ -153,4 +160,17 @@ public class SysUserController {
public BaseResponse<IPage<SysUser>> getPageByUserCompany(@ApiParam(value = "分页及查询条件", required = true) @RequestBody SysUserVO sysUserVO) {
return BaseResponse.success(iSysUserService.getPageByUserCompany(sysUserVO));
}
@ApiOperation("获取IAM人员列表接口")
@PostMapping("/iam/users")
public IamApiResponseDTO<List<IamApiUser>> iamUsers(@RequestBody IamApiRequestDTO userRequestDTO) {
return extendFeignClient.getUsers(userRequestDTO);
}
@ApiOperation("同步IAM用户到主表")
@PostMapping("/sync")
public BaseResponse<Boolean> syncIamUser(@RequestBody IamApiUser iamUser) {
Boolean result = iSysUserService.syncIamUser(iamUser);
return BaseResponse.success(result);
}
}

View File

@ -0,0 +1,84 @@
package com.coscoshipping.ebtp.system.user.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
/**
* 提供给IAM同步的用户信息实体
*/
@Data
@Accessors(chain = true)
@ApiModel(value = "IamApiUser对象", description = "人员基本信息表")
public class IamApiUser {
/** HR员工编号 */
private String employeeNo;
/** 员工姓名(中国和外国不同) */
private String name;
/** 员工状态(在职、离职、退休等) */
private String employeeStatusDesc;
/** HR组织机构单位一级编码 */
private String companyName;
/** 员工所属职位编码 */
private String positionCode;
/** 员工所属职位描述 */
private String positionName;
/** 员工所属部门编码(最小组织) */
private String departmentCode;
/** 性别描述(男、女) */
private String gender;
/** 出生日期 */
private String birthDate;
/** 国籍描述 */
private String nationality;
/** 民族描述 */
private String ethnicGroup;
/** 身份证号码 */
private String idCardNo;
/** 政治面貌描述 */
private String politicalStatus;
/** 学位描述 */
private String highestDegree;
/** 学历描述 */
private String highestEducation;
/** 联系电话(座机) */
private String workPhone;
/** 员工手机号码 */
private String mobile;
/** 员工电子邮箱地址 */
private String email;
/** 是否是船员(船员是 其他否) */
private String isCrew;
/** 员工类型描述(合同、劳务派遣、协议制等) */
private String employeeGroup;
/** 入职日期 */
private String entryDate;
/** 离职日期 */
private String leaveDate;
/** 员工SAP用户名 */
private String sapUsername;
/** 人事范围中的国家描述 */
private String country;
/** 人事范围中的地区描述 */
private String region;
/** 最新组织分配的日期 */
private String lastPositionDate;
/** 最新专业技术资格名称 */
private String professionalQualificationName;
/** 最细执业资格小类名称 */
private String qualificationSubtype;
/** 最高学历专业名称 */
private String majorName;
/** 简历信息数据 */
private String workExperience;
/** 创建时间 */
private String createTime;
/** 修改时间 */
private String updateTime;
}

View File

@ -0,0 +1,20 @@
package com.coscoshipping.ebtp.system.user.entity.dto;
import lombok.Data;
/**
* IAM用户请求DTO
* 用于分页查询IAM用户信息
*/
@Data
public class IamApiRequestDTO {
/* 分页索引从0开始 */
private Integer pageIndex = 0;
/* 分页大小支持至少300 */
private Integer pageSize = 10;
/* 最近变更时间的起始时间unix毫秒时间戳用于增量 */
private Long startTime;
/* 最近变更时间的终止时间unix毫秒时间戳用于增量 */
private Long endTime;
}

View File

@ -0,0 +1,116 @@
package com.coscoshipping.ebtp.system.user.entity.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import java.io.Serializable;
/**
* IAM基础响应DTO
* 用于统一处理IAM接口的响应格式
* @param <T> 响应数据类型
*/
@Data
public class IamApiResponseDTO<T> implements Serializable {
private static final long serialVersionUID = 6769157532172136264L;
/**
* 错误码
* 0表示成功其他值表示失败
*/
private Integer errorCode;
/**
* 错误信息
*/
private String errorMsg;
/**
* 总记录数
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
private Integer total;
/**
* 响应数据
* 泛型类型,具体数据结构由调用方定义
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
private T data;
public static IamApiResponseDTO<Object> success() {
IamApiResponseDTO<Object> resp = new IamApiResponseDTO<>();
resp.setErrorCode(0);
resp.setErrorMsg(null);
return resp;
}
public static <T> IamApiResponseDTO<T> success(T data) {
IamApiResponseDTO<T> resp = new IamApiResponseDTO<>();
resp.setErrorCode(0);
resp.setErrorMsg(null);
resp.setData(data);
return resp;
}
public static <T> IamApiResponseDTO<T> success(String errorMsg, T data) {
IamApiResponseDTO<T> resp = new IamApiResponseDTO<>();
resp.setErrorCode(0);
resp.setErrorMsg(errorMsg);
resp.setData(data);
return resp;
}
public static IamApiResponseDTO<Object> fail() {
IamApiResponseDTO<Object> resp = new IamApiResponseDTO<>();
resp.setErrorCode(-1);
resp.setErrorMsg("error");
return resp;
}
public static IamApiResponseDTO<String> fail(String errorMsg) {
IamApiResponseDTO<String> resp = new IamApiResponseDTO<>();
resp.setErrorCode(-1);
resp.setErrorMsg(errorMsg);
resp.setData(null);
return resp;
}
public static IamApiResponseDTO<String> fail(Integer errorCode, String errorMsg) {
IamApiResponseDTO<String> resp = new IamApiResponseDTO<>();
resp.setErrorCode(errorCode);
resp.setErrorMsg(errorMsg);
resp.setData(null);
return resp;
}
public static <T> IamApiResponseDTO<T> fail(T data) {
IamApiResponseDTO<T> resp = new IamApiResponseDTO<>();
resp.setErrorCode(-1);
resp.setErrorMsg("error");
resp.setData(null);
return resp;
}
public static <T> IamApiResponseDTO<T> fail(String errorMsg, T data) {
IamApiResponseDTO<T> resp = new IamApiResponseDTO<>();
resp.setErrorCode(-1);
resp.setErrorMsg(errorMsg);
resp.setData(null);
return resp;
}
public static <T> IamApiResponseDTO<T> fail(Integer errorCode, String errorMsg, T data) {
IamApiResponseDTO<T> resp = new IamApiResponseDTO<>();
resp.setErrorCode(errorCode);
resp.setErrorMsg(errorMsg);
resp.setData(null);
return resp;
}
public IamApiResponseDTO() {
}
public IamApiResponseDTO(final Integer errorCode, final String errorMsg, final Integer total, final T data) {
this.errorCode = errorCode;
this.errorMsg = errorMsg;
this.total = total;
this.data = data;
}
}

View File

@ -55,4 +55,11 @@ public interface SysUserService extends IBaseService<SysUser> {
* @return 分页用户数据
*/
IPage<SysUser> getPageByUserCompany(SysUserVO sysUserVO);
/**
* 同步IAM用户到主表
* @param iamUser IAM用户对象
* @return 是否成功
*/
Boolean syncIamUser(com.coscoshipping.ebtp.system.user.entity.IamApiUser iamUser);
}

View File

@ -2,6 +2,7 @@ package com.coscoshipping.ebtp.system.user.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@ -13,9 +14,11 @@ import com.coscoshipping.ebtp.system.role.entity.SysRole;
import com.coscoshipping.ebtp.system.role.entity.vo.AllRolesAndAssignRoleVO;
import com.coscoshipping.ebtp.system.user.entity.dto.SysInnerUserInfo;
import com.coscoshipping.ebtp.system.user.entity.vo.SysUserVO;
import com.coscoshipping.ebtp.system.user.util.Md5Util;
import com.coscoshipping.ebtp.system.userrole.service.SysUserRoleService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.chinaunicom.mall.ebtp.common.base.service.impl.BaseServiceImpl;
import com.chinaunicom.mall.ebtp.common.util.PropertyUtils;
@ -40,6 +43,9 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
@Autowired
private SysUserRoleService sysUserRoleService;
@Value("${login.reset_password}")
private String resetPassword;
@Override
public IPage<SysUser> getPage(SysUserVO sysUserVO) {
@ -122,6 +128,37 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser>
return result;
}
@Override
public Boolean syncIamUser(com.coscoshipping.ebtp.system.user.entity.IamApiUser iamUser) {
// 字段映射
SysUser sysUser = new SysUser();
sysUser.setName(iamUser.getName());
sysUser.setDisplayName(iamUser.getName());
sysUser.setEmployeeNumber(iamUser.getEmployeeNo());
sysUser.setMobile(iamUser.getMobile());
sysUser.setEmail(iamUser.getEmail());
sysUser.setSex(iamUser.getGender());
sysUser.setPosition(iamUser.getPositionName());
sysUser.setOfficePhone(iamUser.getWorkPhone());
sysUser.setOrgId(iamUser.getDepartmentCode());
sysUser.setOrgName(iamUser.getDepartmentCode()); // 若有部门名称字段请替换
sysUser.setStatus("在职".equals(iamUser.getEmployeeStatusDesc()) ? 1 : 0);
// 判断是否已存在(以 employeeNumber 为唯一标识)
LambdaQueryWrapper<SysUser> query = Wrappers.lambdaQuery(SysUser.class)
.eq(SysUser::getEmployeeNumber, iamUser.getEmployeeNo());
SysUser exist = this.getOne(query);
if (exist != null) {
sysUser.setUserId(exist.getUserId());
return this.updateById(sysUser);
} else {
sysUser.setUserId(PropertyUtils.getSnowflakeId());
String defaultPassword = Md5Util.encode(resetPassword);
sysUser.setPassword(defaultPassword);
return this.save(sysUser);
}
}
/**
* 保存前的数据校验
*/