grouped transactions

This commit is contained in:
Sayyid Hamid Mahdavi 2026-02-07 13:21:01 +03:30
parent 27db599e8c
commit e045ffd9b1
2 changed files with 40 additions and 32 deletions

View file

@ -223,3 +223,7 @@ class ApplicationWithdrawSerializer(serializers.ModelSerializer):
)
read_only_fields = ['updated_at', 'state', 'created_at', 'payee', 'payee_type', 'payee_wallet']
class TransactionGroupedSerializer(serializers.Serializer):
pass

View file

@ -1,10 +1,12 @@
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.postgres.aggregates import ArrayAgg
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 drf_spectacular.utils import extend_schema
from oauth2_provider.contrib.rest_framework import TokenHasScope, IsAuthenticatedOrTokenHasScope
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.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.wallet.models import Transaction, Wallet, Account
from apps.wallet.serializers import TransactionSerializer, DepositSerializer, WithdrawSerializer, \
AccountSerializer
AccountSerializer, TransactionGroupedSerializer
from ..constans import StateChoices, TypeChoices
from ..filters import AccountFilter, UserTransactionFilter
from ..forms import TransactionActionForm
@ -308,12 +314,11 @@ class WalletTransactionListView(generics.ListAPIView):
class UserTransactionViewSet(mixins.ListModelMixin,
# mixins.CreateModelMixin,
# mixins.RetrieveModelMixin,
# mixins.UpdateModelMixin,
# mixins.DestroyModelMixin,
GenericViewSet):
# mixins.CreateModelMixin,
# mixins.RetrieveModelMixin,
# mixins.UpdateModelMixin,
# mixins.DestroyModelMixin,
GenericViewSet):
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
serializer_class = TransactionSerializer
required_alternate_scopes = {
@ -331,7 +336,6 @@ class UserTransactionViewSet(mixins.ListModelMixin,
return Transaction.objects.filter(Q(payee_account__owner_uuid=user.uuid) |
Q(payer_account__owner_uuid=user.uuid)).all()
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
@ -343,32 +347,32 @@ class UserTransactionViewSet(mixins.ListModelMixin,
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
@action(detail=False, methods=["GET"])
@extend_schema(responses=TransactionGroupedSerializer(many=True))
@action(detail=False, methods=["GET"], serializer_class=TransactionGroupedSerializer)
def grouped(self):
from collections import defaultdict
from django.db.models import Count, Sum
# فقط ۲ کوئری بهینه
# کوئری ۱: آمار کلی (سبک)
stats = dict(Transaction.objects.values('refrence').annotate(
total=Sum('amount'),
count=Count('id')
).values_list('refrence', 'total', 'count'))
queryset = self.filter_queryset(self.get_queryset())
# کوئری ۲: همه تراکنش‌ها
transactions = Transaction.objects.all().order_by('refrence', 'created_at')
grouped_transaction_list = queryset.values('details__reference_id', 'application').annotate(
total_amount=Sum('amount'),
total_count=Count('uuid'),
transaction_uuid_list=ArrayAgg('uuid'),
)
# گروه‌بندی در پایتون
groups = defaultdict(list)
for t in transactions:
groups[t.refrence].append(t)
page = list(self.paginate_queryset(grouped_transaction_list))
# ترکیب
result = []
for ref, items in groups.items():
result.append({
'refrence': ref,
'stats': {'total': stats.get(ref, 0), 'count': len(items)},
'transactions': items
})
transaction_uuid_list = []
for grouped_transaction in page:
transaction_uuid_list += grouped_transaction['transaction_uuid_list']
transaction_list = Transaction.objects.filter(uuid__in=transaction_uuid_list)
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)