commit ec2e09b84e4bd28044aa36fd91359562228224ba Author: matthewflrnt Date: Wed Oct 14 21:10:10 2026 +0700 initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..1670c5f --- /dev/null +++ b/README.md @@ -0,0 +1,160 @@ +# 🏥 Sistem Informasi Rumah Sakit Jaya Abadi (OOP Implementation) + +Program CLI interaktif berbasis Python yang mengimplementasikan konsep dasar **Object-Oriented Programming (OOP)** untuk pengelolaan alur operasional rumah sakit, mulai dari pendaftaran pasien, penjadwalan janji temu, pemeriksaan dokter, tindakan keperawatan, hingga pencatatan rekam medis. + +--- + +## 📌 Penerapan Konsep OOP + +### 1. Pewarisan (Inheritance) +* **Superclass**: `Employee` + * Menyimpan atribut umum pegawai (`employee_id`, `name`, `age`, `position`, `status`, `birth_date`, `hourly_salary`) dan method dasar (`total_salary()`, `display_info()`, `info_company()`). +* **Subclass**: + 1. `Receptionist`: Menangani registrasi pasien dan pengaturan jadwal temu dengan dokter. + 2. `Doctor`: Melakukan diagnosis, memberikan resep obat, dan mengatur jadwal praktek. + 3. `Nurse`: Melakukan pemeriksaan awal fisik, pemberian obat sesuai resep, dan pembaruan rekam medis. + +--- + +### 2. Enkapsulasi (Encapsulation) +Semua atribut internal pada class `Pasien`, `Employee`, dan `Doctor` dijadikan **private** (menggunakan prefix `__`) untuk melindungi integritas data. Akses data dikontrol menggunakan dekorator `@property` (Getter) dan `@.setter` (Setter): +* Validasi nilai numerik (seperti umur dan gaji tidak boleh negatif). +* Menjaga keamanan data sensitif rekam medis pasien. + +--- + +### 3. Polimorfisme & Method Overriding +Method dari Superclass di-override oleh Subclass sesuai kebutuhan spesifik: +* **`total_salary()` pada `Doctor`**: Meng-override perhitungan gaji dasar `Employee` dengan menambahkan tunjangan spesialis medis (`__tunjangan_spesialis`). +* **`display_info()` pada Seluruh Subclass**: Menyesuaikan tampilan informasi sesuai peran dan spesialisasi masing-masing entitas pegawai (`Receptionist`, `Doctor`, `Nurse`). + +--- + +## 🏗️ Diagram Kelas (Class Diagram) + +```mermaid +classDiagram + class Pasien { + -str __nama + -str __id_pasien + -str __birth_date + -str __alamat + -str __telp + -str __keluhan + -bool __bpjs + -int __no_antrian + -str __dokter + -str __diagnosis + -str __resep + -str __obat + -str __dosis + -str __catatan + -str __status + +get_info() + +get_rekam_medis() + } + + class Employee { + +str company$ + +int total_employee$ + +int working_hours + -str __employee_id + -str __name + -int __age + -str __position + -str __status + -str __birth_date + -int __hourly_salary + +total_salary() int + +display_info() + +info_company()$ + } + + class Receptionist { + +int antrian_counter$ + +display_info() + +register_patient(pasien) + +manage_appointment(pasien, dokter, waktu) + } + + class Doctor { + -int __tunjangan_spesialis + +total_salary() int + +display_info() + +diagnose_patient(pasien, diagnosis, resep) + +set_schedule(hari, jam_mulai, jam_selesai) + } + + class Nurse { + +display_info() + +examine_patient(pasien) + +give_medicine(pasien, obat, dosis) + +update_medical_record(pasien, catatan) + } + + Employee <|-- Receptionist : Mewarisi + Employee <|-- Doctor : Mewarisi + Employee <|-- Nurse : Mewarisi + Receptionist ..> Pasien : Mendaftarkan + Doctor ..> Pasien : Mendiagnosis + Nurse ..> Pasien : Merawat +``` + +--- + +## ⚙️ Fitur dan Alur Sistem + +1. **Menu Pasien**: + * Registrasi data diri pasien baru. + * Melihat daftar semua pasien. + * Melihat detail informasi profil pasien. + * Memeriksa riwayat rekam medis lengkap. +2. **Menu Receptionist**: + * Melihat info & data receptionist. + * Mendaftarkan pasien & menerbitkan nomor antrean. + * Menjadwalkan janji temu pasien dengan dokter spesialis. +3. **Menu Dokter**: + * Melihat info & jadwal dokter. + * Melakukan pemeriksaan, penetapan diagnosis, dan peresepan obat. + * Menetapkan jadwal praktek klinik dokter. +4. **Menu Perawat**: + * Melihat info tenaga perawat. + * Melakukan pemeriksaan awal (vital sign/kondisi fisik). + * Memberikan obat kepada pasien sesuai resep dokter. + * Memperbarui catatan akhir pada rekam medis pasien. +5. **Info Perusahaan**: + * Menampilkan informasi umum instansi rumah sakit dan total pegawai aktif. + +--- + +## 🚀 Cara Menjalankan Program + +Pastikan Python 3 telah terpasang di sistem Anda. + +1. Buka terminal pada folder proyek: + ```bash + cd /home/matthewflrnt/study-archived/semester-3/oop-task/oop-rumahsakit + ``` +2. Jalankan script utama: + ```bash + python3 main.py + ``` + +--- + +## 📝 Ringkasan Jawaban Tugas OOP + +1. **Pewarisan Superclass & Subclass**: + * **Superclass**: `Employee` + * **Subclass**: `Receptionist`, `Doctor`, `Nurse` +2. **Atribut dan Method Spesifik**: + * Diturunkan dari Superclass: `employee_id`, `name`, `age`, `position`, `status`, `birth_date`, `hourly_salary`, method `total_salary()`, dan `display_info()`. + * Khusus Subclass: + * `Receptionist`: `register_patient()`, `manage_appointment()` + * `Doctor`: `__tunjangan_spesialis`, `diagnose_patient()`, `set_schedule()` + * `Nurse`: `examine_patient()`, `give_medicine()`, `update_medical_record()` +3. **Penerapan Method Overriding**: + * `Doctor.total_salary()` meng-override perhitungan gaji dasar untuk menambahkan tunjangan spesialis. + * `Receptionist.display_info()`, `Doctor.display_info()`, dan `Nurse.display_info()` meng-override method cetak info untuk menampilkan detail peran masing-masing. +4. **Enkapsulasi**: + * Semua variabel instance private (`__attribute`) dengan getter dan setter menggunakan properti `@property`. diff --git a/__pycache__/main.cpython-314.pyc b/__pycache__/main.cpython-314.pyc new file mode 100644 index 0000000..35ec81c Binary files /dev/null and b/__pycache__/main.cpython-314.pyc differ diff --git a/individu.py b/individu.py new file mode 100644 index 0000000..fef99dc --- /dev/null +++ b/individu.py @@ -0,0 +1,71 @@ +class Karyawan: + def __init__(self, id_karyawan, nama, gaji_pokok): + self.id_karyawan = id_karyawan + self.nama = nama + self.gaji_pokok = gaji_pokok + + def hitung_total_gaji(self): + return self.gaji_pokok + + +class KaryawanTetap(Karyawan): + def __init__(self, id_karyawan, nama, gaji_pokok, tunjangan): + super().__init__(id_karyawan, nama, gaji_pokok) + self.tunjangan = tunjangan + + # Method overriding + def hitung_total_gaji(self): + return self.gaji_pokok + self.tunjangan + + def tampilkan_data(self): + print("=== KARYAWAN TETAP ===") + print(f"ID Karyawan : {self.id_karyawan}") + print(f"Nama : {self.nama}") + print(f"Gaji Pokok : Rp{self.gaji_pokok:,}") + print(f"Tunjangan : Rp{self.tunjangan:,}") + print(f"Total Gaji : Rp{self.hitung_total_gaji():,}") + + +class KaryawanKontrak(Karyawan): + def __init__(self, id_karyawan, nama, gaji_pokok, hari_kerja, upah_harian): + super().__init__(id_karyawan, nama, gaji_pokok) + self.hari_kerja = hari_kerja + self.upah_harian = upah_harian + + # Method overriding + def hitung_total_gaji(self): + return self.gaji_pokok + (self.hari_kerja * self.upah_harian) + + def tampilkan_data(self): + print("=== KARYAWAN KONTRAK ===") + print(f"ID Karyawan : {self.id_karyawan}") + print(f"Nama : {self.nama}") + print(f"Gaji Pokok : Rp{self.gaji_pokok:,}") + print(f"Hari Kerja : {self.hari_kerja} hari") + print(f"Upah Harian : Rp{self.upah_harian:,}") + print(f"Total Gaji : Rp{self.hitung_total_gaji():,}") + + +# Membuat object Karyawan Tetap +karyawan_tetap = KaryawanTetap( + "T001", + "Budi Santoso", + 5_000_000, + 1_500_000 +) + +# Membuat object Karyawan Kontrak +karyawan_kontrak = KaryawanKontrak( + "K002", + "Siti Aminah", + 2_000_000, + 20, + 100_000 +) + +# Menampilkan data +karyawan_tetap.tampilkan_data() + +print() + +karyawan_kontrak.tampilkan_data() \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..7d6a918 --- /dev/null +++ b/main.py @@ -0,0 +1,796 @@ +# ============================================================ +# SISTEM INFORMASI RUMAH SAKIT JAYA ABADI +# Interactive Terminal Program (OOP Implementation) +# ============================================================ + + +# ───────────────────────────────────────────── +# CLASS: Pasien (Encapsulated) +# ───────────────────────────────────────────── +class Pasien: + jumlah_pasien = 0 + + def __init__(self, nama, tanggal_lahir, id_pasien, alamat, no_telepon, keluhan): + Pasien.jumlah_pasien += 1 + # Atribut private (Enkapsulasi) + self.__nama = nama + self.__id_pasien = id_pasien + self.__birth_date = tanggal_lahir + self.__alamat = alamat + self.__telp = no_telepon + self.__keluhan = keluhan + self.__bpjs = False + self.__no_antrian = None + self.__dokter = None + self.__diagnosis = None + self.__resep = None + self.__obat = None + self.__dosis = None + self.__catatan = None + self.__status = "Belum Daftar" + + # --- GETTER & SETTER (Properties) --- + @property + def nama(self): + return self.__nama + + @nama.setter + def nama(self, value): + self.__nama = value + + @property + def id_pasien(self): + return self.__id_pasien + + @property + def birth_date(self): + return self.__birth_date + + @birth_date.setter + def birth_date(self, value): + self.__birth_date = value + + @property + def alamat(self): + return self.__alamat + + @alamat.setter + def alamat(self, value): + self.__alamat = value + + @property + def telp(self): + return self.__telp + + @telp.setter + def telp(self, value): + self.__telp = value + + @property + def keluhan(self): + return self.__keluhan + + @keluhan.setter + def keluhan(self, value): + self.__keluhan = value + + @property + def bpjs(self): + return self.__bpjs + + @bpjs.setter + def bpjs(self, value): + self.__bpjs = bool(value) + + @property + def no_antrian(self): + return self.__no_antrian + + @no_antrian.setter + def no_antrian(self, value): + self.__no_antrian = value + + @property + def dokter(self): + return self.__dokter + + @dokter.setter + def dokter(self, value): + self.__dokter = value + + @property + def diagnosis(self): + return self.__diagnosis + + @diagnosis.setter + def diagnosis(self, value): + self.__diagnosis = value + + @property + def resep(self): + return self.__resep + + @resep.setter + def resep(self, value): + self.__resep = value + + @property + def obat(self): + return self.__obat + + @obat.setter + def obat(self, value): + self.__obat = value + + @property + def dosis(self): + return self.__dosis + + @dosis.setter + def dosis(self, value): + self.__dosis = value + + @property + def catatan(self): + return self.__catatan + + @catatan.setter + def catatan(self, value): + self.__catatan = value + + @property + def status(self): + return self.__status + + @status.setter + def status(self, value): + self.__status = value + + def get_info(self): + print(f" │ Nama : {self.nama}") + print(f" │ ID : {self.id_pasien}") + print(f" │ Tgl Lahir : {self.birth_date}") + print(f" │ Alamat : {self.alamat}") + print(f" │ No. Telp : {self.telp}") + print(f" │ Keluhan : {self.keluhan}") + print(f" │ BPJS : {'Ya' if self.bpjs else 'Tidak'}") + print(f" │ Status : {self.status}") + + def get_rekam_medis(self): + print(f" ┌{'─' * 40}") + print(f" │ REKAM MEDIS — {self.nama}") + print(f" ├{'─' * 40}") + print(f" │ ID Pasien : {self.id_pasien}") + print(f" │ Keluhan : {self.keluhan}") + if self.no_antrian: + print(f" │ No. Antrian : {self.no_antrian}") + if self.dokter: + print(f" │ Dokter : {self.dokter}") + if self.diagnosis: + print(f" │ Diagnosis : {self.diagnosis}") + if self.resep: + print(f" │ Resep : {self.resep}") + if self.obat: + print(f" │ Obat : {self.obat}") + if self.dosis: + print(f" │ Dosis : {self.dosis}") + if self.catatan: + print(f" │ Catatan : {self.catatan}") + print(f" │ Status : {self.status}") + print(f" └{'─' * 40}") + + +# ───────────────────────────────────────────── +# SUPERCLASS: Employee (Base Class with Encapsulation) +# ───────────────────────────────────────────── +class Employee: + company = "Rumah Sakit Jaya Abadi" + total_employee = 0 + working_hours = 8 + + def __init__(self, employee_id, name, age, position, status, birth_date, hourly_salary): + # Atribut private (Enkapsulasi) + self.__employee_id = employee_id + self.__name = name + self.__age = age + self.__position = position + self.__status = status + self.__birth_date = birth_date + self.__hourly_salary = hourly_salary + Employee.total_employee += 1 + + # --- GETTER & SETTER (Properties) --- + @property + def employee_id(self): + return self.__employee_id + + @property + def name(self): + return self.__name + + @name.setter + def name(self, value): + self.__name = value + + @property + def age(self): + return self.__age + + @age.setter + def age(self, value): + if value > 0: + self.__age = value + + @property + def position(self): + return self.__position + + @position.setter + def position(self, value): + self.__position = value + + @property + def status(self): + return self.__status + + @status.setter + def status(self, value): + self.__status = value + + @property + def birth_date(self): + return self.__birth_date + + @birth_date.setter + def birth_date(self, value): + self.__birth_date = value + + @property + def hourly_salary(self): + return self.__hourly_salary + + @hourly_salary.setter + def hourly_salary(self, value): + if value >= 0: + self.__hourly_salary = value + + def total_salary(self): + return self.__hourly_salary * self.working_hours + + @staticmethod + def info_company(): + print(f" ┌{'─' * 40}") + print(f" │ INFO PERUSAHAAN") + print(f" ├{'─' * 40}") + print(f" │ Nama RS : {Employee.company}") + print(f" │ Total Staff : {Employee.total_employee}") + print(f" └{'─' * 40}") + + def display_info(self): + """Method umum untuk menampilkan informasi dasar pegawai""" + print(f" ┌{'─' * 40}") + print(f" │ {self.name}") + print(f" ├{'─' * 40}") + print(f" │ ID : {self.employee_id}") + print(f" │ Umur : {self.age} tahun") + print(f" │ Posisi : {self.position}") + print(f" │ Status : {self.status}") + print(f" │ Tgl Lahir : {self.birth_date}") + print(f" │ Gaji/Jam : Rp {self.hourly_salary:,}") + print(f" │ Jam Kerja : {self.working_hours} jam") + print(f" │ Total Gaji : Rp {self.total_salary():,}") + print(f" │ Perusahaan : {self.company}") + print(f" └{'─' * 40}") + + +# ───────────────────────────────────────────── +# SUBCLASS 1: Receptionist (Mewarisi Employee) +# ───────────────────────────────────────────── +class Receptionist(Employee): + antrian_counter = 0 + + def __init__(self, employee_id, name, age, position, status, birth_date, hourly_salary): + super().__init__(employee_id, name, age, position, status, birth_date, hourly_salary) + + # --- METHOD OVERRIDING --- + def display_info(self): + """Override method display_info dari Superclass Employee""" + super().display_info() + print(f" │ [Peran Khusus] : Front Office & Pendaftaran Pasien") + print(f" └{'─' * 40}") + + # --- METHOD KHUSUS SUBCLASS --- + def register_patient(self, pasien): + Receptionist.antrian_counter += 1 + pasien.no_antrian = Receptionist.antrian_counter + pasien.status = "Terdaftar" + print(f"\n ┌{'─' * 40}") + print(f" │ PENDAFTARAN BERHASIL") + print(f" ├{'─' * 40}") + print(f" │ No. Antrian : {pasien.no_antrian}") + print(f" │ Pasien : {pasien.nama}") + print(f" │ Keluhan : {pasien.keluhan}") + print(f" │ BPJS : {'Ya' if pasien.bpjs else 'Tidak'}") + print(f" │ Receptionist : {self.name}") + print(f" └{'─' * 40}") + + def manage_appointment(self, pasien, dokter, waktu): + pasien.dokter = dokter.name + pasien.status = "Menunggu Pemeriksaan" + print(f"\n ┌{'─' * 40}") + print(f" │ JANJI TEMU DIBUAT") + print(f" ├{'─' * 40}") + print(f" │ Pasien : {pasien.nama}") + print(f" │ Dokter : {dokter.name}") + print(f" │ Spesialisasi : {dokter.position}") + print(f" │ Waktu : {waktu}") + print(f" │ Receptionist : {self.name}") + print(f" └{'─' * 40}") + + +# ───────────────────────────────────────────── +# SUBCLASS 2: Doctor (Mewarisi Employee) +# ───────────────────────────────────────────── +class Doctor(Employee): + def __init__(self, employee_id, name, age, position, status, birth_date, hourly_salary, tunjangan_spesialis=500000): + super().__init__(employee_id, name, age, position, status, birth_date, hourly_salary) + # Atribut khusus Doctor (Enkapsulasi) + self.__tunjangan_spesialis = tunjangan_spesialis + + @property + def tunjangan_spesialis(self): + return self.__tunjangan_spesialis + + # --- METHOD OVERRIDING --- + def total_salary(self): + """Override kalkulasi gaji: Gaji Pokok + Tunjangan Spesialis Dokter""" + base_salary = super().total_salary() + return base_salary + self.__tunjangan_spesialis + + def display_info(self): + """Override method display_info dari Superclass Employee""" + print(f" ┌{'─' * 40}") + print(f" │ DOKTER SPESIALIS: {self.name}") + print(f" ├{'─' * 40}") + print(f" │ ID Dokter : {self.employee_id}") + print(f" │ Umur : {self.age} tahun") + print(f" │ Spesialisasi : {self.position}") + print(f" │ Status : {self.status}") + print(f" │ Tgl Lahir : {self.birth_date}") + print(f" │ Gaji Pokok : Rp {super().total_salary():,}") + print(f" │ Tunj. Medis : Rp {self.__tunjangan_spesialis:,}") + print(f" │ Total Gaji : Rp {self.total_salary():,}") + print(f" │ Rumah Sakit : {self.company}") + print(f" └{'─' * 40}") + + # --- METHOD KHUSUS SUBCLASS --- + def diagnose_patient(self, pasien, diagnosis, resep): + pasien.dokter = self.name + pasien.diagnosis = diagnosis + pasien.resep = resep + pasien.status = "Sudah Didiagnosis" + print(f"\n ┌{'─' * 40}") + print(f" │ HASIL DIAGNOSIS") + print(f" ├{'─' * 40}") + print(f" │ Pasien : {pasien.nama}") + print(f" │ Keluhan : {pasien.keluhan}") + print(f" │ Diagnosis : {diagnosis}") + print(f" │ Resep : {resep}") + print(f" │ Dokter : {self.name}") + print(f" └{'─' * 40}") + + def set_schedule(self, hari, jam_mulai, jam_selesai): + print(f"\n ┌{'─' * 40}") + print(f" │ JADWAL PRAKTEK DOKTER") + print(f" ├{'─' * 40}") + print(f" │ Dokter : {self.name}") + print(f" │ Spesialisasi : {self.position}") + print(f" │ Hari : {hari}") + print(f" │ Jam : {jam_mulai} - {jam_selesai}") + print(f" └{'─' * 40}") + + +# ───────────────────────────────────────────── +# SUBCLASS 3: Nurse (Mewarisi Employee) +# ───────────────────────────────────────────── +class Nurse(Employee): + def __init__(self, employee_id, name, age, position, status, birth_date, hourly_salary): + super().__init__(employee_id, name, age, position, status, birth_date, hourly_salary) + + # --- METHOD OVERRIDING --- + def display_info(self): + """Override method display_info dari Superclass Employee""" + super().display_info() + print(f" │ [Unit/Ruangan] : {self.position}") + print(f" └{'─' * 40}") + + # --- METHOD KHUSUS SUBCLASS --- + def examine_patient(self, pasien): + pasien.status = "Sedang Diperiksa Perawat" + print(f"\n ┌{'─' * 40}") + print(f" │ PEMERIKSAAN AWAL") + print(f" ├{'─' * 40}") + print(f" │ Pasien : {pasien.nama}") + print(f" │ Keluhan : {pasien.keluhan}") + print(f" │ Perawat : {self.name}") + print(f" │ Unit/Ruangan : {self.position}") + print(f" └{'─' * 40}") + + def give_medicine(self, pasien, obat, dosis): + pasien.obat = obat + pasien.dosis = dosis + pasien.status = "Obat Diberikan" + print(f"\n ┌{'─' * 40}") + print(f" │ PEMBERIAN OBAT") + print(f" ├{'─' * 40}") + print(f" │ Pasien : {pasien.nama}") + print(f" │ Diagnosis : {pasien.diagnosis}") + print(f" │ Obat : {obat}") + print(f" │ Dosis : {dosis}") + print(f" │ Perawat : {self.name}") + print(f" └{'─' * 40}") + + def update_medical_record(self, pasien, catatan): + pasien.catatan = catatan + pasien.status = "Selesai" + print(f"\n ┌{'─' * 40}") + print(f" │ REKAM MEDIS DIPERBARUI") + print(f" ├{'─' * 40}") + print(f" │ Pasien : {pasien.nama}") + print(f" │ Diagnosis : {pasien.diagnosis}") + print(f" │ Resep : {pasien.resep}") + print(f" │ Obat : {pasien.obat}") + print(f" │ Catatan : {catatan}") + print(f" │ Diupdate oleh: {self.name}") + print(f" │ Status : {pasien.status}") + print(f" └{'─' * 40}") + + +# ───────────────────────────────────────────── +# DATA AWAL +# ───────────────────────────────────────────── +receptionists = [ + Receptionist("EMP001", "Matthew", 20, "Receptionist", "permanent", "2006-05-10", 200000), + Receptionist("EMP002", "Budi", 22, "Receptionist", "internship", "2004-03-15", 150000), +] + +doctors = [ + Doctor("EMP003", "Dr. Andi", 35, "Cardiologist", "permanent", "1991-08-20", 500000, 750000), + Doctor("EMP004", "Dr. Sinta", 30, "Dermatologist", "permanent", "1996-03-11", 450000, 500000), +] + +nurses = [ + Nurse("PRW-101", "Ns. Siti Aminah, S.Kep", 28, "IGD", "permanent", "1998-04-12", 180000), + Nurse("PRW-102", "Budi Santoso, Amd.Kep", 30, "Bangsal Anak (Melati)", "permanent", "1996-07-23", 160000), + Nurse("PRW-103", "Rina Wijaya, S.Kep", 27, "ICU", "permanent", "1999-01-05", 190000), +] + +patients = [ + Pasien("Bejo", "16/06/2006", "PSN-001", "Simo Kwagean", "085816261843", "Kanker Kulit"), + Pasien("Putri", "17/06/2006", "PSN-002", "Kalijudan", "085816261843", "Kanker Otak"), +] +patient_counter = 2 + + +# ───────────────────────────────────────────── +# HELPER +# ───────────────────────────────────────────── +def header(title): + print(f"\n ╔{'═' * 42}╗") + print(f" ║ {title:^38} ║") + print(f" ╚{'═' * 42}╝") + +def divider(): + print(f"\n {'─' * 44}\n") + +def pilih_dari_list(items, label, attr="nama"): + if not items: + print(f" ⚠ Belum ada {label}.") + return None + print(f"\n Pilih {label}:") + for i, item in enumerate(items, 1): + name = getattr(item, attr, None) or getattr(item, "name", "?") + extra = "" + if hasattr(item, "position"): + extra = f" — {item.position}" + elif hasattr(item, "keluhan"): + extra = f" — {item.keluhan} [{item.status}]" + print(f" {i}. {name}{extra}") + try: + idx = int(input(f"\n Nomor {label} > ")) - 1 + if 0 <= idx < len(items): + return items[idx] + print(" ✗ Nomor tidak valid.") + except ValueError: + print(" ✗ Input harus angka.") + return None + +def pilih_pasien(): + return pilih_dari_list(patients, "Pasien", "nama") + +def pilih_pasien_terdaftar(): + terdaftar = [p for p in patients if p.status != "Belum Daftar"] + if not terdaftar: + print(" ⚠ Belum ada pasien yang terdaftar.") + return None + return pilih_dari_list(terdaftar, "Pasien", "nama") + +def lanjut(): + input("\n Tekan Enter untuk kembali...") + + +# ───────────────────────────────────────────── +# 1. MENU PASIEN +# ───────────────────────────────────────────── +def menu_pasien(): + global patient_counter + while True: + header("MENU PASIEN") + print(" 1. Daftarkan diri (Registrasi)") + print(" 2. Lihat semua pasien") + print(" 3. Lihat info pasien") + print(" 4. Cek rekam medis") + print(" 0. Kembali") + pilihan = input("\n > ") + + if pilihan == "1": + header("REGISTRASI PASIEN BARU") + nama = input(" Nama lengkap : ") + tgl = input(" Tanggal lahir (DD/MM/YYYY) : ") + alamat = input(" Alamat : ") + telp = input(" No. Telepon : ") + keluhan = input(" Keluhan : ") + bpjs = input(" Punya BPJS? (y/n) : ").strip().lower() == "y" + + patient_counter += 1 + id_p = f"PSN-{patient_counter:03d}" + p = Pasien(nama, tgl, id_p, alamat, telp, keluhan) + p.bpjs = bpjs + patients.append(p) + print(f"\n ✓ Registrasi berhasil! ID Anda: {id_p}") + print(f" Silakan menuju Receptionist untuk pendaftaran.") + lanjut() + + elif pilihan == "2": + header("DAFTAR SEMUA PASIEN") + if not patients: + print(" Belum ada pasien.") + else: + print(f" Total: {Pasien.jumlah_pasien} pasien\n") + for p in patients: + print(f" ┌{'─' * 40}") + print(f" │ {p.nama}") + print(f" ├{'─' * 40}") + p.get_info() + print(f" └{'─' * 40}\n") + lanjut() + + elif pilihan == "3": + header("INFO PASIEN") + p = pilih_pasien() + if p: + print(f"\n ┌{'─' * 40}") + print(f" │ {p.nama}") + print(f" ├{'─' * 40}") + p.get_info() + print(f" └{'─' * 40}") + lanjut() + + elif pilihan == "4": + header("CEK REKAM MEDIS") + p = pilih_pasien() + if p: + print() + p.get_rekam_medis() + lanjut() + + elif pilihan == "0": + break + else: + print(" ✗ Pilihan tidak valid.") + + +# ───────────────────────────────────────────── +# 2. MENU RECEPTIONIST +# ───────────────────────────────────────────── +def menu_receptionist(): + while True: + header("MENU RECEPTIONIST") + print(" 1. Lihat info receptionist") + print(" 2. Terima & daftarkan pasien") + print(" 3. Buat janji temu dengan dokter") + print(" 0. Kembali") + pilihan = input("\n > ") + + if pilihan == "1": + header("DATA RECEPTIONIST") + for r in receptionists: + r.display_info() + print() + lanjut() + + elif pilihan == "2": + header("PENDAFTARAN PASIEN") + r = pilih_dari_list(receptionists, "Receptionist", "name") + if r: + belum = [p for p in patients if p.status == "Belum Daftar"] + if not belum: + print("\n ⚠ Semua pasien sudah terdaftar.") + else: + p = pilih_dari_list(belum, "Pasien", "nama") + if p: + r.register_patient(p) + lanjut() + + elif pilihan == "3": + header("BUAT JANJI TEMU") + r = pilih_dari_list(receptionists, "Receptionist", "name") + if r: + p = pilih_pasien_terdaftar() + if p: + d = pilih_dari_list(doctors, "Dokter", "name") + if d: + waktu = input("\n Waktu janji (cth: 10:00) : ") + r.manage_appointment(p, d, waktu) + lanjut() + + elif pilihan == "0": + break + else: + print(" ✗ Pilihan tidak valid.") + + +# ───────────────────────────────────────────── +# 3. MENU DOKTER +# ───────────────────────────────────────────── +def menu_dokter(): + while True: + header("MENU DOKTER") + print(" 1. Lihat info dokter") + print(" 2. Periksa & diagnosis pasien") + print(" 3. Atur jadwal praktek") + print(" 0. Kembali") + pilihan = input("\n > ") + + if pilihan == "1": + header("DATA DOKTER") + for d in doctors: + d.display_info() + print() + lanjut() + + elif pilihan == "2": + header("DIAGNOSIS PASIEN") + d = pilih_dari_list(doctors, "Dokter", "name") + if d: + menunggu = [p for p in patients if p.status in ["Terdaftar", "Menunggu Pemeriksaan"]] + if not menunggu: + print("\n ⚠ Tidak ada pasien yang menunggu pemeriksaan.") + else: + p = pilih_dari_list(menunggu, "Pasien", "nama") + if p: + diagnosis = input("\n Diagnosis : ") + resep = input(" Resep / Obat : ") + d.diagnose_patient(p, diagnosis, resep) + lanjut() + + elif pilihan == "3": + header("JADWAL PRAKTEK") + d = pilih_dari_list(doctors, "Dokter", "name") + if d: + hari = input("\n Hari : ") + mulai = input(" Jam mulai : ") + selesai = input(" Jam selesai : ") + d.set_schedule(hari, mulai, selesai) + lanjut() + + elif pilihan == "0": + break + else: + print(" ✗ Pilihan tidak valid.") + + +# ───────────────────────────────────────────── +# 4. MENU PERAWAT +# ───────────────────────────────────────────── +def menu_perawat(): + while True: + header("MENU PERAWAT") + print(" 1. Lihat info perawat") + print(" 2. Periksa pasien") + print(" 3. Berikan obat") + print(" 4. Update rekam medis") + print(" 0. Kembali") + pilihan = input("\n > ") + + if pilihan == "1": + header("DATA PERAWAT") + for n in nurses: + n.display_info() + print() + lanjut() + + elif pilihan == "2": + header("PEMERIKSAAN PASIEN") + n = pilih_dari_list(nurses, "Perawat", "name") + if n: + diagnosed = [p for p in patients if p.status == "Sudah Didiagnosis"] + if not diagnosed: + print("\n ⚠ Tidak ada pasien yang perlu diperiksa perawat.") + else: + p = pilih_dari_list(diagnosed, "Pasien", "nama") + if p: + n.examine_patient(p) + lanjut() + + elif pilihan == "3": + header("PEMBERIAN OBAT") + n = pilih_dari_list(nurses, "Perawat", "name") + if n: + perlu_obat = [p for p in patients if p.status == "Sedang Diperiksa Perawat"] + if not perlu_obat: + print("\n ⚠ Tidak ada pasien yang perlu diberi obat.") + else: + p = pilih_dari_list(perlu_obat, "Pasien", "nama") + if p: + print(f"\n Resep dokter : {p.resep}") + obat = input(" Nama obat : ") + dosis = input(" Dosis : ") + n.give_medicine(p, obat, dosis) + lanjut() + + elif pilihan == "4": + header("UPDATE REKAM MEDIS") + n = pilih_dari_list(nurses, "Perawat", "name") + if n: + perlu_update = [p for p in patients if p.status == "Obat Diberikan"] + if not perlu_update: + print("\n ⚠ Tidak ada pasien yang perlu diupdate rekam medisnya.") + else: + p = pilih_dari_list(perlu_update, "Pasien", "nama") + if p: + catatan = input("\n Catatan : ") + n.update_medical_record(p, catatan) + lanjut() + + elif pilihan == "0": + break + else: + print(" ✗ Pilihan tidak valid.") + + +# ───────────────────────────────────────────── +# MAIN MENU +# ───────────────────────────────────────────── +def main(): + while True: + print(f"\n ╔{'═' * 42}╗") + print(f" ║ {'RUMAH SAKIT JAYA ABADI':^38} ║") + print(f" ║ {'Sistem Informasi Terpadu':^38} ║") + print(f" ╚{'═' * 42}╝") + print(" 1. Menu Pasien") + print(" 2. Menu Receptionist") + print(" 3. Menu Dokter") + print(" 4. Menu Perawat") + print(" 5. Info Perusahaan") + print(" 0. Keluar") + print(f" {'─' * 44}") + pilihan = input(" > ") + + if pilihan == "1": menu_pasien() + elif pilihan == "2": menu_receptionist() + elif pilihan == "3": menu_dokter() + elif pilihan == "4": menu_perawat() + elif pilihan == "5": + header("INFO PERUSAHAAN") + Employee.info_company() + lanjut() + elif pilihan == "0": + print("\n Terima kasih telah menggunakan sistem ini.") + print(" Semoga lekas sembuh! 🏥\n") + break + else: + print(" ✗ Pilihan tidak valid.") + +if __name__ == "__main__": + main()