| import logging |
| from fastapi import APIRouter, Depends, HTTPException, BackgroundTasks |
| from sqlalchemy.orm import Session |
| from typing import List, Optional |
| from datetime import datetime |
|
|
| from api.auth import get_current_user |
| from models import db_models |
| from models.schemas import ReportGenerateRequest, ReportResponse, ReportFormatSuggestionResponse |
| from core.database import get_db, SessionLocal |
| from api.websocket_routes import manager |
| from services.report_service import report_service |
| from core import constants |
|
|
| router = APIRouter(prefix="/api/reports", tags=["reports"]) |
| logger = logging.getLogger(__name__) |
|
|
| async def run_report_generation(report_id: int, request: ReportGenerateRequest, user_id: int): |
| """Background task for report generation""" |
| db = SessionLocal() |
| connection_id = f"user_{user_id}" |
| try: |
| db_report = db.query(db_models.Report).filter(db_models.Report.id == report_id).first() |
| if not db_report: return |
|
|
| |
| content = await report_service.generate_report( |
| file_key=request.file_key, |
| text_input=request.text_input, |
| format_key=request.format_key, |
| custom_prompt=request.custom_prompt, |
| language=request.language |
| ) |
|
|
| if not content: |
| raise Exception("AI failed to generate report content") |
|
|
| if not db_report.title or "Report-" not in db_report.title: |
| |
| extracted_title = content.split('\n')[0].replace('#', '').strip() |
| if not extracted_title or len(extracted_title) < 3: |
| extracted_title = f"Report {request.format_key}" |
| db_report.title = extracted_title |
| db_report.content = content |
| db_report.status = "completed" |
| db.commit() |
|
|
| |
| await manager.send_result(connection_id, { |
| "type": "report", |
| "id": db_report.id, |
| "status": "completed", |
| "title": db_report.title |
| }) |
|
|
| except Exception as e: |
| logger.error(f"Background report generation failed: {e}") |
| db_report = db.query(db_models.Report).filter(db_models.Report.id == report_id).first() |
| if db_report: |
| db_report.status = "failed" |
| db_report.error_message = str(e) |
| db.commit() |
| await manager.send_error(connection_id, f"Report generation failed: {str(e)}") |
| finally: |
| db.close() |
|
|
| @router.get("/config") |
| async def get_report_config(): |
| """Returns available formats and languages for report generation.""" |
| return { |
| "formats": constants.REPORT_FORMAT_OPTIONS, |
| "languages": constants.LANGUAGES |
| } |
|
|
| @router.get("/suggest-formats", response_model=ReportFormatSuggestionResponse) |
| async def suggest_formats( |
| file_key: Optional[str] = None, |
| text_input: Optional[str] = None, |
| language: str = "Japanese", |
| current_user: db_models.User = Depends(get_current_user)): |
| """ |
| Get 4 AI-suggested report formats based on content. |
| """ |
| suggestions = await report_service.generate_format_suggestions( |
| file_key=file_key, |
| text_input=text_input, |
| language=language |
| ) |
| return {"suggestions": suggestions} |
|
|
| @router.post("/generate", response_model=ReportResponse) |
| async def generate_report( |
| request: ReportGenerateRequest, |
| background_tasks: BackgroundTasks, |
| current_user: db_models.User = Depends(get_current_user), |
| db: Session = Depends(get_db) |
| ): |
| """ |
| Initiates report generation in the background. |
| """ |
| source_id = None |
| if request.file_key: |
| source = db.query(db_models.Source).filter( |
| db_models.Source.s3_key == request.file_key, |
| db_models.Source.user_id == current_user.id |
| ).first() |
| if not source: |
| raise HTTPException(status_code=403, detail="Not authorized to access this file") |
| source_id = source.id |
|
|
| |
| file_base = request.file_key.split('/')[-1].rsplit('.', 1)[0] if request.file_key else None |
| title = f"Report-{file_base}" if file_base else f"Report {request.format_key} {datetime.utcnow().strftime('%Y-%m-%d %H:%M')}" |
| db_report = db_models.Report( |
| title=title, |
| format_key=request.format_key, |
| user_id=current_user.id, |
| source_id=source_id, |
| status="processing" |
| ) |
| db.add(db_report) |
| db.commit() |
| db.refresh(db_report) |
|
|
| |
| background_tasks.add_task(run_report_generation, db_report.id, request, current_user.id) |
|
|
| return db_report |
|
|
| @router.get("/list", response_model=List[ReportResponse]) |
| async def list_reports( |
| current_user: db_models.User = Depends(get_current_user), |
| db: Session = Depends(get_db) |
| ): |
| """ |
| Lists all reports for the current user. |
| """ |
| try: |
| reports = db.query(db_models.Report).filter( |
| db_models.Report.user_id == current_user.id |
| ).order_by(db_models.Report.created_at.desc()).all() |
| return [ReportResponse.model_validate(r) for r in reports] |
| except Exception as e: |
| raise HTTPException(status_code=500, detail=str(e)) |
|
|
| @router.get("/{report_id}", response_model=ReportResponse) |
| async def get_report( |
| report_id: int, |
| current_user: db_models.User = Depends(get_current_user), |
| db: Session = Depends(get_db) |
| ): |
| """ |
| Retrieves a specific report. |
| """ |
| report = db.query(db_models.Report).filter( |
| db_models.Report.id == report_id, |
| db_models.Report.user_id == current_user.id |
| ).first() |
| |
| if not report: |
| raise HTTPException(status_code=404, detail="Report not found") |
| |
| return ReportResponse.model_validate(report) |
|
|
| @router.delete("/{report_id}") |
| async def delete_report( |
| report_id: int, |
| current_user: db_models.User = Depends(get_current_user), |
| db: Session = Depends(get_db) |
| ): |
| """ |
| Deletes a specific report. |
| """ |
| report = db.query(db_models.Report).filter( |
| db_models.Report.id == report_id, |
| db_models.Report.user_id == current_user.id |
| ).first() |
| |
| if not report: |
| raise HTTPException(status_code=404, detail="Report not found") |
| |
| db.delete(report) |
| db.commit() |
| return {"message": "Report deleted successfully"} |
|
|