mirror of
https://github.com/i701/sarlink-portal-api.git
synced 2025-04-19 23:46:53 +00:00
All checks were successful
Build and Push Docker Images / Build and Push Docker Images (push) Successful in 2m23s
218 lines
7.6 KiB
Python
218 lines
7.6 KiB
Python
# Create your views here.
|
|
# billing/views.py
|
|
from datetime import timedelta
|
|
from django.utils import timezone
|
|
|
|
import requests
|
|
from decouple import config
|
|
from rest_framework import generics, status
|
|
from rest_framework.response import Response
|
|
|
|
from api.mixins import StaffEditorPermissionMixin
|
|
|
|
from .models import Device, Payment
|
|
from .serializers import PaymentSerializer, UpdatePaymentSerializer
|
|
|
|
|
|
class InsufficientFundsError(Exception):
|
|
pass
|
|
|
|
|
|
class ListCreatePaymentView(StaffEditorPermissionMixin, generics.ListCreateAPIView):
|
|
serializer_class = PaymentSerializer
|
|
queryset = Payment.objects.all().select_related("user")
|
|
|
|
def get_queryset(self):
|
|
queryset = super().get_queryset()
|
|
if self.request.user.is_superuser:
|
|
return queryset
|
|
return queryset.filter(user=self.request.user)
|
|
|
|
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)
|
|
|
|
for device_id in device_ids:
|
|
device = Device.objects.filter(id=device_id, user=user).first()
|
|
print("DEVICE", device)
|
|
if not device:
|
|
return Response(
|
|
{"message": f"Device with id {device_id} not found."},
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
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)
|
|
for device in devices:
|
|
device.has_a_pending_payment = True
|
|
device.save()
|
|
payment.devices.set(devices)
|
|
|
|
serializer = PaymentSerializer(payment)
|
|
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
|
|
|
|
|
class PaymentDetailAPIView(StaffEditorPermissionMixin, generics.RetrieveAPIView):
|
|
queryset = Payment.objects.select_related("user").all()
|
|
serializer_class = PaymentSerializer
|
|
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()
|
|
number_of_months = instance.number_of_months
|
|
device_expire_date = timezone.now() + timedelta(days=30 * number_of_months)
|
|
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=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):
|
|
# TODO: Fix check for success payment
|
|
payment = self.get_object()
|
|
data = request.data
|
|
user = request.user
|
|
print("logged in user", user)
|
|
print("Payment user", payment.user)
|
|
if payment.paid:
|
|
return Response(
|
|
{"message": "Payment has already been verified."},
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
if payment.user != user and not user.is_superuser:
|
|
return Response(
|
|
{"message": "You are not authorized to verify this payment."},
|
|
status=status.HTTP_403_FORBIDDEN,
|
|
)
|
|
method = data.get("method")
|
|
if not method:
|
|
return Response(
|
|
{"message": "method is required. 'WALLET' or 'TRANSFER'"},
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
|
|
devices = payment.devices.all()
|
|
payment_status = False
|
|
if method == "WALLET":
|
|
if user.wallet_balance < payment.amount:
|
|
return Response(
|
|
{"message": "Insufficient funds in wallet."},
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
else:
|
|
payment_status = self.process_wallet_payment(
|
|
user,
|
|
payment,
|
|
)
|
|
if method == "TRANSFER":
|
|
data = {
|
|
"benefName": f"{user.first_name} {user.last_name}",
|
|
"accountNo": user.acc_no,
|
|
"absAmount": payment.amount,
|
|
"time": (timezone.now() + timedelta(minutes=5)).strftime(
|
|
"%Y-%m-%d %H:%M"
|
|
),
|
|
}
|
|
payment_status = self.verify_transfer_payment(data, payment)
|
|
|
|
if payment_status:
|
|
# Update devices
|
|
expiry_date = timezone.now() + timedelta(days=30 * payment.number_of_months)
|
|
devices.update(
|
|
is_active=True, expiry_date=expiry_date, has_a_pending_payment=False
|
|
)
|
|
|
|
return Response(
|
|
{"message": f"Payment verified successfully using [{method}]."}
|
|
)
|
|
else:
|
|
return Response(
|
|
{"message": f"Payment verification FAILED using [{method}]."}
|
|
)
|
|
|
|
def process_wallet_payment(self, user, payment):
|
|
print("processing wallet payment...")
|
|
print(user, payment.amount)
|
|
|
|
payment.paid = True
|
|
payment.paid_at = timezone.now()
|
|
payment.method = "WALLET"
|
|
payment.save()
|
|
|
|
user.wallet_balance -= payment.amount
|
|
user.save()
|
|
return True
|
|
|
|
def verify_transfer_payment(self, data, payment):
|
|
print("verifying transfer payment...")
|
|
response = requests.post(
|
|
f"{config('PAYMENT_VERIFY_BASE_URL')}/verify-payment",
|
|
json=data,
|
|
headers={"Content-Type": "application/json"},
|
|
)
|
|
response.raise_for_status()
|
|
mib_resp = response.json()
|
|
if not response.json().get("success"):
|
|
return mib_resp["success"]
|
|
else:
|
|
return True
|
|
|
|
|
|
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)
|