# Create your views here. # billing/views.py from .models import Payment, Device from datetime import datetime, timedelta import requests from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from decouple import config from .serializers import PaymentSerializer from rest_framework.permissions import AllowAny from api.mixins import StaffEditorPermissionMixin from rest_framework import generics class InsufficientFundsError(Exception): pass class CreatePaymentView(StaffEditorPermissionMixin, generics.CreateAPIView): serializer_class = PaymentSerializer queryset = Payment.objects.all() def create(self, request): data = request.data user = request.user amount = data.get("amount") number_of_months = data.get("number_of_months") device_ids = data.get("device_ids", []) print(amount, number_of_months, device_ids) if not amount or not number_of_months: return Response( {"message": "amount and number_of_months are required."}, status=status.HTTP_400_BAD_REQUEST, ) if not device_ids: return Response( {"message": "device_ids are required."}, status=status.HTTP_400_BAD_REQUEST, ) # Create payment payment = Payment.objects.create( amount=amount, number_of_months=number_of_months, paid=data.get("paid", False), user=user, ) # Connect devices to payment devices = Device.objects.filter(id__in=device_ids, user=user) payment.devices.set(devices) serializer = PaymentSerializer(payment) return Response(serializer.data, status=status.HTTP_201_CREATED) class VerifyPaymentView(StaffEditorPermissionMixin, generics.UpdateAPIView): serializer_class = PaymentSerializer queryset = Payment.objects.all() 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") if not method: return Response( {"message": "method is required. 'WALLET' or 'TRANSFER'"}, status=status.HTTP_400_BAD_REQUEST, ) if not payment_id: return Response( {"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) devices = payment.devices.all() if data["type"] == "WALLET": print("processing WALLET payment") self.process_wallet_payment(user, payment, float(data["abs_amount"])) elif data["type"] == "TRANSFER": self.verify_external_payment(data, payment) # Update devices expiry_date = datetime.now() + timedelta(days=30 * payment.number_of_months) devices.update(is_active=True, expiry_date=expiry_date) return Response({"message": "Payment verified successfully."}) except Payment.DoesNotExist: return Response( {"message": "Payment not found."}, status=status.HTTP_404_NOT_FOUND ) except InsufficientFundsError: return Response( {"message": "Insufficient funds in wallet."}, status=status.HTTP_400_BAD_REQUEST, ) except Exception as e: return Response( {"message": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR ) def process_wallet_payment(self, user, payment, amount): print("processing wallet payment") print(user, amount) if user.wallet_balance < amount: return Response( {"message": "Insufficient funds in wallet."}, status=status.HTTP_400_BAD_REQUEST, ) payment.paid = True payment.paid_at = datetime.now() payment.method = "WALLET" payment.save() user.wallet_balance -= amount user.save() def verify_external_payment(self, data, payment): response = requests.post( f"{config('PAYMENT_VERIFY_BASE_URL')}/verify-payment", json=data, headers={"Content-Type": "application/json"}, ) response.raise_for_status() print(response.json()) if not response.json().get("success"): raise Exception("Payment verification failed.")