yudao-module-hrm-api/src/main/java/cn/iocoder/yudao/module/hrm/enums/ErrorCodeConstants.java
@@ -31,6 +31,8 @@ ErrorCode EMPLOYEE_CONTRACT_IMPORT_EMPLOYEE_NAME_NOT_EXISTS = new ErrorCode(1_030_000_018, "员工姓名【{}】不存在,请先维护员工档案"); ErrorCode EMPLOYEE_CONTRACT_IMPORT_EMPLOYEE_NAME_MULTIPLE = new ErrorCode(1_030_000_019, "员工姓名【{}】对应多个员工档案,无法自动匹配,请先在页面手工为该员工新增合同"); ErrorCode EMPLOYEE_CONTRACT_IMPORT_CONTRACT_EXISTS = new ErrorCode(1_030_000_020, "该员工【{}】已存在相同类型、相同开始日期的合同,如需覆盖请勾选“已存在时更新”"); ErrorCode EMPLOYEE_PHONE_OCCUPIED_BY_DELETED = new ErrorCode(1_030_000_021, "手机号【{}】已被一条【已删除】的员工档案占用,请更换手机号,或联系管理员清理该历史档案"); ErrorCode EMPLOYEE_NO_OCCUPIED_BY_DELETED = new ErrorCode(1_030_000_022, "员工编号【{}】已被一条【已删除】的员工档案占用,请更换员工编号,或联系管理员清理该历史档案"); // ========== 请假申请 1-030-001-000 ========== ErrorCode LEAVE_APPLICATION_NOT_EXISTS = new ErrorCode(1_030_001_000, "请假申请不存在"); yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/dal/mysql/employee/HrmEmployeeMapper.java
@@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.HrmEmployeePageReqVO; import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeDO; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import java.util.Collection; import java.util.List; @@ -23,6 +25,20 @@ return selectOne(HrmEmployeeDO::getPhone, phone); } /** * 按手机号查询(**包含已逻辑删除的记录**)。 * 唯一性校验必须包含已删除记录:hrm_employee.uk_phone 唯一索引不区分 deleted, * 若只查未删除记录会漏判,写库时抛唯一约束异常,前端表现为“系统异常”。 */ @Select("SELECT * FROM hrm_employee WHERE phone = #{phone} LIMIT 1") HrmEmployeeDO selectByPhoneIgnoreDeleted(@Param("phone") String phone); /** * 按员工编号查询(**包含已逻辑删除的记录**),用途同上。 */ @Select("SELECT * FROM hrm_employee WHERE employee_no = #{employeeNo} LIMIT 1") HrmEmployeeDO selectByEmployeeNoIgnoreDeleted(@Param("employeeNo") String employeeNo); default HrmEmployeeDO selectByName(String name) { return selectOne(HrmEmployeeDO::getName, name); } yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java
@@ -104,9 +104,15 @@ deptApi.validateDeptList(Collections.singleton(createReqVO.getDeptId())); // 2. 校验岗位 postApi.validPostList(createReqVO.getPostIds()); // 3. 校验手机号是否已存在 if (employeeMapper.selectByPhone(createReqVO.getPhone()) != null) { throw exception(EMPLOYEE_PHONE_EXISTS); // 3. 校验手机号是否已存在(**包含已删除档案**:uk_phone 唯一索引不区分 deleted, // 只查未删除记录会漏判,导致写库时抛唯一约束异常,前端显示“系统异常”) if (createReqVO.getPhone() != null) { HrmEmployeeDO existPhone = employeeMapper.selectByPhoneIgnoreDeleted(createReqVO.getPhone()); if (existPhone != null) { throw existPhone.getDeleted() != null && existPhone.getDeleted() ? exception(EMPLOYEE_PHONE_OCCUPIED_BY_DELETED, createReqVO.getPhone()) : exception(EMPLOYEE_PHONE_EXISTS); } } // 4. 同步创建系统用户 AdminUserCreateReqDTO userCreateReqDTO = new AdminUserCreateReqDTO(); @@ -186,10 +192,14 @@ deptApi.validateDeptList(Collections.singleton(updateReqVO.getDeptId())); // 校验岗位 postApi.validPostList(updateReqVO.getPostIds()); // 校验手机号是否已存在(如果手机号有变更) if (!Objects.equals(employee.getPhone(), updateReqVO.getPhone()) && employeeMapper.selectByPhone(updateReqVO.getPhone()) != null) { throw exception(EMPLOYEE_PHONE_EXISTS); // 校验手机号是否已存在(如果手机号有变更;**包含已删除档案**,原因见 createEmployee) if (!Objects.equals(employee.getPhone(), updateReqVO.getPhone()) && updateReqVO.getPhone() != null) { HrmEmployeeDO existPhone = employeeMapper.selectByPhoneIgnoreDeleted(updateReqVO.getPhone()); if (existPhone != null && !Objects.equals(existPhone.getId(), updateReqVO.getId())) { throw existPhone.getDeleted() != null && existPhone.getDeleted() ? exception(EMPLOYEE_PHONE_OCCUPIED_BY_DELETED, updateReqVO.getPhone()) : exception(EMPLOYEE_PHONE_EXISTS); } } // 更新员工主表 HrmEmployeeDO updateObj = BeanUtils.toBean(updateReqVO, HrmEmployeeDO.class); yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java
@@ -223,6 +223,7 @@ } @Override @DataPermission(enable = false) // 仅校验部门是否存在/启用,不受数据权限限制(否则非超管会误报"部门不存在") public void validateDeptList(Collection<Long> ids) { if (CollUtil.isEmpty(ids)) { return;