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
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]
| Aspek | Contoh pertanyaan |
|---|---|
| Structure | Ada property yang tidak dikenal spesifikasi? |
| Cardinality | name wajib (1..*) tapi kosong? |
| Value domains | birthDate berformat tanggal FHIR? kode enum sah? |
| Bindings | Kode di Coding/CodeableConcept ada di value set yang diikat? |
| Invariants | Aturan co-occurrence (mis. constraint dom-2) terpenuhi? |
| Profiles | Aturan profile dari meta.profile, CapabilityStatement, IG, atau konteks terpenuhi? |
| Business rules | Duplikat? reference bisa di-resolve? user berhak? (dibuat di luar spesifikasi) |
$validate.POST [base]/[Resource]/$validate(opsional?profile=…,mode=create|update|delete) mengembalikan OperationOutcome; "This operation returns a 200 OK whether or not the resource is valid", sedangkan 4xx/5xx berarti validasinya sendiri gagal dijalankan. Operasi ini tidak menyimpan resource. [3] Apakah SATUSEHAT menyediakan endpoint$validateuntuk partner: belum terverifikasi (diakses 2026-10-26); yang terdokumentasi adalah validasi saat data dikirim (di bawah).- Validasi di SATUSEHAT. Saat resource interoperabilitas dikirim, sistem memvalidasi kode terminologi (ICD-10, ICD-9 CM, LOINC, SNOMED CT, dan code system lain). API Gateway memeriksa request lewat FHIR Processor dulu; kalau ada kesalahan, respons 4xx berupa OperationOutcome dengan
issue.severity,issue.code(duplicate,format,value),details.text, danexpression(resource dan field). [4] Apakah server SATUSEHAT juga memeriksa klaimmeta.profilesecara penuh: belum terverifikasi (diakses 2026-10-26). - Aturan format yang sering membuat ditolak: waktu dikirim dalam UTC +00 (17.35 WIB →
2023-08-23T10:35:00+00:00) dan tanggal tidak boleh sebelum 3 Juni 2014; elemen wajib atau tidak mengikuti panduan per use case. [5] - Validasi di production itu trade-off. Spesifikasi menyarankan validasi saat development, tapi memperingatkan di production: validasi penuh dengan terminologi mahal, bisa menyebabkan "the loss of critical health care data" karena satu field buruk, dan bisa menolak data historis yang tidak bisa diperbaiki. Anjurannya Postel's law: konservatif saat mengirim, liberal saat menerima. [2] Terjemahan untuk desain Node: validasi sebelum kirim, dan record yang ditolak disimpan bersama OperationOutcome-nya untuk diperbaiki, bukan dibuang.
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]
| Data | Standar di SATUSEHAT | Contoh dari dokumentasi |
|---|---|---|
Diagnosis (Condition.code) | ICD-10 versi 2010 | http://hl7.org/fhir/sid/icd-10 · C47.0 [7] |
| Prosedur dan tindakan medis | ICD-9 CM versi 2010 | (lihat lampiran terminologi) |
Penamaan uji laboratorium (Observation.code) | LOINC | http://loinc.org · 8867-4 Heart rate [8] |
| Istilah klinis | SNOMED CT | http://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]
- Satu arah: "Mappings are one way - from the source to the target system"; kebalikannya tidak bisa diasumsikan benar.
- Terikat konteks: mapping hanya berlaku untuk use case bisnis tertentu; contoh resminya SNOMED CT → ICD-10 untuk analisis data berbeda dengan untuk billing.
- Equivalence per target:
equivalent,equal,wider,narrower,inexact,unmatched,disjoint, dll.; untuknarrowerdaninexactalasannya SHALL dijelaskan dicomment. [11] - Bukan transformasi struktur: ConceptMap memetakan konsep; transformasi instance (tabel → resource) adalah wilayah StructureMap. ConceptMap tidak dirujuk langsung dari resource lain.
- Dipakai lewat
$translate: terminology server menerjemahkansystem+codeberdasarkan ConceptMap; client harus memeriksaequivalencesetiap hasil. [12]
// 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 tabelpasien,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
systemper 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? $validatemengembalikan 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.
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)