Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
d9ae1ad
fix(journal): corrige Journal.get_registered para tratar ISSN print/e…
robertatakenaka Aug 10, 2026
10ae39d
feat(journal): adiciona JournalCollectionViewSet ao Wagtail admin
robertatakenaka Aug 10, 2026
537b461
chore(journal): adiciona pacote de testes journal/tests
robertatakenaka Aug 10, 2026
89d29b7
test(journal): adiciona testes para Journal.get_registered
robertatakenaka Aug 10, 2026
d4365d4
feat(proc): adiciona property journal_history em JournalProc
robertatakenaka Aug 10, 2026
b88da9b
refactor(proc): unifica get_or_fetch/ensure_proc_exists em BaseDataCh…
robertatakenaka Aug 10, 2026
a2d5d61
refactor(proc): renomeia ensure_*_proc_exists para ensure_*_data_is_u…
robertatakenaka Aug 10, 2026
4ec1e2f
chore(proc): adiciona pacote de testes proc/tests
robertatakenaka Aug 10, 2026
eb69780
test(proc): adiciona testes para source_core_api
robertatakenaka Aug 10, 2026
0c6faa8
feat(publication): adiciona translate_status e força status current
robertatakenaka Aug 10, 2026
84ffef2
refactor(publication): move cálculo de current_status para JournalPay…
robertatakenaka Aug 10, 2026
53e7c39
chore(publication): adiciona pacote de testes publication/tests
robertatakenaka Aug 10, 2026
30b4f26
test(publication): adiciona testes para translate_status, JournalPayl…
robertatakenaka Aug 10, 2026
5cf8141
test(publication): adiciona testes para build_journal
robertatakenaka Aug 10, 2026
aed78e2
Corrige o nome do campo collection__acron
robertatakenaka Aug 11, 2026
4f20254
refactor(upload): migra criacao de fasciculos para IssueDataChecker
robertatakenaka Aug 19, 2026
e8ec0c6
Move tests.py de journal, proc, publication para a subpasta respectiv…
robertatakenaka Aug 21, 2026
4aeef11
fix(publication): usar get_webpage_items(purpose=QA) e ampliar captur…
robertatakenaka Aug 21, 2026
64f45f3
test(publication): reescrever ArticleAvailabilityTest para o novo flu…
robertatakenaka Aug 21, 2026
e9b38e9
test(htmlxml): usar MagicMock com _meta para passar na checagem de co…
robertatakenaka Aug 21, 2026
7fc0484
test(migration): corrigir fixtures de paths para refletir source_path…
robertatakenaka Aug 21, 2026
59aa2f1
refactor(journal): simplificar OfficialJournal.get() usando Q(__in=) …
robertatakenaka Aug 21, 2026
df0bac7
feat(proc): processar location da API do Core e simplificar criação d…
robertatakenaka Aug 21, 2026
54d809d
fix(article): evitar mascarar erros inesperados na verificação de URL…
robertatakenaka Aug 24, 2026
bd22157
fix(publication): evitar mascarar erros inesperados na checagem de di…
robertatakenaka Aug 24, 2026
30eb9f7
refactor(journal): substituir Journal.is_complete por verificação dir…
robertatakenaka Aug 24, 2026
9c53cc0
feat(journal): permitir filtrar e visualizar periódicos incompletos n…
robertatakenaka Aug 24, 2026
78bbdd7
refactor(proc): distinguir explicitamente a origem do dado (local ou …
robertatakenaka Aug 24, 2026
ddf2f5f
test(proc): atualizar testes para o novo método is_local_or_remote
robertatakenaka Aug 24, 2026
340ac84
fix(publication): republicar periódico na Core quando houver campos o…
robertatakenaka Aug 24, 2026
bc790b6
test(publication): atualizar testes de publish_journal para o novo cr…
robertatakenaka Aug 24, 2026
75d9c58
Corrige atribuição incorreta de parâmetro na consulta de OfficialJournal
robertatakenaka Aug 25, 2026
1987bbc
Corrige filtro de completude de periódicos no admin do Wagtail
robertatakenaka Aug 25, 2026
f9add33
Atualiza testes de is_local_or_remote para refletir retorno textual
robertatakenaka Aug 25, 2026
9149070
Corrige test_source_core_api
robertatakenaka Aug 26, 2026
bcb1939
Corrige upload/test_controller
robertatakenaka Aug 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions article/page_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from difflib import SequenceMatcher
from html import unescape

from core.utils.requester import fetch_data
from core.utils.requester import fetch_data, NonRetryableError, RetryableError


# Threshold de similaridade para considerar "encontrado"
Expand Down Expand Up @@ -39,7 +39,7 @@ def check_url(url, timeout):
raise ValueError("check_page_url_and_content: URL is required for availability check.")
content = fetch_data(url, timeout=timeout or 30)
return {"content": content}
except Exception as e:
except (NonRetryableError, RetryableError) as e:
return {"error": str(e), "function": "check_url"}


Expand Down
5 changes: 3 additions & 2 deletions htmlxml/test_models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import logging
from unittest.mock import Mock, patch
from unittest.mock import Mock, patch, MagicMock

from django.contrib.auth import get_user_model
from django.test import TestCase
Expand Down Expand Up @@ -111,7 +111,8 @@ def test_get_raises_value_error_without_migrated_article(self):

def test_get_raises_does_not_exist_when_no_record_found(self):
"""Test that get() raises DoesNotExist when no record is found."""
mock_article = Mock(spec=MigratedArticle)
mock_article = MagicMock(spec=MigratedArticle)
mock_article._meta = MigratedArticle._meta # Pass Django model compatibility check

with self.assertRaises(HTMLXML.DoesNotExist):
HTMLXML.get(migrated_article=mock_article)
104 changes: 60 additions & 44 deletions journal/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,34 +170,33 @@ def data(self):

@classmethod
def get(cls, issn_print=None, issn_electronic=None, issnl=None, title=None):
issns = []
params = {}
if issn_electronic:
issns.append(issn_electronic)
params["issn_electronic"] = issn_electronic
if issn_print:
issns.append(issn_print)
params["issn_print"] = issn_print
if issnl:
issns.append(issnl)
params["issnl"] = issnl
if not params:
if not issns:
raise ValueError(
f"OfficialJournal.get requires issn_print, issn_electronic, issnl"
)

try:
return cls.objects.get(**params)
except cls.DoesNotExist:
pass
except cls.MultipleObjectsReturned:
return cls.objects.filter(**params).order_by("-updated").first()
except cls.DoesNotExist:
qs = Q()
if issn_electronic:
qs |= Q(issn_electronic=issn_electronic)
if issn_print:
qs |= Q(issn_print=issn_print)
if issnl:
qs |= Q(issnl=issnl)
obj = cls.objects.filter(qs).order_by("-updated").first()
if not obj:
raise
return obj

qs = Q(issnl__in=issns) | Q(issn_electronic__in=issns) | Q(issn_print__in=issns)
try:
return cls.objects.get(qs)
except cls.MultipleObjectsReturned:
return cls.objects.filter(qs).order_by("-updated").first()

@classmethod
def create_or_update(
Expand Down Expand Up @@ -323,14 +322,10 @@ def issn_electronic(self):

@property
def collections(self):
from collection.models import Collection

return Collection.objects.filter(journalproc__journal=self).distinct()

@property
def collections_acron(self):
from collection.models import Collection

return list(
Collection.objects.filter(journalproc__journal=self)
.values_list("acron", flat=True)
Expand All @@ -340,8 +335,6 @@ def collections_acron(self):

@property
def collections_name(self):
from collection.models import Collection

return list(
Collection.objects.filter(journalproc__journal=self)
.values_list("name", flat=True)
Expand Down Expand Up @@ -378,20 +371,37 @@ def get_registered(journal_title, issn_electronic, issn_print):
official_journal__issn_print=issn_print,
)
except Journal.DoesNotExist:
raise Journal.DoesNotExist(
{
"journal_title": journal_title,
"issn_electronic": issn_electronic,
"issn_print": issn_print,
}
)
try:
# corrige bug por ter troca print por electronic e vice-versa
return Journal.objects.get(
official_journal__issn_electronic=issn_print,
official_journal__issn_print=issn_electronic,
)
except Journal.MultipleObjectsReturned:
return Journal.objects.filter(
official_journal__issn_electronic=issn_print,
official_journal__issn_print=issn_electronic,
).order_by("-updated").first()
except Journal.DoesNotExist:
issns = set()
if issn_electronic:
issns.add(issn_electronic)
if issn_print:
issns.add(issn_print)
journal = Journal.objects.filter(
Q(official_journal__issn_electronic__in=issns) |
Q(official_journal__issn_print__in=issns),
).order_by("-updated").first()
if journal:
return journal
raise Journal.DoesNotExist
except Journal.MultipleObjectsReturned:
return (
Journal.objects.filter(
Q(official_journal__issn_electronic=issn_electronic)
| Q(official_journal__issn_print=issn_print)
official_journal__issn_electronic=issn_electronic,
official_journal__issn_print=issn_print,
)
.order_by("-created")
.order_by("-updated")
.first()
)

Expand Down Expand Up @@ -445,7 +455,7 @@ def create_or_update(
obj.official_journal = official_journal or obj.official_journal
obj.title = title or obj.title
obj.short_title = short_title or obj.short_title
obj.journal_acron = journal_acron
obj.journal_acron = journal_acron or obj.journal_acron
obj.save()
return obj
except cls.DoesNotExist:
Expand Down Expand Up @@ -617,20 +627,20 @@ def subject_areas(self):
@property
def missing_fields(self):
"""
Verifica campos não preenchidos no Journal e retorna um relatório detalhado.
Verifica ausência de campos relevantes para o site público
"""
fields = {
"title": _("Journal Title"),
"short_title": _("Short Title"),
"journal_acron": _("Journal Acronym"),
"official_journal": _("Official Journal"),
"contact_name": _("Contact Name"),
"contact_address": _("Contact Address"),
"contact_location": _("Contact Location"),
"submission_online_url": _("Submission Online URL"),
"logo_url": _("Logo URL"),
"license_code": _("License Code"),
"wos_areas": _("WoS Areas"),
"journal_acron": _("Journal acronym"),
}
missing = []
for field, description in fields.items():
Expand All @@ -640,12 +650,13 @@ def missing_fields(self):

# Verificar official_journal
if self.official_journal:
if not self.official_journal.issn_electronic:
if not self.official_journal.issn_electronic and not self.official_journal.issn_print:
missing.append(_("Electronic ISSN"))
if not self.official_journal.issn_print:
missing.append(_("Print ISSN"))
if not self.official_journal.title_iso:
missing.append(_("ISO Title"))
else:
missing.append(_("Official Journal"))

# Verificar mission
if not self.mission.exists():
Expand All @@ -656,17 +667,24 @@ def missing_fields(self):
missing.append(_("sponsor"))

# Verificar owner
if not self.owner.exists():
if not self.owner.exists() and not self.publisher.exists():
missing.append(_("owner"))

# Verificar publisher
if not self.publisher.exists():
missing.append(_("publisher"))

# Verificar subject
if not self.subject.exists():
missing.append(_("study area"))

for collection in self.collections:
if not JournalHistory.objects.filter(
journal_collection__journal=self,
journal_collection__collection=collection,
).exists():
missing.append(_("history for {}").format(collection))

if len(self.collections) == 0:
missing.append(_("Journal collection"))

return missing


Expand Down Expand Up @@ -907,8 +925,7 @@ class JournalCollection(CommonControlField, ClusterableModel):
base_form_class = CoreAdminModelForm

panels = [
AutocompletePanel("journal"),
AutocompletePanel("collection"),
InlinePanel("journal_history", label=_("Journal history"))
]

class Meta:
Expand Down Expand Up @@ -943,9 +960,7 @@ def create(cls, user, collection, journal):
@classmethod
def create_or_update(cls, user, collection, journal):
try:
obj = cls.get(collection, journal)
obj.updated_by = obj.updated_by or user
obj.save()
return cls.get(collection, journal)
except cls.DoesNotExist:
return cls.create(user, collection, journal)

Expand Down Expand Up @@ -1063,6 +1078,7 @@ def create_or_update(
obj.interruption_reason = interruption_reason
obj.updated_by = obj.updated_by or user
obj.save()
return obj
except cls.DoesNotExist:
return cls.create(
user,
Expand Down
Empty file added journal/tests/__init__.py

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.

Ao executar os testes com make django_test compose=local.yml, a descoberta falha porque a app contém simultaneamente o arquivo tests.py e o pacote tests/ criado neste PR. Ambos correspondem ao mesmo módulo Python.

Sugiro mover o conteúdo de tests.py para dentro de tests/, usando um nome específico, e remover o arquivo original. Embora tests.py seja anterior ao PR, a criação do diretório introduziu a colisão e impede a execução automática da suíte.

O mesmo problema ocorre nas apps proc e publication.

Empty file.
Loading