diff --git a/config/settings/base.py b/config/settings/base.py index 4fb5c844..e1784408 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -292,6 +292,7 @@ "django_filters.rest_framework.DjangoFilterBackend", "rest_framework.filters.OrderingFilter", "fahari.common.filters.OrganisationFilterBackend", + "fahari.common.filters.AllottedFacilitiesFilterBackend", ), "DEFAULT_PAGINATION_CLASS": ( "rest_framework_datatables.pagination.DatatablesPageNumberPagination" diff --git a/fahari/common/filters.py b/fahari/common/filters.py index 7fcb46bd..0d40fa34 100644 --- a/fahari/common/filters.py +++ b/fahari/common/filters.py @@ -65,6 +65,25 @@ def filter_queryset(self, request, queryset, view): return queryset.filter(organisation=request.user.organisation) +class AllottedFacilitiesFilterBackend(filters.BaseFilterBackend): + """Users are only allowed to view records relating to facilities they have been allotted to. + + For this to work, the attribute `facility_field_lookup` must be present on a view. The + attribute should contain a lookup to a facility and should be usable from the queryset + returned by the view. If the aforementioned attribute is not present on a view, then no + filtering is performed and the queryset is returned as is. + """ + + def filter_queryset(self, request, queryset, view): + """Filter records to""" + lookup = getattr(view, "facility_field_lookup", None) + if not lookup: + return queryset + allotted_facilities = UserFacilityAllotment.get_facilities_for_user(request.user) + qs_filter = {"%s__in" % lookup: allotted_facilities} + return queryset.filter(**qs_filter) + + class FacilityFilter(CommonFieldsFilterset): """Filter facilities.""" diff --git a/fahari/common/forms/__init__.py b/fahari/common/forms/__init__.py index 0ff192d5..9bb57656 100644 --- a/fahari/common/forms/__init__.py +++ b/fahari/common/forms/__init__.py @@ -7,12 +7,16 @@ SystemForm, UserFacilityAllotmentForm, ) +from .mixins import FormContextMixin, GetAllottedFacilitiesMixin, GetUserFromContextMixin __all__ = [ "BaseModelForm", "FacilityAttachmentForm", "FacilityForm", "FacilityUserForm", + "FormContextMixin", + "GetAllottedFacilitiesMixin", + "GetUserFromContextMixin", "OrganisationForm", "SystemForm", "UserFacilityAllotmentForm", diff --git a/fahari/common/forms/base_forms.py b/fahari/common/forms/base_forms.py index cd4292cd..fa8dd573 100644 --- a/fahari/common/forms/base_forms.py +++ b/fahari/common/forms/base_forms.py @@ -5,7 +5,7 @@ from .mixins import FormContextMixin -class BaseModelForm(ModelForm, FormContextMixin): +class BaseModelForm(FormContextMixin, ModelForm): """Base form for the majority of model forms in the project.""" def __init__(self, *args, **kwargs): diff --git a/fahari/common/forms/mixins.py b/fahari/common/forms/mixins.py index 542a70cb..403fb316 100644 --- a/fahari/common/forms/mixins.py +++ b/fahari/common/forms/mixins.py @@ -1,14 +1,53 @@ -from typing import Any, Dict +from typing import Any, Dict, Optional, Union -from django.forms import Form +from django.contrib.auth import get_user_model +from django.db.models import Model +from django.forms import ModelForm +from ..models import Facility, UserFacilityAllotment +from ..models.common_models import FacilityManager, FacilityQuerySet -class FormContextMixin(Form): - def __init__(self, context: Dict[str, Any] = None, *args, **kwargs): +User = get_user_model() + + +class FormContextMixin(ModelForm): + """Add context to a form.""" + + def __init__(self, *args, **kwargs): + self._context: Dict[str, Any] = kwargs.pop("context", {}) super().__init__(*args, **kwargs) - self._context: Dict[str, Any] = context or {} @property - def context(self): + def context(self) -> Dict[str, Any]: """Return the context as passed on the form during initialization.""" + return self._context + + +class GetUserFromContextMixin(FormContextMixin): + """Add a method to retrieve the logged in user from a form's context.""" + + def get_logged_in_user(self) -> Optional[Model]: + """Determine and return the logged in user from the context.""" + + request = self.context.get("request", None) + user = getattr(request, "user", None) if request else None + return user + + +class GetAllottedFacilitiesMixin(GetUserFromContextMixin): + """Add a method to retrieve the allotted facilities for the logged-in user. + + The logged-in user is determined from a form's context data. + """ + + def get_allotted_facilities(self) -> Union[FacilityManager, FacilityQuerySet]: + """Return a queryset consisting of all the allotted facilities of the logged in user. + + If the logged in user cannot be determined, then an empty queryset is returned instead. + """ + + user = self.get_logged_in_user() + if not user: + return Facility.objects.none() + return UserFacilityAllotment.get_facilities_for_user(user) diff --git a/fahari/common/tests/test_api.py b/fahari/common/tests/test_api.py index 3bbaef57..87706b12 100644 --- a/fahari/common/tests/test_api.py +++ b/fahari/common/tests/test_api.py @@ -76,6 +76,16 @@ def setUp(self): self.user.organisation = self.global_organisation self.user.save() + # Allot the given users to all the facilities in FYJ counties + self.user_facility_allotment = baker.make( + UserFacilityAllotment, + allotment_type=UserFacilityAllotment.AllotmentType.BY_REGION.value, + counties=WHITELIST_COUNTIES, + organisation=self.global_organisation, + region_type=UserFacilityAllotment.RegionType.COUNTY.value, + user=self.user, + ) + assert self.client.login(username=username, password="pass123") is True self.patch_organisation = partial( @@ -610,10 +620,11 @@ def setUp(self): ) def test_create(self): + user = baker.make(get_user_model(), organisation=self.global_organisation) data = { "allotment_type": self.by_facility.value, "facilities": map(lambda f: f.pk, self.facilities), - "user": self.user.pk, + "user": user.pk, "organisation": self.global_organisation.pk, } response = self.client.post(reverse("common:user_facility_allotment_create"), data=data) @@ -623,21 +634,14 @@ def test_create(self): ) def test_update(self): - instance: UserFacilityAllotment = baker.make( - UserFacilityAllotment, - allotment_type=self.by_facility.value, - facilities=self.facilities, - organisation=self.global_organisation, - user=self.user, - ) + instance = self.user_facility_allotment data = { "pk": instance.pk, - "allotment_type": self.by_region.value, - "region_type": UserFacilityAllotment.RegionType.COUNTY.value, - "counties": ["Nairobi"], + "allotment_type": self.by_facility.value, + "facilities": map(lambda f: f.pk, self.facilities), "user": self.user.pk, "organisation": self.global_organisation.pk, - "active": True, + "active": False, } response = self.client.post( reverse("common:user_facility_allotment_update", kwargs={"pk": instance.pk}), data=data @@ -648,12 +652,13 @@ def test_update(self): ) def test_delete(self): + user = baker.make(get_user_model(), organisation=self.global_organisation) instance: UserFacilityAllotment = baker.make( UserFacilityAllotment, allotment_type=self.by_facility.value, facilities=self.facilities, organisation=self.global_organisation, - user=self.user, + user=user, ) response = self.client.post( reverse("common:user_facility_allotment_delete", kwargs={"pk": instance.pk}), diff --git a/fahari/common/views/__init__.py b/fahari/common/views/__init__.py index e330b433..cf6e018a 100644 --- a/fahari/common/views/__init__.py +++ b/fahari/common/views/__init__.py @@ -23,7 +23,7 @@ UserFacilityAllotmentView, UserFacilityViewSet, ) -from .mixins import ApprovedMixin, BaseFormMixin, GetKwargsMixin +from .mixins import ApprovedMixin, BaseFormMixin, FormContextMixin __all__ = [ "AboutView", @@ -40,7 +40,7 @@ "FacilityUserViewSet", "FacilityView", "FacilityViewSet", - "GetKwargsMixin", + "FormContextMixin", "HomeView", "SystemCreateView", "SystemDeleteView", diff --git a/fahari/common/views/common_views.py b/fahari/common/views/common_views.py index 32aeb9f6..58e9d45f 100644 --- a/fahari/common/views/common_views.py +++ b/fahari/common/views/common_views.py @@ -92,6 +92,7 @@ class FacilityViewSet(BaseView): "mfl_code", "registration_number", ) + facility_field_lookup = "pk" class SystemContextMixin: diff --git a/fahari/common/views/mixins.py b/fahari/common/views/mixins.py index 1d047de9..55fb1bb5 100644 --- a/fahari/common/views/mixins.py +++ b/fahari/common/views/mixins.py @@ -1,3 +1,5 @@ +from typing import Any, Dict + from django.contrib.auth import get_user_model from django.contrib.auth.mixins import ( LoginRequiredMixin, @@ -37,8 +39,22 @@ def form_valid(self, form): return super().form_valid(form) -class GetKwargsMixin(ModelFormMixin, LoginRequiredMixin, View): - def get_form_kwargs(self): +class FormContextMixin(ModelFormMixin, LoginRequiredMixin, View): + """Mixin to inject context data into a form.""" + + def get_form_context(self) -> Dict[str, Any]: + """Return the data to be used as a form's context.""" + + return { + "view": self, + "args": getattr(self, "args", ()), + "kwargs": getattr(self, "kwargs", {}), + "request": getattr(self, "request", None), + } + + def get_form_kwargs(self) -> Dict[str, Any]: + """Extend the base implementation to add context data on the returned form kwargs.""" + kwargs = super().get_form_kwargs() - kwargs["request"] = self.request + kwargs["context"] = self.get_form_context() return kwargs diff --git a/fahari/ops/forms.py b/fahari/ops/forms.py index 7163b64d..806198b9 100644 --- a/fahari/ops/forms.py +++ b/fahari/ops/forms.py @@ -3,9 +3,7 @@ from django import forms from django.forms.widgets import DateInput, DateTimeInput, Select, Textarea, TextInput -from fahari.common.dashboard import get_fahari_facilities_queryset -from fahari.common.forms import BaseModelForm -from fahari.common.models import FacilityUser +from fahari.common.forms import BaseModelForm, GetAllottedFacilitiesMixin from fahari.common.widgets import SearchableComboBox from .models import ( @@ -27,7 +25,7 @@ ) -class FacilitySystemForm(BaseModelForm): +class FacilitySystemForm(GetAllottedFacilitiesMixin, BaseModelForm): field_order = ( "facility", "system", @@ -38,7 +36,7 @@ class FacilitySystemForm(BaseModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper.form_id = "facility_system_form" - self.fields["facility"].queryset = get_fahari_facilities_queryset() + self.fields["facility"].queryset = self.get_allotted_facilities().active() class Meta(BaseModelForm.Meta): model = FacilitySystem @@ -47,7 +45,7 @@ class Meta(BaseModelForm.Meta): } -class FacilitySystemTicketForm(BaseModelForm): +class FacilitySystemTicketForm(GetAllottedFacilitiesMixin, BaseModelForm): field_order = ( "facility_system", @@ -60,20 +58,11 @@ class FacilitySystemTicketForm(BaseModelForm): ) def __init__(self, *args, **kwargs): - request = kwargs.pop("request", None) super().__init__(*args, **kwargs) - if request is not None and hasattr(request, "user"): - user_facility_ids = FacilityUser.objects.filter(user_id=request.user.id).values_list( - "facility_id", flat=True - ) - user_system_facilities = FacilitySystem.objects.filter( - facility_id__in=user_facility_ids - ) - self.fields["facility_system"].queryset = user_system_facilities - else: - self.fields["facility_system"].queryset = FacilitySystem.objects.none() - self.helper.form_id = "facility_system_ticket_form" + self.fields["facility_system"].queryset = FacilitySystem.objects.active().filter( + facility__in=self.get_allotted_facilities() + ) class Meta(BaseModelForm.Meta): model = FacilitySystemTicket @@ -125,7 +114,7 @@ def __init__(self, *args, **kwargs): self.helper.form_id = "facility_system_ticket_resolve_form" -class StockReceiptVerificationForm(BaseModelForm): +class StockReceiptVerificationForm(GetAllottedFacilitiesMixin, BaseModelForm): field_order = ( "facility", "commodity", @@ -144,7 +133,7 @@ class StockReceiptVerificationForm(BaseModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper.form_id = "stock_receipt_verification_form" - self.fields["facility"].queryset = get_fahari_facilities_queryset() + self.fields["facility"].queryset = self.get_allotted_facilities().active() self.fields["delivery_note_image"].required = True class Meta(BaseModelForm.Meta): @@ -216,7 +205,7 @@ class Meta(BaseModelForm.Meta): } -class SiteMentorshipForm(BaseModelForm): +class SiteMentorshipForm(GetAllottedFacilitiesMixin, BaseModelForm): field_order = ( "staff_member", "site", @@ -231,7 +220,7 @@ class SiteMentorshipForm(BaseModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper.form_id = "site_mentorship_form" - self.fields["site"].queryset = get_fahari_facilities_queryset() + self.fields["site"].queryset = self.get_allotted_facilities().active() class Meta(BaseModelForm.Meta): model = SiteMentorship @@ -245,7 +234,7 @@ class Meta(BaseModelForm.Meta): } -class DailyUpdateForm(BaseModelForm): +class DailyUpdateForm(GetAllottedFacilitiesMixin, BaseModelForm): field_order = ( "facility", "date", @@ -263,7 +252,7 @@ class DailyUpdateForm(BaseModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper.form_id = "daily_update_form" - self.fields["facility"].queryset = get_fahari_facilities_queryset() + self.fields["facility"].queryset = self.get_allotted_facilities().active() class Meta(BaseModelForm.Meta): model = DailyUpdate @@ -380,7 +369,7 @@ class Meta(BaseModelForm.Meta): model = UoMCategory -class FacilityNetworkStatusForm(BaseModelForm): +class FacilityNetworkStatusForm(GetAllottedFacilitiesMixin, BaseModelForm): field_order = ( "facility", "has_network", @@ -390,7 +379,7 @@ class FacilityNetworkStatusForm(BaseModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper.form_id = "facility_network_status_form" - self.fields["facility"].queryset = get_fahari_facilities_queryset() + self.fields["facility"].queryset = self.get_allotted_facilities().active() class Meta(BaseModelForm.Meta): model = FacilityNetworkStatus @@ -399,7 +388,7 @@ class Meta(BaseModelForm.Meta): } -class FacilityDeviceForm(BaseModelForm): +class FacilityDeviceForm(GetAllottedFacilitiesMixin, BaseModelForm): field_order = ( "facility", "number_of_devices", @@ -410,7 +399,7 @@ class FacilityDeviceForm(BaseModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper.form_id = "facility_device_form" - self.fields["facility"].queryset = get_fahari_facilities_queryset() + self.fields["facility"].queryset = self.get_allotted_facilities().active() class Meta(BaseModelForm.Meta): model = FacilityDevice @@ -419,7 +408,7 @@ class Meta(BaseModelForm.Meta): } -class FacilityDeviceRequestForm(BaseModelForm): +class FacilityDeviceRequestForm(GetAllottedFacilitiesMixin, BaseModelForm): field_order = ( "facility", "device_requested", @@ -432,7 +421,7 @@ class FacilityDeviceRequestForm(BaseModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper.form_id = "facility_device_request_form" - self.fields["facility"].queryset = get_fahari_facilities_queryset() + self.fields["facility"].queryset = self.get_allotted_facilities().active() class Meta(BaseModelForm.Meta): model = FacilityDeviceRequest @@ -447,7 +436,7 @@ class Meta(BaseModelForm.Meta): } -class SecurityIncidenceForm(BaseModelForm): +class SecurityIncidenceForm(GetAllottedFacilitiesMixin, BaseModelForm): field_order = ( "facility", "title", @@ -459,7 +448,7 @@ class SecurityIncidenceForm(BaseModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.helper.form_id = "security_incidence_form" - self.fields["facility"].queryset = get_fahari_facilities_queryset() + self.fields["facility"].queryset = self.get_allotted_facilities().active() class Meta(BaseModelForm.Meta): model = SecurityIncidence diff --git a/fahari/ops/tests/test_api.py b/fahari/ops/tests/test_api.py index 1bb68352..7ff0b5e1 100644 --- a/fahari/ops/tests/test_api.py +++ b/fahari/ops/tests/test_api.py @@ -268,7 +268,7 @@ def test_create(self): response = self.client.post(reverse("ops:ticket_create"), data=data) self.assertEqual( response.status_code, - 200, + 302, ) def test_update(self): @@ -293,7 +293,7 @@ def test_update(self): self.assertEqual( response.status_code, - 200, + 302, ) def test_delete(self): diff --git a/fahari/ops/views.py b/fahari/ops/views.py index 75a94c3d..7475a045 100644 --- a/fahari/ops/views.py +++ b/fahari/ops/views.py @@ -10,7 +10,7 @@ from django.views.generic.detail import SingleObjectMixin, SingleObjectTemplateResponseMixin from django.views.generic.edit import FormMixin, ProcessFormView -from fahari.common.views import ApprovedMixin, BaseFormMixin, BaseView, GetKwargsMixin +from fahari.common.views import ApprovedMixin, BaseFormMixin, BaseView, FormContextMixin from .filters import ( ActivityLogFilter, @@ -98,30 +98,33 @@ class FacilitySystemsView( permission_required = "ops.view_facilitysystem" -class FacilitySystemCreateView(FacilitySystemContextMixin, BaseFormMixin, CreateView): +class FacilitySystemCreateView( + FacilitySystemContextMixin, FormContextMixin, BaseFormMixin, CreateView +): form_class = FacilitySystemForm success_url = reverse_lazy("ops:versions") model = FacilitySystem -class FacilitySystemUpdateView(FacilitySystemContextMixin, UpdateView, BaseFormMixin): +class FacilitySystemUpdateView( + FacilitySystemContextMixin, FormContextMixin, UpdateView, BaseFormMixin +): form_class = FacilitySystemForm model = FacilitySystem success_url = reverse_lazy("ops:versions") -class FacilitySystemDeleteView(FacilitySystemContextMixin, DeleteView, BaseFormMixin): +class FacilitySystemDeleteView( + FacilitySystemContextMixin, FormContextMixin, DeleteView, BaseFormMixin +): form_class = FacilitySystemForm model = FacilitySystem success_url = reverse_lazy("ops:versions") class FacilitySystemViewSet(BaseView): - queryset = FacilitySystem.objects.filter( - active=True, - ) - + queryset = FacilitySystem.objects.active() serializer_class = FacilitySystemSerializer filterset_class = FacilitySystemFilter ordering_fields = ( @@ -134,6 +137,7 @@ class FacilitySystemViewSet(BaseView): "system__name", "-version", ) + facility_field_lookup = "facility" class FacilitySystemTicketContextMixin: @@ -152,22 +156,24 @@ class FacilitySystemTicketsView( class FacilitySystemTicketCreateView( - FacilitySystemTicketContextMixin, BaseFormMixin, GetKwargsMixin, CreateView + FacilitySystemTicketContextMixin, BaseFormMixin, FormContextMixin, CreateView ): form_class = FacilitySystemTicketForm - success_url = reverse_lazy("ops:tickets") model = FacilitySystemTicket + success_url = reverse_lazy("ops:tickets") class FacilitySystemTicketUpdateView( - FacilitySystemTicketContextMixin, BaseFormMixin, GetKwargsMixin, UpdateView + FacilitySystemTicketContextMixin, BaseFormMixin, FormContextMixin, UpdateView ): form_class = FacilitySystemTicketForm model = FacilitySystemTicket success_url = reverse_lazy("ops:tickets") -class FacilitySystemTicketDeleteView(FacilitySystemTicketContextMixin, DeleteView, BaseFormMixin): +class FacilitySystemTicketDeleteView( + FacilitySystemTicketContextMixin, BaseFormMixin, FormContextMixin, DeleteView +): form_class = FacilitySystemTicketForm model = FacilitySystemTicket success_url = reverse_lazy("ops:tickets") @@ -207,9 +213,7 @@ def get_initial(self): class FacilitySystemTicketViewSet(BaseView): - queryset = FacilitySystemTicket.objects.filter( - active=True, - ) + queryset = FacilitySystemTicket.objects.active() serializer_class = FacilitySystemTicketSerializer filterset_class = FacilitySystemTicketFilter ordering_fields = ( @@ -222,6 +226,7 @@ class FacilitySystemTicketViewSet(BaseView): "facility_system__facility__name", "facility_system__system__name", ) + facility_field_lookup = "facility_system__facility" class StockReceiptVerificationContextMixin: @@ -240,7 +245,7 @@ class StockReceiptVerificationView( class StockReceiptVerificationCreateView( - StockReceiptVerificationContextMixin, BaseFormMixin, CreateView + StockReceiptVerificationContextMixin, BaseFormMixin, FormContextMixin, CreateView ): form_class = StockReceiptVerificationForm model = StockReceiptVerification @@ -248,7 +253,7 @@ class StockReceiptVerificationCreateView( class StockReceiptVerificationUpdateView( - StockReceiptVerificationContextMixin, UpdateView, BaseFormMixin + StockReceiptVerificationContextMixin, BaseFormMixin, FormContextMixin, UpdateView ): form_class = StockReceiptVerificationForm model = StockReceiptVerification @@ -256,7 +261,7 @@ class StockReceiptVerificationUpdateView( class StockReceiptVerificationDeleteView( - StockReceiptVerificationContextMixin, DeleteView, BaseFormMixin + StockReceiptVerificationContextMixin, BaseFormMixin, FormContextMixin, DeleteView ): form_class = StockReceiptVerificationForm model = StockReceiptVerification @@ -264,9 +269,7 @@ class StockReceiptVerificationDeleteView( class StockReceiptVerificationViewSet(BaseView): - queryset = StockReceiptVerification.objects.filter( - active=True, - ) + queryset = StockReceiptVerification.objects.active() serializer_class = StockReceiptVerificationSerializer filterset_class = StockReceiptVerificationFilter ordering_fields = ( @@ -278,6 +281,7 @@ class StockReceiptVerificationViewSet(BaseView): "description", "comments", ) + facility_field_lookup = "facility" class ActivityLogContextMixin: @@ -312,9 +316,7 @@ class ActivityLogDeleteView(ActivityLogContextMixin, DeleteView, BaseFormMixin): class ActivityLogViewSet(BaseView): - queryset = ActivityLog.objects.filter( - active=True, - ) + queryset = ActivityLog.objects.active() serializer_class = ActivityLogSerializer filterset_class = ActivityLogFilter ordering_fields = ( @@ -343,28 +345,32 @@ class SiteMentorshipView( permission_required = "ops.view_sitementorship" -class SiteMentorshipCreateView(SiteMentorshipContextMixin, BaseFormMixin, CreateView): +class SiteMentorshipCreateView( + SiteMentorshipContextMixin, BaseFormMixin, FormContextMixin, CreateView +): form_class = SiteMentorshipForm model = SiteMentorship success_url = reverse_lazy("ops:site_mentorships") -class SiteMentorshipUpdateView(SiteMentorshipContextMixin, UpdateView, BaseFormMixin): +class SiteMentorshipUpdateView( + SiteMentorshipContextMixin, BaseFormMixin, FormContextMixin, UpdateView +): form_class = SiteMentorshipForm model = SiteMentorship success_url = reverse_lazy("ops:site_mentorships") -class SiteMentorshipDeleteView(SiteMentorshipContextMixin, DeleteView, BaseFormMixin): +class SiteMentorshipDeleteView( + SiteMentorshipContextMixin, BaseFormMixin, FormContextMixin, DeleteView +): form_class = SiteMentorshipForm model = SiteMentorship success_url = reverse_lazy("ops:site_mentorships") class SiteMentorshipViewSet(BaseView): - queryset = SiteMentorship.objects.filter( - active=True, - ) + queryset = SiteMentorship.objects.active() serializer_class = SiteMentorshipSerializer filterset_class = SiteMentorshipFilter ordering_fields = ( @@ -378,6 +384,7 @@ class SiteMentorshipViewSet(BaseView): "site__name", "objective", ) + facility_field_lookup = "site" class DailySiteUpdatesContextMixin: @@ -395,28 +402,32 @@ class DailySiteUpdatesView( permission_required = "ops.view_dailyupdate" -class DailyUpdateCreateView(DailySiteUpdatesContextMixin, BaseFormMixin, CreateView): +class DailyUpdateCreateView( + DailySiteUpdatesContextMixin, BaseFormMixin, FormContextMixin, CreateView +): form_class = DailyUpdateForm model = DailyUpdate success_url = reverse_lazy("ops:daily_site_updates") -class DailyUpdateUpdateView(DailySiteUpdatesContextMixin, UpdateView, BaseFormMixin): +class DailyUpdateUpdateView( + DailySiteUpdatesContextMixin, BaseFormMixin, FormContextMixin, UpdateView +): form_class = DailyUpdateForm model = DailyUpdate success_url = reverse_lazy("ops:daily_site_updates") -class DailyUpdateDeleteView(DailySiteUpdatesContextMixin, DeleteView, BaseFormMixin): +class DailyUpdateDeleteView( + DailySiteUpdatesContextMixin, BaseFormMixin, FormContextMixin, DeleteView +): form_class = DailyUpdateForm model = DailyUpdate success_url = reverse_lazy("ops:daily_site_updates") class DailyUpdateViewSet(BaseView): - queryset = DailyUpdate.objects.filter( - active=True, - ) + queryset = DailyUpdate.objects.active() serializer_class = DailyUpdateSerializer filterset_class = DailyUpdateFilter ordering_fields = ( @@ -424,6 +435,7 @@ class DailyUpdateViewSet(BaseView): "facility__name", ) search_fields = ("facility__name",) + facility_field_lookup = "facility" class TimeSheetContextMixin: @@ -474,9 +486,7 @@ def post(self, request, *args, **kwargs): class TimeSheetViewSet(BaseView): - queryset = TimeSheet.objects.filter( - active=True, - ) + queryset = TimeSheet.objects.active() serializer_class = TimeSheetSerializer filterset_class = TimeSheetFilter ordering_fields = ( @@ -530,9 +540,7 @@ class WeeklyProgramUpdatesDeleteView(WeeklyProgramUpdateContextMixin, DeleteView class WeeklyProgramUpdateViewSet(BaseView): - queryset = WeeklyProgramUpdate.objects.filter( - active=True, - ) + queryset = WeeklyProgramUpdate.objects.active() serializer_class = WeeklyProgramUpdateSerializer filterset_class = WeeklyProgramUpdateFilter ordering_fields = ("-date",) @@ -574,9 +582,7 @@ class CommodityDeleteView(CommodityContextMixin, DeleteView, BaseFormMixin): class CommodityViewSet(BaseView): - queryset = Commodity.objects.filter( - active=True, - ) + queryset = Commodity.objects.active() serializer_class = CommoditySerializer filterset_class = CommodityFilter ordering_fields = ( @@ -622,7 +628,7 @@ class UoMDeleteView(UoMContextMixin, BaseFormMixin, DeleteView): class UoMViewSet(BaseView): - queryset = UoM.objects.filter(active=True) + queryset = UoM.objects.active() serializer_class = UoMSerializer filterset_class = UoMFilter ordering_fields = ("name",) @@ -663,7 +669,7 @@ class UoMCategoryDeleteView(UoMCategoryContextMixin, BaseFormMixin, DeleteView): class UoMCategoryViewSet(BaseView): - queryset = UoMCategory.objects.filter(active=True) + queryset = UoMCategory.objects.active() serializer_class = UoMCategorySerializer filterset_class = UoMCategoryFilter ordering_fields = ("name", "measure_type") @@ -685,29 +691,30 @@ class FacilityNetworkStatusListView( permission_required = "ops.view_facilitynetworkstatus" -class FacilityNetworkStatusCreateView(NetworkStatusMixin, BaseFormMixin, CreateView): +class FacilityNetworkStatusCreateView( + NetworkStatusMixin, BaseFormMixin, FormContextMixin, CreateView +): form_class = FacilityNetworkStatusForm model = FacilityNetworkStatus success_url = reverse_lazy("ops:facility_network_status") -class FacilityNetworkStatusUpdateView(NetworkStatusMixin, UpdateView, BaseFormMixin): +class FacilityNetworkStatusUpdateView( + NetworkStatusMixin, BaseFormMixin, FormContextMixin, UpdateView +): form_class = FacilityNetworkStatusForm model = FacilityNetworkStatus success_url = reverse_lazy("ops:facility_network_status") -class FacilityNetworkStatusDeleteView(NetworkStatusMixin, DeleteView, BaseFormMixin): +class FacilityNetworkStatusDeleteView(NetworkStatusMixin, BaseFormMixin, FormMixin, DeleteView): form_class = FacilityNetworkStatusForm model = FacilityNetworkStatus success_url = reverse_lazy("ops:facility_network_status") class FacilityNetworkStatusViewSet(BaseView): - queryset = FacilityNetworkStatus.objects.filter( - active=True, - ) - + queryset = FacilityNetworkStatus.objects.active() serializer_class = FacilityNetworkStatusSerializer filterset_class = FacilityNetworkStatusFilter ordering_fields = ( @@ -720,6 +727,7 @@ class FacilityNetworkStatusViewSet(BaseView): "has_network", "has_internet", ) + facility_field_lookup = "facility" class FacilityDevicesMixin: @@ -737,29 +745,26 @@ class FacilityDevicesListView( permission_required = "ops.view_facilitydevice" -class FacilityDeviceCreateView(FacilityDevicesMixin, BaseFormMixin, CreateView): +class FacilityDeviceCreateView(FacilityDevicesMixin, BaseFormMixin, FormContextMixin, CreateView): form_class = FacilityDeviceForm model = FacilityDevice success_url = reverse_lazy("ops:facility_devices") -class FacilityDeviceUpdateView(FacilityDevicesMixin, UpdateView, BaseFormMixin): +class FacilityDeviceUpdateView(FacilityDevicesMixin, BaseFormMixin, FormContextMixin, UpdateView): form_class = FacilityDeviceForm model = FacilityDevice success_url = reverse_lazy("ops:facility_devices") -class FacilityDeviceDeleteView(FacilityDevicesMixin, DeleteView, BaseFormMixin): +class FacilityDeviceDeleteView(FacilityDevicesMixin, BaseFormMixin, FormContextMixin, DeleteView): form_class = FacilityDeviceForm model = FacilityDevice success_url = reverse_lazy("ops:facility_devices") class FacilityDeviceViewSet(BaseView): - queryset = FacilityDevice.objects.filter( - active=True, - ) - + queryset = FacilityDevice.objects.active() serializer_class = FacilityDeviceSerializer filterset_class = FacilityDeviceFilter ordering_fields = ( @@ -773,6 +778,7 @@ class FacilityDeviceViewSet(BaseView): "number_of_devices", "number_of_ups", ) + facility_field_lookup = "facility" class FacilityDeviceRequestsMixin: @@ -790,29 +796,32 @@ class FacilityDeviceRequestsListView( permission_required = "ops.view_facilitydevicerequest" -class FacilityDeviceRequestCreateView(FacilityDeviceRequestsMixin, BaseFormMixin, CreateView): +class FacilityDeviceRequestCreateView( + FacilityDeviceRequestsMixin, BaseFormMixin, FormContextMixin, CreateView +): form_class = FacilityDeviceRequestForm model = FacilityDeviceRequest success_url = reverse_lazy("ops:facility_device_requests") -class FacilityDeviceRequestUpdateView(FacilityDeviceRequestsMixin, UpdateView, BaseFormMixin): +class FacilityDeviceRequestUpdateView( + FacilityDeviceRequestsMixin, BaseFormMixin, FormContextMixin, UpdateView +): form_class = FacilityDeviceRequestForm model = FacilityDeviceRequest success_url = reverse_lazy("ops:facility_device_requests") -class FacilityDeviceRequestDeleteView(FacilityDeviceRequestsMixin, DeleteView, BaseFormMixin): +class FacilityDeviceRequestDeleteView( + FacilityDeviceRequestsMixin, BaseFormMixin, FormContextMixin, DeleteView +): form_class = FacilityDeviceRequestForm model = FacilityDeviceRequest success_url = reverse_lazy("ops:facility_device_requests") class FacilityDeviceRequestViewSet(BaseView): - queryset = FacilityDeviceRequest.objects.filter( - active=True, - ) - + queryset = FacilityDeviceRequest.objects.active() serializer_class = FacilityDeviceRequestSerializer filterset_class = FacilityDeviceRequestFilter ordering_fields = ( @@ -830,6 +839,7 @@ class FacilityDeviceRequestViewSet(BaseView): "date_requested", "delivery_date", ) + facility_field_lookup = "facility" class SecurityIncidenceMixin: @@ -847,29 +857,32 @@ class SecurityIncidentsListView( permission_required = "ops.view_securityincidence" -class SecurityIncidenceCreateView(SecurityIncidenceMixin, BaseFormMixin, CreateView): +class SecurityIncidenceCreateView( + SecurityIncidenceMixin, BaseFormMixin, FormContextMixin, CreateView +): form_class = SecurityIncidenceForm model = SecurityIncidence success_url = reverse_lazy("ops:security_incidents") -class SecurityIncidenceUpdateView(SecurityIncidenceMixin, UpdateView, BaseFormMixin): +class SecurityIncidenceUpdateView( + SecurityIncidenceMixin, BaseFormMixin, FormContextMixin, UpdateView +): form_class = SecurityIncidenceForm model = SecurityIncidence success_url = reverse_lazy("ops:security_incidents") -class SecurityIncidenceDeleteView(SecurityIncidenceMixin, DeleteView, BaseFormMixin): +class SecurityIncidenceDeleteView( + SecurityIncidenceMixin, BaseFormMixin, FormContextMixin, DeleteView +): form_class = SecurityIncidenceForm model = SecurityIncidence success_url = reverse_lazy("ops:security_incidents") class SecurityIncidenceViewSet(BaseView): - queryset = SecurityIncidence.objects.filter( - active=True, - ) - + queryset = SecurityIncidence.objects.active() serializer_class = SecurityIncidenceSerializer filterset_class = SecurityIncidenceFilter ordering_fields = ( @@ -885,3 +898,4 @@ class SecurityIncidenceViewSet(BaseView): "reported_on", "reported_by", ) + facility_field_lookup = "facility"