diff --git a/config/settings/base.py b/config/settings/base.py index 0fb2450..a9ec8fc 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -95,16 +95,16 @@ "wagtail.search", "wagtail.admin", "wagtail.core", + "wagtail.contrib.modeladmin", + "wagtailvideos", + "wagtailmedia", "taggit", "modelcluster", "wagtail.api.v2", "wagtail.contrib.settings", "wagtail.contrib.frontend_cache", "wagtail.contrib.search_promotions", - "wagtail.contrib.modeladmin", "django_extensions", - "wagtailvideos", - "wagtailmedia", ] LOCAL_APPS = [ diff --git a/mycarehub/clients/admin.py b/mycarehub/clients/admin.py index 455857d..f11bac6 100644 --- a/mycarehub/clients/admin.py +++ b/mycarehub/clients/admin.py @@ -1,4 +1,5 @@ from django.contrib import admin +from django.contrib.admin.decorators import display from mycarehub.common.admin import BaseAdmin @@ -34,7 +35,20 @@ class RelatedPersonAdmin(BaseAdmin): @admin.register(Client) class ClientAdmin(BaseAdmin): - pass + list_display = ( + "get_user_name", + "client_type", + "enrollment_date", + ) + date_hierarchy = "enrollment_date" + exclude = ( + "fhir_patient_id", + "emr_health_record_id", + ) # type: ignore + + @display(ordering="user__name", description="User") + def get_user_name(self, obj): + return obj.user.name if obj.user else "-" @admin.register(ClientFacility) diff --git a/mycarehub/clients/models.py b/mycarehub/clients/models.py index 5b72b8a..2017de5 100644 --- a/mycarehub/clients/models.py +++ b/mycarehub/clients/models.py @@ -40,6 +40,9 @@ class IdentifierUse(models.TextChoices): valid_to = models.DateTimeField(null=True, blank=True) is_primary_identifier = models.BooleanField(default=False) + def __str__(self): + return f"{self.identifier_value} ({self.identifier_type}, {self.identifier_use})" + class SecurityQuestion(AbstractBase): class ResponseType(models.TextChoices): @@ -95,6 +98,9 @@ class RelationshipType(TextChoices): related_name="related_person_contacts", ) + def __str__(self): + return f"{self.first_name} {self.other_name} {self.last_name} ({self.relationship_type})" + class Client(AbstractBase): """ @@ -233,6 +239,11 @@ class Languages(TextChoices): blank=True, ) + def __str__(self): + return ( + f"{self.user.name} ({self.client_type})" if self.user else f"{self.client_type} client" + ) + class ClientFacility(AbstractBase): """ diff --git a/mycarehub/clients/tests/__init__.py b/mycarehub/clients/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mycarehub/clients/tests/test_admin.py b/mycarehub/clients/tests/test_admin.py new file mode 100644 index 0000000..4629201 --- /dev/null +++ b/mycarehub/clients/tests/test_admin.py @@ -0,0 +1,14 @@ +import pytest +from django.contrib.admin.sites import AdminSite +from model_bakery import baker + +from mycarehub.clients.admin import ClientAdmin +from mycarehub.clients.models import Client + +pytestmark = pytest.mark.django_db + + +def test_client_admin_get_user_name(user_with_all_permissions): + admin = ClientAdmin(model=Client, admin_site=AdminSite()) + client = baker.make(Client, user=user_with_all_permissions) + assert admin.get_user_name(client) == user_with_all_permissions.name diff --git a/mycarehub/clients/tests/test_models.py b/mycarehub/clients/tests/test_models.py new file mode 100644 index 0000000..c154c41 --- /dev/null +++ b/mycarehub/clients/tests/test_models.py @@ -0,0 +1,32 @@ +import pytest +from model_bakery import baker + +from mycarehub.clients.models import Client, Identifier, RelatedPerson + +pytestmark = pytest.mark.django_db + + +def test_identifier_str(): + identifier = baker.make( + Identifier, + identifier_value="222", + identifier_type="NATIONAL_ID", + identifier_use="OFFICIAL", + ) + assert str(identifier) == "222 (NATIONAL_ID, OFFICIAL)" + + +def test_related_person_str(): + related_person = baker.make( + RelatedPerson, + first_name="Juha", + last_name="Mwenyewe", + other_name="Kalulu", + relationship_type="SPOUSE", + ) + assert str(related_person) == "Juha Kalulu Mwenyewe (SPOUSE)" + + +def test_client_str(user_with_all_permissions): + client = baker.make(Client, user=user_with_all_permissions, client_type="PMTCT") + assert str(client) == f"{user_with_all_permissions.name} (PMTCT)" diff --git a/mycarehub/clients/tests.py b/mycarehub/clients/tests/test_views.py similarity index 99% rename from mycarehub/clients/tests.py rename to mycarehub/clients/tests/test_views.py index fbf280f..d1c7363 100644 --- a/mycarehub/clients/tests.py +++ b/mycarehub/clients/tests/test_views.py @@ -7,10 +7,7 @@ from faker import Faker from model_bakery import baker -from mycarehub.common.models.common_models import Facility -from mycarehub.common.tests.test_api import CRUDTestMixin - -from .models import ( +from mycarehub.clients.models import ( Client, ClientFacility, Identifier, @@ -18,6 +15,8 @@ SecurityQuestion, SecurityQuestionResponse, ) +from mycarehub.common.models.common_models import Facility +from mycarehub.common.tests.test_api import CRUDTestMixin fake = Faker() diff --git a/mycarehub/common/admin.py b/mycarehub/common/admin.py index 5388b46..70e65f1 100644 --- a/mycarehub/common/admin.py +++ b/mycarehub/common/admin.py @@ -8,8 +8,13 @@ class BaseAdmin(admin.ModelAdmin): readonly_fields = ( "created", - "created_by", "updated", + "created_by", + "updated_by", + "deleted_at", + ) + exclude = ( + "created_by", "updated_by", "deleted_at", ) diff --git a/mycarehub/common/migrations/0011_alter_contact_user.py b/mycarehub/common/migrations/0011_alter_contact_user.py new file mode 100644 index 0000000..21822ae --- /dev/null +++ b/mycarehub/common/migrations/0011_alter_contact_user.py @@ -0,0 +1,21 @@ +# Generated by Django 3.2.9 on 2021-11-23 03:27 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('common', '0010_auto_20211119_0628'), + ] + + operations = [ + migrations.AlterField( + model_name='contact', + name='user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/mycarehub/common/migrations/0012_auto_20211123_0636.py b/mycarehub/common/migrations/0012_auto_20211123_0636.py new file mode 100644 index 0000000..5e90c2e --- /dev/null +++ b/mycarehub/common/migrations/0012_auto_20211123_0636.py @@ -0,0 +1,26 @@ +# Generated by Django 3.2.9 on 2021-11-23 03:36 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('common', '0011_alter_contact_user'), + ] + + operations = [ + migrations.AlterField( + model_name='contact', + name='flavour', + field=models.CharField(blank=True, choices=[('PRO', 'PRO'), ('CONSUMER', 'CONSUMER')], max_length=32, null=True), + ), + migrations.AlterField( + model_name='contact', + name='user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/mycarehub/common/models/common_models.py b/mycarehub/common/models/common_models.py index 36f20cf..de12dc9 100644 --- a/mycarehub/common/models/common_models.py +++ b/mycarehub/common/models/common_models.py @@ -310,6 +310,9 @@ class AddressType(models.TextChoices): postal_code = models.TextField() country = models.CharField(max_length=255, choices=COUNTRY_CODES, default="KEN") + def __str__(self): + return f"{self.text} ({self.address_type})" + class Contact(AbstractBase): class ContactType(models.TextChoices): @@ -323,8 +326,13 @@ class FlavourChoices(models.TextChoices): contact_type = models.CharField(choices=ContactType.choices, max_length=16) contact_value = models.TextField(unique=True) opted_in = models.BooleanField(default=False) - flavour = models.CharField(choices=FlavourChoices.choices, max_length=32, null=True) - user = models.ForeignKey(User, on_delete=models.PROTECT, null=True) + flavour = models.CharField( + choices=FlavourChoices.choices, max_length=32, null=True, blank=True + ) + user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True) + + def __str__(self): + return f"{self.contact_value} ({self.contact_type})" class AuditLog(AbstractBase): diff --git a/mycarehub/common/tests/test_models.py b/mycarehub/common/tests/test_models.py index 42c989b..6d3a3c9 100644 --- a/mycarehub/common/tests/test_models.py +++ b/mycarehub/common/tests/test_models.py @@ -24,6 +24,7 @@ is_image_type, unique_list, ) +from mycarehub.common.models.common_models import Address, Contact fake = Faker() @@ -669,3 +670,13 @@ def test_user_facility_allotment_by_both_facility_and_region(self): allotment.save() assert UserFacilityAllotment.get_facilities_for_allotment(allotment).count() == 5 + + +def test_address_str(): + addr = baker.make(Address, text="Wapi", address_type="BOTH") + assert str(addr) == "Wapi (BOTH)" + + +def test_contact_str(): + contact = baker.make(Contact, contact_value="0722000000", contact_type="PHONE") + assert str(contact) == "0722000000 (PHONE)" diff --git a/mycarehub/users/migrations/0016_alter_userotp_user.py b/mycarehub/users/migrations/0016_alter_userotp_user.py new file mode 100644 index 0000000..ecdc0df --- /dev/null +++ b/mycarehub/users/migrations/0016_alter_userotp_user.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.9 on 2021-11-23 03:27 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0015_user_pin_change_required'), + ] + + operations = [ + migrations.AlterField( + model_name='userotp', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/mycarehub/users/models.py b/mycarehub/users/models.py index 129315b..2e1cdf4 100644 --- a/mycarehub/users/models.py +++ b/mycarehub/users/models.py @@ -14,6 +14,7 @@ UUIDField, ) from django.db.models.base import Model +from django.db.models.deletion import CASCADE from django.db.models.fields import DateField, DateTimeField, IntegerField from django.db.utils import ProgrammingError from django.urls import reverse @@ -218,7 +219,7 @@ class UserOTP(Model): UserOTP stores a user's OTP """ - user = ForeignKey(User, on_delete=PROTECT) + user = ForeignKey(User, on_delete=CASCADE) is_valid = BooleanField() generated_at = DateTimeField(default=timezone.now) valid_until = DateTimeField(null=True, blank=True)