Skip to content

WIP Fix issue am - #1496

Draft
robertatakenaka wants to merge 19 commits into
scieloorg:mainfrom
robertatakenaka:fix_issue_am
Draft

robertatakenaka wants to merge 19 commits into
scieloorg:mainfrom
robertatakenaka:fix_issue_am

Conversation

@robertatakenaka

Copy link
Copy Markdown
Member

O que esse PR faz?

Corrige o tratamento do issue_pid e das chaves legadas (AMJournal, AMIssue, AMArticle) quando o periódico é publicado em mais de uma coleção e o pid diverge entre elas.

  • issue_pid por coleção: passa a ser obtido do AMIssue de cada coleção (Issue.get_issue_pid). Os pids estabelecidos no legado são preservados, e pids novos são gerados apenas nas coleções faltantes, usando a próxima ordem livre quando há colisão.
  • issue_pid_suffix: passa a ser apenas a ordem calculada pela regra (volume/número/suplemento), usada para gerar pids novos. Deixa de ser copiado do pid legado.
  • Exportação para o ArticleMeta: usa o issue_pid da coleção de destino.
  • Fascículo único: o get/create de Issue é serializado por periódico, para que coletas paralelas em coleções diferentes compartilhem um único Issue. Na busca, volume, número e suplemento ausentes deixam de funcionar como curinga.
  • Fascículos migrados (migrated=True) não geram pids na criação. O pid do legado é associado em seguida. Se esse pid já tinha sido gerado para outro fascículo, o outro fascículo recebe um pid novo.
  • Unicidade dos registros legados: constraints de unicidade (collection, pid) em AMIssue e AMJournal. Duplicados existentes são consolidados (BaseLegacyRecord.deduplicate), e a criação concorrente é tratada como atualização.
  • SciELOJournal: passa a usar a mesma coleção do AMJournal coletado.
  • AMArticle: usa exclusivamente o pid v2 do XML de cada coleção (CollectionPidV2). O core não gera nem deriva o pid v2.
  • Limpeza de órfãos: a limpeza de AMIssue órfãos preserva os pids gerados (com new_record).
  • Nova rotina de correção: migrate_issue_legacy_keys / task_migrate_issue_legacy_keys, que corrige fascículos criados antes do AMIssue.
  • Nova API v2: rota api/v2/, sem prefixo de idioma, com o endpoint de issue que expõe o issue_pid por coleção.

Onde a revisão poderia começar?

  1. core/models.py: BaseLegacyRecord (get, deduplicate, create, create_or_update)
  2. issue/models.py: Issue.create_legacy_keys, Issue.get_issue_pid, Issue.get, Issue.get_or_create, Issue.add_am_issue, Issue.save
  3. issue/controller.py: migrate_issue_legacy_keys
  4. article/models.py: Article.create_legacy_keys
  5. issue/tests.py, journal/tests.py e article/tests/test_legacy_keys.py

Como este poderia ser testado manualmente?

  1. Faça backup da base de dados.
  2. Verifique se há duplicados por (collection, pid) em AMIssue e AMJournal. As novas constraints fazem o migrate falhar se houver duplicados, então eles devem ser consolidados antes.
  3. Execute python manage.py migrate.
  4. Execute os testes: python manage.py test issue journal article.
  5. Escolha um periódico publicado em mais de uma coleção, com pids de fascículo diferentes entre elas (ex.: scl e psi).
  6. Execute task_migrate_issue_legacy_keys, filtrando por esse periódico (journal_pid_list) e, opcionalmente, por ano (publication_year). Confira as estatísticas no log.
  7. No admin, confira se cada Issue tem um AMIssue por coleção. Os pids migrados devem estar preservados e os gerados devem existir apenas nas coleções que não tinham pid.
  8. Acesse /api/v2/issue/?collection=<acron3> e confira se issue_pid corresponde ao pid da coleção e se legacy_issue traz os pids de todas as coleções.
  9. Exporte o fascículo para o ArticleMeta e confira se o code corresponde ao issue_pid de cada coleção.
  10. Repita a coleta do ArticleMeta do mesmo periódico em duas coleções e confira que não são criados Issues, AMIssue, AMJournal ou SciELOJournal duplicados.

Algum cenário de contexto que queira dar?

No legado, o issue_pid de um mesmo fascículo pode ser diferente em cada coleção, por exemplo 0103-656420240005 em scl e 1678-517720240002 em psi. Isso ocorre porque o issn_scielo difere entre as coleções e porque a ordem do fascículo foi, muitas vezes, atribuída manualmente.

O core gerava o pid a partir de um único issue_pid_suffix, copiado do pid de uma das coleções. Isso produzia pids errados, ou já usados por outro fascículo, nas demais coleções.

Pelas mesmas razões, o pid v2 do artigo não é gerado nem derivado no core. A geração do pid v2 de artigos novos é responsabilidade do scms-upload, e o core usa o que foi registrado no pid provider para cada coleção.

Fascículos já existentes devem ser corrigidos com task_migrate_issue_legacy_keys após a atualização.

Screenshots

N/A

Quais são os tickets relevantes?

#1495

Referências

N/A


Segurança da informação (NSI.04)

Este PR manipula dados sensíveis ou pessoais (LGPD)?

  • Sim — descreva os controles de proteção aplicados (criptografia, mascaramento, anonimização, etc.):
  • Não

Este PR altera autenticação, autorização, controle de acesso ou gerenciamento de sessão?

  • Sim — descreva o que mudou e por quê:
  • Não

Este PR introduz, atualiza ou remove dependências de terceiros?

  • Sim — as novas dependências foram verificadas no SBOM/Trivy sem vulnerabilidades críticas/altas em aberto?
    • Verificado e aprovado
    • Pendente / vulnerabilidade aceita com justificativa:
  • Não

Este PR foi validado pelo pipeline de segurança (SonarQube / Trivy)?

  • Sim — link do job:
  • Não aplicável a este PR (justifique):

Este PR concatena, monta ou executa comandos SQL, HTML ou JavaScript a partir de entrada externa?

  • Sim — confirme que há sanitização/parametrização (prepared statements, escaping, etc.):
  • Não

Este PR expõe novos endpoints, telas ou serviços?

  • Sim — HTTPS obrigatório está garantido e o acesso segue o princípio de menor privilégio? Novo endpoint /api/v2/issue/, somente leitura, com a mesma autenticação e as mesmas permissões da API v1, servido sob HTTPS como as demais rotas da aplicação.
  • Não

Algum segredo, senha, chave ou token está sendo adicionado ao código-fonte?

  • Não, nenhum segredo foi commitado
  • Sim (bloquear merge e corrigir antes de prosseguir)

Adiciona UniqueConstraint (collection, pid) em AMJournal
(unique_amjournal_collection_pid).
Migração que cria a UniqueConstraint unique_amjournal_collection_pid
(collection, pid) em AMJournal.
create_or_update_scielo_journal aceita uma instância de Collection e só
chama get_collection quando recebe um identificador.
…cleMeta

A coleção do SciELOJournal era obtida dos dados do periódico, que podem
trazer o code e não o acron3 da coleção. Com isso, o SciELOJournal podia
ficar em coleção diferente da do AMJournal e do AMIssue.

Detalhes de implementação:
- _register_journal_data passa journal_am.collection para
  create_or_update_scielo_journal
TestJournalLoadedFromArticleMetaInCollections verifica que são gerados um
único Journal e um AMJournal e um SciELOJournal por coleção. O teste cobre
coletas repetidas e coleção com code diferente de acron3.
O issue_pid pode divergir entre coleções, pois o issn_scielo e a ordem
atribuída manualmente no legado podem ser diferentes. O issue_pid passa a
ser obtido do AMIssue de cada coleção:
- os pids estabelecidos são preservados
- pids novos são gerados apenas nas coleções faltantes
- coletas paralelas do mesmo fascículo em coleções diferentes deixam de
  criar Issues distintos

O issue_pid_suffix passa a ser apenas a ordem calculada pela regra, usada
para gerar pids novos.

Detalhes de implementação:
- AMIssue: UniqueConstraint (collection, pid)
- create_legacy_keys: cria AMIssue só nas coleções sem chave; o pid é
  issn_scielo + ano + issue_pid_suffix, avançando para a próxima ordem
  livre quando já usado na coleção; os erros são registrados por coleção
  em UnexpectedEvent
- novo get_issue_pid(collection, create=True): retorna o pid da coleção
  (Collection ou acron3), priorizando o migrado (com url), e cria o pid
  se ausente
- get: exige journal e year; volume, number e supplement ausentes filtram
  por ausência (None ou ""), em vez de serem ignorados; os campos
  calculados são gravados via update, sem disparar save
- create / get_or_create: o parâmetro migrated substitui issue_pid_suffix,
  que deixa de ser recebido
- get_or_create: transaction.atomic com select_for_update no Journal,
  para serializar a criação; a lógica foi movida para _get_or_create
- add_am_issue: remove o pid gerado na mesma coleção quando chega o pid
  estabelecido; se o AMIssue pertencia a outro fascículo, gera um novo
  pid para esse fascículo; status "done" em vez de "completed"
- save: não gera pids para Issue migrado (_migrated)
Migração que cria a UniqueConstraint unique_amissue_collection_pid
(collection, pid) em AMIssue.
extract_data_from_harvested_data não retorna mais issue_pid_suffix, que
era copiado de pid[-4:]. Esse valor passa a ser calculado pela regra, e o
pid estabelecido fica no AMIssue.
…leMeta

create_issue_from_am_issue cria o Issue com migrated=True e deixa de
passar issue_pid_suffix. Assim nenhum pid é gerado antes de o pid do
AMIssue ser associado por add_am_issue.
_format_code usa Issue.get_issue_pid com a coleção do SciELOJournal, em
vez de montar issn_scielo + ano + issue_pid_suffix.
Somente comentários e docstring; sem mudança de comportamento.
Fascículos criados antes da existência do AMIssue não têm issue_pid por
coleção. Alguns também têm issue_pid_suffix copiado de um pid manual. A
nova rotina associa os pids migrados, recalcula a ordem e gera os pids
faltantes, nessa sequência, para que os pids migrados prevaleçam sobre
os gerados.

Detalhes de implementação:
- novo migrate_issue_legacy_keys, filtrável por coleção, journal pid e
  ano, com três etapas:
  1. associa AMIssue migrados sem new_record via
     create_issue_from_am_issue
  2. recalcula issue_pid_suffix via update, sem save, para não gerar
     pids antes da etapa 3
  3. executa create_legacy_keys nos Issues com menos coleções com AMIssue
     do que coleções do periódico (todos, com force_update)
- retorna estatísticas; erros por Issue são registrados em UnexpectedEvent
A limpeza de AMIssue órfãos removia também os pids gerados pelo sistema,
que não têm data nem url. A correção das chaves legadas de fascículos
passa a estar disponível como tarefa.

Detalhes de implementação:
- task_update_issues_from_amissue: a limpeza exclui os AMIssue com
  new_record
- nova task_migrate_issue_legacy_keys, que chama
  controller.migrate_issue_legacy_keys e registra falhas em
  UnexpectedEvent
Router da API v2 (namespace api_v2), incluído em config/urls.py sob
api/v2/, com o endpoint de issue que expõe o issue_pid por coleção.
Inclui a rota api/v2/ (config.api_router_v2) fora de i18n_patterns, sem
prefixo de idioma, após as rotas mais específicas de api/v2/pid/ e
api/v2/auth/.
O pid v2 pode divergir entre coleções. O core não gera nem deriva esse
pid, pois isso é responsabilidade do scms-upload. A chave legada passa a
vir apenas do pid v2 registrado no pid provider para cada coleção. Uma
coleção sem esse registro fica sem AMArticle.

Detalhes de implementação:
- create_legacy_keys percorre pp_xml.collection_pids_v2, em vez de
  derivar o pid a partir das chaves legadas da issue
- remove AMArticle não migrado (sem data/url) com pid diferente do XML
  da coleção
- reutiliza o AMArticle existente: associa se estiver sem new_record e
  não cria duplicado se pertencer a outro artigo
- tolera artigo sem issue ou sem pp_xml; remove o atalho por contagem de
  coleções
Cobre a criação de AMArticle a partir do CollectionPidV2 registrado no
pid provider, sem geração nem derivação do pid v2 no core.
Cobre:
- geração de pid por coleção, com a próxima ordem livre
- fascículos migrados sem pids gerados
- correção de issue_pid_suffix por migrate_issue_legacy_keys
- substituição do pid gerado pelo pid estabelecido
- get_issue_pid e exportação para o ArticleMeta por coleção
- API v1 x v2 (issue_pid por coleção, rota sem prefixo de idioma)
- carga do mesmo fascículo do ArticleMeta em várias coleções, com um
  Issue único e AMIssue único por (collection, pid)
@robertatakenaka
robertatakenaka marked this pull request as draft November 6, 2026 13:24
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.

1 participant