282 lines
9.9 KiB
Python
Executable file
282 lines
9.9 KiB
Python
Executable file
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 django_filters.rest_framework import DjangoFilterBackend
|
|
|
|
from oauth2_provider.contrib.rest_framework import TokenHasScope, IsAuthenticatedOrTokenHasScope
|
|
from rest_framework import generics, permissions
|
|
from rest_framework.generics import get_object_or_404
|
|
from rest_framework.permissions import AllowAny
|
|
from rest_framework.response import Response
|
|
|
|
from apps.gooyal_oauth2.rest_framework import IsAuthenticatedOrTokenMatchesOASRequirements
|
|
from apps.wallet.models import Transaction, Category, Wallet
|
|
from apps.wallet.serializers import UserTransactionSerializer, DepositSerializer, WithdrawSerializer, \
|
|
MyWalletSerializer
|
|
from ..constans import StateChoices, TypeChoices
|
|
from ..filters import UserTransactionFilter
|
|
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
|
|
|
|
|
|
class MyWalletBalanceView(generics.RetrieveAPIView):
|
|
'''
|
|
API for getting authenticated user balance.
|
|
'''
|
|
permission_classes = [IsAuthenticatedOrTokenHasScope]
|
|
serializer_class = MyWalletSerializer
|
|
required_scopes = ['wallet.wallet:get_balance']
|
|
|
|
def get_object(self):
|
|
return self.request.user
|
|
|
|
|
|
# this is application create invoice view
|
|
class TransactionList(generics.ListAPIView):
|
|
'''
|
|
GET: API for getting list of transactions for authenticated user
|
|
POST: API for creating transaction for transferring funds from authenticated user to application owner. (deprecated)
|
|
args:
|
|
- user: authenticated user
|
|
|
|
'''
|
|
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
|
|
serializer_class = UserTransactionSerializer
|
|
required_alternate_scopes = {
|
|
"GET": [['wallet.user:transaction_list']],
|
|
# "POST": [['wallet.invoice:create']],
|
|
}
|
|
|
|
filter_backends = (DjangoFilterBackend,)
|
|
filterset_class = UserTransactionFilter
|
|
|
|
def get_queryset(self):
|
|
user = self.request.user
|
|
return Transaction.objects.filter(Q(payee_id=user.pk, payee_type=TypeChoices.USER.value) | Q(payer_id=user.pk, payer_type=TypeChoices.USER.value)).all()
|
|
|
|
|
|
# TODO:
|
|
# def perform_create(self, serializer):
|
|
# payer = self.request.user
|
|
# payee = self.request.auth.application_owner
|
|
# serializer.save(payer_id=payer.pk, payee=payee, application=get_application(self.request))
|
|
|
|
|
|
class TransactionDetail(generics.RetrieveAPIView):
|
|
permission_classes = [permissions.IsAuthenticated, IsAuthenticatedOrTokenHasScope]
|
|
serializer_class = UserTransactionSerializer
|
|
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 = UserTransactionSerializer
|
|
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 = UserTransactionSerializer
|
|
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 == StateChoices.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 == StateChoices.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
|
|
qs = super().get_queryset()
|
|
return qs.filter(Q(payee_id=user.pk) | Q(payer_id=user.pk)).all()
|
|
|
|
|
|
@method_decorator(login_required, name='dispatch')
|
|
class TransactionDetailView(UpdateView):
|
|
model = Transaction
|
|
form_class = TransactionActionForm
|
|
template_name = 'wallet/transaction_detail.html'
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context_data = super().get_context_data(**kwargs)
|
|
context_data['StateChoices'] = StateChoices
|
|
return context_data
|
|
|
|
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)
|
|
|
|
|
|
|
|
class CategoryMyWalletBalanceView(generics.RetrieveAPIView):
|
|
'''
|
|
API for getting authenticated user balance.
|
|
'''
|
|
permission_classes = [IsAuthenticatedOrTokenHasScope]
|
|
serializer_class = MyWalletSerializer
|
|
required_scopes = ['wallet.wallet:get_balance']
|
|
|
|
def get_object(self):
|
|
user = self.request.user
|
|
category_uuid = self.kwargs.get('category_uuid')
|
|
if category_uuid:
|
|
category = get_object_or_404(Category.objects.all(), uuid=category_uuid)
|
|
else:
|
|
category = None
|
|
|
|
wallet, created = Wallet.objects.get_or_create(owner_uuid=user.uuid, owner_type=TypeChoices.USER,
|
|
category=category)
|
|
return wallet
|
|
|
|
|
|
# this is application create invoice view
|
|
class CategoryTransactionListView(generics.ListAPIView):
|
|
'''
|
|
GET: API for getting list of transactions for authenticated user
|
|
POST: API for creating transaction for transferring funds from authenticated user to application owner. (deprecated)
|
|
args:
|
|
- user: authenticated user
|
|
|
|
'''
|
|
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
|
|
serializer_class = UserTransactionSerializer
|
|
required_alternate_scopes = {
|
|
"GET": [['wallet.user:transaction_list']],
|
|
# "POST": [['wallet.invoice:create']],
|
|
}
|
|
|
|
filter_backends = (DjangoFilterBackend,)
|
|
filterset_class = UserTransactionFilter
|
|
|
|
def get_queryset(self):
|
|
user = self.request.user
|
|
category_uuid = self.kwargs.get('category_uuid')
|
|
if category_uuid:
|
|
category = get_object_or_404(Category.objects.all(), uuid=category_uuid)
|
|
else:
|
|
category = None
|
|
|
|
wallet, created = Wallet.objects.get_or_create(owner_uuid=user.uuid, owner_type=TypeChoices.USER,
|
|
category=category)
|
|
|
|
return Transaction.objects.filter(Q(payee_wallet=wallet) |
|
|
Q(payer_wallet=wallet)).all()
|
|
|