BuyingAgent/backend/app/api/profiles.py

101 lines
3.6 KiB
Python
Raw Normal View History

from typing import Any
from fastapi import APIRouter, Body, Depends
from sqlalchemy.orm import Session
from app.api.schemas import AttributeDefinitionIn, page, parse_page
from app.domain.serialize import jsonable
from app.errors import AppError
from app.persistence.db import get_session
from app.persistence.repositories import CatalogRepository
from app.services.ingestion_service import IngestionService
router = APIRouter(prefix="/api/v1")
@router.post("/attribute-definitions", status_code=201)
def create_attribute_definition(payload: AttributeDefinitionIn, session: Session = Depends(get_session)):
definition = IngestionService(session).create_definition(payload.model_dump())
return jsonable(definition.__dict__)
@router.get("/attribute-definitions")
def list_attribute_definitions(limit: int = 50, offset: int = 0, session: Session = Depends(get_session)):
limit, offset = parse_page(limit, offset)
items, total = CatalogRepository(session).list_definitions(limit, offset)
return page([jsonable(item.__dict__) for item in items], limit, offset, total)
@router.get("/sources")
def list_sources(session: Session = Depends(get_session)):
items = CatalogRepository(session).list_sources()
return {
"items": [{"id": item.id, "name": item.name, "adapter_type": item.adapter_type} for item in items],
"limit": len(items),
"offset": 0,
"total": len(items),
}
@router.get("/scoring-models/{version}")
def get_scoring_model(version: str, session: Session = Depends(get_session)):
model = CatalogRepository(session).get_scoring_model(version)
if model is None:
raise AppError(404, "NOT_FOUND", "scoring model not found", {"version": version})
return {
"version": model.version,
"algorithm_id": model.algorithm_id,
"definition": model.definition,
"definition_hash": model.definition_hash,
}
@router.post("/profiles", status_code=201)
def create_profile(payload: dict[str, Any] = Body(...), session: Session = Depends(get_session)):
if not isinstance(payload, dict):
raise AppError(422, "PROFILE_INVALID", "profile must be an object")
row = IngestionService(session).create_profile(payload)
return {
"id": row.id,
"version": row.version,
"name": row.name,
"category": row.category,
"scoring_version": row.scoring_version,
"definition": row.definition,
"definition_hash": row.definition_hash,
"created_at": row.created_at,
}
@router.get("/profiles")
def list_profiles(limit: int = 50, offset: int = 0, session: Session = Depends(get_session)):
limit, offset = parse_page(limit, offset)
items, total = CatalogRepository(session).list_profiles(limit, offset)
return page(
[
{
"id": row.id,
"version": row.version,
"name": row.name,
"category": row.category,
"scoring_version": row.scoring_version,
"definition_hash": row.definition_hash,
"created_at": row.created_at,
}
for row in items
],
limit,
offset,
total,
)
@router.get("/profiles/{profile_id}")
def get_profile(profile_id: str, version: int | None = None, session: Session = Depends(get_session)):
if version is None:
raise AppError(422, "VERSION_REQUIRED", "query parameter version is required")
profile = CatalogRepository(session).get_profile(profile_id, version)
if profile is None:
raise AppError(404, "NOT_FOUND", "profile version not found")
return profile.definition