Lewati ke isi

Module: Medical Record (RME)

Modul RME adalah inti dari SentraClinic EMR. Landasan legalitasnya berasal dari Permenkes RI No. 24/2022 yang mewajibkan seluruh RME: (1) terstruktur digital, (2) ditandatangani digital oleh dokter, (3) terhubung ke SatuSehat, dan (4) bersifat immutable setelah sign-off.

RME Lifecycle Flowchart

sequenceDiagram
    participant P as Pasien
    participant N as Perawat/Nurse
    participant D as Dokter/Clinician
    participant DB as Secure DB
    participant BSrE as BSrE Signature API
    participant SS as SatuSehat Kemenkes

    P->>N: Registrasi & Cek Tensi
    N->>DB: Simpan Vital Sign (Encounter created)
    N->>D: Pasien siap diperiksa
    D->>DB: Baca riwayat rekam medis (Generate audit log READ)
    D->>D: Isi SOAP notes & Diagnosa ICD-10
    D->>DB: Kirim e-Prescribing (Stok terpotong sementara via FEFO)
    D->>BSrE: Request Digital Signature dengan PIN Dokter (2FA required)
    BSrE-->>D: Return BSrE signature hash (SHA-256)
    D->>DB: Simpan SOAP + digital_signature_hash (Lock SOAP)
    Note over DB: RME status = LOCKED. UPDATE diblokir.
    DB-->>SS: Kirim payload HL7 FHIR Encounter (Background Job via RabbitMQ)
    Note over D,DB: Addendum Mode diaktifkan jika perlu revisi setelah lock

SOAP Immutability Rules

Setelah dokter melakukan sign-off:

  1. Kolom signed_at dan digital_signature_hash pada tabel soap_notes terisi.
  2. Semua request PUT /encounters/:id/soap setelah ini akan dikembalikan HTTP 423 Locked.
  3. Modifikasi hanya diperbolehkan melalui endpoint POST /soap/:id/addendum yang:
  4. Menyalin baris SOAP lama ke soap_notes_history dengan version incremental.
  5. Tidak menghapus atau menimpa data SOAP original.
  6. Memerlukan BSrE re-signing dengan justifikasi tertulis (addendum_reason).
  7. Mencatat entry baru ke audit_logs dengan action_type = 'UPDATE' dan json_diff penuh.

Catatan penting: Mekanisme 2FA (PIN khusus sign-off) diwajibkan saat dokter menekan tombol "Sign & Lock SOAP". PIN ini terpisah dari password login biasa dan divalidasi oleh Keycloak + BSrE sebelum tanda tangan diterbitkan.

Patient Queue State Machine

[*] --> REGISTERED    : Pasien Terdaftar / Walk-in / Booking Online
REGISTERED --> TRIAGE : Dipanggil ke Ruang Triage oleh Perawat
TRIAGE --> WAITING_DOCTOR : Selesai Vital Sign
WAITING_DOCTOR --> CONSULTATION : Dipanggil oleh Dokter
CONSULTATION --> PHARMACY : Selesai SOAP & Dokter Mengirimkan Resep
PHARMACY --> BILLING  : Obat Selesai Dipacking
BILLING --> COMPLETED : Pembayaran Diterima / Pasien Keluar

TRIAGE --> BILLING    : Batal Berobat / Rujukan Langsung ke RS (Emergency)
CONSULTATION --> BILLING : Selesai Konsultasi Tanpa Resep

Integrity Auditing & SOAP Modification Rules

Setiap akses ke database RME memicu trigger audit tingkat rendah. Jika seorang dokter memodifikasi rekam medis sebelum sign-off:

  1. Sistem menyalin baris SOAP lama ke tabel soap_notes_history.
  2. Data lama tidak ditimpa secara permanen; melainkan data terbaru dipasang sebagai versi v2.
  3. Audit log mencatat: TIMESTAMP, USER_ID, ACTION=UPDATE, DIFFERENCE=JSON_DIFF.

Triage & Prioritisation Algorithm

  • Triage Red (IGD / Critical): Melompati seluruh urutan antrean poli, memicu alarm visual di EMR Dokter dan memindahkan status pasien langsung ke ruang tindakan utama.
  • Triage Yellow (Urgent): Diberikan bobot penambah prioritas sebesar +10 tingkat dalam antrean reguler.
  • Triage Green (Non-Urgent): Mengikuti antrean reguler berdasarkan timestamp registrasi.

Emergency Bypass: Kasir/Suster dapat memicu tombol "Emergency Bypass" di antrean. Sistem segera menghasilkan nomor rekam medis darurat otomatis (RM-EMERGENCY-TEMP-#####), menerbitkan tiket prioritas tertinggi, dan membuka EMR SOAP IGD secara instan tanpa mengharuskan input NIK/KTP pasien di awal. Profil dapat dilengkapi setelah pasien stabil.

Pharmacy FEFO Flow

graph TD
    A[Dokter Kirim e-Prescription] --> B[Apotek: Masuk Antrean Resep Farmasi]
    B --> C{Pemeriksaan Resep: Interaksi Obat & Dosis}
    C -- Ada Isu --> D[Picu Konfirmasi ke Dokter]
    C -- Lolos Verifikasi --> E{Jenis Obat?}
    E -- Non-Racikan --> F[Auto-Alokasi Stok FEFO dari Batch Terdekat]
    E -- Racikan --> G[Compounding: Input Bahan Baku & Jumlah]
    F --> H[Pengemasan & Pemberian Etiket Obat]
    G --> H
    H --> I[Double-Check oleh Apoteker Kedua]
    I --> J[Kirim Notifikasi Pembayaran ke Kasir]
    J --> K[Obat Diserahkan ke Pasien & Edukasi Aturan Minum]

FEFO Allocation Engine (pseudo-code):

async function allocateStockFEFO(medicineId, requestedQty, trx) {
  const activeBatches = await trx('medicine_batches')
    .where('medicine_id', medicineId)
    .where('stock_qty', '>', 0)
    .where('expiry_date', '>', new Date())
    .orderBy('expiry_date', 'asc'); // First Expired, First Out

  let remainingToAllocate = requestedQty;
  const allocations = [];

  for (const batch of activeBatches) {
    if (remainingToAllocate <= 0) break;

    const allocQty = Math.min(batch.stock_qty, remainingToAllocate);
    allocations.push({
      batchId: batch.id,
      batchNumber: batch.batch_number,
      allocatedQty: allocQty
    });

    remainingToAllocate -= allocQty;

    // Deduct stock temporarily inside atomic transaction
    await trx('medicine_batches')
      .where('id', batch.id)
      .decrement('stock_qty', allocQty);
  }

  if (remainingToAllocate > 0) {
    throw new Error(`Insufficient stock for medicine ID: ${medicineId}.`);
  }

  return allocations;
}

Allergy Conflict Detection

Begitu dokter menambahkan obat yang bertentangan dengan profil alergi terdaftar ke dalam tabel resep EMR, sistem secara instan menampilkan modal peringatan berkedip warna merah yang mengharuskan dokter memilih antara: - (a) Membatalkan resep obat, atau - (b) Melakukan bypass manual dengan memasukkan justifikasi medis darurat (misal: "Manfaat melebihi risiko klinis, dilakukan pengawasan ketat") — yang dicatat ke audit log dengan level HIGH_SEVERITY.

User Story: Dokter Menandatangani Rekam Medis

  • As a Dokter Spesialis/Umum
  • I want to Menandatangani rekam medis SOAP secara digital dan menguncinya setelah selesai mendiagnosa pasien.
  • So that Data pemeriksaan terekam dengan aman, terinteroperabilitas dengan SatuSehat, dan mematuhi regulasi Permenkes No. 24/2022.

Acceptance Criteria:

  • Given Dokter telah selesai memasukkan data SOAP dan Encounter berstatus CONSULTATION.
  • When Dokter mengklik "Sign & Lock SOAP" dan memasukkan PIN tanda tangan digital medis yang sah.
  • Then Sistem menghasilkan hash SHA-256 kriptografis via BSrE API dari payload SOAP tersebut.
  • And Mengubah status Encounter menjadi PHARMACY dan status SOAP menjadi locked.
  • And Memicu antrean background job asinkron untuk mengirimkan data FHIR ke SatuSehat Kemenkes.
  • And Menampilkan pesan sukses "EMR Locked and Sync Triggered".