fix - improve response time of org linked ranchers
This commit is contained in:
@@ -7,7 +7,7 @@ ENV_NAME=DEV
|
|||||||
# Database secrets
|
# Database secrets
|
||||||
DB_HOST=31.7.78.133
|
DB_HOST=31.7.78.133
|
||||||
DB_PORT=14352
|
DB_PORT=14352
|
||||||
DB_NAME=Development
|
DB_NAME=Production
|
||||||
DB_USERNAME=postgres
|
DB_USERNAME=postgres
|
||||||
DB_PASSWORD=pfLIVXupbDetvFMt2gUvxLXUL9b4HIOHaPcKXsBEZ1i8zl0iLUjmhUfXlGfJKcTV
|
DB_PASSWORD=pfLIVXupbDetvFMt2gUvxLXUL9b4HIOHaPcKXsBEZ1i8zl0iLUjmhUfXlGfJKcTV
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ class Herd(BaseModel):
|
|||||||
'Rancher',
|
'Rancher',
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
related_name='herd',
|
related_name='herd',
|
||||||
|
db_index=True,
|
||||||
null=True
|
null=True
|
||||||
)
|
)
|
||||||
cooperative = models.ForeignKey(
|
cooperative = models.ForeignKey(
|
||||||
@@ -153,12 +154,14 @@ class RancherOrganizationLink(BaseModel):
|
|||||||
Organization,
|
Organization,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
related_name='rancher_links',
|
related_name='rancher_links',
|
||||||
|
db_index=True,
|
||||||
null=True
|
null=True
|
||||||
)
|
)
|
||||||
rancher = models.ForeignKey(
|
rancher = models.ForeignKey(
|
||||||
Rancher,
|
Rancher,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
related_name='organization_links',
|
related_name='organization_links',
|
||||||
|
db_index=True,
|
||||||
null=True
|
null=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
from django.db.models import Count
|
from django.db.models import Count
|
||||||
|
|
||||||
from apps.authentication.models import Organization
|
from apps.authentication.models import Organization
|
||||||
from apps.authentication.services.service import get_all_org_child
|
from apps.authentication.services.service import get_all_org_child
|
||||||
from apps.herd.models import RancherOrganizationLink
|
from apps.herd.models import RancherOrganizationLink, Herd
|
||||||
|
from apps.livestock.models import LiveStock
|
||||||
|
|
||||||
|
|
||||||
# class RancherOrganizationService:
|
# class RancherOrganizationService:
|
||||||
@@ -63,15 +66,18 @@ class RancherOrganizationService:
|
|||||||
def orgs_linked_rancher(self, org: Organization, org_type_key: str):
|
def orgs_linked_rancher(self, org: Organization, org_type_key: str):
|
||||||
|
|
||||||
# --------------------------------------------------
|
# --------------------------------------------------
|
||||||
# 1. Base organizations queryset
|
# 1. Resolve organization ids
|
||||||
# --------------------------------------------------
|
# --------------------------------------------------
|
||||||
if org.type.key != 'ADM':
|
if org.type.key != 'ADM':
|
||||||
child_orgs = get_all_org_child(org)
|
org_ids = list(
|
||||||
org_ids = [o.id for o in child_orgs]
|
o.id for o in get_all_org_child(org)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
org_ids = Organization.objects.filter(
|
org_ids = list(
|
||||||
type__key=org_type_key
|
Organization.objects.filter(
|
||||||
).values_list('id', flat=True)
|
type__key=org_type_key
|
||||||
|
).values_list('id', flat=True)
|
||||||
|
)
|
||||||
|
|
||||||
organizations = (
|
organizations = (
|
||||||
Organization.objects
|
Organization.objects
|
||||||
@@ -84,12 +90,12 @@ class RancherOrganizationService:
|
|||||||
# 2. Rancher count per organization
|
# 2. Rancher count per organization
|
||||||
# --------------------------------------------------
|
# --------------------------------------------------
|
||||||
rancher_counts = {
|
rancher_counts = {
|
||||||
row['organization_id']: row['cnt']
|
r['organization_id']: r['cnt']
|
||||||
for row in (
|
for r in (
|
||||||
RancherOrganizationLink.objects
|
RancherOrganizationLink.objects
|
||||||
.filter(organization_id__in=org_ids)
|
.filter(organization_id__in=org_ids)
|
||||||
.values('organization_id')
|
.values('organization_id')
|
||||||
.annotate(cnt=Count('rancher_id', distinct=True))
|
.annotate(cnt=Count('rancher_id'))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,39 +103,54 @@ class RancherOrganizationService:
|
|||||||
# 3. Herd count per organization
|
# 3. Herd count per organization
|
||||||
# --------------------------------------------------
|
# --------------------------------------------------
|
||||||
herd_counts = {
|
herd_counts = {
|
||||||
row['organization_id']: row['cnt']
|
r['organization_id']: r['cnt']
|
||||||
for row in (
|
for r in (
|
||||||
RancherOrganizationLink.objects
|
RancherOrganizationLink.objects
|
||||||
.filter(organization_id__in=org_ids)
|
.filter(organization_id__in=org_ids)
|
||||||
.values('organization_id')
|
.values('organization_id')
|
||||||
.annotate(cnt=Count('rancher__herd', distinct=True))
|
.annotate(cnt=Count('rancher__herd'))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
# --------------------------------------------------
|
# --------------------------------------------------
|
||||||
# 4. Livestock count per organization
|
# 4. Livestock count (optimized path)
|
||||||
|
# LiveStockHerd -> Herd -> Org
|
||||||
# --------------------------------------------------
|
# --------------------------------------------------
|
||||||
livestock_counts = {
|
|
||||||
row['organization_id']: row['cnt']
|
# 4-1 livestock count per herd (NO JOIN, NO DISTINCT)
|
||||||
|
livestock_per_herd = {
|
||||||
|
row['herd_id']: row['cnt']
|
||||||
for row in (
|
for row in (
|
||||||
RancherOrganizationLink.objects
|
LiveStock.objects
|
||||||
.filter(organization_id__in=org_ids)
|
.values('herd_id')
|
||||||
.values('organization_id')
|
.annotate(cnt=Count('id'))
|
||||||
.annotate(
|
|
||||||
cnt=Count(
|
|
||||||
'rancher__herd__live_stock_herd',
|
|
||||||
distinct=True
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# 4-2 sum livestock per organization
|
||||||
|
livestock_counts = defaultdict(int)
|
||||||
|
|
||||||
|
herd_org_map = (
|
||||||
|
Herd.objects
|
||||||
|
.filter(
|
||||||
|
rancher__organization_links__organization_id__in=org_ids
|
||||||
|
)
|
||||||
|
.values(
|
||||||
|
'id',
|
||||||
|
'rancher__organization_links__organization_id'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
for row in herd_org_map:
|
||||||
|
livestock_counts[
|
||||||
|
row['rancher__organization_links__organization_id']
|
||||||
|
] += livestock_per_herd.get(row['id'], 0)
|
||||||
|
|
||||||
# --------------------------------------------------
|
# --------------------------------------------------
|
||||||
# 5. Final response (merge in memory)
|
# 5. Final response
|
||||||
# --------------------------------------------------
|
# --------------------------------------------------
|
||||||
response = []
|
return [
|
||||||
for org in organizations:
|
{
|
||||||
response.append({
|
|
||||||
"id": org.id,
|
"id": org.id,
|
||||||
"name": org.name,
|
"name": org.name,
|
||||||
"org_service_area": [
|
"org_service_area": [
|
||||||
@@ -145,6 +166,6 @@ class RancherOrganizationService:
|
|||||||
"rancher_count": rancher_counts.get(org.id, 0),
|
"rancher_count": rancher_counts.get(org.id, 0),
|
||||||
"herd_count": herd_counts.get(org.id, 0),
|
"herd_count": herd_counts.get(org.id, 0),
|
||||||
"livestock_count": livestock_counts.get(org.id, 0),
|
"livestock_count": livestock_counts.get(org.id, 0),
|
||||||
})
|
}
|
||||||
|
for org in organizations
|
||||||
return response
|
]
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
from apps.core.models import BaseModel
|
from apps.core.models import BaseModel
|
||||||
from apps.herd import models as herd_models
|
from apps.herd import models as herd_models
|
||||||
from apps.tag import models as tag_models
|
from apps.tag import models as tag_models
|
||||||
from django.db import models
|
|
||||||
|
|
||||||
|
|
||||||
class LiveStockSpecies(BaseModel): # noqa
|
class LiveStockSpecies(BaseModel): # noqa
|
||||||
@@ -53,6 +54,7 @@ class LiveStock(BaseModel):
|
|||||||
herd_models.Herd,
|
herd_models.Herd,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
related_name="live_stock_herd",
|
related_name="live_stock_herd",
|
||||||
|
db_index=True,
|
||||||
null=True
|
null=True
|
||||||
)
|
)
|
||||||
tag = models.ForeignKey(
|
tag = models.ForeignKey(
|
||||||
@@ -113,9 +115,9 @@ class TemporaryLiveStock(BaseModel):
|
|||||||
null=True
|
null=True
|
||||||
)
|
)
|
||||||
count = models.PositiveBigIntegerField(default=0)
|
count = models.PositiveBigIntegerField(default=0)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f'temporary: {self.id} - rancher: {self.rancher.national_code}'
|
return f'temporary: {self.id} - rancher: {self.rancher.national_code}'
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
return super(TemporaryLiveStock, self).save(*args, **kwargs)
|
return super(TemporaryLiveStock, self).save(*args, **kwargs)
|
||||||
|
|||||||
Reference in New Issue
Block a user