From b87dcfaf268d556feecd81d681198ff2c1200788 Mon Sep 17 00:00:00 2001 From: i701 Date: Sat, 5 Apr 2025 20:53:06 +0500 Subject: [PATCH] Add UpdateUserWalletView and CustomUserByWalletBalanceSerializer for wallet balance updates --- api/serializers.py | 9 +++++++++ api/urls.py | 4 ++++ api/views.py | 25 ++++++++++++++++++++++++- billing/serializers.py | 14 ++++++++++++++ billing/urls.py | 12 +++++++++++- billing/views.py | 17 ++++++++++++++++- devices/serializers.py | 8 ++++++-- pyrightconfig.json | 22 +++++++++++----------- 8 files changed, 95 insertions(+), 16 deletions(-) diff --git a/api/serializers.py b/api/serializers.py index 4e4459b..ab40653 100644 --- a/api/serializers.py +++ b/api/serializers.py @@ -73,6 +73,15 @@ class CustomReadOnlyUserByIDCardSerializer(serializers.ModelSerializer): fields = ("id_card",) +class CustomUserByWalletBalanceSerializer(serializers.ModelSerializer): + """serializer for the user object""" + + class Meta: # type: ignore + model = User + # fields = "__all__" + fields = ("wallet_balance",) + + class UserSerializer(serializers.ModelSerializer): """serializer for the user object""" diff --git a/api/urls.py b/api/urls.py index 2e04e20..9e7f755 100644 --- a/api/urls.py +++ b/api/urls.py @@ -17,6 +17,7 @@ from .views import ( ListCreateIslandView, RetrieveUpdateDestroyIslandView, filter_user, + UpdateUserWalletView, ) @@ -29,6 +30,9 @@ urlpatterns = [ path("tokens/", KnoxTokenListApiView.as_view(), name="knox_tokens"), # path("auth/", CustomAuthToken.as_view()), path("users/", ListUserView.as_view(), name="users"), + path( + "update-wallet//", UpdateUserWalletView.as_view(), name="update-wallet" + ), path("users//", UserDetailAPIView.as_view(), name="user-detail"), path("users/filter/", filter_user, name="filter-users"), path("healthcheck/", healthcheck, name="healthcheck"), diff --git a/api/views.py b/api/views.py index 1525695..31a6e7f 100644 --- a/api/views.py +++ b/api/views.py @@ -11,7 +11,11 @@ from rest_framework.response import Response from rest_framework import status from rest_framework.exceptions import ValidationError from rest_framework.decorators import api_view, permission_classes -from api.serializers import AtollSerializer, IslandSerializer +from api.serializers import ( + AtollSerializer, + IslandSerializer, + CustomUserByWalletBalanceSerializer, +) # knox imports from knox.views import LoginView as KnoxLoginView @@ -44,6 +48,25 @@ class ErrorMessages: INVALID_ACCOUNT = "Please enter a valid account number." +class UpdateUserWalletView(generics.UpdateAPIView): + # Create user API view + serializer_class = CustomUserByWalletBalanceSerializer + permission_classes = (permissions.IsAuthenticated,) + queryset = User.objects.all() + + def update(self, request, *args, **kwargs): + wallet_balance = request.data.get("wallet_balance") + if not wallet_balance: + return Response( + {"message": "wallet_balance is required."}, + status=status.HTTP_400_BAD_REQUEST, + ) + user = self.get_object() + user.wallet_balance = wallet_balance + user.save() + return Response({"message": "Wallet balance updated successfully."}) + + class CreateUserView(generics.CreateAPIView): # Create user API view serializer_class = UserSerializer diff --git a/billing/serializers.py b/billing/serializers.py index efb5aa9..78ca861 100644 --- a/billing/serializers.py +++ b/billing/serializers.py @@ -9,3 +9,17 @@ class PaymentSerializer(serializers.ModelSerializer): class Meta: model = Payment fields = "__all__" + + +class UpdatePaymentSerializer(serializers.ModelSerializer): + class Meta: + model = Payment + fields = [ + "paid", + "paid_at", + "method", + ] + + paid = serializers.BooleanField(required=True, allow_null=True) + paid_at = serializers.DateTimeField(required=True, allow_null=True) + method = serializers.ChoiceField(choices=Payment.PAYMENT_TYPES, required=True) diff --git a/billing/urls.py b/billing/urls.py index dd12115..3281633 100644 --- a/billing/urls.py +++ b/billing/urls.py @@ -1,9 +1,19 @@ # billing/urls.py from django.urls import path -from .views import ListCreatePaymentView, VerifyPaymentView, PaymentDetailAPIView +from .views import ( + ListCreatePaymentView, + VerifyPaymentView, + PaymentDetailAPIView, + UpdatePaymentAPIView, +) urlpatterns = [ path("payment/", ListCreatePaymentView.as_view(), name="create-payment"), path("payment//", PaymentDetailAPIView.as_view(), name="retrieve-payment"), + path( + "payment//update/", + UpdatePaymentAPIView.as_view(), + name="update-payment", + ), path("verify-payment/", VerifyPaymentView.as_view(), name="verify-payment"), ] diff --git a/billing/views.py b/billing/views.py index 00a5676..5465bed 100644 --- a/billing/views.py +++ b/billing/views.py @@ -10,7 +10,7 @@ from rest_framework.response import Response from api.mixins import StaffEditorPermissionMixin from .models import Device, Payment -from .serializers import PaymentSerializer +from .serializers import PaymentSerializer, UpdatePaymentSerializer class InsufficientFundsError(Exception): @@ -75,6 +75,21 @@ class PaymentDetailAPIView(StaffEditorPermissionMixin, generics.RetrieveAPIView) lookup_field = "pk" +class UpdatePaymentAPIView(StaffEditorPermissionMixin, generics.UpdateAPIView): + queryset = Payment.objects.select_related("user").all() + serializer_class = UpdatePaymentSerializer + lookup_field = "pk" + + def update(self, request, *args, **kwargs): + instance = self.get_object() + devices = instance.devices.all() + serializer = self.get_serializer(instance, data=request.data, partial=False) + serializer.is_valid(raise_exception=True) + self.perform_update(serializer) + devices.update(is_active=True, expiry_date=instance.expires_at) + return Response(serializer.data) + + class VerifyPaymentView(StaffEditorPermissionMixin, generics.UpdateAPIView): serializer_class = PaymentSerializer queryset = Payment.objects.all() diff --git a/devices/serializers.py b/devices/serializers.py index 5ac5df6..b153dbc 100644 --- a/devices/serializers.py +++ b/devices/serializers.py @@ -1,11 +1,14 @@ from rest_framework import serializers from .models import Device from api.serializers import CustomReadOnlyUserSerializer + + class CreateDeviceSerializer(serializers.ModelSerializer): class Meta: model = Device fields = ["name", "mac"] + class DeviceSerializer(serializers.ModelSerializer): class Meta: model = Device @@ -14,7 +17,8 @@ class DeviceSerializer(serializers.ModelSerializer): class ReadOnlyDeviceSerializer(serializers.ModelSerializer): user = CustomReadOnlyUserSerializer(read_only=True) - class Meta: #type: ignore + + class Meta: # type: ignore depth = 2 model = Device - fields = "__all__" \ No newline at end of file + fields = "__all__" diff --git a/pyrightconfig.json b/pyrightconfig.json index 6ec5486..ce02071 100644 --- a/pyrightconfig.json +++ b/pyrightconfig.json @@ -1,13 +1,13 @@ { - "venvPath": ".", - "venv": ".venv", - "reportMissingImports": "error", - "include": ["src"], - - "exclude": [ - "council-api/**/migrations", - "**/__pycache__", - "src/experimental", - "src/typestubs" - ] + "venvPath": ".", + "venv": ".venv", + "reportMissingImports": "error", + "include": ["src"], + "typeCheckingMode": "off", + "exclude": [ + "council-api/**/migrations", + "**/__pycache__", + "src/experimental", + "src/typestubs" + ] }