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.", )