mirror of
https://github.com/i701/sarlink-portal-api.git
synced 2025-06-28 09:50:05 +00:00
Add wallet balance to User model and implement Atoll/Island management
- Added `wallet_balance` field to the User model. - Updated UserAdmin to include `wallet_balance` in the admin interface. - Created serializers and views for Atoll and Island management. - Implemented endpoints for listing, creating, and updating Atolls and Islands. - Enhanced payment processing with UUIDs for Payment and Topup models. - Added migration files for new fields and constraints. - Improved error handling and validation in various views. - Updated email templates for better responsiveness and SEO.
This commit is contained in:
141
billing/views.py
141
billing/views.py
@ -1,2 +1,141 @@
|
||||
|
||||
# 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.")
|
||||
|
Reference in New Issue
Block a user