diff --git a/apps/herd/services/rancher_org_link_services.py b/apps/herd/services/rancher_org_link_services.py index 8ca92db..a354158 100644 --- a/apps/herd/services/rancher_org_link_services.py +++ b/apps/herd/services/rancher_org_link_services.py @@ -5,54 +5,146 @@ from apps.authentication.services.service import get_all_org_child from apps.herd.models import RancherOrganizationLink +# class RancherOrganizationService: +# """ +# different services of ranchers linked to organization +# """ +# +# def orgs_linked_rancher(self, org: Organization = None, org_type_key: str = None): +# """ +# list of organizations with their information of rancher, herd, .... +# """ +# if org.type.key != 'ADM': +# organizations = get_all_org_child(org) +# organizations = Organization.objects.filter(id__in=[item.id for item in organizations]) +# else: +# organizations = Organization.objects.filter(type__key=org_type_key) +# +# linked_qs = RancherOrganizationLink.objects.select_related( +# 'rancher', +# 'organization' +# ).filter(organization__in=organizations, organization__type__key=org_type_key) +# +# organizations = organizations.annotate( +# rancher_count=Count( +# 'rancher_links__rancher_id', +# distinct=True +# ), +# herd_count=Count( +# 'rancher_links__rancher__herd', +# distinct=True +# ), +# livestock_count=Count( +# 'rancher_links__rancher__herd__live_stock_herd', +# distinct=True +# ), +# ) +# +# return [ +# { +# "id": org.id, +# "name": org.name, +# "org_service_area": [{'name': city.name, 'id': city.id} for city in org.service_area.all()], +# "org_purchase_policy": org.purchase_policy, +# "province": org.province.name, +# "province_id": org.province.id, +# "city": org.city.name, +# "city_id": org.city.id, +# "rancher_count": org.rancher_count, +# "herd_count": org.herd_count, +# "livestock_count": org.livestock_count, +# } +# for org in organizations +# ] + + class RancherOrganizationService: - """ - different services of ranchers linked to organization - """ - def orgs_linked_rancher(self, org: Organization = None, org_type_key: str = None): - """ - list of organizations with their information of rancher, herd, .... - """ + def orgs_linked_rancher(self, org: Organization, org_type_key: str): + + # -------------------------------------------------- + # 1. Base organizations queryset + # -------------------------------------------------- if org.type.key != 'ADM': - organizations = get_all_org_child(org) - organizations = Organization.objects.filter(id__in=[item.id for item in organizations]) + child_orgs = get_all_org_child(org) + org_ids = [o.id for o in child_orgs] else: - organizations = Organization.objects.filter(type__key=org_type_key) + org_ids = Organization.objects.filter( + type__key=org_type_key + ).values_list('id', flat=True) - linked_qs = RancherOrganizationLink.objects.select_related( - 'rancher', - 'organization' - ).filter(organization__in=organizations, organization__type__key=org_type_key) - - organizations = organizations.annotate( - rancher_count=Count( - 'rancher_links__rancher', - distinct=True - ), - herd_count=Count( - 'rancher_links__rancher__herd', - distinct=True - ), - livestock_count=Count( - 'rancher_links__rancher__herd__live_stock_herd', - distinct=True - ), + organizations = ( + Organization.objects + .filter(id__in=org_ids, type__key=org_type_key) + .select_related('province', 'city') + .prefetch_related('service_area') ) - return [ - { + # -------------------------------------------------- + # 2. Rancher count per organization + # -------------------------------------------------- + rancher_counts = { + row['organization_id']: row['cnt'] + for row in ( + RancherOrganizationLink.objects + .filter(organization_id__in=org_ids) + .values('organization_id') + .annotate(cnt=Count('rancher_id', distinct=True)) + ) + } + + # -------------------------------------------------- + # 3. Herd count per organization + # -------------------------------------------------- + herd_counts = { + row['organization_id']: row['cnt'] + for row in ( + RancherOrganizationLink.objects + .filter(organization_id__in=org_ids) + .values('organization_id') + .annotate(cnt=Count('rancher__herd', distinct=True)) + ) + } + + # -------------------------------------------------- + # 4. Livestock count per organization + # -------------------------------------------------- + livestock_counts = { + row['organization_id']: row['cnt'] + for row in ( + RancherOrganizationLink.objects + .filter(organization_id__in=org_ids) + .values('organization_id') + .annotate( + cnt=Count( + 'rancher__herd__live_stock_herd', + distinct=True + ) + ) + ) + } + + # -------------------------------------------------- + # 5. Final response (merge in memory) + # -------------------------------------------------- + response = [] + for org in organizations: + response.append({ "id": org.id, "name": org.name, - "org_service_area": [{'name': city.name, 'id': city.id} for city in org.service_area.all()], + "org_service_area": [ + {"id": city.id, "name": city.name} + for city in org.service_area.all() + ], "org_purchase_policy": org.purchase_policy, "province": org.province.name, "province_id": org.province.id, "city": org.city.name, "city_id": org.city.id, - "rancher_count": org.rancher_count, - "herd_count": org.herd_count, - "livestock_count": org.livestock_count, - } - for org in organizations - ] + + "rancher_count": rancher_counts.get(org.id, 0), + "herd_count": herd_counts.get(org.id, 0), + "livestock_count": livestock_counts.get(org.id, 0), + }) + + return response