Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion requirements/local.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ coverage==5.5 # https://github.com/nedbat/coveragepy
black==20.8b1 # https://github.com/ambv/black
pylint-django==2.4.4 # https://github.com/PyCQA/pylint-django
pre-commit==2.10.1 # https://github.com/pre-commit/pre-commit
isort==5.9.2 # https://github.com/PyCQA/isort
isort==4.3.21 # https://github.com/PyCQA/isort

# Django
# ------------------------------------------------------------------------------
Expand Down
70 changes: 53 additions & 17 deletions tmh_registry/registry/api/serializers.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,40 @@
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from rest_framework.fields import IntegerField, SerializerMethodField
from rest_framework.serializers import ModelSerializer

from ..models import Hospital, Patient, PatientHospitalMapping


class HospitalSerializer(serializers.ModelSerializer):
class HospitalSerializer(ModelSerializer):
class Meta:
model = Hospital
fields = ["id", "name", "address"]


class ReadPatientSerializer(serializers.ModelSerializer):
age = serializers.IntegerField(allow_null=True)
hospitals = serializers.SerializerMethodField()
class ReadPatientSerializer(ModelSerializer):
age = IntegerField(allow_null=True)
hospitals = SerializerMethodField()

def get_hospitals(self, obj):
hospitals = Hospital.objects.filter(
id__in=PatientHospitalMapping.objects.filter(
patient=obj
).values_list("hospital_id", flat=True)
id__in=obj.hospital_mappings.all().values_list(
"hospital_id", flat=True
)
)
return HospitalSerializer(hospitals, many=True).data
hospital_data = HospitalSerializer(hospitals, many=True).data

# enrich with patient_hospital_id
idx = 0
for hospital in hospital_data:
patient_hospital_id = PatientHospitalMapping.objects.get(
hospital_id=hospital["id"], patient_id=obj.id
).patient_hospital_id
hospital_data[idx].update(
{"patient_hospital_id": patient_hospital_id}
)
idx += 1

return hospital_data

class Meta:
model = Patient
Expand Down Expand Up @@ -51,10 +66,11 @@ def to_representation(self, instance):
return data


class CreatePatientSerializer(serializers.ModelSerializer):
age = serializers.IntegerField(allow_null=True)
hospital_id = serializers.IntegerField(write_only=True)
year_of_birth = serializers.IntegerField(allow_null=True)
class CreatePatientSerializer(ModelSerializer):
age = IntegerField(allow_null=True)
hospital_id = IntegerField(write_only=True)
patient_hospital_id = IntegerField(write_only=True)
year_of_birth = IntegerField(allow_null=True)

class Meta:
model = Patient
Expand All @@ -71,6 +87,7 @@ class Meta:
"phone_2",
"address",
"hospital_id",
"patient_hospital_id",
]

def to_representation(self, instance):
Expand All @@ -85,7 +102,7 @@ def create(self, validated_data):
"year_of_birth"
] = Patient.get_year_of_birth_from_age(validated_data["age"])
else:
raise serializers.ValidationError(
raise ValidationError(
{
"error": "Either 'age' or 'year_of_birth' should be populated."
}
Expand All @@ -97,14 +114,31 @@ def create(self, validated_data):
id=validated_data["hospital_id"]
)
except Hospital.DoesNotExist:
raise serializers.ValidationError(
raise ValidationError(
{
"error": "The hospital you are trying to register this patient does not exist."
}
)
validated_data.pop("hospital_id", None)
else:
raise serializers.ValidationError(
raise ValidationError(
{"error": "The patient needs to be registered to a hospital."}
)

patient_hospital_id = validated_data.pop("patient_hospital_id", None)
if patient_hospital_id:
if PatientHospitalMapping.objects.filter(
hospital_id=hospital.id,
patient_hospital_id=patient_hospital_id,
).exists():
raise ValidationError(
{
"error": f"The patient hospital id {patient_hospital_id} is already "
f"registered to another patient of this hospital."
}
)
else:
raise ValidationError(
{"error": "The patient needs to be registered to a hospital."}
)

Expand All @@ -113,7 +147,9 @@ def create(self, validated_data):
validated_data
)
PatientHospitalMapping.objects.create(
patient=new_patient, hospital=hospital
patient=new_patient,
hospital=hospital,
patient_hospital_id=patient_hospital_id,
)

return new_patient
37 changes: 22 additions & 15 deletions tmh_registry/registry/factories.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import random

import factory
from factory import LazyAttribute, SubFactory
from factory.django import DjangoModelFactory
from faker import Faker

from .models import Hospital, Patient
from .models import Hospital, Patient, PatientHospitalMapping

faker = Faker()

Expand All @@ -13,26 +13,33 @@ class HospitalFactory(DjangoModelFactory):
class Meta:
model = Hospital

name = factory.LazyAttribute(lambda n: "Hospital '%s'" % faker.name())
address = factory.LazyAttribute(lambda n: faker.address())
name = LazyAttribute(lambda n: "Hospital '%s'" % faker.name())
address = LazyAttribute(lambda n: faker.address())


class PatientFactory(DjangoModelFactory):
class Meta:
model = Patient

full_name = factory.LazyAttribute(lambda n: faker.name())
national_id = factory.LazyAttribute(
full_name = LazyAttribute(lambda n: faker.name())
national_id = LazyAttribute(
lambda n: faker.numerify(text="####################")
)
day_of_birth = factory.LazyAttribute(lambda n: faker.date_of_birth().day)
month_of_birth = factory.LazyAttribute(
lambda n: faker.date_of_birth().month
)
year_of_birth = factory.LazyAttribute(lambda n: faker.date_of_birth().year)
gender = factory.LazyAttribute(
day_of_birth = LazyAttribute(lambda n: faker.date_of_birth().day)
month_of_birth = LazyAttribute(lambda n: faker.date_of_birth().month)
year_of_birth = LazyAttribute(lambda n: faker.date_of_birth().year)
gender = LazyAttribute(
lambda n: random.choice([gender.value for gender in Patient.Gender])
)
phone_1 = factory.LazyAttribute(lambda n: faker.numerify(text="#########"))
phone_2 = factory.LazyAttribute(lambda n: faker.numerify(text="#########"))
address = factory.LazyAttribute(lambda n: faker.address())
phone_1 = LazyAttribute(lambda n: faker.numerify(text="#########"))
phone_2 = LazyAttribute(lambda n: faker.numerify(text="#########"))
address = LazyAttribute(lambda n: faker.address())


class PatientHospitalMappingFactory(DjangoModelFactory):
class Meta:
model = PatientHospitalMapping

patient = SubFactory(PatientFactory)
hospital = SubFactory(HospitalFactory)
patient_hospital_id = LazyAttribute(lambda n: faker.ssn())
30 changes: 30 additions & 0 deletions tmh_registry/registry/migrations/0008_auto_20210919_1826.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Generated by Django 3.1.3 on 2021-09-19 18:26

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("registry", "0007_episode_followup"),
]

operations = [
migrations.AlterModelOptions(
name="patienthospitalmapping",
options={"verbose_name_plural": "Patient-Hospital mappings"},
),
migrations.AddField(
model_name="patienthospitalmapping",
name="patient_hospital_id",
field=models.CharField(default="111111", max_length=256),
preserve_default=False,
),
migrations.AlterUniqueTogether(
name="patienthospitalmapping",
unique_together={
("hospital", "patient_hospital_id"),
("patient", "hospital"),
},
),
]
32 changes: 32 additions & 0 deletions tmh_registry/registry/migrations/0009_auto_20210919_1941.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Generated by Django 3.1.3 on 2021-09-19 19:41

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
("registry", "0008_auto_20210919_1826"),
]

operations = [
migrations.AlterField(
model_name="patienthospitalmapping",
name="hospital",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="patient_mappings",
to="registry.hospital",
),
),
migrations.AlterField(
model_name="patienthospitalmapping",
name="patient",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="hospital_mappings",
to="registry.patient",
),
),
]
18 changes: 13 additions & 5 deletions tmh_registry/registry/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,23 @@ def get_year_of_birth_from_age(age):


class PatientHospitalMapping(models.Model):
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
hospital = models.ForeignKey(Hospital, on_delete=models.CASCADE)
patient = models.ForeignKey(
Patient, on_delete=models.CASCADE, related_name="hospital_mappings"
)
hospital = models.ForeignKey(
Hospital, on_delete=models.CASCADE, related_name="patient_mappings"
)
patient_hospital_id = models.CharField(max_length=256)

class Meta:
unique_together = ("patient", "hospital")
verbose_name_plural = "Patient-Hospital mapping"
unique_together = (
("patient", "hospital"),
("hospital", "patient_hospital_id"),
)
verbose_name_plural = "Patient-Hospital mappings"

def __str__(self):
return f"{self.patient.full_name} - {self.hospital.name}"
return f"Patient {self.patient.full_name} ({self.patient_hospital_id}) - Hospital {self.hospital.name}"


class Episode(models.Model):
Expand Down
Loading