Fakultas Ilmu Komputer UI

Commit f9c56752 authored by Jonathan Christopher Jakub's avatar Jonathan Christopher Jakub Committed by Dave Nathanael
Browse files

Implement case counts views for statistics

parent 4dfef732
......@@ -24,6 +24,7 @@ class InvestigationCaseFactory(factory.DjangoModelFactory):
author = factory.SubFactory(AccountFactory)
case_subject = factory.SubFactory(CaseSubjectFactory)
author = factory.SubFactory(AccountFactory)
is_positive = None
class MonitoringCaseFactory(factory.DjangoModelFactory):
......
from django.apps import AppConfig
class ExportablesConfig(AppConfig):
name = 'exportables'
# District
DISTRICTS = (
"Beji",
"Bojongsari",
"Cilodong",
"Cimanggis",
"Cinere",
"Cipayung",
"Limo",
"Pancoran Mas",
"Sawangan",
"Sukmajaya",
"Tapos",
)
DISTRICT = "district"
# Age
AGE = "age"
# Sex
SEX = "sex"
FEMALE = "female"
MALE = "male"
# Outcome
POSITIVE = "positive"
NEGATIVE = "negative"
UNDETERMINED = "undetermined"
# Total
TOTAL = "total_count"
import json
from rest_framework import status
from rest_framework.test import APITestCase
from apps.cases.models import CaseSubject
from apps.cases.tests.factories.case_subjects import CaseSubjectFactory
from apps.cases.tests.factories.cases import InvestigationCaseFactory
class ExportableViewTest(APITestCase):
@classmethod
def setUpTestData(cls):
InvestigationCaseFactory(
case_subject=CaseSubjectFactory(
district="Beji",
age=19,
is_male=True,
),
is_positive=True,
)
InvestigationCaseFactory(
case_subject=CaseSubjectFactory(
district="Cilodong",
age=20,
is_male=False,
),
is_positive=True,
)
InvestigationCaseFactory(
case_subject=CaseSubjectFactory(
district="Tapos",
age=21,
is_male=True,
),
is_positive=False,
)
InvestigationCaseFactory(
case_subject=CaseSubjectFactory(
district="Unknown",
age=21,
is_male=False,
),
is_positive=False,
)
InvestigationCaseFactory(
case_subject=CaseSubjectFactory(
district="Sawangan",
age=22,
is_male=True,
),
is_positive=None,
)
def test_exportable_data_return_values(self):
url = "/exportables/"
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
data = {
"age": {
"19": {
"positive": 1,
"negative": 0,
"undetermined": 0,
"total_count": 1
},
"20": {
"positive": 1,
"negative": 0,
"undetermined": 0,
"total_count": 1
},
"21": {
"positive": 0,
"negative": 2,
"undetermined": 0,
"total_count": 2
},
"22": {
"positive": 0,
"negative": 0,
"undetermined": 1,
"total_count": 1
}
},
"district": {
"Beji": {
"positive": 1,
"negative": 0,
"undetermined": 0,
"total_count": 1
},
"Bojongsari": {
"positive": 0,
"negative": 0,
"undetermined": 0,
"total_count": 0
},
"Cilodong": {
"positive": 1,
"negative": 0,
"undetermined": 0,
"total_count": 1
},
"Cimanggis": {
"positive": 0,
"negative": 0,
"undetermined": 0,
"total_count": 0
},
"Cinere": {
"positive": 0,
"negative": 0,
"undetermined": 0,
"total_count": 0
},
"Cipayung": {
"positive": 0,
"negative": 0,
"undetermined": 0,
"total_count": 0
},
"Limo": {
"positive": 0,
"negative": 0,
"undetermined": 0,
"total_count": 0
},
"Pancoran Mas": {
"positive": 0,
"negative": 0,
"undetermined": 0,
"total_count": 0
},
"Sawangan": {
"positive": 0,
"negative": 0,
"undetermined": 1,
"total_count": 1
},
"Sukmajaya": {
"positive": 0,
"negative": 0,
"undetermined": 0,
"total_count": 0
},
"Tapos": {
"positive": 0,
"negative": 1,
"undetermined": 0,
"total_count": 1
},
"Unknown": {
"positive": 0,
"negative": 1,
"undetermined": 0,
"total_count": 1
}
},
"sex": {
"male": {
"positive": 1,
"negative": 1,
"undetermined": 1,
"total_count": 3
},
"female": {
"positive": 1,
"negative": 1,
"undetermined": 0,
"total_count": 2
}
},
"total_count": 5
}
self.assertJSONEqual(response.content, data)
from django.urls import path
from apps.exportables.views import CaseCountsView
urlpatterns = [
path("", CaseCountsView.as_view()),
]
from apps.exportables.constants import (
DISTRICT,
DISTRICTS,
FEMALE,
MALE,
NEGATIVE,
POSITIVE,
TOTAL,
UNDETERMINED
)
def generate_initial_counts():
return {
POSITIVE: 0,
NEGATIVE: 0,
UNDETERMINED: 0,
TOTAL: 0
}
def generate_initial_group_counts():
age_groups = {}
sex_groups = {
MALE: generate_initial_counts(),
FEMALE: generate_initial_counts(),
}
district_groups = {
district: generate_initial_counts() for district in DISTRICTS
}
return [age_groups, sex_groups, district_groups]
def map_outcome_value(outcome):
if outcome is None:
return UNDETERMINED
if outcome:
return POSITIVE
return NEGATIVE
def map_sex_value(sex):
if sex:
return MALE
return FEMALE
from django.http import JsonResponse
from django.db.models import Max
from rest_framework import status
from rest_framework.views import APIView
from apps.cases.models import (
CaseSubject,
InvestigationCase,
)
from apps.exportables.constants import (
AGE,
DISTRICT,
DISTRICTS,
FEMALE,
MALE,
NEGATIVE,
POSITIVE,
SEX,
TOTAL,
UNDETERMINED
)
from apps.exportables.utils import (
generate_initial_counts,
generate_initial_group_counts,
map_outcome_value,
map_sex_value,
)
class CaseCountsView(APIView):
def get(self, request, format=None):
case_subjects = CaseSubject.objects.all()
investigation_cases = (InvestigationCase.objects
.values("case_subject")
.annotate(latest_investigation_case=Max("created_at"))
.order_by()
.values("case_subject__id", "is_positive")
)
outcomes = {}
for investigation_case in investigation_cases:
related_case_subject_id = investigation_case["case_subject__id"]
outcomes[related_case_subject_id] = investigation_case["is_positive"]
age_groups, sex_groups, district_groups = generate_initial_group_counts()
for case_subject in case_subjects:
outcome = outcomes.get(case_subject.id)
outcome = map_outcome_value(outcome)
# Age-based grouping
subject_age = str(case_subject.age)
if age_groups.get(subject_age) is None:
age_groups[subject_age] = generate_initial_counts()
age_groups[subject_age][outcome] += 1
age_groups[subject_age][TOTAL] += 1
# District-based grouping
subject_district = case_subject.district
if district_groups.get(subject_district) is None:
district_groups[subject_district] = generate_initial_counts()
district_groups[subject_district][outcome] += 1
district_groups[subject_district][TOTAL] += 1
# Sex-based grouping
subject_sex = case_subject.is_male
subject_sex = map_sex_value(subject_sex)
sex_groups[subject_sex][outcome] += 1
sex_groups[subject_sex][TOTAL] += 1
data = {
AGE: age_groups,
DISTRICT: district_groups,
SEX: sex_groups,
TOTAL: len(case_subjects),
}
return JsonResponse(data=data, status=status.HTTP_200_OK)
......@@ -52,6 +52,7 @@ INSTALLED_APPS = [
# Apps
"apps.accounts",
"apps.cases",
"apps.exportables",
"apps.logs",
]
......
......@@ -10,4 +10,5 @@ urlpatterns = [
path("logs/", include("apps.logs.urls")),
path("auth/token/", obtain_auth_token, name="api_token_auth"),
path("auth/", include("django.contrib.auth.urls")),
path("exportables/", include("apps.exportables.urls")),
]
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment