Commit f4f0c70b authored by 刘斌's avatar 刘斌

fix: 完善入职离职

parent 56f2abf2
......@@ -4,8 +4,10 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.scheduling.annotation.EnableAsync;
@Slf4j
@EnableAsync
@EnableCaching
@SpringBootApplication(scanBasePackages = {"top.binfast.daemon.codegen", "top.binfast.app", "com.example"})
public class Application {
......
package com.example.constant;
/**
* @author 刘斌
* @date 2025/10/30 14:54
*/
public interface HrDeptLevel {
Integer DEPT_LEVEL_ONE = 1;
Integer DEPT_LEVEL_TWO = 2;
}
package com.example.constant;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @author 刘斌
* @date 2025/10/30 16:57
*/
@Getter
@AllArgsConstructor
public enum HrFlowEnum {
/**
* 草稿
*/
DRAFT(0, "草稿"),
/**
* 待审核
*/
WAITING(1, "待审核"),
/**
* 已完成
*/
FINISH(2, "已完成");
/**
* 状态
*/
private final Integer status;
/**
* 描述
*/
private final String desc;
private static final Map<Integer, HrFlowEnum> STATUS_MAP = Arrays.stream(HrFlowEnum.values())
.collect(Collectors.toConcurrentMap(HrFlowEnum::getStatus, Function.identity()));
}
package com.example.controller;
import java.util.List;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.alibaba.cola.dto.MultiResponse;
import com.alibaba.cola.dto.PageResponse;
import com.alibaba.cola.dto.Response;
import com.alibaba.cola.dto.SingleResponse;
import com.example.domain.params.EmployeeDeptListParam;
import com.example.domain.params.EmployeeDeptParam;
import com.example.domain.vo.EmployeeDeptVo;
import com.example.service.EmployeeDeptServ;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import top.binfast.common.core.constant.BusinessType;
import top.binfast.common.core.util.ResponseUtils;
import top.binfast.common.core.validate.AddGroup;
import top.binfast.common.core.validate.EditGroup;
import top.binfast.common.core.util.ResponseUtils;
import top.binfast.common.excel.annotion.ExcelExport;
import top.binfast.common.log.annotation.PinSysLog;
import com.example.domain.params.EmployeeDeptListParam;
import com.example.domain.params.EmployeeDeptParam;
import com.example.domain.vo.EmployeeDeptVo;
import com.example.service.EmployeeDeptServ;
import java.util.List;
/**
* 员工部门
......@@ -30,7 +32,7 @@ import com.example.service.EmployeeDeptServ;
*/
@Validated
@RestController
@RequestMapping("/app/dept")
@RequestMapping("/employee/dept")
public class EmployeeDeptCtrl {
@Resource
......@@ -39,7 +41,7 @@ public class EmployeeDeptCtrl {
/**
* 查询员工部门列表
*/
@SaCheckPermission("app:dept:list")
@SaCheckPermission("employee:dept:list")
@GetMapping("/page")
public PageResponse<EmployeeDeptVo> pageList(EmployeeDeptListParam param) {
return employeeDeptServ.queryPageList(param);
......@@ -49,19 +51,39 @@ public class EmployeeDeptCtrl {
* 导出员工部门列表
*/
@ExcelExport
@SaCheckPermission("app:dept:export")
@SaCheckPermission("employee:dept:export")
@PinSysLog(value = "员工部门", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public List<EmployeeDeptVo> export(EmployeeDeptListParam param) {
return employeeDeptServ.queryList(param);
}
/**
* 根据部门级别查询部门名称
*
* @param level 部门级别
*/
@GetMapping("/deptNames/{level}")
public MultiResponse<String> getDeptNamesByLevel(@PathVariable @Min(1) Integer level) {
return MultiResponse.of(employeeDeptServ.selectDeptNamesByLevel(level));
}
/**
* 根据父级部门名称查询部门名称
*
* @param parentName 父级部门名称
*/
@GetMapping("/deptNamesByParentName/{parentName}")
public MultiResponse<String> getDeptNamesByParentName(@PathVariable @NotBlank String parentName) {
return MultiResponse.of(employeeDeptServ.selectDeptNamesByParentName(parentName));
}
/**
* 获取员工部门详细信息
*
* @param id 主键
*/
@SaCheckPermission("app:dept:query")
@SaCheckPermission("employee:dept:query")
@GetMapping("/{id}")
public SingleResponse<EmployeeDeptVo> getDetail(@PathVariable @Min(1)
Long id) {
......@@ -71,7 +93,7 @@ public class EmployeeDeptCtrl {
/**
* 新增员工部门
*/
@SaCheckPermission("app:dept:add")
@SaCheckPermission("employee:dept:add")
@PinSysLog(value = "员工部门", businessType = BusinessType.INSERT)
@PostMapping()
public Response add(@Validated(AddGroup.class) @RequestBody EmployeeDeptParam param) {
......@@ -81,7 +103,7 @@ public class EmployeeDeptCtrl {
/**
* 修改员工部门
*/
@SaCheckPermission("app:dept:edit")
@SaCheckPermission("employee:dept:edit")
@PinSysLog(value = "员工部门", businessType = BusinessType.UPDATE)
@PutMapping()
public Response edit(@Validated(EditGroup.class) @RequestBody EmployeeDeptParam param) {
......@@ -93,7 +115,7 @@ public class EmployeeDeptCtrl {
*
* @param ids 主键串
*/
@SaCheckPermission("app:dept:remove")
@SaCheckPermission("employee:dept:remove")
@PinSysLog(value = "员工部门", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public Response remove(@NotEmpty(message = "主键不能为空")
......
......@@ -93,6 +93,7 @@ public class EmployeeInfoCtrl {
*
* @param id 主键
*/
@TransMethodResult
@SaCheckPermission("employee:info:query")
@GetMapping("/{id}")
public SingleResponse<EmployeeInfoVo> getDetail(@PathVariable @Min(1)
......@@ -120,7 +121,15 @@ public class EmployeeInfoCtrl {
return ResponseUtils.ofResult(employeeInfoServ.updateByParam(param));
}
/**
* 申请离职
*/
@SaCheckPermission("employee:info:resign")
@PinSysLog(value = "员工信息-申请离职", businessType = BusinessType.UPDATE)
@PutMapping("/applyResign/{id}")
public Response applyResign(@PathVariable @Min(1) Long id) {
return ResponseUtils.ofResult(employeeInfoServ.applyResign(id));
}
/**
* 删除员工信息
......
......@@ -28,11 +28,21 @@ public class EmployeeDept extends TenantModel {
*/
private Long parentId;
/**
* 父级部门名称
*/
private String parentName;
/**
* 部门名称
*/
private String name;
/**
* 部门层级
*/
private Integer level;
/**
* 祖级关系
*/
......
......@@ -265,5 +265,15 @@ public class EmployeeInfo extends BaseModel {
*/
private String resignationReason;
/**
* 离职审批状态
*/
private Integer resignationStatus;
/**
* 入职审批状态
*/
private Integer entryStatus;
}
package com.example.domain.params;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Set;
/**
* @author 刘斌
* @date 2025/10/30 11:59
*/
@Data
@AllArgsConstructor
public class EmployeeDeptCheckAndSaveParam {
private Set<String> deptNames;
private Long userId;
private Long tenantId;
}
......@@ -21,6 +21,11 @@ public class EmployeeDeptListParam extends PageQueryParam {
*/
private Long parentId;
/**
* 父级部门名称
*/
private String parentName;
/**
* 部门名称
*/
......
......@@ -29,12 +29,22 @@ public class EmployeeDeptParam {
@NotNull(message = "父级部门不能为空", groups = { AddGroup.class, EditGroup.class })
private Long parentId;
/**
* 父级部门名称
*/
private String parentName;
/**
* 部门名称
*/
@NotBlank(message = "部门名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String name;
/**
* 部门层级
*/
private Integer level;
/**
* 祖级关系
*/
......
......@@ -36,15 +36,26 @@ public class EmployeeDeptVo implements Serializable {
/**
* 父级部门
*/
@ExcelProperty(value = "父级部门")
private Long parentId;
/**
* 父级部门名称
*/
@ExcelProperty(value = "父级部门")
private String parentName;
/**
* 部门名称
*/
@ExcelProperty(value = "部门名称")
private String name;
/**
* 部门层级
*/
private Integer level;
/**
* 祖级关系
*/
......
package com.example.service;
import com.example.domain.EmployeeDept;
import com.example.domain.params.EmployeeDeptCheckAndSaveParam;
import com.example.domain.vo.EmployeeDeptVo;
import com.example.domain.params.EmployeeDeptListParam;
import com.example.domain.params.EmployeeDeptParam;
import com.alibaba.cola.dto.PageResponse;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
import java.util.Set;
/**
* 员工部门Service接口
......@@ -33,6 +35,29 @@ public interface EmployeeDeptServ extends IService<EmployeeDept> {
*/
List<EmployeeDeptVo> queryList(EmployeeDeptListParam param);
/**
* 批量保存部门信息
*
* @param param 部门名称
*/
void checkAndSaveDept(EmployeeDeptCheckAndSaveParam param);
/**
* 查询部门名称
*
* @param level 部门级别
* @return 部门名称
*/
List<String> selectDeptNamesByLevel(Integer level);
/**
* 查询部门名称
*
* @param parentName 部门名称
* @return 部门名称
*/
List<String> selectDeptNamesByParentName(String parentName);
/**
* 查询员工部门
*
......
......@@ -76,6 +76,13 @@ public interface EmployeeInfoServ extends IService<EmployeeInfo> {
*/
Boolean updateByParam(EmployeeInfoParam param);
/**
* 员工离职申请
*
* @param id 主键
*/
Boolean applyResign(Long id);
/**
* 校验并批量删除员工信息信息
*
......
package com.example.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.cola.dto.PageResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import top.binfast.common.core.util.MapstructUtils;
import top.binfast.common.mybatis.util.QueryUtil;
import com.example.constant.HrDeptLevel;
import com.example.domain.EmployeeDept;
import com.example.domain.vo.EmployeeDeptVo;
import com.example.domain.params.EmployeeDeptCheckAndSaveParam;
import com.example.domain.params.EmployeeDeptListParam;
import com.example.domain.params.EmployeeDeptParam;
import com.example.domain.vo.EmployeeDeptVo;
import com.example.mapper.EmployeeDeptMapper;
import com.example.service.EmployeeDeptServ;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.binfast.app.biz.sysapi.bean.model.auth.SysDept;
import top.binfast.common.core.constant.NormalStatus;
import top.binfast.common.core.util.LambdaUtil;
import top.binfast.common.core.util.MapstructUtils;
import top.binfast.common.mybatis.util.QueryUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* 员工部门Service业务层处理
......@@ -69,6 +80,84 @@ public class EmployeeDeptServImpl extends ServiceImpl<EmployeeDeptMapper, Employ
return lambdaQuery;
}
/**
* 批量保存员工部门
*
* @param param 部门名称集合
*/
@Override
@Async
@Transactional(rollbackFor = Exception.class)
public void checkAndSaveDept(EmployeeDeptCheckAndSaveParam param) {
Set<String> deptNames = param.getDeptNames();
if (CollUtil.isEmpty(deptNames)) {
return;
}
List<EmployeeDept> updateList = new ArrayList<>();
for (String deptNameGroup : deptNames) {
String[] split = deptNameGroup.split(StrUtil.DASHED);
if (split.length != 2) {
continue;
}
boolean exists = employeeDeptMapper.exists(new LambdaUpdateWrapper<EmployeeDept>()
.eq(EmployeeDept::getParentName, split[0])
.eq(EmployeeDept::getName, split[1]));
if (!exists) {
EmployeeDept parentDept = employeeDeptMapper.selectOne(new LambdaUpdateWrapper<EmployeeDept>()
.eq(EmployeeDept::getName, split[0]));
if (parentDept == null) {
parentDept = new EmployeeDept();
parentDept.setParentId(0L);
parentDept.setParentName("顶级部门");
parentDept.setName(split[0]);
parentDept.setStatus(NormalStatus.OPEN_STATUS);
parentDept.setLevel(HrDeptLevel.DEPT_LEVEL_ONE);
parentDept.setTenantId(param.getTenantId());
parentDept.setCreateBy(param.getUserId());
employeeDeptMapper.insert(parentDept);
parentDept.setOrderNum(parentDept.getId());
parentDept.setNodePath("/0/" + parentDept.getId());
updateList.add(parentDept);
}
EmployeeDept employeeDept = new EmployeeDept();
employeeDept.setParentId(parentDept.getId());
employeeDept.setParentName(parentDept.getName());
employeeDept.setName(split[1]);
employeeDept.setStatus(NormalStatus.OPEN_STATUS);
parentDept.setLevel(HrDeptLevel.DEPT_LEVEL_TWO);
employeeDept.setTenantId(param.getTenantId());
employeeDept.setCreateBy(param.getUserId());
employeeDeptMapper.insert(employeeDept);
employeeDept.setOrderNum(employeeDept.getId());
employeeDept.setNodePath(parentDept.getNodePath() + "/" + employeeDept.getId() + "/");
updateList.add(employeeDept);
}
}
if (CollUtil.isNotEmpty(updateList)) {
employeeDeptMapper.updateById(updateList);
}
}
/**
* 根据部门等级查询部门名称
*
* @param level 部门等级
* @return 部门名称列表
*/
@Override
public List<String> selectDeptNamesByLevel(Integer level) {
List<EmployeeDept> employeeDeptList = employeeDeptMapper.selectList(new LambdaUpdateWrapper<EmployeeDept>()
.eq(EmployeeDept::getLevel, level));
return LambdaUtil.mapToList(employeeDeptList, EmployeeDept::getName);
}
@Override
public List<String> selectDeptNamesByParentName(String parentName) {
List<EmployeeDept> employeeDeptList = employeeDeptMapper.selectList(new LambdaUpdateWrapper<EmployeeDept>()
.eq(EmployeeDept::getParentName, parentName));
return LambdaUtil.mapToList(employeeDeptList, EmployeeDept::getName);
}
/**
* 查询员工部门
*
......@@ -76,7 +165,7 @@ public class EmployeeDeptServImpl extends ServiceImpl<EmployeeDeptMapper, Employ
* @return 员工部门
*/
@Override
public EmployeeDeptVo queryById(Long id){
public EmployeeDeptVo queryById(Long id) {
EmployeeDept employeeDept = employeeDeptMapper.selectById(id);
return MapstructUtils.convert(employeeDept, EmployeeDeptVo.class);
}
......@@ -108,7 +197,7 @@ public class EmployeeDeptServImpl extends ServiceImpl<EmployeeDeptMapper, Employ
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(EmployeeDept entity){
private void validEntityBeforeSave(EmployeeDept entity) {
// 做一些数据校验,如唯一约束
}
......
......@@ -9,27 +9,25 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.example.constant.HrFlowEnum;
import com.example.domain.EmployeeInfo;
import com.example.domain.params.EmployeeDeptCheckAndSaveParam;
import com.example.domain.params.EmployeeInfoListParam;
import com.example.domain.params.EmployeeInfoParam;
import com.example.domain.vo.EmployeeInfoImportVo;
import com.example.domain.vo.EmployeeInfoVo;
import com.example.mapper.EmployeeInfoMapper;
import com.example.service.EmployeeDeptServ;
import com.example.service.EmployeeInfoServ;
import lombok.RequiredArgsConstructor;
import org.dromara.trans.service.impl.TransService;
import org.springframework.stereotype.Service;
import top.binfast.app.biz.sysapi.bean.model.auth.SysDept;
import top.binfast.app.biz.sysapi.bean.model.auth.SysRole;
import top.binfast.app.biz.sysapi.bean.model.auth.SysUser;
import top.binfast.common.core.enums.ResultCode;
import top.binfast.common.core.util.MapstructUtils;
import top.binfast.common.excel.core.ExcelContextHolder;
import top.binfast.common.mybatis.util.QueryUtil;
import com.example.domain.EmployeeInfo;
import com.example.domain.vo.EmployeeInfoVo;
import com.example.domain.params.EmployeeInfoListParam;
import com.example.domain.params.EmployeeInfoParam;
import com.example.mapper.EmployeeInfoMapper;
import com.example.service.EmployeeInfoServ;
import top.binfast.common.satoken.util.SecurityUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Stream;
/**
......@@ -43,7 +41,7 @@ import java.util.stream.Stream;
public class EmployeeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, EmployeeInfo> implements EmployeeInfoServ {
private final EmployeeInfoMapper employeeInfoMapper;
private final TransService transService;
private final EmployeeDeptServ employeeDeptServ;
/**
* 分页查询员工信息列表
......@@ -139,6 +137,7 @@ public class EmployeeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, Employ
public Response importEmployeeList(Stream<EmployeeInfoImportVo> list) {
List<EmployeeInfoImportVo> errorList = new ArrayList<>();
List<EmployeeInfo> successList = new ArrayList<>();
Set<String> deptNameGroups = new HashSet<>();
list.forEach(item -> {
// System.out.println(item.getNickName());
// item.validGroup(AddGroup.class);
......@@ -157,9 +156,13 @@ public class EmployeeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, Employ
}
EmployeeInfo employeeInfo = MapstructUtils.convert(employeeInfoParam, EmployeeInfo.class);
successList.add(employeeInfo);
deptNameGroups.add(employeeInfo.getFirstLevelDepartment() + StrUtil.DASHED + employeeInfo.getSecondLevelDepartment());
});
if (CollUtil.isNotEmpty(successList)) {
employeeInfoMapper.insert(successList);
EmployeeDeptCheckAndSaveParam checkAndSaveParam =
new EmployeeDeptCheckAndSaveParam(deptNameGroups, SecurityUtils.getCurrentUserId(), SecurityUtils.getTenantId());
employeeDeptServ.checkAndSaveDept(checkAndSaveParam);
}
StringBuilder message;
if (CollUtil.isNotEmpty(errorList)) {
......@@ -190,7 +193,7 @@ public class EmployeeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, Employ
* @return 员工信息
*/
@Override
public EmployeeInfoVo queryById(Long id){
public EmployeeInfoVo queryById(Long id) {
EmployeeInfo employeeInfo = employeeInfoMapper.selectById(id);
return MapstructUtils.convert(employeeInfo, EmployeeInfoVo.class);
}
......@@ -204,6 +207,13 @@ public class EmployeeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, Employ
@Override
public Boolean insertByParam(EmployeeInfoParam param) {
EmployeeInfo employeeInfo = MapstructUtils.convert(param, EmployeeInfo.class);
// 检查或增加部门
Set<String> deptNameGroups = new HashSet<>();
deptNameGroups.add(employeeInfo.getFirstLevelDepartment() + StrUtil.DASHED + employeeInfo.getSecondLevelDepartment());
EmployeeDeptCheckAndSaveParam checkAndSaveParam =
new EmployeeDeptCheckAndSaveParam(deptNameGroups, SecurityUtils.getCurrentUserId(), SecurityUtils.getTenantId());
employeeDeptServ.checkAndSaveDept(checkAndSaveParam);
employeeInfo.setEntryStatus(HrFlowEnum.WAITING.getStatus());
return this.save(employeeInfo);
}
......@@ -222,10 +232,22 @@ public class EmployeeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, Employ
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(EmployeeInfo entity){
private void validEntityBeforeSave(EmployeeInfo entity) {
// 做一些数据校验,如唯一约束
}
/**
* 员工离职申请
*
* @param id 主键
*/
@Override
public Boolean applyResign(Long id) {
EmployeeInfo employeeInfo = employeeInfoMapper.selectById(id);
employeeInfo.setResignationStatus(HrFlowEnum.WAITING.getStatus());
return this.updateById(employeeInfo);
}
/**
* 校验并批量删除员工信息信息
*
......
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