Files
Rasadyar_RSI/app/serializers.py
2026-01-18 11:29:19 +03:30

654 lines
26 KiB
Python

import datetime
from django.db.models import Sum, Avg, Count, Q
from rest_framework import serializers
from app.models import Poultry, PoultryHatching, TransportingChickenDetail, Hatching, TransportingDetail, KillHouse, \
ApkInfo, TransportCarcassDetail, Driver, Guilds, InquiryCredentials, AllProductsTransport, EvacuationDetail, \
RasadyarAppInfo
from authentication.models import Province, City
from helpers import build_calculation
class PoultrySerializer(serializers.ModelSerializer):
hatching = serializers.SerializerMethodField('get_hatching')
class Meta:
model = Poultry
fields = ['FirstName', 'LastName', 'Mobile', 'UnitName', 'EpidemiologicCode', 'SystemCode', 'TrackingCode',
'UnitIsActiveDescription', 'RegDateShamsi', 'LocationNameProvince', 'LocationNameCity', 'hatching']
def get_hatching(self, instance):
hatching = PoultryHatching.objects.filter(poultry=instance)
total_amount = build_calculation(queryset=hatching, column_name='BaseHatchingCount', aggregate_func=Sum)
EvacuationCount = build_calculation(queryset=hatching, column_name='EvacuationCount', aggregate_func=Sum)
LeftOver = build_calculation(queryset=hatching, column_name='LeftOver', aggregate_func=Sum)
return {
"totalAmount": total_amount,
"losses": EvacuationCount,
"LeftOver": LeftOver,
}
# class TransportingForHatchingSerializer(serializers.ModelSerializer):
# class Meta:
# model = TransportingChickenDetail
# fields = '__all__'
class PoultryHatchingSerializer(serializers.ModelSerializer):
# bars = serializers.SerializerMethodField('get_bars')
age = serializers.SerializerMethodField('get_age')
class Meta:
model = PoultryHatching
fields = '__all__'
# def get_bars(self, obj):
# transports = TransportingChickenDetail.objects.filter(trash=False, hatching=obj)
# serializer = TransportingForHatchingSerializer(transports, many=True)
# return serializer.data
def get_age(self, obj):
age = (datetime.datetime.now().date() - obj.Date.date()).days + 1
return age
class HatchingsSerializer(serializers.ModelSerializer):
class Meta:
model = Hatching
fields = '__all__'
class TransportingChickenDetailSerializer(serializers.ModelSerializer):
hatching = PoultryHatchingSerializer(read_only=True)
killing_age = serializers.SerializerMethodField('get_killing_age')
class Meta:
model = TransportingChickenDetail
fields = '__all__'
def get_killing_age(self, obj):
age = (obj.reside_date.date() - obj.hatching.Date.date()).days + 1
return age
class HatchingSerializer(serializers.ModelSerializer):
class Meta:
model = PoultryHatching
fields = '__all__'
class TransportingSerializer(serializers.ModelSerializer):
class Meta:
model = TransportingDetail
fields = '__all__'
class HatchingCalculationSerializer(serializers.ModelSerializer):
class Meta:
model = PoultryHatching
fields = ['EvacuationCount', 'LocationNameCity', 'LocationNameProvince', 'poultry']
class PoultryInfoSerializer(serializers.ModelSerializer):
info = serializers.SerializerMethodField('get_info')
class Meta:
model = Poultry
fields = ['key', 'FirstName', 'LastName', 'Mobile', 'EpidemiologicCode', 'UnitId', 'SystemCode', 'UnitName',
'UnitIsActive',
'RegDateShamsi', 'info', 'LocationNameCity', 'LocationNameProvince', 'UserIsActiveDescription',
'Province', 'City']
def get_info(self, obj):
hatchings = Hatching.objects.filter(poultry=obj, trash=False)
total_hatching = hatchings.aggregate(total=Sum('ChickCountSum'))['total'] or 0
total_leftover = hatchings.aggregate(total=Sum('LeftOver'))['total'] or 0
total_evacuation = hatchings.aggregate(total=Sum('Evacuation'))['total'] or 0
transports = TransportingDetail.objects.filter(hatching__in=hatchings, trash=False)
total_killing = transports.aggregate(total=Sum('GoodAmount'))['total'] or 0
total_left_over_percent = round((total_leftover / total_hatching) * 100, 2) if total_hatching > 0 else 0
total_evacuation_percent = round((total_evacuation / total_hatching) * 100, 2) if total_hatching > 0 else 0
total_killing_percent = round((total_killing / total_hatching) * 100, 2) if total_hatching > 0 else 0
return {
"count_hatching": len(hatchings),
"total_hatching": total_hatching,
"total_leftover": total_leftover,
"total_evacuation": total_evacuation,
"total_left_over_percent": total_left_over_percent,
"total_evacuation_percent": total_evacuation_percent,
"total_killing_percent": total_killing_percent,
"total_killing": total_killing,
"cars_count": len(transports),
"total_cars": total_killing,
"capacity": hatchings.last().CapacityFemale if hatchings else 0,
}
class PoultryForHatchingDetailSerializer(serializers.ModelSerializer):
class Meta:
model = Poultry
fields = ['City', 'Province', 'FirstName', 'LastName', 'UnitName']
class HatchingDetailSerializer(serializers.ModelSerializer):
info = serializers.SerializerMethodField('get_info')
poultry = PoultryForHatchingDetailSerializer(read_only=True)
class Meta:
model = Hatching
fields = ['Date', 'Age', 'KillingAve', 'info', 'CertId',
'RequestCode', 'ChickCountSum', 'Period', 'CapacityFemale', 'LeftOver', 'Evacuation',
'poultry', 'PedigreeName']
def get_info(self, obj):
capacity = obj.CapacityFemale if obj.CapacityFemale else 0
transports = TransportingDetail.objects.filter(hatching=obj, trash=False)
average_slaughter_age = transports.aggregate(avg_age=Avg('Age'))['avg_age'] or 0
load_volume = transports.aggregate(total=Sum('GoodAmount'))['total'] or 0
percent_hatching_license = (capacity / obj.ChickCountSum) * 100
return {
"average_slaughter_age": average_slaughter_age,
"load_volume": load_volume,
"number_loads": len(transports),
"percent_hatching_license": round(percent_hatching_license, 2)
}
class HatchingForUpdateSerializer(serializers.ModelSerializer):
poultry = PoultryInfoSerializer(read_only=True)
EvacuationDetail = serializers.SerializerMethodField()
class Meta:
model = Hatching
fields = '__all__'
def get_EvacuationDetail(self, obj):
queryset = EvacuationDetail.objects.filter(hatching=obj, trash=False)
return EvacuationDetailSerializer(queryset, many=True).data
class PoultryDetailSerializerForTransport(serializers.ModelSerializer):
class Meta:
model = Poultry
fields = ['UnitId', 'PartIdCode', 'Province', 'City', 'UnitName', 'Mobile']
class HatchingDetailSerializerForTransport(serializers.ModelSerializer):
poultry = PoultryDetailSerializerForTransport(read_only=True)
class Meta:
model = Hatching
fields = ['PartIdCode', 'poultry', 'RequestCode', 'PedigreeName']
class TransportingDetailSerializer(serializers.ModelSerializer):
hatching = HatchingDetailSerializerForTransport(read_only=True)
location_kill_house = serializers.SerializerMethodField('get_location_kill_house')
location_poultry = serializers.SerializerMethodField('get_location_poultry')
class Meta:
model = TransportingDetail
fields = ['TrackingCode', 'hatching', 'ResideDatePersian', 'DesUnitName', 'DesPartIdCode', 'Province', 'City',
'GoodAmount',
'TrackingStatusDescription', 'SourceUnitName', 'Age', 'PedigreeName', 'Date', 'Out',
'location_kill_house',
'location_poultry']
def get_location_kill_house(self, obj):
resul = {}
province_kill_house = Province.objects.filter(name=obj.Province).first()
city_kill_house = City.objects.filter(name=obj.City).first()
if province_kill_house:
resul.update({
"provinceLat": province_kill_house.Lat,
"provinceLng": province_kill_house.Lng
})
if city_kill_house:
resul.update({
"cityLat": city_kill_house.Lat,
"cityLng": city_kill_house.Lng
})
return resul
def get_location_poultry(self, obj):
resul = {}
if obj.hatching:
province_kill_house = Province.objects.filter(name=obj.hatching.ProvinceName).first()
city_kill_house = City.objects.filter(name=obj.hatching.CityName).first()
if province_kill_house:
resul.update({
"provinceLat": province_kill_house.Lat,
"provinceLng": province_kill_house.Lng
})
if city_kill_house:
resul.update({
"cityLat": city_kill_house.Lat,
"cityLng": city_kill_house.Lng
})
return resul
class KillHouseSerializer(serializers.ModelSerializer):
info = serializers.SerializerMethodField('get_info')
class Meta:
model = KillHouse
fields = '__all__'
def get_info(self, obj):
# Use pre-computed cache if available (optimization to avoid N+1 queries)
info_cache = self.context.get('info_cache')
if info_cache and obj.PartIdCode in info_cache:
return info_cache[obj.PartIdCode]
# Fallback to original query-based approach if cache not available
request = self.context.get('request')
date1 = request.GET.get('date1') or None
date2 = request.GET.get('date2') or None
bars = TransportingDetail.objects.filter(DesPartIdCode=obj.PartIdCode, trash=False).only('GoodAmount', 'Out', 'Date')
if date1:
date1 = datetime.datetime.strptime(str(date1), '%Y-%m-%d').date()
date2 = datetime.datetime.strptime(str(date2), '%Y-%m-%d').date()
bars = bars.filter(Date__date__gte=date1, Date__date__lte=date2)
aggregation = bars.aggregate(
total=Sum('GoodAmount'),
input_total=Sum('GoodAmount', filter=Q(Out=False)),
output_total=Sum('GoodAmount', filter=Q(Out=True)),
input_count=Count('id', filter=Q(Out=False)),
output_count=Count('id', filter=Q(Out=True)),
total_count=Count('id')
)
all_products = AllProductsTransport.objects.filter(
jihadi_origin=obj.PartIdCode,
trash=False
).only('quantity', 'out', 'date', 'unloading_date')
if date1:
all_products = all_products.filter(
Q(
date__gte=date1,
date__lte=date2,
date__isnull=False
) |
Q(
unloading_date__gte=date1,
unloading_date__lte=date2,
date__isnull=True
)
)
all_products_aggregation = all_products.aggregate(
total=Sum('quantity'),
input_total=Sum('quantity', filter=Q(out=False)),
output_total=Sum('quantity', filter=Q(out=True)),
input_count=Count('id', filter=Q(out=False)),
output_count=Count('id', filter=Q(out=True)),
total_count=Count('id')
)
aggregation['total'] = (aggregation.get('total') or 0) + (all_products_aggregation.get('total') or 0)
aggregation['input_total'] = (aggregation.get('input_total') or 0) + (all_products_aggregation.get('input_total') or 0)
aggregation['output_total'] = (aggregation.get('output_total') or 0) + (all_products_aggregation.get('output_total') or 0)
aggregation['input_count'] = (aggregation.get('input_count') or 0) + (all_products_aggregation.get('input_count') or 0)
aggregation['output_count'] = (aggregation.get('output_count') or 0) + (all_products_aggregation.get('output_count') or 0)
aggregation['total_count'] = (aggregation.get('total_count') or 0) + (all_products_aggregation.get('total_count') or 0)
total_count = aggregation['total_count'] or 0
total_bars_quantity = aggregation['total'] or 0
total_input_bars_quantity = aggregation['input_total'] or 0
total_output_bars_quantity = aggregation['output_total'] or 0
input_bars_count = aggregation['input_count'] or 0
output_bars_count = aggregation['output_count'] or 0
if total_count > 0:
total_input_bars_percent = round((input_bars_count / total_count) * 100, 1)
total_output_bars_percent = round((output_bars_count / total_count) * 100, 1)
else:
total_input_bars_percent = 0
total_output_bars_percent = 0
return {
"bars": total_count,
"total_bars_quantity": total_bars_quantity,
"input_bars": input_bars_count,
"total_input_bars_quantity": total_input_bars_quantity,
"total_input_bars_percent": total_input_bars_percent,
"output_bars": output_bars_count,
"total_output_bars_quantity": total_output_bars_quantity,
"total_output_bars_percent": total_output_bars_percent,
}
class TransportingDetailForUpdateSerializer(serializers.ModelSerializer):
hatching = HatchingDetailSerializerForTransport(read_only=True)
class Meta:
model = TransportingDetail
fields = '__all__'
class HatchingAnalysisSerializer(serializers.ModelSerializer):
class Meta:
model = Hatching
fields = ['CityName', 'ProvinceName', 'PedigreeName']
class HatchingAnalysisSerializerTwo(serializers.ModelSerializer):
class Meta:
model = Hatching
fields = ['CityName', 'ProvinceName']
class TransportingReportDashboard(serializers.ModelSerializer):
class Meta:
model = TransportingDetail
fields = ['age', 'Province', 'City']
class TransportingForClearanceCodeSerializer(serializers.ModelSerializer):
hatching = HatchingDetailSerializerForTransport(read_only=True)
class Meta:
model = TransportingDetail
fields = '__all__'
class ApkInfoSerializer(serializers.ModelSerializer):
class Meta:
model = ApkInfo
fields = ['key', 'info', 'download_link']
class TransportCarcassDetailSerializer(serializers.ModelSerializer):
class Meta:
model = TransportCarcassDetail
fields = '__all__'
class DriverSerializer(serializers.ModelSerializer):
class Meta:
model = Driver
fields = '__all__'
class KillHouseForTransportCarcassSerializer(serializers.ModelSerializer):
info = serializers.SerializerMethodField('get_info')
class Meta:
model = KillHouse
fields = '__all__'
def get_info(self, obj):
bars_dict = self.context.get('bars_dict', {})
buy_dict = self.context.get('buy_dict', {})
bars_data = bars_dict.get(obj.PartIdCode, {})
buy_data = buy_dict.get(obj.PartIdCode, {})
total_count = bars_data.get('total_count', 0) or 0
total_bars_quantity = bars_data.get('total', 0) or 0
total_input_bars_quantity = bars_data.get('input_total', 0) or 0
total_output_bars_quantity = bars_data.get('output_total', 0) or 0
input_bars_count = bars_data.get('input_count', 0) or 0
output_bars_count = bars_data.get('output_count', 0) or 0
buy_input_total = buy_data.get('input_total', 0) or 0
buy_output_total = buy_data.get('output_total', 0) or 0
buy_input_count = buy_data.get('input_count', 0) or 0
buy_output_count = buy_data.get('output_count', 0) or 0
if total_count > 0 and (total_input_bars_quantity + total_output_bars_quantity) > 0:
total_input_bars_percent = round(
(total_input_bars_quantity / (total_input_bars_quantity + total_output_bars_quantity)) * 100, 1
)
total_output_bars_percent = round(
(total_output_bars_quantity / (total_input_bars_quantity + total_output_bars_quantity)) * 100, 1
)
else:
total_input_bars_percent = 0
total_output_bars_percent = 0
return {
"role": 'کشتارگاه',
"bars": int(total_count),
"total_bars_wight": int(total_bars_quantity),
"input_bars": int(input_bars_count),
"total_input_bars_wight": int(total_input_bars_quantity),
"total_input_buy_bars_wight": int(((buy_input_total) * 2.5) * 0.75),
"total_input_bars_percent": total_input_bars_percent,
"output_bars": int(output_bars_count),
"total_output_bars_wight": int(total_output_bars_quantity),
"total_output_buy_bars_wight": int(((buy_output_total) * 2.5) * 0.75),
"total_output_bars_percent": total_output_bars_percent,
"total_ware_house": int(((buy_input_total * 2.5) * 0.75) + ((buy_output_total * 2.5) * 0.75)),
"total_input_buy_bars_count": int(buy_input_count),
"total_output_buy_bars_count": int(buy_output_count),
}
class StewardForTransportCarcassSerializer(serializers.ModelSerializer):
info = serializers.SerializerMethodField()
class Meta:
model = Guilds
fields = '__all__'
def get_info(self, obj):
bars_dict = self.context.get('bars_dict', {})
row = bars_dict.get(obj.jihadi_code, {})
total_count = row.get('total_count', 0) or 0
total_bars_quantity = row.get('total', 0) or 0
total_input_bars_quantity = row.get('input_total', 0) or 0
total_output_bars_quantity = row.get('output_total', 0) or 0
input_bars_count = row.get('input_count', 0) or 0
output_bars_count = row.get('output_count', 0) or 0
total_input_buy_bars_wight = row.get('total_input_buy_bars_wight', 0) or 0
total_output_buy_bars_wight = row.get('total_output_buy_bars_wight', 0) or 0
total_input_buy_bars_count = row.get('total_input_buy_bars_count', 0) or 0
total_output_buy_bars_count = row.get('total_output_buy_bars_count', 0) or 0
total_ware_house = total_input_buy_bars_wight + total_output_buy_bars_wight
if total_count > 0:
total_input_bars_percent = round(
(total_input_bars_quantity / (total_input_bars_quantity + total_output_bars_quantity)) * 100, 1
)
total_output_bars_percent = round(
(total_output_bars_quantity / (total_input_bars_quantity + total_output_bars_quantity)) * 100, 1
)
else:
total_input_bars_percent = 0
total_output_bars_percent = 0
return {
"role": 'مباشر',
"bars": int(total_count),
"total_bars_wight": int(total_bars_quantity),
"input_bars": int(input_bars_count),
"total_input_bars_wight": int(total_input_bars_quantity),
"total_input_buy_bars_wight": int(total_input_buy_bars_wight),
"total_input_bars_percent": total_input_bars_percent,
"output_bars": int(output_bars_count),
"total_output_bars_wight": int(total_output_bars_quantity),
"total_output_buy_bars_wight": int(total_output_buy_bars_wight),
"total_output_bars_percent": total_output_bars_percent,
"total_ware_house": int(total_ware_house),
"total_input_buy_bars_count": int(total_input_buy_bars_count),
"total_output_buy_bars_count": int(total_output_buy_bars_count),
}
class GuildsForTransportCarcassSerializer(serializers.ModelSerializer):
info = serializers.SerializerMethodField('get_info')
class Meta:
model = Guilds
fields = '__all__'
def get_info(self, obj):
bars_dict = self.context.get('bars_dict', {})
data = bars_dict.get(obj.jihadi_code, None)
if not data:
return {
"role": 'صنف',
"total_input_buy_bars_wight": 0,
"total_output_buy_bars_wight": 0,
"total_ware_house": 0,
"total_input_buy_bars_percent": 0,
"total_output_buy_bars_percent": 0,
"total_input_buy_bars_count": 0,
"total_output_buy_bars_count": 0,
}
total_input = data['total_input_buy_bars_wight'] or 0
total_output = data['total_output_buy_bars_wight'] or 0
total_wh = data['total_ware_house'] or 0
total_count = data['total_count'] or 0
if total_count > 0 and total_wh > 0:
total_input_percent = round((total_input / total_wh) * 100, 1)
total_output_percent = round((total_output / total_wh) * 100, 1)
else:
total_input_percent = 0
total_output_percent = 0
return {
"role": 'صنف',
"total_input_buy_bars_wight": int(total_input),
"total_output_buy_bars_wight": int(total_output),
"total_ware_house": int(total_wh),
"total_input_buy_bars_percent": total_input_percent,
"total_output_buy_bars_percent": total_output_percent,
"total_input_buy_bars_count": int(data['total_count_input_buy'] or 0),
"total_output_buy_bars_count": int(data['total_count_output_buy'] or 0),
}
class KillHouseForTransportCarcassForRassadyaarSerializer(serializers.ModelSerializer):
info = serializers.SerializerMethodField('get_info')
class Meta:
model = KillHouse
fields = '__all__'
def get_info(self, obj):
bars_dict = self.context.get('bars_dict', {})
buy_dict = self.context.get('buy_dict', {})
bars_data = bars_dict.get(obj.PartIdCode, {})
buy_data = buy_dict.get(obj.PartIdCode, {})
total_count = bars_data.get('total_count', 0) or 0
total_bars_quantity = bars_data.get('total', 0) or 0
total_input_bars_quantity = bars_data.get('input_total', 0) or 0
total_output_bars_quantity = bars_data.get('output_total', 0) or 0
input_bars_count = bars_data.get('input_count', 0) or 0
output_bars_count = bars_data.get('output_count', 0) or 0
buy_input_total = buy_data.get('input_total', 0) or 0
buy_output_total = buy_data.get('output_total', 0) or 0
buy_input_count = buy_data.get('input_count', 0) or 0
buy_output_count = buy_data.get('output_count', 0) or 0
if total_count > 0 and (total_input_bars_quantity + total_output_bars_quantity) > 0:
total_input_bars_percent = round(
(total_input_bars_quantity / (total_input_bars_quantity + total_output_bars_quantity)) * 100, 1
)
total_output_bars_percent = round(
(total_output_bars_quantity / (total_input_bars_quantity + total_output_bars_quantity)) * 100, 1
)
else:
total_input_bars_percent = 0
total_output_bars_percent = 0
return {
"bars": int(total_count),
"total_bars_wight": int(total_bars_quantity),
"input_bars": int(input_bars_count),
"total_input_bars_wight": int(total_input_bars_quantity),
"total_input_buy_bars_wight": int(buy_input_total),
"total_input_bars_percent": total_input_bars_percent,
"output_bars": int(output_bars_count),
"total_output_bars_wight": int(total_output_bars_quantity),
"total_output_buy_bars_wight": int(buy_output_total),
"total_output_bars_percent": total_output_bars_percent,
"total_ware_house": int(buy_input_total) + int(buy_output_total),
"total_input_buy_bars_count": int(buy_input_count),
"total_output_buy_bars_count": int(buy_output_count),
}
class InquiryCredentialsSerializer(serializers.ModelSerializer):
class Meta:
model = InquiryCredentials
fields = '__all__'
class AllProductsTransportSerializer(serializers.ModelSerializer):
hatching = HatchingDetailSerializerForTransport(read_only=True)
class Meta:
model = AllProductsTransport
fields = '__all__'
class EvacuationDetailSerializer(serializers.ModelSerializer):
class Meta:
model = EvacuationDetail
fields = '__all__'
class RasadyarAppInfoSerializer(serializers.ModelSerializer):
class Meta:
model = RasadyarAppInfo
fields = '__all__'
class AllProductsTransportCustomSerializer(serializers.ModelSerializer):
location_origin = serializers.SerializerMethodField('get_location_origin')
location_destination = serializers.SerializerMethodField('get_location_destination')
class Meta:
model = AllProductsTransport
fields = '__all__'
def get_location_origin(self, obj):
resul = {}
province_origin = Province.objects.filter(name=obj.origin_province).first()
city_origin = City.objects.filter(name=obj.origin_city).first()
if province_origin:
resul.update({
"provinceLat": province_origin.Lat,
"provinceLng": province_origin.Lng
})
if city_origin:
resul.update({
"cityLat": city_origin.Lat,
"cityLng": city_origin.Lng
})
return resul
def get_location_destination(self, obj):
resul = {}
province_destination = Province.objects.filter(name=obj.destination_province).first()
city_destination = City.objects.filter(name=obj.destination_city).first()
if province_destination:
resul.update({
"provinceLat": province_destination.Lat,
"provinceLng": province_destination.Lng
})
if city_destination:
resul.update({
"cityLat": city_destination.Lat,
"cityLng": city_destination.Lng
})
return resul