PostgreSQL数据库函数,实现一个可根据职位角色配置节点,包含多级审批功能,审批过程中有会审、或审

PostgreSQL数据库函数,实现一个可根据职位角色配置节点,包含多级审批功能,审批过程中有会审、或审

在开始实现之前,我们需要定义一些概念和规则:

  1. 审批流程是由若干个审批节点(Approval Node)组成的,每个节点代表一个审批环节。
  2. 每个审批节点包含一个节点ID,一个节点名称,以及一个可选的节点描述。
  3. 审批流程还包括一个开始节点和一个结束节点,它们不需要配置具体的审批人。
  4. 一个审批节点可以有多个后续节点,表示审批通过之后,流程会继续走向这些后续节点中的一个。
  5. 每个审批节点都需要配置一个审批规则,这个规则用于决定流程如何继续,可以是会审、或审或者单人审批。
  6. 审批规则的具体定义会在后文中给出。
  7. 审批记录会被记录在一个单独的审批记录表中,每条记录包含审批节点ID、审批人、审批时间、以及审批结果。

有了以上的规则和概念,我们就可以开始设计审批流程的数据库表和函数了。以下是一个可能的实现方案:

首先,我们需要创建一个审批节点表(ApprovalNode),用于存储所有的审批节点信息。

CREATE TABLE ApprovalNode (
  id SERIAL PRIMARY KEY,
  name TEXT NOT NULL,
  description TEXT,
  rule TEXT NOT NULL,
  next_node_ids INTEGER[]
);

其中,rule字段代表审批规则,它可以取以下三种值之一:

  1. “ALL”: 会审规则。表示所有节点都需要审批通过才能继续流程。
  2. “ANY”: 或审规则。表示所有节点中有至少一个节点审批通过就可以继续流程。
  3. “SINGLE”: 单人审批规则。表示只需要当前节点的一个审批人审批通过就可以继续流程。

next_node_ids表示下一个节点的ID,对于审批流程中的最后一个节点,这个字段为空。

接下来,我们需要创建一个审批记录表(ApprovalRecord),用于记录所有的审批记录信息。

CREATE TABLE ApprovalRecord (
  id SERIAL PRIMARY KEY,
  node_id INTEGER NOT NULL,
  approver TEXT NOT NULL,
  approved_at TIMESTAMP NOT NULL,
  approved_result BOOLEAN NOT NULL
);

其中,node_id表示审批节点的ID,approver表示审批人的名称,approved_at表示审批通过的时间,approved_result表示审批是否通过。

接着,我们需要创建一个函数来查询指定节点的所有后续节点ID。

CREATE FUNCTION getNextNodes(node_id INTEGER)
  RETURNS SETOF INTEGER
  AS $$
    BEGIN
      RETURN QUERY SELECT unnest(next_node_ids)
        FROM ApprovalNode
        WHERE id = node_id;
    END;
  $$
  LANGUAGE plpgsql;

这个函数的作用是查询给定节点的所有后续节点ID。

接下来,我们需要创建一个函数来判断指定节点是否可以通过审批。

CREATE FUNCTION canApprove(node_id INTEGER)
  RETURNS BOOLEAN
  AS $$
    DECLARE
      rule_text TEXT;
      approvers TEXT[];
      approved_count INTEGER;
      total_count INTEGER;
    BEGIN
      -- 查询节点的审批规则和后续节点ID
      SELECT rule, ARRAY(
        SELECT unnest(approver_list)
        FROM ApprovalNode JOIN ApprovalRecord ON ApprovalNode.id = node_id
        WHERE ApprovalNode.rule = 'SINGLE' AND ApprovalRecord.approved_result = true
      ), (
        SELECT COUNT(DISTINCT approver)
        FROM ApprovalRecord
        WHERE node_id = node_id AND approved_result = true
      ), (
        CASE
          WHEN (SELECT rule FROM ApprovalNode WHERE id = node_id) = 'ALL' THEN (
            SELECT COUNT(DISTINCT approver)
            FROM ApprovalRecord
            WHERE node_id = node_id
          )
          ELSE (
            SELECT COUNT(*)
            FROM ApprovalNode
            WHERE id = ANY(next_node_ids)
          )
        END
      )
      INTO rule_text, approvers, approved_count, total_count
      FROM ApprovalNode
      WHERE id = node_id;
      
      -- 判断审批规则
      IF rule_text = 'ALL' AND approved_count < total_count THEN
        RETURN FALSE;
      ELSIF rule_text = 'SINGLE' AND approved_count = 1 THEN
        RETURN TRUE;
      ELSIF rule_text = 'ANY' AND approved_count > 0 THEN
        RETURN TRUE;
      END IF;
      
      -- 如果需要会审,则检查是否所有已有的审批人都通过了审批
      IF rule_text = 'ALL' THEN
        SELECT array_agg(DISTINCT approver)
        INTO approvers
        FROM ApprovalRecord
        WHERE node_id = node_id AND approved_result = true;
      END IF;
      
      -- 如果还有未审批通过的审批人,则返回FALSE
      IF approved_count < total_count AND NOT all(i IN approvers FOR j IN approver_list WHEN i = j) THEN
        RETURN FALSE;
      END IF;
      
      RETURN TRUE;
    END;
  $$
  LANGUAGE plpgsql;

这个函数的作用是判断指定节点是否可以通过审批。具体实现细节可以参考代码中的注释。

最后,我们需要创建一个函数来记录审批记录。

CREATE FUNCTION addApprovalRecord(node_id INTEGER, approver TEXT, approved_result BOOLEAN)
  RETURNS VOID
  AS $$
    BEGIN
      INSERT INTO ApprovalRecord(node_id, approver, approved_at, approved_result)
      VALUES(node_id, approver, NOW(), approved_result);
    END;
  $$
  LANGUAGE plpgsql;

这个函数的作用是记录审批记录信息。

至此,我们已经完成了审批流程的数据库表和函数的设计。在实际使用中,我们可以编写一个类似于控制器的程序来调用这些函数,从而控制审批流程的执行。具体的实现方式会根据具体的需求而有所不同。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值