Skip to content

Commit

Permalink
Convert ABDM into Plug - Part 1/3 (#2161)
Browse files Browse the repository at this point in the history
* added consent flows in abdm

* made patient_abha as a foriegn key field in consent

* renamed patient_health_id to patient_abha

* renamed patient_health_id to patient_abha

* added filterset class to consent

* send external_id as id in consent serializer

* resolved migration conflicts

* seperated out consent request and consent artefact

* get health information from hip

* decrypt data from abdm

* store health information in s3

* moved status from consent request to consent artefact

* display health information

* added patients find apis

* added consents__hiu__notify

* send push notification in patients/on-find

* fixed gateway api calls

* remove date range from health-information/cm/request

* added ratelimits to abdm m3 apis

* added status in consent request

* fix consent denied logic

* added facility filter to consent requests

* fixed a typo

* added patient_abha_object in consent request serializer

* fixed consent status update logic

* support retrieve hi docs by consent id

* added all the suggestions from review

* update migrations

* added date range to health_information__cm__request

* fixed reverse mapping of an enum REVERSE_CONDITION_VERIFICATION_STATUSES

* fix a type in health_id

* fix migration

* fix linting error

* added backend domain env

* removed https prefix while using BACKEND_DOMAIN

Co-authored-by: Aakash Singh <[email protected]>

* removed duplicate conditional logic

Co-authored-by: Aakash Singh <[email protected]>

* fix linting issues

* added patient field to abdm.abhanumber model

* remove abha_number field from facility.patientregistration model

* remove abdm references in the patient serializer

* remove abdm references (auto add care context on consultation create) in the consultation serializer

* removed an unused abdm import

* added related_name to patient field in abdm.abhanumber model

* add hasattr check while patient.abha_number and revert patient.abha_number to abha_number.patient while saving

* added consultation receiver to auto add care context on create

* added abha_number viewset and serializer

* remove abha number from patient model in dummy data

* resolve migration conflicts

* fix linting errors

* fixed migration reference

* Apply suggestions from code review

* resolve migration conflict

* use bulk update in reverse_patient_abhanumber_relation

* resolve migration conflict

* fix the migration logic abha_number not found on patient

* added validation errors

* replaced general exceptions with validation error

* fixed consent filters

* fix migration conflict

* fix dummy data

* revert dummy data changes

* remove abha_number field

* handle json decode errors for abdm responses

* use correct json exception

* fixed migration conflict

* check permission after filtering the query set in AbhaNumberViewSet retrieve

* resolve migration conflict

---------

Co-authored-by: Aakash Singh <[email protected]>
Co-authored-by: Khavin Shankar <[email protected]>
  • Loading branch information
3 people authored Sep 6, 2024
1 parent 4278d87 commit e011af5
Show file tree
Hide file tree
Showing 23 changed files with 8,662 additions and 8,694 deletions.
9 changes: 0 additions & 9 deletions care/abdm/api/serializers/abha.py

This file was deleted.

20 changes: 20 additions & 0 deletions care/abdm/api/serializers/abha_number.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# ModelSerializer
from rest_framework import serializers

from care.abdm.models import AbhaNumber
from care.facility.api.serializers.patient import PatientDetailSerializer
from care.facility.models import PatientRegistration
from care.utils.serializer.external_id_field import ExternalIdSerializerField


class AbhaNumberSerializer(serializers.ModelSerializer):
id = serializers.CharField(source="external_id", read_only=True)
patient = ExternalIdSerializerField(
queryset=PatientRegistration.objects.all(), required=False, allow_null=True
)
patient_object = PatientDetailSerializer(source="patient", read_only=True)
new = serializers.BooleanField(read_only=True)

class Meta:
model = AbhaNumber
exclude = ("deleted", "access_token", "refresh_token", "txn_id")
10 changes: 0 additions & 10 deletions care/abdm/api/serializers/abhanumber.py

This file was deleted.

2 changes: 1 addition & 1 deletion care/abdm/api/serializers/consent.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from rest_framework import serializers

from care.abdm.api.serializers.abhanumber import AbhaNumberSerializer
from care.abdm.api.serializers.abha_number import AbhaNumberSerializer
from care.abdm.models.consent import ConsentArtefact, ConsentRequest
from care.users.api.serializers.user import UserBaseMinimumSerializer

Expand Down
38 changes: 0 additions & 38 deletions care/abdm/api/viewsets/abha.py

This file was deleted.

52 changes: 52 additions & 0 deletions care/abdm/api/viewsets/abha_number.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from django.db.models import Q
from django.http import Http404
from rest_framework.decorators import action
from rest_framework.mixins import RetrieveModelMixin
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet

from care.abdm.api.serializers.abha_number import AbhaNumberSerializer
from care.abdm.models import AbhaNumber
from care.abdm.utils.api_call import HealthIdGateway
from care.utils.queryset.patient import get_patient_queryset


class AbhaNumberViewSet(
GenericViewSet,
RetrieveModelMixin,
):
serializer_class = AbhaNumberSerializer
model = AbhaNumber
queryset = AbhaNumber.objects.all()
permission_classes = (IsAuthenticated,)

def get_object(self):
id = self.kwargs.get("pk")

instance = self.queryset.filter(
Q(abha_number=id) | Q(health_id=id) | Q(patient__external_id=id)
).first()

if not instance or get_patient_queryset(self.request.user).contains(
instance.patient
):
raise Http404

self.check_object_permissions(self.request, instance)

return instance

@action(detail=True, methods=["GET"])
def qr_code(self, request, *args, **kwargs):
obj = self.get_object()
serializer = self.get_serializer(obj)
response = HealthIdGateway().get_qr_code(serializer.data)
return Response(response)

@action(detail=True, methods=["GET"])
def profile(self, request, *args, **kwargs):
obj = self.get_object()
serializer = self.get_serializer(obj)
response = HealthIdGateway().get_profile(serializer.data)
return Response(response)
62 changes: 20 additions & 42 deletions care/abdm/api/viewsets/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,7 @@ class OnFetchView(GenericAPIView):
def post(self, request, *args, **kwargs):
data = request.data

try:
AbdmGateway().init(data["resp"]["requestId"])
except Exception as e:
logger.warning(
f"Error: OnFetchView::post failed while initialising ABDM Gateway, Reason: {e}",
exc_info=True,
)
return Response(
{"detail": "Error: Initialising ABDM Gateway failed."},
status=status.HTTP_400_BAD_REQUEST,
)
AbdmGateway().init(data["resp"]["requestId"])

return Response({}, status=status.HTTP_202_ACCEPTED)

Expand Down Expand Up @@ -337,38 +327,26 @@ def post(self, request, *args, **kwargs):
}
)

try:
AbdmGateway().data_notify(
{
"health_id": consent["notification"]["consentDetail"]["patient"][
"id"
],
"consent_id": data["hiRequest"]["consent"]["id"],
"transaction_id": data["transactionId"],
"session_status": "TRANSFERRED"
AbdmGateway().data_notify(
{
"health_id": consent["notification"]["consentDetail"]["patient"]["id"],
"consent_id": data["hiRequest"]["consent"]["id"],
"transaction_id": data["transactionId"],
"session_status": (
"TRANSFERRED"
if data_transfer_response
and data_transfer_response.status_code == 202
else "FAILED",
"care_contexts": list(
map(
lambda context: {"id": context["careContextReference"]},
consent["notification"]["consentDetail"]["careContexts"][
:-2:-1
],
)
),
}
)
except Exception as e:
logger.warning(
f"Error: RequestDataView::post failed to notify (health-information/notify). Reason: {e}",
exc_info=True,
)
return Response(
{
"detail": "Failed to notify (health-information/notify)",
},
status=status.HTTP_400_BAD_REQUEST,
)
else "FAILED"
),
"care_contexts": list(
map(
lambda context: {"id": context["careContextReference"]},
consent["notification"]["consentDetail"]["careContexts"][
:-2:-1
],
)
),
}
)

return Response({}, status=status.HTTP_202_ACCEPTED)
22 changes: 5 additions & 17 deletions care/abdm/api/viewsets/consent.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@


class ConsentRequestFilter(filters.FilterSet):
patient = filters.UUIDFilter(
field_name="patient_abha__patientregistration__external_id"
)
patient = filters.UUIDFilter(field_name="patient_abha__patient__external_id")
health_id = filters.CharFilter(field_name="patient_abha__health_id")
ordering = filters.OrderingFilter(
fields=(
Expand All @@ -33,7 +31,7 @@ class ConsentRequestFilter(filters.FilterSet):
)
)
facility = filters.UUIDFilter(
field_name="patient_abha__patientregistration__facility__external_id"
field_name="patient_abha__patient__facility__external_id"
)

class Meta:
Expand Down Expand Up @@ -71,19 +69,9 @@ def create(self, request):

consent = ConsentRequest(**serializer.validated_data, requester=request.user)

try:
response = Gateway().consent_requests__init(consent)
if response.status_code != 202:
return Response(response.json(), status=response.status_code)
except Exception as e:
logger.warning(
f"Error: ConsentViewSet::create failed to notify (consent_requests__init). Reason: {e}",
exc_info=True,
)
return Response(
{"detail": "Failed to initialize consent request"},
status=status.HTTP_400_BAD_REQUEST,
)
response = Gateway().consent_requests__init(consent)
if response.status_code != 202:
return Response(response.json(), status=response.status_code)

consent.save()
return Response(
Expand Down
12 changes: 1 addition & 11 deletions care/abdm/api/viewsets/health_information.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,16 +142,6 @@ def health_information__transfer(self, request):
file.upload_completed = True
file.save()

try:
Gateway().health_information__notify(artefact)
except Exception as e:
logger.warning(
f"Error: health_information__transfer::post failed to notify (health-information/notify). Reason: {e}",
exc_info=True,
)
return Response(
{"detail": "Failed to notify (health-information/notify)"},
status=status.HTTP_400_BAD_REQUEST,
)
Gateway().health_information__notify(artefact)

return Response(status=status.HTTP_202_ACCEPTED)
Loading

0 comments on commit e011af5

Please sign in to comment.