# Implementation Tasks ## 0. Users Table for Display Name Resolution - [x] 0.1 Create `app/modules/auth/models.py` - Add `User` model: - `user_id` (PK, VARCHAR 255) - email address - `display_name` (VARCHAR 255, NOT NULL) - `office_location` (VARCHAR 100, nullable) - `job_title` (VARCHAR 100, nullable) - `last_login_at` (TIMESTAMP) - `created_at` (TIMESTAMP, default NOW) - [x] 0.2 Create `app/modules/auth/services/user_service.py`: - `upsert_user(user_id, display_name, office_location, job_title)` function - Uses SQLAlchemy merge or INSERT ON CONFLICT for atomic upsert - Updates `last_login_at` on every call - [x] 0.3 Modify `app/modules/auth/router.py` login endpoint: - After successful AD authentication, call `upsert_user()` with: - `user_id`: userInfo.email - `display_name`: userInfo.name - `office_location`: userInfo.officeLocation - `job_title`: userInfo.jobTitle - [x] 0.4 Run database migration to create `users` table - [x] 0.5 Write unit tests for user upsert: - Test new user creation - Test existing user update - Test last_login_at update ## 1. Configuration and Dependencies - [x] 1.1 Add DIFY settings to `app/core/config.py`: - `DIFY_BASE_URL`: str = "https://dify.theaken.com/v1" - `DIFY_API_KEY`: str (required) - `DIFY_TIMEOUT_SECONDS`: int = 120 - `REPORT_MAX_MESSAGES`: int = 200 - `REPORT_STORAGE_PATH`: str = "reports" - [x] 1.2 Update `.env.example` with DIFY configuration variables - [x] 1.3 Add dependencies to `requirements.txt`: - `python-docx>=1.1.0` - `httpx>=0.27.0` (async HTTP client for DIFY API) - [x] 1.4 Install dependencies: `pip install -r requirements.txt` ## 2. Database Schema and Models - [x] 2.1 Create `app/modules/report_generation/models.py`: - `GeneratedReport` SQLAlchemy model with fields: - report_id (PK, UUID) - room_id (FK to incident_rooms) - generated_by, generated_at - status (pending/collecting_data/generating_content/assembling_document/completed/failed) - error_message - dify_message_id, dify_conversation_id - prompt_tokens, completion_tokens - report_title, report_json (JSONB) - docx_storage_path - [x] 2.2 Create `app/modules/report_generation/schemas.py`: - `ReportGenerateRequest` (optional parameters) - `ReportGenerateResponse` (report_id, status) - `ReportStatusResponse` (full report metadata) - `ReportListResponse` (list of reports) - `AIReportContent` (validated JSON schema from DIFY) - [x] 2.3 Run database migration to create `generated_reports` table ## 3. DIFY Service Integration - [x] 3.1 Create `app/modules/report_generation/prompts.py`: - System prompt template (Traditional Chinese) - JSON output schema with examples - User query template for room data formatting - [x] 3.2 Create `app/modules/report_generation/services/dify_service.py`: - `DifyService` class with httpx async client - `generate_report_content(prompt: str) -> dict` method - Request construction with headers and body - Response parsing and JSON extraction - Error handling (timeout, auth failure, invalid JSON) - Retry logic for recoverable errors - [x] 3.3 Write unit tests for DIFY service: - Mock successful API response - Mock timeout scenario - Mock invalid JSON response - Mock authentication failure ## 4. Report Data Collection Service - [x] 4.1 Create `app/modules/report_generation/services/report_data_service.py`: - `ReportDataService` class - `collect_room_data(room_id: str) -> RoomReportData` method - Query room metadata from `incident_rooms` - Query messages with sender display names - Query members with roles - Query files with metadata - Handle message limit (summarize if exceeds REPORT_MAX_MESSAGES) - [x] 4.2 Create data models for collected data: - `RoomReportData` dataclass - `MessageData` dataclass - `MemberData` dataclass - `FileData` dataclass - [x] 4.3 Create prompt builder function: - `build_report_prompt(room_data: RoomReportData) -> str` - Format room metadata section - Format members section - Format messages timeline - Format files section - [x] 4.4 Write unit tests for data collection: - Test with normal room data - Test with empty room (should raise error) - Test message summarization for large rooms ## 5. Document Assembly Service - [x] 5.1 Create `app/modules/report_generation/services/docx_service.py`: - `DocxAssemblyService` class - `create_document(report_content: dict, room_data: RoomReportData) -> BytesIO` method - Document title and metadata header - Section formatting (headings, paragraphs, tables) - Timeline table generation - Member list formatting - [x] 5.2 Implement image embedding: - Download images from MinIO using existing `minio_service` - Resize images to max width (15cm) - Insert images into document - Handle missing images gracefully - [x] 5.3 Implement document styling: - Set default font (標楷體 or 微軟正黑體) - Set heading styles - Set paragraph spacing - Set table styles - [x] 5.4 Write unit tests for docx assembly: - Test basic document creation - Test with embedded images (mock MinIO) - Test without images - Test missing image handling ## 6. REST API Router - [x] 6.1 Create `app/modules/report_generation/router.py`: - `POST /api/rooms/{room_id}/reports/generate` - Trigger generation - `GET /api/rooms/{room_id}/reports` - List reports - `GET /api/rooms/{room_id}/reports/{report_id}` - Get report status - `GET /api/rooms/{room_id}/reports/{report_id}/download` - Download .docx - [x] 6.2 Create `app/modules/report_generation/dependencies.py`: - `verify_room_access` - Check user is room member - `verify_report_access` - Check report belongs to accessible room - [x] 6.3 Implement generate endpoint: - Verify room membership - Create report record with status "pending" - Return report_id immediately - Trigger async report generation (can use background task or sync for MVP) - [x] 6.4 Implement download endpoint: - Verify report exists and is completed - Load .docx from storage - Return as file response with proper headers - [x] 6.5 Register router in `app/main.py` ## 7. Report Generation Orchestration - [x] 7.1 Create main orchestration function in `services/__init__.py`: - `generate_report(room_id: str, user_id: str, db: Session) -> str` - Update status at each stage - Call data collection service - Call DIFY service - Call docx assembly service - Store document (MinIO or local) - Update final status - [x] 7.2 Implement error handling: - Catch and log all exceptions - Update report status to "failed" with user-friendly error message - Store technical error in database for debugging - [x] 7.3 Implement document storage: - Upload .docx to MinIO under `reports/{room_id}/{report_id}.docx` - Store path in database ## 8. WebSocket Notifications - [x] 8.1 Add report notification schemas to `app/modules/realtime/schemas.py`: - `ReportGeneratedBroadcast` - `ReportGenerationFailedBroadcast` - [x] 8.2 Integrate WebSocket broadcast in report generation: - Broadcast `report_generated` on success - Broadcast `report_generation_failed` on failure ## 9. Frontend Integration - [x] 9.1 Create `frontend/src/services/reports.ts`: - `generateReport(roomId: string): Promise<{report_id: string}>` - `listReports(roomId: string): Promise` - `getReportStatus(roomId: string, reportId: string): Promise` - `downloadReport(roomId: string, reportId: string): Promise` - [x] 9.2 Add TypeScript types for reports in `frontend/src/types/index.ts` - [x] 9.3 Create report generation hooks in `frontend/src/hooks/useReports.ts`: - `useGenerateReport` mutation - `useReportList` query - `useReportStatus` query - [x] 9.4 Add "Generate Report" button to RoomDetail page: - Show only for resolved/archived rooms (or with warning for active) - Disable during generation - Show progress indicator - [x] 9.5 Add report list and download UI: - Show list of generated reports - Download button for each completed report - Status indicator for pending/failed reports - [x] 9.6 Handle WebSocket report notifications: - Update UI when report_generated received - Show toast notification - Refresh report list ## 10. Integration Testing - [x] 10.1 Create `tests/test_report_generation.py`: - Test full report generation flow (with mocked DIFY) - Test API endpoints (generate, list, download) - Test permission checks - Test error scenarios - [x] 10.2 Create integration test with real DIFY (optional, manual): - Test with sample room data - Verify JSON output format - Check document quality ## 11. Documentation - [x] 11.1 Update API documentation with new endpoints - [x] 11.2 Update .env.example with all DIFY configuration --- ## Task Dependencies ``` 0.1 ─▶ 0.2 ─▶ 0.3 ─▶ 0.4 ─▶ 0.5 │ ▼ 1.1 ─┬─▶ 2.1 ─▶ 2.3 ─┴─▶ 4.1 (needs users table for JOIN) 1.2 ─┘ 1.3 ─▶ 1.4 ─┬─▶ 3.1 ─▶ 3.2 ─▶ 3.3 ├─▶ 4.1 ─▶ 4.2 ─▶ 4.3 ─▶ 4.4 └─▶ 5.1 ─▶ 5.2 ─▶ 5.3 ─▶ 5.4 2.2 ─┬─▶ 6.1 ─▶ 6.2 ─▶ 6.3 ─▶ 6.4 ─▶ 6.5 │ 3.2 ─┼─▶ 7.1 ─▶ 7.2 ─▶ 7.3 4.1 ─┤ 5.1 ─┘ 7.1 ─▶ 8.1 ─▶ 8.2 6.5 ─▶ 9.1 ─▶ 9.2 ─▶ 9.3 ─▶ 9.4 ─▶ 9.5 ─▶ 9.6 All ─▶ 10.1 ─▶ 10.2 ─▶ 11.1 ─▶ 11.2 ``` ## Parallelizable Work The following can be done in parallel: - Section 0 (Users Table) should be done first as a prerequisite - Section 3 (DIFY Service) and Section 4 (Data Collection) and Section 5 (Docx Assembly) - Section 6 (API Router) can start once Section 2 (Schemas) is done - Section 9 (Frontend) can start once Section 6 (API) is done ## Summary | Section | Tasks | Description | |---------|-------|-------------| | 0. Users Table | 5 | Display name resolution | | 1. Config | 4 | Configuration and dependencies | | 2. Database | 3 | Models and schemas | | 3. DIFY | 3 | AI service integration | | 4. Data Collection | 4 | Room data gathering | | 5. Docx Assembly | 4 | Document generation | | 6. REST API | 5 | API endpoints | | 7. Orchestration | 3 | Main generation flow | | 8. WebSocket | 2 | Notifications | | 9. Frontend | 6 | UI integration | | 10. Testing | 2 | Integration tests | | 11. Documentation | 2 | Docs update | | **Total** | **43** | |