From 144554e5956b8fd2981ff6724ef7d7c4086a6541 Mon Sep 17 00:00:00 2001 From: harshabonu Date: Sat, 17 Feb 2024 19:33:25 +0530 Subject: [PATCH 1/3] latest Examination Module --- .../applications/examination/api/views.py | 94 ---------- FusionIIIT/applications/examination/models.py | 9 - FusionIIIT/applications/examination/urls.py | 12 +- FusionIIIT/applications/examination/views.py | 150 ++++++++++++++-- FusionIIIT/templates/dashboard/modules.html | 2 +- .../templates/examination/announcement.html | 134 -------------- .../examination/announcement_req.html | 138 +++++++++++++++ .../exam_make_announcement_fac.html | 167 ++++++++++++++++++ .../exam_make_announcement_staff.html | 167 ++++++++++++++++++ .../templates/examination/examination.html | 2 +- .../examination/notReady_publish.html | 4 +- FusionIIIT/templates/examination/publish.html | 4 +- FusionIIIT/templates/examination/submit.html | 16 +- .../templates/examination/timetable.html | 57 ++++++ FusionIIIT/templates/examination/verify.html | 4 +- 15 files changed, 687 insertions(+), 273 deletions(-) delete mode 100644 FusionIIIT/templates/examination/announcement.html create mode 100644 FusionIIIT/templates/examination/announcement_req.html create mode 100644 FusionIIIT/templates/examination/exam_make_announcement_fac.html create mode 100644 FusionIIIT/templates/examination/exam_make_announcement_staff.html create mode 100644 FusionIIIT/templates/examination/timetable.html diff --git a/FusionIIIT/applications/examination/api/views.py b/FusionIIIT/applications/examination/api/views.py index 448b3bbb5..f5a8a9d5d 100644 --- a/FusionIIIT/applications/examination/api/views.py +++ b/FusionIIIT/applications/examination/api/views.py @@ -21,48 +21,6 @@ from rest_framework.response import Response -#Login -# @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/submit/') -# elif str(request.user) == "acadadmin" : -# return HttpResponseRedirect('/examination/submit/') - -# return HttpResponseRedirect('/dashboard/') - -# @login_required(login_url='/accounts/login') - - - - -#Get all students -# @api_view(['GET']) -# def fetch_student_details(request): -# if request.method == 'GET': -# # obj=course_registration.objects.filter(course_id__id=course_id, student_id__batch=batch) -# obj=course_registration.objects.all() -# obj_serialized = serializers.CourseRegistrationSerializer(obj , many=True).data -# resp = { -# 'objt' : obj_serialized -# } - -# return Response(data=resp , status=status.HTTP_200_OK) - - - @api_view(['GET', 'POST']) @@ -219,55 +177,3 @@ def publish_grade(request): return JsonResponse({'error': 'Authentication object not present'}, status=404) - - -# def submit(request): - -# return render(request,'../templates/examination/submit.html' , {}) - -# @login_required(login_url='/accounts/login') -# def verify(request): -# return render(request,'../templates/examination/verify.html' , {}) - -# @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',{}) - - -# @api_view(['POST']) -# def publish_result(request): - - - - - - - - - -# def add_student(request): -# if request.method == 'POST': -# # Assuming the POST request contains necessary data for a new student -# student_id = request.POST.get('student_id') -# course_id = request.POST.get('course_id') -# semester_id = request.POST.get('semester_id') -# grades = request.POST.get('grades') - -# # Create a new private_grade object -# new_student = hidden_grades.objects.create( -# student_id=student_id, -# course_id=course_id, -# semester_id=semester_id, -# grades=grades -# ) - -# return JsonResponse({'message': 'Student added successfully'}) -# else: -# return JsonResponse({'error': 'Invalid request method'}, status=400) - - diff --git a/FusionIIIT/applications/examination/models.py b/FusionIIIT/applications/examination/models.py index edd5e453d..504b2f68b 100644 --- a/FusionIIIT/applications/examination/models.py +++ b/FusionIIIT/applications/examination/models.py @@ -36,12 +36,3 @@ class grade(models.Model): curriculum = models.CharField(max_length=50) semester_id = models.CharField(max_length=10) grade = models.CharField(max_length=5,default="B") - -# class final_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,default="") - -# # def __str__(self): -# # return f"{self.student_id}, {self.course_id}" diff --git a/FusionIIIT/applications/examination/urls.py b/FusionIIIT/applications/examination/urls.py index 101bd40fd..9a767f298 100644 --- a/FusionIIIT/applications/examination/urls.py +++ b/FusionIIIT/applications/examination/urls.py @@ -4,8 +4,16 @@ from . import views from django.contrib import admin - +app_name = 'examination' urlpatterns = [ - url(r'^api/', include('applications.examination.api.urls')) + url(r'^api/', include('applications.examination.api.urls')), + url(r'^$', views.exam, name='exam'), + url(r'submit/', views.submit, name='submit'), + url(r'verify/', views.verify, name='verify'), + url(r'publish/', views.publish, name='publish'), + url(r'notReady_publish/', views.notReady_publish, name='notReady_publish'), + url(r'announcement/', views.announcement, name='announcement'), + url(r'timetable/', views.timetable, name='timetable'), + ] diff --git a/FusionIIIT/applications/examination/views.py b/FusionIIIT/applications/examination/views.py index 82880ad8d..c606b5a79 100644 --- a/FusionIIIT/applications/examination/views.py +++ b/FusionIIIT/applications/examination/views.py @@ -6,15 +6,24 @@ from django.contrib import messages from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User +from datetime import date -# from applications.academic_information.models import Student +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 +from applications.globals.models import (Designation, ExtraInfo, + HoldsDesignation,Faculty) +from applications.eis.models import (faculty_about, emp_research_projects) + +from notification.views import department_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 applications.academic_procedures.models import(course_registration) - -from rest_framework.decorators import api_view -from rest_framework.response import Response @login_required(login_url='/accounts/login') def exam(request): @@ -27,20 +36,125 @@ def exam(request): @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/submit/') - elif str(request.user) == "acadadmin" : - return HttpResponseRedirect('/examination/submit/') + # """ + # 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/submit/') + # elif str(request.user) == "acadadmin" : + # return HttpResponseRedirect('/examination/submit/') - return HttpResponseRedirect('/dashboard/') + return render(request,'../templates/examination/submit.html' , {}) + +@login_required(login_url='/accounts/login') +def submit(request): + return render(request,'../templates/examination/submit.html' , {}) +@login_required(login_url='/accounts/login') +def verify(request): + return render(request,'../templates/examination/verify.html' , {}) + +@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',{}) -@api_view(['POST']) -def fetch_student_details(request): - # obj=course_registration.objects.filter(course_id__id=course_id, student_id__batch=batch) - obj=course_registration.objects.all() - return obj +@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 + + + +@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. + + """ + 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) + 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) + + context = browse_announcements() + return render(request, 'examination/announcement_req.html', {"user_designation":user_info.user_type, + "announcements":context, + "request_to":requests_received + }) \ No newline at end of file diff --git a/FusionIIIT/templates/dashboard/modules.html b/FusionIIIT/templates/dashboard/modules.html index ab5e0c192..d47163423 100755 --- a/FusionIIIT/templates/dashboard/modules.html +++ b/FusionIIIT/templates/dashboard/modules.html @@ -242,7 +242,7 @@
- Examination Module + Examination
Module
diff --git a/FusionIIIT/templates/examination/announcement.html b/FusionIIIT/templates/examination/announcement.html deleted file mode 100644 index a15d1acf1..000000000 --- a/FusionIIIT/templates/examination/announcement.html +++ /dev/null @@ -1,134 +0,0 @@ -{% extends 'examination/base.html' %} -{% block sidetabmenu %} - -{% endblock %} - -{% block content %} - -

Announcement

-
- -{% comment %} Combined {% endcomment %} -
- -{% comment %} First Row {% endcomment %} -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
- - -{% comment %} Second Row {% endcomment %} - -
- -
-
- -
- -
- - - - - - - - - -
- - - - - - - -
- -{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/examination/announcement_req.html b/FusionIIIT/templates/examination/announcement_req.html new file mode 100644 index 000000000..d08136778 --- /dev/null +++ b/FusionIIIT/templates/examination/announcement_req.html @@ -0,0 +1,138 @@ +{% extends 'globals/base.html' %} +{% load static %} + + +{% block title %} + Announcement - Faculty View +{% endblock %} + + +{% block body %} + {% block navBar %} + {% include 'dashboard/navbar.html' %} + {% endblock %} + + {% comment %}The grid starts here!{% endcomment %} +
+ + {% comment %}The left-margin segment!{% endcomment %} +
+ + {% 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 %} + + + +
+ + {% comment %}The Tab-Menu starts here!{% endcomment %} + + {% comment %}The Tab-Menu ends here!{% endcomment %} + +
+ {% comment %} + The left-rail segment ends here! + {% endcomment %} + + + + {% comment %} + The central-rail segment starts here! + {% endcomment %} +
+ + {% comment %}Make announcement{% endcomment %} +
+ {% block make_announcement %} + {% if user_designation == "faculty" %} + {% include "examination/exam_make_announcement_fac.html" %} + {% elif user_designation == "staff" %} + {% include "examination/exam_make_announcement_staff.html" %} + {% endif %} + {% endblock %} +
+ {% comment %}Make announcement{% endcomment %} + + {% comment %}See announcement{% endcomment %} +
+ {% block browse_announcement %} + {% if user_designation == "faculty" %} + {% include "department/browse_announcements.html" %} + {% elif user_designation == "staff" %} + {% include "department/browse_announcements_staff.html" %} + {% endif %} + {% endblock %} +
+ {% comment %}See announcement{% endcomment %} + + {% comment %}status of request!{% endcomment %} +
+ {% block request_status %} + {% include "department/request_status.html" %} + {% endblock %} +
+ {% comment %}status of request!{% endcomment %} + + + +
+ +
+
+ {% comment %} + TODO: the right rail! + {% endcomment %} +
+
+ {% comment %}The right-rail segment ends here!{% endcomment %} + + {% comment %}The right-margin segment!{% endcomment %} +
+ + +
+ {% comment %}The grid ends here!{% endcomment %} + + +{% include 'department/alert.html' %} +{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/examination/exam_make_announcement_fac.html b/FusionIIIT/templates/examination/exam_make_announcement_fac.html new file mode 100644 index 000000000..f795e8c6a --- /dev/null +++ b/FusionIIIT/templates/examination/exam_make_announcement_fac.html @@ -0,0 +1,167 @@ +{% load static %} +{% block make_announcements %} + + {% comment %}The tab menu starts here!{% endcomment %} + + +
+
+ +
+ {% csrf_token %} +
+ Make a new Announcement for Students: +
+ +
+ +
+ +
+ + +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ +
+ + +
+ +
+ + +
+ + + +
+ + + +
+
+ +
+ +
+
+
+
+ +{% endblock %} + +{% block javascript %} + + + + +{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/examination/exam_make_announcement_staff.html b/FusionIIIT/templates/examination/exam_make_announcement_staff.html new file mode 100644 index 000000000..12c6a6afd --- /dev/null +++ b/FusionIIIT/templates/examination/exam_make_announcement_staff.html @@ -0,0 +1,167 @@ +{% load static %} +{% block make_announcements %} + + {% comment %}The tab menu starts here!{% endcomment %} + + +
+
+ +
+ {% csrf_token %} +
+ Make a new Announcement for Students: +
+ +
+ +
+ +
+ + +
+ +
+ + +
+
+ +
+ +
+ + +
+
+ +
+ + +
+ +
+ + +
+ + + +
+ + + +
+
+ +
+ +
+
+
+
+ +{% endblock %} + +{% block javascript %} + + + + +{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/examination/examination.html b/FusionIIIT/templates/examination/examination.html index f2ab2a438..ec48a9a6b 100644 --- a/FusionIIIT/templates/examination/examination.html +++ b/FusionIIIT/templates/examination/examination.html @@ -14,7 +14,7 @@ Announcement - Time Table + Time Table diff --git a/FusionIIIT/templates/examination/notReady_publish.html b/FusionIIIT/templates/examination/notReady_publish.html index 9af2dd9bc..230b89bb8 100644 --- a/FusionIIIT/templates/examination/notReady_publish.html +++ b/FusionIIIT/templates/examination/notReady_publish.html @@ -11,10 +11,10 @@ Publish - Announcement + Announcement - Time Table + Time Table diff --git a/FusionIIIT/templates/examination/publish.html b/FusionIIIT/templates/examination/publish.html index cf0ae053c..97879e2b0 100644 --- a/FusionIIIT/templates/examination/publish.html +++ b/FusionIIIT/templates/examination/publish.html @@ -11,10 +11,10 @@ Publish - Announcement + Announcement - Time Table + Time Table diff --git a/FusionIIIT/templates/examination/submit.html b/FusionIIIT/templates/examination/submit.html index 6cf48adf8..579706bce 100644 --- a/FusionIIIT/templates/examination/submit.html +++ b/FusionIIIT/templates/examination/submit.html @@ -11,10 +11,10 @@ Publish - Announcement + Announcement - Time Table + Time Table @@ -113,13 +113,13 @@

Submit Result

- - - - + Search + + + diff --git a/FusionIIIT/templates/examination/timetable.html b/FusionIIIT/templates/examination/timetable.html new file mode 100644 index 000000000..846dc601f --- /dev/null +++ b/FusionIIIT/templates/examination/timetable.html @@ -0,0 +1,57 @@ + +{% extends 'examination/base.html' %} +{% block sidetabmenu %} + +{% endblock %} + +{% block content %} + +

Time Table

+
+ +
+

Show Time Table

+ + + +
+{% comment %} + +
+
+ +
+ +
{% endcomment %} + + + +{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/examination/verify.html b/FusionIIIT/templates/examination/verify.html index 3aec12b1e..2e8082b14 100644 --- a/FusionIIIT/templates/examination/verify.html +++ b/FusionIIIT/templates/examination/verify.html @@ -64,10 +64,10 @@ Publish - Announcement + Announcement - Time Table + Time Table From 23b806299076cf8ec4f81738b0e4fab2c837e18c Mon Sep 17 00:00:00 2001 From: harshabonu Date: Tue, 20 Feb 2024 15:06:04 +0530 Subject: [PATCH 2/3] latest examination module code --- .../applications/examination/api/urls.py | 5 + .../applications/examination/api/views.py | 115 +++++++++-- FusionIIIT/applications/examination/forms.py | 4 + FusionIIIT/applications/examination/urls.py | 7 + FusionIIIT/applications/examination/views.py | 194 +++++++++++++++--- FusionIIIT/notification/views.py | 14 ++ .../examination/all_course_grade_filled.html | 37 ++++ .../templates/examination/entergrades.html | 70 +++++++ .../templates/examination/grades_updated.html | 94 +++++++++ FusionIIIT/templates/examination/submit.html | 160 ++++++--------- FusionIIIT/templates/examination/verify.html | 127 ++++++------ .../templates/examination/verifygrades.html | 70 +++++++ 12 files changed, 681 insertions(+), 216 deletions(-) create mode 100644 FusionIIIT/applications/examination/forms.py create mode 100644 FusionIIIT/templates/examination/all_course_grade_filled.html create mode 100644 FusionIIIT/templates/examination/entergrades.html create mode 100644 FusionIIIT/templates/examination/grades_updated.html create mode 100644 FusionIIIT/templates/examination/verifygrades.html diff --git a/FusionIIIT/applications/examination/api/urls.py b/FusionIIIT/applications/examination/api/urls.py index 31cbcd277..2690bd1f3 100644 --- a/FusionIIIT/applications/examination/api/urls.py +++ b/FusionIIIT/applications/examination/api/urls.py @@ -10,6 +10,11 @@ # url(r'^add_student/', views.add_student, name='add_student'), url(r'^update_hidden_grade/', views.update_hidden_grade, name='update_hidden_grade'), + + url(r'^update_hidden_grade_multiple/', views.update_hidden_grade_multiple, name='update_hidden_grade_multiple'), + + url(r'^enter_student_grades/', views.enter_student_grades, name='enter_student_grades'), + url(r'^update_authenticator/', views.update_authenticator, name='update_authenticator'), diff --git a/FusionIIIT/applications/examination/api/views.py b/FusionIIIT/applications/examination/api/views.py index f5a8a9d5d..1fe237d94 100644 --- a/FusionIIIT/applications/examination/api/views.py +++ b/FusionIIIT/applications/examination/api/views.py @@ -1,6 +1,7 @@ +from datetime import datetime 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 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 @@ -12,8 +13,9 @@ from applications.globals.models import (DepartmentInfo, Designation, ExtraInfo, Faculty, HoldsDesignation) -from applications.academic_procedures.models import(course_registration) -from applications.examination.models import(hidden_grades , authentication , grade) +from applications.academic_procedures.models import (course_registration) +from applications.examination.models import ( + hidden_grades, authentication, grade) from . import serializers from rest_framework import status @@ -21,8 +23,6 @@ from rest_framework.response import Response - - @api_view(['GET', 'POST']) def fetch_student_details(request): if request.method == 'GET': @@ -36,7 +36,8 @@ def fetch_student_details(request): obj = course_registration.objects.filter(course_id=course_id) # Serialize the queryset - obj_serialized = serializers.CourseRegistrationSerializer(obj, many=True).data + obj_serialized = serializers.CourseRegistrationSerializer( + obj, many=True).data # Prepare the response data resp = { @@ -45,7 +46,7 @@ def fetch_student_details(request): # Return the response return Response(data=resp, status=status.HTTP_200_OK) - + elif request.method == 'POST': # Extract data from the request data = request.data @@ -59,7 +60,8 @@ def fetch_student_details(request): # Check if the entry already exists try: - hidden_grade_obj = hidden_grades.objects.get(student_id=student_id, course_id=course_id) + hidden_grade_obj = hidden_grades.objects.get( + student_id=student_id, course_id=course_id) # If exists, update the grade hidden_grade_obj.grade = grade hidden_grade_obj.save() @@ -73,7 +75,50 @@ def fetch_student_details(request): ) return Response({'message': 'Hidden grade added successfully'}, status=status.HTTP_201_CREATED) + +@api_view(['POST']) +def enter_student_grades(request): + if request.method == 'POST': + # Extract data from the request + data = request.data.get('grades', []) + + if not data: + return Response({'error': 'No data provided'}, status=status.HTTP_400_BAD_REQUEST) + for grade_data in data: + student_id = grade_data.get('student_id') + course_id = grade_data.get('course_id') + semester_id = grade_data.get('semester_id') + grade = grade_data.get('grade') + + if student_id is None or course_id is None or semester_id is None or grade is None: + return Response({'error': 'Incomplete data provided'}, status=status.HTTP_400_BAD_REQUEST) + + try: + hidden_grade_obj = hidden_grades.objects.get( + student_id=student_id, + course_id=course_id, + semester_id=semester_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( + student_id=student_id, + course_id=course_id, + semester_id=semester_id, + grade=grade + ) + + return Response({'message': 'Hidden grades added successfully'}, status=status.HTTP_201_CREATED) + else: + return Response({'error': 'Unsupported method'}, status=status.HTTP_405_METHOD_NOT_ALLOWED) + + + + @api_view(['PATCH']) @@ -87,7 +132,8 @@ def update_hidden_grade(request): grade = request.data['grade'] # Get the hidden grade object for the given course_id and student_id try: - hidden_grade = hidden_grades.objects.get(course_id=course_id, student_id=student_id) + hidden_grade = hidden_grades.objects.get( + course_id=course_id, student_id=student_id) hidden_grade.grade = grade hidden_grade.save() return JsonResponse({'message': 'Grade updated successfully'}, status=200) @@ -97,21 +143,49 @@ def update_hidden_grade(request): return JsonResponse({'error': 'Incomplete data provided'}, status=400) else: return JsonResponse({'error': 'Unsupported method'}, status=405) - - - +@api_view(['PATCH']) +def update_hidden_grade_multiple(request): + if request.method == 'PATCH': + # Check if the data is provided in the request + if 'grades' in request.data: + grades_data = request.data['grades'] + for grade_data in grades_data: + course_id = grade_data.get('course_id') + student_id = grade_data.get('student_id') + semester_id = grade_data.get('semester_id') + grade = grade_data.get('grade') + + if course_id is None or student_id is None or semester_id is None or grade is None: + return Response({'error': 'Incomplete data provided for one of the grades'}, status=400) + + # Get the hidden grade object for the given course_id, student_id, and semester_id + 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() + + return Response({'message': 'Grades updated successfully'}, status=200) + else: + return Response({'error': 'No grade data provided'}, status=400) + else: + return Response({'error': 'Unsupported method'}, status=405) -from datetime import datetime @api_view(['PATCH']) def update_authenticator(request): if request.method == 'PATCH': # Extract year and authenticator number from the request year = request.data.get('year') authenticator_number = request.data.get('authenticator_number') - + # Validate year format try: datetime.strptime(year, '%Y') @@ -120,7 +194,7 @@ def update_authenticator(request): # Retrieve all authentication objects for the given year auth_objects = authentication.objects.filter(year__year=year) - + if not auth_objects.exists(): return Response({'error': 'No authentication entries found for the provided year.'}, status=status.HTTP_404_NOT_FOUND) @@ -134,14 +208,12 @@ def update_authenticator(request): 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}'}, status=status.HTTP_200_OK) - - @api_view(['GET']) def publish_grade(request): course_id = request.GET.get('course_id') @@ -150,7 +222,8 @@ def publish_grade(request): 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) + hidden_grades_list = hidden_grades.objects.filter( + course_id=course_id) # Update final grades table for hidden_grade in hidden_grades_list: @@ -175,5 +248,3 @@ def publish_grade(request): return JsonResponse({'error': 'Not all authenticators are True'}, status=400) else: return JsonResponse({'error': 'Authentication object not present'}, status=404) - - 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/urls.py b/FusionIIIT/applications/examination/urls.py index 9a767f298..7fcd35351 100644 --- a/FusionIIIT/applications/examination/urls.py +++ b/FusionIIIT/applications/examination/urls.py @@ -15,5 +15,12 @@ url(r'notReady_publish/', views.notReady_publish, name='notReady_publish'), url(r'announcement/', views.announcement, name='announcement'), url(r'timetable/', views.timetable, name='timetable'), + path('entergrades/', views.entergrades, name='entergrades'), + path('update_hidden_grades_multiple/', views.Updatehidden_gradesMultipleView.as_view(), + name='update_hidden_grades_multiple'), + path('verifygrades/', views.verifygrades, name='verifygrades'), + path('update_hidden_grades_multiple/', views.Updatehidden_gradesMultipleView.as_view(), + name='update_hidden_grades_multiple'), + # url(r'entergrades/', views.entergrades, name='entergrades'), ] diff --git a/FusionIIIT/applications/examination/views.py b/FusionIIIT/applications/examination/views.py index c606b5a79..a5fa30437 100644 --- a/FusionIIIT/applications/examination/views.py +++ b/FusionIIIT/applications/examination/views.py @@ -1,28 +1,43 @@ +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 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 from applications.globals.models import (Designation, ExtraInfo, - HoldsDesignation,Faculty) + HoldsDesignation, Faculty) from applications.eis.models import (faculty_about, emp_research_projects) - -from notification.views import department_notif +from applications.programme_curriculum.models import Course +from applications.academic_procedures.models import course_registration +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 +from rest_framework.permissions import AllowAny @login_required(login_url='/accounts/login') @@ -43,31 +58,61 @@ def exam(request): # return HttpResponseRedirect('/examination/submit/') # elif str(request.user) == "acadadmin" : # return HttpResponseRedirect('/examination/submit/') - - return render(request,'../templates/examination/submit.html' , {}) + + return HttpResponseRedirect('/examination/submit/') + @login_required(login_url='/accounts/login') def submit(request): - return render(request,'../templates/examination/submit.html' , {}) + # courses = Course.objects.all() + + # coursefilter = CourseFilter(request.GET, queryset=courses) + + # courses = coursefilter.qs + 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}) + # return render(request,'../templates/examination/submit.html' , {}) + @login_required(login_url='/accounts/login') def verify(request): - return render(request,'../templates/examination/verify.html' , {}) + # Retrieve unique course IDs from hidden_grades + unique_course_ids = hidden_grades.objects.values('course_id').distinct() -@login_required(login_url='/accounts/login') + # 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)) + + # Pass the unique course IDs and corresponding course names and codes to the template + 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' ,{}) + 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',{}) + return render(request, '../templates/examination/notReady_publish.html', {}) @login_required(login_url='/accounts/login') def timetable(request): - return render(request,'../templates/examination/timetable.html',{}) - + return render(request, '../templates/examination/timetable.html', {}) def browse_announcements(): @@ -91,15 +136,16 @@ def browse_announcements(): all_ann = Announcements.objects.filter(department="ALL") context = { - "cse" : cse_ann, - "ece" : ece_ann, - "me" : me_ann, - "sm" : sm_ann, - "all" : all_ann + "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 @@ -112,6 +158,41 @@ def get_to_request(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', {}) + + # Retrieve course registrations based on course and semester + registrations = course_registration.objects.filter( + course_id__id=course_id, semester_id=semester_id) + + # Pass the registrations queryset to the template context + 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) + + # Pass the registrations queryset to the template context + context = { + 'registrations': registrations + } + + return render(request, 'examination/verifygrades.html', context) + @login_required(login_url='/accounts/login') def announcement(request): @@ -129,7 +210,8 @@ def announcement(request): """ usrnm = get_object_or_404(User, username=request.user.username) - user_info = ExtraInfo.objects.all().select_related('user','department').filter(user=usrnm).first() + 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) @@ -140,21 +222,65 @@ def announcement(request): 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) + 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) - + batch=batch, + programme=programme, + message=message, + upload_announcement=upload_announcement, + department=department, + ann_date=ann_date) + examination_notif(usrnm, recipients , message) + context = browse_announcements() - return render(request, 'examination/announcement_req.html', {"user_designation":user_info.user_type, - "announcements":context, - "request_to":requests_received - }) \ No newline at end of file + return render(request, 'examination/announcement_req.html', {"user_designation": user_info.user_type, + "announcements": context, + "request_to": requests_received + }) + + +# from rest_framework.views import APIView +# from rest_framework.response import Response +# from rest_framework import status + + +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 = hidden_grades.objects.create( + # student_id=student_id, + # course_id=course_id, + # semester_id=semester_id, + # grade=grade + # ) + print( + f"Student ID: {student_id}, Semester ID: {semester_id}, Course ID: {course_id}, Grade: {grade}") + hidden_grade.save() + + return Response({'message': 'Grades updated successfully'}, status=status.HTTP_200_OK) diff --git a/FusionIIIT/notification/views.py b/FusionIIIT/notification/views.py index 0480575b8..b58f45ed4 100644 --- a/FusionIIIT/notification/views.py +++ b/FusionIIIT/notification/views.py @@ -344,6 +344,20 @@ def department_notif(sender, recipient, type): module=module, verb=verb, flag=flag) +def examination_notif(sender, recipient, type): + 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) diff --git a/FusionIIIT/templates/examination/all_course_grade_filled.html b/FusionIIIT/templates/examination/all_course_grade_filled.html new file mode 100644 index 000000000..20016215f --- /dev/null +++ b/FusionIIIT/templates/examination/all_course_grade_filled.html @@ -0,0 +1,37 @@ +{% extends 'examination/base.html' %} + +{% block sidetabmenu %} + +{% endblock %} + + +{% block content %} +
+

Enter Student Marks

+ +
+
+ ALL GRADES ARE FILLED READY TO VERIFY +
+

Please check back later or contact support for assistance.

+
+ +
+{% endblock %} diff --git a/FusionIIIT/templates/examination/entergrades.html b/FusionIIIT/templates/examination/entergrades.html new file mode 100644 index 000000000..8d1ffb9f1 --- /dev/null +++ b/FusionIIIT/templates/examination/entergrades.html @@ -0,0 +1,70 @@ +{% extends 'examination/base.html' %} + +{% block sidetabmenu %} + +{% endblock %} + + +{% block content %} +
+

Enter Student Marks

+ + {% if registrations %} +
+ {% csrf_token %} +
+ + + + + + + + + + + {% for registration in registrations %} + + + + + + + {% endfor %} + +
Student IDSemester IDCourse IDGrade
{{ registration.student_id.id }}{{ registration.semester_id.id }}{{ registration.course_id.id }} + + + + +
+
+ +
+ {% else %} +
+
+ NO STUDENTS REGISTERED IN THIS COURSE THIS SEMESTER +
+

Please check back later or contact support for assistance.

+
+ {% endif %} +
+{% endblock %} diff --git a/FusionIIIT/templates/examination/grades_updated.html b/FusionIIIT/templates/examination/grades_updated.html new file mode 100644 index 000000000..3e7f1f5c7 --- /dev/null +++ b/FusionIIIT/templates/examination/grades_updated.html @@ -0,0 +1,94 @@ +{% extends 'examination/base.html' %} +{% block sidetabmenu %} + + + + + + + + +{% endblock %} + + +{% block content %} +
+

+
+
+ successfully Grades UPDATED +
+

Please check back later or contact support for assistance.

+
+ {% endif %} +
+{% endblock %} + diff --git a/FusionIIIT/templates/examination/submit.html b/FusionIIIT/templates/examination/submit.html index 579706bce..9fdfbf4f6 100644 --- a/FusionIIIT/templates/examination/submit.html +++ b/FusionIIIT/templates/examination/submit.html @@ -1,4 +1,5 @@ {% extends 'examination/base.html' %} + {% block sidetabmenu %}