From 9d9d4d3b80041baa7e1b8f3fec737663a279f043 Mon Sep 17 00:00:00 2001 From: Mojtaba-z Date: Sat, 30 Aug 2025 16:09:37 +0330 Subject: [PATCH] rancher quota statistics including livestock allocations & incentive plan assignments --- apps/herd/services.py | 3 -- apps/herd/services/services.py | 63 ++++++++++++++++++++++++------- apps/product/models.py | 21 +++++++++++ apps/product/services/services.py | 5 ++- 4 files changed, 75 insertions(+), 17 deletions(-) delete mode 100644 apps/herd/services.py diff --git a/apps/herd/services.py b/apps/herd/services.py deleted file mode 100644 index a572473..0000000 --- a/apps/herd/services.py +++ /dev/null @@ -1,3 +0,0 @@ -# Your services go here - - diff --git a/apps/herd/services/services.py b/apps/herd/services/services.py index 3b4e15b..c876006 100644 --- a/apps/herd/services/services.py +++ b/apps/herd/services/services.py @@ -51,23 +51,60 @@ def rancher_quota_weight(rancher, inventory_entry: InventoryEntry): } quota: Quota = inventory_entry.distribution.quota - allocations = quota.livestock_allocations.all() + allocations = quota.livestock_allocations.all() # list of quota live stock allocations livestock_counts = get_rancher_statistics(rancher) total_weight = 0 - details = {} + alloc_details = {} + plan_details = {} + result_list = [] - for alloc in allocations: - animal_type = alloc.livestock_type.name - per_head = alloc.quantity_kg - count = livestock_counts.get(live_stock_meta.get(animal_type), 0) + # list of quota allocations, get allocations weight on any animal type + for alloc in allocations: # noqa + if alloc.livestock_type: + animal_type = alloc.livestock_type.name + per_head = alloc.quantity_kg + count = livestock_counts.get(live_stock_meta.get(animal_type), 0) - weight = per_head * count - details[animal_type] = {"weight": weight, "type": alloc.livestock_type.weight_type} - total_weight += weight + weight = per_head * count + alloc_details[animal_type] = {"weight": weight, "type": alloc.livestock_type.weight_type} + total_weight += weight - return { - "total": total_weight, - "by_type": details - } + # list of quota incentive plans, get plans weight on any animal type + incentive_plans = quota.incentive_assignments.all() + for plan in incentive_plans: # noqa + if plan.livestock_type: + animal_type = plan.livestock_type.name + per_head = plan.quantity_kg + count = livestock_counts.get(live_stock_meta.get(animal_type), 0) + + weight = per_head * count + plan_details[animal_type] = {"weight": weight, "type": plan.livestock_type.weight_type} + total_weight += weight + + # summation of incentive plans & livestock allocations animal types weight + result_details = {"total": total_weight, 'by_type': {}} + all_keys = set(alloc_details.keys()) | set(plan_details.keys()) # get all keys from plan & allocations data + + for key in all_keys: + alloc_weight = alloc_details.get(key, {}).get("weight", 0) # total weight of quota livestock allocations data + plan_weight = plan_details.get(key, {}).get("weight", 0) # total weight of quota incentive plan data + + # get animal type (Heavy, Light) + animal_type = alloc_details.get( + key, {} + ).get("type") or plan_details.get( + key, {} + ).get("type") + + # final result, total weights + result_list.append({ + "name": key, + "weight": alloc_weight + plan_weight, + "type": animal_type + }) + + result_details['by_type'] = result_list + + return result_details diff --git a/apps/product/models.py b/apps/product/models.py index 1ce656e..3d68997 100644 --- a/apps/product/models.py +++ b/apps/product/models.py @@ -457,10 +457,31 @@ class QuotaIncentiveAssignment(BaseModel): ) quantity_kg = models.PositiveBigIntegerField(default=0) + def calculate_heavy_value(self): + """ calculate total livestock heavy value of incentive plans """ + heavy_weight = QuotaIncentiveAssignment.objects.filter( + quota=self.quota, livestock_type__weight_type='H' + ).aggregate(total=models.Sum('quantity_kg'))['total'] or 0 + + self.heavy_value = heavy_weight + self.save() + + def calculate_light_value(self): + """ calculate total livestock light value of incentive plans """ + + heavy_weight = QuotaIncentiveAssignment.objects.filter( + quota=self.quota, livestock_type__weight_type='L' + ).aggregate(total=models.Sum('quantity_kg'))['total'] or 0 + + self.heavy_value = heavy_weight + self.save() + def __str__(self): return f"Quota ({self.quota.id}) for {self.incentive_plan.name}" def save(self, *args, **kwargs): + self.calculate_heavy_value() + self.calculate_heavy_value() return super(QuotaIncentiveAssignment, self).save(*args, **kwargs) diff --git a/apps/product/services/services.py b/apps/product/services/services.py index bae851c..0b7d22b 100644 --- a/apps/product/services/services.py +++ b/apps/product/services/services.py @@ -41,7 +41,10 @@ def quota_incentive_plans_info(quota: Quota) -> typing.Any: incentive_plans_list = [{ 'name': plan.incentive_plan.name, 'heavy_value': plan.heavy_value, - 'light_value': plan.light_value + 'light_value': plan.light_value, + 'livestock_type': plan.livestock_type.name if plan.livestock_type else "", + 'livestock_weight_type': plan.livestock_type.weight_type if plan.livestock_type else "", + 'quantity_kg': plan.quantity_kg } for plan in incentive_plans] return incentive_plans_list