Full-stack Amazon AI Transcreation Platform with: - FastAPI backend (async, PostgreSQL, Redis, Celery) with 11 DB tables - JWT auth (SSO-ready abstract provider pattern) - 6-agent pipeline orchestrator with deterministic modules - Next.js 14 frontend with Amazon branding (Ember fonts, orange/dark theme) - Job wizard, monitoring HUD, output review, admin screens - 154 TM/reference files imported, 12 locales configured - Docker Compose for all services Agents 2-5 (TM retrieval, ranker, transcreator, compliance) are stubs pending Phase 3 LLM integration. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
105 lines
3.5 KiB
Python
105 lines
3.5 KiB
Python
from uuid import UUID
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
|
from sqlalchemy import func, select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.dependencies import get_db, require_role
|
|
from app.models.client import Client
|
|
from app.schemas.client import ClientCreate, ClientResponse, ClientUpdate
|
|
from app.schemas.common import PaginatedResponse
|
|
|
|
router = APIRouter(prefix="/clients", tags=["clients"])
|
|
|
|
|
|
@router.post(
|
|
"",
|
|
response_model=ClientResponse,
|
|
status_code=status.HTTP_201_CREATED,
|
|
)
|
|
async def create_client(
|
|
body: ClientCreate,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: dict = Depends(require_role(["admin"])),
|
|
) -> ClientResponse:
|
|
"""Create a new client (admin only)."""
|
|
client = Client(name=body.name, settings=body.settings)
|
|
db.add(client)
|
|
await db.flush()
|
|
return ClientResponse.model_validate(client)
|
|
|
|
|
|
@router.get("", response_model=PaginatedResponse[ClientResponse])
|
|
async def list_clients(
|
|
page: int = Query(1, ge=1),
|
|
page_size: int = Query(20, ge=1, le=100),
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: dict = Depends(require_role(["admin"])),
|
|
) -> PaginatedResponse[ClientResponse]:
|
|
"""List all clients (admin only)."""
|
|
count_result = await db.execute(select(func.count(Client.id)))
|
|
total = count_result.scalar() or 0
|
|
|
|
result = await db.execute(
|
|
select(Client)
|
|
.order_by(Client.created_at.desc())
|
|
.offset((page - 1) * page_size)
|
|
.limit(page_size)
|
|
)
|
|
clients = [ClientResponse.model_validate(c) for c in result.scalars().all()]
|
|
|
|
pages = (total + page_size - 1) // page_size if total > 0 else 1
|
|
return PaginatedResponse(
|
|
items=clients, total=total, page=page, page_size=page_size, pages=pages
|
|
)
|
|
|
|
|
|
@router.get("/{client_id}", response_model=ClientResponse)
|
|
async def get_client(
|
|
client_id: UUID,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: dict = Depends(require_role(["admin"])),
|
|
) -> ClientResponse:
|
|
"""Get a client by ID (admin only)."""
|
|
result = await db.execute(select(Client).where(Client.id == client_id))
|
|
client = result.scalar_one_or_none()
|
|
if client is None:
|
|
raise HTTPException(status_code=404, detail="Client not found")
|
|
return ClientResponse.model_validate(client)
|
|
|
|
|
|
@router.put("/{client_id}", response_model=ClientResponse)
|
|
async def update_client(
|
|
client_id: UUID,
|
|
body: ClientUpdate,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: dict = Depends(require_role(["admin"])),
|
|
) -> ClientResponse:
|
|
"""Update a client (admin only)."""
|
|
result = await db.execute(select(Client).where(Client.id == client_id))
|
|
client = result.scalar_one_or_none()
|
|
if client is None:
|
|
raise HTTPException(status_code=404, detail="Client not found")
|
|
|
|
update_data = body.model_dump(exclude_unset=True)
|
|
for field, value in update_data.items():
|
|
setattr(client, field, value)
|
|
|
|
await db.flush()
|
|
return ClientResponse.model_validate(client)
|
|
|
|
|
|
@router.delete("/{client_id}", status_code=status.HTTP_204_NO_CONTENT)
|
|
async def delete_client(
|
|
client_id: UUID,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: dict = Depends(require_role(["admin"])),
|
|
) -> None:
|
|
"""Delete a client (admin only)."""
|
|
result = await db.execute(select(Client).where(Client.id == client_id))
|
|
client = result.scalar_one_or_none()
|
|
if client is None:
|
|
raise HTTPException(status_code=404, detail="Client not found")
|
|
|
|
await db.delete(client)
|
|
await db.flush()
|