|
12 | 12 | from django.views.decorators.http import require_GET |
13 | 13 | from django.core.mail import send_mail |
14 | 14 | import random |
| 15 | +import logging |
15 | 16 |
|
16 | 17 | from rest_framework import viewsets, status, permissions, filters |
17 | 18 | from rest_framework.decorators import action, api_view, permission_classes |
|
32 | 33 | ProjectParticipant |
33 | 34 | ) |
34 | 35 | from .serializers import ( |
35 | | - UserRegistrationSerializer, UserSerializer, UserUpdateSerializer, |
| 36 | + SchoolAddStudentSerializer, SchoolAddTeacherSerializer, UserRegistrationSerializer, UserSerializer, UserUpdateSerializer, |
36 | 37 | PasswordChangeSerializer, SchoolSerializer, SchoolCreateSerializer, |
37 | 38 | SchoolMembershipSerializer, SubjectSerializer, ClassSerializer, |
38 | 39 | TeacherProfileSerializer, StudentProfileSerializer, ProjectSerializer, |
@@ -1123,6 +1124,168 @@ def add_user_to_school(request, school_id): |
1123 | 1124 | status=status.HTTP_500_INTERNAL_SERVER_ERROR) |
1124 | 1125 |
|
1125 | 1126 |
|
| 1127 | +@api_view(['POST']) |
| 1128 | +@permission_classes([CanManageSchoolMembers]) |
| 1129 | +def add_student_to_school(request, school_id): |
| 1130 | + """ |
| 1131 | + Add a student to a school. |
| 1132 | + Only school admins and teachers can add students to their schools. |
| 1133 | + """ |
| 1134 | + try: |
| 1135 | + school = get_object_or_404(School, id=school_id) |
| 1136 | + |
| 1137 | + # Check permission |
| 1138 | + if (school.admin != request.user or request.user.role != "teacher") and not request.user.is_staff: |
| 1139 | + return Response({'error': 'Only school admins and teachers can add students to schools'}, |
| 1140 | + status=status.HTTP_403_FORBIDDEN) |
| 1141 | + |
| 1142 | + serializer_class = SchoolAddStudentSerializer(data=request.data) |
| 1143 | + if not serializer_class.is_valid(): |
| 1144 | + return Response(serializer_class.errors, status=status.HTTP_400_BAD_REQUEST) |
| 1145 | + |
| 1146 | + data = serializer_class.validated_data |
| 1147 | + student_email = data['student_email'] |
| 1148 | + assigned_class_name = data['assigned_class'] |
| 1149 | + |
| 1150 | + try: |
| 1151 | + user = User.objects.get(email=student_email) |
| 1152 | + if user.role and user.role != "student": |
| 1153 | + return Response({'error': 'User already has a role other than student.'}, |
| 1154 | + status=status.HTTP_400_BAD_REQUEST) |
| 1155 | + elif not user.role: |
| 1156 | + user.role = "student" |
| 1157 | + user.save() |
| 1158 | + except User.DoesNotExist: |
| 1159 | + return Response({'error': 'User not found'}, |
| 1160 | + status=status.HTTP_404_NOT_FOUND) |
| 1161 | + |
| 1162 | + # Create school membership |
| 1163 | + membership, created = SchoolMembership.objects.get_or_create( |
| 1164 | + user=user, |
| 1165 | + school=school, |
| 1166 | + defaults={'is_active': True} |
| 1167 | + ) |
| 1168 | + |
| 1169 | + if not created and membership.is_active: |
| 1170 | + return Response({'error': 'User is already a member of this school'}, |
| 1171 | + status=status.HTTP_400_BAD_REQUEST) |
| 1172 | + elif not created: |
| 1173 | + membership.is_active = True |
| 1174 | + membership.save() |
| 1175 | + |
| 1176 | + try: |
| 1177 | + assigned_class = Class.objects.get(name=assigned_class_name, school=school) |
| 1178 | + except Class.DoesNotExist: |
| 1179 | + return Response({'error': 'Class not found in this school'}, status=status.HTTP_400_BAD_REQUEST) |
| 1180 | + |
| 1181 | + # Create appropriate profile |
| 1182 | + StudentProfile.objects.get_or_create( |
| 1183 | + user=user, |
| 1184 | + school=school, |
| 1185 | + defaults={ |
| 1186 | + 'student_id': f"{school.name[:3].upper()}{user.id}", |
| 1187 | + 'current_class': assigned_class |
| 1188 | + } |
| 1189 | + ) |
| 1190 | + |
| 1191 | + return Response({ |
| 1192 | + 'message': f'Successfully added {user.get_full_name()} as {user.role} to {school.name}', |
| 1193 | + 'user_id': str(user.id), |
| 1194 | + 'user_name': user.get_full_name(), |
| 1195 | + 'user_role': user.role, |
| 1196 | + 'school_name': school.name |
| 1197 | + }, status=status.HTTP_200_OK) |
| 1198 | + |
| 1199 | + except Exception as e: |
| 1200 | + logger.error(f"Error adding student to school: {str(e)}") |
| 1201 | + return Response({'error': f'Failed to add student to school: {str(e)}'}, |
| 1202 | + status=status.HTTP_500_INTERNAL_SERVER_ERROR) |
| 1203 | + |
| 1204 | + |
| 1205 | +@api_view(['POST']) |
| 1206 | +@permission_classes([CanManageSchoolMembers]) |
| 1207 | +def add_teacher_to_school(request, school_id): |
| 1208 | + """ |
| 1209 | + Add a teacher to a school. |
| 1210 | + Only school admins can add teachers to their schools. |
| 1211 | + """ |
| 1212 | + try: |
| 1213 | + school = get_object_or_404(School, id=school_id) |
| 1214 | + |
| 1215 | + # Check permission |
| 1216 | + if school.admin != request.user and not request.user.is_staff: |
| 1217 | + return Response({'error': 'Only school admins can add teachers to schools'}, |
| 1218 | + status=status.HTTP_403_FORBIDDEN) |
| 1219 | + |
| 1220 | + serializer_class = SchoolAddTeacherSerializer(data=request.data) |
| 1221 | + if not serializer_class.is_valid(): |
| 1222 | + return Response(serializer_class.errors, status=status.HTTP_400_BAD_REQUEST) |
| 1223 | + |
| 1224 | + data = serializer_class.validated_data |
| 1225 | + teacher_email = data['teacher_email'] |
| 1226 | + teacher_role = data['teacher_role'] |
| 1227 | + assigned_class_names = data.get('assigned_classes') |
| 1228 | + |
| 1229 | + try: |
| 1230 | + user = User.objects.get(email=teacher_email) |
| 1231 | + if user.role and user.role != "teacher": |
| 1232 | + return Response({'error': 'User already has a role other than teacher.'}, |
| 1233 | + status=status.HTTP_400_BAD_REQUEST) |
| 1234 | + elif not user.role: |
| 1235 | + user.role = "teacher" |
| 1236 | + user.save() |
| 1237 | + except User.DoesNotExist: |
| 1238 | + return Response({'error': 'User not found'}, |
| 1239 | + status=status.HTTP_404_NOT_FOUND) |
| 1240 | + |
| 1241 | + # Create school membership |
| 1242 | + membership, created = SchoolMembership.objects.get_or_create( |
| 1243 | + user=user, |
| 1244 | + school=school, |
| 1245 | + defaults={'is_active': True} |
| 1246 | + ) |
| 1247 | + |
| 1248 | + if not created and membership.is_active: |
| 1249 | + return Response({'error': 'User is already a member of this school'}, |
| 1250 | + status=status.HTTP_400_BAD_REQUEST) |
| 1251 | + elif not created: |
| 1252 | + membership.is_active = True |
| 1253 | + membership.save() |
| 1254 | + |
| 1255 | + # Create appropriate profile |
| 1256 | + teacher_profile, _ = TeacherProfile.objects.get_or_create( |
| 1257 | + user=user, |
| 1258 | + school=school, |
| 1259 | + defaults={'teacher_role': teacher_role, 'status': 'active'} |
| 1260 | + ) |
| 1261 | + # Query classes matching names and this school |
| 1262 | + valid_class_names = Class.objects.filter(name__in=assigned_class_names, school=school).values_list('name', flat=True) |
| 1263 | + |
| 1264 | + # Find invalid class names |
| 1265 | + invalid_classes = set(assigned_class_names) - set(valid_class_names) |
| 1266 | + if invalid_classes: |
| 1267 | + return Response( |
| 1268 | + {'error': f'The following classes are invalid or do not belong to the school: {", ".join(invalid_classes)}'}, |
| 1269 | + status=status.HTTP_400_BAD_REQUEST |
| 1270 | + ) |
| 1271 | + |
| 1272 | + valid_classes_qs = Class.objects.filter(name__in=assigned_class_names, school=school) |
| 1273 | + teacher_profile.assigned_classes.set(valid_classes_qs) |
| 1274 | + |
| 1275 | + return Response({ |
| 1276 | + 'message': f'Successfully added {user.get_full_name()} as {user.role} to {school.name}', |
| 1277 | + 'user_id': str(user.id), |
| 1278 | + 'user_name': user.get_full_name(), |
| 1279 | + 'user_role': teacher_role, |
| 1280 | + 'school_name': school.name |
| 1281 | + }, status=status.HTTP_200_OK) |
| 1282 | + |
| 1283 | + except Exception as e: |
| 1284 | + logger.error(f"Error adding teacher to school: {str(e)}") |
| 1285 | + return Response({'error': f'Failed to add teacher to school: {str(e)}'}, |
| 1286 | + status=status.HTTP_500_INTERNAL_SERVER_ERROR) |
| 1287 | + |
| 1288 | + |
1126 | 1289 | @api_view(['POST']) |
1127 | 1290 | @permission_classes([CanManageSchoolContent]) |
1128 | 1291 | def add_student_to_class(request, class_id): |
|
0 commit comments