fix - improve excel reapopnse on transaction
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
from collections import defaultdict
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db import transaction
|
||||
from django.db.models.aggregates import Count
|
||||
|
||||
from apps.herd.models import Herd
|
||||
from apps.livestock.models import LiveStock
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Rebuild heavy/light counts for all herds"
|
||||
BATCH_SIZE = 2000
|
||||
|
||||
def handle(self, *args, **options):
|
||||
self.stdout.write("🔄 Rebuilding herd livestock counts...")
|
||||
|
||||
self.stdout.write("📊 Aggregating livestock data...")
|
||||
livestock_stats = (
|
||||
LiveStock.objects
|
||||
.filter(archive=False, herd__isnull=False)
|
||||
.values('herd_id', 'weight_type')
|
||||
.annotate(cnt=Count('id'))
|
||||
)
|
||||
|
||||
herd_map = defaultdict(lambda: {"H": 0, "L": 0})
|
||||
|
||||
for row in livestock_stats:
|
||||
herd_map[row['herd_id']][row['weight_type']] = row['cnt']
|
||||
|
||||
self.stdout.write(f"✅ Aggregated {len(herd_map)} herds")
|
||||
|
||||
self.stdout.write("✍️ Updating herds in batches...")
|
||||
|
||||
herd_ids = list(herd_map.keys())
|
||||
|
||||
for i in range(0, len(herd_ids), self.BATCH_SIZE):
|
||||
batch_ids = herd_ids[i:i + self.BATCH_SIZE]
|
||||
|
||||
herds = Herd.objects.filter(id__in=batch_ids)
|
||||
|
||||
for herd in herds:
|
||||
counts = herd_map.get(herd.id, {})
|
||||
herd.heavy_livestock_number = counts.get("H", 0)
|
||||
herd.light_livestock_number = counts.get("L", 0)
|
||||
|
||||
with transaction.atomic():
|
||||
Herd.objects.bulk_update(
|
||||
herds,
|
||||
['heavy_livestock_number', 'light_livestock_number']
|
||||
)
|
||||
|
||||
self.stdout.write(
|
||||
f"✔ Updated {i + len(batch_ids)} / {len(herd_ids)} herds"
|
||||
)
|
||||
|
||||
self.stdout.write("🎉 Herd livestock counts rebuilt successfully.")
|
||||
@@ -8,66 +8,10 @@ from apps.herd.models import RancherOrganizationLink, Herd
|
||||
from apps.livestock.models import LiveStock
|
||||
|
||||
|
||||
# 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:
|
||||
|
||||
def orgs_linked_rancher(self, org: Organization, org_type_key: str):
|
||||
|
||||
# --------------------------------------------------
|
||||
# 1. Resolve organization ids
|
||||
# --------------------------------------------------
|
||||
if org.type.key != 'ADM':
|
||||
org_ids = list(
|
||||
o.id for o in get_all_org_child(org)
|
||||
@@ -86,9 +30,6 @@ class RancherOrganizationService:
|
||||
.prefetch_related('service_area')
|
||||
)
|
||||
|
||||
# --------------------------------------------------
|
||||
# 2. Rancher count per organization
|
||||
# --------------------------------------------------
|
||||
rancher_counts = {
|
||||
r['organization_id']: r['cnt']
|
||||
for r in (
|
||||
@@ -99,9 +40,6 @@ class RancherOrganizationService:
|
||||
)
|
||||
}
|
||||
|
||||
# --------------------------------------------------
|
||||
# 3. Herd count per organization
|
||||
# --------------------------------------------------
|
||||
herd_counts = {
|
||||
r['organization_id']: r['cnt']
|
||||
for r in (
|
||||
@@ -112,12 +50,6 @@ class RancherOrganizationService:
|
||||
)
|
||||
}
|
||||
|
||||
# --------------------------------------------------
|
||||
# 4. Livestock count (optimized path)
|
||||
# LiveStockHerd -> Herd -> Org
|
||||
# --------------------------------------------------
|
||||
|
||||
# 4-1 livestock count per herd (NO JOIN, NO DISTINCT)
|
||||
livestock_per_herd = {
|
||||
row['herd_id']: row['cnt']
|
||||
for row in (
|
||||
@@ -127,7 +59,6 @@ class RancherOrganizationService:
|
||||
)
|
||||
}
|
||||
|
||||
# 4-2 sum livestock per organization
|
||||
livestock_counts = defaultdict(int)
|
||||
|
||||
herd_org_map = (
|
||||
@@ -146,9 +77,6 @@ class RancherOrganizationService:
|
||||
row['rancher__organization_links__organization_id']
|
||||
] += livestock_per_herd.get(row['id'], 0)
|
||||
|
||||
# --------------------------------------------------
|
||||
# 5. Final response
|
||||
# --------------------------------------------------
|
||||
return [
|
||||
{
|
||||
"id": org.id,
|
||||
|
||||
Reference in New Issue
Block a user