diff --git a/FusionIIIT/Fusion/middleware/custom_middleware.py b/FusionIIIT/Fusion/middleware/custom_middleware.py index fd8528e6e..74f7d7d72 100644 --- a/FusionIIIT/Fusion/middleware/custom_middleware.py +++ b/FusionIIIT/Fusion/middleware/custom_middleware.py @@ -2,7 +2,7 @@ from django.contrib.auth.signals import user_logged_in from django.dispatch import receiver from applications.globals.models import (ExtraInfo, Feedback, HoldsDesignation, - Issue, IssueImage, DepartmentInfo) + Issue, IssueImage, DepartmentInfo,ModuleAccess) from django.shortcuts import get_object_or_404, redirect, render def user_logged_in_middleware(get_response): @@ -35,7 +35,19 @@ def user_logged_in_handler(sender, user, request, **kwargs): print(i) request.session['currentDesignationSelected'] = designation[0] - request.session['allDesignations'] = designation + request.session['allDesignations'] = designation + first_designation = designation[0] + module_access = ModuleAccess.objects.filter(designation=first_designation).first() + + if module_access: + access_rights = {} + + field_names = [field.name for field in ModuleAccess._meta.get_fields() if field.name not in ['id', 'designation']] + + for field_name in field_names: + access_rights[field_name] = getattr(module_access, field_name) + + request.session['moduleAccessRights'] = access_rights print("logged iN") # Set the flag in the session to indicate that the function has bee+n executed @@ -47,4 +59,4 @@ def middleware(request): response = get_response(request) return response - return middleware \ No newline at end of file + return middleware \ No newline at end of file diff --git a/FusionIIIT/Fusion/settings/common.py b/FusionIIIT/Fusion/settings/common.py index 54494036e..d9017dd40 100644 --- a/FusionIIIT/Fusion/settings/common.py +++ b/FusionIIIT/Fusion/settings/common.py @@ -111,6 +111,7 @@ 'notification', 'notifications', 'applications.academic_procedures', + 'applications.examination', 'applications.academic_information', 'applications.leave', 'applications.library', @@ -127,6 +128,7 @@ 'applications.ps1', 'applications.programme_curriculum', 'applications.placement_cell', + 'applications.otheracademic', 'applications.recruitment', 'applications.scholarships', 'applications.visitor_hostel', @@ -281,4 +283,4 @@ CORS_ORIGIN_ALLOW_ALL = True -ALLOW_PASS_RESET = True \ No newline at end of file +ALLOW_PASS_RESET = True diff --git a/FusionIIIT/Fusion/settings/development.py b/FusionIIIT/Fusion/settings/development.py index 3f95a478c..63587a11f 100644 --- a/FusionIIIT/Fusion/settings/development.py +++ b/FusionIIIT/Fusion/settings/development.py @@ -63,3 +63,5 @@ #the below job which we need to add in production server, to update the mess bill of student everyday at 10 pm in night ('0 22 * * *', 'applications.central_mess.tasks.generate_bill'), ] + +CRONTAB_DJANGO_MANAGE_PATH = '/home/owlman/Desktop/Fuse/Fusion/FusionIIIT/manage.py' \ No newline at end of file diff --git a/FusionIIIT/Fusion/urls.py b/FusionIIIT/Fusion/urls.py index 837bf776a..b9c03eeb8 100755 --- a/FusionIIIT/Fusion/urls.py +++ b/FusionIIIT/Fusion/urls.py @@ -60,4 +60,6 @@ url(r'^income-expenditure/', include('applications.income_expenditure.urls')), url(r'^hr2/', include('applications.hr2.urls')), url(r'^recruitment/', include('applications.recruitment.urls')), + url(r'^examination/', include('applications.examination.urls')), + url(r'^otheracademic/', include('applications.otheracademic.urls')), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/FusionIIIT/applications/academic_information/admin.py b/FusionIIIT/applications/academic_information/admin.py index 94f60274d..522815707 100755 --- a/FusionIIIT/applications/academic_information/admin.py +++ b/FusionIIIT/applications/academic_information/admin.py @@ -32,4 +32,3 @@ class Curriculum_InstructorAdmin(admin.ModelAdmin): admin.site.register(Holiday) admin.site.register(Curriculum,CurriculumAdmin) -#Hello! diff --git a/FusionIIIT/applications/academic_information/api/serializers.py b/FusionIIIT/applications/academic_information/api/serializers.py index 06d6154c5..fd4fb59b7 100644 --- a/FusionIIIT/applications/academic_information/api/serializers.py +++ b/FusionIIIT/applications/academic_information/api/serializers.py @@ -18,7 +18,6 @@ class Meta: class CurriculumSerializer(serializers.ModelSerializer): course_id = CourseSerializer() - class Meta: model = Curriculum fields = ('curriculum_id','course_code','course_id','credits','course_type', diff --git a/FusionIIIT/applications/academic_information/api/urls.py b/FusionIIIT/applications/academic_information/api/urls.py index e7fe37be9..dfda1c00d 100644 --- a/FusionIIIT/applications/academic_information/api/urls.py +++ b/FusionIIIT/applications/academic_information/api/urls.py @@ -14,7 +14,8 @@ # url(r'^meeting',views.meeting_api,name='meeting-get-api'), - # url(r'^calendar',views.calendar_api,name='calendar-get-api'), + url(r'^calendar',views.ListCalendarView.as_view(),name='calendar-get-api'), + url(r'^update-calendar',views.update_calendar,name='calendar-update-api'), # url(r'^holiday',views.holiday_api,name='holiday-get-api'), @@ -27,4 +28,4 @@ # url(r'^grades',views.grades_api,name='grades-get-api'), # url(r'^spi',views.spi_api,name='spi-get-api') -] \ No newline at end of file +] diff --git a/FusionIIIT/applications/academic_information/api/views.py b/FusionIIIT/applications/academic_information/api/views.py index 192785374..4ed4d13ee 100644 --- a/FusionIIIT/applications/academic_information/api/views.py +++ b/FusionIIIT/applications/academic_information/api/views.py @@ -1,181 +1,202 @@ -# from django.contrib.auth import get_user_model -# from django.contrib.auth.decorators import login_required -# from applications.globals.models import (HoldsDesignation,Designation) -# from django.shortcuts import get_object_or_404 -# from django.forms.models import model_to_dict -# from rest_framework.permissions import IsAuthenticated -# from rest_framework.authentication import TokenAuthentication -# from rest_framework import status -# from rest_framework.decorators import api_view, permission_classes,authentication_classes -# from rest_framework.permissions import AllowAny -# from rest_framework.response import Response -# from applications.globals.models import User,ExtraInfo -# from applications.academic_information.models import Student, Course, Curriculum, Curriculum_Instructor, Student_attendance, Meeting, Calendar, Holiday, Grades, Spi, Timetable, Exam_timetable -# from . import serializers - -# @api_view(['GET']) +from django.contrib.auth import get_user_model +from django.contrib.auth.decorators import login_required +from applications.globals.models import (HoldsDesignation,Designation) +from django.shortcuts import get_object_or_404 +from django.forms.models import model_to_dict +from rest_framework.permissions import IsAuthenticated +from rest_framework.authentication import TokenAuthentication +from rest_framework import status +from rest_framework.decorators import api_view, permission_classes,authentication_classes +from rest_framework.permissions import AllowAny +from rest_framework.response import Response +from applications.globals.models import User,ExtraInfo +from applications.academic_information.models import Student, Course, Curriculum, Curriculum_Instructor, Student_attendance, Meeting, Calendar, Holiday, Grades, Spi, Timetable, Exam_timetable +from . import serializers +from rest_framework.generics import ListCreateAPIView + +@api_view(['GET']) +@permission_classes([IsAuthenticated]) +@authentication_classes([TokenAuthentication]) +def student_api(request): + + if request.method == 'GET': + student = Student.objects.all() + student_serialized = serializers.StudentSerializers(student,many=True).data + resp = { + 'students' : student_serialized, + } + return Response(data=resp,status=status.HTTP_200_OK) + + +@api_view(['GET']) # @permission_classes([IsAuthenticated]) # @authentication_classes([TokenAuthentication]) -# def student_api(request): - -# if request.method == 'GET': -# student = Student.objects.all() -# student_serialized = serializers.StudentSerializers(student,many=True).data -# resp = { -# 'students' : student_serialized, -# } -# return Response(data=resp,status=status.HTTP_200_OK) - - -# @api_view(['GET']) -# @permission_classes([IsAuthenticated]) -# @authentication_classes([TokenAuthentication]) -# def course_api(request): - -# if request.method == 'GET': -# course = Course.objects.all() -# course_serialized = serializers.CourseSerializer(course,many=True).data -# resp = { -# 'courses' : course_serialized, -# } -# return Response(data=resp,status=status.HTTP_200_OK) - - -# @api_view(['GET']) -# @permission_classes([IsAuthenticated]) -# @authentication_classes([TokenAuthentication]) -# def curriculum_api(request): - -# if request.method == 'GET': -# curriculum = Curriculum.objects.all() -# curriculum_serialized = serializers.CurriculumSerializer(curriculum,many=True).data -# resp = { -# 'curriculum' : curriculum_serialized, -# } -# return Response(data=resp,status=status.HTTP_200_OK) - - -# @api_view(['GET']) -# @permission_classes([IsAuthenticated]) -# @authentication_classes([TokenAuthentication]) -# def meeting_api(request): - -# if request.method == 'GET': -# meeting = Meeting.objects.all() -# meeting_serialized = serializers.MeetingSerializers(meeting,many=True).data -# resp = { -# 'meeting' : meeting_serialized, -# } -# return Response(data=resp,status=status.HTTP_200_OK) - - -# @api_view(['GET']) -# @permission_classes([IsAuthenticated]) -# @authentication_classes([TokenAuthentication]) -# def calendar_api(request): - -# if request.method == 'GET': -# calendar = Calendar.objects.all() -# calendar_serialized = serializers.CalendarSerializers(calendar,many=True).data -# resp = { -# 'calendar' :calendar_serialized, -# } -# return Response(data=resp,status=status.HTTP_200_OK) - - -# @api_view(['GET']) -# @permission_classes([IsAuthenticated]) -# @authentication_classes([TokenAuthentication]) -# def holiday_api(request): - -# if request.method == 'GET': -# holiday = Holiday.objects.all() -# holiday_serialized = serializers.HolidaySerializers(holiday,many=True).data -# resp = { -# 'holiday' : holiday_serialized, -# } -# return Response(data=resp,status=status.HTTP_200_OK) - - -# @api_view(['GET']) -# @permission_classes([IsAuthenticated]) -# @authentication_classes([TokenAuthentication]) -# def timetable_api(request): - -# if request.method == 'GET': -# timetable = Timetable.objects.all() -# timetable_serialized = serializers.TimetableSerializers(timetable,many=True).data -# resp = { -# 'timetable' : timetable_serialized, -# } -# return Response(data=resp,status=status.HTTP_200_OK) - - -# @api_view(['GET']) -# @permission_classes([IsAuthenticated]) -# @authentication_classes([TokenAuthentication]) -# def exam_timetable_api(request): - -# if request.method == 'GET': -# exam_timetable = Exam_timetable.objects.all() -# exam_timetable_serialized = serializers.Exam_timetableSerializers(exam_timetable,many=True).data -# resp = { -# 'exam_timetable' : exam_timetable_serialized, -# } -# return Response(data=resp,status=status.HTTP_200_OK) - - -# @api_view(['GET']) -# @permission_classes([IsAuthenticated]) -# @authentication_classes([TokenAuthentication]) -# def curriculum_instructor_api(request): - -# if request.method == 'GET': -# curriculum_instructor = Curriculum_Instructor.objects.all() -# curriculum_instructor_serialized = serializers.CurriculumInstructorSerializer(curriculum_instructor,many=True).data -# resp = { -# 'curriculum_instructor' : curriculum_instructor_serialized, -# } -# return Response(data=resp,status=status.HTTP_200_OK) - - -# @api_view(['GET']) -# @permission_classes([IsAuthenticated]) -# @authentication_classes([TokenAuthentication]) -# def student_attendance_api(request): - -# if request.method == 'GET': -# student_attendance = Student_attendance.objects.all() -# student_attendance_serialized = serializers.Student_attendanceSerializers(student_attendance,many=True).data -# resp = { -# 'student_attendance' : student_attendance_serialized, -# } -# return Response(data=resp,status=status.HTTP_200_OK) - - -# @api_view(['GET']) -# @permission_classes([IsAuthenticated]) -# @authentication_classes([TokenAuthentication]) -# def grades_api(request): - -# if request.method == 'GET': -# grades = Grades.objects.all() -# grades_serialized = serializers.GradesSerializers(grades,many=True).data -# resp = { -# 'grades' : grades_serialized, -# } -# return Response(data=resp,status=status.HTTP_200_OK) - - -# @api_view(['GET']) -# @permission_classes([IsAuthenticated]) -# @authentication_classes([TokenAuthentication]) -# def spi_api(request): - -# if request.method == 'GET': -# spi = Spi.objects.all() -# spi_serialized = serializers.SpiSerializers(spi,many=True).data -# resp = { -# 'spi' : spi_serialized, -# } -# return Response(data=resp,status=status.HTTP_200_OK) \ No newline at end of file +def course_api(request): + + if request.method == 'GET': + course = Course.objects.all() + course_serialized = serializers.CourseSerializer(course,many=True).data + resp = { + 'courses' : course_serialized, + } + return Response(data=resp,status=status.HTTP_200_OK) + + + +@api_view(['GET']) +@permission_classes([IsAuthenticated]) +@authentication_classes([TokenAuthentication]) +def curriculum_api(request): + + if request.method == 'GET': + curriculum = Curriculum.objects.all() + curriculum_serialized = serializers.CurriculumSerializer(curriculum,many=True).data + resp = { + 'curriculum' : curriculum_serialized, + } + return Response(data=resp,status=status.HTTP_200_OK) + + +@api_view(['GET']) +@permission_classes([IsAuthenticated]) +@authentication_classes([TokenAuthentication]) +def meeting_api(request): + + if request.method == 'GET': + meeting = Meeting.objects.all() + meeting_serialized = serializers.MeetingSerializers(meeting,many=True).data + resp = { + 'meeting' : meeting_serialized, + } + return Response(data=resp,status=status.HTTP_200_OK) + + +@api_view(['GET']) +@permission_classes([IsAuthenticated]) +@authentication_classes([TokenAuthentication]) +def calendar_api(request): + + if request.method == 'GET': + calendar = Calendar.objects.all() + calendar_serialized = serializers.CalendarSerializers(calendar,many=True).data + resp = { + 'calendar' :calendar_serialized, + } + return Response(data=resp,status=status.HTTP_200_OK) + +class ListCalendarView(ListCreateAPIView): + permission_classes = [IsAuthenticated] + authentication_classes=[TokenAuthentication] + serializer_class = serializers.CalendarSerializers + queryset = Calendar.objects.all() + +@api_view(['PUT']) +@permission_classes([IsAuthenticated]) +@authentication_classes([TokenAuthentication]) +def update_calendar(request): + if request.method == "PUT": + id = request.data.get("id") + instance = Calendar.objects.get(pk = id) + instance.from_date = request.data.get("from_date") + instance.to_date = request.data.get("to_date") + instance.description = request.data.get("description") + instance.save() + + return Response({"message": "Updated successfully!"}) + +@api_view(['GET']) +@permission_classes([IsAuthenticated]) +@authentication_classes([TokenAuthentication]) +def holiday_api(request): + + if request.method == 'GET': + holiday = Holiday.objects.all() + holiday_serialized = serializers.HolidaySerializers(holiday,many=True).data + resp = { + 'holiday' : holiday_serialized, + } + return Response(data=resp,status=status.HTTP_200_OK) + + +@api_view(['GET']) +@permission_classes([IsAuthenticated]) +@authentication_classes([TokenAuthentication]) +def timetable_api(request): + + if request.method == 'GET': + timetable = Timetable.objects.all() + timetable_serialized = serializers.TimetableSerializers(timetable,many=True).data + resp = { + 'timetable' : timetable_serialized, + } + return Response(data=resp,status=status.HTTP_200_OK) + + +@api_view(['GET']) +@permission_classes([IsAuthenticated]) +@authentication_classes([TokenAuthentication]) +def exam_timetable_api(request): + + if request.method == 'GET': + exam_timetable = Exam_timetable.objects.all() + exam_timetable_serialized = serializers.Exam_timetableSerializers(exam_timetable,many=True).data + resp = { + 'exam_timetable' : exam_timetable_serialized, + } + return Response(data=resp,status=status.HTTP_200_OK) + + +@api_view(['GET']) +@permission_classes([IsAuthenticated]) +@authentication_classes([TokenAuthentication]) +def curriculum_instructor_api(request): + + if request.method == 'GET': + curriculum_instructor = Curriculum_Instructor.objects.all() + curriculum_instructor_serialized = serializers.CurriculumInstructorSerializer(curriculum_instructor,many=True).data + resp = { + 'curriculum_instructor' : curriculum_instructor_serialized, + } + return Response(data=resp,status=status.HTTP_200_OK) + + +@api_view(['GET']) +@permission_classes([IsAuthenticated]) +@authentication_classes([TokenAuthentication]) +def student_attendance_api(request): + + if request.method == 'GET': + student_attendance = Student_attendance.objects.all() + student_attendance_serialized = serializers.Student_attendanceSerializers(student_attendance,many=True).data + resp = { + 'student_attendance' : student_attendance_serialized, + } + return Response(data=resp,status=status.HTTP_200_OK) + + +@api_view(['GET']) +@permission_classes([IsAuthenticated]) +@authentication_classes([TokenAuthentication]) +def grades_api(request): + + if request.method == 'GET': + grades = Grades.objects.all() + grades_serialized = serializers.GradesSerializers(grades,many=True).data + resp = { + 'grades' : grades_serialized, + } + return Response(data=resp,status=status.HTTP_200_OK) + + +@api_view(['GET']) +@permission_classes([IsAuthenticated]) +@authentication_classes([TokenAuthentication]) +def spi_api(request): + + if request.method == 'GET': + spi = Spi.objects.all() + spi_serialized = serializers.SpiSerializers(spi,many=True).data + resp = { + 'spi' : spi_serialized, + } + return Response(data=resp,status=status.HTTP_200_OK) \ No newline at end of file diff --git a/FusionIIIT/applications/academic_information/migrations/0001_initial.py b/FusionIIIT/applications/academic_information/migrations/0001_initial.py index 4b0f359c3..22fd38161 100644 --- a/FusionIIIT/applications/academic_information/migrations/0001_initial.py +++ b/FusionIIIT/applications/academic_information/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.1.5 on 2024-04-15 23:58 +# Generated by Django 3.1.5 on 2024-07-16 15:44 from django.db import migrations, models import django.db.models.deletion @@ -9,8 +9,8 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('globals', '0001_initial'), ('programme_curriculum', '0001_initial'), + ('globals', '0001_initial'), ] operations = [ diff --git a/FusionIIIT/applications/academic_information/models.py b/FusionIIIT/applications/academic_information/models.py index d5103fbd7..280e84b32 100755 --- a/FusionIIIT/applications/academic_information/models.py +++ b/FusionIIIT/applications/academic_information/models.py @@ -69,7 +69,7 @@ class Student(models.Model): ''' Current Purpose : To store information pertinent to a user who is also a student - + ATTRIBUTES : @@ -99,9 +99,6 @@ class Student(models.Model): room_no = models.CharField(max_length=10, blank=True, null=True) specialization = models.CharField(max_length=40,choices=Constants.MTechSpecialization, null=True, default='') curr_semester_no = models.IntegerField(default=1) -# pwd_status = models.BooleanField(null=True, blank=True,default=False) -# father_mobile_no = models.CharField(max_length=10, null=True, blank=True, default='9999999999') -# mother_mobile_no = models.CharField(max_length=10, null=True, blank=True, default='9999999999') def __str__(self): username = str(self.id.user.username) @@ -110,17 +107,7 @@ def __str__(self): class Course(models.Model): - ''' - Current Purpose : To store information of a course - - - - ATTRIBUTES : - - course_name(char) - to store the name of the course - course_details(TextField) - to store the course details - - ''' + course_name = models.CharField(max_length=600) course_details = models.TextField(max_length=500) @@ -132,25 +119,7 @@ def __str__(self): class Curriculum(models.Model): - ''' - Current Purpose : Currently this table stores mapping of a course to a particular semester and relevant details - - ! - the table does not follow the conventional definition of the term Curriculum - ATTRIBUTES : - - curriculum_id(AutoField) - to store the automatically generated course id which will be the primary key - course_code(CharField) - stores the course code (can be null) - course_id(academic_information.Course) - foreign key to the course - credits(integer) - stores credits assigned for the course - course_type(char) - to select the type of the course(eg : Professional Core/Project) - programme(char) - to store the programme for which the course is being offered - branch(char) - to store the branch/discipline for which the course is being offered(eg CSE) - batch(integer) - to store the batch for which the course is available(eg:2019) - sem(Integer) - the semester in which the course is offered for a batch - optional(Boolean) - denotes whether the course is optional or not - floated(Boolean) - denotes whether a course is floated for a particular semester or not - - ''' + curriculum_id = models.AutoField(primary_key=True) course_code = models.CharField(max_length = 20) course_id = models.ForeignKey(Course,on_delete= models.CASCADE) @@ -172,23 +141,7 @@ def __str__(self): class Curriculum_Instructor(models.Model): - ''' - Current Purpose : Currently this table stores mapping of a course in a semester to the faculty who will teach the course - - ! - the table does not follow the conventional definition of the term Curriculum - - - - - - ATTRIBUTES : - - curriculum_id(academic_information.Curriculum) - reference to the course details - instructor_id(globals.ExtraInfo) - reference to the faculty who will teach the course - chief_inst(Bool) - denotes whether the faculty is the chief instructor of the course or not - - - ''' + curriculum_id = models.ForeignKey(Curriculum, on_delete=models.CASCADE) instructor_id = models.ForeignKey(ExtraInfo, on_delete=models.CASCADE) chief_inst = models.BooleanField(default=False) @@ -205,27 +158,11 @@ def __str__(self): class Student_attendance(models.Model): - ''' - Current Purpose : Currently this table stores mapping of a student's attendance for a particular course in a semester - - - - - - - ATTRIBUTES : - - student_id(academic_information.Student) - referene to the student for whom the attendance is being recorded - instructor_id(academic_information.Curriculum_Instructor) - reference to the faculty and course - date(DateField) - the date for which the attendance will be recorded - present(Boolean) - to denote whether the student was present or not - - ''' + student_id = models.ForeignKey(Student,on_delete=models.CASCADE) -# course_id = models.ForeignKey(Course) -# attend = models.CharField(max_length=6, choices=Constants.ATTEND_CHOICES) + instructor_id = models.ForeignKey(Curriculum_Instructor, on_delete=models.CASCADE) -# curriculum_id = models.ForeignKey(Curriculum, on_delete=models.CASCADE) + date = models.DateField() present = models.BooleanField(default=False) @@ -237,18 +174,7 @@ def __self__(self): class Meeting(models.Model): - ''' - Current Purpose : stores the information regarding a meeting which was conducted by the academic department - - ATTRIBUTES: - - venue(char) - venue where the meeting will be held(eg:L-103) - date(DateField) - the date on which the meeting was held - time(char) - time at the meeting was held - agenga(text) - the points of discussion for the meeting - minutes_file(char) - the summary of the meeting - - ''' + venue = models.CharField(max_length=50) date = models.DateField() time = models.CharField(max_length=20) @@ -263,15 +189,7 @@ def __str__(self): class Calendar(models.Model): - ''' - Current Purpose : stores the information regarding an academic event(eg : course registrations etc) - - ATTRIBUTES: - - from_date(DateField) - start date of the event - to_date(DateField) - end date of the event - description(Char) - description about the event - ''' + from_date = models.DateField() to_date = models.DateField() description = models.CharField(max_length=40) @@ -284,14 +202,7 @@ def __str__(self): class Holiday(models.Model): - ''' - Current Purpose : stores the information regarding a holiday - - ATTRIBUTES - holiday_date(DateField) - the date of the holidar - holiday_name(char) - to denote the name of the holiday(eg : Republic Day) - holiday_type - to store whether the holiday is restricted or closed - ''' + holiday_date = models.DateField() holiday_name = models.CharField(max_length=40) holiday_type = models.CharField(default='restricted', max_length=30, @@ -305,14 +216,7 @@ def __str__(self): class Grades(models.Model): - ''' - Current Purpose : stores the information regarding the gradees of a student for a course in a semester - - ATTRIBUTES - student_id(academic_information.Student) - Reference to the student for whom the grades is about to be stores - curriculum_id(academic_information.Curriculum) - Reference to the course for which the graded are to be given - grade(Char) - denotes whether the grade given to the student is verified or not - ''' + student_id = models.ForeignKey(Student,on_delete=models.CASCADE) curriculum_id = models.ForeignKey(Curriculum,on_delete=models.CASCADE) grade = models.CharField(max_length=4) @@ -323,14 +227,7 @@ class Meta: class Spi(models.Model): - ''' - Current Purpose : stores the information regarding the SPI of a student for a semester - - ATTRIBUTES - sem(Integer) - the semester to which the spi refers to - student_id(academic_information.Student) - the student for whom the spi is stored - spi(float) - the spi value achieved - ''' + sem = models.IntegerField() student_id = models.ForeignKey(Student, on_delete=models.CASCADE) spi = models.FloatField(default=0) @@ -344,18 +241,7 @@ def __self__(self): class Timetable(models.Model): - ''' - Current Purpose : stores the class-schedule timetable for a batch (eg CSE -2019-Btech) - - ATTRIBUTES - - upload_date(DateTime) - stores the upload date and time - time_table(File) - the file which contains the timetable - batch(Integer) - stores the batch for which the timetable is valid - programme(Char) - stores the programme for which the time table is valid - branch(char) - the branch for which the time table is valid - ''' - + upload_date = models.DateTimeField(auto_now_add=True) time_table = models.FileField(upload_to='Administrator/academic_information/') batch = models.IntegerField(default="2016") @@ -366,17 +252,7 @@ class Meta: class Exam_timetable(models.Model): - ''' - Current Purpose : stores the exam-schedule timetable for a batch (2019-Btech) - - ATTRIBUTES - - upload_date(DateTime) - stores the upload date and time - exam_time_table(File) - the file which contains the timetable - batch(Integer) - stores the batch for which the timetable is valid - programme(Char) - stores the programme for which the time table is valid - - ''' + upload_date = models.DateField(auto_now_add=True) exam_time_table = models.FileField(upload_to='Administrator/academic_information/') batch = models.IntegerField(default="2016") diff --git a/FusionIIIT/applications/academic_information/views.py b/FusionIIIT/applications/academic_information/views.py index 22210a52e..2fab71e2f 100755 --- a/FusionIIIT/applications/academic_information/views.py +++ b/FusionIIIT/applications/academic_information/views.py @@ -28,9 +28,9 @@ -from applications.academic_procedures.views import acad_proced_global_context +from applications.academic_procedures.views import acad_proced_global_context , get_sem_courses from applications.programme_curriculum.models import Batch - +from django.db.models import Q @login_required @@ -107,9 +107,8 @@ def get_context(request): # course_type = Constants.COURSE_TYPE # timetable = Timetable.objects.all() # exam_t = Exam_timetable.objects.all() - procedures_context = acad_proced_global_context() - + notifs = request.user.notifications.all() try: examTtForm = ExamTimetableForm() acadTtForm = AcademicTimetableForm() @@ -176,7 +175,8 @@ def get_context(request): 'batch_branch_data' : procedures_context['batch_branch_data'], 'assistant_flag' : assistant_flag, 'hod_flag' : hod_flag, - 'account_flag' : account_flag + 'account_flag' : account_flag, + 'notifications': notifs, } return context @@ -842,29 +842,44 @@ def generatexlsheet(request): """ if user_check(request): return HttpResponseRedirect('/academic-procedures/') - + # print(request.POST) try: - batch = request.POST['batch'] - course = Courses.objects.get(id = request.POST['course']) + batch = request.POST['batch']#batch hai year wala (2020 , 21) + if batch == "": + batch = datetime.datetime.now().year + course_id = int(request.POST['course']) # id of course in integer + course = course = Courses.objects.get(id=course_id) + + # print(course.name) obj = course_registration.objects.all().filter(course_id = course) except Exception as e: + print(str(e)) batch="" course="" curr_key="" obj="" registered_courses = [] - for i in obj: - if i.student_id.batch_id.year == int(batch): - registered_courses.append(i) + registered_courses = course_registration.objects.filter( + Q(working_year=int(batch)) & + Q(course_id=course) & + Q(student_id__finalregistration__verified=True) + ) + + # for i in obj: + # if i.student_id.batch_id.year == int(batch): + # registered_courses.append(i) ans = [] + student_ids = set() for i in registered_courses: - k = [] - k.append(i.student_id.id.id) - k.append(i.student_id.id.user.first_name) - k.append(i.student_id.id.user.last_name) - k.append(i.student_id.id.department) - ans.append(k) + if i.student_id.id.id not in student_ids: + student_ids.add(i.student_id.id.id ) + k = [] + k.append(i.student_id.id.id) + k.append(i.student_id.id.user.first_name) + k.append(i.student_id.id.user.last_name) + k.append(i.student_id.id.department) + ans.append(k) ans.sort() output = BytesIO() @@ -1029,9 +1044,14 @@ def generate_preregistration_report(request): max_width = max(max_width,len(choices_of_current_student)) for choice in range(1,len(choices_of_current_student)+1): - current_choice = InitialRegistration.objects.get(student_id=student, semester_id__semester_no=sem,course_slot_id = slot,priority = choice) - # #print("current choice is ",current_choice) - z.append(str(current_choice.course_id.code)+"-"+str(current_choice.course_id.name)) + try: + current_choice = InitialRegistration.objects.get(student_id=student, semester_id__semester_no=sem, course_slot_id=slot, priority=choice) + z.append(str(current_choice.course_id.code) + "-" + str(current_choice.course_id.name)) + except : + z.append("No registration found") + # current_choice = InitialRegistration.objects.get(student_id=student, semester_id__semester_no=sem,course_slot_id = slot,priority = choice) + # # #print("current choice is ",current_choice) + # z.append(str(current_choice.course_id.code)+"-"+str(current_choice.course_id.name)) data.append(z) m+=1 @@ -1169,9 +1189,9 @@ def add_new_profile (request): } if request.method == 'POST' and request.FILES: profiles=request.FILES['profiles'] - excel = xlrd.open_workbook(file_contents=profiles.read()) + excel = xlrd.open_workbook(profiles.name,file_contents=profiles.read()) sheet=excel.sheet_by_index(0) - for i in range(sheet.nrows): + for i in range(1,sheet.nrows): roll_no=sheet.cell(i,0).value first_name=str(sheet.cell(i,1).value) last_name=str(sheet.cell(i,2).value) @@ -1191,7 +1211,7 @@ def add_new_profile (request): category="" phone_no=0 address="" - dept=str(sheet.cell(i,12).value) + dept=str(sheet.cell(i,11).value) specialization=str(sheet.cell(i,12).value) hall_no=None @@ -1209,7 +1229,6 @@ def add_new_profile (request): batch_year=request.POST['Batch'] batch = Batch.objects.all().filter(name = programme_name, discipline__acronym = dept, year = batch_year).first() - user = User.objects.create_user( username=roll_no, password='hello123', @@ -1217,6 +1236,7 @@ def add_new_profile (request): last_name=last_name, email=email, ) + einfo = ExtraInfo.objects.create( id=roll_no, @@ -1253,6 +1273,11 @@ def add_new_profile (request): working=user, designation=desig, ) + + user.save() + einfo.save() + stud_data.save() + hold_des.save() sem_id = Semester.objects.get(curriculum = batch.curriculum, semester_no = sem) course_slots = CourseSlot.objects.all().filter(semester = sem_id) @@ -2063,14 +2088,15 @@ def view_all_student_data(request): "specailization": student.specialization, "gender" : student.id.sex, "category": student.category, - "pwd_status": student.pwd_status, + # "pwd_status": student.pwd_status, + "pwd_status": False, "Mobile": student.id.phone_no, "dob" : student.id.date_of_birth, "emailid" : student.id.user.email, "father_name": student.father_name, - "father_mobile_no": student.father_mobile_no, + # "father_mobile_no": student.father_mobile_no, "mother_name": student.mother_name, - "mother_mobile_no": student.mother_mobile_no, + # "mother_mobile_no": student.mother_mobile_no, "address": student.id.address } data.append(obj) @@ -2140,9 +2166,9 @@ def generatestudentxlsheet(request): data = None else: if(request_rollno != ""): - students = Student.objects.select_related('batch_id', 'id__user', 'batch_id__discipline', 'id').filter(id = request_rollno).only('batch', 'id__id', 'id__user', 'programme','pwd_status', 'father_mobile_no', 'mother_mobile_no', 'batch_id__discipline__acronym', 'specialization', 'id__sex', 'category', 'id__phone_no', 'id__date_of_birth', 'id__user__first_name', 'id__user__last_name', 'id__user__email', 'father_name', 'mother_name', 'id__address') + students = Student.objects.select_related('batch_id', 'id__user', 'batch_id__discipline', 'id').filter(id = request_rollno).only('batch', 'id__id', 'id__user', 'programme', 'batch_id__discipline__acronym', 'specialization', 'id__sex', 'category', 'id__phone_no', 'id__date_of_birth', 'id__user__first_name', 'id__user__last_name', 'id__user__email', 'father_name', 'mother_name', 'id__address') else: - students = Student.objects.select_related('batch_id', 'id__user', 'batch_id__discipline', 'id').filter(**filter_names).order_by('id').all().only('batch', 'id__id', 'id__user', 'programme','pwd_status', 'father_mobile_no', 'mother_mobile_no', 'batch_id__discipline__acronym', 'specialization', 'id__sex', 'category', 'id__phone_no', 'id__date_of_birth', 'id__user__first_name', 'id__user__last_name', 'id__user__email', 'father_name', 'mother_name', 'id__address') + students = Student.objects.select_related('batch_id', 'id__user', 'batch_id__discipline', 'id').filter(**filter_names).order_by('id').all().only('batch', 'id__id', 'id__user', 'programme', 'batch_id__discipline__acronym', 'specialization', 'id__sex', 'category', 'id__phone_no', 'id__date_of_birth', 'id__user__first_name', 'id__user__last_name', 'id__user__email', 'father_name', 'mother_name', 'id__address') for i in students: obj = [] obj.append(i.batch) @@ -2153,14 +2179,17 @@ def generatestudentxlsheet(request): obj.append(i.specialization) obj.append(i.id.sex) obj.append(i.category) - obj.append(i.pwd_status) + #obj.append(i.pwd_status) + obj.append(None) obj.append(i.id.phone_no) obj.append(i.id.date_of_birth) obj.append(i.id.user.email) obj.append(i.father_name) - obj.append(i.father_mobile_no) + #obj.append(i.father_mobile_no) + obj.append(None) obj.append(i.mother_name) - obj.append(i.mother_mobile_no) + # obj.append(i.mother_mobile_no) + obj.append(None) obj.append(i.id.address) data.append(obj) data.sort() diff --git a/FusionIIIT/applications/academic_procedures/api/serializers.py b/FusionIIIT/applications/academic_procedures/api/serializers.py index e8020d0e0..e210d8586 100644 --- a/FusionIIIT/applications/academic_procedures/api/serializers.py +++ b/FusionIIIT/applications/academic_procedures/api/serializers.py @@ -1,13 +1,15 @@ from rest_framework.authtoken.models import Token from rest_framework import serializers -from applications.academic_procedures.models import (ThesisTopicProcess, InitialRegistrations, - FinalRegistrations, SemesterMarks, - BranchChange) +from applications.academic_procedures.models import (ThesisTopicProcess, InitialRegistrations,InitialRegistration, + FinalRegistration, FinalRegistrations, SemesterMarks, + BranchChange , StudentRegistrationChecks, Semester, backlog_course , CourseSlot , FeePayments , course_registration) + +from applications.programme_curriculum.models import Course from applications.academic_information.api.serializers import (CurriculumInstructorSerializer, - CurriculumSerializer) -from applications.globals.api.serializers import (UserSerializer, HoldsDesignationSerializer) + CurriculumSerializer , CourseSerializer , StudentSerializers ) +from applications.globals.api.serializers import (UserSerializer, HoldsDesignationSerializer , ExtraInfoSerializer) class ThesisTopicProcessSerializer(serializers.ModelSerializer): @@ -27,6 +29,24 @@ class Meta: model = FinalRegistrations fields = ('__all__') +class InitialRegistrationSerializer(serializers.ModelSerializer): + + class Meta: + model = InitialRegistration + fields = ('__all__') + +class FinalRegistrationSerializer(serializers.ModelSerializer): + + class Meta: + model = FinalRegistration + fields = ('__all__') + +class StudentRegistrationChecksSerializer(serializers.ModelSerializer): + class Meta: + model = StudentRegistrationChecks + fields = '__all__' + + class SemesterMarksSerializer(serializers.ModelSerializer): class Meta: @@ -38,3 +58,27 @@ class BranchChangeSerializer(serializers.ModelSerializer): class Meta: model = BranchChange fields = ('__all__') + +class SemesterSerializer(serializers.ModelSerializer): + + class Meta: + model = Semester + fields = ('__all__') + +class CourseRegistrationSerializer(serializers.ModelSerializer): + class Meta: + model = course_registration + fields = ('__all__') + +class CourseSlotSerializer(serializers.ModelSerializer): + class Meta: + model = CourseSlot + fields = ('__all__') + + +class CourseSerializer(serializers.ModelSerializer): + + class Meta: + model = Course + fields = ['id','code','name','credit'] + \ No newline at end of file diff --git a/FusionIIIT/applications/academic_procedures/api/urls.py b/FusionIIIT/applications/academic_procedures/api/urls.py index 3abeace02..786c12760 100644 --- a/FusionIIIT/applications/academic_procedures/api/urls.py +++ b/FusionIIIT/applications/academic_procedures/api/urls.py @@ -1,12 +1,46 @@ from django.conf.urls import url - from . import views + urlpatterns = [ + url(r'^stu/details', views.academic_procedures_student, name='student_procedures'), + url(r'^stu/pre_registration' , views.student_pre_registration , name = 'pre_registration'), + url(r'^stu/final_registration' , views.final_registration , name = 'final_registration'), + url(r'^stu/add_one_course/' , views.add_one_course , name = 'add_one_course'), + url(r'^stu/view_registration' , views.student_view_registration , name = 'view_registration'), + url(r'^stu/view_offered_courses' , views.view_offered_courses , name = 'student_view_offered_courses'), + url(r'^stu/backlog_courses', views.student_backlog_courses , name = 'student_backlog_courses'), + url(r'^stu/add_course' , views.add_course , name ='add_course') , + url(r'^stu/drop_course' , views.drop_course , name = 'drop_course'), + # url(r'^stu/replaceCourse' , views.replaceCourse , name = 'replaceCourse') + + + + url(r'^acad/view_registrations' , views.acad_view_reigstrations , name='acad_view_registrations'), + url(r'^acad/verify_registration' , views.verify_registration , name='verify_registration'), + url(r'^acad/verify_course' , views.verify_course , name='verify_course'), + url(r'^acad/get_course_list' , views.get_course_list , name = 'get_course_list' ), + url(r'^acad/get_all_courses' , views.get_all_courses , name = 'get_all_courses' ), + url(r'^acad/gen_roll_list' , views.gen_roll_list , name = 'gen_roll_list' ), + url(r'^acad/configure_pre_registration' , views.configure_pre_registration_date , name = 'configure_pre_registration'), + url(r'^acad/configure_final_registration' , views.configure_final_registration_date , name = 'configure_final_registration'), + url(r'^acad/add_course_to_slot' , views.add_course_to_slot , name = 'add_course_to_slot'), + url(r'^acad/remove_course_from_slot' , views.remove_course_from_slot , name = 'remove_course_from_slot'), + url(r'^get_next_sem_courses' , views.get_next_sem_courses , name= 'get_next_sem_courses'), + + + url(r'^fac/view_assigned_courses' , views.faculty_assigned_courses , name = 'faculty_assigned_courses'), + # url(r'^fac/get_roll_list' , views.fetch_roll_list , name = 'fetch_roll_list'), + + + + url(r'^get_user_info' , views.get_user_info , name = 'get_user_info'), + + # these urls were designed previously and are not working any more - url(r'^fac/', views.academic_procedures_faculty, name='faculty_procedures'), - url(r'^stu/', views.academic_procedures_student, name='student_procedures'), - url(r'^addThesis/', views.add_thesis, name='add_thesis'), - url(r'^approve_thesis/(?P[0-9]+)/', views.approve_thesis, name='approve_thesis'), + # url(r'^fac/', views.academic_procedures_faculty, name='faculty_procedures'), + # url(r'^stu', views.academic_procedures_student, name='student_procedures'), + # url(r'^addThesis/', views.add_thesis, name='add_thesis'), + # url(r'^approve_thesis/(?P[0-9]+)/', views.approve_thesis, name='approve_thesis') -] +] \ No newline at end of file diff --git a/FusionIIIT/applications/academic_procedures/api/views.py b/FusionIIIT/applications/academic_procedures/api/views.py index aab6deaa7..bd3f2dc13 100644 --- a/FusionIIIT/applications/academic_procedures/api/views.py +++ b/FusionIIIT/applications/academic_procedures/api/views.py @@ -1,8 +1,10 @@ import datetime - +from django.utils import timezone from django.contrib.auth import get_user_model from django.shortcuts import get_object_or_404, redirect +from django.db import transaction +from django.http import JsonResponse from rest_framework.permissions import IsAuthenticated from rest_framework.authentication import TokenAuthentication from rest_framework import status @@ -10,11 +12,15 @@ from rest_framework.permissions import AllowAny from rest_framework.response import Response -from applications.academic_information.models import Curriculum -from applications.academic_procedures.models import ThesisTopicProcess from applications.globals.models import HoldsDesignation, Designation, ExtraInfo -from applications.programme_curriculum.models import (CourseSlot, Course as Courses, Batch, Semester) +from applications.programme_curriculum.models import ( CourseSlot, Course as Courses, Batch, Semester) +# from applications.programme_curriculum.models import Course + +from applications.academic_procedures.models import ( Student, Curriculum , ThesisTopicProcess, InitialRegistrations, + FinalRegistration, SemesterMarks,backlog_course, + BranchChange , StudentRegistrationChecks, Semester , FeePayments , course_registration) +from applications.academic_information.models import (Curriculum_Instructor , Calendar) from applications.academic_procedures.views import (get_user_semester, get_acad_year, get_currently_registered_courses, @@ -23,7 +29,11 @@ get_registration_courses, get_add_course_options, get_pre_registration_eligibility, get_final_registration_eligibility, - get_add_or_drop_course_date_eligibility) + get_add_or_drop_course_date_eligibility, + get_detailed_sem_courses, + InitialRegistration) + +from applications.academic_procedures.views import get_sem_courses, get_student_registrtion_check, get_cpi, academics_module_notif, get_final_registration_choices, get_currently_registered_course, get_add_course_options, get_drop_course_options, get_replace_course_options from . import serializers @@ -31,46 +41,13 @@ date_time = datetime.datetime.now() -@api_view(['GET']) -def academic_procedures_faculty(request): - current_user = request.user - user_details = current_user.extrainfo - des = current_user.holds_designations.all().first() - if str(des.designation) == 'student': - return Response({'error':'Not a faculty'}, status=status.HTTP_400_BAD_REQUEST) - elif str(current_user) == 'acadadmin': - return Response({'error':'User is acadadmin'}, status=status.HTTP_400_BAD_REQUEST) - - elif str(des.designation) == "Associate Professor" or str(des.designation) == "Professor" or str(des.designation) == "Assistant Professor": - faculty_object = user_details.faculty - month = int(date_time.month) - sem = [] - if month>=7 and month<=12: - sem = [1,3,5,7] - else: - sem = [2,4,6,8] - student_flag = False - fac_flag = True - thesis_supervision_request_list = faculty_object.thesistopicprocess_supervisor.all() - thesis_supervision_request_list_data = serializers.ThesisTopicProcessSerializer(thesis_supervision_request_list, many=True).data - approved_thesis_request_list = serializers.ThesisTopicProcessSerializer(thesis_supervision_request_list.filter(approval_supervisor = True), many=True).data - pending_thesis_request_list = serializers.ThesisTopicProcessSerializer(thesis_supervision_request_list.filter(pending_supervisor = True), many=True).data - courses_list = serializers.CurriculumInstructorSerializer(user_details.curriculum_instructor_set.all(), many=True).data - fac_details = serializers.UserSerializer(current_user).data +#--------------------------------------- APIs of student---------------------------------------------------------- - resp = { - 'student_flag' : student_flag, - 'fac_flag' : fac_flag, - 'thesis_supervision_request_list' : thesis_supervision_request_list_data, - 'pending_thesis_request_list' : pending_thesis_request_list, - 'approved_thesis_request_list' : approved_thesis_request_list, - 'courses_list': courses_list, - 'faculty': fac_details - } - return Response(data=resp, status=status.HTTP_200_OK) +demo_date = timezone.now() +# with this student can get all his details in one api call @api_view(['GET']) def academic_procedures_student(request): current_user = request.user @@ -128,6 +105,10 @@ def academic_procedures_student(request): else: return Response({'message':'Student has no record'}, status=status.HTTP_400_BAD_REQUEST) + + current_date = demo_date.date() + year = demo_date.year + current_date = date_time.date() current_year = date_time.year batch = obj.batch_id @@ -145,8 +126,10 @@ def academic_procedures_student(request): 'cpi' : cpi, 'spi' : cur_spi } + currently_registered_courses = get_currently_registered_courses(user_details.id, user_sem) currently_registered_courses_data = serializers.CurriculumSerializer(currently_registered_courses, many=True).data + try: pre_registered_courses = obj.initialregistrations_set.all().filter(semester = user_sem) pre_registered_courses_show = obj.initialregistrations_set.all().filter(semester = user_sem+1) @@ -158,13 +141,17 @@ def academic_procedures_student(request): except: final_registered_courses = None - pre_registered_courses_data = serializers.InitialRegistrationsSerializer(pre_registered_courses, many=True).data - pre_registered_courses_show_data = serializers.InitialRegistrationsSerializer(pre_registered_courses_show, many=True).data + + # pre_registered_courses_data = serializers.InitialRegistrationsSerializer(pre_registered_courses, many=True).data + # pre_registered_courses_show_data = serializers.InitialRegistrationsSerializer(pre_registered_courses_show, many=True).data final_registered_courses_data = serializers.FinalRegistrationsSerializer(final_registered_courses, many=True).data current_credits = get_current_credits(currently_registered_courses) - - next_sem_branch_courses = get_branch_courses(current_user, user_sem+1, user_branch) + print(current_user, user_sem+1, user_branch) + try: + next_sem_branch_courses = get_branch_courses(current_user, user_sem+1, user_branch) + except Exception as e: + return Response(data = str(e)) next_sem_branch_courses_data = serializers.CurriculumSerializer(next_sem_branch_courses, many=True).data fee_payment_mode_list = dict(Constants.PaymentMode) @@ -173,7 +160,8 @@ def academic_procedures_student(request): next_sem_branch_registration_courses_data = [] for choices in next_sem_branch_registration_courses: next_sem_branch_registration_courses_data.append(serializers.CurriculumSerializer(choices, many=True).data) - # next_sem_branch_registration_courses_data = serializers.CurriculumSerializer(next_sem_branch_registration_courses, many=True).data + # print(next_sem_branch_registration_courses_data) + # next_sem_branch_registration_courses_data = serializers.CurriculumSerializer(next_sem_branch_registration_courses_data, many=True).data final_registration_choices = get_registration_courses(get_branch_courses(request.user, user_sem, user_branch)) final_registration_choices_data = [] @@ -196,37 +184,141 @@ def academic_procedures_student(request): current_sem_branch_courses = get_branch_courses(current_user, user_sem, user_branch) - pre_registration_date_flag = get_pre_registration_eligibility(current_date) + pre_registration_date_flag = get_pre_registration_eligibility(current_date , user_sem , acad_year) final_registration_date_flag = get_final_registration_eligibility(current_date) add_or_drop_course_date_flag = get_add_or_drop_course_date_eligibility(current_date) - student_registration_check_pre = obj.studentregistrationcheck_set.all().filter(semester=user_sem+1) - student_registration_check_final = obj.studentregistrationcheck_set.all().filter(semester=user_sem) + curr_id = batch.curriculum + curr_sem_id = Semester.objects.get(curriculum = curr_id, semester_no = obj.curr_semester_no) + + try: + semester_no = obj.curr_semester_no+1 + next_sem_id = Semester.objects.get(curriculum = curr_id, semester_no = semester_no) + user_sem = semester_no + + except Exception as e: + user_sem = get_user_semester(request.user, ug_flag, masters_flag, phd_flag) + next_sem_id = curr_sem_id + + # student_registration_check_final = get_student_registrtion_check(obj,next_sem_id) + + cpi = get_cpi(user_details.id) + + next_sem_registration_courses = get_sem_courses(next_sem_id, batch) + print(next_sem_registration_courses) + + next_sem_courses = [] + + for course_slot in next_sem_registration_courses: + courses = course_slot.courses.all() + courselist = [] + for course in courses: + courselist.append({'course_id': course.id, 'name': course.name, 'credit': course.credit, 'course_code': course.code}); + next_sem_courses.append({'slot_id': course_slot.id,'slot_name':course_slot.name, 'slot_type': course_slot.type, 'semester': course_slot.semester.semester_no, 'slot_info': course_slot.course_slot_info, 'courses': courselist }) + + # print(next_sem_courses) + + print(current_date, user_sem, year) + pre_registration_date_flag, prd_start_date= get_pre_registration_eligibility(current_date, user_sem, year) + final_registration_date_flag = get_final_registration_eligibility(current_date) + add_or_drop_course_date_flag = get_add_or_drop_course_date_eligibility(current_date) + + # student_registration_check_pre = obj.studentregistrationcheck_set.all().filter(semester=user_sem+1) + # student_registration_check_final = obj.studentregistrationcheck_set.all().filter(semester=user_sem) + + print("nextsem",next_sem_id.semester_no) + student_registration_check = get_student_registrtion_check(obj,next_sem_id.id) + print("adf",student_registration_check) + pre_registration_flag = False final_registration_flag = False - if(student_registration_check_pre): - pre_registration_flag = student_registration_check_pre.pre_registration_flag - if(student_registration_check_final): - final_registration_flag = student_registration_check_final.final_registration_flag + + if(student_registration_check): + pre_registration_flag = student_registration_check.pre_registration_flag + final_registration_flag = student_registration_check.final_registration_flag + # if(student_registration_check): teaching_credit_registration_course = None if phd_flag: teaching_credit_registration_course = Curriculum.objects.all().filter(batch = 2016, sem =6) teaching_credit_registration_course_data = serializers.CurriculumSerializer(teaching_credit_registration_course, many=True).data - if student_flag: - try: - due = obj.dues_set.get() - lib_d = due.library_due - pc_d = due.placement_cell_due - hos_d = due.hostel_due - mess_d = due.mess_due - acad_d = due.academic_due - except: - lib_d, pc_d, hos_d, mess_d, acad_d = 0, 0, 0, 0, 0 - tot_d = lib_d + acad_d + pc_d + hos_d + mess_d + try: + pre_registered_courses = InitialRegistration.objects.all().filter(student_id = user_details.id,semester_id = next_sem_id) + pre_registered_course_show = [] + pre_registration_timestamp=None + for pre_registered_course in pre_registered_courses: + pre_registration_timestamp=pre_registered_course.timestamp + if(pre_registered_course.course_slot_id.name not in pre_registered_course_show): + pre_registered_course_show.append({"slot_name": pre_registered_course.course_slot_id.name ,"course_code":pre_registered_course.course_id.code,"course_name":pre_registered_course.course_id.name,"course_credit":pre_registered_course.course_id.credit,"priority":pre_registered_course.priority}) + else: + pre_registered_course_show[pre_registered_course.course_slot_id.name].append({"course_code":pre_registered_course.course_id.code,"course_name":pre_registered_course.course_id.name,"course_credit":pre_registered_course.course_id.credit,"priority":pre_registered_course.priority}) + pre_registration_timestamp=str(pre_registration_timestamp) + except Exception as e: + pre_registered_courses = None + pre_registered_course_show = None + + next_sem_branch_course = get_sem_courses(next_sem_id, batch) + current_sem_branch_course = get_sem_courses(curr_sem_id, batch) + next_sem_registration_courses = get_sem_courses(next_sem_id, batch) + final_registration_choice, unavailable_courses_nextsem = get_final_registration_choices(next_sem_registration_courses,batch.year) + currently_registered_course = get_currently_registered_course(obj,next_sem_id) + + # currently_registered_course_show = [] + # for registered_course in currently_registered_course: + # currently_registered_course_show.append({"course_code":registered_course[1].code,"course_name":registered_course[1].name,"course_credit":registered_course[1].credit}) + + try: + final_registered_courses = FinalRegistration.objects.all().filter(student_id = user_details.id,semester_id = next_sem_id) + final_registered_course_show=[] + for final_registered_course in final_registered_courses: + final_registered_course_show.append({"course_code":final_registered_course.course_id.code,"course_name":final_registered_course.course_id.name,"course_credit":final_registered_course.course_id.credit}) + + + except Exception as e: + final_registered_courses = None + final_registered_course_show = None + + drop_courses_options = None + add_courses_options = None + replace_courses_options = None + + add_courses_options = get_add_course_options(current_sem_branch_course, currently_registered_course, batch.year) + + add_courses_options_show = [] + for course_option in add_courses_options: + course_slot = course_option[0] + courses = course_option[1] + courselist = [] + for course in courses: + courselist.append({'course_id': course.id, 'name': course.name, 'credit': course.credit, 'course_code': course.code}); + add_courses_options_show.append({'slot_id': course_slot.id,'slot_name':course_slot.name, 'slot_type': course_slot.type, 'semester': course_slot.semester.semester_no, 'slot_info': course_slot.course_slot_info, 'courses': courselist }) + + + drop_courses_options = get_drop_course_options(currently_registered_course) + drop_courses_options_show = [] + + for course in drop_courses_options: + drop_courses_options_show.append({'course_id': course.id, 'name': course.name, 'credit': course.credit, 'course_code': course.code}) + + replace_courses_options = get_replace_course_options(currently_registered_course, batch.year) + print("replace",replace_courses_options) + + backlogCourseList = [] + auto_backlog_courses = list(SemesterMarks.objects.filter(student_id = obj , grade = 'F')) + auto_backlog_courses_list = [] + for i in auto_backlog_courses: + if not i.curr_id.courseslots.filter(type__contains="Optional").exists(): + auto_backlog_courses_list.append({'course_name':i.curr_id.name, 'course_code': i.curr_id.code, 'course_version': i.curr_id.version, 'course_credit': i.curr_id.credit ,'course_grade': i.grade}) + + backlogCourses = backlog_course.objects.select_related('course_id' , 'student_id' , 'semester_id' ).filter(student_id=obj) + for i in backlogCourses: + summer_course = "Yes" if i.is_summer_course else "No" + course_details = i.course_id.course_details if i.course_id.course_details else "N/A" + + backlogCourseList.append([i.course_id.course_name, course_details , i.semester_id.semester_no , summer_course]) registers = obj.register_set.all() course_list = [] @@ -254,145 +346,1199 @@ def academic_procedures_student(request): if user_sem == 2: branchchange_flag=True - # faculty_list = serializers.HoldsDesignationSerializer(get_faculty_list(), many=True).data + faculty_list = serializers.HoldsDesignationSerializer(get_faculty_list(), many=True).data resp = { 'details': details, - 'currently_registered': currently_registered_courses_data, - 'pre_registered_courses' : pre_registered_courses_data, - 'pre_registered_courses_show' : pre_registered_courses_show_data, - 'final_registered_courses' : final_registered_courses_data, + 'user_sem' : user_sem, + # 'currently_registered_course': currently_registered_course, + # 'pre_registered_courses' : pre_registered_courses, + 'pre_registered_courses_show' : pre_registered_course_show, + # 'final_registered_courses' : final_registered_courses, + 'final_registered_course_show' : final_registered_course_show, 'current_credits' : current_credits, 'courses_list': next_sem_branch_courses_data, 'fee_payment_mode_list' : fee_payment_mode_list, + 'next_sem_registration_courses': next_sem_courses, 'next_sem_branch_registration_courses' : next_sem_branch_registration_courses_data, 'final_registration_choices' : final_registration_choices_data, - 'performance_list' : performance_list_data, - 'thesis_request_list' : thesis_request_list, + 'backlogCourseList': auto_backlog_courses_list, + 'student_flag' : student_flag, 'ug_flag' : ug_flag, 'masters_flag' : masters_flag, 'phd_flag' : phd_flag, 'fac_flag' : fac_flag, 'des_flag' : des_flag, - 'thesis_flag' : pre_existing_thesis_flag, - 'drop_courses_options' : currently_registered_courses_data, + + 'prd': pre_registration_date_flag, + 'prd_start_date': prd_start_date, + 'frd': final_registration_date_flag, + 'adc_date_flag': add_or_drop_course_date_flag, + + 'add_courses_options': add_courses_options_show, + 'drop_courses_options' : drop_courses_options_show, + # 'replace_courses_options' : replace_courses_options, + 'pre_registration_date_flag': pre_registration_date_flag, 'final_registration_date_flag': final_registration_date_flag, 'add_or_drop_course_date_flag': add_or_drop_course_date_flag, - 'pre_registration_flag' : pre_registration_flag, 'final_registration_flag': final_registration_flag, + 'pre_registration_flag': pre_registration_flag, 'teaching_credit_registration_course' : teaching_credit_registration_course_data, - 'lib_d':lib_d, - 'acad_d':acad_d, - 'mess_d':mess_d, - 'pc_d':pc_d, - 'hos_d':hos_d, - 'tot_d':tot_d, + 'attendance': attendance_data, 'Branch_Change_Flag':branchchange_flag - # 'faculty_list' : faculty_list } - return Response(data=resp, status=status.HTTP_200_OK) + return Response(data=resp, status=status.HTTP_200_OK) + +@api_view(['GET']) +def get_all_courses(request): + try: + obj = Courses.objects.all() + serializer = serializers.CourseSerializer(obj, many=True).data + + return Response(serializer, status=status.HTTP_200_OK) + except Exception as e: + return Response(data = str(e) , status=status.HTTP_500_INTERNAL_SERVER_ERROR) @api_view(['POST']) -def add_thesis(request): - current_user = request.user - profile = current_user.extrainfo - if profile.user_type == 'student': - if not 'thesis_topic' in request.data: - return Response({'error':'Thesis topic is required'}, status=status.HTTP_400_BAD_REQUEST) - if not 'research_area' in request.data: - return Response({'error':'Research area is required'}, status=status.HTTP_400_BAD_REQUEST) - if 'supervisor_id' in request.data: - try: - supervisor_faculty = User.objects.get(username=request.data['supervisor_id']) - supervisor_faculty = supervisor_faculty.extrainfo - request.data['supervisor_id'] = supervisor_faculty - except: - return Response({'error':'Wrong supervisor id. User does not exist.'}, status=status.HTTP_400_BAD_REQUEST) - else: - return Response({'error':'supervisor id is required'}, status=status.HTTP_400_BAD_REQUEST) - if 'co_supervisor_id' in request.data: +def gen_roll_list(request): + try: + batch = request.data['batch'] + course_id = request.data['course'] + course = Courses.objects.get(id = course_id) + #obj = course_registration.objects.all().filter(course_id = course) + obj=course_registration.objects.filter(course_id__id=course_id, student_id__batch=batch).select_related( + 'student_id__id__user','student_id__id__department').only('student_id__batch', + 'student_id__id__user__first_name', 'student_id__id__user__last_name', + 'student_id__id__department__name','student_id__id__user__username') + except Exception as e: + batch="" + course="" + obj="" + students = [] + for i in obj: + students.append({"rollno":i.student_id.id.user.username, + "name":i.student_id.id.user.first_name+" "+i.student_id.id.user.last_name, + "department":i.student_id.id.department.name}) + # {'students': students, 'batch':batch, 'course':course_id} + return JsonResponse({'students': students, 'batch':batch, 'course':course_id}, status=200) + + +# api for student for adding courses +@api_view(['POST']) +def add_course(request): + try: + current_user = request.user + current_user = ExtraInfo.objects.all().filter(user=current_user).first() + current_user = Student.objects.all().filter(id=current_user.id).first() + + sem_id_instance = Semester.objects.get(id = request.data['semester']) + + count = request.data['ct'] + count = int(count) + reg_curr = [] + + for i in range(1, count+1): + choice = "choice["+str(i)+"]" + slot = "slot["+str(i)+"]" try: - co_supervisor_faculty = User.objects.get(username=request.data['co_supervisor_id']) - co_supervisor_faculty = co_supervisor_faculty.extrainfo - request.data['co_supervisor_id'] = co_supervisor_faculty - except: - return Response({'error':'Wrong co_supervisor id. User does not exist.'}, status=status.HTTP_400_BAD_REQUEST) - else: - co_supervisor_faculty = None - if 'curr_id' in request.data: - curr_id = None - student = profile.student - request.data['student_id'] = profile - request.data['submission_by_student'] = True - serializer = serializers.ThesisTopicProcessSerializer(data=request.data) - if serializer.is_valid(): - serializer.save() - return Response(serializer.data, status=status.HTTP_200_OK) - else: - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) - else: - return Response({'error':'Cannot add thesis'}, status=status.HTTP_400_BAD_REQUEST) + course_id_instance = Courses.objects.get(id = request.data[choice]) + courseslot_id_instance = CourseSlot.objects.get(id = request.data[slot]) + + print(courseslot_id_instance.max_registration_limit) + if course_registration.objects.filter(working_year = current_user.batch_id.year, course_id = course_id_instance).count() < courseslot_id_instance.max_registration_limit and (course_registration.objects.filter(course_id=course_id_instance, student_id=current_user).count() == 0): + print("space left = True") + p = course_registration( + course_id=course_id_instance, + student_id=current_user, + course_slot_id=courseslot_id_instance, + semester_id=sem_id_instance + ) + print(serializers.course_registration(p)) + if p not in reg_curr: + reg_curr.append(p) + else: + print("already exist") + except Exception as e: + error_message = str(e) + resp = {'message': 'Course addition failed', 'error': error_message} + return Response(resp, status=status.HTTP_400_BAD_REQUEST) + print(reg_curr) + course_registration_data = course_registration.objects.bulk_create(reg_curr) + course_registration_data = serializers.CourseRegistrationSerializer(course_registration_data , many = True).data + res = {'message' : 'Courses successfully added' , "courses_added" : course_registration_data } + return Response(data = res , status = status.HTTP_200_OK) + except Exception as e: + print(e) + return Response(data = str(e) , status= status.HTTP_500_INTERNAL_SERVER_ERROR) -@api_view(['PUT']) -def approve_thesis(request, id): + +@api_view(['POST']) +def drop_course(request): current_user = request.user - profile = current_user.extrainfo - if profile.user_type == 'faculty': + current_user = ExtraInfo.objects.all().filter(user=current_user).first() + current_user = Student.objects.all().filter(id = current_user.id).first() + + courses = request.data['courses'] + + for course in courses: try: - thesis = ThesisTopicProcess.objects.get(id=id) - except: - return Response({'error':'This thesis does not exist'}, status=status.HTTP_400_BAD_REQUEST) - if 'member1' in request.data: - try: - user1 = User.objects.get(username=request.data['member1']) - member1 = user1.extrainfo - request.data['member1'] = member1 - except: - return Response({'error':'Wrong username of member 1. User does not exist.'}, status=status.HTTP_400_BAD_REQUEST) - else: - return Response({'error':'Member 1 is required'}, status=status.HTTP_400_BAD_REQUEST) - if 'member2' in request.data: - try: - user2 = User.objects.get(username=request.data['member2']) - member2 = user2.extrainfo - request.data['member2'] = member2 - except: - return Response({'error':'Wrong username of member 2. User does not exist.'}, status=status.HTTP_400_BAD_REQUEST) - else: - return Response({'error':'Member 2 is required'}, status=status.HTTP_400_BAD_REQUEST) - if 'member3' in request.data: - try: - user3 = User.objects.get(username=request.data['member3']) - member3 = user3.extrainfo - request.data['member3'] = member3 - except: - return Response({'error':'Wrong username of member 3. User does not exist.'}, status=status.HTTP_400_BAD_REQUEST) - else: - member3 = None - if not 'approval' in request.data: - return Response({'error':'Approval value is required.'}, status=status.HTTP_400_BAD_REQUEST) - elif request.data['approval'] != 'yes' and request.data['approval'] != 'no': - return Response({'error':'Wrong approval value provided. Approval value should be yes or no'}, status=status.HTTP_400_BAD_REQUEST) - if request.data['approval'] == 'yes': - request.data.pop('approval', None) - request.data['pending_supervisor'] = False - request.data['approval_supervisor'] = True - request.data['forwarded_to_hod'] = True - request.data['pending_hod'] = True + course_id = Courses.objects.all().filter(id=course).first() + course_registration.objects.filter(course_id = course_id, student_id = current_user).delete() + except Exception as e: + resp = {"message" : "Course drop failed", "error" : str(e)} + return Response(data = resp, status = status.HTTP_400_BAD_REQUEST) + + resp = {"message" : "Course successfully dropped"} + return Response(data = resp , status = status.HTTP_200_OK) + + +# simple api for getting to know the details of user who have logined in the system +@api_view(['GET']) +def get_user_info(request): + current_user = request.user + details1 = serializers.UserSerializer(current_user).data + details2 = serializers.ExtraInfoSerializer(current_user.extrainfo).data + details = { + "user_serializer_Data" : details1, + "ExtraInfoSerializer_Data" : details2 + } + return Response(data = details , status= status.HTTP_200_OK) + + +# with this api student can see the list of courses offered to him in upcoming semester +@api_view(['POST']) +def view_offered_courses(request): + try : + obj = Curriculum.objects.filter( + programme = request.data['programme'], + branch = request.data['branch'], + batch = request.data["batch"], + sem = request.data["semester"] + ) + serializer = serializers.CurriculumSerializer(obj, many=True).data + return Response(serializer, status=status.HTTP_200_OK) + except Exception as e: + return Response(data = str(e) , status=status.HTTP_500_INTERNAL_SERVER_ERROR) + # try: + # ug_flag = True + # masters_flag = False + # phd_flag = False + # current_semester = get_user_semester(request.user, ug_flag, masters_flag, phd_flag) + # current_year = date_time.date().year + + # return Response(data= { } , status=status.HTTP_200_OK) + # except Exception as e: + # return Response(data = {"error" : str(e)} , status= status.HTTP_500_INTERNAL_SERVER_ERROR) + + +# with this student can know status of pre registration and final registration +@api_view(['GET']) +def student_view_registration(request): + try: + # getting the registration status of current user for the given semester + current_user = request.user + student_id = current_user.extrainfo.id + + sem_id = Semester.objects.get(id = request.data.get('semester')) + sem_id = serializers.SemesterSerializer(sem_id).data["id"] + + # filter based on the semester id and student id + obj = StudentRegistrationChecks.objects.filter(semester_id_id = sem_id, student_id = student_id) + + # serialize the data for displaying + serializer = serializers.StudentRegistrationChecksSerializer(obj, many=True).data + + return Response(serializer, status=status.HTTP_200_OK) + except Exception as e: + return Response(data = str(e) , status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + +# with this student can do his pre registration for the upcoming semester +@api_view(['POST']) +@transaction.atomic +def student_pre_registration(request): + try: + current_user = request.user + current_user_id = serializers.UserSerializer(current_user).data["id"] + s_id = current_user.extrainfo.id + + current_user = ExtraInfo.objects.all().select_related('user','department').filter(user=current_user_id).first() + current_user = serializers.ExtraInfoSerializer(current_user).data + + current_user_instance = Student.objects.all().filter(id=current_user["id"]).first() + current_user = serializers.StudentSerializers(current_user_instance).data + + sem_id_instance = Semester.objects.get(id = request.data.get('semester')) + sem_id = serializers.SemesterSerializer(sem_id_instance).data["id"] + + # filter based on the semester id and student id + obj = StudentRegistrationChecks.objects.filter(semester_id_id = sem_id, student_id = s_id) + # serialize the data for displaying + student_registration_check = serializers.StudentRegistrationChecksSerializer(obj, many=True).data + + try: + # check if user have already done pre registration + if(student_registration_check and student_registration_check[0]["pre_registration_flag"] ): + return Response(data = {"message" : "You have already registered for this semester" }, status=status.HTTP_400_BAD_REQUEST) + except Exception as e: + return Response(data = str(e) , status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + course_slots=request.data.get("course_slot") + reg_curr = [] + + + for course_slot in course_slots : + course_priorities = request.data.get("course_priority-"+course_slot) + if(course_priorities[0] == 'NULL'): + print("NULL FOUND") + continue + course_slot_id_for_model = CourseSlot.objects.get(id = int(course_slot)) + + # return Response(data = course_slots , status=status.HTTP_200_OK) + for course_priority in course_priorities: + priority_of_current_course,course_id = map(int,course_priority.split("-")) + # get course id for the model + course_id_for_model = Courses.objects.get(id = course_id) + print("check") + p = InitialRegistration( + course_id = course_id_for_model, + semester_id = sem_id_instance, + student_id = current_user_instance, + course_slot_id = course_slot_id_for_model, + priority = priority_of_current_course + ) + p.save() + reg_curr.append(p) + + + try: + serialized_reg_curr = serializers.InitialRegistrationSerializer(reg_curr, many=True).data + + registration_check = StudentRegistrationChecks( + student_id = current_user_instance, + pre_registration_flag = True, + final_registration_flag = False, + semester_id = sem_id_instance + ) + registration_check.save() + return Response(data={"message": "Successfully Registered for the courses.", "registrations": serialized_reg_curr}, status=status.HTTP_200_OK) + except Exception as e: + return Response(data = {"message" : "Error in Registration." , "error" : str(e)} , status=status.HTTP_500_INTERNAL_SERVER_ERROR) + except Exception as e: + return Response(data = {"message" : "Error in Registration." , "error" : str(e)} , status=status.HTTP_500_INTERNAL_SERVER_ERROR) + +@api_view(['POST']) +def final_registration(request): + try: + print(request.data) + current_user = get_object_or_404(User, username=request.data.get('user')) + current_user = ExtraInfo.objects.all().select_related('user','department').filter(user=current_user).first() + current_user = Student.objects.all().filter(id=current_user.id).first() + + sem_id = Semester.objects.get(id = request.data.get('semester')) + + mode = str(request.data.get('mode')) + transaction_id = str(request.data.get('transaction_id')) + deposit_date = request.data.get('deposit_date') + utr_number = str(request.data.get('utr_number')) + fee_paid = request.data.get('fee_paid') + actual_fee = request.data.get('actual_fee') + reason = str(request.data.get('reason')) + if reason=="": + reason=None + # fee_receipt = request.FILES['fee_receipt'] + + obj = FeePayments( + student_id = current_user, + semester_id = sem_id, + mode = mode, + transaction_id = transaction_id, + # fee_receipt = fee_receipt, + deposit_date = deposit_date, + utr_number = utr_number, + fee_paid = fee_paid, + actual_fee = actual_fee, + reason = reason + ) + obj.save() + + try: + return JsonResponse({'message': 'Final Registration Successfull'}) + except Exception as e: + return JsonResponse({'message': 'Final Registration Failed '}, status=500) + + except Exception as e: + return JsonResponse({'message': 'Final Registration Failed '}, status=500) + + +# with this student can do his final registration for the upcoming semester +@api_view(['POST']) +@transaction.atomic +def student_final_registration(request): + try: + current_user = request.user + current_user_id = serializers.UserSerializer(current_user).data["id"] + s_id = current_user.extrainfo.id + + current_user = ExtraInfo.objects.all().select_related('user','department').filter(user=current_user).first() + current_user = serializers.ExtraInfoSerializer(current_user).data + + current_user_instance = Student.objects.all().filter(id=current_user["id"]).first() + current_user = serializers.StudentSerializers(current_user_instance).data + + # these details we need from the body of the request fot doing final registration + sem_id_instance = Semester.objects.get(id = request.data.get('semester')) + sem_id = serializers.SemesterSerializer(sem_id_instance).data["id"] + registration_status = StudentRegistrationChecks.objects.filter(student_id = current_user["id"], semester_id = sem_id) + registration_status = serializers.StudentRegistrationChecksSerializer(registration_status , many = True ).data + + if(len(registration_status)>0 and registration_status[0]["pre_registration_flag"] == False): + return Response(data = {"message" : "Student haven't done pre registration yet."} , status= status.HTTP_400_BAD_REQUEST ) + mode = str(request.data.get('mode')) + transaction_id = str(request.data.get('transaction_id')) + deposit_date = request.data.get('deposit_date') + utr_number = str(request.data.get('utr_number')) + fee_paid = request.data.get('fee_paid') + actual_fee = request.data.get('actual_fee') + reason = str(request.data.get('reason')) + if reason=="": + reason=None + # fee_receipt = request.FILES['fee_receipt'] + + # print(fee_receipt) + obj = FeePayments( + student_id = current_user_instance, + semester_id = sem_id_instance, + mode = mode, + transaction_id = transaction_id, + # fee_receipt = fee_receipt, + deposit_date = deposit_date, + utr_number = utr_number, + fee_paid = fee_paid, + actual_fee = actual_fee, + reason = reason + ) + obj.save() + try: + registration_status = StudentRegistrationChecks.objects.filter(student_id = current_user_instance, semester_id = sem_id).update(final_registration_flag = True) + return Response(data = {"message" : "Final Registration Successfull" } , status= status.HTTP_200_OK) + except Exception as e: + return Response(data = {"message" : "Final Registration Failed " , "error" : str(e)} , status = status.HTTP_500_INTERNAL_SERVER_ERROR) + except Exception as e: + return Response(data = {"message" : "Final Registration Failed " , "error" : str(e)} , status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + +# with this api student can get his backlog courses list +@api_view(['GET']) +def student_backlog_courses(request): + try : + stu_id = Student.objects.select_related('id','id__user','id__department').get(id=request.user.username) + backlogCourseList = [] + backlogCourses = backlog_course.objects.select_related('course_id' , 'student_id' , 'semester_id' ).filter(student_id=stu_id) + for i in backlogCourses: + obj = { + "course_id" : i.course_id.id, + "course_name" : i.course_id.course_name, + "faculty" : i.course_id.course_details, + "semester" : i.semester_id.semester_no, + "is_summer_course" : i.is_summer_course + } + backlogCourseList.append(obj) + + return Response(backlogCourseList, status=status.HTTP_200_OK) + except Exception as e: + return Response(data = str(e) , status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + + +#--------------------------------------- APIs of acad person---------------------------------------------------------- + + +# with this acad admin can fetch the list of courses for any batch , semester and brach +@api_view(['POST']) +def get_course_list(request): + + programme = request.data['programme'] + branch = request.data['branch'] + batch = request.data['batch'] + + try : + print(programme , branch , batch) + obj = Curriculum.objects.filter( + programme = request.data['programme'], + branch = request.data['branch'], + batch = request.data["batch"] + ) + serializer = serializers.CurriculumSerializer(obj, many=True).data + return Response(serializer, status=status.HTTP_200_OK) + except Exception as e: + return Response(data = str(e) , status=status.HTTP_500_INTERNAL_SERVER_ERROR) + # obj = Curriculum.objects.filter(curriculum_id_=curriculum_id, course_type_ = course_type, programme_ = programme, batch_ = batch, branch_ = branch, sem_ = sem, optional_ = optional) + + +# with this api acad person can see the list of students who have completed their pre and final registrations for any semester +@api_view(['GET']) +def acad_view_reigstrations(request): + try: + semester = request.data["semester"] + sem_id_instance = Semester.objects.get(id = request.data.get('semester')) + sem_id = serializers.SemesterSerializer(sem_id_instance).data["id"] + obj = StudentRegistrationChecks.objects.filter(semester_id_id = sem_id, final_registration_flag =True) + student_registration_check = serializers.StudentRegistrationChecksSerializer(obj, many=True).data + + return Response(data= student_registration_check , status=status.HTTP_200_OK) + except Exception as e: + return Response(data = {"error" : str(e)} , status= status.HTTP_500_INTERNAL_SERVER_ERROR) + + +# with this api acad person set the date of pre registration date for any semester +@api_view(['POST']) +def configure_pre_registration_date(request): + try: + try: + from_date = request.data.get('from_date') + to_date = request.data.get('to_date') + semester = request.data.get('semester') + current_year = date_time.date().year + desc = "Pre Registration " + str(semester) +" " + str(current_year) + print(from_date , to_date , desc) + from_date = from_date.split('-') + from_date = [int(i) for i in from_date] + from_date = datetime.datetime(*from_date).date() + to_date = to_date.split('-') + to_date = [int(i) for i in to_date] + to_date = datetime.datetime(*to_date).date() + except Exception as e: + from_date="" + to_date="" + desc="" + pass + c = Calendar( + from_date=from_date, + to_date=to_date, + description=desc) + c.save() + return Response(data = {"message" : "Pre registration for semester " + str(semester) + " will be opened from " + str(from_date) + " to " + str(to_date) + ". " , } , status= status.HTTP_200_OK) + except Exception as e: + return Response(data = {"error " : str(e)} , status= status.HTTP_500_INTERNAL_SERVER_ERROR) + + +# with this api request acad person can set the date of final registration +@api_view(['POST']) +def configure_final_registration_date(request): + try: + try: + from_date = request.data.get('from_date') + to_date = request.data.get('to_date') + semester = request.data.get('semester') + current_year = date_time.date().year + desc = "Physical Reporting at the Institute" + print(from_date , to_date , desc) + from_date = from_date.split('-') + from_date = [int(i) for i in from_date] + from_date = datetime.datetime(*from_date).date() + to_date = to_date.split('-') + to_date = [int(i) for i in to_date] + to_date = datetime.datetime(*to_date).date() + except Exception as e: + from_date="" + to_date="" + desc="" + pass + c = Calendar( + from_date=from_date, + to_date=to_date, + description=desc) + c.save() + return Response(data = {"message" : "Physical Reporting at the Institute will be opened from " + str(from_date) + " to " + str(to_date) + ". " , } , status= status.HTTP_200_OK) + except Exception as e: + return Response(data = {"error " : str(e)} , status= status.HTTP_500_INTERNAL_SERVER_ERROR) + +# with this api request acad person can add any courses in a specific slot +@api_view(['POST']) +def add_course_to_slot(request): + course_code = request.data.get('course_code') + course_slot_name = request.data.get('course_slot_name') + try: + course_slot = CourseSlot.objects.get(name=course_slot_name) + course = Courses.objects.get(code=course_code) + course_slot.courses.add(course) + + return JsonResponse({'message': f'Course {course_code} added to slot {course_slot_name} successfully.'}, status=200) + except CourseSlot.DoesNotExist: + return JsonResponse({'error': 'Course slot does not exist.'}, status=400) + except Courses.DoesNotExist: + return JsonResponse({'error': 'Course does not exist.'}, status=400) + +# with this api request acad person can remove any course from a specific slot +@api_view(['POST']) +def remove_course_from_slot(request): + course_code = request.data.get('course_code') + course_slot_name = request.data.get('course_slot_name') + try: + course_slot = CourseSlot.objects.get(name=course_slot_name) + course = Courses.objects.get(code=course_code) + course_slot.courses.remove(course) + return JsonResponse({'message': f'Course {course_code} removed from slot {course_slot_name} successfully.'}, status=200) + except CourseSlot.DoesNotExist: + return JsonResponse({'error': 'Course slot does not exist.'}, status=400) + except Course.DoesNotExist: + return JsonResponse({'error': 'Course does not exist.'}, status=400) + + + +#--------------------------------------- APIs of faculty---------------------------------------------------------- + +# with this api faculty can know what are the courses assigned to him +@api_view(['GET']) +def faculty_assigned_courses(request): + + + try: + current_user = request.user + curriculum_ids = Curriculum_Instructor.objects.filter(instructor_id=current_user.id).values_list('curriculum_id', flat=True) + course_infos = [] + print(current_user.id) + for curriculum_id in curriculum_ids: + course_info = Curriculum.objects.filter(curriculum_id=curriculum_id).values_list('course_code','course_type','programme','branch','sem','course_id_id').first() + # course_infos.append(course_info) + context = { + "course_code": course_info[0], + "course_type": course_info[1], + "programme": course_info[2], + "branch": course_info[3], + "sem": course_info[4], + "course_id": course_info[5] + } + course_infos.append(context) + + return Response(data= course_infos , status=status.HTTP_200_OK) + except Exception as e: + return Response(data = {"error" : str(e)} , status= status.HTTP_500_INTERNAL_SERVER_ERROR) + + +@api_view(['POST']) +def get_next_sem_courses(request): + try: + next_sem = request.data.get('next_sem') + branch = request.data.get('branch') + programme = request.data.get('programme') + batch = request.data.get('batch') + + # we go to student table and apply filters and get batch_id of the students with these filter + batch_id = Student.objects.filter(programme = programme , batch = batch , specialization = branch)[0].batch_id + + curr_id = batch_id.curriculum + next_sem_id = Semester.objects.get(curriculum = curr_id, semester_no = next_sem) + + if next_sem_id: + next_sem_registration_courses = get_detailed_sem_courses(next_sem_id ) + return JsonResponse(next_sem_registration_courses, safe=False) + except Exception as e: + return Response(data = {"error" : str(e)} , status= status.HTTP_500_INTERNAL_SERVER_ERROR) + +@api_view(['POST']) +def add_one_course(request): + try: + print(request.data) + current_user = get_object_or_404(User, username=request.data.get('user')) + current_user = ExtraInfo.objects.all().filter(user=current_user).first() + current_user = Student.objects.all().filter(id=current_user.id).first() + + sem_id = Semester.objects.get(id=request.data.get('semester')) + choice = request.data.get('choice') + slot = request.data.get('slot') + + try: + course_id = Courses.objects.get(id=choice) + courseslot_id = CourseSlot.objects.get(id=slot) + print(courseslot_id.id) + print(courseslot_id.type) + print(courseslot_id.max_registration_limit) + if course_registration.objects.filter(course_slot_id_id=courseslot_id, student_id=current_user).count() == 1 and courseslot_id.type != "Swayam": + already_registered_course_id = course_registration.objects.filter(course_slot_id_id=courseslot_id, student_id=current_user)[0].course_id + print(already_registered_course_id) + msg = 'Already Registered in the course : ' +already_registered_course_id.code + '-'+ already_registered_course_id.name + return JsonResponse({'message' : msg}) + if((course_registration.objects.filter(course_id=course_id, student_id=current_user).count() >= 1)): + return JsonResponse({'message': 'Already registered in this course!'}, status=200) + # Check if maximum course registration limit has not been reached + if course_registration.objects.filter(student_id__batch_id__year=current_user.batch_id.year, course_id=course_id).count() < courseslot_id.max_registration_limit and \ + (course_registration.objects.filter(course_id=course_id, student_id=current_user).count() == 0): + p = course_registration( + + course_id=course_id, + student_id=current_user, + course_slot_id=courseslot_id, + semester_id=sem_id + ) + p.save() + return JsonResponse({'message': 'Course added successfully'}, status=200) + else: + return JsonResponse({'message': 'Course not added because seats are full!'}, status=404) + except Exception as e: + print(e) + return JsonResponse({'message': 'Error adding course'}, status=500) + except Exception as e: + return JsonResponse({'message': 'Error adding course'}, status=500) + + +@transaction.atomic +@api_view(['POST']) +def verify_registration(request): + if request.data.get('status_req') == "accept" : + student_id = request.data.get('student_id') + student = Student.objects.get(id = student_id) + batch = student.batch_id + curr_id = batch.curriculum + + if(student.curr_semester_no+1 >= 9): + # print('----------------------------------------------------------------' , student.curr_semester_no) + sem_no = 8 else: - request.data.pop('approval', None) - request.data['pending_supervisor'] = False - request.data['approval_supervisor'] = False - request.data['forwarded_to_hod'] = False - request.data['pending_hod'] = False - serializer = serializers.ThesisTopicProcessSerializer(thesis, data=request.data, partial=True) - if serializer.is_valid(): - serializer.save() - return Response(serializer.data, status=status.HTTP_200_OK) + # print('----------------------------------------------------------------' , student.curr_semester_no) + sem_no = student.curr_semester_no+1 + sem_id = Semester.objects.get(curriculum = curr_id, semester_no = sem_no) + # print('----------------------------------------------------------------' , student.curr_semester_no) + + final_register_list = FinalRegistration.objects.all().filter(student_id = student, verified = False, semester_id = sem_id) + + # final_register_list = FinalRegistration.objects.all().filter(student_id = student, verified = False) + + with transaction.atomic(): + for obj in final_register_list: + o = FinalRegistration.objects.filter(id= obj.id).update(verified = True) + academics_module_notif(request.user, student.id.user, 'registration_approved') + + Student.objects.filter(id = student_id).update(curr_semester_no = sem_no) + return JsonResponse({'status': 'success', 'message': 'Successfully Accepted'}) + + elif request.data.get('status_req') == "reject" : + reject_reason = request.data.get('reason') + student_id = request.data.get('student_id') + student_id = Student.objects.get(id = student_id) + batch = student_id.batch_id + curr_id = batch.curriculum + if(student_id.curr_semester_no+1 >= 9): + sem_no = 8 else: - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + sem_no = student_id.curr_semester_no+1 + sem_id = Semester.objects.get(curriculum = curr_id, semester_no = sem_no) + with transaction.atomic(): + academicadmin = get_object_or_404(User, username = "acadadmin") + # FinalRegistration.objects.filter(student_id = student_id, verified = False, semester_id = sem_id).delete() + StudentRegistrationChecks.objects.filter(student_id = student_id, semester_id = sem_id).update(final_registration_flag = False) + FeePayments.objects.filter(student_id = student_id, semester_id = sem_id).delete() + academics_module_notif(academicadmin, student_id.id.user, 'Registration Declined - '+reject_reason) + return JsonResponse({'status': 'success', 'message': 'Successfully Rejected'}) + + return JsonResponse({'status': 'error', 'message': 'Error in processing'}) + +@api_view(['POST']) +def verify_course(request): + current_user = get_object_or_404(User, username=request.user.username) + user_details = ExtraInfo.objects.all().select_related( + 'user', 'department').filter(user=current_user).first() + desig_id = Designation.objects.all().filter(name='adminstrator').first() + temp = HoldsDesignation.objects.all().select_related().filter( + designation=desig_id).first() + # acadadmin = temp.working + k = str(user_details).split() + final_user = k[2] + + # if (str(acadadmin) != str(final_user)): + # return Response() + + roll_no = request.data["rollno"] + obj = ExtraInfo.objects.all().select_related( + 'user', 'department').filter(id=roll_no).first() + firstname = obj.user.first_name + lastname = obj.user.last_name + dict2 = {'roll_no': roll_no, + 'firstname': firstname, 'lastname': lastname} + obj2 = Student.objects.all().select_related( + 'id', 'id__user', 'id__department').filter(id=roll_no).first() + + batch = obj2.batch_id + curr_id = batch.curriculum + curr_sem_id = Semester.objects.get(curriculum = curr_id, semester_no = obj2.curr_semester_no) + # curr_sem_id = obj2.curr_semester_no + details = [] + + current_sem_courses = get_currently_registered_course( + roll_no, curr_sem_id) + + idd = obj2 + for z in current_sem_courses: + z = z[1] + print(z) + course_code = z.code + course_name = z.name + # course_code, course_name = str(z).split(" - ") + k = {} + # reg_ig has course registration id appended with the the roll number + # so that when we have removed the registration we can be redirected to this view + k['reg_id'] = roll_no+" - "+course_code + k['rid'] = roll_no+" - "+course_code + # Name ID Confusion here , be carefull + courseobj2 = Courses.objects.all().filter(code=course_code) + # if(str(z.student_id) == str(idd)): + for p in courseobj2: + k['course_id'] = course_code + k['course_name'] = course_name + k['sem'] = curr_sem_id.semester_no + k['credits'] = p.credit + details.append(k) + + year = demo_date.year + month = demo_date.month + yearr = str(year) + "-" + str(year+1) + semflag = 0 + if(month >= 7): + semflag = 1 else: - return Response({'error':'Cannot approve thesis'}, status=status.HTTP_400_BAD_REQUEST) + semflag = 2 + # TO DO Bdes + date = {'year': yearr, 'semflag': semflag} + course_list = Courses.objects.all() + semester_list = Semester.objects.all() + semester_no_list=[] + for i in semester_list: + semester_no_list.append(int(i.semester_no)) + # return JsonResponse( + # {'details': details, + # # 'dict2': dict2, + # 'course_list': serializers.CourseSerializer(course_list, many=True).data, + # # 'semester_list': semester_list, + # 'date': date} + # ) + + return JsonResponse({ + 'details': details, + 'course_list': serializers.CourseSerializer(course_list, many=True).data, + 'semester_list': serializers.SemesterSerializer(semester_list, many=True).data, + 'date': date + }) + + +# These apis were implemented before but now don't use them they have some errors + + +# @api_view(['GET']) +# def academic_procedures_faculty(request): +# current_user = request.user +# user_details = current_user.extrainfo +# des = current_user.holds_designations.all().first() + +# if str(des.designation) == 'student': +# return Response({'error':'Not a faculty'}, status=status.HTTP_400_BAD_REQUEST) +# elif str(current_user) == 'acadadmin': +# return Response({'error':'User is acadadmin'}, status=status.HTTP_400_BAD_REQUEST) + +# elif str(des.designation) == "Associate Professor" or str(des.designation) == "Professor" or str(des.designation) == "Assistant Professor": +# faculty_object = user_details.faculty +# month = int(date_time.month) +# sem = [] +# if month>=7 and month<=12: +# sem = [1,3,5,7] +# else: +# sem = [2,4,6,8] +# student_flag = False +# fac_flag = True + +# thesis_supervision_request_list = faculty_object.thesistopicprocess_supervisor.all() +# thesis_supervision_request_list_data = serializers.ThesisTopicProcessSerializer(thesis_supervision_request_list, many=True).data +# approved_thesis_request_list = serializers.ThesisTopicProcessSerializer(thesis_supervision_request_list.filter(approval_supervisor = True), many=True).data +# pending_thesis_request_list = serializers.ThesisTopicProcessSerializer(thesis_supervision_request_list.filter(pending_supervisor = True), many=True).data +# courses_list = serializers.CurriculumInstructorSerializer(user_details.curriculum_instructor_set.all(), many=True).data +# fac_details = serializers.UserSerializer(current_user).data + +# resp = { +# 'student_flag' : student_flag, +# 'fac_flag' : fac_flag, +# 'thesis_supervision_request_list' : thesis_supervision_request_list_data, +# 'pending_thesis_request_list' : pending_thesis_request_list, +# 'approved_thesis_request_list' : approved_thesis_request_list, +# 'courses_list': courses_list, +# 'faculty': fac_details +# } +# return Response(data=resp, status=status.HTTP_200_OK) + + + + + + +# @api_view(['GET']) +# def academic_procedures_student(request): +# current_user = request.user +# current_user_data = { +# 'first_name': current_user.first_name, +# 'last_name': current_user.last_name, +# 'username': current_user.username, +# 'email': current_user.email +# } +# user_details = current_user.extrainfo +# des = current_user.holds_designations.all().first() +# if str(des.designation) == 'student': +# obj = user_details.student + +# if obj.programme.upper() == "PH.D": +# student_flag = True +# ug_flag = False +# masters_flag = False +# phd_flag = True +# fac_flag = False +# des_flag = False + +# elif obj.programme.upper() == "M.DES": +# student_flag = True +# ug_flag = False +# masters_flag = True +# phd_flag = False +# fac_flag = False +# des_flag = True + +# elif obj.programme.upper() == "B.DES": +# student_flag = True +# ug_flag = True +# masters_flag = False +# phd_flag = False +# fac_flag = False +# des_flag = True + +# elif obj.programme.upper() == "M.TECH": +# student_flag = True +# ug_flag = False +# masters_flag = True +# phd_flag = False +# fac_flag = False +# des_flag = False + +# elif obj.programme.upper() == "B.TECH": +# student_flag = True +# ug_flag = True +# masters_flag = False +# phd_flag = False +# fac_flag = False +# des_flag = False + +# else: +# return Response({'message':'Student has no record'}, status=status.HTTP_400_BAD_REQUEST) + +# current_date = date_time.date() +# current_year = date_time.year +# batch = obj.batch_id +# user_sem = get_user_semester(request.user, ug_flag, masters_flag, phd_flag) +# acad_year = get_acad_year(user_sem, current_year) +# user_branch = user_details.department.name +# cpi = obj.cpi +# cur_spi='Sem results not available' # To be fetched from db if result uploaded + +# details = { +# 'current_user': current_user_data, +# 'year': acad_year, +# 'user_sem': user_sem, +# 'user_branch' : str(user_branch), +# 'cpi' : cpi, +# 'spi' : cur_spi +# } + +# currently_registered_courses = get_currently_registered_courses(user_details.id, user_sem) +# currently_registered_courses_data = serializers.CurriculumSerializer(currently_registered_courses, many=True).data +# try: +# pre_registered_courses = obj.initialregistrations_set.all().filter(semester = user_sem) +# pre_registered_courses_show = obj.initialregistrations_set.all().filter(semester = user_sem+1) +# except: +# pre_registered_courses = None +# pre_registered_courses_show=None +# try: +# final_registered_courses = obj.finalregistrations_set.all().filter(semester = user_sem) +# except: +# final_registered_courses = None + +# pre_registered_courses_data = serializers.InitialRegistrationsSerializer(pre_registered_courses, many=True).data +# pre_registered_courses_show_data = serializers.InitialRegistrationsSerializer(pre_registered_courses_show, many=True).data +# final_registered_courses_data = serializers.FinalRegistrationsSerializer(final_registered_courses, many=True).data + +# current_credits = get_current_credits(currently_registered_courses) +# print(current_user, user_sem+1, user_branch) +# try: +# next_sem_branch_courses = get_branch_courses(current_user, user_sem+1, user_branch) +# except Exception as e: +# return Response(data = str(e)) +# next_sem_branch_courses_data = serializers.CurriculumSerializer(next_sem_branch_courses, many=True).data + +# fee_payment_mode_list = dict(Constants.PaymentMode) + +# next_sem_branch_registration_courses = get_registration_courses(next_sem_branch_courses) +# next_sem_branch_registration_courses_data = [] +# for choices in next_sem_branch_registration_courses: +# next_sem_branch_registration_courses_data.append(serializers.CurriculumSerializer(choices, many=True).data) +# # next_sem_branch_registration_courses_data = serializers.CurriculumSerializer(next_sem_branch_registration_courses, many=True).data + +# final_registration_choices = get_registration_courses(get_branch_courses(request.user, user_sem, user_branch)) +# final_registration_choices_data = [] +# for choices in final_registration_choices: +# final_registration_choices_data.append(serializers.CurriculumSerializer(choices, many=True).data) + +# performance_list = [] +# result_announced = False +# for i in currently_registered_courses: +# try: +# performance_obj = obj.semestermarks_set.all().filter(curr_id = i).first() +# except: +# performance_obj = None +# performance_list.append(performance_obj) +# performance_list_data = serializers.SemesterMarksSerializer(performance_list, many=True).data + +# thesis_request_list = serializers.ThesisTopicProcessSerializer(obj.thesistopicprocess_set.all(), many=True).data + +# pre_existing_thesis_flag = True if obj.thesistopicprocess_set.all() else False + +# current_sem_branch_courses = get_branch_courses(current_user, user_sem, user_branch) + +# # pre_registration_date_flag = get_pre_registration_eligibility(current_date) +# final_registration_date_flag = get_final_registration_eligibility(current_date) + +# add_or_drop_course_date_flag = get_add_or_drop_course_date_eligibility(current_date) + +# student_registration_check_pre = obj.studentregistrationcheck_set.all().filter(semester=user_sem+1) +# student_registration_check_final = obj.studentregistrationcheck_set.all().filter(semester=user_sem) +# pre_registration_flag = False +# final_registration_flag = False +# if(student_registration_check_pre): +# pre_registration_flag = student_registration_check_pre.pre_registration_flag +# if(student_registration_check_final): +# final_registration_flag = student_registration_check_final.final_registration_flag + +# teaching_credit_registration_course = None +# if phd_flag: +# teaching_credit_registration_course = Curriculum.objects.all().filter(batch = 2016, sem =6) +# teaching_credit_registration_course_data = serializers.CurriculumSerializer(teaching_credit_registration_course, many=True).data + +# if student_flag: +# try: +# due = obj.dues_set.get() +# lib_d = due.library_due +# pc_d = due.placement_cell_due +# hos_d = due.hostel_due +# mess_d = due.mess_due +# acad_d = due.academic_due +# except: +# lib_d, pc_d, hos_d, mess_d, acad_d = 0, 0, 0, 0, 0 + +# tot_d = lib_d + acad_d + pc_d + hos_d + mess_d + +# registers = obj.register_set.all() +# course_list = [] +# for i in registers: +# course_list.append(i.curr_id) +# attendence = [] +# for i in course_list: +# instructors = i.curriculum_instructor_set.all() +# pr,ab=0,0 +# for j in list(instructors): + +# presents = obj.student_attendance_set.all().filter(instructor_id=j, present=True) +# absents = obj.student_attendance_set.all().filter(instructor_id=j, present=False) +# pr += len(presents) +# ab += len(absents) +# attendence.append((i,pr,pr+ab)) +# attendance_data = {} +# for course in attendence: +# attendance_data[course[0].course_id.course_name] = { +# 'present' : course[1], +# 'total' : course[2] +# } + +# branchchange_flag = False +# if user_sem == 2: +# branchchange_flag=True + +# faculty_list = serializers.HoldsDesignationSerializer(get_faculty_list(), many=True).data + +# resp = { +# 'details': details, +# 'currently_registered': currently_registered_courses_data, +# # 'pre_registered_courses' : pre_registered_courses_data, +# # 'pre_registered_courses_show' : pre_registered_courses_show_data, +# 'final_registered_courses' : final_registered_courses_data, +# 'current_credits' : current_credits, +# 'courses_list': next_sem_branch_courses_data, +# 'fee_payment_mode_list' : fee_payment_mode_list, +# 'next_sem_branch_registration_courses' : next_sem_branch_registration_courses_data, +# 'final_registration_choices' : final_registration_choices_data, +# 'performance_list' : performance_list_data, +# 'thesis_request_list' : thesis_request_list, +# 'student_flag' : student_flag, +# 'ug_flag' : ug_flag, +# 'masters_flag' : masters_flag, +# 'phd_flag' : phd_flag, +# 'fac_flag' : fac_flag, +# 'des_flag' : des_flag, +# 'thesis_flag' : pre_existing_thesis_flag, +# 'drop_courses_options' : currently_registered_courses_data, +# # 'pre_registration_date_flag': pre_registration_date_flag, +# 'final_registration_date_flag': final_registration_date_flag, +# 'add_or_drop_course_date_flag': add_or_drop_course_date_flag, +# # 'pre_registration_flag' : pre_registration_flag, +# 'final_registration_flag': final_registration_flag, +# 'teaching_credit_registration_course' : teaching_credit_registration_course_data, +# 'lib_d':lib_d, +# 'acad_d':acad_d, +# 'mess_d':mess_d, +# 'pc_d':pc_d, +# 'hos_d':hos_d, +# 'tot_d':tot_d, +# 'attendance': attendance_data, +# 'Branch_Change_Flag':branchchange_flag +# # 'faculty_list' : faculty_list +# } +# return Response(data=resp, status=status.HTTP_200_OK) + + + + + + + + + + + + + + + + + + + + + + +# These apis are not needed in this module + + + +# @api_view(['POST']) +# def add_thesis(request): +# current_user = request.user +# profile = current_user.extrainfo +# if profile.user_type == 'student': +# if not 'thesis_topic' in request.data: +# return Response({'error':'Thesis topic is required'}, status=status.HTTP_400_BAD_REQUEST) +# if not 'research_area' in request.data: +# return Response({'error':'Research area is required'}, status=status.HTTP_400_BAD_REQUEST) +# if 'supervisor_id' in request.data: +# try: +# supervisor_faculty = User.objects.get(username=request.data['supervisor_id']) +# supervisor_faculty = supervisor_faculty.extrainfo +# request.data['supervisor_id'] = supervisor_faculty +# except: +# return Response({'error':'Wrong supervisor id. User does not exist.'}, status=status.HTTP_400_BAD_REQUEST) +# else: +# return Response({'error':'supervisor id is required'}, status=status.HTTP_400_BAD_REQUEST) +# if 'co_supervisor_id' in request.data: +# try: +# co_supervisor_faculty = User.objects.get(username=request.data['co_supervisor_id']) +# co_supervisor_faculty = co_supervisor_faculty.extrainfo +# request.data['co_supervisor_id'] = co_supervisor_faculty +# except: +# return Response({'error':'Wrong co_supervisor id. User does not exist.'}, status=status.HTTP_400_BAD_REQUEST) +# else: +# co_supervisor_faculty = None +# if 'curr_id' in request.data: +# curr_id = None +# student = profile.student +# request.data['student_id'] = profile +# request.data['submission_by_student'] = True +# serializer = serializers.ThesisTopicProcessSerializer(data=request.data) +# if serializer.is_valid(): +# serializer.save() +# return Response(serializer.data, status=status.HTTP_200_OK) +# else: +# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) +# else: +# return Response({'error':'Cannot add thesis'}, status=status.HTTP_400_BAD_REQUEST) + + + + + + + + + + + + + + + + + +# @api_view(['PUT']) +# def approve_thesis(request, id): +# current_user = request.user +# profile = current_user.extrainfo +# if profile.user_type == 'faculty': +# try: +# thesis = ThesisTopicProcess.objects.get(id=id) +# except: +# return Response({'error':'This thesis does not exist'}, status=status.HTTP_400_BAD_REQUEST) +# if 'member1' in request.data: +# try: +# user1 = User.objects.get(username=request.data['member1']) +# member1 = user1.extrainfo +# request.data['member1'] = member1 +# except: +# return Response({'error':'Wrong username of member 1. User does not exist.'}, status=status.HTTP_400_BAD_REQUEST) +# else: +# return Response({'error':'Member 1 is required'}, status=status.HTTP_400_BAD_REQUEST) +# if 'member2' in request.data: +# try: +# user2 = User.objects.get(username=request.data['member2']) +# member2 = user2.extrainfo +# request.data['member2'] = member2 +# except: +# return Response({'error':'Wrong username of member 2. User does not exist.'}, status=status.HTTP_400_BAD_REQUEST) +# else: +# return Response({'error':'Member 2 is required'}, status=status.HTTP_400_BAD_REQUEST) +# if 'member3' in request.data: +# try: +# user3 = User.objects.get(username=request.data['member3']) +# member3 = user3.extrainfo +# request.data['member3'] = member3 +# except: +# return Response({'error':'Wrong username of member 3. User does not exist.'}, status=status.HTTP_400_BAD_REQUEST) +# else: +# member3 = None +# if not 'approval' in request.data: +# return Response({'error':'Approval value is required.'}, status=status.HTTP_400_BAD_REQUEST) +# elif request.data['approval'] != 'yes' and request.data['approval'] != 'no': +# return Response({'error':'Wrong approval value provided. Approval value should be yes or no'}, status=status.HTTP_400_BAD_REQUEST) +# if request.data['approval'] == 'yes': +# request.data.pop('approval', None) +# request.data['pending_supervisor'] = False +# request.data['approval_supervisor'] = True +# request.data['forwarded_to_hod'] = True +# request.data['pending_hod'] = True +# else: +# request.data.pop('approval', None) +# request.data['pending_supervisor'] = False +# request.data['approval_supervisor'] = False +# request.data['forwarded_to_hod'] = False +# request.data['pending_hod'] = False +# serializer = serializers.ThesisTopicProcessSerializer(thesis, data=request.data, partial=True) +# if serializer.is_valid(): +# serializer.save() +# return Response(serializer.data, status=status.HTTP_200_OK) +# else: +# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) +# else: +# return Response({'error':'Cannot approve thesis'}, status=status.HTTP_400_BAD_REQUEST) \ No newline at end of file diff --git a/FusionIIIT/applications/academic_procedures/migrations/0001_initial.py b/FusionIIIT/applications/academic_procedures/migrations/0001_initial.py index 42142593d..71f23d8c2 100644 --- a/FusionIIIT/applications/academic_procedures/migrations/0001_initial.py +++ b/FusionIIIT/applications/academic_procedures/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.1.5 on 2024-04-15 23:58 +# Generated by Django 3.1.5 on 2024-07-16 15:44 import datetime from django.db import migrations, models @@ -11,9 +11,9 @@ class Migration(migrations.Migration): initial = True dependencies = [ + ('programme_curriculum', '0001_initial'), ('globals', '0001_initial'), ('academic_information', '0001_initial'), - ('programme_curriculum', '0001_initial'), ] operations = [ @@ -368,6 +368,16 @@ class Migration(migrations.Migration): 'db_table': 'Bonafide', }, ), + migrations.CreateModel( + name='backlog_course', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('is_summer_course', models.BooleanField(default=False)), + ('course_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='academic_information.course')), + ('semester_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='programme_curriculum.semester')), + ('student_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='academic_information.student')), + ], + ), migrations.CreateModel( name='AssistantshipClaim', fields=[ @@ -402,4 +412,4 @@ class Migration(migrations.Migration): 'unique_together': {('curr_id', 'student_id')}, }, ), - ] \ No newline at end of file + ] diff --git a/FusionIIIT/applications/academic_procedures/models.py b/FusionIIIT/applications/academic_procedures/models.py index 37b339378..2015a1ee8 100644 --- a/FusionIIIT/applications/academic_procedures/models.py +++ b/FusionIIIT/applications/academic_procedures/models.py @@ -283,6 +283,9 @@ class SemesterMarks(models.Model): # curr_id = models.ForeignKey(Curriculum, on_delete=models.CASCADE) curr_id = models.ForeignKey(Courses, on_delete=models.CASCADE) #course_id = models.ForeignKey(Courses, on_delete=models.CASCADE, null=True) + + # def __str__(self): + # return self.student_id class Meta: db_table = 'SemesterMarks' @@ -565,8 +568,6 @@ class StudentRegistrationChecks(models.Model): final_registration_flag(boolean) - to denote whether the final registration is complete semester_id(programme_curriculum.Semester) - reference to the semester for which the registration will be considered - - ''' @@ -618,9 +619,6 @@ class FinalRegistration(models.Model): verified(Boolean) - denotes whether the registration is verified by academic department and complete course_slot_id(programme_curriculum.CourseSlot) - details about under which course slot the course is offered(Optional/Core other details) - - - ''' @@ -671,18 +669,14 @@ class course_registration(models.Model): ''' Current Purpose : stores information regarding the process of registration of a student for a course - ATTRIBUTES course_id(programme_curriculum.Course) - reference to the course details for which the registration is being done semester_id(programme_curriculum.Semester) - reference to the semester for which the course registration is done student_id(academic_information.Student) - reference to the student course_slot_id(programme_curriculum.CourseSlot) - details about under which course slot the course is offered(Optional/Core other details) - - - ''' - + student_id = models.ForeignKey(Student, on_delete=models.CASCADE) working_year=models.IntegerField(null=True,blank=True,choices=Year_Choices) @@ -691,6 +685,23 @@ class course_registration(models.Model): course_slot_id = models.ForeignKey(CourseSlot, null=True, blank=True, on_delete=models.SET_NULL) # grade = models.CharField(max_length=10) #course_registration_year = models.IntegerField() - + def __str__(self): + return str(self.semester_id.semester_no) class Meta: db_table = 'course_registration' + + +class backlog_course(models.Model): + ''' + Current Purpose : stores information regarding the backlog courses of a student (purpose is unclear and is open to interpretations) + + ATTRIBUTES + course_id(programme_curriculum.Course) - reference to the course details for which the registration is being done + semester_id(programme_curriculum.Semester) - reference to the semester for which the course registration is done + student_id(academic_information.Student) - reference to the student + is_summer_course(Boolean) - details about whether this course is available as summer_course or not + ''' + student_id = models.ForeignKey(Student, on_delete=models.CASCADE) + semester_id = models.ForeignKey(Semester, on_delete=models.CASCADE) + course_id = models.ForeignKey(Course, on_delete=models.CASCADE) + is_summer_course = models.BooleanField(default= False) \ No newline at end of file diff --git a/FusionIIIT/applications/academic_procedures/tests.py b/FusionIIIT/applications/academic_procedures/tests.py index e9137c85e..2c9e754ad 100644 --- a/FusionIIIT/applications/academic_procedures/tests.py +++ b/FusionIIIT/applications/academic_procedures/tests.py @@ -1,3 +1,4 @@ # from django.test import TestCase # Create your tests here. + diff --git a/FusionIIIT/applications/academic_procedures/urls.py b/FusionIIIT/applications/academic_procedures/urls.py index 45f892b49..e11bdcd7d 100644 --- a/FusionIIIT/applications/academic_procedures/urls.py +++ b/FusionIIIT/applications/academic_procedures/urls.py @@ -1,5 +1,4 @@ from django.conf.urls import url, include - from . import views appname = 'procedures' urlpatterns = [ @@ -7,19 +6,23 @@ url(r'^main/', views.academic_procedures, name='procedures'), url(r'^register/', views.register, name='register'), url(r'^pre_registration/', views.pre_registration, name='pre_register'), + url(r'^auto_pre_registration/', views.auto_pre_registration, name='automatic_pre_register'), + url(r'^final_registration/', views.final_registration, name='final_register'), url(r'^addCourse/', views.add_courses, name='addCourse'), + url(r'^add_one_course/' , views.add_one_course , name = 'add_one_course'), url(r'^drop_course/', views.drop_course, name='drop_course'), + url(r'^replaceCourse/', views.replace_courses, name='replace_courses'), + url(r'^replace_one_course/', views.replace_one_course, name='replace_one_course'), url(r'^branch-change/', views.approve_branch_change, name='branch_change'), url(r'^brach-change-request/', views.branch_change_request, name='branch_change_request'), + url(r'^acad_person/verifyCourse/drop/$',views.dropcourseadmin, name='dropcourseadmin'), url(r'^acad_person/verifyCourse/', views.verify_course, name='verifyCourse'), url(r'^acad_person/addCourse/', views.acad_add_course, name="acad_add_course"), url(r'^acad_person/student_list$', views.student_list, name='studentlist'), url(r'^acad_person/course_list$', views.course_list, name='courseList'), url(r'^acad_person/$', views.acad_person, name='acad_person'), - url(r'^acad_person/verifyCourse/drop/$', - views.dropcourseadmin, name='dropcourseadmin'), url(r'^branch-validate', views.approve_branch_change, name='branch_validate'), url(r'^acad_person/branch_change/$', views.acad_branch_change, name='acad_branch_change'), @@ -28,8 +31,9 @@ url(r'^account/$', views.account), url(r'^addThesis/$', views.add_thesis, name='add_thesis'), url(r'^process_verification_request/$', views.process_verification_request), + url(r'^auto_process_verification_request/$', views.auto_process_verification_request), url(r'^teaching_credit/$', views.teaching_credit_register), - url(r'^course_marks_data/$', views.course_marks_data), # -- + url(r'^course_marks_data/$', views.course_marks_data), # -- url(r'^submit_marks/$', views.submit_marks), # -- url(r'^verify_course_marks_data/$', views.verify_course_marks_data), # -- url(r'^verify_marks/$', views.verify_marks), @@ -41,7 +45,10 @@ url(r'^test/$', views.test), url(r'^bonafide_pdf/$', views.Bonafide_form), url(r'^test_ret/$', views.test_ret), + url(r'^api/', include('applications.academic_procedures.api.urls')), + + url(r'^faculty_data/$', views.facultyData, name='faculty_data'), url(r'^ACF/$', views.ACF, name='ACF'), url(r'^MTSGF/$', views.MTSGF), @@ -51,12 +58,19 @@ url(r'^update_phdform/$', views.update_phdform), url(r'^update_dues/$', views.update_dues), url(r'^dues_pdf/$', views.dues_pdf), - url(r'^acad_person/gen_course_list$', - views.gen_course_list, name='gen_course_list'), + url(r'^acad_person/gen_course_list$', views.gen_course_list, name='gen_course_list'), url(r'^update_acad_assistantship/$', views.update_acad_assis), url(r'^update_account_assistantship/$', views.update_account_assistantship), url(r'^update_hod_assistantship/$', views.update_hod_assistantship), url(r'^mdue/$', views.mdue), url(r'^assis_stat/$', views.assis_stat), - url(r'^acad_person/allot_courses/' , views.allot_courses, name='allot_courses') + url(r'^acad_person/allot_courses/' , views.allot_courses, name='allot_courses'), + + url(r'^acad_person/get_next_sem_courses/' , views.get_next_sem_courses , name = 'get_next_sem_courses'), + + url(r'^acad_person/remove_course_from_slot/' , views.remove_course_from_slot , name = 'remove_course_from_slot'), + url(r'^acad_person/add_course_to_slot/' , views.add_course_to_slot , name = 'add_course_to_slot'), + url(r'^acad_person/replaceSwayam/', views.replaceSwayam, name='replaceSwayam'), + url(r'^acad_person/swayam_replace/', views.swayam_replace, name='swayam_replace'), + url(r'^register_backlog_course/' , views.register_backlog_course , name = 'register_backlog_course') ] diff --git a/FusionIIIT/applications/academic_procedures/views.py b/FusionIIIT/applications/academic_procedures/views.py index 7e55e3e45..5b2ea0f20 100644 --- a/FusionIIIT/applications/academic_procedures/views.py +++ b/FusionIIIT/applications/academic_procedures/views.py @@ -11,6 +11,7 @@ import logging from django.db import transaction from django.contrib import messages +from django.db.models import Q from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User from django.db.models import Max,Value,IntegerField,CharField,F,Sum @@ -25,20 +26,25 @@ Student_attendance) from applications.central_mess.models import(Monthly_bill, Payments) - +from applications.online_cms.models import (Student_grades) from applications.programme_curriculum.models import (CourseSlot, Course as Courses, Batch, Semester , CourseInstructor) from applications.globals.models import (DepartmentInfo, Designation, ExtraInfo, Faculty, HoldsDesignation) - +from applications.programme_curriculum.models import Course as Courses from .models import (BranchChange, CoursesMtech, InitialRegistration, StudentRegistrationChecks, Register, Thesis, FinalRegistration, ThesisTopicProcess, Constants, FeePayments, TeachingCreditRegistration, SemesterMarks, MarkSubmissionCheck, Dues,AssistantshipClaim, MTechGraduateSeminarReport, - PhDProgressExamination,CourseRequested, course_registration, MessDue, Assistantship_status) + PhDProgressExamination,CourseRequested, course_registration, MessDue, Assistantship_status , backlog_course) from notification.views import academics_module_notif from .forms import BranchChangeForm from django.db.models.functions import Concat,ExtractYear,ExtractMonth,ExtractDay,Cast +from .api import serializers +from django.core.serializers import serialize +import datetime +"""every newfuncitons that have been created with name auto_ in start of their original name is to implement new logic of registraion .. +unlike the previous registration logic that was done with priority """ demo_date = timezone.now() @@ -53,12 +59,7 @@ available_ece_seats = 100 available_me_seats = 100 -# assistantship_status = Assistantship_status.objects.all() -# for obj in assistantship_status: -# student_status = obj.student_status -# hod_status = obj.hod_status -# account_status = obj.account_status @login_required(login_url='/accounts/login') @@ -75,21 +76,21 @@ def main(request): def academic_procedures(request): current_user = get_object_or_404(User, username=request.user.username) - + #extra info details , user id used as main id user_details = ExtraInfo.objects.select_related('user','department').get(user = request.user) - des = HoldsDesignation.objects.all().select_related().filter(user = request.user).first() + # des = HoldsDesignation.objects.all().select_related().filter(user = request.user).first() - if str(des.designation) == "student": + if request.session.get('currentDesignationSelected') == "student": obj = Student.objects.select_related('id','id__user','id__department').get(id = user_details.id) return HttpResponseRedirect('/academic-procedures/stu/') # return HttpResponseRedirect('/logout/') - elif str(des.designation) == "Associate Professor" or str(des.designation) == "Professor" or str(des.designation) == "Assistant Professor" : + elif request.session.get('currentDesignationSelected') == "faculty" or request.session.get('currentDesignationSelected') == "Associate Professor" or request.session.get('currentDesignationSelected') == "Professor" or request.session.get('currentDesignationSelected') == "Assistant Professor" : return HttpResponseRedirect('/academic-procedures/fac/') # return HttpResponseRedirect('/logout/') - elif str(request.user) == "acadadmin" : + elif request.session.get('currentDesignationSelected') == "acadadmin" : return HttpResponseRedirect('/aims/') elif str(request.user) == "rizwan": @@ -106,7 +107,7 @@ def academic_procedures(request): }) else: - return HttpResponse('person not found') + return HttpResponseRedirect('/dashboard/') # # # @@ -117,19 +118,20 @@ def academic_procedures(request): def academic_procedures_faculty(request): current_user = get_object_or_404(User, username=request.user.username) - + if request.user.extrainfo.user_type != 'faculty': + return HttpResponseRedirect('/dashboard/') #extra info details , user id used as main id user_details = ExtraInfo.objects.select_related('user','department').get(user = request.user) des = HoldsDesignation.objects.all().select_related().filter(user = request.user).first() fac_id = user_details fac_name = user_details.user.first_name + " " + user_details.user.last_name - if str(des.designation) == "student": - return HttpResponseRedirect('/academic-procedures/main/') + # if str(des.designation) == "student": + # return HttpResponseRedirect('/academic-procedures/main/') - elif str(request.user) == "acadadmin": - return HttpResponseRedirect('/academic-procedures/main/') - - elif str(des.designation) == "Associate Professor" or str(des.designation) == "Professor" or str(des.designation) == "Assistant Professor": + # elif str(request.user) == "acadadmin": + # return HttpResponseRedirect('/academic-procedures/main/') + notifs = request.user.notifications.all() + if request.session.get('currentDesignationSelected') == "faculty" or str(des.designation) == "Associate Professor" or str(des.designation) == "Professor" or str(des.designation) == "Assistant Professor": object_faculty = Faculty.objects.select_related('id','id__user','id__department').get(id = user_details.pk) @@ -158,6 +160,15 @@ def academic_procedures_faculty(request): mtechseminar_request_list = MTechGraduateSeminarReport.objects.all().filter(Overall_grade = '') phdprogress_request_list = PhDProgressExamination.objects.all().filter(Overall_grade = '') courses_list = list(CourseInstructor.objects.select_related('course_id', 'batch_id', 'batch_id__discipline').filter(instructor_id__id=fac_id.id).only('course_id__code', 'course_id__name', 'batch_id')) + + assigned_courses = CourseInstructor.objects.select_related('course_id', 'batch_id', 'batch_id__discipline').filter( + instructor_id__id=fac_id.id, # Filter by faculty ID + batch_id__running_batch=True, # Filter by currently running batches + course_id__working_course=True # Filter by currently active courses + ).only('course_id__code', 'course_id__name', 'batch_id') + assigned_courses = list(assigned_courses) + + # print('------------------------------------------------------------------------------------------------------------------' , list(assigned_courses)) r = range(4) return render( request, @@ -181,6 +192,8 @@ def academic_procedures_faculty(request): 'mtechseminar_request_list' : mtechseminar_request_list, 'phdprogress_request_list' : phdprogress_request_list, 'r' : r, + 'assigned_courses' : assigned_courses, + 'notifications': notifs, }) else: HttpResponse("user not found") @@ -205,11 +218,13 @@ def account(request): def academic_procedures_student(request): current_user = get_object_or_404(User, username=request.user.username) - + # if global_var != "student": + # return HttpResponse("Student has no record") user_details = ExtraInfo.objects.select_related('user','department').get(id = request.user) des = HoldsDesignation.objects.all().select_related().filter(user = request.user).first() if str(des.designation) == "student": + notifs = request.user.notifications.all() obj = Student.objects.select_related('id','id__user','id__department').get(id = user_details.id) if obj.programme.upper() == "PHD" : @@ -341,17 +356,23 @@ def academic_procedures_student(request): currently_registered_course = get_currently_registered_course(obj,obj.curr_semester_no) current_credits = get_current_credits(currently_registered_course) - + cur_cpi=0.0 details = { 'current_user': current_user, 'year': acad_year, - 'user_sem': user_sem, + 'user_sem': user_sem - 1, 'user_branch' : str(user_branch), 'cpi' : cpi, } cur_cpi=details['cpi'] + swayam_courses_count = 0 + next_sem_student = user_sem + 1 + if(next_sem_student > 2): + swayam_courses_count = 2 + if(next_sem_student == 6 or next_sem_student == 7 or next_sem_student == 8): + swayam_courses_count = 3 try: pre_registered_courses = InitialRegistration.objects.all().filter(student_id = user_details.id,semester_id = next_sem_id) @@ -374,13 +395,14 @@ def academic_procedures_student(request): for final_registered_course in final_registered_courses: final_registered_course_show.append({"course_code":final_registered_course.course_id.code,"course_name":final_registered_course.course_id.name,"course_credit":final_registered_course.course_id.credit}) add_courses_options = get_add_course_options(current_sem_branch_course, currently_registered_course, batch.year) - #drop_courses_options = get_drop_course_options(currently_registered_course) - + drop_courses_options = get_drop_course_options(currently_registered_course) + replace_courses_options = get_replace_course_options(currently_registered_course, batch.year) except Exception as e: final_registered_courses = None final_registered_course_show = None - #drop_courses_options = None + drop_courses_options = None add_courses_options = None + replace_courses_options = None fee_payment_mode_list = dict(Constants.PaymentMode) @@ -455,10 +477,24 @@ def academic_procedures_student(request): attendence.append((i,pr,pr+ab)) cur_spi='Sem results not available' # To be fetched from db if result uploaded - - Mess_bill = Monthly_bill.objects.filter(student_id = obj) - Mess_pay = Payments.objects.filter(student_id = obj) + backlogCourseList = [] + auto_backlog_courses = list(Student_grades.objects.filter(roll_no = obj , grade = 'F')) + auto_backlog_courses_list = [] + for i in auto_backlog_courses: + if not i.course_id.courseslots.filter(type__contains="Optional").exists(): + auto_backlog_courses_list.append([i.course_id.name, i.course_id.code, i.course_id.version, i.course_id.credit , i.grade]) + backlogCourses = backlog_course.objects.select_related('course_id' , 'student_id' , 'semester_id' ).filter(student_id=obj) + for i in backlogCourses: + summer_course = "Yes" if i.is_summer_course else "No" + course_details = i.course_id.course_details if i.course_id.course_details else "N/A" + + backlogCourseList.append([i.course_id.course_name, course_details , i.semester_id.semester_no , summer_course]) + + # Mess_bill = Monthly_bill.objects.filter(student_id = obj) + # Mess_pay = Payments.objects.filter(student_id = obj) + Mess_bill = [] + Mess_pay = [] # Branch Change Form save if request.method=='POST': if True: @@ -470,7 +506,7 @@ def academic_procedures_student(request): return render( request, '../templates/academic_procedures/academic.html', {'details': details, - # 'calendar': calendar, + # 'calendar': calendar, 'currently_registered': currently_registered_course, 'pre_registered_course' : pre_registered_courses, 'pre_registered_course_show' : pre_registered_course_show, @@ -503,7 +539,8 @@ def academic_procedures_student(request): # 'change_branch': change_branch, # 'add_course': add_course, 'add_courses_options': add_courses_options, - #'drop_courses_options' : drop_courses_options, + 'drop_courses_options' : drop_courses_options, + 'replace_courses_options' : replace_courses_options, # 'pre_register': pre_register, 'pre_registration_timestamp': pre_registration_timestamp, 'prd': pre_registration_date_flag, @@ -512,6 +549,7 @@ def academic_procedures_student(request): 'adc_date_flag': add_or_drop_course_date_flag, 'pre_registration_flag' : pre_registration_flag, 'final_registration_flag': final_registration_flag, + 'swayam_courses_count':swayam_courses_count, # 'final_r': final_register_1, 'teaching_credit_registration_course' : teaching_credit_registration_course, @@ -527,16 +565,19 @@ def academic_procedures_student(request): 'hos_d':hos_d, 'tot_d':tot_d, 'attendence':attendence, + 'backlogCourseList' : backlogCourseList, + 'auto_backlog_courses_list' : auto_backlog_courses_list, 'BranchChangeForm': BranchChangeForm(), 'BranchFlag':branchchange_flag, 'assistantship_flag' : student_status, + 'notifications': notifs, } ) - elif str(des.designation) == "Associate Professor" : + elif request.session.get('currentDesignationSelected') == "Associate Professor" : return HttpResponseRedirect('/academic-procedures/main/') - elif str(request.user) == "acadadmin" : + elif request.session.get('currentDesignationSelected') == "acadadmin" : return HttpResponseRedirect('/academic-procedures/main/') else: @@ -852,12 +893,16 @@ def dropcourseadmin(request): ''' data = request.GET.get('id') data = data.split(" - ") + student_id = data[0] course_code = data[1] + course = Courses.objects.get(code=course_code , version = 1.0) # need to add batch and programme - curriculum_object = Curriculum.objects.all().filter(course_code = course_code) + # curriculum_object = Curriculum.objects.all().filter(course_code = course_code) try: - Register.objects.filter(curr_id = curriculum_object.first(),student_id=int(data[0])).delete() - except: + # Register.objects.filter(curr_id = curriculum_object.first(),student_id=int(data[0])).delete() + course_registration.objects.filter(student_id = student_id , course_id = course.id).delete() + except Exception as e: + print(str(e)) pass # print("hello ") response_data = {} @@ -871,7 +916,7 @@ def gen_course_list(request): course_id = request.POST['course'] course = Courses.objects.get(id = course_id) #obj = course_registration.objects.all().filter(course_id = course) - obj=course_registration.objects.filter(course_id__id=course_id, student_id__batch=batch).select_related( + obj=course_registration.objects.filter(course_id__id=course_id, working_year=batch).select_related( 'student_id__id__user','student_id__id__department').only('student_id__batch', 'student_id__id__user__first_name', 'student_id__id__user__last_name', 'student_id__id__department__name','student_id__id__user__username') @@ -879,13 +924,22 @@ def gen_course_list(request): batch="" course="" obj="" - students = [] - for i in obj: - students.append({"rollno":i.student_id.id.user.username, - "name":i.student_id.id.user.first_name+" "+i.student_id.id.user.last_name, - "department":i.student_id.id.department.name}) + verified_students = [] + for registration in obj: + final_registration = FinalRegistration.objects.filter( + course_id=course, + semester_id=registration.semester_id, + student_id=registration.student_id, + verified=True + ).exists() + if final_registration: + verified_students.append({ + "rollno": registration.student_id.id.user.username, + "name": registration.student_id.id.user.first_name + " " + registration.student_id.id.user.last_name, + "department": registration.student_id.id.department.name + }) html = render_to_string('academic_procedures/gen_course_list.html', - {'students': students, 'batch':batch, 'course':course_id}, request) + {'students': verified_students, 'batch':batch, 'course':course_id}, request) maindict = {'html': html} obj = json.dumps(maindict) return HttpResponse(obj, content_type='application/json') @@ -914,14 +968,13 @@ def verify_course(request): current_user = get_object_or_404(User, username=request.user.username) user_details = ExtraInfo.objects.all().select_related( 'user', 'department').filter(user=current_user).first() - desig_id = Designation.objects.all().filter(name='adminstrator').first() + desig_id = Designation.objects.all().filter(name='acadadmin').first() temp = HoldsDesignation.objects.all().select_related().filter( designation=desig_id).first() acadadmin = temp.working k = str(user_details).split() final_user = k[2] - - if (str(acadadmin) != str(final_user)): + if ('acadadmin' != request.session.get('currentDesignationSelected')): return HttpResponseRedirect('/academic-procedures/') roll_no = request.POST["rollNo"] obj = ExtraInfo.objects.all().select_related( @@ -932,9 +985,12 @@ def verify_course(request): 'firstname': firstname, 'lastname': lastname} obj2 = Student.objects.all().select_related( 'id', 'id__user', 'id__department').filter(id=roll_no).first() - obj = Register.objects.all().select_related('curr_id', 'student_id', 'curr_id__course_id', - 'student_id__id', 'student_id__id__user', 'student_id__id__department').filter(student_id=obj2) - curr_sem_id = obj2.curr_semester_no + # obj = Register.objects.all().select_related('curr_id', 'student_id', 'curr_id__course_id', + # 'student_id__id', 'student_id__id__user', 'student_id__id__department').filter(student_id=obj2) + batch = obj2.batch_id + curr_id = batch.curriculum + curr_sem_id = Semester.objects.get(curriculum = curr_id, semester_no = obj2.curr_semester_no) + # curr_sem_id = obj2.curr_semester_no details = [] current_sem_courses = get_currently_registered_course( @@ -943,7 +999,10 @@ def verify_course(request): idd = obj2 for z in current_sem_courses: z = z[1] - course_code, course_name = str(z).split(" - ") + print(z) + course_code = z.code + course_name = z.name + # course_code, course_name = str(z).split(" - ") k = {} # reg_ig has course registration id appended with the the roll number # so that when we have removed the registration we can be redirected to this view @@ -955,7 +1014,7 @@ def verify_course(request): for p in courseobj2: k['course_id'] = course_code k['course_name'] = course_name - k['sem'] = curr_sem_id + k['sem'] = curr_sem_id.semester_no k['credits'] = p.credit details.append(k) @@ -971,6 +1030,9 @@ def verify_course(request): date = {'year': yearr, 'semflag': semflag} course_list = Courses.objects.all() semester_list = Semester.objects.all() + semester_no_list=[] + for i in semester_list: + semester_no_list.append(int(i.semester_no)) html = render_to_string('academic_procedures/studentCourses.html', {'details': details, 'dict2': dict2, @@ -996,7 +1058,7 @@ def acad_add_course(request): sem_id = request.POST['semester_id'] semester = Semester.objects.get(id=sem_id) cr = course_registration( - course_id=course, student_id=student, semester_id=semester) + course_id=course, student_id=student, semester_id=semester , working_year = datetime.datetime.now().year,) cr.save() return HttpResponseRedirect('/academic-procedures/') @@ -1034,7 +1096,7 @@ def acad_branch_change(request): k = str(user_details).split() final_user = k[2] - if (str(acadadmin) != str(final_user)): + if ('acadadmin' != request.session.get('currentDesignationSelected')): return HttpResponseRedirect('/academic-procedures/') # year = datetime.datetime.now().year @@ -1368,7 +1430,77 @@ def pre_registration(request): else: return HttpResponseRedirect('/academic-procedures/main') +@login_required(login_url='/accounts/login') +@transaction.atomic +def auto_pre_registration(request): + if request.method == 'POST': + try: + current_user = get_object_or_404(User, username=request.POST.get('user')) + current_user = ExtraInfo.objects.all().select_related('user','department').filter(user=current_user).first() + current_user = Student.objects.all().filter(id=current_user.id).first() + sem_id = Semester.objects.get(id = request.POST.get('semester')) + course_slots=request.POST.getlist("course_slot") + try: + student_registeration_check=get_student_registrtion_check(current_user,sem_id) + if(student_registeration_check and student_registeration_check.pre_registration_flag==True): + messages.error(request,"You have already registered for next semester") + return HttpResponseRedirect('/academic-procedures/main') + except Exception as e: + print(e) + + reg_curr = [] + final_reg_curr = [] + existing_entries = set() + for course_slot in course_slots : + course_priorities = request.POST.getlist("course_priority-"+course_slot) + if(course_priorities[0] == 'NULL'): + continue + course_slot_id_for_model = CourseSlot.objects.get(id = int(course_slot)) + print("=----> course_priorities ----- ",course_priorities) + print("------------>course slot id ",course_slot_id_for_model) + for course_priority in course_priorities: + if(course_priority == 'NULL'): + continue + priority_of_current_course,course_id = map(int,course_priority.split("-")) + + course_id_for_model = Courses.objects.get(id = course_id) + current_combination = (course_slot_id_for_model.id, course_id_for_model.id) + if current_combination not in existing_entries: + p = InitialRegistration( + course_id = course_id_for_model, + semester_id = sem_id, + student_id = current_user, + course_slot_id = course_slot_id_for_model, + priority = priority_of_current_course + ) + f =FinalRegistration(student_id=current_user ,course_slot_id=course_slot_id_for_model , course_id=course_id_for_model ,semester_id=sem_id) + final_reg_curr.append(f) + reg_curr.append(p) + existing_entries.add(current_combination) + try: + + InitialRegistration.objects.bulk_create(reg_curr) + FinalRegistration.objects.bulk_create(final_reg_curr) + registration_check = StudentRegistrationChecks( + student_id = current_user, + pre_registration_flag = True, + final_registration_flag = False, + semester_id = sem_id + ) + registration_check.save() + messages.info(request, 'Successfully Registered.') + messages.success(request, "Successfully Registered.") + return HttpResponseRedirect('/academic-procedures/stu') + except Exception as e: + messages.error(request, "Error in Registration.") + return HttpResponseRedirect('/academic-procedures/stu') + except Exception as e: + messages.error(request, "Error in Registration.") + return HttpResponseRedirect('/academic-procedures/main') + else: + return HttpResponseRedirect('/academic-procedures/main') + def get_student_registrtion_check(obj, sem): return StudentRegistrationChecks.objects.all().filter(student_id = obj, semester_id = sem).first() @@ -1428,30 +1560,57 @@ def allot_courses(request): profiles=request.FILES['allotedCourses'] batch_id=request.POST['batch'] sem_no=int(request.POST['semester']) - + batch=Batch.objects.get(id=batch_id) sem_id=Semester.objects.get(curriculum=batch.curriculum,semester_no=sem_no) - + print(batch , sem_id) + # format of excel sheet being uploaded should be xls only , otherwise error excel = xlrd.open_workbook(file_contents=profiles.read()) sheet=excel.sheet_by_index(0) + course_registrations=[] final_registrations=[] + pre_registrations=[] + student_checks=[] + # print('>>>>>>>>>>>>>>>>>>>' , sheet.nrows) + currroll=set() for i in range(1,sheet.nrows): roll_no = str(sheet.cell(i,0).value).split(".")[0] + # print("Roll No from Excel:", roll_no) course_slot_name = sheet.cell_value(i,1) course_code = sheet.cell_value(i,2) course_name = sheet.cell_value(i,3) - user=User.objects.get(username=roll_no) - user_info = ExtraInfo.objects.get(user=user) - student = Student.objects.get(id=user_info) - course_slot=CourseSlot.objects.get(name=course_slot_name.strip(),semester=sem_id) - course = Courses.objects.get(code=course_code.strip(),name=course_name.strip()) - #print(">>>>>",roll_no,course_slot_name,course_code,course_name) + try: + + user=User.objects.get(username=roll_no) + user_info = ExtraInfo.objects.get(user=user) + student = Student.objects.get(id=user_info) + course_slot=CourseSlot.objects.get(name=course_slot_name.strip(),semester=sem_id) + print(course_code.strip() , course_name.strip()) + course = Courses.objects.get(code=course_code.strip(),name=course_name.strip()) + if(roll_no not in currroll): + student_check=StudentRegistrationChecks(student_id = student, semester_id = sem_id, pre_registration_flag = True,final_registration_flag = False) + student_checks.append(student_check) + currroll.add(roll_no) + # print(">>>>>",roll_no,course_slot_name,course_code,course_name) + except Exception as e: + print('----------------------' , e) + pre_registration=InitialRegistration(student_id=student,course_slot_id=course_slot, + course_id=course,semester_id=sem_id,priority=1) + pre_registrations.append(pre_registration) final_registration=FinalRegistration(student_id=student,course_slot_id=course_slot, course_id=course,semester_id=sem_id) final_registrations.append(final_registration) + + courseregistration=course_registration(working_year=datetime.datetime.now().year,course_id=course,semester_id=sem_id,student_id=student,course_slot_id=course_slot) + course_registrations.append(courseregistration) + + try: + InitialRegistration.objects.bulk_create(pre_registrations) + StudentRegistrationChecks.objects.bulk_create(student_checks) FinalRegistration.objects.bulk_create(final_registrations) + course_registration.objects.bulk_create(course_registrations) messages.success(request, 'Successfully uploaded!') return HttpResponseRedirect('/academic-procedures/main') # return HttpResponse("Success") @@ -1499,7 +1658,7 @@ def user_check(request): final_user="" pass - if (str(acadadmin) != str(final_user)): + if ('acadadmin' != request.session.get('currentDesignationSelected')): return True else: return False @@ -1587,7 +1746,8 @@ def add_courses(request): course_id = course_id, student_id=current_user, course_slot_id = courseslot_id, - semester_id=sem_id + semester_id=sem_id, + working_year = datetime.datetime.now().year, ) if p not in reg_curr: reg_curr.append(p) @@ -1627,6 +1787,52 @@ def drop_course(request): else: return HttpResponseRedirect('/academic-procedures/main') +def replace_courses(request): + """ + This function is used to replace elective courses which have been registered + @param: + request - contains metadata about the requested page + @variables: + current_user - contains current logged in user + sem_id - contains current semester id + count - no of courses to be replaced + course_id - contains course id for a particular course + course_slot_id - contains course slot id for a particular course + choice - contains choice of a particular course + slot - contains slot of a particular course + """ + + if request.method == 'POST' : + try: + current_user = get_object_or_404(User, username=request.POST.get('user')) + current_user = ExtraInfo.objects.all().filter(user=current_user).first() + current_user = Student.objects.all().filter(id=current_user.id).first() + + # sem_id = Semester.objects.get(id = request.POST.get('semester')) + count = request.POST.get('ct') + count = int(count) + + for i in range(1, count+1): + choice = "choice["+str(i)+"]" + slot = "slot["+str(i)+"]" + try : + + course_id = Courses.objects.get(id = request.POST.get(choice)) + courseslot_id = CourseSlot.objects.get(id = request.POST.get(slot)) + + registered_course = course_registration.objects.filter(student_id=current_user, course_slot_id = courseslot_id).first() + + if registered_course: + registered_course.course_id = course_id + registered_course.save() + except Exception as e: + continue + return HttpResponseRedirect('/academic-procedures/main') + except Exception as e: + return HttpResponseRedirect('/academic-procedures/main') + else : + return HttpResponseRedirect('/academic-procedures/main') + @@ -1726,7 +1932,7 @@ def get_final_registration_choices(branch_courses,batch): max_limit = courseslot.max_registration_limit lis = [] for course in courseslot.courses.all(): - if FinalRegistration .objects.filter(student_id__batch_id__year = batch, course_id = course).count() < max_limit: + if FinalRegistration.objects.filter(student_id__batch_id__year = batch, course_id = course).count() < max_limit: lis.append(course) else: unavailable_courses.append(course) @@ -1741,10 +1947,13 @@ def get_add_course_options(branch_courses, current_register, batch): for c in current_register: slots.append(c[0]) for courseslot in branch_courses: + if courseslot.type == "Swayam": + continue max_limit = courseslot.max_registration_limit if courseslot not in slots: lis = [] for course in courseslot.courses.all(): + print(course) if course_registration.objects.filter(student_id__batch_id__year = batch, course_id = course).count() < max_limit: lis.append(course) course_option.append((courseslot, lis)) @@ -1757,7 +1966,24 @@ def get_drop_course_options(current_register): courses.append(item[1]) return courses +def get_replace_course_options( current_register, batch): + replace_options = [] + for registered_course in current_register: + courseslot_id = registered_course[0] + course_id = registered_course[1] + + courseslot = courseslot_id + coursename = course_id.name + lis = [] + + if 'Elective' in courseslot.type: + for course in courseslot.courses.all(): + if course != course_id: + lis.append(course) + replace_options.append((courseslot, coursename, lis)) + + return replace_options @@ -1789,7 +2015,11 @@ def get_user_semester(roll_no, ug_flag, masters_flag, phd_flag): def get_branch_courses(roll_no, user_sem, branch): roll = str(roll_no) - year = int(roll[:4]) + try: + year = int(roll[:4]) + except: + year = int(roll[:2]) + year = 2000 + year courses = Curriculum.objects.all().select_related().filter(batch=(year)) courses = courses.filter(sem = user_sem) courses = courses.filter(floated = True) @@ -1819,7 +2049,8 @@ def get_currently_registered_courses(id, user_sem): return ans def get_currently_registered_course(id, sem_id): - obj = course_registration.objects.all().filter(student_id = id, semester_id=sem_id) + # obj = course_registration.objects.all().filter(student_id = id, semester_id=sem_id) + obj = course_registration.objects.all().filter(student_id = id) courses = [] for i in obj: courses.append((i.course_slot_id,i.course_id)) @@ -1864,13 +2095,13 @@ def acad_person(request): des = HoldsDesignation.objects.all().select_related().filter(user = request.user).first() - if str(des.designation) == "student": + if request.session.get('currentDesignationSelected') == "student": return HttpResponseRedirect('/academic-procedures/main/') - elif str(des.designation) == "Associate Professor" : + elif request.session.get('currentDesignationSelected') == "Associate Professor" : return HttpResponseRedirect('/academic-procedures/main/') - elif str(request.user) == "acadadmin" : + elif request.session.get('currentDesignationSelected')== "acadadmin" : # year = datetime.datetime.now().year @@ -2223,12 +2454,13 @@ def student_list(request): batch_id = Batch.objects.get(id = batch) student_obj = FeePayments.objects.all().select_related('student_id').filter(student_id__batch_id = batch_id) if (student_obj): - reg_table = student_obj.prefetch_related('student_id__studentregistrationchecks').filter(semester_id = student_obj[0].semester_id, student_id__studentregistrationchecks__final_registration_flag = True).select_related( + reg_table = student_obj.prefetch_related('student_id__studentregistrationchecks').filter(semester_id = student_obj[0].semester_id, student_id__studentregistrationchecks__final_registration_flag = True , student_id__finalregistration__verified=False , student_id__finalregistration__semester_id= student_obj[0].semester_id ).select_related( 'student_id','student_id__id','student_id__id__user','student_id__id__department').values( 'student_id__id','student_id__id__user__first_name','student_id__id__user__last_name','student_id__batch','student_id__id__department__name', 'student_id__programme','student_id__curr_semester_no','student_id__id__sex','student_id__id__phone_no','student_id__category', 'student_id__specialization','mode','transaction_id','deposit_date','fee_paid','utr_number','reason','fee_receipt','actual_fee', - 'student_id__id__user__username').order_by('student_id__id__user') + 'student_id__id__user__username').order_by('student_id__id__user').distinct() + # print('------------------------------------------------------------------------------------------------------------------------------------------',reg_table) else : reg_table = [] @@ -2288,7 +2520,7 @@ def student_list(request): 'specialization','gender','category', 'pwd_status','phone_no','actual_fee', 'fee_paid','reason','date_deposited', - 'mode','utr_number','fee_receipt')) + 'mode','utr_number','fee_receipt')).distinct() excel_response = BytesIO() @@ -2326,6 +2558,12 @@ def process_verification_request(request): return verify_registration(request) return JsonResponse({'status': 'Failed'}, status=400) + +def auto_process_verification_request(request): + if request.is_ajax(): + return auto_verify_registration(request) + return JsonResponse({'status': 'Failed'}, status=400) + @transaction.atomic def verify_registration(request): @@ -2335,12 +2573,17 @@ def verify_registration(request): batch = student.batch_id curr_id = batch.curriculum - sem_id = Semester.objects.get(curriculum = curr_id, semester_no = student.curr_semester_no+1) + + if(student.curr_semester_no+1 >= 9): + sem_no = 4 + else: + sem_no = student.curr_semester_no+1 - final_register_list = FinalRegistration.objects.all().filter(student_id = student, verified = False, semester_id = sem_id) + sem_id = Semester.objects.get(curriculum = curr_id, semester_no = sem_no) - sem_no = student.curr_semester_no + 1 + final_register_list = FinalRegistration.objects.all().filter(student_id = student, verified = False, semester_id = sem_id) + with transaction.atomic(): ver_reg = [] for obj in final_register_list: @@ -2348,11 +2591,13 @@ def verify_registration(request): course_id=obj.course_id, student_id=student, semester_id=obj.semester_id, - course_slot_id = obj.course_slot_id + course_slot_id = obj.course_slot_id, + working_year = datetime.datetime.now().year, ) ver_reg.append(p) o = FinalRegistration.objects.filter(id= obj.id).update(verified = True) course_registration.objects.bulk_create(ver_reg) + # StudentRegistrationChecks.objects.filter(student_id = student_id, semester_id = sem_id).update(final_registration_flag = True) academics_module_notif(request.user, student.id.user, 'registration_approved') Student.objects.filter(id = student_id).update(curr_semester_no = sem_no) return JsonResponse({'status': 'success', 'message': 'Successfully Accepted'}) @@ -2363,18 +2608,66 @@ def verify_registration(request): batch = student_id.batch_id curr_id = batch.curriculum - sem_id = Semester.objects.get(curriculum = curr_id, semester_no = student_id.curr_semester_no + 1) - + if(student.curr_semester_no+1 >= 9): + sem_no = 4 + else: + sem_no = student.curr_semester_no+1 + sem_id = Semester.objects.get(curriculum = curr_id, semester_no = sem_no) with transaction.atomic(): - academicadmin = get_object_or_404(User, username = "acadadmin") + academicadmin = get_object_or_404(User, username = request.user.username) FinalRegistration.objects.filter(student_id = student_id, verified = False, semester_id = sem_id).delete() StudentRegistrationChecks.objects.filter(student_id = student_id, semester_id = sem_id).update(final_registration_flag = False) FeePayments.objects.filter(student_id = student_id, semester_id = sem_id).delete() academics_module_notif(academicadmin, student_id.id.user, 'Registration Declined - '+reject_reason) return JsonResponse({'status': 'success', 'message': 'Successfully Rejected'}) - - +@transaction.atomic +def auto_verify_registration(request): + if request.POST.get('status_req') == "accept" : + student_id = request.POST.get('student_id') + student = Student.objects.get(id = student_id) + batch = student.batch_id + curr_id = batch.curriculum + + if(student.curr_semester_no+1 >= 9): + # print('----------------------------------------------------------------' , student.curr_semester_no) + sem_no = 8 + else: + # print('----------------------------------------------------------------' , student.curr_semester_no) + sem_no = student.curr_semester_no+1 + sem_id = Semester.objects.get(curriculum = curr_id, semester_no = sem_no) + # print('----------------------------------------------------------------' , student.curr_semester_no) + + final_register_list = FinalRegistration.objects.all().filter(student_id = student, verified = False, semester_id = sem_id) + + # final_register_list = FinalRegistration.objects.all().filter(student_id = student, verified = False) + + with transaction.atomic(): + for obj in final_register_list: + o = FinalRegistration.objects.filter(id= obj.id).update(verified = True) + academics_module_notif(request.user, student.id.user, 'registration_approved') + + Student.objects.filter(id = student_id).update(curr_semester_no = sem_no) + return JsonResponse({'status': 'success', 'message': 'Successfully Accepted'}) + + elif request.POST.get('status_req') == "reject" : + reject_reason = request.POST.get('reason') + student_id = request.POST.get('student_id') + student_id = Student.objects.get(id = student_id) + batch = student_id.batch_id + curr_id = batch.curriculum + if(student_id.curr_semester_no+1 >= 9): + sem_no = 8 + else: + sem_no = student_id.curr_semester_no+1 + sem_id = Semester.objects.get(curriculum = curr_id, semester_no = sem_no) + with transaction.atomic(): + academicadmin = get_object_or_404(User, username = request.user.username) + # FinalRegistration.objects.filter(student_id = student_id, verified = False, semester_id = sem_id).delete() + StudentRegistrationChecks.objects.filter(student_id = student_id, semester_id = sem_id).update(final_registration_flag = False) + FeePayments.objects.filter(student_id = student_id, semester_id = sem_id).delete() + academics_module_notif(academicadmin, student_id.id.user, 'Registration Declined - '+reject_reason) + return JsonResponse({'status': 'success', 'message': 'Successfully Rejected'}) def get_registration_courses(courses): x = [[]] @@ -2439,8 +2732,8 @@ def course_marks_data(request): try: course_id = request.POST.get('course_id') course = Courses.objects.select_related().get(id = course_id) - print(course) - print(course_id) + # print(course) + # print(course_id) student_list = course_registration.objects.filter(course_id__id=course_id).select_related( 'student_id__id__user','student_id__id__department').only('student_id__batch', 'student_id__id__user__first_name', 'student_id__id__user__last_name', @@ -3462,7 +3755,380 @@ def mdue(request): content = json.dumps("success") return HttpResponse(content) + + + +def get_detailed_sem_courses(sem_id): + course_slots = CourseSlot.objects.filter(semester_id=sem_id) + # Serialize queryset of course slots into JSON + course_slots_json = serialize('json', course_slots) + # Convert JSON string into Python object + course_slots_data = json.loads(course_slots_json) + + # Iterate over each course slot data and include associated course data + for slot_data in course_slots_data: + # Retrieve associated courses for the current course slot + slot = CourseSlot.objects.get(id=slot_data['pk']) + courses = list(slot.courses.all().values()) + # Add courses data to the course slot data + slot_data['courses'] = courses + + return course_slots_data + + +def get_next_sem_courses(request): + if request.method == 'POST': + data = json.loads(request.body) + next_sem = data.get('next_sem') + branch = data.get('branch') + programme = data.get('programme') + batch = data.get('batch') + # we go to student table and apply filters and get batch_id of the students with these filter + batch_id = Student.objects.filter(programme = programme , batch = batch , specialization = branch)[0].batch_id + + curr_id = batch_id.curriculum + # print('-----------------------------------------------------------------------------------------', curr_id) + # curr_id = 1 + next_sem_id = Semester.objects.get(curriculum = curr_id, semester_no = next_sem) + if next_sem_id: + next_sem_registration_courses = get_detailed_sem_courses(next_sem_id ) + # print(next_sem_registration_courses) + return JsonResponse(next_sem_registration_courses, safe=False) + return JsonResponse({'error': 'Invalid request'}) + +def add_course_to_slot(request): + if request.method == 'POST': + data = json.loads(request.body) + course_slot_name = data.get('course_slot_name') + course_code = data.get('course_name') + # print('-----------------------------------------------------------------------------------------' , course_slot_name , course_code) + try: + course_slot = CourseSlot.objects.filter(name=course_slot_name).first() + course = Courses.objects.filter(code=course_code).first() + course_slot.courses.add(course) + + return JsonResponse({'message': f'Course {course_code} added to slot {course_slot_name} successfully.'}, status=200) + except CourseSlot.DoesNotExist: + return JsonResponse({'error': 'Course slot does not exist.'}, status=400) + except Course.DoesNotExist: + return JsonResponse({'error': 'Course does not exist.'}, status=400) + return JsonResponse({'error': 'Invalid request method.'}, status=405) + + +def remove_course_from_slot(request): + if request.method == 'POST': + data = json.loads(request.body) + course_slot_name = data.get('course_slot_name') + course_code = data.get('course_name') + # print('-----------------------------------------------------------------------------------------' , course_slot_name , course_code) + try: + course_slot = CourseSlot.objects.filter(name=course_slot_name).first() + course = Courses.objects.filter(code=course_code).first() + course_slot.courses.remove(course) + return JsonResponse({'message': f'Course {course_code} removed from slot {course_slot_name} successfully.'}, status=200) + except CourseSlot.DoesNotExist: + return JsonResponse({'error': 'Course slot does not exist.'}, status=400) + except Course.DoesNotExist: + return JsonResponse({'error': 'Course does not exist.'}, status=400) + + return JsonResponse({'error': 'Invalid request method.'}, status=405) + + +def add_one_course(request): + if request.method == 'POST': + try: + # print(request.POST) + current_user = get_object_or_404(User, username=request.POST.get('user')) + current_user = ExtraInfo.objects.all().filter(user=current_user).first() + current_user = Student.objects.all().filter(id=current_user.id).first() + + sem_id = Semester.objects.get(id=request.POST.get('semester')) + choice = request.POST.get('choice') + slot = request.POST.get('slot') + + try: + course_id = Courses.objects.get(id=choice) + courseslot_id = CourseSlot.objects.get(id=slot) + print(courseslot_id) + print(courseslot_id.type) + if course_registration.objects.filter(course_slot_id_id=courseslot_id, student_id=current_user).count() == 1 and courseslot_id.type != "Swayam": + already_registered_course_id = course_registration.objects.filter(course_slot_id_id=courseslot_id, student_id=current_user)[0].course_id + # print(already_registered_course_id) + msg = 'Already Registered in the course : ' +already_registered_course_id.code + '-'+ already_registered_course_id.name + return JsonResponse({'message' : msg}) + if((course_registration.objects.filter(course_id=course_id, student_id=current_user).count() >= 1)): + return JsonResponse({'message': 'Already registered in this course!'}, status=200) + # Check if maximum course registration limit has not been reached + if course_registration.objects.filter(student_id__batch_id__year=current_user.batch_id.year, course_id=course_id).count() < courseslot_id.max_registration_limit and \ + (course_registration.objects.filter(course_id=course_id, student_id=current_user).count() == 0): + p = course_registration( + course_id=course_id, + student_id=current_user, + course_slot_id=courseslot_id, + semester_id=sem_id, + working_year = datetime.datetime.now().year, + ) + p.save() + return JsonResponse({'message': 'Course added successfully'}) + else: + return JsonResponse({'message': 'Course not added because seats are full!'}, status=200) + except Exception as e: + return JsonResponse({'message': 'Error adding course'}, status=500) + except Exception as e: + return JsonResponse({'message': 'Error adding course'}, status=500) + else: + return JsonResponse({'message': 'Invalid request method'}, status=405) + +def replace_one_course(request): + if request.method == 'POST' : + try: + current_user = get_object_or_404(User, username=request.POST.get('user')) + current_user = ExtraInfo.objects.all().filter(user=current_user).first() + current_user = Student.objects.all().filter(id=current_user.id).first() + + + course_id = Courses.objects.get(id = request.POST.get('choice')) + courseslot_id = CourseSlot.objects.get(id = request.POST.get('slot')) + if course_registration.objects.filter(student_id__batch_id__year=current_user.batch_id.year, course_id=course_id).count() < courseslot_id.max_registration_limit and \ + (course_registration.objects.filter(course_id=course_id, student_id=current_user).count() == 0): + # print('---------------------------------------------------------------------------------' , course_registration.objects.filter(student_id__batch_id__year=current_user.batch_id.year, course_id=course_id).count() , courseslot_id.max_registration_limit ) + registered_course = course_registration.objects.filter(student_id=current_user, course_slot_id = courseslot_id).first() + + if registered_course: + registered_course.course_id = course_id + registered_course.save() + else: + return JsonResponse({'message': 'Cannot Replace to this course seats are full!'}, status=200) + + return JsonResponse({'message': 'Course Replaced Successfully'}, status=200) + except Exception as e: + return JsonResponse({'message': 'Error Replacing course'}, status=500) + else : + return JsonResponse({'message': 'Invalid request method'}, status=405) + +def get_sem_swayam(sem_id, batch): + courses = [] + course_slots = CourseSlot.objects.all().filter(type='Swayam') + + for slot in course_slots: + courses.append(slot) + + return courses + +def replaceSwayam(request): + if(request.POST): + # print(f"++++++++++++++++++++++++++++++++++++++++++++++++{request.POST}") + + current_user = get_object_or_404(User, username=request.user.username) + user_details = ExtraInfo.objects.all().select_related( + 'user', 'department').filter(user=current_user).first() + desig_id = Designation.objects.all().filter(name='acadadmin').first() + temp = HoldsDesignation.objects.all().select_related().filter( + designation=desig_id).first() + acadadmin = temp.working + k = str(user_details).split() + final_user = k[2] + + if ('acadadmin' != request.session.get('currentDesignationSelected')): + return HttpResponseRedirect('/academic-procedures/') + roll_no = request.POST["rollNo"] + obj = ExtraInfo.objects.all().select_related( + 'user', 'department').filter(id=roll_no).first() + firstname = obj.user.first_name + lastname = obj.user.last_name + dict2 = {'roll_no': roll_no, + 'firstname': firstname, 'lastname': lastname} + + details = [] + + obj2 = Student.objects.all().select_related( + 'id', 'id__user', 'id__department').filter(id=roll_no).first() + # obj = Register.objects.all().select_related('curr_id', 'student_id', 'curr_id__course_id', + # 'student_id__id', 'student_id__id__user', 'student_id__id__department').filter(student_id=obj2) + batch = obj2.batch_id + curr_id = batch.curriculum + curr_sem_id = Semester.objects.get(curriculum = curr_id, semester_no = obj2.curr_semester_no) + + current_sem_courses = get_currently_registered_elective( + roll_no, curr_sem_id) + current_sem_swayam = get_sem_swayam(curr_sem_id,2025) + + idd = obj2 + for z in current_sem_courses: + eletive_id=z[2] + z = z[1] + + course_code = z.code + course_name = z.name + + k = {} + # reg_ig has course registration id appended with the the roll number + # so that when we have removed the registration we can be redirected to this view + k['reg_id'] = roll_no+" - "+course_code + k['rid'] = roll_no+" - "+course_code + # Name ID Confusion here , be carefull + courseobj2 = Courses.objects.all().filter(code=course_code) + # if(str(z.student_id) == str(idd)): + for p in courseobj2: + k['course_id'] = course_code + k['course_name'] = course_name + k['sem'] = curr_sem_id.semester_no + k['credits'] = p.credit + k['eletive_id'] = eletive_id + details.append(k) + + year = demo_date.year + month = demo_date.month + yearr = str(year) + "-" + str(year+1) + semflag = 0 + if(month >= 7): + semflag = 1 + else: + semflag = 2 + # TO DO Bdes + date = {'year': yearr, 'semflag': semflag} + course_list = Courses.objects.all() + semester_list = Semester.objects.all() + html = render_to_string('academic_procedures/studentSwayam.html', + {'details': details, + 'dict2': dict2, + 'course_list': course_list, + 'current_sem_swayam':current_sem_swayam, + 'roll_no':roll_no, + 'semester_list': semester_list, + # 'csrf_token' : csrf_token, + 'date': date}, request) + + maindict = {'html': html} + obj = json.dumps(maindict) + return HttpResponse(obj, content_type='application/json') + +def get_currently_registered_elective(student_id, semester_id): + registrations = course_registration.objects.filter(student_id=student_id, semester_id=semester_id) + courses = [] + for registration in registrations: + if registration.course_slot_id.type == "Optional Elective": + courses.append((registration.course_slot_id, registration.course_id, registration.id)) + return courses + + + +def swayam_replace(request): + if request.method == 'POST': + csrf_token = request.POST.get('csrfmiddlewaretoken', None) + + # print(f"---------------------------------{csrf_token}") + try: + + # print(f"djfhajjfsjfhajfhjdsfsdfj{request.POST}") + csrf_token = request.POST.get('csrfmiddlewaretoken', None) + + # print(f"---------------------------------{csrf_token}") + # Accessing individual values by key + user_value = request.POST['user'] + course_id_value = request.POST['course_id'] + + # print(user_value) 20BCS074 + # print(course_id_value) 8955 + + elective_to_delete = course_registration.objects.get(id=course_id_value) + sem = elective_to_delete.semester_id + # print(elective_to_delete) + # print(sem) cse ug curri v1 + + + swayam_course_id_value = request.POST['swayam_course_id'] + swayam_course_id_value_array = [int(id_str) for id_str in swayam_course_id_value.split(',')[:-1]] + # print(swayam_course_id_value_array) + # print(swayam_course_id_value) + + + + swayam_course_slot_id_value = request.POST['swayam_course_slot_id'] + swayam_course_slot_id_value_array = [int(slot_str) for slot_str in swayam_course_slot_id_value.split(',')[:-1]] + # print(swayam_course_slot_id_value_array) + # print(swayam_course_slot_id_value) + + + swayam_semester_id_value = request.POST['swayam_semester_id'] + swayam_semester_id_value_array = [int(semester_str) for semester_str in swayam_semester_id_value.split(',')[:-1]] + + + + + n = len(swayam_course_id_value_array) + # print(n) + # new_row_data = [] + for i in range(n): + course_id_model = Courses.objects.get(id=swayam_course_id_value_array[i]) + # print(course_id_model) + semester_id_model = Semester.objects.get(id=swayam_semester_id_value_array[i]) + student_id_model = Student.objects.get(id=user_value) + course_slot_id_model = CourseSlot.objects.get(id=swayam_course_slot_id_value_array[i]) + obj = course_registration( + course_id = course_id_model, + semester_id = semester_id_model, + student_id = student_id_model, + course_slot_id = course_slot_id_model, + working_year = datetime.datetime.now().year, + ) + obj.save() + + # for j in range(n): + # SwayamCourses.objects.filter(course_id = swayam_course_id_value_array[j], student_id=user_value).update(course_used = True) + + elective_to_delete.delete() + + + messages.success(request, "Your Courses have been replaced.") + return HttpResponseRedirect('/academic-procedures/main') + + + + + except Exception as e: + error_message = str(e) + print("Error:", error_message) + messages.error(request, f"Error in Registration: {error_message}") + return HttpResponseRedirect('/academic-procedures/main') + else: + return HttpResponseRedirect('/academic-procedures/main') + +def register_backlog_course(request): + if request.method == 'POST': + try: + current_user = request.user + current_user = ExtraInfo.objects.all().filter(user=request.user).first() + current_user = Student.objects.all().filter(id=current_user.id).first() + sem_id = Semester.objects.filter(id = request.POST.get('semester')).first() + course_id = Courses.objects.get(code = request.POST.get('courseCode') , version = request.POST.get('Version')) + course_slots = course_id.courseslots.all() + course_slot_id = '' + if course_slots: + course_slot_id = CourseSlot.objects.filter(id = course_slots[0].id).first() + if (sem_id.semester_no - course_slot_id.semester.semester_no)%2 != 0 : + return JsonResponse({'message':'Wait for Next Semester !'}, status=200) + # print('_____________________________________________________________________________________________' , course_id ,current_user , course_slot_id , sem_id) + try: + if course_registration.objects.filter(course_id=course_id, student_id=current_user , semester_id = sem_id).count() == 0: + p = course_registration( + course_id=course_id, + student_id=current_user, + course_slot_id=course_slot_id, + semester_id=sem_id, + working_year = datetime.datetime.now().year, + ) + p.save() + return JsonResponse({'message': 'Successfully Registered Backlog course' }, status=200) + else: + return JsonResponse({'message': 'Already Registered Backlog course' }, status=200) + except Exception as e: + print(str(e)) + return JsonResponse({'message': 'Error Registering course ' + str(e)}, status=500) + except Exception as e: + print(str(e)) + return JsonResponse({'message': 'Adding Backlog Failed ' +str(e)}, status=500) \ No newline at end of file diff --git a/FusionIIIT/applications/central_mess/api/serializers.py b/FusionIIIT/applications/central_mess/api/serializers.py index b30ad2686..1e077d6d4 100644 --- a/FusionIIIT/applications/central_mess/api/serializers.py +++ b/FusionIIIT/applications/central_mess/api/serializers.py @@ -88,4 +88,18 @@ class Meta: class reg_recordSerialzer(serializers.ModelSerializer): class Meta: model = Reg_records - fields=('__all__') \ No newline at end of file + fields=('__all__') + +class RegistrationRequestSerializer(serializers.ModelSerializer): + class Meta: + model = Registration_Request + fields = ('__all__') + +class DeregistrationRequestSerializer(serializers.ModelSerializer): + class Meta: + model = Deregistration_Request + fields = ('__all__') +class UpdatePaymentRequestSerializer(serializers.ModelSerializer): + class Meta: + model = Update_Payment + fields = ('__all__') \ No newline at end of file diff --git a/FusionIIIT/applications/central_mess/api/urls.py b/FusionIIIT/applications/central_mess/api/urls.py index 2bd15c746..e0a86b9d7 100644 --- a/FusionIIIT/applications/central_mess/api/urls.py +++ b/FusionIIIT/applications/central_mess/api/urls.py @@ -23,5 +23,9 @@ # url("billDashboard", views.Bill_dashboard.as_view(), name="billDashboard"), url("get_student_bill",views.Get_Student_bill.as_view(),name="student_bill_API"), url("get_student_payment",views.Get_Student_Payments.as_view(),name="student_payment_API"), - url("get_student_all_details",views.Get_Student_Details.as_view(),name="get_student_details_API") + url("get_student_all_details",views.Get_Student_Details.as_view(),name="get_student_details_API"), + url('registrationRequestApi', views.RegistrationRequestApi.as_view(), name='registrationRequestApi'), + url('deRegistrationRequestApi', views.DeregistrationRequestApi.as_view(), name='deRegistrationRequestApi'), + url('deRegistrationApi', views.DeregistrationApi.as_view(), name='deRegistrationApi'), + url('updatePaymentRequestApi', views.UpdatePaymentRequestApi.as_view(), name='updatePaymentRequestApi'), ] \ No newline at end of file diff --git a/FusionIIIT/applications/central_mess/api/views.py b/FusionIIIT/applications/central_mess/api/views.py index 6d1b7d4ae..4a6076ec4 100644 --- a/FusionIIIT/applications/central_mess/api/views.py +++ b/FusionIIIT/applications/central_mess/api/views.py @@ -1,4 +1,5 @@ #APIs +from django.db.models import F from rest_framework.views import APIView from rest_framework.response import Response from .serializers import * @@ -19,19 +20,47 @@ def post(self, request): data = request.data mess = data['mess'] - _type = data['type'] - desc = data['desc'] + feedback_type = data['feedback_type'] + description = data['description'] username = get_object_or_404(User,username=request.user.username) idd = ExtraInfo.objects.get(user=username) student = Student.objects.get(id=idd.id) obj = Feedback( student_id = student, mess =mess, - feedback_type=_type, - description=desc + feedback_type=feedback_type, + description=description ) obj.save() return Response({'status':200}) + + def put(self, request): + data = request.data + + print(data) + + student_id = data['student_id'] + mess = data['mess'] + feedback_type = data['feedback_type'] + description = data['description'] + fdate = data['fdate'] + new_remark = data['feedback_remark'] + + # username = get_object_or_404(User,username=request.user.username) + # idd = ExtraInfo.objects.get(user=username) + # student = Student.objects.get(id=idd.id) + + feedback_request = get_object_or_404(Feedback, + student_id = student_id, + mess = mess, + feedback_type = feedback_type, + description = description, + fdate = fdate, + ) + feedback_request.feedback_remark = new_remark + feedback_request.save() + + return Response({'status':200}) class MessinfoApi(APIView): @@ -104,30 +133,37 @@ def get(self, request): def post(self, request): data = request.data + student_id = data['student_id'] month = data['month'] year = data['year'] amount = data['amount'] rebate_count = data['rebate_count'] rebate_amount = data['rebate_amount'] - #nonveg_total_bill = data['nonveg_total_bill'] + total_bill = data['amount']-(data['rebate_count']*data['rebate_amount']) paid = data['paid'] - username = get_object_or_404(User,username=request.user.username) + username = get_object_or_404(User,username=student_id) idd = ExtraInfo.objects.get(user=username) student = Student.objects.get(id=idd.id) - - obj = Monthly_bill( - student_id = student, - month = month, - year = year, - amount = amount, - rebate_count = rebate_count, - rebate_amount = rebate_amount, - # nonveg_total_bill = nonveg_total_bill, - paid = paid - ) - obj.save() + try: + reg_main = Monthly_bill.objects.get(student_id=student, year = year, month = month) + reg_main.amount = amount + reg_main.rebate_count = rebate_count + reg_main.rebate_amount = rebate_amount + reg_main.total_bill = total_bill + except Monthly_bill.DoesNotExist: + reg_main = Monthly_bill.objects.create( + student_id=student, + month = month, + year = year, + amount = amount, + rebate_amount = rebate_amount, + rebate_count = rebate_count, + total_bill = total_bill, + paid = paid + ) + reg_main.save() return Response({'status':200}) class PaymentsApi(APIView): @@ -210,7 +246,33 @@ def post(self, request): start_date = start_date ) obj.save() - return Response({'status':200}) + return Response({'status':200}) + + def put(self, request): + data = request.data + + student_id = data['student_id'] + start_date = data['start_date'] + end_date = data['end_date'] + purpose = data['purpose'] + new_status = data['status'] + app_date = data['app_date'] + leave_type = data['leave_type'] + rebate_remark = data['rebate_remark'] + + # username = get_object_or_404(User,username=student_id) + # idd = ExtraInfo.objects.get(user=username) + # student = Student.objects.get(id=idd.id) + + rebate_request = get_object_or_404(Rebate, student_id=student_id, end_date=end_date, start_date=start_date, app_date=app_date, purpose=purpose, leave_type=leave_type) + + # Update the status + rebate_request.status = new_status + rebate_request.rebate_remark = rebate_remark + rebate_request.save() + + return Response({'status': 200}) + class Vacation_foodApi(APIView): def get(self, request): vacation_food_obj = Vacation_food.objects.all(); @@ -241,7 +303,45 @@ def post(self, request): start_date = start_date ) obj.save() - return Response({'status':200}) + return Response({'status':200}) + + def put(self, request): + print(request.data) + data = request.data + + student_id = data['student_id'] + start_date = data['start_date'] + end_date = data['end_date'] + purpose = data['purpose'] + new_status = data['status'] + app_date = data['app_date'] + + + # username = get_object_or_404(User,username=request.user.username) + # idd = ExtraInfo.objects.get(user=username) + # student = Student.objects.get(id=idd.id) + + try: + vacation_food_request = get_object_or_404(Vacation_food, + student_id = student_id, + app_date = app_date, + purpose = purpose, + end_date= end_date, + start_date = start_date + ) + vacation_food_request.status = new_status + vacation_food_request.save() + return Response({'status':200}) + except: + vacation_food_request = Vacation_food.objects.filter(student_id = student_id, + app_date = app_date, + purpose = purpose, + end_date= end_date, + start_date = start_date + ).latest('app_date') + vacation_food_request.status = new_status + vacation_food_request.save() + return Response({'status':200}) class Nonveg_menuApi(APIView): def get(self, request): @@ -331,7 +431,32 @@ def post(self, request): request = request_ ) obj.save() - return Response({'status':200}) + return Response({'status':200}) + + def put(self, request): + print(request.data) + data = request.data + student_id = data['student_id'] + start_date = data['start_date'] + end_date = data['end_date'] + app_date = data['app_date'] + request_= data['request'] + item1 = data['item1'] + item2 = data['item2'] + new_status = data['status'] + + # Fetch the Special_request object you want to update + # username = get_object_or_404(User, username=request.user.username) + # idd = ExtraInfo.objects.get(user=username) + # student = Student.objects.get(id=idd.id) + + special_request = get_object_or_404(Special_request, student_id=student_id, app_date=app_date, item1=item1, item2=item2, end_date=end_date, start_date=start_date, request=request_) + + # Update the status + special_request.status = new_status + special_request.save() + + return Response({'status': 200}) class Mess_meetingApi(APIView): def get(self, request): @@ -484,4 +609,187 @@ def post(self,request): reg_main = Reg_main.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').get(student_id=student) serialized_obj = GetFilteredSerialzer(reg_main) data={'payment':payment_serialized_obj.data,'bill':bill_serialized_obj.data,'reg_records':reg_record_serialized_obj.data,'student_details':serialized_obj.data} - return Response({'payload':data}) \ No newline at end of file + return Response({'payload':data}) + +class RegistrationRequestApi(APIView): + def get(self, request): + registration_requests = Registration_Request.objects.all() + serializer = RegistrationRequestSerializer(registration_requests, many=True) + return Response({'status': 200, 'payload': serializer.data}) + + def post(self, request): + serializer = RegistrationRequestSerializer(data=request.data) + if serializer.is_valid(): + serializer.save() + return Response({'status': 200}) + return Response(serializer.errors, status=400) + + def put(self, request): + try: + data = request.data + print(data) + student_id = data['student_id'] + start_date = data['start_date'] + payment_date = data['payment_date'] + amount = data['amount'] + Txn_no = data['Txn_no'] + img = data['img'] + new_status = data['status'] + new_remark = data['registration_remark'] + mess_option = data['mess_option'] + + username = get_object_or_404(User, username=student_id) + idd = ExtraInfo.objects.get(user=username) + student = Student.objects.get(id=idd.id) + + registration_request = get_object_or_404(Registration_Request, student_id = student_id, start_date = start_date, payment_date = payment_date, amount = amount, Txn_no = Txn_no) + + registration_request.status = new_status + registration_request.registration_remark = new_remark + registration_request.save() + + if (new_status == 'accept'): + new_payment_record = Payments(student_id = student, amount_paid = amount, payment_date=payment_date, payment_month=current_month(), payment_year=current_year()) + new_payment_record.save() + + try: + reg_main = Reg_main.objects.get(student_id=student) + reg_main.current_mess_status = "Registered" + reg_main.balance = F('balance') + amount + reg_main.mess_option = mess_option + except Reg_main.DoesNotExist: + reg_main = Reg_main.objects.create( + student_id=student, + program=student.programme, + current_mess_status="Registered", + balance=amount, + mess_option=mess_option + ) + reg_main.save() + + new_reg_record = Reg_records(student_id=student, start_date=start_date, end_date=None) + new_reg_record.save() + + + return Response({'status': 200}) + except Exception as e: + print({'error': str(e)}) + return Response({'error': str(e)}, status=400) + +class DeregistrationRequestApi(APIView): + def get(self, request): + deregistration_requests = Deregistration_Request.objects.all() + serializer = DeregistrationRequestSerializer(deregistration_requests, many=True) + return Response({'status': 200, 'payload': serializer.data}) + + def post(self, request): + serializer = DeregistrationRequestSerializer(data=request.data) + if serializer.is_valid(): + serializer.save() + return Response({'status': 200}) + return Response(serializer.errors, status=400) + + def put(self, request): + try: + data = request.data + print(data) + student_id = data['student_id'] + end_date = data['end_date'] + new_status = data['status'] + new_remark = data['deregistration_remark'] + + username = get_object_or_404(User, username=student_id) + idd = ExtraInfo.objects.get(user=username) + student = Student.objects.get(id=idd.id) + + deregistration_request = get_object_or_404(Deregistration_Request, student_id = student_id, end_date = end_date) + + deregistration_request.status = new_status + deregistration_request.deregistration_remark = new_remark + deregistration_request.save() + + if (new_status == 'accept'): + + reg_main = Reg_main.objects.get(student_id=student) + reg_main.current_mess_status = "Deregistered" + reg_main.save() + + reg_record = Reg_records.objects.filter(student_id=student).latest('start_date') + reg_record.end_date = end_date + reg_record.save() + return Response({'status': 200}) + except Exception as e: + print({'error': str(e)}) + return Response({'error': str(e)}, status=400) + +class DeregistrationApi(APIView): + def post(self, request): + try: + data = request.data + print(data) + student_id = data['student_id'] + end_date = data['end_date'] + + username = get_object_or_404(User, username=student_id) + idd = ExtraInfo.objects.get(user=username) + student = Student.objects.get(id=idd.id) + + reg_main = Reg_main.objects.get(student_id=student) + reg_main.current_mess_status = "Deregistered" + reg_main.save() + + reg_record = Reg_records.objects.filter(student_id=student).latest('start_date') + reg_record.end_date = end_date + reg_record.save() + return Response({'status': 200}) + except Exception as e: + print({'error': str(e)}) + return Response({'error': str(e)}, status=400) + +class UpdatePaymentRequestApi(APIView): + def get(self, request): + update_payment_requests = Update_Payment.objects.all() + serializer = UpdatePaymentRequestSerializer(update_payment_requests, many=True) + return Response({'status': 200, 'payload': serializer.data}) + + def post(self, request): + serializer = UpdatePaymentRequestSerializer(data=request.data) + if serializer.is_valid(): + serializer.save() + return Response({'status': 200}) + return Response(serializer.errors, status=400) + + def put(self, request): + try: + data = request.data + print(data) + student_id = data['student_id'] + payment_date = data['payment_date'] + amount = data['amount'] + Txn_no = data['Txn_no'] + img = data['img'] + new_status = data['status'] + new_remark = data['update_payment_remark'] + + username = get_object_or_404(User, username=student_id) + idd = ExtraInfo.objects.get(user=username) + student = Student.objects.get(id=idd.id) + + UpdatePayment_request = get_object_or_404(Update_Payment, student_id = student_id, payment_date = payment_date, amount = amount, Txn_no = Txn_no) + + UpdatePayment_request.status = new_status + UpdatePayment_request.update_payment_remark = new_remark + UpdatePayment_request.save() + + if (new_status == 'accept'): + new_payment_record = Payments(student_id = student, amount_paid = amount, payment_date=payment_date, payment_month=current_month(), payment_year=current_year()) + new_payment_record.save() + + reg_main = Reg_main.objects.get(student_id=student) + reg_main.balance = F('balance') + amount + reg_main.save() + + return Response({'status': 200}) + except Exception as e: + print({'error': str(e)}) + return Response({'error': str(e)}, status=400) \ No newline at end of file diff --git a/FusionIIIT/applications/central_mess/forms.py b/FusionIIIT/applications/central_mess/forms.py index ceecf4400..9325df23f 100644 --- a/FusionIIIT/applications/central_mess/forms.py +++ b/FusionIIIT/applications/central_mess/forms.py @@ -2,7 +2,7 @@ from .models import Mess_minutes from .models import Registration_Request -from .models import Semdates +from .models import Update_Payment class MinuteForm(forms.ModelForm): @@ -32,9 +32,22 @@ class Meta: 'img':forms.FileInput(attrs={'class':'ui big input'}), 'start_date':forms.widgets.DateInput(attrs={'type':'date'}), 'payment_date':forms.widgets.DateInput(attrs={'type':'date'}), - } - - + } + + +class UpdatePaymentRequest(forms.ModelForm): + + class Meta: + model = Update_Payment + fields = ('Txn_no','amount','img','payment_date') + + widgets={ + 'Txn_no':forms.TextInput(attrs={'class':'ui big input','style':'border-radius:4px', 'initial':'590'}), + 'amount':forms.TextInput(attrs={'class':'ui big input'}), + 'img':forms.FileInput(attrs={'class':'ui big input'}), + 'payment_date':forms.widgets.DateInput(attrs={'type':'date'}), + } + class UpdateBalanceRequest(forms.ModelForm): class Meta: diff --git a/FusionIIIT/applications/central_mess/handlers.py b/FusionIIIT/applications/central_mess/handlers.py index 47e840810..882cbe4e4 100644 --- a/FusionIIIT/applications/central_mess/handlers.py +++ b/FusionIIIT/applications/central_mess/handlers.py @@ -15,7 +15,7 @@ from applications.academic_information.models import Student from applications.globals.models import ExtraInfo, HoldsDesignation, Designation from .models import (Feedback, Menu, Menu_change_request, Mess_meeting, - Mess_minutes, Mess_reg, Messinfo, Monthly_bill, + Mess_minutes, Mess_reg, Messinfo, Monthly_bill, Update_Payment, Payments, Rebate,Special_request, Vacation_food, MessBillBase,Registration_Request, Reg_main, Reg_records ,Deregistration_Request, Semdates) from notification.views import central_mess_notif @@ -766,6 +766,40 @@ def handle_reg_response(request): return data +def handle_update_payment_response(request): + id = request.POST['id_reg'] + status = request.POST['status'] + remark = request.POST['remark'] + payment_req = Update_Payment.objects.get(pk=id) + payment_date = payment_req.payment_date + student = payment_req.student_id + payment_req.status = status + payment_req.update_remark=remark + + payment_req.save() + + if(status == 'accept'): + amount = payment_req.amount + reg_main_obj= Reg_main.objects.get(student_id=student) + new_balance = reg_main_obj.balance + amount + reg_main_obj.balance = new_balance + reg_main_obj.save() + new_payment_record = Payments(student_id=student, amount_paid = amount, payment_date=payment_date, payment_month=current_month(), payment_year= current_year()) + new_payment_record.save() + + message = 'Your update payment request has been accepted.' + + else: + message = 'Your update payment request has been rejected.' + + receiver = payment_req.student_id.id.user + central_mess_notif(request.user, receiver, 'leave_request', message) + data = { + 'message': 'success' + } + return data + + def handle_dreg_response(request): """ This function is to respond to de registeration requests @@ -816,14 +850,13 @@ def update_month_bill(request): """ student = str(request.POST.get("rollNo")).upper() studentHere = Student.objects.get(id = student) - rebate_count = int(request.POST.get("RebateCount")) - print(rebate_count) - rebate_amount = int(request.POST.get("RebateAmount")) - print(rebate_amount) new_amount = int(request.POST.get("new_amount")) month = request.POST.get("Month") year = int(request.POST.get("Year")) - bill_base_amount = int(MessBillBase.objects.latest('timestamp').bill_amount) + try: + bill_base_amount = int(MessBillBase.objects.latest('timestamp').bill_amount) + except: + bill_base_amount = 150 fixed_amount_per_month = int(bill_base_amount)*int(30) reg_main_obj = Reg_main.objects.get(student_id=student) @@ -838,7 +871,7 @@ def update_month_bill(request): reg_main_obj.save() existing_monthly_bill_object.save() except: - new_monthly_bill_obj = Monthly_bill(student_id = studentHere, rebate_amount=rebate_amount, rebate_count=rebate_count, month=month, year= year, total_bill = new_amount, amount=fixed_amount_per_month) + new_monthly_bill_obj = Monthly_bill(student_id = studentHere, month=month, year= year, total_bill = new_amount, amount=fixed_amount_per_month) curr_balance = curr_balance - new_amount reg_main_obj.balance = curr_balance reg_main_obj.save() diff --git a/FusionIIIT/applications/central_mess/migrations/0001_initial.py b/FusionIIIT/applications/central_mess/migrations/0001_initial.py index c197e0231..7e80bedf5 100644 --- a/FusionIIIT/applications/central_mess/migrations/0001_initial.py +++ b/FusionIIIT/applications/central_mess/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.1.5 on 2024-04-15 23:58 +# Generated by Django 3.1.5 on 2024-07-16 15:44 import applications.central_mess.models import datetime @@ -63,6 +63,19 @@ class Migration(migrations.Migration): ('student_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='academic_information.student')), ], ), + migrations.CreateModel( + name='Update_Payment', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('Txn_no', models.CharField(max_length=20)), + ('img', models.ImageField(default=None, upload_to='images/')), + ('amount', models.IntegerField(default=0)), + ('status', models.CharField(default='pending', max_length=10)), + ('update_remark', models.CharField(default='NA', max_length=50)), + ('payment_date', models.DateField(default=None, null=True)), + ('student_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='academic_information.student')), + ], + ), migrations.CreateModel( name='Special_request', fields=[ @@ -136,6 +149,17 @@ class Migration(migrations.Migration): ('student_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='academic_information.student')), ], ), + migrations.CreateModel( + name='Payments', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('amount_paid', models.IntegerField(default=0)), + ('payment_month', models.CharField(default=applications.central_mess.models.current_month, max_length=20)), + ('payment_year', models.IntegerField(default=applications.central_mess.models.current_year)), + ('payment_date', models.DateField(default=datetime.date(2024, 6, 19))), + ('student_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='academic_information.student')), + ], + ), migrations.CreateModel( name='Mess_minutes', fields=[ @@ -186,7 +210,7 @@ class Migration(migrations.Migration): ('amount_paid', models.IntegerField(default=0)), ('payment_month', models.CharField(default=applications.central_mess.models.current_month, max_length=20)), ('payment_year', models.IntegerField(default=applications.central_mess.models.current_year)), - ('payment_date', models.DateField(default=datetime.date(2024, 4, 15))), + ('payment_date', models.DateField(default=datetime.date(2024, 7, 16))), ('student_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='academic_information.student')), ], options={ diff --git a/FusionIIIT/applications/central_mess/models.py b/FusionIIIT/applications/central_mess/models.py index cd5427736..ae96e8f82 100644 --- a/FusionIIIT/applications/central_mess/models.py +++ b/FusionIIIT/applications/central_mess/models.py @@ -156,8 +156,8 @@ class Payments(models.Model): payment_year = models.IntegerField(default = current_year) payment_date = models.DateField(default= datetime.date.today()) - class Meta: - unique_together = (('student_id', 'payment_date')) + # class Meta: + # unique_together = (('student_id', 'payment_date')) def __str__(self): return '{}'.format(self.student_id.id) @@ -321,3 +321,16 @@ class Semdates(models.Model): end_date = models.DateField(blank=False,default=datetime.date.today) class Meta: unique_together = (('start_date', 'end_date'),) + + +class Update_Payment(models.Model): + student_id = models.ForeignKey(Student, on_delete=models.CASCADE) + Txn_no =models.CharField(max_length=20) + img = models.ImageField(upload_to='images/',default=None) + amount=models.IntegerField(default=0) + status=models.CharField(max_length=10,default='pending') + update_remark=models.CharField(max_length=50,default='NA') + payment_date= models.DateField(default=None, null=True) + def __str__(self): + return str(self.student_id.id) + \ No newline at end of file diff --git a/FusionIIIT/applications/central_mess/urls.py b/FusionIIIT/applications/central_mess/urls.py index 031626819..78b65f22c 100644 --- a/FusionIIIT/applications/central_mess/urls.py +++ b/FusionIIIT/applications/central_mess/urls.py @@ -46,7 +46,8 @@ url(r'^registeredstudent', views.searchAddOrRemoveStudent, name='registeredstudent'), url(r'^registrationRequest', views.reg_request, name='reg_request'), - # url(r'^uploadpayment', views.uploadPaymentDue, name='uploadpayment') + url(r'^updatePaymentReq', views.update_payment, name='update_payment'), + url(r'^respond_to_updatePayment', views.respond_to_update_payment, name='response_to_update_payment'), url(r'^respond_to_reg_req',views.respond_to_reg, name='reg_response'), url(r'^deregistrationRequest', views.de_reg_request, name='deregistrationRequest'), url(r'^updatesemdates', views.update_semdates, name='updatesemdates'), diff --git a/FusionIIIT/applications/central_mess/views.py b/FusionIIIT/applications/central_mess/views.py index 4bc7238bd..60a4abb3b 100644 --- a/FusionIIIT/applications/central_mess/views.py +++ b/FusionIIIT/applications/central_mess/views.py @@ -14,16 +14,16 @@ from .utils import render_to_pdf from applications.academic_information.models import Student from applications.globals.models import ExtraInfo, HoldsDesignation, Designation -from .forms import MinuteForm, MessInfoForm,RegistrationRequest +from .forms import MinuteForm, MessInfoForm,RegistrationRequest,UpdatePaymentRequest from .tasks import * from .models import (Feedback, Menu, Menu_change_request, Mess_meeting, Mess_minutes, Mess_reg, Messinfo, Monthly_bill, Payments, Rebate, - Special_request, Vacation_food, MessBillBase,Registration_Request, Reg_records ,Reg_main,Deregistration_Request,Semdates) + Special_request, Vacation_food, MessBillBase,Registration_Request, Reg_records ,Reg_main,Deregistration_Request,Semdates,Update_Payment) from .handlers import (add_mess_feedback, add_sem_dates, add_vacation_food_request, add_menu_change_request, handle_menu_change_response, handle_vacation_food_request, add_mess_registration_time, add_leave_request, add_mess_meeting_invitation, - handle_rebate_response, add_special_food_request, + handle_rebate_response, add_special_food_request, handle_update_payment_response, handle_special_request, add_bill_base_amount, add_mess_committee, handle_reg_response, handle_dreg_response, update_month_bill,handle_add_reg) from notification.views import central_mess_notif @@ -59,7 +59,7 @@ def mess(request): holds_designations = HoldsDesignation.objects.select_related().filter(user=user) desig = holds_designations form = MinuteForm() - mess_reg = Mess_reg.objects.select_related().last() + # mess_reg = Mess_reg.objects.select_related().last() count1 = 0 count2 = 0 count3 = 0 @@ -82,12 +82,15 @@ def mess(request): splrequest = Special_request.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(student_id=student).order_by('-app_date') reg_form = RegistrationRequest() + update_form=UpdatePaymentRequest() reg_request = Registration_Request.objects.filter(student_id=student) - + update_payment_request = Update_Payment.objects.filter(student_id=student) de_reg_request = Deregistration_Request.objects.filter(student_id=student) + menu_data = Menu.objects.all() + try: mess_optn = Reg_main.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').get(student_id=student) y = Menu.objects.filter(mess_option=mess_optn.mess_option) @@ -127,21 +130,22 @@ def mess(request): # monthly_bill[i].due_amount=(-tot_am) # tot_am+=monthly_bill[i].total_bill # amount_due=-payments[0].amount_paid - amount_due = 0 + # amount_due = 0 ## adding the batch of student if btech or bdes then value of programme is 1 or else 0, holds value of phd and mtech. - if student.programme == 'B.Tech' or student.programme == 'B.Des': - programme = 1 - else: - programme = 0 - meeting = Mess_meeting.objects.all() - minutes = Mess_minutes.objects.all() - count = 0 + # if student.programme == 'B.Tech' or student.programme == 'B.Des': + # programme = 1 + # else: + # programme = 0 + # meeting = Mess_meeting.objects.all() + # minutes = Mess_minutes.objects.all() + # count = 0 # try: # mess_optn = Messinfo.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').get(student_id=student) # y = Menu.objects.filter(mess_option=mess_optn.mess_option) + # bill = Monthly_bill.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(Q(student_id=student) & Q(month=month_g_l) & Q(year=year_g)) # amount_c = MessBillBase.objects.latest('timestamp') @@ -182,169 +186,175 @@ def mess(request): # mess_optn={'mess_option':'no-mess'} # y = Menu.objects.filter(mess_option="mess1") - for d in desig: - if d.designation.name == 'mess_committee' or d.designation.name == 'mess_convener': - newmenu = Menu_change_request.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department','dish').filter(dish__mess_option='mess1').order_by('-app_date') - meeting = Mess_meeting.objects.all() - minutes = Mess_minutes.objects.select_related().all() - feed = Feedback.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(mess='mess1').order_by('-fdate') - feed2 = Feedback.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(mess='mess2').order_by('-fdate') - sprequest = Special_request.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(status='1').order_by('-app_date') - sprequest_past = Special_request.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(status='2').order_by('-app_date') - menuchangerequest= Menu_change_request.objects.select_related('student_id').filter().order_by('-app_date') - # menu_data = Menu.objects.all() - for f in feed: - if f.feedback_type == 'Maintenance' : - count1 += 1 - - elif f.feedback_type == 'Food' : - count2 += 1 - - elif f.feedback_type == 'Cleanliness' : - count3 += 1 - - elif f.feedback_type == 'Others' : - count4 += 1 - count5=0 - count6=0 - count7=0 - count8=0 - - context = { - 'menu': menu_data, - 'reg_menu': y, - 'messinfo': mess_optn, - 'newmenu': newmenu, - 'monthly_bill': monthly_bill, - 'total_due': amount_due, + # for d in desig: + # if d.designation.name == 'mess_committee' or d.designation.name == 'mess_convener': + # newmenu = Menu_change_request.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department','dish').filter(dish__mess_option='mess1').order_by('-app_date') + # meeting = Mess_meeting.objects.all() + # minutes = Mess_minutes.objects.select_related().all() + # feed = Feedback.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(mess='mess1').order_by('-fdate') + # feed2 = Feedback.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(mess='mess2').order_by('-fdate') + # sprequest = Special_request.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(status='1').order_by('-app_date') + # sprequest_past = Special_request.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(status='2').order_by('-app_date') + # menuchangerequest= Menu_change_request.objects.select_related('student_id').filter().order_by('-app_date') + + # # menu_data = Menu.objects.all() + + # for f in feed: + # if f.feedback_type == 'Maintenance' : + # count1 += 1 + + # elif f.feedback_type == 'Food' : + # count2 += 1 + + # elif f.feedback_type == 'Cleanliness' : + # count3 += 1 + + # elif f.feedback_type == 'Others' : + # count4 += 1 + # count5=0 + # count6=0 + # count7=0 + # count8=0 + + # context = { + # 'menu': menu_data, + # 'reg_menu': y, + # 'messinfo': mess_optn, + # 'newmenu': newmenu, + # 'monthly_bill': monthly_bill, + # 'total_due': amount_due, - 'vaca': vaca_obj, - 'info': extrainfo, - 'feedback': feedback_obj, - 'feed1': feed, - 'feed2':'', - 'student': student, - 'mess_reg': mess_reg, - 'current_date': current_date, - 'count': count, - 'rebates': rebates, - 'meeting': meeting, - 'minutes': minutes, - 'sprequest': sprequest, - 'splrequest': splrequest, - 'sprequest_past': sprequest_past, - 'menuchangerequest':menuchangerequest, - 'programme':programme, - 'count1': count1, - 'count2': count2, - 'count3': count3, - 'count4': count4, - 'count5': count5, - 'count6': count6, - 'count7': count7, - 'count8': count8, - 'form': form, - 'desig': desig, - 'reg_form':reg_form, - 'reg_request':reg_request, - 'reg_main':mess_optn, - 'reg_record':reg_record, - 'de_reg_request':de_reg_request, - - } - return render(request, "messModule/mess.html", context) - - if d.designation.name == 'mess_committee_mess2' or d.designation.name == 'mess_convener_mess2': - newmenu = Menu_change_request.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department','dish').filter(dish__mess_option='mess2').order_by('-app_date') - meeting = Mess_meeting.objects.all() - minutes = Mess_minutes.objects.select_related().all() - feed = Feedback.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(mess='mess2').order_by('-fdate') - feed2 = Feedback.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(mess='mess1').order_by('-fdate') - sprequest = Special_request.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(status='1').order_by('-app_date') - sprequest_past = Special_request.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(status='2').order_by('-app_date') - menuchangerequest= Menu_change_request.objects.select_related('student_id').filter().order_by('-app_date') - # menu_data = Menu.objects.all().order_by() - count5=0 - count6=0 - count7=0 - count8=0 - for f in feed: - if f.feedback_type == 'Maintenance' : - count1 += 1 - - elif f.feedback_type == 'Food' : - count2 += 1 - - elif f.feedback_type == 'Cleanliness' : - count3 += 1 - - elif f.feedback_type == 'Others' : - count4 += 1 - - context = { - 'menu': menu_data, - 'reg_menu': y, - 'messinfo': mess_optn, - 'newmenu': newmenu, - 'monthly_bill': monthly_bill, - 'total_due': amount_due, - 'vaca': vaca_obj, - 'info': extrainfo, - 'feedback': feedback_obj, - 'feed2': feed, - 'feed1':'', - 'student': student, - # 'data': data, - 'mess_reg': mess_reg, - 'current_date': current_date, - 'count': count, - 'rebates': rebates, - 'programme': programme, - 'meeting': meeting, - 'minutes': minutes, - 'splrequest': splrequest, - 'sprequest': sprequest, - 'sprequest_past': sprequest_past, - 'menuchangerequest':menuchangerequest, - 'count1': count1, - 'count2': count2, - 'count3': count3, - 'count4': count4, - 'count5': count5, - 'count6': count6, - 'count7': count7, - 'count8': count8, - 'form': form, - 'desig': desig, - 'reg_form':reg_form, - 'reg_request':reg_request, - 'reg_main':mess_optn, - 'reg_record':reg_record, - 'de_reg_request':de_reg_request, - } - return render(request, "messModule/mess.html", context) + # 'vaca': vaca_obj, + # 'info': extrainfo, + # 'feedback': feedback_obj, + # 'feed1': feed, + # 'feed2':'', + # 'student': student, + # 'mess_reg': mess_reg, + # 'current_date': current_date, + # 'count': count, + # 'rebates': rebates, + # 'meeting': meeting, + # 'minutes': minutes, + # 'sprequest': sprequest, + # 'splrequest': splrequest, + # 'sprequest_past': sprequest_past, + # 'menuchangerequest':menuchangerequest, + # 'programme':programme, + # 'count1': count1, + # 'count2': count2, + # 'count3': count3, + # 'count4': count4, + # 'count5': count5, + # 'count6': count6, + # 'count7': count7, + # 'count8': count8, + # 'form': form, + # 'desig': desig, + # 'reg_form':reg_form, + # 'reg_request':reg_request, + # 'reg_main':mess_optn, + # 'reg_record':reg_record, + # 'de_reg_request':de_reg_request, + + # } + # return render(request, "messModule/mess.html", context) + + # if d.designation.name == 'mess_committee_mess2' or d.designation.name == 'mess_convener_mess2': + # newmenu = Menu_change_request.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department','dish').filter(dish__mess_option='mess2').order_by('-app_date') + # meeting = Mess_meeting.objects.all() + # minutes = Mess_minutes.objects.select_related().all() + # feed = Feedback.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(mess='mess2').order_by('-fdate') + # feed2 = Feedback.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(mess='mess1').order_by('-fdate') + # sprequest = Special_request.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(status='1').order_by('-app_date') + # sprequest_past = Special_request.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(status='2').order_by('-app_date') + # menuchangerequest= Menu_change_request.objects.select_related('student_id').filter().order_by('-app_date') + + # # menu_data = Menu.objects.all().order_by() + + # count5=0 + # count6=0 + # count7=0 + # count8=0 + # for f in feed: + # if f.feedback_type == 'Maintenance' : + # count1 += 1 + + # elif f.feedback_type == 'Food' : + # count2 += 1 + + # elif f.feedback_type == 'Cleanliness' : + # count3 += 1 + + # elif f.feedback_type == 'Others' : + # count4 += 1 + + # context = { + # 'menu': menu_data, + # 'reg_menu': y, + # 'messinfo': mess_optn, + # 'newmenu': newmenu, + # 'monthly_bill': monthly_bill, + # 'total_due': amount_due, + # 'vaca': vaca_obj, + # 'info': extrainfo, + # 'feedback': feedback_obj, + # 'feed2': feed, + # 'feed1':'', + # 'student': student, + # # 'data': data, + # 'mess_reg': mess_reg, + # 'current_date': current_date, + # 'count': count, + # 'rebates': rebates, + # 'programme': programme, + # 'meeting': meeting, + # 'minutes': minutes, + # 'splrequest': splrequest, + # 'sprequest': sprequest, + # 'sprequest_past': sprequest_past, + # 'menuchangerequest':menuchangerequest, + # 'count1': count1, + # 'count2': count2, + # 'count3': count3, + # 'count4': count4, + # 'count5': count5, + # 'count6': count6, + # 'count7': count7, + # 'count8': count8, + # 'form': form, + # 'desig': desig, + # 'reg_form':reg_form, + # 'reg_request':reg_request, + # 'reg_main':mess_optn, + # 'reg_record':reg_record, + # 'de_reg_request':de_reg_request, + # } + # return render(request, "messModule/mess.html", context) context = { 'menu': menu_data, - 'reg_menu': y, + # 'reg_menu': y, 'messinfo': mess_optn, 'monthly_bill': monthly_bill, - 'total_due': amount_due, + # 'total_due': amount_due, 'vaca': vaca_obj, 'info': extrainfo, 'feedback': feedback_obj, 'student': student, - 'mess_reg': mess_reg, + # 'mess_reg': mess_reg, 'current_date': current_date, - 'count': count, + # 'count': count, 'rebates': rebates, 'splrequest': splrequest, 'form': form, - 'programme': programme, + # 'programme': programme, 'desig': desig, - 'minutes': minutes, - 'meeting': meeting, + # 'minutes': minutes, + # 'meeting': meeting, 'reg_form':reg_form, + 'update_form':update_form, + 'update_payment_request':update_payment_request, 'reg_main_stud':mess_optn, 'reg_request':reg_request, 'reg_record':reg_record, @@ -363,7 +373,12 @@ def mess(request): elif extrainfo.user_type == 'staff': for d in desig: if(d.designation.name == 'mess_manager'): - current_bill = MessBillBase.objects.latest('timestamp') + try: + current_bill = MessBillBase.objects.latest('timestamp') + except: + new_entry = MessBillBase(bill_amount=150) + new_entry.save() + current_bill = MessBillBase.objects.latest('timestamp') newmenu = Menu_change_request.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department','dish').all().order_by('-app_date') vaca_all = Vacation_food.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').all().order_by('-app_date') members_mess = HoldsDesignation.objects.select_related().filter(Q(designation__name__contains='mess_convener') @@ -371,8 +386,8 @@ def mess(request): y = Menu.objects.all() leave = Rebate.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(status='1').order_by('-app_date') leave_past = Rebate.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(status='2').order_by('-app_date') - meeting = Mess_meeting.objects.all() - minutes = Mess_minutes.objects.all() + # meeting = Mess_meeting.objects.all() + # minutes = Mess_minutes.objects.all() feed1 = Feedback.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(mess='mess1').order_by('-fdate') feed2 = Feedback.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(mess='mess2').order_by('-fdate') @@ -406,6 +421,7 @@ def mess(request): sprequest_past = Special_request.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(status='2').order_by('-app_date') reg_request = Registration_Request.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').all().filter(status='pending') + update_pay_request=Update_Payment.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').all().filter(status='pending') de_reg_request = Deregistration_Request.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').all().filter(status='pending') reg_main = Reg_main.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').filter(current_mess_status='Registered') reg_record = Reg_records.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').all() @@ -423,10 +439,10 @@ def mess(request): 'leave': leave, 'leave_past': leave_past, 'current_date': current_date, - 'mess_reg': mess_reg, + # 'mess_reg': mess_reg, 'desig': desig, - 'meeting': meeting, - 'minutes': minutes, + # 'meeting': meeting, + # 'minutes': minutes, 'sprequest': sprequest, 'sprequest_past': sprequest_past, 'count1': count1, @@ -436,7 +452,8 @@ def mess(request): 'reg_request':reg_request,'reg_record':reg_record,'reg_main':reg_main, 'de_reg_request':de_reg_request, 'bill': bills, - 'reg_form':reg_form + 'reg_form':reg_form, + 'update_pay_request':update_pay_request } return render(request, "messModule/mess.html", context) @@ -489,6 +506,7 @@ def mess(request): } return render(request, 'messModule/mess.html', context) + @login_required @transaction.atomic def mess_info(request): @@ -941,25 +959,13 @@ def post(self, request, *args, **kwargs): extra_info = ExtraInfo.objects.select_related().get(user=user) y = Menu.objects.all() - if extra_info.user_type=='student': - student = Student.objects.select_related('id','id__user','id__department').get(id=extra_info) - mess_info = Messinfo.objects.select_related('student_id','student_id__id','student_id__id__user','student_id__id__department').get(student_id=student) - mess_option = mess_info.mess_option - context = { - 'menu': y, - 'mess_option': mess_option - } - if mess_option=='mess2': - return render_to_pdf('messModule/menudownloadable2.html', context) - else: - return render_to_pdf('messModule/menudownloadable1.html', context) - else: - context = { - 'menu': y, - 'mess_option': 'mess2' - } - return render_to_pdf('messModule/menudownloadable2.html', context) - # return HttpResponse(pdf, content_type='application/pdf') + context = { + 'menu': y, + 'mess_option': 'mess2', + 'date':str(today_g.date()) + } + return render_to_pdf('messModule/menudownloadable2.html', context) + # return HttpResponse(pdf, content_type='application/pdf') class MenuPDF1(View): @@ -979,7 +985,8 @@ def post(self, request, *args, **kwargs): y = Menu.objects.all() context = { 'menu': y, - 'mess_option': 'mess1' + 'mess_option': 'mess1', + 'date':str(today_g.date()) } return render_to_pdf('messModule/menudownloadable1.html', context) @@ -1002,6 +1009,7 @@ def post(self, request, *args, **kwargs): return HttpResponseRedirect('/mess') + def menu_change_request(request): """ This function is to request a change in menu @@ -1553,6 +1561,21 @@ def respond_to_reg(request): data = handle_dreg_response(request) return JsonResponse(data) +@csrf_exempt +@login_required +def respond_to_update_payment(request): + data = { + 'status': 1 + } + user = request.user + designation = HoldsDesignation.objects.select_related().filter(user=user) + for d in designation: + if d.designation.name == 'mess_manager': + data = handle_update_payment_response(request) + + return JsonResponse(data) + + def reg_request(request): @@ -1583,6 +1606,18 @@ def reg_request(request): return HttpResponseRedirect("/mess") +def update_payment(request): + user = request.user + extra_info = ExtraInfo.objects.select_related().get(user=user) + student = Student.objects.select_related('id','id__user','id__department').get(id=extra_info) + if request.method == 'POST': + form = UpdatePaymentRequest(request.POST, request.FILES) + + if form.is_valid(): + temp=form.save(commit=False) + temp.student_id=student + temp.save() + return HttpResponseRedirect("/mess") @csrf_exempt def update_bill_excel(request): diff --git a/FusionIIIT/applications/complaint_system/migrations/0001_initial.py b/FusionIIIT/applications/complaint_system/migrations/0001_initial.py index 44df90d3c..e40ba5606 100644 --- a/FusionIIIT/applications/complaint_system/migrations/0001_initial.py +++ b/FusionIIIT/applications/complaint_system/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.1.5 on 2024-04-15 23:58 +# Generated by Django 3.1.5 on 2024-07-16 15:44 from django.db import migrations, models import django.db.models.deletion diff --git a/FusionIIIT/applications/counselling_cell/migrations/0001_initial.py b/FusionIIIT/applications/counselling_cell/migrations/0001_initial.py index f0214910c..7cd42f1b2 100644 --- a/FusionIIIT/applications/counselling_cell/migrations/0001_initial.py +++ b/FusionIIIT/applications/counselling_cell/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.1.5 on 2024-04-15 23:58 +# Generated by Django 3.1.5 on 2024-07-16 15:44 import datetime from django.db import migrations, models @@ -10,8 +10,8 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('globals', '0001_initial'), ('academic_information', '0001_initial'), + ('globals', '0001_initial'), ] operations = [ diff --git a/FusionIIIT/applications/department/api/permissions.py b/FusionIIIT/applications/department/api/permissions.py new file mode 100644 index 000000000..2b870575b --- /dev/null +++ b/FusionIIIT/applications/department/api/permissions.py @@ -0,0 +1,18 @@ +from rest_framework import permissions +from django.shortcuts import get_object_or_404 +from applications.academic_information.models import ExtraInfo +from applications.globals.models import User + + +class IsFacultyStaffOrReadOnly(permissions.BasePermission): + """ + Custom permission to only allow faculty and staff to edit it. + """ + + def has_permission(self, request, view): + # Read permissions are allowed to any request, + # so we'll always allow GET, HEAD or OPTIONS requests. + if request.method in permissions.SAFE_METHODS: + return True + #only faculty and staff are able to make post request + return not request.user.holds_designations.filter(designation__name='student').exists() diff --git a/FusionIIIT/applications/department/api/serializers.py b/FusionIIIT/applications/department/api/serializers.py new file mode 100644 index 000000000..aa005ad31 --- /dev/null +++ b/FusionIIIT/applications/department/api/serializers.py @@ -0,0 +1,62 @@ +from rest_framework import serializers +from applications.department.models import Announcements +from applications.academic_information.models import Spi, Student +from applications.globals.models import (Designation, ExtraInfo, + HoldsDesignation,Faculty) +from applications.eis.models import (faculty_about, emp_research_projects) + + +class AnnouncementSerializer(serializers.ModelSerializer): + class Meta: + model = Announcements + fields = ('__all__') + + extra_kwargs = { + 'maker_id': {'required': False} + } + + def create(self, validated_data): + user = self.context['request'].user + user_info = ExtraInfo.objects.all().select_related('user','department').filter(user=user).first() + validated_data['maker_id'] = user_info + return Announcements.objects.create(**validated_data) + +class ExtraInfoSerializer(serializers.ModelSerializer): + class Meta: + model = ExtraInfo + fields = ('__all__') + +class SpiSerializer(serializers.ModelSerializer): + class Meta: + model = Spi + fields = ('__all__') + +class StudentSerializer(serializers.ModelSerializer): + class Meta: + model = Student + fields = ('__all__') + +class DesignationSerializer(serializers.ModelSerializer): + class Meta: + model = Designation + fields = ('__all__') + +class HoldsDesignationSerializer(serializers.ModelSerializer): + class Meta: + model = HoldsDesignation + fields = ('__all__') + +class FacultySerializer(serializers.ModelSerializer): + class Meta: + model = Faculty + fields = ('__all__') + +class faculty_aboutSerializer(serializers.ModelSerializer): + class Meta: + model = faculty_about + fields = ('__all__') + +class emp_research_projectsSerializer(serializers.ModelSerializer): + class Meta: + model = emp_research_projects + fields = ('__all__') \ No newline at end of file diff --git a/FusionIIIT/applications/department/api/urls.py b/FusionIIIT/applications/department/api/urls.py new file mode 100644 index 000000000..9e0dae890 --- /dev/null +++ b/FusionIIIT/applications/department/api/urls.py @@ -0,0 +1,12 @@ +from django.conf.urls import url + +from . import views + +urlpatterns = [ + url(r'announcements/$', views.ListCreateAnnouncementView.as_view(),name='announcements'), + url(r'dep-main/$', views.DepMainAPIView.as_view(), name='depmain'), + url(r'fac-view/$', views.FacAPIView.as_view(), name='facapi'), + url(r'staff-view/$',views.StaffAPIView.as_view(),name='staffapi'), + url(r'all-students/(?P[0-9]+)/$', views.AllStudentsAPIView.as_view() ,name='all_students') + +] diff --git a/FusionIIIT/applications/department/api/views.py b/FusionIIIT/applications/department/api/views.py new file mode 100644 index 000000000..686f0268e --- /dev/null +++ b/FusionIIIT/applications/department/api/views.py @@ -0,0 +1,216 @@ +from rest_framework import generics +from rest_framework.views import APIView +from applications.department.models import Announcements +from applications.academic_information.models import Spi, Student +from applications.globals.models import (Designation, ExtraInfo, + HoldsDesignation,Faculty) +from applications.eis.models import (faculty_about, emp_research_projects) +from .serializers import (AnnouncementSerializer,ExtraInfoSerializer,SpiSerializer,StudentSerializer,DesignationSerializer + ,HoldsDesignationSerializer,FacultySerializer,faculty_aboutSerializer,emp_research_projectsSerializer) +from rest_framework.permissions import IsAuthenticated +from .permissions import IsFacultyStaffOrReadOnly +from django.http import JsonResponse +from django.shortcuts import get_object_or_404, render, redirect +from django.contrib.auth.models import User +from rest_framework.response import Response +from rest_framework import status +from django.contrib.auth.decorators import login_required +from django.urls import reverse +from datetime import date +from notification.views import department_notif + + +class ListCreateAnnouncementView(generics.ListCreateAPIView): + queryset = Announcements.objects.all() + serializer_class = AnnouncementSerializer + permission_classes = (IsAuthenticated, IsFacultyStaffOrReadOnly) + + +class DepMainAPIView(APIView): + def get(self, request): + user = request.user + usrnm = get_object_or_404(User, username=user.username) + user_info = ExtraInfo.objects.all().select_related('user', 'department').filter(user=usrnm).first() + ann_maker_id = user_info.id + user_info = ExtraInfo.objects.all().select_related('user', 'department').get(id=ann_maker_id) + + fac_view = user.holds_designations.filter(designation__name='faculty').exists() + student = user.holds_designations.filter(designation__name='student').exists() + staff = user.holds_designations.filter(designation__name='staff').exists() + + context = browse_announcements() + context_f = faculty() + user_designation = "" + + if fac_view: + user_designation = "faculty" + elif student: + user_designation = "student" + else: + user_designation = "staff" + + # serailizing the data + # announcements_serailizer = AnnouncementSerializer(context, many=True) + + + response_data = { + "user_designation": user_designation, + "announcements": context, + "fac_list": context_f + } + + + return Response(data = response_data, status=status.HTTP_200_OK) + # return Response(data = response_data, status=status.HTTP_200_OK) + +class FacAPIView(APIView): + def get(self,request): + usrnm = get_object_or_404(User, username=request.user.username) + user_info = ExtraInfo.objects.all().select_related('user','department').filter(user=usrnm).first() + + + context = browse_announcements() + + + # Serialize the data into JSON formats + data = { + "user_designation": user_info.user_type, + "announcements": list(context.values()), # Assuming 'context' is a dictionary + } + + return Response(data) + +class StaffAPIView(APIView): + def get(self,request): + usrnm = get_object_or_404(User, username=request.user.username) + user_info = ExtraInfo.objects.all().select_related('user','department').filter(user=usrnm).first() + + + context = browse_announcements() + + + # Serialize the data into JSON formats + data = { + "user_designation": user_info.user_type, + "announcements": list(context.values()), # Assuming 'context' is a dictionary + } + + return Response(data) + +class AllStudentsAPIView(APIView): + def get(self,request,bid): + print(self.request.query_params) + # bid = self.request.query_params.get() + + # Decode bid into filter criteria + filter_criteria = decode_bid(bid) + if not filter_criteria: + return Response({'detail': 'Invalid bid value'}, status=status.HTTP_400_BAD_REQUEST) + + # Apply additional department filter since it seems fixed + filter_criteria['id__department__name'] = 'CSE' + + student_list1 = Student.objects.order_by('id').filter( + id__user_type='student', + **filter_criteria + ).select_related('id') + + # paginator = Paginator(student_list1, 25, orphans=5) + # page_number = request.GET.get('page') + # student_list = paginator.get_page(page_number) + + # Serialize the queryset + serializer = StudentSerializer(student_list1, many=True) + serialized_data = serializer.data + + # Create a response dictionary + response_data = {'student_list': serialized_data} + + return Response(response_data) + + +def decode_bid(bid): + """Decodes the bid structure into programme, batch, and department (if applicable).""" + try: + department_code = bid[0] + programme = { + '1': 'B.Tech', + '2': 'M.Tech', + '3': 'PhD', # Assuming there are more departments + }[department_code] + batch = 2021 - len(bid) + 1 + return {'programme': programme, 'batch': batch} + except (IndexError, KeyError): + return None # Handle malformed bid values + +def browse_announcements(): + """ + This function is used to browse Announcements Department-Wise + made by different faculties and admin. + + @variables: + cse_ann - Stores CSE Department Announcements + ece_ann - Stores ECE Department Announcements + me_ann - Stores ME Department Announcements + sm_ann - Stores SM Department Announcements + all_ann - Stores Announcements intended for all Departments + context - Dictionary for storing all above data + + """ + cse_ann = Announcements.objects.filter(department="CSE") + ece_ann = Announcements.objects.filter(department="ECE") + me_ann = Announcements.objects.filter(department="ME") + sm_ann = Announcements.objects.filter(department="SM") + all_ann = Announcements.objects.filter(department="ALL") + + # serailizing the data + cse_ann_serialized = AnnouncementSerializer(cse_ann, many=True) + ece_ann_serialized = AnnouncementSerializer(ece_ann, many=True) + me_ann_serialized = AnnouncementSerializer(me_ann, many=True) + sm_ann_serialized = AnnouncementSerializer(sm_ann, many=True) + all_ann_serialized = AnnouncementSerializer(all_ann, many=True) + + context = { + "cse" : cse_ann_serialized.data, + "ece" : ece_ann_serialized.data, + "me" : me_ann_serialized.data, + "sm" : sm_ann_serialized.data, + "all" : all_ann_serialized.data + } + + return context + +def faculty(): + """ + This function is used to Return data of Faculties Department-Wise. + + @variables: + cse_f - Stores data of faculties from CSE Department + ece_f - Stores data of faculties from ECE Department + me_f - Stores data of faculties from ME Department + sm_f - Stores data of faculties from ME Department + context_f - Stores all above variables in Dictionary + + """ + cse_f=ExtraInfo.objects.filter(department__name='CSE',user_type='faculty') + ece_f=ExtraInfo.objects.filter(department__name='ECE',user_type='faculty') + me_f=ExtraInfo.objects.filter(department__name='ME',user_type='faculty') + sm_f=ExtraInfo.objects.filter(department__name='SM',user_type='faculty') + staff=ExtraInfo.objects.filter(user_type='staff') + + # serailizing the data + cse_f = ExtraInfoSerializer(cse_f, many=True) + ece_f = ExtraInfoSerializer(ece_f, many=True) + me_f = ExtraInfoSerializer(me_f, many=True) + sm_f = ExtraInfoSerializer(sm_f, many=True) + staff = ExtraInfoSerializer(staff, many=True) + + + context_f = { + "cse_f" : cse_f.data, + "ece_f" : ece_f.data, + "me_f" : me_f.data, + "sm_f" : sm_f.data, + "staff" : staff.data, + } + return context_f \ No newline at end of file diff --git a/FusionIIIT/applications/department/migrations/0001_initial.py b/FusionIIIT/applications/department/migrations/0001_initial.py index cb016ad8b..21c891a8e 100644 --- a/FusionIIIT/applications/department/migrations/0001_initial.py +++ b/FusionIIIT/applications/department/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.1.5 on 2024-04-15 23:58 +# Generated by Django 3.1.5 on 2024-07-16 15:44 import datetime from django.db import migrations, models @@ -28,11 +28,22 @@ class Migration(migrations.Migration): ('request_maker', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='globals.extrainfo')), ], ), + migrations.CreateModel( + name='Information', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('phone_number', models.BigIntegerField()), + ('email', models.CharField(max_length=200)), + ('facilites', models.TextField()), + ('labs', models.TextField()), + ('department', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='globals.departmentinfo')), + ], + ), migrations.CreateModel( name='Announcements', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('ann_date', models.DateTimeField(default='04-04-2021')), + ('ann_date', models.DateTimeField(auto_now_add=True)), ('message', models.CharField(max_length=200)), ('batch', models.CharField(default='Year-1', max_length=40)), ('department', models.CharField(default='ALL', max_length=40)), diff --git a/FusionIIIT/applications/department/models.py b/FusionIIIT/applications/department/models.py index 8f7dba039..caebb4d50 100644 --- a/FusionIIIT/applications/department/models.py +++ b/FusionIIIT/applications/department/models.py @@ -3,8 +3,9 @@ from datetime import date # Create your models here. -from applications.globals.models import ExtraInfo +from applications.globals.models import ExtraInfo , DepartmentInfo + class SpecialRequest(models.Model): request_maker = models.ForeignKey(ExtraInfo, on_delete=models.CASCADE) request_date = models.DateTimeField(default=date.today) @@ -21,7 +22,7 @@ def __str__(self): class Announcements(models.Model): maker_id = models.ForeignKey(ExtraInfo, on_delete=models.CASCADE) - ann_date = models.DateTimeField(default="04-04-2021") + ann_date = models.DateTimeField(auto_now_add=True) message = models.CharField(max_length=200) batch = models.CharField(max_length=40,default="Year-1") department = models.CharField(max_length=40,default="ALL") @@ -29,3 +30,14 @@ class Announcements(models.Model): upload_announcement = models.FileField(upload_to='department/upload_announcement', null=True, default=" ") def __str__(self): return str(self.maker_id.user.username) + +class Information(models.Model): + department = models.OneToOneField( + DepartmentInfo, + on_delete=models.CASCADE, + ) + + phone_number = models.BigIntegerField() + email = models.CharField(max_length=200) + facilites = models.TextField() + labs = models.TextField() diff --git a/FusionIIIT/applications/department/static/department/js/function.js b/FusionIIIT/applications/department/static/department/js/function.js index 732b50473..0a64c2c95 100644 --- a/FusionIIIT/applications/department/static/department/js/function.js +++ b/FusionIIIT/applications/department/static/department/js/function.js @@ -5,46 +5,79 @@ $(document).ready(function(){ function announce(event) - { - var message= $('input[name="announcement"]').val(); - var batch = $('input[name="batch"]').val(); - var programme = $('input[name="programme"]').val(); - var department = $('input[name="department"]').val(); - var upload_announcement =$('input[name="upload_announcement"]').val(); - if(message=="" || batch=="" || programme =="" || department=="") - { - alert("Please fill all the details!"); - return; - } - else - { - event.preventDefault(); - $.ajax({ - type : 'POST', - url : '.', - data : { - 'message' : message, - 'batch' : batch, - 'programme' : programme, - 'upload_announcement' : upload_announcement, - 'department' : department, - }, - success : function (data){ + { + var message= $('input[name="announcement"]').val(); + var batch = $('input[name="batch"]').val(); + var programme = $('input[name="programme"]').val(); + var department = $('input[name="department"]').val(); + var upload_announcement =$('input[name="upload_announcement"]').val(); + if(message=="" || batch=="" || programme =="" || department=="") + { + alert("Please fill all the details!"); + return; + } + else + { + event.preventDefault(); + $.ajax({ + type : 'POST', + url : '.', + data : { + 'message' : message, + 'batch' : batch, + 'programme' : programme, + 'upload_announcement' : upload_announcement, + 'department' : department, + }, + success : function (data){ - alert("Announcement successfully made!!"); - setTimeout(function() { - window.location.reload(); - }, 1500); + alert("Announcement successfully made!!"); + setTimeout(function() { + window.location.reload(); + }, 1500); - - }, - error : function (data,err){ - alert('Announcement successfully made ... '); + + }, + error : function (data,err){ + alert('Announcement successfully made ... '); - } - }); - } - }; + } + }); + } +}; + +function updateDepartment(event) { + var email = $('input[name="email"]').val(); + var contactNumber = $('input[name="contact_number"]').val(); + var facilities = $('textarea[name="facilities"]').val(); + var labs = $('textarea[name="labs"]').val(); + + if (email === "" || contactNumber === "" || facilities === "" || labs === "" || departmentId === "") { + alert("Please fill all the details!"); + return; + } else { + event.preventDefault(); + $.ajax({ + type: 'POST', + url: '.', // Specify the URL to your view for updating department information + data: { + 'email': email, + 'contact_number': contactNumber, + 'facilities': facilities, + 'labs': labs, + }, + success: function(data) { + alert("Department information updated successfully!"); + setTimeout(function() { + window.location.reload(); + }, 1500); + }, + error: function(data, err) { + alert('Failed to update department information.'); + } + }); + } +} function request(event) { diff --git a/FusionIIIT/applications/department/urls.py b/FusionIIIT/applications/department/urls.py index b7338374a..094e1e90d 100644 --- a/FusionIIIT/applications/department/urls.py +++ b/FusionIIIT/applications/department/urls.py @@ -1,4 +1,5 @@ from django.conf.urls import url +from django.urls import include from . import views @@ -9,7 +10,11 @@ url(r'^$', views.dep_main, name='dep'), url(r'^facView/$', views.faculty_view, name='faculty_view'), url(r'^staffView/$', views.staff_view, name='staff_view'), - url(r'^All_Students/(?P[0-9]+)/$', views.all_students,name='all_students'), + url(r'All_Students/(?P[0-9]+)/$', views.all_students,name='all_students'), + url(r'alumni/$', views.alumni, name='alumni'), url(r'^approved/$', views.approved, name='approved'), - url(r'^deny/$', views.deny, name='deny') -] + url(r'^deny/$', views.deny, name='deny'), + + url(r'^api/', include("applications.department.api.urls")) + +] \ No newline at end of file diff --git a/FusionIIIT/applications/department/views.py b/FusionIIIT/applications/department/views.py index f138c77db..6e5a0d936 100644 --- a/FusionIIIT/applications/department/views.py +++ b/FusionIIIT/applications/department/views.py @@ -5,7 +5,7 @@ from django.contrib import messages from django.contrib.auth.decorators import login_required -from django.http import HttpResponse, HttpResponseRedirect +from django.http import HttpResponse, HttpResponseRedirect, HttpResponseBadRequest # Create your views here. from django.db.models import Q from django.shortcuts import get_object_or_404, render, redirect @@ -13,16 +13,30 @@ from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from applications.academic_information.models import Spi, Student from applications.globals.models import (Designation, ExtraInfo, - HoldsDesignation,Faculty) + HoldsDesignation,Faculty,DepartmentInfo) from applications.eis.models import (faculty_about, emp_research_projects) - +from .models import Information from notification.views import department_notif -from .models import SpecialRequest, Announcements +from .models import SpecialRequest, Announcements , Information from jsonschema import validate from jsonschema.exceptions import ValidationError -# Create your views here. +def department_information(request): + + cse_info = Information.objects.filter(department_id=51).first() + ece_info = Information.objects.filter(department_id=30).first() + me_info = Information.objects.filter(department_id=37).first() + sm_info = Information.objects.filter(department_id=28).first() + department_context = { + "cse_info" : cse_info, + "ece_info" : ece_info, + "me_info" : me_info, + "sm_info" : sm_info + } + # print(department_context) + # print(me_info.phone_number,me_info.email,me_info.department_id) + return department_context def browse_announcements(): """ @@ -51,7 +65,7 @@ def browse_announcements(): "sm" : sm_ann, "all" : all_ann } - + # print(context) return context def get_make_request(user_id): @@ -97,7 +111,8 @@ def dep_main(request): user_info = ExtraInfo.objects.all().select_related('user','department').filter(user=usrnm).first() ann_maker_id = user_info.id user_info = ExtraInfo.objects.all().select_related('user','department').get(id=ann_maker_id) - + user_departmentid = ExtraInfo.objects.all().select_related('user','department').get(id=ann_maker_id).department_id + requests_made = get_make_request(user_info) fac_view = request.user.holds_designations.filter(designation__name='faculty').exists() @@ -107,7 +122,10 @@ def dep_main(request): context = browse_announcements() context_f = faculty() user_designation = "" - + + + department_context = department_information(request) + if fac_view: user_designation = "faculty" elif student: @@ -131,13 +149,26 @@ def dep_main(request): ) if user_designation == "student": - return render(request,"department/index.html", {"announcements":context, - "fac_list" : context_f, - "requests_made" : requests_made - }) - # elif(str(user.extrainfo.user_type)=="faculty"): + department_templates = { + 51: 'department/cse_index.html', + 30: 'department/ece_index.html', + 37: 'department/me_index.html', + 53: 'department/sm_index.html' + } + default_template = 'department/cse_index.html' + template_name = department_templates.get(user_departmentid, default_template) + + return render(request, template_name, { + "announcements": context, + "fac_list": context_f, + "requests_made": requests_made, + "department_info": department_context + + }) + elif user_designation=="faculty": return HttpResponseRedirect("facView") + elif user_designation=="staff": return HttpResponseRedirect("staffView") @@ -155,11 +186,15 @@ def faculty_view(request): department, ann_date, user_info - Gets and store data from FORM used for Announcements. """ + context_f = faculty() usrnm = get_object_or_404(User, username=request.user.username) user_info = ExtraInfo.objects.all().select_related('user','department').filter(user=usrnm).first() num = 1 ann_maker_id = user_info.id requests_received = get_to_request(usrnm) + user_departmentid = ExtraInfo.objects.all().select_related('user','department').get(id=ann_maker_id).department_id + department_context = department_information(request) + if request.method == 'POST': batch = request.POST.get('batch', '') programme = request.POST.get('programme', '') @@ -178,13 +213,29 @@ def faculty_view(request): upload_announcement=upload_announcement, department = department, ann_date=ann_date) + department_notif(usrnm, recipients , message) context = browse_announcements() - return render(request, 'department/dep_request.html', {"user_designation":user_info.user_type, - "announcements":context, - "request_to":requests_received - }) + + department_templates = { + 51: 'department/csedep_request.html', + 30: 'department/ecedep_request.html', + 37: 'department/medep_request.html', + 53: 'department/smdep_request.html' + } + default_template = 'department/dep_request.html' + + template_name = department_templates.get(user_departmentid, default_template) + + return render(request, template_name, { + "user_designation": user_info.user_type, + "announcements": context, + "request_to": requests_received, + "fac_list": context_f, + "department_info": department_context + }) + def staff_view(request): """ @@ -200,39 +251,143 @@ def staff_view(request): department, ann_date, user_info - Gets and store data from FORM used for Announcements for Students. """ + context_f = faculty() usrnm = get_object_or_404(User, username=request.user.username) user_info = ExtraInfo.objects.all().select_related('user','department').filter(user=usrnm).first() num = 1 ann_maker_id = user_info.id + user_departmentid = ExtraInfo.objects.all().select_related('user','department').get(id=ann_maker_id).department_id + + department_context = department_information(request) + requests_received = get_to_request(usrnm) if request.method == 'POST': - batch = request.POST.get('batch', '') - programme = request.POST.get('programme', '') - message = request.POST.get('announcement', '') - upload_announcement = request.FILES.get('upload_announcement') - department = request.POST.get('department') - ann_date = date.today() - user_info = ExtraInfo.objects.all().select_related('user','department').get(id=ann_maker_id) - getstudents = ExtraInfo.objects.select_related('user') - recipients = User.objects.filter(extrainfo__in=getstudents) - - obj1, created = Announcements.objects.get_or_create(maker_id=user_info, - batch=batch, - programme=programme, - message=message, - upload_announcement=upload_announcement, - department = department, - ann_date=ann_date) - department_notif(usrnm, recipients , message) + form_type = request.POST.get('form_type', '') + if form_type == 'form1' : + + batch = request.POST.get('batch', '') + programme = request.POST.get('programme', '') + message = request.POST.get('announcement', '') + upload_announcement = request.FILES.get('upload_announcement') + department = request.POST.get('department') + ann_date = date.today() + user_info = ExtraInfo.objects.all().select_related('user','department').get(id=ann_maker_id) + getstudents = ExtraInfo.objects.select_related('user') + recipients = User.objects.filter(extrainfo__in=getstudents) + + obj1, created = Announcements.objects.get_or_create(maker_id=user_info, + batch=batch, + programme=programme, + message=message, + upload_announcement=upload_announcement, + department = department, + ann_date=ann_date) + department_notif(usrnm, recipients , message) + + elif form_type == 'form2' : + + email = request.POST.get('email', '') + phone_number = request.POST.get('contact_number', '') + facilites = request.POST.get('facilities', '') + labs = request.POST.get('labs', '') + department_id = user_departmentid + + # Check if a row with the specified department_id already exists + try: + department_info = Information.objects.get(department_id=department_id) + # If row exists, update the values + department_info.email = email + department_info.phone_number_number = phone_number + department_info.facilites = facilites + department_info.labs = labs + department_info.save() + except Information.DoesNotExist: + # If row does not exist, create a new one + department_info = Information.objects.create( + department_id=department_id, + email=email, + phone_number=phone_number, + facilites=facilites, + labs=labs + ) + context = browse_announcements() - return render(request, 'department/dep_request.html', {"user_designation":user_info.user_type, - "announcements":context, - "request_to":requests_received - }) + + + department_templates = { + 51: 'department/csedep_request.html', + 30: 'department/ecedep_request.html', + 37: 'department/medep_request.html', + 53: 'department/smdep_request.html', + + } + default_template = 'department/dep_request.html' + + desig=request.session.get('currentDesignationSelected', 'default_value') + if desig=='deptadmin_cse': + template_name = 'department/admin_cse.html' + + return render(request, template_name, { + "user_designation": user_info.user_type, + "announcements": context, + "request_to": requests_received, + "fac_list": context_f, + "department_info": department_context + }) + elif desig=='deptadmin_ece': + template_name = 'department/admin_ece.html' + return render(request, template_name, { + "user_designation": user_info.user_type, + "announcements": context, + "request_to": requests_received, + "fac_list": context_f, + "department_info": department_context + }) + elif desig=='deptadmin_me': + template_name = 'department/admin_me.html' + return render(request, template_name, { + "user_designation": user_info.user_type, + "announcements": context, + "request_to": requests_received, + "fac_list": context_f, + "department_info": department_context + }) + elif desig=='deptadmin_sm': + template_name = 'department/admin_sm.html' + return render(request, template_name, { + "user_designation": user_info.user_type, + "announcements": context, + "request_to": requests_received, + "fac_list": context_f, + "department_info": department_context + }) + + # if desig == 'deptadmin_cse': + # return render(request, 'admin_cse.html') + # elif desig == 'deptadmin_ece': + # return render(request, 'admin_ece.html') + # elif desig == 'deptadmin_sm': + # return render(request, 'admin_sm.html') + # elif desig == 'deptadmin_me': + # return render(request, 'admin_me.html') + # else: + # return render(request, 'default.html') + + template_name = department_templates.get(user_departmentid, default_template) + return render(request, template_name, { + "user_designation": user_info.user_type, + "announcements": context, + "request_to": requests_received, + "fac_list": context_f, + "department_info": department_context + }) + + @login_required(login_url='/accounts/login') -def all_students(request,bid): + +def all_students(request, bid): """ This function is used to Return data of Faculties Department-Wise. @@ -245,284 +400,62 @@ def all_students(request,bid): student_list - Stores data pagewise """ - if int(bid)==1: - student_list1=Student.objects.order_by('id').filter(programme='B.Tech', - batch=2021, - id__user_type='student', - id__department__name='CSE').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==11: - student_list1=Student.objects.order_by('id').filter(programme='B.Tech', - batch=2020, - id__user_type='student', - id__department__name='CSE').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==111: - student_list1=Student.objects.order_by('id').filter(programme='B.Tech', - batch=2019, - id__user_type='student', - id__department__name='CSE').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==1111: - student_list1=Student.objects.order_by('id').filter(programme='B.Tech', - batch=2018, - id__user_type='student', - id__department__name='CSE').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==11111: - student_list1=Student.objects.order_by('id').filter(programme='M.Tech', - batch=2021, - id__user_type='student', - id__department__name='CSE').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==111111: - student_list1=Student.objects.order_by('id').filter(programme='M.Tech', - batch=2020, - id__user_type='student', - id__department__name='CSE').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==1111111: - student_list1=Student.objects.order_by('id').filter(programme='PhD', - id__user_type='student', - id__department__name='CSE').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==2: - student_list1=Student.objects.order_by('id').filter(programme='B.Tech', - batch=2021, - id__user_type='student', - id__department__name='ECE').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==21: - student_list1=Student.objects.order_by('id').filter(programme='B.Tech', - batch=2020, - id__user_type='student', - id__department__name='ECE').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==211: - student_list1=Student.objects.order_by('id').filter(programme='B.Tech', - batch=2019, - id__user_type='student', - id__department__name='ECE').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==2111: - student_list1=Student.objects.order_by('id').filter(programme='B.Tech', - batch=2018, - id__user_type='student', - id__department__name='ECE').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==21111: - student_list1=Student.objects.order_by('id').filter(programme='M.Tech', - batch=2021, - id__user_type='student', - id__department__name='ECE').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==211111: - student_list1=Student.objects.order_by('id').filter(programme='M.Tech', - batch=2020, - id__user_type='student', - id__department__name='ECE').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==2111111: - student_list1=Student.objects.order_by('id').filter(programme='PhD', - id__user_type='student', - id__department__name='ECE').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==3: - student_list1=Student.objects.order_by('id').filter(programme='B.Tech', - batch=2021, - id__user_type='student', - id__department__name='ME').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==31: - student_list1=Student.objects.order_by('id').filter(programme='B.Tech', - batch=2020, - id__user_type='student', - id__department__name='ME').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==311: - student_list1=Student.objects.order_by('id').filter(programme='B.Tech', - batch=2019, - id__user_type='student', - id__department__name='ME').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==3111: - student_list1=Student.objects.order_by('id').filter(programme='B.Tech', - batch=2018, - id__user_type='student', - id__department__name='ME').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==31111: - student_list1=Student.objects.order_by('id').filter(programme='M.Tech', - batch=2021, - id__user_type='student', - id__department__name='ME').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==311111: - student_list1=Student.objects.order_by('id').filter(programme='M.Tech', - batch=2020, - id__user_type='student', - id__department__name='ME').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==3111111: - student_list1=Student.objects.order_by('id').filter(programme='PhD', - id__user_type='student', - id__department__name='ME').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==4: - student_list1=Student.objects.order_by('id').filter(programme='B.Tech', - batch=2021, - id__user_type='student', - id__department__name='SM').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==41: - student_list1=Student.objects.order_by('id').filter(programme='B.Tech', - batch=2020, - id__user_type='student', - id__department__name='SM').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==411: - student_list1=Student.objects.order_by('id').filter(programme='B.Tech', - batch=2019, - id__user_type='student', - id__department__name='SM').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==4111: - student_list1=Student.objects.order_by('id').filter(programme='B.Tech', - batch=2018, - id__user_type='student', - id__department__name='SM').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==41111: - student_list1=Student.objects.order_by('id').filter(programme='M.Tech', - batch=2021, - id__user_type='student', - id__department__name='SM').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==411111: - student_list1=Student.objects.order_by('id').filter(programme='M.Tech', - batch=2020, - id__user_type='student', - id__department__name='SM').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - elif int(bid)==4111111: - student_list1=Student.objects.order_by('id').filter(programme='PhD', - id__user_type='student', - id__department__name='SM').select_related('id') - paginator=Paginator(student_list1,25,orphans=5) - page_number=request.GET.get('page') - student_list=paginator.get_page(page_number) - id_dict={'student_list':student_list,} - return render(request, 'department/AllStudents.html',context=id_dict) - + def decode_bid(bid): + """Decodes the bid structure into programme, batch, and department (if applicable).""" + + try: + department_code = bid[0] + programme = { + '1': 'B.Tech', + '2': 'M.Tech', + '3': 'PhD', + + }[department_code] + batch = 2021 - len(bid) + 1 + return {'programme': programme, 'batch': batch} + except (IndexError, KeyError): + return None # Handle malformed bid values + # Get sort parameter from the request + sort_by = request.GET.get('sort_by', None) # No default sort + last_sort = request.session.get('last_sort', None) + + # Decode bid into filter criteria + filter_criteria = decode_bid(bid) + if not filter_criteria: + return HttpResponseBadRequest("Invalid bid value") + + # Apply additional department filter since it seems fixed + filter_criteria['id__department__name'] = 'CSE' + + # Apply sort parameter to the queryset + if sort_by: + if last_sort == sort_by: + sort_by = '-' + sort_by # Reverse the order + try: + student_list1 = Student.objects.order_by(sort_by).filter( + id__user_type='student', + **filter_criteria + ).select_related('id') + except: + # If the sort field doesn't exist or isn't sortable, ignore the sort parameter + student_list1 = Student.objects.filter( + id__user_type='student', + **filter_criteria + ).select_related('id') + request.session['last_sort'] = sort_by # Save the sort parameter for the next request + else: + student_list1 = Student.objects.filter( + id__user_type='student', + **filter_criteria + ).select_related('id') + + paginator = Paginator(student_list1, 25, orphans=5) + page_number = request.GET.get('page') + student_list = paginator.get_page(page_number) + id_dict = {'student_list': student_list} + return render(request, 'department/AllStudents.html', context=id_dict) + def faculty(): """ @@ -554,8 +487,35 @@ def faculty(): } + # print(cse_f) return context_f + +def alumni(request): + """ + This function is used to Return data of Alumni Department-Wise. + + @variables: + cse_a - Stores data of alumni from CSE Department + ece_a - Stores data of alumni from ECE Department + me_a - Stores data of alumni from ME Department + sm_a - Stores data of alumni from ME Department + context_a - Stores all above variables in Dictionary + + """ + cse_a=ExtraInfo.objects.filter(department__name='CSE',user_type='alumni') + ece_a=ExtraInfo.objects.filter(department__name='ECE',user_type='alumni') + me_a=ExtraInfo.objects.filter(department__name='ME',user_type='alumni') + sm_a=ExtraInfo.objects.filter(department__name='SM',user_type='alumni') + + context_a = { + "cse_a" : cse_a, + "ece_a" : ece_a, + "me_a" : me_a, + "sm_a" : sm_a + } + return render(request, 'department/alumni.html', context_a) + def approved(request): """ This function is used to approve requests. @@ -572,6 +532,7 @@ def approved(request): request.method = '' return redirect('/dep/facView/') + def deny(request): """ This function is used to deny requests. diff --git a/FusionIIIT/applications/eis/migrations/0001_initial.py b/FusionIIIT/applications/eis/migrations/0001_initial.py index f3dbd4bf3..265b34ac7 100644 --- a/FusionIIIT/applications/eis/migrations/0001_initial.py +++ b/FusionIIIT/applications/eis/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.1.5 on 2024-04-15 23:58 +# Generated by Django 3.1.5 on 2024-07-16 15:44 import datetime from django.conf import settings @@ -11,8 +11,8 @@ class Migration(migrations.Migration): initial = True dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('auth', '0012_alter_user_first_name_max_length'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ diff --git a/FusionIIIT/applications/establishment/migrations/0001_initial.py b/FusionIIIT/applications/establishment/migrations/0001_initial.py index d85fe198d..51caaf80b 100644 --- a/FusionIIIT/applications/establishment/migrations/0001_initial.py +++ b/FusionIIIT/applications/establishment/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.1.5 on 2024-04-15 23:58 +# Generated by Django 3.1.5 on 2024-07-16 15:44 from django.conf import settings from django.db import migrations, models @@ -10,9 +10,9 @@ class Migration(migrations.Migration): initial = True dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('globals', '0001_initial'), ('auth', '0012_alter_user_first_name_max_length'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ diff --git a/FusionIIIT/applications/estate_module/migrations/0001_initial.py b/FusionIIIT/applications/estate_module/migrations/0001_initial.py index 899dbfccc..7d80b342e 100644 --- a/FusionIIIT/applications/estate_module/migrations/0001_initial.py +++ b/FusionIIIT/applications/estate_module/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.1.5 on 2024-04-15 23:58 +# Generated by Django 3.1.5 on 2024-07-16 15:44 from django.conf import settings from django.db import migrations, models diff --git a/FusionIIIT/applications/examination/admin.py b/FusionIIIT/applications/examination/admin.py new file mode 100644 index 000000000..c44d2718b --- /dev/null +++ b/FusionIIIT/applications/examination/admin.py @@ -0,0 +1,8 @@ +from django.contrib import admin +from .models import hidden_grades,authentication,grade + +# Register your models here. + +admin.site.register(hidden_grades) +admin.site.register(authentication) +admin.site.register(grade) \ No newline at end of file diff --git a/FusionIIIT/applications/examination/api/serializers.py b/FusionIIIT/applications/examination/api/serializers.py new file mode 100644 index 000000000..5f3ca03b4 --- /dev/null +++ b/FusionIIIT/applications/examination/api/serializers.py @@ -0,0 +1,22 @@ +from rest_framework.authtoken.models import Token +from rest_framework import serializers +from applications.department.models import(Announcements) + + +from applications.academic_procedures.models import (course_registration) + +class CourseRegistrationSerializer(serializers.ModelSerializer): + class Meta: + model = course_registration + fields = ('__all__') + + +class AnnouncementsSerializer(serializers.ModelSerializer): + class Meta: + model = Announcements + fields = ['maker_id', 'ann_date', 'message', 'batch', 'department', 'programme', 'upload_announcement'] + +class AuthenticationSerializer(serializers.ModelSerializer): + class Meta: + model = Announcements + fields = '__all__' \ No newline at end of file diff --git a/FusionIIIT/applications/examination/api/urls.py b/FusionIIIT/applications/examination/api/urls.py new file mode 100644 index 000000000..15e37a1ab --- /dev/null +++ b/FusionIIIT/applications/examination/api/urls.py @@ -0,0 +1,51 @@ + +from django.conf.urls import url +from django.urls import path, include +from . import views + + +urlpatterns = [ + url(r'^registered_student_details/', views.fetch_student_details, name='fetch_student_details'), + + + url(r'^update_hidden_grade/', views.update_hidden_grade, name='update_hidden_grade'), + + url(r'^add_courses/' , views.add_courses , name = 'add_courses'), + + url(r'^update_authenticator/', views.update_authenticator, name='update_authenticator'), + + url(r'^check_all_authenticators/', views.check_all_authenticators, name='check_all_authenticators'), + + + url(r'^publish_grade/' , views.publish_grade , name='publish_grade'), + + url(r'^generate_transcript_form/' , views.generate_transcript_form , name = 'generate_transcript_form'), + +# Here error + url(r'^generate_transcript/' , views.generate_transcript , name = 'generate_transcript'), + + url(r'^getGrades/' , views.get_grade_for_course , name='get_grade_for_course'), + + url(r'^get_course_names/' , views.get_course_names , name='get_course_names'), + + url(r'^update_grades/' , views.update_grades , name='update_grades'), + + url(r'^fetch_roll_of_courses/' , views.fetch_roll_of_courses , name='fetch_roll_of_courses/'), + + url(r'^get_registered_students_roll_no/' , views.get_registered_students_roll_no , name='get_registered_students_roll_no/'), + + url(r'^get_auth_status/' , views.get_auth_status , name='get_auth_status'), + + url(r'^get_curriculum_values/' , views.get_curriculum_values , name='get_curriculum_values/'), + + + url(r'^announce/' , views.announce , name='announce/'), + + url(r'^submit_grades/$' , views.submit_grades , name='submit_grades/'), + + + # Delete this + + url(r'^add_student_details/' , views.add_student_details , name='add_student_details/'), + +] \ No newline at end of file diff --git a/FusionIIIT/applications/examination/api/views.py b/FusionIIIT/applications/examination/api/views.py new file mode 100644 index 000000000..1eab764ef --- /dev/null +++ b/FusionIIIT/applications/examination/api/views.py @@ -0,0 +1,1122 @@ +from django.db.models.query_utils import Q +from django.http import request,HttpResponse +from django.shortcuts import get_object_or_404, render, HttpResponse,redirect +from django.http import HttpResponse, HttpResponseRedirect +import itertools +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.contrib.auth.models import User +from django.http import JsonResponse + +# from applications.academic_information.models import Student +from applications.globals.models import (DepartmentInfo, Designation, + ExtraInfo, Faculty, HoldsDesignation) + +from applications.academic_procedures.models import(course_registration , Register) +# from applications.academic_information.models import Course , Curriculum +from applications.programme_curriculum.models import Course , Curriculum +from applications.examination.models import(hidden_grades , authentication , grade) +from applications.department.models import(Announcements , SpecialRequest) +from applications.academic_information.models import(Student) +from applications.online_cms.models import(Student_grades) +from applications.globals.models import(ExtraInfo) +from . import serializers +from datetime import date +from rest_framework import status +from rest_framework.decorators import api_view +from rest_framework.response import Response + +from django.core.serializers import serialize +from django.http import JsonResponse +import json +from datetime import datetime + + + +@api_view(['GET', 'POST']) +def fetch_roll_of_courses(request): + """ + This function is used to fetch roll numbers of students registered for a specific course. + + @variables: + course_id - ID of the course for which roll numbers are being fetched + working_year - Year for which roll numbers are being fetched + obj - Queryset containing student registrations filtered by course ID and working year + obj_serialized - Serialized data of student registrations + resp - Dictionary containing the response data + """ + if request.method == 'POST': + # Retrieve the course_id and working_year from the request data + course_id = request.data.get('course_id') + working_year = request.data.get('working_year') + + if course_id is None: + return Response({'error': 'Course ID is required in the request parameters'}, status=status.HTTP_400_BAD_REQUEST) + + # Filter students by the provided course ID and working year + obj = course_registration.objects.filter(course_id=course_id , working_year=working_year) + + # Serialize the queryset + obj_serialized = serializers.CourseRegistrationSerializer(obj, many=True).data + + # Prepare the response data + resp = { + 'objt': obj_serialized + } + + # Return the response + return Response(data=resp, status=status.HTTP_200_OK) + + # Return a default response for GET requests + return Response({'message': 'Students'}, status=status.HTTP_201_CREATED) + + + + + +# @api_view(['GET', 'POST']) +# def fetch_student_details(request): +# """ +# This function is used to fetch student details based on course, semester, and batch. + +# @variables: +# course_id - ID of the course for which student details are being fetched +# semester_id - ID of the semester for which student details are being fetched +# batch - Batch for which student details are being fetched +# course_present - Queryset containing student grades filtered by course, semester, and batch +# data - Dictionary containing the data to be returned in JSON format +# """ +# if request.method == 'GET': +# # Retrieve query parameters +# course_id = int(request.query_params.get('course')) +# semester_id = int(request.query_params.get('semester')) +# year = int(request.query_params.get('batch')) +# print(course_id,semester_id,year) +# if course_id is None or semester_id is None or year is None: +# return JsonResponse({'error': 'Incomplete parameters provided'}, status=400) + +# # Filter student grades based on provided parameters +# course_present = Student_grades.objects.filter(course_id=course_id, semester=semester_id, year=year) + +# # Prepare data to return in JSON format +# data = { +# 'registrations': list(course_present.values()) # Convert queryset to list of dictionaries +# } + +# # Return JSON response +# return JsonResponse(data) + + + +@api_view(['GET']) +def fetch_student_details(request): + """ + This function is used to fetch student details based on course, semester, and batch. + """ + if request.method == 'GET': + # Retrieve query parameters + course_id = request.query_params.get('course') + semester_id = request.query_params.get('semester') + year = request.query_params.get('year') + + if course_id is None or semester_id is None or year is None: + return JsonResponse({'error': 'Incomplete parameters provided'}, status=400) + + # Convert parameters to appropriate types + try: + course_id = int(course_id) + semester_id = (semester_id) + year = year + except ValueError: + return JsonResponse({'error': 'Invalid parameter types'}, status=400) + + # Filter student grades based on provided parameters + course_present = Student_grades.objects.filter(course_id=course_id, semester=semester_id, year=year) + # Prepare data to return in JSON format + data = { + 'registrations': list(course_present.values()) # Convert queryset to list of dictionaries + } + + # Return JSON response + return JsonResponse(data) + else: + return JsonResponse({'error': 'Only GET requests are allowed'}, status=405) + + + + + +@api_view(['GET', 'POST']) +def add_student_details(request): + """ + This function is used to add student details to the database. + + @variables: + course_id - ID of the course for which student details are being added + semester - Semester for which student details are being added + year - Year for which student details are being added + roll_no - Roll number of the student + total_marks - Total marks obtained by the student + grade - Grade obtained by the student + batch - Batch for which student details are being added + student_data_list - List of dictionaries containing student details + success_count - Counter to keep track of successfully added students + """ + if request.method == 'POST': + # Extract list of student details from the request + student_data_list = request.data.get('students', []) + + # Validate data + if not student_data_list: + return Response({'error': 'No student data provided'}, status=400) + + # Counter for successfully added students + success_count = 0 + + # Loop through each student data and add to database + for student_data in student_data_list: + # Extract data for each student + course_id = student_data.get('course_id') + semester = student_data.get('semester') + year = student_data.get('year') + roll_no = student_data.get('roll_no') + total_marks = student_data.get('total_marks') + grade = student_data.get('grade') + batch = student_data.get('batch') + + # Validate data for each student + if not all([course_id, semester, year, roll_no, total_marks, grade, batch]): + continue # Skip this student if data is incomplete + + try: + # Get the Course instance + course_instance = Course.objects.get(pk=course_id) + + # Create new Student_grades instance + Student_grades.objects.create( + course_id=course_instance, + semester=semester, + year=year, + roll_no=roll_no, + total_marks=total_marks, + grade=grade, + batch=batch + ) + + success_count += 1 # Increment success count + except Course.DoesNotExist: + continue # Skip this student if course does not exist + + # Return response with success count + return Response({'success': f'{success_count} student(s) added successfully'}, status=201) + + + + + +@api_view(['GET', 'POST']) +def update_hidden_grade(request): + """ + This function is used to retrieve or update hidden grades for a course. + + @variables: + course_id - ID of the course for which hidden grades are being retrieved or updated + students - Queryset containing students registered for the course + students_serialized - Serialized data of students registered for the course + resp - Dictionary containing the response data + data_list - List of data for multiple students provided in the request body + student_id - ID of the student for which hidden grade is being updated + grade - Grade for the hidden grade being updated + hidden_grade_obj - Hidden grade object corresponding to the course and student + """ + if request.method == 'GET': + # Retrieve the course_id from the request query parameters + course_id = request.query_params.get('course_id') + + if course_id is None: + return JsonResponse({'error': 'Course ID is required in the request parameters'}, status=status.HTTP_400_BAD_REQUEST) + + # Filter students by the provided course ID + students = course_registration.objects.filter(course_id=course_id) + + # Serialize the queryset + students_serialized = serializers.CourseRegistrationSerializer(students, many=True).data + + # Prepare the response data + resp = { + 'students': students_serialized + } + + # Return the response + return JsonResponse(data=resp, status=status.HTTP_200_OK) + + elif request.method == 'POST': + # Extract course_id from query parameters + course_id = request.query_params.get('course_id') + + # Extract data for multiple students + data_list = request.data + + # Check if course_id is provided + if not course_id: + return JsonResponse({'error': 'Course ID is required in the request parameters'}, status=status.HTTP_400_BAD_REQUEST) + + # Process each student in the list + for data in data_list: + student_id = data.get('student_id') + grade = data.get('grade') + + # Check if student_id and grade are provided + if not all([student_id, grade]): + return JsonResponse({'error': 'Incomplete data provided for one of the students'}, status=status.HTTP_400_BAD_REQUEST) + + # Check if the entry already exists + try: + hidden_grade_obj = hidden_grades.objects.get(course_id=course_id, student_id=student_id) + # If exists, update the grade + hidden_grade_obj.grade = grade + hidden_grade_obj.save() + except hidden_grades.DoesNotExist: + # If doesn't exist, create a new entry + hidden_grade_obj = hidden_grades.objects.create( + course_id=course_id, + student_id=student_id, + grade=grade + ) + + return JsonResponse({'message': 'Hidden grades updated successfully'}, status=status.HTTP_201_CREATED) + + else: + return JsonResponse({'error': 'Unsupported method'}, status=status.HTTP_405_METHOD_NOT_ALLOWED) + + + + + +@api_view(['GET']) +def check_all_authenticators(request): + """ + This function is used to check if all authenticators are verified for a specific course and year. + + @variables: + course_id - ID of the course for which all authenticators are being checked + year - Year for which all authenticators are being checked + auth_objects - Queryset containing authentication objects filtered by year + """ + if request.method == 'GET': + # Extract year and course ID from the request + course_id = int(request.query_params.get('course_id')) + year = request.query_params.get('year') + + # Validate year format + try: + datetime.strptime(year, '%Y') + except ValueError: + return Response({'error': 'Invalid year format. Please use YYYY format.'}, status=status.HTTP_400_BAD_REQUEST) + + # Retrieve all authentication objects for the given year and course ID + auth_objects = authentication.objects.filter(year__year=year ,course_id = course_id) + + if not auth_objects.exists(): + return Response({'error': 'No authentication entries found for the provided year.'}, status=status.HTTP_404_NOT_FOUND) + + # Check if all three authenticators are verified for all authentication objects + for auth_object in auth_objects: + if not (auth_object.authenticator_1 and auth_object.authenticator_2 and auth_object.authenticator_3): + return Response({'all_authenticated': False}, status=status.HTTP_200_OK) + + return Response({'all_authenticated': True}, status=status.HTTP_200_OK) + + + + + + +@api_view(['PATCH']) +def update_authenticator(request): + """ + This function is used to update the status of an authenticator for a specific course and year. + + @variables: + course_id - ID of the course for which authenticator status is being updated + year - Year for which authenticator status is being updated + authenticator_number - Number representing the authenticator whose status is being updated + auth_objects - Queryset containing authentication objects filtered by year and course_id + auth_object - Authentication object for the given year and course_id + """ + if request.method == 'PATCH': + # Extract course id, year, and authenticator number from the request + course_id = int(request.data.get('course_id')) + year = request.data.get('year')[:4] + authenticator_number = int(request.data.get('authenticator_number')) + + # Validate year format + print(course_id,year,authenticator_number) + try: + datetime.strptime(year, '%Y') + except ValueError: + return Response({'error': 'Invalid year format. Please use YYYY format.'}, status=status.HTTP_400_BAD_REQUEST) + + # Retrieve all authentication objects for the given year and course id + auth_objects = authentication.objects.filter(year__year=year ,course_id=course_id) + print(authentication.objects.all()[0]) + if not auth_objects.exists(): + return Response({'error': 'No authentication entries found for the provided year and course id.'}, status=status.HTTP_404_NOT_FOUND) + + # Toggle the specified authenticator for each authentication object + for auth_object in auth_objects: + if authenticator_number == 1: + auth_object.authenticator_1 = not auth_object.authenticator_1 + elif authenticator_number == 2: + auth_object.authenticator_2 = not auth_object.authenticator_2 + elif authenticator_number == 3: + auth_object.authenticator_3 = not auth_object.authenticator_3 + else: + return Response({'error': 'Invalid authenticator number'}, status=status.HTTP_400_BAD_REQUEST) + + auth_object.save() + + return Response({'message': f'Authenticator {authenticator_number} toggled successfully for the year {year} and course id {course_id}'}, status=status.HTTP_200_OK) + + + + + +@api_view(['GET','POST']) +def get_auth_status(request): + """ + This function is used to get the authentication status for a specific course and year. + + @variables: + course_id - ID of the course for which authentication status is being retrieved + year - Year for which authentication status is being retrieved + auth_objects - Queryset containing authentication objects filtered by year and course_id + auth_object - Authentication object for the given year and course_id + auth_status - Dictionary containing the authentication status for authenticators 1, 2, and 3 + """ + try: + course_id = int(request.data.get('course_id')) + year = request.data.get('year')[:4] + print(course_id, year) + + # Use filter instead of get to handle multiple objects + auth_objects = authentication.objects.filter(year__year=year, course_id=course_id) + + if auth_objects.exists(): + auth_object = auth_objects.first() # Use first() to get the first object + auth_status = { + 'authenticator1': auth_object.authenticator_1, + 'authenticator2': auth_object.authenticator_2, + 'authenticator3': auth_object.authenticator_3 + } + print(auth_status) + return JsonResponse(auth_status, status=status.HTTP_200_OK) + else: + return Response({'error': 'No authentication entries found for the provided year and course id.'}, status=status.HTTP_404_NOT_FOUND) + except Exception as e: + return JsonResponse({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + + + + + +@api_view(['GET']) +def publish_grade(request): + """ + This function is used to publish grades for a course. + + @variables: + course_id - ID of the course for which grades are being published + auth_obj - Authentication object corresponding to the course_id + hidden_grades_list - List of hidden grades for the given course + hidden_grade - Hidden grade object in the hidden_grades_list + existing_final_grade - Existing final grade object for the student and course + """ + course_id = request.GET.get('course_id') + auth_obj = authentication.objects.filter(course=course_id).first() + + if auth_obj: + if auth_obj.authenticator_1 and auth_obj.authenticator_2 and auth_obj.authenticator_3: + # Get hidden grades for the given course + hidden_grades_list = hidden_grades.objects.filter(course_id=course_id) + + # Update final grades table + for hidden_grade in hidden_grades_list: + # Check if final grade already exists + existing_final_grade = grade.objects.filter( + student_id=hidden_grade.student_id, + course_id=hidden_grade.course_id, + semester_id=hidden_grade.semester_id + ).first() + + if not existing_final_grade: + # Create final grade only if it doesn't already exist + grade.objects.create( + student_id=hidden_grade.student_id, + course_id=hidden_grade.course_id, + semester_id=hidden_grade.semester_id, + grade=hidden_grade.grade + ) + + return JsonResponse({'message': 'Grades are ready to publish'}, status=200) + else: + return JsonResponse({'error': 'Not all authenticators are True'}, status=400) + else: + return JsonResponse({'error': 'Authentication object not present'}, status=404) + + + + + +@api_view(['POST', 'GET']) +def generate_transcript_form(request): + """ + This function is used to generate a transcript form for students. + + @variables: + programme - Programme selected for filtering students + batch - Batch selected for filtering students + specialization - Specialization selected for filtering students + students - Queryset containing filtered students based on programme, batch, and specialization + serialized_students - Serialized JSON string representing the filtered students + students_data - Python object obtained by deserializing the JSON string + programmes - List of distinct programme values from Student objects + specializations - List of distinct specialization values from Student objects + batches - List of distinct batch values from Student objects + context - Dictionary containing programmes, batches, and specializations for rendering the form + """ + if request.method == 'POST': + programme = request.data.get('programme') + batch = request.data.get('batch') + specialization = request.data.get('specialization') + print(programme, batch, specialization) + + if specialization is None: + students = Student.objects.filter(programme=programme, batch=batch) + else: + students = Student.objects.filter(programme=programme, batch=batch, specialization=specialization) + + # Serialize QuerySet to JSON string + serialized_students = serialize('json', students) + print(serialized_students) + # Deserialize JSON string to Python object + students_data = json.loads(serialized_students) + + # Pass the deserialized data to JsonResponse + return JsonResponse({'students': students_data}) + else: + programmes = Student.objects.values_list('programme', flat=True).distinct() + specializations = Student.objects.exclude(specialization__isnull=True).values_list('specialization', flat=True).distinct() + batches = Student.objects.values_list('batch', flat=True).distinct() + context = { + 'programmes': list(programmes), + 'batches': list(batches), + 'specializations': list(specializations), + } + + return JsonResponse(context) + + + + + + + +# @api_view(['POST', 'GET']) +# def generate_transcript(request): +# """ +# This function is used to generate a transcript for a student. + +# @variables: +# student_id - ID of the student for whom the transcript is being generated +# semester - Semester for which the transcript is being generated +# student_grades - Queryset containing grades for the student in the specified semester +# transcript_data - List to hold transcript data for each course +# grade - Grade object for each course in the specified semester +# course_info - Dictionary containing course information to be included in the transcript +# student_info - Information about the student, such as CPI (Cumulative Performance Index) +# cpi - Cumulative Performance Index of the student +# course_detail - Details of the course obtained from Curriculum +# """ +# if request.method == 'POST': +# student_id = request.data.get('student_id') +# semester = request.data.get('semester') + +# # Fetch the courses and grades for the student in the specified semester +# student_grades = Student_grades.objects.filter(roll_no=student_id, semester=semester) +# print(student_id,semester) + +# total_course_registered = Student_grades.objects.filter( +# roll_no=student_id, semester__lte=semester) + +# # Prepare data to be returned +# transcript_data = [] +# for grade in student_grades: +# # Access fields of each object +# course_info = { +# 'course_id': grade.course_id.name, +# 'total_marks': grade.total_marks, +# 'grade': grade.grade, +# 'batch': grade.batch, +# } + +# student_info = Student.objects.filter(id=student_id).first() + +# ##### Student Grades fetch all courses before semester find spi and update cpi in student table +# print(student_info.cpi) +# if student_info: +# cpi = student_info.cpi +# course_info['cpi'] = cpi +# else: +# # Handle case where student info is not found +# print("cpi is not there") +# pass +# # Fetch course details from Curriculum +# course_detail = Course.objects.filter(id=grade.course_id.id).first() +# if course_detail: +# # Include additional attributes +# course_info['course_code'] = course_detail.code +# course_info['credits'] = course_detail.credit +# else: +# # If course details not found, assign default values +# course_info['course_code'] = "Unknown" +# course_info['credits'] = 0 + +# transcript_data.append(course_info) + +# return JsonResponse({'transcript': transcript_data}) +# else: +# return JsonResponse({'error': 'Invalid request method'}) + + + + +@api_view(['POST', 'GET']) +def generate_transcript(request): + """ + This function is used to generate a transcript for a student. + + @variables: + student_id - ID of the student for whom the transcript is being generated + semester - Semester for which the transcript is being generated + student_grades - Queryset containing grades for the student in the specified semester + transcript_data - List to hold transcript data for each course + grade - Grade object for each course in the specified semester + course_info - Dictionary containing course information to be included in the transcript + student_info - Information about the student, such as CPI (Cumulative Performance Index) + cpi - Cumulative Performance Index of the student + course_detail - Details of the course obtained from Curriculum + """ + if request.method == 'POST': + student_id = request.data.get('student_id') + semester = request.data.get('semester') + + # Fetch the courses and grades for the student in the specified semester + student_grades = Student_grades.objects.filter(roll_no=student_id, semester=semester) + print(student_id, semester) + + # Fetch all courses registered by the student up to the specified semester + total_courses_registered = Student_grades.objects.filter( + roll_no=student_id, semester__lte=semester + ).values_list('course_id', flat=True).distinct().count() + + # Prepare data to be returned + transcript_data = [] + for grade in student_grades: + # Access fields of each object + course_info = { + 'course_id': grade.course_id.name, + 'total_marks': grade.total_marks, + 'grade': grade.grade, + 'batch': grade.batch, + } + + student_info = Student.objects.filter(id=student_id).first() + + ##### Student Grades fetch all courses before semester find spi and update cpi in student table + print(student_info.cpi) + if student_info: + cpi = student_info.cpi + course_info['cpi'] = cpi + else: + # Handle case where student info is not found + print("cpi is not there") + pass + # Fetch course details from Curriculum + course_detail = Course.objects.filter(id=grade.course_id.id).first() + if course_detail: + # Include additional attributes + course_info['course_code'] = course_detail.code + course_info['credits'] = course_detail.credit + else: + # If course details not found, assign default values + course_info['course_code'] = "Unknown" + course_info['credits'] = 0 + + transcript_data.append(course_info) + + return JsonResponse({'transcript': transcript_data, 'total_courses_registered': total_courses_registered}) + else: + return JsonResponse({'error': 'Invalid request method'}) + + + + + + + + +# @api_view(['POST', 'GET']) +# def get_curriculum_values(request): +# """ +# This function is used to retrieve curriculum values for a given course. + +# @variables: +# course_id - ID of the course for which curriculum values are being retrieved +# curriculum_values - Curriculum object corresponding to the course_id +# """ +# try: +# course_id = request.data.get('course_id') + +# curriculum_values = Course.objects.get(id=course_id) +# print(Curriculum.objects.all()) +# return JsonResponse({ +# 'course_code': curriculum_values.course_code, +# 'credits': curriculum_values.credits, +# 'course_type': curriculum_values.course_type, +# 'programme': curriculum_values.programme, +# 'branch': curriculum_values.branch, +# 'sem': curriculum_values.sem, +# 'optional': curriculum_values.optional, +# 'floated': curriculum_values.floated +# }) +# except Curriculum.DoesNotExist: +# print(Curriculum.objects.all()) +# return JsonResponse({ +# 'course_code': 'Unknown', +# 'credits': 0, +# 'course_type': 'Unknown', +# 'programme': 'Unknown', +# 'branch': 'Unknown', +# 'sem': 0, +# 'optional': False, +# 'floated': False +# }) + + + + +@api_view(['POST', 'GET']) +def get_curriculum_values(request): + """ + This function is used to retrieve curriculum values for a given course. + + @variables: + course_id - ID of the course for which curriculum values are being retrieved + curriculum_values - Course object corresponding to the course_id + """ + try: + course_id = request.data.get('course_id') + + course_values = Course.objects.get(id=course_id) + + return JsonResponse({ + 'code': course_values.code, + 'name': course_values.name, + 'credit': course_values.credit, + 'lecture_hours': course_values.lecture_hours, + 'tutorial_hours': course_values.tutorial_hours, + 'pratical_hours': course_values.pratical_hours, + 'discussion_hours': course_values.discussion_hours, + 'project_hours': course_values.project_hours, + 'pre_requisits': course_values.pre_requisits, + # Add other fields as needed + }) + except Course.DoesNotExist: + return JsonResponse({ + 'error': 'Course not found for the given ID', + }) + + + + +@api_view(['POST', 'GET']) +def get_grade_for_course(course_id, batch, year, semester_id, selected_student_id): + """ + This function is used to retrieve the grade for a specific course, batch, year, semester, and student. + + @parameters: + course_id - ID of the course for which grade is being retrieved + batch - Batch for which grade is being retrieved + year - Year for which grade is being retrieved + semester_id - ID of the semester for which grade is being retrieved + selected_student_id - ID of the student for whom grade is being retrieved + + @variables: + grades - Queryset containing grades filtered by course_id, batch, year, semester_id, and selected_student_id + """ + # Filter Student_grades based on course_id, batch, year, semester_id, and selected_student_id + grades = Student_grades.objects.filter( + course_id=course_id, + batch=batch, + roll_no=selected_student_id, + year=year, + semester=semester_id, + ) + + # Assuming only one grade is expected for a given combination of parameters + if grades.exists(): + return grades.first().grade + else: + return None # Return None if no grade is found + + + + + +@api_view(['POST', 'GET']) +def get_course_names(request): + """ + This function is used to retrieve course names and IDs. + + @variables: + courses - Queryset containing all Course objects + course_data - List of dictionaries containing course IDs and names + """ + if request.method == 'GET': + # Retrieve all course names and IDs + courses = Course.objects.all() + course_data = [{'id': course.id, 'name': course.name} for course in courses] + + if not course_data: + return JsonResponse({'error': 'No courses found.'}, status=status.HTTP_404_NOT_FOUND) + + return JsonResponse({'courses': course_data}, status=status.HTTP_200_OK) + + + + + +@api_view(['POST']) +def add_courses(request): + """ + This function is used to add courses along with authentication objects. + + @variables: + courses - List of courses received from the request body + created_authentications - List to hold the created authentication objects + course_instance - Instance of the Course model corresponding to the course ID + authentication_object - Authentication object created for the course + serialized_data - Serialized data of the created authentication objects + """ + if request.method == 'POST': + # Get the list of courses from the request body + courses = request.data.get('courses', []) + + # Create a list to hold the created authentication objects + created_authentications = [] + + # Iterate over the list of courses and create an authentication object for each + for course in courses: + try: + # Get the Course instance corresponding to the course ID + course_instance = Course.objects.get(id=course['id']) + + # Create a new authentication object with the Course instance + authentication_object = authentication.objects.create(course_id=course_instance) + + # Append the created authentication object to the list + created_authentications.append(authentication_object) + except Exception as e: + # Handle any errors that occur during object creation + # You can choose to log the error or handle it based on your requirements + print(f"Error creating authentication object for course ID {course['id']}: {e}") + + # Convert the created authentication objects to dictionaries + serialized_data = [{'id': obj.id, 'authenticator_1': obj.authenticator_1, 'authenticator_2': obj.authenticator_2, 'authenticator_3': obj.authenticator_3, 'year': obj.year.year, 'course_id': obj.course_id_id} for obj in created_authentications] + + # Return a JSON response with the serialized data + return JsonResponse(serialized_data, status=201, safe=False) + + + + + +@api_view(['PATCH']) +def update_grades(request): + """ + This function is used to update grades for students. + + @variables: + updated_students_data - JSON data containing updated grades for students + roll_no - Roll number of the student + course_id - ID of the course for which grades are being updated + semester_id - ID of the semester for which grades are being updated + year - Year for which grades are being updated + grade - Updated grade received by the student + total_marks - Updated total marks obtained by the student + student_grade_obj - Student grades object to be updated or created + created - Flag indicating whether a new student grade object was created + """ + if request.method == 'PATCH': + try: + # Extract the updated student data from the request body + updated_students_data = json.loads(request.body) + print(updated_students_data) + # Iterate over each updated student data + for student_data in updated_students_data: + roll_no = student_data.get('roll_no') + course_id = int(student_data.get('course_id')) + semester_id = student_data.get('semester_id') + year = int(student_data.get('year')) + grade = student_data.get('grade') + total_marks = student_data.get('total_marks') + + # Check if all necessary data is provided + if not (roll_no and course_id and semester_id and year and grade and total_marks): + return JsonResponse({'error': 'Incomplete data provided'}, status=400) + + # Update the student grade + student_grade_obj, created = Student_grades.objects.update_or_create( + roll_no=roll_no, + course_id=course_id, + semester=semester_id, + year=year, + defaults={'grade': grade, 'total_marks': total_marks} + ) + + return JsonResponse({'message': 'Student grades updated successfully'}, status=200) + + except json.JSONDecodeError as e: + return JsonResponse({'error': 'Invalid JSON format'}, status=400) + + except KeyError as e: + return JsonResponse({'error': 'Missing required field: ' + str(e)}, status=400) + + except Exception as e: + return JsonResponse({'error': str(e)}, status=500) + + + + + +@api_view(['PATCH']) +def submit_grades(request): + """ + This function is used to submit grades for students. + + @variables: + updated_students_data - JSON data containing updated grades for students + roll_no - Roll number of the student + course_id - ID of the course for which grades are being submitted + semester_id - ID of the semester for which grades are being submitted + year - Year for which grades are being submitted + grade - Grade received by the student (defaulted to 'NA') + total_marks - Total marks obtained by the student (defaulted to 0) + course - Course object corresponding to course_id + student_grade_obj - Student grades object to be updated or created + created - Flag indicating whether a new student grade object was created + """ + if request.method == 'PATCH': + try: + updated_students_data = json.loads(request.body) + print(updated_students_data) + + for student_data in updated_students_data: + roll_no = student_data.get('roll_no') + course_id = int(student_data.get('course_id')) + semester_id = student_data.get('semester_id') + year = int(student_data.get('year')) + grade = student_data.get('grade','NA') + total_marks = student_data.get('total_marks','0') + + if not (roll_no and course_id and semester_id and year and grade and total_marks): + return JsonResponse({'error': 'Incomplete data provided'}, status=400) + + # Retrieve the Course object based on course_id + course = Course.objects.get(id=course_id) + + # Update or create the student grade object + student_grade_obj, created = Student_grades.objects.update_or_create( + roll_no=roll_no, + course_id=course, # Use the Course object instead of course_id + semester=semester_id, + year=year, + defaults={'grade': grade, 'total_marks': total_marks} + ) + + return JsonResponse({'message': 'Student grades updated successfully'}, status=200) + + except json.JSONDecodeError as e: + return JsonResponse({'error': 'Invalid JSON format'}, status=400) + + except KeyError as e: + return JsonResponse({'error': 'Missing required field: ' + str(e)}, status=400) + + except Exception as e: + return JsonResponse({'error': str(e)}, status=500) + + + + +@api_view(['POST', 'GET']) +def get_registered_students_roll_no(request): + """ + This function is used to retrieve registered students' information for a particular course and year. + + @variables: + course_id - ID of the course for which registrations are being retrieved + year - Year for which registrations are being retrieved + registrations - Queryset containing course registrations filtered by course_id and year + data - List to store serialized student data + student_data - Dictionary to store individual student information + student_grade - Grade and total marks of the student for the specified course + """ + # Retrieve the course_id and year from the request query parameters + course_id = request.data.get('course_id') + year = request.data.get('year') + + if not course_id or not year: + return JsonResponse({'error': 'Course ID and year are required'}, status=400) + + try: + # Filter course registrations by course_id and year + registrations = course_registration.objects.filter(course_id=course_id, working_year=year) + # registrations = Register.objects.filter(curr_id=course_id) + print(registrations) + # Serialize the queryset + data = [] + for registration in registrations: + # Access fields of the related Student instance + print(registration) + student_data = { + 'roll_no': registration.student_id.id.user.username, + 'name': registration.student_id.id.user.first_name, # Assuming first_name is a field of the User model + 'email': registration.student_id.id.user.email, # Assuming email is a field of the User model + # Include other relevant fields from the Student model + 'grade': None, + 'marks': None + } + + # Retrieve grades and total marks for the student + try: + print(registration.student_id.id , course_id) + student_grade = Student_grades.objects.get(roll_no=student_data['roll_no'],course_id=course_id) + student_data['grade'] = student_grade.grade + student_data['marks'] = student_grade.total_marks + + # print(student_grade) + except Student_grades.DoesNotExist: + print("Didn't find grades for roll_no:", registration.student_id.id, "and course_id:", course_id) + pass + # print(student_data) + data.append(student_data) + # Return the serialized data in the response + return JsonResponse({'registrations': data}, status=200) + except Exception as e: + return JsonResponse({'error': str(e)}, status=500) + + + + + +@api_view(['POST', 'GET']) +def get_to_request(username): + """ + This function is used to get requests for the receiver + + @variables: + req - Contains request queryset + + """ + req = SpecialRequest.objects.filter(request_receiver=username) + return req + + + + +@api_view(['POST', 'GET']) +def browse_announcements(): + """ + This function is used to browse Announcements Department-Wise + made by different faculties and admin. + + @variables: + cse_ann - Stores CSE Department Announcements + ece_ann - Stores ECE Department Announcements + me_ann - Stores ME Department Announcements + sm_ann - Stores SM Department Announcements + all_ann - Stores Announcements intended for all Departments + context - Dictionary for storing all above data + + """ + cse_ann = Announcements.objects.filter(department="CSE") + ece_ann = Announcements.objects.filter(department="ECE") + me_ann = Announcements.objects.filter(department="ME") + sm_ann = Announcements.objects.filter(department="SM") + all_ann = Announcements.objects.filter(department="ALL") + + context = { + "cse" : cse_ann, + "ece" : ece_ann, + "me" : me_ann, + "sm" : sm_ann, + "all" : all_ann + } + + return context + + + + +@api_view(['POST', 'GET']) +def announce(request): + """ + This function is used to make announcements by faculty or admin. + + @variables: + usrnm - Current user's username + user_info - Extra information of the current user + ann_maker_id - ID of the user making the announcement + batch - Batch for which the announcement is intended + programme - Programme for which the announcement is intended + message - Content of the announcement + upload_announcement - File uploaded with the announcement + department - Department for which the announcement is intended + ann_date - Date of the announcement + getstudents - All users with extra information + + """ + usrnm = get_object_or_404(User, username=request.user.username) + user_info = ExtraInfo.objects.all().select_related('user', 'department').filter(user=usrnm).first() + ann_maker_id = user_info.id + + if request.method == 'POST': + batch = request.data.get('batch', '') + programme = request.data.get('programme', '') + message = request.data.get('announcement', '') + upload_announcement = request.FILES.get('upload_announcement') + department = request.data.get('department', 'ALL') + ann_date = datetime.today() + user_info = ExtraInfo.objects.all().select_related('user', 'department').get(id=ann_maker_id) + getstudents = ExtraInfo.objects.select_related('user') + + obj1, created = Announcements.objects.get_or_create(maker_id=user_info, + batch=batch, + programme=programme, + message=message, + upload_announcement=upload_announcement, + department=department, + ann_date=ann_date) + + response_data = { + 'status': 'success', + 'message': 'Announcement successfully created' + } + return JsonResponse(response_data) + else: + response_data = { + 'error': 'Invalid request method' + } + return JsonResponse(response_data, status=405) diff --git a/FusionIIIT/applications/examination/apps.py b/FusionIIIT/applications/examination/apps.py new file mode 100644 index 000000000..4ea19472a --- /dev/null +++ b/FusionIIIT/applications/examination/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class ExaminationConfig(AppConfig): + name = 'examination' diff --git a/FusionIIIT/applications/examination/forms.py b/FusionIIIT/applications/examination/forms.py new file mode 100644 index 000000000..30314d400 --- /dev/null +++ b/FusionIIIT/applications/examination/forms.py @@ -0,0 +1,4 @@ +from django import forms + +class StudentGradeForm(forms.Form): + grades = forms.CharField(widget=forms.MultipleHiddenInput) diff --git a/FusionIIIT/applications/examination/migrations/0001_initial.py b/FusionIIIT/applications/examination/migrations/0001_initial.py new file mode 100644 index 000000000..4bc165c9d --- /dev/null +++ b/FusionIIIT/applications/examination/migrations/0001_initial.py @@ -0,0 +1,48 @@ +# Generated by Django 3.1.5 on 2024-07-16 15:44 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('programme_curriculum', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='grade', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('student', models.CharField(max_length=20)), + ('curriculum', models.CharField(max_length=50)), + ('semester_id', models.CharField(default='', max_length=10)), + ('grade', models.CharField(default='B', max_length=5)), + ], + ), + migrations.CreateModel( + name='hidden_grades', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('student_id', models.CharField(max_length=20)), + ('course_id', models.CharField(max_length=50)), + ('semester_id', models.CharField(max_length=10)), + ('grade', models.CharField(max_length=5)), + ], + ), + migrations.CreateModel( + name='authentication', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('authenticator_1', models.BooleanField(default=False)), + ('authenticator_2', models.BooleanField(default=False)), + ('authenticator_3', models.BooleanField(default=False)), + ('year', models.DateField(auto_now_add=True)), + ('course_year', models.IntegerField(default=2024)), + ('course_id', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='programme_curriculum.course')), + ], + ), + ] diff --git a/FusionIIIT/media/New_Text_Document_2.txt b/FusionIIIT/applications/examination/migrations/__init__.py similarity index 100% rename from FusionIIIT/media/New_Text_Document_2.txt rename to FusionIIIT/applications/examination/migrations/__init__.py diff --git a/FusionIIIT/applications/examination/models.py b/FusionIIIT/applications/examination/models.py new file mode 100644 index 000000000..5cdced32c --- /dev/null +++ b/FusionIIIT/applications/examination/models.py @@ -0,0 +1,39 @@ +from django.db import models +from applications.academic_procedures.models import (course_registration) +from applications.online_cms.models import (Student_grades) +from applications.academic_information.models import Course +from applications.programme_curriculum.models import Course as Courses, CourseInstructor +# Create your models here. + + +class hidden_grades(models.Model): + student_id = models.CharField(max_length=20) + course_id = models.CharField(max_length=50) + semester_id = models.CharField(max_length=10) + grade = models.CharField(max_length=5) + + def __str__(self): + return f"{self.student_id}, {self.course_id}" + + +class authentication(models.Model): + authenticator_1 = models.BooleanField(default=False) + authenticator_2 = models.BooleanField(default=False) + authenticator_3 = models.BooleanField(default=False) + year = models.DateField(auto_now_add=True) + course_id = models.ForeignKey(Courses, on_delete=models.CASCADE, default=1) + course_year = models.IntegerField(default=2024) + + @property + def working_year(self): + return self.year.year + + def __str__(self): + return f"{self.course_id} , {self.course_year}" + + +class grade(models.Model): + student = models.CharField(max_length=20) + curriculum = models.CharField(max_length=50) + semester_id = models.CharField(max_length=10, default='') + grade = models.CharField(max_length=5, default="B") diff --git a/FusionIIIT/applications/examination/tests.py b/FusionIIIT/applications/examination/tests.py new file mode 100644 index 000000000..7ce503c2d --- /dev/null +++ b/FusionIIIT/applications/examination/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/FusionIIIT/applications/examination/urls.py b/FusionIIIT/applications/examination/urls.py new file mode 100644 index 000000000..83789d49e --- /dev/null +++ b/FusionIIIT/applications/examination/urls.py @@ -0,0 +1,57 @@ + +from django.conf.urls import url +from django.urls import path, include +from . import views +from django.contrib import admin +from .views import update_authentication +from .views import DownloadExcelView, updateGrades + +app_name = 'examination' + +urlpatterns = [ + url(r'^api/', include('applications.examination.api.urls')), + url(r'^$', views.exam, name='exam'), + + + url(r'submit/', views.submit, name='submit'),#old + url(r'verify/', views.verify, name='verify'),#old + url(r'publish/', views.publish, name='publish'),#old + url(r'notReady_publish/', views.notReady_publish, name='notReady_publish'),#old + url(r'timetable/', views.timetable, name='timetable'),#old + # entering and updataing grade + path('entergrades/', views.entergrades, name='entergrades'),#old + path('update_hidden_grades_multiple/', views.Updatehidden_gradesMultipleView.as_view(), + name='update_hidden_grades_multiple'),#old + path('verifygrades/', views.verifygrades, name='verifygrades'),#old + path('update_hidden_grades_multiple/', views.Updatehidden_gradesMultipleView.as_view(), + name='update_hidden_grades_multiple'),#old + path('submit_hidden_grades_multiple/', views.Submithidden_gradesMultipleView.as_view(), + name='submit_hidden_grades_multiple'),#old + path('download_excel/', DownloadExcelView.as_view(), name='download_excel'),#old + + #new + url(r'submitGrades/', views.submitGrades, name='submitGrades'),#new + url(r'submitEntergrades/', views.submitEntergrades, name='submitEntergrades'),#new + path('submitEntergradesStoring/', views.submitEntergradesStoring.as_view(),#new + name='submitEntergradesStoring'), + #new + url(r'updateGrades/', views.updateGrades, name='updateGrades'),#new + path('updateEntergrades/', views.updateEntergrades, name='updateEntergrades'),#new + path('moderate_student_grades/', views.moderate_student_grades.as_view(),#new + name='moderate_student_grades'), + # authenticate new + path('authenticate/', views.authenticate, name='authenticate'), #new + path('authenticategrades/', views.authenticategrades, + name='authenticategrades'),#new + path('update_authentication/', update_authentication.as_view(), + name='update_authentication'),#new + # generate transcript new + path('generate_transcript/', views.generate_transcript, + name='generate_transcript'), #new + path('generate_transcript_form/', views.generate_transcript_form, + name='generate_transcript_form'),#new + # Announcement + url(r'announcement/', views.announcement, name='announcement'),#new + + +] diff --git a/FusionIIIT/applications/examination/views.py b/FusionIIIT/applications/examination/views.py new file mode 100644 index 000000000..e65f34b3e --- /dev/null +++ b/FusionIIIT/applications/examination/views.py @@ -0,0 +1,752 @@ +from notifications.signals import notify +from django.views import View +from django.views.generic import View +from django.http import HttpResponse +import csv +from django.db.models import IntegerField +from django.db.models.functions import Cast +from django.db.models.query_utils import Q +from django.http import request, HttpResponse +from django.shortcuts import get_object_or_404, render, HttpResponse, redirect +from django.http import HttpResponse, HttpResponseRedirect +import itertools +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.contrib.auth.models import User +from datetime import date +import requests +from django.db.models import Q +from django.shortcuts import get_object_or_404, render, redirect +from django.contrib.auth.models import User +from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger +from applications.academic_information.models import Spi, Student, Curriculum +from applications.globals.models import (Designation, ExtraInfo, + HoldsDesignation, Faculty) +from applications.eis.models import (faculty_about, emp_research_projects) +from applications.academic_information.models import Course +from applications.academic_procedures.models import course_registration, Register +from applications.programme_curriculum.filters import CourseFilter +from notification.views import examination_notif +from applications.department.models import SpecialRequest, Announcements +from applications.globals.models import (DepartmentInfo, Designation, + ExtraInfo, Faculty, HoldsDesignation) +from jsonschema import validate +from jsonschema.exceptions import ValidationError +from django.shortcuts import render, redirect, HttpResponse +from rest_framework.views import APIView +from rest_framework.response import Response +from rest_framework import status +from .models import hidden_grades +from .forms import StudentGradeForm +from rest_framework.views import APIView +from rest_framework.response import Response +from rest_framework import status +from .models import hidden_grades, authentication +from rest_framework.permissions import AllowAny +from applications.online_cms.models import (Student_grades) + +from applications.programme_curriculum.models import Course as Courses, CourseInstructor + + +@login_required(login_url='/accounts/login') +def exam(request): + """ + This function is used to Differenciate acadadmin and all other user. + + @param: + request - contains metadata about the requested page + + @variables: + user_details - Gets the information about the logged in user. + des - Gets the designation about the looged in user. + # """ + user_details = ExtraInfo.objects.get(user=request.user) + des = HoldsDesignation.objects.all().filter(user=request.user).first() + if str(des.designation) == "Associate Professor" or str(des.designation) == "Professor" or str(des.designation) == "Assistant Professor": + return HttpResponseRedirect('/examination/updateGrades/') + elif request.session.get("currentDesignationSelected") == "acadadmin": + return HttpResponseRedirect('/examination/updateGrades/') + + return HttpResponseRedirect('/dashboard/') + + +@login_required(login_url='/accounts/login') +def submit(request): + + unique_course_ids = course_registration.objects.values( + 'course_id').distinct() + + # Cast the course IDs to integers + unique_course_ids = unique_course_ids.annotate( + course_id_int=Cast('course_id', IntegerField())) + + # Retrieve course names and course codes based on unique course IDs + courses_info = Course.objects.filter( + id__in=unique_course_ids.values_list('course_id_int', flat=True)) + + return render(request, '../templates/examination/submit.html', {'courses_info': courses_info}) + + +@login_required(login_url='/accounts/login') +def verify(request): + unique_course_ids = hidden_grades.objects.values('course_id').distinct() + + unique_course_ids = unique_course_ids.annotate( + course_id_int=Cast('course_id', IntegerField())) + + courses_info = Course.objects.filter( + id__in=unique_course_ids.values_list('course_id_int', flat=True)) + + return render(request, '../templates/examination/verify.html', {'courses_info': courses_info}) + + +@login_required(login_url='/accounts/login') +def publish(request): + return render(request, '../templates/examination/publish.html', {}) + + +@login_required(login_url='/accounts/login') +def notReady_publish(request): + return render(request, '../templates/examination/notReady_publish.html', {}) + + +@login_required(login_url='/accounts/login') +def timetable(request): + return render(request, '../templates/examination/timetable.html', {}) + + +def browse_announcements(): + """ + This function is used to browse Announcements Department-Wise + made by different faculties and admin. + + @variables: + cse_ann - Stores CSE Department Announcements + ece_ann - Stores ECE Department Announcements + me_ann - Stores ME Department Announcements + sm_ann - Stores SM Department Announcements + all_ann - Stores Announcements intended for all Departments + context - Dictionary for storing all above data + + """ + cse_ann = Announcements.objects.filter(department="CSE") + ece_ann = Announcements.objects.filter(department="ECE") + me_ann = Announcements.objects.filter(department="ME") + sm_ann = Announcements.objects.filter(department="SM") + all_ann = Announcements.objects.filter(department="ALL") + + context = { + "cse": cse_ann, + "ece": ece_ann, + "me": me_ann, + "sm": sm_ann, + "all": all_ann + } + + return context + + +def get_to_request(username): + """ + This function is used to get requests for the receiver + + @variables: + req - Contains request queryset + + """ + req = SpecialRequest.objects.filter(request_receiver=username) + return req + + +def entergrades(request): + course_id = request.GET.get('course') + semester_id = request.GET.get('semester') + + course_present = hidden_grades.objects.filter( + course_id=course_id, semester_id=semester_id) + + if (course_present): + return render(request, 'examination/all_course_grade_filled.html', {}) + + registrations = course_registration.objects.filter( + course_id__id=course_id, semester_id=semester_id) + + context = { + 'registrations': registrations + } + + return render(request, 'examination/entergrades.html', context) + + +def verifygrades(request): + course_id = request.GET.get('course') + semester_id = request.GET.get('semester') + + registrations = hidden_grades.objects.filter( + course_id=course_id, semester_id=semester_id) + + context = { + 'registrations': registrations + } + + return render(request, 'examination/verifygrades.html', context) + + +def authenticate(request): # new + # Retrieve unique course IDs from hidden_grades + unique_course_ids = Student_grades.objects.values('course_id').distinct() + + # Cast the course IDs to integers + unique_course_ids = unique_course_ids.annotate( + course_id_int=Cast('course_id', IntegerField())) + + # Retrieve course names and course codes based on unique course IDs + courses_info = Courses.objects.filter( + id__in=unique_course_ids.values_list('course_id_int', flat=True)) + working_years = Student_grades.objects.values( + 'year').distinct() + context = { + 'courses_info': courses_info, + 'working_years':working_years + + } + print(working_years) + return render(request, '../templates/examination/authenticate.html', context) + + +@login_required(login_url='/accounts/login') +def authenticategrades(request): # new + course_id = request.GET.get('course') + year = request.GET.get('year') + + print(course_id) + print(year) + + course_instance = Courses.objects.get(id=course_id) + registrations = authentication.objects.filter( + course_id=course_instance, course_year=year) + + if registrations: + # Registrations exist, pass them to the template context + context = { + 'registrations': registrations, + 'year': year + } + else: + course_instance = Courses.objects.get(id=course_id) + course_present = Student_grades.objects.filter( + course_id=course_id, year=year) + if (course_present): + authentication_object = authentication.objects.create( + course_id=course_instance, course_year=year) + registrations = authentication.objects.filter( + course_id=course_instance, course_year=year) + + context = { + 'registrations': registrations, + 'course_year': year, + } + + context = { + 'registrations': registrations, + 'year': year + } + + return render(request, 'examination/authenticategrades.html', context) + + +# def examination_notif(sender, recipient, type): +# try: +# url = 'examination:examination' +# module = 'examination' +# verb = type +# flag = "examination" + +# notify.send(sender=sender, +# recipient=recipient, +# url=url, +# module=module, +# verb=verb, +# flag=flag) + +# except Exception as e: +# print("Error sending notification:", e) + + +@login_required(login_url='/accounts/login') +def announcement(request): + """ + This function is contains data for Requests and Announcement Related methods. + Data is added to Announcement Table using this function. + + @param: + request - contains metadata about the requested page + + @variables: + usrnm, user_info, ann_maker_id - Stores data needed for maker + batch, programme, message, upload_announcement, + department, ann_date, user_info - Gets and store data from FORM used for Announcements for Students. + + """ + try: + usrnm = get_object_or_404(User, username=request.user.username) + user_info = usrnm.extrainfo + ann_maker_id = user_info.id + requests_received = get_to_request(usrnm) + + if request.method == 'POST': + batch = request.POST.get('batch', '') + programme = request.POST.get('programme', '') + message = request.POST.get('announcement', '') + upload_announcement = request.FILES.get('upload_announcement') + department = request.POST.get('department') + ann_date = date.today() + + obj1, created = Announcements.objects.get_or_create( + maker_id=user_info, + batch=batch, + programme=programme, + message=message, + upload_announcement=upload_announcement, + department=department, + ann_date=ann_date + ) + + recipients = User.objects.all() # Modify this query as per your requirements + examination_notif(sender=usrnm, recipient=recipients, type=message) + + context = browse_announcements() + return render(request, 'examination/announcement_req.html', { + "user_designation": user_info.user_type, + "announcements": context, + "request_to": requests_received + }) + except Exception as e: + + return render(request, 'examination/announcement_req.html', {"error_message": "An error occurred. Please try again later."}) + + +class Updatehidden_gradesMultipleView(APIView): + permission_classes = [AllowAny] + + def post(self, request): + student_ids = request.POST.getlist('student_ids[]') + semester_ids = request.POST.getlist('semester_ids[]') + course_ids = request.POST.getlist('course_ids[]') + grades = request.POST.getlist('grades[]') + + if len(student_ids) != len(semester_ids) != len(course_ids) != len(grades): + return Response({'error': 'Invalid grade data provided'}, status=status.HTTP_400_BAD_REQUEST) + + for student_id, semester_id, course_id, grade in zip(student_ids, semester_ids, course_ids, grades): + # Create an instance of hidden_grades model and save the data + + try: + hidden_grade = hidden_grades.objects.get( + course_id=course_id, student_id=student_id, semester_id=semester_id) + hidden_grade.grade = grade + hidden_grade.save() + except hidden_grades.DoesNotExist: + # If the grade doesn't exist, create a new one + hidden_grade = hidden_grades.objects.create( + course_id=course_id, student_id=student_id, semester_id=semester_id, grade=grade) + hidden_grade.save() + + hidden_grade.save() + + response = HttpResponse(content_type='text/csv') + response['Content-Disposition'] = 'attachment; filename="grades.csv"' + + # Write data to CSV + writer = csv.writer(response) + writer.writerow(['Student ID', 'Semester ID', 'Course ID', 'Grade']) + for student_id, semester_id, course_id, grade in zip(student_ids, semester_ids, course_ids, grades): + writer.writerow([student_id, semester_id, course_id, grade]) + + return response + return render(request, '../templates/examination/grades_updated.html', {}) + + +class Submithidden_gradesMultipleView(APIView): + permission_classes = [AllowAny] + + def post(self, request): + student_ids = request.POST.getlist('student_ids[]') + semester_ids = request.POST.getlist('semester_ids[]') + course_ids = request.POST.getlist('course_ids[]') + grades = request.POST.getlist('grades[]') + + if len(student_ids) != len(semester_ids) != len(course_ids) != len(grades): + return Response({'error': 'Invalid grade data provided'}, status=status.HTTP_400_BAD_REQUEST) + + for student_id, semester_id, course_id, grade in zip(student_ids, semester_ids, course_ids, grades): + # Create an instance of hidden_grades model and save the data + + try: + hidden_grade = hidden_grades.objects.get( + course_id=course_id, student_id=student_id, semester_id=semester_id) + hidden_grade.grade = grade + hidden_grade.save() + except hidden_grades.DoesNotExist: + # If the grade doesn't exist, create a new one + hidden_grade = hidden_grades.objects.create( + course_id=course_id, student_id=student_id, semester_id=semester_id, grade=grade) + hidden_grade.save() + + hidden_grade.save() + + return render(request, '../templates/examination/grades_updated.html', {}) + + +class update_authentication(View): + def post(self, request, *args, **kwargs): + # Extract data from the POST request + course = request.POST.get('course') + course_year = request.POST.get('course_year') + authenticator1 = request.POST.get('authenticator1') + authenticator2 = request.POST.get('authenticator2') + authenticator3 = request.POST.get('authenticator3') + + # Retrieve the registration object + try: + + course_instance = Courses.objects.get(id=course) + registration = authentication.objects.get( + course_id=course_instance, course_year=course_year) + except authentication.DoesNotExist: + # Redirect if registration does not exist + return redirect('examination:submitGrades') + + # Update authenticators if the values have changed + if authenticator1 is not None: + registration.authenticator_1 = (authenticator1 == '1') + else: + registration.authenticator_1 = 0 + if authenticator2 is not None: + registration.authenticator_2 = (authenticator2 == '1') + else: + registration.authenticator_2 = 0 + if authenticator3 is not None: + registration.authenticator_3 = (authenticator3 == '1') + else: + registration.authenticator_3 = 0 + + # Save the changes + registration.save() + + # Redirect to the appropriate page + return redirect('examination:authenticate') + + +class DownloadExcelView(View): + def post(self, request, *args, **kwargs): + # Retrieve form data + student_ids = request.POST.getlist('student_ids[]') + semester_ids = request.POST.getlist('semester_ids[]') + course_ids = request.POST.getlist('course_ids[]') + grades = request.POST.getlist('grades[]') + + # Create a CSV response + response = HttpResponse(content_type='text/csv') + response['Content-Disposition'] = 'attachment; filename="grades.csv"' + + # Write data to CSV + writer = csv.writer(response) + writer.writerow(['Student ID', 'Semester ID', 'Course ID', 'Grade']) + for student_id, semester_id, course_id, grade in zip(student_ids, semester_ids, course_ids, grades): + writer.writerow([student_id, semester_id, course_id, grade]) + + return response + + +def generate_transcript(request): + + student_id = request.GET.get('student') + semester = request.GET.get('semester') + courses_registered = Student_grades.objects.filter( + roll_no=student_id, semester=semester) + + # Initialize a dictionary to store course grades + course_grades = {} + + total_course_registered = Student_grades.objects.filter( + roll_no=student_id, semester__lte=semester) + # for each_course in total_course_registered: + # course_name = Curriculum.objects.filter( + # curriculum_id=each_course.curr_id_id) + + + + for course in courses_registered: + try: + # Attempt to fetch the grade for the course from Student_grades + grade = Student_grades.objects.get( + roll_no=student_id, course_id=course.course_id) + + # course_detail = Curriculum.objects.get( + # course_id=course.course_id, batch=grade.batch) + course_instance = Courses.objects.get(id=course.course_id_id) + check_authentication_object = authentication.objects.filter( + course_id=course_instance, course_year=grade.year) + all_authenticators_true = True + + if check_authentication_object: + # Iterate over each authentication object + for auth_obj in check_authentication_object: + # Check if all authenticators are true + if not (auth_obj.authenticator_1 and auth_obj.authenticator_2 and auth_obj.authenticator_3): + all_authenticators_true = False + break # No need to check further if any authenticator is False + else: + # Create authentication object if it doesn't exist + authentication_object = authentication.objects.create( + course_id=course_instance, course_year=grade.year) + # Get all registrations for the course and year + registrations = authentication.objects.filter( + course_id=course_instance, course_year=grade.year) + all_authenticators_true = False + + course_grades[course_instance] = { + 'grade': grade, + 'all_authenticators_true': all_authenticators_true + } # Store the grade + except Student_grades.DoesNotExist: + # Grade not available + course_grades[course] = "Grading not done yet" + + context = { + 'courses_grades': course_grades, + 'total_course_registered':total_course_registered + } + # print(context) + + return render(request, 'examination/generate_transcript.html', context) + +# new + + +def generate_transcript_form(request): + if request.method == 'POST': + programme = request.POST.get('programme') + batch = request.POST.get('batch') + specialization = request.POST.get('specialization') + semester = request.POST.get('semester') + + if specialization == None: + students = Student.objects.filter( + programme=programme, batch=batch) + else: + students = Student.objects.filter( + programme=programme, batch=batch, specialization=specialization) + + # Pass the filtered students to the template + context = { + 'students': students, + 'semester': semester + } + return render(request, 'examination/generate_transcript_students.html', context) + else: + programmes = Student.objects.values_list( + 'programme', flat=True).distinct() + specializations = Student.objects.exclude( + specialization__isnull=True).values_list('specialization', flat=True).distinct() + batches = Student.objects.values_list('batch', flat=True).distinct() + context = { + 'programmes': programmes, + 'batches': batches, + 'specializations': specializations, + } + + return render(request, 'examination/generate_transcript_form.html', context) + + +@login_required(login_url='/accounts/login') +def updateGrades(request): + unique_course_ids = Student_grades.objects.values( + 'course_id').distinct() + + # Cast the course IDs to integers + unique_course_ids = unique_course_ids.annotate( + course_id_int=Cast('course_id', IntegerField())) + + # Retrieve course names and course codes based on unique course IDs + + print(unique_course_ids) + courses_info = Courses.objects.filter( + id__in=unique_course_ids.values_list('course_id_int', flat=True)) + + unique_batch_ids = Student_grades.objects.values( + 'batch').distinct() + + context = { + 'courses_info': courses_info, + 'unique_batch_ids': unique_batch_ids, + } + + return render(request, '../templates/examination/submitGrade.html', context) + + +def updateEntergrades(request): + course_id = request.GET.get('course') + semester_id = request.GET.get('semester') + batch = request.GET.get('batch') + + course_present = Student_grades.objects.filter( + course_id=course_id, semester=semester_id, batch=batch) + + context = { + 'registrations': course_present + } + + return render(request, '../templates/examination/updateEntergrades.html', context) + + +class moderate_student_grades(APIView): + permission_classes = [AllowAny] + + def post(self, request): + student_ids = request.POST.getlist('student_ids[]') + semester_ids = request.POST.getlist('semester_ids[]') + course_ids = request.POST.getlist('course_ids[]') + grades = request.POST.getlist('grades[]') + + if len(student_ids) != len(semester_ids) != len(course_ids) != len(grades): + return Response({'error': 'Invalid grade data provided'}, status=status.HTTP_400_BAD_REQUEST) + + for student_id, semester_id, course_id, grade in zip(student_ids, semester_ids, course_ids, grades): + + try: + grade_of_student = Student_grades.objects.get( + course_id=course_id, roll_no=student_id, semester=semester_id) + grade_of_student.grade = grade + grade_of_student.save() + except Student_grades.DoesNotExist: + # If the grade doesn't exist, create a new one + hidden_grade = hidden_grades.objects.create( + course_id=course_id, student_id=student_id, semester_id=semester_id, grade=grade) + hidden_grade.save() + + response = HttpResponse(content_type='text/csv') + response['Content-Disposition'] = 'attachment; filename="grades.csv"' + + # Write data to CSV + writer = csv.writer(response) + writer.writerow(['Student ID', 'Semester ID', 'Course ID', 'Grade']) + for student_id, semester_id, course_id, grade in zip(student_ids, semester_ids, course_ids, grades): + writer.writerow([student_id, semester_id, course_id, grade]) + + return response + return render(request, '../templates/examination/grades_updated.html', {}) + + +@login_required(login_url='/accounts/login') +def submitGrades(request): + + unique_course_ids = course_registration.objects.values( + 'course_id').distinct() + working_years = course_registration.objects.values( + 'working_year').distinct() + + + + # Cast the course IDs to integers + unique_course_ids = unique_course_ids.annotate( + course_id_int=Cast('course_id', IntegerField())) + + # Retrieve course names and course codes based on unique course IDs + + print(unique_course_ids) + courses_info = Courses.objects.filter( + id__in=unique_course_ids.values_list('course_id_int', flat=True)) + + context = { + 'courses_info': courses_info, + 'working_years': working_years + } + + print(working_years) + + return render(request, '../templates/examination/gradeSubmission.html', context) + + +def submitEntergrades(request): + course_id = request.GET.get('course') + year = request.GET.get('year') + if year is None or not year.isdigit(): + message = "YEAR SHOULD NOT BE NONE" + context = { + 'message': message + } + + return render(request, '../templates/examination/message.html', context) + return HttpResponse("Invalid year parameter") + # Handle invalid year parameter + # You can return an error response or redirect the user to an error page + courses_info = Courses.objects.get(id=course_id) + + courses = Student_grades.objects.filter( + course_id=courses_info.id, year=year) + + if courses: + message = "THIS Course was Already Submitted" + context = { + 'message': message + } + + return render(request, '../templates/examination/message.html', context) + + students = course_registration.objects.filter( + course_id_id=course_id, working_year=year) + + # print(students) + + context = { + 'registrations': students, + 'curr_id': course_id, + 'year': year + } + + return render(request, '../templates/examination/gradeSubmissionForm.html', context) + + +class submitEntergradesStoring(APIView): + permission_classes = [AllowAny] + + def post(self, request): + student_ids = request.POST.getlist('student_ids[]') + batch_ids = request.POST.getlist('batch_ids[]') + course_ids = request.POST.getlist('course_ids[]') + semester_ids = request.POST.getlist('semester_ids[]') + year_ids = request.POST.getlist('year_ids[]') + marks = request.POST.getlist('marks[]') + grades = request.POST.getlist('grades[]') + + if len(student_ids) != len(batch_ids) != len(course_ids) != len(semester_ids) != len(year_ids) != len(marks) != len(grades): + return Response({'error': 'Invalid grade data provided'}, status=status.HTTP_400_BAD_REQUEST) + + for student_id, batch_id, course_id, semester_id, year_id, mark, grade in zip(student_ids, batch_ids, course_ids, semester_ids, year_ids, marks, grades): + # Create an instance of hidden_grades model and save the data + + try: + grade_of_student = Student_grades.objects.get( + course_id=course_id, roll_no=student_id, semester=semester_id) + except Student_grades.DoesNotExist: + # If the grade doesn't exist, create a new one + course_instance = Courses.objects.get(id=course_id) + student_grade = Student_grades.objects.create( + course_id=course_instance, roll_no=student_id, semester=semester_id, grade=grade, batch=batch_id, year=year_id, total_marks=mark) + student_grade.save() + + response = HttpResponse(content_type='text/csv') + response['Content-Disposition'] = 'attachment; filename="grades.csv"' + + # Write data to CSV + writer = csv.writer(response) + writer.writerow(['student_id', 'batch_ids', 'course_id', + 'semester_id', 'year_ids', 'marks', 'grade']) + for student_id, batch_id, course_id, semester_id, year_id, mark, grade in zip(student_ids, batch_ids, course_ids, semester_ids, year_ids, marks, grades): + writer.writerow([student_id, batch_id, course_id, + semester_id, year_id, mark, grade]) + + return response + return render(request, '../templates/examination/grades_updated.html', {}) diff --git a/FusionIIIT/applications/feeds/migrations/0001_initial.py b/FusionIIIT/applications/feeds/migrations/0001_initial.py index e989d0101..7b794eac6 100644 --- a/FusionIIIT/applications/feeds/migrations/0001_initial.py +++ b/FusionIIIT/applications/feeds/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.1.5 on 2024-04-15 23:58 +# Generated by Django 3.1.5 on 2024-07-16 15:44 from django.conf import settings from django.db import migrations, models diff --git a/FusionIIIT/applications/filetracking/admin.py b/FusionIIIT/applications/filetracking/admin.py index 144ac4e2a..af7ed0d4b 100644 --- a/FusionIIIT/applications/filetracking/admin.py +++ b/FusionIIIT/applications/filetracking/admin.py @@ -3,7 +3,7 @@ class FileAdmin(admin.ModelAdmin): - list_display = ('uploader', 'designation', + list_display = ('id', 'uploader', 'designation', 'subject', 'upload_date', 'is_read') search_fields = ('uploader__user__username', 'subject', 'description') list_filter = ('is_read',) diff --git a/FusionIIIT/applications/filetracking/api/urls.py b/FusionIIIT/applications/filetracking/api/urls.py index 139f965ff..0d8ecad38 100644 --- a/FusionIIIT/applications/filetracking/api/urls.py +++ b/FusionIIIT/applications/filetracking/api/urls.py @@ -9,6 +9,8 @@ DraftFileView, CreateDraftFile, GetDesignationsView, + CreateArchiveFile, + ArchiveFileView ) urlpatterns = [ @@ -20,5 +22,7 @@ url(r'^forwardfile/(?P\d+)/$', ForwardFileView.as_view(), name='forward_file'), url(r'^draft/$', DraftFileView.as_view(), name='view_drafts'), url(r'^createdraft/$', CreateDraftFile.as_view(), name='create_draft'), + url(r'^createarchive/$', CreateArchiveFile.as_view(), name='archive_file'), + url(r'^archive/$', ArchiveFileView.as_view(), name='view_archived'), url(r'^designations/(?P\w+)/$', GetDesignationsView.as_view(), name='get_designations'), ] diff --git a/FusionIIIT/applications/filetracking/api/views.py b/FusionIIIT/applications/filetracking/api/views.py index 5f395ab41..53daaf425 100644 --- a/FusionIIIT/applications/filetracking/api/views.py +++ b/FusionIIIT/applications/filetracking/api/views.py @@ -1,12 +1,14 @@ import logging from venv import logger from django.forms import ValidationError +from django.contrib.auth.models import User from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status, permissions from rest_framework.authentication import TokenAuthentication from ..models import File, Tracking -from ..sdk.methods import create_draft, create_file, view_drafts, view_file, delete_file, view_inbox, view_outbox, view_history, forward_file, get_designations +from applications.globals.models import Designation +from ..sdk.methods import create_draft, create_file, view_drafts, view_file, delete_file, view_inbox, view_outbox, view_history, forward_file, get_designations, archive_file, view_archived class CreateFileView(APIView): authentication_classes = [TokenAuthentication] @@ -21,11 +23,13 @@ def post(self, request): subject = request.data.get('subject') description = request.data.get('description') + uploaded_file = request.FILES.get('file') # Get the file if provided + if None in [current_designation, receiver_username, receiver_designation, subject, description]: return Response({'error': 'One or more required fields are missing.'}, status=status.HTTP_400_BAD_REQUEST) file_id = create_file(uploader=current_user, uploader_designation=current_designation, - receiver=receiver_username, receiver_designation=receiver_designation, subject=subject, description=description) + receiver=receiver_username, receiver_designation=receiver_designation, subject=subject, description=description, attached_file=uploaded_file) return Response({'file_id': file_id}, status=status.HTTP_201_CREATED) except Exception as e: @@ -145,15 +149,21 @@ def get(self, request, file_id): Returns: rest_framework.response.Response: JSON response containing serialized tracking history. """ - try: - history = view_history(file_id) - return Response(history) + tracking_array = [] + histories = view_history(file_id) + for history in histories: + temp_obj_action = history; + temp_obj_action['receiver_id'] = User.objects.get(id=history['receiver_id']).username + temp_obj_action['receive_design'] = Designation.objects.get(id=history['receive_design']).name + tracking_array.append(temp_obj_action) + + return Response(tracking_array) except Tracking.DoesNotExist: - return Response({'error': f'File with ID {file_id} not found.'}, status=404) + return Response({'error': f'File with ID {file_id} not found.'}, status=404) except Exception as e: - logger.error(f"An unexpected error occurred: {e}") - return Response({'error': 'Internal server error.'}, status=500) + logger.error(f"An unexpected error occurred: {e}") + return Response({'error': 'Internal server error.'}, status=500) class ForwardFileView(APIView): # # # Authentication and permission classes (adjust based on your needs) @@ -235,6 +245,41 @@ def get(self, request): return Response(draft_files, status=status.HTTP_200_OK) except Exception as e: return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + +class ArchiveFileView(APIView): + authentication_classes = [TokenAuthentication] + permission_classes = [permissions.IsAuthenticated] + + def get(self, request): + username = request.query_params.get('username') + designation = request.query_params.get('designation', '') + src_module = request.query_params.get('src_module') + try: + archived_files = view_archived(username, designation, src_module) + return Response(archived_files, status=status.HTTP_200_OK) + except Exception as e: + return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + +class CreateArchiveFile(APIView): + authentication_classes = [TokenAuthentication] + permission_classes = [permissions.IsAuthenticated] + + def post(self, request): + file_id = request.data.get('file_id', None) + + if file_id is None: + return Response({'error': 'Missing file_id'}, status=status.HTTP_400_BAD_REQUEST) + + try: + success = archive_file(file_id) + if success: + return Response({'success': True}) + else: + return Response({'error': 'File does not exist'}, status=status.HTTP_404_NOT_FOUND) + + except Exception as e: + return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) diff --git a/FusionIIIT/applications/filetracking/migrations/0001_initial.py b/FusionIIIT/applications/filetracking/migrations/0001_initial.py index 3375630f7..56a210012 100644 --- a/FusionIIIT/applications/filetracking/migrations/0001_initial.py +++ b/FusionIIIT/applications/filetracking/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.1.5 on 2024-04-15 23:58 +# Generated by Django 3.1.5 on 2024-07-16 15:44 from django.conf import settings from django.db import migrations, models @@ -10,8 +10,8 @@ class Migration(migrations.Migration): initial = True dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('globals', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ diff --git a/FusionIIIT/applications/filetracking/sdk/methods.py b/FusionIIIT/applications/filetracking/sdk/methods.py index 0ea167fc6..7bb56763e 100644 --- a/FusionIIIT/applications/filetracking/sdk/methods.py +++ b/FusionIIIT/applications/filetracking/sdk/methods.py @@ -108,7 +108,7 @@ def view_inbox(username: str, designation: str, src_module: str) -> list: receiver_id=recipient_object, receive_design=user_designation, file_id__src_module=src_module, - file_id__is_read=False).order_by('receive_date'); + file_id__is_read=False).order_by('-receive_date'); received_files = [tracking.file_id for tracking in received_files_tracking] # remove duplicate file ids (from sending back and forth) @@ -120,7 +120,6 @@ def view_inbox(username: str, designation: str, src_module: str) -> list: for file in received_files_serialized: file['sent_by_user'] = get_last_file_sender(file['id']).username file['sent_by_designation'] = get_last_file_sender_designation(file['id']).name - return received_files_serialized @@ -168,7 +167,7 @@ def view_archived(username: str, designation: str, src_module: str) -> dict: current_id=sender_ExtraInfo_object, current_design=user_HoldsDesignation_object, file_id__src_module=src_module, - file_id__is_read=True) + file_id__is_read=True).order_by('-receive_date') archived_tracking = received_archived_tracking | sent_archived_tracking archived_files = [tracking.file_id for tracking in archived_tracking] @@ -237,7 +236,7 @@ def view_drafts(username: str, designation: str, src_module: str) -> dict: user_designation = Designation.objects.get(name=designation) user_ExtraInfo_object = get_ExtraInfo_object_from_username(username) draft_files = File.objects.filter( - tracking__isnull=True, uploader=user_ExtraInfo_object, designation=user_designation, src_module=src_module) + tracking__isnull=True, uploader=user_ExtraInfo_object, designation=user_designation, src_module=src_module).order_by('-upload_date') draft_files_serialized = FileHeaderSerializer(draft_files, many=True) return draft_files_serialized.data diff --git a/FusionIIIT/applications/filetracking/urls.py b/FusionIIIT/applications/filetracking/urls.py index a451738de..7b56041a6 100644 --- a/FusionIIIT/applications/filetracking/urls.py +++ b/FusionIIIT/applications/filetracking/urls.py @@ -11,9 +11,9 @@ url(r'^draftdesign/$', views.draft_design, name='draft_design'), url(r'^drafts/(?P\d+)$', views.drafts_view, name='drafts_view'), url(r'^outbox/(?P\d+)$', views.outbox_view, name='outbox_view'), - url(r'^inbox/(?P\d+)$', views.inbox_view, name='inbox_view'), - url(r'^outward/$', views.outward, name='outward'), - url(r'^inward/$', views.inward, name='inward'), + url(r'^inbox/$', views.inbox_view, name='inbox_view'), + url(r'^outward/$', views.outbox_view, name='outward'), + url(r'^inward/$', views.inbox_view, name='inward'), url(r'^confirmdelete/(?P\d+)$', views.confirmdelete, name='confirm_delete'), url(r'^archive/(?P\d+)/$', views.archive_view, name='archive_view'), @@ -22,7 +22,6 @@ url(r'^forward/(?P\d+)/$', views.forward, name='forward'), url(r'^ajax/$', views.AjaxDropdown1, name='ajax_dropdown1'), url(r'^ajax_dropdown/$', views.AjaxDropdown, name='ajax_dropdown'), - url(r'^test/$', views.test, name='test'), url(r'^delete/(?P\d+)$', views.delete, name='delete'), url(r'^forward_inward/(?P\d+)/$', views.forward_inward, name='forward_inward'), @@ -39,9 +38,9 @@ views.unarchive_file, name='unarchive'), url(r'^getdesignations/(?P\w+)/$', views.get_designations_view, name="get_user_designations"), url(r'^editdraft/(?P\w+)/$', views.edit_draft_view, name="edit_draft"), + url(r'^download_file/(?P\w+)/$', views.download_file, name="download_file"), # REST api urls url(r'^api/', include(urls)) ] - diff --git a/FusionIIIT/applications/filetracking/views.py b/FusionIIIT/applications/filetracking/views.py index a01d71ac1..0bba0d9a1 100644 --- a/FusionIIIT/applications/filetracking/views.py +++ b/FusionIIIT/applications/filetracking/views.py @@ -1,21 +1,33 @@ -from django.contrib import messages -from django.shortcuts import render, get_object_or_404, redirect -from .models import File, Tracking -from applications.globals.models import ExtraInfo, HoldsDesignation, Designation -from django.template.defaulttags import csrf_token +from sqlite3 import IntegrityError from django.http import HttpResponse, HttpResponseRedirect, JsonResponse +from django.contrib import messages +from django.shortcuts import render, get_object_or_404, redirect, reverse from django.contrib.auth.decorators import login_required -from django.db import IntegrityError from django.core import serializers from django.contrib.auth.models import User -from django.http import JsonResponse -from timeit import default_timer as time -from notification.views import office_module_notif, file_tracking_notif -from .utils import * +from django.views.decorators.http import require_POST +from django.utils import timezone from django.utils.dateparse import parse_datetime +from django.core.paginator import Paginator + +from .models import File, Tracking +from applications.globals.models import ExtraInfo, HoldsDesignation, Designation +from .utils import * from .sdk.methods import * from .decorators import * +from datetime import datetime; + +from timeit import default_timer as time +from notification.views import office_module_notif, file_tracking_notif + +import io +from reportlab.lib.pagesizes import letter +from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image +from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle + import json +import zipfile +import os @login_required(login_url="/accounts/login/") @@ -43,7 +55,6 @@ def filetracking(request): context - Holds data needed to make necessary changes in the template. """ - if request.method == "POST": try: if 'save' in request.POST: @@ -59,8 +70,9 @@ def filetracking(request): request, "File should not be greater than 10MB") return redirect("/filetracking") + form_remarks = request.POST.get('remarks') extraJSON = { - 'remarks': request.POST.get('remarks'), + 'remarks': form_remarks if form_remarks is not None else '', } File.objects.create( @@ -111,7 +123,6 @@ def filetracking(request): return redirect('/filetracking/') receive = request.POST.get('receive') try: - print(receive) receive_design = Designation.objects.get(name=receive) except Exception as e: messages.error(request, 'Enter a valid Designation') @@ -128,7 +139,6 @@ def filetracking(request): remarks=remarks, upload_file=upload_file, ) - # office_module_notif(request.user, receiver_id) file_tracking_notif(request.user, receiver_id, subject) messages.success(request, 'File sent successfully') @@ -157,12 +167,15 @@ def filetracking(request): 'holdsdesignations': holdsdesignations, 'designation_name': designation_name, 'designation_id': designation_id, - 'notifications': request.user.notifications.all() + 'notifications': request.user.notifications.all(), + 'path_parent': 'compose' } return render(request, 'filetracking/composefile.html', context) @login_required(login_url="/accounts/login") +@user_is_student +@dropdown_designation_valid def draft_design(request): """ This function redirects the user to the drafts page of designation selected in dropdown @@ -180,6 +193,8 @@ def draft_design(request): @login_required(login_url="/accounts/login") +@user_is_student +@dropdown_designation_valid def drafts_view(request, id): """ This function is used to view all the drafts created by the user ordered by upload date.it collects all the created files from File object. @@ -192,9 +207,6 @@ def drafts_view(request, id): draft - file obeject containing all the files created by user context - holds data needed to render the template - - - """ user_HoldsDesignation_obj = HoldsDesignation.objects.select_related( 'user', 'working', 'designation').get(pk=id) @@ -216,31 +228,33 @@ def drafts_view(request, id): context = { 'draft_files': draft_files, 'designations': designation, - 'notifications': request.user.notifications.all() + 'notifications': request.user.notifications.all(), + 'path_parent': 'draft' } return render(request, 'filetracking/drafts.html', context) @login_required(login_url="/accounts/login") -def outbox_view(request, id): +@user_is_student +@dropdown_designation_valid +def outbox_view(request): """ - The function is used to get all the files sent by user(employee) to other employees - which are filtered from Tracking(table) objects by current user i.e. current_id. - It displays files sent by user to other employees of a Tracking(table) of filetracking(model) - in the 'Outbox' tab of template. - - @param: - request - trivial. - id - user id - - @variables: - outward_files - File objects filtered by current_id i.e, present working user. - context - Holds data needed to make necessary changes in the template. + The function is used to get all the files sent by user(employee) to other employees + which are filtered from Tracking(table) objects by current user i.e. current_id. + It displays files sent by user to other employees of a Tracking(table) of filetracking(model) + in the 'Outbox' tab of template. + @param: + request - trivial. + id - user id + @variables: + outward_files - File objects filtered by current_id i.e, present working user. + context - Holds data needed to make necessary changes in the template. """ - user_HoldsDesignation_obj = HoldsDesignation.objects.select_related( - 'user', 'working', 'designation').get(pk=id) + dropdown_design = request.session.get('currentDesignationSelected', 'default_value') + username = request.user + user_HoldsDesignation_obj = get_HoldsDesignation_obj(username, dropdown_design) s = str(user_HoldsDesignation_obj).split(" - ") designation = s[1] @@ -255,26 +269,41 @@ def outbox_view(request, id): f['sent_to_user'] = last_forw_tracking.receiver_id f['sent_to_design'] = last_forw_tracking.receive_design f['last_sent_date'] = last_forw_tracking.forward_date - f['upload_date'] = parse_datetime(f['upload_date']) f['uploader'] = get_extra_info_object_from_id(f['uploader']) - outward_files = add_uploader_department_to_files_list(outward_files) - user_HoldsDesignation_obj = HoldsDesignation.objects.select_related( - 'user', 'working', 'designation').get(pk=id) - s = str(user_HoldsDesignation_obj).split(" - ") - designation = s[1] + subject_query = request.GET.get('subject', '') + sent_to_query = request.GET.get('sent_to', '') + date_query = request.GET.get('date', '') + + if subject_query: + outward_files = [f for f in outward_files if subject_query.lower() in f['subject'].lower()] + if sent_to_query: + outward_files = [f for f in outward_files if sent_to_query.lower() in f['sent_to_user'].username.lower()] + if date_query: + try: + search_date = datetime.strptime(date_query, '%Y-%m-%d') + outward_files = [f for f in outward_files if f['last_sent_date'].date() == search_date.date()] + except ValueError: + outward_files = [] # Invalid date format + + paginator = Paginator(outward_files, 10) + page_number = request.GET.get('page') + page_obj = paginator.get_page(page_number) context = { - 'out_files': outward_files, + 'page_obj': page_obj, 'viewer_designation': designation, - 'notifications': request.user.notifications.all() + 'notifications': request.user.notifications.all(), + 'path_parent': 'outbox', } return render(request, 'filetracking/outbox.html', context) @login_required(login_url="/accounts/login") -def inbox_view(request, id): +@user_is_student +@dropdown_designation_valid +def inbox_view(request): """ The function is used to fetch the files received by the user form other employees. These files are filtered by receiver id and ordered by receive date. @@ -288,9 +317,11 @@ def inbox_view(request, id): context - Holds data needed to make necessary changes in the template. """ - - user_HoldsDesignation_obj = HoldsDesignation.objects.select_related( - 'user', 'working', 'designation').get(pk=id) + dropdown_design = request.session.get( + 'currentDesignationSelected', 'default_value') + username = request.user + user_HoldsDesignation_obj = get_HoldsDesignation_obj( + username, dropdown_design) s = str(user_HoldsDesignation_obj).split(" - ") designation = s[1] inward_files = view_inbox( @@ -308,18 +339,42 @@ def inbox_view(request, id): designation=user_HoldsDesignation_obj.designation) f['receive_date'] = last_recv_tracking.receive_date f['uploader'] = get_extra_info_object_from_id(f['uploader']) + f['is_forwarded'] = (False if (str(get_current_file_owner(f['id']).username) == str(user_HoldsDesignation_obj.user)) else True) + inward_files = add_uploader_department_to_files_list(inward_files) + subject_query = request.GET.get('subject', '') + sent_to_query = request.GET.get('sent_to', '') + date_query = request.GET.get('date', '') + + if subject_query: + inward_files = [f for f in inward_files if subject_query.lower() in f['subject'].lower()] + if sent_to_query: + inward_files = [f for f in inward_files if sent_to_query.lower() in f['sent_to_user'].username.lower()] + if date_query: + try: + search_date = datetime.strptime(date_query, '%Y-%m-%d') + inward_files = [f for f in inward_files if f['last_sent_date'].date() == search_date.date()] + except ValueError: + inward_files = [] # Invalid date format + + paginator = Paginator(inward_files, 10) + page_number = request.GET.get('page') + page_obj = paginator.get_page(page_number) + context = { - 'in_file': inward_files, + 'page_obj': page_obj, 'designations': designation, - 'notifications': request.user.notifications.all() + 'notifications': request.user.notifications.all(), + 'path_parent': 'inbox' } return render(request, 'filetracking/inbox.html', context) @login_required(login_url="/accounts/login") +@user_is_student +@dropdown_designation_valid def outward(request): """ This function redirects the user to the outbox page of designation selected in dropdown @@ -339,6 +394,8 @@ def outward(request): @login_required(login_url="/accounts/login") +@user_is_student +@dropdown_designation_valid def inward(request): """ This function redirects the user to the inbox page of designation selected in dropdown @@ -356,6 +413,8 @@ def inward(request): @login_required(login_url = "/accounts/login") +@user_is_student +@dropdown_designation_valid def confirmdelete(request,id): """ The function is used to confirm the deletion of a file. @@ -376,6 +435,8 @@ def confirmdelete(request,id): return render(request, 'filetracking/confirmdelete.html', context) @login_required(login_url="/accounts/login") +@user_is_student +@dropdown_designation_valid def view_file(request, id): ''' This function is used to view a particular file received by an employee from another. @@ -411,30 +472,35 @@ def view_file(request, id): current_owner = get_current_file_owner(file.id) file_uploader = get_user_object_from_username(file.uploader.user.username) + last_receiver_designation = get_current_file_owner_designation(file.id).name if current_owner == request.user and file.is_read is False: forward_enable = True - if current_owner == request.user and file_uploader == request.user and file.is_read is False: + if current_owner == request.user and last_receiver_designation == file.designation.name and file_uploader == request.user and file.is_read is False: archive_enable = True + parent_of_prev_path = request.META.get('HTTP_REFERER').strip("/").split('/')[-2] context = { 'designations': designations, 'file': file, 'track': track, 'forward_enable': forward_enable, 'archive_enable': archive_enable, - 'notifications': request.user.notifications.all() + 'notifications': request.user.notifications.all(), + 'path_parent': parent_of_prev_path } return render(request, 'filetracking/viewfile.html', context) @login_required(login_url="/accounts/login") +@user_is_student +@dropdown_designation_valid def archive_file(request, id): '''This function is used to archive a file. It returns unauthorized access if the user is not file uploader and the current owner of the file ''' if request.method == "POST": - file = get_object_or_404(File, id=id); + file = get_object_or_404(File, id=id) current_owner = get_current_file_owner(file.id) file_uploader = get_user_object_from_username(file.uploader.user.username) if current_owner == request.user and file_uploader == request.user: @@ -447,6 +513,8 @@ def archive_file(request, id): return render(request, 'filetracking/composefile.html') @login_required(login_url="/accounts/login") +@user_is_student +@dropdown_designation_valid def forward(request, id): """ The function is used to forward files received by user(employee) from other @@ -477,6 +545,16 @@ def forward(request, id): track = Tracking.objects.select_related('file_id__uploader__user', 'file_id__uploader__department', 'file_id__designation', 'current_id__user', 'current_id__department', 'current_design__user', 'current_design__working', 'current_design__designation', 'receiver_id', 'receive_design').filter(file_id=file).order_by('receive_date') + designations = get_designation(request.user) + + designation_name = request.session.get('currentDesignationSelected', 'default_value') + all_available_designations = request.session.get( + 'allDesignations', 'default_value2') + + username = request.user + designation_id = get_HoldsDesignation_obj( + username, designation_name).id + if request.method == "POST": if 'finish' in request.POST: file.is_read = True @@ -499,11 +577,15 @@ def forward(request, id): 'user', 'working', 'designation').filter(user=request.user) context = { - 'designations': designations, 'file': file, 'track': track, + 'designation_name': designation_name, + 'designation_id': designation_id, + 'notifications': request.user.notifications.all(), + 'path_parent': 'inbox' } + return render(request, 'filetracking/forward.html', context) receive = request.POST.get('receive') try: @@ -513,11 +595,15 @@ def forward(request, id): designations = get_designation(request.user) context = { - 'designations': designations, 'file': file, 'track': track, + 'designation_name': designation_name, + 'designation_id': designation_id, + 'notifications': request.user.notifications.all(), + 'path_parent': 'inbox' } + return render(request, 'filetracking/forward.html', context) upload_file = request.FILES.get('myfile') @@ -531,18 +617,9 @@ def forward(request, id): remarks=remarks, upload_file=upload_file, ) + file_tracking_notif(request.user, receiver_id, file.subject) messages.success(request, 'File sent successfully') - - designations = get_designation(request.user) - - designation_name = request.session.get('currentDesignationSelected', 'default_value') - all_available_designations = request.session.get( - 'allDesignations', 'default_value2') - - username = request.user - designation_id = get_HoldsDesignation_obj( - username, designation_name).id - + return redirect(reverse('filetracking:filetracking')) context = { 'designations': designations, @@ -550,14 +627,16 @@ def forward(request, id): 'track': track, 'designation_name': designation_name, 'designation_id': designation_id, - - 'notifications': request.user.notifications.all() + 'notifications': request.user.notifications.all(), + 'path_parent': 'inbox' } return render(request, 'filetracking/forward.html', context) @login_required(login_url="/accounts/login") +@user_is_student +@dropdown_designation_valid def archive_design(request): """ This function redirects the user to the archive page of designation selected in dropdown @@ -575,6 +654,8 @@ def archive_design(request): @login_required(login_url="/accounts/login") +@user_is_student +@dropdown_designation_valid def archive_view(request, id): """ The function is used to fetch the files in the user's archive @@ -611,15 +692,17 @@ def archive_view(request, id): context = { 'archive_files': archive_files, 'designations': designation, - 'notifications': request.user.notifications.all() + 'notifications': request.user.notifications.all(), + 'path_parent': 'archive' } return render(request, 'filetracking/archive.html', context) @login_required(login_url="/accounts/login") +@user_is_student +@dropdown_designation_valid def archive_finish(request, id): - # file = get_object_or_404(File, ref_id=id) file1 = get_object_or_404(File, id=id) track = Tracking.objects.filter(file_id=file1) @@ -627,6 +710,8 @@ def archive_finish(request, id): @login_required(login_url="/accounts/login") +@user_is_student +@dropdown_designation_valid def finish_design(request): designation = HoldsDesignation.objects.select_related( @@ -640,6 +725,8 @@ def finish_design(request): @login_required(login_url="/accounts/login") +@user_is_student +@dropdown_designation_valid def finish_fileview(request, id): out = Tracking.objects.select_related('file_id__uploader__user', 'file_id__uploader__department', 'file_id__designation', 'current_id__user', 'current_id__department', @@ -658,6 +745,8 @@ def finish_fileview(request, id): @login_required(login_url="/accounts/login") +@user_is_student +@dropdown_designation_valid def finish(request, id): # file = get_object_or_404(File, ref_id=id) file1 = get_object_or_404(File, id=id) @@ -669,14 +758,19 @@ def finish(request, id): track.update(is_read=True) messages.success(request, 'File Archived') - return render(request, 'filetracking/finish.html', {'file': file1, 'track': track, 'fileid': id, - 'notifications': request.user.notifications.all()}) + context = { + 'file': file1, + 'track': track, + 'fileid': id, + 'notifications': request.user.notifications.all() + } + return render(request, 'filetracking/finish.html', ) def AjaxDropdown1(request): """ - This function returns the designation of receiver on the forward or compose file template. + This function returns the designation of receiver on the forward or compose file template. @param: request - trivial. @@ -699,7 +793,7 @@ def AjaxDropdown1(request): def AjaxDropdown(request): """ - This function returns the usernames of receiver on the forward or compose file template. + This function returns the usernames of receiver on the forward or compose file template. @param: request - trivial. @@ -719,12 +813,10 @@ def AjaxDropdown(request): return HttpResponse(JsonResponse(context), content_type='application/json') -def test(request): - return HttpResponse('success') - - @login_required(login_url = "/accounts/login") +@user_is_student +@dropdown_designation_valid def delete(request,id): """ The function is used the delete of a file and it returns to the drafts page. @@ -739,6 +831,8 @@ def delete(request,id): return redirect('/filetracking/draftdesign/') +@user_is_student +@dropdown_designation_valid def forward_inward(request,id): """ This function is used forward the files which are available in the inbox of the user . @@ -787,6 +881,8 @@ def unarchive_file(request, id): @login_required(login_url="/accounts/login") +@user_is_student +@dropdown_designation_valid def edit_draft_view(request, id, *args, **kwargs): """ The function is used to edit and send drafted files, and also alter their title and subject @@ -843,7 +939,8 @@ def edit_draft_view(request, id, *args, **kwargs): 'track': track, 'notifications': request.user.notifications.all() } - return render(request, 'filetracking/editdraft.html', context) + return redirect(reverse('filetracking:filetracking')) + receive = request.POST.get('receive') try: receive_design = Designation.objects.get(name=receive) @@ -857,10 +954,18 @@ def edit_draft_view(request, id, *args, **kwargs): 'file': file, 'notifications': request.user.notifications.all() } - return render(request, 'filetracking/editdraft.html', context) + return redirect(reverse('filetracking:filetracking')) upload_file = request.FILES.get('myfile') + if upload_file is None and file.upload_file is not None: + upload_file = file.upload_file + + # since frontend isnt reflecting uploaded file in edit draft, but upload_file may exist in File + # (this feature isnt working atm, duplicate is still stored) + #if upload_file == file.upload_file: + # upload_file = None + Tracking.objects.create( file_id=file, current_id=current_id, @@ -870,7 +975,10 @@ def edit_draft_view(request, id, *args, **kwargs): remarks=remarks, upload_file=upload_file, ) + + file_tracking_notif(request.user, receiver_id, subject) messages.success(request, 'File sent successfully') + return render(request, 'filetracking/composefile.html') designations = get_designation(request.user) @@ -903,4 +1011,63 @@ def edit_draft_view(request, id, *args, **kwargs): return render(request, 'filetracking/editdraft.html', context) - +@login_required(login_url="/accounts/login/") +@user_is_student +@dropdown_designation_valid +@require_POST +def download_file(request, id): + file = get_object_or_404(File, id=id) + track = Tracking.objects.select_related('file_id__uploader__user', 'file_id__uploader__department', 'file_id__designation', 'current_id__user', 'current_id__department', + 'current_design__user', 'current_design__working', 'current_design__designation', 'receiver_id', 'receive_design').filter(file_id=id).order_by('receive_date') + + buffer = io.BytesIO() + doc = SimpleDocTemplate(buffer, pagesize=letter) + elements = [] + styles = getSampleStyleSheet() + style_heading = styles['Heading1'] + style_paragraph = styles['BodyText'] + + elements.append( + Paragraph(f"
Subject - {file.subject}
", style_heading)) + elements.append(Spacer(1, 12)) + elements.append( + Paragraph(f"Description: {file.description}", style_paragraph)) + elements.append(Spacer(1, 12)) + + for t in track: + sent_by = f"Sent by: {t.current_design} - {t.forward_date.strftime('%B %d, %Y %I:%M %p')}" + received_by = f"Received by: {t.receiver_id} - {t.receive_design}" + combined_info = f"{sent_by}       {received_by}" + elements.append(Paragraph(combined_info, style_paragraph)) + elements.append(Spacer(1, 12)) + remarks = f"Remarks: {t.remarks}" if t.remarks else "Remarks: No Remarks" + elements.append(Paragraph(remarks, style_paragraph)) + elements.append(Spacer(1, 12)) + attachment = f"Attachment: {os.path.basename(t.upload_file.name)}" if t.upload_file else "Attachment: No attachments" + elements.append(Paragraph(attachment, style_paragraph)) + elements.append(Paragraph('
', style_paragraph)) + elements.append(Spacer(2, 12)) + + doc.build(elements) + pdf_data = buffer.getvalue() + buffer.close() + + formal_filename = f'{file.uploader.department.name}-{file.upload_date.year}-{file.upload_date.month}-#{file.id}' + output_filename = f'iiitdmj-fts-{formal_filename}' + + zip_buffer = io.BytesIO() + with zipfile.ZipFile(zip_buffer, 'w') as zip_file: + pdf_filename = f'{file.uploader.department.name}-{file.upload_date.year}-{file.upload_date.month}-#{file.id}-notesheet.pdf' + zip_file.writestr(output_filename+'.pdf', pdf_data) + for t in track: + if t.upload_file: + zip_file.write(t.upload_file.path, + os.path.basename(t.upload_file.name)) + + zip_data = zip_buffer.getvalue() + zip_buffer.close() + + response = HttpResponse(zip_data, content_type='application/zip') + response['Content-Disposition'] = f'attachment; filename="{output_filename}.zip"' + + return response diff --git a/FusionIIIT/applications/finance_accounts/migrations/0001_initial.py b/FusionIIIT/applications/finance_accounts/migrations/0001_initial.py index 8d45f1fc1..7bcb45aba 100644 --- a/FusionIIIT/applications/finance_accounts/migrations/0001_initial.py +++ b/FusionIIIT/applications/finance_accounts/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.1.5 on 2024-04-15 23:58 +# Generated by Django 3.1.5 on 2024-07-16 15:44 from django.db import migrations, models diff --git a/FusionIIIT/applications/globals/admin.py b/FusionIIIT/applications/globals/admin.py index 8ee73973e..ba595e235 100644 --- a/FusionIIIT/applications/globals/admin.py +++ b/FusionIIIT/applications/globals/admin.py @@ -1,7 +1,7 @@ from django.contrib import admin from .models import (DepartmentInfo, Designation, ExtraInfo, Faculty, Feedback, - HoldsDesignation, Issue, IssueImage, Staff) + HoldsDesignation, Issue, IssueImage, Staff,ModuleAccess) # Register your models here. @@ -22,4 +22,5 @@ class HoldsDesignationAdmin(admin.ModelAdmin): admin.site.register(Faculty) admin.site.register(DepartmentInfo) admin.site.register(Designation) +admin.site.register(ModuleAccess) admin.site.register(HoldsDesignation, HoldsDesignationAdmin) diff --git a/FusionIIIT/applications/globals/api/urls.py b/FusionIIIT/applications/globals/api/urls.py index 9f4e6c2b5..e6683eac7 100644 --- a/FusionIIIT/applications/globals/api/urls.py +++ b/FusionIIIT/applications/globals/api/urls.py @@ -7,6 +7,7 @@ url(r'^auth/login/', views.login, name='login-api'), url(r'^auth/logout/', views.logout, name='logout-api'), # generic profile endpoint + #code of corresponding view is modifiedtemporary because of mismatched designations url(r'^profile/(?P.+)/', views.profile, name='profile-api'), # current user profile url(r'^profile/', views.profile, name='profile-api'), diff --git a/FusionIIIT/applications/globals/api/views.py b/FusionIIIT/applications/globals/api/views.py index c6723d0ab..c8fd9f5b1 100644 --- a/FusionIIIT/applications/globals/api/views.py +++ b/FusionIIIT/applications/globals/api/views.py @@ -117,6 +117,9 @@ def profile(request, username=None): user = get_object_or_404(User, username=username) if username else request.user user_detail = serializers.UserSerializer(user).data profile = serializers.ExtraInfoSerializer(user.extrainfo).data + + print(user) + if profile['user_type'] == 'student': student = user.extrainfo.student skills = serializers.HasSerializer(student.has_set.all(),many=True).data @@ -143,6 +146,7 @@ def profile(request, username=None): } return Response(data=resp, status=status.HTTP_200_OK) elif profile['user_type'] == 'faculty': + print(username) return redirect('/eis/api/profile/' + (username+'/' if username else '')) elif profile['user_type'] == 'staff': resp = { diff --git a/FusionIIIT/applications/globals/migrations/0001_initial.py b/FusionIIIT/applications/globals/migrations/0001_initial.py index 7fc43ccef..f67ff0834 100644 --- a/FusionIIIT/applications/globals/migrations/0001_initial.py +++ b/FusionIIIT/applications/globals/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.1.5 on 2024-04-15 23:58 +# Generated by Django 3.1.5 on 2024-07-16 15:44 import applications.globals.models import datetime @@ -106,7 +106,7 @@ class Migration(migrations.Migration): ('working', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='current_designation', to=settings.AUTH_USER_MODEL)), ], options={ - 'unique_together': {('working', 'designation'), ('user', 'designation')}, + 'unique_together': {('user', 'designation'), ('working', 'designation')}, }, ), - ] + ] \ No newline at end of file diff --git a/FusionIIIT/applications/globals/models.py b/FusionIIIT/applications/globals/models.py index d51fbcb69..bc95a3042 100644 --- a/FusionIIIT/applications/globals/models.py +++ b/FusionIIIT/applications/globals/models.py @@ -310,3 +310,30 @@ class Issue(models.Model): """ End of feedback and bug report models""" + + + +class ModuleAccess(models.Model): + designation = models.CharField(max_length=155) + program_and_curriculum = models.BooleanField(default=False) + course_registration = models.BooleanField(default=False) + course_management = models.BooleanField(default=False) + other_academics = models.BooleanField(default=False) + spacs = models.BooleanField(default=False) + department = models.BooleanField(default=False) + examinations = models.BooleanField(default=False) + hr = models.BooleanField(default=False) + iwd = models.BooleanField(default=False) + complaint_management = models.BooleanField(default=False) + fts = models.BooleanField(default=False) + purchase_and_store = models.BooleanField(default=False) + rspc = models.BooleanField(default=False) + hostel_management = models.BooleanField(default=False) + mess_management = models.BooleanField(default=False) + gymkhana = models.BooleanField(default=False) + placement_cell = models.BooleanField(default=False) + visitor_hostel = models.BooleanField(default=False) + phc = models.BooleanField(default=False) + + def __str__(self): + return self.designation diff --git a/FusionIIIT/applications/globals/static/globals/img/Designer.jpg b/FusionIIIT/applications/globals/static/globals/img/Designer.jpg new file mode 100644 index 000000000..ee8305b77 Binary files /dev/null and b/FusionIIIT/applications/globals/static/globals/img/Designer.jpg differ diff --git a/FusionIIIT/applications/globals/static/globals/img/Designer.png b/FusionIIIT/applications/globals/static/globals/img/Designer.png new file mode 100644 index 000000000..c8c2bdf00 Binary files /dev/null and b/FusionIIIT/applications/globals/static/globals/img/Designer.png differ diff --git a/FusionIIIT/applications/globals/static/globals/img/LHTC.jpg b/FusionIIIT/applications/globals/static/globals/img/LHTC.jpg new file mode 100644 index 000000000..7cc2a7731 Binary files /dev/null and b/FusionIIIT/applications/globals/static/globals/img/LHTC.jpg differ diff --git a/FusionIIIT/applications/globals/static/globals/img/fusion.png b/FusionIIIT/applications/globals/static/globals/img/fusion.png new file mode 100644 index 000000000..3de95db63 Binary files /dev/null and b/FusionIIIT/applications/globals/static/globals/img/fusion.png differ diff --git a/FusionIIIT/applications/globals/static/globals/img/fusion_icon.png b/FusionIIIT/applications/globals/static/globals/img/fusion_icon.png new file mode 100644 index 000000000..195e9ded8 Binary files /dev/null and b/FusionIIIT/applications/globals/static/globals/img/fusion_icon.png differ diff --git a/FusionIIIT/applications/globals/static/globals/js/jquery-3.0.0.min.js b/FusionIIIT/applications/globals/static/globals/js/jquery-3.0.0.min.js new file mode 100644 index 000000000..62d410d95 --- /dev/null +++ b/FusionIIIT/applications/globals/static/globals/js/jquery-3.0.0.min.js @@ -0,0 +1,4 @@ +/*! jQuery v3.0.0 | (c) jQuery Foundation | jquery.org/license */ +!function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.0.0",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:f.call(this)},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:h,sort:c.sort,splice:c.splice},r.extend=r.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||r.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(r.isPlainObject(d)||(e=r.isArray(d)))?(e?(e=!1,f=c&&r.isArray(c)?c:[]):f=c&&r.isPlainObject(c)?c:{},g[b]=r.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},r.extend({expando:"jQuery"+(q+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===r.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=r.type(a);return("number"===b||"string"===b)&&!isNaN(a-parseFloat(a))},isPlainObject:function(a){var b,c;return a&&"[object Object]"===k.call(a)?(b=e(a))?(c=l.call(b,"constructor")&&b.constructor,"function"==typeof c&&m.call(c)===n):!0:!1},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?j[k.call(a)]||"object":typeof a},globalEval:function(a){p(a)},camelCase:function(a){return a.replace(t,"ms-").replace(u,v)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(w(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(s,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(w(Object(a))?r.merge(c,"string"==typeof a?[a]:a):h.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:i.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,f=0,h=[];if(w(a))for(d=a.length;d>f;f++)e=b(a[f],f,c),null!=e&&h.push(e);else for(f in a)e=b(a[f],f,c),null!=e&&h.push(e);return g.apply([],h)},guid:1,proxy:function(a,b){var c,d,e;return"string"==typeof b&&(c=a[b],b=a,a=c),r.isFunction(a)?(d=f.call(arguments,2),e=function(){return a.apply(b||this,d.concat(f.call(arguments)))},e.guid=a.guid=a.guid||r.guid++,e):void 0},now:Date.now,support:o}),"function"==typeof Symbol&&(r.fn[Symbol.iterator]=c[Symbol.iterator]),r.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){j["[object "+b+"]"]=b.toLowerCase()});function w(a){var b=!!a&&"length"in a&&a.length,c=r.type(a);return"function"===c||r.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\x00-\\xa0])+",M="\\["+K+"*("+L+")(?:"+K+"*([*^$|!~]?=)"+K+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+L+"))|)"+K+"*\\]",N=":("+L+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+M+")*)|.*)\\)|)",O=new RegExp(K+"+","g"),P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g,ca=function(a,b){return b?"\x00"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"label"in b&&b.disabled===a||"form"in b&&b.disabled===a||"form"in b&&b.disabled===!1&&(b.isDisabled===a||b.isDisabled!==!a&&("label"in b||!ea(b))!==a)}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[0>c?c+b:c]}),even:pa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:pa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:pa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function ta(a,b,c){var d=b.dir,e=b.next,f=e||d,g=c&&"parentNode"===f,h=x++;return b.first?function(b,c,e){while(b=b[d])if(1===b.nodeType||g)return a(b,c,e)}:function(b,c,i){var j,k,l,m=[w,h];if(i){while(b=b[d])if((1===b.nodeType||g)&&a(b,c,i))return!0}else while(b=b[d])if(1===b.nodeType||g)if(l=b[u]||(b[u]={}),k=l[b.uniqueID]||(l[b.uniqueID]={}),e&&e===b.nodeName.toLowerCase())b=b[d]||b;else{if((j=k[f])&&j[0]===w&&j[1]===h)return m[2]=j[2];if(k[f]=m,m[2]=a(b,c,i))return!0}}}function ua(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function wa(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function xa(a,b,c,d,e,f){return d&&!d[u]&&(d=xa(d)),e&&!e[u]&&(e=xa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||va(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:wa(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=wa(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ta(ua(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return xa(i>1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,e>i&&ya(a.slice(i,e)),f>e&&ya(a=a.slice(e)),f>e&&sa(a))}m.push(c)}return ua(m)}function za(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(_,aa),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=V.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(_,aa),$.test(j[0].type)&&qa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&sa(j),!a)return G.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||$.test(a)&&qa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext,B=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,C=/^.[^:#\[\.,]*$/;function D(a,b,c){if(r.isFunction(b))return r.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return r.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(C.test(b))return r.filter(b,a,c);b=r.filter(b,a)}return r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType})}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;d>b;b++)if(r.contains(e[b],this))return!0}));for(c=this.pushStack([]),b=0;d>b;b++)r.find(a,e[b],c);return d>1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(D(this,a||[],!1))},not:function(a){return this.pushStack(D(this,a||[],!0))},is:function(a){return!!D(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var E,F=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,G=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||E,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:F.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),B.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};G.prototype=r.fn,E=r(d);var H=/^(?:parents|prev(?:Until|All))/,I={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(r.contains(this,b[a]))return!0})},closest:function(a,b){var c,d=0,e=this.length,f=[],g="string"!=typeof a&&r(a);if(!A.test(a))for(;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function J(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return J(a,"nextSibling")},prev:function(a){return J(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return a.contentDocument||r.merge([],a.childNodes)}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(I[a]||r.uniqueSort(e),H.test(a)&&e.reverse()),this.pushStack(e)}});var K=/\S+/g;function L(a){var b={};return r.each(a.match(K)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?L(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function M(a){return a}function N(a){throw a}function O(a,b,c){var d;try{a&&r.isFunction(d=a.promise)?d.call(a).done(b).fail(c):a&&r.isFunction(d=a.then)?d.call(a,b,c):b.call(void 0,a)}catch(a){c.call(void 0,a)}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(f>b)){if(a=d.apply(h,i),a===c.promise())throw new TypeError("Thenable self-resolution");j=a&&("object"==typeof a||"function"==typeof a)&&a.then,r.isFunction(j)?e?j.call(a,g(f,c,M,e),g(f,c,N,e)):(f++,j.call(a,g(f,c,M,e),g(f,c,N,e),g(f,c,M,c.notifyWith))):(d!==M&&(h=void 0,i=[a]),(e||c.resolveWith)(h,i))}},k=e?j:function(){try{j()}catch(a){r.Deferred.exceptionHook&&r.Deferred.exceptionHook(a,k.stackTrace),b+1>=f&&(d!==N&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:M,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:M)),c[2][3].add(g(0,a,r.isFunction(d)?d:N))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(1>=b&&(O(a,g.done(h(c)).resolve,g.reject),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)O(e[c],h(c),g.reject);return g.promise()}});var P=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&P.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)};var Q=r.Deferred();r.fn.ready=function(a){return Q.then(a),this},r.extend({isReady:!1,readyWait:1,holdReady:function(a){a?r.readyWait++:r.ready(!0)},ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||Q.resolveWith(d,[r]))}}),r.ready.then=Q.then;function R(){d.removeEventListener("DOMContentLoaded",R),a.removeEventListener("load",R),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",R),a.addEventListener("load",R));var S=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)S(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){ +return j.call(r(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},T=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function U(){this.expando=r.expando+U.uid++}U.uid=1,U.prototype={cache:function(a){var b=a[this.expando];return b||(b={},T(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[r.camelCase(b)]=c;else for(d in b)e[r.camelCase(d)]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][r.camelCase(b)]},access:function(a,b,c){return void 0===b||b&&"string"==typeof b&&void 0===c?this.get(a,b):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d=a[this.expando];if(void 0!==d){if(void 0!==b){r.isArray(b)?b=b.map(r.camelCase):(b=r.camelCase(b),b=b in d?[b]:b.match(K)||[]),c=b.length;while(c--)delete d[b[c]]}(void 0===b||r.isEmptyObject(d))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!r.isEmptyObject(b)}};var V=new U,W=new U,X=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Y=/[A-Z]/g;function Z(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Y,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:X.test(c)?JSON.parse(c):c}catch(e){}W.set(a,b,c)}else c=void 0;return c}r.extend({hasData:function(a){return W.hasData(a)||V.hasData(a)},data:function(a,b,c){return W.access(a,b,c)},removeData:function(a,b){W.remove(a,b)},_data:function(a,b,c){return V.access(a,b,c)},_removeData:function(a,b){V.remove(a,b)}}),r.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=W.get(f),1===f.nodeType&&!V.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=r.camelCase(d.slice(5)),Z(f,d,e[d])));V.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){W.set(this,a)}):S(this,function(b){var c;if(f&&void 0===b){if(c=W.get(f,a),void 0!==c)return c;if(c=Z(f,a),void 0!==c)return c}else this.each(function(){W.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){W.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=V.get(a,b),c&&(!d||r.isArray(c)?d=V.access(a,b,r.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return V.get(a,c)||V.access(a,c,{empty:r.Callbacks("once memory").add(function(){V.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthf;f++)d=a[f],d.style&&(c=d.style.display,b?("none"===c&&(e[f]=V.get(d,"display")||null,e[f]||(d.style.display="")),""===d.style.display&&ba(d)&&(e[f]=fa(d))):"none"!==c&&(e[f]="none",V.set(d,"display",c)));for(f=0;g>f;f++)null!=e[f]&&(a[f].style.display=e[f]);return a}r.fn.extend({show:function(){return ga(this,!0)},hide:function(){return ga(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){ba(this)?r(this).show():r(this).hide()})}});var ha=/^(?:checkbox|radio)$/i,ia=/<([a-z][^\/\0>\x20\t\r\n\f]+)/i,ja=/^$|\/(?:java|ecma)script/i,ka={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ka.optgroup=ka.option,ka.tbody=ka.tfoot=ka.colgroup=ka.caption=ka.thead,ka.th=ka.td;function la(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&r.nodeName(a,b)?r.merge([a],c):c}function ma(a,b){for(var c=0,d=a.length;d>c;c++)V.set(a[c],"globalEval",!b||V.get(b[c],"globalEval"))}var na=/<|&#?\w+;/;function oa(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],n=0,o=a.length;o>n;n++)if(f=a[n],f||0===f)if("object"===r.type(f))r.merge(m,f.nodeType?[f]:f);else if(na.test(f)){g=g||l.appendChild(b.createElement("div")),h=(ia.exec(f)||["",""])[1].toLowerCase(),i=ka[h]||ka._default,g.innerHTML=i[1]+r.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;r.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",n=0;while(f=m[n++])if(d&&r.inArray(f,d)>-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=la(l.appendChild(f),"script"),j&&ma(g),c){k=0;while(f=g[k++])ja.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var pa=d.documentElement,qa=/^key/,ra=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,sa=/^([^.]*)(?:\.(.+)|)/;function ta(){return!0}function ua(){return!1}function va(){try{return d.activeElement}catch(a){}}function wa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)wa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ua;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(pa,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(K)||[""],j=b.length;while(j--)h=sa.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.hasData(a)&&V.get(a);if(q&&(i=q.events)){b=(b||"").match(K)||[""],j=b.length;while(j--)if(h=sa.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&V.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(V.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;cc;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?r(e,this).index(i)>-1:r.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h\x20\t\r\n\f]*)[^>]*)\/>/gi,ya=/\s*$/g;function Ca(a,b){return r.nodeName(a,"table")&&r.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a:a}function Da(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Ea(a){var b=Aa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(V.hasData(a)&&(f=V.access(a),g=V.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)r.event.add(b,e,j[e][c])}W.hasData(a)&&(h=W.access(a),i=r.extend({},h),W.set(b,i))}}function Ga(a,b){var c=b.nodeName.toLowerCase();"input"===c&&ha.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function Ha(a,b,c,d){b=g.apply([],b);var e,f,h,i,j,k,l=0,m=a.length,n=m-1,q=b[0],s=r.isFunction(q);if(s||m>1&&"string"==typeof q&&!o.checkClone&&za.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(m&&(e=oa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(la(e,"script"),Da),i=h.length;m>l;l++)j=e,l!==n&&(j=r.clone(j,!0,!0),i&&r.merge(h,la(j,"script"))),c.call(a[l],j,l);if(i)for(k=h[h.length-1].ownerDocument,r.map(h,Ea),l=0;i>l;l++)j=h[l],ja.test(j.type||"")&&!V.access(j,"globalEval")&&r.contains(k,j)&&(j.src?r._evalUrl&&r._evalUrl(j.src):p(j.textContent.replace(Ba,""),k))}return a}function Ia(a,b,c){for(var d,e=b?r.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||r.cleanData(la(d)),d.parentNode&&(c&&r.contains(d.ownerDocument,d)&&ma(la(d,"script")),d.parentNode.removeChild(d));return a}r.extend({htmlPrefilter:function(a){return a.replace(xa,"<$1>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=la(h),f=la(a),d=0,e=f.length;e>d;d++)Ga(f[d],g[d]);if(b)if(c)for(f=f||la(a),g=g||la(h),d=0,e=f.length;e>d;d++)Fa(f[d],g[d]);else Fa(a,h);return g=la(h,"script"),g.length>0&&ma(g,!i&&la(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(T(c)){if(b=c[V.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[V.expando]=void 0}c[W.expando]&&(c[W.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return S(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(la(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return S(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!ya.test(a)&&!ka[(ia.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(r.cleanData(la(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;r.inArray(this,a)<0&&(r.cleanData(la(this)),c&&c.replaceChild(b,this))},a)}}),r.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){r.fn[a]=function(a){for(var c,d=[],e=r(a),f=e.length-1,g=0;f>=g;g++)c=g===f?this:this.clone(!0),r(e[g])[b](c),h.apply(d,c.get());return this.pushStack(d)}});var Ja=/^margin/,Ka=new RegExp("^("+$+")(?!px)[a-z%]+$","i"),La=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)};!function(){function b(){if(i){i.style.cssText="box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",i.innerHTML="",pa.appendChild(h);var b=a.getComputedStyle(i);c="1%"!==b.top,g="2px"===b.marginLeft,e="4px"===b.width,i.style.marginRight="50%",f="4px"===b.marginRight,pa.removeChild(h),i=null}}var c,e,f,g,h=d.createElement("div"),i=d.createElement("div");i.style&&(i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",o.clearCloneStyle="content-box"===i.style.backgroundClip,h.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",h.appendChild(i),r.extend(o,{pixelPosition:function(){return b(),c},boxSizingReliable:function(){return b(),e},pixelMarginRight:function(){return b(),f},reliableMarginLeft:function(){return b(),g}}))}();function Ma(a,b,c){var d,e,f,g,h=a.style;return c=c||La(a),c&&(g=c.getPropertyValue(b)||c[b],""!==g||r.contains(a.ownerDocument,a)||(g=r.style(a,b)),!o.pixelMarginRight()&&Ka.test(g)&&Ja.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+"":g}function Na(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Oa=/^(none|table(?!-c[ea]).+)/,Pa={position:"absolute",visibility:"hidden",display:"block"},Qa={letterSpacing:"0",fontWeight:"400"},Ra=["Webkit","Moz","ms"],Sa=d.createElement("div").style;function Ta(a){if(a in Sa)return a;var b=a[0].toUpperCase()+a.slice(1),c=Ra.length;while(c--)if(a=Ra[c]+b,a in Sa)return a}function Ua(a,b,c){var d=_.exec(b);return d?Math.max(0,d[2]-(c||0))+(d[3]||"px"):b}function Va(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=r.css(a,c+aa[f],!0,e)),d?("content"===c&&(g-=r.css(a,"padding"+aa[f],!0,e)),"margin"!==c&&(g-=r.css(a,"border"+aa[f]+"Width",!0,e))):(g+=r.css(a,"padding"+aa[f],!0,e),"padding"!==c&&(g+=r.css(a,"border"+aa[f]+"Width",!0,e)));return g}function Wa(a,b,c){var d,e=!0,f=La(a),g="border-box"===r.css(a,"boxSizing",!1,f);if(a.getClientRects().length&&(d=a.getBoundingClientRect()[b]),0>=d||null==d){if(d=Ma(a,b,f),(0>d||null==d)&&(d=a.style[b]),Ka.test(d))return d;e=g&&(o.boxSizingReliable()||d===a.style[b]),d=parseFloat(d)||0}return d+Va(a,b,c||(g?"border":"content"),e,f)+"px"}r.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Ma(a,"opacity");return""===c?"1":c}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=r.camelCase(b),i=a.style;return b=r.cssProps[h]||(r.cssProps[h]=Ta(h)||h),g=r.cssHooks[b]||r.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=_.exec(c))&&e[1]&&(c=da(a,b,e),f="number"),null!=c&&c===c&&("number"===f&&(c+=e&&e[3]||(r.cssNumber[h]?"":"px")),o.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=r.camelCase(b);return b=r.cssProps[h]||(r.cssProps[h]=Ta(h)||h),g=r.cssHooks[b]||r.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=Ma(a,b,d)),"normal"===e&&b in Qa&&(e=Qa[b]),""===c||c?(f=parseFloat(e),c===!0||isFinite(f)?f||0:e):e}}),r.each(["height","width"],function(a,b){r.cssHooks[b]={get:function(a,c,d){return c?!Oa.test(r.css(a,"display"))||a.getClientRects().length&&a.getBoundingClientRect().width?Wa(a,b,d):ca(a,Pa,function(){return Wa(a,b,d)}):void 0},set:function(a,c,d){var e,f=d&&La(a),g=d&&Va(a,b,d,"border-box"===r.css(a,"boxSizing",!1,f),f);return g&&(e=_.exec(c))&&"px"!==(e[3]||"px")&&(a.style[b]=c,c=r.css(a,b)),Ua(a,c,g)}}}),r.cssHooks.marginLeft=Na(o.reliableMarginLeft,function(a,b){return b?(parseFloat(Ma(a,"marginLeft"))||a.getBoundingClientRect().left-ca(a,{marginLeft:0},function(){return a.getBoundingClientRect().left}))+"px":void 0}),r.each({margin:"",padding:"",border:"Width"},function(a,b){r.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+aa[d]+b]=f[d]||f[d-2]||f[0];return e}},Ja.test(a)||(r.cssHooks[a+b].set=Ua)}),r.fn.extend({css:function(a,b){return S(this,function(a,b,c){var d,e,f={},g=0;if(r.isArray(b)){for(d=La(a),e=b.length;e>g;g++)f[b[g]]=r.css(a,b[g],!1,d);return f}return void 0!==c?r.style(a,b,c):r.css(a,b)},a,b,arguments.length>1)}});function Xa(a,b,c,d,e){return new Xa.prototype.init(a,b,c,d,e)}r.Tween=Xa,Xa.prototype={constructor:Xa,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||r.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(r.cssNumber[c]?"":"px")},cur:function(){var a=Xa.propHooks[this.prop];return a&&a.get?a.get(this):Xa.propHooks._default.get(this)},run:function(a){var b,c=Xa.propHooks[this.prop];return this.options.duration?this.pos=b=r.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Xa.propHooks._default.set(this),this}},Xa.prototype.init.prototype=Xa.prototype,Xa.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=r.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){r.fx.step[a.prop]?r.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[r.cssProps[a.prop]]&&!r.cssHooks[a.prop]?a.elem[a.prop]=a.now:r.style(a.elem,a.prop,a.now+a.unit)}}},Xa.propHooks.scrollTop=Xa.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},r.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},r.fx=Xa.prototype.init,r.fx.step={};var Ya,Za,$a=/^(?:toggle|show|hide)$/,_a=/queueHooks$/;function ab(){Za&&(a.requestAnimationFrame(ab),r.fx.tick())}function bb(){return a.setTimeout(function(){Ya=void 0}),Ya=r.now()}function cb(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=aa[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function db(a,b,c){for(var d,e=(gb.tweeners[b]||[]).concat(gb.tweeners["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function eb(a,b,c){var d,e,f,g,h,i,j,k,l="width"in b||"height"in b,m=this,n={},o=a.style,p=a.nodeType&&ba(a),q=V.get(a,"fxshow");c.queue||(g=r._queueHooks(a,"fx"),null==g.unqueued&&(g.unqueued=0,h=g.empty.fire,g.empty.fire=function(){g.unqueued||h()}),g.unqueued++,m.always(function(){m.always(function(){g.unqueued--,r.queue(a,"fx").length||g.empty.fire()})}));for(d in b)if(e=b[d],$a.test(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}n[d]=q&&q[d]||r.style(a,d)}if(i=!r.isEmptyObject(b),i||!r.isEmptyObject(n)){l&&1===a.nodeType&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=q&&q.display,null==j&&(j=V.get(a,"display")),k=r.css(a,"display"),"none"===k&&(j?k=j:(ga([a],!0),j=a.style.display||j,k=r.css(a,"display"),ga([a]))),("inline"===k||"inline-block"===k&&null!=j)&&"none"===r.css(a,"float")&&(i||(m.done(function(){o.display=j}),null==j&&(k=o.display,j="none"===k?"":k)),o.display="inline-block")),c.overflow&&(o.overflow="hidden",m.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]})),i=!1;for(d in n)i||(q?"hidden"in q&&(p=q.hidden):q=V.access(a,"fxshow",{display:j}),f&&(q.hidden=!p),p&&ga([a],!0),m.done(function(){p||ga([a]),V.remove(a,"fxshow");for(d in n)r.style(a,d,n[d])})),i=db(p?q[d]:0,d,m),d in q||(q[d]=i.start,p&&(i.end=i.start,i.start=0))}}function fb(a,b){var c,d,e,f,g;for(c in a)if(d=r.camelCase(c),e=b[d],f=a[c],r.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=r.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function gb(a,b,c){var d,e,f=0,g=gb.prefilters.length,h=r.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=Ya||bb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:r.extend({},b),opts:r.extend(!0,{specialEasing:{},easing:r.easing._default},c),originalProperties:b,originalOptions:c,startTime:Ya||bb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=r.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]),this}}),k=j.props;for(fb(k,j.opts.specialEasing);g>f;f++)if(d=gb.prefilters[f].call(j,a,k,j.opts))return r.isFunction(d.stop)&&(r._queueHooks(j.elem,j.opts.queue).stop=r.proxy(d.stop,d)),d;return r.map(k,db,j),r.isFunction(j.opts.start)&&j.opts.start.call(a,j),r.fx.timer(r.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}r.Animation=r.extend(gb,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return da(c.elem,a,_.exec(b),c),c}]},tweener:function(a,b){r.isFunction(a)?(b=a,a=["*"]):a=a.match(K);for(var c,d=0,e=a.length;e>d;d++)c=a[d],gb.tweeners[c]=gb.tweeners[c]||[],gb.tweeners[c].unshift(b)},prefilters:[eb],prefilter:function(a,b){b?gb.prefilters.unshift(a):gb.prefilters.push(a)}}),r.speed=function(a,b,c){var e=a&&"object"==typeof a?r.extend({},a):{complete:c||!c&&b||r.isFunction(a)&&a,duration:a,easing:c&&b||b&&!r.isFunction(b)&&b};return r.fx.off||d.hidden?e.duration=0:e.duration="number"==typeof e.duration?e.duration:e.duration in r.fx.speeds?r.fx.speeds[e.duration]:r.fx.speeds._default,null!=e.queue&&e.queue!==!0||(e.queue="fx"),e.old=e.complete,e.complete=function(){r.isFunction(e.old)&&e.old.call(this),e.queue&&r.dequeue(this,e.queue)},e},r.fn.extend({fadeTo:function(a,b,c,d){return this.filter(ba).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=r.isEmptyObject(a),f=r.speed(b,c,d),g=function(){var b=gb(this,r.extend({},a),f);(e||V.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=r.timers,g=V.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&_a.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));!b&&c||r.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=V.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=r.timers,g=d?d.length:0;for(c.finish=!0,r.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),r.each(["toggle","show","hide"],function(a,b){var c=r.fn[b];r.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(cb(b,!0),a,d,e)}}),r.each({slideDown:cb("show"),slideUp:cb("hide"),slideToggle:cb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){r.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),r.timers=[],r.fx.tick=function(){var a,b=0,c=r.timers;for(Ya=r.now();b1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?hb:void 0)),void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&r.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(K);if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c); +}}),hb={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=ib[b]||r.find.attr;ib[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=ib[g],ib[g]=e,e=null!=c(a,b,d)?g:null,ib[g]=f),e}});var jb=/^(?:input|select|textarea|button)$/i,kb=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return S(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):jb.test(a.nodeName)||kb.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});var lb=/[\t\r\n\f]/g;function mb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,mb(this)))});if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=mb(c),d=1===c.nodeType&&(" "+e+" ").replace(lb," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=r.trim(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,mb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=mb(c),d=1===c.nodeType&&(" "+e+" ").replace(lb," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=r.trim(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,mb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(K)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=mb(this),b&&V.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":V.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+mb(c)+" ").replace(lb," ").indexOf(b)>-1)return!0;return!1}});var nb=/\r/g,ob=/[\x20\t\r\n\f]+/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":r.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(nb,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:r.trim(r.text(a)).replace(ob," ")}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],(c.selected||i===e)&&!c.disabled&&(!c.parentNode.disabled||!r.nodeName(c.parentNode,"optgroup"))){if(b=r(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=r.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=r.inArray(r.valHooks.option.get(d),f)>-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){return r.isArray(b)?a.checked=r.inArray(r(a).val(),b)>-1:void 0}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var pb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!pb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,pb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(V.get(h,"events")||{})[b.type]&&V.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&T(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!T(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?r.event.trigger(a,b,c,!0):void 0}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=V.access(d,b);e||d.addEventListener(a,c,!0),V.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=V.access(d,b)-1;e?V.access(d,b,e):(d.removeEventListener(a,c,!0),V.remove(d,b))}}});var qb=a.location,rb=r.now(),sb=/\?/;r.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||r.error("Invalid XML: "+b),c};var tb=/\[\]$/,ub=/\r?\n/g,vb=/^(?:submit|button|image|reset|file)$/i,wb=/^(?:input|select|textarea|keygen)/i;function xb(a,b,c,d){var e;if(r.isArray(b))r.each(b,function(b,e){c||tb.test(a)?d(a,e):xb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)xb(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(r.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)xb(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&wb.test(this.nodeName)&&!vb.test(a)&&(this.checked||!ha.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:r.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(ub,"\r\n")}}):{name:b.name,value:c.replace(ub,"\r\n")}}).get()}});var yb=/%20/g,zb=/#.*$/,Ab=/([?&])_=[^&]*/,Bb=/^(.*?):[ \t]*([^\r\n]*)$/gm,Cb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Db=/^(?:GET|HEAD)$/,Eb=/^\/\//,Fb={},Gb={},Hb="*/".concat("*"),Ib=d.createElement("a");Ib.href=qb.href;function Jb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(K)||[];if(r.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Kb(a,b,c,d){var e={},f=a===Gb;function g(h){var i;return e[h]=!0,r.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Lb(a,b){var c,d,e=r.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&r.extend(!0,a,d),a}function Mb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Nb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}r.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:qb.href,type:"GET",isLocal:Cb.test(qb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Hb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":r.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Lb(Lb(a,r.ajaxSettings),b):Lb(r.ajaxSettings,a)},ajaxPrefilter:Jb(Fb),ajaxTransport:Jb(Gb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m,n,o=r.ajaxSetup({},c),p=o.context||o,q=o.context&&(p.nodeType||p.jquery)?r(p):r.event,s=r.Deferred(),t=r.Callbacks("once memory"),u=o.statusCode||{},v={},w={},x="canceled",y={readyState:0,getResponseHeader:function(a){var b;if(k){if(!h){h={};while(b=Bb.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return k?g:null},setRequestHeader:function(a,b){return null==k&&(a=w[a.toLowerCase()]=w[a.toLowerCase()]||a,v[a]=b),this},overrideMimeType:function(a){return null==k&&(o.mimeType=a),this},statusCode:function(a){var b;if(a)if(k)y.always(a[y.status]);else for(b in a)u[b]=[u[b],a[b]];return this},abort:function(a){var b=a||x;return e&&e.abort(b),A(0,b),this}};if(s.promise(y),o.url=((b||o.url||qb.href)+"").replace(Eb,qb.protocol+"//"),o.type=c.method||c.type||o.method||o.type,o.dataTypes=(o.dataType||"*").toLowerCase().match(K)||[""],null==o.crossDomain){j=d.createElement("a");try{j.href=o.url,j.href=j.href,o.crossDomain=Ib.protocol+"//"+Ib.host!=j.protocol+"//"+j.host}catch(z){o.crossDomain=!0}}if(o.data&&o.processData&&"string"!=typeof o.data&&(o.data=r.param(o.data,o.traditional)),Kb(Fb,o,c,y),k)return y;l=r.event&&o.global,l&&0===r.active++&&r.event.trigger("ajaxStart"),o.type=o.type.toUpperCase(),o.hasContent=!Db.test(o.type),f=o.url.replace(zb,""),o.hasContent?o.data&&o.processData&&0===(o.contentType||"").indexOf("application/x-www-form-urlencoded")&&(o.data=o.data.replace(yb,"+")):(n=o.url.slice(f.length),o.data&&(f+=(sb.test(f)?"&":"?")+o.data,delete o.data),o.cache===!1&&(f=f.replace(Ab,""),n=(sb.test(f)?"&":"?")+"_="+rb++ +n),o.url=f+n),o.ifModified&&(r.lastModified[f]&&y.setRequestHeader("If-Modified-Since",r.lastModified[f]),r.etag[f]&&y.setRequestHeader("If-None-Match",r.etag[f])),(o.data&&o.hasContent&&o.contentType!==!1||c.contentType)&&y.setRequestHeader("Content-Type",o.contentType),y.setRequestHeader("Accept",o.dataTypes[0]&&o.accepts[o.dataTypes[0]]?o.accepts[o.dataTypes[0]]+("*"!==o.dataTypes[0]?", "+Hb+"; q=0.01":""):o.accepts["*"]);for(m in o.headers)y.setRequestHeader(m,o.headers[m]);if(o.beforeSend&&(o.beforeSend.call(p,y,o)===!1||k))return y.abort();if(x="abort",t.add(o.complete),y.done(o.success),y.fail(o.error),e=Kb(Gb,o,c,y)){if(y.readyState=1,l&&q.trigger("ajaxSend",[y,o]),k)return y;o.async&&o.timeout>0&&(i=a.setTimeout(function(){y.abort("timeout")},o.timeout));try{k=!1,e.send(v,A)}catch(z){if(k)throw z;A(-1,z)}}else A(-1,"No Transport");function A(b,c,d,h){var j,m,n,v,w,x=c;k||(k=!0,i&&a.clearTimeout(i),e=void 0,g=h||"",y.readyState=b>0?4:0,j=b>=200&&300>b||304===b,d&&(v=Mb(o,y,d)),v=Nb(o,v,y,j),j?(o.ifModified&&(w=y.getResponseHeader("Last-Modified"),w&&(r.lastModified[f]=w),w=y.getResponseHeader("etag"),w&&(r.etag[f]=w)),204===b||"HEAD"===o.type?x="nocontent":304===b?x="notmodified":(x=v.state,m=v.data,n=v.error,j=!n)):(n=x,!b&&x||(x="error",0>b&&(b=0))),y.status=b,y.statusText=(c||x)+"",j?s.resolveWith(p,[m,x,y]):s.rejectWith(p,[y,x,n]),y.statusCode(u),u=void 0,l&&q.trigger(j?"ajaxSuccess":"ajaxError",[y,o,j?m:n]),t.fireWith(p,[y,x]),l&&(q.trigger("ajaxComplete",[y,o]),--r.active||r.event.trigger("ajaxStop")))}return y},getJSON:function(a,b,c){return r.get(a,b,c,"json")},getScript:function(a,b){return r.get(a,void 0,b,"script")}}),r.each(["get","post"],function(a,b){r[b]=function(a,c,d,e){return r.isFunction(c)&&(e=e||d,d=c,c=void 0),r.ajax(r.extend({url:a,type:b,dataType:e,data:c,success:d},r.isPlainObject(a)&&a))}}),r._evalUrl=function(a){return r.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},r.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Ob={0:200,1223:204},Pb=r.ajaxSettings.xhr();o.cors=!!Pb&&"withCredentials"in Pb,o.ajax=Pb=!!Pb,r.ajaxTransport(function(b){var c,d;return o.cors||Pb&&!b.crossDomain?{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Ob[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}:void 0}),r.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),r.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return r.globalEval(a),a}}}),r.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),r.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=r(" -
-
- - - -
-
-
-
- -
- - -
- -
- - -
- -
-
-
- - - -
- -

Download Sample Videos

- -

Are you a mobile app developer?

-

Are you looking for videos of different resolution and sizes to test while designing or developing a mobile app?

-

Sample-Videos.com is a 100% FREE service that allows programmers, testers, designers, developers to download sample videos for demo/test use. No matter what video format they use (MP4, FLV, MKV, 3GP); they will be able to test videos on any Smartphone without any hustle. This is a one stop destination for all sample video testing needs. Just search below for the relevant video formats in specific sizes, download them, and start testing.

-

A mobile screen resolution can be a big challenge when it comes to watching videos online or offline. By testing out videos one can be rest assured regarding the video playback in an app, without annoying the end users. Choose from four different video extensions i.e. 3GP, MKV, FLV, and MP4. The best thing is all of these are free and very easy to download. We provide you with a specific and perfect resolution in all sizes possible with just one simple click. Check out the one which suits your requirements. All you need to do is hit the DOWNLOAD button, and get started.

- - -
-

Download .mp4 Sample Video

- -
- - - - - - - - - - - - - - -
Size(mb)FormatResolutionOne Click Download
1mp41280x720Click
2mp41280x720Click
5mp41280x720Click
10mp41280x720Click
- - - -
20mp41280x720Click
30mp41280x720Click
1mp4720x480Click
2mp4720x480Click
5mp4720x480Click
10mp4720x480Click
20mp4720x480Click
30mp4720x480Click
1mp4640x360Click
2mp4640x360Click
5mp4640x360Click
10mp4640x360Click
20mp4640x360Click
30mp4640x360Click
1mp4360x240Click
2mp4360x240Click
5mp4360x240Click
10mp4360x240Click
20mp4360x240Click
30mp4360x240Click
- -
- -
-
- -

Download .flv Sample Video

-
- - - - - - - - - - - - - - -
Size(mb)FormatResolutionOne Click Download
1flv1280x720Click
2flv1280x720Click
5flv1280x720Click
10flv1280x720Click
- - - -
20flv1280x720Click
30flv1280x720Click
1flv720x480Click
2flv720x480Click
5flv720x480Click
10flv720x480Click
20flv720x480Click
30flv720x480Click
1flv640x360Click
2flv640x360Click
5flv640x360Click
10flv640x360Click
20flv640x360Click
30flv640x360Click
1flv360x240Click
2flv360x240Click
5flv360x240Click
10flv360x240Click
20flv360x240Click
30flv360x240Click
-
- -
-
- -

Download .mkv Sample Video

-
- - - - - - - - - - - - - - -
Size(mb)FormatResolutionOne Click Download
1mkv1280x720Click
2mkv1280x720Click
5mkv1280x720Click
10mkv1280x720Click
- - - -
20mkv1280x720Click
30mkv1280x720Click
1mkv720x480Click
2mkv720x480Click
5mkv720x480Click
10mkv720x480Click
20mkv720x480Click
30mkv720x480Click
1mkv640x360Click
2mkv640x360Click
5mkv640x360Click
10mkv640x360Click
20mkv640x360Click
30mkv640x360Click
1mkv360x240Click
2mkv360x240Click
5mkv360x240Click
10mkv360x240Click
20mkv360x240Click
30mkv360x240Click
- -
- -
-
- -

Download .3gp Sample Video

-
- - - - - - - - - - - - - - - -
Size(mb)FormatResolutionOne Click Download
13gp176x144Click
23gp176x144Click
53gp176x144Click
103gp176x144Click
- - - -
13gp320x240Click
23gp320x240Click
53gp320x240Click
103gp320x240Click
203gp320x240Click
303gp320x240Click
- -
- -
- - - - -
- - -
-
- - - - - -
-
- -
-
-
- -
-
- -
-
-
- -
-
- -
-
- - - -
- -
- -
- - - - - - - -
- - - - -
- - -
- -
- - -
- - - - - - - - - - - - - -
-
- © Sample Video Developers - www.bigbuckbunny.org -
-
- - - - - - - - - - - - - - - - - - - - - -
- - diff --git a/FusionIIIT/media/SamplePNGImage_500kbmb_0BkXR0Y.png b/FusionIIIT/media/SamplePNGImage_500kbmb_0BkXR0Y.png deleted file mode 100644 index b374d33c1..000000000 --- a/FusionIIIT/media/SamplePNGImage_500kbmb_0BkXR0Y.png +++ /dev/null @@ -1,1122 +0,0 @@ - - - Download Sample Videos / Dummy Videos For Demo Use - - - - - - - - - - - - - - - - - -
- - -
-
- - - -
-
-
-
- -
- - -
- -
- - -
- -
-
-
- - - -
- -

Download Sample Videos

- -

Are you a mobile app developer?

-

Are you looking for videos of different resolution and sizes to test while designing or developing a mobile app?

-

Sample-Videos.com is a 100% FREE service that allows programmers, testers, designers, developers to download sample videos for demo/test use. No matter what video format they use (MP4, FLV, MKV, 3GP); they will be able to test videos on any Smartphone without any hustle. This is a one stop destination for all sample video testing needs. Just search below for the relevant video formats in specific sizes, download them, and start testing.

-

A mobile screen resolution can be a big challenge when it comes to watching videos online or offline. By testing out videos one can be rest assured regarding the video playback in an app, without annoying the end users. Choose from four different video extensions i.e. 3GP, MKV, FLV, and MP4. The best thing is all of these are free and very easy to download. We provide you with a specific and perfect resolution in all sizes possible with just one simple click. Check out the one which suits your requirements. All you need to do is hit the DOWNLOAD button, and get started.

- - -
-

Download .mp4 Sample Video

- -
- - - - - - - - - - - - - - -
Size(mb)FormatResolutionOne Click Download
1mp41280x720Click
2mp41280x720Click
5mp41280x720Click
10mp41280x720Click
- - - -
20mp41280x720Click
30mp41280x720Click
1mp4720x480Click
2mp4720x480Click
5mp4720x480Click
10mp4720x480Click
20mp4720x480Click
30mp4720x480Click
1mp4640x360Click
2mp4640x360Click
5mp4640x360Click
10mp4640x360Click
20mp4640x360Click
30mp4640x360Click
1mp4360x240Click
2mp4360x240Click
5mp4360x240Click
10mp4360x240Click
20mp4360x240Click
30mp4360x240Click
- -
- -
-
- -

Download .flv Sample Video

-
- - - - - - - - - - - - - - -
Size(mb)FormatResolutionOne Click Download
1flv1280x720Click
2flv1280x720Click
5flv1280x720Click
10flv1280x720Click
- - - -
20flv1280x720Click
30flv1280x720Click
1flv720x480Click
2flv720x480Click
5flv720x480Click
10flv720x480Click
20flv720x480Click
30flv720x480Click
1flv640x360Click
2flv640x360Click
5flv640x360Click
10flv640x360Click
20flv640x360Click
30flv640x360Click
1flv360x240Click
2flv360x240Click
5flv360x240Click
10flv360x240Click
20flv360x240Click
30flv360x240Click
-
- -
-
- -

Download .mkv Sample Video

-
- - - - - - - - - - - - - - -
Size(mb)FormatResolutionOne Click Download
1mkv1280x720Click
2mkv1280x720Click
5mkv1280x720Click
10mkv1280x720Click
- - - -
20mkv1280x720Click
30mkv1280x720Click
1mkv720x480Click
2mkv720x480Click
5mkv720x480Click
10mkv720x480Click
20mkv720x480Click
30mkv720x480Click
1mkv640x360Click
2mkv640x360Click
5mkv640x360Click
10mkv640x360Click
20mkv640x360Click
30mkv640x360Click
1mkv360x240Click
2mkv360x240Click
5mkv360x240Click
10mkv360x240Click
20mkv360x240Click
30mkv360x240Click
- -
- -
-
- -

Download .3gp Sample Video

-
- - - - - - - - - - - - - - - -
Size(mb)FormatResolutionOne Click Download
13gp176x144Click
23gp176x144Click
53gp176x144Click
103gp176x144Click
- - - -
13gp320x240Click
23gp320x240Click
53gp320x240Click
103gp320x240Click
203gp320x240Click
303gp320x240Click
- -
- -
- - - - -
- - -
-
- - - - - -
-
- -
-
-
- -
-
- -
-
-
- -
-
- -
-
- - - -
- -
- -
- - - - - - - -
- - - - -
- - -
- -
- - -
- - - - - - - - - - - - - -
-
- © Sample Video Developers - www.bigbuckbunny.org -
-
- - - - - - - - - - - - - - - - - - - - - -
- - diff --git a/FusionIIIT/media/Screenshot_1.png b/FusionIIIT/media/Screenshot_1.png deleted file mode 100644 index 03aed985d..000000000 Binary files a/FusionIIIT/media/Screenshot_1.png and /dev/null differ diff --git a/FusionIIIT/media/Screenshot_1_ZRkbwbZ.png b/FusionIIIT/media/Screenshot_1_ZRkbwbZ.png deleted file mode 100644 index 03aed985d..000000000 Binary files a/FusionIIIT/media/Screenshot_1_ZRkbwbZ.png and /dev/null differ diff --git a/FusionIIIT/media/Screenshot_2020-07-01_CBIR_Using_Color_Difference_Histogram_-_Retrieval_-_Jupyter_Notebook.png b/FusionIIIT/media/Screenshot_2020-07-01_CBIR_Using_Color_Difference_Histogram_-_Retrieval_-_Jupyter_Notebook.png deleted file mode 100644 index 80bfcf678..000000000 Binary files a/FusionIIIT/media/Screenshot_2020-07-01_CBIR_Using_Color_Difference_Histogram_-_Retrieval_-_Jupyter_Notebook.png and /dev/null differ diff --git a/FusionIIIT/media/Solution.jpeg b/FusionIIIT/media/Solution.jpeg deleted file mode 100644 index c4467fe4b..000000000 Binary files a/FusionIIIT/media/Solution.jpeg and /dev/null differ diff --git a/FusionIIIT/media/a1.PNG b/FusionIIIT/media/a1.PNG deleted file mode 100644 index 1d1e6039d..000000000 Binary files a/FusionIIIT/media/a1.PNG and /dev/null differ diff --git a/FusionIIIT/media/ajju.pdf b/FusionIIIT/media/ajju.pdf deleted file mode 100644 index 8c794c0a0..000000000 Binary files a/FusionIIIT/media/ajju.pdf and /dev/null differ diff --git a/FusionIIIT/media/ajju_ipTPZnA.pdf b/FusionIIIT/media/ajju_ipTPZnA.pdf deleted file mode 100644 index 8c794c0a0..000000000 Binary files a/FusionIIIT/media/ajju_ipTPZnA.pdf and /dev/null differ diff --git a/FusionIIIT/media/allane.pdf b/FusionIIIT/media/allane.pdf deleted file mode 100644 index aea95724d..000000000 Binary files a/FusionIIIT/media/allane.pdf and /dev/null differ diff --git a/FusionIIIT/media/allane_mqBZZDj.pdf b/FusionIIIT/media/allane_mqBZZDj.pdf deleted file mode 100644 index aea95724d..000000000 Binary files a/FusionIIIT/media/allane_mqBZZDj.pdf and /dev/null differ diff --git a/FusionIIIT/media/bonafide.pdf b/FusionIIIT/media/bonafide.pdf deleted file mode 100644 index 9469632b6..000000000 Binary files a/FusionIIIT/media/bonafide.pdf and /dev/null differ diff --git a/FusionIIIT/media/bonafide_3p6qeQY.pdf b/FusionIIIT/media/bonafide_3p6qeQY.pdf deleted file mode 100644 index 9469632b6..000000000 Binary files a/FusionIIIT/media/bonafide_3p6qeQY.pdf and /dev/null differ diff --git a/FusionIIIT/media/bonafide_W7s1Auu.pdf b/FusionIIIT/media/bonafide_W7s1Auu.pdf deleted file mode 100644 index 9469632b6..000000000 Binary files a/FusionIIIT/media/bonafide_W7s1Auu.pdf and /dev/null differ diff --git a/FusionIIIT/media/bonafide_b25Y6TV.pdf b/FusionIIIT/media/bonafide_b25Y6TV.pdf deleted file mode 100644 index 9469632b6..000000000 Binary files a/FusionIIIT/media/bonafide_b25Y6TV.pdf and /dev/null differ diff --git a/FusionIIIT/media/demo.zip b/FusionIIIT/media/demo.zip deleted file mode 100644 index 15cb0ecb3..000000000 Binary files a/FusionIIIT/media/demo.zip and /dev/null differ diff --git a/FusionIIIT/media/demo_0SCeEho.zip b/FusionIIIT/media/demo_0SCeEho.zip deleted file mode 100644 index 15cb0ecb3..000000000 Binary files a/FusionIIIT/media/demo_0SCeEho.zip and /dev/null differ diff --git a/FusionIIIT/media/demo_Ecf0ATC.zip b/FusionIIIT/media/demo_Ecf0ATC.zip deleted file mode 100644 index 15cb0ecb3..000000000 Binary files a/FusionIIIT/media/demo_Ecf0ATC.zip and /dev/null differ diff --git a/FusionIIIT/media/demo_uqf8R7p.zip b/FusionIIIT/media/demo_uqf8R7p.zip deleted file mode 100644 index 15cb0ecb3..000000000 Binary files a/FusionIIIT/media/demo_uqf8R7p.zip and /dev/null differ diff --git a/FusionIIIT/media/documents/wrist_band.jpg b/FusionIIIT/media/documents/wrist_band.jpg deleted file mode 100644 index abbbdceda..000000000 Binary files a/FusionIIIT/media/documents/wrist_band.jpg and /dev/null differ diff --git a/FusionIIIT/media/event.jpg b/FusionIIIT/media/event.jpg deleted file mode 100644 index bb88b387b..000000000 Binary files a/FusionIIIT/media/event.jpg and /dev/null differ diff --git a/FusionIIIT/media/event.pdf b/FusionIIIT/media/event.pdf deleted file mode 100644 index b92477282..000000000 Binary files a/FusionIIIT/media/event.pdf and /dev/null differ diff --git a/FusionIIIT/media/event_n6JOVni.pdf b/FusionIIIT/media/event_n6JOVni.pdf deleted file mode 100644 index b92477282..000000000 Binary files a/FusionIIIT/media/event_n6JOVni.pdf and /dev/null differ diff --git a/FusionIIIT/media/image.jpg b/FusionIIIT/media/image.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_007RJnp.jpg b/FusionIIIT/media/image_007RJnp.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_007RJnp.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_08EzmEH.jpg b/FusionIIIT/media/image_08EzmEH.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_08EzmEH.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_6xkgtat.jpg b/FusionIIIT/media/image_6xkgtat.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_6xkgtat.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_8Al2hkC.jpg b/FusionIIIT/media/image_8Al2hkC.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_8Al2hkC.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_DArY4kM.jpg b/FusionIIIT/media/image_DArY4kM.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_DArY4kM.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_Dj9wBVK.jpg b/FusionIIIT/media/image_Dj9wBVK.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_Dj9wBVK.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_DnBzrXz.jpg b/FusionIIIT/media/image_DnBzrXz.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_DnBzrXz.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_EHN0uUR.jpg b/FusionIIIT/media/image_EHN0uUR.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_EHN0uUR.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_ERAUsuR.jpg b/FusionIIIT/media/image_ERAUsuR.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_ERAUsuR.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_FCiEnEA.jpg b/FusionIIIT/media/image_FCiEnEA.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_FCiEnEA.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_GDxnCEC.jpg b/FusionIIIT/media/image_GDxnCEC.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_GDxnCEC.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_Gt3KGJq.jpg b/FusionIIIT/media/image_Gt3KGJq.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_Gt3KGJq.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_Gt3KGJq_bdxtRTW.jpg b/FusionIIIT/media/image_Gt3KGJq_bdxtRTW.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_Gt3KGJq_bdxtRTW.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_Gt3KGJq_rXplFd4.jpg b/FusionIIIT/media/image_Gt3KGJq_rXplFd4.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_Gt3KGJq_rXplFd4.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_Gt3KGJq_sTQs693.jpg b/FusionIIIT/media/image_Gt3KGJq_sTQs693.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_Gt3KGJq_sTQs693.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_IsZTv03.jpg b/FusionIIIT/media/image_IsZTv03.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_IsZTv03.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_LUkx8md.jpg b/FusionIIIT/media/image_LUkx8md.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_LUkx8md.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_OFiO2Bh.jpg b/FusionIIIT/media/image_OFiO2Bh.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_OFiO2Bh.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_OLuWcRU.jpg b/FusionIIIT/media/image_OLuWcRU.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_OLuWcRU.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_Onw3X55.jpg b/FusionIIIT/media/image_Onw3X55.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_Onw3X55.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_SGKG9Zh.jpg b/FusionIIIT/media/image_SGKG9Zh.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_SGKG9Zh.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_UiGJa1M.jpg b/FusionIIIT/media/image_UiGJa1M.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_UiGJa1M.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_VAHo0g5.jpg b/FusionIIIT/media/image_VAHo0g5.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_VAHo0g5.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_Z5HxbWe.jpg b/FusionIIIT/media/image_Z5HxbWe.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_Z5HxbWe.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_ZHDevJQ.jpg b/FusionIIIT/media/image_ZHDevJQ.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_ZHDevJQ.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_behus5I.jpg b/FusionIIIT/media/image_behus5I.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_behus5I.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_iBr1k6y.jpg b/FusionIIIT/media/image_iBr1k6y.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_iBr1k6y.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_kKfwblf.jpg b/FusionIIIT/media/image_kKfwblf.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_kKfwblf.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_nJznh8V.jpg b/FusionIIIT/media/image_nJznh8V.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_nJznh8V.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_nbHQErT.jpg b/FusionIIIT/media/image_nbHQErT.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_nbHQErT.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_qsbU8zn.jpg b/FusionIIIT/media/image_qsbU8zn.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_qsbU8zn.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_r9niVQQ.jpg b/FusionIIIT/media/image_r9niVQQ.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_r9niVQQ.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_vanCtHs.jpg b/FusionIIIT/media/image_vanCtHs.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_vanCtHs.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_xStQjYa.jpg b/FusionIIIT/media/image_xStQjYa.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_xStQjYa.jpg and /dev/null differ diff --git a/FusionIIIT/media/image_xZWkinz.jpg b/FusionIIIT/media/image_xZWkinz.jpg deleted file mode 100644 index 725dd6a15..000000000 Binary files a/FusionIIIT/media/image_xZWkinz.jpg and /dev/null differ diff --git a/FusionIIIT/media/mj.png b/FusionIIIT/media/mj.png deleted file mode 100644 index 4a086b80a..000000000 Binary files a/FusionIIIT/media/mj.png and /dev/null differ diff --git a/FusionIIIT/media/mj_Al5ccBb.png b/FusionIIIT/media/mj_Al5ccBb.png deleted file mode 100644 index 4a086b80a..000000000 Binary files a/FusionIIIT/media/mj_Al5ccBb.png and /dev/null differ diff --git a/FusionIIIT/media/mj_J3NIY2c.png b/FusionIIIT/media/mj_J3NIY2c.png deleted file mode 100644 index 4a086b80a..000000000 Binary files a/FusionIIIT/media/mj_J3NIY2c.png and /dev/null differ diff --git a/FusionIIIT/media/mj_NfL2mTM.png b/FusionIIIT/media/mj_NfL2mTM.png deleted file mode 100644 index 4a086b80a..000000000 Binary files a/FusionIIIT/media/mj_NfL2mTM.png and /dev/null differ diff --git a/FusionIIIT/media/mj_ZImWkc8.png b/FusionIIIT/media/mj_ZImWkc8.png deleted file mode 100644 index 4a086b80a..000000000 Binary files a/FusionIIIT/media/mj_ZImWkc8.png and /dev/null differ diff --git a/FusionIIIT/media/mmmm.png b/FusionIIIT/media/mmmm.png deleted file mode 100644 index 52a802bb0..000000000 Binary files a/FusionIIIT/media/mmmm.png and /dev/null differ diff --git a/FusionIIIT/media/mmmm_dFrFt7K.png b/FusionIIIT/media/mmmm_dFrFt7K.png deleted file mode 100644 index 52a802bb0..000000000 Binary files a/FusionIIIT/media/mmmm_dFrFt7K.png and /dev/null differ diff --git a/FusionIIIT/media/output-onlinepngtools_5.png b/FusionIIIT/media/output-onlinepngtools_5.png deleted file mode 100644 index 782551f21..000000000 Binary files a/FusionIIIT/media/output-onlinepngtools_5.png and /dev/null differ diff --git a/FusionIIIT/media/output-onlinepngtools_5_47NIAdi.png b/FusionIIIT/media/output-onlinepngtools_5_47NIAdi.png deleted file mode 100644 index 782551f21..000000000 Binary files a/FusionIIIT/media/output-onlinepngtools_5_47NIAdi.png and /dev/null differ diff --git a/FusionIIIT/media/output-onlinepngtools_5_ZAOVWvi.png b/FusionIIIT/media/output-onlinepngtools_5_ZAOVWvi.png deleted file mode 100644 index 782551f21..000000000 Binary files a/FusionIIIT/media/output-onlinepngtools_5_ZAOVWvi.png and /dev/null differ diff --git a/FusionIIIT/media/photo-1480365501497-199581be0e66.jpg b/FusionIIIT/media/photo-1480365501497-199581be0e66.jpg deleted file mode 100644 index 55c4b20bc..000000000 Binary files a/FusionIIIT/media/photo-1480365501497-199581be0e66.jpg and /dev/null differ diff --git a/FusionIIIT/media/sample.jpg b/FusionIIIT/media/sample.jpg deleted file mode 100644 index 0a18df12f..000000000 Binary files a/FusionIIIT/media/sample.jpg and /dev/null differ diff --git a/FusionIIIT/media/window.png b/FusionIIIT/media/window.png deleted file mode 100644 index 4ddc642a5..000000000 Binary files a/FusionIIIT/media/window.png and /dev/null differ diff --git a/FusionIIIT/media/window_QaSCiCB.png b/FusionIIIT/media/window_QaSCiCB.png deleted file mode 100644 index 4ddc642a5..000000000 Binary files a/FusionIIIT/media/window_QaSCiCB.png and /dev/null differ diff --git a/FusionIIIT/media/wrist_band.jpg b/FusionIIIT/media/wrist_band.jpg deleted file mode 100644 index abbbdceda..000000000 Binary files a/FusionIIIT/media/wrist_band.jpg and /dev/null differ diff --git a/FusionIIIT/media/wrist_band_104sJ7l.jpg b/FusionIIIT/media/wrist_band_104sJ7l.jpg deleted file mode 100644 index abbbdceda..000000000 Binary files a/FusionIIIT/media/wrist_band_104sJ7l.jpg and /dev/null differ diff --git a/FusionIIIT/notification/views.py b/FusionIIIT/notification/views.py index 114bac1ce..ca732a7b7 100644 --- a/FusionIIIT/notification/views.py +++ b/FusionIIIT/notification/views.py @@ -3,37 +3,39 @@ from notifications.signals import notify # Create your views here. + def leave_module_notif(sender, recipient, type, date=None): url = 'leave:leave' module = 'Leave Module' - sender=sender - recipient=recipient - verb='' - if type=='leave_applied': - verb="Your leave has been successfully submitted." - elif type=='request_accepted': + sender = sender + recipient = recipient + verb = '' + if type == 'leave_applied': + verb = "Your leave has been successfully submitted." + elif type == 'request_accepted': verb = "Your responsibility has been accepted " - elif type=='request_declined': + elif type == 'request_declined': verb = "Your responsibility has been declined " - elif type=='leave_accepted': + elif type == 'leave_accepted': verb = "You leave request has been accepted " elif type == 'leave_forwarded': verb = "You leave request has been forwarded " - elif type=='leave_rejected': + elif type == 'leave_rejected': verb = "You leave request has been rejected " - elif type=='offline_leave': + elif type == 'offline_leave': verb = "Your offline leave has been updated " - elif type=='replacement_request': + elif type == 'replacement_request': verb = "You have a replacement request " - elif type=='leave_request': + elif type == 'leave_request': verb = "You have a leave request from " - elif type=='leave_withdrawn': + elif type == 'leave_withdrawn': verb = "The leave has been withdrawn for " + date - elif type=='replacement_cancel': + elif type == 'replacement_cancel': verb = "Your replacement has been cancelled for "+date + notify.send(sender=sender, recipient=recipient, + url=url, module=module, verb=verb) - notify.send(sender=sender, recipient=recipient, url=url, module=module, verb=verb) def placement_cell_notif(sender, recipient, type): url = 'placement:placement' @@ -42,25 +44,30 @@ def placement_cell_notif(sender, recipient, type): recipient = recipient verb = '' - notify.send(sender=sender, recipient=recipient, url=url, module=module, verb=verb) + notify.send(sender=sender, recipient=recipient, + url=url, module=module, verb=verb) + def academics_module_notif(sender, recipient, type): - url='' - module="Academic's Module" + url = '' + module = "Academic's Module" sender = sender recipient = recipient verb = type - notify.send(sender=sender, recipient=recipient, url=url, module=module, verb=verb) + notify.send(sender=sender, recipient=recipient, + url=url, module=module, verb=verb) + def office_module_notif(sender, recipient): - url='office_module:officeOfRegistrar' - module="Academic's Module" + url = 'office_module:officeOfRegistrar' + module = "Academic's Module" sender = sender recipient = recipient verb = "New file received" - notify.send(sender=sender, recipient=recipient, url=url, module=module, verb=verb) + notify.send(sender=sender, recipient=recipient, + url=url, module=module, verb=verb) def central_mess_notif(sender, recipient, type, message=None): @@ -80,7 +87,7 @@ def central_mess_notif(sender, recipient, type, message=None): verb = 'Your vacation request has been' + message elif type == 'meeting_invitation': verb = message - elif type =='special_request': + elif type == 'special_request': verb = "Your special food request has been " + message elif type == 'added_committee': verb = "You have been added to the mess committee. " @@ -117,45 +124,52 @@ def visitors_hostel_notif(sender, recipient, type): notify.send(sender=sender, recipient=recipient, url=url, module=module, verb=verb) -def healthcare_center_notif(sender, recipient, type): +def healthcare_center_notif(sender, recipient, type, message): url='healthcenter:healthcenter' module='Healthcare Center' sender = sender recipient = recipient verb = '' - + flag='' if type == 'appoint': verb = "Your Appointment has been booked" elif type == 'amb_request': verb = "Your Ambulance request has been placed" - elif type == 'Presc': + elif type == 'presc': verb = "You have been prescribed some medicine" elif type == 'appoint_req': verb = "You have a new appointment request" + elif type == 'feedback_submitted': + verb = "Your feedback has been submitted" + elif type == 'feedback_res': + verb = "You have a new feedback" elif type == 'amb_req': verb = "You have a new ambulance request" + elif type == 'new_announce': + verb = message + flag='announcement' elif type == 'rel_forward': verb = "You have a new medical relief forward request" elif type == 'rel_approve': verb = "You have a new medical relief approval request" elif type == 'rel_approved': verb = 'Your medical relief request has been approved' + notify.send(sender=sender, recipient=recipient, url=url, module=module, verb=verb, flag=flag) - notify.send(sender=sender, recipient=recipient, url=url, module=module, verb=verb) - - -def file_tracking_notif(sender, recipient,title): - url='filetracking:inward' - module='File Tracking' +def file_tracking_notif(sender, recipient, title): + url = 'filetracking:inward' + module = 'File Tracking' sender = sender recipient = recipient verb = title - notify.send(sender=sender, recipient=recipient, url=url, module=module, verb=verb) + notify.send(sender=sender, recipient=recipient, + url=url, module=module, verb=verb) + def scholarship_portal_notif(sender, recipient, type): - url='spacs:spacs' - module='Scholarship Portal' + url = 'spacs:spacs' + module = 'Scholarship Portal' sender = sender recipient = recipient verb = '' @@ -181,51 +195,54 @@ def scholarship_portal_notif(sender, recipient, type): verb = "Your Convocation form for D&M Proficiency Gold Medal has been accepted " elif type == 'Reject_Silver': verb = "Your Convocation form for D&M Proficiency Gold Medal has been rejected " - notify.send(sender=sender, recipient=recipient, url=url, module=module, verb=verb) - - + notify.send(sender=sender, recipient=recipient, + url=url, module=module, verb=verb) -def complaint_system_notif(sender, recipient, type, complaint_id,student,message): - if(student==0): +def complaint_system_notif(sender, recipient, type, complaint_id, student, message): + if (student == 0): url = ('complaint:detail') else: - url=('complaint:detail2') - module='Complaint System' + url = ('complaint:detail2') + module = 'Complaint System' sender = sender recipient = recipient verb = message description = complaint_id - notify.send(sender=sender, recipient=recipient, url=url, module=module, verb=verb,description=description) + notify.send(sender=sender, recipient=recipient, url=url, + module=module, verb=verb, description=description) + def office_dean_PnD_notif(sender, recipient, type): url = 'office_module:officeOfDeanPnD' module = 'Office of Dean PnD Module' - sender=sender - recipient=recipient - verb='' - if type=='requisition_filed': + sender = sender + recipient = recipient + verb = '' + if type == 'requisition_filed': verb = "Your requisition has been successfully submitted." - elif type=='request_accepted': + elif type == 'request_accepted': verb = "Your requisition has been accepted." - elif type=='request_rejected': + elif type == 'request_rejected': verb = "Your requisition has been rejected." - elif type=='assignment_created': + elif type == 'assignment_created': verb = "Assignment has been created." - elif type=='assignment_received': + elif type == 'assignment_received': verb = "You have received an assignment." - elif type=='assignment_reverted': + elif type == 'assignment_reverted': verb = "Assignment has been reverted." - elif type=='assignment_approved': + elif type == 'assignment_approved': verb = "Assignment has been approved." - elif type=='assignment_rejected': + elif type == 'assignment_rejected': verb = "Assignment has been rejected." - notify.send(sender=sender, recipient=recipient, url=url, module=module, verb=verb) + notify.send(sender=sender, recipient=recipient, + url=url, module=module, verb=verb) + def office_module_DeanS_notif(sender, recipient, type): - url='office_module:officeOfDeanStudents' - module='Office Module' + url = 'office_module:officeOfDeanStudents' + module = 'Office Module' sender = sender recipient = recipient verb = "" @@ -253,7 +270,8 @@ def office_module_DeanS_notif(sender, recipient, type): elif type == 'budget_alloted': verb = "Budget has been alloted by Junior Superintendent" - notify.send(sender=sender, recipient=recipient, url=url, module=module, verb=verb) + notify.send(sender=sender, recipient=recipient, + url=url, module=module, verb=verb) def gymkhana_voting(sender, recipient, type, title, desc): @@ -286,7 +304,8 @@ def gymkhana_session(sender, recipient, type, club, desc, venue): verb = "" if type == 'new_session': - verb = "A session by {} Club will be organised in {}".format(club, venue) + verb = "A session by {} Club will be organised in {}".format( + club, venue) notify.send(sender=sender, recipient=recipient, @@ -306,7 +325,8 @@ def gymkhana_event(sender, recipient, type, club, event_name, desc, venue): verb = "" if type == 'new_event': - verb = "{} event by {} Club will be organised in {}".format(event_name, club, venue) + verb = "{} event by {} Club will be organised in {}".format( + event_name, club, venue) notify.send(sender=sender, recipient=recipient, @@ -316,39 +336,45 @@ def gymkhana_event(sender, recipient, type, club, event_name, desc, venue): description=desc ) -def AssistantshipClaim_notify(sender,recipient,month,year): - - message="Your Assistantshipclaim of {} month year {} is approved ".format(month,year) + +def AssistantshipClaim_notify(sender, recipient, month, year): + + message = "Your Assistantshipclaim of {} month year {} is approved ".format( + month, year) url = 'academic-procedures:academic_procedures' module = 'Assistantship Request' - notify.send(sender=sender,recipient= recipient, url=url, module=module, verb=message) + notify.send(sender=sender, recipient=recipient, + url=url, module=module, verb=message) +def AssistantshipClaim_faculty_notify(sender, recipient): -def AssistantshipClaim_faculty_notify(sender,recipient): - - message=" Assistantshipclaim is requested " + message = " Assistantshipclaim is requested " url = 'academic-procedures:academic_procedures' module = 'Assistantship Request' - notify.send(sender=sender,recipient= recipient, url=url, module=module, verb=message) + notify.send(sender=sender, recipient=recipient, + url=url, module=module, verb=message) -def AssistantshipClaim_acad_notify(sender,recipient): - message = "AssistantshipClaim is requested " +def AssistantshipClaim_acad_notify(sender, recipient): + message = "AssistantshipClaim is requested " url = 'academic-procedures:academic_procedures' module = 'Assistantship Request' - notify.send(sender=sender,recipient= recipient, url=url, module=module, verb=message) + notify.send(sender=sender, recipient=recipient, + url=url, module=module, verb=message) -def AssistantshipClaim_account_notify(sender,stu, recipient): +def AssistantshipClaim_account_notify(sender, stu, recipient): message = "Assistantship claim of{} is forwaded ".format(stu) url = 'academic-procedures:academic_procedures' module = 'Assistantship Request' - notify.send(sender=sender,recipient= recipient, url=url, module=module, verb=message) + notify.send(sender=sender, recipient=recipient, + url=url, module=module, verb=message) + def department_notif(sender, recipient, type): - url='dep:dep' - module='department' + url = 'dep:dep' + module = 'department' sender = sender recipient = recipient verb = type @@ -374,13 +400,29 @@ def examination_notif(sender, recipient, type): module=module, verb=verb, flag=flag) +def examination_notif(sender, recipient, type,request): + url='examination:examination' + module='examination' + sender = sender + recipient = recipient + verb = type + flag = "examination" + + notify.send(sender=sender, + recipient=recipient, + url=url, + module=module, + verb=verb, + flag=flag) + print("test3") + # return render(request, 'examination/announcement_req.html') def office_module_DeanRSPC_notif(sender, recipient, type): - url='office:officeOfDeanRSPC' - module='Office Module' + url = 'office:officeOfDeanRSPC' + module = 'Office Module' sender = sender recipient = recipient verb = "" @@ -392,11 +434,11 @@ def office_module_DeanRSPC_notif(sender, recipient, type): elif type == 'Pending': verb = "Kindly wait for the response" + notify.send(sender=sender, recipient=recipient, + url=url, module=module, verb=verb) - notify.send(sender=sender, recipient=recipient, url=url, module=module, verb=verb) - -def research_procedures_notif(sender,recipient,type): +def research_procedures_notif(sender, recipient, type): url = 'research_procedures:patent_registration' module = 'Research Procedures' sender = sender @@ -438,4 +480,101 @@ def hostel_notifications(sender, recipient, type): elif type == "fine_imposed": verb = "A fine has been imposed on you." + notify.send(sender=sender,recipient=recipient,url=url,module=module,verb=verb) + +def prog_and_curr_notif(sender, recipient,title): + url='programme_curriculum:inward_files' + module='Programme and Curriculum' + sender = sender + recipient = recipient + verb = title + notify.send(sender=sender, recipient=recipient, url=url, module=module, verb=verb) + +def course_management_notif(sender, recipient, type, course, course_name, course_code, flag): + url = 'online_cms:course' + module="Course Management" + sender = sender + recipient = recipient + verb = type + + notify.send(sender=sender, recipient=recipient, url=url, module=module, verb=verb, flag=flag, course_code=course_code, course=course, cname = course_name) + + +def otheracademic_notif(sender, recipient, type, otheracademic_id,student,message): + if(type=='ug_leave_hod'): + url = ('otheracademic:otheracademic') + elif type=='pg_leave_ta' : + url = ('otheracademic:leaveApproveTA') + elif type=='pg_leave_hod' : + url = ('otheracademic:otheracademic') + elif type=='ast_ta' : + url = ('otheracademic:assistantship_form_approval') + elif type=='ast_thesis' : + url = ('otheracademic:assistantship_thesis') + + elif type=='ast_acadadmin' : + url = ('otheracademic:assistantship_acad_approveform') + elif type=='ast_hod' : + url = ('otheracademic:assistantship_hod') + elif type=='hostel_nodues' : + url = ('otheracademic:hostel_nodues') + elif type=='bank_nodues' : + url = ('otheracademic:Bank_nodues') + elif type=='btp_nodues' : + url = ('otheracademic:BTP_nodues') + elif type=='cse_nodues' : + url = ('otheracademic:CSE_nodues') + elif type=='design_nodues' : + url = ('otheracademic:Design_nodues') + elif type=='acad_nodues' : + url = ('otheracademic:dsa_nodues') + elif type=='ece_nodues' : + url = ('otheracademic:Ece_nodues') + elif type=='library_nodues' : + url = ('otheracademic:library_nodues') + elif type=='mess_nodues' : + url = ('otheracademic:mess_nodues') + elif type=='physics_nodues' : + url = ('otheracademic:Physics_nodues') + elif type=='discipline_nodues' : + url = ('otheracademic:discipline_nodues') + elif type=='me_nodues' : + url = ('otheracademic:ME_nodues') + elif type=="ug_leave_hod_approve": + url = ('otheracademic:leaveStatus') + elif type=="bonafide_acadadmin": + url = ('otheracademic:bonafideApproveForm') + elif type=="bonafide_accept": + url = ('otheracademic:bonafideStatus') + elif type=="ast_ta_accept": + url = ('otheracademic:assistantship_status') + elif type=="nodues_status": + url = ('otheracademic:nodues_status') + elif type=="pg_leave_ta_approve": + url = ('otheracademic:leaveStatusPG') + elif type=="pg_leave_thesis": + url = ('otheracademic:leaveApproveThesis') + else: + url=('otheracademic:otheracademic') + + + module='otheracademic' + sender = sender + recipient = recipient + verb = message + description = otheracademic_id + + notify.send(sender=sender, recipient=recipient, url=url, module=module, verb=verb,description=description) +def iwd_notif(sender,recipient,type): + module= 'iwdModuleV2' + url= 'iwdModuleV2:iwdModuleV2' + verb="" + if type == "file_forward": + verb= "file forwarded from " + sender.username+"." + if type == "Request_added": + verb= "Request added by "+ sender.username + "." + if type == "Request_approved": + verb = "Request approved by " + sender.username + "." + if type == "Request_rejected": + verb = "Request rejected by " + sender.username + "." notify.send(sender=sender,recipient=recipient,url=url,module=module,verb=verb) \ No newline at end of file diff --git a/FusionIIIT/templates/academic_procedures/academic.html b/FusionIIIT/templates/academic_procedures/academic.html index 35eebf446..a08692126 100644 --- a/FusionIIIT/templates/academic_procedures/academic.html +++ b/FusionIIIT/templates/academic_procedures/academic.html @@ -183,7 +183,7 @@ {% include 'academic_procedures/registeredCourse.html' %}
- {% include 'academic_procedures/register.html' %} + {% include 'academic_procedures/auto_pre_registration.html' %}
{% include 'academic_procedures/finalregister.html' %} @@ -204,7 +204,12 @@ Add/drop courses - + + Backlogs + + + Replace +
- +
+ {% include 'academic_procedures/backlog.html' %} +
+
+ {% include 'academic_procedures/replace.html' %} +
@@ -325,6 +335,9 @@ {% comment %} TODO: the right rail! {% endcomment %} + {% block sidepanel%} + {% include 'notifications/academic_procedures_sidepanel.html' %} + {% endblock %} {% comment %}The right-rail segment ends here!{% endcomment %} diff --git a/FusionIIIT/templates/academic_procedures/academicfac.html b/FusionIIIT/templates/academic_procedures/academicfac.html index dd74efff5..51d48685f 100644 --- a/FusionIIIT/templates/academic_procedures/academicfac.html +++ b/FusionIIIT/templates/academic_procedures/academicfac.html @@ -25,7 +25,13 @@ style="max-width: 320px;"> {% if fac_flag %} - + {% if request.user.extrainfo.user_type == 'fx' or request.user.extrainfo.user_type == 'faculty' %} + + Assigned Course + + + {% endif %} + Course Management @@ -61,9 +67,60 @@ Kartik {% endcomment %} +
+
+
+ + + + + + + + + + + + + + + + + + + {% for course in assigned_courses %} + + + + + + + -
+ + +
+ + + {%endfor%} + +

Course Name

Course Code

Course Version

Programme

Branch

Download Roll List

{{course.course_id.name }} {{course.course_id.code }} {{course.course_id.version }} {{course.batch_id.name }} {{course.batch_id.discipline.name }} +
+ {% csrf_token %} + + + +
+
+
+
+
+ +


@@ -78,7 +135,7 @@ - + - + {%if items.0.type != "Swayam" %} + + {%endif %} {% endfor %} @@ -164,6 +231,9 @@ {% comment %} TODO: the right rail! {% endcomment %} + {% block sidepanel%} + {% include 'notifications/academic_procedures_sidepanel.html' %} + {% endblock %} {% comment %}The right-rail segment ends here!{% endcomment %} @@ -181,4 +251,4 @@ -{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/academic_procedures/addCourse.html b/FusionIIIT/templates/academic_procedures/addCourse.html index c58b1ac45..42f38a05d 100755 --- a/FusionIIIT/templates/academic_procedures/addCourse.html +++ b/FusionIIIT/templates/academic_procedures/addCourse.html @@ -11,7 +11,7 @@
{% if adc_date_flag %} - {% if details.cpi >= 6.0 %} + {% if details.cpi >= 0.0 %} {% if add_courses_options %}
{% csrf_token %} diff --git a/FusionIIIT/templates/academic_procedures/allot_courses.html b/FusionIIIT/templates/academic_procedures/allot_courses.html index 5d4fc0e45..f5ac54c7e 100644 --- a/FusionIIIT/templates/academic_procedures/allot_courses.html +++ b/FusionIIIT/templates/academic_procedures/allot_courses.html @@ -27,7 +27,7 @@

Note : Provide the data in Excel Sheet in following format:

RollNo | CourseSlot Name | CourseCode | CourseName -

Download +

Download the sample Excel, fill the data accordingly and then upload the same

diff --git a/FusionIIIT/templates/academic_procedures/auto_finalregister.html b/FusionIIIT/templates/academic_procedures/auto_finalregister.html new file mode 100644 index 000000000..95788c24d --- /dev/null +++ b/FusionIIIT/templates/academic_procedures/auto_finalregister.html @@ -0,0 +1,251 @@ +{% load static %} +{% block finalregister %} + + + + +
Final Registration
+ +
+ {% if curr_sem.semester_no != 8 %} + {% if frd %} + {% if final_registration_flag == True %} +

+

You have already registered for this semester!!!
+

+ + + {% else %} +
+ + {% csrf_token %} +
+ + + + + +
+ +
+
+ + +
+
+ +
+
+
+ + +
+ +
+ +
+
+ +
+
+
+ + +
+
+ + +
+
+
+ + +
+ +
+
+ + +
+
+
+
+
+
+
+ + + +
+
+ +
+
+ +
+ +
+ + + {% comment %}
+ {% csrf_token %} + +

Fee Payment

+ + + + + + {% endcomment %} + {% endif %} + {% else %} +
+

Final Registration Date is yet to come

+
+ {% endif %} + {% else %} +
+

You are not Eligible for Registration !!

+
+ {% endif %} +
+{% endblock %} + + + + + + + + \ No newline at end of file diff --git a/FusionIIIT/templates/academic_procedures/auto_pre_registration.html b/FusionIIIT/templates/academic_procedures/auto_pre_registration.html new file mode 100644 index 000000000..b9129ca23 --- /dev/null +++ b/FusionIIIT/templates/academic_procedures/auto_pre_registration.html @@ -0,0 +1,437 @@ + + + + +{% load static %} +{% block resiterstudent %} + + +
Pre-Registration for Next Semester Courses
+
+ {% if curr_sem.semester_no != 8 %} + {% if prd %} + {% if pre_registration_flag %} + +
You have already registered at + {% if pre_registration_timestamp is not None %} + {{pre_registration_timestamp}} + {% endif %} + !!! +
+
View Courses
+
Hide courses
+
+
+
+

{{obj.course_id.code}} {{obj.course_id.name}}{{ obj.batch_id }}{{ obj.batch_id.name}} {{obj.batch_id.year}}-{{obj.batch_id.discipline.name}} +
MANAGE
+ +
+
+ + + + + + + + + + + {% for course_slot,courses in pre_registered_course_show.items %} + + + + + + + + + + {% endfor %} + + +
+ + + {% else %} +
+ {% csrf_token %} + + + + + + + + + + + + + + + {% for course_slot in next_sem_registration_courses %} + {% if course_slot.type == "Swayam" %} + {% with "x"|ljust:swayam_courses_count as dummy_range %} + {% for _ in dummy_range %} + + + + + + + + + + + {% endfor %} + {% endwith %} + {% else %} + + + + + + + + + + + + + {% endif %} + {% endfor %} + + + + +
#Slot nameSlot typeSemesterCreditsSelect
{{ forloop.counter0|add:forloop.parentloop.counter0|add:"+1" }}.{{course_slot.name}}{{course_slot.type}}{{next_sem.semester_no}} + + {{course_slot.courses.all.0.credit}} +
+ +
+
{{forloop.counter}}.{{course_slot.name}}{{course_slot.type}}{{next_sem.semester_no}} + + {{course_slot.courses.all.0.credit}} +
+ +
+
+
+
+ +
+
+
+ +
+
+
+

You need minimum {{curr_sem.curriculum.min_credit}} credits for semester {{next_sem.semester_no}}

+
+ + {% endif %} + {% else %} + {% if prd_start_date%} + +
Pre Registration will start on {{prd_start_date}}. +
+ {% else %} + +
Pre Registration date hasn't come yet +
+ {% endif %} + {% endif %} + {% else %} +
+

You are not Eligible for Registration !!

+
+ {% endif %} + + + + + +{% endblock %} + + + + diff --git a/FusionIIIT/templates/academic_procedures/backlog.html b/FusionIIIT/templates/academic_procedures/backlog.html new file mode 100644 index 000000000..c2e7897da --- /dev/null +++ b/FusionIIIT/templates/academic_procedures/backlog.html @@ -0,0 +1,76 @@ +{% load static %} +
Backlog Courses
+
+ + + + + + + + + + + + + {% for i in auto_backlog_courses_list %} + + {% for j in i %} + + {% endfor %} + + + {% endfor %} +
Course NameCourse CodeVersionCreditGrade
Apply For Registration
{{ j }}
+ {%if adc_date_flag%} + + {%else %} + + {%endif%} +
+
+ + diff --git a/FusionIIIT/templates/academic_procedures/current_sem.html b/FusionIIIT/templates/academic_procedures/current_sem.html index 59ed5ab02..dedcf982a 100755 --- a/FusionIIIT/templates/academic_procedures/current_sem.html +++ b/FusionIIIT/templates/academic_procedures/current_sem.html @@ -94,6 +94,15 @@
{{curr_sem.semester_no}}
+ +
MANAGE
+ +
+ {% endfor %} diff --git a/FusionIIIT/templates/academic_procedures/dropCourse.html b/FusionIIIT/templates/academic_procedures/dropCourse.html index a44f365a6..e310ec14e 100755 --- a/FusionIIIT/templates/academic_procedures/dropCourse.html +++ b/FusionIIIT/templates/academic_procedures/dropCourse.html @@ -1,7 +1,7 @@ {% load static %} {% block complainthistory %} -
Drop Couse(s)
+
Drop Course(s)
@@ -52,7 +52,7 @@
{% else %} - No Courses to drop +
No Courses to drop
{% endif %} {% else %}
You have to wait for the date
diff --git a/FusionIIIT/templates/academic_procedures/finalregister.html b/FusionIIIT/templates/academic_procedures/finalregister.html index 2349c5f01..e9a000f7e 100755 --- a/FusionIIIT/templates/academic_procedures/finalregister.html +++ b/FusionIIIT/templates/academic_procedures/finalregister.html @@ -143,6 +143,9 @@ + + +
@@ -212,10 +215,6 @@

Fee Payment

- - - - + + + diff --git a/FusionIIIT/templates/academic_procedures/studentCourses.html b/FusionIIIT/templates/academic_procedures/studentCourses.html index 7c1a9152c..1a15c3d1a 100644 --- a/FusionIIIT/templates/academic_procedures/studentCourses.html +++ b/FusionIIIT/templates/academic_procedures/studentCourses.html @@ -8,6 +8,27 @@ .modal('show') ; }); + function courseDropCalled(event) { + // Prevent the default action of the link + event.preventDefault(); + + // Get the URL from the link's href attribute + let url = event.target.href; + + // Perform AJAX request + $.ajax({ + url: url, + type: 'GET', + success: function(data) { + // Reload the page after successful deletion + location.reload(); + }, + error: function(xhr, status, error) { + // Handle errors if needed + console.error(error); + } + }); + } @@ -81,7 +102,7 @@ + href="/academic-procedures/acad_person/verifyCourse/drop/?id={{ items.reg_id|urlencode }}" onclick="courseDropCalled(event)" > DROP diff --git a/FusionIIIT/templates/academic_procedures/studentSwayam.html b/FusionIIIT/templates/academic_procedures/studentSwayam.html new file mode 100644 index 000000000..6a912f3e9 --- /dev/null +++ b/FusionIIIT/templates/academic_procedures/studentSwayam.html @@ -0,0 +1,322 @@ +{% load static %} + + + + +
+
+ {% if dict2 %} + +           +           +           +           + Name = {{ dict2.firstname }} {{ dict2.lastname }} +           +           +           + Roll No = {{ dict2.roll_no }} + + {% endif %} + {% if details %} + + + + + + + + + + + + + + + + + + + + + {% for items in details %} + + + + + + + + + + + + + + {% endfor %} + + +
+ Reg ID# + + Course ID + + Course Name + + Credits + + Semester + + Replace Course +
+ {{ items.rid }} + + {{ items.course_id }} + + {{ items.course_name }} + + {{ items.credits }} + + {{ items.sem }} + + +
+ + + + + + +
+ +
+ {% else %} +
+


+
+ NO RECORDS FOUND +
+ {% endif %} + +
+ {% comment %} {% endcomment %} + + + + +
+ + + + \ No newline at end of file diff --git a/FusionIIIT/templates/academic_procedures/student_table.html b/FusionIIIT/templates/academic_procedures/student_table.html index cf74029d7..696f06cc7 100755 --- a/FusionIIIT/templates/academic_procedures/student_table.html +++ b/FusionIIIT/templates/academic_procedures/student_table.html @@ -101,7 +101,8 @@ var student_id = $(this).attr('data'); $.ajax({ type: 'post', - url: '/academic-procedures/process_verification_request/', + // url: '/academic-procedures/process_verification_request/', + url: '/academic-procedures/auto_process_verification_request/', data: { student_id: student_id, status_req: 'accept', @@ -129,10 +130,12 @@ $('.reg-disapprove').on('click', function(e){ var id = $(this).attr('data-two'); var student_id = $(this).attr('data'); - var reason = $('#fname').val(); + // var reason = $('#fname').val(); + var reason = $(this).closest('.verify').find('.reason').val(); $.ajax({ type: 'post', - url: '/academic-procedures/process_verification_request/', + // url: '/academic-procedures/process_verification_request/', + url: '/academic-procedures/auto_process_verification_request/', data: { student_id: student_id, status_req: 'reject', diff --git a/FusionIIIT/templates/academic_procedures/studentlist.html b/FusionIIIT/templates/academic_procedures/studentlist.html index 8f43ce3d5..b3c3ea209 100755 --- a/FusionIIIT/templates/academic_procedures/studentlist.html +++ b/FusionIIIT/templates/academic_procedures/studentlist.html @@ -61,7 +61,7 @@ Verify Student Registration for Semester {{ date.semflag }} : {{ date.year }} - +
{% if course_verification_date %}
diff --git a/FusionIIIT/templates/academic_procedures/swayam_list.html b/FusionIIIT/templates/academic_procedures/swayam_list.html new file mode 100644 index 000000000..12c50c1de --- /dev/null +++ b/FusionIIIT/templates/academic_procedures/swayam_list.html @@ -0,0 +1,57 @@ +{% comment %} ACAD ADMIN WILL REPLACE COURSES WITH SWAYAM COURSES HERE {% endcomment%} +{% load static %} +{% block allot_swayam %} + + + + + +{% comment %}The tab menu starts here!{% endcomment %} + +
+
+ + {% csrf_token %} +
+ + +
+
+ +
+ + +
+
+ +
+
+ +{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/account/base.html b/FusionIIIT/templates/account/base.html index 986600600..b2bc50b08 100755 --- a/FusionIIIT/templates/account/base.html +++ b/FusionIIIT/templates/account/base.html @@ -70,11 +70,12 @@
{% else %} +
+ min-width: 360px;background-color: unset;backdrop-filter: blur(3px);"> {% endif %} {% block content %} @@ -83,6 +84,8 @@ {% if request.user.is_authenticated %}
+
+
{% comment %}The central-rail segment ends here!{% endcomment %} diff --git a/FusionIIIT/templates/account/login.html b/FusionIIIT/templates/account/login.html index 9bbff7e94..5940456f2 100755 --- a/FusionIIIT/templates/account/login.html +++ b/FusionIIIT/templates/account/login.html @@ -1,16 +1,17 @@ {% extends "account/base.html" %} -{%block content%} +{% block content %} {% load i18n %} {% load account socialaccount %} {% load static semanticui %} +
User Image + src="{% static 'globals/img/user.png' %}" + style="margin-top: -27.5%; margin-left: 27.5%;" + alt="User Image">
- Login -
+ Login +
@@ -18,31 +19,56 @@ {% csrf_token %} {% render_form form %} {% if redirect_field_value %} - + {% endif %}
-
{% get_providers as socialaccount_providers %}
-
- {% if socialaccount_providers %} -
-
- {% include "socialaccount/snippets/provider_list.html" with process="login" %} -
+
+ {% if socialaccount_providers %} +
+
+ {% include "socialaccount/snippets/provider_list.html" with process="login" %}
- {% include "socialaccount/snippets/login_extra.html" %} - {% endif %} -
+
+ {% include "socialaccount/snippets/login_extra.html" %} + {% endif %} +
-{% endblock %} +{% if form.errors %} + +{% endif %} + + +{% endblock %} + \ No newline at end of file diff --git a/FusionIIIT/templates/ais/account.html b/FusionIIIT/templates/ais/account.html index 9f64e467f..15e92bad6 100644 --- a/FusionIIIT/templates/ais/account.html +++ b/FusionIIIT/templates/ais/account.html @@ -1,7 +1,6 @@ {% extends 'globals/base.html' %} {% load static %} - {% block title %} Academic Information System {% endblock %} diff --git a/FusionIIIT/templates/ais/ais.html b/FusionIIIT/templates/ais/ais.html index be1e8e0ed..d749b0270 100755 --- a/FusionIIIT/templates/ais/ais.html +++ b/FusionIIIT/templates/ais/ais.html @@ -47,7 +47,7 @@

@@ -135,7 +146,7 @@
-
+
{% block generateSheet %} {% include 'ais/generateSheet.html' %} {% endblock %} @@ -170,18 +181,26 @@ {% endblock %}
-
- {% block min_credfloat_courses %} - {% include 'ais/new.html' %} + + + + + + + +
+ {% block config_pre_registration %} + {% include 'ais/pre_registration_courses.html' %} {% endblock %}
- {% block curriculum %} - {% include 'ais/curriculum.html' %} + {% block config_pre_reg_courses %} + {% include 'ais/config_courseslot_courses.html' %} {% endblock %}
+
{% block branch_change %} {% include 'academic_procedures/academicadminforbranch.html' %} @@ -206,17 +225,33 @@ {% include 'ais/student_dashboard.html' %} {% endblock %}
+ +
+ {% block allot_swayam %} + {% include 'academic_procedures/swayam_list.html' %} + {% endblock %} +
+ + +
+ {% block curriculum %} + {% include 'ais/curriculum.html' %} + {% endblock %} +
- + {% block sidepanel%} + {% include 'notifications/academic_procedures_sidepanel.html' %} {% endblock %}
-
--> +
{% endblock %} diff --git a/FusionIIIT/templates/ais/config_courseslot_courses.html b/FusionIIIT/templates/ais/config_courseslot_courses.html new file mode 100644 index 000000000..ca3bcba67 --- /dev/null +++ b/FusionIIIT/templates/ais/config_courseslot_courses.html @@ -0,0 +1,140 @@ + + + +{% load static %} +{% block config_courseslot_courses %} + + + +
+ +
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+
+ + + + +{% endblock %} + + + + + + diff --git a/FusionIIIT/templates/ais/generateSheet.html b/FusionIIIT/templates/ais/generateSheet.html index fe03efbfd..16996f7e2 100755 --- a/FusionIIIT/templates/ais/generateSheet.html +++ b/FusionIIIT/templates/ais/generateSheet.html @@ -21,7 +21,7 @@ success: function(jsondata) { $("#loading").hide(); - console.log(jsondata); + // console.log(jsondata); $('#course_list').html(jsondata.html); }, error: function(data) @@ -33,29 +33,29 @@ -
+
{% csrf_token %}
- -
diff --git a/FusionIIIT/templates/ais/pre_registration_courses.html b/FusionIIIT/templates/ais/pre_registration_courses.html new file mode 100644 index 000000000..e861ec3c8 --- /dev/null +++ b/FusionIIIT/templates/ais/pre_registration_courses.html @@ -0,0 +1,254 @@ + + + + +{% load static %} +{% block config_pre_registration %} + + + +
+
+
+ + +
+ +
+ + +
+
+ +
+ + +
+ +
+ + +
+ +
+ +
+
+ + +
+ +
+ +
+ + + + {% csrf_token %} + + + + + + +
+ + +
+
+
+ + + +{% endblock %} + + + + diff --git a/FusionIIIT/templates/ais/profile.html b/FusionIIIT/templates/ais/profile.html index 479de29f6..d30c5fa0e 100755 --- a/FusionIIIT/templates/ais/profile.html +++ b/FusionIIIT/templates/ais/profile.html @@ -29,7 +29,7 @@

Note : Provide the data in Excel Sheet in following format:

RollNo | First Name | Last Name | Email | Sex | DOB | Father's Name | Mother's Name | Category | Phone No | Address | Department | Specialization | Hall No -

Download the sample Excel, fill the data accordingly and then upload the same

+

Download the sample Excel, fill the data accordingly and then upload the same

diff --git a/FusionIIIT/templates/ais/student_dashboard.html b/FusionIIIT/templates/ais/student_dashboard.html index 06ad5ae92..9d1a4c45a 100644 --- a/FusionIIIT/templates/ais/student_dashboard.html +++ b/FusionIIIT/templates/ais/student_dashboard.html @@ -21,7 +21,7 @@
- +
diff --git a/FusionIIIT/templates/coursemanagement/academicinfo.html b/FusionIIIT/templates/coursemanagement/academicinfo.html new file mode 100644 index 000000000..23021753b --- /dev/null +++ b/FusionIIIT/templates/coursemanagement/academicinfo.html @@ -0,0 +1,192 @@ +{% extends 'globals/base.html' %} +{% load static %} + + +{% block title %} +Academic Information System +{% endblock %} + +{% block css %} + + + + + + + +{% endblock %} + +{% block body %} +{% block navBar %} +{% include 'dashboard/navbar.html' %} +{% endblock %} + + +
+ +
+ +
+ + {% block usercard %} + {% include 'globals/usercard.html' %} + {% endblock %} + +
+ + +

+ +
+ +
+ +
+ {% block calendar %} + {% include 'coursemanagement/calendar.html' %} + {% endblock %} +
+ +
+ {% block timetable %} + {% include 'coursemanagement/timetable.html' %} + {% endblock %} +
+ +
+ +
+ + +
+
+{% endblock %} + +{% block javascript %} + + + + + + + + + + +{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/coursemanagement/addcontent.html b/FusionIIIT/templates/coursemanagement/addcontent.html index 22e9986c7..09ec62510 100644 --- a/FusionIIIT/templates/coursemanagement/addcontent.html +++ b/FusionIIIT/templates/coursemanagement/addcontent.html @@ -1,21 +1,46 @@ {% load static %} {% block addcontent %} - - -
+
+

Add a Module

+
+ Add Module +
+ +

Add a Slide

Add Slides
+ + + + + + {% endfor %} + +{% endblock %} + + + + \ No newline at end of file diff --git a/FusionIIIT/templates/coursemanagement/comments.html b/FusionIIIT/templates/coursemanagement/comments.html index 6cdde2aea..f97a2c5b0 100644 --- a/FusionIIIT/templates/coursemanagement/comments.html +++ b/FusionIIIT/templates/coursemanagement/comments.html @@ -2,8 +2,8 @@ {% load humanize %} {% block comments %} -
-

Comments

+
+

Announcements

{% for key, value in answers.items %}
@@ -15,7 +15,6 @@

Comments

-

{{key.comment}}

@@ -23,8 +22,9 @@

Comments

Remove
+
-
+
{% endfor %} + +
+{% if Lecturer == 1%}
{% csrf_token %}
- +
- +
-
- +{% endif %} -{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/coursemanagement/coursemanagement1.html b/FusionIIIT/templates/coursemanagement/coursemanagement1.html index 678d79b71..b0d9b3982 100644 --- a/FusionIIIT/templates/coursemanagement/coursemanagement1.html +++ b/FusionIIIT/templates/coursemanagement/coursemanagement1.html @@ -53,7 +53,7 @@
{% comment %} The left-rail segment starts here! {% endcomment %} -
+
{% comment %}The user image card starts here!{% endcomment %} {% block usercard %} {% include 'globals/usercard.html' %} {% endblock %} {% comment %}The user image card ends here!{% endcomment %} @@ -66,7 +66,7 @@
{% comment %} The left-rail segment ends here! {% endcomment %} {% comment %} The central-rail segment starts here! {% endcomment %} -
+
{% comment %}The view courses start here!{% endcomment %}
{% comment %}The CSS starts here!{% endcomment %} {% comment %}The CSS ends here!{% endcomment %} {% comment %}The tab menu starts here!{% endcomment %} @@ -85,15 +85,15 @@

Course Code Name Of the Course - {% ifequal extrainfo.designation|stringformat:"s" "student" %} - Instructor {% endifequal %} + {% if extrainfo.user_type == 'student'%} + Instructor {% endif %} - {% ifequal extrainfo.designation|stringformat:"s" "student" %} {% for course,instructor in courses.items %} + {% if extrainfo.user_type == 'student'%} {% for course,instructor in courses.items %} - {{course.course_id.course_name}} - {{course.course_id.course_id}} + {{course.curr_id.course_code}} + {{course.curr_id.course_id.course_name}} {{instructor.instructor_id.user.username}} {% endfor %} {% else %} @@ -105,510 +105,30 @@

{% endfor %} - {% endifequal %} + {% endif %}

- - {% comment %}The Basic Course details segment ends here!{% endcomment %} {% comment %}The Assignment segment starts here!{% endcomment %} - -
- -

-
- -
- -
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
- -
- {% comment %}The assignment ends here!{% endcomment %} {% comment %}The video segment starts here!{% endcomment %} -
-

Software Engineering Videos

-
-
-
-
-
- -
-
- -
- -
-
- -
-
- -
-
-
-
- -
-
- -
- -

Computer Networks Videos

-
-
-
-
-
- -
-
- -
- -
-
- -
-
- -
-
-
-
- -
-
- -
- -

Operating System Videos Videos

-
-
-
-
-
- -
-
- -
- -
-
- -
-
- -
-
-
-
- -
-
- -
- - -
- - - - - {% comment %}The video segment ends here!{% endcomment %} {% comment %}The slides segment starts here!{% endcomment %} - -
-

Software Engineering Slides

- -
-
-
- - - - -
-
- - - - - -
-
- - - - - -
-
- - - - -
-
- -
- - - -

Computer Networks Slides

- -
-
-
- - - - -
-
- - - - - -
-
- - - - - -
-
- - - - -
-
- -
- - -

Operating Systems Slides

- -
-
-
- - - - -
-
- - - - - -
-
- - - - - -
-
- - - - -
-
- -
- - - - -
- - - {% comment %}The Slides segment ends here!{% endcomment %} {% comment %}The time-table segment starts here!{% endcomment %} - -
-

Class Time Table

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Days9-10 AM10-11 AM11-12 AM12-01 PM2:30-3:30 PM3:30-5:30 PM
MondaySeptemberjhlilk22NoNoNoNo
Monday January jamiehYesNoNoNo
Monday May 11,jilsewYesNoNoNo
- -

Quiz Time Table

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Days9-10 AM10-11 AM11-12 AM12-01 PM2:30-3:30 PM3:30-5:30 PM
MondaySeptemberjhlilk22NoNoNoNo
Monday January jamiehYesNoNoNo
Monday May 11,jilsewYesNoNoNo
- -
- - {% comment %}The time-table segment ends here!{% endcomment %} {% comment %}The quiz segment starts here!{% endcomment %} -
-
- -
- Hours -
- -
- Minutes -
- -
- Seconds -
- -
- -

-
- - -
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
-
- {% comment %}The view courses end here!{% endcomment %} {% comment %}The submit assignment starts here!{% endcomment %} - -
- {% block submitassignments %} {% include 'coursemanagement/submitassignments.html' %} {% endblock %} -
- - {% comment %}The submit assignment ends here!{% endcomment %} {% comment %}The view performance starts here!{% endcomment %} - -
- {% block viewperformance %} {% include 'coursemanagement/viewperformance.html' %} {% endblock %}
- - {% comment %}The view performance ends here!{% endcomment %} {% comment %}The assessment starts here!{% endcomment %} - -
- {% block assessment %} {% include 'coursemanagement/assessment.html' %} {% endblock %} -
- - {% comment %}The assessment ends here!{% endcomment %} {% comment %}The add contents starts here!{% endcomment %} {% comment %} -
- {% block addcontent %} {% include 'coursemanagement/addcontent.html' %} {% endblock %} -
- {% endcomment %} {% comment %}The add content ends here!{% endcomment %} - - {% comment %}The Attendance starts here!{% endcomment %} {% comment %} -
- {% block attendance %} {% include 'coursemanagement/attendance.html' %} {% endblock %} -
- {% endcomment %} {% comment %}The Attendance ends here!{% endcomment %} - - - - - - - -
- {% comment %}The central-rail segment ends here!{% endcomment %} {% comment %}The right-rail segment starts here!{% endcomment %} +
- {% comment %}The grid ends here!{% endcomment %} {% endblock %} {% block javascript %} - - + -
- - --> + + + + + + + +{% endblock %} diff --git a/FusionIIIT/templates/coursemanagement/manageEval.html b/FusionIIIT/templates/coursemanagement/manageEval.html new file mode 100644 index 000000000..8a2c149a7 --- /dev/null +++ b/FusionIIIT/templates/coursemanagement/manageEval.html @@ -0,0 +1,221 @@ +{% load static %} +{% block css %} + + +{% endblock %} +{% block manageEval %} +
+

Manage Evaluations

+

(Please Click on Generate button before uploading)

+
+ {% csrf_token %} + +
+ + + + + + + + + + + {% if student_grades %} + {% for row in student_grades %} + + + + + + {% endfor %} + {% else%} + {% for stu in registered_students %} + {% if marks_with_roll %} + {% for roll, marks in marks_with_roll.items %} + {% if stu.student_id.id.id == roll %} + + + + + + + {% endif %} + {% endfor %} + {% else %} + + + + + + {% endif %} + {% endfor %} + {% endif %} + +
Roll NoTotal Marks (%) +
Grade
+
Generate
+
+ + + + + +
+ + + + + +
+ + + + + +
+
+
+ +
+ +
+
+
+ + + + + + + + + +{% endblock %} diff --git a/FusionIIIT/templates/coursemanagement/submit_marks.html b/FusionIIIT/templates/coursemanagement/submit_marks.html new file mode 100644 index 000000000..789e90dfe --- /dev/null +++ b/FusionIIIT/templates/coursemanagement/submit_marks.html @@ -0,0 +1,155 @@ +{% load static %} {% block assessment %} + +
+

{{course.name}}

+
+ + {% csrf_token %} +
+
+ + +
+ +
+ + + + + + + + + + + {% for x in registered_students %} + + + + + + {% endfor %} + +
Roll No.Student NameMarks Obtained
+
+

{{x.student_id}}

+
+
+
+

{{x.student_id.id.user.first_name}} {{x.student_id.id.user.last_name}}

+
+
+ + + +
+
+
+ + +
+
+ +{% endblock %} + + + + + + diff --git a/FusionIIIT/templates/coursemanagement/submitassignments.html b/FusionIIIT/templates/coursemanagement/submitassignments.html index 217a12bde..310686ce4 100644 --- a/FusionIIIT/templates/coursemanagement/submitassignments.html +++ b/FusionIIIT/templates/coursemanagement/submitassignments.html @@ -1,7 +1,7 @@ {% load static %} {% block submitassignments %} - + + + + + - + @@ -773,24 +969,24 @@

Quiz Time Table

.modal('show'); }); - + - - - + + + {% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/coursemanagement/viewperformance.html b/FusionIIIT/templates/coursemanagement/viewperformance.html index 386b6a9af..35794b4ac 100644 --- a/FusionIIIT/templates/coursemanagement/viewperformance.html +++ b/FusionIIIT/templates/coursemanagement/viewperformance.html @@ -1,20 +1,24 @@ {% load static %} {% block viewperformance %} -