Files
cpone_midleware/README.md

6.6 KiB

CPONE Middleware Go

Service Go untuk endpoint:

GET /api/cpone/paket
GET /api/cpone/paket/{id}
Authorization: Bearer <your-secure-token>

GET /api/cpone/layanan?page=1
Authorization: Bearer <your-secure-token>
X-RS-Code: <kode-rs>

GET /api/cpone/perusahaan?search=&page=1
GET /api/cpone/perusahaan/{id}
GET /api/cpone/perusahaan/{id}/group-tarif?group_tarif_id=
Authorization: Bearer <your-secure-token>
X-RS-Code: <kode-rs>

GET /api/cpone/tarif-kerjasama?search=&perusahaan_id=&tarif_id=&page=1&per_page=15
Authorization: Bearer <your-secure-token>

GET /api/cpone/tarif-kerjasama/{id}?group_tarif_id=&active=N&effective_date=2026-08-22
Authorization: Bearer <your-secure-token>

GET /api/cpone/layanan-mapping-harga?periodeTarifID=10&layananID=6413,6414,1309
Authorization: Bearer <your-secure-token>

POST /api/cpone/patients/lab-registration
Authorization: Bearer <your-secure-token>
Content-Type: application/json

POST /api/cpone/patients/lab-registration/{regId}/services
Authorization: Bearer <your-secure-token>
Content-Type: application/json

POST /api/cpone/patients/lab-registration/{regId}/packages
Authorization: Bearer <your-secure-token>
Content-Type: application/json

POST /api/cpone/patients/medrec
Authorization: Bearer <your-secure-token>
Content-Type: application/json

Format payload dan response dibuat mengikuti controller PHP CPONE terkait.

Contoh payload pembuatan pasien HIS:

{
  "rs": "PRIMAYA",
  "nama": "BUDI SANTOS",
  "jenis_kelamin": "L",
  "tgl_lahir": "1990-01-15",
  "jenis_nomer_sosial": "KTP",
  "nomer_sosial": "3174011501900001",
  "telepon": "081234567890",
  "ponsel": "081234567890",
  "email": "budi@example.com",
  "tempat_lahir": "JAKARTA",
  "alamat": "JL. CONTOH NO. 1",
  "propinsi": "DKI JAKARTA",
  "kabupaten": "JAKARTA",
  "kecamatan": "KECAMATAN CONTOH",
  "kelurahan": "KELURAHAN CONTOH",
  "kode_pos": "12345",
  "perusahaan_id": "PE260700001",
  "nik_karyawan": "TSB2026002",
  "dependant_id": "D001",
  "nama_karyawan": "BUDI SANTOS",
  "channel": "CPONE"
}

Endpoint mengembalikan created, already_exists, atau possible_duplicate sesuai hasil pemeriksaan identitas dan kemiripan data pasien di HIS.

Contoh payload registrasi laboratorium:

{
  "medrec_id": "00001234",
  "tanggal": "2026-08-18",
  "departemen_id": "LAB",
  "dokter_id": "DR01",
  "dokter_pengirim_id": "DR02",
  "perujuk": null,
  "jenis_pasien_id": "0",
  "periode_tarif_id": 10,
  "kelas_id": "Default",
  "shift_harian_id": null,
  "diagnosa_kerja": "Pemeriksaan laboratorium",
  "catatan": null,
  "channel": "CPONE"
}

dokter_pengirim_id atau perujuk wajib diisi. Endpoint ini membuat registrasi laboratorium tanpa layanan, sama seperti PatientController::registerLab; layanan ditambahkan melalui endpoint terpisah.

Contoh payload penambahan layanan:

{
  "layanan": [
    {
      "layanan_id": "6413",
      "jumlah": 1,
      "cito": false,
      "markup_cito": 0,
      "catatan": null
    }
  ],
  "channel": "CPONE"
}

Harga, diskon publik, share, unit cost, layanan multiple, dan spesimen diambil langsung dari master HIS. Layanan yang sudah ada akan dilewati dan dilaporkan melalui skipped_layanan_ids.

Contoh payload penambahan Paket Dispenser HIS:

{
  "paket_id": "DISP-260800011",
  "cito": false,
  "markup_cito": 0,
  "catatan": "",
  "channel": "CPONE"
}

Paket harus aktif, disetujui, berlaku untuk rawat jalan, dan belum memiliki layanan yang sama pada registrasi. Request ulang untuk paket yang sudah masuk bersifat idempoten dan tidak membuat transaksi ganda.

Config

Copy .env.example menjadi .env, lalu isi koneksi MySQL:

APP_HOST=0.0.0.0
APP_PORT=8080
CPONE_DB_HOST=127.0.0.1
CPONE_DB_PORT=3306
CPONE_DB_DATABASE=cpone_middleware
CPONE_DB_USERNAME=root
CPONE_DB_PASSWORD=
CPONE_BEARER_TOKEN=replace-with-a-secure-token
CPONE_DATABASE_SETTINGS_TOKEN=replace-with-a-different-admin-token
CPONE_DATABASE_CREDENTIAL_KEY=replace-with-a-long-random-encryption-key

Multi-database per kode RS

Tambahkan atau perbarui koneksi RS melalui API berikut. Koneksi akan dites sebelum disimpan; bila Ping gagal, setting tidak disimpan.

POST /api/cpone/database-settings
Authorization: Bearer <your-database-settings-token>
Content-Type: application/json

{
  "kode_rs": "PRIMAYA_BEKASI_BARAT",
  "nama": "Primaya Hospital Bekasi Barat",
  "host": "10.10.10.20",
  "port": "3306",
  "database": "his_bekasi_barat",
  "username": "cpone",
  "password": "secret"
}

Endpoint pengelolaan yang tersedia:

POST /api/cpone/database-settings
GET  /api/cpone/database-settings
GET  /api/cpone/database-settings/{kodeRs}

Saat startup, service otomatis membuat database CPONE_DB_DATABASE beserta tabel hospitals dan hospital_databases. Tidak ada database RS default; semua koneksi HIS harus ditambahkan lewat API. Akun CPONE_DB_USERNAME harus memiliki izin CREATE DATABASE pada bootstrap pertama; alternatifnya jalankan migration di direktori database/migrations secara manual.

Response list/detail tidak pernah menampilkan password, hanya field has_password. Password koneksi RS disimpan terenkripsi AES-GCM menggunakan CPONE_DATABASE_CREDENTIAL_KEY. Jangan mengubah key tersebut setelah data mulai disimpan karena password lama tidak akan bisa didekripsi. Jika key belum diisi, service memakai CPONE_DATABASE_SETTINGS_TOKEN, lalu CPONE_BEARER_TOKEN sebagai fallback; token fallback itu juga tidak boleh diubah tanpa rotasi credential.

Endpoint pengelolaan memakai CPONE_DATABASE_SETTINGS_TOKEN. Jika variabel ini belum diisi, service memakai CPONE_BEARER_TOKEN untuk kompatibilitas; gunakan token admin yang berbeda di production.

Pilih database pada semua endpoint bisnis dengan header:

X-RS-Code: PRIMAYA_BEKASI_BARAT

Sebagai alternatif dapat memakai query ?kode_rs=PRIMAYA_BEKASI_BARAT. Header memiliki prioritas lebih tinggi daripada query. Response juga memuat header X-RS-Code agar koneksi yang terpilih mudah diaudit. Salah satu dari header atau query tersebut wajib dikirim; jika tidak ada, API mengembalikan status 422 dan tidak mengakses database HIS.

Run

cd cpone-middleware
go mod tidy
go run ./cmd/server

SQLC

File sqlc.yaml, sqlc/schema.sql, dan sqlc/query.sql sudah disiapkan.

Catatan penting: sqlc tidak bisa menerima nama tabel dinamis seperti harga_layanan_{periodeTarifID}. Implementasi runtime saat ini tetap memakai database/sql untuk menyusun nama tabel setelah periodeTarifID divalidasi angka, sama seperti PHP memakai HargaLayanan::makeTableName(). Kalau semua periode ingin digenerate oleh sqlc, buat query konkret per tabel periode, misalnya harga_layanan_10, harga_layanan_11, dan seterusnya.