Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
62 KiB
ROLAC Church Management System — Project Planning
教會: River Of Life Christian Church In Arcadia (ROLAC)
規模: 50–100 人
文件版本: v0.3 (2026-05-29)
目錄
- 專案目標
- 系統模組總覽
- 模組詳細規劃
- 3.1 教友管理 (Member Management)
- 3.2 權限控管 & 多角色 (RBAC)
- 3.3 小組架構 (Cell Groups / Ministry Structure)
- 3.4 服事表 (Service Roster)
- 3.5 教會首頁 CMS
- 3.6 奉獻追蹤 (Giving / Donations)
- 3.7 年度收據 (Annual Giving Statement)
- 3.8 Audit Log
- 3.9 報表 (Reports)
- 3.10 Ministry Scope
- 3.11 未來 AI 整合
- 角色與權限矩陣
- 資料模型草圖
- 技術架構建議
- 開發階段規劃 (Roadmap)
- 開放議題 & 待決策
1. 專案目標
| 目標 | 說明 |
|---|---|
| 數位化教友資料 | 取代紙本或分散的試算表,集中管理教友資訊 |
| 透明化財務 | 讓奉獻記錄可查詢、可稽核,年底產生合規收據 |
| 強化小組連結 | 清楚呈現小組架構,追蹤出席與服事參與 |
| 簡化行政工作 | 服事排班、通知、報表自動化,減少人工作業 |
| 對外溝通 | CMS 管理教會網站,發佈消息/活動 |
| 安全與稽核 | 完整 Audit Log,細緻的角色權限,保護敏感資料 |
| 可擴展性 | 為未來 AI 功能(關懷提醒、智能報表)預留介面 |
2. 系統模組總覽
ROLAC CMS
├── 公開前台 (Public Website — rolac.org)
│ └── 教會首頁 CMS(雙語)
└── 後台管理 (Admin Portal — app.rolac.org)
├── 教友管理
├── 小組架構 & Ministry Scope
├── 主日出席記錄
├── 服事表
├── 敬拜歌曲庫
├── 代禱事項
├── 奉獻追蹤(含線上奉獻)& 年度收據
├── 支出追蹤 & 報銷
├── 月結對帳
├── 報表
├── Audit Log
├── 權限控管 (RBAC)
└── [未來] AI 整合
3. 模組詳細規劃
3.1 教友管理 (Member Management)
核心資料欄位
| 欄位群 | 欄位 |
|---|---|
| 基本資料 | 姓名 (中/英)、生日、性別、照片 |
| 聯絡資訊 | 電話、Email、地址 |
| 教會狀態 | 會員/訪客/前會員、受洗日期、入會日期、離會原因 |
| 家庭關係 | 家庭單元 ID、配偶、子女 |
| 小組歸屬 | 所屬小組、負責牧者/組長 |
| 服事歷史 | 參與服事記錄 |
| 自定義標籤 | 關懷需求、恩賜標籤、語言偏好 (中/英) |
功能清單
- 新增 / 編輯 / 軟刪除 教友資料
- 家庭單元管理(一個家庭多位成員)
- 進階搜尋與篩選(按小組、狀態、生日月份…)
- 生日/週年紀念提醒
- 匯入 / 匯出 CSV
- 個人資料變更歷史(誰改了什麼)
3.2 權限控管 & 多角色 (RBAC)
設計原則
- 最小權限原則:每個角色只能存取完成工作所需的資源
- Ministry Scope:部分角色僅能看到自己負責的 Ministry 資料
- 細粒度到 Resource + Action 層級
預設角色(見第 4 節矩陣)
ROLAC 為靈糧堂體制,無長老制。
| 角色 | 中文說明 | 層級 |
|---|---|---|
super_admin |
系統管理員,全權存取 | 系統 |
pastor |
牧師,全覽教友與財務摘要 | 牧者 |
board_member |
理事,教會治理委員 | 治理 |
coworker_chair |
同工會主席,統籌各事工領袖 | 領導 |
ministry_leader |
事工領袖,僅限自身 Ministry 範圍 | 事工 |
district_leader |
區長,管理轄下多個小組 | 小組 |
cell_leader |
小組長,僅限自身小組 | 小組 |
coworker |
同工,參與指定事工的一般同工 | 同工 |
finance |
財務同工,管理奉獻與支出報表 | 功能 |
secretary |
行政秘書,管理教友資料與排班 | 功能 |
worship_leader |
敬拜領袖,管理歌曲庫與敬拜歌單(Phase 暫緩) | 功能 |
member |
一般教友,查看個人資料與服事表 | 教友 |
visitor |
訪客,僅限公開頁面 | 教友 |
3.3 小組架構 (Cell Groups / Ministry Structure)
資料結構(樹狀)
教會 (Church — River Of Life Christian Church In Arcadia)
└── Ministry (事工部門)
└── Cell Group (小組)
└── Member (教友)
ROLAC 實際事工部門(初始種子資料)
| # | 英文名稱 | 中文名稱 | 主要職責 |
|---|---|---|---|
| 1 | Administration | 行政 | 教會行政、秘書、文件管理 |
| 2 | Preaching | 講道 | 主日講道、查經帶領 |
| 3 | Emcee | 司會 | 主日流程主持 |
| 4 | Worship | 敬拜 | 敬拜帶領、詩歌、樂器 |
| 5 | PPT / Media | PPT/影音 | 投影片製作、直播、錄影 |
| 6 | Sound | 音控 | 現場音響、混音 |
| 7 | Facility | 場地組 | 場地佈置、清潔、設備 |
| 8 | Hospitality | 招待 | 門口招待、訪客關懷、奉獻袋收集 |
| 9 | Children | 兒牧 | 兒童主日學、托兒 |
| 10 | Catering | 餐飲 | 每週愛宴、餐飲採購 |
這 10 個 Ministry 為系統初始種子資料(
DbInitializer),可在後台新增 / 修改。
功能清單
- 建立 / 管理 Ministry 與小組層級
- 指派組長與副組長
- 成員歸屬管理(一個教友可屬於多個 Ministry)
- 出席記錄(每次小組聚會)
- 成員轉移與歷史追蹤
- 小組狀態(活躍 / 暫停 / 解散)
- Ministry Scope 權限綁定
3.3b 主日出席記錄 (Sunday Service Attendance)
記錄方式(已確定): 招待同工(Greeting Team)統計總人數後,由秘書或招待組長手動輸入。
統計分類
| 類別 | 說明 |
|---|---|
| 大人 (Adults) | 成年會眾人數 |
| 青少年 (Teenagers) | 青少年人數 |
| 兒童 (Children) | 兒童主日學人數 |
| 合計 (Total) | 系統自動加總 |
資料模型
SundayAttendance
├── Id
├── ServiceDate (日期)
├── ServiceType (主日崇拜 / 特別活動 / 節日崇拜)
├── AdultCount
├── TeenCount
├── ChildrenCount
├── TotalCount (computed: Adult + Teen + Children)
├── Notes (備註,例:聖誕主日特別人數)
├── RecordedByUserId (誰輸入)
└── CreatedAt / UpdatedAt
功能清單
- 每週輸入三個類別人數(簡單表單)
- 合計自動計算
- 月 / 季 / 年 出席趨勢圖
- 出席率計算(以平均或最高值為基準)
- 節日 / 特別活動標記
- 匯出 CSV 供外部報表使用
3.4 服事表 (Service Roster)
ROLAC 主日服事槽位(初始種子資料)
每個槽位屬於一個 Ministry,一次服事可填入一個或多個同工。
| Ministry | 服事槽位 | 人數 | 頻率 |
|---|---|---|---|
| 講道 | 講員 Preacher | 1 | 每週 |
| 司會 | 主持人 Emcee | 1 | 每週 |
| 敬拜 | 敬拜帶領 Worship Leader | 1 | 每週 |
| 敬拜 | 敬拜團員 Worship Team | 2–5 | 每週 |
| 敬拜 | 司琴 Pianist | 1 | 每週 |
| PPT/影音 | PPT 操作 Slide Operator | 1 | 每週 |
| PPT/影音 | 攝影 / 直播 Livestream | 0–1 | 每週 |
| 音控 | 音控 Sound Engineer | 1 | 每週 |
| 場地組 | 場地佈置 Setup | 2–3 | 每週 |
| 場地組 | 場地收拾 Teardown | 2–3 | 每週 |
| 招待 | 門口招待 Greeter | 2–3 | 每週 |
| 招待 | 奉獻袋 Offering Collection | 2 | 每週 |
| 兒牧 | 兒童主日學老師 | 1–2 | 每週 |
| 兒牧 | 兒童助教 Assistant | 0–1 | 每週 |
| 餐飲 | 愛宴負責人 Catering Lead | 1 | 每週 |
| 餐飲 | 愛宴協助 Catering Help | 2–4 | 每週 |
功能清單
- 定義服事槽位(綁定 Ministry,雙語名稱)
- 每週排班(從教友庫中指派到各槽位)
- 週期性排班範本(每週 / 隔週 / 每月輪換)
- 自動衝突檢查(同一人同一主日多個衝突槽位)
- 缺席替換流程(申請 → 系統建議替補 → 確認)
- Email / Push Notification 服事提醒(服事前 2 天)
- 公開服事表嵌入網站(確認後才公開)
- 服事統計(每人參與頻率)
3.5 教會首頁 CMS
雙語範圍(已確定): 網站前台完整支援 英文 (EN) + 繁體中文 (zh-TW) 切換。
所有可見文字均需提供兩個語言版本,包含 SEO meta 欄位。
頁面 / 內容類型
| 類型 | 說明 |
|---|---|
| 首頁 Hero | 輪播橫幅、主題文字(雙語) |
| 關於我們 | 教會簡介、異象、牧師介紹(雙語) |
| 主日資訊 | 時間、地點、Google Map(地址雙語) |
| 消息公告 | 可分類標籤、發佈排程(標題 + 內文雙語) |
| 活動日曆 | 事件列表,可連結報名表單(雙語) |
| 媒體 | 主日講道影片/音訊嵌入(YouTube/Podcast)(標題雙語) |
| 奉獻頁面 | 線上奉獻說明(雙語) |
| 聯絡表單 | 訪客詢問,通知至指定 Email(表單標籤雙語) |
雙語內容資料模型
CMS 所有可編輯的文字欄位,一律使用平行欄位儲存:
CmsContent
├── Id
├── PageSlug (e.g. "home", "about", "announcements")
├── SectionKey (e.g. "hero.title", "hero.subtitle")
├── ContentType (Text | RichText | ImageUrl | Url)
├── ValueEn ← 英文版本
├── ValueZh ← 繁體中文版本
├── IsPublished
├── PublishAt (排程發佈)
├── UpdatedByUserId
└── UpdatedAt
Announcement
├── Id
├── TitleEn / TitleZh
├── BodyEn / BodyZh (Rich text)
├── Category
├── IsPublished
├── PublishAt
├── ExpiresAt
└── CoverImageUrl
Event
├── Id
├── TitleEn / TitleZh
├── DescriptionEn / DescriptionZh
├── Location (共用,或 LocationEn / LocationZh)
├── StartAt / EndAt
├── RegistrationUrl
└── CoverImageUrl
後台 CMS 編輯器 UI(Admin App)
每個可編輯欄位都採用並排雙欄編輯介面:
┌──────────────────────┬──────────────────────┐
│ English │ 繁體中文 │
│ ───────────────── │ ───────────────── │
│ [Welcome to ROLAC] │ [歡迎來到生命之河] │
└──────────────────────┴──────────────────────┘
- 兩欄同時顯示,編輯器可獨立輸入
- 儲存時驗證:若只填一種語言,提示警告(但允許儲存)
- 預覽模式可切換 EN / zh-TW 即時檢視
前台語言切換 UI
- Header 右上角
EN | 中切換按鈕 - 語言偏好存於
localStorage(訪客也記住) - URL 策略:使用 Angular
i18nroute prefix 或 query param,二擇一:- 方案 A(推薦):
rolac.org/en/aboutvsrolac.org/zh/about— 對 SEO 最友善 - 方案 B:
rolac.org/about?lang=zh— 實作較簡單
- 方案 A(推薦):
SEO 雙語支援
每個頁面在 <head> 中加入:
<link rel="alternate" hreflang="en" href="https://rolac.org/en/about" />
<link rel="alternate" hreflang="zh-TW" href="https://rolac.org/zh/about" />
<link rel="alternate" hreflang="x-default" href="https://rolac.org/en/about" />
- Meta title / description 依當前語言動態注入
- 使用 Angular
Metaservice 或ngx-seo
技術需求
- 富文本編輯器:Quill 或 TipTap(Angular 皆有 wrapper)
- 圖片上傳 → Azure Blob
cms/images/ - 預覽草稿後才發佈
- 發佈排程(
PublishAt欄位 + 背景排程 Job)
3.6 奉獻追蹤 (Giving / Donations)
奉獻類型
- 什一奉獻 (Tithe)
- 感恩奉獻 (General Offering)
- 特別奉獻 (Special/Project,可自訂名稱)
- 慣例奉獻 (Pledge)
支付方式(完整)
| 方式 | 類型 | 狀態 | 說明 |
|---|---|---|---|
| 現金 (Cash) | 線下手動 | ✅ Phase 1 | 信封號碼(選填)、匿名旗標 |
| 支票 (Check) | 線下手動 | ✅ Phase 1 | 支票號碼 |
| Zelle | 線下手動 | ✅ Phase 1 | 交易參考碼,無 API |
| PayPal (手動) | 線下手動 | ✅ Phase 1 | Transaction ID 手輸 |
| Stripe (線上) | 線上支付 | 🔜 Phase 4 | 信用卡 / Apple Pay / Google Pay |
| PayPal Checkout (線上) | 線上支付 | 🔜 Phase 4 | PayPal 按鈕嵌入 |
資料模型重點欄位
Giving
├── Id
├── MemberId (可為 null → 匿名 / 訪客線上奉獻)
├── GiverName (線上匿名奉獻者填寫的名字,可 null)
├── GiverEmail (線上奉獻用,發確認信)
├── GivingDate
├── Amount (decimal, 原始金額)
├── FeeAmount (decimal, 手續費,預設 0)
├── NetAmount (computed: Amount − FeeAmount)
├── GivingCategoryId (Tithe / Offering / Special…)
├── PaymentMethod (Cash | Check | Zelle | PayPal | Stripe | PayPalCheckout)
├── PaymentSource (Manual | OnlineStripe | OnlinePayPal)
├── ReferenceNumber (支票號 / Zelle ref / Stripe PaymentIntent ID / PayPal txn)
├── EnvelopeNumber (現金信封號碼,選填)
├── IsAnonymous (bool)
├── FundProjectId (特別奉獻專案,可 null)
├── IsRecurring (bool, 定期奉獻)
├── RecurringScheduleId (FK → GivingRecurringSchedule,可 null)
├── Notes
├── RecordedByUserId (手動輸入者;線上奉獻為 null)
└── StripeEventId (防重複,Webhook idempotency key)
GivingRecurringSchedule ← 定期線上奉獻
├── Id
├── MemberId
├── Amount
├── GivingCategoryId
├── Frequency (Weekly | BiWeekly | Monthly)
├── NextChargeDate
├── StripeSubscriptionId
├── Status (Active | Paused | Cancelled)
└── CreatedAt
功能清單
- 手動記錄奉獻(含現金/支票/Zelle/PayPal)
- 主日奉獻袋批次輸入(Phase 1,見 §3.6c)
- 線上奉獻頁(Phase 4,見 §3.6b)
- 定期自動奉獻(Stripe Subscription,Phase 4)
- PayPal / Stripe 手續費分開記錄,IRS 收據用 NetAmount
- 奉獻目標 / 專案進度條
- 個人奉獻歷史(本人可查)
- 月結對帳報表
3.6c 主日奉獻袋批次輸入 (Sunday Offering Batch Entry — Phase 1)
業務場景
主日聚會結束後,財務同工收到奉獻袋,需要逐一開袋,將每筆現金信封或支票對應到教友姓名,登入系統記錄,年底才能產生個人奉獻收據。
工作流程
財務同工開啟「主日奉獻錄入」
│
▼
選擇日期(預設今天)
│
▼
┌───────────────────────────────────────┐
│ 逐筆快速錄入介面 │
│ ───────────────────────────────── │
│ 搜尋教友:[_______________] ← 即時搜尋 │
│ 奉獻類型:[Tithe ▼] │
│ 支付方式:[● 現金 ○ 支票] │
│ └─ 現金:信封號碼 [___] (選填) │
│ └─ 支票:支票號碼 [___] (必填) │
│ 金額: [$________] │
│ 備注: [_______________] (選填) │
│ │
│ [+ 新增] [匿名奉獻] │
│ ───────────────────────────────── │
│ 已錄入 12 筆 | 小計:$1,250.00 │
└───────────────────────────────────────┘
│
▼
所有信封錄入完成
│
▼
對帳確認頁(顯示今日所有筆數 + 總計)
財務同工核對實際金額 = 系統合計
│
▼
確認送出 → 系統 Bulk Insert
UI 設計要點
| 要點 | 說明 |
|---|---|
| 教友搜尋 | 即時搜尋(姓名中英文 / 拼音),顯示照片方便確認 |
| 鍵盤優先 | Tab 鍵在欄位間切換,Enter 新增,不需滑鼠 |
| 支付方式切換 | 選「支票」才出現支票號碼欄;選「現金」才出現信封號欄 |
| 匿名奉獻 | 一鍵匿名,不需搜尋教友,仍記錄金額供帳目平衡 |
| 即時小計 | 每新增一筆,當日累計金額即時更新 |
| 對帳視圖 | 最後一步顯示完整清單,供財務核對實際鈔票 / 支票 |
| 可編輯 | 送出前可點任一筆修改或刪除 |
| 送出後修改 | 需財務角色才可編輯,修改記錄進 Audit Log |
資料模型補充
OfferingSession ← 每次主日錄入為一個 Session
├── Id
├── SessionDate (主日日期)
├── Status (Open | Submitted)
├── CashTotal (computed)
├── CheckTotal (computed)
├── TotalAmount (computed)
├── SubmittedByUserId
├── SubmittedAt
└── Givings[] (關聯當次錄入的所有 Giving 記錄)
為什麼需要 OfferingSession?
將同一主日的所有奉獻筆數綁在一起,方便財務同工核對「這次錄入的總計」是否與實際收到的現金+支票金額吻合,在確認前可以整批修改,確認後進 Audit Log。
3.6d 支出追蹤 & 報銷 (Expense Tracking & Reimbursement — Phase 1)
業務場景
| 場景 | 說明 |
|---|---|
| 代墊報銷 | 同工先自掏腰包買教會物品,事後憑收據向教會申請報帳 |
| 廠商付款 | 教會直接開支票給廠商(例:每週愛宴午餐外燴) |
| 雜支現金 | 小額現金支出(如停車費、文具) |
支出流程
【場景 A:代墊報銷】
同工提交報銷申請
(日期、金額、類別、說明、收據照片)
│
▼
財務同工審核
├── 批准 → 開支票 / 現金還款給同工
│ 記錄支票號碼 + 付款日期
└── 退回 → 填寫退回原因
【場景 B:廠商直接付款(如愛宴)】
財務同工直接建立支出記錄
(廠商名稱、金額、支票號碼、日期、類別)
→ 狀態直接為「已付款」
支出分類架構(兩層 + Ministry)
每筆支出標記三個維度:
Ministry(事工部門) × 大類(Category Group) × 子項目(Sub-Category)
範例:
敬拜事工 > 影音 > 設備
敬拜事工 > 影音 > 教育訓練
餐飲部門 > 餐飲 > 消耗品
餐飲部門 > 餐飲 > 出餐費用
行政 > 辦公 > 文具耗材
行政 > 人事 > 薪資
兒童事工 > 教材 > 印刷費用
設計原則: 大類(影音、餐飲)是跨 Ministry 共用的,同一大類可出現在不同 Ministry。
例如:敬拜事工和兒童事工都可能有「影音 > 設備」的支出。
資料模型
ExpenseCategoryGroup ← 大類(Level 1)
├── Id
├── NameEn / NameZh (影音 A/V、餐飲 Food、辦公 Office…)
├── SortOrder
└── IsActive
ExpenseSubCategory ← 子項目(Level 2)
├── Id
├── ExpenseCategoryGroupId (FK → ExpenseCategoryGroup)
├── NameEn / NameZh (設備 Equipment、教育訓練 Training、出餐費用 Catering…)
├── SortOrder
└── IsActive
Expense ← 每筆支出
├── Id
├── ExpenseDate
├── Description (說明)
├── Amount
├── MinistryId (哪個事工部門承擔此支出)
├── CategoryGroupId (大類,FK → ExpenseCategoryGroup)
├── SubCategoryId (子項目,FK → ExpenseSubCategory)
├── PaymentMethod (Cash | Check | CreditCard | BankTransfer)
├── CheckNumber (若 PaymentMethod = Check)
├── PayeeType (Vendor | StaffReimbursement)
├── PayeeName (廠商名稱 或 同工姓名)
├── MemberId (若 PayeeType = StaffReimbursement → 指向同工)
├── ReceiptBlobPath (收據照片,Azure Blob: finance/receipts/)
├── Status (Draft | PendingApproval | Approved | Paid | Rejected)
├── RejectionReason
├── SubmittedByUserId
├── ApprovedByUserId
├── ApprovedAt
├── PaidAt
├── Notes
└── CreatedAt
預設大類 & 子項目(種子資料,可在後台自訂)
| 大類(EN / 中) | 子項目 | 常用於 Ministry |
|---|---|---|
| Equipment / 設備 | 購置 · 租借 · 維修 | 敬拜、PPT/影音、音控、場地組、兒牧 |
| Consumables / 耗材 | 電池 · 配件 · 清潔用品 · 文具 | 音控、PPT/影音、場地組、招待、行政 |
| Food & Beverage / 餐飲 | 出餐費用 · 食材採購 · 器具 · 消耗品 | 餐飲、兒牧 |
| Training / 教育訓練 | 課程費用 · 書籍 · 研討會 · 差旅 | 敬拜、PPT/影音、音控、兒牧 |
| Materials / 教材 | 印刷費用 · 手工材料 · 版權購買 | 兒牧、講道、司會 |
| Facility / 場地 | 場地租金 · 水電 · 財產保險 · 裝飾 | 場地組、行政 |
| Printing / 印刷 | 週報 · 程序單 · 海報 | 行政、招待、兒牧 |
| Missions / 宣教 | 奉獻轉帳 · 宣教士支援 · 差旅 | 行政 |
| Benevolence / 關懷 | 急難救助 · 慰問禮品 · 探訪費用 | 行政 |
| Other / 其他 | 雜支 | 所有 |
| Personnel / 人事 | 薪資 · 薪資稅費 · 員工福利 · 勞工保險 · 酬庸 · 同工進修 · 外包勞務 | 行政 |
分類備注:
Facility > 財產保險為建築物/場地責任險;員工健保等歸Personnel > 員工福利。同工代墊報銷(StaffReimbursement)依實際購買物選大類,薪資/福利付款才歸人事。
Ministry × 大類 常用對應(供財務設定參考)
| Ministry | 最常用大類 |
|---|---|
| 行政 Administration | 人事 · 辦公耗材 · 印刷 · 場地 · 宣教 · 關懷 |
| 講道 Preaching | 教材 · 書籍(Training) |
| 司會 Emcee | 印刷(程序單) |
| 敬拜 Worship | 設備 · 教育訓練 · 耗材 |
| PPT/影音 Media | 設備 · 耗材 · 教育訓練 |
| 音控 Sound | 設備 · 耗材 · 教育訓練 |
| 場地組 Facility | 設備 · 場地 · 耗材(清潔) |
| 招待 Hospitality | 耗材 · 印刷(程序單) |
| 兒牧 Children | 教材 · 設備 · 餐飲 · 教育訓練 |
| 餐飲 Catering | 餐飲(出餐費用 · 食材 · 器具) |
UI 選擇流程(錄入時)
選擇 Ministry → 選擇大類 → 選擇子項目
[餐飲 ▼] [餐飲 ▼] [出餐費用 ▼]
[敬拜 ▼] [設備 ▼] [購置 ▼]
- 大類清單不依 Ministry 過濾(保持靈活)
- 選定大類後,子項目自動篩選對應選項
- 找不到適合子項目 → 選「其他」並填說明
狀態流轉
廠商直接付款: (finance 直接建立) → Paid
同工報銷申請: Draft → PendingApproval → Approved → Paid
└─────────────────→ Rejected
月底對帳(月結報表)
這是整個財務閉環的核心:
月結對帳表(MonthlyStatement)
期初餘額(Opening Balance) $X,XXX.XX
+ 本月奉獻收入(從 Giving 表加總) $X,XXX.XX
+ 其他收入(手動補充) $ .00
− 本月支出(從 Expense 表加總) $X,XXX.XX
= 帳面期末餘額(Calculated Closing) $X,XXX.XX
銀行對帳單餘額(Bank Statement Balance) $X,XXX.XX
差異(Difference) $ 0 ← 目標為零
MonthlyStatement
├── Id
├── Year / Month
├── OpeningBalance (手動輸入上月結餘,首月由財務設定)
├── TotalGiving (auto: SUM Giving WHERE month)
├── TotalOtherIncome (手動補充)
├── TotalExpenses (auto: SUM Expense WHERE month AND Status=Paid)
├── CalculatedClosingBalance (computed)
├── BankStatementBalance (財務同工手動輸入)
├── Difference (computed: Calculated − Bank)
├── Notes
├── Status (Draft | Reconciled)
├── ReconciledByUserId
└── ReconciledAt
Phase 3 預算功能(MinistryBudget)預留欄位:
分類架構現在就做好,Phase 3 只需增加MinistryBudget表,
按 Ministry + CategoryGroup + SubCategory 設定年度預算額,
對比實際 Expense 計算使用率,不需改動 Expense 結構。
收據照片上傳(Azure Blob)
finance/
└── receipts/
└── {year}/{month}/{expenseId}-{filename}.jpg
- 使用 Capacitor Camera 拍攝,即時上傳
- 或桌機版直接上傳圖片檔
- Private,API 產生 SAS URL(限財務角色存取)
權限
| 操作 | 角色 |
|---|---|
| 提交報銷申請 | 所有登入用戶(含 member) |
| 審核 / 批准 | finance、super_admin |
| 建立廠商直接付款 | finance、super_admin |
| 查看所有支出 | finance、pastor、super_admin |
| 查看人事類支出 | finance、pastor、super_admin(事工領袖不可見) |
| 查看自己的申請 | 提交者本人 |
| 月底對帳 | finance、super_admin |
3.6b 線上奉獻頁 (Online Giving — Phase 4)
推薦:Stripe(主要)+ PayPal 按鈕(次要)
| 比較項目 | Stripe | PayPal |
|---|---|---|
| Nonprofit 費率 | 1.5% + $0.30(需申請 Stripe Nonprofit Rate) | 1.99% + $0.49(PayPal Giving Fund for 501c3) |
| C# SDK | ✅ 官方 Stripe.net | ✅ PayPalCheckoutSdk |
| Apple Pay / Google Pay | ✅ 原生支援 | ❌ 需另外設定 |
| Webhook 可靠性 | ✅ 非常成熟 | ⚠️ 歷史上較多問題 |
| 定期奉獻 | ✅ Stripe Subscription | ⚠️ 較複雜 |
線上奉獻頁流程(rolac.org/give)
訪客/教友進入 /give 頁面
│
▼
選擇奉獻��金(Tithe / General / Special)
選擇金額(預設選項 $50 / $100 / $200 / 自訂)
選擇頻率(一次性 / 每月)
填寫姓名、Email(非登入狀態)
│
▼
Stripe Payment Element(信用卡 / Apple Pay / Google Pay)
│
▼
Stripe 處理付款
│
┌──┴──┐
成功 失敗
│
▼
Stripe Webhook → POST /api/webhooks/stripe
→ 自動建立 Giving 記錄(PaymentSource = OnlineStripe)
→ Email 確認信給奉獻者
→ 若有 MemberId → 加入個人奉獻歷史
Stripe Webhook 安全驗證(C#)
[HttpPost("/api/webhooks/stripe")]
public async Task<IActionResult> StripeWebhook()
{
var json = await new StreamReader(Request.Body).ReadToEndAsync();
var stripeEvent = EventUtility.ConstructEvent(
json,
Request.Headers["Stripe-Signature"],
_stripeConfig.WebhookSecret // 環境變數
);
if (stripeEvent.Type == EventTypes.PaymentIntentSucceeded)
{
var intent = stripeEvent.Data.Object as PaymentIntent;
await _givingService.RecordOnlineGivingAsync(intent);
}
return Ok();
}
環境變數(加入 .env)
STRIPE_SECRET_KEY=sk_live_...
STRIPE_PUBLISHABLE_KEY=pk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
PAYPAL_CLIENT_ID=...
PAYPAL_CLIENT_SECRET=...
3.7 年度收據 (Annual Giving Statement)
功能清單
- 依年度、教友產生正式奉獻收據
- PDF 格式,含教會抬頭、稅務資訊(EIN)、奉獻明細
- 批次產生(一次為所有符合條件的教友生成)
- Email 直接寄送給教友
- 收據補發 / 作廢紀錄
- 符合 IRS 501(c)(3) 格式要求
3.8 Audit Log
記錄範圍
| 事件類型 | 範例 |
|---|---|
| 資料異動 | 教友資料修改、刪除 |
| 財務操作 | 奉獻新增、編輯、刪除 |
| 權限變更 | 角色指派、撤銷 |
| 認證事件 | 登入成功、失敗、密碼重設 |
| 系統設定 | 設定變更 |
記錄欄位
- timestamp (UTC)
- actor_id (who)
- actor_role
- action (CREATE / UPDATE / DELETE / LOGIN / …)
- resource_type
- resource_id
- before_snapshot (JSON)
- after_snapshot (JSON)
- ip_address
- user_agent
存取控制
- 只有
super_admin與pastor可查看 Audit Log - Audit Log 本身不可刪除(只能 Archive)
3.9 報表 (Reports)
預設報表清單
| 報表名稱 | 說明 | 受眾 |
|---|---|---|
| 教友統計 | 按狀態/性別/年齡/小組分佈 | 牧師、理事、同工會主席 |
| 新人追蹤 | 過去 N 個月新訪客/受洗趨勢 | 牧師 |
| 出席報表 | 主日 & 小組出席率趨勢 | 牧師、組長 |
| 奉獻摘要 | 月/季/年 奉獻總額、按類型分佈 | 財務、牧師 |
| 服事參與 | 每人服事頻率、空缺率 | 事工負責人 |
| 關懷追蹤 | 標記需關懷教友的跟進記錄 | 牧師、組長 |
技術需求
- 圖表視覺化(Bar / Line / Pie)
- 可匯出 CSV / PDF
- 報表可設定排程自動寄送
3.10 Ministry Scope
概念說明
Ministry Scope 讓 ministry_leader 與 cell_leader 只能存取屬於自己事工範圍的教友、服事與報表資料,不會看到其他事工的敏感資訊。
實作要點
- 每筆資源(教友、服事項目、奉獻記錄)綁定
ministry_id - API 層強制過濾(後端 Row-Level Security 或 Middleware)
- 跨事工存取需由上層角色(coworker_chair / pastor)代為操作
- Audit Log 記錄跨 Scope 操作
3.12 敬拜歌曲庫 (Worship Song Library)
用途: 集中管理教會使用的詩歌,整合歌詞庫、敬拜排序規劃、YouTube 參考連結與教會自錄影片。
3.12a 歌曲資料庫 (Song Catalog)
核心欄位
Song
├── Id
├── TitleEn / TitleZh
├── ArtistEn / ArtistZh (原唱/作者)
├── AlbumEn / AlbumZh (選填)
├── CcliNumber (string, 選填) ← CCLI 版權號碼
├── DefaultKey (e.g. "G", "Ab")
├── Tempo (Slow | Mid | Fast)
├── TimeSignature (e.g. "4/4", "3/4")
├── Language (EN | ZH | Bilingual)
├── Tags (string[], e.g. ["Worship","Praise","Christmas"])
├── IsActive (bool, 是否仍在使用)
├── CreatedByUserId
└── UpdatedAt
SongLyrics ← 歌詞分段存放
├── Id
├── SongId
├── SectionType (Verse | Chorus | Bridge | PreChorus | Outro | Intro)
├── SectionOrder (int, 排序)
├── LyricEn
└── LyricZh
SongMedia ← 多媒體連結
├── Id
├── SongId
├── MediaType (YouTubeReference | ChurchRecording | SheetMusic | ChordChart)
├── Title
├── YouTubeVideoId (只存 ID,e.g. "dQw4w9WgXcQ")
├── BlobPath (Azure Blob,教會自錄影片/樂譜 PDF)
└── UploadedAt
功能清單
- 新增 / 編輯 / 封存詩歌
- 雙語歌詞分段輸入(Verse / Chorus / Bridge…)
- 搜尋:標題、標籤、CCLI 號碼、語言篩選
- 上傳樂譜 PDF / 和弦表 → Azure Blob(
worship/sheets/) - 關聯 YouTube 參考影片(只存 Video ID,嵌入播放,不下載)
- 上傳教會自錄影片 → Azure Blob(
worship/recordings/) - 匯出歌詞 PDF(用於投影或印刷)
3.12b 敬拜規劃 / 歌單 (Worship Set / Setlist)
概念: 每次主日或特別聚會,敬拜負責人規劃當次要唱的詩歌清單及順序。
WorshipSet
├── Id
├── ServiceDate
├── ServiceType (主日崇拜 | 禱告會 | 特別聚會)
├── LeadWorshiperId (敬拜帶領人 → Member)
├── Status (Draft | Confirmed | Completed)
├── Notes
├── CreatedByUserId
└── SetItems[]
WorshipSetItem
├── Id
├── WorshipSetId
├── SongId
├── ItemOrder (歌曲順序)
├── PlayKey (本次演唱調性,可與 Song.DefaultKey 不同)
├── Notes (e.g. "唱兩遍,不含橋段")
└── IsSkipped (bool, 臨時略過)
功能清單
- 建立歌單,從歌曲庫拖曳/搜尋新增詩歌
- 調整歌曲順序(拖曳排序)
- 指定每首歌本次演唱調性
- 歌單狀態:草稿 → 確認 → 完成
- 一鍵產生 歌單 PDF(供投影、印刷或發給敬拜隊)
- 歌單 PDF 包含:歌名(雙語)、歌詞、本次調性、備注
- 歷史歌單統計: 哪些詩歌最常使用(供 AI 整合預留)
3.12c YouTube 連結策略
重要:直接下載 YouTube 影片違反 YouTube 服務條款(ToS),無論用途。
| 做法 | 合法性 | 建議 |
|---|---|---|
嵌入 YouTube Player(<iframe>) |
✅ 合法 | 系統使用此方式 |
| 存 YouTube Video ID 在 DB | ✅ 合法 | 前端動態組成嵌入連結 |
| 使用 yt-dlp 或其他工具下載 | ❌ 違反 ToS | 不實作 |
| 教會自錄影片上傳 Azure Blob | ✅ 合法 | 支援此方式 |
| 從 CCLI StreamingPlus 購買下載 | ✅ 合法 | 教會可另外購買版權 |
YouTube 嵌入實作
// Angular 元件中安全嵌入 YouTube
import { DomSanitizer } from '@angular/platform-browser';
get safeYouTubeUrl() {
const videoId = this.song.youTubeVideoId;
return this.sanitizer.bypassSecurityTrustResourceUrl(
`https://www.youtube.com/embed/${videoId}`
);
}
3.12d CCLI 版權合規
什麼是 CCLI?
- Church Copyright Licensing International — 教會詩歌版權授權機構
- ROLAC 應有(或應申請)CCLI License,才能合法在聚會中投影/印刷/錄製詩歌
- 每首有 CCLI 授權的詩歌都有唯一的 CCLI Number
系統支援
- 每首歌可記錄
CcliNumber(選填) - 教會 CCLI License 號碼存於系統設定(
Settings.CcliLicenseNumber) - 歌單 PDF 頁腳自動加印:
CCLI License # XXXXXXXX - 未來可加:使用頻率報告(CCLI 要求每年報告使用歌曲,以計算版稅)
3.12e Azure Blob 存儲結構(敬拜模組)
rolac-storage/
└── worship/
├── sheets/ ← 樂譜 PDF、和弦表
│ └── {songId}-{filename}.pdf
├── recordings/ ← 教會自錄影片(MP4)
│ └── {songId}-{date}.mp4
└── setlists/ ← 歌單 PDF 匯出存檔
└── {setId}-{date}.pdf
存取控制
worship/sheets/→ Private,API 產生 SAS URL(1 小時有效)worship/recordings/→ Private,API 產生 SAS URLworship/setlists/→ Private,敬拜負責人可下載
3.12f 權限控管
| 操作 | 可執行角色 |
|---|---|
| 查看歌曲庫 | 全體登入用戶 |
| 新增 / 編輯詩歌 | worship_leader、ministry_leader(敬拜)、super_admin |
| 刪除 / 封存詩歌 | ministry_leader(敬拜)、super_admin |
| 建立 / 編輯歌單 | worship_leader、ministry_leader(敬拜) |
| 查看歌單 | 全體登入用戶(含一般教友查看已確認歌單) |
| 上傳影片 / 樂譜 | worship_leader、ministry_leader |
新增角色
worship_leader(敬拜帶領人)加入 RBAC 角色清單。
3.13 代禱事項 (Prayer Requests)
核心設計原則
- 教友可提交代禱事項,設定可見範圍
- 牧者/組長可追蹤禱告進度、標記應允
- 不強制公開,隱私保護優先
資料模型
PrayerRequest
├── Id
├── SubmittedByMemberId (提交者;可匿名提交)
├── IsAnonymous (bool — 不顯示提交者姓名)
├── Title (簡短標題)
├── Content (詳細內容)
├── Visibility (Private | CellGroup | AllLeaders | Public)
│ ← Private: 僅牧者/提交者本人
│ ← CellGroup: 提交者的小組成員
│ ← AllLeaders: 所有 Leader 及以上
│ ← Public: 所有登入教友
├── Status (Active | Answered | Archived)
├── AnsweredNote (應允見證,選填)
├── ExpiresAt (自動封存日期,預設 90 天後)
├── CellGroupId (若 Visibility = CellGroup)
├── CreatedAt
└── UpdatedAt
PrayerFollow ← 誰在為這個代禱追蹤
├── Id
├── PrayerRequestId
├── MemberId
├── PrayedAt (最後禱告時間)
└── Note (私人筆記,只有自己看到)
Visibility 存取規則
| Visibility | 可見範圍 |
|---|---|
Private |
提交者本人 + pastor + super_admin |
CellGroup |
同小組成員 + cell_leader + district_leader + pastor |
AllLeaders |
ministry_leader / district_leader / coworker_chair / board_member / pastor 及以上 |
Public |
所有登入教友(含 member) |
功能清單
- 教友提交代禱(可匿名)
- 選擇可見範圍
- 「我在為此禱告」按鈕(記錄 PrayerFollow)
- 牧者 / 組長標記為「已應允」並填寫見證
- 90 天後自動封存(可延長)
- 通知:新公開代禱事項 → 推播通知給相關成員(可關閉)
- App 端「代禱牆」:顯示 Public + CellGroup 範圍的事項
與 CMS 整合(選用)
- 可在網站公開「代禱牆」頁面顯示
Visibility = Public的事項 - 需教友登入才能查看(不對訪客公開)
權限矩陣補充
| 操作 | 角色 |
|---|---|
| 提交代禱 | 所有登入用戶(含 member) |
| 查看 Private | 提交者本人、pastor、super_admin |
| 標記已應允 | pastor、cell_leader(限自己小組)、super_admin |
| 刪除代禱 | 提交者本人、pastor、super_admin |
| 查看所有代禱 | pastor、super_admin |
3.11 未來 AI 整合
這些功能在 Phase 1/2 不實作,但資料模型與 API 設計需為其預留擴展點。
預想功能
| 功能 | 說明 |
|---|---|
| 關懷提醒 | 分析出席模式,自動提醒牧者關懷長時間缺席的教友 |
| 智能排班建議 | 根據服事歷史與可用性,推薦最佳排班組合 |
| 奉獻洞察 | 自然語言查詢(「今年三月奉獻比去年增加多少?」) |
| 講道摘要 | 自動摘要上傳的講道錄音 / 文稿 |
| 新訪客跟進 | AI 起草個人化歡迎信件草稿供牧者審閱後發送 |
| 聊天機器人 | 教會網站 FAQ 機器人,回答主日時間、聯絡方式等 |
技術預留
- 保持 API first 設計,AI 功能透過內部 API 存取資料
- 重要事件發布到事件匯流排(event bus),供 AI Agent 訂閱
- 考慮使用 Claude API (Anthropic) 作為 LLM 後端
4. 角色與權限矩陣
✅ 全權限 🔒 僅限自身 Scope 👁 唯讀 ❌ 無存取
ROLAC 為靈糧堂體制,角色依序:牧師 > 理事 ≈ 同工會主席 > 事工領袖 > 區長 ≈ 小組長 > 同工 > 會友
| 資源 / 操作 | super_admin | pastor | board_member 理事 | coworker_chair 同工會主席 | ministry_leader 事工領袖 | district_leader 區長 | cell_leader 小組長 | coworker 同工 | finance 財務 | secretary 秘書 | member 會友 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 教友資料 — 查看 | ✅ | ✅ | ✅ | ✅ | 🔒事工 | 🔒區 | 🔒組 | 🔒事工 | 👁 | ✅ | 👁自己 |
| 教友資料 — 編輯 | ✅ | ✅ | ❌ | ❌ | 🔒事工 | ❌ | ❌ | ❌ | ❌ | ✅ | 👁自己 |
| 教友資料 — 刪除 | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| 小組 — 管理 | ✅ | ✅ | 👁 | ✅ | 🔒事工 | 🔒區 | 🔒組 | ❌ | ❌ | 👁 | ❌ |
| 服事表 — 查看 | ✅ | ✅ | 👁 | ✅ | 🔒事工 | 🔒區 | 🔒組 | 🔒事工 | ❌ | ✅ | 👁 |
| 服事表 — 編輯 | ✅ | ✅ | ❌ | ✅ | 🔒事工 | ❌ | 🔒組 | ❌ | ❌ | ✅ | ❌ |
| 歌曲庫 — 查看 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | 👁 |
| 歌曲庫 — 編輯 | ✅ | ✅ | ❌ | ✅ | 🔒敬拜 | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| 歌單 — 建立/編輯 | ✅ | ✅ | ❌ | ✅ | 🔒敬拜 | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| 代禱 — 提交 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 代禱 — 查看全部 | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| 代禱 — 標記應允 | ✅ | ✅ | ❌ | ✅ | ❌ | 🔒區 | 🔒組 | ❌ | ❌ | ❌ | ❌ |
| 奉獻 — 查看 | ✅ | ✅ | 👁摘要 | 👁摘要 | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | 👁自己 |
| 奉獻 — 編輯 | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| 支出 — 查看 | ✅ | ✅ | 👁摘要 | 👁摘要 | 🔒事工 | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| 支出 — 申請報銷 | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| 支出 — 審核 | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| 年度收據 — 產生 | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| 月結對帳 | ✅ | 👁 | 👁 | 👁 | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| CMS — 編輯 | ✅ | 👁 | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ |
| 報表 | ✅ | ✅ | 👁 | 🔒 | 🔒事工 | 🔒區 | ❌ | ❌ | 🔒財務 | 👁 | ❌ |
| Audit Log | ✅ | 👁 | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| 角色管理 | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| 系統設定 | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
5. 資料模型草圖
詳細 Schema 設計請參閱
docs/DB_SCHEMA.md(v1.0,含完整欄位定義、索引、EF Core 設定)
Phase 1 核心實體關係:
┌─────────────────┐ ┌─────────────────┐
│ AppUser │────▶│ AppRole │
│ (ASP.NET │ │ (RBAC, 10 角色)│
│ Identity) │ └─────────────────┘
└────────┬────────┘
│ 0..1 : 1
┌────────▼────────┐ ┌─────────────────┐
│ Member │────▶│ FamilyUnit │
│ (教友資料) │ │ (家庭單元) │
└────┬────────┬───┘ └─────────────────┘
│ M:N │ 1:N
│ │
┌────▼──────┐ └──────────────┐
│ Ministry │ ┌───▼──────────────┐
│ (10 部門) │ │ MemberMinistry │
└────┬──────┘ │ (服事歸屬) │
│ 1:N └──────────────────┘
┌────▼──────────────┐
│ UserMinistry │
│ (Ministry Scope) │
└───────────────────┘
┌──────────────────┐ ┌─────────────────────┐
│ OfferingSession │───▶│ Giving │
│ (主日奉獻批次) │ │ (奉獻記錄) │
└──────────────────┘ └──────────┬──────────┘
│ 1:N
▼
┌─────────────────┐
│ GivingReceipt │
│ (年度收據) │
└─────────────────┘
┌──────────────────────┐ ┌─────────────────────┐
│ ExpenseCategoryGroup │────▶│ ExpenseSubCategory │
│ (大類: 設備/餐飲…) │ │ (子項目) │
└──────────────────────┘ └──────────┬──────────┘
│
┌──────────────────────────────────────▼─────────────┐
│ Expense │
│ (MinistryId + CategoryGroupId + SubCategoryId) │
│ Type: VendorPayment | StaffReimbursement │
└──────────────────────────────────────┬─────────────┘
│ 1:N
┌────────────▼────────────┐
│ MonthlyStatement │
│ (月底對帳表) │
└─────────────────────────┘
┌───────────────┐ ┌──────────────┐
│ PrayerRequest │────▶│ PrayerFollow │
│ (代禱事項) │ │ (跟進記錄) │
└───────────────┘ └──────────────┘
AuditLog(bigint PK,immutable,所有操作均記錄)
各模組 Table 數量:
| 模組 | Tables | Phase |
|---|---|---|
| Identity & Auth | 8(ASP.NET Identity 6 + UserMinistry + UserDevice) | P1 |
| Member Management | 4(Member, FamilyUnit, MemberMinistry, MemberTag) | P1 |
| Ministry | 1 | P1 |
| CMS | 4(CmsPage, Announcement, SermonVideo, ContactInquiry) | P1 |
| Giving | 5(GivingCategory, OfferingSession, Giving, GivingReceipt, GivingRecurringSchedule) | P1 |
| Expense | 4(ExpenseCategoryGroup, ExpenseSubCategory, Expense, MonthlyStatement) | P1 |
| Prayer Requests | 2 | P1 |
| Audit Log | 1 | P1 |
| Notifications | 1 | P1 |
| Phase 1 Total | 30 Tables | |
| Service Roster | 2(ServiceSlot, ServiceAssignment) | P2 |
| Sunday Attendance | 1 | P2 |
| Cell Groups | 4(CellGroup, CellGroupMembership, CellGroupMeeting, CellGroupAttendance) | P2 |
| Ministry Budget | 1 | P3 |
| Grand Total | 38 Tables |
6. 技術架構 (已確定)
技術選型
| 層 | 技術 | 說明 |
|---|---|---|
| 前端 / App | Angular + Capacitor | Web → iOS & Android 打包 |
| Admin/Portal UI | Angular Material + Kendo UI | Dashboard、資料表格、排班 |
| Landing Page UI | Tailwind CSS + 自訂元件 | 設計感公開網站 |
| 後端 API | ASP.NET Core (C#) | REST API |
| ORM | Entity Framework Core | Code-first migrations |
| 資料庫 | PostgreSQL | 自架於 Docker |
| 檔案儲存 | 本地檔案儲存(現階段)→ Azure Blob Storage(未來) | 透過 IFileOperationService 抽象,現以 LocalFileOperationService(base folder 由 config 設定)實作,未來切換 AzureFileOperationService。教友照片、PDF 收據、CMS 媒體 |
| 原始碼管理 | Gitea | 自架,Docker 容器 |
| CI/CD | Jenkins | 自架,Docker 容器 |
| 容器化 | Docker + Docker Compose | 所有服務容器化 |
| 主機 | Azure VM (Ubuntu) | Microsoft Nonprofit $2,000 credit |
| 反向代理 | Nginx | SSL 終止、路由分發 |
| SSL | Let's Encrypt + Certbot | 免費自動續期 |
| SendGrid 或 SMTP Relay | 通知、收據寄送 | |
| SMS | Twilio | 服事提醒、緊急通知 |
| PDF 產生 | QuestPDF (C# library) | 年度收據、報表 |
| 多語言 | ngx-translate | 執行期語言切換(en / zh-TW) |
Mobile App 策略 (Angular + Capacitor)
為什麼用 Capacitor 而非純 PWA
| 需求 | PWA | Capacitor |
|---|---|---|
| App Store / Play Store 上架 | ❌ | ✅ |
| 推播通知 (Push Notification) | 有限 | ✅ 原生 |
| 相機(教友照片) | 有限 | ✅ 原生 |
| 離線快取 | Service Worker | ✅ 原生 |
| 開發成本 | 低 | 中(同一 Angular codebase) |
Capacitor 整合要點
- 同一份 Angular codebase → Web + iOS App + Android App
- 使用
@capacitor/push-notifications推播服事提醒 - 使用
@capacitor/camera拍攝/上傳教友照片 - 使用
@capacitor/local-notifications本機提醒(排班、生日) - Jenkins CI 額外加
npx cap build ios/npx cap build android步驟
Mobile-First 設計規範
| 規範 | 要求 |
|---|---|
| 觸控目標 | 最小 44 × 44 px |
| 字體基礎 | 16px(不可縮放到 < 12px) |
| 底部導覽列 | 主要功能用 Bottom Tab Bar,不用側邊 Sidebar |
| 表單 | 單欄式,每個 input 標明 inputmode(數字、Email…) |
| 圖表 | 可橫向捲動,不縮小到難以閱讀 |
| 圖片 | 懶加載(lazy loading)、WebP 格式優先 |
| 離線提示 | 網路斷線時顯示快取資料 + 明確提示 |
多語言 (i18n) 策略
使用 ngx-translate(非 Angular 內建 i18n)
- 理由:執行期動態切換,不需要分開 build;適合 App 場景
- 語言包:
assets/i18n/en.json、assets/i18n/zh-TW.json - 語言偏好存於
localStorage/ Capacitor Preferences - API 回傳資料中,多語系欄位用平行欄位設計(見下)
雙語適用範圍(全系統)
| 範疇 | 雙語方式 |
|---|---|
| Admin App UI 標籤 | ngx-translate JSON(en.json / zh-TW.json) |
| 公開網站 UI 標籤 | 同上 |
| CMS 內容(公告、活動、頁面) | DB 平行欄位(title_en / title_zh) |
| Ministry / 服事類型名稱 | DB 平行欄位 |
| Email / SMS 通知內容 | 依教友語言偏好選範本 |
| IRS 年度收據 | 英文為主,繁中附於後 |
| PDF 報表 | 後台報表以 UI 語言為準 |
多語系資料欄位命名慣例
// DB 欄位(需要雙語的 Entity)
name_en / name_zh
title_en / title_zh
description_en / description_zh
body_en / body_zh
// ngx-translate key(UI 固定字串)
assets/i18n/en.json
assets/i18n/zh-TW.json
語言切換 UI
- 公開網站 & Admin App Header 右上角
EN | 中切換按鈕 - 切換後立即套用,不重整頁面
- 教友個人設定可儲存語言偏好(
Member.LanguagePreference) - 公開網站 URL 加
/en/或/zh/前綴,對 SEO 最友善
其他核心架構原則
- JWT + Refresh Token — API 無狀態認證
- ASP.NET Core Identity — 使用者管理、密碼雜湊
- 全新資料庫 — 無舊資料遷移需求,直接 EF Code-First Migration
檔案儲存抽象層 (File Storage Abstraction)
背景(2026-05-29 決定): Microsoft 拒絕了我們的 Nonprofit / Azure 申請,現階段無法使用 Azure Blob Storage。
因此先改用本地檔案儲存(base folder 由 config 設定),未來取得 Azure 額度後再切換為 Azure Blob,業務程式碼不需改動。
設計:以介面抽象隔離儲存後端
所有檔案讀寫(教友照片、PDF 收據、CMS 媒體、收據照片、敬拜樂譜/影片等)一律透過 IFileOperationService 介面操作,業務層不直接依賴任何特定儲存實作。
IFileOperationService ← 抽象介面(業務層僅依賴此介面)
├── SaveAsync(path, stream) → 儲存檔案,回傳相對路徑 / 識別碼
├── GetAsync(path) → 讀取檔案串流
├── DeleteAsync(path) → 刪除檔案
├── ExistsAsync(path) → 是否存在
└── GetUrlAsync(path, expiry?) → 取得存取 URL(本地:API 代理路徑;Azure:SAS URL)
LocalFileOperationService ← 現階段實作(✅ Phase 1)
├── Base folder 從 config 讀取(e.g. FileStorage:BasePath)
├── 路徑沿用既有結構(cms/images/、finance/receipts/、worship/… 相對於 base folder)
├── Private 檔案經由 API 代理 + 角色授權提供存取(取代 SAS URL)
└── 容器化時 base folder 對映到 Docker volume,確保持久化
AzureFileOperationService ← 未來實作(🔜 取得 Azure 額度後)
├── 對映到 Azure Blob Container
├── GetUrlAsync 回傳具時效的 SAS URL
└── 切換方式:DI 註冊改綁此實作 + 一次性資料搬移,業務程式碼零改動
設定範例(appsettings)
"FileStorage": {
"Provider": "Local", // Local | Azure(未來)
"BasePath": "/data/rolac-files" // 本地 base folder(容器內對映 volume)
}
與本文件其他段落的關係: 文中所有提到
Azure Blob/blob 路徑的地方(§3.5 CMS 圖片、§3.6dfinance/receipts/、§3.12eworship/...),現階段一律改由IFileOperationService+LocalFileOperationService以對應相對路徑儲存於 config 的 base folder 下;待 Azure 開通後切換AzureFileOperationService即還原為 Blob 儲存,路徑結構不變。
7. 開發階段規劃 (Roadmap)
Phase 0 — 技術基礎 & DevOps (2–3 週)
- Azure VM 建置 + Docker 環境
- Gitea + Jenkins 啟動,CI pipeline 通
- Angular + Capacitor 專案骨架(含 ngx-translate en/zh-TW)
- ASP.NET Core API 骨架 + EF Core 初始 Migration
- 認證系統(JWT + Refresh Token + ASP.NET Identity)
- RBAC 框架(角色 + Ministry Scope middleware)
- Audit Log 基礎建設
- 檔案儲存抽象層(
IFileOperationService+LocalFileOperationService,base folder 從 config 讀取) - Mobile-first UI 元件庫設定(底部導覽、touch target 規範)
Phase 1 — 六月上線 MVP(5 週,目標 2026-06-30)
教會首頁 CMS(rolac.org)
- Landing Page 基礎設計(Tailwind,簡化版先上線)
- 首頁 Hero / 關於我們 / 主日資訊(雙語)
- 消息公告(雙語,支援排程發佈)
- 講道影片嵌入(YouTube)
- 聯絡表單
教友管理
- 教友 CRUD(基本資料、照片上傳,經
IFileOperationService→ 本地儲存) - 家庭單元管理
- 搜尋 / 篩選(姓名、狀態、小組)
- 教友狀態(會員 / 訪客 / 前會員)
- i18n 語言切換 UI(EN / 中 按鈕)
奉獻追蹤(手動)
- 奉獻類型設定(Tithe / Offering / Special)
- 單筆奉獻記錄(現金 / 支票 / Zelle / PayPal)
- 主日奉獻袋批次輸入(OfferingSession) ← 鍵盤優先快速錄入
- 個人奉獻歷史查詢(教友 App 端)
- 年度收據 PDF 產生(QuestPDF,EIN 42-2682968)
- 年度收據 Email 批次寄送
支出追蹤 & 報銷
- 支出類別設定(11 大類種子:設備 / 餐飲 / 人事 / 宣教…)
- 廠商直接付款記錄(含支票號碼)
- 同工代墊報銷申請(含收據照片上傳)
- 財務審核流程(Pending → Approved → Paid)
- 月結對帳表(期初餘額 + 奉獻 − 支出 = 帳面期末,對比銀行對帳單)
代禱事項(Prayer Requests)
- 教友提交代禱請求(含 4 個可見範圍:Private / CellGroup / AllLeaders / Public)
- 代禱清單瀏覽(依角色過濾可見範圍)
- 牧者標記「已應允」(PrayerFollow 記錄)
- 代禱事項到期提醒(可選,Email)
基礎功能
- 登入 / 登出 / 密碼重設
- RBAC 角色指派(super_admin、finance、secretary、member 先上)
- Email 通知(SendGrid,收據寄送用)
- Capacitor 打包(Android APK 供內部測試)
Phase 2 — 服事 & 小組(2026 年 8–10 月,目標 10 週)
已確認範圍(2026-05-24 決定)
服事表排班(Service Roster)
- 服事項目設定(雙語名稱,對應 10 個事工部門)
- Kendo Scheduler 排班視圖(月/週/日)
- 衝突檢查(同一人同日多項服事)
- 排班通知(Email + Push,服事前 3 天)
- 缺席申請 & 替換流程
- 服事表 PDF 匯出(週服事表)
主日出席統計(Sunday Attendance)
- 每週輸入:大人 / 青少年 / 兒童 三欄
- 歷史趨勢圖(Kendo Chart,年度/季度)
- 報表匯出(CSV)
小組管理(Cell Group Management)
- 小組架構建立(巢狀樹狀,支援多層)
- 組長指派(組長擁有自身小組資料權限)
- 小組成員指派 / 移轉
- 小組聚會記錄(CellGroupMeeting + 出席 Attendance)
- 小組出席報表
Phase 3 — 財務深化(2026 年 11 月 → 2027 年,目標 4–6 週)
已確認範圍(2026-05-24 決定)
事工預算(Ministry Budget)
- 各事工年度預算設定(MinistryBudget:Ministry + CategoryGroup + SubCategory + FiscalYear + BudgetAmount)
- 預算 vs 實際支出對比(Kendo Chart)
- 超支警示(支出超過預算 80% 時通知財務)
- 年度預算報表 PDF 匯出
備注: Category 結構已於 Phase 1 設計完成,無需 Schema 異動,直接新增 MinistryBudget 表即可。
Phase 4 — 線上奉獻(2027 年,目標 4–6 週)
已確認:Stripe(主)+ PayPal Checkout(次)
- 線上奉獻頁(rolac.org/give)— Stripe 整合
- Stripe Webhook → 自動建立 Giving 記錄
- 定期奉獻(Stripe Subscription)
- PayPal Checkout 按鈕(次要選項)
- 申請 Stripe Nonprofit 費率(目標 1.5% + $0.30)
暫緩模組(無明確時程)
| 模組 | 原因 |
|---|---|
| 敬拜歌曲庫(Worship Song Library) | CCLI License 未確認;優先級 TBD |
| 事工報表(Reports Dashboard) | 等 Phase 1–2 資料累積後再做 |
| 廣播通知(Broadcast Messaging) | 低優先,Email 手動寄送可暫代 |
| 會員目錄 / 通訊錄 | 隱私設計複雜,暫緩 |
| 兒童特殊欄位 | 緊急聯絡人 / 過敏 / 接送授權,暫緩 |
Phase 5 — App 上架 & AI 整合(持續)
- App Store 正式上架(需 Apple Developer 帳號 $99/年)
- Google Play 上架($25 一次性)
- 效能優化 & 安全稽核
- 出席缺席關懷 AI 提醒(Claude API / Anthropic)
- 智能排班建議
- 自然語言報表查詢
- 代禱事項 AI 摘要(週代禱精華)
8. 開放議題 & 待決策
| # | 議題 | 選項 / 說明 | 優先級 | 狀態 |
|---|---|---|---|---|
| 1 | 已決定: C# API + EF + PostgreSQL + Angular | 🔴 高 | ✅ 決定 | |
| 2 | 已決定: Azure VM (Ubuntu + Docker),Nonprofit Credit | 🟡 中 | ✅ 決定 | |
| 3 | 已決定: 招待同工統計,分大人/青少年/兒童,秘書手動輸入 | 🔴 高 | ✅ 決定 | |
| 4 | 已決定: 現金+支票(現有),Zelle+PayPal(即將開放),手動輸入為主,PayPal 未來可 Webhook | 🔴 高 | ✅ 決定 | |
| 5 | 已確認: rolac.org | 🔴 高 | ✅ 決定 | |
| 6 | 已決定: 英文 + 繁體中文,不需簡中 | 🟡 中 | ✅ 決定 | |
| 7 | 已決定: Angular + Capacitor 打包 iOS/Android | 🟡 中 | ✅ 決定 | |
| 8 | 已決定: 無現有資料,全新建置 | 🟡 中 | ✅ 決定 | |
| 9 | 已決定: Phase 2 再建,同 VM port 分離 | 🟡 中 | ✅ 決定 | |
| 10 | AI 整合時程 | Phase 5,但 API 設計預留擴展點 | 🟢 低 | ⏳ 待決 |
| 11 | 已確認: EIN 42-2682968,存為環境變數,不 hardcode |
🟡 中 | ✅ 決定 | |
| 12 | 已決定: 使用 Twilio | 🟢 低 | ✅ 決定 | |
| 13 | App Store 上架策略 | Phase 1–2 TestFlight 內部測試;Phase 5 正式上架 | 🟡 中 | ⏳ Phase 5 再決 |
| 14 | 已決定: 納入 Phase 1,4 個可見範圍 | 🔴 高 | ✅ 決定 | |
| 15 | 已決定: Phase 4,Stripe(主)+ PayPal Checkout(次),Nonprofit 費率申請 | 🔴 高 | ✅ 決定 | |
| 16 | 會員目錄 / 通訊錄 | 隱私考量需 Opt-in,暫緩 | 🟢 低 | ⏳ 未來再評估 |
| 17 | 兒童特殊欄位 | 緊急聯絡人、過敏、接送授權,暫緩 | 🟢 低 | ⏳ 未來再評估 |
| 18 | CCLI License 號碼 | 教會是否已有 CCLI License?需填入系統設定 | 🟡 中 | ⏳ 待確認 |
| 19 | 已決定:Phase 2 = 服事表排班 + 主日出席統計 + 小組管理;Phase 3 = 事工預算 | 🔴 高 | ✅ 決定 | |
| 20 | 已決定:Microsoft 拒絕申請,暫無法用 Azure Blob。改以 IFileOperationService 抽象,現階段用 LocalFileOperationService(base folder 由 config 設定),未來取得 Azure 額度後切換 AzureFileOperationService(見 §6 檔案儲存抽象層) |
🔴 高 | ✅ 決定 |
下拉雙語顯示約定 (Dropdown Bilingual Display)
所有業務下拉選單的選項同時顯示英文與中文,格式 英文/中文(無空格、英文在前;無中文則只顯示英文)。
- DB 查表下拉(giving categories / ministries / expense category groups & subs):
在對應的 API service 載入時計算
label = bilingual(name_en, name_zh),模板綁textField="label"。 不改 DB、不改 schema、不改儲存值。 - 寫死 enum 下拉(payment method / expense status / member status / gender / language / roles):
選項一律定義在
APP/src/app/shared/i18n/option-lists.ts,型別{ value, label }, 模板綁textField="label" valueField="value" [valuePrimitive]="true"。送出/儲存的value不變。 - 共用工具:
APP/src/app/shared/i18n/bilingual.ts的bilingual(en, zh)。 - 新增下拉時沿用以上兩種模式,不要在 component 內各自寫死中文字串。
文件由 ROLAC 開發團隊維護。