Skip to content

Fix improve oai pmh metadata quality for agris ap compliance#1425

Merged
gitnnolabs merged 4 commits intoscieloorg:mainfrom
Rossi-Luciano:fix_improve_OAI-PMH_metadata_quality_for_AGRIS_AP_compliance
Apr 2, 2026
Merged

Fix improve oai pmh metadata quality for agris ap compliance#1425
gitnnolabs merged 4 commits intoscieloorg:mainfrom
Rossi-Luciano:fix_improve_OAI-PMH_metadata_quality_for_AGRIS_AP_compliance

Conversation

@Rossi-Luciano
Copy link
Copy Markdown
Collaborator

Descrição do PR

Corrige a geração de metadados OAI-PMH no SciELO Core para conformidade
com o AGRIS Application Profile. Os problemas foram identificados por análise
comparativa entre o XML interno XOAI (item.compile) e a saída oai_dc_agris
gerada pelo lareferencia-oai-pmh.

As correções afetam o template de compilação do registro XOAI, o índice
de busca OAI e o modelo de licença.


Arquivo 1: article/templates/search/indexes/article/article_compile.txt

Commit

fix(compile): fix OAI-PMH record template for AGRIS AP compliance
 
Corrige múltiplos problemas identificados na saída oai_dc_agris:
 
- dc:description: {{ abs }} chamava __str__ de DocumentAbstract,
  retornando "[None | en] Abstract..." em vez do texto puro.
  Corrigido para {{ abs.plain_text }} com sub-elemento 'abstract'
  e wrapper <element> conforme estrutura esperada pelo crosswalk.
 
- dc:date: object.updated (timestamp de modificação Django) era
  emitido como data de publicação. Corrigido para object.pub_date
  sob sub-elemento 'issued', alinhado com dc.date.issued do crosswalk.
 
- dc:identifier: todos os identificadores estavam sob 'none',
  impedindo o crosswalk de qualificá-los por tipo. Reestruturado
  com sub-elementos nomeados: 'doi' e 'uri'. Identificadores internos
  (pid_v2, pid_v3) mantidos em 'none'.
 
- dc:rights: object.license é ForeignKey, não M2M. A chamada .all()
  nunca executava, resultando em dc:rights sempre vazio.
  Corrigido para acesso direto via object.license.url.
 
- dc:source: object.source retornava vazio para a maioria dos
  registros. Substituído por construção explícita a partir de
  object.journal.title e object.pub_date_year.
 
- dc:relation: adicionado via journal.title para indicar o periódico
  de origem do artigo, conforme recomendação AGRIS AP.
 
- dc:contributor.author: estrutura alterada de dc.creator.none para
  dc.contributor.author, alinhada com o crosswalk. Nome do autor
  emitido no formato "Sobrenome, Nome" usando last_name e given_names
  do modelo ContribPerson. Mantém fallback para person.names quando
  last_name não está disponível.
 
Ref: AGRIS AP — seção 4.2 Creator
     https://www.fao.org/4/ae909e/ae909e05.htm
Ref: AGRIS AP — seção 4.6 Description
Ref: AGRIS AP — seção 4.7 Date
Ref: AGRIS AP — seção 4.8 Identifier
Ref: AGRIS AP — seção 4.11 Rights
Ref: AGRIS AP — seção 4.13 Source

Alterações por correção:

Campo Problema Correção
dc:description __str__ com prefixo [None | en] abs.plain_text + sub-elemento abstract
dc:date object.updated (timestamp interno) object.pub_date sob issued
dc:identifier tudo em none sub-elementos doi, uri
dc:rights .all() em ForeignKey object.license.url direto
dc:source object.source vazio journal.title + pub_date_year
dc:relation ausente adicionado via journal.title
dc:creator none sem inversão de nome contributor.author com Sobrenome, Nome

Arquivo 2: article/search_indexes.py

Commit

fix(search_indexes): fix prepare_license and prepare_creator
                     in ArticleOAIIndex for AGRIS AP compliance
 
prepare_license: retornava o código interno "CC BY 4.0" em vez da
URL da licença Creative Commons. Refatorado para usar License.url,
que reconstrói a URL correta a partir do license_type.
 
prepare_creator: retornava person.names (nome completo sem inversão,
em caixa alta). O AGRIS AP exige o formato "Sobrenome, Nome" para
autores pessoais. Corrigido para construir o nome a partir dos campos
separados last_name, given_names e suffix do modelo ContribPerson.
Mantém fallback para person.names quando last_name não está disponível.
 
Ref: AGRIS AP — seção 4.2 Creator
     https://www.fao.org/4/ae909e/ae909e05.htm
Ref: AGRIS AP — seção 4.11 Rights

Alterações:

# prepare_license — ANTES
def prepare_license(self, obj):
    if obj.license and obj.license.license_type:
        return [obj.license.license_type]
 
# prepare_license — DEPOIS
def prepare_license(self, obj):
    if obj.license and obj.license.url:
        return [obj.license.url]
    return None
 
# prepare_creator — ANTES
def prepare_creator(self, obj):
    if obj.contrib_persons.exists():
        return set([
            person.names
            for person in obj.contrib_persons.all()
            if person.names
        ])
 
# prepare_creator — DEPOIS
def prepare_creator(self, obj):
    if not obj.contrib_persons.exists():
        return None
    result = set()
    for person in obj.contrib_persons.all():
        if person.last_name:
            suffix = f" {person.suffix}" if person.suffix else ""
            given = f", {person.given_names}" if person.given_names else ""
            result.add(f"{person.last_name}{suffix}{given}")
        elif person.names:
            result.add(person.names)
    return result or None

Arquivo 3: core/models.py

Commit

fix(models): fix License.url to correctly reconstruct CC license URL
 
A property License.url existia mas gerava URLs inválidas porque usava
license_type ("CC BY 4.0") diretamente no path da URL.
 
O campo license_type segue o formato "CC {CODE} {VERSION}" com
version=None (ex.: "CC BY 4.0", "CC BY-NC 4.0", "CC BY-SA 4.0").
 
Corrigido para parsear o formato e reconstruir a URL:
  "CC BY 4.0"    → https://creativecommons.org/licenses/by/4.0/
  "CC BY-NC 4.0" → https://creativecommons.org/licenses/by-nc/4.0/
  "CC BY-SA 4.0" → https://creativecommons.org/licenses/by-sa/4.0/

Alterações:

# ANTES
@property
def url(self):
    return f"https://creativecommons.org/licenses/{self.license_type}/{self.version or '4.0'}/"
 
# DEPOIS
@property
def url(self):
    """Reconstrói a URL CC a partir do license_type no formato 'CC {CODE} {VERSION}'"""
    if not self.license_type:
        return None
    parts = self.license_type.split()
    if len(parts) == 3 and parts[0].upper() == "CC":
        code = parts[1].lower()
        version = parts[2]
        return f"https://creativecommons.org/licenses/{code}/{version}/"
    return None

Checklist de revisão — PR 2

  • rebuild_index executado após alterações no search_indexes.py
  • GetRecord testado com artigo que tem contrib_persons, license e abstracts populados
  • dc:creator no formato Sobrenome, Nome confirmado na saída
  • dc:rights com URL CC completa confirmada na saída
  • dc:description sem prefixo [None | en] confirmado na saída
  • dc:date com apenas dcterms:dateIssued confirmado na saída
  • License.url testado com os três tipos (CC BY, CC BY-NC, CC BY-SA)

- dc:description: {{ abs }} chamava __str__ de DocumentAbstract,
  retornando "[None | en] Abstract..." em vez do texto puro.
  Corrigido para {{ abs.plain_text }} com sub-elemento 'abstract'
  e wrapper <element> conforme estrutura esperada pelo crosswalk.

- dc:date: object.updated (timestamp de modificação Django) era
  emitido como data de publicação. Corrigido para object.pub_date
  sob sub-elemento 'issued', alinhado com dc.date.issued do crosswalk.

- dc:identifier: todos os identificadores estavam sob 'none',
  impedindo o crosswalk de qualificá-los por tipo. Reestruturado
  com sub-elementos nomeados: 'doi' e 'uri'. Identificadores internos
  (pid_v2, pid_v3) mantidos em 'none'.

- dc:rights: object.license é ForeignKey, não M2M. A chamada .all()
  nunca executava, resultando em dc:rights sempre vazio.
  Corrigido para acesso direto via object.license.url.

- dc:source: object.source retornava vazio para a maioria dos
  registros. Substituído por construção explícita a partir de
  object.journal.title e object.pub_date_year.

- dc:relation: adicionado via journal.title para indicar o periódico
  de origem do artigo, conforme recomendação AGRIS AP.

- dc:contributor.author: estrutura alterada de dc.creator.none para
  dc.contributor.author, alinhada com o crosswalk. Nome do autor
  emitido no formato "Sobrenome, Nome" usando last_name e given_names
  do modelo ContribPerson. Mantém fallback para person.names quando
  last_name não está disponível.

Ref: AGRIS AP — seção 4.2 Creator
     https://www.fao.org/4/ae909e/ae909e05.htm
Ref: AGRIS AP — seção 4.6 Description
Ref: AGRIS AP — seção 4.7 Date
Ref: AGRIS AP — seção 4.8 Identifier
Ref: AGRIS AP — seção 4.11 Rights
Ref: AGRIS AP — seção 4.13 Source
prepare_license: retornava o código interno "CC BY 4.0" em vez da
URL da licença Creative Commons. Refatorado para usar License.url,
que reconstrói a URL correta a partir do license_type.

prepare_creator: retornava person.names (nome completo sem inversão,
em caixa alta). O AGRIS AP exige o formato "Sobrenome, Nome" para
autores pessoais. Corrigido para construir o nome a partir dos campos
separados last_name, given_names e suffix do modelo ContribPerson.
Mantém fallback para person.names quando last_name não está disponível.

Ref: AGRIS AP — seção 4.2 Creator
     https://www.fao.org/4/ae909e/ae909e05.htm
Ref: AGRIS AP — seção 4.11 Rights
A property License.url existia mas gerava URLs inválidas porque usava
license_type ("CC BY 4.0") diretamente no path da URL.

O campo license_type segue o formato "CC {CODE} {VERSION}" com
version=None (ex.: "CC BY 4.0", "CC BY-NC 4.0", "CC BY-SA 4.0").

Corrigido para parsear o formato e reconstruir a URL:
  "CC BY 4.0"    → https://creativecommons.org/licenses/by/4.0/
  "CC BY-NC 4.0" → https://creativecommons.org/licenses/by-nc/4.0/
  "CC BY-SA 4.0" → https://creativecommons.org/licenses/by-sa/4.0/
@Rossi-Luciano Rossi-Luciano requested a review from gitnnolabs April 1, 2026 14:06
@gitnnolabs
Copy link
Copy Markdown
Collaborator

Validando ...

@gitnnolabs
Copy link
Copy Markdown
Collaborator

PR aprovado e funcionando como esperado!

@gitnnolabs gitnnolabs merged commit 64192ec into scieloorg:main Apr 2, 2026
3 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants