feat: implement researcher and publication management with sync functionality
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from fastapi.responses import Response
|
||||
from sqlalchemy.orm import Session
|
||||
from app.schema.publication import PublicationSchema
|
||||
from app.db.session import get_db
|
||||
from app.repositories.researcher_repository import ResearcherRepository
|
||||
from app.repositories.publication_repository import PublicationRepository
|
||||
from app.services.sync_service import SyncService
|
||||
from app.services.sword_exporter import SWORDExporter
|
||||
from app.utils.orcid_validator import is_valid_orcid
|
||||
|
||||
router = APIRouter(prefix="/researchers", tags=["researchers"])
|
||||
|
||||
|
||||
def validate_orcid_or_400(orcid_id: str):
|
||||
if not is_valid_orcid(orcid_id):
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"ORCID ID '{orcid_id}' no es válido según el formato y dígito de control."
|
||||
)
|
||||
|
||||
|
||||
@router.post("/", response_model=dict)
|
||||
def create_researcher(orcid_id: str, db: Session = Depends(get_db)):
|
||||
validate_orcid_or_400(orcid_id)
|
||||
|
||||
existing = ResearcherRepository.get_by_orcid(db, orcid_id)
|
||||
if existing:
|
||||
return {
|
||||
"status": "ok",
|
||||
"message": "Researcher ya existe.",
|
||||
"orcid_id": existing.orcid_id,
|
||||
"id": existing.id
|
||||
}
|
||||
|
||||
# Aquí podrías opcionalmente validar que el ORCID existe en ORCID API
|
||||
researcher = ResearcherRepository.create(db, orcid_id, name=None)
|
||||
|
||||
return {
|
||||
"status": "ok",
|
||||
"message": "Researcher creado correctamente.",
|
||||
"orcid_id": researcher.orcid_id,
|
||||
"id": researcher.id
|
||||
}
|
||||
|
||||
|
||||
@router.get("/{orcid_id}", response_model=dict)
|
||||
def get_researcher(orcid_id: str, db: Session = Depends(get_db)):
|
||||
validate_orcid_or_400(orcid_id)
|
||||
|
||||
researcher = ResearcherRepository.get_by_orcid(db, orcid_id)
|
||||
if not researcher:
|
||||
raise HTTPException(status_code=404, detail="Researcher not found")
|
||||
|
||||
return {
|
||||
"orcid_id": researcher.orcid_id,
|
||||
"name": researcher.name,
|
||||
"authenticated": researcher.authenticated,
|
||||
"access_token": researcher.access_token,
|
||||
"id": researcher.id,
|
||||
"last_sync_at": researcher.last_sync_at,
|
||||
}
|
||||
|
||||
|
||||
@router.post("/{orcid_id}/sync", response_model=dict)
|
||||
def sync_researcher(orcid_id: str, db: Session = Depends(get_db)):
|
||||
validate_orcid_or_400(orcid_id)
|
||||
|
||||
service = SyncService()
|
||||
result = service.sync_researcher(db, orcid_id)
|
||||
return result
|
||||
|
||||
|
||||
@router.get("/{orcid_id}/publications", response_model=list[PublicationSchema], tags=["researchers"])
|
||||
def get_publications(orcid_id: str, db: Session = Depends(get_db)):
|
||||
researcher = ResearcherRepository.get_by_orcid(db, orcid_id)
|
||||
if not researcher:
|
||||
raise HTTPException(status_code=404, detail="Researcher not found")
|
||||
return researcher.publications
|
||||
|
||||
|
||||
|
||||
@router.get("/{orcid_id}/export/sword.xml")
|
||||
def export_sword_xml(orcid_id: str, db: Session = Depends(get_db)):
|
||||
validate_orcid_or_400(orcid_id)
|
||||
|
||||
researcher = ResearcherRepository.get_by_orcid(db, orcid_id)
|
||||
if not researcher:
|
||||
raise HTTPException(status_code=404, detail="Researcher not found")
|
||||
|
||||
pubs = PublicationRepository.list_by_researcher(db, researcher.id)
|
||||
xml_bytes = SWORDExporter.export_feed_xml(researcher, pubs)
|
||||
|
||||
return Response(
|
||||
content=xml_bytes,
|
||||
media_type="application/xml",
|
||||
headers={
|
||||
"Content-Disposition": f'attachment; filename="sword_{orcid_id}.xml"'
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@router.get("/{orcid_id}/export/sword.zip")
|
||||
def export_sword_zip(orcid_id: str, db: Session = Depends(get_db)):
|
||||
validate_orcid_or_400(orcid_id)
|
||||
|
||||
researcher = ResearcherRepository.get_by_orcid(db, orcid_id)
|
||||
if not researcher:
|
||||
raise HTTPException(status_code=404, detail="Researcher not found")
|
||||
|
||||
pubs = PublicationRepository.list_by_researcher(db, researcher.id)
|
||||
zip_bytes = SWORDExporter.export_zip(researcher, pubs)
|
||||
|
||||
return Response(
|
||||
content=zip_bytes,
|
||||
media_type="application/zip",
|
||||
headers={
|
||||
"Content-Disposition": f'attachment; filename="sword_{orcid_id}.zip"'
|
||||
}
|
||||
)
|
||||
Reference in New Issue
Block a user