from rest_framework import serializers from apps.meetings.models import MeetingRequest, MeetingStatus from apps.profiles.models import Institution, InstitutionMember from apps.account.models import User class InstitutionMeetingMinimalSerializer(serializers.ModelSerializer): class Meta: model = Institution fields = ['id', 'name', 'slug', 'type', 'avatar', 'city', 'country'] class MeetingUserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ['id', 'email', 'fullname', 'avatar'] class MeetingListSerializer(serializers.ModelSerializer): requester_institution = InstitutionMeetingMinimalSerializer(read_only=True) recipient_institution = InstitutionMeetingMinimalSerializer(read_only=True) created_by = MeetingUserSerializer(read_only=True) class Meta: model = MeetingRequest fields = [ 'id', 'title', 'requester_institution', 'recipient_institution', 'created_by', 'status', 'meeting_date', 'meeting_time', 'duration_minutes', 'meeting_url', 'rejection_reason', 'created_at', ] class MeetingDetailSerializer(serializers.ModelSerializer): requester_institution = InstitutionMeetingMinimalSerializer(read_only=True) recipient_institution = InstitutionMeetingMinimalSerializer(read_only=True) created_by = MeetingUserSerializer(read_only=True) class Meta: model = MeetingRequest fields = [ 'id', 'title', 'requester_institution', 'recipient_institution', 'created_by', 'status', 'meeting_date', 'meeting_time', 'duration_minutes', 'meeting_url', 'agenda', 'admin_notes', 'rejection_reason', 'created_at', 'updated_at', ] class MeetingCreateSerializer(serializers.ModelSerializer): requester_institution_id = serializers.PrimaryKeyRelatedField( queryset=Institution.objects.all(), source='requester_institution', write_only=True ) recipient_institution_id = serializers.PrimaryKeyRelatedField( queryset=Institution.objects.all(), source='recipient_institution', write_only=True ) class Meta: model = MeetingRequest fields = [ 'id', 'title', 'requester_institution_id', 'recipient_institution_id', 'meeting_date', 'meeting_time', 'duration_minutes', 'meeting_url', 'agenda', ] def validate(self, attrs): requester = attrs.get('requester_institution') recipient = attrs.get('recipient_institution') if requester == recipient: raise serializers.ValidationError({"recipient_institution_id": "Requester and recipient institutions cannot be the same."}) request = self.context.get('request') user = request.user if request else None if user and not (user.is_superuser or getattr(user, 'user_type', None) in ['super_admin', 'regional_admin']): is_member = InstitutionMember.objects.filter( institution=requester, user=user, role__in=['admin', 'editor'] ).exists() if not is_member: raise serializers.ValidationError({"requester_institution_id": "You are not authorized to schedule meetings for this institution."}) return attrs def create(self, validated_data): request = self.context.get('request') if request and request.user.is_authenticated: validated_data['created_by'] = request.user return super().create(validated_data) class MeetingUpdateSerializer(serializers.ModelSerializer): rejection_reason = serializers.CharField( required=False, allow_blank=True, help_text="Required explanation when rejecting/declining a meeting request." ) class Meta: model = MeetingRequest fields = [ 'status', 'meeting_date', 'meeting_time', 'duration_minutes', 'meeting_url', 'agenda', 'admin_notes', 'rejection_reason', ] def validate(self, attrs): status_val = attrs.get('status') if status_val == MeetingStatus.DECLINED: reason = (attrs.get('rejection_reason') or attrs.get('admin_notes') or '').strip() if not reason: if self.instance and self.instance.rejection_reason: reason = self.instance.rejection_reason else: raise serializers.ValidationError({ "rejection_reason": "An explanation or reason is required when declining a meeting request." }) attrs['rejection_reason'] = reason if not attrs.get('admin_notes'): attrs['admin_notes'] = reason return attrs