import os import shutil from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File, BackgroundTasks from sqlalchemy.orm import Session from typing import List, Optional from database import get_db from models import Activity, Evidence, User from security import get_current_active_user import schemas import uuid from services import activities router = APIRouter( prefix="/activities", tags=["Activities"] ) UPLOAD_DIR = "uploads" if not os.path.exists(UPLOAD_DIR): os.makedirs(UPLOAD_DIR) @router.post("/", response_model=schemas.Activity) def create_activity( activity: schemas.ActivityCreate, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user) ): return activities.create_activity(db, activity, current_user) @router.get("/", response_model=List[schemas.Activity]) def read_activities( project_id: Optional[int] = None, specialty_id: Optional[int] = None, skip: int = 0, limit: int = 100, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user) ): db_activities = activities.get_activities(db, current_user, project_id, specialty_id, skip, limit) return db_activities @router.get("/{activity_id}", response_model=schemas.Activity) def read_activity( activity_id: int, db: Session = Depends(get_db) ): return activities.get_activity(db, activity_id) @router.put("/{activity_id}", response_model=schemas.Activity) def update_activity( activity_id: int, activity: schemas.ActivityUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user) ): db_activity = db.query(Activity).filter(Activity.id == activity_id).first() if not db_activity: raise HTTPException(status_code=404, detail="Activity not found") update_data = activity.dict(exclude_unset=True) for key, value in update_data.items(): setattr(db_activity, key, value) db.commit() db.refresh(db_activity) return db_activity @router.post("/{activity_id}/upload", response_model=schemas.Evidence) async def upload_evidence( activity_id: int, background_tasks: BackgroundTasks, file: UploadFile = File(...), description: Optional[str] = None, captured_at: Optional[str] = None, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user) ): # Verify activity exists db_activity = db.query(Activity).filter(Activity.id == activity_id).first() if not db_activity: raise HTTPException(status_code=404, detail="Activity not found") # Generate unique filename file_ext = os.path.splitext(file.filename)[1] unique_filename = f"{uuid.uuid4()}{file_ext}" file_path = os.path.join(UPLOAD_DIR, unique_filename) # Save file with open(file_path, "wb") as buffer: shutil.copyfileobj(file.file, buffer) import datetime db_captured_at = None if captured_at: try: db_captured_at = datetime.datetime.fromisoformat(captured_at.replace('Z', '+00:00')) except: db_captured_at = datetime.datetime.utcnow() # Determine transcription status initial_status = "none" if file.content_type and "audio" in file.content_type: initial_status = "pending" # Save to database db_evidence = Evidence( activity_id=activity_id, file_path=file_path, media_type=file.content_type, description=description, captured_at=db_captured_at, transcription_status=initial_status ) db.add(db_evidence) db.commit() db.refresh(db_evidence) # If it's audio, queue transcription if initial_status == "pending": from services.transcription_worker import process_transcription background_tasks.add_task(process_transcription, db_evidence.id) return db_evidence @router.post("/evidence/{evidence_id}/retry-transcription", response_model=schemas.Evidence) async def retry_transcription( evidence_id: int, background_tasks: BackgroundTasks, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user) ): db_evidence = db.query(Evidence).filter(Evidence.id == evidence_id).first() if not db_evidence: raise HTTPException(status_code=404, detail="Evidence not found") if not db_evidence.media_type or "audio" not in db_evidence.media_type: raise HTTPException(status_code=400, detail="Only audio evidence can be transcribed") # Update status to pending db_evidence.transcription_status = "pending" db_evidence.transcription = None db.commit() db.refresh(db_evidence) # Queue transcription task from services.transcription_worker import process_transcription background_tasks.add_task(process_transcription, db_evidence.id) return db_evidence return db_evidence @router.put("/evidence/{evidence_id}", response_model=schemas.Evidence) def update_evidence( evidence_id: int, evidence: schemas.EvidenceUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user) ): db_evidence = db.query(Evidence).filter(Evidence.id == evidence_id).first() if not db_evidence: raise HTTPException(status_code=404, detail="Evidence not found") update_data = evidence.dict(exclude_unset=True) for key, value in update_data.items(): setattr(db_evidence, key, value) db.commit() db.refresh(db_evidence) return db_evidence @router.delete("/evidence/{evidence_id}") def delete_evidence( evidence_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user) ): db_evidence = db.query(Evidence).filter(Evidence.id == evidence_id).first() if not db_evidence: raise HTTPException(status_code=404, detail="Evidence not found") # Optional: Delete file from disk if db_evidence.file_path and os.path.exists(db_evidence.file_path): try: os.remove(db_evidence.file_path) except: pass db.delete(db_evidence) db.commit() return {"detail": "Evidence deleted"}