Skip to content

Commit

Permalink
Merge pull request #2032 from coronasafe/develop
Browse files Browse the repository at this point in the history
  • Loading branch information
gigincg authored Mar 28, 2024
2 parents 6ded533 + fa46f2f commit ae87c53
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 19 deletions.
31 changes: 24 additions & 7 deletions care/facility/api/serializers/file_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,12 @@ def check_permissions(file_type, associating_id, user, action="create"):
return patient.id
elif file_type == FileUpload.FileType.CONSULTATION.value:
consultation = PatientConsultation.objects.get(external_id=associating_id)
if consultation.discharge_date:
if not action == "read":
raise serializers.ValidationError(
{
"consultation": "Cannot upload file for a discharged consultation."
}
)
if consultation.discharge_date and not action == "read":
raise serializers.ValidationError(

Check warning on line 38 in care/facility/api/serializers/file_upload.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/serializers/file_upload.py#L38

Added line #L38 was not covered by tests
{
"consultation": "Cannot upload file for a discharged consultation."
}
)
if consultation.patient.assigned_to:
if user == consultation.patient.assigned_to:
return consultation.id
Expand All @@ -53,6 +52,24 @@ def check_permissions(file_type, associating_id, user, action="create"):
):
raise Exception("No Permission")
return consultation.id
elif file_type == FileUpload.FileType.CONSENT_RECORD.value:
consultation = PatientConsultation.objects.get(
consent_records__contains=[{"id": associating_id}]
)
if consultation.discharge_date and not action == "read":
raise serializers.ValidationError(

Check warning on line 60 in care/facility/api/serializers/file_upload.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/serializers/file_upload.py#L60

Added line #L60 was not covered by tests
{
"consultation": "Cannot upload file for a discharged consultation."
}
)
if (
user == consultation.assigned_to
or user == consultation.patient.assigned_to
or has_facility_permission(user, consultation.facility)
or has_facility_permission(user, consultation.patient.facility)
):
return associating_id
raise Exception("No Permission")

Check warning on line 72 in care/facility/api/serializers/file_upload.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/serializers/file_upload.py#L72

Added line #L72 was not covered by tests
elif file_type == FileUpload.FileType.DISCHARGE_SUMMARY.value:
consultation = PatientConsultation.objects.get(external_id=associating_id)
if (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Generated by Django 4.2.10 on 2024-03-27 17:32

from django.db import migrations, models

import care.utils.models.validators


class Migration(migrations.Migration):
dependencies = [
("facility", "0422_merge_20240325_1411"),
]

operations = [
migrations.AddField(
model_name="patientconsultation",
name="consent_records",
field=models.JSONField(
default=list,
validators=[
care.utils.models.validators.JSONFieldSchemaValidator(
{
"$schema": "http://json-schema.org/draft-07/schema#",
"items": [
{
"additionalProperties": False,
"properties": {
"deleted": {"type": "boolean"},
"id": {"type": "string"},
"patient_code_status": {"type": "number"},
"type": {"type": "number"},
},
"required": ["id", "type"],
"type": "object",
}
],
"type": "array",
}
)
],
),
),
migrations.AlterField(
model_name="fileupload",
name="file_type",
field=models.IntegerField(
choices=[
(1, "PATIENT"),
(2, "CONSULTATION"),
(3, "SAMPLE_MANAGEMENT"),
(4, "CLAIM"),
(5, "DISCHARGE_SUMMARY"),
(6, "COMMUNICATION"),
(7, "CONSENT_RECORD"),
],
default=1,
),
),
]
1 change: 1 addition & 0 deletions care/facility/models/file_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class FileType(enum.Enum):
CLAIM = 4
DISCHARGE_SUMMARY = 5
COMMUNICATION = 6
CONSENT_RECORD = 7

class FileCategory(enum.Enum):
UNSPECIFIED = "UNSPECIFIED"
Expand Down
18 changes: 18 additions & 0 deletions care/facility/models/json_schema/consultation.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,21 @@
}
],
}

CONSENT_RECORDS = {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"items": [
{
"type": "object",
"properties": {
"id": {"type": "string"},
"type": {"type": "number"},
"patient_code_status": {"type": "number"},
"deleted": {"type": "boolean"},
},
"additionalProperties": False,
"required": ["id", "type"],
}
],
}
17 changes: 6 additions & 11 deletions care/facility/models/patient_consultation.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
COVID_CATEGORY_CHOICES,
PatientBaseModel,
)
from care.facility.models.json_schema.consultation import CONSENT_RECORDS
from care.facility.models.mixins.permissions.patient import (
ConsultationRelatedPermissionMixin,
)
Expand All @@ -25,6 +26,7 @@
reverse_choices,
)
from care.users.models import User
from care.utils.models.validators import JSONFieldSchemaValidator


class PatientConsultation(PatientBaseModel, ConsultationRelatedPermissionMixin):
Expand Down Expand Up @@ -244,6 +246,10 @@ class PatientConsultation(PatientBaseModel, ConsultationRelatedPermissionMixin):
prn_prescription = JSONField(default=dict)
discharge_advice = JSONField(default=dict)

consent_records = JSONField(
default=list, validators=[JSONFieldSchemaValidator(CONSENT_RECORDS)]
)

def get_related_consultation(self):
return self

Expand Down Expand Up @@ -280,17 +286,6 @@ def get_related_consultation(self):
def __str__(self):
return f"{self.patient.name}<>{self.facility.name}"

def save(self, *args, **kwargs):
"""
# Removing Patient Hospital Change on Referral
if not self.pk or self.referred_to is not None:
# pk is None when the consultation is created
# referred to is not null when the person is being referred to a new facility
self.patient.facility = self.referred_to or self.facility
self.patient.save()
"""
super(PatientConsultation, self).save(*args, **kwargs)

class Meta:
constraints = [
models.CheckConstraint(
Expand Down
61 changes: 61 additions & 0 deletions care/facility/tests/test_file_upload.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import json

from rest_framework import status
from rest_framework.test import APITestCase

from care.facility.models.file_upload import FileUpload
from care.utils.tests.test_utils import TestUtils


Expand Down Expand Up @@ -46,3 +49,61 @@ def test_file_upload_whitelist(self):
},
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)


class ConsentFileUploadApiTestCase(TestUtils, APITestCase):
@classmethod
def setUpTestData(cls) -> None:
cls.state = cls.create_state()
cls.district = cls.create_district(cls.state)
cls.local_body = cls.create_local_body(cls.district)
cls.super_user = cls.create_super_user("su", cls.district)
cls.facility = cls.create_facility(cls.super_user, cls.district, cls.local_body)
cls.user = cls.create_user("nurse", cls.district, home_facility=cls.facility)
cls.patient = cls.create_patient(
cls.district, cls.facility, local_body=cls.local_body
)
cls.consultation = cls.create_consultation(cls.patient, cls.facility)

def test_consent_file_upload(self):
response = self.client.patch(
f"/api/v1/consultation/{self.consultation.external_id}/",
{
"consent_records": json.dumps(
[
{
"id": "consent-12345",
"type": 2,
"patient_code_status": 1,
}
]
)
},
)
self.assertEqual(response.status_code, status.HTTP_200_OK)

upload_response = self.client.post(
"/api/v1/files/",
{
"original_name": "test.pdf",
"file_type": "CONSENT_RECORD",
"name": "Test File",
"associating_id": "consent-12345",
"file_category": "UNSPECIFIED",
"mime_type": "application/pdf",
},
)

self.assertEqual(upload_response.status_code, status.HTTP_201_CREATED)

self.assertEqual(
FileUpload.objects.filter(associating_id="consent-12345").count(), 1
)

all_files = self.client.get(
"/api/v1/files/?associating_id=consent-12345&file_type=CONSENT_RECORD&is_archived=false"
)

self.assertEqual(all_files.status_code, status.HTTP_200_OK)
self.assertEqual(all_files.data["count"], 1)
self.assertEqual(all_files.data["results"][0]["name"], "Test File")
14 changes: 13 additions & 1 deletion care/users/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import uuid

from django.conf import settings
from django.contrib.auth.models import AbstractUser, UserManager
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
Expand Down Expand Up @@ -130,7 +131,18 @@ def get_entire_queryset(self):
return super().get_queryset().select_related("local_body", "district", "state")

def create_superuser(self, username, email, password, **extra_fields):
district = District.objects.all()[0]
district = District.objects.all().first()
data_command = (

Check warning on line 135 in care/users/models.py

View check run for this annotation

Codecov / codecov/patch

care/users/models.py#L134-L135

Added lines #L134 - L135 were not covered by tests
"load_data" if settings.IS_PRODUCTION is True else "load_dummy_data"
)
if not district:
proceed = input(

Check warning on line 139 in care/users/models.py

View check run for this annotation

Codecov / codecov/patch

care/users/models.py#L139

Added line #L139 was not covered by tests
f"It looks like you haven't loaded district data. It is recommended to populate district data before you create a super user. Please run `python manage.py {data_command}`.\n Proceed anyway? [y/N]"
)
if proceed.lower() != "y":
raise Exception("Aborted Superuser Creation")
district = None

Check warning on line 144 in care/users/models.py

View check run for this annotation

Codecov / codecov/patch

care/users/models.py#L143-L144

Added lines #L143 - L144 were not covered by tests

extra_fields["district"] = district
extra_fields["phone_number"] = "+919696969696"
extra_fields["gender"] = 3
Expand Down

0 comments on commit ae87c53

Please sign in to comment.