diff --git a/FusionIIIT/applications/academic_information/utils.py b/FusionIIIT/applications/academic_information/utils.py new file mode 100644 index 000000000..2fed73044 --- /dev/null +++ b/FusionIIIT/applications/academic_information/utils.py @@ -0,0 +1,135 @@ +from applications.academic_information.models import (Calendar, Student,Curriculum_Instructor, Curriculum, + Student_attendance) +from ..academic_procedures.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 , backlog_course,) + +from applications.programme_curriculum.models import(Course,CourseSlot,Batch,Semester) +from django.http import HttpResponse, JsonResponse +from django.utils import timezone +from django.core import serializers +from django.db.models import Q +import datetime +import random +from django.db import transaction +time = timezone.now() +def check_for_registration_complete (request): + batch = int(request.POST.get('batch')) + sem = int(request.POST.get('sem')) + year = request.POST.get('year') + + + date = time.date() + + try: + + pre_registration_date = Calendar.objects.all().filter(description=f"Pre Registration {sem} {year}").first() + prd_start_date = pre_registration_date.from_date + prd_end_date = pre_registration_date.to_date + + if date=prd_start_date and date<=prd_end_date: + return JsonResponse({'status':-1 , "message":"registration is under process"}) + + if course_registration.objects.filter(Q(semester_id__semester_no = sem) & Q(student_id__batch = batch)).exists() : + return JsonResponse({'status':2,"message":"courses already allocated"}) + + return JsonResponse({"status":1 , "message" : "courses not yet allocated"}) + except : + return JsonResponse({"status":-3, "message" : "No such registration found"}) + +@transaction.atomic +def random_algo(batch,sem,year,course_slot) : + unique_course = InitialRegistration.objects.filter(Q(semester_id__semester_no = sem) & Q( course_slot_id__name = course_slot ) & Q(student_id__batch = batch)).values_list('course_id',flat=True).distinct() + max_seats={} + seats_alloted = {} + present_priority = {} + next_priority = {} + total_seats = 0 + for course in unique_course : + max_seats[course] = Course.objects.get(id=course).max_seats + total_seats+=max_seats[course] + seats_alloted[course] = 0 + present_priority[course] = [] + next_priority[course] = [] + + priority_1 = InitialRegistration.objects.filter(Q(semester_id__semester_no = sem) & Q( course_slot_id__name = course_slot ) & Q(student_id__batch = batch) & Q(priority=1)) + rem=len(priority_1) + if rem > total_seats : + return -1 + + for p in priority_1 : + present_priority[p.course_id.id].append([p.student_id.id.id,p.course_slot_id.id]) + with transaction.atomic() : + p_priority = 1 + while rem > 0 : + for course in present_priority : + while(len(present_priority[course])) : + random_student_selected = random.choice(present_priority[course]) + + present_priority[course].remove(random_student_selected) + + if seats_alloted[course] < max_seats[course] : + stud = Student.objects.get(id__id = random_student_selected[0]) + curriculum_object = Student.objects.get(id__id = random_student_selected[0]).batch_id.curriculum + course_object = Course.objects.get(id=course) + course_slot_object = CourseSlot.objects.get(id = random_student_selected[1]) + semester_object = Semester.objects.get(Q(semester_no = sem) & Q(curriculum = curriculum_object)) + course_registration.objects.create( + student_id = stud, + working_year = year, + semester_id = semester_object, + course_id = course_object, + course_slot_id = course_slot_object + ) + seats_alloted[course] += 1 + rem-=1 + else : + next = InitialRegistration.objects.get(Q(student_id__id__id = random_student_selected[0]) & Q( course_slot_id__name = course_slot ) & Q(semester_id__semester_no = sem) & Q(student_id__batch = batch) & Q(priority=p_priority+1)) + next_priority[next.course_id.id].append([next.student_id.id.id,next.course_slot_id.id]) + p_priority+=1 + present_priority = next_priority + next_priority = {course : [] for course in unique_course} + + return 1 + +@transaction.atomic +def allocate(request) : + batch = request.POST.get('batch') + sem = request.POST.get('sem') + year = request.POST.get('year') + unique_course_slot = InitialRegistration.objects.filter(Q(semester_id__semester_no = sem) & Q(student_id__batch = batch)).values_list('course_slot_id',flat=True).distinct() + unique_course_name = [] + try: + with transaction.atomic() : + for course_slot in unique_course_slot : + course_slot_object = CourseSlot.objects.get(id=course_slot) + if course_slot_object.type == "Professional Elective": # Runs only for open elective course slots + if course_slot_object.name not in unique_course_name: + stat = random_algo(batch,sem,year,course_slot_object.name) + unique_course_name.append(course_slot_object.name) + if(stat == -1) : + raise Exception("seats not enough for course_slot"+str(course_slot_object.name)) + + return JsonResponse({'status': 1 , 'message' : "course allocation successful"}) + except: + return JsonResponse({'status': -1 , 'message' : "seats not enough for course_slot"+str(course_slot_object.name) }) + + +def view_alloted_course(request) : + batch = request.POST.get('batch') + sem = request.POST.get('sem') + year = request.POST.get('year') + course = request.POST.get('course') + + registrations = course_registration.objects.filter(Q(student_id__batch = batch) & Q(working_year = year) & Q(semester_id__semester_no = sem) & Q(course_id__code = course)) + return_list = [] + for registration in registrations: + obj = { + 'student':registration.student_id.id.id + } + return_list.append(obj) + return JsonResponse({'status':1 , 'student_list':return_list }) \ No newline at end of file diff --git a/FusionIIIT/applications/academic_information/views.py b/FusionIIIT/applications/academic_information/views.py index 2fab71e2f..f4ef54b5f 100755 --- a/FusionIIIT/applications/academic_information/views.py +++ b/FusionIIIT/applications/academic_information/views.py @@ -31,6 +31,7 @@ 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 +from .utils import check_for_registration_complete,allocate,view_alloted_course @login_required @@ -214,7 +215,14 @@ def homepage(request): """ if user_check(request): return HttpResponseRedirect('/academic-procedures/') - + + if request.method == "POST": + if 'check_allocation' in request.POST : + return check_for_registration_complete(request) + if 'start_allocation' in request.POST : + return allocate(request) + if 'view_allocation' in request.POST : + return view_alloted_course(request) context = get_context(request) return render(request, "ais/ais.html", context) diff --git a/FusionIIIT/applications/academic_procedures/models.py b/FusionIIIT/applications/academic_procedures/models.py index 2015a1ee8..6c1083dda 100644 --- a/FusionIIIT/applications/academic_procedures/models.py +++ b/FusionIIIT/applications/academic_procedures/models.py @@ -605,8 +605,7 @@ class InitialRegistration(models.Model): class Meta: db_table = 'InitialRegistration' - - + class FinalRegistration(models.Model): ''' Current Purpose : stores information regarding the process of final(complete) registration of a student for a course @@ -690,7 +689,6 @@ def __str__(self): 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) diff --git a/FusionIIIT/applications/programme_curriculum/migrations/0002_course_max_seats.py b/FusionIIIT/applications/programme_curriculum/migrations/0002_course_max_seats.py new file mode 100644 index 000000000..75700de21 --- /dev/null +++ b/FusionIIIT/applications/programme_curriculum/migrations/0002_course_max_seats.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.5 on 2024-10-23 00:20 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('programme_curriculum', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='course', + name='max_seats', + field=models.IntegerField(default=90), + ), + ] diff --git a/FusionIIIT/applications/programme_curriculum/models.py b/FusionIIIT/applications/programme_curriculum/models.py index 655994c1c..b09482669 100644 --- a/FusionIIIT/applications/programme_curriculum/models.py +++ b/FusionIIIT/applications/programme_curriculum/models.py @@ -261,7 +261,7 @@ class Course(models.Model): working_course = models.BooleanField(default=True) disciplines = models.ManyToManyField(Discipline, blank=True) latest_version = models.BooleanField(default=True) - + max_seats = models.IntegerField(default=90) class Meta: unique_together = ('code', 'version') diff --git a/FusionIIIT/templates/academic_procedures/auto_pre_registration.html b/FusionIIIT/templates/academic_procedures/auto_pre_registration.html index 033c468fe..fcf496fcf 100644 --- a/FusionIIIT/templates/academic_procedures/auto_pre_registration.html +++ b/FusionIIIT/templates/academic_procedures/auto_pre_registration.html @@ -247,7 +247,7 @@
- +
@@ -291,6 +291,8 @@ var inp = document.getElementsByClassName("Prechoices"); var count = 0; + document.getElementById('register-button').style.display = 'none'; + let course_slots = document.getElementsByName("course_slot"); let credits = document.getElementsByClassName("credit_values"); @@ -303,6 +305,7 @@ // // console.log("course_priority-" + course_slot_id , course_priority[j].value ) if ((!(course_slot_type.startsWith("Optional") && course_slot_type != "Optional Elective") && !course_slot_type.startsWith("Swayam") )&& course_priority[j].value == "NULL") { alert("Please select all choices for " + parseInt(i + 1) + " " + course_slot_type + " slot"); + document.getElementById('register-button').style = "text-allign:center;"; return false; } let selected_course = course_priority[j].value.split("-"); diff --git a/FusionIIIT/templates/ais/ais.html b/FusionIIIT/templates/ais/ais.html index d749b0270..7e248a2ed 100755 --- a/FusionIIIT/templates/ais/ais.html +++ b/FusionIIIT/templates/ais/ais.html @@ -111,6 +111,10 @@ Student Dashboard + + Start elective assignment + +