129 lines
4.8 KiB
Python
129 lines
4.8 KiB
Python
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()]
|
|
}
|