grouped transactions
This commit is contained in:
parent
27db599e8c
commit
e045ffd9b1
2 changed files with 40 additions and 32 deletions
|
|
@ -223,3 +223,7 @@ class ApplicationWithdrawSerializer(serializers.ModelSerializer):
|
||||||
)
|
)
|
||||||
|
|
||||||
read_only_fields = ['updated_at', 'state', 'created_at', 'payee', 'payee_type', 'payee_wallet']
|
read_only_fields = ['updated_at', 'state', 'created_at', 'payee', 'payee_type', 'payee_wallet']
|
||||||
|
|
||||||
|
|
||||||
|
class TransactionGroupedSerializer(serializers.Serializer):
|
||||||
|
pass
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.contrib.postgres.aggregates import ArrayAgg
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
from django.views.generic import DetailView, ListView, UpdateView
|
from django.views.generic import DetailView, ListView, UpdateView
|
||||||
from django_filters.rest_framework import DjangoFilterBackend
|
from django_filters.rest_framework import DjangoFilterBackend
|
||||||
|
from drf_spectacular.utils import extend_schema
|
||||||
|
|
||||||
from oauth2_provider.contrib.rest_framework import TokenHasScope, IsAuthenticatedOrTokenHasScope
|
from oauth2_provider.contrib.rest_framework import TokenHasScope, IsAuthenticatedOrTokenHasScope
|
||||||
from rest_framework import generics, permissions, mixins
|
from rest_framework import generics, permissions, mixins
|
||||||
|
|
@ -14,10 +16,14 @@ from rest_framework.permissions import AllowAny
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.viewsets import ViewSet, GenericViewSet
|
from rest_framework.viewsets import ViewSet, GenericViewSet
|
||||||
|
|
||||||
|
from apps.wallet.models import Transaction
|
||||||
|
from django.contrib.postgres.aggregates import ArrayAgg
|
||||||
|
from django.db.models import Sum, Count, F, StringAgg
|
||||||
|
|
||||||
from apps.gooyal_oauth2.rest_framework import IsAuthenticatedOrTokenMatchesOASRequirements
|
from apps.gooyal_oauth2.rest_framework import IsAuthenticatedOrTokenMatchesOASRequirements
|
||||||
from apps.wallet.models import Transaction, Wallet, Account
|
from apps.wallet.models import Transaction, Wallet, Account
|
||||||
from apps.wallet.serializers import TransactionSerializer, DepositSerializer, WithdrawSerializer, \
|
from apps.wallet.serializers import TransactionSerializer, DepositSerializer, WithdrawSerializer, \
|
||||||
AccountSerializer
|
AccountSerializer, TransactionGroupedSerializer
|
||||||
from ..constans import StateChoices, TypeChoices
|
from ..constans import StateChoices, TypeChoices
|
||||||
from ..filters import AccountFilter, UserTransactionFilter
|
from ..filters import AccountFilter, UserTransactionFilter
|
||||||
from ..forms import TransactionActionForm
|
from ..forms import TransactionActionForm
|
||||||
|
|
@ -308,12 +314,11 @@ class WalletTransactionListView(generics.ListAPIView):
|
||||||
|
|
||||||
|
|
||||||
class UserTransactionViewSet(mixins.ListModelMixin,
|
class UserTransactionViewSet(mixins.ListModelMixin,
|
||||||
# mixins.CreateModelMixin,
|
# mixins.CreateModelMixin,
|
||||||
# mixins.RetrieveModelMixin,
|
# mixins.RetrieveModelMixin,
|
||||||
# mixins.UpdateModelMixin,
|
# mixins.UpdateModelMixin,
|
||||||
# mixins.DestroyModelMixin,
|
# mixins.DestroyModelMixin,
|
||||||
GenericViewSet):
|
GenericViewSet):
|
||||||
|
|
||||||
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
|
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
|
||||||
serializer_class = TransactionSerializer
|
serializer_class = TransactionSerializer
|
||||||
required_alternate_scopes = {
|
required_alternate_scopes = {
|
||||||
|
|
@ -331,7 +336,6 @@ class UserTransactionViewSet(mixins.ListModelMixin,
|
||||||
return Transaction.objects.filter(Q(payee_account__owner_uuid=user.uuid) |
|
return Transaction.objects.filter(Q(payee_account__owner_uuid=user.uuid) |
|
||||||
Q(payer_account__owner_uuid=user.uuid)).all()
|
Q(payer_account__owner_uuid=user.uuid)).all()
|
||||||
|
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
queryset = self.filter_queryset(self.get_queryset())
|
queryset = self.filter_queryset(self.get_queryset())
|
||||||
|
|
||||||
|
|
@ -343,32 +347,32 @@ class UserTransactionViewSet(mixins.ListModelMixin,
|
||||||
serializer = self.get_serializer(queryset, many=True)
|
serializer = self.get_serializer(queryset, many=True)
|
||||||
return Response(serializer.data)
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
@extend_schema(responses=TransactionGroupedSerializer(many=True))
|
||||||
@action(detail=False, methods=["GET"])
|
@action(detail=False, methods=["GET"], serializer_class=TransactionGroupedSerializer)
|
||||||
def grouped(self):
|
def grouped(self):
|
||||||
from collections import defaultdict
|
|
||||||
from django.db.models import Count, Sum
|
|
||||||
|
|
||||||
# فقط ۲ کوئری بهینه
|
queryset = self.filter_queryset(self.get_queryset())
|
||||||
# کوئری ۱: آمار کلی (سبک)
|
|
||||||
stats = dict(Transaction.objects.values('refrence').annotate(
|
|
||||||
total=Sum('amount'),
|
|
||||||
count=Count('id')
|
|
||||||
).values_list('refrence', 'total', 'count'))
|
|
||||||
|
|
||||||
# کوئری ۲: همه تراکنشها
|
grouped_transaction_list = queryset.values('details__reference_id', 'application').annotate(
|
||||||
transactions = Transaction.objects.all().order_by('refrence', 'created_at')
|
total_amount=Sum('amount'),
|
||||||
|
total_count=Count('uuid'),
|
||||||
|
transaction_uuid_list=ArrayAgg('uuid'),
|
||||||
|
)
|
||||||
|
|
||||||
# گروهبندی در پایتون
|
page = list(self.paginate_queryset(grouped_transaction_list))
|
||||||
groups = defaultdict(list)
|
|
||||||
for t in transactions:
|
|
||||||
groups[t.refrence].append(t)
|
|
||||||
|
|
||||||
# ترکیب
|
transaction_uuid_list = []
|
||||||
result = []
|
|
||||||
for ref, items in groups.items():
|
for grouped_transaction in page:
|
||||||
result.append({
|
transaction_uuid_list += grouped_transaction['transaction_uuid_list']
|
||||||
'refrence': ref,
|
|
||||||
'stats': {'total': stats.get(ref, 0), 'count': len(items)},
|
transaction_list = Transaction.objects.filter(uuid__in=transaction_uuid_list)
|
||||||
'transactions': items
|
|
||||||
})
|
transaction_dict = {t.pk: t for t in transaction_list}
|
||||||
|
|
||||||
|
for grouped_transaction in page:
|
||||||
|
for i, transaction in enumerate(grouped_transaction['transaction_uuid_list']):
|
||||||
|
grouped_transaction['transaction_uuid_list'][i] = transaction_dict[transaction]
|
||||||
|
|
||||||
|
serializer = self.get_serializer(page, many=True)
|
||||||
|
return self.get_paginated_response(serializer.data)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue