373 lines
16 KiB
Python
Executable file
373 lines
16 KiB
Python
Executable file
from django.db.models import Q
|
|
from oauth2_provider.contrib.rest_framework import TokenHasScope, IsAuthenticatedOrTokenHasScope
|
|
from rest_framework import generics, permissions, mixins
|
|
from rest_framework.exceptions import APIException
|
|
from rest_framework.generics import get_object_or_404
|
|
from rest_framework.request import Request
|
|
from rest_framework.response import Response
|
|
|
|
from apps.users.models import User
|
|
from apps.wallet.constans import TypeChoices, StateChoices
|
|
from apps.wallet.models import Transaction, Category, Wallet
|
|
from apps.wallet.serializers import ApplicationDepositSerializer, ApplicationWithdrawSerializer, \
|
|
ApplicationTransactionSerializer, ApplicationBalanceSerializer, MyWalletSerializer
|
|
|
|
|
|
def get_application(request):
|
|
try:
|
|
application = request.auth.application
|
|
except:
|
|
application = None
|
|
return application
|
|
|
|
|
|
def get_wallet_category(request: Request):
|
|
pass
|
|
|
|
|
|
class BalanceAPIView(generics.RetrieveAPIView):
|
|
'''
|
|
API for getting specified user or application balance.
|
|
'''
|
|
permission_classes = [TokenHasScope]
|
|
serializer_class = ApplicationBalanceSerializer
|
|
required_scopes = ['wallet.application:get_balance']
|
|
|
|
def get_object(self):
|
|
return get_application(self.request)
|
|
|
|
|
|
class UserBalanceAPIView(generics.RetrieveAPIView):
|
|
'''
|
|
API for getting specified user or application balance.
|
|
'''
|
|
permission_classes = [IsAuthenticatedOrTokenHasScope]
|
|
serializer_class = MyWalletSerializer
|
|
required_scopes = ['wallet.application:get_user_balance']
|
|
|
|
def get_object(self):
|
|
user_uuid = self.kwargs.get('uuid')
|
|
user, created = User.objects.get_or_create(uuid=user_uuid)
|
|
# user = get_object_or_404(User.objects.all(), uuid=user_uuid)
|
|
|
|
return user
|
|
|
|
|
|
class TransactionDetailAPIView(generics.RetrieveAPIView):
|
|
permission_classes = [TokenHasScope]
|
|
serializer_class = ApplicationTransactionSerializer
|
|
lookup_field = 'uuid'
|
|
required_scopes = ['wallet.application:get_transaction_detail']
|
|
|
|
def get_queryset(self):
|
|
application = get_application(self.request)
|
|
return Transaction.objects.filter(Q(application=application) |
|
|
Q(payer_id=application.pk, payer_type=TypeChoices.APPLICATION.value) |
|
|
Q(payee_id=application.pk, payee_type=TypeChoices.APPLICATION.value)
|
|
).all()
|
|
|
|
|
|
class TransactionListAPIView(generics.ListAPIView):
|
|
permission_classes = [TokenHasScope]
|
|
serializer_class = ApplicationTransactionSerializer
|
|
lookup_field = 'uuid'
|
|
required_scopes = ['wallet.application:get_transaction_list']
|
|
|
|
def get_queryset(self):
|
|
application = get_application(self.request)
|
|
return Transaction.objects.filter(Q(application=application) |
|
|
Q(payer_id=application.pk, payer_type=TypeChoices.APPLICATION.value) |
|
|
Q(payee_id=application.pk, payee_type=TypeChoices.APPLICATION.value)
|
|
).all()
|
|
|
|
|
|
# from application to another entity
|
|
# TODO: better name
|
|
class DepositSubmitAPIView(generics.CreateAPIView):
|
|
permission_classes = [IsAuthenticatedOrTokenHasScope]
|
|
serializer_class = ApplicationDepositSerializer
|
|
required_scopes = ['wallet.application.deposit:submit']
|
|
|
|
def get_queryset(self):
|
|
application = get_application(self.request)
|
|
return Transaction.objects.filter(application=application,
|
|
payer_id=application.pk,
|
|
payer_type=TypeChoices.APPLICATION.value).all()
|
|
|
|
def perform_create(self, serializer):
|
|
# TODO: get_or_create instead of create if uuid given
|
|
# TODO: it is possible to merage create and submit in one step for improve performance
|
|
application = get_application(self.request)
|
|
instance = serializer.save(payer_id=application.pk,
|
|
payer_type=TypeChoices.APPLICATION.value,
|
|
application=application)
|
|
try:
|
|
instance.submit()
|
|
except Exception as e:
|
|
print(e)
|
|
APIException('Failed to submit deposit')
|
|
|
|
|
|
class DepositVerifyAPIView(generics.RetrieveAPIView):
|
|
permission_classes = [IsAuthenticatedOrTokenHasScope]
|
|
serializer_class = ApplicationDepositSerializer
|
|
lookup_field = 'uuid'
|
|
required_scopes = ['wallet.application.deposit:verify']
|
|
|
|
def get_queryset(self):
|
|
application = get_application(self.request)
|
|
return Transaction.objects.filter(application=application,
|
|
payer_id=application.pk,
|
|
payer_type=TypeChoices.APPLICATION.value).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)
|
|
|
|
|
|
# from another entity to application
|
|
class WithdrawSubmitAPIView(generics.CreateAPIView):
|
|
permission_classes = [TokenHasScope]
|
|
serializer_class = ApplicationWithdrawSerializer
|
|
required_scopes = ['wallet.application.withdraw:submit']
|
|
|
|
def get_queryset(self):
|
|
application = get_application(self.request)
|
|
return Transaction.objects.filter(application=application,
|
|
payee_id=application.pk,
|
|
payee_type=TypeChoices.APPLICATION.value).all()
|
|
|
|
def perform_create(self, serializer):
|
|
# TODO: get_or_create instead of create if uuid given
|
|
# TODO: it is possible to merage create and submit in one step for improve performance
|
|
application = get_application(self.request)
|
|
instance = serializer.save(payee_id=application.pk,
|
|
payee_type=TypeChoices.APPLICATION.value,
|
|
application=application)
|
|
|
|
instance.submit()
|
|
|
|
|
|
class WithdrawVerifyAPIView(generics.RetrieveAPIView):
|
|
permission_classes = [TokenHasScope]
|
|
serializer_class = ApplicationWithdrawSerializer
|
|
lookup_field = 'uuid'
|
|
required_scopes = ['wallet.application.withdraw:verify']
|
|
|
|
def get_queryset(self):
|
|
application = get_application(self.request)
|
|
return Transaction.objects.filter(application=application,
|
|
payee_id=application.pk,
|
|
payee_type=TypeChoices.APPLICATION.value).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 CategoryBalanceAPIView(generics.RetrieveAPIView):
|
|
'''
|
|
API for getting specified user or application balance.
|
|
'''
|
|
permission_classes = [TokenHasScope]
|
|
serializer_class = ApplicationBalanceSerializer
|
|
required_scopes = ['wallet.application:get_balance']
|
|
|
|
def get_object(self):
|
|
category_uuid = self.kwargs.get('category_uuid')
|
|
if category_uuid:
|
|
category = get_object_or_404(Category.objects.all(), uuid=category_uuid)
|
|
else:
|
|
category = None
|
|
|
|
application = get_application(self.request)
|
|
wallet, created = Wallet.objects.get_or_create(owner_uuid=application.uuid, owner_type=TypeChoices.APPLICATION,
|
|
category=category)
|
|
return wallet
|
|
|
|
|
|
class CategoryUserBalanceAPIView(generics.RetrieveAPIView):
|
|
'''
|
|
API for getting specified user or application balance.
|
|
'''
|
|
permission_classes = [IsAuthenticatedOrTokenHasScope]
|
|
serializer_class = MyWalletSerializer
|
|
required_scopes = ['wallet.application:get_user_balance']
|
|
|
|
def get_object(self):
|
|
category_uuid = self.kwargs.get('category_uuid')
|
|
if category_uuid:
|
|
category = get_object_or_404(Category.objects.all(), uuid=category_uuid)
|
|
else:
|
|
category = None
|
|
|
|
user_uuid = self.kwargs.get('uuid')
|
|
user, created = User.objects.get_or_create(uuid=user_uuid)
|
|
application = get_application(self.request)
|
|
wallet, created = Wallet.objects.get_or_create(owner_uuid=user_uuid, owner_type=TypeChoices.USER,
|
|
category=category)
|
|
return wallet
|
|
|
|
|
|
class CategoryTransactionDetailAPIView(generics.RetrieveAPIView):
|
|
permission_classes = [TokenHasScope]
|
|
serializer_class = ApplicationTransactionSerializer
|
|
lookup_field = 'uuid'
|
|
required_scopes = ['wallet.application:get_transaction_detail']
|
|
|
|
def get_queryset(self):
|
|
# TODO: what about category
|
|
application = get_application(self.request)
|
|
return Transaction.objects.filter(Q(application=application) |
|
|
Q(payer_wallet__owner_uuid=application.pk,
|
|
payer_wallet__owner_type=TypeChoices.APPLICATION) |
|
|
Q(payee_wallet__owner_uuid=application.pk,
|
|
payee_wallet__owner_type=TypeChoices.APPLICATION)
|
|
).all()
|
|
|
|
|
|
class CategoryTransactionListAPIView(generics.ListAPIView):
|
|
permission_classes = [TokenHasScope]
|
|
serializer_class = ApplicationTransactionSerializer
|
|
lookup_field = 'uuid'
|
|
required_scopes = ['wallet.application:get_transaction_list']
|
|
|
|
def get_queryset(self):
|
|
# TODO: what about category?
|
|
application = get_application(self.request)
|
|
return Transaction.objects.filter(Q(application=application) |
|
|
Q(payer_wallet__owner_uuid=application.pk,
|
|
payer_wallet__owner_type=TypeChoices.APPLICATION) |
|
|
Q(payee_wallet__owner_uuid=application.pk,
|
|
payee_wallet__owner_type=TypeChoices.APPLICATION)
|
|
).all()
|
|
|
|
|
|
# from application to another entity
|
|
# TODO: better name
|
|
class CategoryDepositSubmitAPIView(generics.CreateAPIView):
|
|
permission_classes = [IsAuthenticatedOrTokenHasScope]
|
|
serializer_class = ApplicationDepositSerializer
|
|
required_scopes = ['wallet.application.deposit:submit']
|
|
|
|
def get_queryset(self):
|
|
category_uuid = self.kwargs.get('category_uuid')
|
|
if category_uuid:
|
|
category = get_object_or_404(Category.objects.all(), uuid=category_uuid)
|
|
else:
|
|
category = None
|
|
application = get_application(self.request)
|
|
wallet, created = Wallet.objects.get_or_create(owner_uuid=application.uuid, owner_type=TypeChoices.APPLICATION,
|
|
category=category)
|
|
return Transaction.objects.filter(application=application, payer_wallet=wallet).all()
|
|
|
|
def perform_create(self, serializer):
|
|
# TODO: get_or_create instead of create if uuid given
|
|
# TODO: it is possible to merage create and submit in one step for improve performance
|
|
application = get_application(self.request)
|
|
category_uuid = self.kwargs.get('category_uuid')
|
|
if category_uuid:
|
|
category = get_object_or_404(Category.objects.all(), uuid=category_uuid)
|
|
else:
|
|
category = None
|
|
payee_id = serializer.validated_data.pop('payee_id')
|
|
payee_type = serializer.validated_data.pop('payee_type')
|
|
payer_wallet, _ = Wallet.objects.get_or_create(owner_uuid=application.uuid, owner_type=TypeChoices.APPLICATION,
|
|
category=category)
|
|
payee_wallet, _ = Wallet.objects.get_or_create(owner_uuid=payee_id, owner_type=payee_type, category=category)
|
|
|
|
instance = serializer.save(payer_wallet=payer_wallet, application=application, payee_wallet=payee_wallet)
|
|
instance.category_submit()
|
|
|
|
|
|
class CategoryDepositVerifyAPIView(generics.RetrieveAPIView):
|
|
permission_classes = [IsAuthenticatedOrTokenHasScope]
|
|
serializer_class = ApplicationDepositSerializer
|
|
lookup_field = 'uuid'
|
|
required_scopes = ['wallet.application.deposit:verify']
|
|
|
|
def get_queryset(self):
|
|
application = get_application(self.request)
|
|
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 = Wallet.objects.get(owner_uuid=application.uuid, owner_type=TypeChoices.APPLICATION, category=category)
|
|
return Transaction.objects.filter(application=application, payer_wallet=wallet).all()
|
|
|
|
def retrieve(self, request, *args, **kwargs):
|
|
instance = self.get_object()
|
|
if instance.state == StateChoices.PENDING:
|
|
instance.category_verify()
|
|
|
|
serializer = self.get_serializer(instance)
|
|
return Response(serializer.data)
|
|
|
|
|
|
# from another entity to application
|
|
class CategoryWithdrawSubmitAPIView(generics.CreateAPIView):
|
|
permission_classes = [TokenHasScope]
|
|
serializer_class = ApplicationWithdrawSerializer
|
|
required_scopes = ['wallet.application.withdraw:submit']
|
|
|
|
def get_queryset(self):
|
|
category_uuid = self.kwargs.get('category_uuid')
|
|
if category_uuid:
|
|
category = get_object_or_404(Category.objects.all(), uuid=category_uuid)
|
|
else:
|
|
category = None
|
|
application = get_application(self.request)
|
|
wallet, created = Wallet.objects.get_or_create(owner_uuid=application.uuid, owner_type=TypeChoices.APPLICATION,
|
|
category=category)
|
|
return Transaction.objects.filter(application=application, wallet=wallet).all()
|
|
|
|
def perform_create(self, serializer):
|
|
# TODO: get_or_create instead of create if uuid given
|
|
# TODO: it is possible to merage create and submit in one step for improve performance
|
|
application = get_application(self.request)
|
|
category_uuid = self.kwargs.get('category_uuid')
|
|
if category_uuid:
|
|
category = get_object_or_404(Category.objects.all(), uuid=category_uuid)
|
|
else:
|
|
category = None
|
|
payer_id = serializer.validated_data.pop('payer_id')
|
|
payer_type = serializer.validated_data.pop('payer_type')
|
|
payee_wallet, _ = Wallet.objects.get_or_create(owner_uuid=application.uuid, owner_type=TypeChoices.APPLICATION,
|
|
category=category)
|
|
payer_wallet, _ = Wallet.objects.get_or_create(owner_uuid=payer_id, owner_type=payer_type, category=category)
|
|
instance = serializer.save(payer_wallet=payer_wallet, application=application, payee_wallet=payee_wallet)
|
|
instance.category_submit()
|
|
|
|
|
|
class CategoryWithdrawVerifyAPIView(generics.RetrieveAPIView):
|
|
permission_classes = [TokenHasScope]
|
|
serializer_class = ApplicationWithdrawSerializer
|
|
lookup_field = 'uuid'
|
|
required_scopes = ['wallet.application.withdraw:verify']
|
|
|
|
def get_queryset(self):
|
|
application = get_application(self.request)
|
|
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 = Wallet.objects.get(owner_uuid=application.uuid, owner_type=TypeChoices.APPLICATION, category=category)
|
|
return Transaction.objects.filter(application=application, payee_wallet=wallet).all()
|
|
|
|
def retrieve(self, request, *args, **kwargs):
|
|
instance = self.get_object()
|
|
if instance.state == StateChoices.PENDING:
|
|
instance.category_verify()
|
|
|
|
serializer = self.get_serializer(instance)
|
|
return Response(serializer.data)
|