feat: add display name resolution for researchers from ORCID
- Introduced a new function to fetch and extract the display name of researchers from the ORCID API. - Updated the researcher search response to set the display name if it is not already defined, enhancing researcher data accuracy.
This commit is contained in:
@@ -15,7 +15,7 @@ from app.schema.researcher import (
|
||||
ResearcherWithPublicationsSchema,
|
||||
)
|
||||
from app.services.normalizer import PublicationNormalizer
|
||||
from app.services.orcid_client import get_works_summary, get_work_detail
|
||||
from app.services.orcid_client import get_display_name, get_works_summary, get_work_detail
|
||||
from app.schema.publication import PublicationSchema
|
||||
from app.db.models import PublicationDownload
|
||||
from app.security.jwt import get_optional_current_researcher
|
||||
@@ -159,6 +159,16 @@ def build_search_response(orcid_id: str, db: Session, current: Researcher | None
|
||||
db.add(researcher)
|
||||
db.flush()
|
||||
|
||||
# Si todavía no conocemos el nombre del investigador (por ejemplo, recién
|
||||
# creado al sincronizarse desde el buscador), lo resolvemos contra el
|
||||
# endpoint `/record` público de ORCID. No tocamos un nombre ya existente
|
||||
# para no pisar valores establecidos por el flujo de autenticación.
|
||||
if not researcher.name:
|
||||
display_name = get_display_name(orcid_id)
|
||||
if display_name:
|
||||
researcher.name = display_name
|
||||
db.flush()
|
||||
|
||||
publications = _upsert_researcher_publications(researcher, orcid_id, db)
|
||||
publications_out = _decorate_downloaded_by_me(db=db, current=current, publications=publications)
|
||||
stats = build_researcher_stats(publications_out)
|
||||
|
||||
@@ -148,3 +148,50 @@ def get_works_summary(orcid_id: str) -> dict:
|
||||
def get_work_detail(orcid_id: str, put_code: int) -> dict | None:
|
||||
client = ORCIDClient()
|
||||
return client.fetch_work_detail(orcid_id, put_code)
|
||||
|
||||
|
||||
def get_record(orcid_id: str) -> dict:
|
||||
client = ORCIDClient()
|
||||
return client.fetch_record(orcid_id)
|
||||
|
||||
|
||||
def extract_display_name(record: dict | None) -> str | None:
|
||||
"""
|
||||
Devuelve un nombre legible a partir de la respuesta de `/record` de ORCID.
|
||||
|
||||
Prioriza `credit-name` (el nombre tal y como el investigador prefiere mostrarlo);
|
||||
si no está disponible, compone `given-names` + `family-name`.
|
||||
"""
|
||||
if not record:
|
||||
return None
|
||||
|
||||
name = (record.get("person") or {}).get("name") or {}
|
||||
|
||||
credit = name.get("credit-name")
|
||||
if isinstance(credit, dict):
|
||||
credit_value = credit.get("value")
|
||||
if credit_value:
|
||||
return credit_value
|
||||
|
||||
given_obj = name.get("given-names")
|
||||
family_obj = name.get("family-name")
|
||||
given = given_obj.get("value") if isinstance(given_obj, dict) else None
|
||||
family = family_obj.get("value") if isinstance(family_obj, dict) else None
|
||||
|
||||
full = " ".join(part for part in (given, family) if part)
|
||||
return full or None
|
||||
|
||||
|
||||
def get_display_name(orcid_id: str) -> str | None:
|
||||
"""
|
||||
Obtiene el nombre público del investigador desde ORCID.
|
||||
|
||||
Devuelve `None` (sin propagar la excepción) si la API de ORCID no responde
|
||||
o el `record` no contiene un nombre utilizable, para no romper el flujo de
|
||||
búsqueda cuando solo falla la resolución del nombre.
|
||||
"""
|
||||
try:
|
||||
record = get_record(orcid_id)
|
||||
except Exception:
|
||||
return None
|
||||
return extract_display_name(record)
|
||||
|
||||
Reference in New Issue
Block a user