审批流程的设计

应用场景

在项目开发中,有时会遇到一些审批流程的需求,流程大同小异,可以根据需求进行设计开发。

表结构示例

CREATE TABLE `tt_audit` (
  `id` int(10) NOT NULL COMMENT '流水号',
  `submit_date` date NOT NULL COMMENT '提交日期',
  `submit_reason` varchar(500)  DEFAULT '' COMMENT '提交意见',
  `submit_user_id` varchar(30) NOT NULL DEFAULT '' COMMENT '提交方用户id',
  `submit_files` varchar(200) DEFAULT NULL COMMENT '提议内容的文件',
  `first_audit_result` tinyint(4)  DEFAULT '0' COMMENT '第一次审核结果 1:通过, 2:驳回',
  `first_audit_idea` varchar(500)  DEFAULT '' COMMENT '第一次审核意见',
  `first_audit_user_id` varchar(30) DEFAULT '' COMMENT '第一次审核的用户id',
  `first_audit_time` datetime DEFAULT NULL COMMENT '第一次审核时间',
  `disapprove_reason` varchar(500) DEFAULT '' COMMENT '不认可原因1',
  `second_audit_result` tinyint(4) DEFAULT '0' COMMENT '二次复审结果 1:通过, 2:驳回',
  `second_audit_idea` varchar(500)  DEFAULT '' COMMENT '二次复审意见',
  `second_audit_user_id` varchar(30) DEFAULT '' COMMENT '二次复审人的用户id',
  `second_audit_time` datetime DEFAULT NULL COMMENT '二次复审意见时间',
  `disapprove_reason2` varchar(500)  DEFAULT '' COMMENT '不认可原因2',
  `third_audit_result` tinyint(4)  DEFAULT '0' COMMENT '第三次复审结果 1:通过, 2:驳回',
  `third_audit_idea` varchar(500)  DEFAULT '' COMMENT '第三次复审意见',
  `third_audit_user_id` varchar(30) DEFAULT '' COMMENT '第三次审核人的用户id',
  `third_audit_user_name` varchar(30) DEFAULT '' COMMENT '第三次审核人姓名',
  `third_audit_time` datetime DEFAULT NULL COMMENT '第三次复审意见时间',
  `finish_time` datetime DEFAULT NULL COMMENT '审核完成时间',
  `deal_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '处理节点状态.1:待第一次审核, 10:第一次审核-通过,
  20:第一次审核-驳回, 30:待二次复审, 40:二次复审完成, 50:二次复审-通过,
  60:二次复审-驳回, 70:待第三次审核, 80:第三次审核完成, 90:审核完成',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间,默认当前时间',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间,更新时默认当前时间',
  PRIMARY KEY (`id`),
  KEY `idx_submit_user_id` (`submit_user_id`),
  KEY `idx_submit_date` (`submit_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='审核流程表'

设计审批流程表的时候,要注意几点:

  • 要有创建时间、更新时间,出现问题时,有记录时间可以定位。
  • 审核状态,数值最好分隔开,用10,20,30,40,50,不要用12345,这样后续需求变更,流程中新增审核状态时,可以在中间加上新的数值。
  • 反馈时间,反馈人id,反馈人姓名,这几个得有。
  • 审核时间、审核人id、审核人姓名,这几个最好加上,出现线上问题时,方便回溯。

审批流程

多思考业务流程。

  • 审批人是一个还是多个?
  • 审批人需要哪些角色/权限?
  • 审批流程是一次审批,还是多次审批?

审批通知

审批完成之后,最好能用消息/短信通知创建人。

代码示例

  • 审核结果的枚举:

@AllArgsConstructor
@Getter
public enum AuditEnum {


    AUDIT_DEFAULT((byte) 0, ""),
    AUDIT_PASS((byte) 1, "通过"),
    AUDIT_REJECT((byte) 2, "驳回");

    private final byte auditNum;
    private final String auditDesc;

    public static String getDescByAuditNum(byte num) {
        AuditEnum[] values = AuditEnum.values();
        for (AuditEnum e : values) {
            if (e.getAuditNum() == num) {
                return e.getAuditDesc();
            }
        }
        return null;
    }

    public static byte getNumByAuditDesc(String desc) {
        AuditEnum[] values = AuditEnum.values();
        for (AuditEnum e : values) {
            if (e.getAuditDesc().equals(desc)) {
                return e.getAuditNum();
            }
        }
        return (byte) 0;
    }

}

  • 处理状态的枚举:
@AllArgsConstructor
@Getter
public enum DealStatusEnum {

    WAIT_AUDIT((byte) 10, "待初次审核"),
    WAIT_SECOND_AUDIT((byte) 20, "待二次复审"),
    WAIT_THIRD_AUDIT((byte) 30, "待第三次审核"),
    AUDIT_FINISH((byte) 40, "审核完成-通过"),
    AUDIT_HEAD_REJECT((byte) 50, "初次审核不通过"),
    AUDIT_SECOND_REJECT((byte) 60, "二次复审不通过"),
    AUDIT_THIRD_REJECT((byte) 70, "第三次审核不通过"),

    AUDIT_REJECT((byte) 80, "审核完成-驳回");



    private final byte dealStatus;
    private final String dealStatusDesc;

    public static String getDescByStatus(byte dealStatus){
        DealStatusEnum[] values = DealStatusEnum.values();
        for(DealStatusEnum e : values) {
            if(e.getDealStatus() == dealStatus) {
                return e.getDealStatusDesc();
            }
        }
        return null;
    }

}

  • 审批流程:

public class AuditImpl {

    public int audit(SuggestionAuditDTO auditDTO) {

        //当前状态
        Byte dealStatus = auditDTO.getDealStatus();
        suggestion.setDealStatus(dealStatus);

        //根据处理节点的状态,判断审核结果/意见
        if (WAIT_HEAD_AUDIT.getDealStatus() == dealStatus) {
            setFirstAudit(suggestion, auditResult, auditIdea);
        } else if (WAIT_SECOND_AUDIT.getDealStatus() == dealStatus) {
            setSecondAudit(suggestion, auditResult, auditIdea);
        } else if (WAIT_Third_AUDIT.getDealStatus() == dealStatus) {
            setThirdAudit(suggestion, auditResult, auditIdea);
        }
        return updateByIdSelective(suggestion);
    }


    /**
     * 设置第一次审批的结果
     *
     */
    public void setFirstAudit(Suggestion suggestion, Byte auditResult, String auditIdea) {

        suggestion.setFirstAuditResult(auditResult);
        suggestion.setFirstAuditIdea(auditIdea);
        suggestion.setFirstAuditTime(new Date());
        suggestion.setFirstUserId(userId);
        setDealStatusByAudit(suggestion, auditResult, AUDIT_HEAD_PASS.getDealStatus(), AUDIT_HEAD_REJECT.getDealStatus());
    }



    /**
     * 根据审核结果,设置处理节点
     *
     * @param suggestion
     * @param auditResult  审核结果
     * @param passStatus 通过跳转的处理节点
     * @param rejectStatus 不通过跳转的处理节点
     */
    public void setDealStatusByAudit(Suggestion suggestion, Byte auditResult,Byte passStatus, Byte rejectStatus) {
        if (AUDIT_PASS.getAuditNum() == auditResult) {
            suggestion.setDealStatus(passStatus);
        } else if (AUDIT_REJECT.getAuditNum() == auditResult) {
            suggestion.setDealStatus(rejectStatus);
        }

    }


    /**
     * 设置二次复审的结果
     */
    public void setSecondAudit(Suggestion suggestion, Byte auditResult, String auditIdea) {

        suggestion.setSecondAuditResult(auditResult);
        suggestion.setSecondAuditIdea(auditIdea);
        suggestion.setSecondAuditTime(new Date());
        suggestion.setSecondAuditEmpCode(ContextUtils.getContext().getUserNo());
        setDealStatusByAudit(suggestion, auditResult, SECOND_AUDIT_PASS.getDealStatus(), SECOND_AUDIT_REJECT.getDealStatus());
    }



    /**
     * 设置第三次审核的结果
     */
    public void setThirdAudit(Suggestion suggestion, Byte auditResult, String auditIdea ) {

        suggestion.setThirdAuditResult(auditResult);
        suggestion.setThirdAuditIdea(auditIdea);
        suggestion.setThirdAuditTime(new Date());
        suggestion.setThirdAuditEmpCode(userId);

        setDealStatusByAudit(suggestion, auditResult, Third_AUDIT_FINISH.getDealStatus()
                , Third_AUDIT_FINISH.getDealStatus());
    }
    
    
    
}

posted on   乐之者v  阅读(335)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
历史上的今天:
2021-02-22 ElastaticSearch--- es多字段聚合
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示