跳至主要内容

報表責任分區

具體報表以 RPT 為契約,在應用程式的 report 責任分區集中參數、純值輸入、計算、範本與產生入口。 HTML+CSS 用來理解、溝通及確認版面;Java 範本依已確認規格建立文件,框架 renderer 產生 PDF。 架構取捨見 ADR-021,規格與證據流程見 報表規格。

目錄與所有權​

沿專案既有 businessLayout 組織,同一業務 owner 的報表集中管理:

佈局RPT 實作DB 資料 adapter
layer-firstreport/{domain}/repository/{domain}/,需要時加 report/ 子包
package-by-feature{domain}/report/該 domain 的 repository 分區

報表跨多個領域時,由其業務用途指定 owner,資料來源以 Source adapter 組合。 這些程式屬 application domain;feature core 仍依既有 feature ownership 與 partition 管理。

與同名 job 領域的區別​

本指南的 report 分區是具體 RPT 的文件組成,不以 package 中含 report 判定。 例如 layer-first 既有 job 領域的 controller/report/、dto/report/、entity/report/、repository/report/、 service/report/ 及 runtime 組裝 feature/report/、feature/reportjob/ 都不屬 RPT 分區,仍遵守各自的層與 feature 規範。 repository/report/ 是 job 資源持久化;repository/{domain}/report/ 可放該業務 domain 的 RPT Source adapter。

report 本體的依賴禁令不套用到 job controller/service 或 Source adapter;正式 Source adapter 位於 repository, 可使用 JPA/Entity 完成查詢及純值投影,再將完整輸入交給 report。 報表 advisory rule 的 paths 僅是載入提示,須先辨別檔案的責任,再套用相應條款。

各層責任​

部分責任
controllerHTTP 輸入與回應、wire 解析、下載 adapter
service/產品 job操作授權、可見範圍決定、一致性讀取交易、tenant context、非同步與保存/下載生命週期
repository/資料 adapter在查詢套用範圍、條件、排序、limit;依已定義資料來源完成純值投影及必要代碼標籤
entity持久化模型與關聯
reportRPT 參數及呼叫情境契約、輸入模型、資料來源介面、排序/分組/合計、格式與範本、產生協調及容量限制
框架 renderer通用排版、字型與 PDF 輸出

service 決定資料可見範圍,Source adapter 在查詢落實它;generator 可再核對回傳資料沒有越界。 資料完整性與業務決策仍沿既有 Domain Model/Service 契約;報表計算依 RPT 定義,不複製產品狀態流轉或授權政策。

RPT 明訂支援的同步/非同步模式、預設及選擇規則,見報表規格「執行方式」 (docs-methodology/specs/report-specification.md)。service/controller 依產品 API 實現交付;僅同步的報表不要求 job, 非同步工作只在規格支援且產品流程採用時組合。容量硬上限不因模式放寬,逾時不自行建立 job 或重試; 等待中止與伺服器取消須分開定義。範本仍只負責文件內容與版面,不管理模式或 job 生命週期。

依賴方向​

generator 接收 RPT request 與已授權的 call context,以 Source 取得完整純值輸入,再交給範本與框架 renderer。 Source 契約放在 report;正式 DB adapter 位於 repository 並實作契約,依賴方向由 adapter 指向 report 的介面與模型。 generator 不匯入具體 Repository、產品 Service、Controller DTO 或 HTTP request/session。

範本只依賴輸入模型及公開 authoring API;report 不依賴 JPA、Hibernate、Spring Data 或持久化 Entity, 不在渲染期間觸發 lazy association。領域純值 enum/value type 可以重用;它位於 entity package 不代表本身是持久化 Entity。

一致性讀取交易由呼叫端管理,Source 在交易內完成查詢及投影,dataAsOf 由呼叫端提供。 是否在渲染前結束交易,由資料快照與既有 job 的一致性契約決定,不能因搬移 package 改變交易語意。

命名示意​

以下為占位示意,實際名稱以專案的統一語言為準:

report/{domain}/
{ReportName}Request.java
{ReportName}Data.java
{ReportName}Generator.java # Source 可為獨立介面或入口內的公開契約
{ReportName}Report.java # Java 範本
repository/{domain}/report/
Jpa{ReportName}Source.java # 正式查詢與純值投影

參考實作 app-v2026.1.23 起將 feature/report 限於字型、renderer 與同步名額, 背景 executor/維護排程移至另行選用的 feature/reportjob;job 資源仍在 service/report 等業務層。 來源與遷移界線見 ADR-035,已採納並於 app-v2026.1.23 發布。 具體 RPT 的 report 分區與 job domain 各有責任;建立 RPT 本身不要求建立 job、產品端點或 Spring bean。

搬移與驗證​

搬移需同步 consumer imports、測試位置、當前實作連結與重跑命令;範本、參數及資料行為不變時,不因目錄調整遞增 RPT revision。 若同時改變契約或輸出語意,依 RPT 版次規則修訂。 以架構測試守住依賴方向,以既有內容/容量/分頁測試及正式 adapter 的範圍查詢測試驗證行為。

舊 PDF、JUnit XML 與接受帳本保留為當時版本的歷史。移除舊來源路徑或修改 RPT bytes 會使既有帳本 stale; 不要改寫舊指紋、XML 類名或接受紀錄。重錄依現行 report skill,完成所需 HTML 包與真人確認後再建立新的 PDF 帳本。 單純重構的測試結果可以另存為 peer review 證據,不能據此宣告新的 PDF 接受或產品驗收。