From 061663cf05323e91dde1911efa4f145dea046b06 Mon Sep 17 00:00:00 2001 From: Rossi-Luciano Date: Tue, 20 Jan 2026 10:25:33 -0300 Subject: [PATCH 1/5] =?UTF-8?q?feat(validacao):=20aprimora=20valida=C3=A7?= =?UTF-8?q?=C3=A3o=20de=20aff=20com=20novas=20regras=20e=20i18n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Ativa validações de orgdiv1/orgdiv2 (anteriormente comentadas) - Adiciona suporte para pesquisador autônomo (orgname não obrigatório) - Adiciona validação de email no texto original da afiliação - Implementa suporte i18n (advice_text/advice_params) em todas validações - Corrige cálculo de campos inválidos no método compare() - Adiciona docstrings e comentários para melhor documentação --- packtools/sps/validation/aff.py | 136 ++++++++++++++++++++++++++++++-- 1 file changed, 129 insertions(+), 7 deletions(-) diff --git a/packtools/sps/validation/aff.py b/packtools/sps/validation/aff.py index d45196b49..ea0d69372 100644 --- a/packtools/sps/validation/aff.py +++ b/packtools/sps/validation/aff.py @@ -39,6 +39,7 @@ def get_default_params(self): "country_code_error_level": "CRITICAL", "state_error_level": "WARNING", "city_error_level": "WARNING", + "email_in_original_error_level": "ERROR", "translation_aff_rules": { "id_error_level": "CRITICAL", "label_error_level": "ERROR", @@ -107,6 +108,12 @@ def validate_translations_consistency(self): "translation_count": len(trans_affs), "language": lang, }, + advice_text='Ensure translation has same number of affiliations ({expected_count}) as main text', + advice_params={ + "expected_count": len(main_affs), + "obtained_count": len(trans_affs), + "language": lang + } ) def validate_not_translation_affiliations(self): @@ -183,6 +190,7 @@ def get_default_params(self): "country_code_error_level": "CRITICAL", "state_error_level": "WARNING", "city_error_level": "WARNING", + "email_in_original_error_level": "ERROR", "translation_aff_rules": { "id_error_level": "CRITICAL", "label_error_level": "ERROR", @@ -206,12 +214,26 @@ def get_default_params(self): "country_code": 1, } } + @property def info(self): aff_id = self.affiliation.get("id") or self.affiliation.get("original") parent = self.affiliation.get("parent_id") or self.affiliation.get("parent") return f'({parent} - {aff_id})' - + + def is_autonomous_researcher(self): + """ + Check if affiliation is for an autonomous researcher. + + Returns + ------- + bool + True if original contains "Pesquisador Autônomo" (case insensitive) + """ + if not self.original: + return False + return "pesquisador autônomo" in self.original.lower() + def validate_original(self): error_level = self.params["original_error_level"] @@ -227,12 +249,18 @@ def validate_original(self): advice=f'Mark the complete original affiliation text with in for {self.original}', data=self.affiliation, error_level=error_level, + advice_text='Mark the complete original affiliation text with in ', + advice_params={} ) def validate_orgname(self): orgname = self.affiliation.get("orgname") error_level = self.params["orgname_error_level"] + # Pesquisador Autônomo não requer orgname + if self.is_autonomous_researcher(): + return + yield build_response( title="orgname", parent=self.affiliation, @@ -245,6 +273,8 @@ def validate_orgname(self): advice=f'Mark the main institution with in for {self.original}', data=self.affiliation, error_level=error_level, + advice_text='Mark the main institution with in for {original}', + advice_params={"original": self.original or ""} ) def validate_orgdiv1(self): @@ -263,6 +293,8 @@ def validate_orgdiv1(self): advice=f'Mark the first hierarchical subdivision with in for {self.original}', data=self.affiliation, error_level=error_level, + advice_text='Mark the first hierarchical subdivision with in for {original}', + advice_params={"original": self.original or ""} ) def validate_orgdiv2(self): @@ -281,6 +313,8 @@ def validate_orgdiv2(self): advice=f'Mark the second hierarchical subdivision with in for {self.original}', data=self.affiliation, error_level=error_level, + advice_text='Mark the second hierarchical subdivision with in for {original}', + advice_params={"original": self.original or ""} ) def validate_label(self): @@ -299,6 +333,8 @@ def validate_label(self): advice=f'Mark affiliation label with