diff --git a/greg/admin.py b/greg/admin.py index d73bdab829f508534fac1eea3473a2ef7a1a1a35..91825c58f637218813f70f302f7ba0135dc38ac9 100644 --- a/greg/admin.py +++ b/greg/admin.py @@ -3,11 +3,11 @@ from reversion.admin import VersionAdmin from greg.models import ( Person, - PersonRole, Role, + RoleType, PersonIdentity, + ConsentType, Consent, - PersonConsent, OrganizationalUnit, Sponsor, SponsorOrganizationalUnit, @@ -17,7 +17,7 @@ admin.site.site_header = "Guest Registration Admin" class RoleInline(admin.TabularInline): - model = PersonRole + model = Role extra = 1 @@ -27,7 +27,7 @@ class PersonIdentityInline(admin.TabularInline): class ConsentInline(admin.TabularInline): - model = PersonConsent + model = Consent extra = 1 @@ -47,18 +47,18 @@ class PersonAdmin(VersionAdmin): role_count.short_description = "# roles" # type: ignore -class PersonRoleAdmin(VersionAdmin): - list_display = ("id", "person", "role") +class RoleAdmin(VersionAdmin): + list_display = ("id", "person", "type") search_fields = ( "person__id", - "role__id", + "type__id", ) - raw_id_fields = ("person", "role") + raw_id_fields = ("person", "type") readonly_fields = ("id", "created", "updated") -class RoleAdmin(VersionAdmin): - list_display = ("id", "type", "name_nb", "name_en") +class RoleTypeAdmin(VersionAdmin): + list_display = ("id", "identifier", "name_nb", "name_en") readonly_fields = ("id", "created", "updated") @@ -68,19 +68,19 @@ class PersonIdentityAdmin(VersionAdmin): readonly_fields = ("id", "created", "updated") -class ConsentAdmin(admin.ModelAdmin): - list_display = ("id", "consent_name_en", "valid_from", "user_allowed_to_change") +class ConsentAdmin(VersionAdmin): + list_display = ("id", "person", "get_consent_type_name") readonly_fields = ("id", "created", "updated") + def get_consent_type_name(self, obj): + return obj.type.name_en -class PersonConsentAdmin(VersionAdmin): - list_display = ("id", "person", "get_consent_name_en") - readonly_fields = ("id", "created", "updated") + get_consent_type_name.short_description = "Consent name" # type: ignore - def get_consent_name_en(self, obj): - return obj.consent.consent_name_en - get_consent_name_en.short_description = "Consent name" # type: ignore +class ConsentTypeAdmin(admin.ModelAdmin): + list_display = ("id", "name_en", "valid_from", "user_allowed_to_change") + readonly_fields = ("id", "created", "updated") class OrganizationalUnitAdmin(VersionAdmin): @@ -104,11 +104,11 @@ class SponsorOrganizationalUnitAdmin(VersionAdmin): admin.site.register(Person, PersonAdmin) -admin.site.register(PersonRole, PersonRoleAdmin) admin.site.register(Role, RoleAdmin) +admin.site.register(RoleType, RoleTypeAdmin) admin.site.register(PersonIdentity, PersonIdentityAdmin) admin.site.register(Consent, ConsentAdmin) -admin.site.register(PersonConsent, PersonConsentAdmin) +admin.site.register(ConsentType, ConsentTypeAdmin) admin.site.register(OrganizationalUnit, OrganizationalUnitAdmin) admin.site.register(Sponsor, SponsorAdmin) admin.site.register(SponsorOrganizationalUnit, SponsorOrganizationalUnitAdmin) diff --git a/greg/api/filters.py b/greg/api/filters.py index c7af546c6b456316345e0f4977fc2a1675cec7e9..534f5ee06fc96306d381441b32c5a00a06a5dafe 100644 --- a/greg/api/filters.py +++ b/greg/api/filters.py @@ -6,16 +6,16 @@ from django_filters.rest_framework import ( from greg.models import ( Person, - PersonRole, + Role, PersonIdentity, ) -class PersonRoleFilter(FilterSet): +class RoleFilter(FilterSet): type = BaseInFilter(field_name="role__type", lookup_expr="in") class Meta: - model = PersonRole + model = Role fields = ["type"] diff --git a/greg/api/serializers/__init__.py b/greg/api/serializers/__init__.py index f6fe4dc2514fc0c9f45510b26ab737a03fca983b..ca5bdad3c424bdcde320e7ef21107d2e4870a92f 100644 --- a/greg/api/serializers/__init__.py +++ b/greg/api/serializers/__init__.py @@ -1,11 +1,11 @@ from .notification import NotificationSerializer from .person import PersonSerializer -from .role import RoleSerializer +from .role_type import RoleTypeSerializer def get_serializer(instance): return { "notification": NotificationSerializer, "person": PersonSerializer, - "role": RoleSerializer, + "role": RoleTypeSerializer, }.get(instance._meta.verbose_name) diff --git a/greg/api/serializers/consent_type.py b/greg/api/serializers/consent_type.py new file mode 100644 index 0000000000000000000000000000000000000000..c3e626c22d4c625e78e92eed864a0be6a4d114d9 --- /dev/null +++ b/greg/api/serializers/consent_type.py @@ -0,0 +1,9 @@ +from rest_framework.serializers import ModelSerializer + +from greg.models import ConsentType + + +class ConsentTypeSerializer(ModelSerializer): + class Meta: + model = ConsentType + fields = "__all__" diff --git a/greg/api/serializers/person.py b/greg/api/serializers/person.py index 720972d75296594cc6438df985d29276efe04638..72e18ba65f72919c6ecc12109bbc79defe5f8a89 100644 --- a/greg/api/serializers/person.py +++ b/greg/api/serializers/person.py @@ -1,13 +1,15 @@ from rest_framework import serializers -from greg.models import Person, PersonRole, Role, PersonIdentity, PersonConsent, Consent +from greg.models import Person, Role, RoleType, PersonIdentity, Consent, ConsentType -class PersonRoleSerializer(serializers.ModelSerializer): - role = serializers.SlugRelatedField(queryset=Role.objects.all(), slug_field="type") +class RoleSerializer(serializers.ModelSerializer): + type = serializers.SlugRelatedField( + queryset=RoleType.objects.all(), slug_field="identifier" + ) class Meta: - model = PersonRole + model = Role fields = [ "id", "start_date", @@ -16,7 +18,7 @@ class PersonRoleSerializer(serializers.ModelSerializer): "unit", "created", "updated", - "role", + "type", ] @@ -41,28 +43,28 @@ class PersonIdentitySerializer(serializers.ModelSerializer): ) -class ConsentSerializerBrief(serializers.ModelSerializer): +class ConsentTypeSerializerBrief(serializers.ModelSerializer): class Meta: - model = Consent + model = ConsentType fields = [ - "type", + "identifier", "valid_from", "user_allowed_to_change", ] -class PersonConsentSerializerBrief(serializers.ModelSerializer): - consent = ConsentSerializerBrief(read_only=True) +class ConsentSerializerBrief(serializers.ModelSerializer): + type = ConsentTypeSerializerBrief(read_only=True) class Meta: - model = PersonConsent - fields = ["consent", "consent_given_at"] + model = Consent + fields = ["type", "consent_given_at"] class PersonSerializer(serializers.ModelSerializer): identities = PersonIdentitySerializer(many=True, read_only=True) - person_roles = PersonRoleSerializer(many=True, read_only=True) - person_consent = PersonConsentSerializerBrief(many=True, read_only=True) + roles = RoleSerializer(many=True, read_only=True) + consents = ConsentSerializerBrief(many=True, read_only=True) class Meta: model = Person @@ -79,6 +81,6 @@ class PersonSerializer(serializers.ModelSerializer): "registration_completed_date", "token", "identities", - "person_roles", - "person_consent", + "roles", + "consents", ] diff --git a/greg/api/serializers/role.py b/greg/api/serializers/role.py deleted file mode 100644 index 3fd2d03d884330f481e529919126ee6350221e2f..0000000000000000000000000000000000000000 --- a/greg/api/serializers/role.py +++ /dev/null @@ -1,9 +0,0 @@ -from rest_framework.serializers import ModelSerializer - -from greg.models import Role - - -class RoleSerializer(ModelSerializer): - class Meta: - model = Role - fields = "__all__" diff --git a/greg/api/serializers/consent.py b/greg/api/serializers/role_type.py similarity index 50% rename from greg/api/serializers/consent.py rename to greg/api/serializers/role_type.py index 5c1663f2da723d94f477a82e3fb97d9351892e35..d52c5efcf2fd41b190b2ee160ebb5e9d4c0ca841 100644 --- a/greg/api/serializers/consent.py +++ b/greg/api/serializers/role_type.py @@ -1,9 +1,9 @@ from rest_framework.serializers import ModelSerializer -from greg.models import Consent +from greg.models import RoleType -class ConsentSerializer(ModelSerializer): +class RoleTypeSerializer(ModelSerializer): class Meta: - model = Consent + model = RoleType fields = "__all__" diff --git a/greg/api/urls.py b/greg/api/urls.py index 6428641d97d1370684bb8c48b6c231bf16bd2ae8..71ecf1bfeb1ef0cf3143ddbaa06cea97abb95773 100644 --- a/greg/api/urls.py +++ b/greg/api/urls.py @@ -3,20 +3,20 @@ from django.urls import ( ) from rest_framework.routers import DefaultRouter -from greg.api.views.consent import ConsentViewSet +from greg.api.views.consent_type import ConsentTypeViewSet from greg.api.views.organizational_unit import OrganizationalUnitViewSet from greg.api.views.person import ( - PersonRoleViewSet, + RoleViewSet, PersonViewSet, PersonIdentityViewSet, ) -from greg.api.views.role import RoleViewSet +from greg.api.views.role_type import RoleTypeViewSet from greg.api.views.sponsor import SponsorViewSet, SponsorGuestsViewSet router = DefaultRouter() router.register(r"persons", PersonViewSet, basename="person") -router.register(r"roles", RoleViewSet, basename="role") -router.register(r"consents", ConsentViewSet, basename="consent") +router.register(r"roletypes", RoleTypeViewSet, basename="roletype") +router.register(r"consenttypes", ConsentTypeViewSet, basename="consenttype") router.register(r"sponsors", SponsorViewSet, basename="sponsor") router.register(r"orgunit", OrganizationalUnitViewSet, basename="orgunit") @@ -26,12 +26,12 @@ urlpatterns = router.urls urlpatterns += [ re_path( r"^persons/(?P<person_id>[0-9]+)/roles/$", - PersonRoleViewSet.as_view({"get": "list", "post": "create"}), + RoleViewSet.as_view({"get": "list", "post": "create"}), name="person_role-list", ), re_path( r"^persons/(?P<person_id>[0-9]+)/roles/(?P<id>[0-9]+)/$", - PersonRoleViewSet.as_view( + RoleViewSet.as_view( {"get": "retrieve", "patch": "partial_update", "delete": "destroy"} ), name="person_role-detail", diff --git a/greg/api/views/consent.py b/greg/api/views/consent.py deleted file mode 100644 index 4996325e7cb9b40ffb64fde25a8d6b374e81d3e6..0000000000000000000000000000000000000000 --- a/greg/api/views/consent.py +++ /dev/null @@ -1,14 +0,0 @@ -from rest_framework import viewsets - -from greg.api.pagination import PrimaryKeyCursorPagination -from greg.api.serializers.consent import ConsentSerializer -from greg.models import Consent - - -class ConsentViewSet(viewsets.ModelViewSet): - """Consent API""" - - queryset = Consent.objects.all().order_by("id") - serializer_class = ConsentSerializer - pagination_class = PrimaryKeyCursorPagination - lookup_field = "id" diff --git a/greg/api/views/consent_type.py b/greg/api/views/consent_type.py new file mode 100644 index 0000000000000000000000000000000000000000..88daf30123463b249f434e94976a2892e22cc12f --- /dev/null +++ b/greg/api/views/consent_type.py @@ -0,0 +1,14 @@ +from rest_framework import viewsets + +from greg.api.pagination import PrimaryKeyCursorPagination +from greg.api.serializers.consent_type import ConsentTypeSerializer +from greg.models import ConsentType + + +class ConsentTypeViewSet(viewsets.ModelViewSet): + """Consent API""" + + queryset = ConsentType.objects.all().order_by("id") + serializer_class = ConsentTypeSerializer + pagination_class = PrimaryKeyCursorPagination + lookup_field = "id" diff --git a/greg/api/views/person.py b/greg/api/views/person.py index bb58842992f4afc293d90a6f7457388046579382..9e342bea3647d15589914dbc19760f5bbb580b4f 100644 --- a/greg/api/views/person.py +++ b/greg/api/views/person.py @@ -4,14 +4,14 @@ from drf_spectacular.utils import extend_schema, OpenApiParameter from rest_framework import viewsets, status from rest_framework.response import Response -from greg.api.filters import PersonFilter, PersonRoleFilter, PersonIdentityFilter +from greg.api.filters import PersonFilter, RoleFilter, PersonIdentityFilter from greg.api.pagination import PrimaryKeyCursorPagination from greg.api.serializers.person import ( PersonSerializer, - PersonRoleSerializer, + RoleSerializer, PersonIdentitySerializer, ) -from greg.models import Person, PersonRole, PersonIdentity +from greg.models import Person, Role, PersonIdentity class PersonViewSet(viewsets.ModelViewSet): @@ -39,14 +39,14 @@ class PersonViewSet(viewsets.ModelViewSet): return super().list(request, *args, **kwargs) -class PersonRoleViewSet(viewsets.ModelViewSet): +class RoleViewSet(viewsets.ModelViewSet): """Person role API""" - queryset = PersonRole.objects.all().order_by("id") - serializer_class = PersonRoleSerializer + queryset = Role.objects.all().order_by("id") + serializer_class = RoleSerializer pagination_class = PrimaryKeyCursorPagination filter_backends = (filters.DjangoFilterBackend,) - filterset_class = PersonRoleFilter + filterset_class = RoleFilter lookup_field = "id" def get_queryset(self): diff --git a/greg/api/views/role.py b/greg/api/views/role.py deleted file mode 100644 index fbfce2fd85e3b515ccbce00cbe9778aa3b7d8994..0000000000000000000000000000000000000000 --- a/greg/api/views/role.py +++ /dev/null @@ -1,14 +0,0 @@ -from rest_framework import viewsets - -from greg.api.pagination import PrimaryKeyCursorPagination -from greg.api.serializers.role import RoleSerializer -from greg.models import Role - - -class RoleViewSet(viewsets.ModelViewSet): - """Role API""" - - queryset = Role.objects.all().order_by("id") - serializer_class = RoleSerializer - pagination_class = PrimaryKeyCursorPagination - lookup_field = "id" diff --git a/greg/api/views/role_type.py b/greg/api/views/role_type.py new file mode 100644 index 0000000000000000000000000000000000000000..cb39712515c5e87325dac0ae3551e3b5399af8ac --- /dev/null +++ b/greg/api/views/role_type.py @@ -0,0 +1,14 @@ +from rest_framework import viewsets + +from greg.api.pagination import PrimaryKeyCursorPagination +from greg.api.serializers.role_type import RoleTypeSerializer +from greg.models import RoleType + + +class RoleTypeViewSet(viewsets.ModelViewSet): + """Role type API""" + + queryset = RoleType.objects.all().order_by("id") + serializer_class = RoleTypeSerializer + pagination_class = PrimaryKeyCursorPagination + lookup_field = "id" diff --git a/greg/api/views/sponsor.py b/greg/api/views/sponsor.py index d88772b523da93de2e60eb1a6cf15c644a298111..6e149fea441514b7d3a58aa2928da00e6d53e080 100644 --- a/greg/api/views/sponsor.py +++ b/greg/api/views/sponsor.py @@ -39,5 +39,5 @@ class SponsorGuestsViewSet(mixins.ListModelMixin, GenericViewSet): if not self.kwargs: return qs.none() sponsor_id = self.kwargs["sponsor_id"] - qs = qs.filter(person_roles__registered_by=sponsor_id).order_by("id") + qs = qs.filter(roles__registered_by=sponsor_id).order_by("id") return qs diff --git a/greg/migrations/0001_initial.py b/greg/migrations/0001_initial.py index 57ab464e0e28796d720fd454be2879facd5ea84a..d6d120a4efcd69a9195173bfdf361b55c9e44df1 100644 --- a/greg/migrations/0001_initial.py +++ b/greg/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.2.5 on 2021-08-23 08:53 +# Generated by Django 3.2.5 on 2021-08-31 10:57 import datetime import dirtyfields.dirtyfields @@ -15,18 +15,18 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='Consent', + name='ConsentType', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created', models.DateTimeField(auto_now_add=True)), ('updated', models.DateTimeField(auto_now=True)), - ('type', models.SlugField(max_length=64, unique=True)), - ('consent_name_en', models.CharField(max_length=256)), - ('consent_name_nb', models.CharField(max_length=256)), - ('consent_description_en', models.TextField()), - ('consent_description_nb', models.TextField()), - ('consent_link_en', models.URLField(null=True)), - ('consent_link_nb', models.URLField(null=True)), + ('identifier', models.SlugField(max_length=64, unique=True)), + ('name_en', models.CharField(max_length=256)), + ('name_nb', models.CharField(max_length=256)), + ('description_en', models.TextField()), + ('description_nb', models.TextField()), + ('link_en', models.URLField(null=True)), + ('link_nb', models.URLField(null=True)), ('valid_from', models.DateField(default=datetime.date.today)), ('user_allowed_to_change', models.BooleanField()), ], @@ -87,12 +87,12 @@ class Migration(migrations.Migration): bases=(dirtyfields.dirtyfields.DirtyFieldsMixin, models.Model), ), migrations.CreateModel( - name='Role', + name='RoleType', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created', models.DateTimeField(auto_now_add=True)), ('updated', models.DateTimeField(auto_now=True)), - ('type', models.SlugField(max_length=64, unique=True)), + ('identifier', models.SlugField(max_length=64, unique=True)), ('name_nb', models.CharField(max_length=256)), ('name_en', models.CharField(max_length=256)), ('description_nb', models.TextField()), @@ -142,7 +142,7 @@ class Migration(migrations.Migration): field=models.ManyToManyField(related_name='sponsor_unit', through='greg.SponsorOrganizationalUnit', to='greg.OrganizationalUnit'), ), migrations.CreateModel( - name='PersonRole', + name='Role', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created', models.DateTimeField(auto_now_add=True)), @@ -152,9 +152,9 @@ class Migration(migrations.Migration): ('contact_person_unit', models.TextField(blank=True)), ('comments', models.TextField(blank=True)), ('available_in_search', models.BooleanField(default=False)), - ('person', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='person_roles', to='greg.person')), + ('person', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='roles', to='greg.person')), ('registered_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='sponsor_role', to='greg.sponsor')), - ('role', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='person_roles', to='greg.role')), + ('type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='persons', to='greg.roletype')), ('unit', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='unit_person_role', to='greg.organizationalunit')), ], bases=(dirtyfields.dirtyfields.DirtyFieldsMixin, models.Model), @@ -174,32 +174,22 @@ class Migration(migrations.Migration): ('verified_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='sponsor', to='greg.sponsor')), ], options={ - 'abstract': False, + 'verbose_name_plural': 'person identities', }, bases=(dirtyfields.dirtyfields.DirtyFieldsMixin, models.Model), ), migrations.CreateModel( - name='PersonConsent', + name='Consent', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created', models.DateTimeField(auto_now_add=True)), ('updated', models.DateTimeField(auto_now=True)), ('consent_given_at', models.DateField(null=True)), - ('consent', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='link_person_consent', to='greg.consent')), - ('person', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='link_person_consent', to='greg.person')), + ('person', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='consents', to='greg.person')), + ('type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='persons', to='greg.consenttype')), ], bases=(dirtyfields.dirtyfields.DirtyFieldsMixin, models.Model), ), - migrations.AddField( - model_name='person', - name='consents', - field=models.ManyToManyField(related_name='consent', through='greg.PersonConsent', to='greg.Consent'), - ), - migrations.AddField( - model_name='person', - name='roles', - field=models.ManyToManyField(related_name='persons', through='greg.PersonRole', to='greg.Role'), - ), migrations.AddConstraint( model_name='sponsororganizationalunit', constraint=models.UniqueConstraint(fields=('sponsor', 'organizational_unit'), name='sponsor_organizational_unit_unique'), @@ -209,15 +199,15 @@ class Migration(migrations.Migration): constraint=models.UniqueConstraint(fields=('feide_id',), name='unique_feide_id'), ), migrations.AddConstraint( - model_name='personrole', - constraint=models.UniqueConstraint(fields=('person_id', 'role_id', 'unit_id', 'start_date', 'end_date'), name='person_role_unique'), - ), - migrations.AddConstraint( - model_name='personconsent', - constraint=models.UniqueConstraint(fields=('person', 'consent'), name='person_consent_unique'), + model_name='role', + constraint=models.UniqueConstraint(fields=('person_id', 'type_id', 'unit_id', 'start_date', 'end_date'), name='person_role_type_unique'), ), migrations.AddConstraint( model_name='organizationalunit', constraint=models.UniqueConstraint(fields=('orgreg_id',), name='unique_orgreg_id'), ), + migrations.AddConstraint( + model_name='consent', + constraint=models.UniqueConstraint(fields=('person', 'type'), name='person_consent_type_unique'), + ), ] diff --git a/greg/migrations/0002_auto_20210827_1437.py b/greg/migrations/0002_auto_20210827_1437.py deleted file mode 100644 index db4be5644728b585677111dd9a127c568fd6df4e..0000000000000000000000000000000000000000 --- a/greg/migrations/0002_auto_20210827_1437.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 3.2.5 on 2021-08-27 14:37 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('greg', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='personconsent', - name='consent', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='person_consent', to='greg.consent'), - ), - migrations.AlterField( - model_name='personconsent', - name='person', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='person_consent', to='greg.person'), - ), - ] diff --git a/greg/models.py b/greg/models.py index 2571bba1084c9198397ddd87a303321076cbd5bb..89b98116868821320d64c851b1708e78b8f2a596 100644 --- a/greg/models.py +++ b/greg/models.py @@ -44,10 +44,6 @@ class Person(BaseModel): mobile_phone_verified_date = models.DateField(null=True) registration_completed_date = models.DateField(null=True) token = models.CharField(max_length=32, blank=True) - roles = models.ManyToManyField("Role", through="PersonRole", related_name="persons") - consents = models.ManyToManyField( - "Consent", through="PersonConsent", related_name="consent" - ) def __str__(self): return "{} {} ({})".format(self.first_name, self.last_name, self.pk) @@ -120,10 +116,10 @@ class Person(BaseModel): ) -class Role(BaseModel): +class RoleType(BaseModel): """A role variant.""" - type = models.SlugField(max_length=64, unique=True) + identifier = models.SlugField(max_length=64, unique=True) name_nb = models.CharField(max_length=256) name_en = models.CharField(max_length=256) description_nb = models.TextField() @@ -131,26 +127,24 @@ class Role(BaseModel): default_duration_days = models.IntegerField(null=True) def __str__(self): - return str(self.name_nb or self.name_en) + return "{} ({})".format(str(self.name_en or self.name_nb), self.identifier) def __repr__(self): - return "{}(id={!r}, type={!r}, name_nb={!r}, name_en={!r})".format( + return "{}(pk={!r}, identifier={!r}, name_nb={!r}, name_en={!r})".format( self.__class__.__name__, self.pk, - self.type, + self.identifier, self.name_nb, self.name_en, ) -class PersonRole(BaseModel): +class Role(BaseModel): """The relationship between a person and a role.""" - person = models.ForeignKey( - "Person", on_delete=models.CASCADE, related_name="person_roles" - ) - role = models.ForeignKey( - "Role", on_delete=models.PROTECT, related_name="person_roles" + person = models.ForeignKey("Person", on_delete=models.CASCADE, related_name="roles") + type = models.ForeignKey( + "RoleType", on_delete=models.PROTECT, related_name="persons" ) unit = models.ForeignKey( "OrganizationalUnit", on_delete=models.PROTECT, related_name="unit_person_role" @@ -169,14 +163,14 @@ class PersonRole(BaseModel): class Meta: constraints = [ models.UniqueConstraint( - fields=["person_id", "role_id", "unit_id", "start_date", "end_date"], - name="person_role_unique", + fields=["person_id", "type_id", "unit_id", "start_date", "end_date"], + name="person_role_type_unique", ) ] def __repr__(self): - return "{}(id={!r}, person={!r}, role={!r})".format( - self.__class__.__name__, self.pk, self.person, self.role + return "{}(id={!r}, person={!r}, type={!r})".format( + self.__class__.__name__, self.pk, self.person, self.type ) @@ -240,43 +234,49 @@ class PersonIdentity(BaseModel): self.verified_when, ) + class Meta: + verbose_name_plural = "person identities" -class Consent(BaseModel): + +class ConsentType(BaseModel): """ Describes some consent, like acknowledging the IT department guidelines, a guest can give. """ - type = models.SlugField(max_length=64, unique=True) - consent_name_en = models.CharField(max_length=256) - consent_name_nb = models.CharField(max_length=256) - consent_description_en = models.TextField() - consent_description_nb = models.TextField() - consent_link_en = models.URLField(null=True) - consent_link_nb = models.URLField(null=True) + identifier = models.SlugField(max_length=64, unique=True) + name_en = models.CharField(max_length=256) + name_nb = models.CharField(max_length=256) + description_en = models.TextField() + description_nb = models.TextField() + link_en = models.URLField(null=True) + link_nb = models.URLField(null=True) valid_from = models.DateField(default=date.today) user_allowed_to_change = models.BooleanField() + def __str__(self): + return "{} ({})".format(str(self.name_en or self.name_nb), self.identifier) + def __repr__(self): - return "{}(id={!r}, type={!r}, consent_name_en={!r}, valid_from={!r}, user_allowed_to_change={!r})".format( + return "{}(id={!r}, identifier={!r}, name_en={!r}, valid_from={!r}, user_allowed_to_change={!r})".format( self.__class__.__name__, self.pk, - self.type, - self.consent_name_en, + self.identifier, + self.name_en, self.valid_from, self.user_allowed_to_change, ) -class PersonConsent(BaseModel): +class Consent(BaseModel): """ Links a person and a consent he has given. """ person = models.ForeignKey( - "Person", on_delete=models.CASCADE, related_name="person_consent" + "Person", on_delete=models.CASCADE, related_name="consents" ) - consent = models.ForeignKey( - "Consent", on_delete=models.PROTECT, related_name="person_consent" + type = models.ForeignKey( + "ConsentType", on_delete=models.PROTECT, related_name="persons" ) # If the date is blank it means the person has not given consent yet consent_given_at = models.DateField(null=True) @@ -284,16 +284,16 @@ class PersonConsent(BaseModel): class Meta: constraints = [ models.UniqueConstraint( - fields=["person", "consent"], name="person_consent_unique" + fields=["person", "type"], name="person_consent_type_unique" ) ] def __repr__(self): - return "{}(id={!r}, person={!r}, consent={!r}, consent_given_at={!r})".format( + return "{}(id={!r}, person={!r}, type={!r}, consent_given_at={!r})".format( self.__class__.__name__, self.pk, self.person, - self.consent, + self.type, self.consent_given_at, ) @@ -313,6 +313,9 @@ class OrganizationalUnit(BaseModel): self.__class__.__name__, self.pk, self.orgreg_id, self.name_en, self.parent ) + def __str__(self): + return "{} ({})".format(str(self.name_en or self.name_nb), self.orgreg_id) + class Meta: constraints = [ models.UniqueConstraint(name="unique_orgreg_id", fields=["orgreg_id"]) @@ -334,6 +337,9 @@ class Sponsor(BaseModel): related_name="sponsor_unit", ) + def __str__(self): + return "{} ({} {})".format(self.feide_id, self.first_name, self.last_name) + def __repr__(self): return "{}(id={!r}, feide_id={!r}, first_name={!r}, last_name={!r})".format( self.__class__.__name__, diff --git a/greg/schedule.py b/greg/schedule.py index e9a907e36be35fd8c55d6ff7fc215c468c01731d..ee08c9a79ce2285b1d7189ce9cbfcf7d000713c9 100644 --- a/greg/schedule.py +++ b/greg/schedule.py @@ -5,7 +5,7 @@ from typing import Optional from abc import ABC, abstractmethod from django.utils import timezone -from greg.models import PersonRole, Notification, ScheduleTask +from greg.models import Role, Notification, ScheduleTask class BaseSchedule(ABC): @@ -77,12 +77,12 @@ class ExpiringRolesNotification(BaseSchedule): self.__get_roles_about_to_expire(check_date) def __get_roles_about_to_expire(self, end_date: date): - roles_about_to_expire = PersonRole.objects.filter(end_date=end_date) + roles_about_to_expire = Role.objects.filter(end_date=end_date) - for person_role in roles_about_to_expire: - meta = {"person_id": person_role.person.id, "role_id": person_role.role.id} + for role in roles_about_to_expire: + meta = {"person_id": role.person.id, "type_id": role.type.id} self._store_notification( - identifier=person_role.id, + identifier=role.id, object_type="PersonRole", operation="expire_reminder", **meta diff --git a/greg/signals.py b/greg/signals.py index e1d0f60c7abab9bd97d0c988a5e6e46ea6d4037d..b9fcde01d6292c097009a3633557f332db85fb88 100644 --- a/greg/signals.py +++ b/greg/signals.py @@ -7,22 +7,22 @@ from django.dispatch import receiver from greg.models import ( Person, - PersonRole, Role, + RoleType, Notification, PersonIdentity, - PersonConsent, Consent, + ConsentType, ) logger = logging.getLogger(__name__) SUPPORTED_MODELS = ( Person, - PersonRole, Role, + RoleType, PersonIdentity, - PersonConsent, + Consent, ) @@ -123,20 +123,20 @@ def m2m_changed_notification_callback( ): if action not in ("post_add", "post_remove"): return - if sender not in (PersonConsent, PersonRole, PersonIdentity): + if sender not in (Consent, Role, PersonIdentity): return operation = "add" if action == "post_add" else "delete" instance_type = type(instance) - if sender is PersonConsent: + if sender is Consent: person_consents = [] - if instance_type is Person and model is Consent: - person_consents = PersonConsent.objects.filter( + if instance_type is Person and model is ConsentType: + person_consents = Consent.objects.filter( person_id=instance.id, consent_id__in=pk_set ) - elif instance_type is Consent and model is Person: - person_consents = PersonConsent.objects.filter( + elif instance_type is ConsentType and model is Person: + person_consents = Consent.objects.filter( consent_id=instance.id, person_id__in=pk_set ) @@ -144,26 +144,22 @@ def m2m_changed_notification_callback( meta = _create_metadata(pc) _store_notification( identifier=pc.id, - object_type=PersonConsent._meta.object_name, + object_type=Consent._meta.object_name, operation=operation, **meta ) - elif sender is PersonRole: - person_roles = [] - if instance_type is Person and model is Role: - person_roles = PersonRole.objects.filter( - person_id=instance.id, role_id__in=pk_set - ) - elif instance_type is Role and model is Person: - person_roles = PersonRole.objects.filter( - role_id=instance.id, person_id__in=pk_set - ) - - for pr in person_roles: + elif sender is Role: + roles = [] + if instance_type is Person and model is RoleType: + roles = Role.objects.filter(person_id=instance.id, role_id__in=pk_set) + elif instance_type is RoleType and model is Person: + roles = Role.objects.filter(role_id=instance.id, person_id__in=pk_set) + + for pr in roles: meta = _create_metadata(pr) _store_notification( identifier=pr.id, - object_type=PersonRole._meta.object_name, + object_type=Role._meta.object_name, operation=operation, **meta ) @@ -172,14 +168,14 @@ def m2m_changed_notification_callback( def _create_metadata(instance) -> Dict: meta = {} - if isinstance(instance, PersonRole): + if isinstance(instance, Role): meta["person_id"] = instance.person.id - meta["role_id"] = instance.role.id + meta["type_id"] = instance.type.id if isinstance(instance, PersonIdentity): meta["person_id"] = instance.person.id meta["identity_id"] = instance.id - if isinstance(instance, PersonConsent): + if isinstance(instance, Consent): meta["person_id"] = instance.person.id - meta["consent_id"] = instance.consent.id + meta["consent_id"] = instance.type.id return meta diff --git a/greg/tests/api/test_consent.py b/greg/tests/api/test_consent.py deleted file mode 100644 index dd59ad52e5a87aa7eb7b16d13aeae765eb72e532..0000000000000000000000000000000000000000 --- a/greg/tests/api/test_consent.py +++ /dev/null @@ -1,30 +0,0 @@ -import pytest -from rest_framework import status -from rest_framework.reverse import reverse - -from greg.models import Consent - - -@pytest.fixture -def consent_foo() -> Consent: - return Consent.objects.create( - type="test_consent", - consent_name_en="Test1", - consent_name_nb="Test2", - consent_description_en="Test description", - consent_description_nb="Test beskrivelse", - consent_link_en="https://example.org", - consent_link_nb="https://example.org", - valid_from="2018-01-20", - user_allowed_to_change=True, - ) - - -@pytest.mark.django_db -def test_get_consent(client, consent_foo): - resp = client.get(reverse("v1:consent-detail", kwargs={"id": consent_foo.id})) - assert resp.status_code == status.HTTP_200_OK - data = resp.json() - assert data.get("id") == consent_foo.id - assert data.get("type") == consent_foo.type - assert data.get("consent_name_en") == consent_foo.consent_name_en diff --git a/greg/tests/api/test_consent_type.py b/greg/tests/api/test_consent_type.py new file mode 100644 index 0000000000000000000000000000000000000000..e2eaf0f45dff1eff082604f0b554921b4574ff56 --- /dev/null +++ b/greg/tests/api/test_consent_type.py @@ -0,0 +1,32 @@ +import pytest +from rest_framework import status +from rest_framework.reverse import reverse + +from greg.models import ConsentType + + +@pytest.fixture +def consent_type_foo() -> ConsentType: + return ConsentType.objects.create( + identifier="test_consent", + name_en="Test1", + name_nb="Test2", + description_en="Test description", + description_nb="Test beskrivelse", + link_en="https://example.org", + link_nb="https://example.org", + valid_from="2018-01-20", + user_allowed_to_change=True, + ) + + +@pytest.mark.django_db +def test_get_consent_type(client, consent_type_foo: ConsentType): + resp = client.get( + reverse("v1:consenttype-detail", kwargs={"id": consent_type_foo.id}) + ) + assert resp.status_code == status.HTTP_200_OK + data = resp.json() + assert data.get("id") == consent_type_foo.id + assert data.get("identifier") == consent_type_foo.identifier + assert data.get("name_en") == consent_type_foo.name_en diff --git a/greg/tests/api/test_person.py b/greg/tests/api/test_person.py index 772c6ee546a8823dc339d19b12495ffe1008a0c6..f7442c3a09e2597fc634d83d28da9779e7dd3d12 100644 --- a/greg/tests/api/test_person.py +++ b/greg/tests/api/test_person.py @@ -10,18 +10,18 @@ from django.core.exceptions import ValidationError from greg.models import ( PersonIdentity, Sponsor, - Role, + RoleType, OrganizationalUnit, - Consent, + ConsentType, Person, - PersonRole, + Role, ) @pytest.fixture -def role_visiting_professor() -> Role: - return Role.objects.create( - type="visiting_professor", +def role_type_visiting_professor() -> RoleType: + return RoleType.objects.create( + identifier="visiting_professor", name_nb="Gjesteprofessor", name_en="Visiting professor", description_nb="Gjesteprofessor", @@ -44,10 +44,10 @@ def sponsor_bar() -> Sponsor: @pytest.fixture def role_data_guest( - role_test_guest: Role, sponsor_bar: Sponsor, unit_foo: OrganizationalUnit + role_type_test_guest: RoleType, sponsor_bar: Sponsor, unit_foo: OrganizationalUnit ) -> Dict: return { - "role": "Test Guest", + "type": "Test Guest", "start_date": "2021-06-10", "end_date": "2021-08-10", "registered_by": sponsor_bar.id, @@ -56,15 +56,15 @@ def role_data_guest( @pytest.fixture -def consent_foo() -> Consent: - return Consent.objects.create( - type="test_consent", - consent_name_en="Test1", - consent_name_nb="Test2", - consent_description_en="Test description", - consent_description_nb="Test beskrivelse", - consent_link_en="https://example.org", - consent_link_nb="https://example.org", +def consent_foo() -> ConsentType: + return ConsentType.objects.create( + identifier="test_consent", + name_en="Test1", + name_nb="Test2", + description_en="Test description", + description_nb="Test beskrivelse", + link_en="https://example.org", + link_nb="https://example.org", valid_from="2018-01-20", user_allowed_to_change=True, ) @@ -114,7 +114,7 @@ def test_persons_verified_filter_exclude( @pytest.mark.django_db def test_add_role( - client, person_foo, role_visiting_professor, sponsor_guy, unit_human_resources + client, person_foo, role_type_visiting_professor, sponsor_guy, unit_human_resources ): url = reverse("v1:person_role-list", kwargs={"person_id": person_foo.id}) roles_for_person = client.get(url).json()["results"] @@ -123,7 +123,7 @@ def test_add_role( assert len(roles_for_person) == 0 role_data = { - "role": "visiting_professor", + "type": "visiting_professor", "start_date": "2021-06-10", "end_date": "2021-08-10", "registered_by": "1", @@ -398,16 +398,14 @@ def test_remove_person( @pytest.mark.django_db -def test_add_duplicate_role_fails( - client, person_foo: Person, person_foo_role: PersonRole -): +def test_add_duplicate_role_fails(client, person_foo: Person, person_foo_role: Role): url = reverse("v1:person_role-list", kwargs={"person_id": person_foo.id}) roles_for_person = client.get(url).json()["results"] assert len(roles_for_person) == 1 role_data = { - "role": person_foo_role.role_id, + "type": person_foo_role.type_id, "start_date": person_foo_role.start_date, "end_date": person_foo_role.end_date, "registered_by": person_foo_role.registered_by, diff --git a/greg/tests/conftest.py b/greg/tests/conftest.py index 63646efdd9947cd04f5ec31079c855447e8b73b2..bf70862847668e3623708bdd7bfaf35f9bab9d5a 100644 --- a/greg/tests/conftest.py +++ b/greg/tests/conftest.py @@ -11,8 +11,8 @@ from greg.models import ( Sponsor, PersonIdentity, Role, + RoleType, OrganizationalUnit, - PersonRole, ) # faker spams the logs with localisation warnings @@ -82,8 +82,8 @@ def person_foo_not_verified(person_foo) -> PersonIdentity: @pytest.fixture() -def role_test_guest() -> Role: - return Role.objects.create(type="Test Guest") +def role_type_test_guest() -> RoleType: + return RoleType.objects.create(identifier="Test Guest") @pytest.fixture @@ -94,13 +94,13 @@ def unit_foo() -> OrganizationalUnit: @pytest.fixture def person_foo_role( person_foo: Person, - role_test_guest: Role, + role_type_test_guest: RoleType, sponsor_guy: Sponsor, unit_foo: OrganizationalUnit, -) -> PersonRole: - return PersonRole.objects.create( +) -> Role: + return Role.objects.create( person=person_foo, - role=role_test_guest, + type=role_type_test_guest, start_date="2021-08-02", end_date="2021-08-06", registered_by=sponsor_guy, diff --git a/greg/tests/models/test_consent.py b/greg/tests/models/test_consent.py index 8f7711e08ff37e9e20dc7f8ce9eacca45f51ce34..df6c6483b70fc0db99811dfb3d79b6387cba5b87 100644 --- a/greg/tests/models/test_consent.py +++ b/greg/tests/models/test_consent.py @@ -4,8 +4,8 @@ import pytest from greg.models import ( Person, + ConsentType, Consent, - PersonConsent, ) @@ -21,35 +21,40 @@ def person() -> Person: @pytest.fixture() -def consent() -> Consent: - return Consent.objects.create( - type="it_guidelines", - consent_name_en="IT Guidelines", - consent_name_nb="IT Regelverk", - consent_description_en="IT Guidelines description", - consent_description_nb="IT Regelverk beskrivelse", - consent_link_en="https://example.org/it_guidelines", +def consent_type() -> ConsentType: + return ConsentType.objects.create( + identifier="it-guidelines", + name_en="IT Guidelines", + name_nb="IT Regelverk", + description_en="IT Guidelines description", + description_nb="IT Regelverk beskrivelse", + link_en="https://example.org/it-guidelines", + link_nb="https://example.org/it-guidelines", user_allowed_to_change=False, ) @pytest.mark.django_db -def test_add_consent_to_person(person: Person, consent: Consent): +def test_add_consent_to_person(person: Person, consent_type: ConsentType): consent_given_date = "2021-06-20" - person.consents.add(consent, through_defaults={"consent_given_at": consent_given_date}) # type: ignore - person_consent_links = PersonConsent.objects.filter(person_id=person.id) + Consent.objects.create( + person=person, type=consent_type, consent_given_at=consent_given_date + ) + consents = Consent.objects.filter(person_id=person.id) - assert len(person_consent_links) == 1 - assert person_consent_links[0].person_id == person.id - assert person_consent_links[0].consent_id == consent.id - assert person_consent_links[0].consent_given_at == datetime.date(2021, 6, 20) + assert len(consents) == 1 + assert consents[0].person_id == person.id + assert consents[0].type_id == consent_type.id + assert consents[0].consent_given_at == datetime.date(2021, 6, 20) @pytest.mark.django_db -def test_add_not_acknowledged_consent_to_person(person: Person, consent: Consent): - person.consents.add(consent) - person_consent_links = PersonConsent.objects.filter(person_id=person.id) - assert len(person_consent_links) == 1 - assert person_consent_links[0].person_id == person.id - assert person_consent_links[0].consent_id == consent.id - assert person_consent_links[0].consent_given_at is None +def test_add_not_acknowledged_consent_to_person( + person: Person, consent_type: ConsentType +): + Consent.objects.create(person=person, type=consent_type) + consents = Consent.objects.filter(person_id=person.id) + assert len(consents) == 1 + assert consents[0].person_id == person.id + assert consents[0].type_id == consent_type.id + assert consents[0].consent_given_at is None diff --git a/greg/tests/models/test_person.py b/greg/tests/models/test_person.py index 87455763326c84b814830ceb84f00f52c9b869fa..52b0fd337abf739f528bf3f61bb9eb1c6b3a6703 100644 --- a/greg/tests/models/test_person.py +++ b/greg/tests/models/test_person.py @@ -10,13 +10,13 @@ from greg.models import ( OrganizationalUnit, Person, PersonIdentity, - PersonRole, Role, + RoleType, Sponsor, ) -person_role_with = partial( - PersonRole.objects.create, +role_with = partial( + Role.objects.create, start_date="2020-03-05", end_date="2020-06-10", contact_person_unit="Contact Person", @@ -25,17 +25,17 @@ person_role_with = partial( @pytest.fixture -def role_foo() -> Role: - return Role.objects.create(type="role_foo", name_en="Role Foo") +def role_type_foo() -> RoleType: + return RoleType.objects.create(identifier="role_foo", name_en="Role Foo") @pytest.fixture -def role_bar() -> Role: - return Role.objects.create(type="role_bar", name_en="Role Bar") +def role_type_bar() -> RoleType: + return RoleType.objects.create(identifier="role_bar", name_en="Role Bar") @pytest.fixture -def person(role_foo: Role, role_bar: Role) -> Person: +def person(role_type_foo: RoleType, role_type_bar: RoleType) -> Person: person = Person.objects.create( first_name="Test", last_name="Tester", @@ -43,21 +43,6 @@ def person(role_foo: Role, role_bar: Role) -> Person: email="test@example.org", mobile_phone="123456789", ) - - ou = OrganizationalUnit.objects.create(orgreg_id="12345", name_en="Test unit") - person_role_with( - person=person, - role=role_foo, - unit=ou, - registered_by=Sponsor.objects.create(feide_id="foosponsor@uio.no"), - ) - person_role_with( - person=person, - role=role_bar, - unit=ou, - registered_by=Sponsor.objects.create(feide_id="barsponsor@uio.no"), - ) - return person @@ -107,11 +92,23 @@ def feide_verified(person: Person, feide_id: PersonIdentity) -> Person: @pytest.mark.django_db -def test_add_multiple_roles_to_person(person, role_foo, role_bar): - person_roles = person.roles.all() - assert len(person_roles) == 2 - assert role_foo in person_roles - assert role_bar in person_roles +def test_add_multiple_roles_to_person( + person: Person, role_type_foo: RoleType, role_type_bar: RoleType +): + ou = OrganizationalUnit.objects.create(orgreg_id="12345", name_en="Test unit") + role_with( + person=person, + type=role_type_foo, + unit=ou, + registered_by=Sponsor.objects.create(feide_id="foosponsor@uio.no"), + ) + role_with( + person=person, + type=role_type_bar, + unit=ou, + registered_by=Sponsor.objects.create(feide_id="barsponsor@uio.no"), + ) + assert person.roles.count() == 2 @pytest.mark.django_db diff --git a/greg/tests/populate_database.py b/greg/tests/populate_database.py index 1dd064aabab4ffaea36a2546180f7ce6a3f310e8..38103ad354ed965230c3d66bb6df49e7f2d9a4fd 100644 --- a/greg/tests/populate_database.py +++ b/greg/tests/populate_database.py @@ -1,16 +1,18 @@ import random from typing import List, TypeVar -from django.db import connection, IntegrityError +from django.db import IntegrityError, connection from faker import Faker + from greg.models import ( + Consent, + ConsentType, + OrganizationalUnit, Person, + PersonIdentity, Role, - OrganizationalUnit, + RoleType, Sponsor, - PersonRole, - Consent, - PersonIdentity, ) R = TypeVar("R") @@ -28,8 +30,8 @@ class DatabasePopulation: persons: List[Person] = [] units: List[OrganizationalUnit] = [] sponsors: List[Sponsor] = [] - role_types: List[Role] = [] - consents: List[Consent] = [] + role_types: List[RoleType] = [] + consent_types: List[ConsentType] = [] random: random.Random def __init__(self, set_seed_to_zero=True): @@ -62,7 +64,7 @@ class DatabasePopulation: for role_type in ("Visiting Professor", "Professor Emeritus", "Consultant"): self.role_types.append( - Role.objects.create(type=role_type, name_en=role_type) + RoleType.objects.create(identifier=role_type, name_en=role_type) ) for i in range(10): @@ -80,14 +82,15 @@ class DatabasePopulation: ) for i in range(10): - self.consents.append( - Consent.objects.create( - type=self.faker.slug(), - consent_name_en=self.faker.sentence(nb_words=6), - consent_name_nb=self.faker.sentence(nb_words=6), - consent_description_en=self.faker.paragraph(nb_sentences=5), - consent_description_nb=self.faker.paragraph(nb_sentences=5), - consent_link_en=self.faker.url(), + self.consent_types.append( + ConsentType.objects.create( + identifier=self.faker.slug(), + name_en=self.faker.sentence(nb_words=6), + name_nb=self.faker.sentence(nb_words=6), + description_en=self.faker.paragraph(nb_sentences=5), + description_nb=self.faker.paragraph(nb_sentences=5), + link_en=self.faker.url(), + link_nb=self.faker.url(), user_allowed_to_change=self.random.random() > 0.5, ) ) @@ -100,17 +103,13 @@ class DatabasePopulation: def __add_random_person_identification_connections(self, connections_to_create=5): person_identifier_count = 0 while person_identifier_count < connections_to_create: - person = self.get_random_element_from_list(self.persons) - identity_type = self.get_random_element_from_list( - PersonIdentity.IdentityType.choices - )[0] + person = random.choice(self.persons) + identity_type = random.choice(PersonIdentity.IdentityType.choices)[0] if self.random.random() > 0.5: - sponsor = self.get_random_element_from_list(self.sponsors) + sponsor = random.choice(self.sponsors) verified_when = self.faker.date_this_year() - identity_type = self.get_random_element_from_list( - PersonIdentity.IdentityType.choices - )[0] + identity_type = random.choice(PersonIdentity.IdentityType.choices)[0] verified = self.faker.text(max_nb_chars=50) else: sponsor = None @@ -132,8 +131,8 @@ class DatabasePopulation: def __add_random_sponsor_unit_connections(self, connections_to_create=5): sponsor_unit_count = 0 while sponsor_unit_count < connections_to_create: - sponsor = self.get_random_element_from_list(self.sponsors) - unit = self.get_random_element_from_list(self.units) + sponsor = random.choice(self.sponsors) + unit = random.choice(self.units) sponsor.units.add( unit, @@ -145,17 +144,17 @@ class DatabasePopulation: person_role_count = 0 while person_role_count < connections_to_create: try: - PersonRole.objects.create( - person=self.get_random_element_from_list(self.persons), - role=self.get_random_element_from_list(self.role_types), - unit=self.get_random_element_from_list(self.units), + Role.objects.create( + person=random.choice(self.persons), + type=random.choice(self.role_types), + unit=random.choice(self.units), start_date=self.faker.date_this_decade(), end_date=self.faker.date_this_decade( before_today=False, after_today=True ), contact_person_unit=self.faker.name(), available_in_search=self.random.random() > 0.5, - registered_by=self.get_random_element_from_list(self.sponsors), + registered_by=random.choice(self.sponsors), ) person_role_count += 1 except IntegrityError: @@ -166,34 +165,31 @@ class DatabasePopulation: def __add_random_person_consent_connections(self, number_of_connections_to_make=5): person_consent_count = 0 while person_consent_count < number_of_connections_to_make: - person = self.get_random_element_from_list(self.persons) - consent = self.get_random_element_from_list(self.consents) - - person.consents.add( - consent, - through_defaults={"consent_given_at": self.faker.date_this_decade()}, + person = random.choice(self.persons) + consent_type = random.choice(self.consent_types) + Consent.objects.create( + person=person, + type=consent_type, + consent_given_at=self.faker.date_this_decade(), ) person_consent_count += 1 def truncate_tables(self): with connection.cursor() as cursor: for table in ( - "greg_personconsent", "greg_consent", + "greg_consenttype", "greg_notification", "greg_personidentity", - "greg_personrole", "greg_person", "greg_sponsororganizationalunit", "greg_sponsor", "greg_organizationalunit", "greg_role", + "greg_roletype", ): cursor.execute(f"DELETE FROM {table}") - def get_random_element_from_list(self, input_list: List[R]) -> R: - return input_list[self.random.randint(0, len(input_list) - 1)] - if __name__ == "__main__": database_population = DatabasePopulation() diff --git a/greg/tests/test_expire_role.py b/greg/tests/test_expire_role.py index d116eb92c8342fc4019872cca27dad4e00254116..b1a45bd4f62b7409347ccbfecce7270681d2fd26 100644 --- a/greg/tests/test_expire_role.py +++ b/greg/tests/test_expire_role.py @@ -6,10 +6,10 @@ from django.utils import timezone from greg.models import ( ScheduleTask, - Role, + RoleType, Person, OrganizationalUnit, - PersonRole, + Role, Notification, Sponsor, ) @@ -24,12 +24,12 @@ def role_task(): @pytest.fixture -def role_bar() -> Role: - return Role.objects.create(type="role_bar", name_en="Role Bar") +def role_type_bar() -> RoleType: + return RoleType.objects.create(identifier="role_bar", name_en="Role Bar") @pytest.fixture -def person(role_bar: Role) -> Person: +def person() -> Person: return Person.objects.create( first_name="Test", last_name="Tester", @@ -50,15 +50,15 @@ def sponsor() -> Sponsor: @pytest.fixture -def person_role( +def role( person: Person, - role_bar: Role, + role_type_bar: RoleType, organizational_unit: OrganizationalUnit, sponsor: Sponsor, -) -> PersonRole: - return PersonRole.objects.create( +) -> Role: + return Role.objects.create( person=person, - role=role_bar, + type=role_type_bar, unit=organizational_unit, start_date="2020-03-05", end_date=datetime.today() + timedelta(days=30), @@ -69,12 +69,12 @@ def person_role( @pytest.mark.django_db -def test_role_picked_up(role_task: ScheduleTask, person_role: PersonRole): +def test_role_picked_up(role_task: ScheduleTask, role: Role): role_notification = ExpiringRolesNotification() assert len(Notification.objects.filter(~Q(operation="add"))) == 0 role_notification.run() notification = Notification.objects.get(operation="expire_reminder") - assert notification.identifier == person_role.id + assert notification.identifier == role.id role_notification.run() notifications = Notification.objects.filter(operation="expire_reminder") assert len(notifications) == 1 @@ -82,10 +82,10 @@ def test_role_picked_up(role_task: ScheduleTask, person_role: PersonRole): @pytest.mark.django_db def test_no_notification_for_role_not_about_to_expire( - role_task: ScheduleTask, person_role: PersonRole + role_task: ScheduleTask, role: Role ): - person_role.end_date = datetime.today() + timedelta(days=31) - person_role.save() + role.end_date = datetime.today() + timedelta(days=31) + role.save() role_notification = ExpiringRolesNotification() assert len(Notification.objects.filter(operation="expire_reminder")) == 0 # Role should not be picked up since it expires in 31 days diff --git a/greg/tests/test_notifications.py b/greg/tests/test_notifications.py index 584858f9337cbf6b6054c9ddce946ddb57095232..88437f6cda911e29697592aa0012ccc56e5317cb 100644 --- a/greg/tests/test_notifications.py +++ b/greg/tests/test_notifications.py @@ -1,14 +1,15 @@ import pytest from greg.models import ( - Person, - Notification, Consent, - Role, + ConsentType, + Notification, OrganizationalUnit, - Sponsor, - PersonConsent, + Person, PersonIdentity, + Role, + RoleType, + Sponsor, ) @@ -24,8 +25,8 @@ def person() -> Person: @pytest.fixture -def role_foo() -> Role: - return Role.objects.create(type="role_foo", name_en="Role Foo") +def role_type_foo() -> RoleType: + return RoleType.objects.create(identifier="role_foo", name_en="Role Foo") @pytest.fixture @@ -39,14 +40,15 @@ def sponsor() -> Sponsor: @pytest.fixture -def consent() -> Consent: - return Consent.objects.create( - type="it_guidelines", - consent_name_en="IT Guidelines", - consent_name_nb="IT Regelverk", - consent_description_en="IT Guidelines description", - consent_description_nb="IT Regelverk beskrivelse", - consent_link_en="https://example.org/it_guidelines", +def consent_type() -> ConsentType: + return ConsentType.objects.create( + identifier="it-guidelines", + name_en="IT Guidelines", + name_nb="IT Regelverk", + description_en="IT Guidelines description", + description_nb="IT Regelverk beskrivelse", + link_en="https://example.org/it-guidelines", + link_nb="https://example.org/it-guidelines", user_allowed_to_change=False, ) @@ -91,115 +93,125 @@ def test_person_delete_notification(person: Person): @pytest.mark.django_db def test_role_add_notification( - person: Person, role_foo: Role, org_unit_bar: OrganizationalUnit, sponsor: Sponsor + person: Person, + role_type_foo: RoleType, + org_unit_bar: OrganizationalUnit, + sponsor: Sponsor, ): - person.roles.add( # type: ignore - role_foo, - through_defaults={ - "start_date": "2021-05-06", - "end_date": "2021-10-20", - "unit": org_unit_bar, - "registered_by": sponsor, - }, + Role.objects.create( + person=person, + type=role_type_foo, + start_date="2021-05-06", + end_date="2021-10-20", + unit=org_unit_bar, + registered_by=sponsor, ) - notifications = Notification.objects.filter(object_type="PersonRole") + notifications = Notification.objects.filter(object_type="Role") assert len(notifications) == 1 assert notifications[0].operation == "add" meta_data = notifications[0].meta assert meta_data["person_id"] == person.id - assert meta_data["role_id"] == role_foo.id + assert meta_data["type_id"] == role_type_foo.id @pytest.mark.django_db def test_role_update_notification( - person: Person, role_foo: Role, org_unit_bar: OrganizationalUnit, sponsor: Sponsor + person: Person, + role_type_foo: RoleType, + org_unit_bar: OrganizationalUnit, + sponsor: Sponsor, ): - person.roles.add( # type: ignore - role_foo, - through_defaults={ - "start_date": "2021-05-06", - "end_date": "2021-10-20", - "unit": org_unit_bar, - "registered_by": sponsor, - }, + Role.objects.create( + person=person, + type=role_type_foo, + start_date="2021-05-06", + end_date="2021-10-20", + unit=org_unit_bar, + registered_by=sponsor, ) - - assert len(person.person_roles.all()) == 1 - person_role = person.person_roles.all()[0] + assert len(person.roles.all()) == 1 + person_role = person.roles.all()[0] person_role.end_date = "2021-10-21" person_role.save() - notifications = Notification.objects.filter(object_type="PersonRole") + notifications = Notification.objects.filter(object_type="Role") assert len(notifications) == 2 assert notifications[1].operation == "update" meta_data = notifications[1].meta assert meta_data["person_id"] == person.id - assert meta_data["role_id"] == role_foo.id + assert meta_data["type_id"] == role_type_foo.id @pytest.mark.django_db def test_role_delete_notification( - person: Person, role_foo: Role, org_unit_bar: OrganizationalUnit, sponsor: Sponsor + person: Person, + role_type_foo: RoleType, + org_unit_bar: OrganizationalUnit, + sponsor: Sponsor, ): - person.roles.add( # type: ignore - role_foo, - through_defaults={ - "start_date": "2021-05-06", - "end_date": "2021-10-20", - "unit": org_unit_bar, - "registered_by": sponsor, - }, + Role.objects.create( + person=person, + type=role_type_foo, + start_date="2021-05-06", + end_date="2021-10-20", + unit=org_unit_bar, + registered_by=sponsor, ) - - assert len(person.person_roles.all()) == 1 - person_role = person.person_roles.all()[0] + assert len(person.roles.all()) == 1 + person_role = person.roles.all()[0] person_role.delete() - notifications = Notification.objects.filter(object_type="PersonRole") + notifications = Notification.objects.filter(object_type="Role") assert len(notifications) == 2 assert notifications[1].operation == "delete" meta_data = notifications[1].meta assert meta_data["person_id"] == person.id - assert meta_data["role_id"] == role_foo.id + assert meta_data["type_id"] == role_type_foo.id @pytest.mark.django_db -def test_consent_add_notification(person: Person, consent: Consent): - person.consents.add(consent, through_defaults={"consent_given_at": "2021-06-20"}) # type: ignore - notifications = Notification.objects.filter(object_type="PersonConsent") +def test_consent_add_notification(person: Person, consent_type: ConsentType): + Consent.objects.create( + person=person, type=consent_type, consent_given_at="2021-06-20" + ) + notifications = Notification.objects.filter(object_type="Consent") assert len(notifications) == 1 assert notifications[0].identifier == person.id meta_data = notifications[0].meta assert meta_data["person_id"] == person.id - assert meta_data["consent_id"] == consent.id + assert meta_data["consent_id"] == consent_type.id @pytest.mark.django_db -def test_consent_update_notification(person: Person, consent: Consent): - person.consents.add(consent, through_defaults={"consent_given_at": "2021-06-20"}) # type: ignore - person_consents = PersonConsent.objects.filter(person=person, consent=consent) - person_consents[0].consent_given_at = "2021-06-21" - person_consents[0].save() +def test_consent_update_notification(person: Person, consent_type: ConsentType): + Consent.objects.create( + person=person, type=consent_type, consent_given_at="2021-06-20" + ) + consents = Consent.objects.filter(person=person, type=consent_type) + consents[0].consent_given_at = "2021-06-21" + consents[0].save() - notifications = Notification.objects.filter(object_type="PersonConsent") + notifications = Notification.objects.filter(object_type="Consent") assert len(notifications) == 2 assert notifications[0].identifier == person.id meta_data = notifications[0].meta assert meta_data["person_id"] == person.id - assert meta_data["consent_id"] == consent.id + assert meta_data["consent_id"] == consent_type.id @pytest.mark.django_db -def test_consent_delete_notification(person: Person, consent: Consent): - person.consents.add(consent, through_defaults={"consent_given_at": "2021-06-20"}) # type: ignore - person_consents = PersonConsent.objects.filter(person=person, consent=consent) - person_consents[0].delete() - notifications = Notification.objects.filter(object_type="PersonConsent") +def test_consent_delete_notification(person: Person, consent_type: ConsentType): + Consent.objects.create( + person=person, type=consent_type, consent_given_at="2021-06-20" + ) + consents = Consent.objects.filter(person=person, type=consent_type) + consents[0].delete() + notifications = Notification.objects.filter(object_type="Consent") assert len(notifications) == 2 assert notifications[1].identifier == person.id assert notifications[1].operation == "delete" meta_data = notifications[0].meta assert meta_data["person_id"] == person.id - assert meta_data["consent_id"] == consent.id + assert meta_data["consent_id"] == consent_type.id @pytest.mark.django_db