from django.contrib.auth import get_user_model from rest_framework import serializers from drf_spectacular.utils import extend_schema_field from apps.profiles.models.institution import ( Institution, InstitutionMember, InstitutionTimeline, InstitutionMedia, InstitutionFollower, ) User = get_user_model() class InstitutionTimelineSerializer(serializers.ModelSerializer): class Meta: model = InstitutionTimeline fields = [ 'id', 'institution', 'year', 'title', 'description', 'order', 'created_at', ] read_only_fields = ['id', 'institution', 'created_at'] class InstitutionMediaSerializer(serializers.ModelSerializer): media_type_display = serializers.CharField(source='get_media_type_display', read_only=True) class Meta: model = InstitutionMedia fields = [ 'id', 'institution', 'file', 'media_type', 'media_type_display', 'title', 'caption', 'uploaded_at', ] read_only_fields = ['id', 'institution', 'uploaded_at', 'media_type_display'] class MemberUserMiniSerializer(serializers.ModelSerializer): class Meta: model = User fields = ['id', 'email', 'fullname', 'avatar', 'phone_number'] read_only_fields = ['id', 'email', 'fullname', 'avatar', 'phone_number'] class InstitutionMemberSerializer(serializers.ModelSerializer): user = MemberUserMiniSerializer(read_only=True) role_display = serializers.CharField(source='get_role_display', read_only=True) class Meta: model = InstitutionMember fields = [ 'id', 'institution', 'user', 'role', 'role_display', 'title', 'joined_at', ] read_only_fields = ['id', 'institution', 'role_display', 'joined_at'] class InstitutionMemberAddSerializer(serializers.Serializer): email = serializers.EmailField(required=True) role = serializers.ChoiceField( choices=InstitutionMember.MemberRole.choices, default=InstitutionMember.MemberRole.VIEWER ) title = serializers.CharField(required=False, allow_blank=True, max_length=150) def validate_email(self, value): normalized = value.strip().lower() if not User.objects.filter(email__iexact=normalized).exists(): raise serializers.ValidationError("No registered user found with this email address.") return normalized class InstitutionListSerializer(serializers.ModelSerializer): type_display = serializers.CharField(source='get_type_display', read_only=True) verification_status_display = serializers.CharField(source='get_verification_status_display', read_only=True) is_following = serializers.SerializerMethodField() class Meta: model = Institution fields = [ 'id', 'name', 'slug', 'type', 'type_display', 'country', 'city', 'address', 'latitude', 'longitude', 'avatar', 'cover_image', 'verification_status', 'verification_status_display', 'follower_count', 'is_featured', 'tags', 'is_following', 'created_at', ] read_only_fields = fields @extend_schema_field(serializers.BooleanField) def get_is_following(self, obj) -> bool: request = self.context.get('request') if not request or not request.user.is_authenticated: return False return obj.is_followed_by(request.user) class InstitutionDetailSerializer(serializers.ModelSerializer): type_display = serializers.CharField(source='get_type_display', read_only=True) verification_status_display = serializers.CharField(source='get_verification_status_display', read_only=True) timeline_entries = InstitutionTimelineSerializer(many=True, read_only=True) media_items = InstitutionMediaSerializer(many=True, read_only=True) members_count = serializers.SerializerMethodField() is_following = serializers.SerializerMethodField() user_role = serializers.SerializerMethodField() created_by_email = serializers.EmailField(source='created_by.email', read_only=True, allow_null=True) class Meta: model = Institution fields = [ 'id', 'name', 'slug', 'type', 'type_display', 'country', 'city', 'address', 'latitude', 'longitude', 'description', 'website', 'email', 'phone', 'established_year', 'cover_image', 'avatar', 'social_media', 'working_hours', 'tags', 'verification_status', 'verification_status_display', 'follower_count', 'is_featured', 'is_active', 'created_by_email', 'members_count', 'is_following', 'user_role', 'timeline_entries', 'media_items', 'created_at', 'updated_at', ] read_only_fields = [ 'id', 'slug', 'verification_status', 'verification_status_display', 'follower_count', 'is_featured', 'is_active', 'created_by_email', 'members_count', 'is_following', 'user_role', 'timeline_entries', 'media_items', 'created_at', 'updated_at', ] @extend_schema_field(serializers.IntegerField) def get_members_count(self, obj) -> int: return obj.members.count() @extend_schema_field(serializers.BooleanField) def get_is_following(self, obj) -> bool: request = self.context.get('request') if not request or not request.user.is_authenticated: return False return obj.is_followed_by(request.user) @extend_schema_field(serializers.CharField(allow_null=True)) def get_user_role(self, obj): request = self.context.get('request') if not request or not request.user.is_authenticated: return None return obj.get_user_role(request.user) class InstitutionCreateUpdateSerializer(serializers.ModelSerializer): class Meta: model = Institution fields = [ 'name', 'type', 'country', 'city', 'address', 'latitude', 'longitude', 'description', 'website', 'email', 'phone', 'established_year', 'cover_image', 'avatar', 'social_media', 'working_hours', 'tags', 'is_featured', ] def create(self, validated_data): user = self.context.get('request').user if self.context.get('request') else None if user and user.is_authenticated: validated_data['created_by'] = user # Only super admins or regional admins can set is_featured directly upon creation if user and not (getattr(user, 'is_super_admin', False) or getattr(user, 'is_regional_admin', False)): validated_data['is_featured'] = False institution = super().create(validated_data) # Creator automatically becomes the Admin member if user and user.is_authenticated: InstitutionMember.objects.create( institution=institution, user=user, role=InstitutionMember.MemberRole.ADMIN, title="Founder / Primary Administrator" ) return institution class FollowResponseSerializer(serializers.Serializer): is_following = serializers.BooleanField() follower_count = serializers.IntegerField() message = serializers.CharField()