Skip to content

Commit 167c32d

Browse files
committed
Endpoint and serializer for Health units
1 parent 39e133f commit 167c32d

File tree

3 files changed

+212
-0
lines changed

3 files changed

+212
-0
lines changed

local_units/serializers.py

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,3 +945,176 @@ def validate(self, validated_data):
945945
health_instance = HealthData.objects.create(**health_data)
946946
validated_data["health"] = health_instance
947947
return validated_data
948+
949+
950+
# Public, flattened serializer for Health Local Units (Type Code = 2)
951+
class _CodeNameSerializer(serializers.Serializer):
952+
code = serializers.IntegerField()
953+
name = serializers.CharField()
954+
955+
956+
class HealthLocalUnitFlatSerializer(serializers.ModelSerializer):
957+
# LocalUnit basics
958+
id = serializers.IntegerField(read_only=True)
959+
country_id = serializers.IntegerField(source="country.id", read_only=True)
960+
country_name = serializers.CharField(source="country.name", read_only=True)
961+
country_iso3 = serializers.CharField(source="country.iso3", read_only=True)
962+
type_code = serializers.IntegerField(source="type.code", read_only=True)
963+
type_name = serializers.CharField(source="type.name", read_only=True)
964+
status_display = serializers.CharField(source="get_status_display", read_only=True)
965+
location = serializers.SerializerMethodField()
966+
967+
# HealthData flattened
968+
affiliation = serializers.SerializerMethodField()
969+
functionality = serializers.SerializerMethodField()
970+
health_facility_type = serializers.SerializerMethodField()
971+
primary_health_care_center = serializers.SerializerMethodField()
972+
hospital_type = serializers.SerializerMethodField()
973+
974+
general_medical_services = serializers.SerializerMethodField()
975+
specialized_medical_beyond_primary_level = serializers.SerializerMethodField()
976+
blood_services = serializers.SerializerMethodField()
977+
professional_training_facilities = serializers.SerializerMethodField()
978+
979+
class Meta:
980+
model = LocalUnit
981+
fields = (
982+
# LocalUnit
983+
"id",
984+
"country_id",
985+
"country_name",
986+
"country_iso3",
987+
"local_branch_name",
988+
"english_branch_name",
989+
"address_loc",
990+
"address_en",
991+
"city_loc",
992+
"city_en",
993+
"postcode",
994+
"phone",
995+
"email",
996+
"link",
997+
"focal_person_loc",
998+
"focal_person_en",
999+
"date_of_data",
1000+
"subtype",
1001+
"type_code",
1002+
"type_name",
1003+
"status",
1004+
"status_display",
1005+
"location",
1006+
# HealthData core
1007+
"affiliation",
1008+
"other_affiliation",
1009+
"functionality",
1010+
"focal_point_email",
1011+
"focal_point_phone_number",
1012+
"focal_point_position",
1013+
"health_facility_type",
1014+
"other_facility_type",
1015+
"primary_health_care_center",
1016+
"speciality",
1017+
"hospital_type",
1018+
"is_teaching_hospital",
1019+
"is_in_patient_capacity",
1020+
"is_isolation_rooms_wards",
1021+
"maximum_capacity",
1022+
"number_of_isolation_rooms",
1023+
"is_warehousing",
1024+
"is_cold_chain",
1025+
"ambulance_type_a",
1026+
"ambulance_type_b",
1027+
"ambulance_type_c",
1028+
"general_medical_services",
1029+
"specialized_medical_beyond_primary_level",
1030+
"other_services",
1031+
"blood_services",
1032+
"professional_training_facilities",
1033+
"total_number_of_human_resource",
1034+
"general_practitioner",
1035+
"specialist",
1036+
"residents_doctor",
1037+
"nurse",
1038+
"dentist",
1039+
"nursing_aid",
1040+
"midwife",
1041+
"other_medical_heal",
1042+
"other_profiles",
1043+
"feedback",
1044+
)
1045+
1046+
# NOTE: HealthData direct field mappings via source
1047+
other_affiliation = serializers.CharField(source="health.other_affiliation", read_only=True)
1048+
focal_point_email = serializers.EmailField(source="health.focal_point_email", read_only=True)
1049+
focal_point_phone_number = serializers.CharField(source="health.focal_point_phone_number", read_only=True)
1050+
focal_point_position = serializers.CharField(source="health.focal_point_position", read_only=True)
1051+
other_facility_type = serializers.CharField(source="health.other_facility_type", read_only=True)
1052+
speciality = serializers.CharField(source="health.speciality", read_only=True)
1053+
is_teaching_hospital = serializers.BooleanField(source="health.is_teaching_hospital", read_only=True)
1054+
is_in_patient_capacity = serializers.BooleanField(source="health.is_in_patient_capacity", read_only=True)
1055+
is_isolation_rooms_wards = serializers.BooleanField(source="health.is_isolation_rooms_wards", read_only=True)
1056+
maximum_capacity = serializers.IntegerField(source="health.maximum_capacity", read_only=True)
1057+
number_of_isolation_rooms = serializers.IntegerField(source="health.number_of_isolation_rooms", read_only=True)
1058+
is_warehousing = serializers.BooleanField(source="health.is_warehousing", read_only=True)
1059+
is_cold_chain = serializers.BooleanField(source="health.is_cold_chain", read_only=True)
1060+
ambulance_type_a = serializers.IntegerField(source="health.ambulance_type_a", read_only=True)
1061+
ambulance_type_b = serializers.IntegerField(source="health.ambulance_type_b", read_only=True)
1062+
ambulance_type_c = serializers.IntegerField(source="health.ambulance_type_c", read_only=True)
1063+
other_services = serializers.CharField(source="health.other_services", read_only=True)
1064+
total_number_of_human_resource = serializers.IntegerField(source="health.total_number_of_human_resource", read_only=True)
1065+
general_practitioner = serializers.IntegerField(source="health.general_practitioner", read_only=True)
1066+
specialist = serializers.IntegerField(source="health.specialist", read_only=True)
1067+
residents_doctor = serializers.IntegerField(source="health.residents_doctor", read_only=True)
1068+
nurse = serializers.IntegerField(source="health.nurse", read_only=True)
1069+
dentist = serializers.IntegerField(source="health.dentist", read_only=True)
1070+
nursing_aid = serializers.IntegerField(source="health.nursing_aid", read_only=True)
1071+
midwife = serializers.IntegerField(source="health.midwife", read_only=True)
1072+
other_medical_heal = serializers.BooleanField(source="health.other_medical_heal", read_only=True)
1073+
other_profiles = serializers.CharField(source="health.other_profiles", read_only=True)
1074+
feedback = serializers.CharField(source="health.feedback", read_only=True)
1075+
1076+
def get_location(self, unit) -> dict:
1077+
return {"lat": unit.location.y, "lng": unit.location.x}
1078+
1079+
def _code_name(self, obj):
1080+
if not obj:
1081+
return None
1082+
return {"code": obj.code, "name": obj.name}
1083+
1084+
def _code_name_list(self, qs):
1085+
return [{"code": x.code, "name": x.name} for x in qs.all()] if qs is not None else []
1086+
1087+
def get_affiliation(self, obj):
1088+
return self._code_name(getattr(obj.health, "affiliation", None) if obj.health else None)
1089+
1090+
def get_functionality(self, obj):
1091+
return self._code_name(getattr(obj.health, "functionality", None) if obj.health else None)
1092+
1093+
def get_health_facility_type(self, obj):
1094+
if not obj.health or not obj.health.health_facility_type:
1095+
return None
1096+
ft = obj.health.health_facility_type
1097+
data = {"code": ft.code, "name": ft.name}
1098+
# Attach image_url if request in context
1099+
request = self.context.get("request") if self.context else None
1100+
if request:
1101+
data["image_url"] = FacilityType.get_image_map(ft.code, request)
1102+
return data
1103+
1104+
def get_primary_health_care_center(self, obj):
1105+
return self._code_name(getattr(obj.health, "primary_health_care_center", None) if obj.health else None)
1106+
1107+
def get_hospital_type(self, obj):
1108+
return self._code_name(getattr(obj.health, "hospital_type", None) if obj.health else None)
1109+
1110+
def get_general_medical_services(self, obj):
1111+
return self._code_name_list(obj.health.general_medical_services if obj.health else None)
1112+
1113+
def get_specialized_medical_beyond_primary_level(self, obj):
1114+
return self._code_name_list(obj.health.specialized_medical_beyond_primary_level if obj.health else None)
1115+
1116+
def get_blood_services(self, obj):
1117+
return self._code_name_list(obj.health.blood_services if obj.health else None)
1118+
1119+
def get_professional_training_facilities(self, obj):
1120+
return self._code_name_list(obj.health.professional_training_facilities if obj.health else None)

local_units/views.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
from local_units.serializers import (
4545
DelegationOfficeSerializer,
4646
ExternallyManagedLocalUnitSerializer,
47+
HealthLocalUnitFlatSerializer,
4748
LocalUnitBulkUploadSerializer,
4849
LocalUnitChangeRequestSerializer,
4950
LocalUnitDeprecateSerializer,
@@ -355,6 +356,43 @@ def destroy(self, request, *args, **kwargs):
355356
return bad_request("Delete method not allowed")
356357

357358

359+
class HealthLocalUnitViewSet(viewsets.ReadOnlyModelViewSet):
360+
"""
361+
Public, flattened list of health local units (Type Code = 2).
362+
"""
363+
364+
serializer_class = HealthLocalUnitFlatSerializer
365+
http_method_names = ["get", "head", "options"]
366+
367+
queryset = (
368+
LocalUnit.objects.select_related(
369+
"country",
370+
"type",
371+
"health",
372+
"health__affiliation",
373+
"health__functionality",
374+
"health__health_facility_type",
375+
"health__primary_health_care_center",
376+
"health__hospital_type",
377+
)
378+
.prefetch_related(
379+
"health__general_medical_services",
380+
"health__specialized_medical_beyond_primary_level",
381+
"health__blood_services",
382+
"health__professional_training_facilities",
383+
)
384+
.filter(
385+
visibility=VisibilityChoices.PUBLIC,
386+
is_deprecated=False,
387+
type__code=2,
388+
health__isnull=False,
389+
)
390+
.order_by("id")
391+
)
392+
393+
# NOTE: Filters for region/country/iso/validated/subtype can be added later; base queryset enforces type=2.
394+
395+
358396
class LocalUnitOptionsView(views.APIView):
359397

360398
@extend_schema(request=None, responses=LocalUnitOptionsSerializer)

main/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@
181181
# Local Units apis
182182
router.register(r"local-units", local_units_views.PrivateLocalUnitViewSet, basename="local_units")
183183
router.register(r"public-local-units", local_units_views.LocalUnitViewSet, basename="public_local_units")
184+
router.register(r"health-local-units", local_units_views.HealthLocalUnitViewSet, basename="health_local_units")
184185
router.register(
185186
r"externally-managed-local-unit",
186187
local_units_views.ExternallyManagedLocalUnitViewSet,

0 commit comments

Comments
 (0)