From 95954765692ecbca97a281c05e1494c7a25d3b3f Mon Sep 17 00:00:00 2001 From: i701 Date: Tue, 8 Apr 2025 21:38:43 +0500 Subject: [PATCH] Refactor UpdatePaymentSerializer to include only number_of_months field, add DeletePaymentView for payment deletion, and enhance VerifyPaymentView with payment_id lookup. Introduce pending_payment_id field in DeviceSerializer to track unpaid payments. --- billing/serializers.py | 9 +++------ billing/urls.py | 10 +++++++++- billing/views.py | 37 ++++++++++++++++++++++++++++--------- devices/serializers.py | 12 ++++++++++++ 4 files changed, 52 insertions(+), 16 deletions(-) diff --git a/billing/serializers.py b/billing/serializers.py index ba81c7b..4f8559c 100644 --- a/billing/serializers.py +++ b/billing/serializers.py @@ -14,9 +14,6 @@ class PaymentSerializer(serializers.ModelSerializer): class UpdatePaymentSerializer(serializers.ModelSerializer): class Meta: model = Payment - fields = ["paid", "paid_at", "method", "number_of_months"] - - 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) - number_of_months = serializers.IntegerField(required=True, allow_null=True) + fields = [ + "number_of_months", + ] diff --git a/billing/urls.py b/billing/urls.py index 3281633..d6238eb 100644 --- a/billing/urls.py +++ b/billing/urls.py @@ -5,6 +5,7 @@ from .views import ( VerifyPaymentView, PaymentDetailAPIView, UpdatePaymentAPIView, + DeletePaymentView, ) urlpatterns = [ @@ -15,5 +16,12 @@ urlpatterns = [ UpdatePaymentAPIView.as_view(), name="update-payment", ), - path("verify-payment/", VerifyPaymentView.as_view(), name="verify-payment"), + path( + "payment//delete/", + DeletePaymentView.as_view(), + name="delete-payment", + ), + path( + "payment//verify/", VerifyPaymentView.as_view(), name="verify-payment" + ), ] diff --git a/billing/views.py b/billing/views.py index 4a96573..5fc9842 100644 --- a/billing/views.py +++ b/billing/views.py @@ -92,21 +92,22 @@ class UpdatePaymentAPIView(StaffEditorPermissionMixin, generics.UpdateAPIView): 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=device_expire_date) + devices.update( + is_active=True, expiry_date=device_expire_date, has_a_pending_payment=False + ) return Response(serializer.data) class VerifyPaymentView(StaffEditorPermissionMixin, generics.UpdateAPIView): serializer_class = PaymentSerializer queryset = Payment.objects.all() + lookup_field = "pk" def update(self, request, *args, **kwargs): data = request.data user = request.user - print(user) method = data.get("method") - payment_id = data.get("payment_id") - abs_amount = data.get("abs_amount") + payment_id = kwargs.get("pk") if not method: return Response( {"message": "method is required. 'WALLET' or 'TRANSFER'"}, @@ -117,11 +118,6 @@ class VerifyPaymentView(StaffEditorPermissionMixin, generics.UpdateAPIView): {"message": "payment_id is required."}, status=status.HTTP_400_BAD_REQUEST, ) - if not abs_amount: - return Response( - {"message": "abs_amount is required."}, - status=status.HTTP_400_BAD_REQUEST, - ) try: payment = Payment.objects.get(id=payment_id) @@ -182,3 +178,26 @@ class VerifyPaymentView(StaffEditorPermissionMixin, generics.UpdateAPIView): print(response.json()) if not response.json().get("success"): raise Exception("Payment verification failed.") + + +class DeletePaymentView(StaffEditorPermissionMixin, generics.DestroyAPIView): + queryset = Payment.objects.all() + serializer_class = PaymentSerializer + lookup_field = "pk" + + def delete(self, request, *args, **kwargs): + instance = self.get_object() + user = request.user + if instance.user != user and not user.is_superuser: + return Response( + {"message": "You are not authorized to delete this payment."}, + status=status.HTTP_403_FORBIDDEN, + ) + if instance.paid: + return Response( + {"message": "Paid payments cannot be deleted."}, + status=status.HTTP_400_BAD_REQUEST, + ) + devices = instance.devices.all() + devices.update(is_active=False, expiry_date=None, has_a_pending_payment=False) + return super().delete(request, *args, **kwargs) diff --git a/devices/serializers.py b/devices/serializers.py index 3be26a1..7fec72e 100644 --- a/devices/serializers.py +++ b/devices/serializers.py @@ -1,6 +1,7 @@ from rest_framework import serializers from .models import Device from api.serializers import CustomReadOnlyUserSerializer +from billing.models import Payment # Import the Payment model class CreateDeviceSerializer(serializers.ModelSerializer): @@ -32,10 +33,21 @@ class BlockDeviceSerializer(serializers.ModelSerializer): class DeviceSerializer(serializers.ModelSerializer): + pending_payment_id = serializers.SerializerMethodField() + class Meta: model = Device fields = "__all__" + def get_pending_payment_id(self, obj): + # Query the last unpaid payment for the device + unpaid_payment = ( + Payment.objects.filter(devices=obj, paid=False) + .order_by("-created_at") + .first() + ) + return unpaid_payment.id if unpaid_payment else None + class ReadOnlyDeviceSerializer(serializers.ModelSerializer): user = CustomReadOnlyUserSerializer(read_only=True)