# CPONE Middleware Go ## Deploy ke server Tool deploy melakukan test, vet, build binary `linux/amd64`, upload melalui `scp`, mengganti binary secara atomik, membuat backup binary sebelumnya, lalu me-restart service melalui systemd. Untuk server development yang sudah dikonfigurasi: ```bash make deploy one@devcpone.aplikasi.web.id ``` Bentuk eksplisit yang setara: ```bash make deploy DEPLOY_TARGET=one@devcpone.aplikasi.web.id ``` Default deploy menggunakan: - direktori aplikasi: diambil dari `WorkingDirectory` service (otomatis), atau `$HOME/apps` bila service tidak mendefinisikannya - binary: `/cpone-middleware` - service: `cpone-middleware.service` - service manager: otomatis mendeteksi systemd user (`systemctl --user`) atau systemd system (`systemctl`) - restart: menghentikan `MainPID`, lalu systemd `Restart=always` menyalakan binary baru - SSH memiliki timeout koneksi dan keepalive agar deploy tidak menggantung Jika server memakai izin systemd untuk `restart`, gunakan: ```bash make deploy one@host.example SERVICE=cpone-middleware.service RESTART_MODE=systemctl ``` Untuk direktori khusus, gunakan `REMOTE_DIR=/path/apps`. Untuk target lama `one@devcpone.aplikasi.web.id`, hasil default tetap `/home/one/apps`. Target server harus sudah dapat diakses dengan SSH key/agent; tool tidak menyimpan atau mengirim `.env` lokal. Service Go untuk endpoint: ```text GET /api/cpone/paket GET /api/cpone/paket/{id} Authorization: Bearer POST /api/cpone/paket Authorization: Bearer Content-Type: application/json 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/doctors?search=&DokterID_in=&page=1&per_page=15 GET /api/doctors?search=&DokterID_in=&page=1&per_page=15 Authorization: Bearer X-RS-Code: Endpoint ini menampilkan daftar dokter aktif dari HIS. Parameter `search` hanya mencari berdasarkan nama dokter atau kode dokter (`DokterID`). 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 GET /api/cpone/reports/mcu?tanggal=2026-09-01&tanggal2=2026-09-07 Authorization: Bearer X-RS-Code: 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. Endpoint laporan MCU mengembalikan JSON dengan envelope standar `success`, `message`, dan `data`. Setiap item `data` mempertahankan kolom yang ditulis oleh `docs/lap_mcu.php`, termasuk nilai fallback seperti `Tidak Ada`, `Normal`, dan `UMUM`. Alias kompatibel yang tersedia adalah `/api/cpone/laporan/mcu` dan `/api/cpone/laporan-mcu` serta `/api/cpone/lap-mcu`. Query laporan membutuhkan privilege `SELECT` pada tabel MCU legacy: `pengkajianmcu`, `tandavital_pasien`, `regpas_detail`, `gayahidup`, `riwayatpenyakitdahulu`, `riwayatpenyakitkeluarga`, `riwayatalergi`, seluruh tabel `pemeriksaanfisik_*` yang dipakai laporan, `pemeriksaankhusus`, dan `penyakitakibatkerja`. Contoh payload pembuatan paket beserta layanan: ```json { "nama": "PAKET MCU CPONE TES 2", "jenis_paket": "MCU", "rawat_inap": false, "rawat_jalan": true, "multi_visit": false, "tanggal_mulai": "2026-09-01", "tanggal_selesai": "2026-09-30", "kelas_id": "Default", "header_paket_id": "", "keterangan": "", "layanan": [ { "layanan_id": "1200", "departemen_id": "MED-PNJ-LAB", "jumlah": 1, "jumlah_hari": 1, "harga": "130000.00", "tipe_diskon": "Percentage", "diskon": "0.00", "tipe_share": "Absolute", "share_rs": "65000.00", "share_dokter": "0.00", "share_external": "65000.00", "share_lain": "0.00" } ] } ``` Endpoint mengembalikan HTTP 201 dengan format standar middleware: ```json { "success": true, "status": "created", "message": "Paket berhasil dibuat", "data": { "paket_id": "DISP-260900022", "nama": "PAKET MCU CPONE TES 2", "total_harga": "130000.00", "total_diskon": "0.00", "jumlah_layanan": 1 } } ``` Contoh payload pembuatan pasien HIS: ```json { "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. Registrasi pasien umum/MCU menggunakan endpoint berikut. Jika `medrec_id` belum diisi dan pasien tidak ditemukan, caller dapat membuat pasien melalui endpoint medrec lalu mengulangi request registrasi. `departemen_id` dapat dikosongkan; middleware akan memakai `CPONE_DEPARTEMEN_ID` dari `.env`. ```http POST /api/cpone/patients/registration Authorization: Bearer X-RS-Code: Content-Type: application/json ``` ```json { "medrec_id": "00001234", "nik": "317xxxxxxxxxxxx", "tgl_lahir": "1988-03-03", "tanggal": "2026-09-07", "dokter_id": "D260900003", "jenis_pasien_id": "1", "jenis_reg_id": 2, "periode_tarif_id": "10", "perusahaan_id": "", "asuransi_id": "", "group_tarif_id": "0", "nomer_polis": "", "kelas_id": "Default", "channel": "CPONE" } ``` Endpoint ini idempoten untuk pasien, tanggal, departemen, dan dokter yang sama; registrasi aktif yang sudah ada dikembalikan dengan status `already_registered_visit`. 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 Setiap instalasi CPONE hanya terhubung ke satu database HIS. Copy `.env.example` menjadi `.env`, lalu isi kode instance dan koneksi MySQL HIS: ```text APP_HOST=0.0.0.0 APP_PORT=8080 CPONE_RS_CODE=AWALBROS_DEV CPONE_DEPARTEMEN_ID=08_01 CPONE_DB_HOST=127.0.0.1 CPONE_DB_PORT=3306 CPONE_DB_DATABASE=nama_database_his CPONE_DB_USERNAME=cpone CPONE_DB_PASSWORD= CPONE_BEARER_TOKEN=replace-with-a-secure-token ``` `CPONE_DB_*` adalah koneksi database HIS, bukan database management CPONE. Password hanya dibaca dari `.env`; aplikasi tidak menyimpan kredensial database ke database lain. `CPONE_DEPARTEMEN_ID` adalah `DepartemenID` HIS yang digunakan untuk registrasi laboratorium. Nilai ini diambil dari konfigurasi, sehingga tidak perlu dikirim di payload endpoint registrasi. Semua endpoint bisnis tetap membutuhkan header: ```http X-RS-Code: PRIMAYA_BEKASI_BARAT ``` Sebagai alternatif dapat memakai query `?kode_rs=AWALBROS_DEV`. Header memiliki prioritas lebih tinggi daripada query. Kode tersebut hanya divalidasi terhadap `CPONE_RS_CODE`; kode tidak digunakan untuk memilih database. Request tanpa kode mengembalikan `422`, sedangkan kode untuk instance rumah sakit lain mengembalikan `403`. Response sukses tetap mengembalikan header `X-RS-Code`. Payload `POST /api/cpone/patients/medrec` tidak lagi membutuhkan field `rs`. Nilai `KodeRS` untuk kebutuhan internal HIS diisi dari `CPONE_RS_CODE`. ## 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.