diff --git a/api/views.py b/api/views.py index 15ada04..b1f8936 100644 --- a/api/views.py +++ b/api/views.py @@ -42,7 +42,6 @@ from .serializers import ( AuthSerializer, CustomUserSerializer, CustomReadOnlyUserSerializer, - CustomReadOnlyUserByIDCardSerializer, UserProfileUpdateSerializer, ) @@ -579,16 +578,6 @@ def filter_temporary_user(request): ) -class ListUserByIDCardView(generics.ListAPIView): - # Create user API view - permission_classes = (permissions.AllowAny,) - serializer_class = CustomReadOnlyUserByIDCardSerializer - filter_backends = [DjangoFilterBackend] - filterset_fields = "__all__" - filterset_class = UserFilter - queryset = User.objects.all() - - class UserDetailAPIView(StaffEditorPermissionMixin, generics.RetrieveAPIView): queryset = User.objects.all() serializer_class = CustomReadOnlyUserSerializer diff --git a/apibase/settings.py b/apibase/settings.py index b91ac23..4ae2955 100644 --- a/apibase/settings.py +++ b/apibase/settings.py @@ -235,8 +235,11 @@ REST_FRAMEWORK = { "login": "1000/min", }, "EXCEPTION_HANDLER": "api.exceptions.custom_exception_handler", - "DEFAULT_RENDERER_CLASSES": ("rest_framework.renderers.JSONRenderer",), - # "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema" + "DEFAULT_RENDERER_CLASSES": ( + "rest_framework.renderers.JSONRenderer", + # "rest_framework.renderers.BrowsableAPIRenderer", + ), + # "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema", } diff --git a/billing/views.py b/billing/views.py index 77634d4..aad9276 100644 --- a/billing/views.py +++ b/billing/views.py @@ -13,6 +13,7 @@ from rest_framework.response import Response from api.mixins import StaffEditorPermissionMixin from api.tasks import add_new_devices_to_omada from apibase.env import BASE_DIR, env +from django.db.models import Prefetch import logging from .models import Device, Payment, Topup, WalletTransaction @@ -60,10 +61,18 @@ class ListCreatePaymentView(StaffEditorPermissionMixin, generics.ListCreateAPIVi filterset_class = PaymentFilter def get_queryset(self): - queryset = super().get_queryset() - if self.request.user.is_superuser: - return queryset - return queryset.filter(user=self.request.user) + unpaid_qs = Payment.objects.filter(paid=False).order_by("-created_at") + device_qs = Device.objects.prefetch_related( + Prefetch("payments", queryset=unpaid_qs, to_attr="unpaid_payments") + ) + queryset = Payment.objects.select_related("user").prefetch_related( + Prefetch("devices", queryset=device_qs) + ) + + if not self.request.user.is_superuser: + queryset = queryset.filter(user=self.request.user) + + return queryset def create(self, request): data = request.data @@ -163,7 +172,7 @@ class UpdatePaymentAPIView(StaffEditorPermissionMixin, generics.UpdateAPIView): class VerifyPaymentView(StaffEditorPermissionMixin, generics.UpdateAPIView): serializer_class = PaymentSerializer - queryset = Payment.objects.all() + queryset = Payment.objects.select_related("user").all() lookup_field = "pk" def update(self, request, *args, **kwargs): @@ -322,7 +331,7 @@ class VerifyPaymentView(StaffEditorPermissionMixin, generics.UpdateAPIView): class CancelPaymentView(StaffEditorPermissionMixin, generics.UpdateAPIView): - queryset = Payment.objects.all() + queryset = Payment.objects.select_related("user").all() serializer_class = PaymentSerializer lookup_field = "pk" @@ -352,7 +361,7 @@ class CancelPaymentView(StaffEditorPermissionMixin, generics.UpdateAPIView): class ListCreateTopupView(StaffEditorPermissionMixin, generics.ListCreateAPIView): - queryset = Topup.objects.all() + queryset = Topup.objects.all().prefetch_related("user") serializer_class = TopupSerializer filter_backends = [DjangoFilterBackend] filterset_fields = "__all__" diff --git a/devices/serializers.py b/devices/serializers.py index a5dd133..f125f9c 100644 --- a/devices/serializers.py +++ b/devices/serializers.py @@ -36,9 +36,9 @@ class DeviceSerializer(serializers.ModelSerializer): def get_pending_payment_id(self, obj): unpaid_payment = ( - Payment.objects.filter(devices=obj, paid=False) - .order_by("-created_at") - .first() + obj.unpaid_payments[0] + if hasattr(obj, "unpaid_payments") and obj.unpaid_payments + else None ) return unpaid_payment.id if unpaid_payment else None @@ -63,9 +63,9 @@ class AdminDeviceSerializer(serializers.ModelSerializer): def get_pending_payment_id(self, obj): unpaid_payment = ( - Payment.objects.filter(devices=obj, paid=False) - .order_by("-created_at") - .first() + obj.unpaid_payments[0] + if hasattr(obj, "unpaid_payments") and obj.unpaid_payments + else None ) return unpaid_payment.id if unpaid_payment else None diff --git a/devices/views.py b/devices/views.py index c5e3add..f27c03a 100644 --- a/devices/views.py +++ b/devices/views.py @@ -3,7 +3,9 @@ from xmlrpc.client import Boolean from rest_framework import generics, status from rest_framework.response import Response from django_filters.rest_framework import DjangoFilterBackend +from billing.models import Payment from .models import Device +from django.db.models import Prefetch from .serializers import ( CreateDeviceSerializer, DeviceSerializer, @@ -28,6 +30,13 @@ class DeviceListCreateAPIView( filterset_fields = "__all__" filterset_class = DeviceFilter + def get_queryset(self): + unpaid_qs = Payment.objects.filter(paid=False).order_by("-created_at") + base_qs = Device.objects.select_related("user").prefetch_related( + Prefetch("payments", queryset=unpaid_qs, to_attr="unpaid_payments") + ) + return base_qs.all() + def list(self, request, *args, **kwargs): queryset = self.filter_queryset(self.get_queryset()) all_devices = request.query_params.get("all_devices", "false").lower() in [ @@ -90,7 +99,7 @@ class DeviceDetailAPIView(StaffEditorPermissionMixin, generics.RetrieveAPIView): class DeviceUpdateAPIView(StaffEditorPermissionMixin, generics.UpdateAPIView): - queryset = Device.objects.all() + queryset = Device.objects.select_related("user").all() serializer_class = CreateDeviceSerializer lookup_field = "pk" @@ -116,7 +125,7 @@ class DeviceUpdateAPIView(StaffEditorPermissionMixin, generics.UpdateAPIView): class DeviceBlockAPIView(StaffEditorPermissionMixin, generics.UpdateAPIView): - queryset = Device.objects.all() + queryset = Device.objects.select_related("user").all() serializer_class = BlockDeviceSerializer lookup_field = "pk" @@ -154,7 +163,7 @@ class DeviceBlockAPIView(StaffEditorPermissionMixin, generics.UpdateAPIView): class DeviceDestroyAPIView(StaffEditorPermissionMixin, generics.DestroyAPIView): - queryset = Device.objects.all() + queryset = Device.objects.select_related("user").all() serializer_class = DeviceSerializer lookup_field = "pk"