from apps.livestock.models import LiveStock, TemporaryLiveStock from decimal import Decimal from apps.herd.models import Rancher from apps.warehouse.models import ( InventoryEntry, InventoryQuotaSaleItem ) from django.db.models import Sum from apps.product.models import Quota, QuotaDistribution from apps.herd.services.rancher_service import RancherService from django.db.models import Count, Q import typing def get_rancher_statistics(rancher: Rancher = None) -> typing.Any: """ get statistics of a rancher """ # noqa livestocks = LiveStock.objects.filter(herd__rancher=rancher) # noqa temporary_livestock = TemporaryLiveStock.objects.filter(rancher=rancher) if livestocks: stats = livestocks.aggregate( herd_count=Count("herd", distinct=True), light_count=Count('id', filter=Q(weight_type='L')), heavy_count=Count('id', filter=Q(weight_type='H')), sheep=Count('id', filter=Q(type__name='گوسفند')), # noqa goat=Count('id', filter=Q(type__name='بز')), cow=Count('id', filter=Q(type__name='گاو')), camel=Count('id', filter=Q(type__name='شتر')), horse=Count('id', filter=Q(type__name='بز')), ) else: stats = temporary_livestock.aggregate( herd_count=0, light_count=Count('id', filter=Q(livestock_type__weight_type='L')), heavy_count=Count('id', filter=Q(livestock_type__weight_type='H')), sheep=Count('id', filter=Q(livestock_type__name='گوسفند')), # noqa goat=Count('id', filter=Q(livestock_type__name='بز')), cow=Count('id', filter=Q(livestock_type__name='گاو')), camel=Count('id', filter=Q(livestock_type__name='شتر')), horse=Count('id', filter=Q(livestock_type__name='بز')), ) return [{'name': key, 'value': value} for key, value in stats.items()], stats def rancher_quota_weight( rancher: Rancher, inventory_entry: InventoryEntry = None, distribution: QuotaDistribution = None ): """ :param rancher: Rancher instance :param inventory_entry: InventoryEntry instance :param distribution: QuotaDistribution instance :return: dict {total, by_type} """ live_stock_meta = { "گوسفند": "sheep", # noqa "بز": "goat", "گاو": "cow", "شتر": "camel", "اسب": "horse" } if inventory_entry: quota: Quota = inventory_entry.distribution.quota elif distribution: quota: Quota = distribution.quota else: quota: Quota = Quota() # list of quota live stock allocations allocations = list(quota.livestock_allocations.all().select_related('livestock_type')) # list of quota incentive plans incentive_plans = list(quota.incentive_assignments.all().select_related('livestock_type')) livestock_counts_list, livestock_counts_dict = get_rancher_statistics(rancher) total_weight = 0 merged = {} # calculate quota base weight by livestock type & base total weight for item in allocations: # noqa if item.livestock_type: animal_type_fa = item.livestock_type.name animal_type_en = item.livestock_type.en_name per_head = item.quantity_kg count = livestock_counts_dict.get(live_stock_meta.get(animal_type_fa), 0) weight = per_head * count total_weight += weight if animal_type_en not in merged: merged[animal_type_en] = { "name_fa": animal_type_fa, "weight": weight, "type": item.livestock_type.weight_type } else: merged[animal_type_en]['weight'] += weight # calculate rancher incentive plans weight by livestock type & add it to total_weight for item in incentive_plans: rancher_plans = item.incentive_plan.rancher_plans.select_related( 'rancher', 'livestock_type' ).filter(rancher=rancher, livestock_type=item.livestock_type) if rancher_plans.exists(): # multiple count of rancher livestock on incentive plan & # incentive plan quantity by this livestock type rancher_plan_weight = rancher_plans.first().allowed_quantity * item.quantity_kg total_weight += rancher_plan_weight # get rancher remaining usage of quota for purchase rancher_remaining_usage = RancherService.get_total_used_weight(rancher, InventoryQuotaSaleItem) return { "total_weight": total_weight, "remaining_weight": total_weight - rancher_remaining_usage, "by_type": [{ "name": key, "name_fa": value['name_fa'], "weight": value['weight'], "type": value['type'] } for key, value in merged.items()] }