from datetime import datetime from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from rest_framework.permissions import IsAuthenticated from rest_framework_simplejwt.authentication import JWTAuthentication from django.db.models import Prefetch from module_project import constants from module_project.utils import ApiResponse from module_iam.models import IAmPrincipal from ..models import ( PrincipalHealthData, Intolerance, Symptoms, PastTreatment, ChronicCondition, Medication, Bowel, MealSymptomRecord, MealRecord, ) from .serializers import ( IntoleranceSerializer, SymptomsSerializer, PastTreatmentSerializer, ChronicConditionSerializer, MedicationSerializer, BowelSerializer, MealSymptomRecordSerializer, MealRecordSerializer, IAmPrincipalSerializer, PrincipalHealthDataSerializer, PrincipalAndHealthSerializer, ) class ProfileAPIView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] post_serializer_class = IAmPrincipalSerializer get_serializer_class = PrincipalAndHealthSerializer model = IAmPrincipal def get(self, request): try: obj = self.model.objects.prefetch_related("health_data_principal").get( pk=request.user.pk ) serializer = self.get_serializer_class(obj, context={"request": request}) except self.model.DoesNotExist: return ApiResponse.error( status=status.HTTP_404_NOT_FOUND, message=constants.RECORD_NOT_FOUND ) print(f"object data is {obj}") return ApiResponse.success(message=constants.SUCCESS, data=serializer.data) def post(self, request): data = request.data.copy() # Separate principal and health data principal_data = {} health_data = {} for key, value in data.items(): if key in self.post_serializer_class.Meta.fields: principal_data[key] = value else: health_data[key] = value principal_serializer = self.post_serializer_class( instance=request.user, data=principal_data ) health_serializer = PrincipalHealthDataSerializer(data=health_data) if not principal_serializer.is_valid(): return ApiResponse.error( message=constants.FAILURE, errors=principal_serializer.errors ) if not health_serializer.is_valid(): return ApiResponse.error( message=constants.FAILURE, errors=health_serializer.errors ) try: # with transaction.atomic(): # Ensure atomicity of database operations principal_instance = principal_serializer.save() # Check if health data already exists for the principal health_data_instance, created = PrincipalHealthData.objects.get_or_create( principal=principal_instance ) health_serializer.update(health_data_instance, health_data) except Exception as e: return ApiResponse.error(message=constants.FAILURE, errors=str(e)) return ApiResponse.success(message=constants.SUCCESS) class DailyRecordAPIView(APIView): def serialize_record(self, record): time_obj = datetime.strptime(str(record.time), '%H:%M:%S') return { "id": record.id, "date": record.date, "time": time_obj.strftime('%I:%M %p'), # Add other fields as needed } def get(self, request): date = request.GET.get("date") # date = datetime.now().date() if not date: return ApiResponse.error(message=constants.FAILURE, errors="Date parameter is missing") try: # Convert the date string to a datetime object date_obj = datetime.strptime(date, "%Y-%m-%d").date() except ValueError: return ApiResponse.error(message=constants.FAILURE, errors="Invalid date format") # Define prefetch related queries for filtering the record of paticular date of all related models meal_records_prefetch = Prefetch( "meal_principal", queryset=MealRecord.objects.filter(date=date), to_attr="filtered_meal_record", ) medication_prefetch = Prefetch( "medication_principal", queryset=Medication.objects.filter(date=date), to_attr="filtered_medication", ) bowel_prefetch = Prefetch( "bowel_principal", queryset=Bowel.objects.filter(date=date), to_attr="filtered_bowel", ) meal_symptom_prefetch = Prefetch( "meal_symptom_principal", queryset=MealSymptomRecord.objects.filter(date=date), to_attr="filtered_meal_symptom", ) # Query the IAmPrincipal table of principal with prefetch_related to retrieve related records principal = IAmPrincipal.objects.prefetch_related( meal_records_prefetch, medication_prefetch, bowel_prefetch, meal_symptom_prefetch, ).get(id=request.user.id) serialized_meal_records = [ {"type": "Meal", **self.serialize_record(record)} for record in principal.filtered_meal_record ] serialized_medication = [ {"type": "Medication", **self.serialize_record(record)} for record in principal.filtered_medication ] serialized_bowel = [ {"type": "Bowel Movements", **self.serialize_record(record)} for record in principal.filtered_bowel ] serialized_symptom = [ {"type": "Symptom - Meal", **self.serialize_record(record)} for record in principal.filtered_meal_symptom ] all_records = (serialized_symptom + serialized_meal_records + serialized_medication + serialized_bowel) # all_records_sorted = sorted(all_records, key=lambda x: x["time"], reverse=True) all_records_sorted = sorted( all_records, key=lambda x: x["time"], reverse=True ) return ApiResponse.success( message=constants.SUCCESS, data=all_records_sorted ) class IntoleranceListCreateAPIView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] serializer_class = IntoleranceSerializer model = Intolerance def get(self, request): obj = self.model.objects.filter(principal=request.user) serializer = self.serializer_class(obj, many=True) return ApiResponse.success(message=constants.SUCCESS, data=serializer.data) def post(self, request): print(f"request data for intolerance is {request.data}") serializer = self.serializer_class(data=request.data, many=True) if not serializer.is_valid(): return ApiResponse.error( message=constants.FAILURE, errors=serializer.errors ) try: self.model.objects.filter(principal=request.user).delete() instance = serializer.save(principal=request.user) saved_data_serializer = self.serializer_class(instance, many=True) return ApiResponse.success( message=constants.SUCCESS, data=saved_data_serializer.data ) except Exception as e: return ApiResponse.error(message=constants.FAILURE, errors=str(e)) class SymptomsListCreateAPIView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] serializer_class = SymptomsSerializer model = Symptoms def get(self, request): obj = self.model.objects.filter(principal=request.user) serializer = self.serializer_class(obj, many=True) return ApiResponse.success(message=constants.SUCCESS, data=serializer.data) def post(self, request): print(f"request data for Symptoms is {request.data}") serializer = self.serializer_class(data=request.data, many=True) if not serializer.is_valid(): return ApiResponse.error( message=constants.FAILURE, errors=serializer.errors ) try: self.model.objects.filter(principal=request.user).delete() instance = serializer.save(principal=request.user) saved_data_serializer = self.serializer_class(instance, many=True) return ApiResponse.success( message=constants.SUCCESS, data=saved_data_serializer.data ) except Exception as e: return ApiResponse.error(message=constants.FAILURE, errors=str(e)) class PastTreatmentListCreateAPIView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] serializer_class = PastTreatmentSerializer model = PastTreatment def get(self, request): obj = self.model.objects.filter(principal=request.user) serializer = self.serializer_class(obj, many=True) return ApiResponse.success(message=constants.SUCCESS, data=serializer.data) def post(self, request): print(f"request data for PastTreatment is {request.data}") serializer = self.serializer_class(data=request.data, many=True) if not serializer.is_valid(): return ApiResponse.error( message=constants.FAILURE, errors=serializer.errors ) try: self.model.objects.filter(principal=request.user).delete() instance = serializer.save(principal=request.user) saved_data_serializer = self.serializer_class(instance, many=True) return ApiResponse.success( message=constants.SUCCESS, data=saved_data_serializer.data ) except Exception as e: return ApiResponse.error(message=constants.FAILURE, errors=str(e)) class ChronicConditionListCreateAPIView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] serializer_class = ChronicConditionSerializer model = ChronicCondition def get(self, request): obj = self.model.objects.filter(principal=request.user) serializer = self.serializer_class(obj, many=True) return ApiResponse.success(message=constants.SUCCESS, data=serializer.data) def post(self, request): print(f"request data for PastTreatment is {request.data}") serializer = self.serializer_class(data=request.data, many=True) if not serializer.is_valid(): return ApiResponse.error( message=constants.FAILURE, errors=serializer.errors ) try: self.model.objects.filter(principal=request.user).delete() instance = serializer.save(principal=request.user) saved_data_serializer = self.serializer_class(instance, many=True) return ApiResponse.success( message=constants.SUCCESS, data=saved_data_serializer.data ) except Exception as e: return ApiResponse.error(message=constants.FAILURE, errors=str(e)) class MedicationAPIView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] serializer_class = MedicationSerializer model = Medication def get_objects(self, pk): try: return self.model.objects.get(pk=pk) except self.model.DoesNotExist: return ApiResponse.error( status=status.HTTP_404_NOT_FOUND, message=constants.RECORD_NOT_FOUND ) def get(self, request, pk): obj = self.get_objects(pk) if isinstance(obj, Response): return obj serializer = self.serializer_class(obj) return ApiResponse.success(message=constants.SUCCESS, data=serializer.data) def post(self, request): serializer = self.serializer_class(data=request.data) if not serializer.is_valid(): return ApiResponse.error( message=constants.FAILURE, errors=serializer.errors ) try: serializer.save(principal=request.user) except Exception as e: return ApiResponse.error(message=constants.FAILURE, errors=str(e)) return ApiResponse.success( status=status.HTTP_201_CREATED, message=constants.SUCCESS, data=serializer.data, ) def put(self, request, pk): obj = self.get_objects(pk) if isinstance(obj, Response): return obj serializer = self.serializer_class(obj, data=request.data) if not serializer.is_valid(): return ApiResponse.error(message=constants.FAILURE, errors=serializer.data) try: serializer.save() except Exception as e: return ApiResponse.error(message=constants.FAILURE, errors=str(e)) return ApiResponse.success( status=status.HTTP_201_CREATED, message=constants.SUCCESS, data=serializer.data, ) def delete(self, request, pk): obj = self.get_objects(pk) if isinstance(obj, Response): return obj try: obj.delete() except Exception as e: return ApiResponse.error(message=constants.FAILURE, errors=str(e)) return ApiResponse.success( message=constants.RECORD_DELETED, status=status.HTTP_204_NO_CONTENT ) class BowelAPIView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] serializer_class = BowelSerializer model = Bowel def get_objects(self, pk): try: return self.model.objects.get(pk=pk) except self.model.DoesNotExist: return ApiResponse.error( status=status.HTTP_404_NOT_FOUND, message=constants.RECORD_NOT_FOUND ) def get(self, request, pk): obj = self.get_objects(pk) if isinstance(obj, Response): return obj serializer = self.serializer_class(obj) return ApiResponse.success(message=constants.SUCCESS, data=serializer.data) def post(self, request): serializer = self.serializer_class(data=request.data) if not serializer.is_valid(): return ApiResponse.error( message=constants.FAILURE, errors=serializer.errors ) try: serializer.save(principal=request.user) except Exception as e: return ApiResponse.error(message=constants.FAILURE, errors=str(e)) return ApiResponse.success( status=status.HTTP_201_CREATED, message=constants.SUCCESS, data=serializer.data, ) def put(self, request, pk): obj = self.get_objects(pk) if isinstance(obj, Response): return obj serializer = self.serializer_class(obj, data=request.data) if not serializer.is_valid(): return ApiResponse.error(message=constants.FAILURE, errors=serializer.data) try: serializer.save() except Exception as e: return ApiResponse.error(message=constants.FAILURE, errors=str(e)) return ApiResponse.success( status=status.HTTP_201_CREATED, message=constants.SUCCESS, data=serializer.data, ) def delete(self, request, pk): obj = self.get_objects(pk) if isinstance(obj, Response): return obj try: obj.delete() except Exception as e: return ApiResponse.error(message=constants.FAILURE, errors=str(e)) return ApiResponse.success( message=constants.RECORD_DELETED, status=status.HTTP_204_NO_CONTENT ) class MealSymptomAPIView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] serializer_class = MealSymptomRecordSerializer model = MealSymptomRecord def get_objects(self, pk): try: return self.model.objects.get(pk=pk) except self.model.DoesNotExist: return ApiResponse.error( status=status.HTTP_404_NOT_FOUND, message=constants.RECORD_NOT_FOUND ) def get(self, request, pk): obj = self.get_objects(pk) if isinstance(obj, Response): return obj serializer = self.serializer_class(obj) return ApiResponse.success(message=constants.SUCCESS, data=serializer.data) def post(self, request): serializer = self.serializer_class(data=request.data) if not serializer.is_valid(): return ApiResponse.error( message=constants.FAILURE, errors=serializer.errors ) try: serializer.save(principal=request.user) except Exception as e: return ApiResponse.error(message=constants.FAILURE, errors=str(e)) return ApiResponse.success( status=status.HTTP_201_CREATED, message=constants.SUCCESS, data=serializer.data, ) def put(self, request, pk): obj = self.get_objects(pk) if isinstance(obj, Response): return obj serializer = self.serializer_class(obj, data=request.data) if not serializer.is_valid(): return ApiResponse.error(message=constants.FAILURE, errors=serializer.data) try: serializer.save() except Exception as e: return ApiResponse.error(message=constants.FAILURE, errors=str(e)) return ApiResponse.success( status=status.HTTP_201_CREATED, message=constants.SUCCESS, data=serializer.data, ) def delete(self, request, pk): obj = self.get_objects(pk) if isinstance(obj, Response): return obj try: obj.delete() except Exception as e: return ApiResponse.error(message=constants.FAILURE, errors=str(e)) return ApiResponse.success( message=constants.RECORD_DELETED, status=status.HTTP_204_NO_CONTENT ) class MealAPIView(APIView): authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] serializer_class = MealRecordSerializer model = MealRecord def get_objects(self, pk): try: return self.model.objects.get(pk=pk) except self.model.DoesNotExist: return ApiResponse.error( status=status.HTTP_404_NOT_FOUND, message=constants.RECORD_NOT_FOUND ) def get(self, request, pk): obj = self.get_objects(pk) if isinstance(obj, Response): return obj serializer = self.serializer_class(obj) return ApiResponse.success(message=constants.SUCCESS, data=serializer.data) def post(self, request): serializer = self.serializer_class(data=request.data) if not serializer.is_valid(): return ApiResponse.error( message=constants.FAILURE, errors=serializer.errors ) try: serializer.save(principal=request.user) except Exception as e: return ApiResponse.error(message=constants.FAILURE, errors=str(e)) return ApiResponse.success( status=status.HTTP_201_CREATED, message=constants.SUCCESS, data=serializer.data, ) def put(self, request, pk): obj = self.get_objects(pk) if isinstance(obj, Response): return obj serializer = self.serializer_class(obj, data=request.data) if not serializer.is_valid(): return ApiResponse.error(message=constants.FAILURE, errors=serializer.data) try: serializer.save() except Exception as e: return ApiResponse.error(message=constants.FAILURE, errors=str(e)) return ApiResponse.success( status=status.HTTP_201_CREATED, message=constants.SUCCESS, data=serializer.data, ) def delete(self, request, pk): obj = self.get_objects(pk) if isinstance(obj, Response): return obj try: obj.delete() except Exception as e: return ApiResponse.error(message=constants.FAILURE, errors=str(e)) return ApiResponse.success( message=constants.RECORD_DELETED, status=status.HTTP_204_NO_CONTENT )