2026-10-04 13:04:59 +02:00
|
|
|
from uuid import UUID
|
|
|
|
|
|
|
|
|
|
from fastapi import APIRouter, Depends, Query
|
|
|
|
|
from sqlalchemy.orm import Session
|
|
|
|
|
|
|
|
|
|
from app.api.schemas import (
|
|
|
|
|
CriterionDefinitionIn,
|
|
|
|
|
CriterionMappingIn,
|
|
|
|
|
CriterionMappingPatch,
|
|
|
|
|
DiscoverySearchIn,
|
|
|
|
|
DiscoverySearchPatch,
|
|
|
|
|
SourceAttributeMappingIn,
|
|
|
|
|
SourceAttributeMappingPatch,
|
|
|
|
|
)
|
|
|
|
|
from app.persistence.db import get_session
|
|
|
|
|
from app.services.catalog_service import CatalogService
|
|
|
|
|
from app.services.discovery_service import (
|
|
|
|
|
CriterionDefinitionService,
|
|
|
|
|
CriterionMappingService,
|
|
|
|
|
DiscoverySearchService,
|
|
|
|
|
SourceAttributeMappingService,
|
|
|
|
|
TaxonomyService,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
router = APIRouter(prefix="/api/v1")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/sources/{source_id}/categories")
|
|
|
|
|
def list_source_categories(source_id: str, session: Session = Depends(get_session)):
|
|
|
|
|
return {"items": CatalogService(session).source_categories(source_id)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/sources/{source_id}/categories/{category}/discover-taxonomy", status_code=201)
|
|
|
|
|
def discover_taxonomy(source_id: str, category: str, session: Session = Depends(get_session)):
|
|
|
|
|
return TaxonomyService(session).discover(source_id, category)
|
|
|
|
|
|
|
|
|
|
|
2026-10-04 14:17:56 +02:00
|
|
|
@router.get("/sources/{source_id}/categories/{category}/taxonomy-status")
|
|
|
|
|
def taxonomy_status(source_id: str, category: str, session: Session = Depends(get_session)):
|
|
|
|
|
return TaxonomyService(session).taxonomy_status(source_id, category)
|
|
|
|
|
|
|
|
|
|
|
2026-10-04 13:04:59 +02:00
|
|
|
@router.get("/sources/{source_id}/categories/{category}/filters")
|
|
|
|
|
def list_filters(source_id: str, category: str, session: Session = Depends(get_session)):
|
|
|
|
|
return TaxonomyService(session).filters(source_id, category)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/criterion-definitions", status_code=201)
|
|
|
|
|
def create_criterion_definition(payload: CriterionDefinitionIn, session: Session = Depends(get_session)):
|
|
|
|
|
return CriterionDefinitionService(session).create(payload.model_dump())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/criterion-definitions")
|
|
|
|
|
def list_criterion_definitions(category: str | None = None, session: Session = Depends(get_session)):
|
|
|
|
|
return {"items": CriterionDefinitionService(session).list(category)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/criterion-mappings")
|
|
|
|
|
def list_mappings(source_category_id: UUID | None = None, session: Session = Depends(get_session)):
|
|
|
|
|
return {"items": CriterionMappingService(session).list(source_category_id)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/criterion-mappings", status_code=201)
|
|
|
|
|
def create_mapping(payload: CriterionMappingIn, session: Session = Depends(get_session)):
|
|
|
|
|
return CriterionMappingService(session).create(payload.model_dump())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.patch("/criterion-mappings/{mapping_id}")
|
|
|
|
|
def patch_mapping(mapping_id: UUID, payload: CriterionMappingPatch, session: Session = Depends(get_session)):
|
|
|
|
|
return CriterionMappingService(session).patch(mapping_id, payload.model_dump(exclude_unset=True))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/source-attribute-mappings")
|
|
|
|
|
def list_attribute_mappings(session: Session = Depends(get_session)):
|
|
|
|
|
return {"items": SourceAttributeMappingService(session).list()}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/source-attribute-mappings", status_code=201)
|
|
|
|
|
def create_attribute_mapping(payload: SourceAttributeMappingIn, session: Session = Depends(get_session)):
|
|
|
|
|
return SourceAttributeMappingService(session).create(payload.model_dump())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.patch("/source-attribute-mappings/{mapping_id}")
|
|
|
|
|
def patch_attribute_mapping(
|
|
|
|
|
mapping_id: UUID,
|
|
|
|
|
payload: SourceAttributeMappingPatch,
|
|
|
|
|
session: Session = Depends(get_session),
|
|
|
|
|
):
|
|
|
|
|
return SourceAttributeMappingService(session).patch(mapping_id, payload.model_dump(exclude_unset=True))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/discovery-searches", status_code=201)
|
|
|
|
|
def create_search(payload: DiscoverySearchIn, session: Session = Depends(get_session)):
|
|
|
|
|
return DiscoverySearchService(session).create(payload.model_dump())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/discovery-searches")
|
|
|
|
|
def list_searches(due: bool = Query(default=False), session: Session = Depends(get_session)):
|
|
|
|
|
service = DiscoverySearchService(session)
|
|
|
|
|
return {"items": service.list_due() if due else service.list_all()}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/discovery-searches/{search_id}")
|
|
|
|
|
def get_search(search_id: UUID, session: Session = Depends(get_session)):
|
|
|
|
|
return DiscoverySearchService(session).get(search_id)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.patch("/discovery-searches/{search_id}")
|
|
|
|
|
def patch_search(search_id: UUID, payload: DiscoverySearchPatch, session: Session = Depends(get_session)):
|
|
|
|
|
return DiscoverySearchService(session).patch(search_id, payload.model_dump(exclude_unset=True))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/discovery-searches/{search_id}/generate-query")
|
|
|
|
|
def generate_query(search_id: UUID, session: Session = Depends(get_session)):
|
|
|
|
|
return DiscoverySearchService(session).generate_query(search_id)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/discovery-searches/{search_id}/run", status_code=201)
|
|
|
|
|
def run_search(search_id: UUID, session: Session = Depends(get_session)):
|
|
|
|
|
return DiscoverySearchService(session).run(search_id)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/discovery-searches/{search_id}/runs")
|
|
|
|
|
def list_runs(search_id: UUID, session: Session = Depends(get_session)):
|
|
|
|
|
return {"items": DiscoverySearchService(session).list_runs(search_id)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/search-runs/{run_id}")
|
|
|
|
|
def get_run(run_id: UUID, session: Session = Depends(get_session)):
|
|
|
|
|
return DiscoverySearchService(session).get_run(run_id)
|