Files
resolutionflow/backend/app/api/endpoints/admin_survey.py
chihlasm 74e1dcfccf feat: add admin survey invite CRUD endpoints
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 01:54:13 -05:00

83 lines
2.7 KiB
Python

"""Admin endpoints for managing survey invites."""
import logging
from typing import Annotated
from fastapi import APIRouter, Depends
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.api.deps import require_admin
from app.core.config import settings
from app.core.database import get_db
from app.core.email import EmailService
from app.models.survey_invite import SurveyInvite
from app.models.user import User
from app.schemas.survey import SurveyInviteCreate, SurveyInviteResponse
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/admin", tags=["admin-survey"])
FRONTEND_URL = "https://resolutionflow.com"
def _build_invite_response(invite: SurveyInvite) -> SurveyInviteResponse:
base_url = FRONTEND_URL if not settings.DEBUG else "http://localhost:5173"
return SurveyInviteResponse(
id=str(invite.id),
token=invite.token,
recipient_name=invite.recipient_name,
recipient_email=invite.recipient_email,
status=invite.status,
email_sent=invite.email_sent,
created_at=invite.created_at,
completed_at=invite.completed_at,
survey_url=f"{base_url}/survey?t={invite.token}",
)
@router.post("/survey-invites", response_model=SurveyInviteResponse)
async def create_survey_invite(
data: SurveyInviteCreate,
db: Annotated[AsyncSession, Depends(get_db)],
current_user: Annotated[User, Depends(require_admin)],
):
"""Create a survey invite. Optionally sends email."""
invite = SurveyInvite(
recipient_name=data.recipient_name,
recipient_email=data.recipient_email,
)
db.add(invite)
await db.flush()
if data.send_email and data.recipient_email:
try:
base_url = FRONTEND_URL if not settings.DEBUG else "http://localhost:5173"
survey_url = f"{base_url}/survey?t={invite.token}"
sent = await EmailService.send_survey_invite_email(
to_email=data.recipient_email,
recipient_name=data.recipient_name,
survey_url=survey_url,
)
if sent:
invite.email_sent = True
except Exception:
logger.exception("Failed to send survey invite email")
await db.commit()
await db.refresh(invite)
return _build_invite_response(invite)
@router.get("/survey-invites", response_model=list[SurveyInviteResponse])
async def list_survey_invites(
db: Annotated[AsyncSession, Depends(get_db)],
current_user: Annotated[User, Depends(require_admin)],
):
"""List all survey invites."""
result = await db.execute(
select(SurveyInvite).order_by(SurveyInvite.created_at.desc())
)
invites = result.scalars().all()
return [_build_invite_response(i) for i in invites]