# File: database.py (Versi Final untuk Supabase & Hugging Face) import os from dotenv import load_dotenv import pandas as pd from sqlalchemy import create_engine, MetaData, text # ----------------------------------------------------------------------------- # LANGKAH 1: SETUP KONEKSI DAN METADATA # ----------------------------------------------------------------------------- # Muat variabel dari file .env (penting untuk pengembangan lokal) load_dotenv() dotenv_path = os.path.join(os.path.dirname(__file__), '.env') print(f"Mencari file .env di lokasi: {dotenv_path}") if os.path.exists(dotenv_path): print("File .env DITEMUKAN!") load_dotenv(dotenv_path=dotenv_path) print("Isi DATABASE_URL setelah load:", os.getenv("DATABASE_URL")) else: print("PERINGATAN: File .env TIDAK DITEMUKAN di lokasi tersebut.") # Ambil URL koneksi dari environment variables (atau Hugging Face Secrets) DATABASE_URL = os.getenv("DATABASE_URL") if not DATABASE_URL: raise ValueError("DATABASE_URL tidak ditemukan. Pastikan sudah di-set di environment/secrets.") # Buat engine koneksi ke database PostgreSQL # echo=False bagus untuk produksi agar tidak menampilkan semua query di log engine = create_engine(DATABASE_URL, echo=False) # Buat objek metadata metadata = MetaData() # ----------------------------------------------------------------------------- # LANGKAH 2: REFLEKSI TABEL DARI DATABASE # ----------------------------------------------------------------------------- # Daripada mendefinisikan tabel manual, kita 'mencerminkan' skema # yang SUDAH ADA di database Supabase. Ini lebih aman dan fleksibel. try: print("Mencoba melakukan refleksi tabel dari database...") metadata.reflect(bind=engine) # Ambil referensi ke tabel yang sudah ada users = metadata.tables['users'] data_penyakit = metadata.tables['data_penyakit'] detail_penyakit = metadata.tables['detail_penyakit'] print("Refleksi tabel berhasil.") except Exception as e: print(f"Error saat melakukan refleksi tabel: {e}") print("Pastikan nama tabel (users, data_penyakit, detail_penyakit) sudah benar dan ada di database Supabase.") # Set ke None jika gagal agar aplikasi tidak crash saat di-import users, data_penyakit, detail_penyakit = None, None, None # ----------------------------------------------------------------------------- # LANGKAH 3: FUNGSI-FUNGSI HELPER (JIKA ADA) # ----------------------------------------------------------------------------- # Contoh: Fungsi untuk mengambil data (versi yang lebih aman) def ambil_data_penyakit(puskesmas, tahun): """ Mengambil data penyakit dari database berdasarkan filter dengan cara yang aman untuk mencegah SQL Injection. """ # Gunakan text() dan parameter binding (:nama_param) untuk keamanan query = text(""" SELECT * FROM detail_penyakit WHERE kode_pusk = :pusk AND tahun = :thn """) # Koneksi dibuka dan ditutup secara otomatis dengan 'with' with engine.connect() as conn: df = pd.read_sql(query, conn, params={"pusk": puskesmas, "thn": tahun}) # Logika kategori tetap sama def tentukan_kategori(jenis): if not isinstance(jenis, str): return 'Tidak Menular' menular_keywords = ['Infeksi', 'Demam', 'Diare', 'TBC', 'HIV'] return 'Menular' if any(keyword.lower() in jenis.lower() for keyword in menular_keywords) else 'Tidak Menular' if not df.empty: df['kategori'] = df['jenis_penyakit'].apply(tentukan_kategori) return df # ============================================================================== # SCRIPT UNTUK SETUP AWAL (TIDAK PERLU DIJALANKAN LAGI SETELAH TABEL DIBUAT) # ============================================================================== # Kode di bawah ini HANYA untuk membuat tabel di awal jika kamu mau. # Tapi karena kita sudah buat tabel di UI Supabase, blok ini sebenarnya # tidak perlu dijalankan. Saya tetap sertakan sebagai referensi. def create_tables_initial_setup(): print("PERINGATAN: Fungsi ini akan mencoba membuat tabel. Seharusnya tidak diperlukan jika tabel sudah dibuat di Supabase.") # Definisi manual tabel (hanya untuk fungsi ini) # ... (salin-tempel definisi Table(...) dari file SQLite-mu ke sini) ... # ... # Lalu panggil metadata.create_all(engine) pass # Jalankan 'python database.py' di terminal untuk memverifikasi koneksi if __name__ == "__main__": print("Memverifikasi koneksi dan refleksi tabel...") try: # 1. Verifikasi koneksi with engine.connect() as connection: print("=> Koneksi ke database Supabase BERHASIL!") # 2. Verifikasi hasil refleksi tabel # Cek apakah nama tabel ada di dalam kamus metadata.tables tabel_ditemukan = { 'users': 'users' in metadata.tables, 'data_penyakit': 'data_penyakit' in metadata.tables, 'detail_penyakit': 'detail_penyakit' in metadata.tables } semua_ditemukan = all(tabel_ditemukan.values()) if semua_ditemukan: print("=> Refleksi tabel BERHASIL: Semua tabel (users, data_penyakit, detail_penyakit) ditemukan.") else: print("=> PERINGATAN: Tidak semua tabel ditemukan!") for nama_tabel, status in tabel_ditemukan.items(): print(f" - Tabel '{nama_tabel}': {'Ditemukan' if status else 'TIDAK DITEMUKAN'}") print(" Pastikan nama tabel sudah benar sesuai di database Supabase.") except Exception as e: print(f"Verifikasi GAGAL: {e}")