Функция базы данных PostgreSQL реализует узел, который можно настроить в соответствии с должностными ролями, включая функцию многоуровневого утверждения, а также совместную проверку или проверку в процессе утверждения.

Функция базы данных PostgreSQL реализует узел, который можно настроить в соответствии с должностными ролями, включая функцию многоуровневого утверждения, а также совместную проверку или проверку в процессе утверждения.

Прежде чем приступить к реализации, нам необходимо определить некоторые понятия и правила:

  1. Процесс утверждения состоит из нескольких узлов утверждения (узла утверждения), и каждый узел представляет собой процесс утверждения.
  2. Каждый узел утверждения содержит идентификатор узла, имя узла и необязательное описание узла.
  3. Процесс утверждения также включает в себя начальный и конечный узлы, для которых не требуется настраивать конкретных утверждающих.
  4. Узел утверждения может иметь несколько последующих узлов. Это означает, что после прохождения утверждения процесс продолжится до одного из этих последующих узлов.
  5. Для каждого узла утверждения необходимо настроить правило утверждения, которое используется для определения того, как будет продолжаться процесс (это может быть совместная проверка, коллективная проверка или утверждение одним человеком).
  6. Конкретное определение правил утверждения будет дано позже.
  7. Записи об утверждении будут записаны в отдельной таблице записей об утверждении, и каждая запись включает идентификатор узла утверждения, утверждающего, время утверждения и результат утверждения.

Используя приведенные выше правила и концепции, мы можем приступить к разработке таблиц базы данных и функций процесса утверждения. Вот возможная реализация:

Во-первых, нам нужно создать таблицу узла утверждения (ApprovalNode) для хранения всей информации узла утверждения.

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

Среди них поле правила представляет собой правило утверждения, которое может принимать одно из следующих трех значений:

  1. «ВСЕ»: правила сортировки. Указывает, что для продолжения процесса необходимо утвердить все узлы.
  2. «ЛЮБЫЕ»: дополнительные правила. Указывает, что если хотя бы один узел среди всех узлов одобрен, процесс может быть продолжен.
  3. «SINGLE»: Единое правило утверждения. Указывает, что только один утверждающий текущего узла должен утвердить процесс для продолжения.

next_node_ids указывает идентификатор следующего узла. Для последнего узла в процессе утверждения это поле пусто.

Далее нам нужно создать таблицу записей утверждения (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 указывает идентификатор узла утверждения, утверждающий указывает имя утверждающего, утвержденный_at указывает время, когда утверждение было передано, а утвержденный_результат указывает, было ли одобрено одобрение.

Далее нам нужно создать функцию для запроса всех последующих идентификаторов узлов данного узла.

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;

Эта функция запрашивает все последующие идентификаторы узлов для данного узла.

Далее нам нужно создать функцию, чтобы определить, может ли указанный узел быть одобрен.

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;

Функция этой функции заключается в записи информации об утверждении.

На данный момент мы завершили проектирование таблиц базы данных и функций процесса утверждения. В реальном использовании мы можем написать программу, похожую на контроллер, для вызова этих функций и управления выполнением процесса утверждения. Конкретный метод реализации будет варьироваться в зависимости от конкретных требований.

Guess you like

Origin blog.csdn.net/sunny_day_day/article/details/131164135