From bf1335b6f2fd35068d0d70a1b37dd3974a872cff Mon Sep 17 00:00:00 2001 From: Mojtaba-z Date: Sun, 14 Dec 2025 11:28:10 +0330 Subject: [PATCH] import - rancher page main dashboard --- .../services/rancher_dashboard_service.py | 70 +++++++++---------- apps/herd/services/services.py | 4 +- apps/herd/web/api/v1/api.py | 32 ++++++++- 3 files changed, 66 insertions(+), 40 deletions(-) diff --git a/apps/herd/services/rancher_dashboard_service.py b/apps/herd/services/rancher_dashboard_service.py index ca6dc8d..6991c6c 100644 --- a/apps/herd/services/rancher_dashboard_service.py +++ b/apps/herd/services/rancher_dashboard_service.py @@ -1,47 +1,45 @@ -from django.db import models -from django.db.models import Count, Sum +from django.db.models import Sum, Count, Q +from django.db.models.functions import Coalesce from apps.herd.models import Rancher, Herd -from apps.livestock.models import LiveStock -class FarmerDashboardService: - """ Dashboard aggregation service for Rancher """ +class RancherDashboardService: + """ + Rancher Dashboard Service + """ @staticmethod - def get_basic_info(rancher: Rancher): - return { - "id": rancher.id, - "name": f"{rancher.first_name} {rancher.last_name}", - "mobile": rancher.mobile, - "national_code": rancher.national_code, - "province": rancher.province.name if rancher.province else None, - "city": rancher.city.name if rancher.city else None, - } + def get_main_dashboard( + self, + rancher_search_fields: list[str] = None, + herd_search_fields: list[str] = None, + query_string: str = None + ): + """ + get ranchers main page dashboard + """ + ranchers = Rancher.objects.all() + herds = Herd.objects.all() - @staticmethod - def get_herd_counts(rancher_id): - return Herd.objects.filter(rancher_id=rancher_id).aggregate( - total_herds=Count('id'), - total_heavy=Sum('heavy_livestock_number'), - total_light=Sum('light_livestock_number'), + ranchers_data = ranchers.aggregate( + total_ranchers_count=Coalesce(Count("id"), 0), + total_with_herd=Coalesce(Count("id", filter=Q(without_herd=False)), 0), + total_without_herd=Coalesce(Count("id", filter=Q(without_herd=True)), 0), + total_natural_ranchers=Coalesce(Count("id", filter=Q(rancher_type='N')), 0), + total_legal_ranchers=Coalesce(Count("id", filter=Q(rancher_type='L')), 0), + total_industrial_ranchers=Coalesce(Count("id", filter=Q(rancher_type='I')), 0), + total_village_ranchers=Coalesce(Count("id", filter=Q(rancher_type='V')), 0), + total_nomadic_ranchers=Coalesce(Count("id", filter=Q(rancher_type='N')), 0), ) - @staticmethod - def get_livestock_counts(rancher_id): - return LiveStock.objects.filter(herd__rancher_id=rancher_id, archive=False).aggregate( - total=Count('id'), - heavy=Count('id', filter=models.Q(weight_type='H')), - light=Count('id', filter=models.Q(weight_type='L')), + herds_data = herds.aggregate( + total_herds_count=Coalesce(Count("id"), 0), + total_industrial_herds_count=Coalesce(Count("id", filter=Q(activity='I')), 0), + total_Village_herds_count=Coalesce(Count("id", filter=Q(activity='V')), 0), + total_nomadic_herds_count=Coalesce(Count("id", filter=Q(activity='N')), 0), + total_heavy_livestock_count=Coalesce(Sum("heavy_livestock_number"), 0), + total_light_livestock_count=Coalesce(Sum("light_livestock_number"), 0), ) - @staticmethod - def get_livestock_by_type(rancher_id): - return ( - LiveStock.objects.filter(herd__rancher_id=rancher_id, archive=False) - .values("type__name") - .annotate(count=Count("id")) - ) - -# @staticmethod -# def get_dashboard(rancher_id): + return {"rancher_dashboard": ranchers_data, "herd_dashboard": herds_data} diff --git a/apps/herd/services/services.py b/apps/herd/services/services.py index f09b1e3..11bf3a2 100644 --- a/apps/herd/services/services.py +++ b/apps/herd/services/services.py @@ -90,6 +90,7 @@ def rancher_quota_weight( :param inventory_entry: InventoryEntry instance :param distribution: QuotaDistribution instance :param quota: Quota instance + :param quota_stat: OrganizationQuotaStat instance :return: dict {total, by_type} """ @@ -115,7 +116,6 @@ def rancher_quota_weight( # list of rancher herds herds = rancher.herd.all() herd_livestock_gropes = [herd.activity if herd.activity else 'V' for herd in herds] - print(herd_livestock_gropes) livestock_counts_list, livestock_counts_dict = get_rancher_statistic_by_herd(rancher) total_weight = 0 @@ -153,14 +153,12 @@ def rancher_quota_weight( # incentive plan quantity by this livestock type rancher_plan_weight = rancher_plans.first().allowed_quantity * item.quantity_kg total_weight += rancher_plan_weight - print(total_weight) # get rancher remaining usage of quota for purchase rancher_remaining_usage = RancherService.get_total_used_weight( rancher, InventoryQuotaSaleItem, quota_stat=quota_stat ) - print(rancher_remaining_usage) if total_weight - rancher_remaining_usage < 0: remaining_weight = 0 diff --git a/apps/herd/web/api/v1/api.py b/apps/herd/web/api/v1/api.py index a00bb61..b18bb2f 100644 --- a/apps/herd/web/api/v1/api.py +++ b/apps/herd/web/api/v1/api.py @@ -9,6 +9,7 @@ from apps.core.api import BaseViewSet from apps.core.mixins.search_mixin import DynamicSearchMixin from apps.core.mixins.soft_delete_mixin import SoftDeleteMixin from apps.herd.models import Herd, Rancher +from apps.herd.services.rancher_dashboard_service import RancherDashboardService from apps.herd.web.api.v1.serializers import HerdSerializer, RancherSerializer from apps.livestock.web.api.v1.serializers import LiveStockSerializer from apps.product.web.api.v1.serializers import product_serializers @@ -23,6 +24,13 @@ class HerdViewSet(BaseViewSet, SoftDeleteMixin, viewsets.ModelViewSet): filter_backends = [filters.SearchFilter] search_fields = [ "rancher__ranching_farm", + "rancher__first_name", + "rancher__last_name", + "rancher__mobile", + "rancher__national_code", + "rancher__address", + "rancher__province__name", + "rancher__city__name", "name", "code", "province__name", @@ -105,7 +113,7 @@ class HerdViewSet(BaseViewSet, SoftDeleteMixin, viewsets.ModelViewSet): return self.get_paginated_response(serializer.data) -class RancherViewSet(BaseViewSet, SoftDeleteMixin, viewsets.ModelViewSet, DynamicSearchMixin): +class RancherViewSet(BaseViewSet, RancherDashboardService, SoftDeleteMixin, viewsets.ModelViewSet, DynamicSearchMixin): queryset = Rancher.objects.all() serializer_class = RancherSerializer search_fields = [ @@ -165,3 +173,25 @@ class RancherViewSet(BaseViewSet, SoftDeleteMixin, viewsets.ModelViewSet, Dynami if page is not None: # noqa serializer = product_serializers.IncentivePlanRancherSerializer(page, many=True) return self.get_paginated_response(serializer.data) + + @action( + methods=['get'], + detail=False, + url_path='rancher_main_dashboard', + url_name='rancher_main_dashboard', + name='rancher_main_dashboard' + ) + def rancher_main_dashboard(self, request, pk=None): + """ rancher main dashboard """ + + query_param = self.request.query_params # noqa + + query_string = query_param.get('search', None) + + rancher_dashboard_data = self.get_main_dashboard( + self, + rancher_search_fields=self.search_fields, + herd_search_fields=HerdViewSet.search_fields, + query_string=query_string, + ) + return Response(rancher_dashboard_data)