Files
TEMP_spec_system_V3/功能升級規劃.txt
beabigegg 4f7f46b07a 2ND
2025-08-28 08:59:46 +08:00

204 lines
8.1 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

功能升級計畫:智慧通知模組
1. 專案願景
本次升級旨在將系統的郵件通知功能從一個靜態的範例,全面進化為一個智慧化、高彈性、自動化的通知中樞。完成後,系統將具備以下三大核心能力:
互動式通知:在所有關鍵操作(啟用、展延、終止)中,提供類似 Outlook 的動態收件人搜尋介面。
全流程覆蓋:確保暫規生命週期中的每一個重要節點,都能觸發對應的事件通知。
前瞻性提醒:從被動通知轉向主動預警,自動發送即將到期的提醒郵件,防止暫規失效。
2. 專案藍圖 (Roadmap)
本計畫將分為三個獨立但環環相扣的模組進行開發,建議依序實施。
模組 核心功能 開發重點 狀態
模組 A 動態收件人介面 建置 LDAP 搜尋 API、前端 UI 元件整合 全新開發
模組 B 全流程事件通知 將模組 A 的成果應用於「展延」與「終止」流程 功能擴展
模組 C 自動化排程提醒 引入排程器、建立每日檢查任務、定義提醒規則 全新開發
匯出到試算表
3. 模組 A動態收件人介面 (互動式通知)
此模組是整個計畫的基石,目標是打造一個可複用的收件人選擇器。
A.1. 後端:建置 LDAP 搜尋 API
強化 ldap_utils.py新增 search_ldap_principals 函式,使用服務帳號安全地查詢 AD 中符合條件的使用者,並回傳其姓名與 Email。
建立 API 路由 routes/api.py建立一個新的 Blueprint提供 /api/ldap-search 端點,並使用 @login_required 保護,僅供登入者呼叫。
註冊 API 路由:在 app.py 中註冊 api_bp使 API 生效。
(詳細程式碼請參考前次對話中的計畫,此處不再贅述)
A.2. 前端:整合 Tom Select 動態搜尋元件
修改 templates/base.html透過 CDN 引入 Tom Select 的 CSS 與 JavaScript 函式庫。
修改 templates/activate_spec.html
新增一個 <select multiple> 輸入框,用於選擇收件人。
編寫 JavaScript初始化 Tom Select 元件,並設定其 load 事件去呼叫後端的 /api/ldap-search API實現使用者輸入時的動態搜尋與載入功能。
A.3. 邏輯:更新啟用流程
修改 routes/temp_spec.py 中的 activate_spec 函式:
移除原先寫死的 get_ldap_group_members('TempSpec_Approvers') 邏輯。
改為從 request.form.get('recipients') 獲取由前端 Tom Select 傳來、以逗號分隔的 Email 字串。
解析字串為 Email 列表,並傳遞給 send_email 函式。
4. 模組 B全流程事件通知 (全流程覆蓋)
此模組的目標是將 模組 A 的成果,擴展應用到「展延」與「終止」這兩個操作上。
B.1. 修改 templates/extend_spec.html
複製 activate_spec.html 中新增的「郵件通知對象」HTML 區塊。
將其貼到 extend_spec.html 的表單中,<button type="submit"> 之前。
複製 activate_spec.html 中 {% block scripts %} 內的 Tom Select 初始化腳本,並貼到 extend_spec.html 的 scripts 區塊中。
B.2. 修改 routes/temp_spec.py 中的 extend_spec 函式
Python
# In: routes/temp_spec.py
@temp_spec_bp.route('/extend/<int:spec_id>', methods=['GET', 'POST'])
@editor_or_admin_required
def extend_spec(spec_id):
spec = TempSpec.query.get_or_404(spec_id)
if request.method == 'POST':
# ... (原有的檔案上傳、日期更新等邏輯不變) ...
# ===== START: 新增郵件通知邏輯 =====
recipients_str = request.form.get('recipients')
if recipients_str:
recipients = [email.strip() for email in recipients_str.split(',')]
subject = f"[暫規通知] 規範 '{spec.spec_code}' 已展延"
body = f"""
<html><body>
<p>您好,</p>
<p>暫時規範 <b>{spec.spec_code} - {spec.title}</b> 已成功展延。</p>
<p>新的結束日期為: <b>{spec.end_date.strftime('%Y-%m-%d')}</b></p>
<p>詳細資訊請登入系統查看。</p>
</body></html>
"""
send_email(recipients, subject, body)
# ===== END: 新增郵件通知邏輯 =====
db.session.commit()
flash(f"規範 '{spec.spec_code}' 已成功展延!", 'success')
return redirect(url_for('temp_spec.spec_list'))
default_new_end_date = spec.end_date + timedelta(days=30)
return render_template('extend_spec.html', spec=spec, default_new_end_date=default_new_end_date)
B.3. 針對 terminate_spec 重複 B.1 與 B.2 的步驟
對 templates/terminate_spec.html 和 routes/temp_spec.py 中的 terminate_spec 函式執行相同的修改,調整郵件的 subject 和 body 以符合「終止」的情境。
5. 模組 C自動化排程提醒 (前瞻性提醒)
此模組將為系統引入大腦,使其能夠主動進行管理。
C.1. 安裝與設定排程器
安裝套件:
Bash
pip install Flask-APScheduler
並將 Flask-APScheduler 新增到 requirements.txt 檔案中。
在 app.py 中初始化排程器:
Python
# In: app.py
from flask_apscheduler import APScheduler # <-- 新增
# ...
app = Flask(__name__)
app.config.from_object('config.Config')
# ===== START: 初始化排程器 =====
scheduler = APScheduler()
scheduler.init_app(app)
scheduler.start()
# ===== END: 初始化排程器 =====
db.init_app(app)
# ...
C.2. 建立排程任務 (tasks.py)
為了保持程式碼的模組化,我們建立一個新檔案來存放排程任務。
建立新檔案 tasks.py:
Python
# 檔案位置: beabigegg/temp_spec_system_v3/TEMP_spec_system_V3-b9557250a410cf778a51ece25ffe28543f494ffb/tasks.py (新檔案)
from datetime import date, timedelta
from models import TempSpec
from utils import send_email
from ldap_utils import get_ldap_group_members
def check_expiring_specs(app):
"""
每日執行的排程任務:檢查即將到期的暫規並發送提醒郵件。
"""
with app.app_context():
print("Running scheduled task: Checking for expiring specs...")
today = date.today()
seven_days_later = today + timedelta(days=7)
three_days_later = today + timedelta(days=3)
# 找出 7 天後 和 3 天後到期的暫規
expiring_soon = TempSpec.query.filter(
TempSpec.status == 'active',
TempSpec.end_date.in_([seven_days_later, three_days_later])
).all()
if not expiring_soon:
print("No specs expiring in 3 or 7 days.")
return
# **重要**: 定義預設的通知對象,例如某個管理群組
# 您需要將 'TempSpec_Admins' 替換為實際的 AD 群組名稱
default_recipients = get_ldap_group_members('TempSpec_Admins')
if not default_recipients:
print("Warning: Could not find default recipients in AD group 'TempSpec_Admins'.")
return
for spec in expiring_soon:
remaining_days = (spec.end_date - today).days
# 組合通知郵件
subject = f"[暫規到期提醒] 規範 '{spec.spec_code}' 將於 {remaining_days} 天後到期"
body = f"""
<html><body>
<p>您好,</p>
<p>此為自動提醒郵件。</p>
<p>暫時規範 <b>{spec.spec_code} - {spec.title}</b> 即將到期。</p>
<p><b>結束日期: {spec.end_date.strftime('%Y-%m-%d')} (剩餘 {remaining_days} 天)</b></p>
<p>申請人: {spec.applicant}</p>
<p>請及時處理,如需展延請登入系統操作。</p>
</body></html>
"""
# 發送郵件給預設群組
send_email(default_recipients, subject, body)
print(f"Sent expiry reminder for spec {spec.spec_code} to {len(default_recipients)} recipients.")
C.3. 在 app.py 中註冊與啟動任務
最後,我們需要告訴排程器有這個任務,並設定它每天執行。
Python
# In: app.py
# ... (在 from ... import ... 之後)
from tasks import check_expiring_specs
# ... (在 scheduler.start() 之後)
# 註冊排程任務:每天凌晨 2:00 執行一次
@scheduler.task('cron', id='check_expiring_specs_job', hour=2, minute=0)
def scheduled_job():
check_expiring_specs(app)
# ... (Flask app 的其他部分)