You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
260 lines
8.0 KiB
260 lines
8.0 KiB
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()
|