from django.db.models import Sum from django.shortcuts import get_object_or_404 from rest_framework import generics, views, filters from rest_framework.response import Response from django_filters.rest_framework.backends import DjangoFilterBackend from core.apps.accounts.permissions.permissions import HasRolePermission from core.apps.shared.paginations.custom import CustomPageNumberPagination from core.apps.counterparty.models import Counterparty, CounterpartyFolder from core.apps.counterparty.serializers import counterparty as serializers from core.apps.counterparty.filters.counterparty import CounterpartyFilter from core.apps.finance.models import Expence, Income class CounterpartyListApiView(generics.ListAPIView): serializer_class = serializers.CounterpartyListSerializer queryset = Counterparty.objects.exclude(is_archived=True).exclude(folder__isnull=False) pagination_class = [HasRolePermission] pagination_class = CustomPageNumberPagination filter_backends = [DjangoFilterBackend, filters.SearchFilter] filterset_class = CounterpartyFilter search_fields = [ 'name', 'inn' ] class CounterpartyCreateApiView(generics.GenericAPIView): serializer_class = serializers.CounterpartyCreateSerializer queryset = Counterparty.objects.all() permission_classes = [HasRolePermission] def post(self, request): serializer = self.serializer_class(data=request.data) if serializer.is_valid(raise_exception=True): data = serializer.save() return Response( { 'success': True, 'message': 'Conterparty Created', 'data': serializers.CounterpartyListSerializer(data).data }, status=201 ) return Response( {'success': False, 'message': serializer.errors}, status=400 ) class ArchiveCounterpartyApiView(views.APIView): permission_classes = [HasRolePermission] def get(self, request, id): counterparty = get_object_or_404(Counterparty, id=id) counterparty.is_archived = True counterparty.save() return Response( {'success': True, 'message': 'counterparty archived'}, status=200 ) class ArchivedCounterpartyListApiView(generics.ListAPIView): serializer_class = serializers.CounterpartyListSerializer queryset = Counterparty.objects.exclude(is_archived=False) pagination_class = [HasRolePermission] pagination_class = CustomPageNumberPagination class CounterpartyDeleteApiView(views.APIView): permission_classes = [HasRolePermission] def delete(self, request, id): counterparty = get_object_or_404(Counterparty, id=id) counterparty.delete() return Response( {'success': True, 'message': 'counterparty deleted'}, status=204 ) class CounterpartyUpdateApiView(generics.UpdateAPIView): permission_classes = [HasRolePermission] lookup_field = 'id' serializer_class = serializers.CounterpartyUpdateSerializer queryset = Counterparty.objects.all() class FolderCounterpartyListApiView(generics.GenericAPIView): serializer_class = serializers.CounterpartyListSerializer queryset = Counterparty.objects.exclude(is_archived=True) permission_classes = [HasRolePermission] filter_backends = [filters.SearchFilter] search_fields = [ 'name', 'inn' ] def get(self, reuqest, folder_id): folder = get_object_or_404(CounterpartyFolder, id=folder_id) queryset = self.queryset.filter(folder=folder).exclude(folder__isnull=True) page = self.paginate_queryset(self.filter_queryset(queryset)) if page is not None: serializer = self.serializer_class(page, many=True) return self.get_paginated_response(serializer.data) class CounterpartyStatisticsApiView(views.APIView): permission_classes = [HasRolePermission] def get(self, request): counterparty_ids = request.query_params.getlist('counterparty') if counterparty_ids: queryset = Counterparty.objects.filter(id__in=counterparty_ids) else: queryset = Counterparty.objects.all() res = queryset.aggregate( kredit_usd=Sum('kredit_usd'), kredit_uzs=Sum('kredit_uzs'), total_kredit=Sum('total_kredit'), debit_usd=Sum('debit_usd'), debit_uzs=Sum('debit_uzs'), total_debut=Sum('total_debit'), ) return Response(res) class CounterpartiesApiView(generics.GenericAPIView): serializer_class = serializers.CounterpartyListSerializer queryset = Counterparty.objects.all() permission_classes = [HasRolePermission] filter_backends = [filters.SearchFilter] search_fields = [ 'name', 'inn' ] def get(self, request): page = self.paginate_queryset(self.filter_queryset(self.queryset)) if page is not None: ser = self.serializer_class(page, many=True) return self.get_paginated_response(ser.data) class CounterpartyDetailApiView(views.APIView): permission_classes = [HasRolePermission] def get(self, request, id): obj = get_object_or_404(Counterparty, id=id) serializer = serializers.CounterpartyListSerializer(obj) return Response(serializer.data, status=200) class UnArchiveCounterpartyApiView(views.APIView): permission_classes = [HasRolePermission] def get(self, request, id): obj = get_object_or_404(Counterparty, id=id) obj.is_archived = False obj.save() return Response( {'success': True, 'message': 'Conterparty unarchived'}, status=200 ) class AllCounterpartyListApiView(generics.GenericAPIView): serializer_class = serializers.CounterpartyListSerializer queryset = Counterparty.objects.all() permission_classes = [HasRolePermission] filter_backends = [filters.SearchFilter] search_fields = [ 'name' ] def get(self, request): page = self.paginate_queryset(self.queryset) if page is not None: serializer = self.serializer_class(page, many=True) return self.get_paginated_response(serializer.data) class CounterPartyIncomeExpenceStatisticsApiView(views.APIView): permission_classes = [HasRolePermission] def get(self, request, id): counterparty = get_object_or_404(Counterparty, id=id) incomes = Income.objects.filter( counterparty=counterparty, is_deleted=False ) expences = Expence.objects.filter( counterparty=counterparty, is_deleted=False, ) income_by_currency = {} expence_by_currency = {} for income in incomes: currency = income.currency amount = income.price if currency not in income_by_currency: income_by_currency[currency] = { 'total': 0, 'count': 0, 'amount_uzs': 0 } income_by_currency[currency]['total'] += amount income_by_currency[currency]['count'] += 1 if currency == 'usd': income_by_currency[currency]['amount_uzs'] += amount * income.exchange_rate else: income_by_currency[currency]['amount_uzs'] += amount for expence in expences: currency = expence.currency amount = expence.price if currency not in expence_by_currency: expence_by_currency[currency] = { 'total': 0, 'count': 0, 'amount_uzs': 0 } expence_by_currency[currency]['total'] += amount expence_by_currency[currency]['count'] += 1 if currency == 'usd': expence_by_currency[currency]['amount_uzs'] += amount * expence.exchange_rate else: expence_by_currency[currency]['amount_uzs'] += amount total_income_uzs = sum(data['amount_uzs'] for data in income_by_currency.values()) total_expence_uzs = sum(data['amount_uzs'] for data in expence_by_currency.values()) balance = total_income_uzs - total_expence_uzs data = { 'counterparty': { 'id': counterparty.id, 'name': counterparty.name, }, 'income': { 'by_currency': income_by_currency, 'total_uzs': total_income_uzs, 'total_count': sum(data['count'] for data in income_by_currency.values()) }, 'expence': { 'by_currency': expence_by_currency, 'total_uzs': total_expence_uzs, 'total_count': sum(data['count'] for data in expence_by_currency.values()) }, 'balance': { 'uzs': balance, 'status': 'positive' if balance > 0 else 'negative' if balance < 0 else 'zero' } } return Response(data, status=status.HTTP_200_OK)