652 lines
27 KiB
Python
652 lines
27 KiB
Python
import csv
|
|
import datetime
|
|
import random
|
|
from django.shortcuts import render, redirect, get_object_or_404
|
|
from django.http import HttpResponse, JsonResponse
|
|
from django.contrib import messages
|
|
from django.db import IntegrityError
|
|
from openpyxl import Workbook
|
|
from .models import (
|
|
ProgramStudi, Dosen, TahunAkademik, Hari,
|
|
MataKuliah, Ruangan, Kelas, Jam, DosenPengampu, Jadwal, DaftarHadir
|
|
)
|
|
|
|
def dashboard(request):
|
|
context = {
|
|
"count_prodi": ProgramStudi.objects.count(),
|
|
"count_dosen": Dosen.objects.count(),
|
|
"count_matkul": MataKuliah.objects.count(),
|
|
"count_ruangan": Ruangan.objects.count(),
|
|
"count_kelas": Kelas.objects.count(),
|
|
"count_jadwal": Jadwal.objects.count(),
|
|
"count_daftar_hadir": DaftarHadir.objects.count(),
|
|
}
|
|
return render(request, "core/dashboard.html", context)
|
|
|
|
# --- AJAX HELPERS ---
|
|
def get_kelas_by_prodi(request):
|
|
prodi_id = request.GET.get('prodi_id')
|
|
kelas = Kelas.objects.filter(prodi_id=prodi_id).values('id', 'nama')
|
|
return JsonResponse(list(kelas), safe=False)
|
|
|
|
def get_matkul_by_prodi(request):
|
|
prodi_id = request.GET.get('prodi_id')
|
|
matkul = MataKuliah.objects.filter(prodi_id=prodi_id).values('id', 'kode', 'nama')
|
|
return JsonResponse(list(matkul), safe=False)
|
|
|
|
# --- PRODI ---
|
|
def prodi_list(request):
|
|
prodi_all = ProgramStudi.objects.all()
|
|
if request.method == "POST":
|
|
if "delete_massal" in request.POST:
|
|
ids = request.POST.getlist("selected_ids")
|
|
ProgramStudi.objects.filter(id__in=ids).delete()
|
|
messages.success(request, f"Berhasil menghapus {len(ids)} Program Studi.")
|
|
else:
|
|
pk = request.POST.get("pk")
|
|
nama = request.POST.get("nama")
|
|
if pk:
|
|
obj = get_object_or_404(ProgramStudi, pk=pk)
|
|
obj.nama = nama
|
|
obj.save()
|
|
messages.success(request, "Program Studi berhasil diupdate.")
|
|
else:
|
|
ProgramStudi.objects.create(nama=nama)
|
|
messages.success(request, "Program Studi berhasil ditambahkan.")
|
|
return redirect("prodi_list")
|
|
return render(request, "core/prodi_list.html", {"prodi_all": prodi_all})
|
|
|
|
def prodi_delete(request, pk):
|
|
get_object_or_404(ProgramStudi, pk=pk).delete()
|
|
messages.success(request, "Program Studi berhasil dihapus.")
|
|
return redirect("prodi_list")
|
|
|
|
# --- DOSEN ---
|
|
def dosen_list(request):
|
|
dosen_all = Dosen.objects.all()
|
|
if request.method == "POST":
|
|
if "delete_massal" in request.POST:
|
|
ids = request.POST.getlist("selected_ids")
|
|
Dosen.objects.filter(id__in=ids).delete()
|
|
messages.success(request, f"Berhasil menghapus {len(ids)} Dosen.")
|
|
else:
|
|
pk = request.POST.get("pk")
|
|
nidn = request.POST.get("nidn")
|
|
nama = request.POST.get("nama")
|
|
if pk:
|
|
obj = get_object_or_404(Dosen, pk=pk)
|
|
obj.nidn = nidn
|
|
obj.nama = nama
|
|
obj.save()
|
|
messages.success(request, "Dosen berhasil diupdate.")
|
|
else:
|
|
Dosen.objects.create(nidn=nidn, nama=nama)
|
|
messages.success(request, "Dosen berhasil ditambahkan.")
|
|
return redirect("dosen_list")
|
|
return render(request, "core/dosen_list.html", {"dosen_all": dosen_all})
|
|
|
|
def dosen_delete(request, pk):
|
|
get_object_or_404(Dosen, pk=pk).delete()
|
|
messages.success(request, "Dosen berhasil dihapus.")
|
|
return redirect("dosen_list")
|
|
|
|
def dosen_template(request):
|
|
response = HttpResponse(content_type='text/csv')
|
|
response['Content-Disposition'] = 'attachment; filename="template_dosen.csv"'
|
|
writer = csv.writer(response)
|
|
writer.writerow(['nidn', 'nama'])
|
|
writer.writerow(['12345678', 'Dr. Nama Dosen, M.Kom'])
|
|
return response
|
|
|
|
def dosen_import(request):
|
|
if request.method == 'POST' and request.FILES.get('csv_file'):
|
|
csv_file = request.FILES['csv_file']
|
|
decoded_file = csv_file.read().decode('utf-8').splitlines()
|
|
reader = csv.DictReader(decoded_file)
|
|
count = 0
|
|
for row in reader:
|
|
Dosen.objects.update_or_create(
|
|
nidn=row['nidn'],
|
|
defaults={'nama': row['nama']}
|
|
)
|
|
count += 1
|
|
messages.success(request, f"Berhasil mengimport {count} data Dosen.")
|
|
return redirect('dosen_list')
|
|
|
|
# --- MATA KULIAH ---
|
|
def matkul_list(request):
|
|
matkul_all = MataKuliah.objects.all()
|
|
prodi_all = ProgramStudi.objects.all()
|
|
if request.method == "POST":
|
|
if "delete_massal" in request.POST:
|
|
ids = request.POST.getlist("selected_ids")
|
|
MataKuliah.objects.filter(id__in=ids).delete()
|
|
messages.success(request, f"Berhasil menghapus {len(ids)} Mata Kuliah.")
|
|
else:
|
|
pk = request.POST.get("pk")
|
|
kode = request.POST.get("kode")
|
|
nama = request.POST.get("nama")
|
|
sks = request.POST.get("sks")
|
|
semester = request.POST.get("semester")
|
|
prodi_id = request.POST.get("prodi")
|
|
prodi = get_object_or_404(ProgramStudi, id=prodi_id)
|
|
try:
|
|
if pk:
|
|
obj = get_object_or_404(MataKuliah, pk=pk)
|
|
obj.kode = kode
|
|
obj.nama = nama
|
|
obj.sks = sks
|
|
obj.semester = semester
|
|
obj.prodi = prodi
|
|
obj.save()
|
|
messages.success(request, "Mata Kuliah berhasil diupdate.")
|
|
else:
|
|
MataKuliah.objects.create(kode=kode, nama=nama, sks=sks, semester=semester, prodi=prodi)
|
|
messages.success(request, "Mata Kuliah berhasil ditambahkan.")
|
|
except IntegrityError:
|
|
messages.error(request, "Gagal menyimpan. Kode atau Nama Mata Kuliah sudah ada di Program Studi ini.")
|
|
return redirect("matkul_list")
|
|
return render(request, "core/matkul_list.html", {"matkul_all": matkul_all, "prodi_all": prodi_all})
|
|
|
|
def matkul_delete(request, pk):
|
|
get_object_or_404(MataKuliah, pk=pk).delete()
|
|
messages.success(request, "Mata Kuliah berhasil dihapus.")
|
|
return redirect("matkul_list")
|
|
|
|
def matkul_template(request):
|
|
response = HttpResponse(content_type='text/csv')
|
|
response['Content-Disposition'] = 'attachment; filename="template_matkul.csv"'
|
|
writer = csv.writer(response)
|
|
writer.writerow(['kode', 'nama', 'sks', 'semester', 'program_studi'])
|
|
writer.writerow(['MK001', 'Algoritma Pemrograman', '3', '1', 'Teknik Informatika'])
|
|
return response
|
|
|
|
def matkul_import(request):
|
|
if request.method == 'POST' and request.FILES.get('csv_file'):
|
|
csv_file = request.FILES['csv_file']
|
|
decoded_file = csv_file.read().decode('utf-8').splitlines()
|
|
reader = csv.DictReader(decoded_file)
|
|
count = 0
|
|
for row in reader:
|
|
prodi_nama = row.get('program_studi')
|
|
prodi, _ = ProgramStudi.objects.get_or_create(nama=prodi_nama)
|
|
MataKuliah.objects.update_or_create(
|
|
kode=row['kode'],
|
|
prodi=prodi,
|
|
defaults={
|
|
'nama': row['nama'],
|
|
'sks': row['sks'],
|
|
'semester': row['semester']
|
|
}
|
|
)
|
|
count += 1
|
|
messages.success(request, f"Berhasil mengimport {count} data Mata Kuliah.")
|
|
return redirect('matkul_list')
|
|
|
|
# --- RUANGAN ---
|
|
def ruangan_list(request):
|
|
ruangan_all = Ruangan.objects.all()
|
|
prodi_all = ProgramStudi.objects.all()
|
|
if request.method == "POST":
|
|
if "delete_massal" in request.POST:
|
|
ids = request.POST.getlist("selected_ids")
|
|
Ruangan.objects.filter(id__in=ids).delete()
|
|
messages.success(request, f"Berhasil menghapus {len(ids)} Ruangan.")
|
|
else:
|
|
pk = request.POST.get("pk")
|
|
nama = request.POST.get("nama")
|
|
kapasitas = request.POST.get("kapasitas")
|
|
prodi_id = request.POST.get("prodi")
|
|
prodi = get_object_or_404(ProgramStudi, id=prodi_id) if prodi_id else None
|
|
if pk:
|
|
obj = get_object_or_404(Ruangan, pk=pk)
|
|
obj.nama = nama
|
|
obj.kapasitas = kapasitas
|
|
obj.prodi = prodi
|
|
obj.save()
|
|
messages.success(request, "Ruangan berhasil diupdate.")
|
|
else:
|
|
Ruangan.objects.create(nama=nama, kapasitas=kapasitas, prodi=prodi)
|
|
messages.success(request, "Ruangan berhasil ditambahkan.")
|
|
return redirect("ruangan_list")
|
|
return render(request, "core/ruangan_list.html", {"ruangan_all": ruangan_all, "prodi_all": prodi_all})
|
|
|
|
def ruangan_delete(request, pk):
|
|
get_object_or_404(Ruangan, pk=pk).delete()
|
|
messages.success(request, "Ruangan berhasil dihapus.")
|
|
return redirect("ruangan_list")
|
|
|
|
def ruangan_template(request):
|
|
response = HttpResponse(content_type='text/csv')
|
|
response['Content-Disposition'] = 'attachment; filename="template_ruangan.csv"'
|
|
writer = csv.writer(response)
|
|
writer.writerow(['nama', 'kapasitas', 'program_studi'])
|
|
writer.writerow(['Ruang A1', '40', 'Teknik Informatika'])
|
|
return response
|
|
|
|
def ruangan_import(request):
|
|
if request.method == 'POST' and request.FILES.get('csv_file'):
|
|
csv_file = request.FILES['csv_file']
|
|
decoded_file = csv_file.read().decode('utf-8').splitlines()
|
|
reader = csv.DictReader(decoded_file)
|
|
count = 0
|
|
for row in reader:
|
|
prodi_nama = row.get('program_studi')
|
|
prodi = None
|
|
if prodi_nama:
|
|
prodi, _ = ProgramStudi.objects.get_or_create(nama=prodi_nama)
|
|
Ruangan.objects.create(nama=row['nama'], kapasitas=row['kapasitas'], prodi=prodi)
|
|
count += 1
|
|
messages.success(request, f"Berhasil mengimport {count} data Ruangan.")
|
|
return redirect('ruangan_list')
|
|
|
|
# --- KELAS ---
|
|
def kelas_list(request):
|
|
kelas_all = Kelas.objects.all()
|
|
prodi_all = ProgramStudi.objects.all()
|
|
if request.method == "POST":
|
|
if "delete_massal" in request.POST:
|
|
ids = request.POST.getlist("selected_ids")
|
|
Kelas.objects.filter(id__in=ids).delete()
|
|
messages.success(request, f"Berhasil menghapus {len(ids)} Kelas.")
|
|
else:
|
|
pk = request.POST.get("pk")
|
|
nama = request.POST.get("nama")
|
|
prodi_id = request.POST.get("prodi")
|
|
prodi = get_object_or_404(ProgramStudi, id=prodi_id) if prodi_id else None
|
|
if pk:
|
|
obj = get_object_or_404(Kelas, pk=pk)
|
|
obj.nama = nama
|
|
obj.prodi = prodi
|
|
obj.save()
|
|
messages.success(request, "Kelas berhasil diupdate.")
|
|
else:
|
|
Kelas.objects.create(nama=nama, prodi=prodi)
|
|
messages.success(request, "Kelas berhasil ditambahkan.")
|
|
return redirect("kelas_list")
|
|
return render(request, "core/kelas_list.html", {"kelas_all": kelas_all, "prodi_all": prodi_all})
|
|
|
|
def kelas_delete(request, pk):
|
|
get_object_or_404(Kelas, pk=pk).delete()
|
|
messages.success(request, "Kelas berhasil dihapus.")
|
|
return redirect("kelas_list")
|
|
|
|
def kelas_template(request):
|
|
response = HttpResponse(content_type='text/csv')
|
|
response['Content-Disposition'] = 'attachment; filename="template_kelas.csv"'
|
|
writer = csv.writer(response)
|
|
writer.writerow(['nama', 'program_studi'])
|
|
writer.writerow(['Kelas A', 'Teknik Informatika'])
|
|
return response
|
|
|
|
def kelas_import(request):
|
|
if request.method == 'POST' and request.FILES.get('csv_file'):
|
|
csv_file = request.FILES['csv_file']
|
|
decoded_file = csv_file.read().decode('utf-8').splitlines()
|
|
reader = csv.DictReader(decoded_file)
|
|
count = 0
|
|
for row in reader:
|
|
prodi_nama = row.get('program_studi')
|
|
prodi = None
|
|
if prodi_nama:
|
|
prodi, _ = ProgramStudi.objects.get_or_create(nama=prodi_nama)
|
|
Kelas.objects.create(nama=row['nama'], prodi=prodi)
|
|
count += 1
|
|
messages.success(request, f"Berhasil mengimport {count} data Kelas.")
|
|
return redirect('kelas_list')
|
|
|
|
# --- JAM ---
|
|
def jam_list(request):
|
|
jam_all = Jam.objects.all()
|
|
if request.method == "POST":
|
|
if "delete_massal" in request.POST:
|
|
ids = request.POST.getlist("selected_ids")
|
|
Jam.objects.filter(id__in=ids).delete()
|
|
messages.success(request, f"Berhasil menghapus {len(ids)} Jam.")
|
|
else:
|
|
pk = request.POST.get("pk")
|
|
range_waktu = request.POST.get("range_waktu")
|
|
if pk:
|
|
obj = get_object_or_404(Jam, pk=pk)
|
|
obj.range_waktu = range_waktu
|
|
obj.save()
|
|
messages.success(request, "Jam berhasil diupdate.")
|
|
else:
|
|
Jam.objects.create(range_waktu=range_waktu)
|
|
messages.success(request, "Jam berhasil ditambahkan.")
|
|
return redirect("jam_list")
|
|
return render(request, "core/jam_list.html", {"jam_all": jam_all})
|
|
|
|
def jam_delete(request, pk):
|
|
get_object_or_404(Jam, pk=pk).delete()
|
|
messages.success(request, "Jam berhasil dihapus.")
|
|
return redirect("jam_list")
|
|
|
|
def jam_generate(request):
|
|
if request.method == "POST":
|
|
start_str = request.POST.get("jam_mulai") # e.g. "07:00"
|
|
end_str = request.POST.get("jam_selesai") # e.g. "17:00"
|
|
mins_per_sks = int(request.POST.get("durasi_per_sks", 50))
|
|
sks_per_slot = int(request.POST.get("jumlah_sks", 2))
|
|
jeda_mins = int(request.POST.get("jeda", 0))
|
|
|
|
start_time = datetime.datetime.strptime(start_str, "%H:%M")
|
|
end_time = datetime.datetime.strptime(end_str, "%H:%M")
|
|
|
|
slot_duration = mins_per_sks * sks_per_slot
|
|
current_time = start_time
|
|
|
|
count = 0
|
|
while current_time + datetime.timedelta(minutes=slot_duration) <= end_time:
|
|
slot_end = current_time + datetime.timedelta(minutes=slot_duration)
|
|
range_waktu = f"{current_time.strftime('%H:%M')} - {slot_end.strftime('%H:%M')}"
|
|
Jam.objects.get_or_create(range_waktu=range_waktu)
|
|
current_time = slot_end + datetime.timedelta(minutes=jeda_mins)
|
|
count += 1
|
|
|
|
messages.success(request, f"Berhasil menggenerate {count} slot waktu.")
|
|
return redirect("jam_list")
|
|
|
|
# --- TAHUN AKADEMIK ---
|
|
def tahun_list(request):
|
|
tahun_all = TahunAkademik.objects.all()
|
|
if request.method == "POST":
|
|
if "delete_massal" in request.POST:
|
|
ids = request.POST.getlist("selected_ids")
|
|
TahunAkademik.objects.filter(id__in=ids).delete()
|
|
messages.success(request, f"Berhasil menghapus {len(ids)} Tahun Akademik.")
|
|
else:
|
|
pk = request.POST.get("pk")
|
|
nama = request.POST.get("nama")
|
|
is_active = request.POST.get("is_active") == "on"
|
|
if pk:
|
|
obj = get_object_or_404(TahunAkademik, pk=pk)
|
|
if is_active:
|
|
TahunAkademik.objects.update(is_active=False)
|
|
obj.nama = nama
|
|
obj.is_active = is_active
|
|
obj.save()
|
|
messages.success(request, "Tahun Akademik berhasil diupdate.")
|
|
else:
|
|
if is_active:
|
|
TahunAkademik.objects.update(is_active=False)
|
|
TahunAkademik.objects.create(nama=nama, is_active=is_active)
|
|
messages.success(request, "Tahun Akademik berhasil ditambahkan.")
|
|
return redirect("tahun_list")
|
|
return render(request, "core/tahun_list.html", {"tahun_all": tahun_all})
|
|
|
|
def tahun_delete(request, pk):
|
|
get_object_or_404(TahunAkademik, pk=pk).delete()
|
|
messages.success(request, "Tahun Akademik berhasil dihapus.")
|
|
return redirect("tahun_list")
|
|
|
|
# --- HARI ---
|
|
def hari_list(request):
|
|
hari_all = Hari.objects.all()
|
|
if request.method == "POST":
|
|
if "delete_massal" in request.POST:
|
|
ids = request.POST.getlist("selected_ids")
|
|
Hari.objects.filter(id__in=ids).delete()
|
|
messages.success(request, f"Berhasil menghapus {len(ids)} Hari.")
|
|
else:
|
|
pk = request.POST.get("pk")
|
|
nama = request.POST.get("nama")
|
|
if pk:
|
|
obj = get_object_or_404(Hari, pk=pk)
|
|
obj.nama = nama
|
|
obj.save()
|
|
messages.success(request, "Hari berhasil diupdate.")
|
|
else:
|
|
Hari.objects.create(nama=nama)
|
|
messages.success(request, "Hari berhasil ditambahkan.")
|
|
return redirect("hari_list")
|
|
return render(request, "core/hari_list.html", {"hari_all": hari_all})
|
|
|
|
def hari_delete(request, pk):
|
|
get_object_or_404(Hari, pk=pk).delete()
|
|
messages.success(request, "Hari berhasil dihapus.")
|
|
return redirect("hari_list")
|
|
|
|
# --- DOSEN PENGAMPU ---
|
|
def pengampu_list(request):
|
|
pengampu_all = DosenPengampu.objects.all()
|
|
dosen_all = Dosen.objects.all()
|
|
matkul_all = MataKuliah.objects.all()
|
|
tahun_all = TahunAkademik.objects.all()
|
|
prodi_all = ProgramStudi.objects.all()
|
|
kelas_all = Kelas.objects.all()
|
|
if request.method == "POST":
|
|
if "delete_massal" in request.POST:
|
|
ids = request.POST.getlist("selected_ids")
|
|
DosenPengampu.objects.filter(id__in=ids).delete()
|
|
messages.success(request, f"Berhasil menghapus {len(ids)} Dosen Pengampu.")
|
|
else:
|
|
pk = request.POST.get("pk")
|
|
dosen_id = request.POST.get("dosen")
|
|
matkul_id = request.POST.get("matkul")
|
|
tahun_id = request.POST.get("tahun")
|
|
prodi_id = request.POST.get("prodi")
|
|
kelas_id = request.POST.get("kelas")
|
|
|
|
dosen = get_object_or_404(Dosen, id=dosen_id)
|
|
matkul = get_object_or_404(MataKuliah, id=matkul_id)
|
|
tahun = get_object_or_404(TahunAkademik, id=tahun_id)
|
|
prodi = get_object_or_404(ProgramStudi, id=prodi_id) if prodi_id else None
|
|
kelas = get_object_or_404(Kelas, id=kelas_id) if kelas_id else None
|
|
|
|
if pk:
|
|
obj = get_object_or_404(DosenPengampu, pk=pk)
|
|
obj.dosen = dosen
|
|
obj.matkul = matkul
|
|
obj.tahun_akademik = tahun
|
|
obj.prodi = prodi
|
|
obj.kelas = kelas
|
|
obj.save()
|
|
messages.success(request, "Dosen Pengampu berhasil diupdate.")
|
|
else:
|
|
DosenPengampu.objects.create(
|
|
dosen=dosen, matkul=matkul, tahun_akademik=tahun,
|
|
prodi=prodi, kelas=kelas
|
|
)
|
|
messages.success(request, "Dosen Pengampu berhasil ditambahkan.")
|
|
return redirect("pengampu_list")
|
|
return render(request, "core/pengampu_list.html", {
|
|
"pengampu_all": pengampu_all,
|
|
"dosen_all": dosen_all,
|
|
"matkul_all": matkul_all,
|
|
"tahun_all": tahun_all,
|
|
"prodi_all": prodi_all,
|
|
"kelas_all": kelas_all,
|
|
})
|
|
|
|
def pengampu_delete(request, pk):
|
|
get_object_or_404(DosenPengampu, pk=pk).delete()
|
|
messages.success(request, "Dosen Pengampu berhasil dihapus.")
|
|
return redirect("pengampu_list")
|
|
|
|
# --- DAFTAR HADIR ---
|
|
def daftar_hadir_list(request):
|
|
hadir_all = DaftarHadir.objects.all()
|
|
jadwal_all = Jadwal.objects.all()
|
|
if request.method == "POST":
|
|
if "delete_massal" in request.POST:
|
|
ids = request.POST.getlist("selected_ids")
|
|
DaftarHadir.objects.filter(id__in=ids).delete()
|
|
messages.success(request, f"Berhasil menghapus {len(ids)} Daftar Hadir.")
|
|
else:
|
|
pk = request.POST.get("pk")
|
|
jadwal_id = request.POST.get("jadwal")
|
|
tanggal = request.POST.get("tanggal")
|
|
pertemuan = request.POST.get("pertemuan_ke")
|
|
ket = request.POST.get("keterangan")
|
|
jadwal = get_object_or_404(Jadwal, id=jadwal_id)
|
|
if pk:
|
|
obj = get_object_or_404(DaftarHadir, pk=pk)
|
|
obj.jadwal = jadwal
|
|
obj.tanggal = tanggal
|
|
obj.pertemuan_ke = pertemuan
|
|
obj.keterangan = ket
|
|
obj.save()
|
|
messages.success(request, "Daftar Hadir berhasil diupdate.")
|
|
else:
|
|
DaftarHadir.objects.create(jadwal=jadwal, tanggal=tanggal, pertemuan_ke=pertemuan, keterangan=ket)
|
|
messages.success(request, "Daftar Hadir berhasil ditambahkan.")
|
|
return redirect("daftar_hadir_list")
|
|
return render(request, "core/daftar_hadir_list.html", {"hadir_all": hadir_all, "jadwal_all": jadwal_all})
|
|
|
|
def daftar_hadir_delete(request, pk):
|
|
get_object_or_404(DaftarHadir, pk=pk).delete()
|
|
messages.success(request, "Daftar Hadir berhasil dihapus.")
|
|
return redirect("daftar_hadir_list")
|
|
|
|
# --- JADWAL ---
|
|
def jadwal_list(request):
|
|
jadwal_all = Jadwal.objects.all().order_by('hari', 'jam')
|
|
pengampu_all = DosenPengampu.objects.all()
|
|
ruangan_all = Ruangan.objects.all()
|
|
hari_all = Hari.objects.all()
|
|
jam_all = Jam.objects.all()
|
|
kelas_all = Kelas.objects.all()
|
|
|
|
if request.method == "POST":
|
|
if "delete_massal" in request.POST:
|
|
ids = request.POST.getlist("selected_ids")
|
|
Jadwal.objects.filter(id__in=ids).delete()
|
|
messages.success(request, f"Berhasil menghapus {len(ids)} Jadwal.")
|
|
else:
|
|
pk = request.POST.get("pk")
|
|
pengampu_id = request.POST.get("pengampu")
|
|
ruangan_id = request.POST.get("ruangan")
|
|
hari_id = request.POST.get("hari")
|
|
jam_id = request.POST.get("jam")
|
|
kelas_id = request.POST.get("kelas")
|
|
|
|
pengampu = get_object_or_404(DosenPengampu, id=pengampu_id)
|
|
ruangan = get_object_or_404(Ruangan, id=ruangan_id)
|
|
hari = get_object_or_404(Hari, id=hari_id)
|
|
jam = get_object_or_404(Jam, id=jam_id)
|
|
kelas = get_object_or_404(Kelas, id=kelas_id)
|
|
|
|
if pk:
|
|
obj = get_object_or_404(Jadwal, pk=pk)
|
|
obj.dosen_pengampu = pengampu
|
|
obj.ruangan = ruangan
|
|
obj.hari = hari
|
|
obj.jam = jam
|
|
obj.kelas = kelas
|
|
obj.save()
|
|
messages.success(request, "Jadwal berhasil diupdate.")
|
|
else:
|
|
Jadwal.objects.create(
|
|
dosen_pengampu=pengampu, ruangan=ruangan,
|
|
hari=hari, jam=jam, kelas=kelas, is_manual=True
|
|
)
|
|
messages.success(request, "Jadwal berhasil ditambahkan secara manual.")
|
|
return redirect("jadwal_list")
|
|
|
|
return render(request, "core/jadwal_list.html", {
|
|
"jadwal_all": jadwal_all,
|
|
"pengampu_all": pengampu_all,
|
|
"ruangan_all": ruangan_all,
|
|
"hari_all": hari_all,
|
|
"jam_all": jam_all,
|
|
"kelas_all": kelas_all,
|
|
})
|
|
|
|
def buat_jadwal(request):
|
|
if request.method == "POST":
|
|
pengampu_all = DosenPengampu.objects.all()
|
|
ruangan_all = Ruangan.objects.all()
|
|
hari_all = Hari.objects.all()
|
|
jam_all = Jam.objects.all()
|
|
|
|
if not (pengampu_all and ruangan_all and hari_all and jam_all):
|
|
messages.error(request, "Data Master belum lengkap.")
|
|
return redirect("buat_jadwal")
|
|
|
|
# Only delete schedules that were not manually created
|
|
Jadwal.objects.filter(is_manual=False).delete()
|
|
|
|
# Get pengampu that don't have a schedule yet (including manual ones)
|
|
pengampu_with_jadwal = Jadwal.objects.values_list('dosen_pengampu_id', flat=True)
|
|
pending_pengampu = pengampu_all.exclude(id__in=pengampu_with_jadwal)
|
|
|
|
for pengampu in pending_pengampu:
|
|
# We use the class assigned in DosenPengampu
|
|
kelas = pengampu.kelas
|
|
if not kelas:
|
|
# Fallback to random class if not assigned in Pengampu (for legacy data)
|
|
kelas_all = Kelas.objects.all()
|
|
kelas = random.choice(kelas_all) if kelas_all.exists() else None
|
|
|
|
if not kelas: continue
|
|
|
|
# Simple logic to find an available slot (avoiding collisions for manual ones)
|
|
# This is still a basic random generator but it now respects existing manual entries
|
|
max_tries = 50
|
|
for _ in range(max_tries):
|
|
h = random.choice(hari_all)
|
|
j = random.choice(jam_all)
|
|
r = random.choice(ruangan_all)
|
|
|
|
# Check for collisions in that room/time
|
|
if not Jadwal.objects.filter(hari=h, jam=j, ruangan=r).exists() and \
|
|
not Jadwal.objects.filter(hari=h, jam=j, kelas=kelas).exists() and \
|
|
not Jadwal.objects.filter(hari=h, jam=j, dosen_pengampu__dosen=pengampu.dosen).exists():
|
|
|
|
Jadwal.objects.create(
|
|
dosen_pengampu=pengampu,
|
|
ruangan=r,
|
|
hari=h,
|
|
jam=j,
|
|
kelas=kelas,
|
|
is_manual=False
|
|
)
|
|
break
|
|
|
|
messages.success(request, "Jadwal berhasil digenerate otomatis (menghindari jadwal manual).")
|
|
return redirect("jadwal_list")
|
|
return render(request, "core/buat_jadwal.html")
|
|
|
|
def jadwal_delete(request, pk):
|
|
get_object_or_404(Jadwal, pk=pk).delete()
|
|
messages.success(request, "Jadwal berhasil dihapus.")
|
|
return redirect("jadwal_list")
|
|
|
|
def jadwal_export_excel(request):
|
|
wb = Workbook()
|
|
ws = wb.active
|
|
ws.title = "Jadwal Kuliah"
|
|
|
|
headers = [
|
|
'No', 'Hari', 'Jam', 'Kode MK', 'Mata Kuliah', 'SKS', 'Semester',
|
|
'Dosen', 'Kelas', 'Ruangan', 'Program Studi', 'Tahun Akademik'
|
|
]
|
|
ws.append(headers)
|
|
|
|
jadwal_all = Jadwal.objects.all().select_related(
|
|
'hari', 'jam', 'dosen_pengampu__matkul', 'dosen_pengampu__dosen',
|
|
'kelas', 'ruangan', 'dosen_pengampu__matkul__prodi', 'dosen_pengampu__tahun_akademik'
|
|
).order_by('hari', 'jam')
|
|
|
|
for i, j in enumerate(jadwal_all, 1):
|
|
ws.append([
|
|
i,
|
|
j.hari.nama,
|
|
j.jam.range_waktu,
|
|
j.dosen_pengampu.matkul.kode,
|
|
j.dosen_pengampu.matkul.nama,
|
|
j.dosen_pengampu.matkul.sks,
|
|
j.dosen_pengampu.matkul.semester,
|
|
j.dosen_pengampu.dosen.nama,
|
|
j.kelas.nama,
|
|
j.ruangan.nama,
|
|
j.dosen_pengampu.matkul.prodi.nama,
|
|
j.dosen_pengampu.tahun_akademik.nama
|
|
])
|
|
|
|
response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
|
|
response['Content-Disposition'] = 'attachment; filename="jadwal_kuliah.xlsx"'
|
|
wb.save(response)
|
|
return response
|