Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • andretol/greg
1 result
Show changes
Commits on Source (13)
......@@ -6,4 +6,4 @@ from greg.models import Sponsor
class SponsorSerializer(serializers.ModelSerializer):
class Meta:
model = Sponsor
fields = ["id", "feide_id"]
fields = ["id", "feide_id", "first_name", "last_name"]
from drf_spectacular.utils import extend_schema, OpenApiParameter
from rest_framework import mixins
from rest_framework.viewsets import ReadOnlyModelViewSet, GenericViewSet
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from greg.api.pagination import PrimaryKeyCursorPagination
from greg.api.serializers import PersonSerializer
......@@ -8,7 +8,7 @@ from greg.api.serializers.sponsor import SponsorSerializer
from greg.models import Sponsor, Person
class SponsorViewSet(ReadOnlyModelViewSet):
class SponsorViewSet(ModelViewSet):
"""Sponsor API"""
queryset = Sponsor.objects.all().order_by("id")
......
# Generated by Django 3.2.5 on 2021-08-06 13:28
# Generated by Django 3.2.5 on 2021-08-20 08:20
import datetime
import dirtyfields.dirtyfields
......@@ -119,6 +119,8 @@ class Migration(migrations.Migration):
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
('feide_id', models.CharField(max_length=256)),
('first_name', models.CharField(max_length=256)),
('last_name', models.CharField(max_length=256)),
],
bases=(dirtyfields.dirtyfields.DirtyFieldsMixin, models.Model),
),
......@@ -155,9 +157,6 @@ class Migration(migrations.Migration):
('role', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='person_roles', to='greg.role')),
('unit', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='unit_person_role', to='greg.organizationalunit')),
],
options={
'abstract': False,
},
bases=(dirtyfields.dirtyfields.DirtyFieldsMixin, models.Model),
),
migrations.CreateModel(
......@@ -166,7 +165,7 @@ class Migration(migrations.Migration):
('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.CharField(choices=[('ID_PORTEN', 'Id Porten'), ('FEIDE_ID', 'Feide Id'), ('PASSPORT', 'Passport'), ('DRIVERS_LICENSE', 'Drivers License'), ('NATIONAL_ID_CARD', 'National Id Card'), ('OTHER', 'Other')], max_length=16)),
('type', models.CharField(choices=[('ID_PORTEN', 'Id Porten'), ('FEIDE_ID', 'Feide Id'), ('PASSPORT', 'Passport'), ('DRIVERS_LICENSE', 'Drivers License'), ('NATIONAL_ID_CARD', 'National Id Card'), ('NATIONAL_ID_NUMBER', 'National Id Number'), ('OTHER', 'Other')], max_length=18)),
('source', models.CharField(max_length=256)),
('value', models.CharField(max_length=256)),
('verified', models.CharField(blank=True, choices=[('AUTOMATIC', 'Automatic'), ('MANUAL', 'Manual')], max_length=9)),
......@@ -209,6 +208,10 @@ class Migration(migrations.Migration):
model_name='sponsor',
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'),
......
......@@ -103,6 +103,14 @@ class PersonRole(BaseModel):
"Sponsor", on_delete=models.PROTECT, related_name="sponsor_role"
)
class Meta:
constraints = [
models.UniqueConstraint(
fields=["person_id", "role_id", "unit_id", "start_date", "end_date"],
name="person_role_unique",
)
]
def __repr__(self):
return "{}(id={!r}, person={!r}, role={!r})".format(
self.__class__.__name__, self.pk, self.person, self.role
......@@ -137,6 +145,8 @@ class PersonIdentity(BaseModel):
PASSPORT = "PASSPORT"
DRIVERS_LICENSE = "DRIVERS_LICENSE"
NATIONAL_ID_CARD = "NATIONAL_ID_CARD"
# In Norway this is the foedselsnummer
NATIONAL_ID_NUMBER = "NATIONAL_ID_NUMBER"
# Sponsor writes what is used in the value column
OTHER = "OTHER"
......@@ -147,7 +157,7 @@ class PersonIdentity(BaseModel):
person = models.ForeignKey(
"Person", on_delete=models.CASCADE, related_name="person"
)
type = models.CharField(max_length=16, choices=IdentityType.choices)
type = models.CharField(max_length=18, choices=IdentityType.choices)
source = models.CharField(max_length=256)
value = models.CharField(max_length=256)
verified = models.CharField(max_length=9, choices=Verified.choices, blank=True)
......@@ -253,6 +263,9 @@ class Sponsor(BaseModel):
"""
feide_id = models.CharField(max_length=256)
first_name = models.CharField(max_length=256)
last_name = models.CharField(max_length=256)
units = models.ManyToManyField(
"OrganizationalUnit",
through="SponsorOrganizationalUnit",
......@@ -260,8 +273,12 @@ class Sponsor(BaseModel):
)
def __repr__(self):
return "{}(id={!r}, feide_id={!r})".format(
self.__class__.__name__, self.pk, self.feide_id
return "{}(id={!r}, feide_id={!r}, first_name={!r}, last_name={!r})".format(
self.__class__.__name__,
self.pk,
self.feide_id,
self.first_name,
self.last_name,
)
class Meta:
......@@ -308,3 +325,8 @@ class ScheduleTask(models.Model):
name = models.CharField(max_length=32)
last_completed = models.DateTimeField(null=True)
def __repr__(self):
return "{}(id={!r}, name={!r}, last_completed={!r})".format(
self.__class__.__name__, self.pk, self.name, self.last_completed
)
......@@ -11,6 +11,8 @@ from greg.models import (
Role,
OrganizationalUnit,
Consent,
Person,
PersonRole,
)
......@@ -350,3 +352,28 @@ def test_remove_person(
reverse("person_identity-list", kwargs={"person_id": person_foo.id})
)
assert len(response.json()["results"]) == 0
@pytest.mark.django_db
def test_add_duplicate_role_fails(
client, person_foo: Person, person_foo_role: PersonRole
):
url = reverse("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,
"start_date": person_foo_role.start_date,
"end_date": person_foo_role.end_date,
"registered_by": person_foo_role.registered_by,
"unit": person_foo_role.unit_id,
}
response = client.post(url, role_data)
# If the role cannot be create the return code is 400
assert response.status_code == status.HTTP_400_BAD_REQUEST
# Check that there is still only one role attached to the person
roles_for_person = client.get(url).json()["results"]
assert len(roles_for_person) == 1
import pytest
from rest_framework import status
from rest_framework.reverse import reverse
from greg.models import Role, Sponsor, OrganizationalUnit, PersonRole, Person
@pytest.fixture
def person_foo_role(
person_foo: Person,
role_test_guest: Role,
sponsor_guy: Sponsor,
unit_foo: OrganizationalUnit,
) -> PersonRole:
return PersonRole.objects.create(
person=person_foo,
role=role_test_guest,
start_date="2021-08-02",
end_date="2021-08-06",
registered_by=sponsor_guy,
unit=unit_foo,
@pytest.mark.django_db
def test_add_sponsor(client):
data = {
"feide_id": "sponsor@example.org",
"first_name": "Test",
"last_name": "Sponsor",
}
post_response = client.post(reverse("sponsor-list"), data=data)
assert post_response.status_code == status.HTTP_201_CREATED
response_data = post_response.json()
list_response = client.get(
reverse("sponsor-detail", kwargs={"id": response_data["id"]})
)
list_response_data = list_response.json()
assert list_response_data["feide_id"] == data["feide_id"]
assert list_response_data["first_name"] == data["first_name"]
assert list_response_data["last_name"] == data["last_name"]
@pytest.mark.django_db
......
......@@ -6,7 +6,14 @@ from django.contrib.auth import get_user_model
import pytest
from greg.models import Person, Sponsor, PersonIdentity, Role, OrganizationalUnit
from greg.models import (
Person,
Sponsor,
PersonIdentity,
Role,
OrganizationalUnit,
PersonRole,
)
# faker spams the logs with localisation warnings
# see https://github.com/joke2k/faker/issues/753
......@@ -46,7 +53,9 @@ def person_bar() -> Person:
@pytest.fixture
def sponsor_guy() -> Sponsor:
return Sponsor.objects.create(feide_id="guy@example.org")
return Sponsor.objects.create(
feide_id="guy@example.org", first_name="Sponsor", last_name="Guy"
)
@pytest.fixture
......@@ -80,3 +89,20 @@ def role_test_guest() -> Role:
@pytest.fixture
def unit_foo() -> OrganizationalUnit:
return OrganizationalUnit.objects.create(orgreg_id="12345", name_en="foo_unit")
@pytest.fixture
def person_foo_role(
person_foo: Person,
role_test_guest: Role,
sponsor_guy: Sponsor,
unit_foo: OrganizationalUnit,
) -> PersonRole:
return PersonRole.objects.create(
person=person_foo,
role=role_test_guest,
start_date="2021-08-02",
end_date="2021-08-06",
registered_by=sponsor_guy,
unit=unit_foo,
)