Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Location, Device, Filters and More #2782

Merged
merged 26 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
07f3f70
added swaggar support
DraKen0009 Jan 22, 2025
837f0ae
added more swaggar support
DraKen0009 Jan 22, 2025
853427f
fixed create mixin change
DraKen0009 Jan 22, 2025
58a9987
reverted status code change
DraKen0009 Jan 22, 2025
00550df
Merge branch 'develop' into prafful/feat/adding-swagger-support
DraKen0009 Jan 22, 2025
1932fd6
Merge branch 'develop' into prafful/feat/adding-swagger-support
DraKen0009 Jan 23, 2025
aff7fdb
created a decorator for schema generation
DraKen0009 Jan 24, 2025
83cf327
merged develop
DraKen0009 Jan 24, 2025
de73f58
updated the decorator
DraKen0009 Jan 24, 2025
d7b4084
updated decorator to include tags
DraKen0009 Jan 26, 2025
a46ca16
Merge branch 'develop' into prafful/feat/adding-swagger-support
DraKen0009 Jan 26, 2025
45cdda8
update for tags
DraKen0009 Jan 26, 2025
fff6497
Add Location Spec
vigneshhari Jan 26, 2025
f71f10b
Add filters in resource request
vigneshhari Jan 26, 2025
680b141
Merge branch 'vigneshhari/locations' into prafful/feat/adding-swagger…
vigneshhari Jan 26, 2025
b9d5b0f
Merge pull request #2772 from ohcnetwork/prafful/feat/adding-swagger-…
vigneshhari Jan 26, 2025
b84c835
cleanup migrations
vigneshhari Jan 26, 2025
7539d2e
Added TODO items
vigneshhari Jan 26, 2025
70c9bfc
Clean up HTML files and references
vigneshhari Jan 27, 2025
5795b88
Clean up HTML files and references
vigneshhari Jan 27, 2025
2e6d015
Location API fixes
vigneshhari Jan 27, 2025
a2bcd02
Location API fixes
vigneshhari Jan 27, 2025
8d62a30
Fixed permission issues ?
vigneshhari Jan 27, 2025
be2f03c
Linting fixes
vigneshhari Jan 27, 2025
6176fd6
updated swagger schema (#2789)
DraKen0009 Jan 29, 2025
37c3df3
Fixing bugs
vigneshhari Jan 29, 2025
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
9 changes: 9 additions & 0 deletions care/emr/api/otp_viewsets/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@

from django.conf import settings
from django.utils import timezone
from drf_spectacular.utils import extend_schema
from pydantic import BaseModel, Field, field_validator
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.response import Response

from care.emr.api.viewsets.base import EMRBaseViewSet
from care.facility.models.patient import PatientMobileOTP
from care.utils.decorators.schema_decorator import generate_swagger_schema_decorator
from care.utils.models.validators import mobile_validator
from care.utils.sms.send_sms import send_sms
from config.patient_otp_token import PatientToken
Expand Down Expand Up @@ -41,10 +43,14 @@ class OTPLoginSpec(OTPLoginRequestSpec):
otp: str = Field(min_length=settings.OTP_LENGTH, max_length=settings.OTP_LENGTH)


@generate_swagger_schema_decorator
class OTPLoginView(EMRBaseViewSet):
authentication_classes = []
permission_classes = []

@extend_schema(
request=OTPLoginRequestSpec,
)
@action(detail=False, methods=["POST"])
def send(self, request):
data = OTPLoginRequestSpec(**request.data)
Expand Down Expand Up @@ -76,6 +82,9 @@ def send(self, request):
otp_obj.save()
return Response({"otp": "generated"})

@extend_schema(
request=OTPLoginSpec,
)
@action(detail=False, methods=["POST"])
def login(self, request):
data = OTPLoginSpec(**request.data)
Expand Down
2 changes: 2 additions & 0 deletions care/emr/api/otp_viewsets/patient.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
PatientOTPReadSpec,
PatientOTPWriteSpec,
)
from care.utils.decorators.schema_decorator import generate_swagger_schema_decorator
from config.patient_otp_authentication import (
JWTTokenPatientAuthentication,
OTPAuthenticatedPermission,
)


@generate_swagger_schema_decorator
class PatientOTPView(EMRCreateMixin, EMRListMixin, EMRBaseViewSet):
authentication_classes = [JWTTokenPatientAuthentication]
permission_classes = [OTPAuthenticatedPermission]
Expand Down
12 changes: 12 additions & 0 deletions care/emr/api/otp_viewsets/slot.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from drf_spectacular.utils import extend_schema
from pydantic import UUID4, BaseModel
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
Expand All @@ -18,6 +19,7 @@
TokenBookingReadSpec,
TokenSlotBaseSpec,
)
from care.utils.decorators.schema_decorator import generate_swagger_schema_decorator
from config.patient_otp_authentication import (
JWTTokenPatientAuthentication,
OTPAuthenticatedPermission,
Expand All @@ -33,19 +35,26 @@ class CancelAppointmentSpec(BaseModel):
appointment: UUID4


@generate_swagger_schema_decorator
class OTPSlotViewSet(EMRRetrieveMixin, EMRBaseViewSet):
authentication_classes = [JWTTokenPatientAuthentication]
permission_classes = [OTPAuthenticatedPermission]
database_model = TokenSlot
pydantic_read_model = TokenSlotBaseSpec

@extend_schema(
request=SlotsForDayRequestSpec,
)
@action(detail=False, methods=["POST"])
def get_slots_for_day(self, request, *args, **kwargs):
request_data = SlotsForDayRequestSpec(**request.data)
return SlotViewSet.get_slots_for_day_handler(
request_data.facility, request.data
)

@extend_schema(
request=AppointmentBookingSpec,
)
@action(detail=True, methods=["POST"])
def create_appointment(self, request, *args, **kwargs):
request_data = AppointmentBookingSpec(**request.data)
Expand All @@ -57,6 +66,9 @@ def create_appointment(self, request, *args, **kwargs):
self.get_object(), request.data, None
)

@extend_schema(
request=CancelAppointmentSpec,
)
@action(detail=False, methods=["POST"])
def cancel_appointment(self, request, *args, **kwargs):
request_data = CancelAppointmentSpec(**request.data)
Expand Down
2 changes: 2 additions & 0 deletions care/emr/api/viewsets/allergy_intolerance.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@
)
from care.emr.resources.questionnaire.spec import SubjectType
from care.security.authorization import AuthorizationController
from care.utils.decorators.schema_decorator import generate_swagger_schema_decorator


class AllergyIntoleranceFilters(FilterSet):
clinical_status = CharFilter(field_name="clinical_status")


@generate_swagger_schema_decorator
@extend_schema_view(
create=extend_schema(request=AllergyIntoleranceWriteSpec),
)
Expand Down
8 changes: 7 additions & 1 deletion care/emr/api/viewsets/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from django.db import transaction
from django.http.response import Http404
from pydantic import ValidationError
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError as RestFrameworkValidationError
from rest_framework.generics import get_object_or_404
Expand Down Expand Up @@ -183,11 +184,15 @@ def perform_destroy(self, instance):
instance.deleted = True
instance.save(update_fields=["deleted"])

def validate_destroy(self, instance):
pass

def destroy(self, request, *args, **kwargs):
instance = self.get_object()
self.validate_destroy(instance)
self.authorize_destroy(instance)
self.perform_destroy(instance)
return Response(status=204)
return Response(status=status.HTTP_204_NO_CONTENT)


class EMRUpsertMixin:
Expand Down Expand Up @@ -225,6 +230,7 @@ class EMRBaseViewSet(GenericViewSet):
pydantic_retrieve_model: EMRResource = None
database_model: EMRBaseModel = None
lookup_field = "external_id"
tags = [__name__]

def get_exception_handler(self):
return emr_exception_handler
Expand Down
4 changes: 4 additions & 0 deletions care/emr/api/viewsets/batch_request.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.db import transaction
from drf_spectacular.utils import extend_schema
from pydantic import BaseModel, Field
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet
Expand Down Expand Up @@ -26,6 +27,9 @@ class BatchRequestView(GenericViewSet):
def get_exception_handler(self):
return emr_exception_handler

@extend_schema(
request=BatchRequest,
)
vigneshhari marked this conversation as resolved.
Show resolved Hide resolved
def create(self, request, *args, **kwargs):
requests = BatchRequest(**request.data)
errored = False
Expand Down
4 changes: 4 additions & 0 deletions care/emr/api/viewsets/condition.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
)
from care.emr.resources.questionnaire.spec import SubjectType
from care.security.authorization import AuthorizationController
from care.utils.decorators.schema_decorator import generate_swagger_schema_decorator


class ValidateEncounterMixin:
Expand Down Expand Up @@ -58,6 +59,7 @@ class ConditionFilters(FilterSet):
severity = CharFilter(field_name="severity", lookup_expr="iexact")


@generate_swagger_schema_decorator
class SymptomViewSet(
ValidateEncounterMixin,
EncounterBasedAuthorizationBase,
Expand Down Expand Up @@ -98,6 +100,7 @@ def get_queryset(self):
InternalQuestionnaireRegistry.register(SymptomViewSet)


@generate_swagger_schema_decorator
class DiagnosisViewSet(
ValidateEncounterMixin,
EncounterBasedAuthorizationBase,
Expand Down Expand Up @@ -139,6 +142,7 @@ def get_queryset(self):
InternalQuestionnaireRegistry.register(DiagnosisViewSet)


@generate_swagger_schema_decorator
class ChronicConditionViewSet(
EMRQuestionnaireResponseMixin,
EMRCreateMixin,
Expand Down
14 changes: 13 additions & 1 deletion care/emr/api/viewsets/encounter.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
)
from care.facility.models import Facility
from care.security.authorization import AuthorizationController
from care.utils.decorators.schema_decorator import generate_swagger_schema_decorator


class LiveFilter(filters.CharFilter):
Expand Down Expand Up @@ -78,6 +79,7 @@ class EncounterFilters(filters.FilterSet):
live = LiveFilter()


@generate_swagger_schema_decorator
class EncounterViewSet(
EMRCreateMixin, EMRRetrieveMixin, EMRUpdateMixin, EMRListMixin, EMRBaseViewSet
):
Expand Down Expand Up @@ -175,6 +177,10 @@ def organizations(self, request, *args, **kwargs):
class EncounterOrganizationManageSpec(BaseModel):
organization: UUID4

@extend_schema(
request=EncounterOrganizationManageSpec,
responses={200: FacilityOrganizationReadSpec},
)
@action(detail=True, methods=["POST"])
def organizations_add(self, request, *args, **kwargs):
instance = self.get_object()
Expand All @@ -195,6 +201,9 @@ def organizations_add(self, request, *args, **kwargs):
)
return Response(FacilityOrganizationReadSpec.serialize(organization).to_json())

@extend_schema(
request=EncounterOrganizationManageSpec,
)
@action(detail=True, methods=["DELETE"])
def organizations_remove(self, request, *args, **kwargs):
instance = self.get_object()
Expand All @@ -213,7 +222,7 @@ def organizations_remove(self, request, *args, **kwargs):
EncounterOrganization.objects.filter(
encounter=instance, organization=organization
).delete()
return Response({}, status=204)
return Response({}, status=status.HTTP_204_NO_CONTENT)

def _check_discharge_summary_access(self, encounter):
if not AuthorizationController.call(
Expand Down Expand Up @@ -284,6 +293,9 @@ def validate_email(cls, value):
django_validate_email(value)
return value

@extend_schema(
request=EmailDischargeSummarySpec,
)
@action(detail=True, methods=["POST"])
def email_discharge_summary(self, request, *args, **kwargs):
encounter = self.get_object()
Expand Down
30 changes: 17 additions & 13 deletions care/emr/api/viewsets/facility.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from care.facility.models import Facility
from care.security.authorization import AuthorizationController
from care.users.models import User
from care.utils.decorators.schema_decorator import generate_swagger_schema_decorator
from care.utils.file_uploads.cover_image import delete_cover_image, upload_cover_image
from care.utils.models.validators import (
cover_image_validator,
Expand Down Expand Up @@ -71,6 +72,7 @@ class FacilityFilters(filters.FilterSet):
phone_number = CharFilter(field_name="phone_number", lookup_expr="iexact")


@generate_swagger_schema_decorator
class FacilityViewSet(EMRModelViewSet):
database_model = Facility
pydantic_model = FacilityCreateSpec
Expand Down Expand Up @@ -112,25 +114,25 @@ def authorize_destroy(self, instance):
raise PermissionDenied("Only Super Admins can delete Facilities")

@method_decorator(parser_classes([MultiPartParser]))
@action(methods=["POST"], detail=True)
@action(methods=["POST", "DELETE"], detail=True)
def cover_image(self, request, external_id):
facility = self.get_object()
self.authorize_update({}, facility)
serializer = FacilityImageUploadSerializer(facility, data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)

@cover_image.mapping.delete
def cover_image_delete(self, *args, **kwargs):
facility = self.get_object()
self.authorize_update({}, facility)
delete_cover_image(facility.cover_image_url, "cover_images")
facility.cover_image_url = None
facility.save()
return Response(status=204)
if request.method == "POST":
serializer = FacilityImageUploadSerializer(facility, data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
if request.method == "DELETE":
delete_cover_image(facility.cover_image_url, "cover_images")
facility.cover_image_url = None
facility.save()
return Response(status=204)
return Response(data="Method Not Allowed", status=405)
vigneshhari marked this conversation as resolved.
Show resolved Hide resolved


@generate_swagger_schema_decorator
class FacilitySchedulableUsersViewSet(EMRModelReadOnlyViewSet):
database_model = User
pydantic_read_model = UserSpec
Expand All @@ -149,6 +151,7 @@ class FacilityUserFilter(FilterSet):
username = CharFilter(field_name="username", lookup_expr="icontains")


@generate_swagger_schema_decorator
class FacilityUsersViewSet(EMRModelReadOnlyViewSet):
database_model = User
pydantic_read_model = UserSpec
Expand All @@ -163,6 +166,7 @@ def get_queryset(self):
)


@generate_swagger_schema_decorator
class AllFacilityViewSet(EMRModelReadOnlyViewSet):
permission_classes = ()
authentication_classes = ()
Expand Down
3 changes: 3 additions & 0 deletions care/emr/api/viewsets/facility_organization.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from care.facility.models import Facility
from care.security.authorization import AuthorizationController
from care.security.models import RoleModel
from care.utils.decorators.schema_decorator import generate_swagger_schema_decorator


class FacilityOrganizationFilter(filters.FilterSet):
Expand All @@ -28,6 +29,7 @@ class FacilityOrganizationFilter(filters.FilterSet):
org_type = filters.CharFilter(field_name="org_type", lookup_expr="iexact")


@generate_swagger_schema_decorator
class FacilityOrganizationViewSet(EMRModelViewSet):
database_model = FacilityOrganization
pydantic_model = FacilityOrganizationWriteSpec
Expand Down Expand Up @@ -150,6 +152,7 @@ def mine(self, request, *args, **kwargs):
return Response({"count": len(data), "results": data})


@generate_swagger_schema_decorator
class FacilityOrganizationUsersViewSet(EMRModelViewSet):
database_model = FacilityOrganizationUser
pydantic_model = FacilityOrganizationUserWriteSpec
Expand Down
8 changes: 8 additions & 0 deletions care/emr/api/viewsets/file_upload.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.utils import timezone
from django_filters import rest_framework as filters
from drf_spectacular.utils import extend_schema
from pydantic import BaseModel
from rest_framework.decorators import action
from rest_framework.exceptions import PermissionDenied
Expand All @@ -22,6 +23,7 @@
FileUploadUpdateSpec,
)
from care.security.authorization import AuthorizationController
from care.utils.decorators.schema_decorator import generate_swagger_schema_decorator


def file_authorizer(user, file_type, associating_id, permission):
Expand Down Expand Up @@ -57,6 +59,7 @@ class FileUploadFilter(filters.FilterSet):
is_archived = filters.BooleanFilter(field_name="is_archived")


@generate_swagger_schema_decorator
class FileUploadViewSet(
EMRCreateMixin, EMRRetrieveMixin, EMRUpdateMixin, EMRListMixin, EMRBaseViewSet
):
Expand Down Expand Up @@ -110,6 +113,7 @@ def get_queryset(self):
file_authorizer(self.request.user, obj.file_type, obj.associating_id, "read")
return super().get_queryset()

@extend_schema(responses={200: FileUploadListSpec})
@action(detail=True, methods=["POST"])
def mark_upload_completed(self, request, *args, **kwargs):
obj = self.get_object()
Expand All @@ -121,6 +125,10 @@ def mark_upload_completed(self, request, *args, **kwargs):
class ArchiveRequestSpec(BaseModel):
archive_reason: str

@extend_schema(
request=ArchiveRequestSpec,
responses={200: FileUploadListSpec},
)
@action(detail=True, methods=["POST"])
def archive(self, request, *args, **kwargs):
obj = self.get_object()
Expand Down
Loading