diff --git a/FusionIIIT/applications/academic_information/migrations/0002_auto_20240409_2009.py b/FusionIIIT/applications/academic_information/migrations/0002_auto_20240409_2009.py new file mode 100644 index 000000000..6449a6614 --- /dev/null +++ b/FusionIIIT/applications/academic_information/migrations/0002_auto_20240409_2009.py @@ -0,0 +1,22 @@ +# Generated by Django 3.1.5 on 2024-04-09 20:09 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('academic_information', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='student', + name='hall_no', + ), + migrations.AddField( + model_name='student', + name='hall_id', + field=models.CharField(blank=True, max_length=10, null=True), + ), + ] diff --git a/FusionIIIT/applications/academic_information/migrations/0003_auto_20240409_2014.py b/FusionIIIT/applications/academic_information/migrations/0003_auto_20240409_2014.py new file mode 100644 index 000000000..d7e4a4dee --- /dev/null +++ b/FusionIIIT/applications/academic_information/migrations/0003_auto_20240409_2014.py @@ -0,0 +1,22 @@ +# Generated by Django 3.1.5 on 2024-04-09 20:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('academic_information', '0002_auto_20240409_2009'), + ] + + operations = [ + migrations.RemoveField( + model_name='student', + name='hall_id', + ), + migrations.AddField( + model_name='student', + name='hall_no', + field=models.IntegerField(default=0), + ), + ] diff --git a/FusionIIIT/applications/globals/migrations/0021_merge_20240319_2339.py b/FusionIIIT/applications/globals/migrations/0021_merge_20240319_2339.py new file mode 100644 index 000000000..211941fa5 --- /dev/null +++ b/FusionIIIT/applications/globals/migrations/0021_merge_20240319_2339.py @@ -0,0 +1,14 @@ +# Generated by Django 3.1.5 on 2024-03-19 23:39 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('globals', '0020_auto_20240315_2158'), + ('globals', '0018_auto_20240315_2157'), + ] + + operations = [ + ] diff --git a/FusionIIIT/applications/globals/migrations/0022_auto_20240409_2009.py b/FusionIIIT/applications/globals/migrations/0022_auto_20240409_2009.py new file mode 100644 index 000000000..f5307c78b --- /dev/null +++ b/FusionIIIT/applications/globals/migrations/0022_auto_20240409_2009.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.5 on 2024-04-09 20:09 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('globals', '0021_merge_20240319_2339'), + ] + + operations = [ + migrations.AlterField( + model_name='extrainfo', + name='user_status', + field=models.CharField(choices=[('NEW', 'NEW'), ('PRESENT', 'PRESENT')], default='PRESENT', max_length=50), + ), + ] diff --git a/FusionIIIT/applications/hostel_management/.DS_Store b/FusionIIIT/applications/hostel_management/.DS_Store index 2af87a218..11d50077a 100644 Binary files a/FusionIIIT/applications/hostel_management/.DS_Store and b/FusionIIIT/applications/hostel_management/.DS_Store differ diff --git a/FusionIIIT/applications/hostel_management/forms.py b/FusionIIIT/applications/hostel_management/forms.py index b1772bdf9..6c2ede700 100644 --- a/FusionIIIT/applications/hostel_management/forms.py +++ b/FusionIIIT/applications/hostel_management/forms.py @@ -29,5 +29,6 @@ class Meta: 'arrival_time', 'departure_date', 'departure_time', - 'nationality' + 'nationality', + 'room_type' ) \ No newline at end of file diff --git a/FusionIIIT/applications/hostel_management/migrations/.DS_Store b/FusionIIIT/applications/hostel_management/migrations/.DS_Store new file mode 100644 index 000000000..833f18baa Binary files /dev/null and b/FusionIIIT/applications/hostel_management/migrations/.DS_Store differ diff --git a/FusionIIIT/applications/hostel_management/migrations/0020_auto_20240409_1513.py b/FusionIIIT/applications/hostel_management/migrations/0020_auto_20240409_1513.py new file mode 100644 index 000000000..1a1870c6e --- /dev/null +++ b/FusionIIIT/applications/hostel_management/migrations/0020_auto_20240409_1513.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.5 on 2024-04-09 15:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('hostel_management', '0019_merge_20240315_2153'), + ] + + operations = [ + migrations.AddField( + model_name='guestroom', + name='room_type', + field=models.CharField(choices=[('single', 'Single'), ('double', 'Double'), ('triple', 'Triple')], default='single', max_length=10), + ), + migrations.AddField( + model_name='guestroombooking', + name='room_type', + field=models.CharField(choices=[('single', 'Single'), ('double', 'Double'), ('triple', 'Triple')], default='single', max_length=10), + ), + ] diff --git a/FusionIIIT/applications/hostel_management/models.py b/FusionIIIT/applications/hostel_management/models.py index 1108f573a..fea05bb1c 100644 --- a/FusionIIIT/applications/hostel_management/models.py +++ b/FusionIIIT/applications/hostel_management/models.py @@ -125,6 +125,13 @@ class GuestRoomBooking(models.Model): status = models.CharField(max_length=255, choices=HostelManagementConstants.BOOKING_STATUS ,default ="Pending") booking_date = models.DateField(auto_now_add=False, auto_now=False, default=timezone.now) nationality = models.CharField(max_length=255, blank=True) + ROOM_TYPES = [ + ('single', 'Single'), + ('double', 'Double'), + ('triple', 'Triple'), + # Add more room types as needed + ] + room_type = models.CharField(max_length=10, choices=ROOM_TYPES ,default='single') def __str__(self): return '%s ----> %s - %s' % (self.id, self.guest_name, self.status) @@ -141,7 +148,7 @@ class StaffSchedule(models.Model): 'start_time' stores the start time of a schedule. 'end_time' stores the end time of a schedule. """ - hall = models.ForeignKey(Hall, on_delete=models.CASCADE) + hall = models.ForeignKey(Hall, on_delete=models.CASCADE) staff_id = models.ForeignKey(Staff, on_delete=models.CASCADE) staff_type = models.CharField(max_length=100, default='Caretaker') day = models.CharField(max_length=15, choices=HostelManagementConstants.DAYS_OF_WEEK) @@ -309,10 +316,16 @@ class GuestRoom(models.Model): 'vacant' boolean value to determine if the room is vacant 'occupied_till', date field that tells the next time the room will be vacant, null if 'vacant' == True """ + ROOM_TYPES = [ + ('single', 'Single'), + ('double', 'Double'), + ('triple', 'Triple'), + ] hall = models.ForeignKey(Hall, on_delete=models.CASCADE) room = models.CharField(max_length=255) occupied_till = models.DateField(null=True, blank=True) vacant = models.BooleanField(default=True) + room_type = models.CharField(max_length=10, choices=ROOM_TYPES ,default='single') @property def _vacant(self) -> bool: if self.occupied_till and self.occupied_till > timezone.now(): diff --git a/FusionIIIT/applications/hostel_management/urls.py b/FusionIIIT/applications/hostel_management/urls.py index 5b64da506..0a3ed5b75 100644 --- a/FusionIIIT/applications/hostel_management/urls.py +++ b/FusionIIIT/applications/hostel_management/urls.py @@ -93,6 +93,7 @@ #guest room path('book_guest_room/', views.request_guest_room, name="book_guest_room"), path('update_guest_room/', views.update_guest_room, name="update_guest_room"), + path('available_guest_rooms/', views.available_guestrooms_api, name='available_guestrooms_api'), # !!todo: Add Fine Functionality @@ -107,5 +108,9 @@ path('student//name/', views.get_student_name, name='find_name'), + + path('edit-student//', views.edit_student, name='edit_student'), + + ] \ No newline at end of file diff --git a/FusionIIIT/applications/hostel_management/views.py b/FusionIIIT/applications/hostel_management/views.py index aae447a88..ef16e3082 100644 --- a/FusionIIIT/applications/hostel_management/views.py +++ b/FusionIIIT/applications/hostel_management/views.py @@ -76,6 +76,9 @@ from django.db import transaction from .forms import HallForm from notification.views import hostel_notifications +from django.db.models.signals import post_save +from django.dispatch import receiver +from django.db import transaction def is_superuser(user): @@ -295,16 +298,76 @@ def hostel_view(request, context={}): staff_id=staff_student_info).hall_id hall_num = Hall.objects.get(id=hall_caretaker_id) - hostel_students_details = StudentDetails.objects.filter(hall_id=hall_num) - context['hostel_students_details']= hostel_students_details - elif HallWarden.objects.filter(faculty_id=staff_student_info).exists(): + hall_number = int(''.join(filter(str.isdigit,hall_num.hall_id))) + + + # hostel_students_details = Student.objects.filter(hall_no=hall_number) + # context['hostel_students_details']= hostel_students_details + + hostel_students_details = [] + students = Student.objects.filter(hall_no=hall_number) + + # Retrieve additional information for each student + for student in students: + student_info = {} + student_info['student_id'] = student.id.id + student_info['first_name'] = student.id.user.first_name + student_info['programme'] = student.programme + student_info['batch'] = student.batch + student_info['hall_number'] = student.hall_no + student_info['room_number'] = student.room_no + student_info['specialization'] = student.specialization + # student_info['parent_contact'] = student.parent_contact + + # Fetch address and phone number from ExtraInfo model + extra_info = ExtraInfo.objects.get(user=student.id.user) + student_info['address'] = extra_info.address + student_info['phone_number'] = extra_info.phone_no + + hostel_students_details.append(student_info) + + context['hostel_students_details'] = hostel_students_details + + if request.user.id in Faculty.objects.values_list('id__user', flat=True): + staff_student_info = request.user.extrainfo.id + if HallWarden.objects.filter(faculty_id=staff_student_info).exists(): hall_warden_id = HallWarden.objects.get( faculty_id=staff_student_info).hall_id hall_num = Hall.objects.get(id=hall_warden_id) - hostel_students_details = StudentDetails.objects.filter(hall_id=hall_num) + + hall_number = int(''.join(filter(str.isdigit,hall_num.hall_id))) + print(hall_number) + + # hostel_students_details = Student.objects.filter(hall_no=hall_number) + # context['hostel_students_details']= hostel_students_details + + hostel_students_details = [] + students = Student.objects.filter(hall_no=hall_number) + + # Retrieve additional information for each student + for student in students: + student_info = {} + student_info['student_id'] = student.id.id + student_info['first_name'] = student.id.user.first_name + student_info['programme'] = student.programme + student_info['batch'] = student.batch + student_info['hall_number'] = student.hall_no + student_info['room_number'] = student.room_no + student_info['specialization'] = student.specialization + # student_info['parent_contact'] = student.parent_contact + + # Fetch address and phone number from ExtraInfo model + extra_info = ExtraInfo.objects.get(user=student.id.user) + student_info['address'] = extra_info.address + student_info['phone_number'] = extra_info.phone_no + + hostel_students_details.append(student_info) + context['hostel_students_details'] = hostel_students_details + + # print(request.user.username); if Student.objects.filter(id_id=request.user.username).exists(): @@ -937,6 +1000,7 @@ def post(self, request, *args, **kwargs): return JsonResponse({'status': 'error', 'error': str(e)}, status=500) + @method_decorator(user_passes_test(is_superuser), name='dispatch') class AssignBatchView(View): authentication_classes = [SessionAuthentication] @@ -948,49 +1012,68 @@ def get(self, request, *args, **kwargs): hall = Hall.objects.all() return render(request, self.template_name, {'halls': hall}) + def update_student_hall_allotment(self, hall, assigned_batch): + hall_number = int(''.join(filter(str.isdigit, hall.hall_id))) + students = Student.objects.filter(batch=int(assigned_batch)) + + + for student in students: + student.hall_no = hall_number + student.save() + + def post(self, request, *args, **kwargs): try: - data = json.loads(request.body.decode('utf-8')) - hall_id = data.get('hall_id') + with transaction.atomic(): # Start a database transaction - hall = Hall.objects.get(hall_id=hall_id) - previous_batch = hall.assigned_batch # Get the previous batch - hall.assigned_batch = data.get('batch') - hall.save() - - # Update the assignedBatch field in HostelAllotment table for the corresponding hall - room_allotments = HostelAllotment.objects.filter(hall=hall) - for room_allotment in room_allotments: - room_allotment.assignedBatch = hall.assigned_batch - room_allotment.save() - - # retrieve the current caretaker and current warden for the hall - current_caretaker =HallCaretaker.objects.filter(hall=hall).first() - current_warden = HallWarden.objects.filter(hall=hall).first() + data = json.loads(request.body.decode('utf-8')) + hall_id = data.get('hall_id') - # Record the transaction history - HostelTransactionHistory.objects.create( - hall=hall, - change_type='Batch', - previous_value=previous_batch, - new_value=hall.assigned_batch - ) + hall = Hall.objects.get(hall_id=hall_id) + previous_batch = hall.assigned_batch # Get the previous batch + hall.assigned_batch = data.get('batch') + hall.save() - # Create hostel history - try: - HostelHistory.objects.create( - hall=hall, - caretaker=current_caretaker.staff if (current_caretaker and current_caretaker.staff) else None, - - batch=hall.assigned_batch, - warden=current_warden.faculty if( current_warden and current_warden.faculty) else None + + + + # Update the assignedBatch field in HostelAllotment table for the corresponding hall + room_allotments = HostelAllotment.objects.filter(hall=hall) + for room_allotment in room_allotments: + room_allotment.assignedBatch = hall.assigned_batch + room_allotment.save() + + # retrieve the current caretaker and current warden for the hall + current_caretaker =HallCaretaker.objects.filter(hall=hall).first() + current_warden = HallWarden.objects.filter(hall=hall).first() + + # Record the transaction history + HostelTransactionHistory.objects.create( + hall=hall, + change_type='Batch', + previous_value=previous_batch, + new_value=hall.assigned_batch ) - print("hostel hostory created succeessfully") - except Exception as e: - print ("Error creating history",e) - return JsonResponse({'status': 'success', 'message': 'Batch assigned successfully'}, status=200) + # Create hostel history + try: + HostelHistory.objects.create( + hall=hall, + caretaker=current_caretaker.staff if (current_caretaker and current_caretaker.staff) else None, + + batch=hall.assigned_batch, + warden=current_warden.faculty if( current_warden and current_warden.faculty) else None + + ) + print("hostel history created succeessfully") + except Exception as e: + print ("Error creating history",e) + + self.update_student_hall_allotment(hall, hall.assigned_batch) + print("batch assigned successssssssssssssssssss") + + return JsonResponse({'status': 'success', 'message': 'Batch assigned successfully'}, status=200) except Hall.DoesNotExist: return JsonResponse({'status': 'error', 'error': f'Hall with ID {hall_id} not found'}, status=404) @@ -1547,10 +1630,33 @@ def request_guest_room(request): departure_date = form.cleaned_data['departure_date'] departure_time = form.cleaned_data['departure_time'] nationality = form.cleaned_data['nationality'] + room_type = form.cleaned_data['room_type'] # Add room type + + + max_guests = { + 'single': 1, + 'double': 2, + 'triple': 3, + } + # Fetch available room count based on room type and hall + available_rooms_count = GuestRoom.objects.filter( + hall=hall, room_type=room_type, vacant=True + ).count() + + # Check if there are enough available rooms + if available_rooms_count < rooms_required: + messages.error(request, "Not enough available rooms.") + return HttpResponseRedirect(reverse("hostelmanagement:hostel_view")) + + # Check if the number of guests exceeds the capacity of selected rooms + if total_guest > rooms_required * max_guests.get(room_type, 1): + messages.error(request, "Number of guests exceeds the capacity of selected rooms.") + return HttpResponseRedirect(reverse("hostelmanagement:hostel_view")) + newBooking = GuestRoomBooking.objects.create(hall=hall, intender=request.user, guest_name=guest_name, guest_address=guest_address, guest_phone=guest_phone, guest_email=guest_email, rooms_required=rooms_required, total_guest=total_guest, purpose=purpose, - arrival_date=arrival_date, arrival_time=arrival_time, departure_date=departure_date, departure_time=departure_time, nationality=nationality) + arrival_date=arrival_date, arrival_time=arrival_time, departure_date=departure_date, departure_time=departure_time, nationality=nationality,room_type=room_type) newBooking.save() messages.success(request, "Room request submitted successfully!") @@ -1614,6 +1720,21 @@ def update_guest_room(request): return HttpResponseRedirect(reverse("hostelmanagement:hostel_view")) +def available_guestrooms_api(request): + if request.method == 'GET': + + hall_id = request.GET.get('hall_id') + print(hall_id) + room_type = request.GET.get('room_type') + + if hall_id and room_type: + available_rooms_count = GuestRoom.objects.filter(hall_id=hall_id, room_type=room_type, vacant=True).count() + print('~~~~~~~~~~~~~~~~~~`',available_rooms_count) + return JsonResponse({'available_rooms_count': available_rooms_count}) + + return JsonResponse({'error': 'Invalid request'}, status=400) + + # //Caretaker can approve or reject leave applied by the student @csrf_exempt def update_leave_status(request): @@ -1834,3 +1955,22 @@ def delete(self, request, fine_id): raise NotFound(detail="Hostel fine not found") return Response({'message': 'Fine deleted successfully.'}, status=status.HTTP_204_NO_CONTENT) + + + +def edit_student(request, student_id): + student = get_object_or_404(Student, id=student_id) + print('~~~~~~~~~~~~~~~~~~~~~~~~~`',student_id) + + if request.method == 'POST': + # Process the form submission to update student details + # For example: + student.first_name = request.POST.get('first_name') + student.last_name = request.POST.get('last_name') + # Update other fields as needed + student.save() + # Redirect to a page showing the updated details or any other desired page + return redirect('student_details') # Redirect to the student details page + + # If it's a GET request, render the edit student details form + return render(request, 'update_student_details.html', {'student': student}) \ No newline at end of file diff --git a/FusionIIIT/templates/hostelmanagement/assign_batch.html b/FusionIIIT/templates/hostelmanagement/assign_batch.html index 25b7cefbb..1d073f7d1 100644 --- a/FusionIIIT/templates/hostelmanagement/assign_batch.html +++ b/FusionIIIT/templates/hostelmanagement/assign_batch.html @@ -40,7 +40,7 @@

Assign Batch

}) .then(response => response.json()) .then(data => { - alert(data.message); + alert("batch assigned succesfully"); }) .catch(error => { console.error('Error:', error); diff --git a/FusionIIIT/templates/hostelmanagement/book_guest_room.html b/FusionIIIT/templates/hostelmanagement/book_guest_room.html index dcbe353d9..6a9d2a85d 100644 --- a/FusionIIIT/templates/hostelmanagement/book_guest_room.html +++ b/FusionIIIT/templates/hostelmanagement/book_guest_room.html @@ -1,135 +1,227 @@ -{% block book_guest_room %} -
-
-
- - Book a Guest Room! +{% block book_guest_room %} + +
+
+ + Book a Guest Room! +
+ {{ form.non_field_errors }} +
+
+ {% csrf_token %} +
+ + +
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ {% comment %}
+ + + +
{% endcomment %} + +
+
+ {{ form.guests.errors }} + + +
+
+ {{ form.nationality.errors }} + + +
+
+
+
+ {{ form.rooms_required.errors }} + +
- {{ form.non_field_errors }} -
-
- {% csrf_token %} -
- - -
-
-
- - -
-
- - -
-
-
-
- - -
-
- - -
-
- {% comment %}
- - - -
{% endcomment %} - -
-
- {{ form.guests.errors }} - - -
-
- {{ form.nationality.errors }} - - -
-
-
-
- {{ form.rooms_required.errors }} - - -
-
- {{ form.guest_name.errors }} - - -
-
-
-
- {{ form.guest_email.errors }} - - -
-
- {{ form.guest_phone.errors }} - - -
-
-
- {{ form.guest_address.errors }} - - -
-
- {{ form.purpose.errors }} - - -
- - -
-
- - -
-
-
+
+ +
+ + +
+
+ +
+ +
+
+
+ + + +
+ +
+ {{ form.guest_name.errors }} + + +
+
+ {{ form.guest_address.errors }} + + +
+
- - - + } + } + + // Event listener for change in room type selection + document.addEventListener('DOMContentLoaded', function () { + console.log('DOMContentLoaded event fired.'); + document.getElementById('id_room_type').addEventListener('change', fetchAvailableRoomsCount); + }); + // // Get today's date in YYYY-MM-DD format + var today = new Date().toISOString().split('T')[0]; + document.getElementById("arrival_date").value = ""; + document.getElementById("departure_date").value = ""; + document.getElementById("arrival_date").min = today; + document.getElementById("arrival_date").addEventListener("change", function () { + document.getElementById("departure_date").min = document.getElementById("arrival_date").value; + }); + + // Function to validate phone number + function validatePhoneNumber() { + var phoneNumber = document.getElementById('guest_phone_input').value; + var phoneError = document.getElementById('phone_error'); + + // Check if phone number is exactly 10 digits + if (phoneNumber.length !== 10) { + phoneError.innerText = 'Phone number must be exactly 10 digits.'; + return false; // Prevent form submission + } else { + phoneError.innerText = ''; // Clear error message + return true; // Allow form submission + } + } + + // Event listener for input change in phone number field + document.getElementById('guest_phone_input').addEventListener('input', function () { + validatePhoneNumber(); + }); + + // Event listener for form submission + document.getElementById('book_guest_room').addEventListener('submit', function (event) { + if (!validatePhoneNumber()) { + event.preventDefault(); // Prevent form submission if phone number is invalid + } + }); + {% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/hostelmanagement/student_details.html b/FusionIIIT/templates/hostelmanagement/student_details.html index fbbedb4d5..e7c1c3f0e 100644 --- a/FusionIIIT/templates/hostelmanagement/student_details.html +++ b/FusionIIIT/templates/hostelmanagement/student_details.html @@ -6,28 +6,29 @@

Student Details

ID First Name - Last Name + Programme Batch - Room Number + Hall Number + Room Number Specialization - Parent Contact + Contact number Address + {% for stu in hostel_students_details %} - {{ stu.id }} + {{ stu.student_id }} {{ stu.first_name }} - {{ stu.last_name }} {{ stu.programme }} {{ stu.batch }} - {{ stu.room_num }} - {{ stu.hall_id }} - {{ stu.specialization }} - {{ stu.parent_contact }} + hall {{ stu.hall_number }} + {{ stu.room_number }} + {{ stu.specialization }} + {{ stu.phone_number }} {{ stu.address }} {% endfor %} diff --git a/FusionIIIT/templates/hostelmanagement/update_student_details.html b/FusionIIIT/templates/hostelmanagement/update_student_details.html new file mode 100644 index 000000000..fadc92bd8 --- /dev/null +++ b/FusionIIIT/templates/hostelmanagement/update_student_details.html @@ -0,0 +1,17 @@ +{% extends 'base.html' %} + +{% block content %} +

Edit Student Details

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