Lesson 0023 · FHIR · Modul SATUSEHAT · ±20 menit

SATUSEHAT: validasi profile, mapping data legacy, ConceptMap

Apa artinya valid terhadap profile, bagaimana SATUSEHAT menolak data, dan bagaimana tabel serta kode lokal SIMRS lama dipetakan ke resource dan terminologi standar

Target lesson ini: Anda bisa menjawab "Bagaimana memetakan data rumah sakit lama ke FHIR?" dalam 90 detik (profile, validasi dan OperationOutcome, ICD-10/LOINC/KFA, ConceptMap).

Di lesson 0022 Anda sudah tahu cara masuk ke SATUSEHAT: token, prasyarat, dan identifier. Lesson ini membahas apa yang terjadi pada data yang Anda kirim (validasi) dan bagaimana data SIMRS lama dibentuk menjadi resource FHIR (mapping). Klaim yang tidak bisa diverifikasi dari halaman publik tetap ditandai belum terverifikasi (diakses 2026-10-26).

1c. Validasi terhadap profile (±7 menit)

Spesifikasi dasar FHIR adalah "platform specification" yang biasanya perlu diadaptasi per konteks: elemen mana yang dipakai, fitur API mana, dan terminologi mana untuk elemen tertentu. Adaptasi itu diterbitkan sebagai Implementation Guide berisi Profile (StructureDefinition), ValueSet, dan ConceptMap. [1] Memvalidasi sebuah resource berarti memeriksa: [2]

AspekContoh pertanyaan
StructureAda property yang tidak dikenal spesifikasi?
Cardinalityname wajib (1..*) tapi kosong?
Value domainsbirthDate berformat tanggal FHIR? kode enum sah?
BindingsKode di Coding/CodeableConcept ada di value set yang diikat?
InvariantsAturan co-occurrence (mis. constraint dom-2) terpenuhi?
ProfilesAturan profile dari meta.profile, CapabilityStatement, IG, atau konteks terpenuhi?
Business rulesDuplikat? reference bisa di-resolve? user berhak? (dibuat di luar spesifikasi)

Latihan 1 — Validasi

Validasi menolak kode yang tidak dikenal. Jadi pertanyaan berikutnya: bagaimana kode lokal di SIMRS lama menjadi kode standar yang diterima?

1d. Mapping data legacy → FHIR, dan ConceptMap (±8 menit)

Mapping punya dua lapis: struktur (tabel/kolom → resource/elemen) dan kode (kode lokal → terminologi standar). Terminologi standar SATUSEHAT: [6]

DataStandar di SATUSEHATContoh dari dokumentasi
Diagnosis (Condition.code)ICD-10 versi 2010http://hl7.org/fhir/sid/icd-10 · C47.0 [7]
Prosedur dan tindakan medisICD-9 CM versi 2010(lihat lampiran terminologi)
Penamaan uji laboratorium (Observation.code)LOINChttp://loinc.org · 8867-4 Heart rate [8]
Istilah klinisSNOMED CThttp://snomed.info/sct
Obat (Medication.code)KFA (Kamus Farmasi dan Alat Kesehatan)http://sys-ids.kemkes.go.id/kfa · 93001019 [9]
// Hanya untuk dibaca: satu baris tabel lama → Condition (struktur + kode)
type DiagnosaRow = { no_reg: string; kode_dx: string; ket: string; tgl: string };  // tgl: "2026-10-26 17:35" WIB, tanpa zona

function toCondition(row: DiagnosaRow, ctx: { patientIhs: string; encounterId: string }, map: Map<string, Coding>): Condition {
  const icd = map.get(row.kode_dx);                        // hasil ConceptMap lokal → ICD-10, bisa undefined
  if (!icd) throw new UnmappedCode(row.kode_dx);           // masuk antrean review coder, jangan dikirim asal
  return {
    resourceType: "Condition",
    code: { coding: [icd,                                  // kode standar
                     { system: "https://simrs.rs-contoh.id/fhir/CodeSystem/dx-lokal", code: row.kode_dx }], // kode asal (system ilustrasi)
            text: row.ket },
    subject:   { reference: `Patient/${ctx.patientIhs}` },
    encounter: { reference: `Encounter/${ctx.encounterId}` },
    recordedDate: wibToUtc(row.tgl),                       // "2026-10-26T10:35:00+00:00"
  };
}

Dokumentasi Condition SATUSEHAT menandai code, subject, dan encounter sebagai wajib; elemen lain wajib atau tidak mengikuti panduan per use case, jadi potongan di atas sengaja tidak lengkap. [7] Membawa kode lokal sebagai Coding tambahan sah karena CodeableConcept boleh berisi beberapa Coding untuk konsep yang sama (lesson 0005); apakah SATUSEHAT menerima Coding tambahan dengan system lokal di setiap elemen: belum terverifikasi (diakses 2026-10-26).

ConceptMap adalah resource FHIR untuk menyatakan mapping kode itu secara formal. Profiling R4 menyebut tujuannya: "Map between local and standard terminologies or content models". [1] Yang perlu Anda ucapkan di interview: [10]

// Bentuk ConceptMap R4 (struktur mengikuti contoh resmi; kode lokal ilustrasi, target dari dokumentasi SATUSEHAT)
{
  "resourceType": "ConceptMap",
  "status": "active",
  "group": [{
    "source": "https://simrs.rs-contoh.id/fhir/CodeSystem/lab-lokal",
    "target": "http://loinc.org",
    "element": [
      { "code": "NADI", "display": "Nadi per menit",
        "target": [{ "code": "8867-4", "display": "Heart rate", "equivalence": "equivalent" }] },
      { "code": "CEK-UMUM", "display": "Paket cek umum",
        "target": [{ "equivalence": "unmatched", "comment": "Paket, bukan satu tes: pecah per pemeriksaan" }] }
    ]
  }]
}

Struktur group.source/target → element.code → target.code/equivalence/comment mengikuti contoh resmi R4. [13] Padanan JS: tabel lookup Map<kodeLokal, Coding> yang diberi metadata (arah, konteks, tingkat kecocokan) dan bisa dipertukarkan antar sistem. Di proyek nyata, tabel ini disusun dan direview oleh coder klinis, bukan developer sendirian.

Latihan 2 — Terminologi dan mapping

Latihan 3 — Jawab lisan

Pasang timer di ponsel, jawab dengan suara keras, baru buka jawaban contoh. Centang hanya poin yang benar-benar Anda sebut.

"Rumah sakit kami punya SIMRS lama dengan tabel pasien, kunjungan, diagnosa, dan kode lokal. Bagaimana Anda memetakannya ke FHIR untuk dikirim ke SATUSEHAT?" (90 detik)
Bandingkan dengan jawaban contoh dan checklist-nya

"Saya mulai dari profile target, bukan dari tabel: IG SATUSEHAT dan panduan use case menentukan elemen wajib dan terminologinya. Lalu peta tabel ke resource: pasien → Patient (cari nomor IHS lewat NIK, simpan di tabel kita), kunjungan → Encounter dengan identifier http://sys-ids.kemkes.go.id/encounter/{id-organisasi} + nomor kunjungan lokal, diagnosa → Condition yang merujuk Encounter dan Patient. Kode lokal dipetakan ke terminologi standar: diagnosis ke ICD-10, lab ke LOINC, obat ke KFA. Secara konsep itu ConceptMap: satu arah, per konteks, tiap pasangan punya equivalence; kode yang tidak cocok masuk antrean review coder, tidak dibuang. Format dinormalisasi: waktu ke UTC, gender ke male/female. Sebelum kirim, uji di sandbox; OperationOutcome disimpan per record supaya bisa diperbaiki dan dikirim ulang secara idempoten berdasarkan identifier."

Checklist: apakah Anda menyebut…

  • mulai dari profile/IG dan panduan use case (elemen wajib, terminologi)?
  • tabel → resource: pasien → Patient (nomor IHS via NIK), kunjungan → Encounter, diagnosa → Condition?
  • identifier lokal dengan system per organisasi, Reference antar resource?
  • kode lokal → ICD-10/LOINC/KFA; ConceptMap satu arah dengan equivalence?
  • kode tak terpetakan → antrean review; normalisasi format (UTC, gender)?
  • validasi di sandbox, simpan OperationOutcome, kirim ulang idempoten?

Lulus kalau minimal 4 dari 6.

"Apa artinya resource 'valid terhadap profile'? Di mana Anda menjalankan validasi di pipeline integrasi kami?" (60 detik)
Bandingkan dengan jawaban contoh dan checklist-nya

"Valid berarti lolos struktur, cardinality, tipe nilai, binding kode, invariant, dan aturan profile; profile adalah StructureDefinition yang mempersempit resource dasar, misalnya mewajibkan identifier atau mengikat kode ke ICD-10. Resource bisa mengklaim profile lewat meta.profile, dan server bisa memeriksanya lewat $validate yang mengembalikan OperationOutcome, 200 baik valid maupun tidak. Business rule seperti duplikat dan reference yang resolve ada di luar spesifikasi. Di pipeline: validasi sedini mungkin di sisi kami dan di sandbox saat development; di production kami tetap menangani OperationOutcome dari server. Validasi penuh dengan terminologi mahal dan bisa membuang data klinis karena satu field buruk, jadi record yang gagal disimpan untuk diperbaiki. Prinsipnya Postel's law."

Checklist: apakah Anda menyebut…

  • aspek validasi: struktur, cardinality, nilai, binding kode, invariant, profile?
  • profile = StructureDefinition yang mempersempit resource; klaim lewat meta.profile?
  • $validate mengembalikan OperationOutcome (200 walau tidak valid)?
  • business rule (duplikat, reference) di luar spesifikasi?
  • validasi di development/sandbox; production: biaya dan risiko kehilangan data?
  • record gagal disimpan untuk diperbaiki; Postel's law?

Lulus kalau minimal 4 dari 6.

Bacaan lanjutan (opsional, tidak dihitung dalam durasi) SATUSEHAT Platform: Orientasi / Prerequisites, lalu ikuti tautannya ke halaman resource Patient dan Encounter. Untuk konsep validasi, baca FHIR R4: Validating Resources (pendek, satu halaman).

Sumber (SATUSEHAT diakses 2026-10-26): [1] FHIR R4 Profiling · [2] FHIR R4 Validating Resources · [3] FHIR R4 $validate · [4] Validasi Interoperabilitas · [5] Resource Encounter · [6] Terminologi · [7] Resource Condition · [8] Resource Observation · [9] Resource Medication (KFA) · [10] FHIR R4 ConceptMap · [11] FHIR R4 ConceptMapEquivalence · [12] FHIR R4 ConceptMap $translate · [13] FHIR R4 contoh ConceptMap (JSON)