from rest_framework import serializers from .models import LocationStatistics, LocationGroupStatistics class LocationStatisticsSerializer(serializers.ModelSerializer): """货位统计序列化器""" warehouse_display = serializers.CharField(source='warehouse_name', read_only=True) layer_display = serializers.SerializerMethodField() t5_group_count = serializers.SerializerMethodField() t4_group_count = serializers.SerializerMethodField() s4_group_count = serializers.SerializerMethodField() t2_group_count = serializers.SerializerMethodField() t1_group_count = serializers.SerializerMethodField() t5_used_group_count = serializers.SerializerMethodField() t4_used_group_count = serializers.SerializerMethodField() s4_used_group_count = serializers.SerializerMethodField() t2_used_group_count = serializers.SerializerMethodField() t1_used_group_count = serializers.SerializerMethodField() t5_available_group_count = serializers.SerializerMethodField() t4_available_group_count = serializers.SerializerMethodField() s4_available_group_count = serializers.SerializerMethodField() t2_available_group_count = serializers.SerializerMethodField() t1_available_group_count = serializers.SerializerMethodField() class Meta: model = LocationStatistics fields = [ 'id', 'warehouse_code', 'warehouse_name', 'warehouse_display', 'layer', 'layer_display', 't5_total', 't5_used', 't5_available', 't5_group_count', 't5_used_group_count', 't5_available_group_count', 't4_total', 't4_used', 't4_available', 't4_group_count', 't4_used_group_count', 't4_available_group_count', 's4_total', 's4_used', 's4_available', 's4_group_count', 's4_used_group_count', 's4_available_group_count', 't2_total', 't2_used', 't2_available', 't2_group_count', 't2_used_group_count', 't2_available_group_count', 't1_total', 't1_used', 't1_available', 't1_group_count', 't1_used_group_count', 't1_available_group_count', 'total_locations', 'total_used', 'total_available', 'utilization_rate', 'statistic_time', 'is_latest' ] def get_layer_display(self, obj): return f"{obj.layer}层" def get_t5_group_count(self, obj): return self._get_type_group_count(obj, 'T5') def get_t5_used_group_count(self, obj): return self._get_type_group_count(obj, 'T5', 'used') def get_t5_available_group_count(self, obj): return self._get_type_group_count(obj, 'T5', 'available') def get_t4_group_count(self, obj): return self._get_type_group_count(obj, 'T4') def get_t4_used_group_count(self, obj): return self._get_type_group_count(obj, 'T4', 'used') def get_t4_available_group_count(self, obj): return self._get_type_group_count(obj, 'T4', 'available') def get_s4_group_count(self, obj): return self._get_type_group_count(obj, 'S4') def get_s4_used_group_count(self, obj): return self._get_type_group_count(obj, 'S4', 'used') def get_s4_available_group_count(self, obj): return self._get_type_group_count(obj, 'S4', 'available') def get_t2_group_count(self, obj): return self._get_type_group_count(obj, 'T2') def get_t2_used_group_count(self, obj): return self._get_type_group_count(obj, 'T2', 'used') def get_t2_available_group_count(self, obj): return self._get_type_group_count(obj, 'T2', 'available') def get_t1_group_count(self, obj): return self._get_type_group_count(obj, 'T1') def get_t1_used_group_count(self, obj): return self._get_type_group_count(obj, 'T1', 'used') def get_t1_available_group_count(self, obj): return self._get_type_group_count(obj, 'T1', 'available') def _get_group_stats(self, obj): if not hasattr(self, '_group_stats_cache'): self._group_stats_cache = {} key = (obj.warehouse_code, obj.layer, obj.statistic_time) if key not in self._group_stats_cache: self._group_stats_cache[key] = list( LocationGroupStatistics.objects.filter( warehouse_code=obj.warehouse_code, layer=obj.layer, statistic_time=obj.statistic_time ) ) return self._group_stats_cache[key] def _get_type_group_count(self, obj, type_code, usage=None): group_stats = self._get_group_stats(obj) count = 0 for stat in group_stats: breakdown = stat.location_type_breakdown or {} type_info = breakdown.get(type_code, {}) if usage == 'used': if type_info.get('used', 0) > 0: count += 1 elif usage == 'available': if type_info.get('available', 0) > 0: count += 1 else: if type_info.get('total', 0) > 0: count += 1 return count class LocationGroupStatisticsSerializer(serializers.ModelSerializer): """货位组统计序列化器""" warehouse_display = serializers.CharField(source='warehouse_name', read_only=True) layer_display = serializers.SerializerMethodField() class Meta: model = LocationGroupStatistics fields = [ 'id', 'warehouse_code', 'warehouse_name', 'warehouse_display', 'layer', 'layer_display', 'location_group', 'total_locations', 'used_locations', 'available_locations', 'utilization_rate', 'location_type_breakdown', 'statistic_time' ] ordering = ['warehouse_code', 'layer', 'total_locations'] def get_layer_display(self, obj): return f"{obj.layer}层"