# ROLAC — 通知系統設計 **文件版本:** v0.1 (2026-05-24) --- ## 通知渠道總覽 | 渠道 | 技術 | 適用場景 | 狀態 | |------|------|----------|------| | **Email** | SendGrid / SMTP | 年度收據、週報、重要公告 | Phase 0 | | **Push Notification** | Capacitor Push | 服事提醒、排班更新、活動通知 | Phase 1 | | **SMS** | Twilio | 緊急通知、服事前一天提醒 | Phase 2 | | **App 內通知** | Angular 元件 | 所有通知的 in-app 備份 | Phase 1 | --- ## 各渠道設計 > **實作狀態 (2026-06-23):** Email (SMTP/MailKit) + Line 已於 API 端實作,見 > [docs/superpowers/specs/2026-06-23-notification-service-email-line-design.md](superpowers/specs/2026-06-23-notification-service-email-line-design.md)。 > 本檔早期願景中的 SendGrid/Push/SMS 仍為未來規劃。 ### Email (SendGrid) **觸發時機** | 事件 | 收件人 | 說明 | |------|--------|------| | 年度奉獻收據產生 | 個別教友 | 含 PDF 附件 | | 歡迎新教友 | 新教友 | 帳號啟用信 | | 密碼重設 | 帳號持有人 | OTP / Reset Link | | 服事排班確認 | 當週服事同工 | 每週四自動發送 | | 系統 Build 失敗 | admin@rolac.org | Jenkins CI 通知 | **Email 範本要求** - 雙語(EN / zh-TW),依教友語言偏好發送 - 教會 Logo header - 手機版 Responsive HTML - Unsubscribe 連結(行銷類) --- ### Push Notification (Capacitor) **使用 `@capacitor/push-notifications`** 後端使用 **Firebase Cloud Messaging (FCM)** 作為推播服務(Android + iOS 共用)。 **推播事件** | 事件 | 時機 | 內容範例 | |------|------|----------| | 服事提醒 | 服事前 2 天 09:00 | "您下週日的敬拜服事提醒" | | 排班更新 | 立即 | "您的服事排班已更新,請查閱" | | 新消息公告 | 發佈後立即 | "[公告] 復活節特別聚會" | | 生日祝福 | 當天 08:00 | 可選,需教友同意 | **裝置 Token 管理** ``` UserDevice ├── Id ├── UserId ├── DeviceToken (FCM token) ├── Platform (ios | android) ├── AppVersion ├── LastSeenAt └── IsActive ``` - Token 登入時更新,登出時標記 `IsActive = false` - FCM token 失效時(delivery failure)自動清理 --- ### SMS (Twilio) **使用時機:輔助通知,非主要渠道** | 事件 | 觸發條件 | 說明 | |------|----------|------| | 服事前一天提醒 | 前一天 16:00 | 確保沒裝 App 的同工也收到 | | 緊急取消通知 | 手動觸發 | 主日緊急狀況(天氣、設備) | | 新教友歡迎 | 首次建立帳號 | 可選 | **教友設定** - 預設 **關閉** SMS,教友自行在個人設定開啟 - 須明確同意才接收(Opt-in 機制) - 每則 SMS 結尾附 "Reply STOP to unsubscribe" **Twilio 設定** ```csharp // appsettings.json(實際值存環境變數) "Twilio": { "AccountSid": "${TWILIO_ACCOUNT_SID}", "AuthToken": "${TWILIO_AUTH_TOKEN}", "FromNumber": "${TWILIO_FROM_NUMBER}" // e.g. +1-xxx-xxx-xxxx } ``` **費用估算(50–100 人教會)** - 假設 30 人開啟 SMS、每月約 8 次通知 - 30 人 × 8 次 = 240 SMS/月 - Twilio 美國 SMS ~$0.0079/則 → **約 $2/月** --- ## 通知偏好設定(教友端) 教友在 App 個人設定頁面可控制: ``` 通知設定 ├── Email 通知 │ ├── ✅ 服事排班(必開,不可關) │ ├── ✅ 重要公告 │ └── ☐ 活動資訊 ├── Push 通知 │ ├── ✅ 服事提醒 │ ├── ✅ 排班更新 │ └── ☐ 生日祝福 └── SMS 通知(預設關閉) ├── ☐ 服事前一天提醒 └── ☐ 緊急通知 ``` --- ## 後端通知服務架構 ```csharp // INotificationService 統一介面 public interface INotificationService { Task SendEmailAsync(NotificationRequest request); Task SendPushAsync(NotificationRequest request); Task SendSmsAsync(NotificationRequest request); Task SendAllAsync(NotificationRequest request); // 依偏好自動選渠道 } // NotificationRequest public record NotificationRequest( string UserId, string TemplateKey, // e.g. "roster.reminder" Dictionary Data, NotificationChannel[] Channels ); ``` **排程通知(Hangfire 或 Quartz.NET)** - 服事提醒:每週六 09:00 掃描下週服事表,批次發送 - SMS 提醒:每週六 16:00 補發 SMS(對已開啟 SMS 的教友) - 生日提醒:每天 08:00 掃描當天生日教友 --- ## 通知語言規則 1. 以教友個人語言偏好為準(`Member.LanguagePreference: en | zh-TW`) 2. 若未設定,預設英文 3. 批次發送(如年度收據)依每人偏好分別產生對應語言的郵件