Skip to content

Corrige download XLS/CSV da listagem de periódicos no SciELO.org - #1475

Merged
samuelveigarangel merged 5 commits into
scieloorg:mainfrom
samuelveigarangel:fix/download-journals-list-scielo-org
Sep 15, 2026
Merged

samuelveigarangel merged 5 commits into
scieloorg:mainfrom
samuelveigarangel:fix/download-journals-list-scielo-org

Conversation

@samuelveigarangel

Copy link
Copy Markdown
Collaborator

O que esse PR faz?

Corrige o download XLS/CSV da listagem de periódicos no SciELO.org, que saía apenas com o nome das colunas. O arquivo passa a incluir os periódicos visíveis na listagem, filtrar por categoria quando o download parte da URL de uma área, e nomear o arquivo com o slug da categoria ou all_journals. Também adiciona a opção Todos no select de categoria.

Onde a revisão poderia começar?

core/home/views.py (_get_scielo_journals_data e _journals_download_filename) e, em seguida, journal/models.py (SciELOJournal.scielo_url, owner_name e as_export_dict).

Como este poderia ser testado manualmente?

  1. Abrir a listagem geral de periódicos no SciELO.org e baixar XLS e CSV: o arquivo deve ter linhas (título, URL SciELO, publisher) e o nome all_journals_AAAA-MM-DD.csv (ou .xls).
  2. Abrir uma URL de categoria (ex.: lista-por-tema/health-sciences/) e baixar XLS/CSV: o arquivo deve conter só os periódicos daquela área e o nome health-sciences_AAAA-MM-DD.csv.
  3. No select de categoria, escolher Todos e confirmar o retorno à listagem completa.
  4. Conferir que periódicos sem domínio da coleção não esvaziam o arquivo inteiro.

Algum cenário de contexto que queira dar?

A view engolia qualquer exceção ao montar a URL (domain.rstrip com domain nulo) e devolvia lista vazia, por isso o download vinha só com o cabeçalho. A listagem por categoria já filtrava por journal__subject__code, mas o botão de download não enviava a categoria.

Screenshots

Não aplicável.

Quais são os tickets relevantes?

Não há issue vinculada.

Referências

Não há.


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

Seção obrigatória. Marque as opções aplicáveis e justifique quando necessário. Referência: NSI.04 - Norma de Desenvolvimento Seguro.

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): alteração de listagem/download de periódicos já públicos; o pipeline de CI do repositório deve rodar na PR.

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?
  • 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)

Made with Cursor

samuelveigarangel and others added 4 commits September 9, 2026 15:08
A montagem de scielo_url, publisher e o dicionário do download passa a viver no modelo, para a view só consultar e serializar.

Co-authored-by: Cursor <cursoragent@cursor.com>
O arquivo deixa de sair só com o cabeçalho, aplica os mesmos filtros da listagem e nomeia o download com a categoria ou all_journals.

Co-authored-by: Cursor <cursoragent@cursor.com>
A listagem por área passa a voltar para todos os periódicos e o botão de download respeita a categoria da URL.

Co-authored-by: Cursor <cursoragent@cursor.com>
Os testes garantem que o XLS/CSV traz periódicos, filtra por área e usa all_journals ou o slug da categoria no filename.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread journal/models.py
Comment on lines +2239 to +2248
def scielo_url(self):
domain = ""
if self.collection and self.collection.domain:
domain = self.collection.domain
if not domain:
return ""
return (
f"{domain.rstrip('/')}/scielo.php?script=sci_serial"
f"&pid={self.issn_scielo or ''}&lng=en"
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uma dúvida:

Essa URL é a padrão para coleção clássica. Pelo que notei, ao acessar para periódico brasileira, ela redireciona para o site opac. Ou seja, https://www.scielo.br/scielo.php?script=sci_serial&pid=2318-8219&lng=es&nrm=iso é redirecionado para https://www.scielo.br/j/abcic/. Pretende-se implementar algo aqui para suportar diretamente o domínio do opac (que usa acronym do periódico) e não precisar do redirect?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pelo o que me foi informado, apenas a coleção do brasil e republica dominicana aderiu ao novo site, e ambos possuem redirecionamento.

@pitangainnovare pitangainnovare left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Ha dois testes simples quebrados.
  • Há uma dúvida em relação ao campo owner: o cabeçalho do CSV mostra publisher, mas as linhas são preenchidas com owner; pelo que vi, isso já era antes do PR. Seria o caso de alterar para outro campo ou é assim mesmo?
  • Há um export silencioso de todos os journals quando a categoria informada é inválida. Seria o caso de gerar algum erro ou manter assim mesmo?

Essencialmente, basta corrigir os testes. Os outros pontos são mais para discussão.

Comment thread core/home/views.py
filename = f"journals_{date}.xls"
category = request.GET.get("category") if request is not None else None
if category and slugs_to_category_code.get(category):
prefix = f"{category.replace('-', '_')}_journals"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

esse _journals causa uma falha nos testes:

  • test_csv_download_filters_by_category
  • test_xls_download_filename_uses_category_when_present
(base) rafaeljpd@feeradesk-x3d:~/Repos/pi/scl/core$ docker compose -f local.yml run --rm django pytest core/home/tests.py -q
WARN[0000] /home/rafaeljpd/Repos/pi/scl/core/local.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion 
[+] Creating 3/3
 ✔ Container scielo_core_local_mailhog   Running                                                                                                                                                                        0.0s 
 ✔ Container scielo_core_local_postgres  Running                                                                                                                                                                        0.0s 
 ✔ Container scielo_core_local_redis     Running                                                                                                                                                                        0.0s 
[+] Running 1/1
 ✔ Container core-solr-1  Started                                                                                                                                                                                       0.0s 
PostgreSQL is available
Test session starts (platform: linux, Python 3.11.13, pytest 7.4.3, pytest-sugar 0.9.7)
django: version: 5.2.7, settings: config.settings.test (from option)
rootdir: /app
configfile: pytest.ini
plugins: Faker-40.38.0, sugar-0.9.7, django-test-migrations-1.3.0, django-4.8.0, anyio-3.7.1

 core/home/tests.py ✓✓✓✓                                                                                                                                                                                       31% ███▏      

―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― TestGetScieloJournalsData.test_csv_download_filters_by_category ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――

self = <core.home.tests.TestGetScieloJournalsData testMethod=test_csv_download_filters_by_category>

    def test_csv_download_filters_by_category(self):
        health = Subject.objects.create(
            creator=self.user,
            code="Health Sciences",
            value="Health Sciences",
        )
        self.journal.subject.add(health)
        other_journal = Journal.objects.create(
            creator=self.user,
            title="Other Journal",
        )
        SciELOJournal.objects.create(
            issn_scielo="3333-3333",
            collection=self.collection,
            journal=other_journal,
            journal_acron="tjother",
            status="C",
        )
    
        response = self.client.get(
            reverse("download_csv_journals_page_scielo_org"),
            {"category": "health-sciences"},
        )
        content = response.content.decode("utf-8")
        self.assertIn("Test Journal Peru", content)
        self.assertNotIn("Other Journal", content)
        date = timezone.now().strftime("%Y-%m-%d")
>       self.assertIn(
            f'filename="health-sciences_{date}.csv"',
            response["Content-Disposition"],
        )
E       AssertionError: 'filename="health-sciences_2026-09-13.csv"' not found in 'attachment; filename="health_sciences_journals_2026-09-13.csv"'

core/home/tests.py:182: AssertionError
--------------------------------------------------------------------------------------------------- Captured stderr call ----------------------------------------------------------------------------------------------------
INFO 2026-09-13 14:32:20,335 views 1 134249559516992 Generated CSV file with: 1 journals
----------------------------------------------------------------------------------------------------- Captured log call -----------------------------------------------------------------------------------------------------
INFO     core.home.views:views.py:156 Generated CSV file with: 1 journals

 core/home/tests.py ⨯✓✓✓✓✓✓✓                                                                                                                                                                                   92% █████████▎

―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― TestGetScieloJournalsData.test_xls_download_filename_uses_category_when_present ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――

self = <core.home.tests.TestGetScieloJournalsData testMethod=test_xls_download_filename_uses_category_when_present>

    def test_xls_download_filename_uses_category_when_present(self):
        response = self.client.get(
            reverse("download_xls_journals_page_scielo_org"),
            {"category": "health-sciences"},
        )
        date = timezone.now().strftime("%Y-%m-%d")
>       self.assertIn(
            f'filename="health-sciences_{date}.xls"',
            response["Content-Disposition"],
        )
E       AssertionError: 'filename="health-sciences_2026-09-13.xls"' not found in 'attachment; filename="health_sciences_journals_2026-09-13.xls"'

core/home/tests.py:201: AssertionError
--------------------------------------------------------------------------------------------------- Captured stderr call ----------------------------------------------------------------------------------------------------
INFO 2026-09-13 14:32:20,439 views 1 134249559516992 Generated XLS file with: 0 journals
----------------------------------------------------------------------------------------------------- Captured log call -----------------------------------------------------------------------------------------------------
INFO     core.home.views:views.py:132 Generated XLS file with: 0 journals

 core/home/tests.py ⨯                                                                                                                                                                                         100% ██████████
===================================================================================================== warnings summary ======================================================================================================
../usr/local/lib/python3.11/site-packages/django/db/backends/utils.py:98
  /usr/local/lib/python3.11/site-packages/django/db/backends/utils.py:98: RuntimeWarning: Accessing the database during app initialization is discouraged. To fix this warning, avoid executing queries in AppConfig.ready() or when your app modules are imported.
    warnings.warn(self.APPS_NOT_READY_WARNING_MSG, category=RuntimeWarning)

core/home/tests.py::TestGetScieloJournalsData::test_csv_download_contains_journal_rows
core/home/tests.py::TestGetScieloJournalsData::test_csv_download_filename_uses_all_journals_without_category
core/home/tests.py::TestGetScieloJournalsData::test_csv_download_filters_by_category
core/home/tests.py::TestGetScieloJournalsData::test_xls_download_contains_journal_rows
core/home/tests.py::TestGetScieloJournalsData::test_xls_download_filename_uses_category_when_present
  /usr/local/lib/python3.11/site-packages/django/core/handlers/base.py:61: UserWarning: No directory at: /app/staticfiles/
    mw_instance = middleware(adapted_handler)

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
================================================================================================== short test summary info ==================================================================================================
FAILED core/home/tests.py::TestGetScieloJournalsData::test_csv_download_filters_by_category - AssertionError: 'filename="health-sciences_2026-09-13.csv"' not found in 'attachment; filename="health_sciences_journals_2026-09-13.csv"'
FAILED core/home/tests.py::TestGetScieloJournalsData::test_xls_download_filename_uses_category_when_present - AssertionError: 'filename="health-sciences_2026-09-13.xls"' not found in 'attachment; filename="health_sciences_journals_2026-09-13.xls"'

Results (1.16s):
      11 passed
       2 failed
         - core/home/tests.py:155 TestGetScieloJournalsData.test_csv_download_filters_by_category
         - core/home/tests.py:195 TestGetScieloJournalsData.test_xls_download_filename_uses_category_when_present

(base) rafaeljpd@feeradesk-x3d:~/Repos/pi/scl/core$ 

Comment thread journal/models.py
return {
"title": title,
"scielo_url": self.scielo_url,
"owner": self.owner_name,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A terceira coluna do arquivo é apresentada como publisher, mas ela é preenchida com owner_name. Vi que isso já era assim.

Seria o caso de alterar para o campo publisher (publisher_names ou algo assim)?

Comment thread core/home/views.py
Comment on lines +75 to +78
if category:
category_code = slugs_to_category_code.get(category)
if category_code:
filters &= Q(journal__subject__code=category_code)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Se informar uma categoria inexistente, todos os journals são retornados.

Nada bloqueante.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Boa questão. Eu acho que não vejo problema em retornar todos os journals. O que você acha ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deixar como está.

@samuelveigarangel
samuelveigarangel merged commit bef16b5 into scieloorg:main Sep 15, 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