from django.contrib import messages from django.contrib.auth.decorators import login_required from django.db.models import Q from django.urls import reverse from django.utils.decorators import method_decorator from django.views.generic import DetailView, ListView, UpdateView from oauth2_provider.contrib.rest_framework import TokenHasScope, IsAuthenticatedOrTokenHasScope from rest_framework import generics, permissions from rest_framework.response import Response from apps.gooyal_oauth2.rest_framework import IsAuthenticatedOrTokenMatchesOASRequirements from apps.wallet.models import Transaction from apps.wallet.serializers import TransactionSerializer, DepositSerializer, WithdrawSerializer from .constans import STATE_CHOICES from .forms import TransactionActionForm from django.utils.translation import gettext_lazy as _ def get_application(request): try: application = request.auth.application except: application = None return application # TODO: this is user invoice create view # class TransactionList(generics.ListCreateAPIView): # permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements] # serializer_class = TransactionSerializer # required_alternate_scopes = { # "GET": [['wallet.transaction:list']], # "POST": [['wallet.invoice:create']], # } # # def get_queryset(self): # user = self.request.user # return Transaction.objects.filter(Q(payee=user) | Q(payer=user)).all() # # def perform_create(self, serializer): # user = self.request.user # serializer.save(payee=user, application=get_application(self.request)) # this is application create invoice view class TransactionList(generics.ListCreateAPIView): permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements] serializer_class = TransactionSerializer required_alternate_scopes = { "GET": [['wallet.transaction:list']], "POST": [['wallet.invoice:create']], } def get_queryset(self): user = self.request.user return Transaction.objects.filter(Q(payee=user) | Q(payer=user)).all() def perform_create(self, serializer): payer = self.request.user payee = self.request.auth.application.user serializer.save(payer=payer, payee=payee, application=get_application(self.request)) class TransactionDetail(generics.RetrieveAPIView): permission_classes = [permissions.IsAuthenticated, IsAuthenticatedOrTokenHasScope] serializer_class = TransactionSerializer lookup_field = 'uuid' required_scopes = ['wallet.transaction:retrieve'] def get_queryset(self): user = self.request.user return Transaction.objects.filter(Q(payee=user) | Q(payer=user) | Q(payer__isnull=True)).all() class TransactionPay(generics.RetrieveAPIView): permission_classes = [permissions.IsAuthenticated, IsAuthenticatedOrTokenHasScope] serializer_class = TransactionSerializer lookup_field = 'uuid' required_scopes = ['wallet.invoice:pay'] def get_queryset(self): user = self.request.user return Transaction.objects.filter(Q(payer=user) | Q(payer__isnull=True)).all() def retrieve(self, request, *args, **kwargs): instance = self.get_object() instance.pay(payer=self.request.user) serializer = self.get_serializer(instance) return Response(serializer.data) class TransactionReceipt(generics.RetrieveAPIView): permission_classes = [permissions.IsAuthenticated, IsAuthenticatedOrTokenHasScope] serializer_class = TransactionSerializer lookup_field = 'uuid' required_scopes = ['wallet.invoice:receipt'] def get_queryset(self): user = self.request.user return Transaction.objects.filter(payer=user).all() def retrieve(self, request, *args, **kwargs): instance = self.get_object() instance.receipt() serializer = self.get_serializer(instance) return Response(serializer.data) class DepositSubmit(generics.CreateAPIView): permission_classes = [TokenHasScope] serializer_class = DepositSerializer required_scopes = ['wallet.deposit:submit'] def get_queryset(self): application = get_application(self.request) return Transaction.objects.filter(application=application).all() def perform_create(self, serializer): payer = self.request.auth.application.user serializer.save(payer=payer, application=get_application(self.request)) class DepositVerify(generics.RetrieveAPIView): permission_classes = [TokenHasScope] serializer_class = DepositSerializer lookup_field = 'uuid' required_scopes = ['wallet.deposit:verify'] def get_queryset(self): application = get_application(self.request) return Transaction.objects.filter(application=application).all() def retrieve(self, request, *args, **kwargs): instance = self.get_object() if instance.state == STATE_CHOICES.pending: instance.verify() serializer = self.get_serializer(instance) return Response(serializer.data) class WithdrawSubmit(generics.CreateAPIView): permission_classes = [TokenHasScope] serializer_class = WithdrawSerializer required_scopes = ['wallet.withdraw:submit'] def get_queryset(self): application = get_application(self.request) return Transaction.objects.filter(application=application).all() def perform_create(self, serializer): payee = self.request.auth.application.user serializer.save(payee=payee, application=get_application(self.request)) class WithdrawVerify(generics.RetrieveAPIView): permission_classes = [TokenHasScope] serializer_class = WithdrawSerializer lookup_field = 'uuid' required_scopes = ['wallet.withdraw:verify'] def get_queryset(self): application = get_application(self.request) return Transaction.objects.filter(application=application).all() def retrieve(self, request, *args, **kwargs): instance = self.get_object() if instance.state == STATE_CHOICES.pending: instance.verify() serializer = self.get_serializer(instance) return Response(serializer.data) @method_decorator(login_required, name='dispatch') class TransactionListView(ListView): model = Transaction template_name = 'wallet/transaction_list.html' def get_queryset(self): user = self.request.user return Transaction.objects.filter(Q(payee=user) | Q(payer=user)).all() @method_decorator(login_required, name='dispatch') class TransactionDetailView(UpdateView): model = Transaction form_class = TransactionActionForm template_name = 'wallet/transaction_detail.html' def get_queryset(self): user = self.request.user return Transaction.objects.filter(Q(payee=user) | Q(payer=user) | Q(payer__isnull=True)).all() def get_success_url(self): return reverse('wallet:transaction_detail', kwargs={'pk': self.get_object().pk}) def form_valid(self, form): transaction: Transaction = form.instance if 'pay' in self.request.POST: result = transaction.pay(payer=self.request.user) messages.error(self.request, _('success.')) if 'receipt' in self.request.POST: result = transaction.receipt() messages.error(self.request, _('success.')) return super().form_valid(form)