Corrige publicação de PDF entre outras questões v3.0.0rc23 - #1042
Merged
robertatakenaka merged 20 commits intoAug 4, 2026
Conversation
…e todos os campos textuais Propósito: eliminar falso positivo de correspondência na estratégia journal-article, onde um candidato de outro artigo (mesmo periódico, nenhum outro dado em comum) entrava como unmatched só por bater em um único hash textual (ex.: z_partial_body genérico 'ARTIGO DE REVISÃO'), causando QueryDocumentMultipleObjectsReturnedError indevido no registro de artigos novos. Solução técnica: article_data_query deixou de montar OR condicional entre z_surnames/z_collab/z_links/z_partial_body e passou a sempre retornar uma query AND exigindo correspondência simultânea dos 4 campos. Adicionado o método get_article_data_query(issue: bool), que compõe explicitamente a busca com fascículo (dados textuais + issue_params + article_location_params) e sem fascículo (dados textuais + volume/number/suppl/elocation_id/fpage/lpage nulos no candidato).
…s e adiciona fallback em get_readable_data Propósito: corrigir o mesmo incidente de correspondência indevida na origem — select_records montava a query da branch journal-article sem nenhuma restrição de fascículo/localização, e data_to_compare/data ficavam sem article_titles/body_fragment quando readable_data estava vazio (registros antigos). Solução técnica: select_records passa a chamar qbuilder.get_article_data_query(issue=True) na branch journal-issue-article e get_article_data_query(issue=False) na branch journal-article, em vez de montar a query manualmente. Adicionado PidProviderXML.get_readable_data(), usado em data_to_compare e em data, que recalcula os dados legíveis via xml_with_pre.get_article_data() quando readable_data estiver vazio ou nulo.
…cobertura de get_article_data_query Propósito: refletir a correção de article_data_query (fim do branch OR) e cobrir o novo método get_article_data_query, evitando regressão do bug de falso match relatado em produção. Solução técnica: ArticleDataQueryTests reescrita para validar a query AND pura (sem merge com article_location_params) e garantir que a versão OR antiga não é mais produzida. Nova classe GetArticleDataQueryTests cobre issue=True/False e confirma que os dois ramos geram queries distintas. CompareItemsTests ganhou testes de regressão para o fallback de how_similar com None.
…_article_data_query Propósito: manter a suíte compatível com a nova implementação de select_records, que não monta mais a query da branch journal-article/journal-issue-article manualmente. Solução técnica: mock_qbuilder.get_article_data_query recebe side_effect parametrizado por issue (True/False), substituindo o mock direto de issue_params/article_data_query. Testes passam a verificar também a ordem e os argumentos das chamadas a get_article_data_query, incluindo o teste de lazy evaluation do generator.
…forçar match textual Propósito: eliminar falso-positivo de correspondência na estratégia journal-article, onde um candidato de outro artigo (mesmo periódico, nenhum outro dado em comum) era classificado como unmatched só por bater em z_partial_body genérico (ex.: rótulo de seção 'ARTIGO DE REVISÃO'), causando QueryDocumentMultipleObjectsReturnedError indevido em artigos novos. Solução técnica: QueryBuilderPidProviderXML passa a ler xml_adapter.xml_with_pre.body_fragment_fingerprint (fingerprint sha256 do corpo inteiro do artigo, já existente em XMLWithPre), sem necessidade de mudança no packtools/adapter. Novo método partial_body_query monta z_partial_body__in com os hashes disponíveis (legado + novo fingerprint), reaproveitando a coluna z_partial_body sem migração; quando nenhum hash está disponível, usa z_partial_body__isnull=True em vez de __in=(None, None), que em SQL nunca casaria com candidatos NULL. article_data_query simplificada para delegar o campo de corpo a partial_body_query.
…dy e documenta o campo Propósito: persistir o novo sinal de correspondência (corpo inteiro do artigo) sem exigir migração de banco, reaproveitando a coluna z_partial_body já existente. Solução técnica: _add_data passa a gravar xml_adapter.xml_with_pre.body_fragment_fingerprint em z_partial_body (antes gravava o hash de xml_adapter.z_partial_body, baseado só no primeiro parágrafo). Adicionado help_text no campo explicando que registros antigos mantêm o formato legado e que a query de match (partial_body_query) compara com ambos os formatos via IN.
… fingerprint do corpo inteiro Propósito: validar a correção do falso-match do incidente e travar a regressão do IN (NULL, NULL), que nunca casaria com candidatos sem hash de corpo. Solução técnica: nova classe PartialBodyQueryTests cobre os 4 cenários (só legado, só fingerprint, ambos, nenhum) e garante isnull=True no caso 'nenhum'. ArticleDataQueryTests atualizada para refletir a delegação a partial_body_query, incluindo teste de que dois artigos com mesmo z_partial_body legado mas fingerprints de corpo diferentes produzem queries distintas.
…dade_no_resultados_de_article_data_query Remove ambiguidade no resultados de article data query
## Propósito Atualizar a dependência packtools de 4.16.8 para 4.16.11, disponibilizando recursos necessários para os ajustes subsequentes em Article, SPSPkg e Package (pkg_name_variations, deprecated_sps_pkg_name_list, get_complete_publication_date e path_in_zip em renditions). ## Solução técnica Bump de versão da referência git no requirements/base.txt (packtools.git@4.16.8 -> packtools.git@4.16.11).
…orage ## Propósito Evitar chamada de upload_to_the_cloud com content=None quando o item não possui conteúdo disponível (após KeyError tratado em item["content"]). ## Solução técnica Adicionado `if not content: continue` antes da chamada de upload_to_the_cloud, pulando itens sem conteúdo em vez de tentar enviá-los.
…xistente ## Propósito Corrigir falha em localizar um Article já existente quando o sps_pkg_name do pacote mudou entre versões (nomes depreciados), o que causava criação de registros duplicados em vez de atualização do existente. ## Solução técnica - get_first passa a aceitar o parâmetro name_list e inclui Q(sps_pkg__sps_pkg_name__in=name_list) na busca. - create_or_update tenta obter xml_with_pre.pkg_name_variations; se o atributo não existir (AttributeError), monta a lista manualmente a partir de sps_pkg_name + deprecated_sps_pkg_name_list, e passa essa lista para get_first.
## Propósito Corrigir múltiplos pontos relacionados à publicação de pacotes: leitura incorreta do conteúdo de renditions dentro do zip, ausência de fallback na extração da data de publicação, impossibilidade de forçar reprocessamento do SPSPkg já registrado no Core, e falha na localização de PidReservation/pid_v2 quando o nome do pacote mudou entre versões. Também remove logs de depuração (logging.info) que não agregam valor em produção e renomeia variável para refletir seu real significado. ## Solução técnica - upload_package_directory_path: renomeia variável sps_pkg_name para xml_name, já que representa o nome do arquivo e não necessariamente o nome do pacote SPS. - PackageZip.xmls: remove logging.info supérfluo. - Package.renditions: passa a ler o conteúdo via zf.read(rendition["path_in_zip"]) em vez de rendition["name"], já que o path dentro do zip pode diferir do nome exibido. - Package.set_pid_v2_and_publication_date: adiciona fallback para xml_with_pre.get_complete_publication_date() quando article_publication_date não está disponível/é inválida. - Package.prepare_sps_package / prepare_to_publish: adicionam o parâmetro force_update, permitindo forçar a atualização do SPSPkg mesmo quando já registrado e válido no Core; ajustado o filtro de pdf_langs em renditions removendo a checagem redundante contra xml_with_pre.filenames. - PidReservation.get: passa a aceitar name_list, permitindo buscar por múltiplas variações de pkg_name (pkg_name__in). - PidV2Generator.generate: usa xml_with_pre.pkg_name_variations (com fallback para sps_pkg_name + deprecated_sps_pkg_name_list) ao consultar PidReservation, evitando falha na resolução de pid_v2 quando o nome do pacote mudou; remove logs de depuração (logging.info) intermediários do fluxo.
…tar colisão de nomes Propósito: Os parâmetros do construtor de MinioStorage (bucket, object_name_prefix, public_url) tinham nomes genéricos que colidiam semanticamente com properties de mesmo nome em MinioConfiguration, dificultando o rastreamento de onde cada valor era originado. Solução técnica: Renomeados os parâmetros do __init__ para minio_bucket, minio_object_name_prefix e minio_public_url, deixando explícito que são valores específicos de configuração do Minio. Atributos internos (self.bucket, self.object_name_prefix, self.public_url) mantidos inalterados para não impactar o restante da classe.
…com host_root_dir Propósito: get_files_storage montava o MinioStorage usando 'obj.host_root_dir or obj.bucket' diretamente na chamada, sem centralizar essa regra, e a property public_url aplicava o prefixo de host_root_dir por cima da public_base_url informada pelo usuário, alterando um valor que deveria ser respeitado como está. Solução técnica: - Introduzida a property kwargs em MinioConfiguration, centralizando a montagem dos argumentos usados por MinioStorage (agora com os nomes minio_bucket, minio_object_name_prefix, minio_public_url). - Criada a property minio_bucket, que resolve a precedência entre host_root_dir e bucket. - Property object_name_prefix renomeada para minio_object_name_prefix (mesma lógica: bucket vira prefixo somente quando host_root_dir existe). - Property public_url renomeada para minio_public_url e corrigida: quando public_base_url é informado, ele é usado exatamente como está (sem concatenar prefixo); quando ausente, a URL é montada a partir do host e, nesse caso, o minio_bucket é anexado como subcaminho. - get_files_storage agora usa obj.kwargs + minio_http_client, evitando duplicar a lógica de resolução de bucket/prefixo/url na chamada.
…ublic_url Propósito: Os testes existentes validavam os nomes antigos de parâmetros e a regra antiga de public_url (que sempre concatenava o prefixo por cima da public_base_url informada). Solução técnica: Testes ajustados para os nomes minio_bucket, minio_object_name_prefix e minio_public_url, e para o novo comportamento de minio_public_url: - Quando public_base_url é informada, é usada exatamente como está, mesmo havendo host_root_dir. - Quando ausente, a URL é montada a partir do host, anexando minio_bucket como subcaminho. Removidas notas de docstring que descreviam o contrato antigo.
…o e não ser o campo mais adequado para tal
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
O que esse PR faz?
Este PR consolida a
maincom as PRs #1036 e #1038, reunindo as correções e refatorações abaixo para viabilizar uma release imediata da v3.x:QueryDocumentMultipleObjectsReturnedErrorcausado pela lógica OR emarticle_data_query. Introduzpartial_body_query, que passa a compararz_partial_bodycom múltiplos candidatos (z_partial_body__in) — hash legado (primeiro parágrafo) e o novobody_fragment_fingerprint(hash do corpo inteiro do artigo) — corrigindo também o bug dez_partial_body__in=(None, None)nunca casar com registrosNULL(substituído porz_partial_body__isnull=True). Adicionaget_article_data_query(issue=True/False)para centralizar a composição da query nas branches "journal-issue-article" e "journal-article" deselect_records.get_readable_data()passa a ter fallback paraxml_with_pre.get_article_data()quandoreadable_dataestá vazio.compare_itemsagora trataNonecomo string vazia ao chamarhow_similar.get_first/PidReservation.getpassam a aceitarname_list, permitindo casar contrapkg_name_variations(ou, na ausência,sps_pkg_name+deprecated_sps_pkg_name_list), reduzindo duplicidade de artigos/PIDs por variação de nome de pacote.MinioStorage/MinioConfigurationparaminio_bucket,minio_object_name_prefix,minio_public_url, evitando colisão de nomes e deixando explícito o contrato. Adicionakwargsproperty emMinioConfigurationpara montar os argumentos doMinioStorage, corrigindo bug em queget_files_storagequebrava (AttributeError) ao usarselfem vez doobjrecuperado no fallback. Reorganiza a suíte de testes parafiles_storage/tests/.renditionspassa a usarpath_in_zip(em vez dename) para ler o conteúdo dentro do ZIP, corrigindo leitura de renditions com nomes divergentes.prepare_to_publish/prepare_sps_packagerecebemforce_update, permitindo forçar a reconstrução doSPSPkgmesmo quando já registrado/válido (usado no fluxo de publicação em lote).update_status_and_add_commentsdeixa de concatenarcommentsemqa_comment(comentado, decisão de não poluir a caixa de QA). Remove chamadas delogging.infode depuração no fluxo de geração de PID v2.InspectFirstIndexView, restaurando o comportamento doModelAdminlegado — clique no item da listagem abre a inspect view (quando disponível) em vez da edit view; a ação "Edit" continua acessível pelo menu "...".SPSPkgignora renditions semcontent(evita upload de arquivo vazio/corrompido para o storage).packtoolsde4.16.8para4.16.11.Onde a revisão poderia começar?
pid_provider/query_params.py(partial_body_query,article_data_query,get_article_data_query) — é o núcleo da correção do incidente de falso-positivo.pid_provider/models.py(select_records,get_readable_data) — consumo do novoget_article_data_query.files_storage/models.py(kwargs,minio_bucket,minio_object_name_prefix,minio_public_url) — correção do bug deget_files_storage.Como este poderia ser testado manualmente?
pytest pid_provider/tests/test_query_params.py pid_provider/tests/test_select_records.py files_storage/tests/test_minio.py files_storage/tests/test_models.py.sps_pkg_nametenha variações (ex.: nome atual + nomes deprecated) e confirmar que não gera artigo/PID duplicado.MinioConfiguration.get_files_storage, testar o caminho de fallback (nome de configuração inexistente) e confirmar que não lançaAttributeError.PackageViewSet), clicar em um item da listagem e confirmar que abre a tela de inspeção; verificar que "Edit" ainda está disponível no menu de ações.SPSPkgjá estejaregistered_in_coree válido, forçandoforce_update=True, e confirmar que o pacote é reconstruído.Algum cenário de contexto que queira dar?
Este PR é o merge da
maincom as PRs #1036 e #1038, feito com o objetivo de consolidar rapidamente as correções pendentes (principalmente a correção do incidente de falso-positivo emarticle_data_query) e viabilizar uma release imediata da versão v3.x. Por ser um merge consolidador, o diff cobre múltiplas áreas (pid_provider,files_storage,upload,article,package) que foram revisadas individualmente em suas PRs de origem.Screenshots
Não aplicável (mudanças de backend/lógica de dados; a única alteração de UI é o comportamento de clique na listagem do Upload, sem alteração visual).
Quais são os tickets relevantes?
main+ Corrige a obtenção dos pdfs do pacote do Upload v3.x #1036 + Corrige os dados de Minio para obter o endereço correto dos documentos carregados #1038.QueryDocumentMultipleObjectsReturnedError(referenciado no histórico de commits dopid_provider).Referências
packtoolsv4.16.11: https://github.com/scieloorg/packtoolsSegurança da informação (NSI.04)
Este PR manipula dados sensíveis ou pessoais (LGPD)?
Este PR altera autenticação, autorização, controle de acesso ou gerenciamento de sessão?
wagtail_hooks.pyaltera apenas a navegação da listagem — para onde o clique leva —, sem impacto em permissões, autenticação ou sessão)Este PR introduz, atualiza ou remove dependências de terceiros?
packtoolsde 4.16.8 para 4.16.11, necessária para suportarpkg_name_variations/body_fragment_fingerprint; verificação SBOM/Trivy a confirmar antes do merge final.Este PR foi validado pelo pipeline de segurança (SonarQube / Trivy)?
Este PR concatena, monta ou executa comandos SQL, HTML ou JavaScript a partir de entrada externa?
Q()/filtros nomeados, sem concatenação de strings)Este PR expõe novos endpoints, telas ou serviços?
InspectFirstIndexViewapenas customiza o comportamento de uma view já registrada)Algum segredo, senha, chave ou token está sendo adicionado ao código-fonte?