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

Adds Nurse user type and promote existing staffs to nurse #1589

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 7 additions & 1 deletion care/facility/api/serializers/patient_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
PatientSampleFlow,
)
from care.users.api.serializers.user import UserBaseMinimumSerializer
from care.users.models import User
from care.utils.serializer.external_id_field import ExternalIdSerializerField
from config.serializers import ChoiceField

Expand Down Expand Up @@ -103,7 +104,12 @@
notes = serializers.CharField(required=False)

def update(self, instance, validated_data):
instance.last_edited_by = self.context["request"].user
user = self.context["request"].user

Check warning on line 107 in care/facility/api/serializers/patient_sample.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/serializers/patient_sample.py#L107

Added line #L107 was not covered by tests
if user.user_type < User.TYPE_VALUE_MAP["Doctor"]:
raise ValidationError(

Check warning on line 109 in care/facility/api/serializers/patient_sample.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/serializers/patient_sample.py#L109

Added line #L109 was not covered by tests
{"status": ["User is not allowed to update sample details"]}
)
instance.last_edited_by = user

Check warning on line 112 in care/facility/api/serializers/patient_sample.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/serializers/patient_sample.py#L112

Added line #L112 was not covered by tests
try:
is_completed = validated_data.get("result") in [1, 2]
new_status = validated_data.get(
Expand Down
4 changes: 3 additions & 1 deletion care/facility/api/viewsets/bed.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from django.db.models import OuterRef, Subquery
from django_filters import rest_framework as filters
from drf_spectacular.utils import extend_schema, extend_schema_view
from dry_rest_permissions.generics import DRYPermissions
from rest_framework import filters as drf_filters
from rest_framework import status
from rest_framework.exceptions import PermissionDenied
Expand Down Expand Up @@ -55,7 +56,7 @@ class BedViewSet(
serializer_class = BedSerializer
lookup_field = "external_id"
filter_backends = (filters.DjangoFilterBackend, drf_filters.SearchFilter)
permission_classes = [IsAuthenticated]
permission_classes = (IsAuthenticated,)
search_fields = ["name"]
filterset_class = BedFilter

Expand Down Expand Up @@ -215,6 +216,7 @@ class ConsultationBedViewSet(
.order_by("-created_date")
)
serializer_class = ConsultationBedSerializer
permission_classes = (DRYPermissions,)
filter_backends = (filters.DjangoFilterBackend,)
filterset_class = ConsultationBedFilter
lookup_field = "external_id"
Expand Down
14 changes: 9 additions & 5 deletions care/facility/api/viewsets/file_upload.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django_filters import rest_framework as filters
from dry_rest_permissions.generics import DRYPermissions
from rest_framework.exceptions import ValidationError
from rest_framework.mixins import (
CreateModelMixin,
Expand Down Expand Up @@ -36,20 +37,23 @@
queryset = (
FileUpload.objects.all().select_related("uploaded_by").order_by("-created_date")
)
permission_classes = [IsAuthenticated]
permission_classes = (
IsAuthenticated,
DRYPermissions,
)
lookup_field = "external_id"
filter_backends = (filters.DjangoFilterBackend,)
filterset_class = FileUploadFilter
serializer_class = FileUploadUpdateSerializer

def get_serializer_class(self):
if self.action == "retrieve":
return FileUploadRetrieveSerializer
elif self.action == "list":
if self.action == "list":
return FileUploadListSerializer
elif self.action == "create":
if self.action == "create":
return FileUploadCreateSerializer
else:
return FileUploadUpdateSerializer
return super().get_serializer_class()

Check warning on line 56 in care/facility/api/viewsets/file_upload.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/viewsets/file_upload.py#L56

Added line #L56 was not covered by tests

def get_queryset(self):
if "file_type" not in self.request.GET:
Expand Down
5 changes: 5 additions & 0 deletions care/facility/api/viewsets/notification.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

from care.facility.api.serializers.notification import NotificationSerializer
from care.facility.models.notification import Notification
from care.users.models import User
from care.utils.filters.choicefilter import CareChoiceFilter, inverse_choices
from care.utils.notification_handler import NotificationGenerator
from care.utils.queryset.facility import get_facility_queryset
Expand Down Expand Up @@ -71,6 +72,10 @@
raise ValidationError({"facility": "is required"})
if "message" not in request.data or request.data["message"] == "":
raise ValidationError({"message": "is required"})
if user.user_type < User.TYPE_VALUE_MAP["Doctor"] and request.data["facility"]:
raise ValidationError(

Check warning on line 76 in care/facility/api/viewsets/notification.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/viewsets/notification.py#L76

Added line #L76 was not covered by tests
{"user": "You are not allowed to notify other hospitals"}
)
facilities = get_facility_queryset(user)
facility = get_object_or_404(
facilities.filter(external_id=request.data["facility"])
Expand Down
6 changes: 5 additions & 1 deletion care/facility/api/viewsets/patient_external_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from django_filters.filters import DateFromToRangeFilter
from djqscsv import render_to_csv_response
from drf_spectacular.utils import extend_schema
from dry_rest_permissions.generics import DRYPermissions
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.exceptions import PermissionDenied, ValidationError
Expand Down Expand Up @@ -77,7 +78,10 @@ class PatientExternalTestViewSet(
.all()
.order_by("-id")
)
permission_classes = (IsAuthenticated,)
permission_classes = (
IsAuthenticated,
DRYPermissions,
)
filter_backends = (filters.DjangoFilterBackend,)
filterset_class = PatientExternalTestFilter
parser_classes = (MultiPartParser, FormParser, JSONParser)
Expand Down
23 changes: 15 additions & 8 deletions care/facility/api/viewsets/patient_investigation.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from django_filters import Filter
from django_filters import rest_framework as filters
from drf_spectacular.utils import extend_schema
from dry_rest_permissions.generics import DRYPermissions
from rest_framework import mixins, status, viewsets
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
Expand Down Expand Up @@ -82,7 +83,7 @@ class PatientInvestigationViewSet(
pagination_class = InvestigationResultsSetPagination


class PatientInvestigationFilter(filters.FilterSet):
class PatientInvestigationSummaryFilter(filters.FilterSet):
created_date = filters.DateFromToRangeFilter(field_name="created_date")
modified_date = filters.DateFromToRangeFilter(field_name="modified_date")
investigation = filters.CharFilter(field_name="investigation__external_id")
Expand All @@ -102,7 +103,7 @@ class PatientInvestigationSummaryViewSet(
queryset = InvestigationValue.objects.all()
lookup_field = "external_id"
permission_classes = (IsAuthenticated,)
filterset_class = PatientInvestigationFilter
filterset_class = PatientInvestigationSummaryFilter
filter_backends = (filters.DjangoFilterBackend,)
pagination_class = InvestigationSummaryResultsSetPagination
SESSION_PER_PAGE = 5
Expand All @@ -124,16 +125,19 @@ def get_queryset(self):
* self.SESSION_PER_PAGE
]
)
if not sessions.exists():
if (
not sessions.exists()
or self.request.user.user_type < User.TYPE_VALUE_MAP["Nurse"]
):
return self.queryset.none()
queryset = queryset.filter(session_id__in=sessions.values("session_id"))
if self.request.user.is_superuser:
return queryset
elif self.request.user.user_type >= User.TYPE_VALUE_MAP["StateLabAdmin"]:
if self.request.user.user_type >= User.TYPE_VALUE_MAP["StateLabAdmin"]:
return queryset.filter(
consultation__patient__facility__state=self.request.user.state
)
elif self.request.user.user_type >= User.TYPE_VALUE_MAP["DistrictLabAdmin"]:
if self.request.user.user_type >= User.TYPE_VALUE_MAP["DistrictLabAdmin"]:
return queryset.filter(
consultation__patient__facility__district=self.request.user.district
)
Expand All @@ -157,7 +161,10 @@ class InvestigationValueViewSet(
serializer_class = InvestigationValueSerializer
queryset = InvestigationValue.objects.all()
lookup_field = "external_id"
permission_classes = (IsAuthenticated,)
permission_classes = (
IsAuthenticated,
DRYPermissions,
)
filterset_class = PatientInvestigationFilter
filter_backends = (filters.DjangoFilterBackend,)
pagination_class = InvestigationValueSetPagination
Expand All @@ -173,11 +180,11 @@ def get_queryset(self):
)
if self.request.user.is_superuser:
return queryset
elif self.request.user.user_type >= User.TYPE_VALUE_MAP["StateLabAdmin"]:
if self.request.user.user_type >= User.TYPE_VALUE_MAP["StateLabAdmin"]:
return queryset.filter(
consultation__patient__facility__state=self.request.user.state
)
elif self.request.user.user_type >= User.TYPE_VALUE_MAP["DistrictLabAdmin"]:
if self.request.user.user_type >= User.TYPE_VALUE_MAP["DistrictLabAdmin"]:
return queryset.filter(
consultation__patient__facility__district=self.request.user.district
)
Expand Down
9 changes: 4 additions & 5 deletions care/facility/api/viewsets/patient_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,11 @@
http_method_names = ["get", "post", "patch", "delete"]

def get_serializer_class(self):
serializer_class = self.serializer_class
if self.action == "retrieve":
serializer_class = PatientSampleDetailSerializer
elif self.action == "partial_update":
serializer_class = PatientSamplePatchSerializer
return serializer_class
return PatientSampleDetailSerializer

Check warning on line 92 in care/facility/api/viewsets/patient_sample.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/viewsets/patient_sample.py#L92

Added line #L92 was not covered by tests
if self.action == "partial_update":
return PatientSamplePatchSerializer
return super().get_serializer_class()

Check warning on line 95 in care/facility/api/viewsets/patient_sample.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/viewsets/patient_sample.py#L94-L95

Added lines #L94 - L95 were not covered by tests

def get_queryset(self):
queryset = super(PatientSampleViewSet, self).get_queryset()
Expand Down
10 changes: 6 additions & 4 deletions care/facility/api/viewsets/shifting.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,10 @@
)
ordering_fields = ["id", "created_date", "modified_date", "emergency"]

permission_classes = (IsAuthenticated, DRYPermissions)
permission_classes = (
IsAuthenticated,
DRYPermissions,
)
filter_backends = (
ShiftingFilterBackend,
filters.DjangoFilterBackend,
Expand All @@ -131,10 +134,9 @@
filterset_class = ShiftingFilterSet

def get_serializer_class(self):
serializer_class = self.serializer_class
if self.action == "retrieve":
serializer_class = ShiftingDetailSerializer
return serializer_class
return ShiftingDetailSerializer
return super().get_serializer_class()

Check warning on line 139 in care/facility/api/viewsets/shifting.py

View check run for this annotation

Codecov / codecov/patch

care/facility/api/viewsets/shifting.py#L138-L139

Added lines #L138 - L139 were not covered by tests

@extend_schema(tags=["shift"])
@action(detail=True, methods=["POST"])
Expand Down
3 changes: 2 additions & 1 deletion care/facility/models/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
from care.utils.models.base import BaseModel

READ_ONLY_USER_TYPES = [
User.TYPE_VALUE_MAP["DistrictReadOnlyAdmin"],
User.TYPE_VALUE_MAP["StateReadOnlyAdmin"],
User.TYPE_VALUE_MAP["DistrictReadOnlyAdmin"],
User.TYPE_VALUE_MAP["NurseReadOnly"],
User.TYPE_VALUE_MAP["StaffReadOnly"],
]

Expand Down
3 changes: 2 additions & 1 deletion care/facility/models/bed.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from care.facility.models.asset import Asset, AssetLocation
from care.facility.models.facility import Facility
from care.facility.models.mixins.permissions.facility import FacilityUserPermissionMixin
from care.facility.models.patient_base import BedType, BedTypeChoices
from care.facility.models.patient_consultation import PatientConsultation
from care.utils.models.base import BaseModel
Expand Down Expand Up @@ -65,7 +66,7 @@ def __str__(self):
return f"{self.asset.name} - {self.bed.name}"


class ConsultationBed(BaseModel):
class ConsultationBed(BaseModel, FacilityUserPermissionMixin):
consultation = models.ForeignKey(
PatientConsultation, on_delete=models.PROTECT, null=False, blank=False
)
Expand Down
18 changes: 7 additions & 11 deletions care/facility/models/daily_round.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
COVID_CATEGORY_CHOICES,
PatientBaseModel,
)
from care.facility.models.base import covert_choice_dict
from care.facility.models.base import READ_ONLY_USER_TYPES, covert_choice_dict
from care.facility.models.bed import AssetBed
from care.facility.models.json_schema.daily_round import (
BLOOD_PRESSURE,
Expand Down Expand Up @@ -522,11 +522,9 @@
@staticmethod
def has_write_permission(request):
if "/analyse" not in request.get_full_path():
if (
request.user.user_type == User.TYPE_VALUE_MAP["DistrictReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StateReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StaffReadOnly"]
):
if request.user.user_type in READ_ONLY_USER_TYPES:
return False

Check warning on line 526 in care/facility/models/daily_round.py

View check run for this annotation

Codecov / codecov/patch

care/facility/models/daily_round.py#L526

Added line #L526 was not covered by tests
if request.user.user_type < User.TYPE_VALUE_MAP["Nurse"]:
return False
return DailyRound.has_read_permission(request)

Expand Down Expand Up @@ -582,11 +580,9 @@
)

def has_object_write_permission(self, request):
if (
request.user.user_type == User.TYPE_VALUE_MAP["DistrictReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StateReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StaffReadOnly"]
):
if request.user.user_type in READ_ONLY_USER_TYPES:
return False

Check warning on line 584 in care/facility/models/daily_round.py

View check run for this annotation

Codecov / codecov/patch

care/facility/models/daily_round.py#L584

Added line #L584 was not covered by tests
if request.user.user_type < User.TYPE_VALUE_MAP["Nurse"]:
return False
return (
request.user.is_superuser
Expand Down
3 changes: 2 additions & 1 deletion care/facility/models/file_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
from django.db import models

from care.facility.models import FacilityBaseModel
from care.facility.models.mixins.permissions.facility import FacilityPermissionMixin
from care.users.models import User
from care.utils.csp import config as cs_provider


class FileUpload(FacilityBaseModel):
class FileUpload(FacilityBaseModel, FacilityPermissionMixin):
"""
Stores data about all file uploads
the file can belong to any type ie Patient , Consultation , Daily Round and so on ...
Expand Down
8 changes: 2 additions & 6 deletions care/facility/models/mixins/permissions/asset.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from dry_rest_permissions.generics import DRYPermissions

from care.facility.models.base import READ_ONLY_USER_TYPES
from care.facility.models.mixins.permissions.base import BasePermissionMixin
from care.users.models import User


class IsAssetUser:
Expand Down Expand Up @@ -30,11 +30,7 @@ def has_object_read_permission(self, request):
return True

def has_object_write_permission(self, request):
if (
request.user.user_type == User.TYPE_VALUE_MAP["DistrictReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StateReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StaffReadOnly"]
):
if request.user.user_type in READ_ONLY_USER_TYPES:
return False

return True
Expand Down
19 changes: 4 additions & 15 deletions care/facility/models/mixins/permissions/base.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from care.facility.models.base import READ_ONLY_USER_TYPES
from care.users.models import User


Expand All @@ -8,11 +9,7 @@ def has_read_permission(request):

@staticmethod
def has_write_permission(request):
if (
request.user.user_type == User.TYPE_VALUE_MAP["DistrictReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StateReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StaffReadOnly"]
):
if request.user.user_type in READ_ONLY_USER_TYPES:
return False
return (
request.user.is_superuser
Expand All @@ -36,11 +33,7 @@ def has_object_read_permission(self, request):
)

def has_object_update_permission(self, request):
if (
request.user.user_type == User.TYPE_VALUE_MAP["DistrictReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StateReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StaffReadOnly"]
):
if request.user.user_type in READ_ONLY_USER_TYPES:
return False
return (request.user.is_superuser) or (
(hasattr(self, "created_by") and request.user == self.created_by)
Expand All @@ -57,11 +50,7 @@ def has_object_update_permission(self, request):
)

def has_object_destroy_permission(self, request):
if (
request.user.user_type == User.TYPE_VALUE_MAP["DistrictReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StateReadOnlyAdmin"]
or request.user.user_type == User.TYPE_VALUE_MAP["StaffReadOnly"]
):
if request.user.user_type in READ_ONLY_USER_TYPES:
return False
return request.user.is_superuser or (
hasattr(self, "created_by") and request.user == self.created_by
Expand Down
Loading