Files
Student-Management-System-I…/app/admissionviews.py
T
2025-04-15 04:20:26 +05:45

732 lines
24 KiB
Python

# Standard library imports
from datetime import timedelta, datetime
# Core Django imports
from django.shortcuts import render, redirect, get_object_or_404
from django.http import JsonResponse
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.db.models import Count, Q, Avg
from django.utils import timezone
from django.views.decorators.http import require_http_methods, require_GET
from django.contrib.auth.hashers import check_password, make_password
from django.contrib.auth.models import Group
# Local app imports
from app.models import (
Staff,
Student,
Course,
CourseTracking,
Batch,
StaffLeave,
Notice,
FEEDBACK_TYPE_CHOICES,
)
@login_required
def admission_officer_dashboard(request):
"""View to display the admission officer dashboard"""
# Check if user is in staff and has Admission Officer designation
if (
not isinstance(request.user, Staff)
or request.user.designation != "Admission Officer"
):
messages.error(
request,
"You don't have permission to access the admission officer dashboard.",
)
return redirect("dashboard")
# Get the admission officer object
try:
admission_officer = request.user
except Exception as e:
messages.error(
request,
"Admission Officer profile not found. Please contact administrator.",
)
return redirect("dashboard")
today = timezone.now().date()
last_week = today - timedelta(days=7)
last_month = today - timedelta(days=30)
# Get student statistics and list
total_students = Student.objects.count()
active_students = Student.objects.filter(status="Active").count()
new_students = Student.objects.filter(joining_date__gte=last_month).count()
students = (
Student.objects.select_related("course")
.prefetch_related("batches")
.all()
.order_by("-id")
) # For the student list
# Get course statistics and list
total_courses = Course.objects.count()
active_courses = Course.objects.filter(is_active=True).count()
courses = Course.objects.all().order_by("name") # For the dropdown
# Get batch statistics and list
total_batches = Batch.objects.count()
active_batches = Batch.objects.filter(is_active=True).count()
batches = Batch.objects.all().order_by("-year") # For the dropdown
# Get recent course trackings
recent_trackings = CourseTracking.objects.select_related(
"student", "course"
).order_by("-created_at")
# Get leave statistics
pending_leaves = StaffLeave.objects.filter(
staff=admission_officer, status=0
).count()
approved_leaves = StaffLeave.objects.filter(
staff=admission_officer, status=1
).count()
rejected_leaves = StaffLeave.objects.filter(
staff=admission_officer, status=2
).count()
# Get recent leaves
recent_leaves = StaffLeave.objects.filter(staff=admission_officer).order_by(
"-created_at"
)
# Get recent notices
notices = Notice.objects.all().order_by("-created_at")
# Get feedback types for institute feedback
feedback_types = FEEDBACK_TYPE_CHOICES
context = {
"officer": admission_officer,
"title": "Admission Officer Dashboard",
"total_students": total_students,
"active_students": active_students,
"new_students": new_students,
"students": students, # For the student list
"total_courses": total_courses,
"active_courses": active_courses,
"courses": courses, # For the dropdown
"total_batches": total_batches,
"active_batches": active_batches,
"batches": batches, # For the dropdown
"recent_trackings": recent_trackings,
"pending_leaves": pending_leaves,
"approved_leaves": approved_leaves,
"rejected_leaves": rejected_leaves,
"recent_leaves": recent_leaves,
"notices": notices,
"feedback_types": feedback_types,
}
return render(request, "admission_officer/dashboard.html", context)
@login_required
def add_student(request):
"""View to add a new student"""
if request.method != "POST":
messages.error(request, "Invalid request method")
return redirect("admissionOfficerDashboard")
# Check if user has permission
if (
not isinstance(request.user, Staff)
or request.user.designation != "Admission Officer"
):
messages.error(request, "Permission denied")
return redirect("admissionOfficerDashboard")
try:
# Get form data
name = request.POST.get("name")
phone = request.POST.get("phone")
email = request.POST.get("email")
gender = request.POST.get("gender")
birth_date = request.POST.get("birth_date")
course_id = request.POST.get("course")
current_period = request.POST.get("current_period", 1)
status = request.POST.get("status", "Active")
parent_name = request.POST.get("parent_name")
parent_phone = request.POST.get("parent_phone")
permanent_address = request.POST.get("permanent_address")
temporary_address = request.POST.get("temporary_address")
citizenship_number = request.POST.get("citizenship_number")
# Get batch ID
batch_id = request.POST.get("batches")
# Get photo if uploaded
photo = request.FILES.get("photo")
# Validate required fields
if not all([name, phone, batch_id]):
messages.error(request, "Name, phone, and batch are required")
return redirect("admissionOfficerDashboard")
# Check if student with same phone already exists
if Student.objects.filter(phone=phone).exists():
messages.error(request, "Student with this phone number already exists")
return redirect("admissionOfficerDashboard")
# Create student object
student = Student()
student.name = name
student.phone = phone
student.email = email
student.gender = gender
# Set birth date if provided
if birth_date:
student.birth_date = birth_date
# Set course if provided
if course_id:
try:
course = Course.objects.get(id=course_id)
student.course = course
student.current_period = current_period
except Course.DoesNotExist:
messages.error(request, "Selected course not found")
return redirect("admissionOfficerDashboard")
student.status = status
student.parent_name = parent_name
student.parent_phone = parent_phone
student.permanent_address = permanent_address
student.temporary_address = temporary_address
student.citizenship_number = citizenship_number
# Set photo if uploaded
if photo:
student.image = photo
# Set default password as '123'
student.set_password("123")
# Save student
student.save()
# Add student to Student group
student_group, created = Group.objects.get_or_create(name="Student")
student.groups.add(student_group)
# Add student to batch
if batch_id:
try:
batch = Batch.objects.get(id=batch_id)
student.batches.add(batch)
# Joining date will be set automatically from the batch year in the signal
except Batch.DoesNotExist:
messages.error(request, "Selected batch not found")
# Continue anyway as we've already saved the student
# Create course tracking if course is assigned
if course_id:
try:
# Use today's date if no joining date yet (should be set by batch signal)
start_date = student.joining_date or timezone.now().date()
course_tracking = CourseTracking(
student=student,
course=course,
start_date=start_date,
current_period=current_period,
)
course_tracking.save()
except Exception as e:
print(f"Error creating course tracking: {str(e)}")
messages.success(
request, f'Student "{name}" added successfully. Default password is: 123'
)
return redirect("admissionOfficerDashboard")
except Exception as e:
messages.error(request, f"Error: {str(e)}")
return redirect("admissionOfficerDashboard")
@login_required
def add_batch(request):
"""View to add a new batch"""
if request.method != "POST":
messages.error(request, "Invalid request method")
return redirect("admissionOfficerDashboard")
# Check if user has permission
if (
not isinstance(request.user, Staff)
or request.user.designation != "Admission Officer"
):
messages.error(request, "Permission denied")
return redirect("admissionOfficerDashboard")
try:
# Get form data
name = request.POST.get("name")
start_date = request.POST.get("start_date")
is_active = request.POST.get("is_active") == "on"
# Validate required fields
if not all([name, start_date]):
messages.error(request, "Name and start date are required")
return redirect("admissionOfficerDashboard")
# Create batch
batch = Batch()
batch.name = name
batch.year = start_date # Use start_date for the year field
batch.is_active = is_active
batch.save()
messages.success(request, f'Batch "{name}" added successfully')
return redirect("admissionOfficerDashboard")
except Exception as e:
messages.error(request, f"Error: {str(e)}")
return redirect("admissionOfficerDashboard")
@login_required
def add_course(request):
"""View to add a new course"""
if request.method != "POST":
messages.error(request, "Invalid request method")
return redirect("admissionOfficerDashboard")
# Check if user has permission
if (
not isinstance(request.user, Staff)
or request.user.designation != "Admission Officer"
):
messages.error(request, "Permission denied")
return redirect("admissionOfficerDashboard")
try:
# Get form data
name = request.POST.get("name")
code = request.POST.get("code", "")
duration_type = request.POST.get("duration_type")
duration = request.POST.get("duration")
description = request.POST.get("description", "")
is_active = request.POST.get("is_active") == "on"
# Validate required fields
if not all([name, duration_type, duration]):
messages.error(request, "Name, duration type, and duration are required")
return redirect("admissionOfficerDashboard")
# Create course
course = Course()
course.name = name
course.code = code
course.duration_type = duration_type
course.duration = duration
course.description = description
course.is_active = is_active
course.save()
messages.success(request, f'Course "{name}" added successfully')
return redirect("admissionOfficerDashboard")
except Exception as e:
messages.error(request, f"Error: {str(e)}")
return redirect("admissionOfficerDashboard")
@login_required
def add_course_tracking(request):
"""View to add course tracking for a student"""
if request.method != "POST":
messages.error(request, "Invalid request method")
return redirect("admissionOfficerDashboard")
# Check if user has permission
if (
not isinstance(request.user, Staff)
or request.user.designation != "Admission Officer"
):
messages.error(request, "Permission denied")
return redirect("admissionOfficerDashboard")
try:
# Get form data
student_id = request.POST.get("student")
course_id = request.POST.get("course")
start_date = request.POST.get("start_date")
expected_end_date = request.POST.get("expected_end_date")
current_period = request.POST.get("current_period", 1)
progress_status = request.POST.get("progress_status", "In Progress")
notes = request.POST.get("notes")
# Validate required fields
if not student_id or not course_id:
messages.error(request, "Student and course are required")
return redirect("admissionOfficerDashboard")
# Check if student exists
try:
student = Student.objects.get(id=student_id)
except Student.DoesNotExist:
messages.error(request, "Student not found")
return redirect("admissionOfficerDashboard")
# Check if course exists
try:
course = Course.objects.get(id=course_id)
except Course.DoesNotExist:
messages.error(request, "Course not found")
return redirect("admissionOfficerDashboard")
# Check if tracking already exists
if CourseTracking.objects.filter(student=student, course=course).exists():
messages.error(request, "Student is already enrolled in this course")
return redirect("admissionOfficerDashboard")
# Create course tracking object
tracking = CourseTracking()
tracking.student = student
tracking.course = course
# Set dates if provided
if start_date:
tracking.start_date = start_date
if expected_end_date:
tracking.expected_end_date = expected_end_date
tracking.current_period = int(current_period)
tracking.progress_status = progress_status
tracking.notes = notes
# Save tracking
tracking.save()
messages.success(
request,
f'Course tracking added for student "{student.name}" in course "{course.name}"',
)
return redirect("admissionOfficerDashboard")
except Exception as e:
messages.error(request, f"Error: {str(e)}")
return redirect("admissionOfficerDashboard")
@login_required
def get_courses(request):
"""View to get courses for dropdowns"""
try:
courses = Course.objects.all().order_by("name")
course_data = [
{"id": course.id, "name": course.name, "code": course.code}
for course in courses
]
return JsonResponse({"success": True, "courses": course_data})
except Exception as e:
return JsonResponse({"success": False, "message": str(e)}, status=500)
@login_required
def get_batches(request):
"""View to get batches for dropdowns"""
try:
batches = Batch.objects.all().order_by("-year")
batch_data = []
for batch in batches:
batch_data.append(
{
"id": batch.id,
"name": batch.name,
"year": batch.year.year if batch.year else None,
"display_name": f"{batch.name} ({batch.year.year if batch.year else 'No year'})",
}
)
return JsonResponse({"success": True, "batches": batch_data})
except Exception as e:
return JsonResponse({"success": False, "message": str(e)}, status=500)
@login_required
def get_students(request):
"""View to get students for dropdowns"""
try:
students = Student.objects.all()
student_data = [
{"id": student.id, "name": student.name, "phone": student.phone}
for student in students
]
return JsonResponse({"success": True, "students": student_data})
except Exception as e:
return JsonResponse({"success": False, "message": str(e)}, status=500)
@login_required
def get_student(request, student_id):
"""View to get a student's details by ID"""
# Check if user has permission
if (
not isinstance(request.user, Staff)
or request.user.designation != "Admission Officer"
):
return JsonResponse(
{"success": False, "message": "Permission denied"}, status=403
)
try:
# Get student with related data
student = (
Student.objects.select_related("course")
.prefetch_related("batches")
.get(id=student_id)
)
# Build batches data
batches = []
for batch in student.batches.all():
batches.append(
{
"id": batch.id,
"name": batch.name,
"year": batch.year.year if batch.year else None,
}
)
# Build student data
student_data = {
"id": student.id,
"name": student.name,
"phone": student.phone,
"email": student.email,
"gender": student.gender,
"birth_date": student.birth_date.strftime("%Y-%m-%d")
if student.birth_date
else None,
"status": student.status,
"parent_name": student.parent_name,
"parent_phone": student.parent_phone,
"permanent_address": student.permanent_address,
"temporary_address": student.temporary_address,
"citizenship_number": student.citizenship_no,
"current_period": student.current_period,
"joining_date": student.joining_date.strftime("%Y-%m-%d")
if student.joining_date
else None,
"image": student.image.url if student.image else None,
"course": {"id": student.course.id, "name": student.course.name}
if student.course
else None,
"batches": batches,
}
return JsonResponse({"success": True, "student": student_data})
except Student.DoesNotExist:
return JsonResponse(
{"success": False, "message": "Student not found"}, status=404
)
except Exception as e:
return JsonResponse({"success": False, "message": str(e)}, status=500)
@login_required
def edit_student(request):
"""View to edit a student's details"""
if request.method != "POST":
return JsonResponse(
{"success": False, "message": "Invalid request method"}, status=405
)
# Check if user has permission
if (
not isinstance(request.user, Staff)
or request.user.designation != "Admission Officer"
):
return JsonResponse(
{"success": False, "message": "Permission denied"}, status=403
)
try:
# Get student ID from form data
student_id = request.POST.get("student_id")
if not student_id:
return JsonResponse(
{"success": False, "message": "Student ID is required"}, status=400
)
# Get student object
student = get_object_or_404(Student, id=student_id)
# Update student fields
student.name = request.POST.get("name", student.name)
student.phone = request.POST.get("phone", student.phone)
student.email = request.POST.get("email", student.email)
student.gender = request.POST.get("gender", student.gender)
# Handle birth date
birth_date = request.POST.get("birth_date")
if birth_date:
student.birth_date = birth_date
# Handle course
course_id = request.POST.get("course")
if course_id:
try:
course = Course.objects.get(id=course_id)
student.course = course
except Course.DoesNotExist:
pass
# Handle status
status = request.POST.get("status")
if status:
student.status = status
# Handle parent info
student.parent_name = request.POST.get("parent_name", student.parent_name)
student.parent_phone = request.POST.get("parent_phone", student.parent_phone)
# Handle address
student.permanent_address = request.POST.get(
"permanent_address", student.permanent_address
)
# Handle citizenship
student.citizenship_no = request.POST.get(
"citizenship_number", student.citizenship_no
)
# Save student
student.save()
# Handle batch
batch_id = request.POST.get("batches")
if batch_id:
try:
batch = Batch.objects.get(id=batch_id)
# Clear existing batches and add the new one
student.batches.clear()
student.batches.add(batch)
except Batch.DoesNotExist:
pass
return JsonResponse(
{"success": True, "message": "Student updated successfully"}
)
except Exception as e:
return JsonResponse({"success": False, "message": str(e)}, status=500)
@login_required
def get_course_tracking(request, tracking_id):
"""View to get a course tracking's details by ID"""
# Check if user has permission
if (
not isinstance(request.user, Staff)
or request.user.designation != "Admission Officer"
):
return JsonResponse(
{"success": False, "message": "Permission denied"}, status=403
)
try:
# Get tracking with related data
tracking = CourseTracking.objects.select_related("student", "course").get(
id=tracking_id
)
# Build tracking data
tracking_data = {
"id": tracking.id,
"student": {"id": tracking.student.id, "name": tracking.student.name},
"course": {"id": tracking.course.id, "name": tracking.course.name},
"start_date": tracking.start_date.strftime("%Y-%m-%d"),
"expected_end_date": tracking.expected_end_date.strftime("%Y-%m-%d")
if tracking.expected_end_date
else None,
"completion_percentage": tracking.completion_percentage,
"progress_status": tracking.progress_status,
"current_period": tracking.current_period,
"notes": tracking.notes,
"current_period_display": tracking.current_period_display,
}
return JsonResponse({"success": True, "tracking": tracking_data})
except CourseTracking.DoesNotExist:
return JsonResponse(
{"success": False, "message": "Course tracking not found"}, status=404
)
except Exception as e:
return JsonResponse({"success": False, "message": str(e)}, status=500)
@login_required
def edit_course_tracking(request):
"""View to edit a course tracking"""
if request.method != "POST":
return JsonResponse(
{"success": False, "message": "Invalid request method"}, status=405
)
# Check if user has permission
if (
not isinstance(request.user, Staff)
or request.user.designation != "Admission Officer"
):
return JsonResponse(
{"success": False, "message": "Permission denied"}, status=403
)
try:
# Get tracking ID from form data
tracking_id = request.POST.get("tracking_id")
if not tracking_id:
return JsonResponse(
{"success": False, "message": "Tracking ID is required"}, status=400
)
# Get tracking object
tracking = get_object_or_404(CourseTracking, id=tracking_id)
# Update tracking fields
start_date = request.POST.get("start_date")
if start_date:
tracking.start_date = start_date
expected_end_date = request.POST.get("expected_end_date")
if expected_end_date:
tracking.expected_end_date = expected_end_date
current_period = request.POST.get("current_period")
if current_period:
tracking.current_period = int(current_period)
progress_status = request.POST.get("progress_status")
if progress_status:
tracking.progress_status = progress_status
completion_percentage = request.POST.get("completion_percentage")
if completion_percentage:
tracking.completion_percentage = int(completion_percentage)
notes = request.POST.get("notes")
if notes is not None: # Allow empty notes
tracking.notes = notes
# Save tracking
tracking.save()
return JsonResponse(
{"success": True, "message": "Course tracking updated successfully"}
)
except Exception as e:
return JsonResponse({"success": False, "message": str(e)}, status=500)