From 8ae2cce79eb8b4c4f01b69d052b232d973ec7f4a Mon Sep 17 00:00:00 2001 From: behruz-dev Date: Wed, 5 Nov 2025 18:33:02 +0500 Subject: [PATCH] fix --- core/apps/counterparty/urls.py | 1 + core/apps/counterparty/views/counterparty.py | 83 ++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/core/apps/counterparty/urls.py b/core/apps/counterparty/urls.py index 14ccb0a..3d9993f 100644 --- a/core/apps/counterparty/urls.py +++ b/core/apps/counterparty/urls.py @@ -18,6 +18,7 @@ urlpatterns = [ path("/", cp_views.CounterpartyDetailApiView.as_view()), path('/un_archive/', cp_views.UnArchiveCounterpartyApiView.as_view()), path('all/', cp_views.AllCounterpartyListApiView.as_view()), + path("/statistics/", cp_views.CounterpartyStatisticsApiView.as_view()), ] )), path('counterparty_folder/', include( diff --git a/core/apps/counterparty/views/counterparty.py b/core/apps/counterparty/views/counterparty.py index 9a3d63e..717d19d 100644 --- a/core/apps/counterparty/views/counterparty.py +++ b/core/apps/counterparty/views/counterparty.py @@ -10,6 +10,7 @@ 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): @@ -176,3 +177,85 @@ class AllCounterpartyListApiView(generics.GenericAPIView): 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)