458 lines
25 KiB
Python
458 lines
25 KiB
Python
"""
|
|
Model Database Baru - sesuai PRD Section 24
|
|
Hanya tabel baru (pekerjaan, kompetensi, clustering_result, dll)
|
|
"""
|
|
|
|
# Mengimpor modul Any untuk type hint fleksibel di Python
|
|
from typing import Any
|
|
# Mengimpor modul kolom dan tipe data dari SQLAlchemy: Column, Integer, String, DateTime, ForeignKey, Float, Boolean, Text
|
|
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Float, Boolean, Text
|
|
# Mengimpor relationship untuk relasi antar tabel ORM
|
|
from sqlalchemy.orm import relationship
|
|
# Mengimpor func untuk fungsi SQL bawaan seperti pengambilan waktu server
|
|
from sqlalchemy.sql import func
|
|
# Mengimpor kelas basis Declarative Base
|
|
from app.models.base import Base
|
|
|
|
|
|
# =========================================================================
|
|
# MODEL ENTITAS: PEKERJAAN (Tabel Pekerjaan Alumni)
|
|
# =========================================================================
|
|
class Pekerjaan(Base):
|
|
"""Tabel Pekerjaan - PRD Section 24: Menyimpan informasi spesifik profesi & tempat kerja alumni"""
|
|
# Nama tabel fisik di database MySQL
|
|
__tablename__ = "pekerjaan"
|
|
|
|
# Primary key identitas record pekerjaan bertipe integer
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
# Foreign key yang berelasi ke kolom id di tabel alumni (unique=True karena One-to-One dengan alumni)
|
|
alumni_id = Column(Integer, ForeignKey("alumni.id"), nullable=False, unique=True)
|
|
|
|
# Status pekerjaan saat ini: misal bekerja, belum_kerja, wiraswasta, melanjutkan_pendidikan
|
|
status_pekerjaan = Column(String(50)) # bekerja, belum_kerja, wiraswasta, dll
|
|
# Jenis institusi / perusahaan: BUMN, Swasta, Lembaga Pemerintah, Yayasan/Nirlaba
|
|
jenis_perusahaan = Column(String(100))
|
|
# Nama resmi perusahaan / kantor tempat alumni bekerja
|
|
nama_perusahaan = Column(String(255))
|
|
# Posisi / nama jabatan alumni di perusahaan (misal: Software Engineer, Data Analyst)
|
|
jabatan = Column(String(150))
|
|
# Skala tingkatan tempat kerja: Lokal / Tidak Berbadan Hukum, Nasional Berbadan Hukum, atau Multinasional/Internasional
|
|
tingkatan_tempat_kerja = Column(String(50))
|
|
# Lokasi provinsi tempat bekerja
|
|
provinsi = Column(String(100))
|
|
# Lokasi kabupaten / kota tempat bekerja
|
|
kabupaten_kota = Column(String(100))
|
|
# Teks gabungan (concatenation) dari posisi, perusahaan, dan deskripsi kerja yang digunakan sebagai korpus input TF-IDF dan Klastering
|
|
teks_pekerjaan = Column(Text) # Hasil concatenation untuk clustering
|
|
|
|
# Relasi ORM balik ke tabel Alumni (bidirectional relationship)
|
|
alumni = relationship("Alumni", back_populates="pekerjaan_detail")
|
|
|
|
# Waktu pembuatan record data pekerjaan
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
# Waktu update terakhir record data pekerjaan
|
|
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
|
|
|
|
|
# =========================================================================
|
|
# MODEL ENTITAS: KOMPETENSI (Tabel Nilai 7 Kelompok Kompetensi)
|
|
# =========================================================================
|
|
class Kompetensi(Base):
|
|
"""Tabel Kompetensi - PRD Section 24: Menyimpan penilaian 7 kompetensi saat lulus kuliah"""
|
|
# Nama tabel fisik di database MySQL
|
|
__tablename__ = "kompetensi"
|
|
|
|
# Primary key identitas record kompetensi bertipe integer
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
# Foreign key yang mengaitkan data kompetensi dengan alumni terkait (One-to-One)
|
|
alumni_id = Column(Integer, ForeignKey("alumni.id"), nullable=False, unique=True)
|
|
|
|
# 7 Kelompok Kompetensi (sesuai standar instrumen Tracer Study Dikti / PRD Section 9.4)
|
|
# 1. Penilaian etika, moral, dan integritas saat lulus
|
|
etika_lulus = Column(String(255))
|
|
# 2. Penilaian keahlian berdasarkan bidang ilmu spesifik (keahlian utama)
|
|
keahlian_lulus = Column(String(255))
|
|
# 3. Penilaian kecakapan penguasaan bahasa Inggris saat lulus
|
|
bahasa_inggris_lulus = Column(String(255))
|
|
# 4. Penilaian kemahiran penggunaan teknologi informasi & komputer
|
|
teknologi_informasi_lulus = Column(String(255))
|
|
# 5. Penilaian kemampuan komunikasi interpersonal dan presentasi
|
|
komunikasi_lulus = Column(String(255))
|
|
# 6. Penilaian kemampuan kerja sama dalam tim (teamwork)
|
|
kerja_sama_lulus = Column(String(255))
|
|
# 7. Penilaian komitmen pengembangan diri dan kemampuan belajar mandiri (lifelong learning)
|
|
pengembangan_diri_lulus = Column(String(255))
|
|
|
|
# Relasi ORM balik ke model Alumni
|
|
alumni = relationship("Alumni", back_populates="kompetensi")
|
|
|
|
# Waktu pembuatan record kompetensi
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
# Waktu pembaruan record kompetensi
|
|
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
|
|
|
|
|
# =========================================================================
|
|
# MODEL ENTITAS: CLUSTERING RESULT (Tabel Hasil Prediksi Klaster KMeans)
|
|
# =========================================================================
|
|
class ClusteringResult(Base):
|
|
"""Tabel Hasil Clustering - PRD Section 24: Menyimpan label klaster per alumni dari algoritma KMeans"""
|
|
# Nama tabel fisik hasil klastering
|
|
__tablename__ = "clustering_result"
|
|
|
|
# Primary key identitas hasil klastering
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
# Foreign key mengacu pada ID alumni yang diklasifikasikan
|
|
alumni_id = Column(Integer, ForeignKey("alumni.id"), nullable=False)
|
|
|
|
# Identifikasi versi model Machine Learning yang menghasilkan prediksi (misal: "kmeans_v1_2024")
|
|
model_version = Column(String(50))
|
|
# Jumlah klaster (k) yang digunakan saat pemodelan (misal: k=3 atau k=4)
|
|
k = Column(Integer, nullable=False) # Jumlah cluster
|
|
# Indeks cluster numerik hasil komputasi KMeans (0, 1, 2, dst.)
|
|
cluster = Column(Integer, nullable=False) # Cluster 0,1,2,3
|
|
# Label kategori klaster yang diformat (misal: 'C0', 'C1', 'C2', 'C3')
|
|
kategori = Column(String(5), nullable=False) # C0, C1, C2, C3
|
|
# Indikator kesesuaian antara bidang kerja alumni dengan profil lulusan prodi (True/False)
|
|
profile_match = Column(Boolean, default=False) # Apakah sesuai profil
|
|
# Kata kunci (keyword) yang cocok antara profil kompetensi alumni dan kamus kata kunci prodi
|
|
matched_keyword = Column(Text) # Keyword yang match
|
|
|
|
# Relasi ORM balik ke entitas Alumni
|
|
alumni = relationship("Alumni", back_populates="clustering_results")
|
|
|
|
# Waktu eksekusi dan pencatatan hasil klastering ke database
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
|
|
|
|
# =========================================================================
|
|
# MODEL ENTITAS: MODEL EVALUATION (Tabel Metrik Evaluasi Model ML)
|
|
# =========================================================================
|
|
class ModelEvaluation(Base):
|
|
"""Tabel Evaluasi Model - PRD Section 24: Menyimpan metrik evaluasi algoritma KMeans (Silhouette Score & Inertia/Elbow)"""
|
|
# Nama tabel riwayat evaluasi model
|
|
__tablename__ = "model_evaluation"
|
|
|
|
# Primary key identitas catatan evaluasi
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
# Kode versi model yang diuji
|
|
model_version = Column(String(50), nullable=False)
|
|
# Nilai hiperparameter k (jumlah cluster) yang diuji
|
|
k = Column(Integer, nullable=False)
|
|
# Nilai Inertia (Within-Cluster Sum of Squares) untuk analisis Elbow Method
|
|
inertia = Column(Float)
|
|
# Nilai Silhouette Coefficient (-1 hingga +1) untuk mengukur kerapatan dan pemisahan antar klaster
|
|
silhouette_score = Column(Float)
|
|
|
|
# Waktu pengujian model dijalankan dan dicatat
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
|
|
|
|
# =========================================================================
|
|
# MODEL ENTITAS: KEYWORD DICTIONARY (Tabel Kamus Kata Kunci Prodi)
|
|
# =========================================================================
|
|
class KeywordDictionary(Base):
|
|
"""Tabel Kamus Kata Kunci - PRD Section 24: Kosakata kompetensi/profesi acuan untuk pencocokan profil lulusan prodi"""
|
|
# Nama tabel kamus kata kunci
|
|
__tablename__ = "keyword_dictionary"
|
|
|
|
# Primary key identitas kata kunci
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
# Kode program studi target (contoh: 'TIF', 'MIF', 'TKK')
|
|
kode_prodi = Column(String(10), nullable=False) # TIF, MIF, TKK
|
|
# Kata kunci keahlian atau pekerjaan (contoh: "programmer", "network engineer", "database")
|
|
keyword = Column(String(100), nullable=False)
|
|
# Klasifikasi kata kunci: 'technical', 'softskill', 'role', dll.
|
|
kategori_keyword = Column(String(50)) # technical, softskill, dll
|
|
# Status apakah kata kunci ini aktif diikutsertakan dalam pencocokan profil lulusan
|
|
aktif = Column(Boolean, default=True)
|
|
|
|
# Waktu penambahan kata kunci ke dalam kamus
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
|
|
|
|
|
|
# =========================================================================
|
|
# MODEL ENTITAS: TRACER RESPONSE (Tabel Respon Lengkap Kuesioner Alumni)
|
|
# =========================================================================
|
|
class TracerResponse(Base):
|
|
"""
|
|
Tabel Respon Tracer Study - Menyimpan SEMUA kolom dari kuesioner tracer study
|
|
Sesuai dengan dokumen Pertanyaan-dan-jawaban.md dan format baku Tracer Study DIKTI
|
|
"""
|
|
# Nama tabel fisik di database MySQL
|
|
__tablename__ = "tracer_responses"
|
|
|
|
# Kolom ID utama entitas respon tracer study (Primary Key)
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
# Foreign key yang menghubungkan respon ke ID alumni (One-to-One, unik)
|
|
alumni_id = Column(Integer, ForeignKey("alumni.id"), nullable=False, unique=True)
|
|
# Kolom Nomor Induk Mahasiswa (NIM) alumni yang diindeks untuk pencarian cepat
|
|
nim: Any = Column(String(50), index=True)
|
|
|
|
# ===== SECTION 1: Identitas Diri (Extended) =====
|
|
# Kode resmi perguruan tinggi asal alumni (contoh: 005016 untuk Politeknik Negeri Jember)
|
|
kode_pt = Column(String(100)) # Kode Perguruan Tinggi
|
|
# Nomor Induk Kependudukan (NIK/KTP) alumni
|
|
nik = Column(String(50)) # NIK/No KTP
|
|
# Nomor Pokok Wajib Pajak (NPWP) alumni jika sudah memiliki
|
|
npwp = Column(String(50)) # NPWP
|
|
# Nomor telepon seluler / WhatsApp aktif alumni
|
|
telepon = Column(String(50)) # No HP/WhatsApp
|
|
# Alamat surat elektronik (email) aktif alumni
|
|
email = Column(String(255)) # Email
|
|
|
|
# ===== SECTION 2: Kuesioner Utama =====
|
|
# Status aktivitas alumni saat ini (F8: Bekerja, Wiraswasta, Belum Kerja, atau Studi Lanjut)
|
|
status_saat_ini = Column(String(255)) # F8: Bekerja/Wiraswasta/Belum/Melanjutkan
|
|
# Masa tunggu mendapatkan pekerjaan pertama dalam hitungan bulan (F502)
|
|
bulan_dapat_kerja = Column(Integer) # F502: 0-12 bulan sebelum/sesudah lulus
|
|
# Status apakah alumni memperoleh pekerjaan dalam kurun waktu <= 6 bulan setelah lulus (F504)
|
|
dapet_kerja_6_bulan = Column(String(255)) # F504: <=6 bulan (Ya/Tidak/kode)
|
|
# Rata-rata pendapatan atau take-home pay per bulan (F505)
|
|
rata_pendapatan = Column(Text) # F505: Gaji per bulan
|
|
# Jumlah bulan yang dibutuhkan untuk mendapatkan pekerjaan setelah resmi diwisuda (F506)
|
|
bulan_dapat_kerja_setelah = Column(Integer) # F506
|
|
|
|
# Lokasi kerja
|
|
# Provinsi wilayah tempat instansi / kantor alumni bekerja (F5a1)
|
|
provinsi_kerja = Column(String(100)) # F5a1
|
|
# Kabupaten atau kota wilayah tempat kantor alumni bekerja (F5a2)
|
|
kab_kota_kerja = Column(String(100)) # F5a2
|
|
|
|
# Info perusahaan
|
|
# Kategori status badan usaha instansi (F1101: Instansi pemerintah, BUMN, swasta, dll)
|
|
jenis_perusahaan_full = Column(String(255)) # F1101: Instansi pemerintah/swasta/BUMN/dll
|
|
# Jumlah total perusahaan yang dilamar atau rincian tambahan jika memilih opsi lainnya (F1102)
|
|
jumlah_perusahaan = Column(Text) # F1102 (dapat berupa teks panjang jika memilih lainnya)
|
|
# Nama resmi lembaga / instansi tempat alumni saat ini berkarir (F5b)
|
|
nama_perusahaan = Column(Text) # F5b
|
|
# Jabatan atau role posisi pekerjaan alumni (F5c: misal Backend Developer, Staff IT)
|
|
jabatan = Column(String(255)) # F5c
|
|
# Skala cakupan operasional tempat kerja (F5d: Lokal, Nasional, Multinasional/Internasional)
|
|
tingkatan_tempat_kerja = Column(String(255)) # F5d
|
|
|
|
# ===== SECTION 3: Studi Lanjut =====
|
|
# Sumber dana pembiayaan studi lanjut (F18a: Biaya Mandiri, Beasiswa LPDP, dll)
|
|
sumber_biaya_studi = Column(String(255)) # F18a: Biaya sendiri/Beasiswa
|
|
# Nama perguruan tinggi tujuan tempat melanjutkan jenjang studi berikutnya (F18b)
|
|
pt_studi_lanjut = Column(Text) # F18b: Nama PT
|
|
# Program studi yang diambil pada jenjang pendidikan lanjutan (F18c)
|
|
prodi_studi_lanjut = Column(Text) # F18c: Nama Prodi
|
|
# Tanggal atau semester resmi mulai perkuliahan studi lanjut (F18d)
|
|
tanggal_masuk_studi = Column(DateTime) # F18d: Tanggal masuk
|
|
|
|
# ===== SECTION 4: Pembiayaan Kuliah =====
|
|
# Sumber dana utama selama menempuh kuliah diploma/sarjana (F1201: Orang Tua, Bidikmisi, Beasiswa ADik)
|
|
sumber_biaya_kuliah = Column(String(255)) # F1201: Biaya sendiri/Beasiswa ADIK/BIDIKMISI/dll
|
|
|
|
# ===== SECTION 5: Kesesuaian Kerja =====
|
|
# Tingkat keeratan hubungan antara bidang keilmuan kuliah dengan pekerjaan (F14: Sangat Erat s.d. Tidak Sama Sekali)
|
|
keeratan_bidang_studi = Column(String(255)) # F14: Sangat Erat - Tidak sama sekali
|
|
# Tingkat kesesuaian strata pendidikan yang dipersyaratkan oleh posisi kerja (F15)
|
|
tingkat_pendidikan_tepat = Column(String(255)) # F15: Setingkat lebih tinggi - Tidak perlu
|
|
|
|
# ===== SECTION 6: Kompetensi SAAT LULUS (F1761-F1773) =====
|
|
# Penilaian penguasaan etika saat baru dinyatakan lulus (F1761)
|
|
etika_lulus_full = Column(String(255)) # F1761
|
|
# Penilaian keahlian bidang ilmu kompetensi inti saat lulus (F1763)
|
|
keahlian_lulus_full = Column(String(255)) # F1763
|
|
# Penilaian kemampuan bahasa Inggris saat lulus (F1765)
|
|
bahasa_inggris_lulus_full = Column(String(255)) # F1765
|
|
# Penilaian penguasaan teknologi informasi saat lulus (F1767)
|
|
teknologi_informasi_lulus_full = Column(String(255)) # F1767
|
|
# Penilaian kemampuan komunikasi verbal/tulisan saat lulus (F1769)
|
|
komunikasi_lulus_full = Column(String(255)) # F1769
|
|
# Penilaian kemampuan kerja sama tim saat lulus (F1771)
|
|
kerja_sama_lulus_full = Column(String(255)) # F1771
|
|
# Penilaian kesiapan pengembangan diri berkelanjutan saat lulus (F1773)
|
|
pengembangan_diri_lulus_full = Column(String(255)) # F1773
|
|
|
|
# ===== SECTION 7: Kompetensi SAAT INI (F1762-F1774) =====
|
|
# Tingkat kebutuhan kompetensi etika dalam pekerjaan saat ini (F1762)
|
|
etika_saat_ini = Column(String(255)) # F1762
|
|
# Tingkat kebutuhan keahlian bidang ilmu dalam pekerjaan saat ini (F1764)
|
|
keahlian_saat_ini = Column(String(255)) # F1764
|
|
# Tingkat kebutuhan bahasa Inggris dalam pekerjaan saat ini (F1766)
|
|
bahasa_inggris_saat_ini = Column(String(255)) # F1766
|
|
# Tingkat kebutuhan teknologi informasi dalam pekerjaan saat ini (F1768)
|
|
teknologi_informasi_saat_ini = Column(String(255)) # F1768
|
|
# Tingkat kebutuhan kemampuan komunikasi dalam pekerjaan saat ini (F1770)
|
|
komunikasi_saat_ini = Column(String(255)) # F1770
|
|
# Tingkat kebutuhan kerja sama tim dalam pekerjaan saat ini (F1772)
|
|
kerja_sama_saat_ini = Column(String(255)) # F1772
|
|
# Tingkat kebutuhan pengembangan diri dalam pekerjaan saat ini (F1774)
|
|
pengembangan_diri_saat_ini = Column(String(255)) # F1774
|
|
|
|
# ===== SECTION 8: Metode Pembelajaran (F21-F27) =====
|
|
# Efektivitas metode perkuliahan teori di kelas (F21)
|
|
metode_perkuliahan = Column(String(255)) # F21
|
|
# Efektivitas metode demonstrasi / peragaan materi kuliah (F22)
|
|
metode_demonstrasi = Column(String(255)) # F22
|
|
# Efektivitas metode pengerjaan proyek riset / tugas akhir (F23)
|
|
metode_proyek_riset = Column(String(255)) # F23
|
|
# Efektivitas pengalaman program magang / kerja praktik (F24)
|
|
metode_magang = Column(String(255)) # F24
|
|
# Efektivitas sesi praktikum di laboratorium komputer (F25)
|
|
metode_praktikum = Column(String(255)) # F25
|
|
# Efektivitas kegiatan kerja lapangan / PKL (F26)
|
|
metode_kerja_lapangan = Column(String(255)) # F26
|
|
# Efektivitas metode diskusi interaktif kelompok (F27)
|
|
metode_diskusi = Column(String(255)) # F27
|
|
|
|
# ===== SECTION 9: Waktu Mencari Kerja (F301-F303) =====
|
|
# Saat mulai mencari kerja (F301: Sebelum wisuda, Setelah wisuda, atau Tidak mencari kerja)
|
|
mulai_cari_kerja = Column(String(255)) # F301: Sebelum/Sesudah wisuda/Tidak
|
|
# Jumlah bulan mulai berburu lowongan kerja sebelum resmi diwisuda (F302)
|
|
bulan_cari_sebelum_lulus = Column(Integer) # F302: 0-12
|
|
# Jumlah bulan mulai berburu lowongan kerja setelah resmi diwisuda (F303)
|
|
bulan_cari_setelah_wisuda = Column(Integer) # F303: 0-12
|
|
|
|
# ===== SECTION 10: Cara Mencari Kerja (F401-F415) =====
|
|
# Mencari kerja melalui iklan lowongan koran/majalah (F401)
|
|
cari_iklan = Column(String(255)) # F401
|
|
# Melamar langsung ke perusahaan tanpa menunggu pengumuman lowongan (F402)
|
|
cari_melamar_tanpa_lowongan = Column(String(255)) # F402
|
|
# Mencari lowongan melalui job fair / bursa pameran kerja (F403)
|
|
cari_bursa_pameran = Column(String(255)) # F403
|
|
# Melamar kerja secara daring via portal internet / LinkedIn / Jobstreet (F404)
|
|
cari_internet = Column(String(255)) # F404
|
|
# Dihubungi langsung oleh perusahaan / headhunter (F405)
|
|
cari_dihubungi_perusahaan = Column(String(255)) # F405
|
|
# Menghubungi dinas tenaga kerja / Kemenakertrans (F406)
|
|
cari_kemenakertrans = Column(String(255)) # F406
|
|
# Menggunakan jasa agen penyalur tenaga kerja resmi (F407)
|
|
cari_agen_tenaga_kerja = Column(String(255)) # F407
|
|
# Memanfaatkan pusat pengembangan karir kampus (CDC Polije) (F408)
|
|
cari_pusat_karir = Column(String(255)) # F408
|
|
# Menghubungi unit kantor kemahasiswaan kampus (F409)
|
|
cari_kantor_mahasiswa = Column(String(255)) # F409
|
|
# Membangun jejaring profesional semasa masih berstatus mahasiswa (F410)
|
|
cari_jejaring = Column(String(255)) # F410
|
|
# Memperoleh informasi lowongan lewat relasi keluarga atau rekan (F411)
|
|
cari_relasi = Column(String(255)) # F411
|
|
# Merintis dan membangun badan usaha bisnis mandiri (F412)
|
|
cari_bangun_usaha = Column(String(255)) # F412
|
|
# Melanjutkan bekerja di institusi tempat pernah magang (F413)
|
|
cari_magang = Column(String(255)) # F413
|
|
# Bekerja di lingkungan institusi kampus tempat kuliah (F414)
|
|
cari_tempat_kuliah = Column(String(255)) # F414
|
|
# Saluran cara pencarian kerja lainnya (F415)
|
|
cari_lainnya = Column(Text) # F415
|
|
|
|
# ===== SECTION 11: Lamaran & Keaktifan (F6, F7, F7a, F1001) =====
|
|
# Jumlah total instansi/perusahaan yang pernah dikirimi surat lamaran kerja (F6)
|
|
jumlah_perusahaan_dilamar = Column(String(100)) # F6
|
|
# Jumlah perusahaan yang memberikan balasan respon atas surat lamaran (F7)
|
|
jumlah_perusahaan_merespons = Column(String(100)) # F7
|
|
# Jumlah perusahaan yang mengundang untuk tahapan wawancara/interview (F7a)
|
|
jumlah_perusahaan_wawancara = Column(String(100)) # F7a
|
|
# Status apakah aktif mencari pekerjaan dalam 4 minggu terakhir (F1001)
|
|
aktif_cari_kerja_4_minggu = Column(String(255)) # F1001: Ya/Tidak/Lainnya
|
|
|
|
# ===== SECTION 12: Kesesuaian Pekerjaan (F1601-F1614) =====
|
|
# Keterangan pekerjaan yang dijalani saat ini tidak sesuai dengan bidang studi (F1601)
|
|
kerja_tidak_sesuai_1 = Column(Text) # F1601
|
|
# Keterangan pekerjaan tidak memerlukan kualifikasi perguruan tinggi (F1602)
|
|
kerja_tidak_sesuai_2 = Column(Text) # F1602
|
|
# Alasan ketidaksesuaian 1: Pertimbangan faktor gaji atau pendapatan (F1603)
|
|
alasan_tidak_sesuai_1 = Column(Text) # F1603
|
|
# Alasan ketidaksesuaian 2: Faktor prospek karir dan jenjang promosi (F1604)
|
|
alasan_tidak_sesuai_2 = Column(Text) # F1604
|
|
# Alasan ketidaksesuaian 3: Pertimbangan keamanan kerja atau stabilitas (F1605)
|
|
alasan_tidak_sesuai_3 = Column(Text) # F1605
|
|
# Alasan ketidaksesuaian 4: Kesesuaian dengan minat dan bakat pribadi (F1606)
|
|
alasan_tidak_sesuai_4 = Column(Text) # F1606
|
|
# Alasan ketidaksesuaian 5: Pertimbangan kedekatan lokasi tempat tinggal (F1607)
|
|
alasan_tidak_sesuai_5 = Column(Text) # F1607
|
|
# Alasan ketidaksesuaian 6: Lingkungan suasana kerja yang nyaman (F1608)
|
|
alasan_tidak_sesuai_6 = Column(Text) # F1608
|
|
# Alasan ketidaksesuaian 7: Belum berhasil mendapat pekerjaan yang sesuai prodi (F1609)
|
|
alasan_tidak_sesuai_7 = Column(Text) # F1609
|
|
# Alasan ketidaksesuaian 8: Belum berencana mencari pekerjaan yang sesuai (F1610)
|
|
alasan_tidak_sesuai_8 = Column(Text) # F1610
|
|
# Alasan ketidaksesuaian 9: Pekerjaan saat ini dirasa cukup menarik (F1611)
|
|
alasan_tidak_sesuai_9 = Column(Text) # F1611
|
|
# Alasan ketidaksesuaian 10: Pengaruh pertimbangan keluarga (F1612)
|
|
alasan_tidak_sesuai_10 = Column(Text) # F1612
|
|
# Alasan ketidaksesuaian 11: Faktor lain yang tidak disebutkan (F1613)
|
|
alasan_tidak_sesuai_11 = Column(Text) # F1613
|
|
# Alasan ketidaksesuaian lainnya dalam uraian narasi bebas (F1614)
|
|
alasan_tidak_sesuai_lainnya = Column(Text) # F1614
|
|
|
|
# ===== Data Extra (untuk kolom dinamis yang tidak terduga) =====
|
|
# Kolom fleksibel berformat JSON text untuk menampung field tambahan dari kuesioner sewaktu-waktu
|
|
data_extra = Column(Text) # JSON untuk kolom tambahan
|
|
|
|
# Relasi ORM balik ke model Alumni (One-to-One)
|
|
alumni = relationship("Alumni", back_populates="tracer_response")
|
|
|
|
# Waktu saat alumni mengirimkan/menyimpan respon kuesioner tracer study
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
# Waktu saat alumni memperbarui data respon kuesioner tracer study
|
|
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
|
|
|
|
|
# =========================================================================
|
|
# MODEL ENTITAS: QUESTIONS (Tabel Master Butir Pertanyaan Kuesioner)
|
|
# =========================================================================
|
|
class Question(Base):
|
|
"""Tabel Questions - Simpan master pertanyaan instrumen tracer study secara dinamis"""
|
|
# Nama tabel master pertanyaan di database
|
|
__tablename__ = "questions"
|
|
|
|
# Primary key identitas pertanyaan bertipe integer
|
|
id: Any = Column(Integer, primary_key=True, index=True)
|
|
# Kode unik butir pertanyaan (contoh: "F8", "F502", "F1761")
|
|
kode: Any = Column(String(20), unique=True, nullable=False, index=True)
|
|
# Bunyi kalimat teks lengkap pertanyaan kuesioner
|
|
pertanyaan: Any = Column(Text, nullable=False)
|
|
# Tipe komponen input formulir: dropdown, pilihan, skala, teks, date, ya_tidak
|
|
tipe: Any = Column(String(20), default="pilihan") # dropdown, pilihan, skala, teks, date, ya_tidak
|
|
# Kategori bagian form instrumen kuesioner (misal: "Identitas", "Pekerjaan", "Kompetensi")
|
|
section: Any = Column(String(100), index=True)
|
|
# Urutan nomor urut tampilan form di antarmuka frontend
|
|
nomor_form: Any = Column(Integer, default=0)
|
|
# Tahun berlakunya instrumen pertanyaan (default: "all" untuk berlaku di semua tahun angkatan)
|
|
tahun: Any = Column(String(20), default="all")
|
|
# Status keaktifan butir pertanyaan (True = ditampilkan di frontend, False = diarsipkan)
|
|
is_active: Any = Column(Boolean, default=True)
|
|
|
|
# Relasi One-to-Many ke tabel AnswerOption (jika tipe pertanyaan memiliki opsi pilihan berganda)
|
|
# cascade="all, delete-orphan": Jika pertanyaan dihapus, seluruh opsi jawabannya otomatis ikut terhapus
|
|
options = relationship("AnswerOption", back_populates="question", cascade="all, delete-orphan")
|
|
|
|
# Waktu penambahan pertanyaan ke sistem
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
# Waktu pembaruan teks atau konfigurasi pertanyaan
|
|
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
|
|
|
|
|
# =========================================================================
|
|
# MODEL ENTITAS: ANSWER OPTIONS (Tabel Master Pilihan Jawaban Kuesioner)
|
|
# =========================================================================
|
|
class AnswerOption(Base):
|
|
"""Tabel Answer Options - Simpan pilihan jawaban opsi berganda untuk setiap butir pertanyaan"""
|
|
# Nama tabel master opsi jawaban di database
|
|
__tablename__ = "answer_options"
|
|
|
|
# Primary key identitas opsi jawaban bertipe integer
|
|
id: Any = Column(Integer, primary_key=True, index=True)
|
|
# Foreign key yang mengaitkan opsi ini ke ID pertanyaan di tabel questions
|
|
question_id: Any = Column(Integer, ForeignKey("questions.id", ondelete="CASCADE"), nullable=False, index=True)
|
|
# Nilai value atau kode jawaban yang disimpan ke database saat dipilih (contoh: "1", "2", "Ya", "Tidak")
|
|
kode: Any = Column(String(50), nullable=False, index=True) # Kode jawaban: 1, 2, 3, atau "1", "Ya", dll
|
|
# Label teks deskripsi jawaban yang ditampilkan kepada pengguna di antarmuka web
|
|
teks: Any = Column(Text, nullable=False) # Teks jawaban
|
|
# Nomor urut posisi urutan opsi jawaban dalam pilihan radio button atau dropdown
|
|
urutan: Any = Column(Integer, default=0)
|
|
# Status keaktifan opsi jawaban (True = aktif dapat dipilih)
|
|
is_active: Any = Column(Boolean, default=True)
|
|
|
|
# Relasi ORM balik ke tabel Question
|
|
question = relationship("Question", back_populates="options")
|
|
|
|
# Waktu pembuatan opsi jawaban
|
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
|