提交 5ffa14e0 authored 作者: douxy's avatar douxy

Merge remote-tracking branch 'refs/remotes/origin/qa' into dxy

package com.sfa.job.domain.qince.dao;
import com.sfa.job.pojo.qince.response.QinceEmployeeDto;
import java.util.List;
import java.util.Set;
/**
* @author : liqiulin
* @date : 2025-12-05 17
* @describe :
*/
public interface IQinceEmployeeDao {
String getQcIdByEmpCode(String empCode);
void userResigned(String empQcId);
List<QinceEmployeeDto> selectListByEmpcodes(Set<String> keySet);
List<QinceEmployeeDto> selectListByOrgCode(String orgCode);
}
package com.sfa.job.domain.qince.dao;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sfa.common.core.enums.qince.QinceEmpStatus;
import com.sfa.common.core.utils.bean.BeanUtils;
import com.sfa.job.domain.qince.entity.QinceEmployee;
import com.sfa.job.domain.qince.mapper.QinceEmployeeMapper;
import com.sfa.job.pojo.qince.response.QinceEmployeeDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Set;
/**
* @author : liqiulin
* @date : 2025-12-05 17
* @describe :
*/
@DS("promotion")
@Service
public class QinceEmployeeDaoImpl implements IQinceEmployeeDao {
@Autowired
private QinceEmployeeMapper qinceEmployeeMapper;
@Override
public String getQcIdByEmpCode(String empCode) {
LambdaQueryWrapper<QinceEmployee> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(QinceEmployee::getEmpCode, empCode);
QinceEmployee qinceEmployee = qinceEmployeeMapper.selectOne(lambdaQueryWrapper);
if (qinceEmployee == null){
return null;
}
return qinceEmployee.getQcId();
}
@Override
public void userResigned(String empQcId) {
qinceEmployeeMapper.userResigned(empQcId);
}
/**
* 根据code批量查询
*/
@Override
public List<QinceEmployeeDto> selectListByEmpcodes(Set<String> keySet) {
LambdaQueryWrapper<QinceEmployee> qw = new LambdaQueryWrapper<>();
qw.in(QinceEmployee::getEmpCode, keySet);
qw.in(QinceEmployee::getEmpStatus, QinceEmpStatus.NORMAL.getStatus());
List<QinceEmployee> qcEmployees = qinceEmployeeMapper.selectList(qw);
return BeanUtils.transitionDtos(qcEmployees, QinceEmployeeDto.class);
}
@Override
public List<QinceEmployeeDto> selectListByOrgCode(String orgCode) {
LambdaQueryWrapper<QinceEmployee> qw = new LambdaQueryWrapper<>();
qw.eq(QinceEmployee::getEmpOrgCode, orgCode);
qw.in(QinceEmployee::getEmpStatus, QinceEmpStatus.NORMAL.getStatus());
List<QinceEmployee> qcEmployees = qinceEmployeeMapper.selectList(qw);
return BeanUtils.transitionDtos(qcEmployees, QinceEmployeeDto.class);
}
}
package com.sfa.job.domain.qince.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import lombok.Data;
/**
* 勤策-人员数据
* @TableName qince_employee
*/
@TableName(value ="qince_employee")
@Data
public class QinceEmployee implements Serializable {
/**
* 主键id
*/
@TableId(type = IdType.AUTO)
private Integer id;
/**
* 勤策的员工唯一标识
*/
private String qcId;
/**
* 来源第三方系统的员工唯一标识
*/
private String empId;
/**
* 员工登录帐号
*/
private String empCode;
/**
* 姓名
*/
private String empName;
/**
* 员工别名
*/
private String aliasName;
/**
* 人员编码
*/
private String employeeCode;
/**
* 员工性别。F:女性,M:男性
*/
private String empSex;
/**
* 员工手机号码
*/
private String empMobile;
/**
* 员工手机地区码
*/
private String mobileDistrictCode;
/**
* 固定电话,示例:025-68736873
*/
private String empTel;
/**
* 生日。格式:yyyy-MM-dd
*/
private String empBirthday;
/**
* QQ
*/
private String empQq;
/**
* 微信
*/
private String empWeixin;
/**
* 来源企微员工唯一标识。只有企微同步过来的人员该字段才有值
*/
private String empWechatCode;
/**
* 身份证号码
*/
private String empIdcard;
/**
* 邮箱
*/
private String empEmail;
/**
* 地址
*/
private String empAddr;
/**
* 来源第三方系统隶属部门
*/
private String empOrgId;
/**
* 隶属部门编码
*/
private String empOrgCode;
/**
* 勤策部门唯一标识
*/
private String waiqin365OrgId;
/**
* 来源第三方系统,员工上级唯一标识
*/
private String empParentId;
/**
* 员工上级编码
*/
private String parentCode;
/**
* 勤策员工上级唯一标识
*/
private String waiqin365ParentId;
/**
* 是否机构领导。0:否,1:是,默认值0
*/
private String empIsOrgLearder;
/**
* 员工账号状态。0:销户,1:正常,2:停用
*/
private String empStatus;
/**
* 手机卡绑定。0:不绑定,1:绑定
*/
private String empImsiBinding;
/**
* 勤策经销商唯一标识
*/
private String dealerId;
/**
* 经销商中文名称
*/
private String dealerName;
/**
* 常驻地省信息
*/
private String empBaseprovince;
/**
* 常驻地市信息
*/
private String empBasecity;
/**
* 勤策职务唯一标识
*/
private String waiqin365PositionId;
/**
* 职务编码
*/
private String empPositionCode;
/**
* 职务名称
*/
private String empPosition;
/**
* 勤策岗位唯一标识
*/
private String waiqin365JobId;
/**
* 岗位编码
*/
private String empJobCode;
/**
* 岗位名称
*/
private String empJob;
/**
* 手机认证,0为是,1为否
*/
private String mobileAuth;
/**
* 客户端类型。0:标准客户端(APP)、1:定制客户端(APP)、2:微信小程序、3:企业微信
*/
private String terminalType;
/**
* 头像上传时间
*/
private String faceTime;
/**
* 入职时间
*/
private String empEnrollmentTime;
/**
* 离职时间
*/
private String empResignationTime;
/**
* 最近登录时间
*/
private String lastUseTime;
/**
* 创建时间
*/
private String createTime;
/**
* 修改时间
*/
private String modifyTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}
\ No newline at end of file
package com.sfa.job.domain.qince.mapper;
import com.sfa.job.domain.qince.entity.QinceEmployee;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
/**
* @author a02200059
* @description 针对表【qince_employee(勤策-人员数据)】的数据库操作Mapper
* @createDate 2025-12-05 17:16:32
* @Entity com.sfa.job.domain.qince.entity.QinceEmployee
*/
@Repository
public interface QinceEmployeeMapper extends BaseMapper<QinceEmployee> {
void userResigned(@Param("empQcId") String empQcId);
}
......@@ -2,6 +2,8 @@ package com.sfa.job.domain.system.dao;
import com.alibaba.fastjson2.JSONObject;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
......@@ -17,4 +19,19 @@ public interface ISysUserDao {
void deleteUser(String employeeNo);
Map<String, String> getUserNoAndNameMap();
void updateOffboardDate(String employeeNo, Date offboardDate);
/**
* @return 离职人员信息
*/
List<String> selectResignedUsers();
void updateUserLeader();
/**
* @Return key:员工工号;value:上级工号
*/
Map<String, String> selectListEmpAndLeader();
}
......@@ -13,6 +13,7 @@ import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
......@@ -76,7 +77,18 @@ public class SysDeptDaoImpl implements ISysDeptDao{
Boolean statusB = jo.getJSONObject("status").getBoolean("is_deleted");
sysDept.setStatus(statusB?"1":"0");
sysDeptMapper.insertOrUpdate(sysDept);
// 查询code是否存在,不存在则新增,保存则修改,ON DUPLICATE KEY 关键字会造成ID大量新增,弃用
SysDept sysDeptOld = sysDeptMapper.selectOneByDeptCode(sysDept.getDeptCode());
if (Objects.isNull(sysDeptOld)){
sysDept.setDeptNameSale(sysDept.getDeptName());
sysDeptMapper.insert(sysDept);
return sysDept;
}else if ("0".equals(sysDeptOld.getDeptNameSaleIsFs())){
sysDept.setDeptNameSale(sysDept.getDeptName());
}
sysDept.setDeptId(sysDeptOld.getDeptId());
sysDeptMapper.updateById(sysDept);
return sysDept;
}
......
package com.sfa.job.domain.system.dao;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sfa.common.core.enums.StatusType;
import com.sfa.job.domain.system.entity.SysUser;
import com.sfa.job.domain.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
/**
......@@ -22,6 +22,8 @@ public class SysUserDaoImpl implements ISysUserDao{
@Autowired
private SysUserMapper sysUserMapper;
@Value("${wxl.lvzx_dept.r_sales_dept_path}")
private String lvzxDeptPath;
@Override
public void insertOrUpdate(JSONObject jo, Long deptId) {
......@@ -46,8 +48,17 @@ public class SysUserDaoImpl implements ISysUserDao{
sysUser.setRoleName("");
sysUser.setWorkCityName(jo.getString("city"));
sysUser.setStatus(StatusType.INVALID.getType()+"");
sysUser.setLeaderFsOpenId(jo.getString("leader_user_id"));
sysUserMapper.insertOrUpdate(sysUser);
// 根据username(工号)查询
SysUser sysUserOld = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserName, sysUser.getUserName()));
if (Objects.nonNull(sysUserOld)){
sysUser.setUserId(sysUserOld.getUserId());
sysUserMapper.putById(sysUser);
return;
}
sysUserMapper.insert(sysUser);
}
@Override
......@@ -65,4 +76,25 @@ public class SysUserDaoImpl implements ISysUserDao{
List<HashMap<String, String>> userNoAndNameMap = sysUserMapper.getUserNoAndNameMap();
return userNoAndNameMap.stream().collect(Collectors.toMap(m -> m.get("user_name"), m -> m.get("nick_name")));
}
@Override
public void updateOffboardDate(String employeeNo, Date offboardDate) {
sysUserMapper.updateOffboardDate(employeeNo, offboardDate);
}
@Override
public List<String> selectResignedUsers() {
return sysUserMapper.selectResignedUsers();
}
@Override
public void updateUserLeader() {
sysUserMapper.updateUserLeader();
}
@Override
public Map<String, String> selectListEmpAndLeader() {
List<HashMap<String, String>> empAndLeaders = sysUserMapper.selectListEmpAndLeader(lvzxDeptPath);
return empAndLeaders.stream().collect(Collectors.toMap(m -> m.get("user_name"), m -> m.get("leader_emp_code")));
}
}
......@@ -30,6 +30,14 @@ public class SysDept implements Serializable {
* 部门名称
*/
private String deptName;
/**
* 销售部门名称
*/
private String deptNameSale;
/**
* 销售部门名称是否同步飞书名称;0:同步;1:不同步
*/
private String deptNameSaleIsFs;
/**
* 飞书部门IDopen_department_id
......
......@@ -46,6 +46,9 @@ public class SysUser implements Serializable {
*/
private String fsUserId;
private String fsOpenId;
private String leaderFsOpenId;
private String leaderEmpCode;
private String leaderEmpName;
/**
* 用户邮箱
......
......@@ -25,6 +25,7 @@ public interface SysDeptMapper extends BaseMapper<SysDept> {
List<HashMap<String, String>> getDeptCodeAndNameMap();
SysDept selectOneByDeptCode(String deptCode);
}
......
......@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
......@@ -25,6 +26,16 @@ public interface SysUserMapper extends BaseMapper<SysUser> {
void updateStatus(@Param("employeeNo") String employeeNo);
List<HashMap<String, String>> getUserNoAndNameMap();
void updateOffboardDate(@Param("employeeNo") String employeeNo, @Param("offboardDate") Date offboardDate);
List<String> selectResignedUsers();
void putById(SysUser sysUser);
void updateUserLeader();
List<HashMap<String, String>> selectListEmpAndLeader(String lvzxDeptPath);
}
......
package com.sfa.job.pojo.qince.response;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
/**
* @author : liqiulin
* @date : 2025-12-29 17
* @describe :
*/
@Data
public class QinceEmployeeDto {
/**
* 主键id
*/
private Integer id;
/**
* 勤策的员工唯一标识
*/
private String qcId;
/**
* 来源第三方系统的员工唯一标识
*/
private String empId;
/**
* 员工登录帐号
*/
private String empCode;
/**
* 姓名
*/
private String empName;
/**
* 员工别名
*/
private String aliasName;
/**
* 人员编码
*/
private String employeeCode;
/**
* 员工手机号码
*/
private String empMobile;
/**
* 员工手机地区码
*/
private String mobileDistrictCode;
/**
* 固定电话,示例:025-68736873
*/
private String empTel;
/**
* 来源第三方系统隶属部门
*/
private String empOrgId;
/**
* 隶属部门编码
*/
private String empOrgCode;
/**
* 勤策部门唯一标识
*/
private String waiqin365OrgId;
/**
* 来源第三方系统,员工上级唯一标识
*/
private String empParentId;
/**
* 员工上级编码
*/
private String parentCode;
/**
* 勤策员工上级唯一标识
*/
private String waiqin365ParentId;
/**
* 员工账号状态。0:销户,1:正常,2:停用
*/
private String empStatus;
/**
* 手机卡绑定。0:不绑定,1:绑定
*/
private String empImsiBinding;
/**
* 勤策经销商唯一标识
*/
private String dealerId;
/**
* 经销商中文名称
*/
private String dealerName;
/**
* 创建时间
*/
private String createTime;
/**
* 修改时间
*/
private String modifyTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}
package com.sfa.job.service.feishu;
import com.alibaba.fastjson2.JSONObject;
import com.lark.oapi.service.corehr.v1.model.Offboarding;
import com.lark.oapi.service.corehr.v2.model.*;
import com.sfa.common.core.enums.promotion.PlanStatus;
import com.sfa.common.core.utils.DateUtils;
import com.sfa.common.core.utils.sdk.FeiShuUtil;
import com.sfa.job.domain.promotion.dao.IActivityPlanDao;
import com.sfa.job.domain.system.dao.ISysDeptDao;
......@@ -11,12 +13,14 @@ import com.sfa.job.domain.system.dao.ISysUserDao;
import com.sfa.job.pojo.feishu.event.EventCallBackDto;
import com.sfa.job.pojo.promotion.response.ActivityPlanApprovalDto;
import com.sfa.job.pojo.response.SysEventLogDto;
import com.sfa.job.service.system.IDeptAndUserService;
import com.sfa.job.util.T100Util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.Objects;
/**
......@@ -36,6 +40,8 @@ public class EventCallbackServiceImpl implements IEventCallbackService{
@Autowired
private ISysEventLogDao sysEventLogDao;
@Autowired
private IDeptAndUserService deptAndUserService;
@Autowired
private FeiShuUtil feiShuUtil;
@Autowired
private T100Util t100Util;
......@@ -187,13 +193,25 @@ public class EventCallbackServiceImpl implements IEventCallbackService{
*/
@Override
public void userResigned(String employmentId) {
// 根据employmentId查询离职信息,如果没有搜索到离职信息,则直接禁用
Date offboardDate = null;
Offboarding offboarding = feiShuUtil.searchOffboardings(employmentId);
if (!Objects.isNull(offboarding)){
String offboardingDate = offboarding.getOffboardingInfo().getOffboardingDate();
offboardDate = DateUtils.parseDate(offboardingDate);
}
Employee emp = feiShuUtil.getEmployeeReq(employmentId);
String employeeNo = emp.getEmployeeNumber();
if (StringUtils.isEmpty(employeeNo)){
return;
}
// 链路中心人员离职
sysUserDao.deleteUser(employeeNo);
sysUserDao.updateOffboardDate(employeeNo,offboardDate);
// 判定offboardDate 是否是以前
if (!offboardDate.before(new Date())){
return;
}
deptAndUserService.userResigned(employeeNo);
}
private void userAUT100(Employee emp){
......
......@@ -7,10 +7,7 @@ package com.sfa.job.service.qince;
*/
public interface IQinceDealerQueryService {
void updateQinceDealerInfo();
void queryCusVisitRecord();
void updateQinceStore();
}
package com.sfa.job.service.qince;
/**
* @author : liqiulin
* @date : 2025-12-29 17
* @describe :
*/
public interface IQinceEmpAndDeptService {
void syncQinceEmpLeaderInfo();
void syncQinceDealerUserLeaderInfo();
}
......@@ -2,12 +2,9 @@ package com.sfa.job.service.qince.impl;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sfa.job.domain.feishu.dao.IQinceMarketEmployeeDao;
import com.sfa.job.domain.qince.dao.IQinceClienteleStoreDao;
import com.sfa.job.domain.system.dao.ISysDeptDao;
import com.sfa.job.domain.system.dao.ISysUserDao;
import com.sfa.job.pojo.feishu.response.QinceMarketEmployeeDto;
import com.sfa.job.pojo.qince.response.QinceClienteleStoreDto;
import com.sfa.job.service.qince.IQinceDealerQueryService;
......@@ -34,10 +31,6 @@ public class QinceDealerQueryServiceImpl implements IQinceDealerQueryService {
@Autowired
private IQinceMarketEmployeeDao qinceMarketEmployeeDao;
@Autowired
private ISysDeptDao sysDeptDao;
@Autowired
private ISysUserDao sysUserDao;
@Autowired
private QinCeUtils qinCeUtils;
@Override
......@@ -50,18 +43,12 @@ public class QinceDealerQueryServiceImpl implements IQinceDealerQueryService {
log.info("push qc 经销商(架构): 今日无新增/修改经销商");
return;
}
// 查询部门Map<部门编码,部门名称>,人员Map<工号,姓名>
// Map<String,String> deptMap = sysDeptDao.getDeptCodeAndNameMap();
// Map<String,String> userMap = sysUserDao.getUserNoAndNameMap();
/**
* 2. 反写勤策中的自定义字段:大区、战区
*/
for (QinceMarketEmployeeDto mDto : mDtos) {
try {
Map<String, Object> ext1 = new HashMap<>();
// String dqtq = "BM0020".equals(mDto.getDqDeptCode()) ? "北京特区" : deptMap.get(mDto.getDqDeptCode());
ext1.put("dealer_ext_key", "大区");
ext1.put("dealer_ext_value",mDto.getDqDeptName());
......@@ -73,9 +60,6 @@ public class QinceDealerQueryServiceImpl implements IQinceDealerQueryService {
params.put("dealer_id", mDto.getDealerCode());
params.put("exts", Arrays.asList(ext1, ext2));
params.put("dealer_emp_code", mDto.getFEmpNo());
// params.put("dealer_manager", mDto.getFEmpName());
String url = qinCeUtils.builderUrl(QinCeUtils.MODIFY_DEALER, params);
qinCeUtils.postQC(url, params);
log.info("push qc 经销商(架构)success:{}:{}", mDto.getDealerName(), JSONObject.toJSONString(params));
......@@ -104,7 +88,7 @@ public class QinceDealerQueryServiceImpl implements IQinceDealerQueryService {
String queryDate = DateUtil.yesterday().toString(DatePattern.NORM_DATE_PATTERN);
Map<String, Object> params = qinCeUtils.queryCusVisitRecordParams(queryDate);
String url = qinCeUtils.builderUrl(QinCeUtils.QUERY_CUS_VISIT_RECORD, params);
JSONArray recordsJson = qinCeUtils.postArray(url, params);
qinCeUtils.postArray(url, params);
} catch (Exception e) {
log.error("查询城市经理客户拜访失败:{}", e.getMessage());
}
......@@ -113,7 +97,7 @@ public class QinceDealerQueryServiceImpl implements IQinceDealerQueryService {
@Override
public void updateQinceStore() {
// 查询昨日新增终端
// 查询昨日新增或修改的终端
String yesterday = DatePattern.NORM_DATE_FORMAT.format(DateUtil.yesterday());
List<QinceClienteleStoreDto> storeDtoList = qinceClienteleStoreDao.findListByCreateDate(yesterday);
if (CollectionUtils.isEmpty(storeDtoList)){
......@@ -126,9 +110,6 @@ public class QinceDealerQueryServiceImpl implements IQinceDealerQueryService {
List<QinceMarketEmployeeDto> mDtos = qinceMarketEmployeeDao.selectByDealerCodes(groupStores.keySet());
Map<String, QinceMarketEmployeeDto> dealerMap = mDtos.stream().collect(Collectors.toMap(dto -> dto.getDealerCode(), dto -> dto));
// Map<String,String> deptMap = sysDeptDao.getDeptCodeAndNameMap();
// Map<String,String> userMap = sysUserDao.getUserNoAndNameMap();
for (Map.Entry<String, List<QinceClienteleStoreDto>> storesEntry : groupStores.entrySet()) {
QinceMarketEmployeeDto mDto = dealerMap.get(storesEntry.getKey());
if (mDto == null){
......@@ -136,7 +117,6 @@ public class QinceDealerQueryServiceImpl implements IQinceDealerQueryService {
continue;
}
List<QinceClienteleStoreDto> stores = storesEntry.getValue();
// String dqtq = "BM0020".equals(mDto.getDqDeptCode()) ? "北京特区" : deptMap.get(mDto.getDqDeptCode());
pushQinceStoreInfo(stores, mDto);
log.info("push qc 终端(架构/负责人)success:{}:{}", mDto.getDealerName(),stores.size());
}
......
package com.sfa.job.service.qince.impl;
import com.alibaba.fastjson2.JSONObject;
import com.sfa.common.core.utils.StringUtils;
import com.sfa.common.core.utils.sdk.FeiShuUtil;
import com.sfa.common.core.utils.sdk.FeiShuUtils;
import com.sfa.job.domain.feishu.dao.IQinceMarketEmployeeDao;
import com.sfa.job.domain.qince.dao.IQinceEmployeeDao;
import com.sfa.job.domain.system.dao.ISysUserDao;
import com.sfa.job.pojo.feishu.response.QinceMarketEmployeeDto;
import com.sfa.job.pojo.qince.response.QinceEmployeeDto;
import com.sfa.job.service.qince.IQinceEmpAndDeptService;
import com.sfa.job.util.QinCeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author : liqiulin
* @date : 2025-12-29 17
* @describe :
*/
@Slf4j
@Service
public class QinceEmpAndDeptServiceImpl implements IQinceEmpAndDeptService {
@Autowired
private QinCeUtils qinCeUtils;
@Autowired
private ISysUserDao sysUserDao;
@Autowired
private IQinceEmployeeDao qinceEmployeeDao;
@Autowired
private IQinceMarketEmployeeDao qinceMarketEmployeeDao;
@Override
public void syncQinceEmpLeaderInfo() {
// 查询飞书的上下级关系(仅区域销售部)
Map<String, String> empCodeAndLeader = sysUserDao.selectListEmpAndLeader();
List<QinceEmployeeDto> qinceEmployeeDtos = qinceEmployeeDao.selectListByEmpcodes(empCodeAndLeader.keySet());
log.info("飞书-区域销售部共【{}】人", qinceEmployeeDtos.size());
Set<String> leaderCodes = new HashSet<>(empCodeAndLeader.values());
List<QinceEmployeeDto> leaderDtos = qinceEmployeeDao.selectListByEmpcodes(leaderCodes);
Map<String, QinceEmployeeDto> leaderEmpInfoMap = leaderDtos.stream().collect(Collectors.toMap(m -> m.getEmpCode(), m -> m));
log.info("飞书关联勤策-区域销售部共【{}】人", qinceEmployeeDtos.size());
for (QinceEmployeeDto empDto : qinceEmployeeDtos) {
String leaderCode = empCodeAndLeader.get(empDto.getEmpCode());
QinceEmployeeDto leaderEmpInfo = leaderEmpInfoMap.get(leaderCode);
// 如果上级为空或上级未发生变化,则不处理
if (StringUtils.isBlank(leaderCode) || Objects.isNull(leaderEmpInfo) || leaderCode.equals(empDto.getParentCode())) {
continue;
}
updateQinceUserLeader("区域销售部",empDto,leaderEmpInfo);
}
}
/**
* 更新经销商业代人员上级
*/
@Override
public void syncQinceDealerUserLeaderInfo() {
// 查询经销商人客关系
List<QinceMarketEmployeeDto> marketDtos = qinceMarketEmployeeDao.selectByTodayUpdate();
// 查询客户经理的勤策个人信息
if (CollectionUtils.isEmpty(marketDtos)){
log.info("push qc 经销商业代上级: 今日无新增/修改经销商");
return;
}
Set<String> marketEmpCodes = marketDtos.stream().map(m -> m.getFEmpNo()).collect(Collectors.toSet());
List<QinceEmployeeDto> leaderDtos = qinceEmployeeDao.selectListByEmpcodes(marketEmpCodes);
Map<String, QinceEmployeeDto> leaderEmpInfoMap = leaderDtos.stream().collect(Collectors.toMap(m -> m.getEmpCode(), m -> m));
if (CollectionUtils.isEmpty(leaderDtos)){
String logText = "【ERROR】勤员人员信息中,无经销商客户经理信息,经销商包含:" + JSONObject.toJSONString(marketEmpCodes);
log.info(logText);
FeiShuUtils.pustRoot(FeiShuUtil.qinceWebhook, logText);
return;
}
for (QinceMarketEmployeeDto marketDto : marketDtos) {
updateQinceDealerUserLeader(marketDto,leaderEmpInfoMap);
}
}
/**
* 更新业代上级
*/
private void updateQinceDealerUserLeader(QinceMarketEmployeeDto marketDto,Map<String, QinceEmployeeDto> leaderEmpInfoMap){
// 查询勤策-经销商部门下的人员
String dealerCode = marketDto.getDealerCode();
List<QinceEmployeeDto> dealerEmpDtos = qinceEmployeeDao.selectListByOrgCode(dealerCode);
log.info("勤策经销商部门【{}:{}】下共【{}】位业代人员", dealerCode,marketDto.getDealerName(), dealerEmpDtos.size());
String fEmpNo = marketDto.getFEmpNo();
if (Objects.isNull(fEmpNo)){
return;
}
QinceEmployeeDto leaderEmpInfo = leaderEmpInfoMap.get(fEmpNo);
// 对比当前人员上级-经销商客户经理:不同则修改;相同则跳过
for (QinceEmployeeDto dealerEmpDto : dealerEmpDtos) {
if (Objects.nonNull(dealerEmpDto.getParentCode()) && fEmpNo.equals(dealerEmpDto.getParentCode())){
continue;
}
updateQinceUserLeader(marketDto.getDealerName(),dealerEmpDto,leaderEmpInfo);
}
}
/**
* @param empDto 员工对象
* @param leaderEmpInfo 员工上级对象
*/
private void updateQinceUserLeader(String qcDeptName,QinceEmployeeDto empDto,QinceEmployeeDto leaderEmpInfo){
String logtext;
try {
Map<String, Object> params = qinCeUtils.putUserLeaderParams(empDto.getQcId(), leaderEmpInfo.getQcId());
String url = qinCeUtils.builderUrl(QinCeUtils.MODIFY_USER, params);
qinCeUtils.postQC(url, params);
logtext = "【OK】更新勤策「"+qcDeptName+"」部门的【" + empDto.getEmpCode() + ":" + empDto.getEmpName() + "】上级Leader为【" + leaderEmpInfo.getEmpCode() + ":" + leaderEmpInfo.getEmpName() + "】成功";
log.info(logtext);
} catch (Exception e) {
logtext = "【ERROR】更新勤策「"+qcDeptName+"」部门的【" + empDto.getEmpCode() + ":" + empDto.getEmpName() + "】上级Leader信息失败:" + e.getMessage();
log.error(logtext);
}
FeiShuUtils.pustRoot(FeiShuUtil.qinceWebhook, logtext);
}
}
......@@ -3,14 +3,19 @@ package com.sfa.job.service.system;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.sfa.common.core.utils.sdk.FeiShuUtil;
import com.sfa.job.domain.qince.dao.IQinceEmployeeDao;
import com.sfa.job.domain.system.dao.ISysDeptDao;
import com.sfa.job.domain.system.dao.ISysUserDao;
import com.sfa.job.domain.system.entity.SysDept;
import com.sfa.job.util.QinCeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
/**
* @author : liqiulin
......@@ -27,7 +32,10 @@ public class DeptAndUserServiceImpl implements IDeptAndUserService {
private ISysDeptDao sysDeptDao;
@Autowired
private ISysUserDao sysUserDao;
@Autowired
private IQinceEmployeeDao qinceEmployeeDao;
@Autowired
private QinCeUtils qinCeUtils;
/**
* 从飞书同步全量部门信息
*/
......@@ -62,8 +70,42 @@ public class DeptAndUserServiceImpl implements IDeptAndUserService {
}
insertOrUpdateUsers(users,dept.getDeptId());
}
sysUserDao.updateDeptLeader();
sysUserDao.updateUserLeader();
}
@Override
public void userResigned(String employeeNo) {
//1、链路中心人员离职 - 根据工号
sysUserDao.deleteUser(employeeNo);
//2、勤策人员离职 - 根据工号+勤策ID
try {
String empQcId = qinceEmployeeDao.getQcIdByEmpCode(employeeNo);
if (StringUtils.isEmpty(empQcId)){
return;
}
Map<String, Object> map = qinCeUtils.disabledUserParams(employeeNo,empQcId);
String url = qinCeUtils.builderUrl(QinCeUtils.MODIFY_USER, map);
qinCeUtils.postQC(url, map);
qinceEmployeeDao.userResigned(empQcId);
}catch (Exception e){
log.error("勤策接口禁用用户异常,详情:{}",e.getMessage());
}
}
@Override
public void usersResigned() {
// 查询离职日期是今日及以前,且状态是未离职人员
List<String> resignedUsers = sysUserDao.selectResignedUsers();
if (CollectionUtils.isEmpty(resignedUsers)){
log.info("今日暂无需要处理的离职人员;");
return;
}
for (String userCode : resignedUsers){
userResigned(userCode);
}
}
/**
......
......@@ -10,4 +10,9 @@ public interface IDeptAndUserService {
void deptAll();
void userAll();
void userResigned(String employeeNo);
void usersResigned();
}
......@@ -48,6 +48,9 @@ public class QinCeUtils {
public static final String QUERY_CUS_VISIT_RECORD = "/api/cusVisit/v1/queryCusVisitRecord/";
// 直营发货单自定义字段更新
public static final String MODIFY_SENT_DEFINED_VAL = "/api/dmssent/v1/modifyUseDefinedVal/";
// 修改人员
public static final String MODIFY_USER = "/api/employee/v3/modifyEmployee/";
public String builderUrl(String sidepath, Map<String, Object> params) {
......@@ -84,6 +87,23 @@ public class QinCeUtils {
return params;
}
public Map<String,Object> disabledUserParams(String userCode,String qcId){
Map<String,Object> params = new HashMap<>();
// 员工登录帐号
params.put("emp_code",userCode);
params.put("id",qcId);
// 员工账号状态。0:删除,1:正常,2:停用
// 不传,默认值为1
params.put("emp_status", "2");
return params;
}
public Map<String,Object> putUserLeaderParams(String qcId,String leaderQcId){
Map<String,Object> params = new HashMap<>();
params.put("id",qcId);
params.put("waiqin365_parent_id", leaderQcId);
return params;
}
public JSONObject postQC(String url, Object params) throws Exception {
......
package com.sfa.job.xxljob.qince;
import com.sfa.job.service.qince.IQinceDealerQueryService;
import com.sfa.job.service.qince.IQinceEmpAndDeptService;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -15,7 +16,9 @@ import org.springframework.stereotype.Component;
@Slf4j
public class QinceCoreTask {
@Autowired
private IQinceDealerQueryService qinceCoreService;
private IQinceDealerQueryService qinceDealerQueryService;
@Autowired
private IQinceEmpAndDeptService qinceEmpAndDeptService;
/**
* 回写勤策-经销商大区、战区信息
......@@ -24,7 +27,7 @@ public class QinceCoreTask {
@XxlJob("qince_modify_dealer")
public void qinceCoreTask() {
log.info("回写勤策-经销商大区、战区信息 start");
qinceCoreService.updateQinceDealerInfo();
qinceDealerQueryService.updateQinceDealerInfo();
log.info("回写勤策-经销商大区、战区信息 end");
}
......@@ -34,17 +37,32 @@ public class QinceCoreTask {
@XxlJob("qince_modify_store")
public void qinceCoreStore(){
log.info("回写勤策-终端详情 start");
qinceCoreService.updateQinceStore();
qinceDealerQueryService.updateQinceStore();
log.info("回写勤策-终端详情 end");
}
/**
* 同步完飞书组织架构(sync_feishu_user)
* 同步勤策t-1人员信息(qince_employee_task)
* 根据飞书上下级关系,同步勤策上下级信息
*/
@XxlJob("qince_modify_emp_leader")
public void updateQinceEmpLeader() {
log.info("同步勤策员工上下级关系 start");
// 同步内部员工
qinceEmpAndDeptService.syncQinceEmpLeaderInfo();
// 同步经销商业代
qinceEmpAndDeptService.syncQinceDealerUserLeaderInfo();
log.info("同步勤策员工上下级关系 end");
}
/**
* 暂停开发
*/
// @XxlJob("qince_cus_visit_record")
public void queryCusVisitRecord() {
log.info("查询勤策客户拜访记录 start");
qinceCoreService.queryCusVisitRecord();
qinceDealerQueryService.queryCusVisitRecord();
log.info("查询勤策客户拜访记录 start");
}
}
......@@ -37,4 +37,14 @@ public class SystemTask {
deptAndUserService.userAll();
log.info("结束同步飞书用户数据");
}
/**
* 同步人员离职
*/
@XxlJob("sync_user_resigned")
public void userResigned() {
log.info("开始处理离职人员");
deptAndUserService.usersResigned();
log.info("结束处理离职人员");
}
}
......@@ -4,10 +4,12 @@
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sfa.job.domain.system.mapper.SysDeptMapper">
<resultMap id="BaseResultMap" type="com.sfa.job.domain.system.entity.SysDept">
<resultMap id="SysDeptBase" type="com.sfa.job.domain.system.entity.SysDept">
<id property="deptId" column="dept_id" jdbcType="BIGINT"/>
<result property="deptCode" column="dept_code" jdbcType="VARCHAR"/>
<result property="deptName" column="dept_name" jdbcType="VARCHAR"/>
<result property="deptNameSale" column="dept_name_sale" jdbcType="VARCHAR"/>
<result property="deptNameSaleIsFs" column="dept_name_sale_is_fs" jdbcType="VARCHAR"/>
<result property="fsDeptId" column="fs_dept_id" jdbcType="VARCHAR"/>
<result property="parentId" column="parent_id" jdbcType="BIGINT"/>
<result property="parentCode" column="parent_code" jdbcType="VARCHAR"/>
......@@ -90,4 +92,8 @@
<select id="getDeptCodeAndNameMap" resultType="java.util.HashMap">
select dept_code,dept_name from sys_dept where del_flag = '0';
</select>
<select id="selectOneByDeptCode" resultMap="SysDeptBase">
select * from sys_dept where dept_code = #{deptCode}
</select>
</mapper>
......@@ -102,4 +102,39 @@
from sys_user where del_flag = 0
</select>
<update id="updateOffboardDate">
update sys_user set offboard_date = #{offboardDate} where user_name = #{employeeNo}
</update>
<select id="selectResignedUsers" resultType="java.util.List">
select user_name from sys_user where del_flag = '0' and offboard_date &lt;= current_date();
</select>
<update id="putById" parameterType="com.sfa.job.domain.system.entity.SysUser">
update sys_user set
dept_id = #{deptId},
nick_name = #{nickName},
email = #{email},
phonenumber = #{phonenumber},
work_city_name = #{workCityName},
update_by = #{updateBy},
fs_open_id = #{fsOpenId},
leader_fs_open_id = #{leaderFsOpenId},
update_user_id = #{updateUserId}
where user_id = #{userId}
</update>
<update id="updateUserLeader">
update sys_user su1 inner join sys_user su2 on su1.leader_fs_open_id = su2.fs_open_id
set su1.leader_emp_code = su2.user_name,su1.leader_emp_name = su2.nick_name
where su1.del_flag = 0;
</update>
<select id="selectListEmpAndLeader" resultType="java.util.HashMap">
select user_name,leader_emp_code
from sys_user
where del_flag = '0'
and leader_emp_code is not null
and dept_id in (select dept_id from sys_dept where del_flag = '0' and ancestors like concat(#{lvzxDeptPath},'%'))
</select>
</mapper>
......@@ -13,6 +13,6 @@
<select id="findListByCreateDate" resultType="com.sfa.job.domain.qince.entity.QinceClienteleStore">
select qc_id, store_name, store_code,dealer_id,dealers_name,create_time
from qince_clientele_store
where create_time like concat(#{yesterday},'%') and store_status = '1'
where dealer_id is not null and store_status = '1' and store_modifyier_name != '外部系统' and (create_time like concat(#{yesterday}, '%') or store_modify_time like concat(#{yesterday}, '%'))
</select>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sfa.job.domain.qince.mapper.QinceEmployeeMapper">
<resultMap id="QinceEmployeeBase" type="com.sfa.job.domain.qince.entity.QinceEmployee">
<id property="id" column="id" jdbcType="INTEGER"/>
<result property="qcId" column="qc_id" jdbcType="VARCHAR"/>
<result property="empId" column="emp_id" jdbcType="VARCHAR"/>
<result property="empCode" column="emp_code" jdbcType="VARCHAR"/>
<result property="empName" column="emp_name" jdbcType="VARCHAR"/>
<result property="aliasName" column="alias_name" jdbcType="VARCHAR"/>
<result property="employeeCode" column="employee_code" jdbcType="VARCHAR"/>
<result property="empSex" column="emp_sex" jdbcType="CHAR"/>
<result property="empMobile" column="emp_mobile" jdbcType="VARCHAR"/>
<result property="mobileDistrictCode" column="mobile_district_code" jdbcType="VARCHAR"/>
<result property="empTel" column="emp_tel" jdbcType="VARCHAR"/>
<result property="empBirthday" column="emp_birthday" jdbcType="CHAR"/>
<result property="empQq" column="emp_qq" jdbcType="VARCHAR"/>
<result property="empWeixin" column="emp_weixin" jdbcType="VARCHAR"/>
<result property="empWechatCode" column="emp_wechat_code" jdbcType="VARCHAR"/>
<result property="empIdcard" column="emp_idcard" jdbcType="VARCHAR"/>
<result property="empEmail" column="emp_email" jdbcType="VARCHAR"/>
<result property="empAddr" column="emp_addr" jdbcType="VARCHAR"/>
<result property="empOrgId" column="emp_org_id" jdbcType="VARCHAR"/>
<result property="empOrgCode" column="emp_org_code" jdbcType="VARCHAR"/>
<result property="waiqin365OrgId" column="waiqin365_org_id" jdbcType="VARCHAR"/>
<result property="empParentId" column="emp_parent_id" jdbcType="VARCHAR"/>
<result property="parentCode" column="parent_code" jdbcType="VARCHAR"/>
<result property="waiqin365ParentId" column="waiqin365_parent_id" jdbcType="VARCHAR"/>
<result property="empIsOrgLearder" column="emp_is_org_learder" jdbcType="CHAR"/>
<result property="empStatus" column="emp_status" jdbcType="CHAR"/>
<result property="empImsiBinding" column="emp_imsi_binding" jdbcType="CHAR"/>
<result property="dealerId" column="dealer_id" jdbcType="VARCHAR"/>
<result property="dealerName" column="dealer_name" jdbcType="VARCHAR"/>
<result property="empBaseprovince" column="emp_baseprovince" jdbcType="VARCHAR"/>
<result property="empBasecity" column="emp_basecity" jdbcType="VARCHAR"/>
<result property="waiqin365PositionId" column="waiqin365_position_id" jdbcType="VARCHAR"/>
<result property="empPositionCode" column="emp_position_code" jdbcType="VARCHAR"/>
<result property="empPosition" column="emp_position" jdbcType="VARCHAR"/>
<result property="waiqin365JobId" column="waiqin365_job_id" jdbcType="VARCHAR"/>
<result property="empJobCode" column="emp_job_code" jdbcType="VARCHAR"/>
<result property="empJob" column="emp_job" jdbcType="VARCHAR"/>
<result property="mobileAuth" column="mobile_auth" jdbcType="CHAR"/>
<result property="terminalType" column="terminal_type" jdbcType="VARCHAR"/>
<result property="faceTime" column="face_time" jdbcType="VARCHAR"/>
<result property="empEnrollmentTime" column="emp_enrollment_time" jdbcType="VARCHAR"/>
<result property="empResignationTime" column="emp_resignation_time" jdbcType="VARCHAR"/>
<result property="lastUseTime" column="last_use_time" jdbcType="VARCHAR"/>
<result property="createTime" column="create_time" jdbcType="VARCHAR"/>
<result property="modifyTime" column="modify_time" jdbcType="VARCHAR"/>
</resultMap>
<update id="userResigned" parameterType="java.lang.String">
update qince_employee set emp_status = '2',emp_resignation_time = now() where qc_id = #{empQcId}
</update>
</mapper>
package com.sfa.job.service.feishu;
import com.sfa.common.core.utils.DateUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Date;
import static org.junit.Assert.*;
/**
* @author : liqiulin
* @date : 2025-12-05 16
* @describe :
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class EventCallbackServiceImplTest {
@Autowired
private IEventCallbackService eventCallbackService;
@Test
public void userResigned() {
eventCallbackService.userResigned("7566837232418670089");
}
public static void main(String[] args) {
String offboardingDate = "2025-11-28";
Date date = DateUtils.parseDate(offboardingDate);
System.out.println(date);
}
}
\ No newline at end of file
package com.sfa.job.service.system;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.Assert.*;
......@@ -9,9 +13,14 @@ import static org.junit.Assert.*;
* @date : 2024-12-10 15
* @describe :
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class DeptAndUserServiceImplTest {
@Autowired
private IDeptAndUserService deptAndUserService;
@Test
public void userAll() {
deptAndUserService.usersResigned();
}
}
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论