Files
goodtimes/manage_referrals/api/views.py
2024-06-07 20:34:45 +05:30

196 lines
6.8 KiB
Python

from rest_framework import status
from rest_framework.views import APIView
from django.conf import settings
from manage_referrals.models import ReferralCode, ReferralRecord, ReferralRecordReward
from django.shortcuts import get_object_or_404
from goodtimes import constants
from django.db import transaction
from goodtimes.utils import ApiResponse
from manage_wallets.models import WithdrawalRequest
from .serializers import (
ReferralCodeSerializer,
ReferralRecordRewardSerializer,
ReferralRecordSerializer,
)
from rest_framework.permissions import IsAuthenticated
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework.response import Response
class ReferralCodeViews(APIView):
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
model = ReferralCode
serializer = ReferralCodeSerializer
def get(self, request, *args, **kwargs):
referral_obj = self.model.filter_referral_code(principal=request.user)
serializer_obj = self.serializer(referral_obj, many=True)
success_message = {
"status": status.HTTP_200_OK,
"message": constants.SUCCESS,
"data": serializer_obj.data,
}
return ApiResponse.success(**success_message)
class ReferralRecordViews(APIView):
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
model = ReferralRecord
serializer = ReferralRecordSerializer
def get(self, request, *args, **kwargs):
referral_obj = self.model.filter_invite_records(referrer_principal=request.user)
serializer_obj = self.serializer(referral_obj, many=True)
success_message = {
"status": status.HTTP_200_OK,
"message": constants.SUCCESS,
"data": {"count": referral_obj.count(), "record": serializer_obj.data},
}
return ApiResponse.success(**success_message)
class RewardListView(APIView):
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
model = ReferralRecordReward
serializer = ReferralRecordRewardSerializer
def get(self, request):
# Filter rewards based on specified conditions
current_principal = (
request.user
) # Adjust based on how user is linked to principal
# Filter rewards based on the authenticated referrer
rewards_query = ReferralRecordReward.objects.filter(
referral_record__referrer_principal=current_principal,
sell=False,
deleted=False,
active=True,
)
# Serialize the results
rewards_serializer = ReferralRecordRewardSerializer(rewards_query, many=True)
# Get the count of unredeemed rewards
unredeemed_count = rewards_query.count()
success_message = {
"status": status.HTTP_200_OK,
"message": constants.SUCCESS,
"data": {
"reward_count": unredeemed_count,
"rewards": rewards_serializer.data,
},
}
return ApiResponse.success(**success_message)
class RedeemRewardView(APIView):
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
def patch(self, request, unique_token):
# Retrieve the reward using the unique token
try:
reward = ReferralRecordReward.objects.get(
unique_token=unique_token, sell=False
)
except ReferralRecordReward.DoesNotExist:
return ApiResponse.error(
status=status.HTTP_404_NOT_FOUND,
message=constants.FAILURE,
errors="No unsold token found.",
)
# Check if a withdrawal request already exists for this token
if WithdrawalRequest.objects.filter(token=unique_token).exists():
return ApiResponse.error(
status=status.HTTP_400_BAD_REQUEST,
message=constants.FAILURE,
errors="A withdrawal request for this token already exists.",
)
with transaction.atomic():
# Create a new withdrawal request
WithdrawalRequest.objects.create(
principal=request.user, token=unique_token, coins=1, amount=reward.value
)
# Update reward to mark it as sold
reward.sell = True
reward.save()
return ApiResponse.success(
status=status.HTTP_200_OK,
message=constants.SUCCESS,
data="Token sold successfully.",
)
class RedeemSelectedRewardsView(APIView):
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
def patch(self, request):
# Extract the number of tokens from the request data
num_tokens_to_sell = request.data.get("num_tokens", None)
if num_tokens_to_sell is None:
return ApiResponse.error(
status=status.HTTP_400_BAD_REQUEST,
message=constants.FAILURE,
errors="Number of tokens to sell is required.",
)
try:
num_tokens_to_sell = int(num_tokens_to_sell)
except ValueError:
return ApiResponse.error(
status=status.HTTP_400_BAD_REQUEST,
message=constants.FAILURE,
errors="Invalid number of tokens.",
)
# Retrieve the rewards for the authenticated user
rewards = ReferralRecordReward.objects.filter(
referral_record__referrer_principal=request.user, sell=False
).order_by(
"id"
) # FIFO method
if rewards.count() < num_tokens_to_sell:
return ApiResponse.error(
status=status.HTTP_404_NOT_FOUND,
message=constants.FAILURE,
errors="Not enough unsold rewards available.",
)
# Select the required number of rewards
rewards_to_sell = rewards[:num_tokens_to_sell]
total_value = sum(reward.value for reward in rewards_to_sell)
total_coins = sum(reward.coins for reward in rewards_to_sell)
tokens = ",".join(str(reward.unique_token) for reward in rewards_to_sell)
with transaction.atomic():
# Create a new withdrawal request
withdrawal_request = WithdrawalRequest.objects.create(
principal=request.user,
coins=total_coins,
amount=total_value,
token=tokens,
)
# Update each reward to mark it as sold
for reward in rewards_to_sell:
reward.sell = True
reward.save()
return ApiResponse.success(
status=status.HTTP_200_OK,
message=constants.SUCCESS,
data="Selected tokens sold successfully.",
)