diff --git a/FusionIIIT/applications/hostel_management/__init__.py b/FusionIIIT/applications/hostel_management/__init__.py index e69de29bb..67240824f 100644 --- a/FusionIIIT/applications/hostel_management/__init__.py +++ b/FusionIIIT/applications/hostel_management/__init__.py @@ -0,0 +1 @@ +from .templatetags.custom_filters import * \ No newline at end of file diff --git a/FusionIIIT/applications/hostel_management/admin.py b/FusionIIIT/applications/hostel_management/admin.py index 8e8917269..d2b9e16b2 100644 --- a/FusionIIIT/applications/hostel_management/admin.py +++ b/FusionIIIT/applications/hostel_management/admin.py @@ -21,4 +21,5 @@ admin.site.register(GuestRoom) admin.site.register(HostelTransactionHistory) admin.site.register(HostelHistory) +admin.site.register(HostelRoom) diff --git a/FusionIIIT/applications/hostel_management/forms.py b/FusionIIIT/applications/hostel_management/forms.py index 8a1780d27..d71017031 100644 --- a/FusionIIIT/applications/hostel_management/forms.py +++ b/FusionIIIT/applications/hostel_management/forms.py @@ -30,4 +30,20 @@ class Meta: 'departure_time', 'nationality', 'room_type' - ) \ No newline at end of file + ) + + +class AddNewHallForm(forms.ModelForm): + single_seater = forms.IntegerField(min_value=0, label='Single Seater Rooms') + double_seater = forms.IntegerField(min_value=0, label='Double Seater Rooms') + triple_seater = forms.IntegerField(min_value=0, label='Triple Seater Rooms') + + class Meta: + model = Hall + fields = ['hall_id', 'hall_name','single_seater', 'double_seater', 'triple_seater'] + help_texts = { + 'hall_id': 'Hall ID should be like hall1, hall2, hall3, etc.', + } + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.fields['hall_id'].help_text = 'Hall ID should be like hall1, hall2, hall3, etc.' \ No newline at end of file diff --git a/FusionIIIT/applications/hostel_management/migrations/0002_auto_20240801_1159.py b/FusionIIIT/applications/hostel_management/migrations/0002_auto_20240801_1159.py new file mode 100644 index 000000000..2ff936f76 --- /dev/null +++ b/FusionIIIT/applications/hostel_management/migrations/0002_auto_20240801_1159.py @@ -0,0 +1,42 @@ +# Generated by Django 3.1.5 on 2024-08-01 11:59 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('academic_information', '0001_initial'), + ('hostel_management', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='hall', + name='double_seater', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='hall', + name='single_seater', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='hall', + name='triple_seater', + field=models.IntegerField(default=0), + ), + migrations.CreateModel( + name='HostelRoom', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('room_type', models.CharField(choices=[('Single Seater', 'Single Seater'), ('Double Seater', 'Double Seater'), ('Triple Seater', 'Triple Seater')], max_length=20)), + ('room_number', models.CharField(max_length=20)), + ('status', models.CharField(choices=[('available', 'Available'), ('occupied', 'Occupied')], default='available', max_length=10)), + ('available_seats', models.IntegerField()), + ('hall', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='hostel_management.hall')), + ('occupants', models.ManyToManyField(blank=True, to='academic_information.Student')), + ], + ), + ] diff --git a/FusionIIIT/applications/hostel_management/models.py b/FusionIIIT/applications/hostel_management/models.py index 9c20f9b6e..fc40ced92 100644 --- a/FusionIIIT/applications/hostel_management/models.py +++ b/FusionIIIT/applications/hostel_management/models.py @@ -56,6 +56,10 @@ class Hall(models.Model): ] type_of_seater = models.CharField(max_length=50, choices=TYPE_OF_SEATER_CHOICES, default='single') + single_seater=models.IntegerField(default=0) + double_seater=models.IntegerField(default=0) + triple_seater=models.IntegerField(default=0) + def __str__(self): return self.hall_id @@ -368,4 +372,27 @@ class HostelHistory(models.Model): warden = models.ForeignKey(Faculty, on_delete=models.SET_NULL, null=True, related_name='warden_history') def __str__(self): - return f"History for {self.hall.hall_name} - {self.timestamp}" \ No newline at end of file + return f"History for {self.hall.hall_name} - {self.timestamp}" + + +class HostelRoom(models.Model): + ROOM_TYPES = [ + ('Single Seater', 'Single Seater'), + ('Double Seater', 'Double Seater'), + ('Triple Seater', 'Triple Seater'), + ] + + STATUS_CHOICES = [ + ('available', 'Available'), + ('occupied', 'Occupied'), + ] + + hall = models.ForeignKey(Hall, on_delete=models.CASCADE) + room_type = models.CharField(max_length=20, choices=ROOM_TYPES) + room_number = models.CharField(max_length=20) + status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='available') + occupants = models.ManyToManyField(Student, blank=True) + available_seats = models.IntegerField() + + def __str__(self): + return f"{self.room_number} - {self.get_room_type_display()}" \ No newline at end of file diff --git a/FusionIIIT/applications/hostel_management/templatetags/custom_filters.py b/FusionIIIT/applications/hostel_management/templatetags/custom_filters.py new file mode 100644 index 000000000..40d48e628 --- /dev/null +++ b/FusionIIIT/applications/hostel_management/templatetags/custom_filters.py @@ -0,0 +1,16 @@ +# templatetags/custom_filters.py +from django import template + +register = template.Library() + +@register.filter +def filter_by_type(rooms, room_type): + return [room for room in rooms if room.room_type == room_type] + +@register.filter +def occupied_seats(rooms): + return sum(room.occupants.count() for room in rooms) + +@register.filter +def vacant_seats(rooms): + return sum(room.available_seats for room in rooms) diff --git a/FusionIIIT/applications/hostel_management/urls.py b/FusionIIIT/applications/hostel_management/urls.py index 95fcdeeb8..bfe5e9574 100644 --- a/FusionIIIT/applications/hostel_management/urls.py +++ b/FusionIIIT/applications/hostel_management/urls.py @@ -114,5 +114,21 @@ path('edit-student//', views.EditStudentView.as_view(), name='edit_student'), path('remove-student//', views.RemoveStudentView.as_view(), name='remove-student'), + path('addNewHall',views.AddNewHall.as_view(), name='add_new_hall'), + path('hostelDetails//', views.HostelDetails.as_view(), name='hostel_details'), + path('hostelAllotmentPage/', views.hostel_allotment_page, name='hostel_allotment_page'), + path('hostels/', views.fetch_hostels, name='fetch_hostels'), + path('allot-hostel/', views.allot_hostel, name='allot_hostel'), + path('students/', views.fetch_students, name='fetch_students'), + + path('allot-rooms//', views.allot_rooms_to_students, name='allot_rooms'), + path('remove-room-allotments//', views.remove_room_allotments, name='remove_room_allotments'), + path('remove-hostel-allotment/', views.remove_hostel_allotment, name='remove_hostel_allotment'), + + path('hostel//manual-room-allocation/', views.manual_room_allocation, name='manual_room_allocation'), + path('reassign-room/', views.reassign_student_room, name='reassign_student_room'), + path('swap-rooms/', views.swap_student_rooms, name='swap_student_rooms'), + + ] \ No newline at end of file diff --git a/FusionIIIT/applications/hostel_management/utils.py b/FusionIIIT/applications/hostel_management/utils.py index 101ae76df..30e6679d4 100644 --- a/FusionIIIT/applications/hostel_management/utils.py +++ b/FusionIIIT/applications/hostel_management/utils.py @@ -117,4 +117,7 @@ def save_worker_report_sheet(excel, sheet, user_id): # hall_no = HallCaretaker.objects.get(staff__id=user_id).hall # print(month,year) # new_report = WorkerReport.objects.create(worker_id=worker_id, hall=hall_no, worker_name=worker_name, month=month, year=year, absent=absent, total_day=working_days, remark="none") -# new_report.save() \ No newline at end of file +# new_report.save() + +def sort_students_by_preference(students): + return students.order_by('batch', '-programme') \ No newline at end of file diff --git a/FusionIIIT/applications/hostel_management/views.py b/FusionIIIT/applications/hostel_management/views.py index 78f317135..39a8ec3d0 100644 --- a/FusionIIIT/applications/hostel_management/views.py +++ b/FusionIIIT/applications/hostel_management/views.py @@ -17,6 +17,7 @@ from django.urls import reverse from .models import StudentDetails from rest_framework.exceptions import APIException +from django.http import Http404 @@ -58,7 +59,7 @@ from django.db.models import Q from django.contrib import messages from .utils import render_to_pdf, save_worker_report_sheet, get_caretaker_hall -from .utils import add_to_room, remove_from_room +from .utils import add_to_room, remove_from_room,sort_students_by_preference from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status @@ -74,7 +75,7 @@ from Fusion.settings.common import LOGIN_URL from django.shortcuts import get_object_or_404, redirect, render from django.db import transaction -from .forms import HallForm +from .forms import HallForm ,AddNewHallForm from notification.views import hostel_notifications from django.db.models.signals import post_save from django.dispatch import receiver @@ -111,7 +112,7 @@ def hostel_view(request, context={}): halls_student = {} for hall in all_hall: halls_student[hall.hall_id] = Student.objects.filter( - hall_no=int(hall.hall_id[4])).select_related('id__user') + hall_no=int(hall.hall_id[4])).select_related('id__user').order_by('id__user__username') hall_staffs = {} for hall in all_hall: @@ -161,6 +162,9 @@ def hostel_view(request, context={}): 'assigned_batch': hall.assigned_batch, 'assigned_caretaker': caretaker.staff.id.user.username if caretaker else None, 'assigned_warden': warden.faculty.id.user.username if warden else None, + 'single_seater':hall.single_seater, + 'double_seater':hall.double_seater, + 'triple_seater':hall.triple_seater, } hostel_details.append(hostel_detail) @@ -239,6 +243,7 @@ def hostel_view(request, context={}): all_complaints = HostelComplaint.objects.all() add_hostel_form = HallForm() + add_new_hallForm = AddNewHallForm() warden_ids = Faculty.objects.all().select_related('id__user') # //! My change for imposing fines @@ -428,6 +433,8 @@ def hostel_view(request, context={}): 'students': students, 'hostel_transactions':hostel_transactions, 'hostel_history':hostel_history, + 'add_new_hallForm':add_new_hallForm, + **context } @@ -2120,3 +2127,495 @@ def dispatch(self, request, *args, **kwargs): return super().dispatch(request, *args, **kwargs) + +@method_decorator(user_passes_test(is_superuser), name='dispatch') +class AddNewHall(View): + template_name = 'hostelmanagement/addNewHall.html' + + def get(self, request, *args, **kwargs): + add_new_hallForm = AddNewHallForm() + return render(request, self.template_name, {'add_new_hallForm': add_new_hallForm}) + + def post(self, request, *args, **kwargs): + form = AddNewHallForm(request.POST) + if form.is_valid(): + hall_id = form.cleaned_data['hall_id'] + hall_name = form.cleaned_data['hall_name'] + single_seater = form.cleaned_data['single_seater'] + double_seater = form.cleaned_data['double_seater'] + triple_seater = form.cleaned_data['triple_seater'] + + # Check if a hall with the given name already exists + if Hall.objects.filter(hall_id=hall_id).exists(): + error_message = f'Hall with ID {hall_id} already exists.' + return HttpResponse(error_message, status=400) + + # Calculate total rooms and max occupancy + total_rooms = single_seater + double_seater + triple_seater + max_occupancy = single_seater * 1 + double_seater * 2 + triple_seater * 3 + + # Create the hall + hall = Hall.objects.create( + hall_id=hall_id, + hall_name=hall_name, + max_accomodation=max_occupancy, + single_seater=single_seater, + double_seater=double_seater, + triple_seater=triple_seater + ) + + # Create rooms based on the provided details + room_types = [ + {'type': 'Single Seater', 'quantity': single_seater, 'prefix': 'S', 'seats': 1}, + {'type': 'Double Seater', 'quantity': double_seater, 'prefix': 'D', 'seats': 2}, + {'type': 'Triple Seater', 'quantity': triple_seater, 'prefix': 'T', 'seats': 3}, + ] + + room_number = 1 + for room_type in room_types: + for _ in range(room_type['quantity']): + HostelRoom.objects.create( + hall=hall, + room_type=room_type['type'], + room_number=f"{room_type['prefix']}{room_number}", + status='available', + available_seats=room_type['seats'] + ) + room_number += 1 + + messages.success(request, 'Hall and rooms added successfully!') + return HttpResponseRedirect(reverse("hostelmanagement:hostel_view")) + + return render(request, self.template_name, {'form': form}) + +def natural_sort_key(s): + return [int(text) if text.isdigit() else text.lower() for text in re.split('([0-9]+)', s)] + + +@method_decorator(login_required, name='dispatch') +class HostelDetails(View): + template_name = 'hostelmanagement/hostel_details.html' + + def get(self, request, id): + if request.user.id in Student.objects.values_list('id__user', flat=True): + return JsonResponse({'error': 'Unauthorized'}, status=400) + + + hall = get_object_or_404(Hall, hall_id=id) + rooms = HostelRoom.objects.filter(hall=hall).select_related('hall').prefetch_related('occupants') + + # Sort rooms using the custom sorting function + rooms = sorted(rooms, key=lambda room: natural_sort_key(room.room_number)) + + room_types = ['Single Seater', 'Double Seater', 'Triple Seater'] + + return render(request, self.template_name, {'hall': hall, 'rooms': rooms, 'room_types': room_types}) + +@csrf_exempt +def fetch_students(request): + if request.method == 'GET': + batch = request.GET.get('batch', None) + if batch is None: + return JsonResponse({'error': 'Batch parameter is required'}, status=400) + + students = Student.objects.filter(batch=batch).order_by('id__user__username') + + + data = [{'id': student.id.id, 'username': student.id.user.username, 'hostel':student.hall_no}for student in students] + return JsonResponse(data, safe=False) + + return JsonResponse({'error': 'Invalid request method'}, status=405) + +@csrf_exempt +def fetch_hostels(request): + if request.method == 'GET': + hostels = Hall.objects.all() + data = [{'id': hostel.hall_id, 'name': hostel.hall_name, 'maxOccupancy': hostel.max_accomodation, + 'students': hostel.number_students, 'typeOfSeater': hostel.type_of_seater} for hostel in hostels] + return JsonResponse(data, safe=False) + return JsonResponse({'error': 'Invalid request method'}, status=405) + +@csrf_exempt +def hostel_allotment_page(request): + + return render(request, 'hostelmanagement/hostel_allotment_page.html') + +# Function to convert 'hall1', 'hall2', ... to '1', '2', ... +def hall_identifier_to_number(identifier): + try: + return int(identifier.replace('hall', '')) + except ValueError: + return None + +# Function to map '1', '2', ... to 'hall1', 'hall2', ... +def hall_number_to_identifier(number): + return f'hall{number}' + + + +@csrf_exempt +def allot_hostel(request): + if request.method == 'POST': + + + try: + data = json.loads(request.body) + + hostel_id = data.get('hostelId') + student_ids = data.get('studentIds') + hostel = get_object_or_404(Hall, hall_id=hostel_id) + students = Student.objects.filter(id__in=student_ids) + + print(hostel) + for student in students: + # Check if student already has a hostel assigned + if student.hall_no: + print(student.hall_no) + student.room_no = None + # If a hostel is already assigned, decrement previous hostel's number_students + current_hostel_id = hall_number_to_identifier(student.hall_no) + try: + current_hostel = get_object_or_404(Hall, hall_id=current_hostel_id) + + if current_hostel.number_students > 0: # Ensure number_students doesn't go below zero + current_hostel.number_students -= 1 + current_hostel.save() + except Http404: + pass # Handle cases where current_hostel_id doesn't exist in Hall model + + # Assign new hostel + + student.hall_no = hall_identifier_to_number(hostel_id) + print(student) + student.save() + + # Increment new hostel's number_students + hostel.number_students += 1 + hostel.save() + + return JsonResponse({'message': 'Hostel allotted successfully'}, status=200) + + except Hall.DoesNotExist: + return JsonResponse({'message': 'Hostel not found.'}, status=404) + except Student.DoesNotExist: + return JsonResponse({'message': 'Student not found.'}, status=404) + + except Exception as e: + return JsonResponse({'message': 'Error allotting hostel', 'error': str(e)}, status=500) + + return JsonResponse({'message': 'Invalid request method'}, status=405) + + +@csrf_exempt +def allot_rooms_to_students(request, hostel_id): + + if request.method == 'POST': + try: + hostel = get_object_or_404(Hall, hall_id=hostel_id) + + rooms = list(HostelRoom.objects.filter(hall=hostel, status='available')) + + # Sort rooms using the custom sorting function + rooms = sorted(rooms, key=lambda room: natural_sort_key(room.room_number)) + + students = Student.objects.filter(hall_no=hall_identifier_to_number(hostel_id)) + + students_to_allot = students.filter(room_no__isnull=True) + + print(students_to_allot.count()) + if students_to_allot.count() == 0: + return JsonResponse({'message': 'All students already have rooms allocated'}, status=200) + + # Group rooms by type + room_groups = { + 'single': [room for room in rooms if room.room_type == 'Single Seater'], + 'double': [room for room in rooms if room.room_type == 'Double Seater'], + 'triple': [room for room in rooms if room.room_type == 'Triple Seater'] + } + + # Sort students based on preferences + sorted_students = sort_students_by_preference(students_to_allot) + + # Allot rooms to students + for student in sorted_students: + room = None + + # Attempt to find an available room + if room_groups['single']: + room = room_groups['single'][0] + elif room_groups['double']: + room = room_groups['double'][0] + elif room_groups['triple']: + room = room_groups['triple'][0] + else: + return JsonResponse({'message': 'Not enough rooms available'}, status=400) + + # Assign room to student + student.room_no = room.room_number + student.save() + + + + # Update room status if fully occupied + room.occupants.add(student) + room.available_seats -= 1 + + if room.available_seats == 0: + room.status = 'occupied' + if room.room_type == 'Single Seater': + room_groups['single'].pop(0) + elif room.room_type == 'Double Seater': + room_groups['double'].pop(0) + elif room.room_type == 'Triple Seater': + room_groups['triple'].pop(0) + + room.save() + + return JsonResponse({'message': 'Rooms allotted successfully'}, status=200) + + except Hall.DoesNotExist: + return JsonResponse({'message': 'Hostel not found'}, status=404) + except Exception as e: + return JsonResponse({'message': 'Error allotting rooms', 'error': str(e)}, status=500) + + return JsonResponse({'message': 'Invalid request method'}, status=405) + + +# View function to remove room allotments for a specific hostel +@csrf_exempt +def remove_room_allotments(request, hostel_id): + try: + hostel = get_object_or_404(Hall, hall_id =hostel_id) + + # Find all rooms in the specified hostel + rooms = HostelRoom.objects.filter(hall=hostel) + + # Iterate over each room + for room in rooms: + # If the room is not occupied, continue to the next room + if room.occupants.count() == 0: + continue + + # Find all students who are occupants of this room + occupants = room.occupants.all() + + # Iterate over each occupant and remove their room allotment + for occupant in occupants: + # Reset the occupant's room number + occupant.room_no = None + occupant.save() + + # Calculate capacity based on room type + capacity = 0 + if room.room_type == 'Single Seater': + capacity = 1 + elif room.room_type == 'Double Seater': + capacity = 2 + elif room.room_type == 'Triple Seater': + capacity = 3 + + # Clear the occupants of the room and update available seats and status + room.occupants.clear() + room.available_seats = capacity # Assuming capacity is a field in Room model + room.status = 'available' + room.save() + + + return JsonResponse({'message': 'Room allotments removed successfully'}, status=200) + + + + except Exception as e: + return JsonResponse({ + 'message': 'Error removing room allotments for the hostel', + 'error': str(e) + }, status=500) + +@csrf_exempt +def remove_hostel_allotment(request): + if request.method == 'POST': + try: + # Get all students + students = Student.objects.all() + + for student in students: + # Check if student already has a hostel assigned + + if student.hall_no: + + # If a hostel is already assigned, decrement previous hostel's number_students + current_hostel_id = hall_number_to_identifier(student.hall_no) + try: + current_hostel = get_object_or_404(Hall, hall_id=current_hostel_id) + if current_hostel.number_students > 0: # Ensure number_students doesn't go below zero + current_hostel.number_students -= 1 + current_hostel.save() + except Http404: + pass # Handle cases where current_hostel_id doesn't exist in Hall model + + + # Check if student already has a room assigned + if student.room_no and student.hall_no!=0: + + try: + # Retrieve and update the previous room within the previous hostel + current_hostel_id = hall_number_to_identifier(student.hall_no) + hostel = get_object_or_404(Hall, hall_id =current_hostel_id) + + previous_room = HostelRoom.objects.get(hall=hostel, room_number=student.room_no) + + + + if(previous_room and previous_room.occupants.count()>0): + capacity = 0 + if previous_room.room_type == 'Single Seater': + capacity = 1 + elif previous_room.room_type == 'Double Seater': + capacity = 2 + elif previous_room.room_type == 'Triple Seater': + capacity = 3 + + + previous_room.available_seats =capacity + previous_room.occupants.clear() + previous_room.status = 'available' + previous_room.save() + else: + print("No previous room") + + except HostelRoom.DoesNotExist: + print(f"HostelRoom.DoesNotExist: {student.room_no} in Hall {current_hostel_id}") + + pass # Handle cases where the previous room doesn't exist + + # Reset the student's hostel and room assignment + + student.hall_no = 0 # Setting to 0 as null is not allowed + student.room_no = None + student.save() + + return JsonResponse({'message': 'Hostel allotments removed successfully'}, status=200) + + except Exception as e: + return JsonResponse({'message': 'Error removing hostel allotments', 'error': str(e)}, status=500) + + return JsonResponse({'message': 'Invalid request method'}, status=405) + + +def manual_room_allocation(request, hostel_id): + hostel = get_object_or_404(Hall, hall_id=hostel_id) + students = Student.objects.filter(hall_no=hall_identifier_to_number(hostel_id)) + + + rooms = HostelRoom.objects.filter(hall=hostel, available_seats__gt=0) + + context = { + 'hostel': hostel, + 'students': students, + 'rooms': rooms + } + + return render(request, 'hostelmanagement/manual_room_allocation.html', context) + + +@csrf_exempt +def reassign_student_room(request): + + + if request.method == 'POST': + data = json.loads(request.body) + student_id = data.get('studentId') + new_roomNum = data.get('roomNum') + + student = get_object_or_404(Student, id=student_id) + + current_hostel_id = hall_number_to_identifier(student.hall_no) + hostel = get_object_or_404(Hall, hall_id =current_hostel_id) + + new_room=HostelRoom.objects.get(hall=hostel, room_number=new_roomNum ) + + if not student: + return JsonResponse({'message': 'Student not found'}, status=404) + + if not new_room or new_room.available_seats <= 0: + return JsonResponse({'message': 'New room is not available'}, status=400) + + # Find the current room of the student + current_room=HostelRoom.objects.get(hall=hostel, room_number=student.room_no) + + # Remove the student from the current room + if current_room: + current_room.occupants.remove(student) + current_room.available_seats += 1 + if current_room.available_seats > 0: + current_room.status = 'available' + current_room.save() + + # Add the student to the new room + + + new_room.occupants.add(student) + new_room.available_seats -= 1 + if new_room.available_seats == 0: + new_room.status = 'occupied' + new_room.save() + + # Update the student's room reference + student.room_no = new_room.room_number + student.save() + + return JsonResponse({'message': 'Student reassigned successfully', 'hostel': student.hall_no}) + else: + return JsonResponse({'message': 'Invalid request method'}, status=405) + + + +@csrf_exempt +def swap_student_rooms(request): + + if request.method == 'POST': + + + try: + data = json.loads(request.body) + student_id1 = data['studentId1'] + student_id2 = data['studentId2'] + + if(student_id1==student_id2): + return JsonResponse({'message': 'Choose two different student'}, status=400) + + student1 = get_object_or_404(Student, id=student_id1) + student2 = get_object_or_404(Student, id=student_id2) + + current_hostel_id = hall_number_to_identifier(student1.hall_no) + hostel = get_object_or_404(Hall, hall_id =current_hostel_id) + + # Get current rooms of both students + room1=HostelRoom.objects.get(hall=hostel, room_number=student1.room_no) + room2=HostelRoom.objects.get(hall=hostel, room_number=student2.room_no) + + + + # Swap the students in their respective rooms + room1.occupants.remove(student1) + room2.occupants.remove(student2) + + room1.occupants.add(student2) + room2.occupants.add(student1) + + room1.save() + room2.save() + + # Update the students' room references + student1.room_no, student2.room_no = student2.room_no, student1.room_no + student1.save() + student2.save() + + + + return JsonResponse({'message': 'Rooms swapped successfully'}, status=200) + + except Exception as e: + print(e) + return JsonResponse({'message': 'Error swapping rooms', 'error': str(e)}, status=500) + return JsonResponse({'message': 'Invalid request method'}, status=400) \ No newline at end of file diff --git a/FusionIIIT/applications/iwdModuleV2/migrations/0002_bills_budget_inventory_requests_useditems_workorder.py b/FusionIIIT/applications/iwdModuleV2/migrations/0002_bills_budget_inventory_requests_useditems_workorder.py new file mode 100644 index 000000000..6a55cb2de --- /dev/null +++ b/FusionIIIT/applications/iwdModuleV2/migrations/0002_bills_budget_inventory_requests_useditems_workorder.py @@ -0,0 +1,85 @@ +# Generated by Django 3.1.5 on 2024-07-05 15:01 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('iwdModuleV2', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Budget', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200)), + ('budgetIssued', models.IntegerField(default=0)), + ], + ), + migrations.CreateModel( + name='Inventory', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200)), + ('quantity', models.IntegerField(default=0)), + ('cost', models.IntegerField(default=0)), + ], + ), + migrations.CreateModel( + name='Requests', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200)), + ('description', models.CharField(max_length=200)), + ('area', models.CharField(max_length=200)), + ('requestCreatedBy', models.CharField(max_length=200)), + ('engineerProcessed', models.IntegerField(default=0)), + ('directorApproval', models.IntegerField(default=0)), + ('deanProcessed', models.IntegerField(default=0)), + ('status', models.CharField(max_length=200)), + ('issuedWorkOrder', models.IntegerField(default=0)), + ('workCompleted', models.IntegerField(default=0)), + ('billGenerated', models.IntegerField(default=0)), + ('billProcessed', models.IntegerField(default=0)), + ('billSettled', models.IntegerField(default=0)), + ], + ), + migrations.CreateModel( + name='WorkOrder', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200)), + ('date', models.DateField(default=datetime.date.today)), + ('agency', models.CharField(max_length=200)), + ('amount', models.IntegerField(default=0)), + ('deposit', models.IntegerField(default=0)), + ('alloted_time', models.CharField(max_length=200)), + ('start_date', models.DateField()), + ('completion_date', models.DateField()), + ('request_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='iwdModuleV2.requests')), + ], + ), + migrations.CreateModel( + name='UsedItems', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('itemName', models.CharField(max_length=200)), + ('cost', models.IntegerField(default=0)), + ('quantity', models.IntegerField(default=0)), + ('date', models.DateField(default=datetime.date.today)), + ('request_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='iwdModuleV2.requests')), + ], + ), + migrations.CreateModel( + name='Bills', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('file', models.FileField(upload_to='')), + ('request_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='iwdModuleV2.requests')), + ], + ), + ] diff --git a/FusionIIIT/applications/iwdModuleV2/migrations/0003_auto_20240801_1159.py b/FusionIIIT/applications/iwdModuleV2/migrations/0003_auto_20240801_1159.py new file mode 100644 index 000000000..3949fa433 --- /dev/null +++ b/FusionIIIT/applications/iwdModuleV2/migrations/0003_auto_20240801_1159.py @@ -0,0 +1,19 @@ +# Generated by Django 3.1.5 on 2024-08-01 11:59 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('iwdModuleV2', '0002_bills_budget_inventory_requests_useditems_workorder'), + ] + + operations = [ + migrations.DeleteModel( + name='Inventory', + ), + migrations.DeleteModel( + name='UsedItems', + ), + ] diff --git a/FusionIIIT/applications/online_cms/migrations/0002_auto_20240801_1159.py b/FusionIIIT/applications/online_cms/migrations/0002_auto_20240801_1159.py new file mode 100644 index 000000000..9ce2f2e0e --- /dev/null +++ b/FusionIIIT/applications/online_cms/migrations/0002_auto_20240801_1159.py @@ -0,0 +1,40 @@ +# Generated by Django 3.1.5 on 2024-08-01 11:59 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('academic_information', '0001_initial'), + ('online_cms', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='attendance', + name='no_of_attendance', + field=models.IntegerField(default=1), + ), + migrations.AlterField( + model_name='attendance', + name='present', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='gradingscheme', + name='type_of_evaluation', + field=models.CharField(max_length=100), + ), + migrations.CreateModel( + name='StudentEvaluation', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('marks', models.DecimalField(decimal_places=2, max_digits=10, null=True)), + ('total_marks', models.DecimalField(decimal_places=2, default=0, max_digits=10)), + ('evaluation_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='online_cms.gradingscheme')), + ('student_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='academic_information.student')), + ], + ), + ] diff --git a/FusionIIIT/applications/research_procedures/migrations/0002_auto_20240801_1159.py b/FusionIIIT/applications/research_procedures/migrations/0002_auto_20240801_1159.py new file mode 100644 index 000000000..bac50df3d --- /dev/null +++ b/FusionIIIT/applications/research_procedures/migrations/0002_auto_20240801_1159.py @@ -0,0 +1,19 @@ +# Generated by Django 3.1.5 on 2024-08-01 11:59 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('research_procedures', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='staff_allocations', + name='start_date', + field=models.DateField(default=datetime.date(2024, 8, 1)), + ), + ] diff --git a/FusionIIIT/templates/hostelmanagement/addNewHall.html b/FusionIIIT/templates/hostelmanagement/addNewHall.html new file mode 100644 index 000000000..b3722c295 --- /dev/null +++ b/FusionIIIT/templates/hostelmanagement/addNewHall.html @@ -0,0 +1,19 @@ + +{% block Add_hostel %} +

Add New Hall

+
+ {% csrf_token %} + {{ add_new_hallForm.as_p }} + +
+ {% if messages %} +
+ {% for message in messages %} +
+ {{ message }} +
+ {% endfor %} +
+ {% endif %} + +{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/hostelmanagement/admin_hostel_list.html b/FusionIIIT/templates/hostelmanagement/admin_hostel_list.html index ffee96966..6a7f69206 100644 --- a/FusionIIIT/templates/hostelmanagement/admin_hostel_list.html +++ b/FusionIIIT/templates/hostelmanagement/admin_hostel_list.html @@ -7,13 +7,17 @@

Hostel List

Hall ID Hall Name - Seater Type - Max Accommodation + Single Seater + Double Seater + Triple Seater + + Max Accomm. Occupied Vacant Seats - Assigned Batch + Assigned Caretaker Assigned Warden + @@ -22,13 +26,16 @@

Hostel List

{{ detail.hall_id }} {{ detail.hall_name }} - {{ detail.seater_type}} + {{detail.single_seater }} + {{detail.double_seater }} + {{detail.triple_seater }} {{ detail.max_accomodation }} {{ detail.number_students }} {{ detail.vacant_seat}} - {{ detail.assigned_batch }} + {{ detail.assigned_caretaker }} {{ detail.assigned_warden }} + diff --git a/FusionIIIT/templates/hostelmanagement/alloted_hostel_room.html b/FusionIIIT/templates/hostelmanagement/alloted_hostel_room.html index 4377cb59f..7276558e0 100644 --- a/FusionIIIT/templates/hostelmanagement/alloted_hostel_room.html +++ b/FusionIIIT/templates/hostelmanagement/alloted_hostel_room.html @@ -18,6 +18,9 @@ Edit Student + + Room Allotment + {% endif %} diff --git a/FusionIIIT/templates/hostelmanagement/edit_student.html b/FusionIIIT/templates/hostelmanagement/edit_student.html index 9026a4f42..79093dca8 100644 --- a/FusionIIIT/templates/hostelmanagement/edit_student.html +++ b/FusionIIIT/templates/hostelmanagement/edit_student.html @@ -29,29 +29,29 @@

Edit Student Details

{% csrf_token %} -
+

-
+

-
+

-
+

-
+
-
+
-
+

diff --git a/FusionIIIT/templates/hostelmanagement/hostel.html b/FusionIIIT/templates/hostelmanagement/hostel.html index 5cdea03c7..c8542227c 100644 --- a/FusionIIIT/templates/hostelmanagement/hostel.html +++ b/FusionIIIT/templates/hostelmanagement/hostel.html @@ -211,12 +211,12 @@ - {% if is_superuser %} + {% if is_superuser %} @@ -261,6 +261,13 @@ {% endif %} + {% if is_superuser %} + + Hostel Allotment + + + {% endif %} + + +{% block hostel_Allotment %} + + +
+

Hostel Allotment

+ +
+
+ + +
+ +
+ + +
+ +
+ Selected Students: 0 +
+ + +
+ +
+
+ +
+ + + +
+
+ +{% block scripts %} + +{% endblock %} + +{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/hostelmanagement/hostel_details.html b/FusionIIIT/templates/hostelmanagement/hostel_details.html new file mode 100644 index 000000000..c3af86fd0 --- /dev/null +++ b/FusionIIIT/templates/hostelmanagement/hostel_details.html @@ -0,0 +1,149 @@ + +{% extends 'globals/base.html' %} +{% load custom_filters %} +{% load static %} + +{% block title %} +Hostel Allotment +{% endblock %} + +{% block body %} +{% block navBar %} +{% include 'dashboard/navbar.html' %} +{% endblock %} + +
+
+
+
+ {% block userCard %} + {% include 'globals/usercard.html' %} + {% endblock %} +
+
+
+
+
+
+

{{ hall.hall_name }} Room Details

+ + +
+ + + +
+ + {% for type in room_types %} +
+
{{ type }}
+
+
+
+
+ + Total Rooms: {{ rooms|filter_by_type:type|length }} + + + Occupied Seats: {{rooms|filter_by_type:type|occupied_seats }} + + + + Vacant Seats: {{rooms|filter_by_type:type|vacant_seats }} + + +
+
+
+
+ +
+ {% for room in rooms|filter_by_type:type %} +
+
+
+
Room Number: {{ room.room_number }}
+
+ Vacant Seats: {{ room.available_seats }} +
+ {% if room.occupants.all %} +
+
    + {% for occupant in room.occupants.all %} +
  • + {{ occupant.id.user.username }} +
  • + {% endfor %} +
+
+ {% else %} +
+

No occupants

+
+ {% endif %} +
+
+
+ {% endfor %} +
+
+ {% endfor %} +
+
+
+ + + + + +{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/hostelmanagement/manual_room_allocation.html b/FusionIIIT/templates/hostelmanagement/manual_room_allocation.html new file mode 100644 index 000000000..7a5418448 --- /dev/null +++ b/FusionIIIT/templates/hostelmanagement/manual_room_allocation.html @@ -0,0 +1,181 @@ + + +{% extends 'globals/base.html' %} + +{% load static %} + +{% block title %} +Hostel Allotment +{% endblock %} + +{% block body %} +{% block navBar %} +{% include 'dashboard/navbar.html' %} +{% endblock %} + +
+
+
+
+ {% block userCard %} + {% include 'globals/usercard.html' %} + {% endblock %} +
+
+
+

Manual Room Allocation

+
+
+
+ + +
+ +
+ + +
+ + + + +
+
+ +
+

Swap Rooms

+ +
+ + +
+ +
+ + +
+ + + + + +
+
+ + + +
+ +
+ +{% block scripts %} + + + +{% endblock %} +{% endblock %} \ No newline at end of file