簽核引擎與應用整合

簽核不是一個「審批模組」,而是一層掛在資料寫入路徑上的攔截器。這代表:不論資料從 Custom App、REST API 還是 AI 助理寫進來,簽核都會生效——沒有繞過的路徑。


運作原理

在一般系統中,新增一筆請假單或採購單,資料會立刻寫入生效。AI GO 的差別在於:

  1. 寫入攔截:當管理者為某張表啟用簽核流程後,對該表的寫入會被自動攔截
  2. 派單:系統依流程定義推導出合格審核人並發送通知,產生簽核申請
  3. 核准回調:所有關卡通過後,平台自動執行原本被攔截的操作——包含它連帶觸發的所有業務引擎(開票、扣庫存、產傳票)

若任一關卡駁回,資料會退回草稿狀態,可修改後重新送審。

三種寫入的攔截語意不同

操作攔截行為
新增資料以待審核狀態保存,通過後正式生效
更新不執行。變更內容暫存,通過後由平台自動套用
刪除不執行。通過後由平台自動執行

更新與刪除的差別很重要:它們不會先寫進去再回滾,而是根本不執行。呼叫端會收到一個帶有申請識別碼的待簽核例外。

呼叫端不需要也不應該重試——重試只會產生重複的簽核申請。正確處理是捕捉例外並告知使用者「已送出簽核」。


設定簽核流程

入口:主控台「系統與維運管理 › 簽核流程引擎」,需要 system.admin 權限。

1. 指定目標

選擇要套用的資料表(銷售訂單、請假單、進項帳單等)。一張表同時只能啟用一個流程。

2. 觸發條件

可設定只在特定條件下才需要簽核。例如「金額大於 100,000 的採購單才需主管簽核」——低於門檻的直接放行,不製造無謂的審批負擔。

條件也可以依記錄的欄位值路由到不同流程。

3. 規劃關卡

按順序建立多個關卡(第一關部門經理、第二關財務總監)。每個關卡可設定:

  • 是否為必要關卡
  • 簽核類型:單人核准即可,或多人會簽(全員通過才算過)

4. 定義合格審核人

每個關卡指定審核人資格,支援三種規則:

規則說明
指定使用者特定帳號
指定角色具備該角色的所有成員(如所有財務主管)
動態部門主管依「申請人的部門主管」動態派單,可設定往上追溯的層級

動態部門主管是最實用的一種——組織異動時不需要回頭改流程定義。


在 Custom App 中整合

簽核 SDK 讓您把簽核直接做進應用程式,使用者不需要切換到主控台。

伺服器端

def execute(ctx):
    # 觸發者本人的待簽核清單
    pending = ctx.approval.list_pending()

    # 查某筆記錄的簽核狀態(含各關卡明細)
    status = ctx.approval.get_record_status('sale_orders', order_id)

    # 以觸發者身分核准/駁回
    ctx.approval.approve(line_id, comment='確認無誤')
    ctx.approval.reject(line_id, comment='金額與報價不符')

    # 取消申請(限申請人本人、限進行中)
    ctx.approval.cancel(request_id, reason='重新評估')

前端

src/approval.ts 提供對應的前端方法,可以直接組出簽核面板——顯示歷史軌跡、輸入意見、一鍵核准或駁回。

身分綁定

簽核 SDK 綁使用者身分,這是它與其他 SDK 最大的差別:

  • list_pending() 回的是觸發者本人的待辦,不是全組織的
  • approve() 會驗證觸發者是否為該關卡的合格審核人,不是就拒絕
  • 沒有平台使用者身分的呼叫(如排程)會被拒絕

這代表您無法用應用程式的權限「代替別人簽核」。


透過 API 整合

外部系統可以完整整合簽核機制:

GET  /api/v1/approvals/record/{res_model}/{res_id}
POST /api/v1/approvals/{request_line_id}/approve
POST /api/v1/approvals/{request_line_id}/reject
POST /api/v1/approvals/{request_id}/retry

查詢狀態:回傳每一關卡的狀態、審核人名稱、簽核意見與時間明細。若尚未發起簽核則回傳空。

核准:帶入簽核明細行的識別碼與意見。系統會驗證呼叫者資格;最後一關核准時自動執行回調。

駁回:原始記錄重設為草稿,可修改後重送。

回調重試:簽核全數通過但回調因外部因素失敗時,管理者可手動重試。回調失敗不會讓簽核狀態退回——它是獨立的補救動作。


常見設計模式

讓使用者知道「已送出簽核」而不是「失敗」

def execute(ctx):
    try:
        ctx.db.update('sale_orders', order_id, {'state': 'sale'})
        return ctx.response.json({'status': 'updated'})
    except Exception as e:
        if 'approval' in str(e).lower():
            return ctx.response.json({
                'status': 'pending_approval',
                'message': '變更已送出簽核,通過後自動生效'
            })
        raise

在列表上顯示簽核狀態

get_record_status 批次查詢,把「待第 2 關 / 財務總監」這類資訊直接標在列表上,使用者不必逐筆點進去看。

主管的待辦面板

list_pending() 在應用首頁做一個待辦區塊。這是簽核 SDK 最高價值的用法——主管不必為了簽核而登入另一套系統。


邊界與注意事項

  • 一張表一個流程:需要不同條件走不同路徑時,用條件路由而非多個流程
  • 簽核與業務引擎的順序:回調在簽核通過後才執行,因此開票、扣庫存、產傳票都發生在通過的那一刻,不是送審的當下
  • 排程觸發的寫入:簽核守衛仍會生效,簽核介面上的申請人顯示為 API
  • 稽核:所有簽核決定都留下完整紀錄,包含審核人、時間與意見