OA系统实现(请假审批,mybatis)-2

接上一个
开发多级审批流程
在这里插入图片描述
在这里插入图片描述
设计约束
每一个请假单对应一个审批流程
请假单创建后,按业务规则生成部门经理、总经理审批任务
审批任务的经办人只能审批自己辖区内的请假申请
所有审批任务"通过",代表请假已经批准
任意审批任务"驳回"操作,其余审批任务取消,请假申请被驳回
请假流程中任意节点产生的操作都要生成对应的系统通知

请假申请表
在这里插入图片描述
在这里插入图片描述
请假流程表
在这里插入图片描述
在这里插入图片描述
请假通知表
在这里插入图片描述
在这里插入图片描述
相关的实体类都进行创建

请假单接口的创建

public interface LeaveFormDao {
    public void insert(LeaveForm form);
	
    public List<Map> selectByParams(@Param("pf_state") String pfState,
                                    @Param("pf_operator_id") Long operatorId);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace与包名一致-->
<mapper namespace="com.imooc.oa.dao.LeaveFormDao">
    <!--id与方法名对应
    parameterType与方法参数类型对应
    resultType与方法返回类型对应-->
    <insert id="insert" parameterType="com.imooc.oa.entity.LeaveForm"
            useGeneratedKeys="true" keyProperty="formId" keyColumn="form_id">
        INSERT INTO adm_leave_form(employee_id, form_type, start_time, end_time,
                                   reason, create_time, state)
        VALUES (#{employeeId}, #{formType}, #{startTime}, #{endTime},
                #{reason}, #{createTime}, #{state})
    </insert>
</mapper>

在配置文件中进行注册
剩下两个表的操作都一样

开发请假功能
请假单流程服务和消息提示 LeaveFormService

 public LeaveForm createLeaveForm(LeaveForm form) {
        LeaveForm savedForm = (LeaveForm) MybatisUtils.excuteUpdate(sqlSession -> {
            //1.持久化form表单数据,8级以下员工表单状态为processing(正在审批) ,8级(总经理)状态为approved(审批通过)
            EmployeeDao employeeDao = sqlSession.getMapper(EmployeeDao.class);
            Employee employee = employeeDao.selectById(form.getEmployeeId());//传入员工编号 获取员工信息
            // 判断请假单审批状态
            if (employee.getLevel() == 8) {
                form.setState("approved");//审批通过
            } else {
                form.setState("processing");//正在审批
            }
            LeaveFormDao leaveFormDao = sqlSession.getMapper(LeaveFormDao.class);
            // 将当前状态写入请假表单中
            leaveFormDao.insert(form);
            //2.增加第一条流程数据,说明申请人的表单已提交,状态为complete(正在处理)
            ProcessFlowDao processFlowDao = sqlSession.getMapper(ProcessFlowDao.class);
            ProcessFlow flow1 = new ProcessFlow();
            flow1.setFormId(form.getFormId());//表单编号
            flow1.setOperatorId(employee.getEmployeeId());//经办人编号,这里应该是自己的编号
            flow1.setAction("apply");//申请
            flow1.setCreateTime(new Date());
            flow1.setOrderNo(1);//任务序号
            flow1.setState("complete");
            flow1.setIsLast(0);//是否为最后一个流程
            processFlowDao.insert(flow1);
            //3.分情况创建其余流程数据
            //3.1 7级以下员工,生成部门经理审批任务,请假时间大于36小时,还需生成总经理审批任务
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH时");
            NoticeDao noticeDao = sqlSession.getMapper(NoticeDao.class);
            /*
            普通员工请假
            <72小时 部门经理审批
            >72小时 部门经理审批通过,还需要总经理审批
            */ 
            if (employee.getLevel() < 7) {
            	// 获取上级对象
                Employee dmanager = employeeDao.selectLeader(employee);
                // 创建部门经理审批流程
                ProcessFlow flow2 = new ProcessFlow();
                flow2.setFormId(form.getFormId());
                flow2.setOperatorId(dmanager.getEmployeeId());
                flow2.setAction("audit");//审批
                flow2.setCreateTime(new Date());
                flow2.setOrderNo(2);
                flow2.setState("process");//正在处理
                long diff = form.getEndTime().getTime() - form.getStartTime().getTime();
                float hours = diff / (1000 * 60 * 60) * 1f;
                // 大于72小时需要再创建一个总经理审批流程
                if (hours >= BussinessConstants.MANAGER_AUDIT_HOURS) {
                    flow2.setIsLast(0);
                    processFlowDao.insert(flow2);
                    Employee manager = employeeDao.selectLeader(dmanager);
                    ProcessFlow flow3 = new ProcessFlow();
                    flow3.setFormId(form.getFormId());
                    flow3.setOperatorId(manager.getEmployeeId());
                    flow3.setAction("audit");//审批
                    flow3.setCreateTime(new Date());
                    flow3.setState("ready");//准备审批
                    flow3.setOrderNo(3);//任务序号
                    flow3.setIsLast(1);//为最后节点
                    processFlowDao.insert(flow3);
                } else {
                    flow2.setIsLast(1);
                    processFlowDao.insert(flow2);
                }
                // 创建请假单用户的提示消息
                // 请假单已提交信息
                String noticeContent = String.format("您的请假申请[%s-%s]已提交,请等待上级批准.",
                        sdf.format(form.getStartTime()), sdf.format(form.getEndTime()));
                // 接收人(提交表单的员工)   显示的消息
                noticeDao.insert(new Notice(employee.getEmployeeId(), noticeContent));

                // 接收人(上级) 通知部门经理审批消息
                noticeContent = String.format("%s-%s提起请假申请[%s-%s],请尽快审批",
                        employee.getTitle(), employee.getName(), sdf.format(form.getStartTime()),
                        sdf.format(form.getEndTime()));
                noticeDao.insert(new Notice(dmanager.getEmployeeId(), noticeContent));
            } else if (employee.getLevel() == 7) {//部门经理
                //3.2 7级员工,生成总经理审批任务
                Employee manager = employeeDao.selectLeader(employee);
                ProcessFlow flow = new ProcessFlow();
                flow.setFormId(form.getFormId());
                flow.setOperatorId(manager.getEmployeeId());
                flow.setAction("audit");
                flow.setCreateTime(new Date());
                flow.setState("process");
                flow.setOrderNo(2);
                flow.setIsLast(1);
                processFlowDao.insert(flow);


                // 请假单已提交信息
                String noticeContent = String.format("您的请假申请[%s-%s]已提交,请等待上级批准.",
                        sdf.format(form.getStartTime()), sdf.format(form.getEndTime()));
                // 接收人(提交表单的员工)   显示的消息
                noticeDao.insert(new Notice(employee.getEmployeeId(), noticeContent));

                // 接收人(上级) 通知总经理审批消息
                noticeContent = String.format("%s-%s提起请假申请[%s-%s],请尽快审批",
                        employee.getTitle(), employee.getName(), sdf.format(form.getStartTime()),
                        sdf.format(form.getEndTime()));
                noticeDao.insert(new Notice(manager.getEmployeeId(), noticeContent));

            } else if (employee.getLevel() == 8) {
                //3.3 8级员工,生成总经理审批任务,系统自动通过
                ProcessFlow flow = new ProcessFlow();
                flow.setFormId(form.getFormId());
                flow.setOperatorId(employee.getEmployeeId());
                flow.setAction("audit");
                flow.setResult("approved");
                flow.setReason("自动通过");
                flow.setCreateTime(new Date());
                flow.setAuditTime(new Date());
                flow.setState("complete");
                flow.setOrderNo(2);
                flow.setIsLast(1);
                processFlowDao.insert(flow);

                // 请假单已提交信息
                String noticeContent = String.format("您的请假申请[%s-%s]系统已自动批准通过,请等待上级批准.",
                        sdf.format(form.getStartTime()), sdf.format(form.getEndTime()));
                // 接收人(提交表单的员工)   显示的消息
                noticeDao.insert(new Notice(employee.getEmployeeId(), noticeContent));
            }
            return form;
        });
        return savedForm;
    }

创建一个动态SQL根据传入的员工获取对应的上级主管对象

/**
     * 根据传入员工对象获取上级主管对象
     * @param employee 员工对象
     * @return 上级主管对象
     */
    public Employee selectLeader(@Param("emp") Employee employee);
<select id="selectLeader" parameterType="com.imooc.oa.entity.Employee"
            resultType="com.imooc.oa.entity.Employee">
        select * from adm_employee
        where
        <if test="emp.level &lt; 7">
            level = 7 and department_id = #{emp.departmentId}
        </if>
        <if test="emp.level == 7">
            level = 8
        </if>
        <if test="emp.level == 8">
            employee_id = #{emp.employeeId}
        </if>
    </select>

Servlet

@WebServlet(name = "LeaveFormServlet", urlPatterns = "/leave/*")
public class LeaveFormServlet extends HttpServlet {

    private LeaveFormService leaveFormService = new LeaveFormService();
    private Logger logger = LoggerFactory.getLogger(LeaveFormService.class);

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        //http://localhost/leave/create
        String uri = request.getRequestURI();
        // 对url进行截取
        String methodName = uri.substring(uri.lastIndexOf("/") + 1);
        // 创建请假表单
        if (methodName.equals("create")) {
            this.create(request, response);
        } else if (methodName.equals("list")) {
        	//获取请假表单
            this.getLeaveFormList(request, response);
        } else if (methodName.equals("audit")) {//审核请假单
            this.audit(request, response);
        }

    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        this.doPost(request, response);
    }
	// 创建请假单
    private void create(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        // 1.接收各项请假单数据集
        HttpSession session = request.getSession();
        // 获取登录用户 
        // 获取用户提交的请假单数据
        User user = (User) session.getAttribute("login_user");
        String formType = request.getParameter("formType");
        String strStartTime = request.getParameter("startTime");
        String strEndTime = request.getParameter("endTime");
        String reason = request.getParameter("reason");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH");

        Map<String, String> result = new HashMap();
        try {
            LeaveForm form = new LeaveForm();
            form.setEmployeeId(user.getEmployeeId());
            form.setStartTime(sdf.parse(strStartTime));
            form.setEndTime(sdf.parse(strEndTime));
            form.setFormType(Integer.parseInt(formType));
            form.setReason(reason);//请假原因
            form.setCreateTime(new Date());
            // 2.调用业务逻辑方法
            // 创建请假单
            leaveFormService.createLeaveForm(form);
            result.put("code", "0");
            result.put("message", "success");
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("请假申请异常", e);
            result.put("code", e.getClass().getCanonicalName());
            result.put("message", e.getMessage());
        }
        // 组织相应结果
        String json = JSON.toJSONString(result);
        response.getWriter().println(json);
    }

    /**
     * 查询需要审核的请假单列表
     *
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    public void getLeaveFormList(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
            // 获取登录用户
        User user = (User) request.getSession().getAttribute("login_user");
        // 获取 
        List<Map> formList = leaveFormService.getLeaveFormList("process", user.getEmployeeId());
        Map result = new HashMap();
        result.put("code", "0");
        result.put("msg", "");
        result.put("count", formList.size());
        result.put("data", formList);
        String json = JSON.toJSONString(result);
        response.getWriter().println(json);
    }

    // 审核
    public void audit(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        String formId = request.getParameter("formId");
        String result = request.getParameter("result");
        String reason = request.getParameter("reason");
        User user = (User) request.getSession().getAttribute("login_user");
        Map<String, String> mpResult = new HashMap<>();
        try {

            leaveFormService.audit(Long.parseLong(formId), user.getEmployeeId(), result, reason);
            mpResult.put("code", "0");
            mpResult.put("message", "success");
        } catch (Exception e) {
            logger.error("请假单审核失败", e);
            mpResult.put("code", e.getClass().getSimpleName());
            mpResult.put("message", e.getMessage());
        }
        String json = JSON.toJSONString(mpResult);
        response.getWriter().println(json);
    }
}

前端代码就不列出来了。

为了解决页面显示问题

@WebServlet(name = "ForwardServlet", urlPatterns = "/forward/*")
public class ForwardServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        String uri = request.getRequestURI();
        /*
         * /forward/form
         * /forward/a/b/c/form
         */
        String subUri = uri.substring(1);
        String page = subUri.substring(subUri.indexOf("/"));
        request.getRequestDispatcher(page + ".ftl").forward(request, response);
    }
}

请假审批功能
首先查询自己要审批的表单条件是,审批人为自己和审批状态为processing(正在处理)

<select id="selectByParams" parameterType="java.util.Map" resultType="java.util.Map">
        select f.*, e.name, d.*
        from adm_leave_form f,
             adm_process_flow pf,
             adm_employee e,
             adm_department d
        where f.form_id = pf.form_id
          and pf.state = #{pf_state}
          and pf.operator_id = #{pf_operator_id}
          and f.employee_id = e.employee_id
          and e.department_id = d.department_id
    </select>
public List<Map> getLeaveFormList(String pfState, Long operatorId) {
        return (List<Map>) MybatisUtils.executeQuery(sqlSession -> {
            LeaveFormDao dao = sqlSession.getMapper(LeaveFormDao.class);
            List<Map> formList = dao.selectByParams(pfState, operatorId);//状态、经办人编号
            return formList;
        });
    }

/**
     * 查询需要审核的请假单列表
     */
    public void getLeaveFormList(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        User user = (User) request.getSession().getAttribute("login_user");
        List<Map> formList = leaveFormService.getLeaveFormList("process", user.getEmployeeId());//当前登录的员工编号
        Map result = new HashMap();
        result.put("code", "0");
        result.put("msg", "");
        result.put("count", formList.size());
        result.put("data", formList);
        String json = JSON.toJSONString(result);
        response.getWriter().println(json);
    }

审批业务逻辑
情况1:普通员工请假,小于72小时,部门经理审批
情况2:普通员工请假,大于72小时,部门经理审批通过,总经理需要再次审批
情况3:普通员工请假,大于72小时,部门经理审批未通过,总经理不用审批
情况4:部门经理请假,总经理审批
情况5:总经理请假,直接通过

/**
     * 修改流程表审批状态、申请表状态、和通知信息
     * @param formId     申请表ID
     * @param operatorId 经办人编号
     * @param result     approved-同意 refused-驳回
     * @param reason     审批意见
     */
    public void audit(Long formId, Long operatorId, String result, String reason) {
        MybatisUtils.excuteUpdate(sqlSession -> {
            //1.无论同意/驳回,当前任务状态变更为complete(处理完成).
            ProcessFlowDao processFlowDao = sqlSession.getMapper(ProcessFlowDao.class);
            // 根据对应的表单号查询该表单对应的处理流程顺序信息
            List<ProcessFlow> flowList = processFlowDao.selectByFormId(formId);
            if (flowList.size() == 0) {
                throw new BussinessException("PF001", "无效的审批流程");
            }
            // process 正在处理  把处理过程为process的提取出来
            List<ProcessFlow> processList = 
                    flowList.stream().filter(p -> p.getOperatorId().equals(operatorId) && p.getState().equals(
                            "process")).collect(Collectors.toList());
            ProcessFlow process = null;
            if (processList.size() == 0) {
                throw new BussinessException("PF002", "未找到待处理任务");
            } else {
                process = processList.get(0);
                process.setState("complete");
                process.setResult(result);// 设置同意还是驳回
                process.setReason(reason);// 设置审批意见
                process.setAuditTime(new Date());
                processFlowDao.update(process);
            }
            //2.如果当前任务是最后一个节点,代表流程结束,更新请假单状态为对应的approved/refused
            LeaveFormDao leaveFormDao = sqlSession.getMapper(LeaveFormDao.class);
            // 查询请假表内容
            LeaveForm form = leaveFormDao.selectById(formId);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH时");
            EmployeeDao employeeDao = sqlSession.getMapper(EmployeeDao.class);
            Employee employee = employeeDao.selectById(form.getEmployeeId());
            Employee operator = employeeDao.selectById(operatorId);
            NoticeDao noticeDao = sqlSession.getMapper(NoticeDao.class);

            // 当前为最后一个流程 代表流程结束,更新请假表单状态对应的approved/refused
            if (process.getIsLast() == 1) {
                form.setState(result);// 通过/拒绝
                leaveFormDao.update(form);

                String strResult = null;
                if (result.equals("approved")) {
                    strResult = "批准";
                } else if (result.equals("refused")) {
                    strResult = "驳回";
                }
                // 起始时间-结束时间-经办人职务-经办人名字-批准/驳回-审批意见
                String noticeContent = String.format("您的请假申请[%s-%s]%s%s已%s,审批意见:%s,审批流程已结束",
                        sdf.format(form.getStartTime()), sdf.format(form.getEndTime()), operator.getTitle(),
                        operator.getName(), strResult, reason);// 发给表单提交人
                noticeDao.insert(new Notice(form.getEmployeeId(), noticeContent));
                // 职务-员工-起始时间-结束时间-审核/驳回-审批意见
                noticeContent = String.format("%s-%s提起的请假申请[%s-%s]您已%s,审批意见:%s,审批流程已结束",
                        employee.getTitle(), employee.getName(), sdf.format(form.getStartTime()),
                        sdf.format(form.getEndTime()),
                        strResult, reason);//发给审批人的通知
                noticeDao.insert(new Notice(operator.getEmployeeId(), noticeContent));


            } else {// 不是最后一个流程
                // readyList包含所有的后序节点
                List<ProcessFlow> readyList =
                        flowList.stream().filter(p -> p.getState().equals("ready")).collect(Collectors.toList());
                //3.如果当前任务不是最后一个节点且审批通过,那下一个节点的状态从ready变为process
                if (result.equals("approved")) {//同意
                    ProcessFlow readyProcess = readyList.get(0);
                    readyProcess.setState("process");
                    processFlowDao.update(readyProcess);

                    // 消息1:通知表单提交人,部门经理已经审批通过,交由上级处理
                    String noticeContent1 = String.format("您的请假申请[%s-%s]%s%s已批准,审批意见:%s,请等待上级领导审批",
                            sdf.format(form.getStartTime()), sdf.format(form.getEndTime()),
                            operator.getTitle(), operator.getName(), reason);
                    noticeDao.insert(new Notice(form.getEmployeeId(), noticeContent1));

                    // 消息2:通知总经理有新的审批任务
                    String noticeContent2 = String.format("%s-%s提起请假申请[%s-%s],请尽快审批",
                            employee.getTitle(), employee.getName(), sdf.format(form.getStartTime()),
                            sdf.format(form.getEndTime()));
                    noticeDao.insert(new Notice(readyProcess.getOperatorId(), noticeContent2));

                    // 消息3:通知部门经理(当前经办人),员工的申请单你已批准,交由上级继续审批
                    String noticeContent3 = String.format("%s-%s提起的请假申请[%s-%s]您已批准,审批意见:%s,请等待上级领导审批",
                            employee.getTitle(), employee.getName(), sdf.format(form.getStartTime()),
                            sdf.format(form.getEndTime()),
                            reason);
                    noticeDao.insert(new Notice(operator.getEmployeeId(), noticeContent3));


                } else if (result.equals("refused")) {// 驳回
                    //4.如果当前任务不是最后一个节点且审批驳回,则后续所有任务状态变为cancel,请假单状态变为refused
                    for (ProcessFlow p :
                            readyList) {
                        p.setState("cancel");
                        processFlowDao.update(p);
                    }
                    // 表单设置为被拒绝
                    form.setState("refused");
                    leaveFormDao.update(form);

                    // 消息1:通知申请人表单已经被驳回
                    String noticeContent1 = String.format("您的请假申请[%s-%s]%s%s已驳回,原因是%s",
                            sdf.format(form.getStartTime()), sdf.format(form.getEndTime()),
                            operator.getTitle(), operator.getName(), reason);
                    noticeDao.insert(new Notice(form.getEmployeeId(), noticeContent1));

                    //消息2:通知经办人表单"您已驳回"
                    String noticeContent3 = String.format("%s-%s提起的请假申请[%s-%s]您已驳回,审批意见%s,审批流程已结束",
                            employee.getTitle(), employee.getName(), sdf.format(form.getStartTime()),
                            sdf.format(form.getEndTime()),
                            reason);
                    noticeDao.insert(new Notice(operator.getEmployeeId(), noticeContent3));
                }
            }
            return null;
        });
    }

  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值