# app.py 重構計畫

## 文件資訊
- **建立日期**: 2026-01-18
- **目標檔案**: app.py (7,253 行)
- **目標**: 模組化拆分，提高可維護性

---

## 一、現況分析

### 1.1 檔案規模
- **總行數**: 7,253 行
- **路由數量**: 49 個
- **函數數量**: 約 70 個

### 1.2 最大函數 (需優先拆分)

| 排名 | 函數名稱 | 行數 | 所屬模組建議 |
|------|----------|------|--------------|
| 1 | `sales_analysis()` | 1,020 行 | sales_routes.py |
| 2 | `get_monthly_summary_data()` | 388 行 | monthly_routes.py |
| 3 | `import_excel()` | 288 行 | import_routes.py |
| 4 | `get_sales_table_data()` | 267 行 | sales_routes.py |
| 5 | `export_top_detail()` | 256 行 | sales_routes.py |
| 6 | `get_top_detail()` | 252 行 | sales_routes.py |
| 7 | `edm_dashboard()` | 244 行 | edm_routes.py |
| 8 | `index()` | 190 行 | dashboard_routes.py |

### 1.3 現有路由分類

```
頁面路由 (12個):
├── / (首頁/商品看板)
├── /settings (設定)
├── /system_settings (系統設定)
├── /brand_assets (品牌資源)
├── /edm (EDM 儀表板)
├── /festival (節慶儀表板)
├── /abc_analysis/detail (ABC 分析詳情)
├── /logs (系統日誌)
├── /monthly_summary_analysis (月結分析)
├── /sales_analysis (業績分析)
├── /growth_analysis (成長分析)
└── /daily_sales (當日業績)

API 路由 (37個):
├── 系統 API (3個): /health, /metrics, /api/logs
├── 分類管理 API (4個): /api/categories/*
├── 匯出 API (11個): /api/export/*
├── 任務觸發 API (6個): /api/run_*, /api/trigger_*
├── 匯入 API (2個): /api/import_excel, /api/import/monthly_summary
├── 備份 API (2個): /api/backup, /api/backup/download/*
├── 業績分析 API (5個): /api/sales_analysis/*
├── 月結分析 API (1個): /api/monthly_summary_data
├── 其他 API (3個): /api/test_url, /api/history/*, /api/price_change_details
└── 當日業績匯出 (2個): /daily_sales/export*
```

---

## 二、重構架構設計

### 2.1 目標目錄結構

```
momo_pro_system/
├── app.py                    # 主應用程式 (精簡後約 500 行)
├── config.py                 # 配置檔 (保持不變)
├── auth.py                   # 認證模組 (保持不變)
│
├── routes/                   # 🆕 路由模組目錄
│   ├── __init__.py          # Blueprint 註冊中心
│   ├── dashboard_routes.py  # 商品看板 (首頁)
│   ├── sales_routes.py      # 業績分析相關
│   ├── daily_sales_routes.py # 當日業績相關
│   ├── monthly_routes.py    # 月結分析相關
│   ├── edm_routes.py        # EDM 儀表板
│   ├── export_routes.py     # 匯出功能
│   ├── import_routes.py     # 匯入功能
│   ├── system_routes.py     # 系統管理 (設定、日誌、備份)
│   └── api_routes.py        # 通用 API (健康檢查、任務觸發等)
│
├── services/                 # 服務層 (現有)
│   ├── __init__.py
│   ├── cache_service.py     # 🆕 快取服務 (從 app.py 抽出)
│   ├── sales_service.py     # 🆕 業績計算服務
│   ├── dashboard_service.py # 🆕 看板數據服務
│   └── ... (現有服務)
│
├── utils/                    # 工具函數 (現有)
│   ├── __init__.py
│   ├── validators.py        # 🆕 驗證函數 (從 app.py 抽出)
│   ├── formatters.py        # 🆕 格式化函數
│   └── ... (現有工具)
│
├── database/                 # 資料庫層 (保持不變)
├── vendor_routes.py          # 廠商缺貨路由 (已存在)
└── auto_import_routes.py     # 自動匯入路由 (已存在)
```

### 2.2 模組劃分詳情

#### 模組 1: `routes/dashboard_routes.py` (~400 行)
```python
# 包含路由:
- GET /                      # index() - 商品看板首頁
- GET /brand_assets          # brand_assets()

# 包含函數:
- get_consolidated_data()    # 153 行
- get_full_dashboard_data()  # 148 行
- get_dashboard_stats()      # 16 行
```

#### 模組 2: `routes/sales_routes.py` (~2,000 行)
```python
# 包含路由:
- GET /sales_analysis                    # sales_analysis() - 1,020 行
- GET /api/sales_analysis/table_data     # get_sales_table_data() - 267 行
- GET /api/sales_analysis/table_data_pandas
- GET /api/sales_analysis/top_detail     # get_top_detail() - 252 行
- GET /api/sales_analysis/export_top_detail
- GET /api/sales_analysis/yoy_comparison

# 包含函數:
- _get_filtered_sales_data()
```

#### 模組 3: `routes/daily_sales_routes.py` (~800 行)
```python
# 包含路由:
- GET /daily_sales           # daily_sales() - 161 行
- GET /daily_sales/export    # export_daily_sales_category()
- GET /daily_sales/export_marketing
- GET /growth_analysis       # growth_analysis()

# 包含函數:
- preprocess_daily_sales_data()
- calculate_daily_kpis()
- calculate_dod()
- calculate_wow()
- prepare_daily_charts()
- prepare_category_summary()
- prepare_marketing_summary()
- get_taiwan_holiday()
- prepare_calendar_data()
```

#### 模組 4: `routes/monthly_routes.py` (~500 行)
```python
# 包含路由:
- GET /monthly_summary_analysis
- GET /api/monthly_summary_data  # 388 行
- POST /api/import/monthly_summary
```

#### 模組 5: `routes/edm_routes.py` (~400 行)
```python
# 包含路由:
- GET /edm                   # edm_dashboard() - 244 行
- GET /festival              # festival_dashboard() - 148 行
```

#### 模組 6: `routes/export_routes.py` (~800 行)
```python
# 包含路由:
- GET /api/export/all_categories
- GET /api/export/excel/all
- GET /api/export/excel/changes
- GET /api/export/excel/delisted
- GET /api/export/price_changes   # 156 行
- GET /api/export/low_prices
- GET /api/export/changes
- GET /api/export/excel/abc       # 175 行
- GET /api/export/excel/vendor    # 135 行
- GET /api/export/excel/seasonality_detail
```

#### 模組 7: `routes/import_routes.py` (~350 行)
```python
# 包含路由:
- POST /api/import_excel     # import_excel() - 288 行
```

#### 模組 8: `routes/system_routes.py` (~400 行)
```python
# 包含路由:
- GET /settings
- GET /system_settings
- GET /logs
- GET /api/logs
- POST /api/backup
- GET /api/backup/download/<path:filename>
- POST /api/categories (CRUD)
- POST /api/test_url

# 包含函數:
- load_categories()
- save_categories()
- load_scheduler_stats()
```

#### 模組 9: `routes/api_routes.py` (~300 行)
```python
# 包含路由:
- GET /health
- GET /metrics
- POST /api/run_task
- POST /api/run_edm_task
- POST /api/run_festival_task
- POST /api/trigger_momo_notification
- POST /api/trigger_edm_notification
- POST /api/test_notification
- GET /api/history/<int:product_id>
- GET /api/price_change_details
- GET /abc_analysis/detail

# 包含函數:
- track_query_time()
```

---

## 三、重構執行步驟

### 階段 1: 準備工作 (風險: 低)
1. ✅ 完整備份現有程式碼
2. 建立 `routes/` 目錄結構
3. 建立 `routes/__init__.py` Blueprint 註冊中心

### 階段 2: 抽取共用模組 (風險: 低)
1. 建立 `services/cache_service.py` - 抽取快取相關變數和函數
2. 建立 `utils/validators.py` - 抽取驗證函數
3. 建立 `utils/formatters.py` - 抽取格式化函數

### 階段 3: 拆分路由模組 (風險: 中)
**執行順序 (由簡單到複雜):**

| 順序 | 模組 | 路由數 | 複雜度 | 依賴關係 |
|------|------|--------|--------|----------|
| 1 | system_routes.py | 8 | 低 | 無外部依賴 |
| 2 | api_routes.py | 10 | 低 | scheduler |
| 3 | export_routes.py | 10 | 中 | DatabaseManager, Exporter |
| 4 | import_routes.py | 1 | 中 | DatabaseManager |
| 5 | edm_routes.py | 2 | 中 | DatabaseManager |
| 6 | monthly_routes.py | 3 | 中 | DatabaseManager |
| 7 | dashboard_routes.py | 2 | 高 | cache_service, DatabaseManager |
| 8 | daily_sales_routes.py | 4 | 高 | 多個輔助函數 |
| 9 | sales_routes.py | 6 | 高 | cache_service, 複雜邏輯 |

### 階段 4: 整合測試 (風險: 低)
1. 本機測試所有路由
2. UAT 環境部署測試
3. 回歸測試所有功能

---

## 四、安全措施

### 4.1 備份策略
```bash
# 重構前完整備份
cp -r /Users/ogt/momo_pro_system /Users/ogt/momo_pro_system_backup_$(date +%Y%m%d_%H%M%S)

# 資料庫備份
cp /Users/ogt/momo_pro_system/data/momo_database.db /Users/ogt/momo_pro_system/backups/
```

### 4.2 漸進式部署
1. 每拆分一個模組後立即測試
2. 使用 feature flag 控制新舊路由切換
3. 保留原始 app.py 直到所有模組穩定

### 4.3 回滾方案
```bash
# 如發生嚴重問題，立即回滾
cp /Users/ogt/momo_pro_system_backup_YYYYMMDD/app.py /Users/ogt/momo_pro_system/app.py
rm -rf /Users/ogt/momo_pro_system/routes/
# 重新部署
```

---

## 五、預期效益

### 5.1 程式碼品質
| 指標 | 重構前 | 重構後 |
|------|--------|--------|
| app.py 行數 | 7,253 | ~500 |
| 最大函數行數 | 1,020 | ~200 |
| 模組數量 | 1 | 10 |
| 可測試性 | 低 | 高 |

### 5.2 維護性改善
- **問題定位**: 從搜尋 7000 行 → 搜尋 300-800 行
- **功能擴展**: 只需修改相關模組
- **團隊協作**: 可並行開發不同模組
- **部署風險**: 可單獨部署/回滾特定模組

---

## 六、時程規劃

| 階段 | 工作項目 | 預估工作量 |
|------|----------|------------|
| 1 | 準備工作 + 共用模組 | 1-2 小時 |
| 2 | system_routes + api_routes | 2-3 小時 |
| 3 | export_routes + import_routes | 2-3 小時 |
| 4 | edm_routes + monthly_routes | 2-3 小時 |
| 5 | dashboard_routes | 2-3 小時 |
| 6 | daily_sales_routes | 3-4 小時 |
| 7 | sales_routes (最複雜) | 4-5 小時 |
| 8 | 整合測試 + 修復 | 2-3 小時 |
| **總計** | | **18-26 小時** |

---

## 七、注意事項

### 7.1 已知問題需修復
1. **datetime 重複導入**: 多處函數內有 `from datetime import datetime`，需統一移除
2. **快取變數**: `_SALES_DF_CACHE` 等全域變數需移至 cache_service.py
3. **循環依賴**: 拆分時需注意模組間的 import 順序

### 7.2 不動的部分
- `config.py` - 配置檔保持不變
- `auth.py` - 認證模組保持不變
- `vendor_routes.py` - 已是 Blueprint，保持不變
- `auto_import_routes.py` - 已是 Blueprint，保持不變
- `database/` 目錄 - 資料庫層保持不變
- `services/` 目錄 - 現有服務保持不變

---

## 八、執行確認

重構開始前，請確認：
- [ ] 已完成完整備份
- [ ] 已確認 UAT 環境可正常運作
- [ ] 已預留足夠時間進行測試
- [ ] 已準備好回滾方案

---

*文件結束*
