Skip to content
Snippets Groups Projects
Commit d512e792 authored by Tore.Brede's avatar Tore.Brede
Browse files

Merge branch 'GREG-4_simple_admin_interface' into 'master'

GREG-4: Simple admin interface

See merge request !2
parents 7ed94058 10d18b6d
No related branches found
No related tags found
1 merge request!2GREG-4: Simple admin interface
......@@ -4,8 +4,31 @@ from greg.models import (
Person,
PersonRole,
Role,
PersonIdentity,
Consent,
PersonConsent,
OrganizationalUnit,
Sponsor,
SponsorOrganizationalUnit,
)
admin.site.site_header = "Guest Registration Admin"
class RoleInline(admin.TabularInline):
model = PersonRole
extra = 1
class PersonIdentityInline(admin.TabularInline):
model = PersonIdentity
extra = 1
class ConsentInline(admin.TabularInline):
model = PersonConsent
extra = 1
class PersonAdmin(admin.ModelAdmin):
list_display = (
......@@ -15,6 +38,7 @@ class PersonAdmin(admin.ModelAdmin):
)
search_fields = ("first_name", "last_name") # TODO: "identities__value"?
readonly_fields = ("id", "created", "updated")
inlines = (RoleInline, PersonIdentityInline, ConsentInline)
def role_count(self, person):
return str(person.roles.count())
......@@ -37,6 +61,53 @@ class RoleAdmin(admin.ModelAdmin):
readonly_fields = ("id", "created", "updated")
class PersonIdentityAdmin(admin.ModelAdmin):
list_display = ("id", "person", "type", "verified")
list_filter = ("verified",)
readonly_fields = ("id", "created", "updated")
class ConsentAdmin(admin.ModelAdmin):
list_display = ("id", "consent_name_en", "valid_from", "user_allowed_to_change")
readonly_fields = ("id", "created", "updated")
class PersonConsentAdmin(admin.ModelAdmin):
list_display = ("id", "person", "get_consent_name_en")
readonly_fields = ("id", "created", "updated")
def get_consent_name_en(self, obj):
return obj.consent.consent_name_en
get_consent_name_en.short_description = "Consent name"
class OrganizationalUnitAdmin(admin.ModelAdmin):
list_display = ("id", "name_en", "parent")
readonly_fields = ("id", "created", "updated")
class OrganizationalUnitInline(admin.TabularInline):
model = SponsorOrganizationalUnit
extra = 1
class SponsorAdmin(admin.ModelAdmin):
list_display = ("id", "feide_id")
inlines = (OrganizationalUnitInline,)
readonly_fields = ("id", "created", "updated")
class SponsorOrganizationalUnitAdmin(admin.ModelAdmin):
readonly_fields = ("id", "created", "updated")
admin.site.register(Person, PersonAdmin)
admin.site.register(PersonRole, PersonRoleAdmin)
admin.site.register(Role, RoleAdmin)
admin.site.register(PersonIdentity, PersonIdentityAdmin)
admin.site.register(Consent, ConsentAdmin)
admin.site.register(PersonConsent, PersonConsentAdmin)
admin.site.register(OrganizationalUnit, OrganizationalUnitAdmin)
admin.site.register(Sponsor, SponsorAdmin)
admin.site.register(SponsorOrganizationalUnit, SponsorOrganizationalUnitAdmin)
# Generated by Django 3.2.5 on 2021-07-13 06:47
# Generated by Django 3.2.5 on 2021-07-14 12:28
import datetime
import dirtyfields.dirtyfields
......@@ -75,10 +75,10 @@ class Migration(migrations.Migration):
('last_name', models.CharField(max_length=256)),
('date_of_birth', models.DateField()),
('email', models.EmailField(max_length=254)),
('email_verified_date', models.DateField(blank=True, null=True)),
('email_verified_date', models.DateField(null=True)),
('mobile_phone', models.CharField(max_length=15)),
('mobile_phone_verified_date', models.DateField(blank=True, null=True)),
('registration_completed_date', models.DateField(blank=True, null=True)),
('mobile_phone_verified_date', models.DateField(null=True)),
('registration_completed_date', models.DateField(null=True)),
('token', models.CharField(blank=True, max_length=32)),
],
options={
......@@ -159,7 +159,7 @@ class Migration(migrations.Migration):
('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)),
('verified_when', models.DateField(blank=True)),
('verified_when', models.DateField(null=True)),
('person', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='person', to='greg.person')),
('verified_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='sponsor', to='greg.sponsor')),
],
......@@ -200,7 +200,7 @@ class Migration(migrations.Migration):
),
migrations.AddConstraint(
model_name='personrole',
constraint=models.UniqueConstraint(fields=('person', 'role'), name='personrole_person_role_unique'),
constraint=models.UniqueConstraint(fields=('person', 'role', 'unit'), name='personrole_person_role_unit_unique'),
),
migrations.AddConstraint(
model_name='personconsent',
......
......@@ -36,10 +36,10 @@ class Person(BaseModel):
last_name = models.CharField(max_length=256)
date_of_birth = models.DateField()
email = models.EmailField()
email_verified_date = models.DateField(null=True, blank=True)
email_verified_date = models.DateField(null=True)
mobile_phone = models.CharField(max_length=15)
mobile_phone_verified_date = models.DateField(null=True, blank=True)
registration_completed_date = models.DateField(null=True, blank=True)
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(
......@@ -106,7 +106,8 @@ class PersonRole(BaseModel):
class Meta:
constraints = [
models.UniqueConstraint(
fields=["person", "role"], name="personrole_person_role_unique"
fields=["person", "role", "unit"],
name="personrole_person_role_unit_unique",
)
]
......@@ -157,7 +158,7 @@ class PersonIdentity(BaseModel):
verified_by = models.ForeignKey(
"Sponsor", on_delete=models.PROTECT, related_name="sponsor", null=True
)
verified_when = models.DateField(blank=True)
verified_when = models.DateField(null=True)
def __repr__(self):
return (
......
import random
from typing import List, TypeVar
from django.db import connection, IntegrityError
from faker import Faker
from greg.models import (
Person,
Role,
OrganizationalUnit,
Sponsor,
PersonRole,
Consent,
PersonIdentity,
)
# Set seeds so that the generated data is always the same
random.seed(0)
Faker.seed(0)
R = TypeVar("R")
def get_random_element_from_list(input_list: List[R]) -> R:
return input_list[random.randint(0, len(input_list) - 1)]
class DatabasePopulation:
"""
Helper class for populating database with random data. It can be useful to see how things look in the interface
for example.
Run the file in the Django shell: exec(open('greg/tests/populate_database.py').read())
"""
faker: Faker
persons: List[Person] = []
units: List[OrganizationalUnit] = []
sponsors: List[Sponsor] = []
role_types: List[Role] = []
consents: List[Consent] = []
def __init__(self):
self.faker = Faker()
def populate_database(self):
for i in range(10):
first_name = self.faker.first_name()
last_name = self.faker.last_name()
self.persons.append(
Person.objects.create(
first_name=first_name,
last_name=last_name,
date_of_birth=self.faker.date_of_birth(maximum_age=50),
email=f"{first_name}.{last_name}@example.org",
mobile_phone=self.faker.phone_number(),
)
)
for role_type in ("Visiting Professor", "Professor Emeritus", "Consultant"):
self.role_types.append(
Role.objects.create(type=role_type, name_en=role_type)
)
for i in range(10):
self.units.append(
OrganizationalUnit.objects.create(
orgreg_id=f"12345{i}", name_en=self.faker.company()
)
)
for i in range(5):
self.sponsors.append(
Sponsor.objects.create(
feide_id=self.faker.bothify(text="???####@uio.no")
)
)
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(),
user_allowed_to_change=random.random() > 0.5,
)
)
self.__add_random_person_role_connections()
self.__add_random_person_consent_connections()
self.__add_random_sponsor_unit_connections()
self.__add_random_person_identification_connections()
def __add_random_person_identification_connections(self, connections_to_create=5):
person_identifier_count = 0
while person_identifier_count < connections_to_create:
person = get_random_element_from_list(self.persons)
identity_type = get_random_element_from_list(
PersonIdentity.IdentityType.choices
)[0]
if random.random() > 0.5:
sponsor = get_random_element_from_list(self.sponsors)
verified_when = self.faker.date_this_year()
identity_type = get_random_element_from_list(
PersonIdentity.IdentityType.choices
)[0]
verified = self.faker.text(max_nb_chars=50)
else:
sponsor = None
verified_when = None
verified = ""
PersonIdentity.objects.create(
person=person,
type=identity_type,
source=self.faker.text(max_nb_chars=50),
value=self.faker.numerify("##################"),
verified_by=sponsor,
verified=verified,
verified_when=verified_when,
)
person_identifier_count += 1
def __add_random_sponsor_unit_connections(self, connections_to_create=5):
sponsor_unit_count = 0
while sponsor_unit_count < connections_to_create:
sponsor = get_random_element_from_list(self.sponsors)
unit = get_random_element_from_list(self.units)
sponsor.units.add(
unit, through_defaults={"hierarchical_access": random.random() > 0.5}
)
sponsor_unit_count += 1
def __add_random_person_role_connections(self, connections_to_create=5):
person_role_count = 0
while person_role_count < connections_to_create:
try:
PersonRole.objects.create(
person=get_random_element_from_list(self.persons),
role=get_random_element_from_list(self.role_types),
unit=get_random_element_from_list(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=random.random() > 0.5,
registered_by=get_random_element_from_list(self.sponsors),
)
person_role_count += 1
except IntegrityError:
# This is probably caused by the same person added with the same role to the same unit.
# Try again and see if the randomly selected values will make it pass on the next attempt
pass
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 = get_random_element_from_list(self.persons)
consent = get_random_element_from_list(self.consents)
person.consents.add(
consent,
through_defaults={"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_notification",
"greg_personidentity",
"greg_personrole",
"greg_person",
"greg_sponsororganizationalunit",
"greg_sponsor",
"greg_organizationalunit",
"greg_role",
):
cursor.execute(f"DELETE FROM {table}")
if __name__ == "__main__":
database_population = DatabasePopulation()
database_population.truncate_tables()
database_population.populate_database()
......@@ -35,6 +35,7 @@ pylint = "*"
pylint-django = "*"
rope = "*"
autopep8 = "*"
Faker = "^8.10.1"
[build-system]
requires = ["poetry-core>=1.0.0"]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment