From 8946d5fda7f63f94803c4903cf5c878290408660 Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Tue, 23 May 2023 16:21:36 +0530 Subject: [PATCH 01/11] used prefetch_related method to optimize the query performed to fetch a many to many relationship --- care/users/api/serializers/user.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/care/users/api/serializers/user.py b/care/users/api/serializers/user.py index e3b0edc0db..ad594f1ceb 100644 --- a/care/users/api/serializers/user.py +++ b/care/users/api/serializers/user.py @@ -358,11 +358,6 @@ class UserAssignedSerializer(serializers.ModelSerializer): home_facility_object = FacilityBareMinimumSerializer( source="home_facility", read_only=True ) - skills = serializers.SerializerMethodField() - - def get_skills(self, obj): - qs = obj.skills.filter(userskill__deleted=False) - return SkillSerializer(qs, many=True).data class Meta: model = User @@ -382,6 +377,14 @@ class Meta: "skills", ) + def to_representation(self, instance): + representation = super().to_representation(instance) + instance = User.objects.prefetch_related("skills").get(pk=instance.pk) + skills = instance.skills.filter(userskill__deleted=False) + skills_data = SkillSerializer(skills, many=True).data + representation["skills"] = skills_data + return representation + class UserListSerializer(serializers.ModelSerializer): local_body_object = LocalBodySerializer(source="local_body", read_only=True) From 7d410fdb541859ccee1e8e51bdbd1d50d831207f Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Sat, 27 May 2023 00:12:51 +0530 Subject: [PATCH 02/11] Revert "add direnv support (#1304)" This reverts commit f6136618821e17278bd46824a0bcd9e3faad1960. --- .envrc | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 .envrc diff --git a/.envrc b/.envrc deleted file mode 100644 index f5f5cd5cd5..0000000000 --- a/.envrc +++ /dev/null @@ -1,2 +0,0 @@ -source .venv/bin/activate; unset PS1 -dotenv From 7179fdf297aac1c4a25d0b756e2d5881a1247d4d Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Sat, 27 May 2023 00:17:28 +0530 Subject: [PATCH 03/11] Revert "Revert "add direnv support (#1304)"" This reverts commit 7d410fdb541859ccee1e8e51bdbd1d50d831207f. --- .envrc | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .envrc diff --git a/.envrc b/.envrc new file mode 100644 index 0000000000..f5f5cd5cd5 --- /dev/null +++ b/.envrc @@ -0,0 +1,2 @@ +source .venv/bin/activate; unset PS1 +dotenv From 9cb5f7c0cf3145ddeb1d8de3c1436dac3a34563b Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Sat, 27 May 2023 00:18:01 +0530 Subject: [PATCH 04/11] Revert "used prefetch_related method to optimize the query performed to fetch a many to many relationship" This reverts commit 8946d5fda7f63f94803c4903cf5c878290408660. --- care/users/api/serializers/user.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/care/users/api/serializers/user.py b/care/users/api/serializers/user.py index ad594f1ceb..e3b0edc0db 100644 --- a/care/users/api/serializers/user.py +++ b/care/users/api/serializers/user.py @@ -358,6 +358,11 @@ class UserAssignedSerializer(serializers.ModelSerializer): home_facility_object = FacilityBareMinimumSerializer( source="home_facility", read_only=True ) + skills = serializers.SerializerMethodField() + + def get_skills(self, obj): + qs = obj.skills.filter(userskill__deleted=False) + return SkillSerializer(qs, many=True).data class Meta: model = User @@ -377,14 +382,6 @@ class Meta: "skills", ) - def to_representation(self, instance): - representation = super().to_representation(instance) - instance = User.objects.prefetch_related("skills").get(pk=instance.pk) - skills = instance.skills.filter(userskill__deleted=False) - skills_data = SkillSerializer(skills, many=True).data - representation["skills"] = skills_data - return representation - class UserListSerializer(serializers.ModelSerializer): local_body_object = LocalBodySerializer(source="local_body", read_only=True) From 7000a38bafd16e789ccf6ffc5f9a1f41d0c34429 Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Sat, 27 May 2023 02:17:43 +0530 Subject: [PATCH 05/11] used prefetch where we are querying the skills using UserAssigned Serializer --- care/facility/api/viewsets/facility_users.py | 20 ++++++++++++++------ care/users/api/serializers/user.py | 6 +----- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/care/facility/api/viewsets/facility_users.py b/care/facility/api/viewsets/facility_users.py index fc8c4ecb86..2fc1e751a5 100644 --- a/care/facility/api/viewsets/facility_users.py +++ b/care/facility/api/viewsets/facility_users.py @@ -1,3 +1,5 @@ +from django.core.exceptions import ObjectDoesNotExist +from django.db.models import Prefetch from django_filters import rest_framework as filters from rest_framework import mixins from rest_framework.exceptions import ValidationError @@ -6,12 +8,14 @@ from care.facility.models.facility import Facility from care.users.api.serializers.user import UserAssignedSerializer -from care.users.models import User +from care.users.models import Skill, User class UserFilter(filters.FilterSet): - user_type = filters.TypedChoiceFilter(choices=[(key, key) for key in User.TYPE_VALUE_MAP.keys()], - coerce=lambda role: User.TYPE_VALUE_MAP[role]) + user_type = filters.TypedChoiceFilter( + choices=[(key, key) for key in User.TYPE_VALUE_MAP.keys()], + coerce=lambda role: User.TYPE_VALUE_MAP[role], + ) class Meta: model = User @@ -21,13 +25,17 @@ class Meta: class FacilityUserViewSet(GenericViewSet, mixins.ListModelMixin): serializer_class = UserAssignedSerializer filterset_class = UserFilter - queryset = User.objects.all() + queryset = User.objects.all().prefetch_related( + Prefetch("skills", queryset=Skill.objects.filter(userskill__deleted=False)) + ) permission_classes = [IsAuthenticated] filter_backends = [filters.DjangoFilterBackend] def get_queryset(self): try: - facility = Facility.objects.get(external_id=self.kwargs.get("facility_external_id")) + facility = Facility.objects.get( + external_id=self.kwargs.get("facility_external_id") + ) return facility.users.filter(deleted=False).order_by("-last_login") - except: + except ObjectDoesNotExist: raise ValidationError({"Facility": "Facility not found"}) diff --git a/care/users/api/serializers/user.py b/care/users/api/serializers/user.py index e3b0edc0db..f3d418af3d 100644 --- a/care/users/api/serializers/user.py +++ b/care/users/api/serializers/user.py @@ -358,11 +358,7 @@ class UserAssignedSerializer(serializers.ModelSerializer): home_facility_object = FacilityBareMinimumSerializer( source="home_facility", read_only=True ) - skills = serializers.SerializerMethodField() - - def get_skills(self, obj): - qs = obj.skills.filter(userskill__deleted=False) - return SkillSerializer(qs, many=True).data + skills = SkillSerializer(many=True, read_only=True) class Meta: model = User From a75b98ddfa2a472f59a4a4d7091016489ce0570f Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Sat, 27 May 2023 16:27:29 +0530 Subject: [PATCH 06/11] Revert "used prefetch where we are querying the skills using UserAssigned Serializer" This reverts commit 7000a38bafd16e789ccf6ffc5f9a1f41d0c34429. --- care/facility/api/viewsets/facility_users.py | 20 ++++++-------------- care/users/api/serializers/user.py | 6 +++++- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/care/facility/api/viewsets/facility_users.py b/care/facility/api/viewsets/facility_users.py index 2fc1e751a5..fc8c4ecb86 100644 --- a/care/facility/api/viewsets/facility_users.py +++ b/care/facility/api/viewsets/facility_users.py @@ -1,5 +1,3 @@ -from django.core.exceptions import ObjectDoesNotExist -from django.db.models import Prefetch from django_filters import rest_framework as filters from rest_framework import mixins from rest_framework.exceptions import ValidationError @@ -8,14 +6,12 @@ from care.facility.models.facility import Facility from care.users.api.serializers.user import UserAssignedSerializer -from care.users.models import Skill, User +from care.users.models import User class UserFilter(filters.FilterSet): - user_type = filters.TypedChoiceFilter( - choices=[(key, key) for key in User.TYPE_VALUE_MAP.keys()], - coerce=lambda role: User.TYPE_VALUE_MAP[role], - ) + user_type = filters.TypedChoiceFilter(choices=[(key, key) for key in User.TYPE_VALUE_MAP.keys()], + coerce=lambda role: User.TYPE_VALUE_MAP[role]) class Meta: model = User @@ -25,17 +21,13 @@ class Meta: class FacilityUserViewSet(GenericViewSet, mixins.ListModelMixin): serializer_class = UserAssignedSerializer filterset_class = UserFilter - queryset = User.objects.all().prefetch_related( - Prefetch("skills", queryset=Skill.objects.filter(userskill__deleted=False)) - ) + queryset = User.objects.all() permission_classes = [IsAuthenticated] filter_backends = [filters.DjangoFilterBackend] def get_queryset(self): try: - facility = Facility.objects.get( - external_id=self.kwargs.get("facility_external_id") - ) + facility = Facility.objects.get(external_id=self.kwargs.get("facility_external_id")) return facility.users.filter(deleted=False).order_by("-last_login") - except ObjectDoesNotExist: + except: raise ValidationError({"Facility": "Facility not found"}) diff --git a/care/users/api/serializers/user.py b/care/users/api/serializers/user.py index f3d418af3d..e3b0edc0db 100644 --- a/care/users/api/serializers/user.py +++ b/care/users/api/serializers/user.py @@ -358,7 +358,11 @@ class UserAssignedSerializer(serializers.ModelSerializer): home_facility_object = FacilityBareMinimumSerializer( source="home_facility", read_only=True ) - skills = SkillSerializer(many=True, read_only=True) + skills = serializers.SerializerMethodField() + + def get_skills(self, obj): + qs = obj.skills.filter(userskill__deleted=False) + return SkillSerializer(qs, many=True).data class Meta: model = User From f59ff6b993d51a4e3748193ba5fd2efa064a206c Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Sat, 27 May 2023 19:06:28 +0530 Subject: [PATCH 07/11] made neccessary changes for prefetching the skills --- care/facility/api/viewsets/facility_users.py | 17 +++++++++----- .../api/viewsets/patient_consultation.py | 11 +++++++++- care/users/api/serializers/user.py | 22 ++++++++++++++----- 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/care/facility/api/viewsets/facility_users.py b/care/facility/api/viewsets/facility_users.py index fc8c4ecb86..9781219981 100644 --- a/care/facility/api/viewsets/facility_users.py +++ b/care/facility/api/viewsets/facility_users.py @@ -1,3 +1,4 @@ +from django.core.exceptions import ObjectDoesNotExist from django_filters import rest_framework as filters from rest_framework import mixins from rest_framework.exceptions import ValidationError @@ -10,8 +11,10 @@ class UserFilter(filters.FilterSet): - user_type = filters.TypedChoiceFilter(choices=[(key, key) for key in User.TYPE_VALUE_MAP.keys()], - coerce=lambda role: User.TYPE_VALUE_MAP[role]) + user_type = filters.TypedChoiceFilter( + choices=[(key, key) for key in User.TYPE_VALUE_MAP.keys()], + coerce=lambda role: User.TYPE_VALUE_MAP[role], + ) class Meta: model = User @@ -27,7 +30,11 @@ class FacilityUserViewSet(GenericViewSet, mixins.ListModelMixin): def get_queryset(self): try: - facility = Facility.objects.get(external_id=self.kwargs.get("facility_external_id")) - return facility.users.filter(deleted=False).order_by("-last_login") - except: + facility = Facility.objects.get( + external_id=self.kwargs.get("facility_external_id") + ) + queryset = facility.users.filter(deleted=False).order_by("-last_login") + queryset = self.get_serializer_class().skills_eager_loading(queryset) + return queryset + except ObjectDoesNotExist: raise ValidationError({"Facility": "Facility not found"}) diff --git a/care/facility/api/viewsets/patient_consultation.py b/care/facility/api/viewsets/patient_consultation.py index 19a7cc70e9..dead0b0f74 100644 --- a/care/facility/api/viewsets/patient_consultation.py +++ b/care/facility/api/viewsets/patient_consultation.py @@ -1,4 +1,5 @@ from django.core.validators import validate_email +from django.db.models import Prefetch from django.db.models.query_utils import Q from django_filters import rest_framework as filters from drf_yasg import openapi @@ -25,7 +26,7 @@ email_discharge_summary, generate_and_upload_discharge_summary_task, ) -from care.users.models import User +from care.users.models import Skill, User from care.utils.cache.cache_allowed_facilities import get_accessible_facilities @@ -68,6 +69,14 @@ def get_permissions(self): return super().get_permissions() def get_queryset(self): + if self.serializer_class == PatientConsultationSerializer: + self.queryset = self.queryset.prefetch_related( + "assigned_to", + Prefetch( + "assigned_to__skills", + queryset=Skill.objects.filter(userskill__deleted=False), + ), + ) if self.request.user.is_superuser: return self.queryset elif self.request.user.user_type >= User.TYPE_VALUE_MAP["StateLabAdmin"]: diff --git a/care/users/api/serializers/user.py b/care/users/api/serializers/user.py index e3b0edc0db..532e4d698c 100644 --- a/care/users/api/serializers/user.py +++ b/care/users/api/serializers/user.py @@ -3,6 +3,7 @@ from django.contrib.auth import get_user_model from django.contrib.auth.hashers import make_password from django.db import transaction +from django.db.models import Prefetch from rest_framework import exceptions, serializers from care.facility.api.serializers.facility import FacilityBareMinimumSerializer @@ -13,7 +14,7 @@ StateSerializer, ) from care.users.api.serializers.skill import SkillSerializer -from care.users.models import GENDER_CHOICES +from care.users.models import GENDER_CHOICES, Skill from care.utils.queryset.facility import get_home_facility_queryset from care.utils.serializer.external_id_field import ExternalIdSerializerField from care.utils.serializer.phonenumber_ispossible_field import ( @@ -358,11 +359,20 @@ class UserAssignedSerializer(serializers.ModelSerializer): home_facility_object = FacilityBareMinimumSerializer( source="home_facility", read_only=True ) - skills = serializers.SerializerMethodField() - - def get_skills(self, obj): - qs = obj.skills.filter(userskill__deleted=False) - return SkillSerializer(qs, many=True).data + # skills = serializers.SerializerMethodField() + skills = SkillSerializer(many=True, read_only=True) + + # def get_skills(self, obj): + # qs = obj.skills.filter(userskill__deleted=False) + # return SkillSerializer(qs, many=True).data + + @staticmethod + def skills_eager_loading(queryset): + """Perform necessary eager loading of data.""" + queryset = queryset.prefetch_related( + Prefetch("skills", queryset=Skill.objects.filter(userskill__deleted=False)) + ) + return queryset class Meta: model = User From e6541ef4f8e470d8fc140a49184e0b3ce96ddbd3 Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Tue, 30 May 2023 17:15:24 +0530 Subject: [PATCH 08/11] Revert "made neccessary changes for prefetching the skills" This reverts commit f59ff6b993d51a4e3748193ba5fd2efa064a206c. --- care/facility/api/viewsets/facility_users.py | 17 +++++--------- .../api/viewsets/patient_consultation.py | 11 +--------- care/users/api/serializers/user.py | 22 +++++-------------- 3 files changed, 12 insertions(+), 38 deletions(-) diff --git a/care/facility/api/viewsets/facility_users.py b/care/facility/api/viewsets/facility_users.py index 9781219981..fc8c4ecb86 100644 --- a/care/facility/api/viewsets/facility_users.py +++ b/care/facility/api/viewsets/facility_users.py @@ -1,4 +1,3 @@ -from django.core.exceptions import ObjectDoesNotExist from django_filters import rest_framework as filters from rest_framework import mixins from rest_framework.exceptions import ValidationError @@ -11,10 +10,8 @@ class UserFilter(filters.FilterSet): - user_type = filters.TypedChoiceFilter( - choices=[(key, key) for key in User.TYPE_VALUE_MAP.keys()], - coerce=lambda role: User.TYPE_VALUE_MAP[role], - ) + user_type = filters.TypedChoiceFilter(choices=[(key, key) for key in User.TYPE_VALUE_MAP.keys()], + coerce=lambda role: User.TYPE_VALUE_MAP[role]) class Meta: model = User @@ -30,11 +27,7 @@ class FacilityUserViewSet(GenericViewSet, mixins.ListModelMixin): def get_queryset(self): try: - facility = Facility.objects.get( - external_id=self.kwargs.get("facility_external_id") - ) - queryset = facility.users.filter(deleted=False).order_by("-last_login") - queryset = self.get_serializer_class().skills_eager_loading(queryset) - return queryset - except ObjectDoesNotExist: + facility = Facility.objects.get(external_id=self.kwargs.get("facility_external_id")) + return facility.users.filter(deleted=False).order_by("-last_login") + except: raise ValidationError({"Facility": "Facility not found"}) diff --git a/care/facility/api/viewsets/patient_consultation.py b/care/facility/api/viewsets/patient_consultation.py index dead0b0f74..19a7cc70e9 100644 --- a/care/facility/api/viewsets/patient_consultation.py +++ b/care/facility/api/viewsets/patient_consultation.py @@ -1,5 +1,4 @@ from django.core.validators import validate_email -from django.db.models import Prefetch from django.db.models.query_utils import Q from django_filters import rest_framework as filters from drf_yasg import openapi @@ -26,7 +25,7 @@ email_discharge_summary, generate_and_upload_discharge_summary_task, ) -from care.users.models import Skill, User +from care.users.models import User from care.utils.cache.cache_allowed_facilities import get_accessible_facilities @@ -69,14 +68,6 @@ def get_permissions(self): return super().get_permissions() def get_queryset(self): - if self.serializer_class == PatientConsultationSerializer: - self.queryset = self.queryset.prefetch_related( - "assigned_to", - Prefetch( - "assigned_to__skills", - queryset=Skill.objects.filter(userskill__deleted=False), - ), - ) if self.request.user.is_superuser: return self.queryset elif self.request.user.user_type >= User.TYPE_VALUE_MAP["StateLabAdmin"]: diff --git a/care/users/api/serializers/user.py b/care/users/api/serializers/user.py index 532e4d698c..e3b0edc0db 100644 --- a/care/users/api/serializers/user.py +++ b/care/users/api/serializers/user.py @@ -3,7 +3,6 @@ from django.contrib.auth import get_user_model from django.contrib.auth.hashers import make_password from django.db import transaction -from django.db.models import Prefetch from rest_framework import exceptions, serializers from care.facility.api.serializers.facility import FacilityBareMinimumSerializer @@ -14,7 +13,7 @@ StateSerializer, ) from care.users.api.serializers.skill import SkillSerializer -from care.users.models import GENDER_CHOICES, Skill +from care.users.models import GENDER_CHOICES from care.utils.queryset.facility import get_home_facility_queryset from care.utils.serializer.external_id_field import ExternalIdSerializerField from care.utils.serializer.phonenumber_ispossible_field import ( @@ -359,20 +358,11 @@ class UserAssignedSerializer(serializers.ModelSerializer): home_facility_object = FacilityBareMinimumSerializer( source="home_facility", read_only=True ) - # skills = serializers.SerializerMethodField() - skills = SkillSerializer(many=True, read_only=True) - - # def get_skills(self, obj): - # qs = obj.skills.filter(userskill__deleted=False) - # return SkillSerializer(qs, many=True).data - - @staticmethod - def skills_eager_loading(queryset): - """Perform necessary eager loading of data.""" - queryset = queryset.prefetch_related( - Prefetch("skills", queryset=Skill.objects.filter(userskill__deleted=False)) - ) - return queryset + skills = serializers.SerializerMethodField() + + def get_skills(self, obj): + qs = obj.skills.filter(userskill__deleted=False) + return SkillSerializer(qs, many=True).data class Meta: model = User From c82bc1c9a779fcb54dd6b03e112a5f25244ae7d7 Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Sat, 3 Jun 2023 04:24:10 +0530 Subject: [PATCH 09/11] Manually cascade delete M2M models when related model is deleted --- care/facility/models/asset.py | 6 ++ care/facility/models/bed.py | 5 ++ care/facility/models/facility.py | 17 +++++- care/facility/models/patient.py | 6 ++ care/facility/models/patient_consultation.py | 10 ++++ care/facility/models/patient_investigation.py | 56 +++++++++++++++---- care/users/models.py | 7 +++ 7 files changed, 95 insertions(+), 12 deletions(-) diff --git a/care/facility/models/asset.py b/care/facility/models/asset.py index 7923cc055d..c249ee8a10 100644 --- a/care/facility/models/asset.py +++ b/care/facility/models/asset.py @@ -39,6 +39,12 @@ class RoomType(enum.Enum): Facility, on_delete=models.PROTECT, null=False, blank=False ) + def delete(self, *args, **kwargs): + UserDefaultAssetLocation.objects.filter(location=self).delete() + FacilityDefaultAssetLocation.objects.filter(location=self).delete() + + super().delete(*args, **kwargs) + class Asset(BaseModel): class AssetType(enum.Enum): diff --git a/care/facility/models/bed.py b/care/facility/models/bed.py index 0d8b2e536e..01d52ac17b 100644 --- a/care/facility/models/bed.py +++ b/care/facility/models/bed.py @@ -51,6 +51,11 @@ def save(self, *args, **kwargs) -> None: self.validate() return super().save(*args, **kwargs) + def delete(self, *args, **kwargs): + ConsultationBed.objects.filter(bed=self).delete() + + super().delete(*args, **kwargs) + class AssetBed(BaseModel): asset = models.ForeignKey(Asset, on_delete=models.PROTECT, null=False, blank=False) diff --git a/care/facility/models/facility.py b/care/facility/models/facility.py index 476612f9d1..2d7cb5b417 100644 --- a/care/facility/models/facility.py +++ b/care/facility/models/facility.py @@ -6,7 +6,13 @@ from partial_index import PQ, PartialIndex from simple_history.models import HistoricalRecords -from care.facility.models import FacilityBaseModel, phone_number_regex, reverse_choices +from care.facility.models import ( + FacilityBaseModel, + FacilityDefaultAssetLocation, + PatientSample, + phone_number_regex, + reverse_choices, +) from care.facility.models.mixins.permissions.facility import ( FacilityPermissionMixin, FacilityRelatedPermissionMixin, @@ -193,6 +199,15 @@ def save(self, *args, **kwargs) -> None: facility=self, user=self.created_by, created_by=self.created_by ) + def delete(self, *args, **kwargs): + FacilityDefaultAssetLocation.objects.filter(facility=self).delete() + FacilityUser.objects.filter(facility=self).delete() + PatientSample.objects.filter(testing_facility=self).update( + testing_facility=None + ) + + super().delete(*args, **kwargs) + CSV_MAPPING = { "name": "Facility Name", "facility_type": "Facility Type", diff --git a/care/facility/models/patient.py b/care/facility/models/patient.py index 729bd4f8f5..d9a20b8354 100644 --- a/care/facility/models/patient.py +++ b/care/facility/models/patient.py @@ -15,6 +15,7 @@ FacilityBaseModel, LocalBody, PatientBaseModel, + PatientSample, State, Ward, ) @@ -510,6 +511,11 @@ def save(self, *args, **kwargs) -> None: is_active=self.is_active, ) + def delete(self, *args, **kwargs): + PatientSample.objects.filter(patient=self).delete() + + super().delete(*args, **kwargs) + CSV_MAPPING = { # Patient Details "external_id": "Patient ID", diff --git a/care/facility/models/patient_consultation.py b/care/facility/models/patient_consultation.py index aedbe58a65..d97ec55f87 100644 --- a/care/facility/models/patient_consultation.py +++ b/care/facility/models/patient_consultation.py @@ -6,7 +6,10 @@ from care.facility.models import ( CATEGORY_CHOICES, COVID_CATEGORY_CHOICES, + ConsultationBed, + InvestigationValue, PatientBaseModel, + PatientSample, ) from care.facility.models.mixins.permissions.patient import ( PatientRelatedPermissionMixin, @@ -232,6 +235,13 @@ def save(self, *args, **kwargs): """ super(PatientConsultation, self).save(*args, **kwargs) + def delete(self, *args, **kwargs): + ConsultationBed.objects.filter(consultation=self).delete() + InvestigationValue.objects.filter(consultation=self).delete() + PatientSample.objects.filter(consultation=self).delete() + + super().delete(*args, **kwargs) + class Meta: constraints = [ models.CheckConstraint( diff --git a/care/facility/models/patient_investigation.py b/care/facility/models/patient_investigation.py index ea842bc7b8..9321ed2f1d 100644 --- a/care/facility/models/patient_investigation.py +++ b/care/facility/models/patient_investigation.py @@ -1,9 +1,10 @@ +from uuid import uuid4 + from django.db import models -from care.utils.models.base import BaseModel + from care.facility.models.patient_consultation import PatientConsultation -from uuid import uuid4 from care.users.models import User - +from care.utils.models.base import BaseModel TestTypeChoices = [("Float", "Float"), ("String", "String"), ("Choice", "Choice")] @@ -14,6 +15,11 @@ class PatientInvestigationGroup(BaseModel): def __str__(self) -> str: return self.name + def delete(self, *args, **kwargs): + InvestigationValue.objects.filter(group=self).delete() + + super().delete(*args, **kwargs) + class PatientInvestigation(BaseModel): name = models.CharField(max_length=500, blank=False, null=False) @@ -22,27 +28,55 @@ class PatientInvestigation(BaseModel): ideal_value = models.TextField(blank=True, null=True) min_value = models.FloatField(blank=True, default=None, null=True) max_value = models.FloatField(blank=True, default=None, null=True) - investigation_type = models.CharField(max_length=10, choices=TestTypeChoices, blank=False, null=True, default=None) + investigation_type = models.CharField( + max_length=10, choices=TestTypeChoices, blank=False, null=True, default=None + ) choices = models.TextField(null=True, blank=True) def __str__(self) -> str: return self.name + " in " + self.unit + " as " + self.investigation_type + def delete(self, *args, **kwargs): + InvestigationValue.objects.filter(investigation=self).delete() + + super().delete(*args, **kwargs) + class InvestigationSession(BaseModel): - external_id = models.UUIDField(default=uuid4, unique=True, db_index=True) # session_id - created_by = models.ForeignKey(User, null=False, blank=False, on_delete=models.PROTECT) + external_id = models.UUIDField( + default=uuid4, unique=True, db_index=True + ) # session_id + created_by = models.ForeignKey( + User, null=False, blank=False, on_delete=models.PROTECT + ) class Meta: indexes = [ - models.Index(fields=["-created_date",]), + models.Index( + fields=[ + "-created_date", + ] + ), ] + def delete(self, *args, **kwargs): + InvestigationValue.objects.filter(session=self).delete() + + super().delete(*args, **kwargs) + class InvestigationValue(BaseModel): - investigation = models.ForeignKey(PatientInvestigation, on_delete=models.PROTECT, blank=False, null=False) - group = models.ForeignKey(PatientInvestigationGroup, on_delete=models.PROTECT, blank=True, null=True) + investigation = models.ForeignKey( + PatientInvestigation, on_delete=models.PROTECT, blank=False, null=False + ) + group = models.ForeignKey( + PatientInvestigationGroup, on_delete=models.PROTECT, blank=True, null=True + ) value = models.FloatField(blank=True, null=True, default=None) notes = models.TextField(blank=True, null=True, default=None) - consultation = models.ForeignKey(PatientConsultation, on_delete=models.PROTECT, blank=False, null=False) - session = models.ForeignKey(InvestigationSession, on_delete=models.PROTECT, blank=False, null=False) + consultation = models.ForeignKey( + PatientConsultation, on_delete=models.PROTECT, blank=False, null=False + ) + session = models.ForeignKey( + InvestigationSession, on_delete=models.PROTECT, blank=False, null=False + ) diff --git a/care/users/models.py b/care/users/models.py index a9401ede93..4b456c5efe 100644 --- a/care/users/models.py +++ b/care/users/models.py @@ -6,6 +6,7 @@ from django.utils.translation import ugettext_lazy as _ from partial_index import PQ, PartialIndex +from care.facility.models import FacilityUser, PatientSample, UserDefaultAssetLocation from care.utils.models.base import BaseModel @@ -345,6 +346,12 @@ def delete(self, *args, **kwargs): self.deleted = True self.save() + UserDefaultAssetLocation.objects.filter(user=self).delete() + FacilityUser.objects.filter(user=self).delete() + FacilityUser.objects.filter(created_by=self).delete() + PatientSample.objects.filter(created_by=self).update(created_by=None) + PatientSample.objects.filter(last_edited_by=self).update(last_edited_by=None) + def get_absolute_url(self): return reverse("users:detail", kwargs={"username": self.username}) From 615fa24bd90230b8a4873a66a86596b574309002 Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Sat, 3 Jun 2023 15:18:25 +0530 Subject: [PATCH 10/11] changes it to soft delete from hard delete - fix --- care/facility/models/asset.py | 4 ++-- care/facility/models/bed.py | 2 +- care/facility/models/facility.py | 4 ++-- care/facility/models/patient.py | 2 +- care/facility/models/patient_consultation.py | 6 +++--- care/facility/models/patient_investigation.py | 6 +++--- care/users/models.py | 6 +++--- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/care/facility/models/asset.py b/care/facility/models/asset.py index c249ee8a10..8aa374871a 100644 --- a/care/facility/models/asset.py +++ b/care/facility/models/asset.py @@ -40,8 +40,8 @@ class RoomType(enum.Enum): ) def delete(self, *args, **kwargs): - UserDefaultAssetLocation.objects.filter(location=self).delete() - FacilityDefaultAssetLocation.objects.filter(location=self).delete() + UserDefaultAssetLocation.objects.filter(location=self).update(deleted=True) + FacilityDefaultAssetLocation.objects.filter(location=self).update(deleted=True) super().delete(*args, **kwargs) diff --git a/care/facility/models/bed.py b/care/facility/models/bed.py index 01d52ac17b..fe34c181aa 100644 --- a/care/facility/models/bed.py +++ b/care/facility/models/bed.py @@ -52,7 +52,7 @@ def save(self, *args, **kwargs) -> None: return super().save(*args, **kwargs) def delete(self, *args, **kwargs): - ConsultationBed.objects.filter(bed=self).delete() + ConsultationBed.objects.filter(bed=self).update(deleted=True) super().delete(*args, **kwargs) diff --git a/care/facility/models/facility.py b/care/facility/models/facility.py index 2d7cb5b417..8bfffb73c2 100644 --- a/care/facility/models/facility.py +++ b/care/facility/models/facility.py @@ -200,8 +200,8 @@ def save(self, *args, **kwargs) -> None: ) def delete(self, *args, **kwargs): - FacilityDefaultAssetLocation.objects.filter(facility=self).delete() - FacilityUser.objects.filter(facility=self).delete() + FacilityDefaultAssetLocation.objects.filter(facility=self).update(deleted=True) + FacilityUser.objects.filter(facility=self).update(deleted=True) PatientSample.objects.filter(testing_facility=self).update( testing_facility=None ) diff --git a/care/facility/models/patient.py b/care/facility/models/patient.py index d9a20b8354..5e8907cd12 100644 --- a/care/facility/models/patient.py +++ b/care/facility/models/patient.py @@ -512,7 +512,7 @@ def save(self, *args, **kwargs) -> None: ) def delete(self, *args, **kwargs): - PatientSample.objects.filter(patient=self).delete() + PatientSample.objects.filter(patient=self).update(deleted=True) super().delete(*args, **kwargs) diff --git a/care/facility/models/patient_consultation.py b/care/facility/models/patient_consultation.py index d97ec55f87..8566e9f859 100644 --- a/care/facility/models/patient_consultation.py +++ b/care/facility/models/patient_consultation.py @@ -236,9 +236,9 @@ def save(self, *args, **kwargs): super(PatientConsultation, self).save(*args, **kwargs) def delete(self, *args, **kwargs): - ConsultationBed.objects.filter(consultation=self).delete() - InvestigationValue.objects.filter(consultation=self).delete() - PatientSample.objects.filter(consultation=self).delete() + ConsultationBed.objects.filter(consultation=self).update(deleted=True) + InvestigationValue.objects.filter(consultation=self).update(deleted=True) + PatientSample.objects.filter(consultation=self).update(deleted=True) super().delete(*args, **kwargs) diff --git a/care/facility/models/patient_investigation.py b/care/facility/models/patient_investigation.py index 9321ed2f1d..897f331ce3 100644 --- a/care/facility/models/patient_investigation.py +++ b/care/facility/models/patient_investigation.py @@ -16,7 +16,7 @@ def __str__(self) -> str: return self.name def delete(self, *args, **kwargs): - InvestigationValue.objects.filter(group=self).delete() + InvestigationValue.objects.filter(group=self).update(deleted=True) super().delete(*args, **kwargs) @@ -37,7 +37,7 @@ def __str__(self) -> str: return self.name + " in " + self.unit + " as " + self.investigation_type def delete(self, *args, **kwargs): - InvestigationValue.objects.filter(investigation=self).delete() + InvestigationValue.objects.filter(investigation=self).update(deleted=True) super().delete(*args, **kwargs) @@ -60,7 +60,7 @@ class Meta: ] def delete(self, *args, **kwargs): - InvestigationValue.objects.filter(session=self).delete() + InvestigationValue.objects.filter(session=self).update(deleted=True) super().delete(*args, **kwargs) diff --git a/care/users/models.py b/care/users/models.py index 4b456c5efe..3845d4f5f2 100644 --- a/care/users/models.py +++ b/care/users/models.py @@ -346,9 +346,9 @@ def delete(self, *args, **kwargs): self.deleted = True self.save() - UserDefaultAssetLocation.objects.filter(user=self).delete() - FacilityUser.objects.filter(user=self).delete() - FacilityUser.objects.filter(created_by=self).delete() + UserDefaultAssetLocation.objects.filter(user=self).update(deleted=True) + FacilityUser.objects.filter(user=self).update(deleted=True) + FacilityUser.objects.filter(created_by=self).update(deleted=True) PatientSample.objects.filter(created_by=self).update(created_by=None) PatientSample.objects.filter(last_edited_by=self).update(last_edited_by=None) From c7ea42ff87696c6ec12b75d3689d46c274b1df7d Mon Sep 17 00:00:00 2001 From: yaswanthsaivendra Date: Thu, 8 Jun 2023 01:50:29 +0530 Subject: [PATCH 11/11] fixed circular import --- care/facility/models/facility.py | 10 +++------- care/facility/models/patient.py | 3 ++- care/facility/models/patient_consultation.py | 9 ++++++--- care/users/models.py | 7 ++++++- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/care/facility/models/facility.py b/care/facility/models/facility.py index 8bfffb73c2..11b1f61735 100644 --- a/care/facility/models/facility.py +++ b/care/facility/models/facility.py @@ -6,13 +6,7 @@ from partial_index import PQ, PartialIndex from simple_history.models import HistoricalRecords -from care.facility.models import ( - FacilityBaseModel, - FacilityDefaultAssetLocation, - PatientSample, - phone_number_regex, - reverse_choices, -) +from care.facility.models import FacilityBaseModel, phone_number_regex, reverse_choices from care.facility.models.mixins.permissions.facility import ( FacilityPermissionMixin, FacilityRelatedPermissionMixin, @@ -200,6 +194,8 @@ def save(self, *args, **kwargs) -> None: ) def delete(self, *args, **kwargs): + from care.facility.models import FacilityDefaultAssetLocation, PatientSample + FacilityDefaultAssetLocation.objects.filter(facility=self).update(deleted=True) FacilityUser.objects.filter(facility=self).update(deleted=True) PatientSample.objects.filter(testing_facility=self).update( diff --git a/care/facility/models/patient.py b/care/facility/models/patient.py index 5e8907cd12..2dbdf6d3c6 100644 --- a/care/facility/models/patient.py +++ b/care/facility/models/patient.py @@ -15,7 +15,6 @@ FacilityBaseModel, LocalBody, PatientBaseModel, - PatientSample, State, Ward, ) @@ -512,6 +511,8 @@ def save(self, *args, **kwargs) -> None: ) def delete(self, *args, **kwargs): + from care.facility.models import PatientSample + PatientSample.objects.filter(patient=self).update(deleted=True) super().delete(*args, **kwargs) diff --git a/care/facility/models/patient_consultation.py b/care/facility/models/patient_consultation.py index 8566e9f859..1557257d85 100644 --- a/care/facility/models/patient_consultation.py +++ b/care/facility/models/patient_consultation.py @@ -6,10 +6,7 @@ from care.facility.models import ( CATEGORY_CHOICES, COVID_CATEGORY_CHOICES, - ConsultationBed, - InvestigationValue, PatientBaseModel, - PatientSample, ) from care.facility.models.mixins.permissions.patient import ( PatientRelatedPermissionMixin, @@ -236,6 +233,12 @@ def save(self, *args, **kwargs): super(PatientConsultation, self).save(*args, **kwargs) def delete(self, *args, **kwargs): + from care.facility.models import ( + ConsultationBed, + InvestigationValue, + PatientSample, + ) + ConsultationBed.objects.filter(consultation=self).update(deleted=True) InvestigationValue.objects.filter(consultation=self).update(deleted=True) PatientSample.objects.filter(consultation=self).update(deleted=True) diff --git a/care/users/models.py b/care/users/models.py index 3845d4f5f2..45e9b8aa2d 100644 --- a/care/users/models.py +++ b/care/users/models.py @@ -6,7 +6,6 @@ from django.utils.translation import ugettext_lazy as _ from partial_index import PQ, PartialIndex -from care.facility.models import FacilityUser, PatientSample, UserDefaultAssetLocation from care.utils.models.base import BaseModel @@ -343,6 +342,12 @@ def check_username_exists(username): return User.objects.get_entire_queryset().filter(username=username).exists() def delete(self, *args, **kwargs): + from care.facility.models.facility import ( + FacilityUser, + PatientSample, + UserDefaultAssetLocation, + ) + self.deleted = True self.save()