From 89cbd321e2fdddacfd7abadaef7d2e1c5e6c706b Mon Sep 17 00:00:00 2001 From: Samuel Veiga Rangel Date: Thu, 6 Mar 2025 23:00:26 -0300 Subject: [PATCH 01/19] Altera modelagem de EditorialBoardMember para incluir no formulario de Journal --- editorialboard/models.py | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/editorialboard/models.py b/editorialboard/models.py index 06c0fe9be..a4ca44abc 100644 --- a/editorialboard/models.py +++ b/editorialboard/models.py @@ -140,16 +140,13 @@ def create( ) -class EditorialBoardMember(CommonControlField, Orderable): - editorial_board = ParentalKey( - EditorialBoard, related_name="editorial_board_member" +class EditorialBoardMember(CommonControlField, ClusterableModel, Orderable): + journal = ParentalKey( + Journal, related_name="editorial_board_member_journal", null=True ) researcher = models.ForeignKey( Researcher, null=True, blank=True, related_name="+", on_delete=models.SET_NULL ) - role = models.ForeignKey( - "RoleModel", null=True, blank=True, related_name="+", on_delete=models.SET_NULL - ) image = models.ForeignKey( "wagtailimages.Image", null=True, @@ -159,14 +156,14 @@ class EditorialBoardMember(CommonControlField, Orderable): help_text=_("Upload a profile photo of the editorial board member."), ) area = models.TextField(null=True, blank=True) + class Meta: - unique_together = [("editorial_board", "researcher", "role")] + unique_together = [("journal", "researcher")] panels = [ AutocompletePanel("researcher"), - AutocompletePanel("role"), FieldPanel("image"), - # AutocompletePanel("editorial_board", read_only=True), + InlinePanel("role_editorial_board", label=_("Role")), ] base_form_class = CoreAdminModelForm @@ -430,6 +427,22 @@ def _create_or_update_journal(journal_title): logging.info(f"EditorialBoard {journal_title} {e}") +class RoleEditorialBoard(CommonControlField, Orderable): + editorial_board = ParentalKey( + EditorialBoardMember, related_name="role_editorial_board" + ) + role = models.ForeignKey( + "RoleModel", null=True, blank=True, related_name="+", on_delete=models.SET_NULL + ) + initial_year = models.CharField(max_length=4, blank=True, null=True) + final_year = models.CharField(max_length=4, blank=True, null=True) + + panels = [ + AutocompletePanel("role"), + FieldPanel("initial_year"), + FieldPanel("final_year"), + ] + class EditorialBoardMemberFile(models.Model): attachment = models.ForeignKey( "wagtaildocs.Document", From 90effe2a24ce1a4515aca09454f278d01fee8108 Mon Sep 17 00:00:00 2001 From: Samuel Veiga Rangel Date: Thu, 6 Mar 2025 23:04:01 -0300 Subject: [PATCH 02/19] Reaproveita os metodos de Researcher --- editorialboard/models.py | 53 ++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/editorialboard/models.py b/editorialboard/models.py index a4ca44abc..1d3fd2d16 100644 --- a/editorialboard/models.py +++ b/editorialboard/models.py @@ -191,7 +191,7 @@ def _get( params = dict( editorial_board=editorial_board, researcher=researcher, - role=role, + role_editorial_board__role=role, ) logging.info(params) if role and researcher: @@ -273,30 +273,30 @@ def create_or_update( editorial_board_final_year=None, ): if not researcher: - researcher = EditorialBoardMember._create_or_update_researcher( - user, - given_names, - last_name, - suffix, - declared_person_name, - lattes, - orcid, - email, - gender_code, - gender_identification_status, - institution_name, - institution_div1, - institution_div2, - institution_city_name, - institution_country_text, - institution_country_acronym, - institution_country_name, - institution_state_text, - institution_state_acronym, - institution_state_name, + researcher = Researcher.create_or_update( + user=user, + given_names=given_names, + last_name=last_name, + declared_name=declared_person_name, + suffix=suffix, + lattes=lattes, + orcid=orcid, + email=email, + aff_name=institution_name, + aff_div1=institution_div1, + aff_div2=institution_div2, + aff_city_name=institution_city_name, + aff_country_text=institution_country_text, + aff_country_acronym=institution_country_acronym, + aff_country_name=institution_country_name, + aff_state_text=institution_state_text, + aff_state_acronym=institution_state_acronym, + aff_state_name=institution_state_name, + gender=gender_code, + gender_identification_status=gender_identification_status, ) if not journal: - journal = EditorialBoardMember._create_or_update_journal(journal_title) + journal = EditorialBoardMember._get_journal(journal_title=journal_title) editorial_board = EditorialBoard.create_or_update( user, @@ -414,15 +414,14 @@ def _create_or_update_location( logging.exception(e) return - @staticmethod - def _create_or_update_journal(journal_title): + @classmethod + def _get_journal(cls, journal_title): try: journal_title = journal_title and journal_title.strip() - return Journal.objects.get( + return cls.objects.get( Q(title__icontains=journal_title) | Q(official__title__icontains=journal_title) ) - logging.info(f"EditorialBoard {journal_title} OK") except Journal.DoesNotExist as e: logging.info(f"EditorialBoard {journal_title} {e}") From 083b0aaa836bbd31d5c1b73cacab021502d6e55e Mon Sep 17 00:00:00 2001 From: Samuel Veiga Rangel Date: Thu, 6 Mar 2025 23:05:07 -0300 Subject: [PATCH 03/19] Remove metodos que ja tratam os dados nos metodos de Researcher --- editorialboard/models.py | 101 --------------------------------------- 1 file changed, 101 deletions(-) diff --git a/editorialboard/models.py b/editorialboard/models.py index 1d3fd2d16..a62b8fe5b 100644 --- a/editorialboard/models.py +++ b/editorialboard/models.py @@ -313,107 +313,6 @@ def create_or_update( return cls._create_or_update(user, editorial_board, researcher, role) - @staticmethod - def _create_or_update_researcher( - user, - given_names=None, - last_name=None, - suffix=None, - declared_person_name=None, - lattes=None, - orcid=None, - email=None, - gender_code=None, - gender_identification_status=None, - institution_name=None, - institution_div1=None, - institution_div2=None, - institution_city_name=None, - institution_country_text=None, - institution_country_acronym=None, - institution_country_name=None, - institution_state_text=None, - institution_state_acronym=None, - institution_state_name=None, - ): - location = EditorialBoardMember._create_or_update_location( - user, - institution_city_name, - institution_country_text, - institution_country_acronym, - institution_country_name, - institution_state_text, - institution_state_acronym, - institution_state_name, - ) - affiliation = Affiliation.create_or_update( - user, - name=institution_name, - acronym=None, - level_1=institution_div1, - level_2=institution_div2, - level_3=None, - location=location, - official=None, - is_official=None, - url=None, - institution_type=None, - ) - gender = Gender.create_or_update(user, code=gender_code, gender=gender_code) - return Researcher.create_or_update( - user, - given_names=given_names, - last_name=last_name, - suffix=suffix, - declared_name=declared_person_name, - affiliation=affiliation, - year=None, - orcid=orcid, - lattes=lattes, - other_ids=None, - email=email, - gender=gender, - gender_identification_status=gender_identification_status, - ) - - @staticmethod - def _create_or_update_location( - user, - city_name=None, - country_text=None, - country_acronym=None, - country_name=None, - state_text=None, - state_acronym=None, - state_name=None, - ): - state = None - country = None - if state_text: - for item in State.standardize(state_text, user): - state = item.get("state") - if country_text: - for item in Country.standardize(country_text, user): - country = item.get("country") - - try: - return Location.create_or_update( - user, - country=country, - country_name=country_name, - country_acron3=None, - country_acronym=country_acronym, - state=state, - state_name=state_name, - state_acronym=state_acronym, - city=None, - city_name=city_name, - lang=None, - ) - except Exception as e: - logging.exception(e) - return - @classmethod def _get_journal(cls, journal_title): try: From 48e1b4166c4da724db0d6acb670a147b6a4d665c Mon Sep 17 00:00:00 2001 From: Samuel Veiga Rangel Date: Thu, 6 Mar 2025 23:05:37 -0300 Subject: [PATCH 04/19] Remove paramentros inutilizaveis --- editorialboard/models.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/editorialboard/models.py b/editorialboard/models.py index a62b8fe5b..9af462140 100644 --- a/editorialboard/models.py +++ b/editorialboard/models.py @@ -265,10 +265,6 @@ def create_or_update( institution_state_name=None, declared_role=None, std_role=None, - member_activity_initial_year=None, - member_activity_final_year=None, - member_activity_initial_month=None, - member_activity_final_month=None, editorial_board_initial_year=None, editorial_board_final_year=None, ): From 263466384579332b0744c19318549d8a50d2d95a Mon Sep 17 00:00:00 2001 From: Samuel Veiga Rangel Date: Fri, 7 Mar 2025 01:58:57 -0300 Subject: [PATCH 05/19] Modifica testes para modelagem nova de EditorialBoardMember. --- editorialboard/tests.py | 149 +++++++++++++++------------------------- 1 file changed, 55 insertions(+), 94 deletions(-) diff --git a/editorialboard/tests.py b/editorialboard/tests.py index c82559ecd..5d018cc5e 100644 --- a/editorialboard/tests.py +++ b/editorialboard/tests.py @@ -5,13 +5,12 @@ # Create your tests here. +from core.models import Gender +from location.models import Location from editorialboard.models import ( EditorialBoardMember, - EditorialBoardMemberActivity, - EditorialBoardRole, - EditorialBoard, ) -from researcher.models import ResearcherAKA +from researcher.models import ResearcherAKA, Researcher from journal.models import Journal @@ -22,12 +21,33 @@ class EditorialBoardMemberTest(TestCase): def setUp(self): self.user = User.objects.create(username="user") self.journal = Journal.objects.create(title="Revista XXXX") - logging.info(self.journal.title) - logging.info(self.user) + self.gender = Gender.create_or_update(user=self.user, code="F", gender="F") + self.researcher = Researcher.create_or_update( + self.user, + given_names=None, + last_name="Taomeaome", + suffix=None, + declared_name="Anna Taomeaome", + lattes="qwertpoiuytkdiekd", + orcid="1234-1234-0987-0987", + email="user@dom.org", + gender=self.gender, + gender_identification_status="DECLARED", + aff_name="Universidade Federal de São Carlos", + aff_div1=None, + aff_div2=None, + aff_city_name="São Carlos", + aff_country_text="Brasil", + aff_country_acronym=None, + aff_country_name=None, + aff_state_text="São Paulo", + aff_state_acronym=None, + aff_state_name=None, + ) def test__create_or_update_location(self): - location = EditorialBoardMember._create_or_update_location( + location = Location.create_or_update( self.user, city_name="Campinas", country_text="Brasil", @@ -42,123 +62,64 @@ def test__create_or_update_location(self): self.assertEqual("SP", location.state.acronym) def test_create_or_update_researcher(self): - - researcher = EditorialBoardMember._create_or_update_researcher( - self.user, - given_names=None, - last_name=None, - suffix=None, - declared_person_name="Anna Taomeaome", - lattes="qwertpoiuytkdiekd", - orcid="1234-1234-0987-0987", - email="user@dom.org", - gender_code="F", - gender_identification_status="DECLARED", - institution_name="Universidade Federal de São Carlos", - institution_div1=None, - institution_div2=None, - institution_city_name="São Carlos", - institution_country_text="Brasil", - institution_country_acronym=None, - institution_country_name=None, - institution_state_text="São Paulo", - institution_state_acronym=None, - institution_state_name=None, + editorial_board_member = EditorialBoardMember.create_or_update( + user=self.user, + researcher=self.researcher, + journal=self.journal, + declared_role="editor de seção", + std_role=None, + editorial_board_initial_year="2010", + editorial_board_final_year="2012", ) self.assertEqual( - "São Paulo", researcher.affiliation.institution.location.state.name + "São Paulo", editorial_board_member.researcher.affiliation.institution.location.state.name ) self.assertEqual( - "São Carlos", researcher.affiliation.institution.location.city.name + "São Carlos", editorial_board_member.researcher.affiliation.institution.location.city.name ) self.assertEqual( - "Brasil", researcher.affiliation.institution.location.country.name + "Brasil", editorial_board_member.researcher.affiliation.institution.location.country.name ) self.assertEqual( "Universidade Federal de São Carlos", - researcher.affiliation.institution.institution_identification.name, + editorial_board_member.researcher.affiliation.institution.institution_identification.name, ) - self.assertEqual("F", researcher.person_name.gender.code) - self.assertEqual("F", researcher.person_name.gender.gender) + self.assertEqual("F", editorial_board_member.researcher.person_name.gender.code) + self.assertEqual("F", editorial_board_member.researcher.person_name.gender.gender) self.assertEqual( - "DECLARED", researcher.person_name.gender_identification_status + "DECLARED", editorial_board_member.researcher.person_name.gender_identification_status ) - self.assertEqual("Anna Taomeaome", researcher.person_name.declared_name) + self.assertEqual("Anna Taomeaome", editorial_board_member.researcher.person_name.declared_name) self.assertEqual( "qwertpoiuytkdiekd", ResearcherAKA.objects.get( - researcher=researcher, researcher_identifier__source_name="LATTES" + researcher=editorial_board_member.researcher, researcher_identifier__source_name="LATTES" ).researcher_identifier.identifier, ) self.assertEqual( "1234-1234-0987-0987", ResearcherAKA.objects.get( - researcher=researcher, researcher_identifier__source_name="ORCID" + researcher=editorial_board_member.researcher, researcher_identifier__source_name="ORCID" ).researcher_identifier.identifier, ) self.assertEqual( "user@dom.org", ResearcherAKA.objects.get( - researcher=researcher, researcher_identifier__source_name="EMAIL" + researcher=editorial_board_member.researcher, researcher_identifier__source_name="EMAIL" ).researcher_identifier.identifier, ) - def test_create_or_update(self): - member = EditorialBoardMember.create_or_update( - self.user, - researcher=None, - journal=None, - journal_title="Revista XXXX", - given_names=None, - last_name=None, - suffix=None, - declared_person_name="Anna Taomeaome", - lattes="qwertpoiuytkdiekd", - orcid="1234-1234-0987-0987", - email="user@dom.org", - gender_code="F", - gender_identification_status="DECLARED", - institution_name="Universidade Federal de São Carlos", - institution_div1=None, - institution_div2=None, - institution_city_name="São Carlos", - institution_country_text="Brasil", - institution_country_acronym=None, - institution_country_name=None, - institution_state_text="São Paulo", - institution_state_acronym=None, - institution_state_name=None, + def test_editorial_board_member_create_or_update(self): + editorial_board = EditorialBoardMember.create_or_update( + user=self.user, + journal=self.journal, + researcher=self.researcher, declared_role="editor de seção", - std_role=None, - member_activity_initial_year="2000", - member_activity_final_year="2010", - member_activity_initial_month="01", - member_activity_final_month="12", editorial_board_initial_year="2010", editorial_board_final_year="2012", ) - - self.assertEqual( - "2000", - EditorialBoardMemberActivity.objects.get( - member=member, - role__declared_role="editor de seção", - initial_year="2000", - ).initial_year, - ) - self.assertEqual( - "2010", EditorialBoard.objects.get(journal=self.journal).initial_year - ) - self.assertEqual( - "2012", EditorialBoard.objects.get(journal=self.journal).final_year - ) - - for item in EditorialBoardRole.objects.get( - editorial_board__journal=self.journal, - role__std_role="associate editor", - ).members.all(): - with self.subTest(item): - self.assertEqual( - "Anna Taomeaome", item.researcher.person_name.declared_name - ) + self.assertEqual(self.researcher, editorial_board.researcher) + self.assertEqual("Revista XXXX", editorial_board.journal.title) + self.assertEqual(1, EditorialBoardMember.objects.get(journal=self.journal).role_editorial_board.count()) + self.assertEqual("editor de seção", EditorialBoardMember.objects.get(journal=self.journal).role_editorial_board.first().role.declared_role) From 556c83aa25b252768edf63b04d50e630b6bf3026 Mon Sep 17 00:00:00 2001 From: Samuel Veiga Rangel Date: Fri, 7 Mar 2025 02:00:11 -0300 Subject: [PATCH 06/19] Modifica metodos de EditorialBoardMember e cria metodos de RoleEditorialBoard --- editorialboard/models.py | 160 +++++++++++++++++++-------------------- 1 file changed, 79 insertions(+), 81 deletions(-) diff --git a/editorialboard/models.py b/editorialboard/models.py index 9af462140..1bd0b5d00 100644 --- a/editorialboard/models.py +++ b/editorialboard/models.py @@ -184,58 +184,49 @@ def autocomplete_label(self): @classmethod def _get( cls, - editorial_board, + journal, researcher, - role, ): params = dict( - editorial_board=editorial_board, + journal=journal, researcher=researcher, - role_editorial_board__role=role, ) - logging.info(params) - if role and researcher: - try: + if researcher and journal: return cls.objects.get(**params) - except cls.MultipleObjectsReturned: - return cls.objects.filter(*params).first() - raise ValueError("EditorialBoardMember._get requires editorial_board and researcher and role") + raise ValueError("EditorialBoardMember._get requires journal and researcher and role") @classmethod def _create( cls, user, + journal, researcher, - editorial_board, - role, ): - if role and researcher and editorial_board: + if researcher and journal: try: obj = cls() obj.creator = user - obj.editorial_board = editorial_board + obj.journal = journal obj.researcher = researcher - obj.role = role obj.save() return obj except IntegrityError: - return cls._get(editorial_board, researcher, role) - raise ValueError("EditorialBoardMember._create requires editorial_board and researcher and role") + return cls._get(journal, researcher) + raise ValueError("EditorialBoardMember._create requires journal and researcher and role") @classmethod def _create_or_update( cls, user, - editorial_board, - researcher, - role, + journal, + researcher, ): - if role and researcher and editorial_board: + if researcher and journal: try: - return cls._get(editorial_board, researcher, role) + return cls._get(journal, researcher) except cls.DoesNotExist: - return cls._create(user, editorial_board, researcher, role) - raise ValueError("EditorialBoardMember._create requires editorial_board and researcher and journal") + return cls._create(user, journal, researcher) + raise ValueError("EditorialBoardMember._create requires journal and researcher and journal") @classmethod def create_or_update( @@ -243,77 +234,36 @@ def create_or_update( user, researcher=None, journal=None, - journal_title=None, - given_names=None, - last_name=None, - suffix=None, - declared_person_name=None, - lattes=None, - orcid=None, - email=None, - gender_code=None, - gender_identification_status=None, - institution_name=None, - institution_div1=None, - institution_div2=None, - institution_city_name=None, - institution_country_text=None, - institution_country_acronym=None, - institution_country_name=None, - institution_state_text=None, - institution_state_acronym=None, - institution_state_name=None, declared_role=None, std_role=None, editorial_board_initial_year=None, editorial_board_final_year=None, ): - if not researcher: - researcher = Researcher.create_or_update( - user=user, - given_names=given_names, - last_name=last_name, - declared_name=declared_person_name, - suffix=suffix, - lattes=lattes, - orcid=orcid, - email=email, - aff_name=institution_name, - aff_div1=institution_div1, - aff_div2=institution_div2, - aff_city_name=institution_city_name, - aff_country_text=institution_country_text, - aff_country_acronym=institution_country_acronym, - aff_country_name=institution_country_name, - aff_state_text=institution_state_text, - aff_state_acronym=institution_state_acronym, - aff_state_name=institution_state_name, - gender=gender_code, - gender_identification_status=gender_identification_status, - ) - if not journal: - journal = EditorialBoardMember._get_journal(journal_title=journal_title) - - editorial_board = EditorialBoard.create_or_update( - user, - journal, - editorial_board_initial_year, - editorial_board_final_year, - ) - + role = None if std_role or declared_role: role = RoleModel.create_or_update( user, std_role=std_role, declared_role=declared_role ) + editorial_board_member = EditorialBoardMember._create_or_update( + user, + journal, + researcher, + ) - return cls._create_or_update(user, editorial_board, researcher, role) + role_editorial_board = RoleEditorialBoard.create_or_update( + editorial_board_member, + role, + editorial_board_initial_year, + editorial_board_final_year, + ) + return editorial_board_member - @classmethod - def _get_journal(cls, journal_title): + @staticmethod + def _get_journal(journal_title): try: journal_title = journal_title and journal_title.strip() - return cls.objects.get( + return Journal.objects.get( Q(title__icontains=journal_title) | Q(official__title__icontains=journal_title) ) @@ -337,6 +287,54 @@ class RoleEditorialBoard(CommonControlField, Orderable): FieldPanel("final_year"), ] + @classmethod + def get( + cls, + editorial_board_member, + role, + initial_year, + final_year, + ): + params = dict( + editorial_board=editorial_board_member, + role=role, + initial_year=initial_year, + final_year=final_year, + ) + if editorial_board_member and role: + return cls.objects.get(**params) + raise ValueError("RoleEditorialBoard.get requires editorial_board_member and role") + + @classmethod + def create( + cls, + editorial_board_member, + role, + initial_year, + final_year, + ): + obj = cls() + obj.editorial_board = editorial_board_member + obj.role = role + obj.initial_year = initial_year + obj.final_year = final_year + obj.save() + return obj + + @classmethod + def create_or_update( + cls, + editorial_board_member, + role, + initial_year, + final_year, + ): + try: + return cls.get(editorial_board_member, role, initial_year, final_year) + except cls.DoesNotExist: + return cls.create(editorial_board_member, role, initial_year, final_year) + + class EditorialBoardMemberFile(models.Model): attachment = models.ForeignKey( "wagtaildocs.Document", From 6d7e8218a7303ac107525b75a8b29722d3d5efe8 Mon Sep 17 00:00:00 2001 From: Samuel Veiga Rangel Date: Fri, 7 Mar 2025 02:00:42 -0300 Subject: [PATCH 07/19] Inclui painel de EditorialBoardMember no formulario de Journal --- journal/models.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/journal/models.py b/journal/models.py index f95e10cb7..9518a0ec2 100755 --- a/journal/models.py +++ b/journal/models.py @@ -777,6 +777,10 @@ def autocomplete_label(self): AutocompletePanel("abstract_language"), ] + panels_editorial_board = [ + InlinePanel("editorial_board_member_journal", label=_("Editorial Board")), + ] + edit_handler = TabbedInterface( [ ObjectList(panels_titles, heading=_("Titles")), @@ -792,6 +796,7 @@ def autocomplete_label(self): ObjectList( panels_instructions_for_authors, heading=_("Instructions for Authors") ), + ObjectList(panels_editorial_board, heading=_("Editorial Board")), ] ) From f65560251e4e865857d8190dd8f9e0685c13e27b Mon Sep 17 00:00:00 2001 From: Samuel Veiga Rangel Date: Fri, 7 Mar 2025 02:01:38 -0300 Subject: [PATCH 08/19] Migracao --- ...ialboardmember_unique_together_and_more.py | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 editorialboard/migrations/0005_alter_editorialboardmember_unique_together_and_more.py diff --git a/editorialboard/migrations/0005_alter_editorialboardmember_unique_together_and_more.py b/editorialboard/migrations/0005_alter_editorialboardmember_unique_together_and_more.py new file mode 100644 index 000000000..63f4cb95d --- /dev/null +++ b/editorialboard/migrations/0005_alter_editorialboardmember_unique_together_and_more.py @@ -0,0 +1,117 @@ +# Generated by Django 5.0.8 on 2025-03-07 05:01 + +import django.db.models.deletion +import modelcluster.fields +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("editorialboard", "0004_editorialboardmember_image"), + ("journal", "0029_alter_scielojournal_journal_acron"), + ("researcher", "0004_alter_institutionalauthor_unique_together"), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.AlterUniqueTogether( + name="editorialboardmember", + unique_together={("journal", "researcher")}, + ), + migrations.AddField( + model_name="editorialboardmember", + name="journal", + field=modelcluster.fields.ParentalKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="editorial_board_member_journal", + to="journal.journal", + ), + ), + migrations.CreateModel( + name="RoleEditorialBoard", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "sort_order", + models.IntegerField(blank=True, editable=False, null=True), + ), + ( + "created", + models.DateTimeField( + auto_now_add=True, verbose_name="Creation date" + ), + ), + ( + "updated", + models.DateTimeField( + auto_now=True, verbose_name="Last update date" + ), + ), + ("initial_year", models.CharField(blank=True, max_length=4, null=True)), + ("final_year", models.CharField(blank=True, max_length=4, null=True)), + ( + "creator", + models.ForeignKey( + editable=False, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="%(class)s_creator", + to=settings.AUTH_USER_MODEL, + verbose_name="Creator", + ), + ), + ( + "editorial_board", + modelcluster.fields.ParentalKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="role_editorial_board", + to="editorialboard.editorialboardmember", + ), + ), + ( + "role", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="editorialboard.rolemodel", + ), + ), + ( + "updated_by", + models.ForeignKey( + blank=True, + editable=False, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="%(class)s_last_mod_user", + to=settings.AUTH_USER_MODEL, + verbose_name="Updater", + ), + ), + ], + options={ + "abstract": False, + }, + ), + migrations.RemoveField( + model_name="editorialboardmember", + name="editorial_board", + ), + migrations.RemoveField( + model_name="editorialboardmember", + name="role", + ), + ] From b4dc707da0e7329506800821a6e94ad702518cf7 Mon Sep 17 00:00:00 2001 From: Samuel Veiga Rangel Date: Wed, 12 Mar 2025 14:15:32 -0300 Subject: [PATCH 09/19] Altera ordem de criacao de AlterUniqueTogether --- ...alter_editorialboardmember_unique_together_and_more.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/editorialboard/migrations/0005_alter_editorialboardmember_unique_together_and_more.py b/editorialboard/migrations/0005_alter_editorialboardmember_unique_together_and_more.py index 63f4cb95d..42b9f03b3 100644 --- a/editorialboard/migrations/0005_alter_editorialboardmember_unique_together_and_more.py +++ b/editorialboard/migrations/0005_alter_editorialboardmember_unique_together_and_more.py @@ -16,10 +16,6 @@ class Migration(migrations.Migration): ] operations = [ - migrations.AlterUniqueTogether( - name="editorialboardmember", - unique_together={("journal", "researcher")}, - ), migrations.AddField( model_name="editorialboardmember", name="journal", @@ -30,6 +26,10 @@ class Migration(migrations.Migration): to="journal.journal", ), ), + migrations.AlterUniqueTogether( + name="editorialboardmember", + unique_together={("journal", "researcher")}, + ), migrations.CreateModel( name="RoleEditorialBoard", fields=[ From c88cfc0196bec94d68bc85407cc19e9a487986e2 Mon Sep 17 00:00:00 2001 From: Samuel Veiga Rangel Date: Wed, 19 Mar 2025 20:38:54 -0300 Subject: [PATCH 10/19] Remove modelo inutilizavel --- editorialboard/models.py | 119 --------------------------------------- 1 file changed, 119 deletions(-) diff --git a/editorialboard/models.py b/editorialboard/models.py index 1bd0b5d00..c879bcee2 100644 --- a/editorialboard/models.py +++ b/editorialboard/models.py @@ -21,125 +21,6 @@ from . import choices -class EditorialBoard(CommonControlField, ClusterableModel): - journal = models.ForeignKey( - Journal, null=True, blank=True, related_name="+", on_delete=models.SET_NULL - ) - initial_year = models.CharField(max_length=4, blank=True, null=True) - final_year = models.CharField(max_length=4, blank=True, null=True) - - autocomplete_search_field = "journal__title" - - def autocomplete_label(self): - return str(self) - - class Meta: - unique_together = [("journal", "initial_year", "final_year")] - - indexes = [ - models.Index( - fields=[ - "initial_year", - ] - ), - models.Index( - fields=[ - "final_year", - ] - ), - ] - - panels = [ - AutocompletePanel("journal"), - FieldPanel("initial_year"), - FieldPanel("final_year"), - InlinePanel("editorial_board_member", label=_("Member")), - ] - base_form_class = CoreAdminModelForm - - def __str__(self): - return f"{self.journal} {self.initial_year}-{self.final_year}" - - - @property - def order_by_role(self): - role_order = [role[0] for role in choices.ROLE] - order = [When(role__std_role=role, then=Value(i)) for i, role in enumerate(role_order)] - - editorial_members = EditorialBoardMember.objects.filter(editorial_board=self) - - ordered_editorial_board = editorial_members.annotate( - editorial_order=Case(*order, default=Value(len(role_order)), output_field=IntegerField()) - ).order_by("editorial_order") - - return ordered_editorial_board - - - @classmethod - def create_or_update( - cls, - user, - journal, - initial_year, - final_year, - journal_title=None, - ): - if not journal and journal_title: - journal_title = journal_title.strip() - journal = Journal.objects.get( - Q(title__icontains=journal_title) - | Q(official__title__icontains=journal_title) - ) - logging.info(f"EditorialBoard {journal_title} OK") - try: - return cls.get(journal, initial_year, final_year) - except cls.DoesNotExist: - return cls.create(user, journal, initial_year, final_year) - - @classmethod - def get( - cls, - journal, - initial_year, - final_year, - ): - try: - return cls.objects.get( - journal=journal, - initial_year=initial_year, - final_year=final_year, - ) - except cls.MultipleObjectsReturned: - return cls.objects.filter( - journal=journal, - initial_year=initial_year, - final_year=final_year, - ).first() - - @classmethod - def create( - cls, - user, - journal, - initial_year, - final_year, - ): - try: - obj = cls() - obj.creator = user - obj.journal = journal - obj.initial_year = initial_year - obj.final_year = final_year - obj.save() - return obj - except IntegrityError: - return cls.objects.get( - journal=journal, - initial_year=initial_year, - final_year=final_year, - ) - - class EditorialBoardMember(CommonControlField, ClusterableModel, Orderable): journal = ParentalKey( Journal, related_name="editorial_board_member_journal", null=True From 48879e35ff5780840c8458b6b24323888c68012c Mon Sep 17 00:00:00 2001 From: Samuel Veiga Rangel Date: Wed, 26 Mar 2025 11:13:10 -0300 Subject: [PATCH 11/19] Cria teste para import_valide_ebm --- editorialboard/tests.py | 60 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/editorialboard/tests.py b/editorialboard/tests.py index 5d018cc5e..b03a3d81f 100644 --- a/editorialboard/tests.py +++ b/editorialboard/tests.py @@ -1,7 +1,9 @@ -import logging +from unittest.mock import patch -from django.test import TestCase +from django.test import TestCase, RequestFactory from django.contrib.auth import get_user_model +from django.contrib.messages.storage.fallback import FallbackStorage +from wagtail.documents.models import Document # Create your tests here. @@ -9,11 +11,13 @@ from location.models import Location from editorialboard.models import ( EditorialBoardMember, + EditorialBoardMemberFile, ) +from editorialboard.views import import_file_ebm from researcher.models import ResearcherAKA, Researcher from journal.models import Journal - +from django.core.files.uploadedfile import SimpleUploadedFile User = get_user_model() @@ -45,7 +49,7 @@ def setUp(self): aff_state_name=None, ) - def test__create_or_update_location(self): + def test_create_or_update_location(self): location = Location.create_or_update( self.user, @@ -123,3 +127,51 @@ def test_editorial_board_member_create_or_update(self): self.assertEqual("Revista XXXX", editorial_board.journal.title) self.assertEqual(1, EditorialBoardMember.objects.get(journal=self.journal).role_editorial_board.count()) self.assertEqual("editor de seção", EditorialBoardMember.objects.get(journal=self.journal).role_editorial_board.first().role.declared_role) + + +class ImportFileEBMTest(TestCase): + def setUp(self): + self.user = User.objects.create(username="user") + self.journal = Journal.objects.create(title="Revista XXXX") + self.csv_content = """Nome do membro;Sobrenome;Periódico;Suffix;declared_person_name;CV Lattes;ORCID iD;Email;Gender;institution_city_name;institution_state_text;institution_state_acronym;institution_state_name;institution_country_text;institution_country_acronym;institution_country_name;institution_div1;institution_div2;Instituição;Cargo / instância do membro;Data +John;Doe;Revista XXXX;Jr;John Doe;lattes;0000-0000-0000-0000;john@doe.com;M;City;State;ST;State Name;Country;CN;Country Name;Div1;Div2;Institution;Editor;2020""" + self.factory = RequestFactory() + + def create_editorial_file(self, csv_content): + csv_file = SimpleUploadedFile( + name="test.csv", + content=csv_content.encode("utf-8"), + content_type="text/csv", + ) + document = Document.objects.create(title="Test CSV", file=csv_file) + + return EditorialBoardMemberFile.objects.create(attachment=document) + + def add_messages_middleware(self, request): + """Add session and messages middleware to the request.""" + from django.contrib.sessions.middleware import SessionMiddleware + from django.contrib.messages.middleware import MessageMiddleware + + # Pass a dummy get_response function to the middleware + SessionMiddleware(lambda req: None).process_request(request) + MessageMiddleware(lambda req: None).process_request(request) + request.session.save() + request._messages = FallbackStorage(request) + return request + + def test_import_file_edm(self): + editorial_file = self.create_editorial_file(self.csv_content) + request = self.factory.get(f"/import-ebm/?file_id={editorial_file.pk}") + request.user = self.user + request.META["HTTP_REFERER"] = "/some-valid-url/" + request = self.add_messages_middleware(request) + response = import_file_ebm(request) + self.assertEqual(response.status_code, 302) + self.assertEqual(Location.objects.all().count(), 1) + self.assertEqual(Researcher.objects.all().count(), 1) + self.assertEqual(EditorialBoardMember.objects.all().count(), 1) + self.assertEqual(EditorialBoardMember.objects.first().researcher.person_name.fullname, "John Doe Jr") + self.assertEqual(EditorialBoardMember.objects.first().journal.title, "Revista XXXX") + self.assertEqual(EditorialBoardMember.objects.first().role_editorial_board.first().role.declared_role, "Editor") + self.assertEqual(EditorialBoardMember.objects.first().role_editorial_board.first().initial_year, "2020") + self.assertEqual(EditorialBoardMember.objects.first().role_editorial_board.first().final_year, "2020") \ No newline at end of file From d972ff1fd1bf90b84c8a9ce0cc6bfa964eac8c79 Mon Sep 17 00:00:00 2001 From: Samuel Veiga Rangel Date: Wed, 26 Mar 2025 11:13:30 -0300 Subject: [PATCH 12/19] Modifica funcao import_valide_ebm --- editorialboard/views.py | 102 ++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 50 deletions(-) diff --git a/editorialboard/views.py b/editorialboard/views.py index f2e543a16..6ce4d5cf3 100644 --- a/editorialboard/views.py +++ b/editorialboard/views.py @@ -1,9 +1,7 @@ import csv import os -from datetime import datetime +import sys -from django.contrib.auth import get_user_model -from django.http import Http404, HttpResponse from django.shortcuts import get_object_or_404, redirect from django.utils.translation import gettext as _ from wagtail.admin import messages @@ -11,6 +9,11 @@ from core.libs import chkcsv from .models import EditorialBoardMember, EditorialBoardMemberFile +from journal.models import Journal +from location.models import Location +from researcher.models import Researcher +from tracker.models import UnexpectedEvent +from core.models import Gender def validate_ebm(request): @@ -71,61 +74,60 @@ def import_file_ebm(request): with open(file_path, "r") as csvfile: data = csv.DictReader(csvfile, delimiter=";") for line, row in enumerate(data): - given_names = row["Nome do membro"] - last_name = row["Sobrenome"] - # ed = EditorialBoardMember() - # ed.get_or_create( - # row["Periódico"], - # row["Cargo / instância do membro"], - # row["Data"], - # row["Email"], - # row["Institution"], - # given_names, - # last_name, - # row["Suffix"], - # row["ORCID iD"], - # row["CV Lattes"], - # row["Gender"], - # row["Gender status"], - # request.user, - # ) - # ,User) - - EditorialBoardMember.create_or_update( - request.user, - researcher=None, - journal=None, - journal_title=row["Periódico"], + given_names = row.get("Nome do membro") + last_name = row.get("Sobrenome") + journal = Journal.objects.get(title__icontains=row.get("Periódico")) + gender = Gender.create_or_update(user=request.user, code=row.get("Gender"), gender="F") + location = Location.create_or_update( + user=request.user, + city_name=row.get("institution_city_name"), + state_text=row.get("institution_state_text"), + state_acronym=row.get("institution_state_acronym"), + state_name=row.get("institution_state_name"), + country_text=row.get("institution_country_text"), + country_acronym=row.get("institution_country_acronym"), + country_name=row.get("institution_country_name"), + ) + researcher = Researcher.create_or_update( + user=request.user, given_names=given_names, last_name=last_name, - suffix=row["Suffix"], - declared_person_name=row.get("declared_person_name"), - lattes=row["CV Lattes"], - orcid=row["ORCID iD"], - email=row["Email"], - gender_code=row["Gender"], - gender_identification_status=row["Gender status"], - institution_name=row["Institution"], - institution_div1=row.get("institution_div1"), - institution_div2=row.get("institution_div2"), - institution_city_name=row.get("institution_city_name"), - institution_country_text=row.get("institution_country_text"), - institution_country_acronym=row.get("institution_country_acronym"), - institution_country_name=row.get("institution_country_name"), - institution_state_text=row.get("institution_state_text"), - institution_state_acronym=row.get("institution_state_acronym"), - institution_state_name=row.get("institution_state_name"), + suffix=row.get("Suffix"), + declared_name=row.get("declared_person_name"), + lattes=row.get("CV Lattes"), + orcid=row.get("ORCID iD"), + email=row.get("Email"), + gender=gender, + location=location, + aff_div1=row.get("institution_div1"), + aff_div2=row.get("institution_div2"), + aff_name=row.get("Instituição"), + ) + EditorialBoardMember.create_or_update( + user=request.user, + researcher=researcher, + journal=journal, declared_role=row["Cargo / instância do membro"], std_role=None, - member_activity_initial_year=row["Data"], - member_activity_final_year=row["Data"], - member_activity_initial_month="01", - member_activity_final_month="12", editorial_board_initial_year=row["Data"], editorial_board_final_year=row["Data"], ) + except Exception as ex: - messages.error(request, _("Import error: %s, Line: %s") % (ex, str(line + 2))) + messages.error(request, _("Import error: %s, Line: %s. Exception: %s") % (ex, str(line + 2), ex)) + exc_type, exc_value, exc_traceback = sys.exc_info() + UnexpectedEvent.create( + item=str(file_upload), + action="editorialboard.views.import_file_ebm", + exception=ex, + exc_traceback=exc_traceback, + detail=dict( + line=line, + row=row, + file_path=file_path, + file_id=file_id, + ), + ) else: messages.success(request, _("File imported successfully!")) From 3e7275b56c7601b930f75898f027c473fa1a92d7 Mon Sep 17 00:00:00 2001 From: Samuel Veiga Rangel Date: Wed, 26 Mar 2025 11:13:40 -0300 Subject: [PATCH 13/19] Fix imports --- editorialboard/wagtail_hooks.py | 46 ++++++++++++++++----------------- journalpage/utils/utils.py | 6 ++--- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/editorialboard/wagtail_hooks.py b/editorialboard/wagtail_hooks.py index b0b175659..74f644ebe 100644 --- a/editorialboard/wagtail_hooks.py +++ b/editorialboard/wagtail_hooks.py @@ -12,7 +12,7 @@ from .button_helper import EditorialBoardMemberHelper from .models import ( - EditorialBoard, + # EditorialBoard, EditorialBoardMember, EditorialBoardMemberFile, RoleModel, @@ -91,27 +91,27 @@ def form_valid(self, form): return HttpResponseRedirect(self.get_success_url()) -class EditorialBoardAdmin(ModelAdmin): - model = EditorialBoard - create_view_class = EditorialBoardCreateView - menu_label = _("EditorialBoard") - menu_icon = "folder" - menu_order = 9 - add_to_settings_menu = False - exclude_from_explorer = False - list_display = ( - "journal", - "initial_year", - "final_year", - "created", - "updated", - ) - list_filter = ("initial_year", "final_year") - search_fields = ( - "journal__title", - "initial_year", - "final_year", - ) +# class EditorialBoardAdmin(ModelAdmin): +# model = EditorialBoard +# create_view_class = EditorialBoardCreateView +# menu_label = _("EditorialBoard") +# menu_icon = "folder" +# menu_order = 9 +# add_to_settings_menu = False +# exclude_from_explorer = False +# list_display = ( +# "journal", +# "initial_year", +# "final_year", +# "created", +# "updated", +# ) +# list_filter = ("initial_year", "final_year") +# search_fields = ( +# "journal__title", +# "initial_year", +# "final_year", +# ) class EditorialBoardAdminGroup(ModelAdminGroup): @@ -120,7 +120,7 @@ class EditorialBoardAdminGroup(ModelAdminGroup): menu_order = get_menu_order("editorialboard") # will put in 3rd place (000 being 1st, 100 2nd) items = ( RoleModelAdmin, - EditorialBoardAdmin, + # EditorialBoardAdmin, EditorialBoardMemberAdmin, EditorialBoardMemberFileAdmin, ) diff --git a/journalpage/utils/utils.py b/journalpage/utils/utils.py index ddc8509a5..ca400e006 100644 --- a/journalpage/utils/utils.py +++ b/journalpage/utils/utils.py @@ -1,5 +1,5 @@ from journal.models import Journal -from editorialboard.models import EditorialBoard +from editorialboard.models import EditorialBoardMember from editorialboard.choices import ROLE from django.shortcuts import render @@ -24,10 +24,10 @@ def find_most_recent_journal(journal): def get_editorial_board(journal): try: - editorial_board = EditorialBoard.objects.filter(journal=journal).latest( + editorial_board = EditorialBoardMember.objects.filter(journal=journal).latest( "initial_year" ) - except EditorialBoard.DoesNotExist: + except EditorialBoardMember.DoesNotExist: editorial_board = None return editorial_board From edd8fc01106bc0365da56916dd953b8d310d6329 Mon Sep 17 00:00:00 2001 From: Samuel Veiga Rangel Date: Sun, 27 Apr 2025 15:22:09 -0300 Subject: [PATCH 14/19] Remove imports --- editorialboard/models.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/editorialboard/models.py b/editorialboard/models.py index c879bcee2..2fc66a179 100644 --- a/editorialboard/models.py +++ b/editorialboard/models.py @@ -1,22 +1,20 @@ import logging import os -from itertools import cycle -from django.db import models, IntegrityError -from django.db.models import Q, Case, When, Value, IntegerField + +from django.db import IntegrityError, models +from django.db.models import Q from django.utils.translation import gettext_lazy as _ from modelcluster.fields import ParentalKey from modelcluster.models import ClusterableModel -from wagtail.admin.panels import FieldPanel, InlinePanel, MultiFieldPanel +from wagtail.admin.panels import FieldPanel, InlinePanel from wagtail.models import Orderable from wagtailautocomplete.edit_handlers import AutocompletePanel -from core.choices import MONTHS -from core.models import CommonControlField, Gender from core.forms import CoreAdminModelForm +from core.models import CommonControlField from core.utils.standardizer import remove_extra_spaces from journal.models import Journal -from location.models import Location, City, State, Country -from researcher.models import Researcher, Affiliation +from researcher.models import Researcher from . import choices From 6d0047bbdeae415ecb02a738b7b4e12f0bd55cd8 Mon Sep 17 00:00:00 2001 From: Samuel Veiga Rangel Date: Sun, 27 Apr 2025 15:33:05 -0300 Subject: [PATCH 15/19] Ignora permissionamento para superuser --- journal/wagtail_hooks.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/journal/wagtail_hooks.py b/journal/wagtail_hooks.py index 1d0bfa9a1..65ac3d05b 100755 --- a/journal/wagtail_hooks.py +++ b/journal/wagtail_hooks.py @@ -78,14 +78,15 @@ def get_edit_handler(self): """ edit_handler = super().get_edit_handler() user_permissions = self.request.user.get_all_permissions() - for object_list in edit_handler.children: - for field in object_list.children: - if isinstance(field, FieldPanel) and f"journal.can_edit_{field.field_name}" not in user_permissions: - field.__setattr__('read_only', True) - elif isinstance(field, InlinePanel) and f"journal.can_edit_{field.relation_name}" not in user_permissions: - field.classname = field.classname + ' read-only-inline-panel' - for inline_field in field.panel_definitions: - inline_field.__setattr__('read_only', True) + if not self.request.user.is_superuser: + for object_list in edit_handler.children: + for field in object_list.children: + if isinstance(field, FieldPanel) and f"journal.can_edit_{field.field_name}" not in user_permissions: + field.__setattr__('read_only', True) + elif isinstance(field, InlinePanel) and f"journal.can_edit_{field.relation_name}" not in user_permissions: + field.classname = field.classname + ' read-only-inline-panel' + for inline_field in field.panel_definitions: + inline_field.__setattr__('read_only', True) return edit_handler From c2fd118faa056caaf304eed46eb5324e888a31dc Mon Sep 17 00:00:00 2001 From: Samuel Veiga Rangel Date: Sun, 27 Apr 2025 15:33:29 -0300 Subject: [PATCH 16/19] Inclui novo modelo de Researcher --- editorialboard/models.py | 8 ++++---- editorialboard/wagtail_hooks.py | 5 ----- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/editorialboard/models.py b/editorialboard/models.py index 2fc66a179..fb9182bad 100644 --- a/editorialboard/models.py +++ b/editorialboard/models.py @@ -14,7 +14,7 @@ from core.models import CommonControlField from core.utils.standardizer import remove_extra_spaces from journal.models import Journal -from researcher.models import Researcher +from researcher.models import NewResearcher from . import choices @@ -24,7 +24,7 @@ class EditorialBoardMember(CommonControlField, ClusterableModel, Orderable): Journal, related_name="editorial_board_member_journal", null=True ) researcher = models.ForeignKey( - Researcher, null=True, blank=True, related_name="+", on_delete=models.SET_NULL + NewResearcher, null=True, blank=True, related_name="+", on_delete=models.SET_NULL ) image = models.ForeignKey( "wagtailimages.Image", @@ -157,8 +157,8 @@ class RoleEditorialBoard(CommonControlField, Orderable): role = models.ForeignKey( "RoleModel", null=True, blank=True, related_name="+", on_delete=models.SET_NULL ) - initial_year = models.CharField(max_length=4, blank=True, null=True) - final_year = models.CharField(max_length=4, blank=True, null=True) + initial_year = models.DateField(blank=True, null=True) + final_year = models.DateField(blank=True, null=True) panels = [ AutocompletePanel("role"), diff --git a/editorialboard/wagtail_hooks.py b/editorialboard/wagtail_hooks.py index 74f644ebe..9a864bf2a 100644 --- a/editorialboard/wagtail_hooks.py +++ b/editorialboard/wagtail_hooks.py @@ -46,11 +46,6 @@ class EditorialBoardMemberAdmin(ModelAdmin): "journal__title", "researcher__person_name__fullname", ) - custom_panels = [ - FieldPanel("researcher", read_only=True), - FieldPanel("role", read_only=True), - ] - edit_handler = ObjectList(custom_panels) class EditorialBoardMemberFileAdmin(ModelAdmin): From 30f43607a1ff87e0704097a0f98702e7c80b6418 Mon Sep 17 00:00:00 2001 From: Samuel Veiga Rangel Date: Sun, 27 Apr 2025 15:33:36 -0300 Subject: [PATCH 17/19] migracoes --- ...ditorialboardmember_researcher_and_more.py | 29 +++++++++++++++++++ ..._roleeditorialboard_final_year_and_more.py | 23 +++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 editorialboard/migrations/0006_alter_editorialboardmember_researcher_and_more.py create mode 100644 editorialboard/migrations/0007_alter_roleeditorialboard_final_year_and_more.py diff --git a/editorialboard/migrations/0006_alter_editorialboardmember_researcher_and_more.py b/editorialboard/migrations/0006_alter_editorialboardmember_researcher_and_more.py new file mode 100644 index 000000000..a3acda5f2 --- /dev/null +++ b/editorialboard/migrations/0006_alter_editorialboardmember_researcher_and_more.py @@ -0,0 +1,29 @@ +# Generated by Django 5.0.8 on 2025-04-27 18:22 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("editorialboard", "0005_alter_editorialboardmember_unique_together_and_more"), + ("researcher", "0005_newresearcher_researcherids_and_more"), + ] + + operations = [ + migrations.AlterField( + model_name="editorialboardmember", + name="researcher", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="+", + to="researcher.newresearcher", + ), + ), + migrations.DeleteModel( + name="EditorialBoard", + ), + ] diff --git a/editorialboard/migrations/0007_alter_roleeditorialboard_final_year_and_more.py b/editorialboard/migrations/0007_alter_roleeditorialboard_final_year_and_more.py new file mode 100644 index 000000000..1683a6298 --- /dev/null +++ b/editorialboard/migrations/0007_alter_roleeditorialboard_final_year_and_more.py @@ -0,0 +1,23 @@ +# Generated by Django 5.0.8 on 2025-04-27 18:31 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("editorialboard", "0006_alter_editorialboardmember_researcher_and_more"), + ] + + operations = [ + migrations.AlterField( + model_name="roleeditorialboard", + name="final_year", + field=models.DateField(blank=True, null=True), + ), + migrations.AlterField( + model_name="roleeditorialboard", + name="initial_year", + field=models.DateField(blank=True, null=True), + ), + ] From 9fb17963a9f396db2c947f120ec4eae8598fe558 Mon Sep 17 00:00:00 2001 From: Samuel Veiga Rangel Date: Sun, 27 Apr 2025 16:20:49 -0300 Subject: [PATCH 18/19] Fix NewResearcher.get_or_create --- researcher/models.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/researcher/models.py b/researcher/models.py index 545028c86..779800f54 100644 --- a/researcher/models.py +++ b/researcher/models.py @@ -747,9 +747,12 @@ def get(cls, suffix, given_names, last_name, researcher_identifier): "Researcher.get requires given_names, last_name parameters" ) fullname = cls.join_names(given_names, last_name, suffix) - if researcher_identifier: - qs = cls.get_by_orcid(researcher_identifier) - return qs.get(fullname__iexact=fullname) + if researcher_identifier and researcher_identifier.source_name == "ORCID": + try: + qs = cls.get_by_orcid(researcher_identifier) + return qs.get(fullname__iexact=fullname) + except cls.DoesNotExist: + pass return cls.objects.get(fullname__iexact=fullname) @classmethod @@ -775,9 +778,6 @@ def create( affiliation=affiliation, ) obj.save() - if researcher_identifier: - obj.researcher_ids.add(researcher_identifier) - obj.save() return obj except IntegrityError: return cls.get( @@ -800,14 +800,14 @@ def get_or_create( gender_identification_status=None, ): try: - return cls.get( + obj = cls.get( given_names=given_names, last_name=last_name, suffix=suffix, researcher_identifier=researcher_identifier, ) except cls.DoesNotExist: - return cls.create( + obj = cls.create( user=user, given_names=given_names, last_name=last_name, @@ -817,7 +817,6 @@ def get_or_create( gender=gender, gender_identification_status=gender_identification_status, ) - except (InvalidOrcidError, ValueError) as e: data = dict( given_names=given_names, @@ -835,7 +834,11 @@ def get_or_create( "data": data, }, ) - + finally: + if researcher_identifier: + obj.researcher_ids.add(researcher_identifier) + obj.save() + return obj class ResearcherIds(CommonControlField): """ From fc073434815a40b83fea3603f05374cd988e68ad Mon Sep 17 00:00:00 2001 From: Samuel Veiga Rangel Date: Sun, 27 Apr 2025 16:21:00 -0300 Subject: [PATCH 19/19] New testes --- editorialboard/tests.py | 136 ++++++++++++++++++++++++---------------- 1 file changed, 81 insertions(+), 55 deletions(-) diff --git a/editorialboard/tests.py b/editorialboard/tests.py index b03a3d81f..ae2f94e3c 100644 --- a/editorialboard/tests.py +++ b/editorialboard/tests.py @@ -14,7 +14,8 @@ EditorialBoardMemberFile, ) from editorialboard.views import import_file_ebm -from researcher.models import ResearcherAKA, Researcher +from researcher.models import NewResearcher, ResearcherIds +from organization.models import Organization from journal.models import Journal from django.core.files.uploadedfile import SimpleUploadedFile @@ -26,44 +27,74 @@ def setUp(self): self.user = User.objects.create(username="user") self.journal = Journal.objects.create(title="Revista XXXX") self.gender = Gender.create_or_update(user=self.user, code="F", gender="F") - self.researcher = Researcher.create_or_update( + self.location = Location.create_or_update( self.user, - given_names=None, + city_name="São Paulo", + country_text="Brasil", + country_acronym="BR", + country_name=None, + state_name="São Paulo", + state_acronym="SP", + ) + self.organization = Organization.create_or_update( + user=self.user, + name="Name of institution", + acronym="Acronym of institution", + url="www.teste.com.br", + location=self.location, + institution_type_mec="outros", + is_official=True, + ) + self.researcher_identifier_orcid = ResearcherIds.get_or_create( + user=self.user, + identifier="0000-0002-9147-0547", + source_name="ORCID", + ) + self.researcher_identifier_lattes = ResearcherIds.get_or_create( + user=self.user, + identifier="qwertpoiuytkdiekd", + source_name="LATTES", + ) + self.researcher_identifier_email = ResearcherIds.get_or_create( + user=self.user, + identifier="user@dom.org", + source_name="EMAIL", + ) + self.researcher = NewResearcher.get_or_create( + self.user, + given_names="Anna", last_name="Taomeaome", - suffix=None, - declared_name="Anna Taomeaome", - lattes="qwertpoiuytkdiekd", - orcid="1234-1234-0987-0987", - email="user@dom.org", + suffix="Jr.", + researcher_identifier=self.researcher_identifier_orcid, + affiliation=self.organization, gender=self.gender, gender_identification_status="DECLARED", - aff_name="Universidade Federal de São Carlos", - aff_div1=None, - aff_div2=None, - aff_city_name="São Carlos", - aff_country_text="Brasil", - aff_country_acronym=None, - aff_country_name=None, - aff_state_text="São Paulo", - aff_state_acronym=None, - aff_state_name=None, ) - - def test_create_or_update_location(self): - - location = Location.create_or_update( + self.researcher = NewResearcher.get_or_create( self.user, - city_name="Campinas", - country_text="Brasil", - country_acronym=None, - country_name=None, - state_text="SP", - state_acronym=None, - state_name=None, + given_names="Anna", + last_name="Taomeaome", + suffix="Jr.", + researcher_identifier=self.researcher_identifier_email, + affiliation=self.organization, + gender=self.gender, + gender_identification_status="DECLARED", + ) + self.researcher = NewResearcher.get_or_create( + self.user, + given_names="Anna", + last_name="Taomeaome", + suffix="Jr.", + researcher_identifier=self.researcher_identifier_lattes, + affiliation=self.organization, + gender=self.gender, + gender_identification_status="DECLARED", ) - self.assertEqual("Brasil", location.country.name) - self.assertEqual("Campinas", location.city.name) - self.assertEqual("SP", location.state.acronym) + + def test_create_or_update_location(self): + self.assertEqual("Brasil", self.location.country.name) + self.assertEqual("São Paulo", self.location.city.name) + self.assertEqual("SP", self.location.state.acronym) def test_create_or_update_researcher(self): editorial_board_member = EditorialBoardMember.create_or_update( @@ -72,46 +103,41 @@ def test_create_or_update_researcher(self): journal=self.journal, declared_role="editor de seção", std_role=None, - editorial_board_initial_year="2010", - editorial_board_final_year="2012", + editorial_board_initial_year="2010-03-01", + editorial_board_final_year="2012-03-01", ) self.assertEqual( - "São Paulo", editorial_board_member.researcher.affiliation.institution.location.state.name + "São Paulo", editorial_board_member.researcher.affiliation.location.state.name ) self.assertEqual( - "São Carlos", editorial_board_member.researcher.affiliation.institution.location.city.name + "São Paulo", editorial_board_member.researcher.affiliation.location.city.name ) self.assertEqual( - "Brasil", editorial_board_member.researcher.affiliation.institution.location.country.name + "Brasil", editorial_board_member.researcher.affiliation.location.country.name ) self.assertEqual( - "Universidade Federal de São Carlos", - editorial_board_member.researcher.affiliation.institution.institution_identification.name, + "Name of institution", + editorial_board_member.researcher.affiliation.name, ) - self.assertEqual("F", editorial_board_member.researcher.person_name.gender.code) - self.assertEqual("F", editorial_board_member.researcher.person_name.gender.gender) + self.assertEqual("F", editorial_board_member.researcher.gender.code) + self.assertEqual("F", editorial_board_member.researcher.gender.gender) self.assertEqual( - "DECLARED", editorial_board_member.researcher.person_name.gender_identification_status + "DECLARED", editorial_board_member.researcher.gender_identification_status ) - self.assertEqual("Anna Taomeaome", editorial_board_member.researcher.person_name.declared_name) + self.assertEqual("Anna Taomeaome Jr.", editorial_board_member.researcher.fullname) + self.assertEqual( "qwertpoiuytkdiekd", - ResearcherAKA.objects.get( - researcher=editorial_board_member.researcher, researcher_identifier__source_name="LATTES" - ).researcher_identifier.identifier, + editorial_board_member.researcher.researcher_ids.filter(source_name="LATTES").first().identifier, ) self.assertEqual( - "1234-1234-0987-0987", - ResearcherAKA.objects.get( - researcher=editorial_board_member.researcher, researcher_identifier__source_name="ORCID" - ).researcher_identifier.identifier, + "0000-0002-9147-0547", + editorial_board_member.researcher.researcher_ids.filter(source_name="ORCID").first().identifier, ) self.assertEqual( "user@dom.org", - ResearcherAKA.objects.get( - researcher=editorial_board_member.researcher, researcher_identifier__source_name="EMAIL" - ).researcher_identifier.identifier, + editorial_board_member.researcher.researcher_ids.filter(source_name="EMAIL").first().identifier, ) def test_editorial_board_member_create_or_update(self): @@ -120,8 +146,8 @@ def test_editorial_board_member_create_or_update(self): journal=self.journal, researcher=self.researcher, declared_role="editor de seção", - editorial_board_initial_year="2010", - editorial_board_final_year="2012", + editorial_board_initial_year="2010-01-01", + editorial_board_final_year="2012-01-01", ) self.assertEqual(self.researcher, editorial_board.researcher) self.assertEqual("Revista XXXX", editorial_board.journal.title)