From ec2e09b84e4bd28044aa36fd91359562228224ba Mon Sep 17 00:00:00 2001 From: matthewflrnt Date: Wed, 14 Oct 2026 21:10:10 +0700 Subject: [PATCH] initial commit --- README.md | 160 +++++++ __pycache__/main.cpython-314.pyc | Bin 0 -> 38490 bytes individu.py | 71 +++ main.py | 796 +++++++++++++++++++++++++++++++ 4 files changed, 1027 insertions(+) create mode 100644 README.md create mode 100644 __pycache__/main.cpython-314.pyc create mode 100644 individu.py create mode 100644 main.py 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 0000000000000000000000000000000000000000..35ec81c9a4729ea79798b62389e0e67082cd1671 GIT binary patch literal 38490 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 literal 0 HcmV?d00001 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()