from rest_framework import serializers from django.utils.translation import gettext_lazy as _ from ..models import HadisSect, HadisCategory, Hadis class HadisCategorySectListSerializer(serializers.ModelSerializer): """Serializer for HadisSect list with grouped response""" source_types = serializers.SerializerMethodField() class Meta: model = HadisSect fields = ['id', 'title', 'description', 'source_types'] def get_source_types(self, obj): """Get unique source types for this sect's categories""" source_types = HadisCategory.objects.filter( sect=obj ).values_list('source_type', flat=True).distinct() return list(source_types) class HadisCategoryTreeSerializer(serializers.ModelSerializer): """Serializer for HadisCategory tree structure""" sect_id = serializers.IntegerField(source='sect.id', read_only=True) sect_type = serializers.CharField(source='sect.sect_type', read_only=True) children = serializers.SerializerMethodField() class Meta: model = HadisCategory fields = ['id', 'title', 'source_type', 'sect_id', 'sect_type', 'children'] def get_name(self, obj): """Get category name based on request language""" request = self.context.get('request') language_code = getattr(request, 'LANGUAGE_CODE', 'en') return obj.get_translation(language_code) if hasattr(obj, 'get_translation') else obj.title def get_children(self, obj): """Get active children categories that have children or hadis""" children = obj.get_children().filter(sect=obj.sect).order_by('order') # Filter children that have either children or hadis filtered_children = [] for child in children: has_children = child.get_children().filter(sect=obj.sect).exists() has_hadis = Hadis.objects.filter(category=child, status=True).exists() if has_children or has_hadis: filtered_children.append(child) return [self.to_dict(cat) for cat in filtered_children] def get_hadis_count(self, obj): """Get total hadis count including children categories""" # Get direct hadis count direct_count = Hadis.objects.filter(category=obj, status=True).count() # Get hadis count from all descendants descendants = obj.get_descendants().filter(sect=obj.sect) descendant_count = 0 for descendant in descendants: descendant_count += Hadis.objects.filter(category=descendant, status=True).count() return direct_count + descendant_count def get_has_hadis(self, obj): """Check if category can have hadis (no active children) and has hadis""" # Check if category has active children has_active_children = obj.get_children().filter(sect=obj.sect).exists() # If has active children, cannot have hadis if has_active_children: return False # If no active children, check if has hadis return Hadis.objects.filter(category=obj, status=True).exists() def get_xmind_file(self, obj): """Get absolute URL for xmind file""" if obj.xmind_file: request = self.context.get('request') if request: return request.build_absolute_uri(obj.xmind_file.url) return obj.xmind_file.url return None def get_has_xmind_file(self, obj): """Check if category has xmind file""" return bool(obj.xmind_file) def get_thumbnail(self, obj): """Get absolute URL for thumbnail""" if hasattr(obj, 'thumbnail') and obj.thumbnail: request = self.context.get('request') if request: return request.build_absolute_uri(obj.thumbnail.url) return obj.thumbnail.url return None def get_hadis_index(self, obj): """Get list of hadis numbers in this category (not including children)""" return list( Hadis.objects.filter( category=obj, status=True ).order_by('number').values_list('number', flat=True) ) def to_dict(self, c): """Convert category to dictionary""" children = c.get_children().filter(sect=c.sect).order_by('order') filtered_children = [] for child in children: has_children = child.get_children().filter(sect=c.sect).exists() has_hadis = Hadis.objects.filter(category=child, status=True).exists() if has_children or has_hadis: filtered_children.append(child) return { 'id': c.id, 'name': self.get_name(c), 'description': c.description, 'hadis_count': self.get_hadis_count(c), 'has_hadis': self.get_has_hadis(c), 'hadis_index': self.get_hadis_index(c) if self.get_has_hadis(c) else [], 'order': c.order, 'thumbnail': self.get_thumbnail(c), 'xmind_file': self.get_xmind_file(c), 'has_xmind_file': self.get_has_xmind_file(c), 'children': [] if not filtered_children else [self.to_dict(i) for i in filtered_children], }