Manajemen ruang bedah (Operating Room Management) merupakan salah satu pilar operasional paling krusial sekaligus paling rumit di rumah sakit. Ruang bedah menyumbang sebagian besar pendapatan rumah sakit, namun juga merupakan area dengan pemborosan biaya tertinggi jika tidak dikelola dengan efisien.
Penjadwalan operasi bedah secara manual sering kali menimbulkan tabrakan jadwal (scheduling conflict), tingginya waktu tunggu dokter bedah, hingga masa kosong ruang bedah (idle time) yang tidak produktif.
Untuk memecahkan masalah alokasi sumber daya yang kompleks ini, kita dapat mengadaptasi konsep industri manufaktur, yaitu algoritma Job Shop Scheduling (JSS). Dengan memetakan operasi medis sebagai Jobs dan ruang bedah serta tenaga medis sebagai Machines, kita dapat merancang sistem penjadwalan otomatis yang meminimalkan total waktu penyelesaian (makespan).
Artikel ini akan membahas arsitektur sistem, logika matematika JSS medis, rancangan database PostgreSQL, implementasi mesin penjadwalan berbasis PHP, dan visualisasi Gantt Chart menggunakan React + TailwindCSS.
1. Arsitektur Aplikasi Manajemen Ruang Bedah JSS
Aplikasi manajemen ruang bedah berbasis JSS dirancang untuk menyinkronkan data ketersediaan dokter, perawat, ruang operasi, dan pasien secara real-time.
Berikut adalah cetak biru arsitektur sistem aplikasi manajemen ruang bedah berbasis JSS:

Alur Kerja Sistem:
- Surgery Scheduling Requests: Input data pasien, jenis operasi bedah, dokter bedah penanggung jawab, estimasi durasi, dan peralatan khusus yang diperlukan.
- JSS Optimizer Engine:
- Menerima data operasi sebagai Jobs beserta urutan langkah medis (Operations seperti persiapan, pembiusan, tindakan bedah, pembersihan ruangan).
- Menerima data sumber daya rumah sakit sebagai Machines (ruang bedah, dokter bedah, anestesiolog, perawat).
- Menghitung jadwal optimal untuk meminimalkan makespan dan memaksimalkan penggunaan ruang operasi menggunakan logika penjadwalan (solver core).
- PostgreSQL Database: Menyimpan status ketersediaan sumber daya dan hasil jadwal final yang telah dikomit.
- React Gantt Chart UI: Menyajikan hasil jadwal dalam bentuk bagan waktu visual dinamis (Gantt Chart) agar mudah dipahami oleh staf admin dan tim medis.
2. Memetakan Masalah Ruang Bedah ke Job Shop Scheduling (JSS)
Untuk menerapkan algoritma JSS pada sistem rumah sakit, kita perlu memetakan elemen-elemen klinis ke dalam terminologi teori penjadwalan industri.
Berikut adalah visualisasi sistem pemetaan dan model logika berpikir JSS:

Model Pemetaan JSS:
- Surgeries sebagai Jobs ($J$): Setiap tindakan operasi pasien dianggap sebagai satu Job unik. Setiap Job terdiri dari serangkaian urutan tugas (Operations) yang harus diselesaikan secara berurutan.
- Medical Procedures sebagai Operations ($O_{i,j}$): Langkah-langkah di dalam satu tindakan bedah. Contoh:
- Preparation (Persiapan pasien di ruang bedah).
- Anesthesia (Pemberian bius oleh anestesiolog).
- Surgery Action (Tindakan bedah oleh dokter bedah utama).
- Post-Op Cleanup (Pembersihan dan sterilisasi ruangan oleh tim sanitasi).
- Resources sebagai Machines ($M_k$): Sumber daya yang memproses setiap operasi. Setiap mesin hanya dapat memproses satu operasi pada satu waktu (resource capacity constraint). Sumber daya ini meliputi:
- Operating Room (OR 1, OR 2, OR 3).
- Surgeons (Dokter Bedah).
- Anesthesiologists (Dokter Anestesi).
- Peralatan khusus (seperti Robot Bedah Da Vinci, MRI, Mesin Ventilator).
- Processing Time ($p_{i,j}$): Estimasi waktu pengerjaan untuk masing-masing tahap operasi.
- Makespan ($C_{\text{max}}$): Total durasi waktu yang dibutuhkan dari awal operasi pertama dimulai hingga operasi terakhir di hari itu selesai sepenuhnya. Goal utama dari optimasi JSS adalah meminimalkan nilai makespan: $$\text{Minimize } C_{\text{max}} = \max(C_j)$$
3. Rancangan Skema Database di PostgreSQL
PostgreSQL akan mencatat data transaksi operasi, ketersediaan staf medis, dan alokasi ruang bedah. Kita akan merancang skema database relasional berikut:
-- Menyimpan daftar ruangan bedah (Resources - Machines)
CREATE TABLE operating_rooms (
id SERIAL PRIMARY KEY,
room_number VARCHAR(50) UNIQUE NOT NULL,
specialty VARCHAR(100),
is_active BOOLEAN DEFAULT TRUE
);
-- Menyimpan data dokter dan perawat (Resources - Machines)
CREATE TABLE medical_staff (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
role VARCHAR(100) NOT NULL, -- 'Surgeon', 'Anesthesiologist', 'Scrub Nurse'
specialty VARCHAR(100)
);
-- Menyimpan kasus operasi (Jobs)
CREATE TABLE surgery_jobs (
id SERIAL PRIMARY KEY,
patient_name VARCHAR(255) NOT NULL,
diagnosis VARCHAR(255),
priority_level INT DEFAULT 1, -- Semakin tinggi angka, semakin prioritas (emergency)
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Menyimpan detail langkah prosedur operasi (Operations)
CREATE TABLE surgery_operations (
id SERIAL PRIMARY KEY,
job_id INT REFERENCES surgery_jobs(id) ON DELETE CASCADE,
step_sequence INT NOT NULL, -- Urutan langkah (1, 2, 3...)
operation_name VARCHAR(100) NOT NULL, -- 'Prep', 'Anesthesia', 'Surgery', 'Cleanup'
required_room_id INT REFERENCES operating_rooms(id),
required_staff_id INT REFERENCES medical_staff(id),
processing_time INT NOT NULL -- Durasi dalam menit
);
-- Menyimpan hasil penjadwalan optimal final
CREATE TABLE optimal_schedules (
id SERIAL PRIMARY KEY,
job_id INT REFERENCES surgery_jobs(id) ON DELETE CASCADE,
operation_id INT REFERENCES surgery_operations(id) ON DELETE CASCADE,
start_time TIMESTAMP NOT NULL,
end_time TIMESTAMP NOT NULL
);
4. Implementasi Mesin Penjadwalan JSS (PHP)
Karena penjadwalan JSS termasuk ke dalam permasalahan NP-Hard yang sangat kompleks untuk diselesaikan secara eksak pada skala besar, kita umumnya menggunakan pendekatan Heuristic atau Dispatching Rules (seperti Shortest Processing Time (SPT) atau Earliest Start Time (EST)) untuk menghasilkan jadwal yang mendekati optimal dengan cepat.
Berikut adalah implementasi solver berbasis aturan prioritas Shortest Processing Time (SPT) menggunakan PHP untuk menjadwalkan operasi bedah tanpa tabrakan:
<?php
class SurgeryJob {
public int $id;
public string $patientName;
public array $operations = []; // Array of SurgeryOperation
public function __construct(int $id, string $patientName) {
$this->id = $id;
$this->patientName = $patientName;
}
}
class SurgeryOperation {
public int $id;
public int $stepSequence;
public string $name;
public int $roomId;
public int $staffId;
public int $processingTime; // dalam menit
public function __construct(int $id, int $stepSequence, string $name, int $roomId, int $staffId, int $processingTime) {
$this->id = $id;
$this->stepSequence = $stepSequence;
$this->name = $name;
$this->roomId = $roomId;
$this->staffId = $staffId;
$this->processingTime = $processingTime;
}
}
class JSSSurgeryScheduler {
// Menyimpan waktu ketersediaan terakhir dari masing-masing resource (room & staff)
private array $roomAvailability = []; // [roomId => lastAvailableTimeInMinutes]
private array $staffAvailability = []; // [staffId => lastAvailableTimeInMinutes]
public function schedule(array $jobs, int $startOfDayOffsetInMinutes = 480): array {
$scheduledEvents = [];
// 1. Kumpulkan semua operasi dari seluruh Jobs
$allOperations = [];
foreach ($jobs as $job) {
foreach ($job->operations as $op) {
// Simpan metadata job di dalam operasi untuk mempermudah pemrosesan
$op->jobId = $job->id;
$op->patientName = $job->patientName;
$allOperations[] = $op;
}
}
// 2. Terapkan Heuristic: Shortest Processing Time (SPT)
// Urutkan operasi dari yang durasinya paling pendek untuk mengurangi antrean rata-rata
usort($allOperations, function($a, $b) {
return $a->processingTime <=> $b->processingTime;
});
// Track start time untuk masing-masing job agar mematuhi precedence constraint (langkah berurutan)
$jobLastEndTime = []; // [jobId => lastEndTimeInMinutes]
foreach ($allOperations as $op) {
$roomId = $op->roomId;
$staffId = $op->staffId;
// Inisialisasi waktu ketersediaan resource jika belum ada
if (!isset($this->roomAvailability[$roomId])) {
$this->roomAvailability[$roomId] = $startOfDayOffsetInMinutes;
}
if (!isset($this->staffAvailability[$staffId])) {
$this->staffAvailability[$staffId] = $startOfDayOffsetInMinutes;
}
if (!isset($jobLastEndTime[$op->jobId])) {
$jobLastEndTime[$op->jobId] = $startOfDayOffsetInMinutes;
}
// Waktu mulai operasi adalah nilai maksimal dari kesiapan ruangan, staf, dan langkah sebelumnya dari Job ini
$startTime = max(
$this->roomAvailability[$roomId],
$this->staffAvailability[$staffId],
$jobLastEndTime[$op->jobId]
);
$endTime = $startTime + $op->processingTime;
// Update ketersediaan resource
$this->roomAvailability[$roomId] = $endTime;
$this->staffAvailability[$staffId] = $endTime;
$jobLastEndTime[$op->jobId] = $endTime;
$scheduledEvents[] = [
'job_id' => $op->jobId,
'patient_name' => $op->patientName,
'operation_id' => $op->id,
'operation_name' => $op->name,
'room_id' => $roomId,
'staff_id' => $staffId,
'start_time' => $startTime, // dalam menit dari tengah malam
'end_time' => $endTime
];
}
return $scheduledEvents;
}
}
5. Visualisasi Gantt Chart (React + TailwindCSS)
Setelah jadwal dihasilkan oleh backend PHP, staf admin membutuhkan tampilan grafis yang intuitif untuk memantau aktivitas ruang bedah secara real-time.
Berikut adalah diagram alur logis dari proses perhitungan dan resolusi konflik jadwal sebelum dirender ke antarmuka:

Desain antarmuka dashboard penjadwalan ruang bedah Gantt Chart di atas diimplementasikan menggunakan komponen React dan utilitas TailwindCSS berikut:

import React from 'react';
const scheduledData = [
{ room: 'OR-01', patient: 'A. Smith', procedure: 'Appendectomy', start: '08:30', end: '10:00', color: 'bg-cyan-500/20 border-cyan-500 text-cyan-400' },
{ room: 'OR-01', patient: 'B. Jones', procedure: 'Hernia Repair', start: '10:15', end: '11:45', color: 'bg-cyan-500/20 border-cyan-500 text-cyan-400' },
{ room: 'OR-02', patient: 'C. Davis', procedure: 'THR', start: '09:00', end: '11:00', color: 'bg-emerald-500/20 border-emerald-500 text-emerald-400' },
];
export function ORSchedulerDashboard() {
return (
<div class="min-h-screen bg-neutral-950 text-neutral-100 p-8 font-sans">
<div class="max-w-7xl mx-auto space-y-6">
<!-- Header -->
<header class="flex justify-between items-center border-b border-neutral-900 pb-4">
<div>
<h1 class="text-2xl font-bold tracking-tight text-white">OR SURGERY SCHEDULER</h1>
<p class="text-xs text-neutral-400">Sistem Optimasi Alokasi Ruang Bedah Berbasis JSS</p>
</div>
<div class="text-xs bg-neutral-900 border border-neutral-800 px-3 py-1.5 rounded-lg text-neutral-300">
October 26, 2023 | 09:30 AM
</div>
</header>
<!-- KPI Metrics Display -->
<div class="grid grid-cols-4 gap-6">
<div class="bg-neutral-900 p-5 rounded-lg border border-neutral-800 space-y-2">
<p class="text-xs text-neutral-400 uppercase tracking-wider">Makespan</p>
<p class="text-3xl font-bold text-cyan-400">14h 15m</p>
</div>
<div class="bg-neutral-900 p-5 rounded-lg border border-neutral-800 space-y-2">
<p class="text-xs text-neutral-400 uppercase tracking-wider">Idle Time</p>
<p class="text-3xl font-bold text-emerald-400">45m</p>
</div>
<div class="bg-neutral-900 p-5 rounded-lg border border-neutral-800 space-y-2">
<p class="text-xs text-neutral-400 uppercase tracking-wider">Total Surgeries</p>
<p class="text-3xl font-bold text-white">24</p>
</div>
<div class="bg-neutral-900 p-5 rounded-lg border border-neutral-800 space-y-2">
<p class="text-xs text-neutral-400 uppercase tracking-wider">Room Utilization</p>
<p class="text-3xl font-bold text-white">94%</p>
</div>
</div>
<div class="grid grid-cols-4 gap-8">
<!-- Sidebar Resources -->
<aside class="col-span-1 bg-neutral-900/50 p-5 rounded-lg border border-neutral-900 space-y-4">
<h3 class="font-bold text-sm text-neutral-300">Active Resources</h3>
<div class="space-y-2 text-xs">
<div class="flex justify-between items-center bg-neutral-900 p-2 rounded border border-neutral-800">
<span class="text-neutral-300">Dr. Aris V. (Surgeon)</span>
<span class="w-2 h-2 rounded-full bg-emerald-500"></span>
</div>
<div class="flex justify-between items-center bg-neutral-900 p-2 rounded border border-neutral-800">
<span class="text-neutral-300">Dr. Lee (Anesthesiologist)</span>
<span class="w-2 h-2 rounded-full bg-emerald-500"></span>
</div>
</div>
</aside>
<!-- Gantt Chart Main Area -->
<main class="col-span-3 bg-neutral-900/50 p-6 rounded-lg border border-neutral-900 space-y-4">
<h3 class="font-bold text-sm text-neutral-300">Surgery Gantt Chart Visualization</h3>
<!-- Timeline Grid Header -->
<div class="grid grid-cols-6 border-b border-neutral-800 pb-2 text-xs text-neutral-400 text-center">
<div>Room</div>
<div>08:00 AM</div>
<div>10:00 AM</div>
<div>12:00 PM</div>
<div>02:00 PM</div>
<div>04:00 PM</div>
</div>
<!-- Gantt Rows -->
<div class="space-y-4 pt-2">
{['OR-01', 'OR-02', 'OR-03'].map((room) => (
<div key={room} class="grid grid-cols-6 items-center text-xs h-16 border-b border-neutral-900 pb-2">
<div class="font-bold text-white text-center">{room}</div>
<!-- Render Gantt Blocks Based on Timeline -->
<div class="col-span-5 relative h-full w-full bg-neutral-950/40 rounded border border-neutral-900 flex items-center">
{scheduledData.filter(d => d.room === room).map((item, index) => (
<div
key={index}
className={`absolute border p-2 rounded text-[10px] leading-tight font-semibold ${item.color}`}
style={{
left: item.start === '08:30' ? '10%' : item.start === '09:00' ? '20%' : '45%',
width: '35%'
}}
>
<p class="font-bold truncate">{item.patient}</p>
<p class="opacity-80 truncate">{item.procedure}</p>
</div>
))}
</div>
</div>
))}
</div>
</main>
</div>
</div>
</div>
);
}
6. Kesimpulan & Manfaat JSS pada Manajemen Rumah Sakit
Dengan mengimplementasikan pemodelan penjadwalan industri berbasis Job Shop Scheduling (JSS) pada manajemen operasi medis, rumah sakit dapat memperoleh keuntungan nyata:
- Reduksi Makespan Global: Memastikan semua rangkaian operasi selesai secepat mungkin, memungkinkan staf medis untuk pulang tepat waktu dan menekan biaya lembur.
- Peningkatan Utilitas Ruang Operasi: Menghindari lubang-lubang waktu kosong (idle time) di antara jadwal operasi bedah.
- Manajemen Konflik Otomatis: Menjamin tidak ada dokter bedah atau peralatan vital yang dijadwalkan di dua ruangan berbeda pada waktu yang bersamaan.
Referensi & Resource Penting
- Applegate, D., & Cook, W. (1991). A computational study of the job-shop scheduling problem. ORSA Journal on Computing, 3(2), 149-156. Studi klasik penyelesaian matematika JSS.
- Cardoen, B., Demeulemeester, E., & Beliën, J. (2010). Operating room planning and scheduling: A literature review. European Journal of Operational Research, 201(3), 621-632. Tinjauan akademis lengkap mengenai aplikasi optimasi riset operasi di rumah sakit.
- Garey, M. R., Johnson, D. S., & Sethi, R. (1976). The complexity of flow-shop and job-shop scheduling. Mathematics of Operations Research. Membuktikan sifat NP-Complete dari penjadwalan kompleks.
- React-Gantt Component Guide. Panduan integrasi Gantt Chart interaktif pada library React: Frappe Gantt React Wrapper.