搜尋開發指南

試試「多租戶」、「啟動」或「outbox」。
搜尋僅使用本站文件,不會傳送至外部服務。

文件目錄

NEXUSPRO / HANDBOOK

表單與申請

從 Form Definition、版本與 quota,到草稿、附件、送出和 workflow preview 的完整開發邊界。

內容核對 2026-09-28·圖文指南

本章目標與前置條件

讀完後,你應能從 template definition 追到 form instance,理解 revision、兩種 quota、attachment 與 workflow preview 的責任,知道請假表單怎麼把送審交給 attendance,並知道 fixture UI 不能代替 live API。前置條件是能閱讀 JSON schema、版本號、SWR mutation 與基本審批流程。

功能現況

區塊後端已註冊的 API/規則前端現況
Designerfield-types、templates list/get/create/update(沒有刪除路由)、validate、publish、versions、published、quota-policy(GET/PUT)、data-sources/workspace/forms 的 features/form-designer 有欄位(含 table 明細欄)、layout、condition、stage 編輯與 validation;沒有 quota 編輯,只讀 quota-policy、不呼叫 PUT
Runtimedrafts、建草稿前的 template preview、forms list/detail/definition、update/delete、submit、duplicate、workflow、workflow/preview、approve/reject/return/withdraw/admin-cancel、export、本人 quota 用量/forms 的 features/forms 有 list、modal、fields、template preview、workflow panel 與 action mutation
附件/v1/attachments create/metadata/content,form adapter 串接 upload lifecycleuseUploadFormAttachment 先建 metadata,再上傳 content,保留 schema 檢查
capabilityattendance.leave、attendance.overtime、attendance.correction、attendance.leave_cancellation、attendance.overtime_cancellation;綁定隨 definition 保存designer 沒有 capability 綁定編輯 UI,features/forms/capabilityFields.ts 只是 designer 與申請端共用的 schema 詞彙;加班時數推導、銷假紀錄回顯、代理人員工編號帶入都在申請端 FormsPage
fixture boundarydevelopment + NEXT_PUBLIC_MSW=true 時可使用 fixture;admin cancel fixture 明確拒絕偽造成功live mode 需 /v1/me 與後端;本文未把 fixture 當部署證據

核心概念

Definition schemaVersion=1

目前前端 schema 將 definition 拆成 fields、layouts、stages、entryStageId、capabilities 與 summaryFieldIds。field type(含 table)、condition operator、approval mode、security classification、data source key 等都是封閉詞彙;新增詞彙要同步 domain validator、OpenAPI、前端 schema 與 contract test。definition 在 DB 以 JSONB 保存,只檢查是 JSON object,詞彙沒有 DB constraint,後端 validator 是唯一把關。

查找值、明細表格與代理人欄位

  • 查找欄位的值是 server lookup 回傳的 value。leave_types 一律回假別 UUID(code 只為歷史 definition 保留),attendance.leave 送出時以 UUID 解析,送 code 會 422。
  • table 欄位以 table_columns 定義 1–20 個子欄(文字、數值、日期、選項或核取方塊,不可巢狀,也不可有預設值、唯讀或跨欄參照);值是最多 100 列、以子欄 ID 為鍵的物件陣列,必填子欄在送出時才檢查。
  • 請假單種子另有代理人欄位:proxy(employees lookup)與唯讀的 proxy_id;前端依所選代理人自動帶入員工編號(features/forms/proxyEmployeeNo.ts)。

Revision、quota 與 effect

Instance 每次保存有 revision,前端會把 revision 放入 workflow preview cache key,避免舊結果覆蓋新草稿。

這裡的 quota 是表單模板層級的「送單次數」配額,和假別天數餘額無關:送出時在表單交易內預留,quota_state 由 none 變 reserved,核准後為 consumed、其他終態為 released;額滿回 409 quota_exhausted(50600),quota_not_supported_for_template(50601)表示模板不支援送單次數限制。GET /v1/forms/templates/:formTemplateId/quota 的 reserved、consumed、remaining 由 server 判斷。假別的預扣與扣抵見假勤管理。

表單狀態和 attendance effect 狀態分開:核准後 effect_status 先是 pending,attendance 回報後才變 applied 或 failed(帶 effect_error_code),effectStatus 不能被簡化成 approved。

Preview 只計算,不寫業務狀態

POST /v1/forms/{formInstanceId}/workflow/preview 要求封閉空物件 {},service 只讀已保存的 draft/returned values,回傳 complete、stages、assignees、outcome 與 warnings。planned、skipped、undetermined 不是同義詞;資料不足時要保留 warning,不可猜成 false。建草稿前的 POST /v1/forms/templates/{formTemplateId}/preview 同樣只收 {},回傳 template、definition、applicant、預設值與同一套 workflow 預覽,不建立 instance。

請假申請的交接

請假表單(attendance.leave)送出時依序發生:

  1. 表單服務先以獨立 attendance 交易寫 leave admission,凍結政策版本與 hours_per_day;假別停用回 409 leave_type_inactive,天制假別缺 hours_per_day 回 409 leave_unit_conversion_unconfigured。
  2. 表單交易(tenant transaction 內的同步 PostgreSQL 狀態機)鎖定實例、比對 revision、預留送單次數 quota,並寫 outbox form.leave.reservation_requested。交易失敗會補償刪除 admission;commit 結果不明時保留。
  3. worker 的 attendance effect 非同步預扣假別餘額,所以送出 API 回 200 時預扣可能尚未完成。之後核准發 form.leave.approved,拒絕、退回、撤回或管理員取消發 form.leave.reservation_released。

一條請求鏈

架構流程圖 · Mermaid

正在繪製架構圖…

查看圖表原始碼
flowchart LR
  Designer["FormDesigner(/workspace/forms)"] --> Template["/v1/forms/templates"]
  Applicant["FormsPage(/forms)"] --> Draft["/v1/forms/drafts + /v1/forms"]
  Applicant --> Attach["/v1/attachments"]
  Draft --> Preview["workflow/preview"]
  Draft --> Submit["submit"]
  Submit --> Admission["請假單才有:leave admission"]
  Admission --> Tx["表單交易:quota 預留 + outbox"]
  Submit --> Tx
  Tx -- "reservation_requested" --> Effect["worker:attendance effect"]
  Tx --> Action["approve/reject/return/withdraw/admin-cancel"]
  Action -- "approved/reservation_released" --> Effect

Live API 的 features/forms/api.ts 刻意以 zod strict schema 解析 response(多數模組預設 .passthrough()),並將 cache key 以 tenant/account/fixture 狀態隔離。create、update、delete、submit、duplicate、withdraw、admin-cancel 成功後,共用的 useRevalidateFormLists 只重抓表單列表與 quota key;workflow preview 靠 key 內的 revision 自動重取,持久化 workflow 目前只在 admin-cancel 後手動 mutate。失敗時保留使用者輸入,不要以 fixture fallback 蓋掉錯誤。

實作步驟與示例

  1. 先鎖定是 template、instance、workflow 或 attachment 改動,再在 api/openapi.yaml 寫清 wire contract 與 BREAKING 影響;路由權限點以 internal/route/testdata/registry.golden 為準。
  2. 改 definition 時先更新 field/condition/stage 的 domain validator,再更新 OpenAPI、service、handler 與前端 schema;definition 是 JSONB,詞彙不靠 migration 把關,已發布版本只能新增、不能改寫。
  3. 表單提交必須通過 server validation、quota、permission、revision/idempotency 與 capability mapping;前端只做即時提示。submit、approve、reject、return、withdraw、admin-cancel 都要 Idempotency-Key;reject、return、admin-cancel 要非空 comment(最多 1000 字);admin-cancel 另需 tenant-wide 的 workflow.run.admin_cancel 決策,否則 403;刪除草稿要帶 ?revision=,duplicate 則在 body 帶 revision。
  4. workflow preview 必須用最新 draft revision;若回應落後,前端只重取一次,仍落後就顯示錯誤,而非展示舊 stage。
http
POST /v1/forms/00000000-0000-4000-8000-000000000001/workflow/preview
Content-Type: application/json

{}

這個 UUID 僅為格式示例,不是可用資料。要驗證時,使用受控 tenant 內真實 draft,確認回應 revision 等於或追上草稿 revision,並逐一檢查 stage outcome、warning 與 assignee;不要把空 body 以外的草稿值塞入 preview endpoint。

驗證矩陣

驗證問題程式碼/測試證據仍需另外做的驗收
definition 欄位/conditionfeatures/form-designer/api.ts、validateFormDefinition 測試、internal/domain/form/validate_test.go、internal/domain/form/validation_table_test.golive template validate/publish
runtime draft/revisionfeatures/forms/create-draft.contract.test.tsx、features/forms/resume-draft.test.tsx、features/forms/list-revalidation.contract.test.tsx、internal/api/v1/form_test.go真實租戶保存與並行 revision
workflow/template previewinternal/api/v1/form_workflow_preview_test.go、internal/api/v1/form_template_preview_test.go、features/forms/workflow-preview.contract.test.tsx、features/forms/template-preview.contract.test.tsx後端 service、角色解析與資料庫投影
actions/quotafeatures/forms/submitDraft.test.ts、features/forms/admin-cancel.contract.test.tsx、internal/api/v1/form_admin_cancel_test.go、internal/domain/form/quota_test.go、tests/unit/forminstance/events_test.go請假送出與核准的 effect 已有 2026-09-22 本機實測(見假勤管理);withdraw/reject/return 的 release 尚未實測
table 欄位internal/api/v1/form_table_json_test.go、internal/service/form/instance/values_table_test.go、features/forms/table-values.test.tslive 保存與送出
attachmentfeatures/forms/upload-identity.test.tsx、internal/api/v1/attachments_test.goobject storage、病毒掃描、內容下載

常見錯誤

  • 直接修改已發布 version;已發布版本不可改寫,應改 template 草稿(PUT 帶 revision),再走 validate/publish 產生新 version。
  • 用表單畫面自行算 remaining 或把 complete=false 當作條件不成立。
  • 把 quotaState(送單次數)當成假別餘額,或以為 designer 能設定 quota policy。
  • 假別欄位送 code;attendance.leave 只接受 lookup 回傳的假別 UUID。
  • 忘記把 draft revision 放入 cache key,導致 preview 看到上一版 stage。
  • 以「fixture action 成功」宣稱後端 action 成功;admin cancel 在 fixture 中刻意不偽造 authority。
  • 上傳 content 前跳過 metadata/identity 檢查,或把附件的 secret/object key 寫進文件與 log。

相關文件

內容來源與核實範圍

以下路徑相對於所列業務倉庫;核實層級為「已讀原始碼」,不是本輪業務測試或部署驗收。

  • nexus-pro-be-plus/internal/api/v1/form_routes.go
  • nexus-pro-be-plus/internal/api/v1/form_runtime.go
  • nexus-pro-be-plus/internal/api/v1/form_design.go
  • nexus-pro-be-plus/internal/api/v1/form_admin_cancel.go
  • nexus-pro-be-plus/internal/api/v1/form_quota.go
  • nexus-pro-be-plus/internal/api/v1/form_workflow_preview_test.go
  • nexus-pro-be-plus/internal/api/v1/attachments.go
  • nexus-pro-be-plus/internal/domain/form/definition.go
  • nexus-pro-be-plus/internal/domain/form/validate.go
  • nexus-pro-be-plus/internal/domain/form/validation_table.go
  • nexus-pro-be-plus/internal/domain/form/runtime.go
  • nexus-pro-be-plus/internal/domain/form/runtime_preview.go
  • nexus-pro-be-plus/internal/service/form/instance/commands.go
  • nexus-pro-be-plus/internal/service/form/instance/events.go
  • nexus-pro-be-plus/internal/wiring/gpsform_ports.go
  • nexus-pro-be-plus/db/migrations/000041_form_design.sql
  • nexus-pro-web-plus/features/forms/api.ts
  • nexus-pro-web-plus/features/form-designer/api.ts
  • nexus-pro-web-plus/features/form-designer/FormDesignerPage.tsx
  • nexus-pro-web-plus/features/form-designer/_components/BuilderView.test.tsx
  • nexus-pro-web-plus/features/forms/FormsPage.tsx
  • nexus-pro-web-plus/features/forms/_components/WorkflowPanel.tsx
  • nexus-pro-web-plus/features/forms/proxyEmployeeNo.ts
  • nexus-pro-web-plus/features/forms/overtimeHours.ts
NexusPro 開發指南以程式碼為準 · 以驗證為據