amazon-transcreation/backend/app/api/v1/output.py
DJP 5ef7e588b6 feat: wire analytics to real data and add audit logging across all endpoints
Replace mock chart data on reports page with real backend queries (jobs over
time, locale stats, usage stats, quality metrics). Add audit logging to auth
(login/login_failed), file management (upload/delete TM and reference files),
and feedback submission so the system logs page shows complete activity.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 17:17:14 -04:00

92 lines
3.1 KiB
Python

from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.responses import FileResponse
from sqlalchemy.ext.asyncio import AsyncSession
from app.dependencies import get_current_user, get_db
from app.schemas.feedback import FeedbackCreate, FeedbackResponse
from app.schemas.output import OutputPreviewResponse
from app.services.audit_service import AuditService
from app.services.feedback_service import FeedbackService
from app.services.output_service import OutputService
router = APIRouter(prefix="/output", tags=["output"])
output_service = OutputService()
feedback_service = FeedbackService()
audit_service = AuditService()
@router.get(
"/jobs/{job_id}/locales/{locale_code}/preview",
response_model=OutputPreviewResponse,
)
async def get_output_preview(
job_id: UUID,
locale_code: str,
db: AsyncSession = Depends(get_db),
current_user: dict = Depends(get_current_user),
) -> OutputPreviewResponse:
"""Get preview data for a locale instance output."""
preview = await output_service.get_preview(db, job_id, locale_code)
if preview is None:
raise HTTPException(
status_code=404,
detail="No output found for this job/locale combination",
)
return preview
@router.post(
"/feedback",
response_model=FeedbackResponse,
status_code=status.HTTP_201_CREATED,
)
async def create_feedback(
body: FeedbackCreate,
db: AsyncSession = Depends(get_db),
current_user: dict = Depends(get_current_user),
) -> FeedbackResponse:
"""Submit feedback on an output row."""
feedback = await feedback_service.create_feedback(
db, body, current_user["user_id"]
)
await audit_service.log(
db, action="feedback", entity_type="output_row", entity_id=str(body.output_row_id),
user_id=current_user["user_id"],
details={"flag_type": body.flag_type.value, "comment": body.comment},
)
await db.commit()
return FeedbackResponse.model_validate(feedback)
@router.get("/feedback/{output_id}", response_model=list[FeedbackResponse])
async def list_feedback_for_output(
output_id: UUID,
db: AsyncSession = Depends(get_db),
current_user: dict = Depends(get_current_user),
) -> list[FeedbackResponse]:
"""List all feedback for a specific output row."""
items = await feedback_service.list_feedback(db, output_id=output_id)
return [FeedbackResponse.model_validate(f) for f in items]
@router.get("/jobs/{job_id}/locales/{locale_code}/export")
async def export_output(
job_id: UUID,
locale_code: str,
db: AsyncSession = Depends(get_db),
current_user: dict = Depends(get_current_user),
) -> FileResponse:
"""Export output as xlsx for a locale instance."""
file_path = await output_service.trigger_export(db, job_id, locale_code)
if file_path is None:
raise HTTPException(
status_code=404,
detail="No export available for this job/locale combination",
)
return FileResponse(
path=file_path,
filename=f"{job_id}_{locale_code}_output.xlsx",
media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
)