Files
PROJECT-CONTORL/openspec/changes/archive/2025-12-29-add-automation/design.md
beabigegg 95c281d8e1 feat: implement automation module
- Event-based triggers (Phase 1):
  - Trigger/TriggerLog models with field_change type
  - TriggerService for condition evaluation and action execution
  - Trigger CRUD API endpoints
  - Task integration (status, assignee, priority changes)
  - Frontend: TriggerList, TriggerForm components

- Weekly reports (Phase 2):
  - ScheduledReport/ReportHistory models
  - ReportService for stats generation
  - APScheduler for Friday 16:00 job
  - Report preview/generate/history API
  - Frontend: WeeklyReportPreview, ReportHistory components

- Tests: 23 new tests (14 triggers + 9 reports)
- OpenSpec: add-automation change archived

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 22:59:00 +08:00

186 lines
4.7 KiB
Markdown
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.

## Context
自動化系統需要處理兩種類型的自動化:
1. 事件驅動 - 任務欄位變更時觸發
2. 時間驅動 - 排程執行(如週報)
## Goals / Non-Goals
**Goals:**
- 提供欄位變更觸發器status, assignee, priority
- 實作每週五 16:00 自動週報
- 整合現有通知系統
- 記錄所有觸發器執行日誌
**Non-Goals:**
- 複雜的工作流引擎
- 跨任務觸發器
- Email 發送(僅系統內通知)
## Decisions
### 1. 排程方案
**Decision:** 使用 APScheduler 而非 Celery
**Rationale:**
- 無需額外 worker 進程,減少部署複雜度
- 嵌入 FastAPI 應用內運行
- 足夠處理週報等簡單定時任務
- 未來如需擴展可遷移至 Celery
**Configuration:**
```python
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.cron import CronTrigger
scheduler = AsyncIOScheduler()
scheduler.add_job(
generate_weekly_reports,
CronTrigger(day_of_week='fri', hour=16, minute=0),
id='weekly_report'
)
```
### 2. 觸發器評估策略
**Decision:** 同步評估,任務更新時直接執行
**Rationale:**
- 簡化實作,無需消息隊列
- 觸發器執行速度快(僅發送通知)
- 失敗可即時回報
**Flow:**
```
Task Update → Detect Changes → Find Matching Triggers → Execute Actions → Log Results
```
### 3. 條件定義格式
**Decision:** 使用 JSON 結構定義條件
```json
{
"field": "status_id",
"operator": "equals",
"value": "uuid-of-testing-status"
}
```
**Supported Operators:**
- `equals` - 等於
- `not_equals` - 不等於
- `changed_to` - 變更為特定值
- `changed_from` - 從特定值變更
### 4. 動作定義格式
**Decision:** 使用 JSON 陣列定義動作
```json
[
{
"type": "notify",
"target": "assignee",
"template": "任務 {task.title} 狀態已變更為 {new_value}"
}
]
```
**Supported Actions (Phase 1):**
- `notify` - 發送系統通知
**Target Types:**
- `assignee` - 任務指派者
- `creator` - 任務建立者
- `project_owner` - 專案擁有者
- `user:<user_id>` - 指定使用者
## Data Model
```sql
-- 觸發器表
pjctrl_triggers
├── id: UUID (PK)
├── project_id: UUID (FK -> projects)
├── name: VARCHAR(200)
├── description: TEXT
├── trigger_type: ENUM('field_change', 'schedule')
├── conditions: JSON
├── actions: JSON
├── is_active: BOOLEAN DEFAULT true
├── created_by: UUID (FK -> users)
├── created_at: TIMESTAMP
└── updated_at: TIMESTAMP
-- 觸發器執行日誌
pjctrl_trigger_logs
├── id: UUID (PK)
├── trigger_id: UUID (FK -> triggers)
├── task_id: UUID (FK -> tasks, nullable)
├── executed_at: TIMESTAMP
├── status: ENUM('success', 'failed')
├── details: JSON
└── error_message: TEXT
-- 排程報告設定
pjctrl_scheduled_reports
├── id: UUID (PK)
├── report_type: ENUM('weekly')
├── recipient_id: UUID (FK -> users)
├── is_active: BOOLEAN DEFAULT true
├── last_sent_at: TIMESTAMP
└── created_at: TIMESTAMP
-- 報告歷史
pjctrl_report_history
├── id: UUID (PK)
├── report_id: UUID (FK -> scheduled_reports)
├── generated_at: TIMESTAMP
├── content: JSON
├── status: ENUM('sent', 'failed')
└── error_message: TEXT
```
## API Design
```
# Triggers
POST /api/projects/{project_id}/triggers # 建立觸發器
GET /api/projects/{project_id}/triggers # 列出專案觸發器
GET /api/triggers/{id} # 觸發器詳情
PUT /api/triggers/{id} # 更新觸發器
DELETE /api/triggers/{id} # 刪除觸發器
GET /api/triggers/{id}/logs # 觸發器執行日誌
# Reports
GET /api/reports/weekly/preview # 預覽週報
POST /api/reports/weekly/generate # 手動觸發週報
GET /api/reports/history # 報告歷史
```
## Risks / Trade-offs
| Risk | Mitigation |
|------|------------|
| 大量觸發器影響效能 | 限制每專案觸發器數量,建立索引 |
| APScheduler 單點故障 | 記錄 last_sent_at 防止重複,考慮多實例鎖 |
| 觸發器條件複雜度 | Phase 1 僅支援簡單條件,後續擴展 |
## Integration Points
1. **Task Update Hook**
-`tasks/router.py` 的 update_task 後調用 TriggerService.evaluate()
2. **Notification Integration**
- 使用現有 NotificationService.create_notification()
3. **Audit Integration**
- 觸發器執行記錄至 TriggerLog非 AuditLog
## Open Questions
- [ ] 是否需要支援 Email 發送?(目前僅系統內通知)
- [ ] 週報收件者如何設定?(主管自動訂閱 or 手動設定)