# CPONE Middleware Go Service Go untuk endpoint: ```text GET /api/cpone/paket GET /api/cpone/paket/{id} Authorization: Bearer GET /api/cpone/layanan?page=1 Authorization: Bearer X-RS-Code: GET /api/cpone/perusahaan?search=&page=1 GET /api/cpone/perusahaan/{id} GET /api/cpone/perusahaan/{id}/group-tarif?group_tarif_id= Authorization: Bearer X-RS-Code: GET /api/cpone/tarif-kerjasama?search=&perusahaan_id=&tarif_id=&page=1&per_page=15 Authorization: Bearer GET /api/cpone/tarif-kerjasama/{id}?group_tarif_id=&active=N&effective_date=2026-08-22 Authorization: Bearer GET /api/cpone/periode-tarif Authorization: Bearer X-RS-Code: Endpoint ini menampilkan seluruh periode tarif dari HIS dengan `NA = 'N'`. GET /api/cpone/periode-tarif/{PeriodeTarifID}?search=&page=1 Authorization: Bearer X-RS-Code: Endpoint ini mengambil detail seluruh tarif layanan dari tabel dinamis `harga_layanan_{PeriodeTarifID}` beserta layanan, departemen, dan kelas tarif. Parameter `search` mencari berdasarkan `LayananID` atau `NamaLayanan`; hasil dipaginasi 20 data per halaman. GET /api/cpone/layanan-mapping-harga?periodeTarifID=10&layananID=6413,6414,1309 Authorization: Bearer POST /api/cpone/patients/lab-registration Authorization: Bearer Content-Type: application/json POST /api/cpone/patients/lab-registration/{regId}/services Authorization: Bearer Content-Type: application/json POST /api/cpone/patients/lab-registration/{regId}/packages Authorization: Bearer Content-Type: application/json POST /api/cpone/patients/medrec Authorization: Bearer Content-Type: application/json ``` Format payload dan response dibuat mengikuti controller PHP CPONE terkait. Contoh payload pembuatan pasien HIS: ```json { "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: ```json { "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: ```json { "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: ```json { "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: ```text 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. ```http POST /api/cpone/database-settings Authorization: Bearer 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: ```text POST /api/cpone/database-settings GET /api/cpone/database-settings GET /api/cpone/database-settings/{kodeRs} ``` Daftar ringkas rumah sakit aktif dapat diambil tanpa memilih database HIS: ```http GET /api/cpone/hospitals Authorization: Bearer ``` Response hanya memuat `kode_rs`, `nama`, dan `status`; rumah sakit nonaktif tidak ditampilkan. 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: ```http 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 ```bash 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.