diff --git a/apps/device/views.py b/apps/device/views.py index 20bba21..f84fd9d 100644 --- a/apps/device/views.py +++ b/apps/device/views.py @@ -1,8 +1,10 @@ import logging from common.apps.billing.mixins import QuotaMixin +from common.apps.space.models import Space from common.pagination.base_pagination import BasePagination from common.utils.switch_tenant import UseTenantFromRequestMixin +from common.views.deactivation import DeactivationMixin from common.views.space import SpaceListCreateAPIView, SpaceUpdateAPIView from django.db import transaction from django.db.models import OuterRef, Subquery @@ -39,7 +41,12 @@ logger = logging.getLogger(__name__) -class DeviceViewSet(UseTenantFromRequestMixin, QuotaMixin, viewsets.ModelViewSet): +class DeviceViewSet( + DeactivationMixin, + UseTenantFromRequestMixin, + QuotaMixin, + viewsets.ModelViewSet, +): queryset = Device.objects.select_related("lorawan_device", "network_server").all() pagination_class = BasePagination filter_backends = [OrderingFilter, SearchFilter, DjangoFilterBackend] @@ -125,7 +132,7 @@ def list(self, request, *args, **kwargs): return Response(serializer.data) -class FindDeviceByCodeView(views.APIView): +class FindDeviceByCodeView(DeactivationMixin, views.APIView): def get(self, request, *args, **kwargs): claim_code = kwargs.get("claim_code") device = Device.objects.filter(lorawan_device__claim_code=claim_code).first() @@ -134,6 +141,7 @@ def get(self, request, *args, **kwargs): {"result": "The device not found in the organization!"}, status.HTTP_404_NOT_FOUND, ) + self.check_deactivated(device) if device.status != DeviceStatus.IN_INVENTORY: return Response( {"result": "The device has been used elsewhere!"}, @@ -142,9 +150,13 @@ def get(self, request, *args, **kwargs): return Response(DeviceSerializer(device).data, status=200) -class DeleteSpaceDeviceViewSet(generics.RetrieveUpdateDestroyAPIView): +class DeleteSpaceDeviceViewSet( + DeactivationMixin, + generics.RetrieveUpdateDestroyAPIView, +): lookup_field = "id" - queryset = SpaceDevice.objects.all() + queryset = SpaceDevice.objects.select_related("device", "space").all() + deactivation = ["device", "space"] def get_serializer_class(self): if self.request.method == "GET": @@ -153,8 +165,12 @@ def get_serializer_class(self): class TripViewSet( - mixins.RetrieveModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet + DeactivationMixin, + mixins.RetrieveModelMixin, + mixins.ListModelMixin, + viewsets.GenericViewSet, ): + deactivation = ["space_device.device", "space_device.space"] pagination_class = BasePagination filter_backends = [OrderingFilter, DjangoFilterBackend] filterset_fields = ["space_device__device_id"] @@ -171,6 +187,8 @@ def get_queryset(self): "space_device__space__slug_name": space_slug_name, "space_device__space__is_active": True, } + space = Space.objects.filter(slug_name=space_slug_name).first() + self.check_deactivated(space) queryset = Trip.objects.filter(**filters).select_related( "space_device", @@ -225,6 +243,8 @@ def list(self, request, *args, **kwargs): ) except SpaceDevice.DoesNotExist: raise ParseError("Device does not exist or is not linked to any space.") + self.check_deactivated(space_device.space) + self.check_deactivated(space_device.device) current_trip = ( Trip.objects.filter(space_device=space_device, is_finished=False) @@ -251,7 +271,11 @@ def list(self, request, *args, **kwargs): return Response(serializer.data) -class DeviceLookupView(UseTenantFromRequestMixin, generics.RetrieveAPIView): +class DeviceLookupView( + DeactivationMixin, + UseTenantFromRequestMixin, + generics.RetrieveAPIView, +): swagger_schema = None serializer_class = FormatDeviceSerializer queryset = Device.objects.select_related("lorawan_device").prefetch_related( @@ -270,10 +294,11 @@ def get_queryset(self): def get_object(self): dev_eui = self.kwargs.get("dev_eui").lower() - return get_object_or_404( + instance = get_object_or_404( self.get_queryset(), lorawan_device__dev_eui=dev_eui, ) + return self.check_deactivated_object(instance) class SpaceDeviceLookupView(UseTenantFromRequestMixin, generics.RetrieveAPIView): @@ -288,9 +313,10 @@ def get_object(self): return get_object_or_404(queryset, device_id=device_id) -class RetrieveSpaceDeviceView(generics.RetrieveAPIView): +class RetrieveSpaceDeviceView(DeactivationMixin, generics.RetrieveAPIView): serializer_class = SpaceDeviceSerializer lookup_field = "device_id" + deactivation = ["device", "space"] queryset = SpaceDevice.objects.select_related( "device", "device__lorawan_device", @@ -316,10 +342,14 @@ class ListPublicSpaceDeviceView(generics.ListAPIView): def get_queryset(self): service = SpaceDeviceListService(self.request) - return service.get_public_devices_queryset().order_by("-created_at") + return ( + service.get_public_devices_queryset() + .filter(is_deactivated=False) + .order_by("-created_at") + ) -class RetrievePublicSpaceDeviceView(generics.RetrieveAPIView): +class RetrievePublicSpaceDeviceView(DeactivationMixin, generics.RetrieveAPIView): serializer_class = SpaceDeviceSerializer permission_classes = [AllowAny] lookup_field = "id" @@ -335,6 +365,7 @@ class BulkUpdateSpaceDeviceView(SpaceUpdateAPIView): queryset = SpaceDevice.objects.select_related("device", "space", "position").all() serializer_class = UpdateSpaceDevicePositionSerializer space_field = "space" + deactivation = ["device", "space"] http_method_names = ["put"] @swagger_auto_schema( @@ -360,6 +391,8 @@ def put(self, request, *args, **kwargs): ordered_instances = [ instances[item["id"]] for item in serializer.validated_data ] + for instance in ordered_instances: + self.check_deactivated_object(instance) with transaction.atomic(): serializer = self.get_serializer(