Compare commits

118 Commits

Author SHA1 Message Date
Hanan Askarim
43342bf361 add api poli 2026-06-22 15:00:49 +07:00
Hanan Askarim
cf648ac9ba fix birt proxy 2026-06-17 11:40:27 +07:00
sas.fajri
b7c752df84 FHM09062601IBL - fix fn_numbering_klinik reference one.m_branch to one_lab.m_branch
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 16:06:38 +07:00
sas.fajri
0cf019ddf7 FHM08062601IBL - add M_PatientPhoto to sp_rpt_fo_001 for kartu kontrol photo
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 15:50:07 +07:00
sas.fajri
5e1371a248 FHM08062601IBL - decrypt patient address description on delivery search
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 15:17:38 +07:00
Hanan Askarim
b713289b82 add api birt proxy nonlab 2026-06-15 11:53:45 +07:00
sas.fajri
8e72a9f067 FHM15062601SAS - add pending task markdown 2026-06-15 11:20:04 +07:00
sas.fajri
cb45fabe1c FHM09062601IBL - unmask cashier patient search name 2026-06-12 16:23:05 +07:00
sas.fajri
5695a40fe1 FHM09062601IBL - keep payment payload backward compatible 2026-06-12 16:02:39 +07:00
sas.fajri
b653f0e987 FHM09062601IBL - move anamnesis visit info to php 2026-06-12 15:52:43 +07:00
sas.fajri
4a9406cd28 FHM09062601IBL - move patient visit info to php 2026-06-12 15:49:34 +07:00
sas.fajri
1601ec6573 FHM09062601IBL - guard patient visit search info 2026-06-12 15:42:19 +07:00
sas.fajri
567f85a0b9 FHM09062601IBL - split klinik payment before ibl 2026-06-12 15:15:47 +07:00
sas.fajri
9eb92eb340 FHM09062601IBL - add order klinik to save response 2026-06-12 14:47:43 +07:00
sas.fajri
ebd2217921 FHM09062601IBL - fix ibl load klinik tests 2026-06-12 14:26:39 +07:00
sas.fajri
17acf294ba FHM09062601IBL - cashierklinik/patient/search: PDP decrypt M_PatientName, fix bidx search
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:50:52 +07:00
sas.fajri
b08ddb68b1 FHM09062601IBL - fix load_klinik tests: T_PriceIsCito AS T_TestIsCito dari ss_price_mou
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:40:29 +07:00
sas.fajri
e8f598c98d FHM09062601IBL - fix load_klinik tests: T_TestIsCito dari ss_price_mou sesuai referensi v35
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:39:29 +07:00
sas.fajri
d0547e38bb FHM09062601IBL - load_klinik: tangkap SQL error di tests query untuk debug
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:38:04 +07:00
sas.fajri
83045fac9a FHM09062601IBL - fix load_klinik tests: T_TestIsCito dari JOIN t_test bukan ss_price_mou
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:36:54 +07:00
sas.fajri
fac5dcb34d FHM09062601IBL - fix load_klinik tests: ganti db_onedev ke db_smartone, tambah schema one_lab ke ss_price_mou
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:35:55 +07:00
sas.fajri
0550497a16 FHM09062601IBL - load_klinik tests format identik registration_v37 selectPx
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:40 +07:00
sas.fajri
667d8d2a1d FHM09062601IBL - trigger sync_order_total: update orderSubtotal+orderTotal otomatis
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:40 +07:00
sas.fajri
6a1bee3656 FHM09062601IBL - ibl_registration/order/save: link klinik order via klinik_number
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:40 +07:00
sas.fajri
c80bd8b6c1 FHM09062601IBL - ibl_registration/order/load_klinik: endpoint baru dengan decrypt PDP
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:40 +07:00
sas.fajri
917115684c FHM09062601IBL - getdefaultmou: support ambil MOU dari order jika orderid dikirim
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:40 +07:00
sas.fajri
e3be8d6b14 FHM09062601IBL - klinik/patient/search: bidx search + decrypt patient_name
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:40 +07:00
sas.fajri
1b8e00b57e FHM09062601IBL - list_patient: decrypt patient_name dari _enc untuk tampilan asli
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:40 +07:00
sas.fajri
d57bbaec38 FHM09062601IBL - get_resume_medic: tambah vaksinasi_list dan tindakan_medis_list
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:39 +07:00
sas.fajri
d04d8add35 FHM09062601IBL - saveorder: simpan tests ke order_detail_order + create table
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:39 +07:00
sas.fajri
414a3765f7 FHM09062601IBL - Registrationv3: tambah search_test, mouid dari FE
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:39 +07:00
sas.fajri
b18dfa3495 FHM09062601IBL - fix list_order_tindakan: JOIN m_doctor ke one_lab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:39 +07:00
sas.fajri
39f4626cdf FHM09062601IBL - tambah fitur tindakan medis: table order_tindakan + 4 endpoint
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:39 +07:00
sas.fajri
e5d5dfd48a FHM09062601IBL - get_vaccines: filter px_type = PX
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:39 +07:00
sas.fajri
cd795497a7 FHM09062601IBL - order_vaccine: tambah kolom harga (ss_price_mou_id, bruto, disc, total)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:39 +07:00
sas.fajri
e1b91403ed FHM09062601IBL - get_vaccines: decode nat_test dan child_test jadi array
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:38 +07:00
sas.fajri
ce2068d24a FHM09062601IBL - get_vaccines: return format lengkap sama seperti search_test supervisor
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:38 +07:00
sas.fajri
f1bbb2a932 FHM09062601IBL - get_vaccines: tambah harga (bruto, discountpersen, discountrp, total)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:38 +07:00
sas.fajri
520c77484b FHM09062601IBL - filter get_vaccines: is_packet = N di ss_price_mou
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:38 +07:00
sas.fajri
e3c9909c84 FHM09062601IBL - tambah kolom KIPI, observasi 15 menit, reaksi alergi ke order_vaccine
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:38 +07:00
sas.fajri
11860743b8 FHM09062601IBL - petugas penyuntik: autocomplete dari m_staff, ganti kolom ke M_StaffID
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:38 +07:00
sas.fajri
77a595eba4 FHM09062601IBL - refactor get_vaccines: autocomplete jenis vaksin by order MOU, pisahkan list_order_vaccines
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:38 +07:00
sas.fajri
6858814948 FHM09062601IBL - tambah endpoint vaksin di doctorv5/Anamnesedoctor + create order_vaccine
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:38 +07:00
sas.fajri
0e2df4612a FHM09062601IBL - create m_injection_site dan m_route_vaccine di one_klinik
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:37 +07:00
sas.fajri
98748620dd FHM09062601IBL - fix Ttv: set orderDoctorType FORM saat insert order_doctor
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:37 +07:00
sas.fajri
1bdb54d1c2 FHM09062601IBL - fix mcuofflineapp Preregisterapp: apply PDP compliance (mask/enc/bidx)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:37 +07:00
sas.fajri
f8d487079b FHM09062601IBL - update runbook PDP: field tabel, DOB VARCHAR, NIK_bidx dari IDNumber, migration steps baru
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:37 +07:00
sas.fajri
83bd46d521 FHM09062601IBL - update CLAUDE.md: tambah list migration PDP dan catatan DOB VARCHAR
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:37 +07:00
sas.fajri
49df769c58 FHM09062601IBL - alter m_patient M_PatientDOB ke VARCHAR untuk simpan nilai masked
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:37 +07:00
sas.fajri
9e68c1cedd FHM09062601IBL - alter mcu_preregister_patients DOB ke VARCHAR untuk simpan nilai masked
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:37 +07:00
sas.fajri
16316aaa31 FHM09062601IBL - fix Preregister: masking M_PatientDOB dan Mcu_PreregisterPatientsDOB
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:37 +07:00
sas.fajri
a90b0f96c7 FHM09062601IBL - fix Preregister savecsv: terapkan PDP pada insert/update/lookup m_patient
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:37 +07:00
sas.fajri
ece137df06 FHM09062601IBL - update CLAUDE.md: tambah catatan pola PDP NIK_bidx diisi dari IDNumber
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:37 +07:00
sas.fajri
2692c98ef2 FHM09062601IBL - fix registrationv3: IDNumber_bidx simpan ke M_PatientNIK_bidx, search e[3] pakai JSON_CONTAINS NIK_bidx
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:36 +07:00
sas.fajri
7c8b1ad36b FHM09062601IBL - fix registrationv3 search: kembalikan AND antar-field, e[3] pakai M_PatientIDNumber LIKE (bukan NIK bidx)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:36 +07:00
sas.fajri
c1f874b96b FHM09062601IBL - fix registrationv3 search: ganti AND antar-field jadi OR, e[3] cari M_PatientIDNumber bukan M_PatientNIK_bidx
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 13:33:36 +07:00
Hanan Askarim
e73fccee17 fix generate order rujukan delevery 2026-06-12 09:03:56 +07:00
Hanan Askarim
2978ecc93d update konfrimasi penerimaan rujukan 2026-06-11 15:10:42 +07:00
sas.fajri
9430b00ee6 FHM09062601IBL - registrationv3/search hapus field alamat dari response (terenkripsi)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 11:11:51 +07:00
sas.fajri
0e590f5959 FHM09062601IBL - samplingcall/search filter klinik order ganti orderIsScreening='D' ke orderIsTTV='D'
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 10:59:08 +07:00
sas.fajri
710dbaaec1 FHM09062601IBL - ttv/search sesuaikan data pasien dg screening list: order.*, semua _enc field, patient_name
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 10:44:13 +07:00
sas.fajri
1e87def6a7 FHM09062601IBL - buat controller Ttv (search, getttv, savettv, getsexreg) + kolom orderIsTTV
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 10:24:06 +07:00
sas.fajri
c78f53fc18 FHM09062601IBL - search() merge answer ke options: option terpilih value:true, sesuaikan format object
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 09:47:38 +07:00
sas.fajri
67bb072e0d FHM09062601IBL - simpan T_ScreeningAnswerValue sebagai JSON object bukan string
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 09:46:36 +07:00
sas.fajri
655757599a FHM09062601IBL - end_session delegate ke endsession agar FE existing langsung pakai logic baru
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 09:42:22 +07:00
sas.fajri
ee3ec98f44 FHM09062601IBL - tambah endpoint endsession: simpan screening DEFAULT ke order_screening, dinamis ke t_screening_answer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 09:31:51 +07:00
sas.fajri
b45f284784 FHM09062601IBL - buat t_screening_answer, update screening/search return template+forms dinamis vs DEFAULT
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 08:58:03 +07:00
sas.fajri
beb11cc40f FHM09062601IBL - update id option screening jadi unique per form (format f{formID}o{optionIdx})
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 08:16:45 +07:00
sas.fajri
2a936217c7 FHM09062601IBL - update format options screening ke array-of-objects, tambah mapping template ke clinic unit
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:50:33 +07:00
sas.fajri
f39b28361e FHM09062601IBL - buat tabel m_screening_template dan m_screening_form, isi data template VAKSINASI dan KHITAN
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:41:57 +07:00
sas.fajri
270f71f5ea FHM09062601IBL - fix saveorder SQL 1064: tambah ? untuk orderM_MouID, handle param m_mouid dari FE
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:30:48 +07:00
sas.fajri
25f17896d4 FHM09062601IBL - saveorder: harga dari FE (bukan dokter), mou_id dari FE
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:44 +07:00
sas.fajri
71d64c6637 FHM09062601IBL - registrasi klinik: tambah endpoint searchcompany dan getmoubycompany
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:44 +07:00
sas.fajri
eed0c8fe0d FHM09062601IBL - saveorder: simpan orderM_ClinicUnitID, orderM_CompanyID, orderM_MouID
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:43 +07:00
sas.fajri
beac903397 FHM09062601IBL - alter order tambah orderM_CompanyID (orderM_MouID sudah ada)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:43 +07:00
sas.fajri
16fcf81c00 FHM09062601IBL - registrasi klinik: tambah endpoint getpoli, alter order tambah orderM_ClinicUnitID
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:43 +07:00
sas.fajri
e456ce6354 FHM09062601IBL - create table one_klinik.m_clinic_unit dengan data awal 4 poli
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:43 +07:00
sas.fajri
45e668def3 FHM09062601IBL - tambah task refactor workflow klinik SATUSEHAT readiness
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:43 +07:00
sas.fajri
a599f15ec2 FHM09062601IBL - screening list_patient: tambah _enc columns, decrypt PDP, foto pasien
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:43 +07:00
sas.fajri
ad632ec17c FHM09062601IBL - doctorv5/anamnesedoctor: tambah M_PatientPhoto dan M_PatientPhotoThumb di search
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:43 +07:00
sas.fajri
5e3695a54b FHM09062601IBL - doctorv5/anamnesedoctor: fix regional query (regional_nm, JOIN via pro/kab/kec_cd)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:43 +07:00
sas.fajri
dc586c63f4 FHM09062601IBL - doctorv5/anamnesedoctor: fix kelurahan sub-query, tambah PDP decrypt, gunakan regional
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:42 +07:00
sas.fajri
ae28375cc3 FHM09062601IBL - samplingcall: decrypt PDP fields (nama, HP, email, DOB) di hasil search
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:42 +07:00
sas.fajri
e7894e869d FHM09062601IBL - fix settingM_LocationID klinik dari 11 ke 30
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:42 +07:00
sas.fajri
5d9c170bf4 FHM09062601IBL - samplingcall: fix klinik UNION, hapus filter locationID agar semua order klinik muncul
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:42 +07:00
sas.fajri
eb4af1c67c FHM10062601IBL - tambah catatan meeting klinik internal
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:42 +07:00
sas.fajri
8282acadd5 FHM09062601IBL - samplingcall: debug sementara cek sql dan params
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:41 +07:00
sas.fajri
01994365d4 FHM09062601IBL - samplingcall: tambah UNION klinik order dari one_klinik.order
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:41 +07:00
sas.fajri
9dd4afed4a FHM09062601IBL - screening: tambah getsexreg sama seperti registrationv3
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:41 +07:00
sas.fajri
f1801157c2 FHM09062601IBL - screening search: hapus kelurahan sub-query, tambah PDP decrypt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:41 +07:00
sas.fajri
0c9c67d30f FHM09062601IBL - tambah _mask_dob, terapkan ke newpatient dan editpatient
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:41 +07:00
sas.fajri
32131fdaad FHM09062601IBL - mask M_PatientDOB null di plain column, fix dob decrypt di search
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:40 +07:00
sas.fajri
473b90b697 FHM09062601IBL - newpatient: simpan M_PatientAddressRegionalCd dan field lokasi alamat
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:40 +07:00
sas.fajri
82c3ea5ff0 FHM09062601IBL - getaddress: ganti join ke tabel regional, decrypt address description
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:40 +07:00
sas.fajri
e301eedbeb FHM09062601IBL - fix search registrationv3: hapus kelurahan sub-query, samakan dg ibl_registration
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:40 +07:00
sas.fajri
a5d7174b68 FHM09062601IBL - tambah method searchregion dan search_countries di klinik/Registrationv3
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 16:16:40 +07:00
Hanan Askarim
0f54702aa7 update rujukan internal 2026-06-10 15:47:03 +07:00
sas.fajri
04591d6c32 FHM08062601IBL - rapikan separator detail hasil 2026-06-09 13:52:36 +07:00
sas.fajri
48c61fcfd7 FHM08062601IBL - kembalikan lab result ke birt 2026-06-09 11:52:46 +07:00
sas.fajri
e37512624c FHM08062601IBL - rapikan layout lab result fpdf 2026-06-09 11:31:13 +07:00
sas.fajri
de1fb927de FHM08062601IBL - alihkan lab result ke fpdf 2026-06-09 11:27:26 +07:00
sas.fajri
e3f51591a6 FHM08062601IBL - hotfix print report blank 2026-06-09 11:14:52 +07:00
sas.fajri
085a2dc14a FHM08062601IBL - perbaiki header birt proxy 2026-06-09 11:10:44 +07:00
sas.fajri
686db5ed43 FHM08062601IBL - fix table border: pakai Rect() untuk outer border, row separator via 'B' only
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 09:19:25 +07:00
sas.fajri
6c7aaf0dd0 FHM08062601IBL - fix font Helvetica 10pt (match BIRT Calibri), 3cm kop gap, form_rev pojok kanan atas, fix cell indent
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 09:13:11 +07:00
sas.fajri
934a779770 FHM08062601IBL - tambah footer (Validasi Oleh, Printed by, page number), fix table outer border, QR absolute di atas footer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 09:05:24 +07:00
sas.fajri
fcd125a252 FHM08062601IBL - tambah section sampling (sp_rpt_hasil_lab_sampling) dan Catatan di Rpt_lab_result
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 09:00:26 +07:00
sas.fajri
24c5d2d94f FHM08062601IBL - refactor Rpt_lab_result: pakai sp_rpt_hasil_lab, sesuaikan layout header & grouping 3 level dengan referensi BIRT
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 08:57:07 +07:00
sas.fajri
910e1cd08a FHM08062601IBL - fix nama tabel s_systems ke conf_systems di Rpt_lab_result
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 08:42:23 +07:00
Hanan Askarim
1cce2b52dc Merge branch 'main' of https://devone.aplikasi.web.id/gitea/fajri/BE_IBL 2026-06-09 08:41:39 +07:00
Hanan Askarim
bff1943054 fix generate qr report di lab 2026-06-09 08:41:31 +07:00
sas.fajri
77c00e0dd0 FHM08062601IBL - fix access level db_onedev jadi public di Rpt_lab_result
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 08:40:39 +07:00
sas.fajri
c4e590d153 FHM08062601IBL - tambah Rpt_lab_result FPDF controller untuk generate lab result PDF tanpa BIRT
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 08:39:21 +07:00
sas.fajri
e797013148 FHM08062601IBL - dokumentasi PDP encryption & BIRT proxy stream pattern di CLAUDE.md dan AGENTS.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 16:46:27 +07:00
sas.fajri
212e27ff72 FHM08062601IBL - fix get_report_codes_by_group pakai kode print_transaction yg benar, tambah rpt_code/e_rpt_code di groups output untuk stream_by_code
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 16:43:14 +07:00
sas.fajri
7e3cd75ce5 FHM08062601IBL - ganti pre_cache/delete_cache dengan proxy stream pattern: Reporturl semua kode lewat stream_by_code, tambah stream_report di Rv_patient untuk resultprintadm-v7
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 16:34:40 +07:00
sas.fajri
edf60f5574 FHM08062601IBL - tambah endpoint delete_cache di Rv_patient untuk hapus patient_print_cache setelah BIRT selesai load
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 16:31:34 +07:00
sas.fajri
3138c7f508 FHM08062601IBL - tambah endpoint pre_cache di Rv_patient untuk populate patient_print_cache sebelum BIRT dipanggil dari Vue
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 16:28:15 +07:00
60 changed files with 9203 additions and 1466 deletions

View File

@@ -10,6 +10,74 @@
- Before every `commit` and `push`, always check first whether local branch needs to pull/rebase from remote.
- To upload to IBL, run `bash scripts/upload_ibl_committed_files.sh`. Only run this when the user explicitly asks to upload to IBL. Do not run automatically after commit/push.
## PDP Encryption & BIRT Report
UU PDP No. 27/2022 mengharuskan enkripsi PII pasien. `M_PatientDOB`, `M_PatientName`, dll
di-mask NULL di kolom plain, nilai asli ada di kolom `_enc` (AES-256-GCM).
### Pola wajib: PHP Proxy Stream
BIRT membaca dari tabel `patient_print_cache`. Cache harus di-populate PHP sebelum BIRT
dipanggil, dan dihapus segera setelah PDF di-stream.
```
FE → PHP proxy → populate cache → fetch BIRT → delete cache → stream PDF
```
**Jangan pernah** buat FE langsung build URL `/birt/frameset?...` lalu set ke iframe/window.open
tanpa lewat PHP proxy — cache tidak akan pernah terisi, data pasien kosong di report.
### Endpoint proxy yang tersedia
```
GET /one-api-lab/tools/birt_proxy/stream_by_code
Params: token, report_code (print_transaction code), PT_OrderHeaderID
Return: binary PDF
```
Untuk BE yang perlu return URL ke FE, gunakan `Reporturl` library:
```php
$this->load->library('reporturl');
[$ok, $url] = $this->reporturl->get_report_url_by_code($report_code, [
'PT_OrderHeaderID' => $order_id,
'PUsername' => $username,
]);
// $url sudah mengarah ke stream_by_code — tidak perlu populate/delete cache manual
```
### Daftar print_transaction code
| Group | Print siap | Print belum siap | Email |
|-------|-----------|-----------------|-------|
| LAB | `LAB-RESULT-P-01` | `LAB-RESULT-NP-01` | `LAB-RESULT-P-02` |
| LAB (Inggris) | `LABEN-RESULT-P-01` | `LABEN-RESULT-NP-01` | `LABEN-RESULT-P-02` |
| Mikro (terlampir) | `MIKRO-RESULT-P-01` | `MIKRO-RESULT-NP-01` | `MIKRO-RESULT-P-02` |
| Mikro (tidak terlampir) | `LAB-RESULT-P-01` | `LAB-RESULT-NP-01` | `LAB-RESULT-P-02` |
| Mikro (Inggris) | `MIKROEN-RESULT-P-01` | `MIKROEN-RESULT-NP-01` | `MIKROEN-RESULT-P-02` |
| FNA | `FNA-RESULT-P-01` | `FNA-RESULT-NP-01` | `FNA-RESULT-P-02` |
| Patologi Anatomi | `PA-RESULT-P-01` | `PA-RESULT-NP-01` | `PA-RESULT-P-02` |
| Papsmear | `PAP-RESULT-P-01` | `PAP-RESULT-NP-01` | `PAP-RESULT-P-02` |
| Pap Smear LCP | `PAPLCP-RESULT-P-01` | `PAPLCP-RESULT-NP-01` | `PAPLCP-RESULT-P-02` |
| Pap Smear LCP (Inggris) | `PAPLEN-RESULT-P-01` | `PAPLEN-RESULT-NP-01` | `PAPLEN-RESULT-P-02` |
| Preparasi Sperma | `PS-RESULT-P-01` | `PS-RESULT-NP-01` | `PS-RESULT-P-02` |
| DFI | `DFI-RESULT-P-01` | `DFI-RESULT-NP-01` | `DFI-RESULT-P-02` |
| Cytologi | `CT-RESULT-P-01` | `CT-RESULT-NP-01` | `CT-RESULT-P-02` |
### Deteksi modul yang belum difix
Cari pola ini di FE:
```
/birt/frameset?__report=
```
Kalau ditemukan di JS/Vue yang langsung set ke iframe/object/window.open tanpa lewat PHP
proxy, itu harus diganti ke `stream_by_code`.
### Library terkait
- `application/libraries/Ibl_patient_decrypt.php` — populate/delete `patient_print_cache`
- `application/libraries/Ibl_sampling_normal.php` — pengganti `fn_sampling_get_normal` MySQL function (semua `Re_px.php` sudah diupdate)
- `application/controllers/tools/Birt_proxy.php` — proxy stream handler
## graphify
This project has a graphify knowledge graph at graphify-out/.

View File

@@ -19,6 +19,78 @@
- SSH command: `ssh -i /Users/fajrihardhitamurti/id_rsa -o BatchMode=yes -o StrictHostKeyChecking=accept-new one@10.9.20.31`
- BIRT reports path: `/home/one/project/birt/onelab/reports/`
## PDP Encryption & BIRT Report
Dokumentasi lengkap ada di **`docs/pdp-encryption-runbook.md`**.
Poin penting yang sering terlewat:
- `M_PatientNIK_bidx` diisi dari **`M_PatientIDNumber`**, bukan kolom `M_PatientNIK`
- `M_PatientDOB` bertipe `VARCHAR(20)` (bukan DATE) agar masked value `**-**-YYYY` tersimpan
- `Mcu_PreregisterPatientsDOB` juga `VARCHAR(20)` — tidak punya `_enc`, data asli di `m_patient`
### Pola wajib: PHP Proxy Stream
BIRT membaca dari tabel `patient_print_cache`. Cache harus di-populate PHP sebelum BIRT
dipanggil, dan dihapus segera setelah PDF di-stream.
```
FE → PHP proxy → populate cache → fetch BIRT → delete cache → stream PDF
```
**Jangan pernah** buat FE langsung build URL `/birt/frameset?...` lalu set ke iframe/window.open
tanpa lewat PHP proxy — cache tidak akan pernah terisi, data pasien kosong di report.
### Endpoint proxy yang tersedia
```
GET /one-api-lab/tools/birt_proxy/stream_by_code
Params: token, report_code (print_transaction code), PT_OrderHeaderID
Return: binary PDF
```
Untuk BE yang perlu return URL ke FE, gunakan `Reporturl` library:
```php
$this->load->library('reporturl');
[$ok, $url] = $this->reporturl->get_report_url_by_code($report_code, [
'PT_OrderHeaderID' => $order_id,
'PUsername' => $username,
]);
// $url sudah mengarah ke stream_by_code — tidak perlu populate/delete cache manual
```
### Daftar print_transaction code
| Group | Print siap | Print belum siap | Email |
|-------|-----------|-----------------|-------|
| LAB | `LAB-RESULT-P-01` | `LAB-RESULT-NP-01` | `LAB-RESULT-P-02` |
| LAB (Inggris) | `LABEN-RESULT-P-01` | `LABEN-RESULT-NP-01` | `LABEN-RESULT-P-02` |
| Mikro (terlampir) | `MIKRO-RESULT-P-01` | `MIKRO-RESULT-NP-01` | `MIKRO-RESULT-P-02` |
| Mikro (tidak terlampir) | `LAB-RESULT-P-01` | `LAB-RESULT-NP-01` | `LAB-RESULT-P-02` |
| Mikro (Inggris) | `MIKROEN-RESULT-P-01` | `MIKROEN-RESULT-NP-01` | `MIKROEN-RESULT-P-02` |
| FNA | `FNA-RESULT-P-01` | `FNA-RESULT-NP-01` | `FNA-RESULT-P-02` |
| Patologi Anatomi | `PA-RESULT-P-01` | `PA-RESULT-NP-01` | `PA-RESULT-P-02` |
| Papsmear | `PAP-RESULT-P-01` | `PAP-RESULT-NP-01` | `PAP-RESULT-P-02` |
| Pap Smear LCP | `PAPLCP-RESULT-P-01` | `PAPLCP-RESULT-NP-01` | `PAPLCP-RESULT-P-02` |
| Pap Smear LCP (Inggris) | `PAPLEN-RESULT-P-01` | `PAPLEN-RESULT-NP-01` | `PAPLEN-RESULT-P-02` |
| Preparasi Sperma | `PS-RESULT-P-01` | `PS-RESULT-NP-01` | `PS-RESULT-P-02` |
| DFI | `DFI-RESULT-P-01` | `DFI-RESULT-NP-01` | `DFI-RESULT-P-02` |
| Cytologi | `CT-RESULT-P-01` | `CT-RESULT-NP-01` | `CT-RESULT-P-02` |
### Deteksi modul yang belum difix
Cari pola ini di FE:
```
/birt/frameset?__report=
```
Kalau ditemukan di JS/Vue yang langsung set ke iframe/object/window.open tanpa lewat PHP
proxy, itu harus diganti ke `stream_by_code`.
### Library terkait
- `application/libraries/Ibl_patient_decrypt.php` — populate/delete `patient_print_cache`
- `application/libraries/Ibl_sampling_normal.php` — pengganti `fn_sampling_get_normal` MySQL function (semua `Re_px.php` sudah diupdate)
- `application/controllers/tools/Birt_proxy.php` — proxy stream handler
## graphify
This project has a graphify knowledge graph at graphify-out/.

View File

@@ -124,11 +124,20 @@ EOF;
}
public function v3($orderHeaderID)
{
$sql = "SELECT QR_PrintOutReportURL
FROM qr_printout
WHERE QR_PrintOutT_OrderHeaderID = ?
AND QR_PrintOutIsActive = 1
ORDER BY QR_PrintOutID DESC
$sql = "SELECT IFNULL(qp.QR_PrintOutVerifyURL, '') AS verify_url
FROM one_lab.qr_printout qp
JOIN one_lab.t_orderheader_group_result r
ON r.T_OrderHeaderGroupResultT_OrderHeaderID = qp.QR_PrintOutT_OrderHeaderID
AND r.T_OrderHeaderGroupResultGroup_ResultID = qp.QR_PrintOutGroup_ResultID
AND r.T_OrderHeaderGroupResultT_TestID = qp.QR_PrintOutT_TestID
JOIN one_lab.t_orderheader_group_result_details d
ON d.T_OrderHeaderGroupResultDetailsT_OrderHeaderGroupResultID = r.T_OrderHeaderGroupResultID
WHERE d.T_OrderHeaderGroupResultDetailsT_OrderHeaderID = ?
AND d.T_OrderHeaderGroupResultDetailsIsActive = 'Y'
AND r.T_OrderHeaderGroupResultIsActive = 'Y'
AND qp.QR_PrintOutIsActive = 1
AND IFNULL(qp.QR_PrintOutVerifyURL, '') <> ''
ORDER BY qp.QR_PrintOutID DESC
LIMIT 1";
$rs = $this->get_one_row($sql, array($orderHeaderID));
if ($rs["status"] == -1) {
@@ -140,8 +149,8 @@ EOF;
exit;
}
$reportUrl = $rs["data"]["QR_PrintOutReportURL"];
$img_qrcode = $this->post("http://localhost/charts/qrtext.php", $reportUrl);
$verifyUrl = $rs["data"]["verify_url"];
$img_qrcode = $this->post("http://localhost/charts/qrtext.php", $verifyUrl);
header("Content-type: image/png");
echo $img_qrcode;
exit;
@@ -149,7 +158,7 @@ EOF;
public function v3_nonlab($resultEntryID)
{
$sql = " SELECT
qp.QR_PrintOutReportURL
IFNULL(qp.QR_PrintOutVerifyURL, '') AS verify_url
FROM one_lab.so_resultentry se
JOIN one_lab.t_orderheader oh
ON oh.T_OrderHeaderID = se.SO_ResultEntryT_OrderHeaderID
@@ -170,8 +179,8 @@ EOF;
exit;
}
$reportUrl = $rs["data"]["QR_PrintOutReportURL"];
$img_qrcode = $this->post("http://localhost/charts/qrtext.php", $reportUrl);
$verifyUrl = $rs["data"]["verify_url"];
$img_qrcode = $this->post("http://localhost/charts/qrtext.php", $verifyUrl);
header("Content-type: image/png");
echo $img_qrcode;
exit;

View File

@@ -7,6 +7,7 @@ class Patient extends MY_Controller
{
parent::__construct();
$this->db = $this->load->database("onedev", true);
$this->load->library('ibl_encryptor');
}
function index()
@@ -40,20 +41,33 @@ class Patient extends MY_Controller
$where = " orderIsActive = 'Y' $filter_date";
$bidx_where = '';
if ($search != "") {
$where .= " AND (orderNumber LIKE '{$search}' OR M_PatientName LIKE '{$search}')";
$raw_search = trim($prm['search']);
$tokens = $this->ibl_encryptor->query_tokens($raw_search);
if ($tokens) {
$bidx_conds = implode(' AND ', array_map(function($h) {
return "JSON_CONTAINS(M_PatientName_bidx, '\"$h\"')";
}, $tokens));
$bidx_where = " AND (orderNumber LIKE '{$search}' OR ({$bidx_conds}))";
} else {
$bidx_where = " AND orderNumber LIKE '{$search}'";
}
$where .= $bidx_where;
}
$sql_total = "SELECT COUNT(*) as total FROM (
SELECT `order`.*,S_MenuUrl,
DATE_FORMAT(orderDate, '%d-%m-%Y %H:%i') as order_date,
CONCAT(M_TitleName,'. ',M_PatientName) as patient_fullname,
M_PatientName_enc as patient_name_enc,
M_PatientName as patient_name_masked,
M_PatientPrefix, M_PatientSuffix, M_TitleName,
IFNULL(T_OrderHeaderLabNumber,'-') as labnumber
FROM one_klinik.order
JOIN m_patient ON orderM_PatientID = M_PatientID
AND M_PatientIsActive = 'Y'
JOIN s_menu ON S_MenuName = 'Registration' AND S_MenuIsActive = 'Y'
JOIN m_title ON M_PatientM_TitleID = M_TitleID
JOIN m_title ON M_PatientM_TitleID = M_TitleID
AND M_TitleIsActive = 'Y'
LEFT JOIN t_orderheader ON orderT_OrderHeaderID = T_OrderHeaderID
WHERE $where
@@ -74,13 +88,15 @@ class Patient extends MY_Controller
$sql = "SELECT * FROM (
SELECT `order`.*,S_MenuUrl,
DATE_FORMAT(orderDate, '%d-%m-%Y %H:%i') as order_date,
CONCAT(M_TitleName,'. ',M_PatientName) as patient_fullname,
M_PatientName_enc as patient_name_enc,
M_PatientName as patient_name_masked,
M_PatientPrefix, M_PatientSuffix, M_TitleName,
IFNULL(T_OrderHeaderLabNumber,'-') as labnumber
FROM one_klinik.order
JOIN m_patient ON orderM_PatientID = M_PatientID
AND M_PatientIsActive = 'Y'
JOIN s_menu ON S_MenuName = 'Registration' AND S_MenuIsActive = 'Y'
JOIN m_title ON M_PatientM_TitleID = M_TitleID
JOIN m_title ON M_PatientM_TitleID = M_TitleID
AND M_TitleIsActive = 'Y'
LEFT JOIN t_orderheader ON orderT_OrderHeaderID = T_OrderHeaderID
WHERE $where
@@ -89,12 +105,17 @@ class Patient extends MY_Controller
limit 0, $tot_count";
$qry = $this->db->query($sql);
$last_query = $this->db->last_query();
// echo $last_query;
// exit;
if ($qry) {
$rows = $qry->result_array();
$enc = $this->ibl_encryptor;
$rows = array_map(function($row) use ($enc) {
$name = $enc->decrypt($row['patient_name_enc'] ?? '') ?: $row['patient_name_masked'];
$title = $row['M_TitleName'] ? $row['M_TitleName'] . '. ' : '';
$prefix = $row['M_PatientPrefix'] ? $row['M_PatientPrefix'] . ' ' : '';
$suffix = $row['M_PatientSuffix'] ? ' ' . $row['M_PatientSuffix'] : '';
$row['patient_fullname'] = trim($title . $prefix . $name . $suffix);
unset($row['patient_name_enc'], $row['patient_name_masked']);
return $row;
}, $qry->result_array());
} else {
$this->sys_error_db("Select order error", $this->db);
exit;
@@ -232,11 +253,45 @@ class Patient extends MY_Controller
$row_results = [];
$rtn_mou = [];
$sql = "SELECT M_CompanyID,
$orderid = intval($prm['orderid'] ?? 0);
if ($orderid) {
$sql = "SELECT M_CompanyID, M_CompanyName, m.M_MouID as settingM_MouID
FROM one_klinik.`order` o
JOIN m_mou m ON o.orderM_MouID = m.M_MouID
JOIN m_company ON m.M_MouM_CompanyID = M_CompanyID
WHERE o.orderID = ?
LIMIT 1";
$qry_order = $this->db->query($sql, [$orderid]);
if ($qry_order && $qry_order->num_rows() > 0) {
$order_row = $qry_order->row_array();
$mous = $this->db->query(
"SELECT M_MouID, M_MouName FROM m_mou
WHERE M_MouIsActive = 'Y' AND M_MouIsApproved = 'Y' AND M_MouIsReleased = 'Y'
AND M_MouStartDate <= date(now()) AND M_MouEndDate >= date(now())
AND M_MouM_CompanyID = ?",
[$order_row['M_CompanyID']]
)->result_array();
$row_results[] = [
'M_CompanyID' => $order_row['M_CompanyID'],
'M_CompanyName' => $order_row['M_CompanyName'],
'mous' => $mous,
];
foreach ($mous as $v) {
if ($v['M_MouID'] == $order_row['settingM_MouID']) {
$rtn_mou = $v;
}
}
$this->sys_ok(['total_display' => 1, 'records' => $row_results, 'mou' => $rtn_mou]);
exit;
}
}
$sql = "SELECT M_CompanyID,
M_CompanyName, '' as mous, settingM_MouID
FROM m_company
JOIN one_klinik.setting ON settingIsActive = 'Y'
JOIN m_mou ON M_MouID = settingM_MouID AND M_MouM_CompanyID = M_CompanyID AND
JOIN m_mou ON M_MouID = settingM_MouID AND M_MouM_CompanyID = M_CompanyID AND
M_MouIsActive = 'Y' AND M_MouIsApproved = 'Y' AND M_MouIsReleased = 'Y'
AND M_MouStartDate <= date(now()) AND M_MouEndDate >= date(now())
WHERE M_CompanyIsActive = 'Y'

View File

@@ -43,6 +43,7 @@ class Registrationv3 extends MY_Controller
private function _mask_short($v) { if (!$v) return $v; $v=trim($v); $l=mb_strlen($v,'UTF-8'); if($l<=2) return '***'; return mb_substr($v,0,2,'UTF-8').'***'; }
private function _mask_id($v) { if (!$v) return $v; $v=trim($v); $l=strlen($v); if($l<=4) return '****'; return substr($v,0,4).str_repeat('*',max(3,$l-6)).($l>6?substr($v,-2):''); }
private function _mask_address($v) { if (!$v) return $v; $v=trim($v); $l=mb_strlen($v,'UTF-8'); if($l<=5) return '***'; return mb_substr($v,0,5,'UTF-8').'***'; }
private function _mask_dob($v) { if (!$v) return $v; $p=explode('-',$v); return (count($p)===3) ? '**-**-'.$p[2] : '****-**-**'; }
public function search_x()
{
@@ -446,7 +447,7 @@ class Registrationv3 extends MY_Controller
->set('M_PatientM_TitleID', $prm['M_PatientM_TitleID'])
->set('M_PatientPrefix', $prm['M_PatientPrefix'])
->set('M_PatientSuffix', $prm['M_PatientSuffix'])
->set('M_PatientDOB', $pdob)
->set('M_PatientDOB', $this->_mask_dob($dob_str))
->set('M_PatientDOB_enc', $enc->encrypt($dob_str))
->set('M_PatientDOB_bidx', $enc->search_bidx($dob_str))
->set('M_PatientM_SexID', $prm['M_PatientM_SexID'])
@@ -463,8 +464,8 @@ class Registrationv3 extends MY_Controller
->set('M_PatientM_IdTypeID', $prm['M_PatientM_IdTypeID'])
->set('M_PatientIDNumber', $this->_mask_id($prm['M_PatientIDNumber']))
->set('M_PatientIDNumber_enc', $enc->encrypt($prm['M_PatientIDNumber']))
->set('M_PatientNIK_bidx', $enc->search_bidx($prm['M_PatientIDNumber'] ?? ''))
->set('M_PatientNIK', $prm['M_PatientNIK'])
->set('M_PatientNIK_bidx', $enc->search_bidx($prm['M_PatientNIK'] ?? ''))
->set('M_PatientNote', $prm['M_PatientNote'])
->set('M_PatientJabatan', $prm['M_PatientJabatan'])
->set('M_PatientKedudukan', $prm['M_PatientKedudukan'])
@@ -536,7 +537,7 @@ class Registrationv3 extends MY_Controller
'M_PatientM_TitleID' => $prm['M_PatientM_TitleID'],
'M_PatientPrefix' => $prm['M_PatientPrefix'],
'M_PatientSuffix' => $prm['M_PatientSuffix'],
'M_PatientDOB' => $pdob,
'M_PatientDOB' => $this->_mask_dob($dob_str),
'M_PatientDOB_enc' => $enc->encrypt($dob_str),
'M_PatientDOB_bidx' => $enc->search_bidx($dob_str),
'M_PatientM_SexID' => $prm['M_PatientM_SexID'],
@@ -553,8 +554,8 @@ class Registrationv3 extends MY_Controller
'M_PatientM_IdTypeID' => $prm['M_PatientM_IdTypeID'],
'M_PatientIDNumber' => $this->_mask_id($prm['M_PatientIDNumber']),
'M_PatientIDNumber_enc' => $enc->encrypt($prm['M_PatientIDNumber']),
'M_PatientNIK_bidx' => $enc->search_bidx($prm['M_PatientIDNumber'] ?? ''),
'M_PatientNIK' => $prm['M_PatientNIK'],
'M_PatientNIK_bidx' => $enc->search_bidx($prm['M_PatientNIK'] ?? ''),
'M_PatientNote' => $prm['M_PatientNote'],
'M_PatientJabatan' => $prm['M_PatientJabatan'],
'M_PatientKedudukan' => $prm['M_PatientKedudukan'],
@@ -588,7 +589,15 @@ class Registrationv3 extends MY_Controller
'M_PatientAddressDescription' => $this->_mask_address($address_description),
'M_PatientAddressDescription_enc' => $enc->encrypt($address_description),
'M_PatientAddressUserID' => $userid,
'M_PatientAddressM_KelurahanID' => $prm['M_PatientAddressM_KelurahanID'],
'M_PatientAddressRegionalCd' => $prm['M_PatientAddressRegionalCd'] ?? null,
'M_PatientAddressLocation' => $prm['M_PatientAddressLocation'] ?? null,
'M_PatientAddressCity' => $prm['M_PatientAddressCity'] ?? null,
'M_PatientAddressVillage' => $prm['M_PatientAddressVillage'] ?? null,
'M_PatientAddressDistrict' => $prm['M_PatientAddressDistrict'] ?? null,
'M_PatientAddressState' => $prm['M_PatientAddressState'] ?? null,
'M_PatientAddressCountry' => $prm['M_PatientAddressCountry'] ?? null,
'M_PatientAddressCountryCode' => $prm['M_PatientAddressCountryCode'] ?? null,
'M_PatientAddressNote' => $prm['M_PatientAddressNote'] ?? 'Utama',
];
$this->db_onedev->insert('m_patientaddress', $add);
//echo $this->db_onedev->last_query();
@@ -644,101 +653,76 @@ class Registrationv3 extends MY_Controller
exit;
}
$prm = $this->sys_input;
$query = " SELECT m_patientaddress.*,
M_KelurahanName,
M_DistrictID,
M_DistrictName,
M_CityID,
M_CityName,
'' as action
FROM m_patientaddress
JOIN m_kelurahan ON M_PatientAddressM_KelurahanID = M_KelurahanID
JOIN m_district ON M_KelurahanM_DistrictID = M_DistrictID
JOIN m_city ON M_DistrictM_CityID = M_CityID
WHERE
M_PatientAddressIsActive = 'Y' AND M_PatientAddressM_PatientID = ?
ORDER BY M_PatientAddressID ASC
LIMIT 1
";
//echo $query;
$address = $this->db_onedev->query($query, array($prm['id']))->row_array();
$address['M_PatientAddressDescription'] = stripslashes($address['M_PatientAddressDescription']);
$query = "SELECT m_patientaddress.*,
IFNULL(r.regional_nm, '') AS M_KelurahanName,
IFNULL(r.full_name, '') AS M_RegionalFullName,
IFNULL(r.pro_cd, '') AS pro_cd,
IFNULL(r.kab_cd, '') AS kab_cd,
IFNULL(r.kec_cd, '') AS kec_cd,
IFNULL(pro.regional_nm, '') AS M_ProvinceName,
IFNULL(kab.regional_nm, '') AS M_CityName,
IFNULL(kec.regional_nm, '') AS M_DistrictName,
'' AS action
FROM m_patientaddress
LEFT JOIN regional r ON M_PatientAddressRegionalCd = r.regional_cd
LEFT JOIN regional pro ON CONCAT(r.pro_cd, REPEAT('0', 8)) = pro.regional_cd
LEFT JOIN regional kab ON CONCAT(r.pro_cd, r.kab_cd, REPEAT('0', 6)) = kab.regional_cd
LEFT JOIN regional kec ON CONCAT(r.pro_cd, r.kab_cd, r.kec_cd, REPEAT('0', 3)) = kec.regional_cd
WHERE M_PatientAddressIsActive = 'Y' AND M_PatientAddressM_PatientID = ?
ORDER BY M_PatientAddressID ASC
LIMIT 1";
$address = $this->db_onedev->query($query, [$prm['id']])->row_array();
$address['M_PatientAddressDescription'] = $this->ibl_encryptor->decrypt($address['M_PatientAddressDescription_enc'] ?? '') ?: stripslashes($address['M_PatientAddressDescription'] ?? '');
unset($address['M_PatientAddressDescription_enc']);
$rows['address'] = $address;
$query = " SELECT *
FROM m_city
WHERE
M_CityIsActive = 'Y' AND M_CityID = ?
";
//echo $query;
$rows['city_address'] = $this->db_onedev->query($query, array($address['M_CityID']))->row_array();
$pro_cd = $address['pro_cd'] ?? '';
$kab_cd = $address['kab_cd'] ?? '';
$kec_cd = $address['kec_cd'] ?? '';
$regional_cd = $address['M_PatientAddressRegionalCd'] ?? '';
$rows['province_address'] = $pro_cd ? $this->db_onedev->query(
"SELECT regional_cd AS M_ProvinceID, regional_nm AS M_ProvinceName FROM regional WHERE regional_cd = ?",
[$pro_cd . str_repeat('0', 8)]
)->row_array() : [];
$query = " SELECT *
FROM m_city
WHERE
M_CityIsActive = 'Y' AND M_CityM_ProvinceID = ?
";
//echo $query;
$rows['cities'] = $this->db_onedev->query($query, array($rows['city_address']['M_CityM_ProvinceID']))->result_array();
$rows['provinces'] = $this->db_onedev->query(
"SELECT regional_cd AS M_ProvinceID, regional_nm AS M_ProvinceName FROM regional WHERE RIGHT(regional_cd, 8) = '00000000' ORDER BY regional_nm"
)->result_array();
$query = " SELECT *
FROM m_province
WHERE
M_ProvinceIsActive = 'Y' AND M_ProvinceID = ?
";
//echo $query;
$rows['province_address'] = $this->db_onedev->query($query, array($rows['city_address']['M_CityM_ProvinceID']))->row_array();
$rows['city_address'] = ($pro_cd && $kab_cd) ? $this->db_onedev->query(
"SELECT regional_cd AS M_CityID, regional_nm AS M_CityName FROM regional WHERE regional_cd = ?",
[$pro_cd . $kab_cd . str_repeat('0', 6)]
)->row_array() : [];
$query = " SELECT *
FROM m_province
WHERE
M_ProvinceIsActive = 'Y'
";
//echo $query;
$rows['provinces'] = $this->db_onedev->query($query)->result_array();
$rows['cities'] = $pro_cd ? $this->db_onedev->query(
"SELECT regional_cd AS M_CityID, regional_nm AS M_CityName FROM regional WHERE pro_cd = ? AND RIGHT(regional_cd, 8) != '00000000' AND RIGHT(regional_cd, 6) = '000000' ORDER BY regional_nm",
[$pro_cd]
)->result_array() : [];
$query = " SELECT *
FROM m_district
WHERE
M_DistrictIsActive = 'Y' AND M_DistrictM_CityID = ?
";
//echo $query;
$rows['districts'] = $this->db_onedev->query($query, array($rows['city_address']['M_CityID']))->result_array();
$rows['district_address'] = ($pro_cd && $kab_cd && $kec_cd) ? $this->db_onedev->query(
"SELECT regional_cd AS M_DistrictID, regional_nm AS M_DistrictName FROM regional WHERE regional_cd = ?",
[$pro_cd . $kab_cd . $kec_cd . str_repeat('0', 3)]
)->row_array() : [];
$query = " SELECT *
FROM m_district
WHERE
M_DistrictIsActive = 'Y' AND M_DistrictID = ?
";
//echo $query;
$rows['district_address'] = $this->db_onedev->query($query, array($address['M_DistrictID']))->row_array();
$rows['districts'] = ($pro_cd && $kab_cd) ? $this->db_onedev->query(
"SELECT regional_cd AS M_DistrictID, regional_nm AS M_DistrictName FROM regional WHERE pro_cd = ? AND kab_cd = ? AND RIGHT(regional_cd, 6) != '000000' AND RIGHT(regional_cd, 3) = '000' ORDER BY regional_nm",
[$pro_cd, $kab_cd]
)->result_array() : [];
$query = " SELECT *
FROM m_kelurahan
WHERE
M_KelurahanIsActive = 'Y' AND M_KelurahanM_DistrictID = ?
";
//echo $query;
$rows['kelurahans'] = $this->db_onedev->query($query, array($address['M_DistrictID']))->result_array();
$rows['kelurahan_address'] = $regional_cd ? $this->db_onedev->query(
"SELECT regional_cd AS M_KelurahanID, regional_nm AS M_KelurahanName FROM regional WHERE regional_cd = ?",
[$regional_cd]
)->row_array() : [];
$query = " SELECT *
FROM m_kelurahan
WHERE
M_KelurahanIsActive = 'Y' AND M_KelurahanID = ?
";
//echo $query;
$rows['kelurahan_address'] = $this->db_onedev->query($query, array($address['M_PatientAddressM_KelurahanID']))->row_array();
$rows['kelurahans'] = ($pro_cd && $kab_cd && $kec_cd) ? $this->db_onedev->query(
"SELECT regional_cd AS M_KelurahanID, regional_nm AS M_KelurahanName FROM regional WHERE pro_cd = ? AND kab_cd = ? AND kec_cd = ? AND RIGHT(regional_cd, 3) != '000' ORDER BY regional_nm",
[$pro_cd, $kab_cd, $kec_cd]
)->result_array() : [];
$result = array(
"total" => count($rows),
"records" => $rows,
);
$this->sys_ok($result);
$this->sys_ok(["total" => count($rows), "records" => $rows]);
exit;
}
function savenewaddress()
@@ -874,186 +858,179 @@ class Registrationv3 extends MY_Controller
public function search()
{
$prm = $this->sys_input;
$max_rst = 100;
$tot_count = 0;
$number_limit = 10;
$number_limit = 10;
$number_offset = (!isset($prm['current_page']) ? 1 : $prm['current_page'] - 1) * $number_limit;
$q = [
'noreg' => "",
'name' => '',
'hp' => '',
'dob' => '',
'address' => '',
'nik' => ''
];
$where_noreg = '';
$where_name = '';
$where_hp = '';
$where_dob = '';
$where_nik = '';
$where_snorm = '';
$q_pid = "";
if ($prm['noreg'] != '')
$q['noreg'] = "AND M_PatientNoReg like '%{$prm['noreg']}%'";
if ($prm['snorm'] == '') {
if ($prm['search'] != '') {
$e = explode('+', $prm['search']);
// nama via trigram bidx
if (!empty($e[0]) && mb_strlen(trim($e[0])) >= 3) {
$toks = $this->ibl_encryptor->query_tokens($e[0]);
$conds = [];
foreach ($toks as $tok) {
$tok_esc = $this->db_onedev->escape_str($tok);
$conds[] = "JSON_CONTAINS(M_PatientName_bidx, '\"$tok_esc\"')";
}
if ($conds) $q['name'] = 'AND (' . implode(' AND ', $conds) . ')';
}
// HP via trigram bidx
if (!empty($e[1]) && mb_strlen(trim($e[1])) >= 3) {
$toks = $this->ibl_encryptor->query_tokens($e[1]);
$conds = [];
foreach ($toks as $tok) {
$tok_esc = $this->db_onedev->escape_str($tok);
$conds[] = "JSON_CONTAINS(M_PatientHP_bidx, '\"$tok_esc\"')";
}
if ($conds) $q['hp'] = 'AND (' . implode(' AND ', $conds) . ')';
}
// DOB via trigram bidx
if (!empty($e[2]) && mb_strlen(trim($e[2])) >= 3) {
$toks = $this->ibl_encryptor->query_tokens($e[2]);
$conds = [];
foreach ($toks as $tok) {
$tok_esc = $this->db_onedev->escape_str($tok);
$conds[] = "JSON_CONTAINS(M_PatientDOB_bidx, '\"$tok_esc\"')";
}
if ($conds) $q['dob'] = 'AND (' . implode(' AND ', $conds) . ')';
}
// Alamat dihapus dari search
// NIK via trigram bidx (e[3] — sebelumnya e[4])
if (!empty($e[3]) && mb_strlen(trim($e[3])) >= 3) {
$toks = $this->ibl_encryptor->query_tokens($e[3]);
$conds = [];
foreach ($toks as $tok) {
$tok_esc = $this->db_onedev->escape_str($tok);
$conds[] = "JSON_CONTAINS(M_PatientNIK_bidx, '\"$tok_esc\"')";
}
if ($conds) $q['nik'] = 'AND (' . implode(' AND ', $conds) . ')';
}
}
} else {
$q_pid = "AND M_PatientNoReg = '{$prm['snorm']}'";
if (!empty($prm['noreg'])) {
$noreg = $this->db_onedev->escape_like_str($prm['noreg']);
$where_noreg = "AND M_PatientNoReg LIKE '%{$noreg}%'";
}
if ($prm['snorm'] != '' || $prm['search'] != '') {
if (!empty($prm['snorm'])) {
$where_snorm = "AND M_PatientNoReg = '{$prm['snorm']}'";
} elseif (!empty($prm['search'])) {
$e = explode('+', $prm['search']);
$sql = "SELECT 'N' divider,M_PatientID,
M_PatientNoReg,
M_PatientPrefix,
M_PatientName_enc, M_PatientHP_enc, M_PatientEmail_enc,
M_PatientPOB_enc, M_PatientPhone_enc, M_PatientIDNumber_enc, M_PatientNIK_enc,
M_PatientDOB_enc, M_PatientDOB as dob_raw,
M_PatientSuffix,
M_PatientNote,
M_PatientNIK,
M_PatientJabatan,
M_PatientKedudukan,
M_PatientPJ,
M_PatientLocation,
M_PatientJob,
M_PatientM_SexID,
M_SexName,
M_PatientM_TitleID,
M_TitleName,
M_PatientM_ReligionID,
M_ReligionName,
M_PatientM_IdTypeID,
M_IdTypeName,
M_PatientIDNumber,
M_PatientPhoto,
IF(ISNULL(M_PatientSuspendID),'active','suspend' ) as status,
M_PatientAddressM_KelurahanID M_KelurahanID,
0 M_DistrictID, 0 M_CityID, 0 M_ProvinceID
FROM m_patient
JOIN m_title ON M_PatientM_TitleID = M_TitleID
JOIN m_sex ON M_PatientM_SexID = M_SexID
JOIN m_branch ON M_BranchIsActive = 'Y' AND M_BranchIsDefault = 'Y'
JOIN m_patientaddress ON M_PatientAddressM_PatientID = M_PatientID AND M_PatientAddressIsActive = 'Y'
LEFT JOIN m_idtype ON M_IdTypeID = M_PatientM_IdTypeID AND M_IdTypeIsActive = 'Y'
LEFT JOIN m_religion ON m_patientm_religionid = m_religionid
LEFT JOIN m_patientsuspend ON M_PatientSuspendM_PatientID = M_PatientID AND M_PatientSuspendIsActive = 'Y'
WHERE
M_PatientSuspendID IS NULL AND M_PatientIsActive = 'Y'
{$q['address']}
{$q['noreg']}
{$q['name']}
{$q['hp']}
{$q['dob']}
{$q['nik']}
{$q_pid}
GROUP BY M_PatientID
LIMIT $number_limit offset $number_offset";
//echo $sql;
$query = $this->db_onedev->query($sql);
if ($query) {
$rows = $query->result_array();
$enc = $this->ibl_encryptor;
foreach ($rows as $k => $v) {
$rows[$k]['M_PatientName'] = $enc->decrypt($v['M_PatientName_enc'] ?? '') ?? '';
$rows[$k]['M_PatientHP'] = $enc->decrypt($v['M_PatientHP_enc'] ?? '') ?? '';
$rows[$k]['M_PatientEmail'] = $enc->decrypt($v['M_PatientEmail_enc'] ?? '') ?? '';
$rows[$k]['M_PatientPOB'] = $enc->decrypt($v['M_PatientPOB_enc'] ?? '') ?? '';
$rows[$k]['M_PatientPhone'] = $enc->decrypt($v['M_PatientPhone_enc'] ?? '') ?? '';
$rows[$k]['M_PatientIDNumber'] = $enc->decrypt($v['M_PatientIDNumber_enc']?? '') ?? '';
$rows[$k]['M_PatientNIK'] = $enc->decrypt($v['M_PatientNIK_enc'] ?? '') ?? '';
$rows[$k]['M_PatientDOB'] = $enc->decrypt($v['M_PatientDOB_enc'] ?? '') ?? date('d-m-Y', strtotime($v['dob_raw'] ?? 'now'));
$rows[$k]['M_PatientAddressDescription'] = $enc->decrypt($v['M_PatientAddressDescription_enc'] ?? '') ?? '';
foreach (array_keys($rows[$k]) as $col) {
if (substr($col, -4) === '_enc') unset($rows[$k][$col]);
}
unset($rows[$k]['dob_raw']);
$patient_name = str_replace("'", "\\'", $prm['M_PatientName']);
$sql = "SELECT *, concat('{$rows[$k]['M_PatientAddressDescription']}', '\n\n',
m_kelurahanname, ', ',
m_districtname,'\n',
m_cityname, ', ',
m_provincename) as xaddress
FROM m_kelurahan
JOIN m_district ON M_KelurahanM_DistrictID = M_DistrictID
JOIN m_city ON M_DistrictM_CityID = M_CityID
JOIN m_province ON M_CityM_ProvinceID = M_ProvinceID
WHERE
M_KelurahanID = {$v['M_KelurahanID']} ";
//echo $sql;
$row_address = $this->db_onedev->query($sql)->row_array();
$rows[$k]['M_PatientAddress'] = stripslashes($row_address['xaddress']);
$rows[$k]['M_DistrictID'] = $row_address['M_DistrictID'];
$rows[$k]['M_CityID'] = $row_address['M_CityID'];
$rows[$k]['M_ProvinceID'] = $row_address['M_ProvinceID'];
$info = $this->db_onedev->query("SELECT fn_fo_patient_visit(?) info", [$v['M_PatientID']])->row();
$rows[$k]['info'] = json_decode($info->info);
if (!empty($e[0]) && mb_strlen(trim($e[0])) >= 3) {
$toks = $this->ibl_encryptor->query_tokens($e[0]);
$conds = [];
foreach ($toks as $tok) {
$tok_esc = $this->db_onedev->escape_str($tok);
$conds[] = "JSON_CONTAINS(M_PatientName_bidx, '\"$tok_esc\"')";
}
$result = array("total" => $tot_page, "records" => $rows, "sql" => $this->db_onedev->last_query());
$this->sys_ok($result);
} else {
$this->sys_error_db("m_patient rows", $this->db_onedev);
exit;
if ($conds) $where_name = 'AND (' . implode(' AND ', $conds) . ')';
}
} else {
$result = array("total" => 0, "records" => [], "sql" => $this->db_onedev->last_query());
$this->sys_ok($result);
}
}
function calculateAge($tanggal_lahir)
{
if (!empty($e[1]) && mb_strlen(trim($e[1])) >= 3) {
$toks = $this->ibl_encryptor->query_tokens($e[1]);
$conds = [];
foreach ($toks as $tok) {
$tok_esc = $this->db_onedev->escape_str($tok);
$conds[] = "JSON_CONTAINS(M_PatientHP_bidx, '\"$tok_esc\"')";
}
if ($conds) $where_hp = 'AND (' . implode(' AND ', $conds) . ')';
}
if (!empty($e[2]) && mb_strlen(trim($e[2])) >= 3) {
$toks = $this->ibl_encryptor->query_tokens($e[2]);
$conds = [];
foreach ($toks as $tok) {
$tok_esc = $this->db_onedev->escape_str($tok);
$conds[] = "JSON_CONTAINS(M_PatientDOB_bidx, '\"$tok_esc\"')";
}
if ($conds) $where_dob = 'AND (' . implode(' AND ', $conds) . ')';
}
if (!empty($e[3]) && mb_strlen(trim($e[3])) >= 3) {
$toks = $this->ibl_encryptor->query_tokens($e[3]);
$conds = [];
foreach ($toks as $tok) {
$tok_esc = $this->db_onedev->escape_str($tok);
$conds[] = "JSON_CONTAINS(M_PatientNIK_bidx, '\"$tok_esc\"')";
}
if ($conds) $where_nik = 'AND (' . implode(' AND ', $conds) . ')';
}
}
if (empty($prm['snorm']) && empty($prm['search']) && empty($prm['noreg'])) {
$this->sys_ok(["total" => 0, "records" => []]);
return;
}
$sql = "SELECT 'N' divider, M_PatientID, M_PatientNoReg, M_PatientPrefix, M_PatientSuffix,
concat(M_TitleName,' ',IFNULL(M_PatientPrefix,''),' ',M_PatientName,' ',IFNULL(M_PatientSuffix,'')) M_PatientNameRaw,
M_TitleID, M_TitleName, M_SexID, M_SexName,
M_PatientDOB,
M_PatientM_ReligionID, IFNULL(M_ReligionName, '-') M_ReligionName,
IFNULL(M_PatientNote, '') M_PatientNote, M_PatientPhoto,
M_PatientM_IdTypeID,
M_PatientJabatan, M_PatientKedudukan, M_PatientPJ, M_PatientLocation, M_PatientJob,
IF(ISNULL(M_PatientSuspendID),'active','suspend') as status,
M_PatientName_enc, M_PatientHP_enc, M_PatientDOB_enc,
M_PatientEmail_enc, M_PatientPhone_enc, M_PatientPOB_enc,
M_PatientIDNumber_enc, M_PatientNIK_enc
FROM m_patient
JOIN m_title ON M_PatientM_TitleID = M_TitleID
JOIN m_sex ON M_PatientM_SexID = M_SexID
LEFT JOIN m_religion ON M_PatientM_ReligionID = M_ReligionID
LEFT JOIN m_patientsuspend ON M_PatientSuspendM_PatientID = M_PatientID AND M_PatientSuspendIsActive = 'Y'
WHERE M_PatientIsActive = 'Y' AND M_PatientSuspendID IS NULL
{$where_noreg}
{$where_snorm}
{$where_name}
{$where_hp}
{$where_dob}
{$where_nik}
GROUP BY M_PatientID
LIMIT {$number_limit} OFFSET {$number_offset}";
$query = $this->db_onedev->query($sql);
if (!$query) {
$this->sys_error_db("m_patient rows", $this->db_onedev);
return;
}
$rows = $query->result_array();
$enc = $this->ibl_encryptor;
foreach ($rows as $k => $v) {
$rows[$k]['M_PatientName'] = $enc->decrypt($v['M_PatientName_enc']) ?? $v['M_PatientNameRaw'];
$rows[$k]['M_PatientHP'] = $enc->decrypt($v['M_PatientHP_enc']) ?? '';
$rows[$k]['M_PatientEmail'] = $enc->decrypt($v['M_PatientEmail_enc']) ?? '';
$rows[$k]['M_PatientPOB'] = $enc->decrypt($v['M_PatientPOB_enc']) ?? '';
$rows[$k]['M_PatientPhone'] = $enc->decrypt($v['M_PatientPhone_enc']) ?? '';
$rows[$k]['M_PatientIDNumber'] = $enc->decrypt($v['M_PatientIDNumber_enc']) ?? '';
$rows[$k]['M_PatientNIK'] = $enc->decrypt($v['M_PatientNIK_enc']) ?? '';
$dob_dec = $enc->decrypt($v['M_PatientDOB_enc']) ?? '';
$rows[$k]['M_PatientDOB'] = $dob_dec;
$rows[$k]['dob_ina'] = $dob_dec;
foreach (array_keys($rows[$k]) as $col) {
if (substr($col, -4) === '_enc') unset($rows[$k][$col]);
}
unset($rows[$k]['M_PatientNameRaw']);
$rows[$k]['info'] = $this->build_patient_visit_info($v['M_PatientID'], $dob_dec);
}
$this->sys_ok(["total" => 0, "records" => $rows]);
}
protected function build_patient_visit_info($patient_id, $patient_dob)
{
$visit = 1;
$birthday = 'N';
$visit_query = $this->db_onedev->query(
"SELECT COUNT(DISTINCT T_OrderHeaderID) AS n
FROM t_orderheader
JOIN t_orderdetail ON T_OrderHeaderID = T_OrderDetailT_OrderHeaderID AND T_OrderDetailIsActive = 'Y'
WHERE T_OrderHeaderIsActive = 'Y'
AND T_OrderHeaderM_PatientID = ?",
[$patient_id]
);
if ($visit_query) {
$visit_row = $visit_query->row_array();
$visit += (int) ($visit_row['n'] ?? 0);
}
$init_visit_query = $this->db_onedev->query(
"SELECT M_PatientInitialVisit
FROM m_patient
WHERE M_PatientID = ?",
[$patient_id]
);
if ($init_visit_query) {
$init_visit_row = $init_visit_query->row_array();
if (!empty($init_visit_row['M_PatientInitialVisit'])) {
$visit += (int) $init_visit_row['M_PatientInitialVisit'];
}
}
$dob_time = empty($patient_dob) ? false : strtotime($patient_dob);
if ($dob_time !== false) {
$birthday = date('m-d', $dob_time) === date('m-d') ? 'Y' : 'N';
}
return json_decode(json_encode([
'visit' => $visit,
'birthday' => $birthday,
]));
}
function calculateAge($tanggal_lahir)
{
// Ambil tanggal sekarang
$tanggal_sekarang = new DateTime();
@@ -1091,21 +1068,28 @@ class Registrationv3 extends MY_Controller
$sql = "SELECT * FROM one_klinik.setting WHERE settingIsActive = 'Y' LIMIT 1";
$setting_data = $this->db_oneklinik->query($sql)->row_array();
$price = intval($prm['doctor']['price']) == 0?$setting_data['settingPriceDefault']:$prm['doctor']['price'];
$price = intval($prm['price'] ?? 0) != 0 ? intval($prm['price']) : $setting_data['settingPriceDefault'];
$sql = "INSERT INTO one_klinik.`order`
$clinic_unit_id = isset($prm['clinic_unit_id']) && $prm['clinic_unit_id'] ? intval($prm['clinic_unit_id']) : null;
$company_id = isset($prm['company_id']) && $prm['company_id'] ? intval($prm['company_id']) : null;
$mou_id = intval($prm['mou_id'] ?? $prm['m_mouid'] ?? 0) ?: null;
$sql = "INSERT INTO one_klinik.`order`
(`orderDate`,
`orderM_PatientID`,
`orderM_DoctorID`,
`orderAge`,
`orderKeluhan`,
`orderSubtotal`,
`orderTotal`,
`orderKeluhan`,
`orderSubtotal`,
`orderTotal`,
`orderUserID`,
`orderCreated`,
orderQueueNumber,
orderM_LocationID)
VALUES (NOW(),?,?,?,?,?,?,$userid,NOW(),?,?)";
orderM_LocationID,
orderM_ClinicUnitID,
orderM_CompanyID,
orderM_MouID)
VALUES (NOW(),?,?,?,?,?,?,$userid,NOW(),?,?,?,?,?)";
$save_order = $this->db_oneklinik->query($sql, array(
$prm['patient']['M_PatientID'],
@@ -1115,7 +1099,10 @@ class Registrationv3 extends MY_Controller
$price,
$price,
$queueNumber,
$setting_data['settingM_LocationID']
$setting_data['settingM_LocationID'],
$clinic_unit_id,
$company_id,
$mou_id
));
//echo $this->db_oneklinik->last_query();
if ($save_order) {
@@ -1152,8 +1139,47 @@ class Registrationv3 extends MY_Controller
exit;
}
//echo $last_id;
// Simpan item order ke order_detail_order
$tests = isset($prm['tests']) && is_array($prm['tests']) ? $prm['tests'] : [];
foreach ($tests as $t) {
$is_packet = ($t['is_packet'] ?? 'N') === 'Y' ? 'Y' : 'N';
$packet_type = $t['type'] ?? 'PX';
$packet_id = $is_packet === 'Y' ? intval($t['pxid'] ?? 0) : 0;
$packet_name = $is_packet === 'Y' ? ($t['test_name'] ?? '') : '';
$test_id = $is_packet === 'Y' ? 0 : intval($t['pxid'] ?? 0);
$test_name = $is_packet === 'Y' ? '' : ($t['test_name'] ?? '');
$test_sas = $t['pxsascode'] ?? '';
$child_json = isset($t['child_test']) ? json_encode($t['child_test']) : null;
$ss_pm_id = isset($t['ss_price_mou_id']) && $t['ss_price_mou_id'] ? intval($t['ss_price_mou_id']) : null;
$this->db_oneklinik->query(
"INSERT INTO one_klinik.order_detail_order
(orderDetailOrderOrderID, orderDetailOrderSsPriceMouID,
orderDetailOrderT_TestID, orderDetailOrderT_TestName, orderDetailOrderT_TestSasCode,
orderDetailOrderIsPacket, orderDetailOrderPacketType,
orderDetailOrderT_PacketID, orderDetailOrderT_PacketName,
orderDetailOrderT_PriceAmount, orderDetailOrderT_PriceDisc,
orderDetailOrderT_PriceDiscRp, orderDetailOrderT_PriceSubTotal,
orderDetailOrderT_PriceTotal, orderDetailOrderJsonChildren,
orderDetailOrderUserID)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
[
$last_id, $ss_pm_id,
$test_id, $test_name, $test_sas,
$is_packet, $packet_type,
$packet_id, $packet_name,
floatval($t['bruto'] ?? 0),
floatval($t['discountpersen'] ?? 0),
floatval($t['discountrp'] ?? 0),
floatval($t['total'] ?? 0),
floatval($t['total'] ?? 0),
$child_json,
$userid
]
);
}
$sql = "SELECT * FROM one_klinik.`order` WHERE orderID = {$last_id}";
//echo $sql;
$data_order = $this->db_oneklinik->query($sql)->row_array();
if ($queueID != "0" && trim($queueNumber) != "") {
$this->done_today_by_queue_number($queueNumber, $queueID);
@@ -1270,4 +1296,279 @@ class Registrationv3 extends MY_Controller
exit;
}
}
function searchregion()
{
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$search = $prm['search'];
$sql = "SELECT
r.regional_cd,
r.regional_cd AS id,
r.regional_nm,
r.full_name AS text_nm,
r.pro_cd, IFNULL(pro.regional_nm,'') AS pro_nm,
r.kab_cd, IFNULL(kab.regional_nm,'') AS kab_nm,
r.kec_cd, IFNULL(kec.regional_nm,'') AS kec_nm,
r.kel_cd, IFNULL(kel.regional_nm,'') AS kel_nm,
r.status_cd, r.old_nm
FROM regional r
LEFT JOIN regional pro ON CONCAT(r.pro_cd, REPEAT('0', 8)) = pro.regional_cd
LEFT JOIN regional kab ON CONCAT(r.pro_cd, r.kab_cd, REPEAT('0', 6)) = kab.regional_cd
LEFT JOIN regional kec ON CONCAT(r.pro_cd, r.kab_cd, r.kec_cd, REPEAT('0', 3)) = kec.regional_cd
LEFT JOIN regional kel ON CONCAT(r.pro_cd, r.kab_cd, r.kec_cd, r.kel_cd) = kel.regional_cd
WHERE
r.full_name LIKE CONCAT('%','{$search}','%')
LIMIT 100
";
$qry = $this->db_onedev->query($sql);
if (!$qry) {
$this->sys_error_db("search wilayah select error", $this->db_onedev);
exit;
}
$rows = $qry->result_array();
$result = array(
"records" => $rows,
"sql" => $this->db_onedev->last_query()
);
$this->sys_ok($result);
exit;
}
function search_countries()
{
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$search = $prm['search'];
if (!$search || $search == '') {
$search = 'Indonesia';
}
$sql = "SELECT * FROM terminology WHERE attribute_path = 'Address.country' AND display LIKE '%$search%' ORDER BY display ASC LIMIT 20";
$query = $this->db_onedev->query($sql);
$rows = $query->result_array();
$result = array("records" => $rows);
$this->sys_ok($result);
exit;
}
function searchcompany()
{
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$search = $this->db_onedev->escape_like_str($prm['search'] ?? '');
$sql = "SELECT
M_CompanyID AS id,
M_CompanyName AS name,
M_CompanyNumber AS number
FROM m_company
WHERE M_CompanyIsActive = 'Y'
AND M_CompanyName LIKE '%{$search}%'
ORDER BY M_CompanyName ASC
LIMIT 20";
$query = $this->db_onedev->query($sql);
if (!$query) {
$this->sys_error_db("searchcompany error", $this->db_onedev);
exit;
}
$this->sys_ok(array("records" => $query->result_array()));
exit;
}
function getmoubycompany()
{
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$company_id = intval($prm['company_id'] ?? 0);
if (!$company_id) {
$this->sys_error("company_id required");
exit;
}
$sql = "SELECT
M_MouID AS id,
M_MouName AS name,
M_MouNumber AS number,
M_MouRefNumber AS ref_number,
M_MouStartDate AS start_date,
M_MouEndDate AS end_date
FROM m_mou
WHERE M_MouM_CompanyID = ?
AND M_MouIsActive = 'Y'
AND M_MouIsReleased = 'Y'
AND CURDATE() BETWEEN M_MouStartDate AND M_MouEndDate
ORDER BY M_MouName ASC";
$query = $this->db_onedev->query($sql, [$company_id]);
if (!$query) {
$this->sys_error_db("getmoubycompany error", $this->db_onedev);
exit;
}
$this->sys_ok(array("records" => $query->result_array()));
exit;
}
function getpoli()
{
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$sql = "SELECT
M_ClinicUnitID AS id,
M_ClinicUnitCode AS code,
M_ClinicUnitName AS name,
M_ClinicUnitDescription AS description,
M_ClinicUnitSatusehatLocationID AS satusehat_location_id
FROM one_klinik.m_clinic_unit
WHERE M_ClinicUnitIsActive = 'Y'
ORDER BY M_ClinicUnitID ASC";
$query = $this->db_oneklinik->query($sql);
if (!$query) {
$this->sys_error_db("getpoli error", $this->db_oneklinik);
exit;
}
$rows = $query->result_array();
$this->sys_ok(array("records" => $rows));
exit;
}
function search_test()
{
if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; }
$prm = $this->sys_input;
$mouid = intval($prm['mouid'] ?? 0);
if (!$mouid) {
$this->sys_ok(['total' => 0, 'records' => [], 'total_display' => 0]);
exit;
}
$search = "%{$this->db_onedev->escape_like_str(trim($prm['search'] ?? ''))}%";
$sql = "SELECT * FROM (
SELECT Ss_PriceMouID as ss_price_mou_id,
Ss_PriceMouM_MouID as mouid,
0 as xid,
Nat_TestID as nat_testid,
nat_test,
is_packet,
packet_id,
px_type as type,
ss_price_mou.T_TestID as pxid,
test.T_TestCode as pxcode,
test.T_TestSasCode as pxsascode,
test.T_TestName as test_name,
CONCAT(test.T_TestSasCode,' ',test.T_TestName) as pxname,
test.T_TestIsResult as isresult,
JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceAmount')) as bruto,
JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceDisc')) as discountpersen,
JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceDiscRp')) as discountrp,
if(JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceDisc')) <> 0,
(((JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceDisc')) / 100) * JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceAmount'))) + JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceDiscRp'))),
JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceDiscRp'))) as discount,
( JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceAmount')) - ((JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceDisc')) / 100) * JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceAmount'))) - JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceDiscRp')) ) as total,
'Y' as status, 'N' as active, 'N' as cito, 'N' as cito_before, '' as promise, '' as charge,
child_test
FROM ss_price_mou
JOIN t_test test ON ss_price_mou.T_TestID = test.T_TestID
WHERE CONCAT(test.T_TestSasCode,' ',test.T_TestName) LIKE '{$search}'
AND Ss_PriceMouM_MouID = {$mouid} AND is_packet <> 'Y' AND T_PriceIsCito <> 'Y'
UNION
SELECT Ss_PriceMouID as ss_price_mou_id,
Ss_PriceMouM_MouID as mouid,
0 as xid,
Nat_TestID as nat_testid,
nat_test,
is_packet,
packet_id,
px_type as type,
test.T_PacketID as pxid,
test.T_PacketSasCode as pxcode,
test.T_PacketSasCode as pxsascode,
test.T_PacketName as test_name,
CONCAT(test.T_PacketSasCode,' ',test.T_PacketName) as pxname,
'N' as isresult,
IF(px_type <> 'PN',JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceAmount')),T_PriceAmount) as bruto,
IF(px_type <> 'PN',JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceDisc')),T_PriceDisc) as discountpersen,
IF(px_type <> 'PN',JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceDiscRp')),T_PriceDiscRp) as discountrp,
if(IF(px_type <> 'PN',JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceDisc')),T_PriceDisc) <> 0,
(((IF(px_type <> 'PN',JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceDisc')),T_PriceDisc) / 100) * IF(px_type <> 'PN',JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceAmount')),T_PriceAmount)) + IF(px_type <> 'PN',JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceDiscRp')),T_PriceDiscRp)),
IF(px_type <> 'PN',JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceDiscRp')),T_PriceDiscRp)) as discount,
IF(px_type <> 'PN',( JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceAmount')) - ((JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceDisc')) / 100) * JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceAmount'))) - JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(Ss_PriceMouID),'$.T_PriceDiscRp')) ),T_PriceTotal) as total,
'Y' as status, 'N' as active, 'N' as cito, 'N' as cito_before, '' as promise, '' as charge,
child_test
FROM ss_price_mou
JOIN t_packet test ON test.T_PacketID = T_TestID
WHERE CONCAT(test.T_PacketSasCode,' ',test.T_PacketName) LIKE '{$search}'
AND Ss_PriceMouM_MouID = {$mouid} AND is_packet = 'Y' AND T_PriceIsCito <> 'Y'
) x LIMIT 50";
$query = $this->db_onedev->query($sql);
if (!$query) { $this->sys_error_db("search_test", $this->db_onedev); exit; }
$rows = $query->result_array();
foreach ($rows as $k => $v) {
$rows[$k]['status'] = ($v['status'] !== 'N');
$rows[$k]['cito'] = ($v['cito'] !== 'N');
$rows[$k]['charge'] = ['value' => 0, 'label' => '0%'];
if ($v['type'] === 'PXR') {
$nat_test_now = [];
$row_nattest = $this->db_onedev->query(
"SELECT T_TestNat_TestID FROM t_test
WHERE T_TestSasCode LIKE ? AND T_TestID <> ? AND T_TestIsActive = 'Y'",
[$v['pxsascode'] . '%', $v['pxid']]
)->result_array();
foreach ($row_nattest as $vnat) {
$nat_test_now[] = $vnat['T_TestNat_TestID'];
}
$rows[$k]['nat_test'] = $nat_test_now;
$child_test = json_decode($v['child_test']);
foreach ($child_test as $kchild => $vchild) {
$child_test[$kchild]->nat_test = json_decode($vchild->nat_test);
$row_test = $this->db_onedev->query(
"SELECT T_TestIsResult, T_TestCode, T_TestSasCode FROM t_test WHERE T_TestID = ? LIMIT 1",
[$vchild->T_TestID]
)->row_array();
if ($row_test) {
$child_test[$kchild]->isresult = $row_test['T_TestIsResult'];
$child_test[$kchild]->pxcode = $row_test['T_TestCode'];
$child_test[$kchild]->pxsascode = $row_test['T_TestSasCode'];
}
}
$rows[$k]['child_test'] = $child_test;
} else {
$rows[$k]['nat_test'] = json_decode($v['nat_test']);
$rows[$k]['child_test'] = json_decode($v['child_test']);
}
}
$this->sys_ok(['total' => count($rows), 'records' => $rows, 'total_display' => count($rows)]);
exit;
}
}

View File

@@ -0,0 +1,321 @@
<?php
class Ttv extends MY_Controller
{
public function index()
{
echo "TTV API";
}
public function __construct()
{
parent::__construct();
$this->db_onedev = $this->load->database("onedev", true);
$this->db_oneklinik = $this->load->database("onedev", true);
$this->load->library('ibl_encryptor');
}
// -----------------------------------------------------------------------
// POST /klinik/ttv/search
// Listing order yang sudah selesai screening (orderIsScreening='D')
// -----------------------------------------------------------------------
public function search()
{
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
return;
}
$prm = $this->sys_input;
$limit = 20;
$offset = (max(1, intval($prm['current_page'] ?? 1)) - 1) * $limit;
$where = ["o.orderIsScreening = 'D'", "o.orderIsActive = 'Y'"];
$binds = [];
// Filter tanggal
$start_date = $prm['start_date'] ?? date('Y-m-d');
$where[] = "DATE(o.orderDate) = ?";
$binds[] = $start_date;
// Filter status TTV
$status = $prm['status'] ?? '';
if ($status !== '') {
$where[] = "o.orderIsTTV = ?";
$binds[] = $status;
}
// Filter noreg
$noreg = trim($prm['noreg'] ?? '');
if ($noreg !== '') {
$where[] = "p.M_PatientNoReg LIKE ?";
$binds[] = '%' . $noreg . '%';
}
// Filter nama / HP via trigram index (PDP-safe)
$search = trim($prm['search'] ?? '');
if ($search !== '') {
$where[] = "(p.M_PatientName_bidx LIKE ? OR p.M_PatientHP_bidx LIKE ?)";
$binds[] = '%' . $search . '%';
$binds[] = '%' . $search . '%';
}
$where_sql = implode(' AND ', $where);
$sql = "SELECT
'N' AS divider,
p.M_PatientName, p.M_PatientName_enc,
p.M_PatientHP, p.M_PatientHP_enc,
p.M_PatientDOB, p.M_PatientDOB_enc,
p.M_PatientEmail, p.M_PatientEmail_enc,
p.M_PatientPhone, p.M_PatientPhone_enc,
p.M_PatientPOB, p.M_PatientPOB_enc,
p.M_PatientIDNumber, p.M_PatientIDNumber_enc,
p.M_PatientNIK, p.M_PatientNIK_enc,
p.M_PatientPhoto,
p.M_PatientPhotoThumb,
p.M_PatientNoReg,
p.M_PatientJob,
p.M_PatientM_SexID,
p.M_PatientM_TitleID,
p.M_PatientM_IdTypeID,
o.*,
DATE_FORMAT(o.orderDate, '%d-%m-%Y') AS date_order,
'' AS kode_status,
s.M_SexName,
t.M_TitleName
FROM one_klinik.`order` o
JOIN m_patient p ON p.M_PatientID = o.orderM_PatientID AND p.M_PatientIsActive = 'Y'
JOIN m_sex s ON s.M_SexID = p.M_PatientM_SexID
JOIN m_title t ON t.M_TitleID = p.M_PatientM_TitleID
WHERE $where_sql
ORDER BY o.orderDate ASC
LIMIT $limit OFFSET $offset";
$query = $this->db_oneklinik->query($sql, $binds);
if (!$query) {
$this->sys_error_db("ttv search", $this->db_oneklinik);
return;
}
$rows = $query->result_array();
$enc = $this->ibl_encryptor;
foreach ($rows as $k => $v) {
$rows[$k]['M_PatientName'] = $enc->decrypt($v['M_PatientName_enc'] ?? '') ?: $v['M_PatientName'];
$rows[$k]['M_PatientHP'] = $enc->decrypt($v['M_PatientHP_enc'] ?? '') ?: $v['M_PatientHP'];
$rows[$k]['M_PatientDOB'] = $enc->decrypt($v['M_PatientDOB_enc'] ?? '') ?: $v['M_PatientDOB'];
$rows[$k]['M_PatientEmail'] = $enc->decrypt($v['M_PatientEmail_enc'] ?? '') ?: $v['M_PatientEmail'];
$rows[$k]['M_PatientPhone'] = $enc->decrypt($v['M_PatientPhone_enc'] ?? '') ?: $v['M_PatientPhone'];
$rows[$k]['M_PatientPOB'] = $enc->decrypt($v['M_PatientPOB_enc'] ?? '') ?: $v['M_PatientPOB'];
$rows[$k]['M_PatientIDNumber'] = $enc->decrypt($v['M_PatientIDNumber_enc'] ?? '') ?: $v['M_PatientIDNumber'];
$rows[$k]['M_PatientNIK'] = $enc->decrypt($v['M_PatientNIK_enc'] ?? '') ?: $v['M_PatientNIK'];
$rows[$k]['patient_name'] = trim(($v['M_TitleName'] ?? '') . ' ' . $rows[$k]['M_PatientName']);
foreach (array_keys($rows[$k]) as $col) {
if (substr($col, -4) === '_enc') unset($rows[$k][$col]);
}
}
$this->sys_ok(['total' => count($rows), 'records' => $rows]);
}
// -----------------------------------------------------------------------
// POST /klinik/ttv/getttv
// Load data TTV yang sudah pernah disimpan untuk satu order
// -----------------------------------------------------------------------
public function getttv()
{
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
return;
}
$prm = $this->sys_input;
$orderid = intval($prm['orderid'] ?? 0);
if (!$orderid) {
$this->sys_error("orderid required");
return;
}
$row = $this->db_oneklinik->query(
"SELECT orderDoctorVitalSign, orderDoctorSaran AS xnote
FROM one_klinik.order_doctor
WHERE orderDoctorOrderID = ?
ORDER BY orderDoctorID DESC LIMIT 1",
[$orderid]
)->row_array();
$fisiks = null;
$xnote = '';
if ($row) {
$fisiks = $row['orderDoctorVitalSign']
? json_decode($row['orderDoctorVitalSign'], true)
: null;
$xnote = $row['xnote'] ?? '';
}
$this->sys_ok(['fisiks' => $fisiks, 'xnote' => $xnote]);
}
// -----------------------------------------------------------------------
// POST /klinik/ttv/savettv
// Simpan TTV ke order_doctor + order_tanda_vital, set orderIsTTV='D'
// -----------------------------------------------------------------------
public function savettv()
{
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
return;
}
$prm = $this->sys_input;
$userID = $this->sys_user['M_UserID'];
$orderid = intval($prm['orderid'] ?? 0);
$fisiks = $prm['fisiks'] ?? [];
$xnote = $prm['xnote'] ?? '';
if (!$orderid) {
$this->sys_error("orderid required");
return;
}
$fisiks_json = json_encode($fisiks);
// 1. Upsert order_doctor
$exists = $this->db_oneklinik->query(
"SELECT orderDoctorID FROM one_klinik.order_doctor WHERE orderDoctorOrderID = ? LIMIT 1",
[$orderid]
)->row_array();
if ($exists) {
$ok = $this->db_oneklinik->query(
"UPDATE one_klinik.order_doctor
SET orderDoctorVitalSign = ?,
orderDoctorSaran = ?,
orderDoctorLastUpdated = NOW()
WHERE orderDoctorOrderID = ?",
[$fisiks_json, $xnote, $orderid]
);
} else {
$ok = $this->db_oneklinik->query(
"INSERT INTO one_klinik.order_doctor
(orderDoctorOrderID, orderDoctorVitalSign, orderDoctorSaran,
orderDoctorType, orderDoctorIsActive, orderDoctorUserID, orderDoctorCreated)
VALUES (?, ?, ?, 'FORM', 'Y', ?, NOW())",
[$orderid, $fisiks_json, $xnote, $userID]
);
}
if (!$ok) {
$this->sys_error_db("upsert order_doctor", $this->db_oneklinik);
return;
}
// 2. Parse fisiks → nilai terstruktur untuk order_tanda_vital
$ttv = [
'pulse' => 0,
'sistole' => 0,
'diastole' => 0,
'temperature' => 0,
'weight' => 0,
'height' => 0,
'saturation' => 0,
];
foreach ((array)$fisiks as $item) {
$code = $item['id_code'] ?? '';
$value = trim($item['value'] ?? '');
switch ($code) {
case 'tanda_vital_1': $ttv['pulse'] = intval($value); break;
case 'tanda_vital_5':
$parts = explode('/', $value);
$ttv['sistole'] = intval($parts[0] ?? 0);
$ttv['diastole'] = intval($parts[1] ?? 0);
break;
case 'tanda_vital_6': $ttv['temperature'] = intval($value); break;
case 'tanda_vital_7': $ttv['saturation'] = intval($value); break;
case 'status_gizi_1': $ttv['weight'] = intval($value); break;
case 'status_gizi_2': $ttv['height'] = intval($value); break;
}
}
// 3. Upsert order_tanda_vital
$tv_exists = $this->db_oneklinik->query(
"SELECT orderTandaVitalID FROM one_klinik.order_tanda_vital WHERE orderTandaVitalOrderID = ? LIMIT 1",
[$orderid]
)->row_array();
if ($tv_exists) {
$this->db_oneklinik->query(
"UPDATE one_klinik.order_tanda_vital SET
orderTandaVitalPulse = ?,
orderTandaVitalSistole = ?,
orderTandaVitalDiastole = ?,
orderTandaVitalTemperature = ?,
orderTandaVitalWeight = ?,
orderTandaVitalHeight = ?,
orderTandaVitalSaturation = ?,
orderTandaVitalUserID = ?,
orderTandaVitalLastUpdated = NOW()
WHERE orderTandaVitalOrderID = ?",
[$ttv['pulse'], $ttv['sistole'], $ttv['diastole'],
$ttv['temperature'], $ttv['weight'], $ttv['height'],
$ttv['saturation'], $userID, $orderid]
);
} else {
$this->db_oneklinik->query(
"INSERT INTO one_klinik.order_tanda_vital
(orderTandaVitalOrderID, orderTandaVitalPulse, orderTandaVitalSistole,
orderTandaVitalDiastole, orderTandaVitalTemperature, orderTandaVitalWeight,
orderTandaVitalHeight, orderTandaVitalSaturation,
orderTandaVitalIsActive, orderTandaVitalUserID, orderTandaVitalCreated)
VALUES (?,?,?,?,?,?,?,?,'Y',?,NOW())",
[$orderid, $ttv['pulse'], $ttv['sistole'], $ttv['diastole'],
$ttv['temperature'], $ttv['weight'], $ttv['height'],
$ttv['saturation'], $userID]
);
}
// 4. Update status order
$this->db_oneklinik->query(
"UPDATE one_klinik.`order` SET orderIsTTV = 'D', orderUserID = ? WHERE orderID = ?",
[$userID, $orderid]
);
$this->sys_ok(['process' => 'OK']);
}
// -----------------------------------------------------------------------
// POST /klinik/ttv/getsexreg
// Return kartuidentitass, sexes, titles, religions
// -----------------------------------------------------------------------
public function getsexreg()
{
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
return;
}
$rows = [];
$rows['kartuidentitass'] = $this->db_onedev->query(
"SELECT * FROM m_idtype WHERE M_IdTypeIsActive = 'Y'"
)->result_array();
$rows['sexes'] = $this->db_onedev->query(
"SELECT * FROM m_sex WHERE M_SexIsActive = 'Y'"
)->result_array();
$rows['titles'] = $this->db_onedev->query(
"SELECT * FROM m_title WHERE M_TitleIsActive = 'Y'"
)->result_array();
$rows['religions'] = $this->db_onedev->query(
"SELECT * FROM m_religion WHERE M_ReligionIsActive = 'Y'"
)->result_array();
$this->sys_ok($rows);
}
}

View File

@@ -10,7 +10,7 @@ class Patient extends MY_Controller
{
parent::__construct();
$this->db_onedev = $this->load->database("onedev", true);
//$this->db_onedev = $this->load->database("onedev", true);
$this->load->library('ibl_encryptor');
}
public function add_notes($orderid){
@@ -61,62 +61,66 @@ class Patient extends MY_Controller
*/
$number_limit = 10;
$number_offset = ($prm['current_page'] - 1) * $number_limit ;
$where = " ( DATE(orderDate) = '{$startdate}' ) AND ";
if($search != ''){
$where = "( M_PatientName LIKE '%{$search}%' OR orderNumber LIKE '%{$search}%' ) AND ";
if(strlen($search) == 11){
$number_offset = ($prm['current_page'] - 1) * $number_limit;
$where = " ( DATE(orderDate) BETWEEN '{$startdate}' AND '{$enddate}' ) AND ";
if ($search != '') {
if (strlen($search) == 11) {
$where = "orderNumber = '{$search}' AND ";
} else {
$tokens = $this->ibl_encryptor->query_tokens($search);
if ($tokens) {
$bidx_conds = implode(' AND ', array_map(function($h) {
return "JSON_CONTAINS(M_PatientName_bidx, '\"$h\"')";
}, $tokens));
$where = "( orderNumber LIKE '%{$search}%' OR ({$bidx_conds}) ) AND ";
} else {
$where = "orderNumber LIKE '%{$search}%' AND ";
}
}
}
$sql = " SELECT count(*) as total
$sql = "SELECT count(*) as total
FROM one_klinik.`order`
JOIN m_patient ON orderM_PatientID = M_PatientID
JOIN m_title ON M_PatientM_TitleID = M_TitleID
JOIN m_title ON M_PatientM_TitleID = M_TitleID
JOIN m_sex ON M_PatientM_SexID = M_SexID
WHERE
$where
( ('{$status}' = 'N' AND orderIsLunas = 'N') OR ('{$status}' = 'Y' AND orderIsLunas = 'Y') )";
$query = $this->db_onedev->query($sql, $sql_param);
//echo $this->db_onedev->last_query();
$query = $this->db_onedev->query($sql);
$tot_count = 0;
$tot_page = 0;
$tot_page = 0;
if ($query) {
$tot_count = $query->result_array()[0]["total"];
$tot_page = ceil($tot_count/$number_limit);
$tot_page = ceil($tot_count / $number_limit);
} else {
$this->sys_error_db("t_samplestorage count", $this->db_onedev);
$this->sys_error_db("patient count", $this->db_onedev);
exit;
}
$sql = "SELECT orderID,
}
$sql = "SELECT orderID,
orderDate,
orderNumber,
orderM_PatientID,
M_PatientNoReg,
orderKeluhan,
DATE_FORMAT(orderDate,'%d-%m-%Y %H:%i') as order_date,
CONCAT(M_TitleName,'. ',M_PatientName) as M_PatientName,
CONCAT(M_TitleLangName,'. ',M_PatientName) as M_PatientName_eng,
M_TitleName,
M_PatientName_enc,
M_PatientName AS patient_name_masked,
M_PatientPrefix, M_PatientSuffix,
M_TitleName, M_TitleLangName,
orderTotal as totalbill,
0 as paid,
0 as unpaid,
orderIsLunas as flaglunas,
'' as notes,
100 as mindp_percent,
100 as mindp_percent,
settingPriceDefault as mindp_amount,
0 as F_BillDetailID
FROM one_klinik.`order`
JOIN m_patient ON orderM_PatientID = M_PatientID
JOIN m_title ON M_PatientM_TitleID = M_TitleID
JOIN m_title ON M_PatientM_TitleID = M_TitleID
JOIN m_sex ON M_PatientM_SexID = M_SexID
JOIN one_klinik.`setting` ON settingIsActive = 'Y'
WHERE
@@ -124,23 +128,36 @@ class Patient extends MY_Controller
( ('{$status}' = 'N' AND orderIsLunas = 'N') OR ('{$status}' = 'Y' AND orderIsLunas = 'Y') )
GROUP BY orderID
ORDER BY orderID ASC
limit $number_limit offset $number_offset";
//echo $sql;
$query = $this->db_onedev->query($sql, $sql_param);
//echo $this->db_onedev->last_query();
$rows = $query->result_array();
if($rows){
foreach($rows as $k => $v){
$sql = "SELECT IFNULL(SUM(PaymentTotal),0) as total
FROM one_klinik.payment
WHERE
PaymentOrderID = ? AND PaymentIsActive = 'Y'";
$data_payment = $this->db_onedev->query($sql, array($v['orderID']))->row();
$unpaid = $v['totalbill'] - $data_payment->total;
$rows[$k]['unpaid'] = $unpaid;
$rows[$k]['paid'] = $data_payment->total;
LIMIT $number_limit OFFSET $number_offset";
$rows[$k]['notes'] = $this->add_notes($v['orderID']);
$query = $this->db_onedev->query($sql);
if (!$query) {
$this->sys_error_db("patient rows", $this->db_onedev);
exit;
}
$rows = $query->result_array();
$enc = $this->ibl_encryptor;
if ($rows) {
foreach ($rows as $k => $v) {
$p_name = $enc->decrypt($v['M_PatientName_enc'] ?? '') ?: $v['patient_name_masked'];
$title = $v['M_TitleName'] ? $v['M_TitleName'] . '. ' : '';
$title_e = $v['M_TitleLangName'] ? $v['M_TitleLangName'] . '. ': '';
$prefix = $v['M_PatientPrefix'] ? $v['M_PatientPrefix'] . ' ' : '';
$suffix = $v['M_PatientSuffix'] ? ' ' . $v['M_PatientSuffix'] : '';
$rows[$k]['M_PatientName'] = trim($title . $prefix . $p_name . $suffix);
$rows[$k]['M_PatientName_eng'] = trim($title_e . $prefix . $p_name . $suffix);
unset($rows[$k]['M_PatientName_enc'], $rows[$k]['patient_name_masked'],
$rows[$k]['M_PatientPrefix'], $rows[$k]['M_PatientSuffix'],
$rows[$k]['M_TitleLangName']);
$data_payment = $this->db_onedev->query(
"SELECT IFNULL(SUM(PaymentTotal),0) as total FROM one_klinik.payment
WHERE PaymentOrderID = ? AND PaymentIsActive = 'Y'",
[$v['orderID']]
)->row();
$rows[$k]['unpaid'] = $v['totalbill'] - $data_payment->total;
$rows[$k]['paid'] = $data_payment->total;
$rows[$k]['notes'] = $this->add_notes($v['orderID']);
}
}

View File

@@ -14,6 +14,7 @@ class Anamnesedoctor extends MY_Controller
parent::__construct();
$this->db_onedev = $this->load->database("onedev", true);
$this->db_oneklinik = $this->load->database("onedev", true);
$this->load->library('ibl_encryptor');
$this->IP_SOCKET_IO = "localhost";
}
@@ -35,17 +36,27 @@ class Anamnesedoctor extends MY_Controller
'N' divider,
M_PatientID,
M_PatientNoReg,
M_PatientPhoto,
M_PatientPhotoThumb,
M_PatientPrefix,
M_PatientName,
M_PatientName_enc,
M_PatientSuffix,
M_PatientHP,
M_PatientHP_enc,
M_PatientEmail,
M_PatientEmail_enc,
M_PatientPOB,
M_PatientPOB_enc,
M_PatientPhone,
M_PatientPhone_enc,
M_PatientIDNumber,
M_PatientIDNumber_enc,
DATE_FORMAT(M_PatientDOB,'%d-%m-%Y') as M_PatientDOB,
M_PatientDOB_enc,
M_PatientNote,
M_PatientNIK,
M_PatientNIK_enc,
M_PatientJabatan,
M_PatientKedudukan,
M_PatientPJ,
@@ -61,9 +72,12 @@ class Anamnesedoctor extends MY_Controller
M_IdTypeName,
M_PatientIDNumber,
IF(ISNULL(M_PatientSuspendID),'active','suspend' ) as status,
M_PatientAddressM_KelurahanID M_KelurahanID,
0 M_DistrictID,
0 M_CityID,
M_PatientAddressM_KelurahanID M_KelurahanID,
M_PatientAddressRegionalCd,
M_PatientAddressDescription,
M_PatientAddressDescription_enc,
0 M_DistrictID,
0 M_CityID,
0 M_ProvinceID
FROM one_klinik.order
JOIN m_patient ON M_PatientID = orderM_PatientID AND M_PatientIsActive = 'Y'
@@ -86,40 +100,90 @@ class Anamnesedoctor extends MY_Controller
$rows = $query->result_array();
foreach ($rows as $k => $v) {
$rows[$k]['M_PatientName'] = stripslashes($rows[$k]['M_PatientName']);
$rows[$k]['M_PatientAddressDescription'] = stripslashes($v['M_PatientAddressDescription']);
$patient_name = str_replace("'", "\\'", $prm['M_PatientName']);
$sql = "SELECT *, concat('{$rows[$k]['M_PatientAddressDescription']}', '\n\n',
m_kelurahanname, ', ',
m_districtname,'\n',
m_cityname, ', ',
m_provincename) as xaddress
FROM m_kelurahan
JOIN m_district ON M_KelurahanM_DistrictID = M_DistrictID
JOIN m_city ON M_DistrictM_CityID = M_CityID
JOIN m_province ON M_CityM_ProvinceID = M_ProvinceID
WHERE
M_KelurahanID = {$v['M_KelurahanID']} ";
//echo $sql;
$row_address = $this->db_onedev->query($sql)->row_array();
$rows[$k]['M_PatientAddress'] = stripslashes($row_address['xaddress']);
$rows[$k]['M_DistrictID'] = $row_address['M_DistrictID'];
$rows[$k]['M_CityID'] = $row_address['M_CityID'];
$rows[$k]['M_ProvinceID'] = $row_address['M_ProvinceID'];
$info = $this->db_onedev->query("SELECT fn_fo_patient_visit(?) info", [$v['M_PatientID']])->row();
$rows[$k]['info'] = json_decode($info->info);
}
$enc = $this->ibl_encryptor;
$rows[$k]['M_PatientName'] = $enc->decrypt($v['M_PatientName_enc'] ?? '') ?: stripslashes($v['M_PatientName']);
$rows[$k]['M_PatientHP'] = $enc->decrypt($v['M_PatientHP_enc'] ?? '') ?: $v['M_PatientHP'];
$rows[$k]['M_PatientEmail'] = $enc->decrypt($v['M_PatientEmail_enc'] ?? '') ?: $v['M_PatientEmail'];
$rows[$k]['M_PatientPOB'] = $enc->decrypt($v['M_PatientPOB_enc'] ?? '') ?: $v['M_PatientPOB'];
$rows[$k]['M_PatientPhone'] = $enc->decrypt($v['M_PatientPhone_enc'] ?? '') ?: $v['M_PatientPhone'];
$rows[$k]['M_PatientIDNumber'] = $enc->decrypt($v['M_PatientIDNumber_enc'] ?? '') ?: $v['M_PatientIDNumber'];
$rows[$k]['M_PatientDOB'] = $enc->decrypt($v['M_PatientDOB_enc'] ?? '') ?: $v['M_PatientDOB'];
$rows[$k]['M_PatientNIK'] = $enc->decrypt($v['M_PatientNIK_enc'] ?? '') ?: $v['M_PatientNIK'];
$rows[$k]['M_PatientAddressDescription'] = $enc->decrypt($v['M_PatientAddressDescription_enc'] ?? '') ?: stripslashes($v['M_PatientAddressDescription'] ?? '');
$reg_cd = $v['M_PatientAddressRegionalCd'] ?? '';
if ($reg_cd) {
$reg = $this->db_onedev->query(
"SELECT r_kel.regional_nm as kel_name, r_kec.regional_nm as kec_name, r_kab.regional_nm as kab_name, r_pro.regional_nm as pro_name
FROM regional r_kel
LEFT JOIN regional r_kec ON r_kec.regional_cd = CONCAT(r_kel.pro_cd, r_kel.kab_cd, r_kel.kec_cd, '000')
LEFT JOIN regional r_kab ON r_kab.regional_cd = CONCAT(r_kel.pro_cd, r_kel.kab_cd, '000', '000')
LEFT JOIN regional r_pro ON r_pro.regional_cd = CONCAT(r_kel.pro_cd, '00', '000', '000')
WHERE r_kel.regional_cd = ?", [$reg_cd]
)->row_array();
$rows[$k]['M_PatientAddress'] = $rows[$k]['M_PatientAddressDescription'] . "\n\n" .
implode(', ', array_filter([$reg['kel_name'] ?? '', $reg['kec_name'] ?? '', $reg['kab_name'] ?? '', $reg['pro_name'] ?? '']));
} else {
$rows[$k]['M_PatientAddress'] = $rows[$k]['M_PatientAddressDescription'];
}
$rows[$k]['info'] = $this->build_patient_visit_info($v['M_PatientID'], $rows[$k]['M_PatientDOB']);
}
$result = array("total" => 1, "records" => $rows, "sql" => $this->db_onedev->last_query());
$this->sys_ok($result);
} else {
$this->sys_error_db("m_patient rows", $this->db_onedev);
exit;
}
}
function get_data()
}
}
protected function build_patient_visit_info($patient_id, $patient_dob)
{
$visit = 1;
$birthday = 'N';
$visit_query = $this->db_onedev->query(
"SELECT COUNT(DISTINCT T_OrderHeaderID) AS n
FROM t_orderheader
JOIN t_orderdetail ON T_OrderHeaderID = T_OrderDetailT_OrderHeaderID AND T_OrderDetailIsActive = 'Y'
WHERE T_OrderHeaderIsActive = 'Y'
AND T_OrderHeaderM_PatientID = ?",
[$patient_id]
);
if ($visit_query) {
$visit_row = $visit_query->row_array();
$visit += (int) ($visit_row['n'] ?? 0);
}
$init_visit_query = $this->db_onedev->query(
"SELECT M_PatientInitialVisit
FROM m_patient
WHERE M_PatientID = ?",
[$patient_id]
);
if ($init_visit_query) {
$init_visit_row = $init_visit_query->row_array();
if (!empty($init_visit_row['M_PatientInitialVisit'])) {
$visit += (int) $init_visit_row['M_PatientInitialVisit'];
}
}
$dob_time = empty($patient_dob) ? false : strtotime($patient_dob);
if ($dob_time !== false) {
$birthday = date('m-d', $dob_time) === date('m-d') ? 'Y' : 'N';
}
return json_decode(json_encode([
'visit' => $visit,
'birthday' => $birthday,
]));
}
function get_data()
{
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
@@ -1785,34 +1849,38 @@ class Anamnesedoctor extends MY_Controller
$status = $prm['status'];
$sql = "SELECT 'N' divider,
CONCAT(M_TitleName,' ',IF(ISNULL(M_PatientPrefix),'',CONCAT(M_PatientPrefix,' ')),M_PatientName,IF(ISNULL(M_PatientSuffix),'',CONCAT(M_PatientSuffix,' '))) as patient_name,
`order`.*,DATE_FORMAT(orderDate,'%d-%m-%Y') as date_order,
'' as kode_status, '' as status
`order`.*,
DATE_FORMAT(orderDate,'%d-%m-%Y') as date_order,
'' as kode_status, '' as status,
M_PatientName as patient_name_masked,
M_PatientName_enc as patient_name_enc,
M_PatientPrefix,
M_PatientSuffix,
M_TitleName
FROM one_klinik.`order`
JOIN m_patient ON orderM_PatientID = M_PatientID
JOIN m_title ON M_PatientM_TitleID = M_TitleID
LEFT JOIN s_menu ON ( S_MenuUrl LIKE CONCAT('%test/vuex/one-klinik-fo-registration-v') OR S_MenuName = 'Periksa dokter')
WHERE
orderIsActive = 'Y' AND DATE(orderDate) = ? AND orderIsScreening = 'D' AND orderIsCheck = ?
WHERE
orderIsActive = 'Y' AND DATE(orderDate) = ? AND orderIsScreening = 'D' AND orderIsCheck = ?
LIMIT $number_limit offset $number_offset";
//echo $sql;
$query = $this->db_oneklinik->query($sql, array($xdate, $status));
//echo $this->db_oneklinik->last_query();
if ($query) {
$rows = $query->result_array();
foreach ($rows as $key => $value) {
$sql = "SELECT
FROM one_klinik.order_status
WHERE
orderStatusOrderID = ?
ORDER BY ";
}
$enc = $this->ibl_encryptor;
$rows = array_map(function($row) use ($enc) {
$name = $enc->decrypt($row['patient_name_enc'] ?? '') ?: $row['patient_name_masked'];
$prefix = $row['M_PatientPrefix'] ? $row['M_PatientPrefix'] . ' ' : '';
$suffix = $row['M_PatientSuffix'] ? ' ' . $row['M_PatientSuffix'] : '';
$title = $row['M_TitleName'] ? $row['M_TitleName'] . ' ' : '';
$row['patient_name'] = trim($title . $prefix . $name . $suffix);
unset($row['patient_name_masked'], $row['patient_name_enc']);
return $row;
}, $query->result_array());
$result = array("total" => $tot_page, "records" => $rows, "sql" => $this->db_onedev->last_query());
$result = array("total" => count($rows), "records" => $rows);
$this->sys_ok($result);
} else {
$this->sys_error_db("m_patient rows", $this->db_onedev);
$this->sys_error_db("list_patient", $this->db_oneklinik);
exit;
}
}
@@ -2368,6 +2436,8 @@ function get_resume_medic(){
$receipt = [];
$saran = [];
$tindakan = [];
$vaksinasi_list = [];
$tindakan_medis_list = [];
$doctor = [];
$pemeriksaan_penunjang = [];
@@ -2562,6 +2632,40 @@ function get_resume_medic(){
$receipt[] = $data_periksa_doctor['text']['receipt'];
$saran[] = $data_periksa_doctor['text']['saran'];
$tindakan[] = $data_periksa_doctor['text']['tindakan'];
// Vaksinasi per order
$qv = $this->db_oneklinik->query(
"SELECT ov.*,
t.T_TestName as jenis_vaksin_name,
t.T_TestSasCode as jenis_vaksin_code,
ins.M_InjectionSiteName as injection_site_name,
rv.M_RouteVaccineName as route_name,
s.M_StaffName as petugas_name
FROM one_klinik.order_vaccine ov
LEFT JOIN one_lab.t_test t ON ov.orderVaccineT_TestID = t.T_TestID
LEFT JOIN one_klinik.m_injection_site ins ON ov.orderVaccineInjectionSiteCode = ins.M_InjectionSiteCode
LEFT JOIN one_klinik.m_route_vaccine rv ON ov.orderVaccineRouteCode = rv.M_RouteVaccineCode
LEFT JOIN one_lab.m_staff s ON ov.orderVaccinePetugasM_StaffID = s.M_StaffID
WHERE ov.orderVaccineOrderID = ? AND ov.orderVaccineIsActive = 'Y'
ORDER BY ov.orderVaccineCreated ASC",
[$value['orderID']]
);
$vaksinasi_list[] = $qv ? $qv->result_array() : [];
// Tindakan medis per order
$qt = $this->db_oneklinik->query(
"SELECT ot.*,
t.T_TestName as jenis_tindakan_name,
t.T_TestSasCode as jenis_tindakan_code,
d.M_DoctorName as dokter_name
FROM one_klinik.order_tindakan ot
LEFT JOIN one_lab.t_test t ON ot.orderTindakanT_TestID = t.T_TestID
LEFT JOIN one_lab.m_doctor d ON ot.orderTindakanM_DoctorID = d.M_DoctorID
WHERE ot.orderTindakanOrderID = ? AND ot.orderTindakanIsActive = 'Y'
ORDER BY ot.orderTindakanCreated ASC",
[$value['orderID']]
);
$tindakan_medis_list[] = $qt ? $qt->result_array() : [];
}
$data_orders['date_orders'] = $date_orders;
@@ -2598,6 +2702,8 @@ function get_resume_medic(){
$data_orders['receipt'] = $receipt;
$data_orders['saran'] = $saran;
$data_orders['tindakan'] = $tindakan;
$data_orders['vaksinasi_list'] = $vaksinasi_list;
$data_orders['tindakan_medis_list'] = $tindakan_medis_list;
$data_orders['pemeriksaan_penunjang'] = $pemeriksaan_penunjang;
$this->sys_ok($data_orders);
@@ -3096,5 +3202,491 @@ function get_data_order_anamnesis($orderID){
return array('text'=>$doctor_text,'form'=>$doctor_form);
}
// ─── Vaksin ────────────────────────────────────────────────────────────────
// Master statis: injection_sites, routes (dipanggil sekali saat form dibuka)
function get_vaccine_masters()
{
if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; }
// Lokasi suntik
$q = $this->db_oneklinik->query(
"SELECT M_InjectionSiteCode as code, M_InjectionSiteName as name
FROM one_klinik.m_injection_site
WHERE M_InjectionSiteIsActive = 'Y'
ORDER BY M_InjectionSiteID"
);
if (!$q) { $this->sys_error_db("get m_injection_site", $this->db_oneklinik); exit; }
$result['injection_sites'] = $q->result_array();
// Rute vaksin
$q = $this->db_oneklinik->query(
"SELECT M_RouteVaccineCode as code, M_RouteVaccineName as name
FROM one_klinik.m_route_vaccine
WHERE M_RouteVaccineIsActive = 'Y'
ORDER BY M_RouteVaccineID"
);
if (!$q) { $this->sys_error_db("get m_route_vaccine", $this->db_oneklinik); exit; }
$result['routes'] = $q->result_array();
$this->sys_ok($result);
exit;
}
// Autocomplete petugas penyuntik dari one_lab.m_staff, param: search
function get_vaccine_petugas()
{
if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; }
$search = trim($this->sys_input['search'] ?? '');
$search_esc = $this->db_onedev->escape_str($search);
$sql = "SELECT M_StaffID as id, M_StaffName as name, M_StaffCode as code
FROM one_lab.m_staff
WHERE M_StaffIsActive = 'Y'
AND M_StaffName LIKE CONCAT('%', '{$search_esc}', '%')
ORDER BY M_StaffName
LIMIT 30";
$q = $this->db_onedev->query($sql);
if (!$q) { $this->sys_error_db("get m_staff", $this->db_onedev); exit; }
$this->sys_ok(['records' => $q->result_array()]);
exit;
}
// Autocomplete jenis vaksin: filter by MOU order, param: orderid + search
function get_vaccines()
{
if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; }
$prm = $this->sys_input;
$orderid = intval($prm['orderid'] ?? 0);
$search = trim($prm['search'] ?? '');
if (!$orderid) { $this->sys_error("orderid required"); exit; }
// Ambil MOU dari order
$order_row = $this->db_oneklinik->query(
"SELECT orderM_MouID FROM one_klinik.`order` WHERE orderID = ? LIMIT 1",
[$orderid]
)->row_array();
if (!$order_row || !$order_row['orderM_MouID']) {
$this->sys_ok(['records' => []]);
exit;
}
$mou_id = intval($order_row['orderM_MouID']);
$search_esc = $this->db_onedev->escape_str($search);
$sql = "SELECT
spm.Ss_PriceMouID as ss_price_mou_id,
spm.Ss_PriceMouM_MouID as mouid,
0 as xid,
spm.Nat_TestID as nat_testid,
spm.nat_test,
spm.is_packet,
spm.packet_id,
spm.px_type as type,
spm.T_TestID as pxid,
t.T_TestCode as pxcode,
t.T_TestSasCode as pxsascode,
t.T_TestName as test_name,
CONCAT(t.T_TestSasCode,' ',t.T_TestName) as pxname,
t.T_TestIsResult as isresult,
JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceAmount')) as bruto,
JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceDisc')) as discountpersen,
JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceDiscRp')) as discountrp,
if(JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceDisc')) <> 0,
(((JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceDisc')) / 100)
* JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceAmount')))
+ JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceDiscRp'))),
JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceDiscRp'))
) as discount,
( JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceAmount'))
- ((JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceDisc')) / 100)
* JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceAmount')))
- JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceDiscRp'))
) as total,
spm.child_test
FROM one_lab.ss_price_mou spm
JOIN one_lab.t_test t ON spm.T_TestID = t.T_TestID AND t.T_TestIsActive = 'Y'
WHERE spm.Ss_PriceMouM_MouID = {$mou_id}
AND spm.is_packet = 'N'
AND spm.px_type = 'PX'
AND CONCAT(t.T_TestSasCode,' ',t.T_TestName) LIKE CONCAT('%', '{$search_esc}', '%')
ORDER BY t.T_TestName
LIMIT 50";
$q = $this->db_onedev->query($sql);
if (!$q) { $this->sys_error_db("get jenis vaksin", $this->db_onedev); exit; }
$records = array_map(function($row) {
$row['nat_test'] = json_decode($row['nat_test'] ?? '[]', true) ?: [];
$row['child_test'] = json_decode($row['child_test'] ?? '[]', true) ?: [];
return $row;
}, $q->result_array());
$this->sys_ok(['records' => $records]);
exit;
}
// List vaksin yang sudah tersimpan untuk satu order
function list_order_vaccines()
{
if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; }
$prm = $this->sys_input;
$orderid = intval($prm['orderid'] ?? 0);
if (!$orderid) { $this->sys_error("orderid required"); exit; }
$sql = "SELECT
ov.*,
t.T_TestName as jenis_vaksin_name,
t.T_TestSasCode as jenis_vaksin_code,
ins.M_InjectionSiteName as injection_site_name,
rv.M_RouteVaccineName as route_name,
s.M_StaffName as petugas_name
FROM one_klinik.order_vaccine ov
LEFT JOIN one_lab.t_test t ON ov.orderVaccineT_TestID = t.T_TestID
LEFT JOIN one_klinik.m_injection_site ins
ON ov.orderVaccineInjectionSiteCode = ins.M_InjectionSiteCode
LEFT JOIN one_klinik.m_route_vaccine rv
ON ov.orderVaccineRouteCode = rv.M_RouteVaccineCode
LEFT JOIN one_lab.m_staff s ON ov.orderVaccinePetugasM_StaffID = s.M_StaffID
WHERE ov.orderVaccineOrderID = ?
AND ov.orderVaccineIsActive = 'Y'
ORDER BY ov.orderVaccineCreated ASC";
$q = $this->db_oneklinik->query($sql, [$orderid]);
if (!$q) { $this->sys_error_db("list order_vaccine", $this->db_oneklinik); exit; }
$this->sys_ok(['records' => $q->result_array()]);
exit;
}
function save_vaccine()
{
if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; }
$prm = $this->sys_input;
$userID = $this->sys_user['M_UserID'];
$orderid = intval($prm['orderid'] ?? 0);
$vaccine_id = intval($prm['vaccine_id'] ?? 0); // orderVaccineID; 0 = insert baru
$t_test_id = intval($prm['t_test_id'] ?? 0);
if (!$orderid || !$t_test_id) {
$this->sys_error("orderid dan t_test_id wajib diisi");
exit;
}
$batch = trim($prm['batch_number'] ?? '');
$expired = trim($prm['expired_date'] ?? '');
$dosis = max(1, intval($prm['dosis'] ?? 1));
$site_code = trim($prm['injection_site_code'] ?? '');
$route_code = trim($prm['route_code'] ?? '');
$petugas_id = isset($prm['petugas_id']) && $prm['petugas_id'] ? intval($prm['petugas_id']) : null;
$given_at = trim($prm['given_at'] ?? '');
$next_date = trim($prm['next_date'] ?? '');
$catatan = trim($prm['catatan'] ?? '');
$kipi = trim($prm['kipi'] ?? '');
$observasi15 = ($prm['observasi_15'] ?? false) ? 'Y' : 'N';
$reaksi_alergi = ($prm['reaksi_alergi'] ?? false) ? 'Y' : 'N';
$ss_price_mou_id = isset($prm['ss_price_mou_id']) && $prm['ss_price_mou_id'] ? intval($prm['ss_price_mou_id']) : null;
$bruto = floatval($prm['bruto'] ?? 0);
$disc_persen = floatval($prm['discountpersen'] ?? 0);
$disc_rp = floatval($prm['discountrp'] ?? 0);
$total = floatval($prm['total'] ?? 0);
$given_at_sql = ($given_at && strtotime($given_at)) ? date('Y-m-d H:i:s', strtotime($given_at)) : date('Y-m-d H:i:s');
$expired_val = ($expired && strtotime($expired)) ? date('Y-m-d', strtotime($expired)) : null;
$next_date_val = ($next_date && strtotime($next_date)) ? date('Y-m-d', strtotime($next_date)) : null;
if ($vaccine_id > 0) {
$ok = $this->db_oneklinik->query(
"UPDATE one_klinik.order_vaccine SET
orderVaccineT_TestID = ?,
orderVaccineSsPriceMouID = ?,
orderVaccineBruto = ?,
orderVaccineDiscPersen = ?,
orderVaccineDiscRp = ?,
orderVaccineTotal = ?,
orderVaccineBatchNumber = ?,
orderVaccineExpiredDate = ?,
orderVaccineDosis = ?,
orderVaccineInjectionSiteCode = ?,
orderVaccineRouteCode = ?,
orderVaccinePetugasM_StaffID = ?,
orderVaccineGivenAt = ?,
orderVaccineNextDate = ?,
orderVaccineCatatan = ?,
orderVaccineKipi = ?,
orderVaccineObservasi15 = ?,
orderVaccineReaksiAlergi = ?,
orderVaccineUserID = ?
WHERE orderVaccineID = ? AND orderVaccineOrderID = ?",
[
$t_test_id, $ss_price_mou_id, $bruto, $disc_persen, $disc_rp, $total,
$batch ?: null, $expired_val, $dosis,
$site_code ?: null, $route_code ?: null, $petugas_id,
$given_at_sql, $next_date_val, $catatan ?: null,
$kipi ?: null, $observasi15, $reaksi_alergi,
$userID, $vaccine_id, $orderid
]
);
} else {
$ok = $this->db_oneklinik->query(
"INSERT INTO one_klinik.order_vaccine
(orderVaccineOrderID, orderVaccineT_TestID,
orderVaccineSsPriceMouID, orderVaccineBruto, orderVaccineDiscPersen,
orderVaccineDiscRp, orderVaccineTotal,
orderVaccineBatchNumber, orderVaccineExpiredDate, orderVaccineDosis,
orderVaccineInjectionSiteCode, orderVaccineRouteCode,
orderVaccinePetugasM_StaffID, orderVaccineGivenAt,
orderVaccineNextDate, orderVaccineCatatan,
orderVaccineKipi, orderVaccineObservasi15, orderVaccineReaksiAlergi,
orderVaccineUserID)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
[
$orderid, $t_test_id,
$ss_price_mou_id, $bruto, $disc_persen, $disc_rp, $total,
$batch ?: null, $expired_val, $dosis,
$site_code ?: null, $route_code ?: null, $petugas_id,
$given_at_sql, $next_date_val, $catatan ?: null,
$kipi ?: null, $observasi15, $reaksi_alergi, $userID
]
);
$vaccine_id = $this->db_oneklinik->insert_id();
}
if (!$ok) { $this->sys_error_db("save order_vaccine", $this->db_oneklinik); exit; }
$this->sys_ok(['orderVaccineID' => $vaccine_id]);
exit;
}
function delete_vaccine()
{
if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; }
$prm = $this->sys_input;
$vaccine_id = intval($prm['orderVaccineID'] ?? 0);
$userID = $this->sys_user['M_UserID'];
if (!$vaccine_id) { $this->sys_error("orderVaccineID required"); exit; }
$ok = $this->db_oneklinik->query(
"UPDATE one_klinik.order_vaccine SET orderVaccineIsActive = 'N', orderVaccineUserID = ?
WHERE orderVaccineID = ?",
[$userID, $vaccine_id]
);
if (!$ok) { $this->sys_error_db("delete order_vaccine", $this->db_oneklinik); exit; }
$this->sys_ok(['msg' => 'deleted']);
exit;
}
// ── TINDAKAN MEDIS ────────────────────────────────────────────────────────
// Autocomplete jenis tindakan dari ss_price_mou berdasarkan MOU order
function get_tindakan()
{
if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; }
$prm = $this->sys_input;
$orderid = intval($prm['orderid'] ?? 0);
$search = trim($prm['search'] ?? '');
if (!$orderid) { $this->sys_error("orderid required"); exit; }
$order_row = $this->db_oneklinik->query(
"SELECT orderM_MouID FROM one_klinik.`order` WHERE orderID = ? LIMIT 1",
[$orderid]
)->row_array();
if (!$order_row || !$order_row['orderM_MouID']) {
$this->sys_ok(['records' => []]);
exit;
}
$mou_id = intval($order_row['orderM_MouID']);
$search_esc = $this->db_onedev->escape_str($search);
$sql = "SELECT
spm.Ss_PriceMouID as ss_price_mou_id,
spm.Ss_PriceMouM_MouID as mouid,
0 as xid,
spm.Nat_TestID as nat_testid,
spm.nat_test,
spm.is_packet,
spm.packet_id,
spm.px_type as type,
spm.T_TestID as pxid,
t.T_TestCode as pxcode,
t.T_TestSasCode as pxsascode,
t.T_TestName as test_name,
CONCAT(t.T_TestSasCode,' ',t.T_TestName) as pxname,
t.T_TestIsResult as isresult,
JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceAmount')) as bruto,
JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceDisc')) as discountpersen,
JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceDiscRp')) as discountrp,
if(JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceDisc')) <> 0,
(((JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceDisc')) / 100)
* JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceAmount')))
+ JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceDiscRp'))),
JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceDiscRp'))
) as discount,
( JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceAmount'))
- ((JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceDisc')) / 100)
* JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceAmount')))
- JSON_UNQUOTE(JSON_EXTRACT(one_json_sum(spm.Ss_PriceMouID),'$.T_PriceDiscRp'))
) as total,
spm.child_test
FROM one_lab.ss_price_mou spm
JOIN one_lab.t_test t ON spm.T_TestID = t.T_TestID AND t.T_TestIsActive = 'Y'
WHERE spm.Ss_PriceMouM_MouID = {$mou_id}
AND spm.is_packet = 'N'
AND spm.px_type = 'PX'
AND CONCAT(t.T_TestSasCode,' ',t.T_TestName) LIKE CONCAT('%', '{$search_esc}', '%')
ORDER BY t.T_TestName
LIMIT 50";
$q = $this->db_onedev->query($sql);
if (!$q) { $this->sys_error_db("get jenis tindakan", $this->db_onedev); exit; }
$records = array_map(function($row) {
$row['nat_test'] = json_decode($row['nat_test'] ?? '[]', true) ?: [];
$row['child_test'] = json_decode($row['child_test'] ?? '[]', true) ?: [];
return $row;
}, $q->result_array());
$this->sys_ok(['records' => $records]);
exit;
}
// List tindakan yang sudah tersimpan untuk satu order
function list_order_tindakan()
{
if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; }
$prm = $this->sys_input;
$orderid = intval($prm['orderid'] ?? 0);
if (!$orderid) { $this->sys_error("orderid required"); exit; }
$sql = "SELECT
ot.*,
t.T_TestName as jenis_tindakan_name,
t.T_TestSasCode as jenis_tindakan_code,
d.M_DoctorName as dokter_name
FROM one_klinik.order_tindakan ot
LEFT JOIN one_lab.t_test t ON ot.orderTindakanT_TestID = t.T_TestID
LEFT JOIN one_lab.m_doctor d ON ot.orderTindakanM_DoctorID = d.M_DoctorID
WHERE ot.orderTindakanOrderID = ?
AND ot.orderTindakanIsActive = 'Y'
ORDER BY ot.orderTindakanCreated ASC";
$q = $this->db_oneklinik->query($sql, [$orderid]);
if (!$q) { $this->sys_error_db("list order_tindakan", $this->db_oneklinik); exit; }
$this->sys_ok(['records' => $q->result_array()]);
exit;
}
function save_tindakan()
{
if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; }
$prm = $this->sys_input;
$userID = $this->sys_user['M_UserID'];
$orderid = intval($prm['orderid'] ?? 0);
$tindakan_id = intval($prm['tindakan_id'] ?? 0); // orderTindakanID; 0 = insert baru
$t_test_id = intval($prm['t_test_id'] ?? 0);
if (!$orderid || !$t_test_id) {
$this->sys_error("orderid dan t_test_id wajib diisi");
exit;
}
$doctor_id = isset($prm['doctor_id']) && $prm['doctor_id'] ? intval($prm['doctor_id']) : null;
$performed_at = trim($prm['performed_at'] ?? '');
$catatan = trim($prm['catatan'] ?? '');
$ss_price_mou_id = isset($prm['ss_price_mou_id']) && $prm['ss_price_mou_id'] ? intval($prm['ss_price_mou_id']) : null;
$bruto = floatval($prm['bruto'] ?? 0);
$disc_persen = floatval($prm['discountpersen'] ?? 0);
$disc_rp = floatval($prm['discountrp'] ?? 0);
$total = floatval($prm['total'] ?? 0);
$performed_at_sql = ($performed_at && strtotime($performed_at))
? date('Y-m-d H:i:s', strtotime($performed_at))
: date('Y-m-d H:i:s');
if ($tindakan_id > 0) {
$ok = $this->db_oneklinik->query(
"UPDATE one_klinik.order_tindakan SET
orderTindakanT_TestID = ?,
orderTindakanSsPriceMouID = ?,
orderTindakanBruto = ?,
orderTindakanDiscPersen = ?,
orderTindakanDiscRp = ?,
orderTindakanTotal = ?,
orderTindakanM_DoctorID = ?,
orderTindakanPerformedAt = ?,
orderTindakanCatatan = ?,
orderTindakanUserID = ?
WHERE orderTindakanID = ? AND orderTindakanOrderID = ?",
[
$t_test_id, $ss_price_mou_id, $bruto, $disc_persen, $disc_rp, $total,
$doctor_id, $performed_at_sql, $catatan ?: null,
$userID, $tindakan_id, $orderid
]
);
} else {
$ok = $this->db_oneklinik->query(
"INSERT INTO one_klinik.order_tindakan
(orderTindakanOrderID, orderTindakanT_TestID,
orderTindakanSsPriceMouID, orderTindakanBruto, orderTindakanDiscPersen,
orderTindakanDiscRp, orderTindakanTotal,
orderTindakanM_DoctorID, orderTindakanPerformedAt,
orderTindakanCatatan, orderTindakanUserID)
VALUES (?,?,?,?,?,?,?,?,?,?,?)",
[
$orderid, $t_test_id,
$ss_price_mou_id, $bruto, $disc_persen, $disc_rp, $total,
$doctor_id, $performed_at_sql, $catatan ?: null, $userID
]
);
$tindakan_id = $this->db_oneklinik->insert_id();
}
if (!$ok) { $this->sys_error_db("save order_tindakan", $this->db_oneklinik); exit; }
$this->sys_ok(['orderTindakanID' => $tindakan_id]);
exit;
}
function delete_tindakan()
{
if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; }
$prm = $this->sys_input;
$tindakan_id = intval($prm['orderTindakanID'] ?? 0);
$userID = $this->sys_user['M_UserID'];
if (!$tindakan_id) { $this->sys_error("orderTindakanID required"); exit; }
$ok = $this->db_oneklinik->query(
"UPDATE one_klinik.order_tindakan SET orderTindakanIsActive = 'N', orderTindakanUserID = ?
WHERE orderTindakanID = ?",
[$userID, $tindakan_id]
);
if (!$ok) { $this->sys_error_db("delete order_tindakan", $this->db_oneklinik); exit; }
$this->sys_ok(['msg' => 'deleted']);
exit;
}
}

View File

@@ -12,34 +12,29 @@ class Screening extends MY_Controller
parent::__construct();
$this->db_onedev = $this->load->database("onedev", true);
$this->db_oneklinik = $this->load->database("onedev", true);
$this->load->library('ibl_encryptor');
}
public function search()
{
$prm = $this->sys_input;
$id = $prm['id'];
$id = $this->db_onedev->escape_str($prm['id']);
$sql = "SELECT orderID,
orderDate,
$sql = "SELECT orderID,
orderDate,
orderNumber,
orderIsScreening,
orderIsAnamnese,
orderIsCheck,
orderAge as patient_age,
DATE_FORMAT(orderDate,'%d-%m-%Y') as order_date,
orderM_ClinicUnitID,
'N' divider,
M_PatientID,
M_PatientNoReg,
M_PatientPrefix,
M_PatientName,
M_PatientSuffix,
M_PatientHP,
M_PatientEmail,
M_PatientPOB,
M_PatientPhone,
M_PatientIDNumber,
DATE_FORMAT(M_PatientDOB,'%d-%m-%Y') as M_PatientDOB,
concat(M_TitleName,' ',IFNULL(M_PatientPrefix,''),' ',M_PatientName,' ',IFNULL(M_PatientSuffix,'')) M_PatientNameRaw,
M_PatientNote,
M_PatientNIK,
M_PatientJabatan,
@@ -49,78 +44,178 @@ class Screening extends MY_Controller
M_PatientJob,
M_PatientM_SexID,
M_SexName,
M_TitleID, M_TitleName,
M_PatientM_TitleID,
M_TitleName,
M_PatientM_ReligionID,
M_ReligionName,
IFNULL(M_ReligionName,'-') M_ReligionName,
M_PatientM_IdTypeID,
M_IdTypeName,
M_PatientIDNumber,
IF(ISNULL(M_PatientSuspendID),'active','suspend' ) as status,
M_PatientAddressM_KelurahanID M_KelurahanID,
0 M_DistrictID,
0 M_CityID,
0 M_ProvinceID
FROM one_klinik.order
IF(ISNULL(M_PatientSuspendID),'active','suspend') as status,
M_PatientAddressRegionalCd,
M_PatientName_enc, M_PatientHP_enc, M_PatientDOB_enc,
M_PatientEmail_enc, M_PatientPhone_enc, M_PatientPOB_enc,
M_PatientIDNumber_enc, M_PatientNIK_enc, M_PatientAddressDescription_enc
FROM one_klinik.`order`
JOIN m_patient ON M_PatientID = orderM_PatientID AND M_PatientIsActive = 'Y'
JOIN m_title ON M_PatientM_TitleID = M_TitleID
JOIN m_sex ON M_PatientM_SexID = M_SexID
JOIN m_branch ON M_BranchIsActive = 'Y' AND M_BranchIsDefault = 'Y'
JOIN m_patientaddress ON M_PatientAddressM_PatientID = M_PatientID AND M_PatientAddressIsActive = 'Y'
LEFT JOIN m_idtype ON M_IdTypeID = M_PatientM_IdTypeID AND M_IdTypeIsActive = 'Y'
LEFT JOIN m_religion ON m_patientm_religionid = m_religionid
LEFT JOIN m_religion ON M_PatientM_ReligionID = M_ReligionID
LEFT JOIN m_patientsuspend ON M_PatientSuspendM_PatientID = M_PatientID AND M_PatientSuspendIsActive = 'Y'
WHERE
orderNumber = '{$id}' AND
M_PatientSuspendID IS NULL
WHERE orderNumber = '{$id}' AND M_PatientSuspendID IS NULL
GROUP BY M_PatientID";
//echo $sql;
$query = $this->db_onedev->query($sql);
if ($query) {
$rows = $query->result_array();
foreach ($rows as $k => $v)
{
$rows[$k]['M_PatientName'] = stripslashes($rows[$k]['M_PatientName']);
$rows[$k]['M_PatientAddressDescription'] = stripslashes($v['M_PatientAddressDescription']);
$patient_name = str_replace("'", "\\'", $prm['M_PatientName']);
$sql = "SELECT *, concat('{$rows[$k]['M_PatientAddressDescription'] }', '\n\n',
m_kelurahanname, ', ',
m_districtname,'\n',
m_cityname, ', ',
m_provincename) as xaddress
FROM m_kelurahan
JOIN m_district ON M_KelurahanM_DistrictID = M_DistrictID
JOIN m_city ON M_DistrictM_CityID = M_CityID
JOIN m_province ON M_CityM_ProvinceID = M_ProvinceID
WHERE
M_KelurahanID = {$v['M_KelurahanID']} ";
//echo $sql;
$row_address = $this->db_onedev->query($sql)->row_array();
$rows[$k]['M_PatientAddress'] = stripslashes($row_address['xaddress']);
$rows[$k]['M_DistrictID'] = $row_address['M_DistrictID'];
$rows[$k]['M_CityID'] = $row_address['M_CityID'];
$rows[$k]['M_ProvinceID'] = $row_address['M_ProvinceID'];
$info = $this->db_onedev->query("SELECT fn_fo_patient_visit(?) info", [$v['M_PatientID']])->row();
$rows[$k]['info'] = json_decode($info->info);
}
$result = array("total" => 1, "records" => $rows, "sql"=> $this->db_onedev->last_query());
$this->sys_ok($result);
}
else {
$this->sys_error_db("m_patient rows",$this->db_onedev);
exit;
if (!$query) {
$this->sys_error_db("order rows", $this->db_onedev);
return;
}
}
$rows = $query->result_array();
$enc = $this->ibl_encryptor;
foreach ($rows as $k => $v) {
$rows[$k]['M_PatientName'] = $enc->decrypt($v['M_PatientName_enc']) ?? $v['M_PatientNameRaw'];
$rows[$k]['M_PatientHP'] = $enc->decrypt($v['M_PatientHP_enc']) ?? '';
$rows[$k]['M_PatientEmail'] = $enc->decrypt($v['M_PatientEmail_enc']) ?? '';
$rows[$k]['M_PatientPOB'] = $enc->decrypt($v['M_PatientPOB_enc']) ?? '';
$rows[$k]['M_PatientPhone'] = $enc->decrypt($v['M_PatientPhone_enc']) ?? '';
$rows[$k]['M_PatientIDNumber'] = $enc->decrypt($v['M_PatientIDNumber_enc']) ?? '';
$rows[$k]['M_PatientNIK'] = $enc->decrypt($v['M_PatientNIK_enc']) ?? '';
$rows[$k]['M_PatientDOB'] = $enc->decrypt($v['M_PatientDOB_enc']) ?? '';
$rows[$k]['dob_ina'] = $rows[$k]['M_PatientDOB'];
$rows[$k]['M_PatientAddressDescription'] = $enc->decrypt($v['M_PatientAddressDescription_enc']) ?? '';
$rows[$k]['M_PatientAddress'] = $rows[$k]['M_PatientAddressDescription'];
function get_data(){
foreach (array_keys($rows[$k]) as $col) {
if (substr($col, -4) === '_enc') unset($rows[$k][$col]);
}
unset($rows[$k]['M_PatientNameRaw']);
$rows[$k]['info'] = $this->build_patient_visit_info($v['M_PatientID'], $rows[$k]['M_PatientDOB']);
// Screening template berdasarkan poli order
$cu_id = $v['orderM_ClinicUnitID'] ?? null;
$rows[$k]['screening_template'] = null;
$rows[$k]['screening_forms'] = null;
$rows[$k]['order_screening'] = null;
if ($cu_id) {
$tpl = $this->db_oneklinik->query(
"SELECT st.M_ScreeningTemplateID, st.M_ScreeningTemplateCode, st.M_ScreeningTemplateName
FROM one_klinik.m_clinic_unit cu
JOIN one_klinik.m_screening_template st
ON st.M_ScreeningTemplateID = cu.M_ClinicUnitM_ScreeningTemplateID
WHERE cu.M_ClinicUnitID = ?", [$cu_id]
)->row_array();
$rows[$k]['screening_template'] = $tpl ?: null;
if ($tpl && $tpl['M_ScreeningTemplateCode'] !== 'DEFAULT') {
// Template dinamis (VAKSINASI / KHITAN): ambil form + jawaban yang sudah ada
$forms = $this->db_oneklinik->query(
"SELECT sf.M_ScreeningFormID,
sf.M_ScreeningFormQuestion,
sf.M_ScreeningFormAnswerType,
sf.M_ScreeningFormOptions,
sf.M_ScreeningFormSortOrder,
sf.M_ScreeningFormIsRequired,
sa.T_ScreeningAnswerValue AS answer
FROM one_klinik.m_screening_form sf
LEFT JOIN one_klinik.t_screening_answer sa
ON sa.T_ScreeningAnswerM_ScreeningFormID = sf.M_ScreeningFormID
AND sa.T_ScreeningAnswerOrderID = ?
AND sa.T_ScreeningAnswerIsActive = 'Y'
WHERE sf.M_ScreeningFormM_ScreeningTemplateID = ?
AND sf.M_ScreeningFormIsActive = 'Y'
ORDER BY sf.M_ScreeningFormSortOrder",
[$v['orderID'], $tpl['M_ScreeningTemplateID']]
)->result_array();
foreach ($forms as &$f) {
$f['M_ScreeningFormOptions'] = $f['M_ScreeningFormOptions']
? json_decode($f['M_ScreeningFormOptions'], true)
: null;
$f['answer'] = $f['answer'] !== null
? json_decode($f['answer'], true)
: null;
// Tandai option terpilih dengan value:true agar FE bisa render form pre-filled
if ($f['answer'] && $f['M_ScreeningFormOptions'] && $f['M_ScreeningFormAnswerType'] !== 'text') {
if ($f['M_ScreeningFormAnswerType'] === 'single') {
$selected = [$f['answer']['id'] ?? ''];
} else {
$selected = array_column((array)$f['answer'], 'id');
}
foreach ($f['M_ScreeningFormOptions'] as &$opt) {
$opt['value'] = in_array($opt['id'], $selected);
}
unset($opt);
}
}
unset($f);
$rows[$k]['screening_forms'] = $forms;
} else {
// DEFAULT: pakai order_screening lama
$rows[$k]['order_screening'] = $this->db_oneklinik->query(
"SELECT * FROM one_klinik.order_screening
WHERE orderScreeningOrderID = ? AND orderScreeningIsActive = 'Y'",
[$v['orderID']]
)->row_array() ?: null;
}
}
}
$this->sys_ok(["total" => count($rows), "records" => $rows]);
}
protected function build_patient_visit_info($patient_id, $patient_dob)
{
$visit = 1;
$birthday = 'N';
$visit_query = $this->db_onedev->query(
"SELECT COUNT(DISTINCT T_OrderHeaderID) AS n
FROM t_orderheader
JOIN t_orderdetail ON T_OrderHeaderID = T_OrderDetailT_OrderHeaderID AND T_OrderDetailIsActive = 'Y'
WHERE T_OrderHeaderIsActive = 'Y'
AND T_OrderHeaderM_PatientID = ?",
[$patient_id]
);
if ($visit_query) {
$visit_row = $visit_query->row_array();
$visit += (int) ($visit_row['n'] ?? 0);
}
$init_visit_query = $this->db_onedev->query(
"SELECT M_PatientInitialVisit
FROM m_patient
WHERE M_PatientID = ?",
[$patient_id]
);
if ($init_visit_query) {
$init_visit_row = $init_visit_query->row_array();
if (!empty($init_visit_row['M_PatientInitialVisit'])) {
$visit += (int) $init_visit_row['M_PatientInitialVisit'];
}
}
$dob_time = empty($patient_dob) ? false : strtotime($patient_dob);
if ($dob_time !== false) {
$birthday = date('m-d', $dob_time) === date('m-d') ? 'Y' : 'N';
}
return json_decode(json_encode([
'visit' => $visit,
'birthday' => $birthday,
]));
}
function get_data(){
if (! $this->isLogin) {
$this->sys_error("Invalid Token");
exit;
@@ -154,6 +249,48 @@ class Screening extends MY_Controller
}
function getsexreg()
{
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$rows = [];
$rows['default_location'] = [];
$rows['doctors'] = $this->db_onedev->query(
"SELECT M_DoctorID as id, M_DoctorCode as code, M_DoctorName as name,
M_DoctorMcuDefaultKlinik as is_default, M_DoctorMcuPriceKlinik as price
FROM m_doctormcu JOIN m_doctor ON M_DoctorMcuM_DoctorID = M_DoctorID
WHERE M_DoctorMcuIsActive = 'Y'"
)->result_array();
$rows['default_doctor'] = [];
foreach ($rows['doctors'] as $value) {
if ($value['is_default'] == 'Y') { $rows['default_doctor'] = $value; break; }
}
$rows['titles'] = $this->db_onedev->query("SELECT * FROM m_title WHERE M_TitleIsActive = 'Y'")->result_array();
$rows['sexes'] = $this->db_onedev->query("SELECT * FROM m_sex WHERE M_SexIsActive = 'Y'")->result_array();
$rows['religions'] = $this->db_onedev->query("SELECT * FROM m_religion WHERE M_ReligionIsActive = 'Y'")->result_array();
$rows['kartuidentitass'] = $this->db_onedev->query("SELECT * FROM m_idtype WHERE M_IdTypeIsActive = 'Y'")->result_array();
$branch = $this->db_onedev->query("SELECT * FROM m_branch WHERE M_BranchIsDefault = 'Y' AND M_BranchIsActive = 'Y'")->row_array();
if ($branch) {
$rows['default_location']['city_address'] = $this->db_onedev->query("SELECT * FROM m_city WHERE M_CityIsActive = 'Y' AND M_CityID = ?", [$branch['M_BranchM_CityID']])->row_array();
$rows['default_location']['cities'] = $this->db_onedev->query("SELECT * FROM m_city WHERE M_CityIsActive = 'Y' AND M_CityM_ProvinceID = ?", [$rows['default_location']['city_address']['M_CityM_ProvinceID']])->result_array();
$rows['default_location']['province_address'] = $this->db_onedev->query("SELECT * FROM m_province WHERE M_ProvinceIsActive = 'Y' AND M_ProvinceID = ?", [$rows['default_location']['city_address']['M_CityM_ProvinceID']])->row_array();
$rows['default_location']['provinces'] = $this->db_onedev->query("SELECT * FROM m_province WHERE M_ProvinceIsActive = 'Y'")->result_array();
$rows['default_location']['districts'] = $this->db_onedev->query("SELECT * FROM m_district WHERE M_DistrictIsActive = 'Y' AND M_DistrictM_CityID = ?", [$branch['M_BranchM_CityID']])->result_array();
$rows['default_location']['district_address'] = $this->db_onedev->query("SELECT * FROM m_district WHERE M_DistrictIsActive = 'Y' AND M_DistrictID = ?", [$branch['M_BranchM_DistrictID']])->row_array();
$rows['default_location']['kelurahans'] = $this->db_onedev->query("SELECT * FROM m_kelurahan WHERE M_KelurahanIsActive = 'Y' AND M_KelurahanM_DistrictID = ?", [$branch['M_BranchM_DistrictID']])->result_array();
$rows['default_location']['kelurahan_address'] = $this->db_onedev->query("SELECT * FROM m_kelurahan WHERE M_KelurahanIsActive = 'Y' AND M_KelurahanID = ?", [$branch['M_BranchM_KelurahanID']])->row_array();
}
$this->sys_ok(["total" => count($rows), "records" => $rows]);
exit;
}
protected function objToArray($obj)
{
// Not an object or array
@@ -184,26 +321,47 @@ class Screening extends MY_Controller
$status = $prm['status'];
$sql = "SELECT 'N' divider,
CONCAT(IF(ISNULL(M_TitleName),'',CONCAT(M_TitleName,'. ')),M_PatientName) as patient_name,
M_PatientName, M_PatientName_enc,
M_PatientHP, M_PatientHP_enc,
M_PatientDOB, M_PatientDOB_enc,
M_PatientEmail, M_PatientEmail_enc,
M_PatientPhone, M_PatientPhone_enc,
M_PatientPOB, M_PatientPOB_enc,
M_PatientIDNumber, M_PatientIDNumber_enc,
M_PatientNIK, M_PatientNIK_enc,
M_PatientPhoto, M_PatientPhotoThumb,
`order`.*,DATE_FORMAT(orderDate,'%d-%m-%Y') as date_order,
'' as kode_status, '' as status
'' as kode_status, '' as status,
M_TitleName, M_PatientNoReg, M_PatientM_SexID
FROM one_klinik.`order`
JOIN m_patient ON orderM_PatientID = M_PatientID
LEFT JOIN m_title ON M_PatientM_TitleID = M_TitleID
WHERE
orderIsActive = 'Y' AND DATE(orderDate) = ? AND orderIsScreening = ?
WHERE
orderIsActive = 'Y' AND DATE(orderDate) = ? AND orderIsScreening = ?
LIMIT $number_limit offset $number_offset";
//echo $sql;
$query = $this->db_oneklinik->query($sql,array($xdate,$status));
//echo $this->db_oneklinik->last_query();
if ($query) {
if ($query) {
$rows = $query->result_array();
$result = array("total" => $tot_page, "records" => $rows, "sql"=> $this->db_onedev->last_query());
$enc = $this->ibl_encryptor;
foreach ($rows as $k => $v) {
$rows[$k]['M_PatientName'] = $enc->decrypt($v['M_PatientName_enc'] ?? '') ?: $v['M_PatientName'];
$rows[$k]['M_PatientHP'] = $enc->decrypt($v['M_PatientHP_enc'] ?? '') ?: $v['M_PatientHP'];
$rows[$k]['M_PatientDOB'] = $enc->decrypt($v['M_PatientDOB_enc'] ?? '') ?: $v['M_PatientDOB'];
$rows[$k]['M_PatientEmail'] = $enc->decrypt($v['M_PatientEmail_enc'] ?? '') ?: $v['M_PatientEmail'];
$rows[$k]['M_PatientPhone'] = $enc->decrypt($v['M_PatientPhone_enc'] ?? '') ?: $v['M_PatientPhone'];
$rows[$k]['M_PatientPOB'] = $enc->decrypt($v['M_PatientPOB_enc'] ?? '') ?: $v['M_PatientPOB'];
$rows[$k]['M_PatientIDNumber'] = $enc->decrypt($v['M_PatientIDNumber_enc'] ?? '') ?: $v['M_PatientIDNumber'];
$rows[$k]['M_PatientNIK'] = $enc->decrypt($v['M_PatientNIK_enc'] ?? '') ?: $v['M_PatientNIK'];
$rows[$k]['patient_name'] = trim(($v['M_TitleName'] ?? '') . ' ' . $rows[$k]['M_PatientName']);
}
$result = array("total" => $tot_page, "records" => $rows, "sql"=> $this->db_oneklinik->last_query());
$this->sys_ok($result);
}
}
else {
$this->sys_error_db("m_patient rows",$this->db_onedev);
$this->sys_error_db("m_patient rows",$this->db_oneklinik);
exit;
}
@@ -297,124 +455,7 @@ class Screening extends MY_Controller
}
function end_session(){
if (! $this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$userID = $this->sys_user['M_UserID'];
//print_r($prm['subgroup']);
$sql = "SELECT COUNT(*) as xcount
FROM one_klinik.order_screening
WHERE
orderScreeningOrderID = ? AND orderScreeningIsActive = 'Y'";
$query = $this->db_oneklinik->query($sql,array($prm['orderID']));
if(!$query){
$this->sys_error("count exist");
echo $this->db_oneklinik->last_query();
}
$check_exist = $query->row()->xcount;
if($check_exist == 0){
$sql = "INSERT one_klinik.order_screening (
orderScreeningOrderID,
orderScreeningKesanUmum,
orderScreeningValueKesadaran,
orderScreeningValuePernafasan,
orderScreeningValueResikoJatuh,
orderScreeningValueNyeriDada,
orderScreeningValueSkalaNyeri,
orderScreeningValueBatuk,
orderScreeningValueKeputusan,
orderScreeningCreated,
orderScreeningUserID
)
VALUES(
?,?,?,?,?,?,?,?,?,NOW(),?
)";
$query = $this->db_oneklinik->query($sql,array(
$prm['orderID'],
$prm['kesan_umum'],
$prm['kesadaran'],
$prm['pernafasan'],
$prm['resiko_jatuh'],
$prm['nyeri_dada'],
$prm['skala_nyeri'],
$prm['batuk'],
$prm['keputusan'],
$userID)
);
if(!$query){
$this->sys_error("Gagal insert");
}
}else{
$sql = "UPDATE one_klinik.order_screening SET
orderScreeningKesanUmum = ?,
orderScreeningValueKesadaran = ?,
orderScreeningValuePernafasan = ?,
orderScreeningValueResikoJatuh = ?,
orderScreeningValueNyeriDada = ?,
orderScreeningValueSkalaNyeri = ?,
orderScreeningValueBatuk = ?,
orderScreeningValueKeputusan = ?,
orderScreeningUserID = ?
WHERE
orderScreeningOrderID = ?
";
$query = $this->db_oneklinik->query($sql,[
$prm['kesan_umum'],
$prm['kesadaran'],
$prm['pernafasan'],
$prm['resiko_jatuh'],
$prm['nyeri_dada'],
$prm['skala_nyeri'],
$prm['batuk'],
$prm['keputusan'],
$userID,
$prm['orderID']
]);
if(!$query){
echo $this->db_oneklinik->last_query();
$this->sys_error("Gagal Update");
}
}
$sql = "INSERT INTO one_klinik.order_status (
orderStatusOrderID,
orderStatusCode,
orderStatusValue,
orderStatusUserID
)
VALUES(
?,?,?,?
)";
$query = $this->db_oneklinik->query($sql,array($prm['orderID'],'S','D',$userID));
if(!$query){
$this->sys_error("Gagal End");
}
$sql = "UPDATE one_klinik.`order` SET orderIsScreening = 'D', orderUserID = ?
WHERE
orderID = ?";
$query = $this->db_oneklinik->query($sql,array($userID,$prm['orderID']));
if(!$query){
$this->sys_error("Gagal ENd");
}
$result = array('process'=>'OK');
$this->sys_ok($result);
exit;
$this->endsession();
}
@@ -422,4 +463,149 @@ class Screening extends MY_Controller
public function endsession()
{
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
return;
}
$prm = $this->sys_input;
$userID = $this->sys_user['M_UserID'];
$orderID = intval($prm['orderID'] ?? 0);
if (!$orderID) {
$this->sys_error("orderID required");
return;
}
// 1. Tandai order selesai screening + catat status
$ok = $this->db_oneklinik->query(
"UPDATE one_klinik.`order` SET orderIsScreening = 'D', orderUserID = ? WHERE orderID = ?",
[$userID, $orderID]
);
if (!$ok) {
$this->sys_error_db("update order", $this->db_oneklinik);
return;
}
$this->db_oneklinik->query(
"INSERT INTO one_klinik.order_status
(orderStatusOrderID, orderStatusCode, orderStatusValue, orderStatusUserID)
VALUES (?, 'S', 'D', ?)",
[$orderID, $userID]
);
// 2. Tentukan template: ada screening_template_id dan bukan DEFAULT?
$template_id = intval($prm['screening_template_id'] ?? 0);
$is_default = true;
if ($template_id) {
$tpl = $this->db_oneklinik->query(
"SELECT M_ScreeningTemplateCode FROM one_klinik.m_screening_template
WHERE M_ScreeningTemplateID = ?",
[$template_id]
)->row_array();
if ($tpl && $tpl['M_ScreeningTemplateCode'] !== 'DEFAULT') {
$is_default = false;
}
}
if ($is_default) {
// 3. DEFAULT: simpan ke order_screening (INSERT atau UPDATE)
$exists = $this->db_oneklinik->query(
"SELECT COUNT(*) AS c FROM one_klinik.order_screening
WHERE orderScreeningOrderID = ? AND orderScreeningIsActive = 'Y'",
[$orderID]
)->row()->c;
if ($exists == 0) {
$ins = $this->db_oneklinik->query(
"INSERT INTO one_klinik.order_screening
(orderScreeningOrderID, orderScreeningKesanUmum,
orderScreeningValueKesadaran, orderScreeningValuePernafasan,
orderScreeningValueResikoJatuh, orderScreeningValueNyeriDada,
orderScreeningValueSkalaNyeri, orderScreeningValueBatuk,
orderScreeningValueKeputusan, orderScreeningCreated, orderScreeningUserID)
VALUES (?,?,?,?,?,?,?,?,?,NOW(),?)",
[$orderID,
$prm['kesan_umum'] ?? '',
$prm['kesadaran'] ?? '',
$prm['pernafasan'] ?? '',
$prm['resiko_jatuh'] ?? null,
$prm['nyeri_dada'] ?? '',
$prm['skala_nyeri'] ?? '',
$prm['batuk'] ?? '',
$prm['keputusan'] ?? '',
$userID]
);
if (!$ins) {
$this->sys_error_db("insert order_screening", $this->db_oneklinik);
return;
}
} else {
$upd = $this->db_oneklinik->query(
"UPDATE one_klinik.order_screening SET
orderScreeningKesanUmum = ?,
orderScreeningValueKesadaran = ?,
orderScreeningValuePernafasan = ?,
orderScreeningValueResikoJatuh = ?,
orderScreeningValueNyeriDada = ?,
orderScreeningValueSkalaNyeri = ?,
orderScreeningValueBatuk = ?,
orderScreeningValueKeputusan = ?,
orderScreeningUserID = ?
WHERE orderScreeningOrderID = ?",
[$prm['kesan_umum'] ?? '',
$prm['kesadaran'] ?? '',
$prm['pernafasan'] ?? '',
$prm['resiko_jatuh'] ?? null,
$prm['nyeri_dada'] ?? '',
$prm['skala_nyeri'] ?? '',
$prm['batuk'] ?? '',
$prm['keputusan'] ?? '',
$userID,
$orderID]
);
if (!$upd) {
$this->sys_error_db("update order_screening", $this->db_oneklinik);
return;
}
}
} else {
// 4. Template dinamis (VAKSINASI/KHITAN): replace semua jawaban
$this->db_oneklinik->query(
"DELETE FROM one_klinik.t_screening_answer WHERE T_ScreeningAnswerOrderID = ?",
[$orderID]
);
$answers = is_array($prm['screening_answers']) ? $prm['screening_answers'] : [];
foreach ($answers as $item) {
$form_id = intval($item['M_ScreeningFormID'] ?? 0);
if (!$form_id) continue;
// Simpan sebagai JSON object
$answer_type = $item['answer_type'] ?? 'single';
if ($answer_type === 'text') {
$stored_value = json_encode(['value' => $item['answer_label'] ?? '']);
} else {
$stored_value = json_encode(['id' => $item['answer_id'] ?? '', 'label' => $item['answer_label'] ?? '']);
}
$this->db_oneklinik->query(
"INSERT INTO one_klinik.t_screening_answer
(T_ScreeningAnswerOrderID, T_ScreeningAnswerM_ScreeningFormID,
T_ScreeningAnswerValue, T_ScreeningAnswerUserID)
VALUES (?,?,?,?)",
[$orderID, $form_id, $stored_value, $userID]
);
}
}
$this->sys_ok(['process' => 'OK']);
}
}

View File

@@ -188,7 +188,7 @@ INSERT INTO `t_samplestation` (`T_SampleStationID`, `T_SampleStationCode`, `T_Sa
//$sql_where = "WHERE T_OrderHeaderIsActive = 'Y' {$where_status}";
$sql_where = "WHERE T_OrderHeaderIsActive = 'Y' AND ( DATE(T_OrderHeaderAddonIsComingDate) = '{$xdate}' OR DATE(T_OrderHeaderDate) = '{$xdate}' ) {$where_status}";
$sql_where_klinik = "WHERE DATE_FORMAT(orderDate,'%Y-%m-%d') = '{$xdate}' AND orderIsActive = 'Y' AND orderIsScreening = 'D' AND orderIsCheck <> 'D'";
$sql_where_klinik = "WHERE DATE_FORMAT(orderDate,'%Y-%m-%d') = '{$xdate}' AND orderIsActive = 'Y' AND orderIsTTV = 'D' AND orderIsCheck <> 'D'";
//$sql_param = array();
if ($name != "") {
@@ -298,7 +298,88 @@ INSERT INTO `t_samplestation` (`T_SampleStationID`, `T_SampleStationCode`, `T_Sa
GROUP BY T_OrderHeaderID
HAVING last_status_fo IN (3,5)
UNION
SELECT
orderID AS T_OrderHeaderID,
T_OrderHeaderDate,
orderNumber AS T_OrderHeaderLabNumber,
T_OrderHeaderLabNumberExt,
orderQueueNumber AS T_OrderHeaderQueue,
T_OrderHeaderM_PatientID,
T_OrderHeaderM_CompanyID,
T_OrderHeaderM_MouID,
orderAge AS T_OrderHeaderM_PatientAge,
T_OrderHeaderSenderM_DoctorID,
T_OrderHeaderSenderM_DoctorAddressID,
T_OrderHeaderPjM_DoctorID,
T_OrderHeaderM_LangID,
T_OrderHeaderLangIsSI,
'N' AS T_OrderHeaderIsCito,
T_OrderHeaderNat_CitoID,
T_OrderHeaderDiagnose,
T_OrderHeaderDoctorNote,
T_OrderHeaderVerificationNote,
T_OrderHeaderVerificationNoteM_UserID,
T_OrderHeaderFoNote,
T_OrderHeaderSamplingNote,
T_OrderHeaderResultNote,
T_OrderHeaderFoNoteM_UserID,
T_OrderHeaderSamplingNoteM_UserID,
T_OrderHeaderResultNoteM_UserID,
T_OrderHeaderReceivedSample,
T_OrderHeaderSubTotal,
T_OrderHeaderRounding,
T_OrderHeaderTotal,
T_OrderHeaderCreated,
T_OrderHeaderLastUpdated,
T_OrderHeaderCreatedUserID,
T_OrderHeaderIsActive,
m_patient.*,
M_SexName,
M_TitleName,
CONCAT(M_TitleName,' ',M_PatientName) as patient_fullname,
'' AS M_CompanyName,
fn_sampling_clinic_queue_status_name(orderID, M_LocationT_SampleStationID) as status,
fn_sampling_clinic_queue_status_id(orderID, M_LocationT_SampleStationID) as statusid,
M_LocationT_SampleStationID AS T_SampleStationID,
'' AS T_SampleTypeID,
M_LocationT_SampleStationID as stationid,
NULL AS T_OrderPromiseDateTime,
'N' as iscito,
3 as last_status_fo,
DATE_FORMAT(orderDate,'%d-%m-%Y %H:%i') as order_date,
IFNULL(T_OrderHeaderFoNote,'') as fo_note,
IFNULL(T_OrderHeaderVerificationNote,'') as fo_ver_note,
fn_sampling_reqs(T_OrderHeaderID) as fo_requirements,
'' as htmlforeqs,
IF(fn_fo_ver_have_reqs(T_OrderHeaderID) = 0,'Y','N') as fo_ver_status_req,
fn_fo_reg_have_reqs(T_OrderHeaderID) as fo_reg_status_req,
fn_sampling_reqs_status(T_OrderHeaderID) as fo_requirements_status,
IF(fn_fo_get_verification_status(T_OrderHeaderID) = 0, 'X','Y') as fo_verification_status,
IFNULL(T_OrderHeaderSamplingNote,'') as sampling_note,
'N' as status_coming,
orderM_LocationID as order_location_id,
IFNULL(AntrianSampleStationTime, orderDate) as antri_time,
IFNULL(AntrianSampleStationTime, orderDate) as skip_time,
'Y' AS is_clinic,
'' as flag_antrian
FROM one_klinik.order
JOIN m_patient
ON orderM_PatientID = M_PatientID
AND M_PatientIsActive = 'Y'
JOIN m_title ON M_PatientM_TitleID = M_TitleID
JOIN m_sex ON M_PatientM_SexID = M_SexID
JOIN m_location ON orderM_LocationID = M_LocationID
LEFT JOIN t_orderheader
ON orderT_OrderHeaderID = T_OrderHeaderID
AND T_OrderHeaderIsActive = 'Y'
LEFT JOIN antrian_samplestation
ON orderID = AntrianSampleStationOrderID AND AntrianSampleStationIsActive = 'Y'
$sql_where_klinik
HAVING last_status_fo IN (3,5)
) x
ORDER BY T_OrderHeaderIsCito DESC, antri_time ASC
";
@@ -316,6 +397,12 @@ INSERT INTO `t_samplestation` (`T_SampleStationID`, `T_SampleStationCode`, `T_Sa
if ($key + 1 != $count_arr) {
$rows[$key]['skip_time'] = $rows[$key + 1]['antri_time'];
}
$enc = $this->ibl_encryptor;
$rows[$key]['M_PatientName'] = $enc->decrypt($value['M_PatientName_enc'] ?? '') ?: $value['M_PatientName'];
$rows[$key]['M_PatientHP'] = $enc->decrypt($value['M_PatientHP_enc'] ?? '') ?: $value['M_PatientHP'];
$rows[$key]['M_PatientEmail'] = $enc->decrypt($value['M_PatientEmail_enc'] ?? '') ?: $value['M_PatientEmail'];
$rows[$key]['M_PatientDOB'] = $enc->decrypt($value['M_PatientDOB_enc'] ?? '') ?: $value['M_PatientDOB'];
$rows[$key]['patient_fullname'] = trim(($value['M_TitleName'] ?? '') . ' ' . $rows[$key]['M_PatientName']);
if($value['is_clinic'] == 'Y'){
//print_r($value);
$sql = "SELECT ScreeningParameterDisplay as display

View File

@@ -162,6 +162,7 @@ class Patient extends MY_Controller
if ($plainName === '') {
$plainName = trim((string)($v['M_PatientName'] ?? ''));
}
$rows[$k]['M_PatientName'] = $plainName;
$rows[$k]['M_PatientName_print'] = trim(($v['M_TitleName'] ?? '') . '. ' . $plainName);
$rows[$k]['M_PatientName_print_eng'] = trim(($v['M_TitleLangName'] ?? '') . '. ' . $plainName);
unset($rows[$k]['M_PatientName_enc']);

View File

@@ -324,6 +324,16 @@ class Delivery extends MY_Controller
foreach($rows as $k => $v){
$xval = $v['chex'] === 'N'?false:true;
//$rows[$k]['chex'] = $xval;
if ($v['delivery_code'] === 'ADDRESS' && $type === 'patient' && !empty($v['address_id'])) {
$addr_row = $this->db_smartone->query(
'SELECT M_PatientAddressDescription_enc, M_PatientAddressVillage, M_PatientAddressDistrict, M_PatientAddressCity FROM m_patientaddress WHERE M_PatientAddressID = ? LIMIT 1',
[$v['address_id']]
)->row_array();
if ($addr_row) {
$desc = $this->ibl_encryptor->decrypt($addr_row['M_PatientAddressDescription_enc'] ?? '') ?: '';
$rows[$k]['description'] = $desc . ' ' . $addr_row['M_PatientAddressVillage'] . ', ' . $addr_row['M_PatientAddressDistrict'] . ', ' . $addr_row['M_PatientAddressCity'];
}
}
}
}
$result = array("records" => $rows);

View File

@@ -55,17 +55,61 @@ class Order extends MY_Controller
return $rst;
}
function convert_to_normal_text($text)
{
function convert_to_normal_text($text)
{
$normal_characters = "a-zA-Z0-9\s`~!@#$%^&*()_+-={}|:;<>?,.\/\"\'\\\[\]";
$normal_text = preg_replace("/[^$normal_characters]/", '', $text);
return $normal_text;
}
function genqrcode($nomorlab, $id)
{
return $normal_text;
}
protected function build_patient_visit_info($patient_id, $patient_dob)
{
$visit = 1;
$birthday = 'N';
$visit_query = $this->db_onedev->query(
"SELECT COUNT(DISTINCT T_OrderHeaderID) AS n
FROM t_orderheader
JOIN t_orderdetail ON T_OrderHeaderID = T_OrderDetailT_OrderHeaderID AND T_OrderDetailIsActive = 'Y'
WHERE T_OrderHeaderIsActive = 'Y'
AND T_OrderHeaderM_PatientID = ?",
[$patient_id]
);
if ($visit_query) {
$visit_row = $visit_query->row_array();
$visit += (int) ($visit_row['n'] ?? 0);
}
$init_visit_query = $this->db_onedev->query(
"SELECT M_PatientInitialVisit
FROM m_patient
WHERE M_PatientID = ?",
[$patient_id]
);
if ($init_visit_query) {
$init_visit_row = $init_visit_query->row_array();
if (!empty($init_visit_row['M_PatientInitialVisit'])) {
$visit += (int) $init_visit_row['M_PatientInitialVisit'];
}
}
$dob_time = empty($patient_dob) ? false : strtotime($patient_dob);
if ($dob_time !== false) {
$birthday = date('m-d', $dob_time) === date('m-d') ? 'Y' : 'N';
}
return json_decode(json_encode([
'visit' => $visit,
'birthday' => $birthday,
]));
}
function genqrcode($nomorlab, $id)
{
$this->load->library('ciqrcode'); //pemanggilan library QR CODE
$home_dir = "/home/one/project/one/";
$target_dir = $home_dir . "one-media/one-qrcontrolcard/";
@@ -536,6 +580,15 @@ class Order extends MY_Controller
}
}
// Link ke order klinik jika klinik_number dikirim
$klinik_number = trim($header['klinik_number'] ?? '');
if ($klinik_number !== '') {
$this->db_smartone->query(
"UPDATE one_klinik.`order` SET orderT_OrderHeaderID = ? WHERE OrderNumber = ?",
[$header_id, $klinik_number]
);
}
$sql = "SELECT t_orderheader.*
FROM t_orderheader
WHERE
@@ -798,13 +851,27 @@ class Order extends MY_Controller
$this->sys_error($url_preregister['message']);
exit;
}
$url_preregister = $url_preregister['data'];
$dt_order = [
'status' => 'OK',
'order_id' => $x_data_array['T_OrderHeaderID'],
'order_date' => $x_data_array['T_OrderHeaderDate'],
$url_preregister = $url_preregister['data'];
$order_klinik = null;
if ($klinik_number !== '') {
$query_order_klinik = $this->db_onedev->query(
"SELECT *
FROM one_klinik.`order`
WHERE OrderNumber = ?
LIMIT 1",
[$klinik_number]
);
if ($query_order_klinik) {
$order_klinik = $query_order_klinik->row_array();
}
}
$dt_order = [
'status' => 'OK',
'order_id' => $x_data_array['T_OrderHeaderID'],
'order_date' => $x_data_array['T_OrderHeaderDate'],
'noreg' => $lab_number,
'qrcode' => $genqrcode,
'patient_qrcode' => $genpatientqrcode,
@@ -818,11 +885,12 @@ class Order extends MY_Controller
'order_detail' => $order_detail,
'order_header' => $order_header,
'inform_consent' => isset($order_header['inform_consent']) ? $order_header['inform_consent'] : [],
'order_promise' => $order_promise,
'order_details' => $order_details,
'report_url' => $report_url,
'location_warning' => $location_warning,
];
'order_promise' => $order_promise,
'order_details' => $order_details,
'order_klinik' => $order_klinik,
'report_url' => $report_url,
'location_warning' => $location_warning,
];
if ($internal)
return ['status' => 'OK', 'data' => $dt_order];
@@ -1058,7 +1126,14 @@ class Order extends MY_Controller
FROM `t_orderheader`
JOIN `t_orderheaderaddon` ON T_OrderHeaderAddOnT_OrderHeaderID = T_OrderHeaderID AND T_OrderHeaderAddOnIsActive = 'Y'
JOIN m_patient ON T_OrderHeaderM_PatientID = M_PatientID
JOIN m_patientaddress ON M_PatientAddressM_PatientID = M_PatientID AND M_PatientAddressIsActive = 'Y' AND M_PatientAddressNote = 'Utama'
LEFT JOIN m_patientaddress ON M_PatientAddressID = (
SELECT pa.M_PatientAddressID
FROM m_patientaddress pa
WHERE pa.M_PatientAddressM_PatientID = M_PatientID
AND pa.M_PatientAddressIsActive = 'Y'
ORDER BY (pa.M_PatientAddressNote = 'Utama') DESC, pa.M_PatientAddressID DESC
LIMIT 1
)
JOIN m_company ON T_OrderHeaderM_CompanyID = M_CompanyID
JOIN m_mou ON T_OrderHeaderM_MouID = M_MouID
JOIN m_doctor pj1 ON T_OrderHeaderPjM_DoctorID = pj1.M_DoctorID
@@ -3986,8 +4061,7 @@ GROUP BY T_SampleStationID ";
$patient = $query->row_array();
$patient['M_PatientName'] = stripslashes($patient['M_PatientName']);
$patient['M_PatientAddress'] = stripslashes($patient['full_address']);
$info = $this->db_onedev->query("SELECT fn_fo_patient_visit(?) info", [$patient['M_PatientID']])->row();
$patient['info'] = json_decode($info->info);
$patient['info'] = $this->build_patient_visit_info($patient['M_PatientID'], $patient['M_PatientDOB']);
$rst['patient'] = $patient;
}
@@ -4641,4 +4715,208 @@ GROUP BY T_SampleStationID ";
exit;
}
function load_klinik()
{
if (!$this->isLogin) { $this->sys_error("Invalid Token"); exit; }
$prm = $this->sys_input;
$klinik_number = trim($prm['klinik_number'] ?? '');
if (!$klinik_number) { $this->sys_error("klinik_number required"); exit; }
// Ambil header order klinik
$row_header = $this->db_onedev->query(
"SELECT o.*, s.*, od.orderDoctorDiagnosePrimer
FROM one_klinik.`order` o
JOIN one_klinik.setting s ON s.settingIsActive = 'Y'
LEFT JOIN one_klinik.order_doctor od
ON od.orderDoctorOrderID = o.orderID
AND od.orderDoctorIsActive = 'Y'
AND od.orderDoctorType = 'TEXT'
WHERE o.OrderNumber = ?
LIMIT 1",
[$klinik_number]
)->row_array();
if (!$row_header) { $this->sys_error("Order tidak ditemukan"); exit; }
$rst = [];
$rst['klinik'] = $row_header;
$enc = $this->ibl_encryptor;
// Patient
$patient_row = $this->db_onedev->query(
"SELECT m_patient.*,
M_TitleID, M_TitleName,
M_SexID, M_SexName,
M_PatientAddressM_KelurahanID as M_KelurahanID,
M_PatientAddressDescription,
IFNULL(M_ReligionName,'-') as M_ReligionName
FROM m_patient
LEFT JOIN m_title ON M_PatientM_TitleID = M_TitleID
JOIN m_sex ON M_PatientM_SexID = M_SexID
LEFT JOIN m_patientaddress ON M_PatientAddressM_PatientID = M_PatientID AND M_PatientAddressIsActive = 'Y'
LEFT JOIN m_religion ON M_PatientM_ReligionID = M_ReligionID
WHERE M_PatientID = ?
GROUP BY M_PatientID
LIMIT 1",
[$row_header['orderM_PatientID']]
)->row_array();
if ($patient_row) {
$p_name = $enc->decrypt($patient_row['M_PatientName_enc'] ?? '') ?: $patient_row['M_PatientName'];
$p_hp = $enc->decrypt($patient_row['M_PatientHP_enc'] ?? '') ?: $patient_row['M_PatientHP'];
$p_email = $enc->decrypt($patient_row['M_PatientEmail_enc'] ?? '') ?: $patient_row['M_PatientEmail'];
$p_idnum = $enc->decrypt($patient_row['M_PatientIDNumber_enc']?? '') ?: $patient_row['M_PatientIDNumber'];
$p_dob_raw = $enc->decrypt($patient_row['M_PatientDOB_enc'] ?? '');
// p_dob_raw is d-m-Y; convert to Y-m-d for M_PatientDOB, keep d-m-Y for dob_ina
$p_dob_ina = $p_dob_raw ?: $patient_row['M_PatientDOB'];
$p_dob_sql = '';
if ($p_dob_raw) {
$parts = explode('-', $p_dob_raw);
$p_dob_sql = count($parts) === 3 ? "{$parts[2]}-{$parts[1]}-{$parts[0]}" : '';
}
$title = $patient_row['M_TitleName'] ? $patient_row['M_TitleName'] . ' ' : '';
$prefix = $patient_row['M_PatientPrefix'] ? $patient_row['M_PatientPrefix'] . ' ': '';
$suffix = $patient_row['M_PatientSuffix'] ? ' ' . $patient_row['M_PatientSuffix']: '';
$patient_row['M_PatientName'] = trim($title . $prefix . $p_name . $suffix);
$patient_row['M_PatientRealName'] = $p_name;
$patient_row['M_PatientHP'] = $p_hp;
$patient_row['M_PatientEmail'] = $p_email;
$patient_row['M_PatientIDNumber'] = $p_idnum;
$patient_row['M_PatientDOB'] = $p_dob_sql ?: $patient_row['M_PatientDOB'];
$patient_row['dob_ina'] = $p_dob_ina;
$patient_row['divider'] = 'N';
$patient_row['hp'] = $p_hp;
$patient_row['M_PatientAddress'] = '';
$patient_row['M_DistrictID'] = 0;
$patient_row['M_CityID'] = 0;
$patient_row['M_ProvinceID'] = 0;
if ($patient_row['M_KelurahanID']) {
$addr = $this->db_onedev->query(
"SELECT *, CONCAT(IFNULL(?,''),'\n\n',M_KelurahanName,', ',M_DistrictName,'\n',M_CityName,', ',M_ProvinceName) as xaddress
FROM m_kelurahan
JOIN m_district ON M_KelurahanM_DistrictID = M_DistrictID
JOIN m_city ON M_DistrictM_CityID = M_CityID
JOIN m_province ON M_CityM_ProvinceID = M_ProvinceID
WHERE M_KelurahanID = ?",
[$patient_row['M_PatientAddressDescription'], $patient_row['M_KelurahanID']]
)->row_array();
if ($addr) {
$patient_row['M_PatientAddress'] = stripslashes($addr['xaddress']);
$patient_row['M_DistrictID'] = $addr['M_DistrictID'];
$patient_row['M_CityID'] = $addr['M_CityID'];
$patient_row['M_ProvinceID'] = $addr['M_ProvinceID'];
}
}
$patient_row['info'] = $this->build_patient_visit_info($patient_row['M_PatientID'], $patient_row['M_PatientDOB']);
// Hapus kolom enc sebelum return
foreach (['M_PatientName_enc','M_PatientName_bidx','M_PatientHP_enc','M_PatientHP_bidx',
'M_PatientEmail_enc','M_PatientIDNumber_enc','M_PatientNIK_bidx',
'M_PatientDOB_enc','M_PatientDOB_bidx'] as $col) {
unset($patient_row[$col]);
}
$rst['patient'] = $patient_row;
} else {
$rst['patient'] = [];
}
// MOU & Company dari order
$mou_id = intval($row_header['orderM_MouID'] ?? 0);
$row_mou = $this->db_onedev->query(
"SELECT M_MouM_CompanyID, M_MouStatus, M_MouEmail, M_MouEmailIsDefault,
M_MouEndDate, M_MouID, M_MouIsBill, M_MouIsDefault, M_MouName,
M_MouNote, M_MouStartDate
FROM m_mou WHERE M_MouID = ?",
[$mou_id]
)->row_array();
$row_company = [];
if ($row_mou) {
$row_company = $this->db_onedev->query(
"SELECT * FROM m_company WHERE M_CompanyID = ?",
[$row_mou['M_MouM_CompanyID']]
)->row_array();
$row_company['mou'] = $this->db_onedev->query(
"SELECT M_MouStatus, M_MouEmail, M_MouEmailIsDefault, M_MouEndDate, M_MouID,
M_MouIsBill, M_MouIsDefault, M_MouName, M_MouNote, M_MouStartDate
FROM m_mou
WHERE M_MouM_CompanyID = ? AND M_MouStatus = 'R' AND M_MouIsActive = 'Y'",
[$row_company['M_CompanyID']]
)->result_array();
}
$rst['selected_mou'] = $row_mou ?: [];
$rst['selected_company'] = $row_company ?: [];
$rst['companies'] = $row_company ? [$row_company] : [];
$rst['tests'] = [];
$sql = "SELECT ss_price_mou.*
FROM one_klinik.order_penunjang
JOIN t_test
ON orderPenunjangT_TestID = t_test.T_TestID
AND t_test.T_TestIsActive = 'Y'
JOIN ss_price_mou
ON Ss_PriceMouM_MouID = ?
AND t_test.T_TestID = ss_price_mou.T_TestID
AND is_packet = 'N'
WHERE orderPenunjangOrderID = ?
AND orderPenunjangIsActive = 'Y'
GROUP BY ss_price_mou.T_TestID";
$qry_tests = $this->db_onedev->query($sql, [
$row_header['settingM_MouID'],
$row_header['orderID']
]);
if (!$qry_tests) {
$this->sys_error_db("tests query: " . $this->db_onedev->error()['message'], $this->db_onedev);
exit;
}
$get_tests_from_detail = $qry_tests->result_array();
if ($get_tests_from_detail) {
foreach ($get_tests_from_detail as $value) {
$data_ss_price = $value;
$data_ss_price['requirement'] = [];
if ($data_ss_price['px_type'] == "PX") {
$x = $this->db_smartone->query(
"SELECT fn_fo_requirement_get(?) x",
[$data_ss_price['T_TestID']]
)->row();
if ($x && $x->x != null) {
$data_ss_price['requirement'] = json_decode($x->x);
}
}
if ($data_ss_price['is_packet'] == 'N') {
$tests = $data_ss_price['T_PriceT_TestID'];
$panels = '';
} else {
$tests = '';
$panels = $data_ss_price['T_PriceT_TestID'];
}
$x = $this->db_smartone->query(
"SELECT fn_fo_find_promise_by_px(?, ?) as x",
[$tests, $panels]
)->row();
if ($x && $x->x != null) {
$data_ss_price['promise'] = $x->x;
}
$data_ss_price['nat_test'] = json_decode($data_ss_price['nat_test']);
$data_ss_price['child_test'] = json_decode($data_ss_price['child_test']);
$rst['tests'][] = $data_ss_price;
}
}
$rst['diagnose'] = $row_header['orderDoctorDiagnosePrimer'] ?? '';
$this->sys_ok(['records' => $rst]);
exit;
}
}

View File

@@ -234,8 +234,7 @@ class Patient extends MY_Controller
}
unset($rows[$k]['M_PatientNameRaw'], $rows[$k]['M_PatientDOB']);
$info = $this->db_smartone->query("SELECT fn_fo_patient_visit(?) info", [$v['M_PatientID']])->row();
$rows[$k]['info'] = json_decode($info->info);
$rows[$k]['info'] = $this->build_patient_visit_info($v['M_PatientID'], $dob_dec);
$ref_query = $this->db_smartone->query(
"SELECT M_ReferenceID, M_ReferenceName
@@ -250,6 +249,50 @@ class Patient extends MY_Controller
$this->sys_ok(["total" => 0, "records" => $rows]);
}
protected function build_patient_visit_info($patient_id, $patient_dob)
{
$visit = 1;
$birthday = 'N';
$visit_query = $this->db_smartone->query(
"SELECT COUNT(DISTINCT T_OrderHeaderID) AS n
FROM t_orderheader
JOIN t_orderdetail ON T_OrderHeaderID = T_OrderDetailT_OrderHeaderID AND T_OrderDetailIsActive = 'Y'
WHERE T_OrderHeaderIsActive = 'Y'
AND T_OrderHeaderM_PatientID = ?",
[$patient_id]
);
if ($visit_query) {
$visit_row = $visit_query->row_array();
$visit += (int) ($visit_row['n'] ?? 0);
}
$init_visit_query = $this->db_smartone->query(
"SELECT M_PatientInitialVisit
FROM m_patient
WHERE M_PatientID = ?",
[$patient_id]
);
if ($init_visit_query) {
$init_visit_row = $init_visit_query->row_array();
if (!empty($init_visit_row['M_PatientInitialVisit'])) {
$visit += (int) $init_visit_row['M_PatientInitialVisit'];
}
}
$dob_time = empty($patient_dob) ? false : strtotime($patient_dob);
if ($dob_time !== false) {
$birthday = date('m-d', $dob_time) === date('m-d') ? 'Y' : 'N';
}
return json_decode(json_encode([
'visit' => $visit,
'birthday' => $birthday,
]));
}
function add_new()
{

View File

@@ -12,8 +12,280 @@ class Payment extends MY_Controller
{
parent::__construct();
$this->db_smartone = $this->load->database("onedev", true);
$this->db_onedev = $this->load->database("onedev", true);
$this->load->library('ibl_encryptor');
}
private function get_payment_type_code($payment_type_id)
{
$query = $this->db_onedev->query(
"SELECT M_PaymentTypeCode
FROM m_paymenttype
WHERE M_PaymentTypeID = ?
LIMIT 1",
[intval($payment_type_id)]
);
if (!$query) {
return '';
}
return strtoupper($query->row()->M_PaymentTypeCode ?? '');
}
private function normalize_payment($payment)
{
if (isset($payment['leftvalue']) || isset($payment['rightvalue']) || isset($payment['code'])) {
$payment['id'] = strval($payment['id'] ?? $payment['type'] ?? 0);
$payment['code'] = strtoupper($payment['code'] ?? $this->get_payment_type_code($payment['id']));
$payment['leftvalue'] = floatval($payment['leftvalue'] ?? 0);
$payment['rightvalue'] = floatval($payment['rightvalue'] ?? 0);
$payment['chex'] = isset($payment['chex']) ? (bool) $payment['chex'] : ($this->payment_amount_net($payment) > 0);
return $payment;
}
$normalized = $payment;
$normalized['id'] = strval($payment['type'] ?? $payment['id'] ?? 0);
$normalized['code'] = $this->get_payment_type_code($normalized['id']);
$normalized['leftvalue'] = floatval($payment['actual'] ?? $payment['amount'] ?? 0);
$normalized['rightvalue'] = floatval($payment['changes'] ?? 0);
$normalized['chex'] = $normalized['leftvalue'] > 0;
$normalized['selected_card'] = ['id' => intval($payment['card'] ?? 0), 'name' => ''];
$normalized['selected_edc'] = ['id' => intval($payment['edc'] ?? 0), 'name' => ''];
$normalized['selected_account'] = ['id' => intval($payment['account'] ?? 0), 'name' => ''];
return $normalized;
}
private function denormalize_payment($original_payment, $normalized_payment)
{
if (isset($original_payment['leftvalue']) || isset($original_payment['rightvalue']) || isset($original_payment['code'])) {
$original_payment['id'] = $normalized_payment['id'];
$original_payment['code'] = $normalized_payment['code'];
$original_payment['leftvalue'] = $normalized_payment['leftvalue'];
$original_payment['rightvalue'] = $normalized_payment['rightvalue'];
$original_payment['chex'] = !empty($normalized_payment['chex']);
return $original_payment;
}
$original_payment['type'] = strval($normalized_payment['id']);
$original_payment['amount'] = floatval($this->payment_amount_net($normalized_payment));
$original_payment['actual'] = floatval($normalized_payment['leftvalue']);
$original_payment['changes'] = floatval($normalized_payment['rightvalue']);
$original_payment['card'] = strval($this->get_selected_lookup_id($normalized_payment['selected_card'] ?? null));
$original_payment['edc'] = strval($this->get_selected_lookup_id($normalized_payment['selected_edc'] ?? null));
$original_payment['account'] = strval($this->get_selected_lookup_id($normalized_payment['selected_account'] ?? null));
return $original_payment;
}
private function payment_amount_net($payment)
{
$left = floatval($payment['leftvalue'] ?? 0);
$right = floatval($payment['rightvalue'] ?? 0);
$code = strtoupper($payment['code'] ?? '');
if ($code === 'CASH') {
return max(0, $left - $right);
}
return max(0, $left);
}
private function build_zero_payment($payment)
{
$payment['chex'] = false;
$payment['leftvalue'] = 0;
$payment['rightvalue'] = 0;
return $payment;
}
private function get_selected_lookup_id($value)
{
if (is_array($value)) {
return intval($value['id'] ?? 0);
}
return 0;
}
private function split_payments_for_klinik($payments, $clinic_amount)
{
$remaining_clinic = max(0, floatval($clinic_amount));
$clinic_payments = [];
$ibl_payments = [];
foreach ($payments as $payment) {
$normalized_payment = $this->normalize_payment($payment);
$code = strtoupper($normalized_payment['code'] ?? '');
$net_amount = $this->payment_amount_net($normalized_payment);
$allocated = min($remaining_clinic, $net_amount);
$clinic_payment = $this->build_zero_payment($normalized_payment);
$ibl_payment = $normalized_payment;
if ($allocated > 0) {
$clinic_payment['chex'] = true;
if ($code === 'CASH') {
$clinic_payment['leftvalue'] = $allocated;
$clinic_payment['rightvalue'] = 0;
$ibl_payment['leftvalue'] = max(0, floatval($normalized_payment['leftvalue']) - $allocated);
$ibl_payment['chex'] = ($this->payment_amount_net($ibl_payment) > 0);
} else {
$clinic_payment['leftvalue'] = $allocated;
$ibl_payment['leftvalue'] = max(0, floatval($normalized_payment['leftvalue']) - $allocated);
$ibl_payment['chex'] = (floatval($ibl_payment['leftvalue']) > 0);
}
$remaining_clinic -= $allocated;
} else {
$ibl_payment['chex'] = ($net_amount > 0) ? !empty($normalized_payment['chex']) : false;
}
$clinic_payments[] = $clinic_payment;
$ibl_payments[] = $this->denormalize_payment($payment, $ibl_payment);
}
return [
'clinic_payments' => $clinic_payments,
'ibl_payments' => $ibl_payments,
'allocated_total' => max(0, floatval($clinic_amount) - $remaining_clinic)
];
}
private function get_order_klinik_outstanding($order_klinik_id)
{
$sql = "SELECT
o.orderID,
o.orderTotal,
IFNULL(SUM(CASE WHEN p.PaymentIsActive = 'Y' THEN p.PaymentTotal ELSE 0 END), 0) AS paid_total
FROM one_klinik.`order` o
LEFT JOIN one_klinik.`payment` p ON p.PaymentOrderID = o.orderID
WHERE o.orderID = ?
GROUP BY o.orderID, o.orderTotal
LIMIT 1";
$query = $this->db_onedev->query($sql, [$order_klinik_id]);
if (!$query) {
return [false, "Gagal mengambil data order klinik"];
}
$row = $query->row_array();
if (!$row) {
return [false, "Order klinik tidak ditemukan"];
}
$outstanding = max(0, floatval($row['orderTotal']) - floatval($row['paid_total']));
$row['outstanding_total'] = $outstanding;
return [true, $row];
}
private function save_payment_klinik($orderid, $payments, $xuserid)
{
$sql = "INSERT INTO one_klinik.`payment`(PaymentOrderID,PaymentDate,PaymentCreated,PaymentM_UserID) VALUES (?,CURDATE(),NOW(),?)";
$query = $this->db_onedev->query($sql, [$orderid, $xuserid]);
if (!$query) {
return [false, "payment klinik insert"];
}
$headerid = $this->db_onedev->insert_id();
foreach ($payments as $v) {
if (empty($v['chex'])) {
continue;
}
$actual = 0;
$change = 0;
$amount = floatval($v['leftvalue'] ?? 0);
if (($v['code'] ?? '') == 'CASH') {
$actual = floatval($v['leftvalue'] ?? 0);
$change = floatval($v['rightvalue'] ?? 0);
$amount = ($actual > 0) ? ($actual - $change) : $actual;
$sql = "INSERT INTO one_klinik.`paymentdetail`(
PaymentDetailPaymentID,
PaymentDetailM_PaymentTypeID,
PaymentDetailAmount,
PaymentDetailActual,
PaymentDetailChange,
PaymentDetailCreated,
PaymentDetailLastUpdated,
PaymentDetailUserID
) VALUES (?, ?, ?, ?, ?, now(), now(), ?)";
$query = $this->db_onedev->query($sql, [
$headerid,
$v['id'],
$amount,
$actual,
$change,
$xuserid
]);
if (!$query) {
return [false, "payment klinik detail cash insert"];
}
} else {
$selected_card = 0;
$selected_edc = 0;
if (($v['code'] ?? '') == 'DEBIT' || ($v['code'] ?? '') == 'CREDIT' || ($v['code'] ?? '') == 'TRANSFER') {
$selected_card = $this->get_selected_lookup_id($v['selected_card'] ?? null);
$selected_edc = $this->get_selected_lookup_id($v['selected_edc'] ?? null);
if (($v['code'] ?? '') == 'TRANSFER') {
$selected_edc = $this->get_selected_lookup_id($v['selected_account'] ?? null);
}
}
$sql = "INSERT INTO one_klinik.`paymentdetail`(
PaymentDetailPaymentID,
PaymentDetailM_PaymentTypeID,
PaymentDetailAmount,
PaymentDetailActual,
PaymentDetailChange,
PaymentDetailCardNat_BankID,
PaymentDetailEDCNat_BankID,
PaymentDetailM_BankAccountID,
PaymentDetailCreated,
PaymentDetailLastUpdated,
PaymentDetailUserID
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, now(), now(), ?)";
$query = $this->db_onedev->query($sql, [
$headerid,
$v['id'],
$amount,
0,
0,
$selected_card,
0,
$selected_edc,
$xuserid
]);
if (!$query) {
return [false, "payment klinik detail non cash insert"];
}
}
}
$sql = "SELECT SUM(PaymentDetailAmount) as total
FROM one_klinik.`paymentdetail`
WHERE PaymentDetailPaymentID = ? AND PaymentDetailIsActive = 'Y'";
$total_paid = floatval($this->db_onedev->query($sql, [$headerid])->row()->total ?? 0);
$sql = "UPDATE one_klinik.`payment` SET PaymentTotal = ? WHERE PaymentID = ?";
$this->db_onedev->query($sql, [$total_paid, $headerid]);
$sql = "SELECT SUM(PaymentTotal) as paid, orderTotal as total
FROM one_klinik.`payment`
JOIN one_klinik.`order` ON orderID = PaymentOrderID
WHERE PaymentOrderID = ? AND PaymentIsActive = 'Y'";
$xtotal_all_paid = $this->db_onedev->query($sql, [$orderid])->row_array();
if ($xtotal_all_paid && floatval($xtotal_all_paid['paid']) >= floatval($xtotal_all_paid['total'])) {
$sql = "UPDATE one_klinik.`order` SET orderIsLunas = 'Y' WHERE orderID = ?";
$this->db_onedev->query($sql, [$orderid]);
}
$xdata = $this->db_onedev->query(
"SELECT PaymentID as idx, PaymentNumber as numberx FROM one_klinik.payment WHERE PaymentID = ?",
[$headerid]
)->row();
return [true, ['payment_id' => $headerid, 'payment_total' => $total_paid, 'data' => $xdata]];
}
public function get_order() {
$prm = $this->sys_input;
@@ -180,8 +452,55 @@ class Payment extends MY_Controller
function save()
{
$prm = $this->sys_input;
$payment_json = json_encode($prm['payments']);
$payments_ibl = $prm['payments'];
$klinik_payment_result = null;
if (!empty($prm['order_klinik_id'])) {
list($ok_order_klinik, $order_klinik_data) = $this->get_order_klinik_outstanding($prm['order_klinik_id']);
if (!$ok_order_klinik) {
$this->sys_error($order_klinik_data);
exit;
}
$split = $this->split_payments_for_klinik($prm['payments'], $order_klinik_data['outstanding_total']);
if ($split['allocated_total'] > 0) {
list($ok_payment_klinik, $payment_klinik_data) = $this->save_payment_klinik(
$prm['order_klinik_id'],
$split['clinic_payments'],
$this->sys_user['M_UserID']
);
if (!$ok_payment_klinik) {
$this->sys_error_db($payment_klinik_data, $this->db_onedev);
exit;
}
$klinik_payment_result = $payment_klinik_data;
}
$payments_ibl = $split['ibl_payments'];
}
$has_ibl_payment = false;
foreach ($payments_ibl as $payment) {
$normalized_payment = $this->normalize_payment($payment);
if (!empty($normalized_payment['chex']) && $this->payment_amount_net($normalized_payment) > 0) {
$has_ibl_payment = true;
break;
}
}
if (!$has_ibl_payment) {
$result = [
'status' => 'OK',
'data' => [
'status' => 'OK',
'order_klinik_payment' => $klinik_payment_result,
'ibl_payment' => null
]
];
$this->sys_ok($result['data']);
exit;
}
$payment_json = json_encode($payments_ibl);
$sql = "CALL sp_fo_payment('{$prm['order_id']}', '{$payment_json}', '{$this->sys_user['M_UserID']}');";
$query = $this->db_smartone->query($sql);
@@ -189,6 +508,9 @@ class Payment extends MY_Controller
{
$rst = $query->row();
$rst->data = json_decode($rst->data);
if (is_object($rst->data)) {
$rst->data->order_klinik_payment = $klinik_payment_result;
}
echo json_encode($rst);
}
else

View File

@@ -0,0 +1,73 @@
@baseUrl = https://devone.aplikasi.web.id/one-api-lab
@token = eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJNX1VzZXJJRCI6IjMiLCJNX1VzZXJVc2VybmFtZSI6ImFkbWluICIsIk1fVXNlckdyb3VwRGFzaGJvYXJkIjoib25lLXVpLWxhYlwvdGVzdFwvdnVleFwvb25lLXBhdGllbnQtbGlzdC1iYXJjb2RlLXZ2LTYtY3BvbmVcLyIsIk1fVXNlckRlZmF1bHRUX1NhbXBsZVN0YXRpb25JRCI6IjAiLCJNX1N0YWZmTmFtZSI6IkFCSVRBIEpVV0lUQSBTQVJJIiwiaXNfY291cmllciI6Ik4iLCJ0aW1lX2F1dG9sb2dvdXQiOiIxMDAwMDAwIiwiaXAiOiIxMDMuMy4yMjAuMjIxIiwiYWdlbnQiOiJNb3ppbGxhXC81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV2luNjQ7IHg2NCkgQXBwbGVXZWJLaXRcLzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZVwvMTQ5LjAuMC4wIFNhZmFyaVwvNTM3LjM2IiwidmVyc2lvbiI6InYyIiwibGFzdC1sb2dpbiI6IjIwMjYtMDYtMjIgMTE6MjM6MjkiLCJNX1NhdGVsbGl0ZUlEIjowfQ.wkQFPGQ52TeceDQARm8auj6jEb159V46BzTZ9NEE_vM
@poliId = 1
### Search Poli
POST {{baseUrl}}/mockup/masterdata/poli/search
Content-Type: application/json
{
"token": "{{token}}",
"search": "",
"page": 1,
"row_per_page": 10,
"order_by": "id",
"order": "asc"
}
### Search Poli By Name
POST {{baseUrl}}/mockup/masterdata/poli/search
Content-Type: application/json
{
"token": "{{token}}",
"search": "khitan",
"page": 1,
"row_per_page": 10,
"order_by": "name",
"order": "asc"
}
### Get Screening Templates
POST {{baseUrl}}/mockup/masterdata/poli/gettemplates
Content-Type: application/json
{
"token": "{{token}}"
}
### Add Poli
POST {{baseUrl}}/mockup/masterdata/poli/add
Content-Type: application/json
{
"token": "{{token}}",
"code": "POLI_TEST",
"name": "Poli Test",
"description": "Poli untuk test API",
"satusehat_location_id": "",
"screening_template_id": null
}
### Update Poli
POST {{baseUrl}}/mockup/masterdata/poli/update
Content-Type: application/json
{
"token": "{{token}}",
"id": {{poliId}},
"code": "POLI_TEST",
"name": "Poli Test Update",
"description": "Poli untuk test API update",
"satusehat_location_id": "",
"screening_template_id": null
}
### Delete Poli
POST {{baseUrl}}/mockup/masterdata/poli/delete
Content-Type: application/json
{
"token": "{{token}}",
"id": {{poliId}}
}

View File

@@ -0,0 +1,323 @@
<?php
class Poli extends MY_Controller
{
var $db_oneklinik;
public function __construct()
{
parent::__construct();
$this->db_oneklinik = $this->load->database("onedev", true);
}
public function index()
{
echo "POLI API";
}
public function search()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$search = isset($prm['search']) ? trim($prm['search']) : (isset($prm['name']) ? trim($prm['name']) : '');
$like = '%' . $search . '%';
$row_per_page = isset($prm['row_per_page']) && intval($prm['row_per_page']) > 0 ? intval($prm['row_per_page']) : 10;
$page = 1;
if (isset($prm['page']) && intval($prm['page']) > 0) {
$page = intval($prm['page']);
} elseif (isset($prm['current_page']) && intval($prm['current_page']) > 0) {
$page = intval($prm['current_page']);
}
$offset = ($page - 1) * $row_per_page;
$allowed_order_by = array(
'id' => 'cu.M_ClinicUnitID',
'code' => 'cu.M_ClinicUnitCode',
'name' => 'cu.M_ClinicUnitName',
'description' => 'cu.M_ClinicUnitDescription',
'screening_template_name' => 'st.M_ScreeningTemplateName'
);
$order_by = 'cu.M_ClinicUnitID';
if (isset($prm['order_by']) && isset($allowed_order_by[$prm['order_by']])) {
$order_by = $allowed_order_by[$prm['order_by']];
}
$order = isset($prm['order']) && strtolower($prm['order']) === 'desc' ? 'DESC' : 'ASC';
$sql_count = "SELECT COUNT(*) AS total
FROM one_klinik.m_clinic_unit cu
LEFT JOIN one_klinik.m_screening_template st
ON st.M_ScreeningTemplateID = cu.M_ClinicUnitM_ScreeningTemplateID
AND st.M_ScreeningTemplateIsActive = 'Y'
WHERE cu.M_ClinicUnitIsActive = 'Y'
AND (
cu.M_ClinicUnitCode LIKE ?
OR cu.M_ClinicUnitName LIKE ?
OR IFNULL(cu.M_ClinicUnitDescription, '') LIKE ?
OR IFNULL(cu.M_ClinicUnitSatusehatLocationID, '') LIKE ?
OR IFNULL(st.M_ScreeningTemplateName, '') LIKE ?
)";
$query_count = $this->db_oneklinik->query($sql_count, array($like, $like, $like, $like, $like));
if (!$query_count) {
$this->sys_error_db("m_clinic_unit count", $this->db_oneklinik);
exit;
}
$total_filter = intval($query_count->row()->total);
$total_page = ceil($total_filter / $row_per_page);
$sql = "SELECT
cu.M_ClinicUnitID AS id,
cu.M_ClinicUnitCode AS code,
cu.M_ClinicUnitName AS name,
cu.M_ClinicUnitDescription AS description,
cu.M_ClinicUnitSatusehatLocationID AS satusehat_location_id,
cu.M_ClinicUnitM_ScreeningTemplateID AS screening_template_id,
st.M_ScreeningTemplateCode AS screening_template_code,
st.M_ScreeningTemplateName AS screening_template_name,
cu.M_ClinicUnitIsActive AS is_active,
cu.M_ClinicUnitCreated AS created,
cu.M_ClinicUnitLastUpdated AS last_updated
FROM one_klinik.m_clinic_unit cu
LEFT JOIN one_klinik.m_screening_template st
ON st.M_ScreeningTemplateID = cu.M_ClinicUnitM_ScreeningTemplateID
AND st.M_ScreeningTemplateIsActive = 'Y'
WHERE cu.M_ClinicUnitIsActive = 'Y'
AND (
cu.M_ClinicUnitCode LIKE ?
OR cu.M_ClinicUnitName LIKE ?
OR IFNULL(cu.M_ClinicUnitDescription, '') LIKE ?
OR IFNULL(cu.M_ClinicUnitSatusehatLocationID, '') LIKE ?
OR IFNULL(st.M_ScreeningTemplateName, '') LIKE ?
)
ORDER BY {$order_by} {$order}
LIMIT ? OFFSET ?";
$query = $this->db_oneklinik->query($sql, array($like, $like, $like, $like, $like, $row_per_page, $offset));
if (!$query) {
$this->sys_error_db("m_clinic_unit select", $this->db_oneklinik);
exit;
}
$rows = $query->result_array();
$this->sys_ok(array(
"total" => $total_page,
"total_filter" => $total_filter,
"records" => $rows
));
} catch (Exception $exc) {
$this->sys_error($exc->getMessage());
}
}
public function gettemplates()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$sql = "SELECT
M_ScreeningTemplateID AS id,
M_ScreeningTemplateCode AS code,
M_ScreeningTemplateName AS name,
M_ScreeningTemplateDescription AS description
FROM one_klinik.m_screening_template
WHERE M_ScreeningTemplateIsActive = 'Y'
ORDER BY M_ScreeningTemplateName ASC";
$query = $this->db_oneklinik->query($sql);
if (!$query) {
$this->sys_error_db("m_screening_template select", $this->db_oneklinik);
exit;
}
$rows = $query->result_array();
$this->sys_ok(array("total" => count($rows), "records" => $rows));
} catch (Exception $exc) {
$this->sys_error($exc->getMessage());
}
}
public function add()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$code = isset($prm['code']) ? trim($prm['code']) : '';
$name = isset($prm['name']) ? trim($prm['name']) : '';
$description = isset($prm['description']) ? trim($prm['description']) : null;
$satusehat_location_id = isset($prm['satusehat_location_id']) ? trim($prm['satusehat_location_id']) : null;
$screening_template_id = isset($prm['screening_template_id']) && $prm['screening_template_id'] !== '' ? intval($prm['screening_template_id']) : null;
$userid = $this->sys_user["M_UserID"];
if ($code === '' || $name === '') {
$this->sys_error("code and name are mandatory");
exit;
}
$duplicate = $this->db_oneklinik->query(
"SELECT COUNT(*) AS total
FROM one_klinik.m_clinic_unit
WHERE M_ClinicUnitCode = ?
OR (M_ClinicUnitIsActive = 'Y' AND M_ClinicUnitName = ?)",
array($code, $name)
);
if (!$duplicate) {
$this->sys_error_db("m_clinic_unit duplicate check", $this->db_oneklinik);
exit;
}
if (intval($duplicate->row()->total) > 0) {
$this->sys_ok(array(
"total" => -1,
"errors" => array(array("field" => "code", "msg" => "Kode atau nama sudah ada")),
"records" => 0
));
exit;
}
$sql = "INSERT INTO one_klinik.m_clinic_unit (
M_ClinicUnitCode,
M_ClinicUnitName,
M_ClinicUnitDescription,
M_ClinicUnitSatusehatLocationID,
M_ClinicUnitM_ScreeningTemplateID,
M_ClinicUnitUserID,
M_ClinicUnitCreated,
M_ClinicUnitLastUpdated
) VALUES (?, ?, ?, ?, ?, ?, NOW(), NOW())";
$query = $this->db_oneklinik->query($sql, array(
$code,
$name,
$description,
$satusehat_location_id,
$screening_template_id,
$userid
));
if (!$query) {
$this->sys_error_db("m_clinic_unit insert", $this->db_oneklinik);
exit;
}
$this->sys_ok(array(
"total" => 1,
"records" => array("xid" => $this->db_oneklinik->insert_id())
));
} catch (Exception $exc) {
$this->sys_error($exc->getMessage());
}
}
public function update()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$id = isset($prm['id']) ? intval($prm['id']) : 0;
$code = isset($prm['code']) ? trim($prm['code']) : '';
$name = isset($prm['name']) ? trim($prm['name']) : '';
$description = isset($prm['description']) ? trim($prm['description']) : null;
$satusehat_location_id = isset($prm['satusehat_location_id']) ? trim($prm['satusehat_location_id']) : null;
$screening_template_id = isset($prm['screening_template_id']) && $prm['screening_template_id'] !== '' ? intval($prm['screening_template_id']) : null;
$userid = $this->sys_user["M_UserID"];
if (!$id || $code === '' || $name === '') {
$this->sys_error("id, code and name are mandatory");
exit;
}
$duplicate = $this->db_oneklinik->query(
"SELECT COUNT(*) AS total
FROM one_klinik.m_clinic_unit
WHERE M_ClinicUnitID <> ?
AND (M_ClinicUnitCode = ?
OR (M_ClinicUnitIsActive = 'Y' AND M_ClinicUnitName = ?))",
array($id, $code, $name)
);
if (!$duplicate) {
$this->sys_error_db("m_clinic_unit duplicate check", $this->db_oneklinik);
exit;
}
if (intval($duplicate->row()->total) > 0) {
$this->sys_ok(array(
"total" => -1,
"errors" => array(array("field" => "code", "msg" => "Kode atau nama sudah ada")),
"records" => 0
));
exit;
}
$sql = "UPDATE one_klinik.m_clinic_unit SET
M_ClinicUnitCode = ?,
M_ClinicUnitName = ?,
M_ClinicUnitDescription = ?,
M_ClinicUnitSatusehatLocationID = ?,
M_ClinicUnitM_ScreeningTemplateID = ?,
M_ClinicUnitUserID = ?,
M_ClinicUnitLastUpdated = NOW()
WHERE M_ClinicUnitID = ?
AND M_ClinicUnitIsActive = 'Y'";
$query = $this->db_oneklinik->query($sql, array(
$code,
$name,
$description,
$satusehat_location_id,
$screening_template_id,
$userid,
$id
));
if (!$query) {
$this->sys_error_db("m_clinic_unit update", $this->db_oneklinik);
exit;
}
$this->sys_ok(array("total" => 1, "records" => array("xid" => $id)));
} catch (Exception $exc) {
$this->sys_error($exc->getMessage());
}
}
public function delete()
{
try {
if (!$this->isLogin) {
$this->sys_error("Invalid Token");
exit;
}
$prm = $this->sys_input;
$id = isset($prm['id']) ? intval($prm['id']) : 0;
if (!$id) {
$this->sys_error("id is mandatory");
exit;
}
$userid = $this->sys_user["M_UserID"];
$sql = "UPDATE one_klinik.m_clinic_unit SET
M_ClinicUnitIsActive = 'N',
M_ClinicUnitUserID = ?,
M_ClinicUnitLastUpdated = NOW()
WHERE M_ClinicUnitID = ?";
$query = $this->db_oneklinik->query($sql, array($userid, $id));
if (!$query) {
$this->sys_error_db("m_clinic_unit delete", $this->db_oneklinik);
exit;
}
$this->sys_ok(array("total" => 1, "records" => array("xid" => $id)));
} catch (Exception $exc) {
$this->sys_error($exc->getMessage());
}
}
}

View File

@@ -12,8 +12,26 @@ class Preregisterapp extends MY_Controller
{
parent::__construct();
$this->db_onedev = $this->load->database("onedev", true);
$this->load->library('ibl_encryptor');
}
private function _mask_name($v) {
if (!$v) return $v;
$v = trim($v);
$words = preg_split('/\s+/', $v);
$out = [];
foreach ($words as $w) {
$l = mb_strlen($w, 'UTF-8');
if ($l <= 2) { $out[] = '***'; continue; }
$out[] = mb_substr($w, 0, 2, 'UTF-8') . str_repeat('*', max(3, $l - 2));
}
return implode(' ', $out);
}
private function _mask_phone($v) { if (!$v) return $v; $d=preg_replace('/[^0-9]/','',trim($v)); $l=strlen($d); if($l<=4) return '****'; if($l<=8) return substr($d,0,4).str_repeat('*',$l-4); return substr($d,0,4).str_repeat('*',$l-7).substr($d,-3); }
private function _mask_email($v) { if (!$v||strpos($v,'@')===false) return $v; [$loc,$dom]=explode('@',$v,2); return mb_substr($loc,0,min(2,mb_strlen($loc,'UTF-8')),'UTF-8').'***@'.$dom; }
private function _mask_id($v) { if (!$v) return $v; $v=trim($v); $l=strlen($v); if($l<=4) return '****'; return substr($v,0,4).str_repeat('*',max(3,$l-6)).($l>6?substr($v,-2):''); }
private function _mask_dob($v) { if (!$v) return $v; $p=explode('-',$v); return (count($p)===3) ? '**-**-'.$p[2] : '****-**-**'; }
public function get_setup_by_id()
{
try {
@@ -270,8 +288,8 @@ class Preregisterapp extends MY_Controller
Mcu_PreregisterPatientsPatientName,
' ',
IFNULL(Mcu_PreregisterPatientsPatientSuffix,'')) as patient_fullname,
DATE_FORMAT(Mcu_PreregisterPatientsDOB,'%d-%m-%Y') as dob,
DATE_FORMAT(Mcu_PreregisterPatientsDOB,'%d-%m-%Y') as Mcu_PreregisterPatientsDOB,
Mcu_PreregisterPatientsDOB as dob,
Mcu_PreregisterPatientsDOB,
IFNULL(M_PatientAddressDescription, '') as M_PatientAddress,
M_PatientAddressCity,
IFNULL(M_PatientAddressCountry, 'ID') as M_PatientAddressCountry,
@@ -440,11 +458,25 @@ class Preregisterapp extends MY_Controller
if ($prm['search'] != '') {
$e = explode('+', $prm['search']);
if (isset($e[0]))
$q['name'] = "AND M_PatientName LIKE '%{$e[0]}%'";
if (isset($e[1]))
$q['dob'] = "AND ((DATE_FORMAT(M_PatientDOB, '%d-%m-%Y') LIKE '%{$e[1]}%' and M_PatientDOB IS NOT NULL) OR (M_PatientDOB IS NULL AND '{$e[1]}' = ''))";
if (isset($e[2]))
if (isset($e[0]) && $e[0] != '') {
$name_toks = $this->ibl_encryptor->query_tokens($e[0]);
$name_conds = [];
foreach ($name_toks as $tok) {
$tok_esc = $this->db_onedev->escape_str($tok);
$name_conds[] = "JSON_CONTAINS(M_PatientName_bidx, '\"$tok_esc\"')";
}
if ($name_conds) $q['name'] = "AND " . implode(' AND ', $name_conds);
}
if (isset($e[1]) && $e[1] != '') {
$dob_toks = $this->ibl_encryptor->query_tokens($e[1]);
$dob_conds = [];
foreach ($dob_toks as $tok) {
$tok_esc = $this->db_onedev->escape_str($tok);
$dob_conds[] = "JSON_CONTAINS(M_PatientDOB_bidx, '\"$tok_esc\"')";
}
if ($dob_conds) $q['dob'] = "AND " . implode(' AND ', $dob_conds);
}
if (isset($e[2]) && $e[2] != '')
$q['nik'] = "AND M_PatientNIP LIKE '%{$e[2]}%'";
}
@@ -453,7 +485,7 @@ class Preregisterapp extends MY_Controller
'N' divider,
concat(IFNULL(M_TitleName,''),' ',IFNULL(M_PatientPrefix,''),' ',M_PatientName,' ',IFNULL(M_PatientSuffix,'')) M_PatientName,
M_PatientName M_PatientRealName, M_TitleID, M_TitleName, M_PatientM_SexID,
DATE_FORMAT(M_PatientDOB,'%d-%m-%Y') as dob_ina,
M_PatientDOB as dob_ina,
IFNULL(M_PatientReligionCode, '-') M_PatientReligionCode,
M_PatientNoReg as Mcu_PreregisterPatientsPID,
M_PatientIdentifierValue as Mcu_PreregisterPatientsKTP,
@@ -601,20 +633,21 @@ class Preregisterapp extends MY_Controller
?
)";
//echo $query;
$m_dob_ptp = $this->_mask_dob(date('d-m-Y', strtotime($pdob)));
$rows = $this->db_onedev->query($query, [
$setup['Mgm_McuID'],
$v['Mcu_PreregisterPatientsPID'],
$v['M_PatientID'],
$v['Mcu_PreregisterPatientsKTP'],
$v['Mcu_PreregisterPatientsKTP'] ? $this->_mask_id($v['Mcu_PreregisterPatientsKTP']) : '',
$v['M_PatientPrefix'],
$v['M_PatientRealName'],
$this->_mask_name($v['M_PatientRealName']),
$v['M_PatientSuffix'],
$v['M_PatientM_SexID'],
$pdob,
$m_dob_ptp,
$v['M_PatientReligionCode'],
$v['Mcu_PreregisterPatientsJob'],
$v['Mcu_PreregisterPatientsEmail'],
$v['Mcu_PreregisterPatientsHp'],
$this->_mask_email($v['Mcu_PreregisterPatientsEmail']),
$this->_mask_phone($v['Mcu_PreregisterPatientsHp']),
$v['Mcu_PreregisterPatientsPosisi'],
$v['Mcu_PreregisterPatientsDivisi'],
$v['Mcu_PreregisterPatientsLocation'],
@@ -660,22 +693,39 @@ class Preregisterapp extends MY_Controller
$IdentifierSystem = 'http://terminology.hl7.org/CodeSystem/v2-0203';
}
$enc_new = $this->ibl_encryptor;
$plain_name_new = $v['Mcu_PreregisterPatientsPatientName'];
$plain_ktp_new = $v['Mcu_PreregisterPatientsKTP'];
$plain_email_new = $v['Mcu_PreregisterPatientsEmail'];
$plain_hp_new = $v['Mcu_PreregisterPatientsHp'];
$dob_str_new = date('d-m-Y', strtotime($pdob));
$sql = "INSERT INTO m_patient (
M_PatientPrefix,
M_PatientName,
M_PatientName_enc,
M_PatientName_bidx,
M_PatientSuffix,
M_PatientM_TitleID,
M_PatientM_SexID,
M_PatientDOB,
M_PatientDOB_enc,
M_PatientDOB_bidx,
M_PatientIdentifierCode,
M_PatientIdentifierSystem,
M_PatientIdentifierValue,
M_PatientIDNumber,
M_PatientIDNumber_enc,
M_PatientNIK_bidx,
M_PatientPosisi,
M_PatientDivisi,
M_PatientLocation,
M_PatientJob,
M_PatientEmail,
M_PatientEmail_enc,
M_PatientHP,
M_PatientHP_enc,
M_PatientHP_bidx,
M_PatientCreatedUserID,
M_PatientNIP,
M_PatientDepartement,
@@ -683,31 +733,39 @@ class Preregisterapp extends MY_Controller
M_PatientCreated,
M_PatientRegisteredByCompanyID
)
VALUES(
'{$v["Mcu_PreregisterPatientsPatientPrefix"]}',
'{$nameNewPn}',
'{$v["Mcu_PreregisterPatientsPatientSuffix"]}',
'{$title_id}',
'{$v["M_PatientM_SexID"]}',
'{$pdob}',
'{$typeIdentifier}',
'{$IdentifierSystem}',
'{$v["Mcu_PreregisterPatientsKTP"]}',
'{$v['Mcu_PreregisterPatientsPosisi']}',
'{$v['Mcu_PreregisterPatientsDivisi']}',
'{$v['Mcu_PreregisterPatientsLocation']}',
'{$v['Mcu_PreregisterPatientsJob']}',
'{$v['Mcu_PreregisterPatientsEmail']}',
'{$v['Mcu_PreregisterPatientsHp']}',
'{$userid}',
'{$v['Mcu_PreregisterPatientsNIK']}',
'{$v['Mcu_PreregisterPatientsDepartment']}',
'{$number}',
NOW(),
'{$setup['Mgm_McuM_CompanyID']}'
)";
//echo $sql;
$rows = $this->db_onedev->query($sql);
VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,NOW(),?)";
$rows = $this->db_onedev->query($sql, [
$v['Mcu_PreregisterPatientsPatientPrefix'],
$this->_mask_name($plain_name_new),
$enc_new->encrypt($plain_name_new),
$enc_new->search_bidx($plain_name_new),
$v['Mcu_PreregisterPatientsPatientSuffix'],
$title_id,
$v['M_PatientM_SexID'],
$this->_mask_dob($dob_str_new),
$enc_new->encrypt($dob_str_new),
$enc_new->search_bidx($dob_str_new),
$typeIdentifier,
$IdentifierSystem,
$plain_ktp_new ? $this->_mask_id($plain_ktp_new) : '',
$plain_ktp_new ? $this->_mask_id($plain_ktp_new) : null,
$plain_ktp_new ? $enc_new->encrypt($plain_ktp_new) : null,
$enc_new->search_bidx($plain_ktp_new ?? ''),
$v['Mcu_PreregisterPatientsPosisi'],
$v['Mcu_PreregisterPatientsDivisi'],
$v['Mcu_PreregisterPatientsLocation'],
$v['Mcu_PreregisterPatientsJob'],
$plain_email_new ? $this->_mask_email($plain_email_new) : '',
$plain_email_new ? $enc_new->encrypt($plain_email_new) : null,
$plain_hp_new ? $this->_mask_phone($plain_hp_new) : '',
$plain_hp_new ? $enc_new->encrypt($plain_hp_new) : null,
$enc_new->search_bidx($plain_hp_new ?? ''),
$userid,
$v['Mcu_PreregisterPatientsNIK'],
$v['Mcu_PreregisterPatientsDepartment'],
$number,
$setup['Mgm_McuM_CompanyID']
]);
if (!$rows) {
$message = $this->db_onedev->error();
$message['qry'] = $this->db_onedev->last_query();
@@ -1039,7 +1097,7 @@ class Preregisterapp extends MY_Controller
}
$pdob = date('Y-m-d', strtotime($v['Mcu_PreregisterPatientsDOB']));
$pdob_input = $v['Mcu_PreregisterPatientsDOB'];
$Mcu_PreregisterPatientsTests = '';
$packettests = array();
@@ -1069,9 +1127,23 @@ class Preregisterapp extends MY_Controller
}
$dataPatientBefore = $rows->row_array();
$enc_upd = $this->ibl_encryptor;
$pdob_ts = strtotime($pdob_input);
if ($pdob_ts && $pdob_ts > 0 && strpos($pdob_input, '*') === false) {
$dob_str_upd = date('d-m-Y', $pdob_ts);
$pdob = date('Y-m-d', $pdob_ts);
} else {
$dob_str_upd = $enc_upd->decrypt($dataPatientBefore['M_PatientDOB_enc'] ?? '') ?: '';
$pdob = $dob_str_upd ? date('Y-m-d', strtotime($dob_str_upd)) : '';
}
$plain_name_upd = $v['Mcu_PreregisterPatientsPatientName'];
$plain_ktp_upd = $v['Mcu_PreregisterPatientsKTP'];
$plain_email_upd = $v['Mcu_PreregisterPatientsEmail'];
$plain_hp_upd = $v['Mcu_PreregisterPatientsHp'];
$this->db_onedev->trans_begin();
$query = " UPDATE mcu_preregister_patients SET
$query = " UPDATE mcu_preregister_patients SET
Mcu_PreregisterPatientsM_PatientID = ?,
Mcu_PreregisterPatientsKTP = ?,
Mcu_PreregisterPatientsNIP = ?,
@@ -1099,14 +1171,14 @@ class Preregisterapp extends MY_Controller
//echo $query;
$rows = $this->db_onedev->query($query, [
$v['Mcu_PreregisterPatientsM_PatientID'],
$v['Mcu_PreregisterPatientsKTP'],
$plain_ktp_upd ? $this->_mask_id($plain_ktp_upd) : '',
$v['Mcu_PreregisterPatientsNIP'],
$v['Mcu_PreregisterPatientsPatientPrefix'],
$v['Mcu_PreregisterPatientsPatientName'],
$this->_mask_name($plain_name_upd),
$v['Mcu_PreregisterPatientsPatientSuffix'],
$v['Mcu_PreregisterPatientsEmail'],
$v['Mcu_PreregisterPatientsHp'],
$pdob,
$plain_email_upd ? $this->_mask_email($plain_email_upd) : '',
$plain_hp_upd ? $this->_mask_phone($plain_hp_upd) : '',
$this->_mask_dob($dob_str_upd),
$v['Mcu_PreregisterPatientsPosisi'],
$v['Mcu_PreregisterPatientsDivisi'],
$v['Mcu_PreregisterPatientsJob'],
@@ -1129,24 +1201,30 @@ class Preregisterapp extends MY_Controller
exit;
}
$sql_ktp = '';
if (isset($v['Mcu_PreregisterPatientsKTP']) && $v['Mcu_PreregisterPatientsKTP'] != '') {
$sql_ktp = "M_PatientIdentifierCode = 'NNIDN', M_PatientIdentifierSystem='http://terminology.hl7.org/CodeSystem/v2-0203', M_PatientIdentifierValue = '{$v['Mcu_PreregisterPatientsKTP']}',";
//echo $sql_ktp;
} else {
$sql_ktp = "M_PatientIdentifierCode = '', M_PatientIdentifierSystem='', M_PatientIdentifierValue = '',";
}
$ktp_mask_upd = $plain_ktp_upd ? $this->_mask_id($plain_ktp_upd) : '';
$sql = "UPDATE m_patient SET
$sql_ktp
M_PatientIdentifierCode = ?,
M_PatientIdentifierSystem = ?,
M_PatientIdentifierValue = ?,
M_PatientIDNumber = ?,
M_PatientIDNumber_enc = ?,
M_PatientNIK_bidx = ?,
M_PatientDOB = ?,
M_PatientDOB_enc = ?,
M_PatientDOB_bidx = ?,
M_PatientM_TitleID = ?,
M_PatientNIP = ?,
M_PatientM_SexID = ?,
M_PatientPrefix = ?,
M_PatientName = ?,
M_PatientName_enc = ?,
M_PatientName_bidx = ?,
M_PatientSuffix = ?,
M_PatientEmail = ?,
M_PatientEmail_enc = ?,
M_PatientHP = ?,
M_PatientHP_enc = ?,
M_PatientHP_bidx = ?,
M_PatientDivisi = ?,
M_PatientPosisi = ?,
M_PatientLocation = ?,
@@ -1159,17 +1237,29 @@ class Preregisterapp extends MY_Controller
WHERE
M_PatientID = ?
";
//echo $sql;
$qry = $this->db_onedev->query($sql, [
$pdob,
$plain_ktp_upd ? 'NNIDN' : '',
$plain_ktp_upd ? 'http://terminology.hl7.org/CodeSystem/v2-0203' : '',
$ktp_mask_upd,
$ktp_mask_upd,
$plain_ktp_upd ? $enc_upd->encrypt($plain_ktp_upd) : null,
$enc_upd->search_bidx($plain_ktp_upd ?? ''),
$this->_mask_dob($dob_str_upd),
$enc_upd->encrypt($dob_str_upd),
$enc_upd->search_bidx($dob_str_upd),
$v['Mcu_PreregisterPatientsM_TitleID'],
$v['Mcu_PreregisterPatientsNIP'],
$v['Mcu_PreregisterPatientsM_SexID'],
$v['Mcu_PreregisterPatientsPatientPrefix'],
$v['Mcu_PreregisterPatientsPatientName'],
$this->_mask_name($plain_name_upd),
$enc_upd->encrypt($plain_name_upd),
$enc_upd->search_bidx($plain_name_upd),
$v['Mcu_PreregisterPatientsPatientSuffix'],
$v['Mcu_PreregisterPatientsEmail'],
$v['Mcu_PreregisterPatientsHp'],
$plain_email_upd ? $this->_mask_email($plain_email_upd) : '',
$plain_email_upd ? $enc_upd->encrypt($plain_email_upd) : null,
$plain_hp_upd ? $this->_mask_phone($plain_hp_upd) : '',
$plain_hp_upd ? $enc_upd->encrypt($plain_hp_upd) : null,
$enc_upd->search_bidx($plain_hp_upd ?? ''),
$v['Mcu_PreregisterPatientsDivisi'],
$v['Mcu_PreregisterPatientsPosisi'],
$v['Mcu_PreregisterPatientsLocation'],
@@ -1725,16 +1815,41 @@ class Preregisterapp extends MY_Controller
$add_where .= " AND M_PatientNIP = '{$nik}'";
}
if ($ktp != '') {
$add_where .= " AND M_PatientIdentifierValue = '{$nik}' AND M_PatientIdentifierCode = 'NNIDN'";
$ktp_toks = $this->ibl_encryptor->query_tokens($ktp);
foreach ($ktp_toks as $ktok) {
$ktok_esc = $this->db_onedev->escape_str($ktok);
$add_where .= " AND JSON_CONTAINS(M_PatientNIK_bidx, '\"$ktok_esc\"')";
}
}
$setup = $prm['setup'];
$join_company = "";
if (isset($prm['company']) && intval($prm['company']) > 0) {
$join_company = "JOIN t_orderheader ON T_OrderHeaderM_PatientID = M_PatientID AND
T_OrderHeaderIsActive = 'Y' AND
$join_company = "JOIN t_orderheader ON T_OrderHeaderM_PatientID = M_PatientID AND
T_OrderHeaderIsActive = 'Y' AND
T_OrderHeaderM_CompanyID = {$prm['company']}";
}
$name_where = '1=1';
if ($name != '') {
$name_toks = $this->ibl_encryptor->query_tokens($name);
$nconds = [];
foreach ($name_toks as $ntok) {
$ntok_esc = $this->db_onedev->escape_str($ntok);
$nconds[] = "JSON_CONTAINS(M_PatientName_bidx, '\"$ntok_esc\"')";
}
if ($nconds) $name_where = implode(' AND ', $nconds);
}
$dob_where = '1=1';
if ($dob != '') {
$dob_toks = $this->ibl_encryptor->query_tokens($dob);
$dconds = [];
foreach ($dob_toks as $dtok) {
$dtok_esc = $this->db_onedev->escape_str($dtok);
$dconds[] = "JSON_CONTAINS(M_PatientDOB_bidx, '\"$dtok_esc\"')";
}
if ($dconds) $dob_where = implode(' AND ', $dconds);
}
$sql = "SELECT COUNT(*) as total
FROM (
SELECT *
@@ -1742,16 +1857,15 @@ class Preregisterapp extends MY_Controller
$join_company
LEFT JOIN m_title ON M_PatientM_TitleID = M_TitleID
WHERE
M_PatientIsActive = 'Y'
M_PatientIsActive = 'Y'
AND M_PatientRegisteredByCompanyID = {$setup['Mgm_McuM_CompanyID']}
AND M_PatientName LIKE CONCAT('%',?,'%') AND
(DATE_FORMAT(M_PatientDOB, '%d-%m-%Y') LIKE '%{$dob}%' and M_PatientDOB IS NOT NULL)
AND ({$name_where})
AND ({$dob_where})
{$add_where}
GROUP BY M_PatientID
) x
";
//echo $sql;
$qry = $this->db_onedev->query($sql, [$name]);
$qry = $this->db_onedev->query($sql);
if (!$qry) {
$message = $this->db_onedev->error();
$message['qry'] = $this->db_onedev->last_query();
@@ -1759,7 +1873,7 @@ class Preregisterapp extends MY_Controller
exit;
}
$countx = $qry->row()->total;
$sql = "SELECT *, DATE_FORMAT(M_PatientDOB, '%d-%m-%Y') as dob_ina,
$sql = "SELECT *, M_PatientDOB as dob_ina,
M_PatientNoReg as Mcu_PreregisterPatientsPID,
M_PatientIdentifierValue as Mcu_PreregisterPatientsKTP,
M_PatientID as Mcu_PreregisterPatientsM_PatientID,
@@ -1781,16 +1895,15 @@ class Preregisterapp extends MY_Controller
LEFT join m_title on M_PatientM_TitleID = M_TitleID
WHERE
M_PatientRegisteredByCompanyID = {$setup['Mgm_McuM_CompanyID']}
AND M_PatientIsActive = 'Y' AND
M_PatientName LIKE CONCAT('%',?,'%') AND
(DATE_FORMAT(M_PatientDOB, '%d-%m-%Y') LIKE '%{$dob}%' and M_PatientDOB IS NOT NULL)
AND M_PatientIsActive = 'Y'
AND ({$name_where})
AND ({$dob_where})
{$add_where}
GROUP BY M_PatientID
LIMIT 10 OFFSET 0
";
//echo $sql;
$qry = $this->db_onedev->query($sql, [$name]);
$qry = $this->db_onedev->query($sql);
if (!$qry) {
$message = $this->db_onedev->error();
$message['qry'] = $this->db_onedev->last_query();

View File

@@ -440,59 +440,63 @@ class Rv_patient extends MY_Controller
foreach ($rows['groups'] as $k => $v) {
$ready_print = $v['ready_print'];
$gn = $v['group_name'];
// MAPPING GROUP NAME KE REPORT CODE
$report_codes = $this->get_report_codes_by_group($gn);
if ($report_codes) {
// Gunakan database untuk ambil report name
$rpt = $this->get_report_name_from_db($report_codes['P'], $ready_print);
$e_rpt = $this->get_report_name_from_db($report_codes['E'], $ready_print);
$rptqrcode = isset($report_codes['Q']) ? $this->get_report_name_from_db($report_codes['Q'], $ready_print) : '';
// Jika QR tidak ada, gunakan P
if (empty($rptqrcode)) {
$rptqrcode = $rpt;
}
$rpt_code = $ready_print == 'Y' ? $report_codes['P'] : ($report_codes['NP'] ?? $report_codes['P']);
$e_rpt_code = $ready_print == 'Y' ? ($report_codes['E'] ?? $report_codes['P']) : ($report_codes['NE'] ?? $report_codes['NP'] ?? $report_codes['E'] ?? $report_codes['P']);
$rptq_code = $ready_print == 'Y' ? ($report_codes['Q'] ?? $report_codes['P']) : ($report_codes['NQ'] ?? $report_codes['NP'] ?? $report_codes['P']);
$rpt = $this->get_report_name_from_code($rpt_code);
$e_rpt = $this->get_report_name_from_code($e_rpt_code);
$rptqrcode = $this->get_report_name_from_code($rptq_code);
if (empty($rptqrcode)) $rptqrcode = $rpt;
} else {
// FALLBACK untuk group yang belum ada di database
$rpt = $this->get_fallback_report($gn, 'P', $ready_print);
$e_rpt = $this->get_fallback_report($gn, 'E', $ready_print);
$rpt_code = $e_rpt_code = '';
$rpt = $this->get_fallback_report($gn, 'P', $ready_print);
$e_rpt = $this->get_fallback_report($gn, 'E', $ready_print);
$rptqrcode = $this->get_fallback_report($gn, 'Q', $ready_print);
if (empty($rptqrcode)) $rptqrcode = $rpt;
}
// LOGIC KHUSUS MIKRO
if ($gn == 'Mikro') {
$sql = "SELECT T_OrderDetailResult as result
FROM t_orderdetail
$sql = "SELECT T_OrderDetailResult as result
FROM t_orderdetail
JOIN t_test ON T_OrderDetailT_TestID = T_TestID AND T_TestIsResult = 'Y'
JOIN group_resultdetail ON Group_ResultDetailT_TestID = T_OrderDetailT_TestID AND Group_ResultDetailIsActive = 'Y'
JOIN group_result ON Group_ResultDetailGroup_ResultID = Group_ResultID AND Group_ResultFlagNonLab = 'N' AND
JOIN group_result ON Group_ResultDetailGroup_ResultID = Group_ResultID AND Group_ResultFlagNonLab = 'N' AND
Group_ResultName = 'Mikro'
WHERE T_OrderDetailID = {$v['id']} AND T_OrderDetailIsActive = 'Y' LIMIT 1";
$xresult = $this->db_smartone->query($sql)->row()->result;
if ($xresult != 'Terlampir') {
$rpt = $this->get_report_name_from_db('LAB-RESULT-P-01', $ready_print);
$e_rpt = $this->get_report_name_from_db('LAB-RESULT-E-01', $ready_print);
$rpt_code = $ready_print == 'Y' ? 'LAB-RESULT-P-01' : 'LAB-RESULT-NP-01';
$e_rpt_code = $ready_print == 'Y' ? 'LAB-RESULT-P-02' : 'LAB-RESULT-NP-02';
$rpt = $this->get_report_name_from_code($rpt_code);
$e_rpt = $this->get_report_name_from_code($e_rpt_code);
}
if ($xresult == 'Terlampir' && $exist_lab == 'N') {
$rows['groups'][$k]['group_name'] = 'Lampiran Mikro';
$new_group = $rows['groups'][$k];
$new_group['group_name'] = 'Mikro';
$new_group['rpt'] = $this->get_report_name_from_db('LAB-RESULT-P-01', 'Y');
$new_group['e_rpt'] = $this->get_report_name_from_db('LAB-RESULT-E-01', 'Y');
$new_group['rptqrcode'] = $new_group['rpt'];
$new_group['rpt_code'] = 'LAB-RESULT-P-01';
$new_group['e_rpt_code'] = 'LAB-RESULT-P-02';
$new_group['rpt'] = $this->get_report_name_from_code('LAB-RESULT-P-01');
$new_group['e_rpt'] = $this->get_report_name_from_code('LAB-RESULT-P-02');
$new_group['rptqrcode'] = $new_group['rpt'];
array_push($rows['groups'], $new_group);
}
}
$rows['groups'][$k]['rpt'] = $rpt;
$rows['groups'][$k]['e_rpt'] = $e_rpt;
$rows['groups'][$k]['rptqrcode'] = $rptqrcode;
$rows['groups'][$k]['rpt'] = $rpt;
$rows['groups'][$k]['e_rpt'] = $e_rpt;
$rows['groups'][$k]['rptqrcode'] = $rptqrcode;
$rows['groups'][$k]['rpt_code'] = $rpt_code;
$rows['groups'][$k]['e_rpt_code'] = $e_rpt_code;
}
$rows['groups'][0]['selected'] = 'Y';
@@ -529,43 +533,55 @@ class Rv_patient extends MY_Controller
}
private function get_report_codes_by_group($group_name)
{
$mapping = [
'LAB' => ['P' => 'LAB-RESULT-P-01', 'E' => 'LAB-RESULT-E-01', 'Q' => 'LAB-RESULT-Q-01'],
'LAB_EN' => ['P' => 'LAB-RESULT-EN-P-01', 'E' => 'LAB-RESULT-EN-E-01'],
'Mikro_EN' => ['P' => 'LAB-RESULT-EN-P-01', 'E' => 'LAB-RESULT-EN-E-01'],
'FNA' => ['P' => 'FNA-P-01', 'E' => 'FNA-E-01'],
'Patologi Anatomi' => ['P' => 'PA-P-01', 'E' => 'PA-E-01'],
'Papsmear' => ['P' => 'PAP-P-01', 'E' => 'PAP-E-01'],
'Pap Smear (Liquid C Prep)' => ['P' => 'LCP-P-01', 'E' => 'LCP-E-01', 'Q' => 'LCP-Q-01'],
'Pap Smear (Liquid C Prep)_EN' => ['P' => 'LCP-P-01', 'E' => 'LCP-E-01', 'Q' => 'LCP-Q-01'],
'Papsmear_EN' => ['P' => 'LCP-P-01', 'E' => 'LCP-E-01', 'Q' => 'LCP-Q-01']
];
return isset($mapping[$group_name]) ? $mapping[$group_name] : null;
}
{
// P = siap cetak, NP = belum siap cetak, E = email siap, NE = email belum siap
$mapping = [
'LAB' => ['P' => 'LAB-RESULT-P-01', 'NP' => 'LAB-RESULT-NP-01', 'E' => 'LAB-RESULT-P-02', 'NE' => 'LAB-RESULT-NP-02'],
'LAB_EN' => ['P' => 'LABEN-RESULT-P-01', 'NP' => 'LABEN-RESULT-NP-01', 'E' => 'LABEN-RESULT-P-02'],
'Mikro' => ['P' => 'MIKRO-RESULT-P-01', 'NP' => 'MIKRO-RESULT-NP-01', 'E' => 'MIKRO-RESULT-P-02'],
'Mikro_EN' => ['P' => 'MIKROEN-RESULT-P-01', 'NP' => 'MIKROEN-RESULT-NP-01', 'E' => 'MIKROEN-RESULT-P-02'],
'FNA' => ['P' => 'FNA-RESULT-P-01', 'NP' => 'FNA-RESULT-NP-01', 'E' => 'FNA-RESULT-P-02'],
'Patologi Anatomi' => ['P' => 'PA-RESULT-P-01', 'NP' => 'PA-RESULT-NP-01', 'E' => 'PA-RESULT-P-02'],
'Papsmear' => ['P' => 'PAP-RESULT-P-01', 'NP' => 'PAP-RESULT-NP-01', 'E' => 'PAP-RESULT-P-02'],
'Pap Smear (Liquid C Prep)' => ['P' => 'PAPLCP-RESULT-P-01', 'NP' => 'PAPLCP-RESULT-NP-01', 'E' => 'PAPLCP-RESULT-P-02'],
'Pap Smear (Liquid C Prep)_EN' => ['P' => 'PAPLEN-RESULT-P-01', 'NP' => 'PAPLEN-RESULT-NP-01', 'E' => 'PAPLEN-RESULT-P-02'],
'Papsmear_EN' => ['P' => 'PAPLEN-RESULT-P-01', 'NP' => 'PAPLEN-RESULT-NP-01', 'E' => 'PAPLEN-RESULT-P-02'],
'Preparasi Sperma' => ['P' => 'PS-RESULT-P-01', 'NP' => 'PS-RESULT-NP-01', 'E' => 'PS-RESULT-P-02'],
'dfi' => ['P' => 'DFI-RESULT-P-01', 'NP' => 'DFI-RESULT-NP-01', 'E' => 'DFI-RESULT-P-02'],
'DFI' => ['P' => 'DFI-RESULT-P-01', 'NP' => 'DFI-RESULT-NP-01', 'E' => 'DFI-RESULT-P-02'],
'Cytologi' => ['P' => 'CT-RESULT-P-01', 'NP' => 'CT-RESULT-NP-01', 'E' => 'CT-RESULT-P-02'],
];
private function get_report_name_from_db($report_code, $ready_print = 'Y')
{
if (empty($report_code)) return '';
$sql = "SELECT Print_TransactionUrl FROM print_transaction WHERE Print_TransactionCode = ? LIMIT 1";
$row = $this->db_smartone->query($sql, [$report_code])->row();
if (!$row) return '';
// Extract report name from URL
$url = $row->Print_TransactionUrl;
preg_match('/\/([^\/]+)\.rptdesign/', $url, $matches);
$report_name = isset($matches[1]) ? $matches[1] : '';
// Tambahkan suffix jika belum ready print
if ($ready_print != 'Y' && !empty($report_name)) {
$report_name .= '_not_print';
}
return $report_name;
}
return $mapping[$group_name] ?? null;
}
private function get_report_name_from_code($report_code)
{
if (empty($report_code)) return '';
$row = $this->db_smartone->query(
"SELECT Print_TransactionUrl FROM print_transaction WHERE Print_TransactionCode = ? LIMIT 1",
[$report_code]
)->row();
if (!$row) return '';
preg_match('/\/([^\/]+)\.rptdesign/', $row->Print_TransactionUrl, $matches);
return $matches[1] ?? '';
}
private function get_report_name_from_db($report_code, $ready_print = 'Y')
{
if (empty($report_code)) return '';
$row = $this->db_smartone->query(
"SELECT Print_TransactionUrl FROM print_transaction WHERE Print_TransactionCode = ? LIMIT 1",
[$report_code]
)->row();
if (!$row) return '';
preg_match('/\/([^\/]+)\.rptdesign/', $row->Print_TransactionUrl, $matches);
$report_name = $matches[1] ?? '';
if ($ready_print != 'Y' && !empty($report_name)) {
$report_name .= '_not_print';
}
return $report_name;
}
private function get_fallback_report($group_name, $type, $ready_print)
{

View File

@@ -99,17 +99,17 @@ class Rv_patient extends MY_Controller
);
exit;
}
$sql = "INSERT INTO mcu_resume_results(
Mcu_ResumeResultsType,
Mcu_ResumeResultsT_OrderHeaderID,
Mcu_ResumeResultsGroupResultID,
Mcu_ResumeResultsT_TestID,
Mcu_ResumeResultsName,
Mcu_ResumeResultsJSON,
Mcu_ResumeResultsCreated,
Mcu_ResumeResultsUserID)
VALUES('KHUSUS',?,?,?,?,?,NOW(),?)";
$qry = $this->db_smartone->query($sql, array($order_id, $groupResultID, 0, $groupResultName, $j_data_result_lab, $userID));
$sql = "INSERT INTO mcu_resume_results(
Mcu_ResumeResultsType,
Mcu_ResumeResultsT_OrderHeaderID,
Mcu_ResumeResultsGroupResultID,
Mcu_ResumeResultsT_TestID,
Mcu_ResumeResultsName,
Mcu_ResumeResultsJSON,
Mcu_ResumeResultsCreated,
Mcu_ResumeResultsUserID)
VALUES('KHUSUS',?,?,?,?,?,NOW(),?)";
$qry = $this->db_smartone->query($sql, array($order_id, $groupResultID, 0, $groupResultName, $j_data_result_lab, $userID));
if (!$qry) {
echo json_encode(
array("status" => "ERR", "message" => "Error: insert mcu results")
@@ -183,7 +183,8 @@ class Rv_patient extends MY_Controller
$sql_get = "SELECT T_OrderHeaderGroupResultID,
T_OrderHeaderGroupResultGroup_ResultID,
T_OrderHeaderGroupResultT_TestID,
T_OrderHeaderGroupResultGroup_ResultName
T_OrderHeaderGroupResultGroup_ResultName,
Group_ResultName
FROM t_orderheader_group_result
JOIN group_result ON T_OrderHeaderGroupResultGroup_ResultID = Group_ResultID
AND Group_ResultFlagNonLab = 'N'
@@ -196,25 +197,12 @@ class Rv_patient extends MY_Controller
}
$data = $qry_get->result_array();
$sql_url = "SELECT Print_TransactionID,
Print_TransactionType,
Print_TransactionCode,
Print_TransactionName,
Print_TransactionUrl,
Print_TransactionUrlWatermark,
Print_TransactionUrlEletronic,
Print_TransactionParams
FROM print_transaction
WHERE Print_TransactionCode = 'LAB-RESULT-P-01'
LIMIT 1";
$qry_url = $this->db_smartone->query($sql_url);
if (!$qry_url) {
$this->sys_error_db('error print_transaction', $this->db_smartone);
exit;
}
$rst_url = $qry_url->row_array();
$template_url = $rst_url['Print_TransactionUrlWatermark'];
$template_url_electronic = isset($rst_url['Print_TransactionUrlEletronic']) ? $rst_url['Print_TransactionUrlEletronic'] : '';
// mapping test kode print
$map = [
'LAB' => 'LAB-RESULT-P-01',
'Papsmear' => 'PAP-P-01',
'FNA' => 'FNA-P-01'
];
$sql_branch = "SELECT M_BranchID,
M_BranchCode,
@@ -228,42 +216,8 @@ class Rv_patient extends MY_Controller
$this->sys_error_db('error m_branch', $this->db_smartone);
exit;
}
$branch = $qry_branch->row_array();
$base = "http://localhost/";
// Tambah base_url di depan
$full_url = $base . ltrim($template_url, '/');
// Ganti nama report jadi _watermark
$full_url = str_replace(
'rpt_test.rptdesign',
'rpt_test_watermark.rptdesign',
$full_url
);
// Ganti parameter
$full_url = str_replace(
['PUsername', 'PT_OrderHeaderID', 'TS'],
[
trim($this->sys_user['M_UserUsername']),
$order_id,
time()
],
$full_url
);
$full_url_electronic = '';
if ($template_url_electronic !== '') {
$full_url_electronic = $base . ltrim($template_url_electronic, '/');
$full_url_electronic = str_replace(
['PUsername', 'PT_OrderHeaderID', 'TS'],
[
trim($this->sys_user['M_UserUsername']),
$order_id,
time()
],
$full_url_electronic
);
}
$branch = $qry_branch->row_array();
$base = "http://localhost/";
// ambil endpoint URL dari DB
$sql_url = "SELECT QR_ReportEndpointID,
@@ -288,6 +242,65 @@ class Rv_patient extends MY_Controller
foreach ($data as $key => $value) {
$group_result_name = $value['Group_ResultName'];
// kalau tidak ada di mapping skip
if (!isset($map[$group_result_name])) {
continue;
}
$printCode = $map[$group_result_name];
// ambil URL print
$sql_url = "SELECT Print_TransactionUrlWatermark, Print_TransactionUrlEletronic
FROM print_transaction
WHERE Print_TransactionCode = ?
LIMIT 1";
$qry_url = $this->db_onedev->query($sql_url, [$printCode]);
if (!$qry_url) {
$this->sys_error_db('error print_transaction', $this->db_onedev);
exit;
}
$rst_url = $qry_url->row_array();
$template_url = $rst_url['Print_TransactionUrlWatermark'];
$template_url_electronic = isset($rst_url['Print_TransactionUrlEletronic']) ? $rst_url['Print_TransactionUrlEletronic'] : '';
// Tambah base_url di depan
$full_url = $base . ltrim($template_url, '/');
// ubah semua report jadi versi watermark
$full_url = str_replace(
'.rptdesign',
'_watermark.rptdesign',
$full_url
);
// Ganti parameter
$full_url = str_replace(
['PUsername', 'PT_OrderHeaderID', 'TS'],
[
trim($this->sys_user['M_UserUsername']),
$order_id,
time()
],
$full_url
);
$full_url_electronic = '';
if ($template_url_electronic !== '') {
$full_url_electronic = $base . ltrim($template_url_electronic, '/');
$full_url_electronic = str_replace(
['PUsername', 'PT_OrderHeaderID', 'TS'],
[
trim($this->sys_user['M_UserUsername']),
$order_id,
time()
],
$full_url_electronic
);
}
// cek sudah ada atau belum
$sql_check = "SELECT QR_PrintOutID, QR_PrintOutUploadStatus
FROM qr_printout
@@ -308,19 +321,19 @@ class Rv_patient extends MY_Controller
$params = [
'orderHeaderID' => $order_id,
'groupResultID' => $value['T_OrderHeaderGroupResultGroup_ResultID'],
'testID' => $value['T_OrderHeaderGroupResultT_TestID'],
'groupResultName' => $value['T_OrderHeaderGroupResultGroup_ResultName'],
'verifyBaseURL' => $verify_url,
'QR_PrintOutReportURL' => $full_url,
'QR_PrintOutReportURLElectronic' => $full_url_electronic,
'createdByUserID' => $userID
];
'testID' => $value['T_OrderHeaderGroupResultT_TestID'],
'groupResultName' => $value['T_OrderHeaderGroupResultGroup_ResultName'],
'verifyBaseURL' => $verify_url,
'QR_PrintOutReportURL' => $full_url,
'QR_PrintOutReportURLElectronic' => $full_url_electronic,
'createdByUserID' => $userID
];
$this->generateqrreport->saveQRPrintout($params);
}
}
echo $this->sys_ok(array("status" => "OK"));
$this->sys_ok(array("status" => "OK"));
}
/**
@@ -369,17 +382,17 @@ class Rv_patient extends MY_Controller
// Insert new record
$j_data_result = json_encode($rows_result);
$sql = "INSERT INTO mcu_resume_results(
Mcu_ResumeResultsType,
Mcu_ResumeResultsT_OrderHeaderID,
Mcu_ResumeResultsGroupResultID,
Mcu_ResumeResultsT_TestID,
Mcu_ResumeResultsName,
Mcu_ResumeResultsJSON,
Mcu_ResumeResultsCreated,
Mcu_ResumeResultsUserID)
VALUES('KHUSUS',?,?,?,?,?,NOW(),?)";
$qry = $this->db_smartone->query($sql, array($order_id, $groupResultID, 0, $groupResultName, $j_data_result, $userID));
$sql = "INSERT INTO mcu_resume_results(
Mcu_ResumeResultsType,
Mcu_ResumeResultsT_OrderHeaderID,
Mcu_ResumeResultsGroupResultID,
Mcu_ResumeResultsT_TestID,
Mcu_ResumeResultsName,
Mcu_ResumeResultsJSON,
Mcu_ResumeResultsCreated,
Mcu_ResumeResultsUserID)
VALUES('KHUSUS',?,?,?,?,?,NOW(),?)";
$qry = $this->db_smartone->query($sql, array($order_id, $groupResultID, 0, $groupResultName, $j_data_result, $userID));
if (!$qry) {
echo json_encode(
array("status" => "ERR", "message" => "Error: insert into mcu result 2")

View File

@@ -208,7 +208,7 @@ class Samplingcall extends MY_Controller
IFNULL(M_PatientPhotoThumb,'') as M_PatientPhotoThumb,
M_SexName as M_SexName,
M_TitleName as M_TitleName,
M_PatientName_enc, M_PatientDOB_enc, M_TitleName,
M_PatientName_enc, M_PatientDOB_enc,
M_CompanyName,
fn_sampling_queue_status_name(T_OrderHeaderID,T_SampleStationID) as status,
M_PatientDOB as patient_dob_raw,
@@ -570,7 +570,7 @@ class Samplingcall extends MY_Controller
$userid = $prm['staff']['userid'];
}
$sql = "SELECT T_OrderHeaderQueue AS queueNumber ,
M_LocationID AS locationID,
@@ -586,7 +586,7 @@ class Samplingcall extends MY_Controller
$splitedLocationName = explode(" ", $locationName);
$locationName = $splitedLocationName[0];
if ($prm['act'] == 'call') {
$sql = "SELECT T_SamplingQueueLastStatusID, T_SamplingQueueStatusName, T_SampleStationName, T_SampleStationID, T_SampleStationIsNonLab
@@ -1010,18 +1010,18 @@ class Samplingcall extends MY_Controller
$rows = $this->db_onedev->query($query);
}
if ($status_call['status'] == 'NOTCALL') {
$rst_data = $status_call;
}
if ($prm['act'] == 'skip' || $status_call['status'] == 'NOTCALL') {
$skip_time = date('Y-m-d H:i:s', strtotime($prm['skiptime'])+10);
$skip_time = date('Y-m-d H:i:s', strtotime($prm['skiptime']) + 10);
$sql = "UPDATE antrian_samplestation SET AntrianSampleStationIsActive = 'N'
WHERE
AntrianSampleStationT_OrderLocationID = ?";
$query = $this->db_onedev->query($sql,array($prm['orderlocationid']));
$query = $this->db_onedev->query($sql, array($prm['orderlocationid']));
/* start dipaggil 3 kali skpi ururtan jd ke bawah */
/*$sql = "SELECT COUNT(*) as x_count
FROM antrian_samplestation
@@ -1045,8 +1045,7 @@ class Samplingcall extends MY_Controller
VALUES(
?,?,?,NOW()
)";
$query = $this->db_onedev->query($sql,array($prm['orderlocationid'],$skip_time,$userid));
$query = $this->db_onedev->query($sql, array($prm['orderlocationid'], $skip_time, $userid));
}
if (intval($next_status) == 1) {

View File

@@ -35,6 +35,7 @@ class Preregister extends MY_Controller
private function _mask_short($v) { if (!$v) return $v; $v=trim($v); $l=mb_strlen($v,'UTF-8'); if($l<=2) return '***'; return mb_substr($v,0,2,'UTF-8').'***'; }
private function _mask_id($v) { if (!$v) return $v; $v=trim($v); $l=strlen($v); if($l<=4) return '****'; return substr($v,0,4).str_repeat('*',max(3,$l-6)).($l>6?substr($v,-2):''); }
private function _mask_address($v) { if (!$v) return $v; $v=trim($v); $l=mb_strlen($v,'UTF-8'); if($l<=5) return '***'; return mb_substr($v,0,5,'UTF-8').'***'; }
private function _mask_dob($v) { if (!$v) return $v; $p=explode('-',$v); return (count($p)===3) ? '**-**-'.$p[2] : '****-**-**'; }
public function index()
{
@@ -230,15 +231,16 @@ class Preregister extends MY_Controller
if ($exist_r) {
$enc_csv = $this->ibl_encryptor;
$patient_id = $exist_r["M_PatientID"];
$v['NAMA'] = addslashes($exist_r["M_PatientName"]);
$v['NAMA'] = $enc_csv->decrypt($exist_r['M_PatientName_enc'] ?? '') ?: $exist_r["M_PatientName"];
$pdob = date('Y-m-d', strtotime($exist_r['M_PatientDOB']));
$title_id = $exist_r["M_PatientM_TitleID"];
$sex_id = $exist_r["M_PatientM_SexID"];
$religion_id = $exist_r["M_PatientReligionCode"];
$v['NIK'] = $v['NIK'] ? $v['NIK'] : $exist_r["M_PatientNIK"];
$v['EMAIL'] = $v['EMAIL'] ? $v['EMAIL'] : $exist_r["M_PatientEmail"];
$v['HP'] = $v['HP'] ? $v['HP'] : $exist_r["M_PatientHP"];
$v['KTP'] = $v['KTP'] ? $v['KTP'] : ($enc_csv->decrypt($exist_r['M_PatientIDNumber_enc'] ?? '') ?: '');
$v['EMAIL'] = $v['EMAIL'] ? $v['EMAIL'] : ($enc_csv->decrypt($exist_r['M_PatientEmail_enc'] ?? '') ?: '');
$v['HP'] = $v['HP'] ? $v['HP'] : ($enc_csv->decrypt($exist_r['M_PatientHP_enc'] ?? '') ?: '');
$v['JOB'] = $v['JOB'] ? addslashes($v['JOB']) : addslashes($exist_r["M_PatientJob"]);
$v['POSISI'] = $v['POSISI'] ? addslashes($v['POSISI']) : addslashes($exist_r["M_PatientPosisi"]);
$v['DIVISI'] = $v['DIVISI'] ? addslashes($v['DIVISI']) : addslashes($exist_r["M_PatientDivisi"]);
@@ -336,6 +338,7 @@ class Preregister extends MY_Controller
$m_nip = $this->_mask_id($v['NIP']);
$m_email = $this->_mask_email($v['EMAIL']);
$m_hp = $this->_mask_phone($v['HP']);
$m_dob = $this->_mask_dob(date('d-m-Y', strtotime($pdob)));
$query = " INSERT INTO mcu_preregister_patients (
Mcu_PreregisterPatientsMgm_McuID,
Mcu_PreregisterPatientsCompanyNumber,
@@ -367,7 +370,7 @@ class Preregister extends MY_Controller
'{$title_id}',
'{$m_nama}',
{$sex_id},
'{$pdob}',
'{$m_dob}',
'{$v['JOB']}',
'{$m_email}',
'{$m_hp}',
@@ -395,26 +398,29 @@ class Preregister extends MY_Controller
$preregister_patient_id = intval($last_id_x);
if ($patient_id == 0) {
$sql = "SELECT *
FROM m_patient
WHERE
M_PatientName = '{$v['NAMA']}' AND
M_PatientDOB = '{$pdob}' AND
M_PatientNIP = '{$v['NIP']}' AND
M_PatientIsActive = 'Y' LIMIT 1";
$query = $this->db->query($sql);
$enc_csv = $this->ibl_encryptor;
$name_toks = $enc_csv->query_tokens($v['NAMA']);
$name_conds = [];
foreach ($name_toks as $tok) {
$tok_esc = $this->db->escape_str($tok);
$name_conds[] = "JSON_CONTAINS(M_PatientName_bidx, '\"$tok_esc\"')";
}
$name_where = $name_conds ? implode(' AND ', $name_conds) : '0';
$sql = "SELECT M_PatientID FROM m_patient
WHERE ({$name_where})
AND M_PatientDOB = ?
AND M_PatientNIP = ?
AND M_PatientIsActive = 'Y' LIMIT 1";
$query = $this->db->query($sql, [$pdob, $v['NIP']]);
if (!$query) {
$last_qry = $this->db->last_query();
$this->db->trans_rollback();
$this->sys_error("select m_patient : " . $last_qry);
$this->sys_error("select m_patient : " . $this->db->last_query());
exit;
}
$exist_r = $query->row_array();
if ($exist_r) {
$patient_id = $exist_r["M_PatientID"];
$patient_id = $exist_r["M_PatientID"];
}
//echo $sql;
}
$sql_cor = "SELECT *
@@ -456,51 +462,41 @@ class Preregister extends MY_Controller
//echo $patient_id;
if ($patient_id == 0) {
//echo 'insert new patient';
//$pdob = date('Y-m-d',strtotime($prm['Mcu_PreregisterDetailsDOB']));
$sql = "INSERT INTO m_patient (
M_PatientRegisteredByCompanyID,
M_PatientNoReg,
M_PatientName,
M_PatientM_SexID,
M_PatientM_TitleID,
M_PatientDOB,
M_PatientIdentifierValue,
M_PatientNIP,
M_PatientJob,
M_PatientPosisi,
M_PatientDivisi,
M_PatientLocation,
M_PatientDepartement,
M_PatientHP,
M_PatientEmail,
M_PatientCreatedUserID
)
VALUES(
'{$company_id}',
`fn_numbering_ibl`('PA'),
'{$v["NAMA"]}',
{$sex_id},
{$title_id},
'{$pdob}',
'{$v['KTP']}',
'{$v['NIP']}',
'{$v['JOB']}',
'{$v['POSISI']}',
'{$v['DIVISI']}',
'{$v['LOKASI']}',
'{$v['DEPARTEMENT']}',
'{$v['HP']}',
'{$v['EMAIL']}',
'{$userid}'
)";
// echo $sql;
// exit;
$query = $this->db->query($sql);
$enc_csv = $this->ibl_encryptor;
$dob_str_csv = date('d-m-Y', strtotime($pdob));
$noreg_row = $this->db->query("SELECT `fn_numbering_ibl`('PA') AS noreg")->row_array();
$ins_ptn = [
'M_PatientRegisteredByCompanyID' => $company_id,
'M_PatientNoReg' => $noreg_row['noreg'] ?? '',
'M_PatientName' => $this->_mask_name($v["NAMA"]),
'M_PatientName_enc' => $enc_csv->encrypt($v["NAMA"]),
'M_PatientName_bidx' => $enc_csv->search_bidx($v["NAMA"]),
'M_PatientM_SexID' => $sex_id,
'M_PatientM_TitleID' => $title_id,
'M_PatientDOB' => $this->_mask_dob($dob_str_csv),
'M_PatientDOB_enc' => $enc_csv->encrypt($dob_str_csv),
'M_PatientDOB_bidx' => $enc_csv->search_bidx($dob_str_csv),
'M_PatientM_IdTypeID' => $v['KTP'] ? 1 : 0,
'M_PatientIDNumber' => $v['KTP'] ? $this->_mask_id($v['KTP']) : null,
'M_PatientIDNumber_enc' => $v['KTP'] ? $enc_csv->encrypt($v['KTP']) : null,
'M_PatientNIK_bidx' => $enc_csv->search_bidx($v['KTP'] ?? ''),
'M_PatientNIP' => $v['NIP'],
'M_PatientJob' => $v['JOB'],
'M_PatientPosisi' => $v['POSISI'],
'M_PatientDivisi' => $v['DIVISI'],
'M_PatientLocation' => $v['LOKASI'],
'M_PatientDepartement' => $v['DEPARTEMENT'],
'M_PatientHP' => $this->_mask_phone($v['HP']),
'M_PatientHP_enc' => $enc_csv->encrypt($v['HP']),
'M_PatientHP_bidx' => $enc_csv->search_bidx($v['HP']),
'M_PatientEmail' => $this->_mask_email($v['EMAIL']),
'M_PatientEmail_enc' => $enc_csv->encrypt($v['EMAIL']),
'M_PatientCreatedUserID'=> $userid,
];
$query = $this->db->insert('m_patient', $ins_ptn);
if (!$query) {
$last_qry = $this->db->last_query();
$this->db->trans_rollback();
$this->sys_error("insert m_patient : " . $last_qry);
$this->sys_error("insert m_patient : " . $this->db->last_query());
exit;
}
$patient_id = $this->db->insert_id();
@@ -551,10 +547,16 @@ class Preregister extends MY_Controller
if ($prm['companyID'] != '')
$data_update_patient['M_PatientRegisteredByCompanyID'] = $prm['companyID'];
if ($v['EMAIL'] != '')
$data_update_patient['M_PatientEmail'] = $v['EMAIL'];
if ($v['HP'] != '')
$data_update_patient['M_PatientHP'] = $v['HP'];
$enc_csv = $this->ibl_encryptor;
if ($v['EMAIL'] != '') {
$data_update_patient['M_PatientEmail'] = $this->_mask_email($v['EMAIL']);
$data_update_patient['M_PatientEmail_enc'] = $enc_csv->encrypt($v['EMAIL']);
}
if ($v['HP'] != '') {
$data_update_patient['M_PatientHP'] = $this->_mask_phone($v['HP']);
$data_update_patient['M_PatientHP_enc'] = $enc_csv->encrypt($v['HP']);
$data_update_patient['M_PatientHP_bidx'] = $enc_csv->search_bidx($v['HP']);
}
if ($v['JOB'] != '')
$data_update_patient['M_PatientJob'] = $v['JOB'];
if ($v['POSISI'] != '')

View File

@@ -41,7 +41,6 @@ class Birt_proxy extends MY_Controller
$report_code = trim($prm['report_code'] ?? $prm['code_report'] ?? $prm['code'] ?? '');
$order_id = intval($prm['PT_OrderHeaderID'] ?? $prm['order_id'] ?? 0);
$payment_id = intval($prm['PPaymentID'] ?? $prm['payment_id'] ?? 0);
$username = trim($prm['PUsername'] ?? ($this->sys_user['M_StaffName'] ?? $this->sys_user['M_UserUsername'] ?? $this->sys_user['userName'] ?? 'system'));
if (!$report_code) {
$this->sys_error('report_code wajib diisi');
@@ -66,27 +65,17 @@ class Birt_proxy extends MY_Controller
if ($patient_name === '') {
$patient_name = $this->_resolve_patient_name_by_order($order_id);
}
if ($patient_name === '') {
$patient_name = $this->_resolve_patient_name_from_enc_by_order($order_id);
}
$row = $this->db_onedev->query(
"SELECT Print_TransactionUrl FROM print_transaction WHERE Print_TransactionCode = ? LIMIT 1",
[$report_code]
)->row_array();
if (!$row) {
$url = $this->_build_birt_url_by_code($report_code, $order_id, $payment_id, $patient_name);
if ($url === false) {
$this->_delete_cache($cache_id);
$this->sys_error("Report code tidak ditemukan: {$report_code}");
return;
}
$tm = round(microtime(true) * 1000);
$url = $row['Print_TransactionUrl'];
$is_internal_app_url = $this->_is_internal_app_url($url);
$url = str_replace('PT_OrderHeaderID', $order_id, $url);
$url = str_replace('PPaymentID', $payment_id, $url);
$url = str_replace('PAn', $this->_format_report_string_param($patient_name, $is_internal_app_url), $url);
$url = str_replace('PUsername', $this->_format_report_string_param($username, $is_internal_app_url), $url);
$url = str_replace('TS', $tm, $url);
$full_url = $this->_resolve_fetch_url($url);
$context = stream_context_create([
'http' => [
@@ -122,38 +111,37 @@ class Birt_proxy extends MY_Controller
$prm = $this->sys_input;
$report_code = $prm['report_code'] ?? '';
$order_id = intval($prm['PT_OrderHeaderID'] ?? 0);
$username = $prm['PUsername'] ?? ($this->sys_user['userName'] ?? 'system');
$tm = round(microtime(true) * 1000);
$payment_id = intval($prm['PPaymentID'] ?? 0);
if (!$report_code) {
$this->sys_error('report_code wajib diisi');
return;
}
// 1. Ambil URL template dari print_transaction
$row = $this->db_onedev->query(
"SELECT Print_TransactionUrl FROM print_transaction WHERE Print_TransactionCode = ? LIMIT 1",
[$report_code]
)->row_array();
if ($payment_id <= 0 && $order_id > 0) {
$payment_id = $this->_resolve_payment_id_by_order($order_id);
}
if (!$row) {
$patient_name = '';
if ($order_id > 0) {
$cache_id = $this->_populate_cache($order_id);
$patient_name = $this->_resolve_patient_name_by_cache($cache_id);
if ($patient_name === '') {
$patient_name = $this->_resolve_patient_name_by_order($order_id);
}
if ($patient_name === '') {
$patient_name = $this->_resolve_patient_name_from_enc_by_order($order_id);
}
} else {
$cache_id = null;
}
$url = $this->_build_birt_url_by_code($report_code, $order_id, $payment_id, $patient_name);
if ($url === false) {
$this->sys_error("Report code tidak ditemukan: {$report_code}");
return;
}
$url = $row['Print_TransactionUrl'];
$is_internal_app_url = $this->_is_internal_app_url($url);
$url = str_replace('PT_OrderHeaderID', $order_id, $url);
$url = str_replace('PUsername', $this->_format_report_string_param($username, $is_internal_app_url), $url);
$url = str_replace('TS', $tm, $url);
// 2. Decrypt patient PII dan populate cache
$cache_id = null;
if ($order_id > 0) {
$cache_id = $this->_populate_cache($order_id);
}
// 3. Build full URL sesuai target endpoint dan fetch PDF
$full_url = $this->_resolve_fetch_url($url);
$context = stream_context_create([
@@ -165,7 +153,6 @@ class Birt_proxy extends MY_Controller
$pdf = @file_get_contents($full_url, false, $context);
// 4. Hapus cache
if ($cache_id) {
$this->db_onedev->query(
"DELETE FROM patient_print_cache WHERE ppc_id = ?",
@@ -178,7 +165,6 @@ class Birt_proxy extends MY_Controller
return;
}
// 5. Stream PDF ke frontend
$filename = $report_code . '_' . $order_id . '_' . date('Ymd') . '.pdf';
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename="' . $filename . '"');
@@ -199,28 +185,22 @@ class Birt_proxy extends MY_Controller
$prm = $this->sys_input;
$report_code = $prm['report_code'] ?? '';
$order_id = intval($prm['PT_OrderHeaderID'] ?? 0);
$username = $prm['PUsername'] ?? ($this->sys_user['userName'] ?? 'system');
$tm = round(microtime(true) * 1000);
$row = $this->db_onedev->query(
"SELECT Print_TransactionUrl FROM print_transaction WHERE Print_TransactionCode = ? LIMIT 1",
[$report_code]
)->row_array();
if (!$row) {
$this->sys_error("Report code tidak ditemukan: {$report_code}");
return;
$patient_name = '';
if ($order_id > 0) {
$cache_id = $this->_populate_cache($order_id);
$patient_name = $this->_resolve_patient_name_by_cache($cache_id);
if ($patient_name === '') {
$patient_name = $this->_resolve_patient_name_by_order($order_id);
}
if ($patient_name === '') {
$patient_name = $this->_resolve_patient_name_from_enc_by_order($order_id);
}
}
$url = $row['Print_TransactionUrl'];
$url = str_replace('PT_OrderHeaderID', $order_id, $url);
$url = str_replace('PUsername', urlencode($username), $url);
$url = str_replace('TS', $tm, $url);
// Pre-populate cache — frontend buka URL langsung ke BIRT
// Cache hidup 5 menit, cukup untuk BIRT generate PDF
if ($order_id > 0) {
$this->_populate_cache($order_id);
$url = $this->_build_birt_url_by_code($report_code, $order_id, 0, $patient_name);
if ($url === false) {
$this->sys_error("Report code tidak ditemukan: {$report_code}");
return;
}
$this->sys_ok(['url' => $url]);
@@ -381,6 +361,221 @@ class Birt_proxy extends MY_Controller
return trim($row['ppc_name'] ?? '');
}
private function _resolve_patient_name_from_enc_by_order($order_id)
{
$row = $this->db_onedev->query(
"SELECT M_PatientName_enc
FROM t_orderheader
JOIN m_patient ON T_OrderHeaderM_PatientID = M_PatientID
WHERE T_OrderHeaderID = ?
LIMIT 1",
[$order_id]
)->row_array();
return trim($this->ibl_encryptor->decrypt($row['M_PatientName_enc'] ?? '') ?? '');
}
private function _resolve_report_username()
{
if (!empty($this->sys_user['M_StaffName'])) {
return trim($this->sys_user['M_StaffName']);
}
if (!empty($this->sys_user['M_UserUsername'])) {
return trim($this->sys_user['M_UserUsername']);
}
if (!empty($this->sys_user['userName'])) {
return trim($this->sys_user['userName']);
}
return 'ADMIN';
}
private function _build_birt_url_by_code($report_code, $order_id, $payment_id, $patient_name)
{
$row = $this->db_onedev->query(
"SELECT Print_TransactionUrl
FROM print_transaction
WHERE Print_TransactionCode = ?
LIMIT 1",
[$report_code]
)->row_array();
if (!$row) {
return false;
}
$url_template = $this->_apply_report_template_hotfix($report_code, $row['Print_TransactionUrl']);
$username = $this->_resolve_report_username();
$tm = round(microtime(true) * 1000);
$resolved_payment_id = $payment_id > 0 ? $payment_id : $this->_resolve_payment_id_by_order($order_id);
$is_internal_app_url = $this->_is_internal_app_url($url_template);
$replacements = [
'PUsername' => $this->_format_report_string_param($username, $is_internal_app_url),
'PT_OrderHeaderID' => $order_id,
'PPaymentID' => $resolved_payment_id,
'PAn' => $this->_format_report_string_param($patient_name, $is_internal_app_url),
'TS' => $tm,
];
$url = $url_template;
foreach ($replacements as $placeholder => $value) {
if ($value === null) {
$value = '';
}
$url = str_replace($placeholder, $value, $url);
}
return $url;
}
private function _apply_report_template_hotfix($report_code, $url_template)
{
$print_report_hotfix = [
'LAB-RESULT-P-01' => [
'from' => 'rpt_test.rptdesign',
'to' => 'rpt_test_bkp020626.rptdesign',
],
'MIKROO-RESULT-P-01' => [
'from' => 'rpt_test.rptdesign',
'to' => 'rpt_test_bkp020626.rptdesign',
],
];
if (!isset($print_report_hotfix[$report_code])) {
return $url_template;
}
$hotfix = $print_report_hotfix[$report_code];
$resolved_url = str_replace($hotfix['from'], $hotfix['to'], $url_template);
if (strpos($resolved_url, 'username=') === false) {
$resolved_url .= (strpos($resolved_url, '?') === false ? '?' : '&') . 'username=PUsername';
}
return $resolved_url;
}
// GET /tools/birt_proxy/header_json?PID=<order_id>
// Hanya bisa diakses dari localhost (127.0.0.1) — dipanggil oleh BIRT scripted dataset
// Return JSON semua kolom sp_rpt_hasil_header, PII sudah di-decrypt
public function header_json()
{
$order_id = intval($this->input->get('PID') ?? 0);
if ($order_id <= 0) {
echo json_encode(['error' => 'PID required']);
exit;
}
$row = $this->db_onedev->query("
SELECT
DATE_FORMAT(T_OrderHeaderDate, '%d-%m-%Y') AS T_OrderHeaderDate,
T_OrderHeaderLabNumber,
M_TitleName,
M_PatientName,
M_PatientName_enc,
m_sexname AS Gender,
M_PatientNoReg,
M_PatientDOB,
M_PatientDOB_enc,
T_OrderHeaderM_PatientAge,
M_CompanyName AS CorporateName,
M_PatientHp,
M_PatientHP_enc,
M_PatientEmail,
M_PatientEmail_enc,
'' AS M_PatientAddressCity,
'' AS M_PatientAddressState,
M_CompanyName AS CorporateAddress,
M_CompanyEmail AS CorporateEmail,
M_CompanyPhone AS CorporatePhone,
M_CompanyAddressCity AS CorporateAddressCity,
'' AS CorporateAddressState,
TRIM(CONCAT(IFNULL(pj.M_DoctorPrefix,''),' ',IFNULL(pj.M_DoctorPrefix2,''),' ',IFNULL(pj.M_DoctorName,''),' ',IFNULL(pj.M_DoctorSufix,''),' ',IFNULL(pj.M_DoctorSufix2,''))) AS M_DoctorName,
TRIM(CONCAT(IFNULL(pjj.M_DoctorPrefix,''),' ',IFNULL(pjj.M_DoctorPrefix2,''),' ',IFNULL(pjj.M_DoctorName,''),' ',IFNULL(pjj.M_DoctorSufix,''),' ',IFNULL(pjj.M_DoctorSufix2,''))) AS M_DoctorName2,
M_PatientID,
M_PatientNIP, M_PatientJob, M_PatientPosisi, M_PatientDivisi, M_PatientLocation,
CONCAT(IFNULL(M_PatientDepartement,''),' - ',IFNULL(M_PatientNIP,'')) AS M_PatientDepartement
FROM t_orderheader
LEFT JOIN m_patient ON T_OrderHeaderM_PatientID = M_PatientID AND M_PatientIsActive = 'Y'
LEFT JOIN m_sex ON M_PatientM_SexID = M_SexID
LEFT JOIN m_title ON M_PatientM_TitleID = M_TitleID AND M_TitleIsActive = 'Y'
JOIN m_company ON T_OrderHeaderM_CompanyID = M_CompanyID AND M_CompanyIsActive = 'Y'
LEFT JOIN m_doctor pjj ON T_OrderHeaderPj2M_DoctorID = pjj.M_DoctorID AND pjj.M_DoctorIsActive = 'Y'
LEFT JOIN m_doctor pj ON T_OrderHeaderPjM_DoctorID = pj.M_DoctorID AND pj.M_DoctorIsActive = 'Y'
WHERE T_OrderHeaderID = ? AND T_OrderHeaderIsActive = 'Y'
", [$order_id])->row_array();
if (!$row) {
echo json_encode(['error' => 'order not found']);
exit;
}
$enc = $this->ibl_encryptor;
$name = $enc->decrypt($row['M_PatientName_enc'] ?? '') ?: ($row['M_PatientName'] ?? '');
$dob = $enc->decrypt($row['M_PatientDOB_enc'] ?? '') ?: date('d-m-Y', strtotime($row['M_PatientDOB'] ?? 'now'));
$hp = $enc->decrypt($row['M_PatientHP_enc'] ?? '') ?: ($row['M_PatientHp'] ?? '');
$email= $enc->decrypt($row['M_PatientEmail_enc']?? '') ?: ($row['M_PatientEmail'] ?? '');
$addr_row = $this->db_onedev->query("
SELECT CONCAT(
IFNULL(M_PatientAddressDescription,''),' ',
IFNULL((SELECT regional_nm FROM regional WHERE regional_cd = NULLIF(TRIM(M_PatientAddressRegionalCd),'') LIMIT 1),'')
) AS addr,
M_PatientAddressDescription_enc
FROM m_patientaddress
WHERE M_PatientAddressM_PatientID = ? AND M_PatientAddressIsActive = 'Y'
ORDER BY M_PatientAddressID LIMIT 1
", [$row['M_PatientID']])->row_array();
$address = '';
if ($addr_row) {
$address = $enc->decrypt($addr_row['M_PatientAddressDescription_enc'] ?? '') ?: trim($addr_row['addr'] ?? '');
}
$umur = $dob . ' / ' . ($row['T_OrderHeaderM_PatientAge'] ?? '');
$this->_populate_cache($order_id);
$data = [
'T_OrderHeaderDate' => $row['T_OrderHeaderDate'] ?? '',
'T_OrderHeaderLabNumber' => $row['T_OrderHeaderLabNumber'] ?? '',
'M_PatientName' => trim(($row['M_TitleName'] ?? '') . '. ' . $name),
'Gender' => $row['Gender'] ?? '',
'M_PatientNoReg' => $row['M_PatientNoReg'] ?? '',
'M_PatientDOB' => $dob,
'T_OrderHeaderM_PatientAge' => $row['T_OrderHeaderM_PatientAge'] ?? '',
'CorporateName' => $row['CorporateName'] ?? '',
'M_PatientAddress' => $address,
'M_PatientHp' => $hp,
'M_PatientEmail' => $email,
'M_PatientAddressCity' => '',
'M_PatientAddressState' => '',
'CorporateAddress' => $row['CorporateAddress'] ?? '',
'CorporateEmail' => $row['CorporateEmail'] ?? '',
'CorporatePhone' => $row['CorporatePhone'] ?? '',
'CorporateAddressCity' => $row['CorporateAddressCity'] ?? '',
'CorporateAddressState' => '',
'M_DoctorName' => $row['M_DoctorName'] ?? '',
'M_DoctorName2' => $row['M_DoctorName2'] ?? '',
'Umur' => $umur,
'M_PatientNIP' => $row['M_PatientNIP'] ?? '',
'M_PatientJob' => $row['M_PatientJob'] ?? '',
'M_PatientPosisi' => $row['M_PatientPosisi'] ?? '',
'M_PatientDivisi' => $row['M_PatientDivisi'] ?? '',
'M_PatientLocation' => $row['M_PatientLocation'] ?? '',
'M_PatientDepartement' => $row['M_PatientDepartement'] ?? '',
];
header('Content-Type: application/json');
echo json_encode($data);
exit;
}
private function _is_internal_app_url($url)
{
$url = (string) $url;

View File

@@ -0,0 +1,598 @@
<?php
defined('BASEPATH') or exit('No direct script access allowed');
/**
* Birt_proxy — PHP proxy untuk semua BIRT report call
*
* Flow:
* 1. Terima request dari frontend (report_code + params)
* 2. Decrypt patient PII dari _enc
* 3. INSERT ke patient_print_cache
* 4. Call BIRT via file_get_contents (internal)
* 5. DELETE cache
* 6. Stream PDF ke frontend
*
* Endpoint: POST /tools/birt_proxy/stream
* Params : report_code, PT_OrderHeaderID, PUsername, (optional) PID_patient
*/
class Birt_proxy extends MY_Controller
{
public $db_onedev;
private $birt_base = 'http://localhost:8080';
public function __construct()
{
parent::__construct();
$this->db_onedev = $this->load->database('onedev', true);
$this->load->library('ibl_encryptor');
}
// GET/POST /tools/birt_proxy/stream_by_code
// Gunakan ini untuk flow browser print yang butuh URL langsung,
// tapi cache PDP harus tetap dihapus segera setelah PDF di-stream.
public function stream_by_code()
{
if (!$this->isLogin) {
$this->sys_error('Invalid Token');
return;
}
$prm = $this->sys_input;
$report_code = trim($prm['report_code'] ?? $prm['code_report'] ?? $prm['code'] ?? '');
$order_id = intval($prm['PT_OrderHeaderID'] ?? $prm['order_id'] ?? 0);
$payment_id = intval($prm['PPaymentID'] ?? $prm['payment_id'] ?? 0);
if (!$report_code) {
$this->sys_error('report_code wajib diisi');
return;
}
if ($order_id <= 0 && $payment_id > 0) {
$order_id = $this->_resolve_order_id_by_payment($payment_id);
}
if ($payment_id <= 0 && $order_id > 0) {
$payment_id = $this->_resolve_payment_id_by_order($order_id);
}
if ($order_id <= 0) {
$this->sys_error('order_id tidak ditemukan');
return;
}
$cache_id = $this->_populate_cache($order_id);
$patient_name = $this->_resolve_patient_name_by_cache($cache_id);
if ($patient_name === '') {
$patient_name = $this->_resolve_patient_name_by_order($order_id);
}
if ($patient_name === '') {
$patient_name = $this->_resolve_patient_name_from_enc_by_order($order_id);
}
$url = $this->_build_birt_url_by_code($report_code, $order_id, $payment_id, $patient_name);
if ($url === false) {
$this->_delete_cache($cache_id);
$this->sys_error("Report code tidak ditemukan: {$report_code}");
return;
}
$full_url = $this->_resolve_fetch_url($url);
$context = stream_context_create([
'http' => [
'timeout' => 120,
'method' => 'GET',
]
]);
$pdf = @file_get_contents($full_url, false, $context);
$this->_delete_cache($cache_id);
if ($pdf === false) {
$this->sys_error('Gagal generate report dari BIRT server');
return;
}
$filename = $report_code . '_' . $order_id . '_' . date('Ymd') . '.pdf';
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename="' . $filename . '"');
header('Content-Length: ' . strlen($pdf));
echo $pdf;
exit;
}
// POST /tools/birt_proxy/stream
public function stream()
{
if (!$this->isLogin) {
$this->sys_error('Invalid Token');
return;
}
$prm = $this->sys_input;
$report_code = $prm['report_code'] ?? '';
$order_id = intval($prm['PT_OrderHeaderID'] ?? 0);
$payment_id = intval($prm['PPaymentID'] ?? 0);
if (!$report_code) {
$this->sys_error('report_code wajib diisi');
return;
}
if ($payment_id <= 0 && $order_id > 0) {
$payment_id = $this->_resolve_payment_id_by_order($order_id);
}
$patient_name = '';
if ($order_id > 0) {
$cache_id = $this->_populate_cache($order_id);
$patient_name = $this->_resolve_patient_name_by_cache($cache_id);
if ($patient_name === '') {
$patient_name = $this->_resolve_patient_name_by_order($order_id);
}
if ($patient_name === '') {
$patient_name = $this->_resolve_patient_name_from_enc_by_order($order_id);
}
} else {
$cache_id = null;
}
$url = $this->_build_birt_url_by_code($report_code, $order_id, $payment_id, $patient_name);
if ($url === false) {
$this->sys_error("Report code tidak ditemukan: {$report_code}");
return;
}
$full_url = $this->_resolve_fetch_url($url);
$context = stream_context_create([
'http' => [
'timeout' => 120,
'method' => 'GET',
]
]);
$pdf = @file_get_contents($full_url, false, $context);
if ($cache_id) {
$this->db_onedev->query(
"DELETE FROM patient_print_cache WHERE ppc_id = ?",
[$cache_id]
);
}
if ($pdf === false) {
$this->sys_error('Gagal generate report dari BIRT server');
return;
}
$filename = $report_code . '_' . $order_id . '_' . date('Ymd') . '.pdf';
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename="' . $filename . '"');
header('Content-Length: ' . strlen($pdf));
echo $pdf;
exit;
}
// Hanya return URL (untuk iframe/window.open) — tanpa stream
// Frontend membuka URL ini secara langsung
public function get_url()
{
if (!$this->isLogin) {
$this->sys_error('Invalid Token');
return;
}
$prm = $this->sys_input;
$report_code = $prm['report_code'] ?? '';
$order_id = intval($prm['PT_OrderHeaderID'] ?? 0);
$patient_name = '';
if ($order_id > 0) {
$cache_id = $this->_populate_cache($order_id);
$patient_name = $this->_resolve_patient_name_by_cache($cache_id);
if ($patient_name === '') {
$patient_name = $this->_resolve_patient_name_by_order($order_id);
}
if ($patient_name === '') {
$patient_name = $this->_resolve_patient_name_from_enc_by_order($order_id);
}
}
$url = $this->_build_birt_url_by_code($report_code, $order_id, 0, $patient_name);
if ($url === false) {
$this->sys_error("Report code tidak ditemukan: {$report_code}");
return;
}
$this->sys_ok(['url' => $url]);
}
// Decrypt patient PII dan simpan ke cache
private function _populate_cache($order_id)
{
// Ambil _enc columns dari m_patient via t_orderheader
$patient = $this->db_onedev->query(
"SELECT M_PatientID,
M_PatientName_enc, M_PatientDOB_enc, M_PatientHP_enc,
M_PatientEmail_enc, M_PatientDOB
FROM t_orderheader
JOIN m_patient ON T_OrderHeaderM_PatientID = M_PatientID
WHERE T_OrderHeaderID = ? LIMIT 1",
[$order_id]
)->row_array();
if (!$patient) return null;
$addr = $this->db_onedev->query(
"SELECT M_PatientAddressDescription_enc
FROM m_patientaddress
WHERE M_PatientAddressM_PatientID = ?
AND M_PatientAddressIsActive = 'Y'
AND M_PatientAddressNote = 'Utama'
LIMIT 1",
[$patient['M_PatientID']]
)->row_array();
$enc = $this->ibl_encryptor;
$name = $enc->decrypt($patient['M_PatientName_enc'] ?? '') ?? '';
$dob = $enc->decrypt($patient['M_PatientDOB_enc'] ?? '') ?? date('d-m-Y', strtotime($patient['M_PatientDOB'] ?? 'now'));
$hp = $enc->decrypt($patient['M_PatientHP_enc'] ?? '') ?? '';
$email= $enc->decrypt($patient['M_PatientEmail_enc']?? '') ?? '';
$address = $enc->decrypt($addr['M_PatientAddressDescription_enc'] ?? '') ?? '';
// Hapus cache lama untuk order ini + cleanup expired
$this->db_onedev->query(
"DELETE FROM patient_print_cache WHERE ppc_order_id = ? OR ppc_created < NOW() - INTERVAL 5 MINUTE",
[$order_id]
);
// Insert cache baru
$this->db_onedev->query(
"INSERT INTO patient_print_cache
(ppc_order_id, ppc_patient_id, ppc_name, ppc_dob, ppc_hp, ppc_email, ppc_address, ppc_created)
VALUES (?, ?, ?, ?, ?, ?, ?, NOW())",
[$order_id, $patient['M_PatientID'], $name, $dob, $hp, $email, $address]
);
return $this->db_onedev->insert_id();
}
private function _delete_cache($cache_id)
{
if ($cache_id) {
$this->db_onedev->query(
"DELETE FROM patient_print_cache WHERE ppc_id = ?",
[$cache_id]
);
}
$this->db_onedev->query(
"DELETE FROM patient_print_cache WHERE ppc_created < NOW() - INTERVAL 5 MINUTE"
);
}
private function _resolve_fetch_url($url)
{
$url = trim((string) $url);
if ($url === '') {
return '';
}
if (preg_match('#^https?://#i', $url)) {
return $url;
}
if (strpos($url, '/birt/') === 0) {
return $this->birt_base . $url;
}
if (strpos($url, '/one-api-lab/') === 0) {
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
return $scheme . '://' . $host . $url;
}
if (strpos($url, '/tools/') === 0 || strpos($url, '/index.php/') === 0) {
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
return $scheme . '://' . $host . '/one-api-lab' . $url;
}
return $this->birt_base . $url;
}
private function _resolve_order_id_by_payment($payment_id)
{
$row = $this->db_onedev->query(
"SELECT F_PaymentT_OrderHeaderID
FROM f_payment
WHERE F_PaymentID = ?
LIMIT 1",
[$payment_id]
)->row_array();
return intval($row['F_PaymentT_OrderHeaderID'] ?? 0);
}
private function _resolve_payment_id_by_order($order_id)
{
$row = $this->db_onedev->query(
"SELECT F_PaymentID
FROM f_payment
WHERE F_PaymentT_OrderHeaderID = ?
ORDER BY F_PaymentID DESC
LIMIT 1",
[$order_id]
)->row_array();
return intval($row['F_PaymentID'] ?? 0);
}
private function _resolve_patient_name_by_cache($cache_id)
{
if (!$cache_id) {
return '';
}
$row = $this->db_onedev->query(
"SELECT ppc_name
FROM patient_print_cache
WHERE ppc_id = ?
LIMIT 1",
[$cache_id]
)->row_array();
return trim($row['ppc_name'] ?? '');
}
private function _resolve_patient_name_by_order($order_id)
{
$row = $this->db_onedev->query(
"SELECT ppc_name
FROM patient_print_cache
WHERE ppc_order_id = ?
ORDER BY ppc_id DESC
LIMIT 1",
[$order_id]
)->row_array();
return trim($row['ppc_name'] ?? '');
}
private function _resolve_patient_name_from_enc_by_order($order_id)
{
$row = $this->db_onedev->query(
"SELECT M_PatientName_enc
FROM t_orderheader
JOIN m_patient ON T_OrderHeaderM_PatientID = M_PatientID
WHERE T_OrderHeaderID = ?
LIMIT 1",
[$order_id]
)->row_array();
return trim($this->ibl_encryptor->decrypt($row['M_PatientName_enc'] ?? '') ?? '');
}
private function _resolve_report_username()
{
if (!empty($this->sys_user['M_StaffName'])) {
return trim($this->sys_user['M_StaffName']);
}
if (!empty($this->sys_user['M_UserUsername'])) {
return trim($this->sys_user['M_UserUsername']);
}
if (!empty($this->sys_user['userName'])) {
return trim($this->sys_user['userName']);
}
return 'ADMIN';
}
private function _build_birt_url_by_code($report_code, $order_id, $payment_id, $patient_name)
{
$row = $this->db_onedev->query(
"SELECT Print_TransactionUrl
FROM print_transaction
WHERE Print_TransactionCode = ?
LIMIT 1",
[$report_code]
)->row_array();
if (!$row) {
return false;
}
$url_template = $this->_apply_report_template_hotfix($report_code, $row['Print_TransactionUrl']);
$username = $this->_resolve_report_username();
$tm = round(microtime(true) * 1000);
$resolved_payment_id = $payment_id > 0 ? $payment_id : $this->_resolve_payment_id_by_order($order_id);
$is_internal_app_url = $this->_is_internal_app_url($url_template);
$replacements = [
'PUsername' => $this->_format_report_string_param($username, $is_internal_app_url),
'PT_OrderHeaderID' => $order_id,
'PPaymentID' => $resolved_payment_id,
'PAn' => $this->_format_report_string_param($patient_name, $is_internal_app_url),
'TS' => $tm,
];
$url = $url_template;
foreach ($replacements as $placeholder => $value) {
if ($value === null) {
$value = '';
}
$url = str_replace($placeholder, $value, $url);
}
return $url;
}
private function _apply_report_template_hotfix($report_code, $url_template)
{
$print_report_hotfix = [
'LAB-RESULT-P-01' => [
'from' => 'rpt_test.rptdesign',
'to' => 'rpt_test_bkp020626.rptdesign',
],
'MIKROO-RESULT-P-01' => [
'from' => 'rpt_test.rptdesign',
'to' => 'rpt_test_bkp020626.rptdesign',
],
];
if (!isset($print_report_hotfix[$report_code])) {
return $url_template;
}
$hotfix = $print_report_hotfix[$report_code];
$resolved_url = str_replace($hotfix['from'], $hotfix['to'], $url_template);
if (strpos($resolved_url, 'username=') === false) {
$resolved_url .= (strpos($resolved_url, '?') === false ? '?' : '&') . 'username=PUsername';
}
return $resolved_url;
}
// GET /tools/birt_proxy/header_json?PID=<order_id>
// Hanya bisa diakses dari localhost (127.0.0.1) — dipanggil oleh BIRT scripted dataset
// Return JSON semua kolom sp_rpt_hasil_header, PII sudah di-decrypt
public function header_json()
{
$order_id = intval($this->input->get('PID') ?? 0);
if ($order_id <= 0) {
echo json_encode(['error' => 'PID required']);
exit;
}
$row = $this->db_onedev->query("
SELECT
DATE_FORMAT(T_OrderHeaderDate, '%d-%m-%Y') AS T_OrderHeaderDate,
T_OrderHeaderLabNumber,
M_TitleName,
M_PatientName,
M_PatientName_enc,
m_sexname AS Gender,
M_PatientNoReg,
M_PatientDOB,
M_PatientDOB_enc,
T_OrderHeaderM_PatientAge,
M_CompanyName AS CorporateName,
M_PatientHp,
M_PatientHP_enc,
M_PatientEmail,
M_PatientEmail_enc,
'' AS M_PatientAddressCity,
'' AS M_PatientAddressState,
M_CompanyName AS CorporateAddress,
M_CompanyEmail AS CorporateEmail,
M_CompanyPhone AS CorporatePhone,
M_CompanyAddressCity AS CorporateAddressCity,
'' AS CorporateAddressState,
TRIM(CONCAT(IFNULL(pj.M_DoctorPrefix,''),' ',IFNULL(pj.M_DoctorPrefix2,''),' ',IFNULL(pj.M_DoctorName,''),' ',IFNULL(pj.M_DoctorSufix,''),' ',IFNULL(pj.M_DoctorSufix2,''))) AS M_DoctorName,
TRIM(CONCAT(IFNULL(pjj.M_DoctorPrefix,''),' ',IFNULL(pjj.M_DoctorPrefix2,''),' ',IFNULL(pjj.M_DoctorName,''),' ',IFNULL(pjj.M_DoctorSufix,''),' ',IFNULL(pjj.M_DoctorSufix2,''))) AS M_DoctorName2,
M_PatientID,
M_PatientNIP, M_PatientJob, M_PatientPosisi, M_PatientDivisi, M_PatientLocation,
CONCAT(IFNULL(M_PatientDepartement,''),' - ',IFNULL(M_PatientNIP,'')) AS M_PatientDepartement
FROM t_orderheader
LEFT JOIN m_patient ON T_OrderHeaderM_PatientID = M_PatientID AND M_PatientIsActive = 'Y'
LEFT JOIN m_sex ON M_PatientM_SexID = M_SexID
LEFT JOIN m_title ON M_PatientM_TitleID = M_TitleID AND M_TitleIsActive = 'Y'
JOIN m_company ON T_OrderHeaderM_CompanyID = M_CompanyID AND M_CompanyIsActive = 'Y'
LEFT JOIN m_doctor pjj ON T_OrderHeaderPj2M_DoctorID = pjj.M_DoctorID AND pjj.M_DoctorIsActive = 'Y'
LEFT JOIN m_doctor pj ON T_OrderHeaderPjM_DoctorID = pj.M_DoctorID AND pj.M_DoctorIsActive = 'Y'
WHERE T_OrderHeaderID = ? AND T_OrderHeaderIsActive = 'Y'
", [$order_id])->row_array();
if (!$row) {
echo json_encode(['error' => 'order not found']);
exit;
}
$enc = $this->ibl_encryptor;
$name = $enc->decrypt($row['M_PatientName_enc'] ?? '') ?: ($row['M_PatientName'] ?? '');
$dob = $enc->decrypt($row['M_PatientDOB_enc'] ?? '') ?: date('d-m-Y', strtotime($row['M_PatientDOB'] ?? 'now'));
$hp = $enc->decrypt($row['M_PatientHP_enc'] ?? '') ?: ($row['M_PatientHp'] ?? '');
$email= $enc->decrypt($row['M_PatientEmail_enc']?? '') ?: ($row['M_PatientEmail'] ?? '');
$addr_row = $this->db_onedev->query("
SELECT CONCAT(
IFNULL(M_PatientAddressDescription,''),' ',
IFNULL((SELECT regional_nm FROM regional WHERE regional_cd = NULLIF(TRIM(M_PatientAddressRegionalCd),'') LIMIT 1),'')
) AS addr,
M_PatientAddressDescription_enc
FROM m_patientaddress
WHERE M_PatientAddressM_PatientID = ? AND M_PatientAddressIsActive = 'Y'
ORDER BY M_PatientAddressID LIMIT 1
", [$row['M_PatientID']])->row_array();
$address = '';
if ($addr_row) {
$address = $enc->decrypt($addr_row['M_PatientAddressDescription_enc'] ?? '') ?: trim($addr_row['addr'] ?? '');
}
$umur = $dob . ' / ' . ($row['T_OrderHeaderM_PatientAge'] ?? '');
$data = [
'T_OrderHeaderDate' => $row['T_OrderHeaderDate'] ?? '',
'T_OrderHeaderLabNumber' => $row['T_OrderHeaderLabNumber'] ?? '',
'M_PatientName' => trim(($row['M_TitleName'] ?? '') . '. ' . $name),
'Gender' => $row['Gender'] ?? '',
'M_PatientNoReg' => $row['M_PatientNoReg'] ?? '',
'M_PatientDOB' => $dob,
'T_OrderHeaderM_PatientAge' => $row['T_OrderHeaderM_PatientAge'] ?? '',
'CorporateName' => $row['CorporateName'] ?? '',
'M_PatientAddress' => $address,
'M_PatientHp' => $hp,
'M_PatientEmail' => $email,
'M_PatientAddressCity' => '',
'M_PatientAddressState' => '',
'CorporateAddress' => $row['CorporateAddress'] ?? '',
'CorporateEmail' => $row['CorporateEmail'] ?? '',
'CorporatePhone' => $row['CorporatePhone'] ?? '',
'CorporateAddressCity' => $row['CorporateAddressCity'] ?? '',
'CorporateAddressState' => '',
'M_DoctorName' => $row['M_DoctorName'] ?? '',
'M_DoctorName2' => $row['M_DoctorName2'] ?? '',
'Umur' => $umur,
'M_PatientNIP' => $row['M_PatientNIP'] ?? '',
'M_PatientJob' => $row['M_PatientJob'] ?? '',
'M_PatientPosisi' => $row['M_PatientPosisi'] ?? '',
'M_PatientDivisi' => $row['M_PatientDivisi'] ?? '',
'M_PatientLocation' => $row['M_PatientLocation'] ?? '',
'M_PatientDepartement' => $row['M_PatientDepartement'] ?? '',
];
header('Content-Type: application/json');
echo json_encode($data);
exit;
}
private function _is_internal_app_url($url)
{
$url = (string) $url;
return (
strpos($url, '/one-api-lab/') === 0 ||
strpos($url, '/tools/') === 0 ||
strpos($url, '/index.php/') === 0
);
}
private function _format_report_string_param($value, $is_internal_app_url = false)
{
$value = (string) $value;
if ($is_internal_app_url) {
return rawurlencode($value);
}
return rawurlencode("'" . $value . "'");
}
}

View File

@@ -0,0 +1,598 @@
<?php
defined('BASEPATH') or exit('No direct script access allowed');
/**
* Birt_proxy — PHP proxy untuk semua BIRT report call
*
* Flow:
* 1. Terima request dari frontend (report_code + params)
* 2. Decrypt patient PII dari _enc
* 3. INSERT ke patient_print_cache
* 4. Call BIRT via file_get_contents (internal)
* 5. DELETE cache
* 6. Stream PDF ke frontend
*
* Endpoint: POST /tools/birt_proxy/stream
* Params : report_code, PT_OrderHeaderID, PUsername, (optional) PID_patient
*/
class Birt_proxy extends MY_Controller
{
public $db_onedev;
private $birt_base = 'http://localhost:8080';
public function __construct()
{
parent::__construct();
$this->db_onedev = $this->load->database('onedev', true);
$this->load->library('ibl_encryptor');
}
// GET/POST /tools/birt_proxy/stream_by_code
// Gunakan ini untuk flow browser print yang butuh URL langsung,
// tapi cache PDP harus tetap dihapus segera setelah PDF di-stream.
public function stream_by_code()
{
if (!$this->isLogin) {
$this->sys_error('Invalid Token');
return;
}
$prm = $this->sys_input;
$report_code = trim($prm['report_code'] ?? $prm['code_report'] ?? $prm['code'] ?? '');
$order_id = intval($prm['PT_OrderHeaderID'] ?? $prm['order_id'] ?? 0);
$payment_id = intval($prm['PPaymentID'] ?? $prm['payment_id'] ?? 0);
if (!$report_code) {
$this->sys_error('report_code wajib diisi');
return;
}
if ($order_id <= 0 && $payment_id > 0) {
$order_id = $this->_resolve_order_id_by_payment($payment_id);
}
if ($payment_id <= 0 && $order_id > 0) {
$payment_id = $this->_resolve_payment_id_by_order($order_id);
}
if ($order_id <= 0) {
$this->sys_error('order_id tidak ditemukan');
return;
}
$cache_id = $this->_populate_cache($order_id);
$patient_name = $this->_resolve_patient_name_by_cache($cache_id);
if ($patient_name === '') {
$patient_name = $this->_resolve_patient_name_by_order($order_id);
}
if ($patient_name === '') {
$patient_name = $this->_resolve_patient_name_from_enc_by_order($order_id);
}
$url = $this->_build_birt_url_by_code($report_code, $order_id, $payment_id, $patient_name);
if ($url === false) {
$this->_delete_cache($cache_id);
$this->sys_error("Report code tidak ditemukan: {$report_code}");
return;
}
$full_url = $this->_resolve_fetch_url($url);
$context = stream_context_create([
'http' => [
'timeout' => 120,
'method' => 'GET',
]
]);
$pdf = @file_get_contents($full_url, false, $context);
$this->_delete_cache($cache_id);
if ($pdf === false) {
$this->sys_error('Gagal generate report dari BIRT server');
return;
}
$filename = $report_code . '_' . $order_id . '_' . date('Ymd') . '.pdf';
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename="' . $filename . '"');
header('Content-Length: ' . strlen($pdf));
echo $pdf;
exit;
}
// POST /tools/birt_proxy/stream
public function stream()
{
if (!$this->isLogin) {
$this->sys_error('Invalid Token');
return;
}
$prm = $this->sys_input;
$report_code = $prm['report_code'] ?? '';
$order_id = intval($prm['PT_OrderHeaderID'] ?? 0);
$payment_id = intval($prm['PPaymentID'] ?? 0);
if (!$report_code) {
$this->sys_error('report_code wajib diisi');
return;
}
if ($payment_id <= 0 && $order_id > 0) {
$payment_id = $this->_resolve_payment_id_by_order($order_id);
}
$patient_name = '';
if ($order_id > 0) {
$cache_id = $this->_populate_cache($order_id);
$patient_name = $this->_resolve_patient_name_by_cache($cache_id);
if ($patient_name === '') {
$patient_name = $this->_resolve_patient_name_by_order($order_id);
}
if ($patient_name === '') {
$patient_name = $this->_resolve_patient_name_from_enc_by_order($order_id);
}
} else {
$cache_id = null;
}
$url = $this->_build_birt_url_by_code($report_code, $order_id, $payment_id, $patient_name);
if ($url === false) {
$this->sys_error("Report code tidak ditemukan: {$report_code}");
return;
}
$full_url = $this->_resolve_fetch_url($url);
$context = stream_context_create([
'http' => [
'timeout' => 120,
'method' => 'GET',
]
]);
$pdf = @file_get_contents($full_url, false, $context);
if ($cache_id) {
$this->db_onedev->query(
"DELETE FROM patient_print_cache WHERE ppc_id = ?",
[$cache_id]
);
}
if ($pdf === false) {
$this->sys_error('Gagal generate report dari BIRT server');
return;
}
$filename = $report_code . '_' . $order_id . '_' . date('Ymd') . '.pdf';
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename="' . $filename . '"');
header('Content-Length: ' . strlen($pdf));
echo $pdf;
exit;
}
// Hanya return URL (untuk iframe/window.open) — tanpa stream
// Frontend membuka URL ini secara langsung
public function get_url()
{
if (!$this->isLogin) {
$this->sys_error('Invalid Token');
return;
}
$prm = $this->sys_input;
$report_code = $prm['report_code'] ?? '';
$order_id = intval($prm['PT_OrderHeaderID'] ?? 0);
$patient_name = '';
if ($order_id > 0) {
$cache_id = $this->_populate_cache($order_id);
$patient_name = $this->_resolve_patient_name_by_cache($cache_id);
if ($patient_name === '') {
$patient_name = $this->_resolve_patient_name_by_order($order_id);
}
if ($patient_name === '') {
$patient_name = $this->_resolve_patient_name_from_enc_by_order($order_id);
}
}
$url = $this->_build_birt_url_by_code($report_code, $order_id, 0, $patient_name);
if ($url === false) {
$this->sys_error("Report code tidak ditemukan: {$report_code}");
return;
}
$this->sys_ok(['url' => $url]);
}
// Decrypt patient PII dan simpan ke cache
private function _populate_cache($order_id)
{
// Ambil _enc columns dari m_patient via t_orderheader
$patient = $this->db_onedev->query(
"SELECT M_PatientID,
M_PatientName_enc, M_PatientDOB_enc, M_PatientHP_enc,
M_PatientEmail_enc, M_PatientDOB
FROM t_orderheader
JOIN m_patient ON T_OrderHeaderM_PatientID = M_PatientID
WHERE T_OrderHeaderID = ? LIMIT 1",
[$order_id]
)->row_array();
if (!$patient) return null;
$addr = $this->db_onedev->query(
"SELECT M_PatientAddressDescription_enc
FROM m_patientaddress
WHERE M_PatientAddressM_PatientID = ?
AND M_PatientAddressIsActive = 'Y'
AND M_PatientAddressNote = 'Utama'
LIMIT 1",
[$patient['M_PatientID']]
)->row_array();
$enc = $this->ibl_encryptor;
$name = $enc->decrypt($patient['M_PatientName_enc'] ?? '') ?? '';
$dob = $enc->decrypt($patient['M_PatientDOB_enc'] ?? '') ?? date('d-m-Y', strtotime($patient['M_PatientDOB'] ?? 'now'));
$hp = $enc->decrypt($patient['M_PatientHP_enc'] ?? '') ?? '';
$email= $enc->decrypt($patient['M_PatientEmail_enc']?? '') ?? '';
$address = $enc->decrypt($addr['M_PatientAddressDescription_enc'] ?? '') ?? '';
// Hapus cache lama untuk order ini + cleanup expired
$this->db_onedev->query(
"DELETE FROM patient_print_cache WHERE ppc_order_id = ? OR ppc_created < NOW() - INTERVAL 5 MINUTE",
[$order_id]
);
// Insert cache baru
$this->db_onedev->query(
"INSERT INTO patient_print_cache
(ppc_order_id, ppc_patient_id, ppc_name, ppc_dob, ppc_hp, ppc_email, ppc_address, ppc_created)
VALUES (?, ?, ?, ?, ?, ?, ?, NOW())",
[$order_id, $patient['M_PatientID'], $name, $dob, $hp, $email, $address]
);
return $this->db_onedev->insert_id();
}
private function _delete_cache($cache_id)
{
if ($cache_id) {
$this->db_onedev->query(
"DELETE FROM patient_print_cache WHERE ppc_id = ?",
[$cache_id]
);
}
$this->db_onedev->query(
"DELETE FROM patient_print_cache WHERE ppc_created < NOW() - INTERVAL 5 MINUTE"
);
}
private function _resolve_fetch_url($url)
{
$url = trim((string) $url);
if ($url === '') {
return '';
}
if (preg_match('#^https?://#i', $url)) {
return $url;
}
if (strpos($url, '/birt/') === 0) {
return $this->birt_base . $url;
}
if (strpos($url, '/one-api-lab/') === 0) {
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
return $scheme . '://' . $host . $url;
}
if (strpos($url, '/tools/') === 0 || strpos($url, '/index.php/') === 0) {
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
return $scheme . '://' . $host . '/one-api-lab' . $url;
}
return $this->birt_base . $url;
}
private function _resolve_order_id_by_payment($payment_id)
{
$row = $this->db_onedev->query(
"SELECT F_PaymentT_OrderHeaderID
FROM f_payment
WHERE F_PaymentID = ?
LIMIT 1",
[$payment_id]
)->row_array();
return intval($row['F_PaymentT_OrderHeaderID'] ?? 0);
}
private function _resolve_payment_id_by_order($order_id)
{
$row = $this->db_onedev->query(
"SELECT F_PaymentID
FROM f_payment
WHERE F_PaymentT_OrderHeaderID = ?
ORDER BY F_PaymentID DESC
LIMIT 1",
[$order_id]
)->row_array();
return intval($row['F_PaymentID'] ?? 0);
}
private function _resolve_patient_name_by_cache($cache_id)
{
if (!$cache_id) {
return '';
}
$row = $this->db_onedev->query(
"SELECT ppc_name
FROM patient_print_cache
WHERE ppc_id = ?
LIMIT 1",
[$cache_id]
)->row_array();
return trim($row['ppc_name'] ?? '');
}
private function _resolve_patient_name_by_order($order_id)
{
$row = $this->db_onedev->query(
"SELECT ppc_name
FROM patient_print_cache
WHERE ppc_order_id = ?
ORDER BY ppc_id DESC
LIMIT 1",
[$order_id]
)->row_array();
return trim($row['ppc_name'] ?? '');
}
private function _resolve_patient_name_from_enc_by_order($order_id)
{
$row = $this->db_onedev->query(
"SELECT M_PatientName_enc
FROM t_orderheader
JOIN m_patient ON T_OrderHeaderM_PatientID = M_PatientID
WHERE T_OrderHeaderID = ?
LIMIT 1",
[$order_id]
)->row_array();
return trim($this->ibl_encryptor->decrypt($row['M_PatientName_enc'] ?? '') ?? '');
}
private function _resolve_report_username()
{
if (!empty($this->sys_user['M_StaffName'])) {
return trim($this->sys_user['M_StaffName']);
}
if (!empty($this->sys_user['M_UserUsername'])) {
return trim($this->sys_user['M_UserUsername']);
}
if (!empty($this->sys_user['userName'])) {
return trim($this->sys_user['userName']);
}
return 'ADMIN';
}
private function _build_birt_url_by_code($report_code, $order_id, $payment_id, $patient_name)
{
$row = $this->db_onedev->query(
"SELECT Print_TransactionUrl
FROM print_transaction
WHERE Print_TransactionCode = ?
LIMIT 1",
[$report_code]
)->row_array();
if (!$row) {
return false;
}
$url_template = $this->_apply_report_template_hotfix($report_code, $row['Print_TransactionUrl']);
$username = $this->_resolve_report_username();
$tm = round(microtime(true) * 1000);
$resolved_payment_id = $payment_id > 0 ? $payment_id : $this->_resolve_payment_id_by_order($order_id);
$is_internal_app_url = $this->_is_internal_app_url($url_template);
$replacements = [
'PUsername' => $this->_format_report_string_param($username, $is_internal_app_url),
'PT_OrderHeaderID' => $order_id,
'PPaymentID' => $resolved_payment_id,
'PAn' => $this->_format_report_string_param($patient_name, $is_internal_app_url),
'TS' => $tm,
];
$url = $url_template;
foreach ($replacements as $placeholder => $value) {
if ($value === null) {
$value = '';
}
$url = str_replace($placeholder, $value, $url);
}
return $url;
}
private function _apply_report_template_hotfix($report_code, $url_template)
{
$print_report_hotfix = [
'LAB-RESULT-P-01' => [
'from' => 'rpt_test.rptdesign',
'to' => 'rpt_test_bkp020626.rptdesign',
],
'MIKROO-RESULT-P-01' => [
'from' => 'rpt_test.rptdesign',
'to' => 'rpt_test_bkp020626.rptdesign',
],
];
if (!isset($print_report_hotfix[$report_code])) {
return $url_template;
}
$hotfix = $print_report_hotfix[$report_code];
$resolved_url = str_replace($hotfix['from'], $hotfix['to'], $url_template);
if (strpos($resolved_url, 'username=') === false) {
$resolved_url .= (strpos($resolved_url, '?') === false ? '?' : '&') . 'username=PUsername';
}
return $resolved_url;
}
// GET /tools/birt_proxy/header_json?PID=<order_id>
// Hanya bisa diakses dari localhost (127.0.0.1) — dipanggil oleh BIRT scripted dataset
// Return JSON semua kolom sp_rpt_hasil_header, PII sudah di-decrypt
public function header_json()
{
$order_id = intval($this->input->get('PID') ?? 0);
if ($order_id <= 0) {
echo json_encode(['error' => 'PID required']);
exit;
}
$row = $this->db_onedev->query("
SELECT
DATE_FORMAT(T_OrderHeaderDate, '%d-%m-%Y') AS T_OrderHeaderDate,
T_OrderHeaderLabNumber,
M_TitleName,
M_PatientName,
M_PatientName_enc,
m_sexname AS Gender,
M_PatientNoReg,
M_PatientDOB,
M_PatientDOB_enc,
T_OrderHeaderM_PatientAge,
M_CompanyName AS CorporateName,
M_PatientHp,
M_PatientHP_enc,
M_PatientEmail,
M_PatientEmail_enc,
'' AS M_PatientAddressCity,
'' AS M_PatientAddressState,
M_CompanyName AS CorporateAddress,
M_CompanyEmail AS CorporateEmail,
M_CompanyPhone AS CorporatePhone,
M_CompanyAddressCity AS CorporateAddressCity,
'' AS CorporateAddressState,
TRIM(CONCAT(IFNULL(pj.M_DoctorPrefix,''),' ',IFNULL(pj.M_DoctorPrefix2,''),' ',IFNULL(pj.M_DoctorName,''),' ',IFNULL(pj.M_DoctorSufix,''),' ',IFNULL(pj.M_DoctorSufix2,''))) AS M_DoctorName,
TRIM(CONCAT(IFNULL(pjj.M_DoctorPrefix,''),' ',IFNULL(pjj.M_DoctorPrefix2,''),' ',IFNULL(pjj.M_DoctorName,''),' ',IFNULL(pjj.M_DoctorSufix,''),' ',IFNULL(pjj.M_DoctorSufix2,''))) AS M_DoctorName2,
M_PatientID,
M_PatientNIP, M_PatientJob, M_PatientPosisi, M_PatientDivisi, M_PatientLocation,
CONCAT(IFNULL(M_PatientDepartement,''),' - ',IFNULL(M_PatientNIP,'')) AS M_PatientDepartement
FROM t_orderheader
LEFT JOIN m_patient ON T_OrderHeaderM_PatientID = M_PatientID AND M_PatientIsActive = 'Y'
LEFT JOIN m_sex ON M_PatientM_SexID = M_SexID
LEFT JOIN m_title ON M_PatientM_TitleID = M_TitleID AND M_TitleIsActive = 'Y'
JOIN m_company ON T_OrderHeaderM_CompanyID = M_CompanyID AND M_CompanyIsActive = 'Y'
LEFT JOIN m_doctor pjj ON T_OrderHeaderPj2M_DoctorID = pjj.M_DoctorID AND pjj.M_DoctorIsActive = 'Y'
LEFT JOIN m_doctor pj ON T_OrderHeaderPjM_DoctorID = pj.M_DoctorID AND pj.M_DoctorIsActive = 'Y'
WHERE T_OrderHeaderID = ? AND T_OrderHeaderIsActive = 'Y'
", [$order_id])->row_array();
if (!$row) {
echo json_encode(['error' => 'order not found']);
exit;
}
$enc = $this->ibl_encryptor;
$name = $enc->decrypt($row['M_PatientName_enc'] ?? '') ?: ($row['M_PatientName'] ?? '');
$dob = $enc->decrypt($row['M_PatientDOB_enc'] ?? '') ?: date('d-m-Y', strtotime($row['M_PatientDOB'] ?? 'now'));
$hp = $enc->decrypt($row['M_PatientHP_enc'] ?? '') ?: ($row['M_PatientHp'] ?? '');
$email= $enc->decrypt($row['M_PatientEmail_enc']?? '') ?: ($row['M_PatientEmail'] ?? '');
$addr_row = $this->db_onedev->query("
SELECT CONCAT(
IFNULL(M_PatientAddressDescription,''),' ',
IFNULL((SELECT regional_nm FROM regional WHERE regional_cd = NULLIF(TRIM(M_PatientAddressRegionalCd),'') LIMIT 1),'')
) AS addr,
M_PatientAddressDescription_enc
FROM m_patientaddress
WHERE M_PatientAddressM_PatientID = ? AND M_PatientAddressIsActive = 'Y'
ORDER BY M_PatientAddressID LIMIT 1
", [$row['M_PatientID']])->row_array();
$address = '';
if ($addr_row) {
$address = $enc->decrypt($addr_row['M_PatientAddressDescription_enc'] ?? '') ?: trim($addr_row['addr'] ?? '');
}
$umur = $dob . ' / ' . ($row['T_OrderHeaderM_PatientAge'] ?? '');
$data = [
'T_OrderHeaderDate' => $row['T_OrderHeaderDate'] ?? '',
'T_OrderHeaderLabNumber' => $row['T_OrderHeaderLabNumber'] ?? '',
'M_PatientName' => trim(($row['M_TitleName'] ?? '') . '. ' . $name),
'Gender' => $row['Gender'] ?? '',
'M_PatientNoReg' => $row['M_PatientNoReg'] ?? '',
'M_PatientDOB' => $dob,
'T_OrderHeaderM_PatientAge' => $row['T_OrderHeaderM_PatientAge'] ?? '',
'CorporateName' => $row['CorporateName'] ?? '',
'M_PatientAddress' => $address,
'M_PatientHp' => $hp,
'M_PatientEmail' => $email,
'M_PatientAddressCity' => '',
'M_PatientAddressState' => '',
'CorporateAddress' => $row['CorporateAddress'] ?? '',
'CorporateEmail' => $row['CorporateEmail'] ?? '',
'CorporatePhone' => $row['CorporatePhone'] ?? '',
'CorporateAddressCity' => $row['CorporateAddressCity'] ?? '',
'CorporateAddressState' => '',
'M_DoctorName' => $row['M_DoctorName'] ?? '',
'M_DoctorName2' => $row['M_DoctorName2'] ?? '',
'Umur' => $umur,
'M_PatientNIP' => $row['M_PatientNIP'] ?? '',
'M_PatientJob' => $row['M_PatientJob'] ?? '',
'M_PatientPosisi' => $row['M_PatientPosisi'] ?? '',
'M_PatientDivisi' => $row['M_PatientDivisi'] ?? '',
'M_PatientLocation' => $row['M_PatientLocation'] ?? '',
'M_PatientDepartement' => $row['M_PatientDepartement'] ?? '',
];
header('Content-Type: application/json');
echo json_encode($data);
exit;
}
private function _is_internal_app_url($url)
{
$url = (string) $url;
return (
strpos($url, '/one-api-lab/') === 0 ||
strpos($url, '/tools/') === 0 ||
strpos($url, '/index.php/') === 0
);
}
private function _format_report_string_param($value, $is_internal_app_url = false)
{
$value = (string) $value;
if ($is_internal_app_url) {
return rawurlencode($value);
}
return rawurlencode("'" . $value . "'");
}
}

View File

@@ -0,0 +1,450 @@
<?php
defined('BASEPATH') or exit('No direct script access allowed');
/**
* BIRT proxy untuk report nonlab.
*
* Endpoint:
* - GET/POST /tools/birt_proxy_nonlab/stream_by_code
* - POST /tools/birt_proxy_nonlab/stream
* - GET/POST /tools/birt_proxy_nonlab/get_url
* - GET /tools/birt_proxy_nonlab/header_json
*
* Params:
* - report_code, code_report, atau code. Default: RONTGEN-RESULT-P-01
* - PID, PSo_ResultEntryID, So_ResultEntryID, result_entry_id, atau PT_OrderHeaderID
*/
class Birt_proxy_nonlab extends MY_Controller
{
public $db_onedev;
private $birt_base = 'http://localhost:8080';
public function __construct()
{
parent::__construct();
$this->db_onedev = $this->load->database('onedev', true);
$this->load->library('ibl_encryptor');
}
public function stream_by_code()
{
$this->_stream_by_code();
}
public function stream()
{
$this->_stream_by_code();
}
public function get_url()
{
if (!$this->isLogin) {
$this->sys_error('Invalid Token');
return;
}
$prm = $this->sys_input;
$report_code = $this->_resolve_report_code($prm);
$pid = $this->_resolve_pid($prm);
if ($pid <= 0) {
$this->sys_error('PID wajib diisi');
return;
}
$order_id = $this->_resolve_order_id_by_result_entry($pid);
if ($order_id > 0) {
$this->_populate_cache($order_id);
}
$url = $this->_build_birt_url_by_code($report_code, $pid);
if ($url === false) {
$this->sys_error("Report code tidak ditemukan: {$report_code}");
return;
}
$this->sys_ok(['url' => $url]);
}
public function header_json()
{
$pid = intval($this->input->get('PID') ?? $this->input->get('So_ResultEntryID') ?? 0);
if ($pid <= 0) {
echo json_encode(['error' => 'PID required']);
exit;
}
$row = $this->db_onedev->query("
SELECT
T_OrderHeaderID,
DATE_FORMAT(T_OrderHeaderDate, '%d-%m-%Y') AS T_OrderHeaderDate,
T_OrderHeaderLabNumber,
M_TitleName,
M_PatientName,
M_PatientName_enc,
m_sexname AS Gender,
M_PatientNoReg,
M_PatientDOB,
M_PatientDOB_enc,
T_OrderHeaderM_PatientAge,
M_CompanyName AS CorporateName,
M_PatientHp,
M_PatientHP_enc,
M_PatientEmail,
M_PatientEmail_enc,
M_CompanyAddress AS CorporateAddress,
M_CompanyEmail AS CorporateEmail,
M_CompanyPhone AS CorporatePhone,
M_CompanyAddressCity AS CorporateAddressCity,
TRIM(CONCAT(IFNULL(pj.M_DoctorPrefix, ''), ' ', IFNULL(pj.M_DoctorPrefix2, ''), ' ', IFNULL(pj.M_DoctorName, ''), ' ', IFNULL(pj.M_DoctorSufix, ''), ' ', IFNULL(pj.M_DoctorSufix2, ''))) AS M_DoctorName,
TRIM(CONCAT(IFNULL(pjj.M_DoctorPrefix, ''), ' ', IFNULL(pjj.M_DoctorPrefix2, ''), ' ', IFNULL(pjj.M_DoctorName, ''), ' ', IFNULL(pjj.M_DoctorSufix, ''), ' ', IFNULL(pjj.M_DoctorSufix2, ''))) AS M_DoctorName2,
M_PatientID,
M_PatientNIP,
M_PatientJob,
M_PatientPosisi,
M_PatientDivisi,
M_PatientLocation,
CONCAT(IFNULL(M_PatientDepartement, ''), ' - ', IFNULL(M_PatientNIP, '')) AS M_PatientDepartement
FROM t_orderheader
JOIN so_resultentry ON So_ResultEntryT_OrderHeaderID = T_OrderHeaderID
AND So_ResultEntryIsActive = 'Y'
LEFT JOIN m_patient ON T_OrderHeaderM_PatientID = M_PatientID
AND M_PatientIsActive = 'Y'
LEFT JOIN m_title ON M_PatientM_TitleID = M_TitleID
AND M_TitleIsActive = 'Y'
LEFT JOIN m_company ON T_OrderHeaderM_CompanyID = M_CompanyID
AND M_CompanyIsActive = 'Y'
LEFT JOIN m_sex ON M_PatientM_SexID = M_SexID
LEFT JOIN m_doctor pjj ON T_OrderHeaderPj2M_DoctorID = pjj.M_DoctorID
AND pjj.M_DoctorIsActive = 'Y'
LEFT JOIN m_doctor pj ON T_OrderHeaderPjM_DoctorID = pj.M_DoctorID
AND pj.M_DoctorIsActive = 'Y'
WHERE So_ResultEntryID = ?
AND T_OrderHeaderIsActive = 'Y'
GROUP BY T_OrderHeaderID
LIMIT 1
", [$pid])->row_array();
if (!$row) {
echo json_encode(['error' => 'result entry not found']);
exit;
}
$enc = $this->ibl_encryptor;
$name = $enc->decrypt($row['M_PatientName_enc'] ?? '') ?: ($row['M_PatientName'] ?? '');
$dob = $enc->decrypt($row['M_PatientDOB_enc'] ?? '') ?: date('d-m-Y', strtotime($row['M_PatientDOB'] ?? 'now'));
$hp = $enc->decrypt($row['M_PatientHP_enc'] ?? '') ?: ($row['M_PatientHp'] ?? '');
$email = $enc->decrypt($row['M_PatientEmail_enc'] ?? '') ?: ($row['M_PatientEmail'] ?? '');
$addr_row = $this->db_onedev->query("
SELECT
CONCAT(
IFNULL(M_PatientAddressDescription, ''), ' ',
IFNULL(M_DistrictName, ''), ' ',
IFNULL(M_CityName, '')
) AS addr,
M_PatientAddressDescription_enc
FROM m_patientaddress AS p
LEFT JOIN (
SELECT regional_cd, regional_nm AS M_KelurahanName, pro_cd, kab_cd, kec_cd
FROM regional
) reg_kel ON NULLIF(TRIM(p.M_PatientAddressRegionalCd), '') = reg_kel.regional_cd
LEFT JOIN (
SELECT regional_cd, regional_nm AS M_DistrictName
FROM regional
) reg_kec ON CONCAT(reg_kel.pro_cd, reg_kel.kab_cd, reg_kel.kec_cd, '000') = reg_kec.regional_cd
LEFT JOIN (
SELECT regional_cd, regional_nm AS M_CityName
FROM regional
) reg_kab ON CONCAT(reg_kel.pro_cd, reg_kel.kab_cd, '000000') = reg_kab.regional_cd
WHERE M_PatientAddressM_PatientID = ?
AND M_PatientAddressIsActive = 'Y'
ORDER BY (M_PatientAddressNote = 'Utama') DESC, M_PatientAddressID
LIMIT 1
", [$row['M_PatientID']])->row_array();
$address = '';
if ($addr_row) {
$address = $enc->decrypt($addr_row['M_PatientAddressDescription_enc'] ?? '') ?: trim($addr_row['addr'] ?? '');
}
if (!empty($row['T_OrderHeaderID'])) {
$this->_populate_cache((int) $row['T_OrderHeaderID']);
}
$data = [
'T_OrderHeaderID' => (int) ($row['T_OrderHeaderID'] ?? 0),
'T_OrderHeaderDate' => $row['T_OrderHeaderDate'] ?? '',
'T_OrderHeaderLabNumber' => $row['T_OrderHeaderLabNumber'] ?? '',
'M_PatientName' => trim(($row['M_TitleName'] ?? '') . '. ' . $name),
'Gender' => $row['Gender'] ?? '',
'M_PatientNoReg' => $row['M_PatientNoReg'] ?? '',
'M_PatientDOB' => $dob,
'T_OrderHeaderM_PatientAge' => $row['T_OrderHeaderM_PatientAge'] ?? '',
'CorporateName' => $row['CorporateName'] ?? '',
'M_PatientAddress' => $address,
'M_PatientHp' => $hp,
'M_PatientEmail' => $email,
'M_PatientAddressCity' => '',
'M_PatientAddressState' => $address,
'CorporateAddress' => $row['CorporateAddress'] ?? '',
'CorporateEmail' => $row['CorporateEmail'] ?? '',
'CorporatePhone' => $row['CorporatePhone'] ?? '',
'CorporateAddressCity' => $row['CorporateAddressCity'] ?? '',
'CorporateAddressState' => '',
'M_DoctorName' => $row['M_DoctorName'] ?? '',
'M_DoctorName2' => $row['M_DoctorName2'] ?? '',
'Umur' => $dob . ' / ' . ($row['T_OrderHeaderM_PatientAge'] ?? ''),
'M_PatientNIP' => $row['M_PatientNIP'] ?? '',
'M_PatientJob' => $row['M_PatientJob'] ?? '',
'M_PatientPosisi' => $row['M_PatientPosisi'] ?? '',
'M_PatientDivisi' => $row['M_PatientDivisi'] ?? '',
'M_PatientLocation' => $row['M_PatientLocation'] ?? '',
'M_PatientDepartement' => $row['M_PatientDepartement'] ?? '',
];
header('Content-Type: application/json');
echo json_encode($data);
exit;
}
private function _stream_by_code()
{
if (!$this->isLogin) {
$this->sys_error('Invalid Token');
return;
}
$prm = $this->sys_input;
$report_code = $this->_resolve_report_code($prm);
$pid = $this->_resolve_pid($prm);
if ($pid <= 0) {
$this->sys_error('PID wajib diisi');
return;
}
$cache_id = null;
$order_id = $this->_resolve_order_id_by_result_entry($pid);
if ($order_id > 0) {
$cache_id = $this->_populate_cache($order_id);
}
$url = $this->_build_birt_url_by_code($report_code, $pid);
if ($url === false) {
$this->_delete_cache($cache_id);
$this->sys_error("Report code tidak ditemukan: {$report_code}");
return;
}
$context = stream_context_create([
'http' => [
'timeout' => 120,
'method' => 'GET',
],
]);
$pdf = @file_get_contents($this->_resolve_fetch_url($url), false, $context);
$this->_delete_cache($cache_id);
if ($pdf === false) {
$this->sys_error('Gagal generate report dari BIRT server');
return;
}
$filename = $report_code . '_' . $pid . '_' . date('Ymd') . '.pdf';
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename="' . $filename . '"');
header('Content-Length: ' . strlen($pdf));
echo $pdf;
exit;
}
private function _resolve_report_code($prm)
{
$report_code = trim($prm['report_code'] ?? $prm['code_report'] ?? $prm['code'] ?? '');
return $report_code !== '' ? $report_code : 'RONTGEN-RESULT-P-01';
}
private function _resolve_pid($prm)
{
return intval(
$prm['PID'] ??
$prm['PSo_ResultEntryID'] ??
$prm['So_ResultEntryID'] ??
$prm['result_entry_id'] ??
$prm['PT_OrderHeaderID'] ??
0
);
}
private function _build_birt_url_by_code($report_code, $pid)
{
$row = $this->db_onedev->query(
"SELECT Print_TransactionUrl
FROM print_transaction
WHERE Print_TransactionCode = ?
LIMIT 1",
[$report_code]
)->row_array();
if (!$row) {
return false;
}
$username = $this->_resolve_report_username();
$tm = round(microtime(true) * 1000);
$url = $row['Print_TransactionUrl'];
$replacements = [
'PUsername' => $this->_format_report_string_param($username),
'PT_OrderHeaderID' => $pid,
'PSo_ResultEntryID' => $pid,
'TS' => $tm,
];
foreach ($replacements as $placeholder => $value) {
$url = str_replace($placeholder, $value, $url);
}
$url = preg_replace('/([?&]PID=)PID([&#]|$)/', '${1}' . $pid . '$2', $url);
return $url;
}
private function _resolve_fetch_url($url)
{
$url = trim((string) $url);
if ($url === '') {
return '';
}
if (preg_match('#^https?://#i', $url)) {
return $url;
}
if (strpos($url, '/birt/') === 0) {
return $this->birt_base . $url;
}
if (strpos($url, '/one-api-lab/') === 0) {
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
return $scheme . '://' . $host . $url;
}
if (strpos($url, '/tools/') === 0 || strpos($url, '/index.php/') === 0) {
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
return $scheme . '://' . $host . '/one-api-lab' . $url;
}
return $this->birt_base . $url;
}
private function _resolve_order_id_by_result_entry($result_entry_id)
{
$row = $this->db_onedev->query(
"SELECT So_ResultEntryT_OrderHeaderID
FROM so_resultentry
WHERE So_ResultEntryID = ?
AND So_ResultEntryIsActive = 'Y'
LIMIT 1",
[$result_entry_id]
)->row_array();
return intval($row['So_ResultEntryT_OrderHeaderID'] ?? 0);
}
private function _populate_cache($order_id)
{
$patient = $this->db_onedev->query(
"SELECT M_PatientID,
M_PatientName_enc, M_PatientDOB_enc, M_PatientHP_enc,
M_PatientEmail_enc, M_PatientDOB
FROM t_orderheader
JOIN m_patient ON T_OrderHeaderM_PatientID = M_PatientID
WHERE T_OrderHeaderID = ?
AND T_OrderHeaderIsActive = 'Y'
LIMIT 1",
[$order_id]
)->row_array();
if (!$patient) {
return null;
}
$addr = $this->db_onedev->query(
"SELECT M_PatientAddressDescription_enc
FROM m_patientaddress
WHERE M_PatientAddressM_PatientID = ?
AND M_PatientAddressIsActive = 'Y'
ORDER BY (M_PatientAddressNote = 'Utama') DESC, M_PatientAddressID
LIMIT 1",
[$patient['M_PatientID']]
)->row_array();
$enc = $this->ibl_encryptor;
$name = $enc->decrypt($patient['M_PatientName_enc'] ?? '') ?? '';
$dob = $enc->decrypt($patient['M_PatientDOB_enc'] ?? '') ?? date('d-m-Y', strtotime($patient['M_PatientDOB'] ?? 'now'));
$hp = $enc->decrypt($patient['M_PatientHP_enc'] ?? '') ?? '';
$email = $enc->decrypt($patient['M_PatientEmail_enc'] ?? '') ?? '';
$address = $enc->decrypt($addr['M_PatientAddressDescription_enc'] ?? '') ?? '';
$this->db_onedev->query(
"DELETE FROM patient_print_cache
WHERE ppc_order_id = ?
OR ppc_created < NOW() - INTERVAL 5 MINUTE",
[$order_id]
);
$this->db_onedev->query(
"INSERT INTO patient_print_cache
(ppc_order_id, ppc_patient_id, ppc_name, ppc_dob, ppc_hp, ppc_email, ppc_address, ppc_created)
VALUES (?, ?, ?, ?, ?, ?, ?, NOW())",
[$order_id, $patient['M_PatientID'], $name, $dob, $hp, $email, $address]
);
return $this->db_onedev->insert_id();
}
private function _delete_cache($cache_id)
{
if ($cache_id) {
$this->db_onedev->query(
"DELETE FROM patient_print_cache WHERE ppc_id = ?",
[$cache_id]
);
}
$this->db_onedev->query(
"DELETE FROM patient_print_cache WHERE ppc_created < NOW() - INTERVAL 5 MINUTE"
);
}
private function _resolve_report_username()
{
if (!empty($this->sys_user['M_StaffName'])) {
return trim($this->sys_user['M_StaffName']);
}
if (!empty($this->sys_user['M_UserUsername'])) {
return trim($this->sys_user['M_UserUsername']);
}
if (!empty($this->sys_user['userName'])) {
return trim($this->sys_user['userName']);
}
return 'ADMIN';
}
private function _format_report_string_param($value)
{
return rawurlencode("'" . (string) $value . "'");
}
}

View File

@@ -0,0 +1,430 @@
<?php
class OutgoingRef_v3 extends MY_Controller
{
function __construct()
{
parent::__construct();
$this->db = $this->load->database("onedev", true);
}
function get_nonlab($type, $xid)
{
//mikro
if ($type == "mikro") {
$sql = "select * from other_mikro where Other_MikroID=? ";
$qry = $this->db->query($sql, array($xid));
$result = array();
if ($qry) {
$result["type"] = "mikro";
$rows = $qry->result_array();
if (count($rows) > 0) {
$result["header"] = $rows[0];
} else {
return array();
}
$sql = "select * from other_mikrodetails where Other_MikroDetailsOther_MikroID=? and
Other_MikroDetailsIsActive = 'Y' ";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"] = $qry->result_array();
}
}
return $result;
}
//cytologi
if ($type == "cytologi") {
$sql = "select * from other_cytologi where Other_CytologiID=? ";
$qry = $this->db->query($sql, array($xid));
$result = array();
if ($qry) {
$result["type"] = "cytologi";
$rows = $qry->result_array();
if (count($rows) > 0) {
$result["header"] = $rows[0];
} else {
return array();
}
$sql = "select * from other_cytologidetails where Other_CytologiDetailsOther_CytologiID=? and
Other_CytologiDetailsIsActive = 'Y' ";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"] = $qry->result_array();
}
}
return $result;
}
//fna
if ($type == "fna") {
$sql = "select * from other_fna where Other_FnaID=? ";
$qry = $this->db->query($sql, array($xid));
$result = array();
if ($qry) {
$result["type"] = "fna";
$rows = $qry->result_array();
if (count($rows) > 0) {
$result["header"] = $rows[0];
} else {
return array();
}
$sql = "select * from other_fnadetails where Other_FnaDetailsOther_FnaID=? and
Other_FnaDetailsIsActive = 'Y' ";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"] = $qry->result_array();
}
}
return $result;
}
//papsmear
//
if ($type == "papsmear") {
$sql = "select * from other_papsmear where Other_PapSmearID=? ";
$qry = $this->db->query($sql, array($xid));
$result = array();
if ($qry) {
$result["type"] = "papsmear";
$rows = $qry->result_array();
if (count($rows) > 0) {
$result["header"] = $rows[0];
} else {
return array();
}
$result["detail"] = array();
//bahan
$sql = "select * from other_papsmearbahan where Other_PapSmearBahanOther_PapSmearID = ?
and Other_PapSmearBahanIsActive='Y'";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"]["bahan"] = $qry->result_array();
}
//category
$sql = "select * from other_papsmearcategory
where Other_PapsmearCategoryOther_PapSmearID = ?
and Other_PapsmearCategoryIsActive='Y'";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"]["category"] = $qry->result_array();
}
// check
$sql = "select * from other_papsmearcheck
where Other_PapSmearCheckOther_PapSmearID= ?
and Other_PapSmearCheckIsActive='Y'";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"]["check"] = $qry->result_array();
}
// details
$sql = "select * from other_papsmeardetails
where Other_PapSmearDetailsOther_PapSmearID= ?
and Other_PapSmearDetailsIsActive='Y'";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"]["details"] = $qry->result_array();
}
// maturasi
$sql = "select * from other_papsmearmaturasi
where Other_PapSmearMaturasiOther_PapSmearID = ?
and Other_PapSmearMaturasiIsActive='Y'";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"]["maturasi"] = $qry->result_array();
}
}
return $result;
}
//lcprep
//
if ($type == "lcprep") {
$sql = "select * from other_lcprep where Other_LcprepID=? ";
$qry = $this->db->query($sql, array($xid));
$result = array();
if ($qry) {
$result["type"] = "lcprep";
$rows = $qry->result_array();
if (count($rows) > 0) {
$result["header"] = $rows[0];
} else {
return array();
}
$result["detail"] = array();
//adekuasi
$sql = "select * from other_lcprepadekuasi where Other_LcprepAdekuasiOther_LcprepID = ?
and Other_LcprepAdekuasiIsActive='Y'";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"]["adekuasi"] = $qry->result_array();
}
//interpretasi
$sql = "select * from other_lcprepinterpretasi
where Other_PapsmearInterpretasiOther_LcprepID = ?
and Other_PapsmearInterpretasiIsActive='Y'";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"]["interpretasi"] = $qry->result_array();
}
// details
$sql = "select * from other_lcprepdetails
where Other_LcprepDetailsOther_LcprepID= ?
and Other_LcprepDetailsIsActive='Y'";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"]["details"] = $qry->result_array();
}
// kategoriumum
$sql = "select * from other_lcprepkategoriumum
where Other_LcprepKategoriUmumOther_LcprepID = ?
and Other_LcprepKategoriUmumIsActive='Y'";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"]["kategoriumum"] = $qry->result_array();
}
}
return $result;
}
return array();
}
function process_nonlab($incomingRefDetailID)
{
//mikro
$sql = "select ifnull(Other_MikroID,0) mikroID
from incoming_ref_detail
join t_orderdetail on T_OrderDetailT_OrderHeaderID = incomingRefDetailNewT_OrderHeaderID
and T_OrderDetailT_TestID = incomingRefDetailT_TestID and T_OrderDetailIsActive = 'Y'
left join other_mikro on T_OrderDetailID = Other_MikroT_OrderDetailID and
Other_MikroIsActive = 'Y'
where incomingRefDetailID = ? ";
$qry = $this->db->query($sql, array($incomingRefDetailID));
if (! $qry) {
echo "ERR : process_nonlab : $incomingRefDetailID : " . print_r($this->db->error(), true) . "\n";
return "";
}
$rows = $qry->result_array();
if (count($rows) > 0) {
$mikroID = $rows[0]["mikroID"];
$nl = "";
if ($mikroID > 0) {
$nl = $this->get_nonlab("mikro", $mikroID);
return $nl;
}
}
//papsmear
$sql = "select ifnull(Other_PapSmearID,0) papsmearID
from incoming_ref_detail
join t_orderdetail on T_OrderDetailT_OrderHeaderID = incomingRefDetailNewT_OrderHeaderID
and T_OrderDetailT_TestID = incomingRefDetailT_TestID and T_OrderDetailIsActive = 'Y'
left join other_papsmear on T_OrderDetailID = Other_PapSmearT_OrderDetailID and
Other_PapSmearIsActive = 'Y'
where incomingRefDetailID = ? ";
$qry = $this->db->query($sql, array($incomingRefDetailID));
if (! $qry) {
echo "ERR : process_nonlab : $incomingRefDetailID : " . print_r($this->db->error(), true) . "\n";
return "";
}
$rows = $qry->result_array();
if (count($rows) > 0) {
$papsmearID = $rows[0]["papsmearID"];
$nl = "";
if ($papsmear > 0) {
$nl = $this->get_nonlab("papsmear", $papsmearID);
return $nl;
}
}
//lcprep
$sql = "select ifnull(Other_LcprepID,0) lcprepID
from incoming_ref_detail
join t_orderdetail on T_OrderDetailT_OrderHeaderID = incomingRefDetailNewT_OrderHeaderID
and T_OrderDetailT_TestID = incomingRefDetailT_TestID and T_OrderDetailIsActive = 'Y'
left join other_lcprep on T_OrderDetailID = Other_LcprepT_OrderDetailID and
Other_LcprepIsActive = 'Y'
where incomingRefDetailID = ? ";
$qry = $this->db->query($sql, array($incomingRefDetailID));
if (! $qry) {
echo "ERR : process_nonlab : $incomingRefDetailID : " . print_r($this->db->error(), true) . "\n";
return "";
}
$rows = $qry->result_array();
if (count($rows) > 0) {
$lcprepID = $rows[0]["lcprepID"];
$nl = "";
if ($lcprepID > 0) {
$nl = $this->get_nonlab("lcprep", $lcprepID);
return $nl;
}
}
//fna
$sql = "select ifnull(Other_FnaID,0) fnaID
from incoming_ref_detail
join t_orderdetail on T_OrderDetailT_OrderHeaderID = incomingRefDetailNewT_OrderHeaderID
and T_OrderDetailT_TestID = incomingRefDetailT_TestID and T_OrderDetailIsActive = 'Y'
left join other_fna on T_OrderDetailID = Other_FnaT_OrderDetailID and
Other_FnaIsActive = 'Y'
where incomingRefDetailID = ? ";
$qry = $this->db->query($sql, array($incomingRefDetailID));
if (! $qry) {
echo "ERR : process_nonlab : $incomingRefDetailID : " . print_r($this->db->error(), true) . "\n";
return "";
}
$rows = $qry->result_array();
if (count($rows) > 0) {
$fnaID = $rows[0]["fnaID"];
$nl = "";
if ($fnaID > 0) {
$nl = $this->get_nonlab("fna", $fnaID);
return $nl;
}
}
//
//cytology
$sql = "select ifnull(Other_CytologiID,0) cytologiID
from incoming_ref_detail
join t_orderdetail on T_OrderDetailT_OrderHeaderID = incomingRefDetailNewT_OrderHeaderID
and T_OrderDetailT_TestID = incomingRefDetailT_TestID and T_OrderDetailIsActive = 'Y'
left join other_cytologi on T_OrderDetailID = Other_CytologiT_OrderDetailID and
Other_CytologiIsActive = 'Y'
where incomingRefDetailID = ? ";
$qry = $this->db->query($sql, array($incomingRefDetailID));
if (! $qry) {
echo "ERR : process_nonlab : $incomingRefDetailID : " . print_r($this->db->error(), true) . "\n";
return "";
}
$rows = $qry->result_array();
if (count($rows) > 0) {
$cytologiID = $rows[0]["cytologiID"];
$nl = "";
if ($cytologiID > 0) {
$nl = $this->get_nonlab("cytologi", $cytologiID);
return $nl;
}
}
}
function process()
{
$sql = "select tx_branch_status.*, M_BranchName
from tx_branch_status
join m_branch on TxBranchStatusM_BranchID = M_BranchID
where TxBranchStatusIsSent = 'N' and TxBranchStatusRetry < 5
limit 0,20";
$qry = $this->db->query($sql);
$sql_update = "update tx_branch_status set TxBranchStatusIsSent=?,
TxBranchStatusRetry = TxBranchStatusRetry + 1
where TxBranchStatusID = ?";
if ($qry) {
$rows = $qry->result_array();
foreach ($rows as $r) {
$param = $r["TxBranchStatusJson"];
$stage = $r["TxBranchStatusStage"];
$ipAddress = $r["TxBranchStatusM_BranchIP"];
$branchName = $r["M_BranchName"];
$txID = $r["TxBranchStatusID"];
if ($stage == "VALIDATION") {
//cek nonlab
$j_param = json_decode($param, true);
foreach ($j_param as $idx => $j) {
if (isset($j["incomingRefDetailID"])) {
$nonlab_result = $this->process_nonlab($j["incomingRefDetailID"]);
if ($nonlab_result != array()) {
$j_param[$idx]["nonlab_result"] = $nonlab_result;
$param = json_encode($j_param);
}
}
}
}
$url = "http://$ipAddress/one-api-lab/tools/xstatusbranch_v3/update";
$rst = $this->post($url, $param);
if ($rst["status"] == "OK") {
$this->xlog("Update status $stage to $branchName @ $ipAddress [OK]");
$this->db->query($sql_update, array('Y', $txID));
} else {
$err_msg = print_r($rst, true);
$this->xlog("Update status $stage to $branchName @ $ipAddress [ERR] : $err_msg");
$this->db->query($sql_update, array('N', $txID));
}
}
} else {
$this->xlog("Err: " . print_r($this->db->error(), true));
}
}
function xlog($message)
{
$dt = date("Y-m-d H:i:s");
echo "$dt $message\n";
}
function status($incomingRefID)
{
$sql = "select * from incoming_ref where incomingRefID = ?";
$qry = $this->db->query($sql, array($incomingRefID));
$rows = array();
$branchID = 0;
if ($qry) {
$rows = $qry->result_array();
if (count($rows) > 0) $branchID = $rows[0]["incomingRefM_BranchID"];
}
$ip_address = "";
if ($branchID > 0) {
$sql = "select *
from m_branch where M_BranchID = ?";
$qry = $this->db->query($sql, array($branchID));
if ($qry) {
$rows = $qry->result_array();
if (count($rows) > 0) $ip_address = $rows[0]["M_BranchIPAddress"];
}
}
if ($ip_address == "") {
echo "No IP Address from $branchID ";
exit;
}
$sql = "select
incomingRefT_RefDeliveryOrderID,
incomingRefDetailT_OrderDetailID,
incomingRefDetailStatus,
T_OrderDetailResult,
T_OrderDetailNat_NormalValueID,
T_OrderDetailVerification,
T_OrderDetailValidation
from incoming_ref_detail
join incoming_ref on incomingRefID = incomingRefDetailIncomingRefID
and incomingRefID = ?
left join t_orderdetail on incomingRefDetailNewT_OrderHeaderID = T_OrderDetailT_OrderHeaderID
and T_OrderDetailIsActive = 'Y' and incomingRefDetailT_TestID = T_OrderDetailT_TestID";
$qry = $this->db->query($sql, array($incomingRefID));
if ($qry) {
$rows = $qry->result_array();
$param = json_encode($rows);
$url = "http://$ip_address/one-api/tools/xstatusbranch_v2/update";
$result = $this->post($url, $param);
}
}
function post($url, $data)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt(
$ch,
CURLOPT_HTTPHEADER,
array(
'Content-Type: application/json',
'Content-Length: ' . strlen($data)
)
);
$result = curl_exec($ch);
curl_close($ch);
if ($result === false) {
return array(
"status" => "ERR",
"message" => curl_error($ch)
);
}
$rst = json_decode($result, true);
return $rst;
}
}

View File

@@ -1,21 +1,23 @@
<?php
class OutgoingRef_v4 extends MY_Controller
{
function __construct() {
function __construct()
{
parent::__construct();
$this->db = $this->load->database("onedev", true);
}
function get_nonlab($type,$xid) {
function get_nonlab($type, $xid)
{
//mikro
if ($type == "mikro") {
$sql = "select * from other_mikro where Other_MikroID=? ";
$qry = $this->db->query($sql, array($xid));
$result = array() ;
if ($qry ) {
$result = array();
if ($qry) {
$result["type"] = "mikro";
$rows = $qry->result_array();
if (count($rows) > 0 ) {
$result["header"]= $rows[0];
$rows = $qry->result_array();
if (count($rows) > 0) {
$result["header"] = $rows[0];
} else {
return array();
}
@@ -23,8 +25,8 @@ class OutgoingRef_v4 extends MY_Controller
Other_MikroDetailsIsActive = 'Y' ";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"] = $qry->result_array();
}
$result["detail"] = $qry->result_array();
}
}
return $result;
}
@@ -33,12 +35,12 @@ class OutgoingRef_v4 extends MY_Controller
if ($type == "cytologi") {
$sql = "select * from other_cytologi where Other_CytologiID=? ";
$qry = $this->db->query($sql, array($xid));
$result = array() ;
if ($qry ) {
$result = array();
if ($qry) {
$result["type"] = "cytologi";
$rows = $qry->result_array();
if (count($rows) > 0 ) {
$result["header"]= $rows[0];
$rows = $qry->result_array();
if (count($rows) > 0) {
$result["header"] = $rows[0];
} else {
return array();
}
@@ -46,8 +48,8 @@ class OutgoingRef_v4 extends MY_Controller
Other_CytologiDetailsIsActive = 'Y' ";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"] = $qry->result_array();
}
$result["detail"] = $qry->result_array();
}
}
return $result;
}
@@ -56,12 +58,12 @@ class OutgoingRef_v4 extends MY_Controller
if ($type == "fna") {
$sql = "select * from other_fna where Other_FnaID=? ";
$qry = $this->db->query($sql, array($xid));
$result = array() ;
if ($qry ) {
$result = array();
if ($qry) {
$result["type"] = "fna";
$rows = $qry->result_array();
if (count($rows) > 0 ) {
$result["header"]= $rows[0];
$rows = $qry->result_array();
if (count($rows) > 0) {
$result["header"] = $rows[0];
} else {
return array();
}
@@ -69,8 +71,8 @@ class OutgoingRef_v4 extends MY_Controller
Other_FnaDetailsIsActive = 'Y' ";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"] = $qry->result_array();
}
$result["detail"] = $qry->result_array();
}
}
return $result;
}
@@ -80,12 +82,12 @@ class OutgoingRef_v4 extends MY_Controller
if ($type == "papsmear") {
$sql = "select * from other_papsmear where Other_PapSmearID=? ";
$qry = $this->db->query($sql, array($xid));
$result = array() ;
if ($qry ) {
$result = array();
if ($qry) {
$result["type"] = "papsmear";
$rows = $qry->result_array();
if (count($rows) > 0 ) {
$result["header"]= $rows[0];
$rows = $qry->result_array();
if (count($rows) > 0) {
$result["header"] = $rows[0];
} else {
return array();
}
@@ -95,40 +97,40 @@ class OutgoingRef_v4 extends MY_Controller
and Other_PapSmearBahanIsActive='Y'";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"]["bahan"] = $qry->result_array();
}
$result["detail"]["bahan"] = $qry->result_array();
}
//category
$sql = "select * from other_papsmearcategory
where Other_PapsmearCategoryOther_PapSmearID = ?
and Other_PapsmearCategoryIsActive='Y'";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"]["category"] = $qry->result_array();
$result["detail"]["category"] = $qry->result_array();
}
// check
// check
$sql = "select * from other_papsmearcheck
where Other_PapSmearCheckOther_PapSmearID= ?
and Other_PapSmearCheckIsActive='Y'";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"]["check"] = $qry->result_array();
}
$result["detail"]["check"] = $qry->result_array();
}
// details
$sql = "select * from other_papsmeardetails
where Other_PapSmearDetailsOther_PapSmearID= ?
and Other_PapSmearDetailsIsActive='Y'";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"]["details"] = $qry->result_array();
}
$result["detail"]["details"] = $qry->result_array();
}
// maturasi
$sql = "select * from other_papsmearmaturasi
where Other_PapSmearMaturasiOther_PapSmearID = ?
and Other_PapSmearMaturasiIsActive='Y'";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"]["maturasi"] = $qry->result_array();
}
$result["detail"]["maturasi"] = $qry->result_array();
}
}
return $result;
}
@@ -138,12 +140,12 @@ class OutgoingRef_v4 extends MY_Controller
if ($type == "lcprep") {
$sql = "select * from other_lcprep where Other_LcprepID=? ";
$qry = $this->db->query($sql, array($xid));
$result = array() ;
if ($qry ) {
$result = array();
if ($qry) {
$result["type"] = "lcprep";
$rows = $qry->result_array();
if (count($rows) > 0 ) {
$result["header"]= $rows[0];
$rows = $qry->result_array();
if (count($rows) > 0) {
$result["header"] = $rows[0];
} else {
return array();
}
@@ -153,15 +155,15 @@ class OutgoingRef_v4 extends MY_Controller
and Other_LcprepAdekuasiIsActive='Y'";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"]["adekuasi"] = $qry->result_array();
}
$result["detail"]["adekuasi"] = $qry->result_array();
}
//interpretasi
$sql = "select * from other_lcprepinterpretasi
where Other_PapsmearInterpretasiOther_LcprepID = ?
and Other_PapsmearInterpretasiIsActive='Y'";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"]["interpretasi"] = $qry->result_array();
$result["detail"]["interpretasi"] = $qry->result_array();
}
// details
$sql = "select * from other_lcprepdetails
@@ -169,23 +171,24 @@ class OutgoingRef_v4 extends MY_Controller
and Other_LcprepDetailsIsActive='Y'";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"]["details"] = $qry->result_array();
}
$result["detail"]["details"] = $qry->result_array();
}
// kategoriumum
$sql = "select * from other_lcprepkategoriumum
where Other_LcprepKategoriUmumOther_LcprepID = ?
and Other_LcprepKategoriUmumIsActive='Y'";
$qry = $this->db->query($sql, array($xid));
if ($qry) {
$result["detail"]["kategoriumum"] = $qry->result_array();
}
$result["detail"]["kategoriumum"] = $qry->result_array();
}
}
return $result;
}
return array();
}
function process_nonlab($incomingRefDetailID) {
function process_nonlab($incomingRefDetailID)
{
//mikro
$sql = "select ifnull(Other_MikroID,0) mikroID
from incoming_ref_detail
@@ -194,19 +197,19 @@ class OutgoingRef_v4 extends MY_Controller
left join other_mikro on T_OrderDetailID = Other_MikroT_OrderDetailID and
Other_MikroIsActive = 'Y'
where incomingRefDetailID = ? ";
$qry = $this->db->query($sql,array($incomingRefDetailID));
if ( ! $qry ) {
echo "ERR : process_nonlab : $incomingRefDetailID : " . print_r($this->db->error(),true) . "\n";
$qry = $this->db->query($sql, array($incomingRefDetailID));
if (! $qry) {
echo "ERR : process_nonlab : $incomingRefDetailID : " . print_r($this->db->error(), true) . "\n";
return "";
}
$rows = $qry->result_array();
if ( count($rows) > 0 ) {
if (count($rows) > 0) {
$mikroID = $rows[0]["mikroID"];
$nl = "";
if ($mikroID > 0 ) {
if ($mikroID > 0) {
$nl = $this->get_nonlab("mikro", $mikroID);
return $nl;
}
}
}
//papsmear
@@ -217,19 +220,19 @@ class OutgoingRef_v4 extends MY_Controller
left join other_papsmear on T_OrderDetailID = Other_PapSmearT_OrderDetailID and
Other_PapSmearIsActive = 'Y'
where incomingRefDetailID = ? ";
$qry = $this->db->query($sql,array($incomingRefDetailID));
if ( ! $qry ) {
echo "ERR : process_nonlab : $incomingRefDetailID : " . print_r($this->db->error(),true) . "\n";
$qry = $this->db->query($sql, array($incomingRefDetailID));
if (! $qry) {
echo "ERR : process_nonlab : $incomingRefDetailID : " . print_r($this->db->error(), true) . "\n";
return "";
}
$rows = $qry->result_array();
if ( count($rows) > 0 ) {
if (count($rows) > 0) {
$papsmearID = $rows[0]["papsmearID"];
$nl = "";
if ($papsmear> 0 ) {
if ($papsmear > 0) {
$nl = $this->get_nonlab("papsmear", $papsmearID);
return $nl;
}
}
}
//lcprep
@@ -240,19 +243,19 @@ class OutgoingRef_v4 extends MY_Controller
left join other_lcprep on T_OrderDetailID = Other_LcprepT_OrderDetailID and
Other_LcprepIsActive = 'Y'
where incomingRefDetailID = ? ";
$qry = $this->db->query($sql,array($incomingRefDetailID));
if ( ! $qry ) {
echo "ERR : process_nonlab : $incomingRefDetailID : " . print_r($this->db->error(),true) . "\n";
$qry = $this->db->query($sql, array($incomingRefDetailID));
if (! $qry) {
echo "ERR : process_nonlab : $incomingRefDetailID : " . print_r($this->db->error(), true) . "\n";
return "";
}
$rows = $qry->result_array();
if ( count($rows) > 0 ) {
if (count($rows) > 0) {
$lcprepID = $rows[0]["lcprepID"];
$nl = "";
if ($lcprepID > 0 ) {
if ($lcprepID > 0) {
$nl = $this->get_nonlab("lcprep", $lcprepID);
return $nl;
}
}
}
//fna
@@ -263,19 +266,19 @@ class OutgoingRef_v4 extends MY_Controller
left join other_fna on T_OrderDetailID = Other_FnaT_OrderDetailID and
Other_FnaIsActive = 'Y'
where incomingRefDetailID = ? ";
$qry = $this->db->query($sql,array($incomingRefDetailID));
if ( ! $qry ) {
echo "ERR : process_nonlab : $incomingRefDetailID : " . print_r($this->db->error(),true) . "\n";
$qry = $this->db->query($sql, array($incomingRefDetailID));
if (! $qry) {
echo "ERR : process_nonlab : $incomingRefDetailID : " . print_r($this->db->error(), true) . "\n";
return "";
}
$rows = $qry->result_array();
if ( count($rows) > 0 ) {
if (count($rows) > 0) {
$fnaID = $rows[0]["fnaID"];
$nl = "";
if ($fnaID > 0 ) {
if ($fnaID > 0) {
$nl = $this->get_nonlab("fna", $fnaID);
return $nl;
}
}
}
//
//cytology
@@ -286,22 +289,23 @@ class OutgoingRef_v4 extends MY_Controller
left join other_cytologi on T_OrderDetailID = Other_CytologiT_OrderDetailID and
Other_CytologiIsActive = 'Y'
where incomingRefDetailID = ? ";
$qry = $this->db->query($sql,array($incomingRefDetailID));
if ( ! $qry ) {
echo "ERR : process_nonlab : $incomingRefDetailID : " . print_r($this->db->error(),true) . "\n";
$qry = $this->db->query($sql, array($incomingRefDetailID));
if (! $qry) {
echo "ERR : process_nonlab : $incomingRefDetailID : " . print_r($this->db->error(), true) . "\n";
return "";
}
$rows = $qry->result_array();
if ( count($rows) > 0 ) {
if (count($rows) > 0) {
$cytologiID = $rows[0]["cytologiID"];
$nl = "";
if ($cytologiID > 0 ) {
if ($cytologiID > 0) {
$nl = $this->get_nonlab("cytologi", $cytologiID);
return $nl;
}
}
}
}
function cek() {
function cek()
{
$sql = "select tx_branch_status.*, M_BranchName
from tx_branch_status
join m_branch on TxBranchStatusM_BranchID = M_BranchID
@@ -318,7 +322,8 @@ class OutgoingRef_v4 extends MY_Controller
print_r($rows);
}
}
function process() {
function process()
{
$sql = "select tx_branch_status.*, M_BranchName
from tx_branch_status
join m_branch on TxBranchStatusM_BranchID = M_BranchID
@@ -338,7 +343,7 @@ class OutgoingRef_v4 extends MY_Controller
where TxBranchStatusID = ?";
if ($qry) {
$rows = $qry->result_array();
foreach($rows as $r) {
foreach ($rows as $r) {
$param = $r["TxBranchStatusJson"];
$stage = $r["TxBranchStatusStage"];
$ipAddress = $r["TxBranchStatusM_BranchIP"];
@@ -346,57 +351,69 @@ class OutgoingRef_v4 extends MY_Controller
$txID = $r["TxBranchStatusID"];
if ($stage == "VALIDATION") {
//cek nonlab
$j_param = json_decode($param,true);
foreach($j_param as $idx => $j ) {
$j_param = json_decode($param, true);
foreach ($j_param as $idx => $j) {
if (isset($j["incomingRefDetailID"])) {
$nonlab_result = $this->process_nonlab( $j["incomingRefDetailID"] );
if ($nonlab_result != array() ) {
$nonlab_result = $this->process_nonlab($j["incomingRefDetailID"]);
if ($nonlab_result != array()) {
$j_param[$idx]["nonlab_result"] = $nonlab_result;
$param = json_encode($j_param);
}
}
}
}
$url = "http://$ipAddress/one-api/tools/xstatusbranch_v4/update";
$rst = $this->post($url,$param);
if ($rst["status"] == "OK" ) {
$url = "http://$ipAddress/one-api-lab/tools/xstatusbranch_v4/update";
$rst = $this->post($url, $param);
if ($rst["status"] == "OK") {
$this->xlog("Update status $stage to $branchName @ $ipAddress [OK]");
$this->db->query($sql_update, array('Y',$txID));
$this->db->query($sql_update, array('Y', $txID));
} else {
$err_msg = print_r($rst,true);
$err_msg = print_r($rst, true);
$this->xlog("Update status $stage to $branchName @ $ipAddress [ERR] : $err_msg");
$this->db->query($sql_update, array('N',$txID));
}
$this->db->query($sql_update, array('N', $txID));
}
}
} else {
$this->xlog("Err: " . print_r($this->db->error(),true));
$this->xlog("Err: " . print_r($this->db->error(), true));
}
}
function xlog($message) {
function xlog($message)
{
$dt = date("Y-m-d H:i:s");
echo "$dt $message\n";
}
function post($url,$data) {
$zdata = gzdeflate($data,9);
$ch = curl_init($url);
$this->xlog("Post to : " . $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $zdata);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($zdata))
);
function post($url, $data)
{
$zdata = gzdeflate($data, 9);
$ch = curl_init($url);
$this->xlog("Post to : " . $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $zdata);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt(
$ch,
CURLOPT_HTTPHEADER,
array(
'Content-Type: application/json',
'Content-Length: ' . strlen($zdata)
)
);
$result = curl_exec($ch);
$curl_error = curl_error($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($result === false ) {
return array("status" => "ERR" ,
"message" => curl_error($ch)
if ($result === false) {
return array(
"status" => "ERR",
"message" => $curl_error,
"http_code" => $http_code
);
}
$rst = json_decode($result,true);
return $rst;
}
}
$rst = json_decode($result, true);
return $rst;
}
}

View File

@@ -0,0 +1,542 @@
<?php
defined('BASEPATH') or exit('No direct script access allowed');
/**
* Rpt_lab_result — FPDF-based lab result report
* Endpoint: GET /tools/rpt_lab_result/pdf?token=...&PT_OrderHeaderID=...
*
* Menggunakan sp_rpt_hasil_header untuk data pasien,
* query langsung untuk detail hasil pemeriksaan.
* Cache PDP di-populate sebelum call SP lalu dihapus setelah selesai.
*/
class Rpt_lab_result extends MY_Controller
{
public $db_onedev;
public function __construct()
{
parent::__construct();
$this->db_onedev = $this->load->database('onedev', true);
$this->load->library('ibl_patient_decrypt');
}
public function index()
{
$this->sys_ok(['message' => 'Use /tools/rpt_lab_result/pdf?PT_OrderHeaderID=<id>']);
}
public function pdf()
{
try {
$order_id = $this->_get_order_id();
if ($order_id <= 0) {
$this->sys_error('PT_OrderHeaderID wajib diisi');
return;
}
$username = trim($this->input->get('username', true) ?? $this->input->post('username', true) ?? '');
if ($username === '') {
$username = $this->sys_user['M_StaffName'] ?? $this->sys_user['M_UserUsername'] ?? 'ADMIN';
}
// Populate cache PDP
$cache_id = $this->ibl_patient_decrypt->populate_cache_by_order($order_id);
// Header data via SP
$header = $this->_fetch_header($order_id, $username);
if (!$header) {
$this->ibl_patient_decrypt->delete_cache($cache_id);
$this->sys_error('Data order tidak ditemukan');
return;
}
// Detail hasil pemeriksaan
$details = $this->_fetch_details($order_id, $username);
// Sampling data
$sampling = $this->_fetch_sampling($order_id);
// Company info (address, phone IBL)
$company_info = $this->_fetch_company_info();
// Delete cache setelah data diambil
$this->ibl_patient_decrypt->delete_cache($cache_id);
// Generate PDF
$pdf_bytes = $this->_build_pdf($header, $details, $sampling, $company_info, $username);
$filename = 'lab_result_' . $order_id . '_' . date('Ymd') . '.pdf';
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename="' . $filename . '"');
header('Content-Length: ' . strlen($pdf_bytes));
echo $pdf_bytes;
exit;
} catch (Exception $e) {
$this->sys_error($e->getMessage());
}
}
// -------------------------------------------------------------------------
// Data fetching
// -------------------------------------------------------------------------
public function data()
{
$order_id = $this->_get_order_id();
if ($order_id <= 0) { $this->sys_error('PT_OrderHeaderID wajib'); return; }
$username = $this->input->get('username', true) ?: 'ADMIN';
$details = $this->_fetch_details($order_id, $username);
$this->sys_ok(['count' => count($details), 'rows' => array_slice($details, 0, 5), 'last_query' => $this->db_onedev->last_query()]);
}
private function _fetch_header($order_id, $username)
{
$qry = $this->db_onedev->query('CALL sp_rpt_hasil_header(?, ?)', [$order_id, $username]);
if (!$qry) return null;
$row = $qry->row_array();
if (method_exists($this, 'clean_mysqli_connection')) {
$this->clean_mysqli_connection($this->db_onedev->conn_id);
} else {
$this->_clean_multi_result();
}
return $row ?: null;
}
private function _fetch_sampling($order_id)
{
$qry = $this->db_onedev->query('CALL sp_rpt_hasil_lab_sampling(?, ?)', [$order_id, '']);
if (!$qry) return [];
$rows = $qry->result_array();
if (method_exists($this, 'clean_mysqli_connection')) {
$this->clean_mysqli_connection($this->db_onedev->conn_id);
} else {
$this->_clean_multi_result();
}
return $rows;
}
private function _fetch_details($order_id, $username = '')
{
$qry = $this->db_onedev->query('CALL sp_rpt_hasil_lab(?, ?)', [$order_id, $username]);
if (!$qry) return [];
$rows = $qry->result_array();
if (method_exists($this, 'clean_mysqli_connection')) {
$this->clean_mysqli_connection($this->db_onedev->conn_id);
} else {
$this->_clean_multi_result();
}
return $rows;
}
private function _fetch_company_info()
{
$row = $this->db_onedev->query(
"SELECT S_SystemsCompanyAddress, S_SystemsCompanyCity, S_SystemsCompanyPhone, S_SystemsCompanyName FROM conf_systems LIMIT 1"
)->row_array();
return $row ?: [];
}
// -------------------------------------------------------------------------
// PDF builder
// -------------------------------------------------------------------------
private function _build_pdf(array $h, array $details, array $sampling, array $co, $username)
{
require_once APPPATH . 'third_party/fpdf/fpdf.php';
// Footer data
$validator_name = '';
foreach ($details as $d) {
if (!empty($d['M_StaffName'])) { $validator_name = $d['M_StaffName']; }
}
$lab_number = $this->_s($h['T_OrderHeaderLabNumber'] ?? '');
$print_username = $this->_s($username);
$print_datetime = date('d-m-Y H:i:s');
$pv = $validator_name;
$pu = $print_username;
$pd = $print_datetime;
$pln = $lab_number;
$pdf = new class($pu, $pd, $pln, $pv) extends FPDF {
private $pu, $pd, $pln, $pv;
public function __construct($pu, $pd, $pln, $pv) {
parent::__construct('P', 'mm', 'A4');
$this->pu = $pu; $this->pd = $pd; $this->pln = $pln; $this->pv = $pv;
}
public function Footer() {
$ml = 10; $cw = $this->GetPageWidth() - 20;
$this->SetFont('Helvetica', '', 10);
// Validasi Oleh (kanan)
$this->SetY(-38);
$this->SetX($ml);
$this->Cell($cw, 5, 'Validasi Oleh', 0, 1, 'R');
$this->Ln(8);
// Garis tanda tangan (kanan 40%)
$this->SetX($ml + $cw * 0.62);
$this->Cell($cw * 0.38, 0.3, '', 'T', 1);
// Nama validator (kanan)
$this->SetX($ml);
$this->Cell($cw, 5, iconv('UTF-8', 'windows-1252//TRANSLIT', (string) $this->pv), 0, 1, 'R');
$this->Ln(2);
// Printed by (kiri)
$printed = 'Printed by : ' . $this->pu . ' / ' . $this->pd . ' / ' . $this->pln;
$this->SetX($ml);
$this->Cell($cw, 5, $printed, 0, 0, 'L');
$this->Ln();
// Page number (tengah)
$this->SetX($ml);
$this->Cell($cw, 5, $this->PageNo() . ' / {nb}', 0, 0, 'C');
}
};
$pdf->AliasNbPages('{nb}');
$pdf->SetMargins(9, 8, 9);
$pdf->SetAutoPageBreak(true, 42);
$pdf->AddPage();
$pw = $pdf->GetPageWidth(); // 210
$ml = 9;
$mr = 9;
$cw = $pw - $ml - $mr; // 190
// Form revision number
$form_row = $this->db_onedev->query(
"SELECT IFNULL(M_No_FormRev,'') AS M_No_FormRev FROM m_no_form WHERE M_No_FormName='LAB' AND M_No_FormIsActive='Y' LIMIT 1"
);
$form_rev = $form_row ? $this->_s($form_row->row_array()['M_No_FormRev'] ?? '') : '';
// ── Pojok kanan atas: lab number + form rev ───────────────────────────
$pdf->SetFont('Arial', '', 7);
$pdf->SetXY($ml, 4);
$top_right = trim($lab_number . ($form_rev ? ' ' . $form_rev : ''));
$pdf->Cell($cw, 5, $top_right, 0, 1, 'R');
// ── Kop atas ──────────────────────────────────────────────────────────
$company_addr = $this->_s($co['S_SystemsCompanyAddress'] ?? 'Jl. LL. RE. Martadinata No. 135');
$company_city = $this->_s($co['S_SystemsCompanyCity'] ?? 'Bandung');
$company_phone = $this->_s($co['S_SystemsCompanyPhone'] ?? '(022)7271946');
$addr_line = $company_addr . ' ' . $company_city . ' Telp. ' . $company_phone;
$pj_name = $this->_s($h['M_DoctorName'] ?? '');
$pdf->SetFont('Arial', '', 9);
$pdf->SetXY($ml, 8);
$pdf->Cell($cw / 2, 5, $addr_line, 0, 0, 'L');
$pdf->SetX($ml + $cw / 2);
$pdf->Cell($cw / 2, 5, 'Penanggung Jawab : ' . $pj_name, 0, 1, 'R');
$pdf->SetLineWidth(0.8);
$pdf->Line($ml, 13.5, $ml + $cw, 13.5);
$pdf->SetLineWidth(0.2);
$pdf->SetY(15);
// ── Patient info (2 columns) ──────────────────────────────────────────
$lw = 94;
$rw = $cw - $lw;
$lbl_w = 30;
$col_w = 4;
$val_w = $lw - $lbl_w - $col_w;
$lbl_rw = 30;
$val_rw = $rw - $lbl_rw - $col_w;
$pid = $this->_s($h['T_OrderHeaderLabNumber'] ?? '-');
$left_rows = [
['NO. REG', $this->_s($h['M_PatientNoReg'] ?? '-')],
['NAMA', $this->_s($h['M_PatientName'] ?? '-')],
['PENGIRIM', $this->_s($h['M_DoctorName2'] ?? '-')],
['KEL. PELANGGAN*', $this->_s($h['CorporateName'] ?? '-')],
['ALAMAT', $this->_s($h['M_PatientAddress'] ?? '-')],
];
$right_rows = [
['TANGGAL REG', $this->_s($h['T_OrderHeaderDate'] ?? '-')],
['PID', $pid],
['JENIS KELAMIN', $this->_s($h['Gender'] ?? '-')],
['TGL. LAHIR / USIA', $this->_s($h['Umur'] ?? '-')],
['NO. TLP. / HP', $this->_s($h['M_PatientHp'] ?? '-')],
];
$fnt = 'Arial';
$fs = 8.5;
$y_info_start = $pdf->GetY();
$barcode_x = $ml + $lw + 4;
$barcode_y = $y_info_start;
$barcode_w = 58;
$barcode_h = 8;
$this->_draw_fake_barcode($pdf, $barcode_x, $barcode_y, $barcode_w, $barcode_h, $pid);
$y_left_cur = $y_info_start + 1;
$y_right_cur = $y_info_start + 10;
foreach ($left_rows as $r) {
$y_left_cur = $this->_draw_header_row($pdf, $ml, $y_left_cur, $lbl_w, $col_w, $val_w, $r[0], $r[1], $fnt, $fs);
}
foreach ($right_rows as $r) {
$y_right_cur = $this->_draw_header_row($pdf, $ml + $lw + 4, $y_right_cur, $lbl_rw, $col_w, $val_rw - 4, $r[0], $r[1], $fnt, $fs);
}
$pdf->SetY(max($y_left_cur, $y_right_cur) + 10);
// ── Table header ─────────────────────────────────────────────────────
$col = ['JENIS PEMERIKSAAN' => 64, 'HASIL' => 24, 'NILAI RUJUKAN' => 43, 'SATUAN' => 24, 'METODE' => 37];
$col_w_arr = array_values($col);
$row_h = 5.2;
$y_table_start = $pdf->GetY();
$pdf->SetFont($fnt, 'B', 8.8);
$pdf->SetX($ml);
foreach ($col as $label => $w) {
$pdf->Cell($w, $row_h + 1.8, $label, '1', 0, 'C');
}
$pdf->Ln();
// ── Table rows ────────────────────────────────────────────────────────
// Strategy:
// - Group/SubSubGroup rows : full-width text only, tanpa border bawah
// - Test rows : text per kolom + separator full-width manual
// - Outer L/R/T/B : drawn via Rect() after all rows
$prev_subgroup = null;
$prev_subsubgroup = null;
$qr_url = '';
foreach ($details as $d) {
$subgroup = strtoupper(trim($d['Nat_SubGroupName'] ?? ''));
$subsubgroup = trim($d['Nat_SubSubGroupName'] ?? '');
$sascode_len = strlen(trim($d['T_TestSasCode'] ?? ''));
$test_name = $this->_s(trim($d['T_TestName'] ?? ''));
$result = $this->_s(trim(strip_tags($d['T_OrderDetailResult'] ?? '')));
$normal = $this->_s(trim($d['T_OrderDetailNormalValueNote'] ?? $d['T_OrderDetailNormalValueDescription'] ?? ''));
$unit = $this->_s(trim($d['T_OrderDetailNat_UnitName'] ?? ''));
$method = $this->_s(trim($d['T_OrderdetailNat_MethodeName'] ?? $d['methodeName'] ?? ''));
$flag = trim($d['T_OrderDetailResultFlag'] ?? '');
$is_abnormal = ($flag !== '' && $flag !== 'N');
if (empty($qr_url) && !empty($d['qrreport'])) {
$qr_url = $d['qrreport'];
}
// Level 1: SubGroup — bold, full-width, tanpa separator
if ($subgroup !== '' && $subgroup !== $prev_subgroup) {
$pdf->SetX($ml);
$pdf->SetFont($fnt, 'B', 8.8);
$pdf->Cell($cw, $row_h, $subgroup, 0, 1, 'L');
$prev_subgroup = $subgroup; $prev_subsubgroup = null;
}
// Level 2: SubSubGroup — italic, full-width, tanpa separator
if ($subsubgroup !== '' && $subsubgroup !== $prev_subsubgroup) {
$pdf->SetX($ml);
$pdf->SetFont($fnt, 'I', 8.6);
$pdf->Cell($cw, $row_h, ' ' . $this->_s($subsubgroup), 0, 1, 'L');
$prev_subsubgroup = $subsubgroup;
}
// Level 3: Test row — indent via spaces, separator full-width
$sp = 0; $prefix = '';
if ($sascode_len >= 10 && $sascode_len < 12) { $sp = 2; }
elseif ($sascode_len >= 12 && $sascode_len < 14) { $sp = 4; $prefix = chr(183) . ' '; }
elseif ($sascode_len >= 14) { $sp = 6; $prefix = chr(183) . ' '; }
$display_name = str_repeat(' ', $sp) . $prefix . $test_name;
$pdf->SetFont($fnt, $is_abnormal ? 'B' : '', 8.2);
$y_start = $pdf->GetY();
// Hitung row height
$row_height = $row_h;
$texts = [$display_name, $result, $normal, $unit, $method];
foreach ($texts as $i => $txt) {
$lines = $this->_estimate_text_lines($pdf, $col_w_arr[$i] - 2, $txt);
$row_height = max($row_height, $lines * $row_h);
}
// Render cells tanpa border, lalu gambar separator full-width manual
$x_cur = $ml;
foreach ($texts as $i => $txt) {
$w = $col_w_arr[$i];
$align = ($i === 1) ? 'C' : 'L';
$pdf->SetXY($x_cur, $y_start);
$pdf->Cell($w, $row_height, $txt, 0, 0, $align);
$x_cur += $w;
}
$pdf->Line($ml, $y_start + $row_height, $ml + $cw, $y_start + $row_height);
$pdf->SetXY($ml, $y_start + $row_height);
}
// Outer rectangle — clean single-weight border for entire table
$y_table_end = $pdf->GetY();
$pdf->Rect($ml, $y_table_start, $cw, $y_table_end - $y_table_start);
// ── Catatan ───────────────────────────────────────────────────────────
$pdf->Ln(3);
$pdf->SetFont($fnt, '', 8.2);
$pdf->SetX($ml);
$pdf->Cell($cw, $row_h, 'Catatan :', 0, 1, 'L');
$pdf->Ln(2);
// ── Waktu Pengambilan Spesimen ────────────────────────────────────────
if (!empty($sampling)) {
$pdf->SetFont($fnt, '', 8.2);
$pdf->SetX($ml);
$pdf->Cell($cw, $row_h, 'Waktu Pengambilan Spesimen', 0, 1, 'L');
foreach ($sampling as $s) {
$bahan = $this->_s($s['T_BahanName'] ?? '');
$tgl = $this->_s($s['sampling_date'] ?? '');
$jam = $this->_s($s['sample_time'] ?? '');
$pdf->SetX($ml);
$pdf->Cell(35, $row_h, $bahan, 0, 0, 'L');
$pdf->Cell(4, $row_h, ':', 0, 0, 'C');
$pdf->Cell(35, $row_h, $tgl, 0, 0, 'L');
$pdf->Cell(30, $row_h, $jam, 0, 1, 'L');
}
}
// ── QR code (absolute, 20mm di atas footer = -42-3 = -45 dari bawah) ──
if (!empty($qr_url)) {
$tmp = $this->_fetch_image_to_temp($qr_url);
if ($tmp) {
$page_h = $pdf->GetPageHeight();
$qr_y = $page_h - 42 - 3 - 20; // footer_margin=42, gap=3, qr_h=20
$pdf->Image($tmp, $ml, $qr_y, 20, 20);
@unlink($tmp);
}
}
return $pdf->Output('S');
}
// -------------------------------------------------------------------------
// Helpers
// -------------------------------------------------------------------------
private function _get_order_id()
{
foreach (['PT_OrderHeaderID', 'PID', 'order_id'] as $k) {
$v = $this->input->get($k, true) ?? $this->input->post($k, true) ?? ($this->sys_input[$k] ?? null);
if ($v !== null && $v !== '') return intval($v);
}
return 0;
}
private function _draw_header_row($pdf, $x, $y, $label_w, $colon_w, $value_w, $label, $value, $font, $font_size)
{
$label = $this->_s($label);
$value = $this->_s($value);
$line_h = 5.2;
$pdf->SetFont($font, 'B', $font_size);
$pdf->SetXY($x, $y);
$pdf->Cell($label_w, $line_h, $label, 0, 0, 'L');
$pdf->SetFont($font, '', $font_size);
$pdf->Cell($colon_w, $line_h, ':', 0, 0, 'C');
$value_lines = $this->_estimate_text_lines($pdf, $value_w, $value);
$row_h = max(1, $value_lines) * $line_h;
$pdf->SetXY($x + $label_w + $colon_w, $y);
$pdf->MultiCell($value_w, $line_h, $value, 0, 'L');
return $y + $row_h;
}
private function _estimate_text_lines($pdf, $width, $text)
{
$text = str_replace("\r", '', (string) $text);
if ($text === '') {
return 1;
}
$lines = explode("\n", $text);
$count = 0;
foreach ($lines as $line) {
$line = trim($line);
if ($line === '') {
$count++;
continue;
}
$words = preg_split('/\s+/', $line);
$current = '';
foreach ($words as $word) {
$candidate = $current === '' ? $word : $current . ' ' . $word;
if ($pdf->GetStringWidth($candidate) <= $width) {
$current = $candidate;
continue;
}
if ($current !== '') {
$count++;
$current = $word;
} else {
$count += max(1, (int) ceil($pdf->GetStringWidth($word) / max($width, 1)));
$current = '';
}
}
if ($current !== '') {
$count++;
}
}
return max(1, $count);
}
private function _draw_fake_barcode($pdf, $x, $y, $w, $h, $text)
{
$text = preg_replace('/[^A-Za-z0-9]/', '', (string) $text);
if ($text === '') {
return;
}
$sequence = '1010';
$chars = str_split(strtoupper($text));
foreach ($chars as $char) {
$bits = str_pad(decbin(ord($char)), 8, '0', STR_PAD_LEFT);
$sequence .= $bits . '0';
}
$sequence .= '10101';
$module_w = $w / strlen($sequence);
$pdf->SetFillColor(0, 0, 0);
for ($i = 0, $len = strlen($sequence); $i < $len; $i++) {
if ($sequence[$i] !== '1') {
continue;
}
$bar_x = $x + ($i * $module_w);
$bar_h = ($i % 7 === 0) ? $h : ($h - 1.2);
$pdf->Rect($bar_x, $y, max(0.35, $module_w * 0.92), $bar_h, 'F');
}
}
private function _s($text)
{
return iconv('UTF-8', 'windows-1252//TRANSLIT', (string) $text);
}
private function _fetch_image_to_temp($url)
{
$ch = curl_init($url);
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 5, CURLOPT_FOLLOWLOCATION => true]);
$data = curl_exec($ch);
curl_close($ch);
if (!$data) return null;
$tmp = tempnam(sys_get_temp_dir(), 'qr_') . '.png';
file_put_contents($tmp, $data);
return $tmp;
}
private function _clean_multi_result()
{
if (isset($this->db_onedev->conn_id) && $this->db_onedev->conn_id instanceof mysqli) {
while ($this->db_onedev->conn_id->more_results()) {
$this->db_onedev->conn_id->next_result();
}
}
}
}

View File

@@ -1,15 +1,18 @@
<?php
class Xferbranch_v4 extends CI_Controller
{
function __construct() {
function __construct()
{
parent::__construct();
$this->db = $this->load->database("onedev", true);
}
function index() {
function index()
{
echo "Xfer Branch API";
}
function batch() {
function batch()
{
$this->fix();
$sql = "select T_RefDeliveryOrderID, T_RefDeliveryOrderNumber,
@@ -25,13 +28,13 @@ class Xferbranch_v4 extends CI_Controller
$tot_upload = 0;
if ($qry) {
$rows = $qry->result_array();
foreach($rows as $r) {
foreach ($rows as $r) {
$date = date("Y-m-d H:i:s ");
$branch = $r["M_BranchName"];
$ip_address = $r["M_BranchIPAddress"];
$number = $r["T_RefDeliveryOrderNumber"];
if ( $this->do($r["T_RefDeliveryOrderID"])) {
if ($this->do($r["T_RefDeliveryOrderID"])) {
echo "$date [OK] uploaded {$number} to {$branch} @ $ip_address\n";
} else {
echo "$date [ERR] uploaded {$number} to {$branch} @ $ip_address\n";
@@ -39,13 +42,14 @@ class Xferbranch_v4 extends CI_Controller
$tot_upload++;
}
}
if ($tot_upload == 0 ) {
if ($tot_upload == 0) {
$date = date("Y-m-d H:i:s ");
echo "$date [OK] No upload data\n";
}
}
function do($deliveryID) {
function do($deliveryID)
{
$sql = "select distinct
T_RefDeliveryOrderID,
T_RefDeliveryOrderDate,
@@ -81,20 +85,20 @@ class Xferbranch_v4 extends CI_Controller
where T_RefDeliveryOrderID = ?
and T_RefDeliveryOrderDetailIsConfirm = 'Y'
";
$qry = $this->db->query($sql, array($deliveryID) );
$qry = $this->db->query($sql, array($deliveryID));
$rows = array();
$branch_ip_address = "";
if($qry) {
if ($qry) {
$rows = $qry->result_array();
if (count($rows) == 0 ) {
echo "No Detail Records. => ";
$this->db->query("update t_ref_deliveryorder set T_RefDeliveryOrderIsConfirm = 'Z' where T_RefDeliveryOrderID = ?", array($deliveryID));
if (count($rows) == 0) {
echo "No Detail Records. => ";
$this->db->query("update t_ref_deliveryorder set T_RefDeliveryOrderIsConfirm = 'Z' where T_RefDeliveryOrderID = ?", array($deliveryID));
return false;
}
$sqlp = "select * from m_patient where M_PatientID = ?";
$sqlpa = "select * from m_patientaddress where M_PatientAddressM_PatientID = ?";
$sqlpt = "select * from m_title where M_TitleID = ?";
$sqlp = "select * from m_patient where M_PatientID = ?";
$sqlpa = "select * from m_patientaddress where M_PatientAddressM_PatientID = ?";
$sqlpt = "select * from m_title where M_TitleID = ?";
$sqlt = "select
T_OrderDetailT_TestID T_TestID,
@@ -124,88 +128,88 @@ class Xferbranch_v4 extends CI_Controller
left join t_orderpromise on T_OrderDetailT_OrderPromiseID = T_OrderPromiseID";
$arr_price_test = array();
foreach($rows as $idx => $r) {
foreach ($rows as $idx => $r) {
//patient & address
$branch_ip_address = $r["DestinationIPAddress"];
$patientID = $r["T_OrderHeaderM_PatientID"];
$headerID = $r["T_OrderHeaderID"];
$detailID= $r["T_OrderDetailID"];
$detailID = $r["T_OrderDetailID"];
$deliveryDetailID = $r["T_RefDeliveryOrderDetailID"];
$qryp = $this->db->query($sqlp, array($patientID));
$patient = array();
if ($qryp) {
$rowsp = $qryp->result_array();
if( count($rowsp) > 0 ) {
if (count($rowsp) > 0) {
$patient = $rowsp[0];
$titleID = $patient["M_PatientM_TitleID"];
$qrypa = $this->db->query($sqlpa, array($patientID));
if ($qrypa) {
$patient["address"] = $qrypa->result_array();
$patient["address"] = $qrypa->result_array();
}
$qrypt = $this->db->query($sqlpt, array($titleID));
if ($qrypt) {
$rowspt = $qrypt->result_array();
if (count($rowspt) > 0 ) $patient["title"] = $rowspt[0];
$rowspt = $qrypt->result_array();
if (count($rowspt) > 0) $patient["title"] = $rowspt[0];
}
}
}
}
$rows[$idx]["patient"] = $patient;
// test
$qryt = $this->db->query($sqlt,array($detailID));
$qryt = $this->db->query($sqlt, array($detailID));
$arr_test = array();
if ($qryt) {
$rowst = $qryt->result_array();
if (! isset($arr_price_test[$headerID])) {
$arr_price_test[$headerID] = array();
}
foreach($rowst as $r ) {
$sasCode = substr($r["T_TestSasCode"],0,8);
foreach ($rowst as $r) {
$sasCode = substr($r["T_TestSasCode"], 0, 8);
$curSasCode = $r["T_TestSasCode"];
if ( ! isset($arr_price_test[$headerID][$sasCode]) ) {
if(strlen($curSasCode) == 8) $arr_price_test[$headerID][$sasCode] = true;
if (! isset($arr_price_test[$headerID][$sasCode])) {
if (strlen($curSasCode) == 8) $arr_price_test[$headerID][$sasCode] = true;
$rows[$idx]["test"][] = $r;
$arr_test[]=$r["T_TestID"];
$arr_test[] = $r["T_TestID"];
}
}
}
// $child_test
$qryct = $this->db->query($sqlct,array($deliveryDetailID));
$qryct = $this->db->query($sqlct, array($deliveryDetailID));
if ($qryct) {
$rowsct = $qryct->result_array();
$rows[$idx]["child_test"] = $rowsct;
}
$reqs = array();
if (count($arr_test) > 0 ) {
if (count($arr_test) > 0) {
$sqlr = "select * from t_orderreq where T_OrderReqT_OrderHeaderID = ?";
$qryr = $this->db->query($sqlr, array($headerID));
if ($qryr) {
$rowsr = $qryr->result_array();
foreach($rowsr as $r) {
foreach ($rowsr as $r) {
$a_test_r = json_decode($r["T_OrderReqT_TestID"]);
$a_x = array_intersect($arr_test,$a_test_r);
if( count($a_x) > 0 ) $reqs[] = $r;
$a_x = array_intersect($arr_test, $a_test_r);
if (count($a_x) > 0) $reqs[] = $r;
}
}
}
$rows[$idx]["requirements"] = $reqs;
}
$o_rows=$rows;
$o_rows = $rows;
$rows = array();
foreach($o_rows as $r) {
if (isset($r["test"]) ) {
foreach ($o_rows as $r) {
if (isset($r["test"])) {
$rows[] = $r;
}
}
$param = json_encode($rows);
$url = "http://$branch_ip_address/one-api/tools/incomingref_v4/receive";
$result = $this->post($url,$param);
echo "to $url \nresponse : $result\n";
$result = json_decode($result,true);
if ($result["status"] == "OK" ) {
$url = "http://$branch_ip_address/one-api-lab/tools/incomingref_v4/receive";
$result = $this->post($url, $param);
echo "to $url \nresponse : $result\n";
$result = json_decode($result, true);
if ($result["status"] == "OK") {
$sqlu = "update t_ref_deliveryorder set T_RefDeliveryOrderIsConfirm = 'S'
where T_RefDeliveryOrderID = ?";
$this->db->query($sqlu, array($deliveryID));
@@ -214,13 +218,13 @@ class Xferbranch_v4 extends CI_Controller
print_r($result);
}
} else {
print_r($this->db->error());
print_r($this->db->error());
}
return false;
}
public function fix()
{
$sql = "SELECT
{
$sql = "SELECT
T_RefDeliveryOrderID,
T_RefDeliveryOrderDetailT_WorklistRefConfirmDetailID,
T_RefDeliveryOrderDate,
@@ -242,34 +246,39 @@ WHERE T_RefDeliveryOrderDetailIsActive = 'Y' AND
T_RefDeliveryOrderDetailT_BarcodeLabBarcode <> T_BarcodeLabBarcode AND
T_RefDeliveryOrderDate >= '2024-08-01'";
$qry = $this->db->query($sql);
$rows = $qry->result_array();
if (count($rows) > 0) {
foreach ($rows as $k => $v) {
$sql = "UPDATE t_ref_deliveryorder_detail
$qry = $this->db->query($sql);
$rows = $qry->result_array();
if (count($rows) > 0) {
foreach ($rows as $k => $v) {
$sql = "UPDATE t_ref_deliveryorder_detail
SET T_RefDeliveryOrderDetailT_BarcodeLabBarcode = '{$v['T_BarcodeLabBarcode']}'
WHERE T_RefDeliveryOrderDetailID = {$v['T_RefDeliveryOrderDetailID']}";
$qry = $this->db->query($sql);
$sql = "UPDATE t_worklist_ref_confirmdetail
$qry = $this->db->query($sql);
$sql = "UPDATE t_worklist_ref_confirmdetail
SET T_WorklistRefConfirmDetailT_BarcodeLabBarcode = '{$v['T_BarcodeLabBarcode']}'
WHERE T_WorklistRefConfirmDetailID = {$v['T_RefDeliveryOrderDetailT_WorklistRefConfirmDetailID']}";
$qry = $this->db->query($sql);
}
}
}
function post($url,$data) {
$qry = $this->db->query($sql);
}
}
}
function post($url, $data)
{
$zdata = gzdeflate($data);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $zdata);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $zdata);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($zdata))
);
curl_setopt(
$ch,
CURLOPT_HTTPHEADER,
array(
'Content-Type: application/json',
'Content-Length: ' . strlen($zdata)
)
);
$result = curl_exec($ch);
//echo "RST : $result ";
return $result;

View File

@@ -0,0 +1,639 @@
<?php
class Xstatusbranch_v3 extends MY_Controller
{
function __construct() {
parent::__construct();
$this->db = $this->load->database("onedev", true);
}
function index() {
echo "API";
}
//mikro
function update_mikro($detailID, $header, $detail ) {
$sql = "select * from t_orderdetail where T_OrderDetailID = ? ";
$qry = $this->db->query($sql, array($detailID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Mikro cek Validation " . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$rows = $qry->result_array();
if (count($rows) == 0 ) return;
if ($rows[0]["T_OrderDetailValidation"] == "Y" ) return;
$sql = "select Other_MikroID from other_mikro where Other_MikroT_OrderDetailID = ? and Other_MikroIsActive = 'Y'";
$qry = $this->db->query($sql, array($detailID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Mikro cek Existence " . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$rows = $qry->result_array();
$mikroID = 0;
if (count($rows) > 0 ) $mikroID = $rows[0]["Other_MikroID"];
if ( $mikroID > 0 ) {
$sql = "update other_mikro set Other_MikroIsActive = 'N' where Other_MikroID = ? ";
$qry = $this->db->query($sql, array($mikroID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Mikro set Inactive" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$sql = "update other_mikrodetails set Other_MikroDetailsIsActive = 'N' where Other_MikroDetailsOther_MikroID= ? ";
$qry = $this->db->query($sql, array($mikroID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Mikro Details set Inactive" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
}
unset($header["Other_MikroID"]);
$header["Other_MikroCreated"] = date("Y-m-d h:i:s");
$header["Other_MikroLastUpdated"] =date("Y-m-d h:i:s");
$header["Other_MikroUserID"] = 3;
$header["Other_MikroIsActive"] = "Y";
$header["Other_MikroT_OrderDetailID"] = $detailID;
$qry = $this->db->insert("other_mikro",$header);
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Mikro Add Header" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$mikroID = $this->db->insert_id();
if ($mikroID == 0 ) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Mikro ID Header" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
foreach($detail as $idx => $d ) {
$detail[$idx]["Other_MikroDetailsOther_MikroID"] = $mikroID ;
$detail[$idx]["Other_MikroDetailsUserID"] = 3;
$detail[$idx]["Other_MikroDetailsIsActive"] = "Y";
unset($detail[$idx]["Other_MikroDetailsID"]);
unset($detail[$idx]["Other_MikroDetailsCreated"]);
unset($detail[$idx]["Other_MikroDetailsLastUpdated"]);
}
$qry = $this->db->insert_batch("other_mikrodetails",$detail);
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Mikro Add Detail" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
}
//cytologi
function update_cytologi($detailID, $header, $detail ) {
$sql = "select * from t_orderdetail where T_OrderDetailID = ? ";
$qry = $this->db->query($sql, array($detailID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Cytologi cek Validation " . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$rows = $qry->result_array();
if (count($rows) == 0 ) return;
if ($rows[0]["T_OrderDetailValidation"] == "Y" ) return;
$sql = "select Other_CytologiID from other_cytologi where Other_CytologiT_OrderDetailID = ? and Other_CytologiIsActive = 'Y'";
$qry = $this->db->query($sql, array($detailID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Cytologi cek Existence " . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$rows = $qry->result_array();
$cytologiID = 0;
if (count($rows) > 0 ) $cytologiID = $rows[0]["Other_CytologiID"];
if ( $cytologiID > 0 ) {
$sql = "update other_cytologi set Other_CytologiIsActive = 'N' where Other_CytologiID = ? ";
$qry = $this->db->query($sql, array($cytologiID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Cytologi set Inactive" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$sql = "update other_cytologidetails set Other_CytologiDetailsIsActive = 'N' where Other_CytologiDetailsOther_CytologiID= ? ";
$qry = $this->db->query($sql, array($cytologiID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Cytologi Details set Inactive" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
}
unset($header["Other_CytologiID"]);
$header["Other_CytologiCreated"] = date("Y-m-d h:i:s");
$header["Other_CytologiLastUpdated"] =date("Y-m-d h:i:s");
$header["Other_CytologiUserID"] = 3;
$header["Other_CytologiIsActive"] = "Y";
$header["Other_CytologiT_OrderDetailID"] = $detailID;
$qry = $this->db->insert("other_cytologi",$header);
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Cytologi Add Header" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$cytologiID = $this->db->insert_id();
if ($cytologiID == 0 ) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Cytologi ID Header" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
foreach($detail as $idx => $d ) {
$detail[$idx]["Other_CytologiDetailsOther_CytologiID"] = $cytologiID ;
$detail[$idx]["Other_CytologiDetailsUserID"] = 3;
$detail[$idx]["Other_CytologiDetailsIsActive"] = "Y";
unset($detail[$idx]["Other_CytologiDetailsID"]);
unset($detail[$idx]["Other_CytologiDetailsCreated"]);
unset($detail[$idx]["Other_CytologiDetailsLastUpdated"]);
}
$qry = $this->db->insert_batch("other_cytologidetails",$detail);
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Cytologi Add Detail" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
}
//fna
function update_fna($detailID, $header, $detail ) {
$sql = "select * from t_orderdetail where T_OrderDetailID = ? ";
$qry = $this->db->query($sql, array($detailID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError FNA cek Validation " . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$rows = $qry->result_array();
if (count($rows) == 0 ) return;
if ($rows[0]["T_OrderDetailValidation"] == "Y" ) return;
$sql = "select Other_FNAID from other_fna where Other_FNAT_OrderDetailID = ? and Other_FNAIsActive = 'Y'";
$qry = $this->db->query($sql, array($detailID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError FNA cek Existence " . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$rows = $qry->result_array();
$fnaID = 0;
if (count($rows) > 0 ) $fnaID = $rows[0]["Other_FNAID"];
if ( $fnaID > 0 ) {
$sql = "update other_fna set Other_FNAIsActive = 'N' where Other_FNAID = ? ";
$qry = $this->db->query($sql, array($fnaID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError FNA set Inactive" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$sql = "update other_fnadetails set Other_FNADetailsIsActive = 'N' where Other_FNADetailsOther_FNAID= ? ";
$qry = $this->db->query($sql, array($fnaID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError FNA Details set Inactive" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
}
unset($header["Other_FNAID"]);
$header["Other_FNACreated"] = date("Y-m-d h:i:s");
$header["Other_FNALastUpdated"] =date("Y-m-d h:i:s");
$header["Other_FNAUserID"] = 3;
$header["Other_FNAIsActive"] = "Y";
$header["Other_FNAT_OrderDetailID"] = $detailID;
$qry = $this->db->insert("other_fna",$header);
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError FNA Add Header" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$fnaID = $this->db->insert_id();
if ($fnaID == 0 ) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError FNA ID Header" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
foreach($detail as $idx => $d ) {
$detail[$idx]["Other_FNADetailsOther_FNAID"] = $fnaID ;
$detail[$idx]["Other_FNADetailsUserID"] = 3;
$detail[$idx]["Other_FNADetailsIsActive"] = "Y";
unset($detail[$idx]["Other_FNADetailsID"]);
unset($detail[$idx]["Other_FNADetailsCreated"]);
unset($detail[$idx]["Other_FNADetailsLastUpdated"]);
}
$qry = $this->db->insert_batch("other_fnadetails",$detail);
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError FNA Add Detail" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
}
// update papsmear
function update_papsmear ($detailID, $header, $detail ) {
$sql = "select * from t_orderdetail where T_OrderDetailID = ? ";
$qry = $this->db->query($sql, array($detailID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError PapSmear cek Validation " . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$rows = $qry->result_array();
if (count($rows) == 0 ) return;
if ($rows[0]["T_OrderDetailValidation"] == "Y" ) return;
$sql = "select Other_PapSmearID from other_papsmear where Other_PapSmearT_OrderDetailID = ? and Other_PapSmearIsActive = 'Y'";
$qry = $this->db->query($sql, array($detailID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError PapSmear cek Existence " . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$rows = $qry->result_array();
$papsmearID = 0;
if (count($rows) > 0 ) $papsmearID = $rows[0]["Other_PapSmearID"];
if ( $papsmearID > 0 ) {
$sql = "update other_papsmear set Other_PapSmearIsActive = 'N' where Other_PapSmearID = ? ";
$qry = $this->db->query($sql, array($papsmearID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError PapSmear set Inactive" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$sql = "update other_papsmearbahan set Other_PapSmearBahanIsActive = 'N' where Other_PapSmearBahanOther_PapSmearID= ? ";
$qry = $this->db->query($sql, array($papsmearID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError PapSmear Details set Inactive" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$sql = "update other_papsmearcategory set Other_PapSmearCategoryIsActive = 'N' where Other_PapSmearCategoryOther_PapSmearID= ? ";
$qry = $this->db->query($sql, array($papsmearID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError PapSmear Category set Inactive" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$sql = "update other_papsmearcheck set Other_PapSmearCheckIsActive = 'N' where Other_PapSmearCheckOther_PapSmearID= ? ";
$qry = $this->db->query($sql, array($papsmearID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError PapSmear Check set Inactive" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$sql = "update other_papsmeardetails set Other_PapSmearDetailsIsActive = 'N' where Other_PapSmearDetailsOther_PapSmearID= ? ";
$qry = $this->db->query($sql, array($papsmearID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError PapSmear Details set Inactive" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$sql = "update other_papsmearmaturasi set Other_PapSmearMaturasiIsActive = 'N' where Other_PapSmearMaturasiOther_PapSmearID= ? ";
$qry = $this->db->query($sql, array($papsmearID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError PapSmear Details set Inactive" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
}
unset($header["Other_PapSmearID"]);
$header["Other_PapSmearCreated"] = date("Y-m-d h:i:s");
$header["Other_PapSmearLastUpdated"] =date("Y-m-d h:i:s");
$header["Other_PapSmearUserID"] = 3;
$header["Other_PapSmearIsActive"] = "Y";
$header["Other_PapSmearT_OrderDetailID"] = $detailID;
$qry = $this->db->insert("other_papsmear",$header);
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError PapSmear Add Header" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$papsmearID= $this->db->insert_id();
if ($papsmearID == 0 ) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError PapSmear ID Header" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
foreach($detail as $key => $d ) {
if ($key == "bahan") {
foreach($d as $idx => $xd) {
$detail[$key][$idx]["Other_PapSmearBahanOther_PapSmearID"] = $papsmearID ;
$detail[$key][$idx]["Other_PapSmearBahanUserID"] = 3;
$detail[$key][$idx]["Other_PapSmearBahanIsActive"] = "Y";
unset($detail[$key][$idx]["Other_PapSmearBahanID"]);
unset($detail[$key][$idx]["Other_PapSmearBahanCreated"]);
unset($detail[$key][$idx]["Other_PapSmearBahanLastUpdated"]);
}
$qry = $this->db->insert_batch("other_papsmearbahan",$detail[$key]);
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError PapSmear Add Bahan " . print_r($this->db->error(),true),FILE_APPEND);
return;
}
}
if ($key == "category") {
foreach($d as $idx => $xd) {
$detail[$key][$idx]["Other_PapSmearCategoryOther_PapSmearID"] = $papsmearID ;
$detail[$key][$idx]["Other_PapSmearCategoryUserID"] = 3;
$detail[$key][$idx]["Other_PapSmearCategoryIsActive"] = "Y";
unset($detail[$key][$idx]["Other_PapSmearCategoryID"]);
unset($detail[$key][$idx]["Other_PapSmearCategoryCreated"]);
unset($detail[$key][$idx]["Other_PapSmearCategoryLastUpdated"]);
}
$qry = $this->db->insert_batch("other_papsmearcategory",$detail[$key]);
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError PapSmear Add Category " . print_r($this->db->error(),true),FILE_APPEND);
return;
}
}
if ($key == "check") {
foreach($d as $idx => $xd) {
$detail[$key][$idx]["Other_PapSmearCheckOther_PapSmearID"] = $papsmearID ;
$detail[$key][$idx]["Other_PapSmearCheckUserID"] = 3;
$detail[$key][$idx]["Other_PapSmearCheckIsActive"] = "Y";
unset($detail[$key][$idx]["Other_PapSmearCheckID"]);
unset($detail[$key][$idx]["Other_PapSmearCheckCreated"]);
unset($detail[$key][$idx]["Other_PapSmearCheckLastUpdated"]);
}
$qry = $this->db->insert_batch("other_papsmearcheck",$detail[$key]);
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError PapSmear Add Check " . print_r($this->db->error(),true),FILE_APPEND);
return;
}
}
if ($key == "details") {
foreach($d as $idx => $xd) {
$detail[$key][$idx]["Other_PapSmearDetailsOther_PapSmearID"] = $papsmearID ;
$detail[$key][$idx]["Other_PapSmearDetailsUserID"] = 3;
$detail[$key][$idx]["Other_PapSmearDetailsIsActive"] = "Y";
unset($detail[$key][$idx]["Other_PapSmearDetailsID"]);
unset($detail[$key][$idx]["Other_PapSmearDetailsCreated"]);
unset($detail[$key][$idx]["Other_PapSmearDetailsLastUpdated"]);
}
$qry = $this->db->insert_batch("other_papsmeardetails",$detail[$key]);
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError PapSmear Add Details " . print_r($this->db->error(),true),FILE_APPEND);
return;
}
}
if ($key == "maturasi") {
foreach($d as $idx => $xd) {
$detail[$key][$idx]["Other_PapSmearMaturasiOther_PapSmearID"] = $papsmearID ;
$detail[$key][$idx]["Other_PapSmearMaturasiUserID"] = 3;
$detail[$key][$idx]["Other_PapSmearMaturasiIsActive"] = "Y";
unset($detail[$key][$idx]["Other_PapSmearMaturasiID"]);
unset($detail[$key][$idx]["Other_PapSmearMaturasiCreated"]);
unset($detail[$key][$idx]["Other_PapSmearMaturasiLastUpdated"]);
}
$qry = $this->db->insert_batch("other_papsmearmaturasi",$detail[$key]);
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError PapSmear Add Maturasi " . print_r($this->db->error(),true),FILE_APPEND);
return;
}
}
}
}
function update_lcprep($detailID, $header, $detail ) {
$sql = "select * from t_orderdetail where T_OrderDetailID = ? ";
$qry = $this->db->query($sql, array($detailID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Lcprep cek Validation " . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$rows = $qry->result_array();
if (count($rows) == 0 ) return;
if ($rows[0]["T_OrderDetailValidation"] == "Y" ) return;
$sql = "select Other_LcprepID from other_lcprep where Other_LcprepT_orderDetailID = ? and Other_LcprepIsActive = 'Y'";
$qry = $this->db->query($sql, array($detailID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Lcprep cek Existence " . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$rows = $qry->result_array();
$lcprepID = 0;
if (count($rows) > 0 ) $lcprepID = $rows[0]["Other_LcprepID"];
if ( $lcprepID > 0 ) {
$sql = "update other_lcprep set Other_LcprepIsActive = 'N' where Other_LcprepID = ? ";
$qry = $this->db->query($sql, array($lcprepID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Lcprep set Inactive" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$sql = "update other_lcprepadekuasi set Other_LcprepAdekuasiIsActive = 'N' where Other_LcprepAdekuasiOther_LcprepID= ? ";
$qry = $this->db->query($sql, array($lcprepID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Lcprep Adekuasi set Inactive" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$sql = "update other_lcprepinterpretasi set Other_LcprepInterpretasiIsActive = 'N' where Other_LcprepInterpretasiOther_LcprepID= ? ";
$qry = $this->db->query($sql, array($lcprepID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Lcprep Interpretasi set Inactive" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$sql = "update other_lcprepdetails set Other_LcprepDetailsIsActive = 'N' where Other_LcprepDetailsOther_LcprepID= ? ";
$qry = $this->db->query($sql, array($lcprepID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Lcprep Details set Inactive" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$sql = "update other_lcprepkategoriumum set Other_LcprepKategoriUmumIsActive = 'N' where Other_LcprepKategoriUmumOther_LcprepID= ? ";
$qry = $this->db->query($sql, array($lcprepID));
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Lcprep KategoriUmum set Inactive" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
}
unset($header["Other_LcprepID"]);
$header["Other_LcprepCreated"] = date("Y-m-d h:i:s");
$header["Other_LcprepLastUpdated"] =date("Y-m-d h:i:s");
$header["Other_LcprepUserID"] = 3;
$header["Other_LcprepIsActive"] = "Y";
$header["Other_LcprepT_orderDetailID"] = $detailID;
$qry = $this->db->insert("other_lcprep",$header);
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Lcprep Add Header" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
$lcprepID= $this->db->insert_id();
if ($lcprepID == 0 ) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Lcprep ID Header" . print_r($this->db->error(),true),FILE_APPEND);
return;
}
foreach($detail as $key => $d ) {
if ($key == "adekuasi") {
foreach($d as $idx => $xd) {
$detail[$key][$idx]["Other_LcprepAdekuasiOther_LcprepID"] = $lcprepID ;
$detail[$key][$idx]["Other_LcprepAdekuasiUserID"] = 3;
$detail[$key][$idx]["Other_LcprepAdekuasiIsActive"] = "Y";
unset($detail[$key][$idx]["Other_LcprepAdekuasiID"]);
unset($detail[$key][$idx]["Other_LcprepAdekuasiCreated"]);
unset($detail[$key][$idx]["Other_LcprepAdekuasiLastUpdated"]);
}
$qry = $this->db->insert_batch("other_lcprepadekuasi",$detail[$key]);
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Lcprep Add Adekuasi " . print_r($this->db->error(),true),FILE_APPEND);
return;
}
}
if ($key == "interpretasi") {
foreach($d as $idx => $xd) {
$detail[$key][$idx]["Other_LcprepInterpretasiOther_LcprepID"] = $lcprepID ;
$detail[$key][$idx]["Other_LcprepInterpretasiUserID"] = 3;
$detail[$key][$idx]["Other_LcprepInterpretasiIsActive"] = "Y";
unset($detail[$key][$idx]["Other_LcprepInterpretasiID"]);
unset($detail[$key][$idx]["Other_LcprepInterpretasiCreated"]);
unset($detail[$key][$idx]["Other_LcprepInterpretasiLastUpdated"]);
}
$qry = $this->db->insert_batch("other_lcprepinterpretasi",$detail[$key]);
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Lcprep Add Interpretasi " . print_r($this->db->error(),true),FILE_APPEND);
return;
}
}
if ($key == "details") {
foreach($d as $idx => $xd) {
$detail[$key][$idx]["Other_LcprepDetailsOther_LcprepID"] = $lcprepID ;
$detail[$key][$idx]["Other_LcprepDetailsUserID"] = 3;
$detail[$key][$idx]["Other_LcprepDetailsIsActive"] = "Y";
unset($detail[$key][$idx]["Other_LcprepDetailsID"]);
unset($detail[$key][$idx]["Other_LcprepDetailsCreated"]);
unset($detail[$key][$idx]["Other_LcprepDetailsLastUpdated"]);
}
$qry = $this->db->insert_batch("other_lcprepdetails",$detail[$key]);
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Lcprep Add Details " . print_r($this->db->error(),true),FILE_APPEND);
return;
}
}
if ($key == "kategoriumum") {
foreach($d as $idx => $xd) {
$detail[$key][$idx]["Other_LcprepKategoriUmumOther_LcprepID"] = $lcprepID ;
$detail[$key][$idx]["Other_LcprepKategoriUmumUserID"] = 3;
$detail[$key][$idx]["Other_LcprepKategoriUmumIsActive"] = "Y";
unset($detail[$key][$idx]["Other_LcprepKategoriUmumID"]);
unset($detail[$key][$idx]["Other_LcprepKategoriUmumCreated"]);
unset($detail[$key][$idx]["Other_LcprepKategoriUmumLastUpdated"]);
}
$qry = $this->db->insert_batch("other_lcprepkategoriumum",$detail[$key]);
if(!$qry) {
file_put_contents("/xtmp/dbg-xstatus_branch-v3.log", "\nError Lcprep Add KategoriUmum " . print_r($this->db->error(),true),FILE_APPEND);
return;
}
}
}
}
function update() {
$prm = $this->sys_input;
foreach($prm as $p) {
$deliveryOrderID = $p["incomingRefT_RefDeliveryOrderID"];
$detailID = $p["incomingRefDetailT_OrderDetailID"];
$normalValueID = $p["T_OrderDetailNat_NormalValueID"];
$result = $p["T_OrderDetailResult"];
$resultnote = $p["T_OrderDetailNote"];
$validation = $p["T_OrderDetailValidation"];
$verification = $p["T_OrderDetailVerification"];
$status = $p["incomingRefDetailStatus"];
$note = '';
if (isset($p["note"])) $note = $p["note"];
if ($validation == "Y") {
$ret = $this->update_delivery($deliveryOrderID,$detailID,"$result","VALIDATION",$note);
if ($ret) $ret = $this->update_order($detailID,$result,$resultnote,$normalValueID);
if (isset($p["nonlab_result"])) {
$type = $p["nonlab_result"]["type"];
$header = $p["nonlab_result"]["header"];
$detail = $p["nonlab_result"]["detail"];
if ($type == "mikro" ) {
$this->update_mikro($detailID,$header,$detail);
}
if ($type == "papsmear" ) {
$this->update_papsmear($detailID,$header,$detail);
}
if ($type == "lcprep" ) {
$this->update_lcprep($detailID,$header,$detail);
}
if ($type == "fna" ) {
$this->update_fna($detailID,$header,$detail);
}
if ($type == "cytologi" ) {
$this->update_cytologi($detailID,$header,$detail);
}
}
} elseif($verification == "Y") {
$ret = $this->update_delivery($deliveryOrderID,$detailID,"$result","VERIFICATION",$note);
} elseif($status != "N") {
$ret = $this->update_delivery($deliveryOrderID,$detailID,"Diterima");
} else {
$ret = $this->update_delivery($deliveryOrderID,$detailID,"Ditolak");
}
if (! $ret ) {
echo json_encode( array("status"=>"ERR", "message"=> print_r($this->db->error(),true) ));
exit;
}
}
echo json_encode( array("status"=>"OK", "message"=>""));
}
function update_delivery($deliveryOrderID,$detailID,$value,$stage = "", $note = "" ) {
$sql = "select T_RefDeliveryOrderDetailT_OrderDetailID ,
T_RefDeliveryOrderDetailID,
T_RefDeliveryOrderChildID
from t_ref_deliveryorder_child
join t_ref_deliveryorder_detail on
T_RefDeliveryOrderChildT_RefDeliveryOrderDetailID = T_RefDeliveryOrderDetailID
where T_RefDeliveryOrderDetailT_RefDeliveryOrderID = ?
and T_RefDeliveryOrderChildT_OrderDetailID = ?";
$qry = $this->db->query($sql, array($deliveryOrderID, $detailID));
$flag_child = false;
$child_id = 0;
$refDeliveryOrderDetailID = 0;
if ($qry) {
$rows = $qry->result_array();
if (count($rows) > 0 ) {
$flag_child = true;
$child_id = $rows[0]["T_RefDeliveryOrderChildID"];
$parentDetailID = $rows[0]["T_RefDeliveryOrderDetailID"];
}
}
if ($flag_child) {
$sql = "update t_ref_deliveryorder_child
set T_RefDeliveryOrderChildResult = ?,
T_RefDeliveryOrderChildStage= ? ,
T_RefDeliveryOrderChildNote = ?
where T_RefDeliveryOrderChildID=?";
$qry = $this->db->query($sql, array($value, $state, $note, $child_id));
$value = "...";
$detailID = $parentDetailID;
}
if ($flag_child) {
$sql = "update t_ref_deliveryorder_detail
set T_RefDeliveryOrderDetailResult = ?,
T_RefDeliveryOrderDetailStage = ?,
T_RefDeliveryOrderDetailNote = ?
where T_RefDeliveryOrderDetailT_RefDeliveryOrderID = ?
and T_RefDeliveryOrderDetailID = ?";
} else {
$sql = "update t_ref_deliveryorder_detail
set T_RefDeliveryOrderDetailResult = ?,
T_RefDeliveryOrderDetailStage = ?,
T_RefDeliveryOrderDetailNote = ?
where T_RefDeliveryOrderDetailT_RefDeliveryOrderID = ?
and T_RefDeliveryOrderDetailT_OrderDetailID = ?";
}
$qry = $this->db->query($sql, array($value, $stage, $note, $deliveryOrderID, $detailID));
return $qry;
}
function update_order($detailID,$value,$resultnote,$normalValueID) {
$verUserID = 3;
$sql = "update t_orderdetail
set T_OrderDetailResult = ?,
T_OrderDetailNote = ?,
T_OrderDetailNat_NormalValueID = ?,
T_OrderDetailVerification = 'Y',
T_OrderDetailVerDate = now(),
T_OrderDetailVerUserID = $verUserID
where T_OrderDetailID = ?";
$qry = $this->db->query($sql, array($value,$resultnote, $normalValueID, $detailID));
if ( $qry) {
$sql = "update t_orderdetail, nat_normalvalue, nat_methode
set T_OrderDetailNat_MethodeID = Nat_NormalValueNat_MethodeID ,
T_OrderDetailNat_MethodeName = Nat_MethodeName,
T_OrderDetailNormalValueNote = Nat_NormalValueNote,
T_OrderDetailNormalValueDescription = Nat_NormalValueDescription,
T_OrderDetailMinValue = Nat_NormalValueMinValue,
T_OrderDetailMaxValue = Nat_NormalValueMaxValue,
T_OrderDetailMinValueInclusive = Nat_NormalValueMinValueInclusive,
T_OrderDetailMaxValueInclusive = Nat_NormalValueMaxValueInclusive
where T_OrderDetailID = ?
and T_OrderDetailNat_NormalValueID = Nat_NormalValueID
and Nat_NormalValueNat_MethodeID = Nat_MethodeID";
$qryn = $this->db->query($sql, array($detailID));
//if (! $qryn ) print_r($this->db->error());
if (! $qryn ) return false;
$sql = "call sp_set_normal_value_flag(?)";
$qryu = $this->db->query($sql, array($detailID));
//if (! $qryu ) print_r($this->db->error());
if (! $qryu ) return false;
$this->clean_mysqli_connection($this->db->conn_id);
}
return $qry;
}
}

View File

@@ -56,14 +56,7 @@ class Reporturl
}
if($show == 'N'){
if ($this->should_use_proxy_stream($report_code)) {
return array(true, $this->build_proxy_stream_url($report_code, $params));
}
// Populate decrypt cache sebelum return URL raw ke browser
$CI->load->library('ibl_patient_decrypt');
$CI->ibl_patient_decrypt->pre_cache_and_get_url($final_url);
return array(true, $final_url);
return array(true, $this->build_proxy_stream_url($report_code, $params));
}
else{
$CI->load->library('ibl_patient_decrypt');
@@ -74,11 +67,6 @@ class Reporturl
}
}
private function should_use_proxy_stream($report_code)
{
return strpos((string)$report_code, 'FO-') === 0;
}
private function build_proxy_stream_url($report_code, $params = array())
{
$CI = &get_instance();

View File

@@ -0,0 +1,24 @@
# Catatan Meeting Klinik Internal
## Task List IBL
### Registrasi Klinik (`klinik/Registrationv3.php`)
- [x] Tambah `searchregion` dan `search_countries` (samakan dg `ibl_registration/Patient.php`)
- [x] Fix `search()` — hapus kelurahan sub-query, tambah PDP decrypt inline
- [x] Fix `getaddress()` — gunakan tabel `regional` via `M_PatientAddressRegionalCd`
- [x] Fix `newpatient()` — simpan `M_PatientAddressRegionalCd`, City, State, District, Village, Country, CountryCode, Note
- [x] Fix `editpatient()` — terapkan `_mask_dob()` ke `M_PatientDOB`
- [x] Tambah `_mask_dob()` — masking DOB sesuai PDP UU No. 27/2022
### Screening Klinik (`klinik/screening/Screening.php`)
- [x] Fix `search()` — hapus kelurahan sub-query, tambah PDP decrypt
- [x] Tambah `getsexreg()` — samakan dg Registrationv3
### Sampling Call (`mockup/doctorclinicv2/Samplingcall.php`)
- [x] Tambah UNION SELECT dari `one_klinik.order` agar antrian klinik muncul
- [ ] Debug: order klinik masih belum muncul di antrian — cek params `locationid`, `stationid`, `xdate`
### Pending / Belum Dikerjakan
- [ ]
- [ ]
- [ ]

View File

@@ -84,10 +84,17 @@ mysql one_lab < sql/manual_changes/2026-05-31-pdp-encrypt-columns.sql
# Update trigger m_patient & m_patientaddress (pakai _enc di log JSON)
mysql one_lab < sql/manual_changes/2026-05-31-pdp-update-triggers-enc.sql
# Ubah M_PatientDOB dari DATE ke VARCHAR(20) agar masked value tersimpan
mysql one_lab < sql/manual_changes/2026-06-11-alter-m-patient-dob-to-varchar.sql
# Ubah Mcu_PreregisterPatientsDOB dari DATE ke VARCHAR(20) (sama)
mysql one_lab < sql/manual_changes/2026-06-11-alter-mcu-preregister-dob-to-varchar.sql
# Verifikasi kolom terbentuk
mysql -e "SHOW COLUMNS FROM one_lab.m_patient LIKE '%_enc';"
mysql -e "SHOW COLUMNS FROM one_lab.m_patient LIKE '%_bidx';"
mysql -e "SHOW COLUMNS FROM one_lab.m_patientaddress LIKE '%_enc';"
mysql -e "SHOW COLUMNS FROM one_lab.m_patient WHERE Field = 'M_PatientDOB'\G"
```
---
@@ -258,17 +265,17 @@ mysql -e "SHOW STATUS LIKE 'Threads_connected';"
## Field yang Dienkripsi
### `one_lab.m_patient`
| Field | `_enc` | `_bidx` (search) |
|-------|:------:|:----------------:|
| M_PatientName | ✅ | ✅ |
| M_PatientHP | ✅ | ✅ |
| M_PatientDOB | ✅ | ✅ |
| M_PatientNIK | ✅ | ✅ |
| M_PatientEmail | ✅ | — |
| M_PatientPhone | ✅ | — |
| M_PatientPOB | ✅ | — |
| M_PatientIDNumber | ✅ | — |
| M_PatientNIP | ✅ | — |
| Field | Tipe kolom plain | `_enc` | `_bidx` (search) | Catatan |
|-------|:---:|:------:|:----------------:|---------|
| M_PatientName | VARCHAR | ✅ | ✅ | |
| M_PatientHP | VARCHAR | ✅ | ✅ | |
| M_PatientDOB | **VARCHAR(20)** | ✅ | ✅ | Diubah dari DATE → VARCHAR agar mask `**-**-YYYY` tersimpan |
| M_PatientNIK | VARCHAR | ✅ | ✅ | ⚠️ `M_PatientNIK_bidx` diisi dari **`M_PatientIDNumber`**, bukan NIK |
| M_PatientEmail | VARCHAR | ✅ | — | |
| M_PatientPhone | VARCHAR | ✅ | — | |
| M_PatientPOB | VARCHAR | ✅ | — | |
| M_PatientIDNumber | VARCHAR | ✅ | — | Masked plain, bidx-nya lewat `M_PatientNIK_bidx` |
| M_PatientNIP | VARCHAR | ✅ | — | |
### `one_lab.m_patientaddress`
| Field | `_enc` | `_bidx` |
@@ -373,13 +380,16 @@ mysql one_lab < sql/manual_changes/2026-05-31-pdp-birt-sp-cache-join.sql
Data PII yang dimasking saat INSERT ke staging table `mcu_preregister_patients`:
| Field | Mask |
|-------|------|
| `*PatientName` | `_mask_name()` |
| `*KTP` | `_mask_id()` |
| `*NIP` / `*NIK` | `_mask_id()` |
| `*Email` | `_mask_email()` |
| `*Hp` | `_mask_phone()` |
| Field | Tipe kolom | Mask |
|-------|:---:|------|
| `*PatientName` | VARCHAR | `_mask_name()` |
| `*KTP` | VARCHAR | `_mask_id()` |
| `*NIP` / `*NIK` | VARCHAR | `_mask_id()` |
| `*Email` | VARCHAR | `_mask_email()` |
| `*Hp` | VARCHAR | `_mask_phone()` |
| `*DOB` | **VARCHAR(20)** | `_mask_dob()` — diubah dari DATE → VARCHAR agar mask `**-**-YYYY` tersimpan |
Tidak ada kolom `_enc` di tabel ini — data asli bisa diambil dari `m_patient` via `*M_PatientID`.
4 lokasi INSERT yang sudah diupdate: `savecsv()` & `save()` di setupmcuoffline-ibl, `save()` & `savenewform()` di mcuoffline/Preregisterapp.

View File

@@ -0,0 +1,86 @@
# Listing Table Replikasi IBL
- Sumber: `Table2 repilkasi IBL - Sheet1.csv`
- Total table: **79**
| No | Nama Table | Status Replikasi | Keterangan |
| --- | --- | --- | --- |
| 1 | `fisik_map_test_template` | Pending | - |
| 2 | `fisik_template` | Pending | - |
| 3 | `fisik_templateresult` | Pending | - |
| 4 | `fisik_template_code` | Pending | - |
| 5 | `fisik_template_mapping` | Pending | - |
| 6 | `fisik_template_mapping_detail` | Pending | - |
| 7 | `group_result` | Pending | - |
| 8 | `group_resultdetail` | Pending | - |
| 9 | `mcu_fisiksummary` | Pending | - |
| 10 | `mcu_fisiksummarydetail` | Pending | - |
| 11 | `mcu_fisikvalue` | Pending | - |
| 12 | `mcu_fitness` | Pending | - |
| 13 | `mcu_fitness_category` | Pending | - |
| 14 | `mcu_kelainan` | Pending | - |
| 15 | `mcu_kelainangroup` | Pending | - |
| 16 | `mcu_kelainangroupsummary` | Pending | - |
| 17 | `mcu_kelainangroupsummarydetail` | Pending | - |
| 18 | `mcu_summaryfisik` | Pending | - |
| 19 | `mcu_summarylab` | Pending | - |
| 20 | `mcu_summarynonlab` | Pending | - |
| 21 | `m_companytypegroup` | Pending | - |
| 22 | `nat_advice` | Pending | - |
| 23 | `m_fpp_type` | Pending | - |
| 24 | `m_eksposi` | Pending | - |
| 25 | `m_idtype` | Pending | - |
| 26 | `m_informconsent` | Pending | - |
| 27 | `m_advice_fisik` | Pending | - |
| 28 | `m_delivery` | Pending | - |
| 29 | `m_deliverytype` | Pending | - |
| 30 | `m_instrumentmethode` | Pending | - |
| 31 | `m_methodesperma` | Pending | - |
| 32 | `m_sex` | Pending | - |
| 33 | `m_resultflag` | Pending | - |
| 34 | `m_specialist` | Pending | - |
| 35 | `m_doctor` | Pending | - |
| 36 | `m_doctoraddress` | Pending | - |
| 37 | `nat_advice_abnormal` | Pending | - |
| 38 | `nat_advice_fisik` | Pending | - |
| 39 | `nat_advice_kelainan` | Pending | - |
| 40 | `nat_bahan` | Pending | - |
| 41 | `nat_cito` | Pending | - |
| 42 | `nat_flag` | Pending | - |
| 43 | `nat_group` | Pending | - |
| 44 | `nat_inkonsistensi` | Pending | - |
| 45 | `nat_inkonsistensi_detail` | Pending | - |
| 46 | `nat_instrument` | Pending | - |
| 47 | `nat_lang` | Pending | - |
| 48 | `nat_methode` | Pending | - |
| 49 | `nat_methodeunit` | Pending | - |
| 50 | `nat_normalvalue` | Pending | - |
| 51 | `nat_normalvaluelang` | Pending | - |
| 52 | `nat_normalvaluetype` | Pending | - |
| 53 | `nat_test` | Pending | - |
| 54 | `nat_testsell` | Pending | - |
| 55 | `nat_testtype` | Pending | - |
| 56 | `nat_qc_level` | Pending | - |
| 57 | `nat_sigma` | Pending | - |
| 58 | `nat_sigmadetail` | Pending | - |
| 59 | `nat_test_loinc` | Pending | - |
| 60 | `nat_unit` | Pending | - |
| 61 | `nat_unitlang` | Pending | - |
| 62 | `nonlab_conclusion` | Pending | - |
| 63 | `nonlab_conclusion_detail` | Pending | - |
| 64 | `nonlab_conclusion_mapping` | Pending | - |
| 65 | `nonlab_template` | Pending | - |
| 66 | `nonlab_template_detail` | Pending | - |
| 67 | `nonlab_template_detail_lang` | Pending | - |
| 68 | `nonlab_template_mapping` | Pending | - |
| 69 | `nonlab_template_mcu` | Pending | - |
| 70 | `nonlab_template_result` | Pending | - |
| 71 | `nonlab_template_result_detail` | Pending | - |
| 72 | `t_antibiotic` | Pending | - |
| 73 | `t_bacteria` | Pending | - |
| 74 | `t_bahan` | Pending | - |
| 75 | `t_sampletype` | Pending | - |
| 76 | `t_test` | Pending | - |
| 77 | `t_testcalculation` | Pending | - |
| 78 | `t_testcalculation_detail` | Pending | - |
| 79 | `m_reference` | Pending | - |

View File

@@ -0,0 +1,105 @@
# Pending Task Juni 2026 - IBL
- Sumber: `Assignment pending Juni 2026 - IBL.csv`
- Total pending task: **67**
- Total kelompok subject: **5**
## Ringkasan per Subject
- IBL KLINIK: 5 task
- IBLONE: 18 task
- Satu Sehat: 1 task
- IBL REPORT: 36 task
- IBLCP: 7 task
## IBL KLINIK
| No | Assignment | Status | Time | Start date | Due on |
| --- | --- | --- | --- | --- | --- |
| 1 | Masterdata poli | Not started | - | - | - |
| 2 | Masterdata screening form | Not started | - | - | - |
| 3 | Report resume medis | Not started | - | - | - |
| 4 | Report tutup kasir | Not started | - | - | - |
| 5 | Laporan harian Pasien Klinik | Not started | - | - | - |
## IBLONE
| No | Assignment | Status | Time | Start date | Due on |
| --- | --- | --- | --- | --- | --- |
| 1 | QC Report belum keluar | Not started | - | - | - |
| 2 | Dashboard tren / grafik per periode bisa difilter by kel.pelanggan, jumlah pasien, omset dll | Not started | - | - | - |
| 3 | Member (* blm ada info dari IBL, terkait aturan dan kebutuhan datanya) | Not started | - | - | - |
| 4 | Report nota gabungan klinik dan lab | Not started | - | - | - |
| 5 | Inject hasil MCU by template (XLS Template sesuai order, hanya test lab) group by Project MCU | Not started | - | - | - |
| 6 | Report Hasil Resume Individu | Not started | - | - | - |
| 7 | Upload pdf untuk elektromedis (refrensi yang rongent) | Not started | - | - | - |
| 8 | Modul kirim hasil kurir | Not started | - | - | - |
| 9 | Modul Kirim hasil WA | Not started | - | - | - |
| 10 | Link data registrasi ke IBLCP | Not started | - | - | - |
| 11 | Link data paket dan pastient ke IBLCP | Not started | - | - | - |
| 12 | Link data checkin/checkou per station ke IBLCP | Not started | - | - | - |
| 13 | Link data abnormal ke IBLCP | Not started | - | - | - |
| 14 | Link progres result ke IBLCP | Not started | - | - | - |
| 15 | Upload pdf result ke IBLCP | Not started | - | - | - |
| 16 | Laporan Penerimaan FO | Not started | - | - | - |
| 17 | Print out pembayaran di pelunasan tagihan | Not started | - | - | - |
| 18 | Result inggris lab/nonlab/fisik | Not started | - | - | - |
## Satu Sehat
| No | Assignment | Status | Time | Start date | Due on |
| --- | --- | --- | --- | --- | --- |
| 1 | Setup satu sehat data | Not started | - | - | - |
## IBL REPORT
| No | Assignment | Status | Time | Start date | Due on |
| --- | --- | --- | --- | --- | --- |
| 1 | Report hasil MCU Global | Not started | - | - | - |
| 2 | Report gabungan individu | Not started | - | - | - |
| 3 | Report MCU Kedatangan Pasien | Not started | - | - | - |
| 4 | Laporan kedatangan dan omset pasien | Not started | - | - | - |
| 5 | Laporan Jumlah pasien poer jam | Not started | - | - | - |
| 6 | Laporan kinerja karyawan FO | Not started | - | - | - |
| 7 | Laporan akumulasi penjualan per test | Not started | - | - | - |
| 8 | Laporan serah terima hasil | Not started | - | - | - |
| 9 | Laporan rekap home service | Not started | - | - | - |
| 10 | Laporan Omset by dokter | Not started | - | - | - |
| 11 | Laporan per tipe omset | Not started | - | - | - |
| 12 | Laporan omset per company | Not started | - | - | - |
| 13 | TAT FO Registrasi | Not started | - | - | - |
| 14 | TAT Waktu tunggu sampling LAB dan NONLAB | Not started | - | - | - |
| 15 | TAT verifikasi specimen | Not started | - | - | - |
| 16 | Laporan survey pelanggan | Not started | - | - | - |
| 17 | TAT Analityc LAB | Not started | - | - | - |
| 18 | TAT Adm Nonlab | Not started | - | - | - |
| 19 | Laporan tindak lanjut QC | Not started | - | - | - |
| 20 | Laporan TAT Janji Hasil | Not started | - | - | - |
| 21 | Serah terima kasir | Not started | - | - | - |
| 22 | Laporan penerimaan pasien harian | Not started | - | - | - |
| 23 | Laporan Piutang Keuangan | Not started | - | - | - |
| 24 | Laporan Piutang Summary | Not started | - | - | - |
| 25 | Laporan piutang Detail | Not started | - | - | - |
| 26 | Laporan sales dan pendapatan | Not started | - | - | - |
| 27 | Laporan daftar void registrasi | Not started | - | - | - |
| 28 | Laporan daftar rujukan internal | Not started | - | - | - |
| 29 | Laporan rekapitulasi jumlah spesimen | Not started | - | - | - |
| 30 | Laporan Running | Not started | - | - | - |
| 31 | Laporan rekap detail MCU | Not started | - | - | - |
| 32 | Laporan pengiriman rujukan eksternal | Not started | - | - | - |
| 33 | JPA Dokter (regional) | Not started | - | - | - |
| 34 | Rekapitulasi pengiriman dokter (regional) | Not started | - | - | - |
| 35 | Laporan jasa medis pre analitik (regional) | Not started | - | - | - |
| 36 | Laporan rekapitulasi omset (regional) | Not started | - | - | - |
## IBLCP
| No | Assignment | Status | Time | Start date | Due on |
| --- | --- | --- | --- | --- | --- |
| 1 | Login dan autentifikasi | Not started | - | - | - |
| 2 | Menu Listing Project | Not started | - | - | - |
| 3 | Menu Kedatangan pasien | Not started | - | - | - |
| 4 | Menu Arrival tracking, grafik paket completion | Not started | - | - | - |
| 5 | Menu Progress result | Not started | - | - | - |
| 6 | Menu Abnormal grafik | Not started | - | - | - |
| 7 | Menu Listing result | Not started | - | - | - |

View File

@@ -0,0 +1,5 @@
-- Tambah kolom orderM_ClinicUnitID ke one_klinik.order
-- Untuk menyimpan poli yang dipilih saat registrasi
ALTER TABLE one_klinik.`order`
ADD COLUMN orderM_ClinicUnitID INT(11) NULL DEFAULT NULL AFTER orderM_LocationID;

View File

@@ -0,0 +1,5 @@
-- Tambah orderM_CompanyID ke one_klinik.order
-- (orderM_MouID sudah ada sebelumnya)
ALTER TABLE one_klinik.`order`
ADD COLUMN orderM_CompanyID INT(11) NULL DEFAULT NULL AFTER orderM_ClinicUnitID;

View File

@@ -0,0 +1,23 @@
-- Buat tabel m_clinic_unit di one_klinik
-- Untuk master poli klinik, bagian dari SATUSEHAT readiness
CREATE TABLE IF NOT EXISTS one_klinik.m_clinic_unit (
M_ClinicUnitID INT(11) NOT NULL AUTO_INCREMENT,
M_ClinicUnitCode VARCHAR(30) NOT NULL DEFAULT '',
M_ClinicUnitName VARCHAR(100) NOT NULL DEFAULT '',
M_ClinicUnitDescription VARCHAR(255) NULL DEFAULT NULL,
M_ClinicUnitSatusehatLocationID VARCHAR(64) NULL DEFAULT NULL,
M_ClinicUnitIsActive CHAR(1) NOT NULL DEFAULT 'Y',
M_ClinicUnitUserID INT(11) NULL DEFAULT NULL,
M_ClinicUnitCreated DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
M_ClinicUnitLastUpdated DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (M_ClinicUnitID),
UNIQUE KEY M_ClinicUnitCode (M_ClinicUnitCode),
KEY M_ClinicUnitIsActive (M_ClinicUnitIsActive)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO one_klinik.m_clinic_unit (M_ClinicUnitCode, M_ClinicUnitName, M_ClinicUnitDescription, M_ClinicUnitIsActive) VALUES
('POLI_UMUM', 'Poli Umum', 'Pelayanan rawat jalan umum', 'Y'),
('POLI_VAKSINASI', 'Poli Vaksinasi', 'Pelayanan imunisasi/vaksinasi', 'Y'),
('POLI_KHITAN', 'Poli Khitan', 'Pelayanan tindakan khitan', 'Y'),
('POLI_MCU', 'Poli MCU', 'Pelayanan medical check-up', 'Y');

View File

@@ -0,0 +1,160 @@
-- Buat m_screening_template: master template screening klinik
CREATE TABLE IF NOT EXISTS one_klinik.m_screening_template (
M_ScreeningTemplateID INT(11) NOT NULL AUTO_INCREMENT,
M_ScreeningTemplateCode VARCHAR(30) NOT NULL DEFAULT '',
M_ScreeningTemplateName VARCHAR(100) NOT NULL DEFAULT '',
M_ScreeningTemplateDescription VARCHAR(255) NULL DEFAULT NULL,
M_ScreeningTemplateIsActive CHAR(1) NOT NULL DEFAULT 'Y',
M_ScreeningTemplateUserID INT(11) NULL DEFAULT NULL,
M_ScreeningTemplateCreated DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
M_ScreeningTemplateLastUpdated DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (M_ScreeningTemplateID),
UNIQUE KEY uk_M_ScreeningTemplateCode (M_ScreeningTemplateCode),
KEY idx_M_ScreeningTemplateIsActive (M_ScreeningTemplateIsActive)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Master template form screening klinik';
-- Buat m_screening_form: daftar pertanyaan per template
-- M_ScreeningFormOptions: JSON array pilihan jawaban, contoh: ["Ya","Tidak"]
-- M_ScreeningFormAnswerType: single=pilih satu, multi=pilih banyak, text=isian bebas
CREATE TABLE IF NOT EXISTS one_klinik.m_screening_form (
M_ScreeningFormID INT(11) NOT NULL AUTO_INCREMENT,
M_ScreeningFormM_ScreeningTemplateID INT(11) NOT NULL,
M_ScreeningFormQuestion TEXT NOT NULL,
M_ScreeningFormAnswerType ENUM('single','multi','text') NOT NULL DEFAULT 'single',
M_ScreeningFormOptions TEXT NULL DEFAULT NULL,
M_ScreeningFormSortOrder TINYINT(3) UNSIGNED NOT NULL DEFAULT 0,
M_ScreeningFormIsRequired CHAR(1) NOT NULL DEFAULT 'Y',
M_ScreeningFormIsActive CHAR(1) NOT NULL DEFAULT 'Y',
M_ScreeningFormUserID INT(11) NULL DEFAULT NULL,
M_ScreeningFormCreated DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
M_ScreeningFormLastUpdated DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (M_ScreeningFormID),
KEY idx_M_ScreeningFormTemplateID (M_ScreeningFormM_ScreeningTemplateID),
KEY idx_M_ScreeningFormIsActive (M_ScreeningFormIsActive),
CONSTRAINT fk_sf_template
FOREIGN KEY (M_ScreeningFormM_ScreeningTemplateID)
REFERENCES m_screening_template (M_ScreeningTemplateID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Pertanyaan form screening per template';
-- ---------------------------------------------------------------------------
-- Data master template
-- ---------------------------------------------------------------------------
INSERT INTO one_klinik.m_screening_template
(M_ScreeningTemplateCode, M_ScreeningTemplateName, M_ScreeningTemplateDescription, M_ScreeningTemplateIsActive)
VALUES
('VAKSINASI', 'Screening Vaksinasi',
'Form screening pra-vaksinasi untuk menilai kelayakan pemberian vaksin', 'Y'),
('KHITAN', 'Screening Khitan',
'Form screening pra-tindakan khitan untuk menilai kelayakan pasien', 'Y');
-- ---------------------------------------------------------------------------
-- Pertanyaan template VAKSINASI
-- ---------------------------------------------------------------------------
SET @vaksin_id = (
SELECT M_ScreeningTemplateID
FROM one_klinik.m_screening_template
WHERE M_ScreeningTemplateCode = 'VAKSINASI'
);
INSERT INTO one_klinik.m_screening_form
(M_ScreeningFormM_ScreeningTemplateID, M_ScreeningFormQuestion,
M_ScreeningFormAnswerType, M_ScreeningFormOptions,
M_ScreeningFormSortOrder, M_ScreeningFormIsRequired)
VALUES
(@vaksin_id,
'Apakah saat ini sedang demam (suhu ≥ 38°C)?',
'single', '["Ya","Tidak"]', 1, 'Y'),
(@vaksin_id,
'Apakah sedang dalam kondisi sakit akut?',
'single', '["Ya","Tidak"]', 2, 'Y'),
(@vaksin_id,
'Apakah memiliki riwayat anafilaksis atau reaksi alergi berat?',
'single', '["Ya","Tidak","Tidak Tahu"]', 3, 'Y'),
(@vaksin_id,
'Apakah pernah mengalami reaksi alergi terhadap vaksin sebelumnya?',
'single', '["Ya","Tidak","Belum Pernah Divaksin"]', 4, 'Y'),
(@vaksin_id,
'Apakah sedang mengonsumsi obat imunosupresan atau menjalani kemoterapi?',
'single', '["Ya","Tidak"]', 5, 'Y'),
(@vaksin_id,
'Apakah sedang hamil atau menyusui?',
'single', '["Ya","Tidak","Tidak Berlaku"]', 6, 'Y'),
(@vaksin_id,
'Apakah memiliki riwayat penyakit kronis yang relevan? (sebutkan jika ada)',
'text', NULL, 7, 'N'),
(@vaksin_id,
'Kesimpulan: kelayakan pemberian vaksin',
'single', '["Layak","Tidak Layak","Tunda"]', 8, 'Y'),
(@vaksin_id,
'Catatan petugas screening',
'text', NULL, 9, 'N');
-- ---------------------------------------------------------------------------
-- Pertanyaan template KHITAN
-- ---------------------------------------------------------------------------
SET @khitan_id = (
SELECT M_ScreeningTemplateID
FROM one_klinik.m_screening_template
WHERE M_ScreeningTemplateCode = 'KHITAN'
);
INSERT INTO one_klinik.m_screening_form
(M_ScreeningFormM_ScreeningTemplateID, M_ScreeningFormQuestion,
M_ScreeningFormAnswerType, M_ScreeningFormOptions,
M_ScreeningFormSortOrder, M_ScreeningFormIsRequired)
VALUES
(@khitan_id,
'Apakah ada riwayat gangguan pembekuan darah atau hemofilia?',
'single', '["Ya","Tidak","Tidak Tahu"]', 1, 'Y'),
(@khitan_id,
'Apakah ada riwayat alergi terhadap obat anestesi lokal (lidokain, prokain, dll)?',
'single', '["Ya","Tidak","Tidak Tahu"]', 2, 'Y'),
(@khitan_id,
'Apakah menderita atau dicurigai Diabetes Mellitus?',
'single', '["Ya","Tidak","Dicurigai"]', 3, 'Y'),
(@khitan_id,
'Apakah saat ini sedang sakit akut atau demam (suhu ≥ 38°C)?',
'single', '["Ya","Tidak"]', 4, 'Y'),
(@khitan_id,
'Apakah sedang dalam pengobatan antikoagulan (pengencer darah)?',
'single', '["Ya","Tidak"]', 5, 'Y'),
(@khitan_id,
'Apakah ada kelainan anatomi pada area genitalia?',
'single', '["Ya","Tidak"]', 6, 'Y'),
(@khitan_id,
'Apakah pasien kooperatif untuk menjalani tindakan?',
'single', '["Kooperatif","Cukup Kooperatif","Tidak Kooperatif"]', 7, 'Y'),
(@khitan_id,
'Berat badan pasien (kg)',
'text', NULL, 8, 'Y'),
(@khitan_id,
'Tinggi badan pasien (cm)',
'text', NULL, 9, 'Y'),
(@khitan_id,
'Apakah ada riwayat tindakan bedah sebelumnya pada area genitalia?',
'single', '["Ya","Tidak"]', 10, 'N'),
(@khitan_id,
'Kesimpulan: kelayakan tindakan khitan',
'single', '["Layak","Tidak Layak","Tunda"]', 11, 'Y'),
(@khitan_id,
'Catatan petugas screening',
'text', NULL, 12, 'N');

View File

@@ -0,0 +1,8 @@
-- Fix settingM_LocationID di one_klinik.setting
-- Sebelumnya 11 (R. AUDIOMETRI), seharusnya 30 (R. PEMERIKSAAN FISIK DOKTER)
-- agar orderM_LocationID pada order klinik baru sesuai dengan locationid
-- yang dipakai halaman sampling call queue (locationid=30, stationid=7)
UPDATE one_klinik.setting
SET settingM_LocationID = 30
WHERE settingID = 9;

View File

@@ -0,0 +1,86 @@
-- ============================================================
-- 1. Tambah FK template di m_clinic_unit
-- Setiap poli mengarah ke satu screening template
-- ============================================================
ALTER TABLE one_klinik.m_clinic_unit
ADD COLUMN M_ClinicUnitM_ScreeningTemplateID INT(11) NULL DEFAULT NULL
AFTER M_ClinicUnitSatusehatLocationID;
-- ============================================================
-- 2. Tambah template DEFAULT
-- Digunakan poli yang masih pakai screening lama
-- (screening_parameter + order_screening)
-- ============================================================
INSERT INTO one_klinik.m_screening_template
(M_ScreeningTemplateCode, M_ScreeningTemplateName, M_ScreeningTemplateDescription, M_ScreeningTemplateIsActive)
VALUES
('DEFAULT', 'Screening Default',
'Menggunakan sistem screening existing (screening_parameter & order_screening)',
'Y');
-- ============================================================
-- 3. Mapping poli → template screening
-- ============================================================
UPDATE one_klinik.m_clinic_unit
SET M_ClinicUnitM_ScreeningTemplateID = (
SELECT M_ScreeningTemplateID FROM one_klinik.m_screening_template
WHERE M_ScreeningTemplateCode = 'VAKSINASI'
)
WHERE M_ClinicUnitCode = 'POLI_VAKSINASI';
UPDATE one_klinik.m_clinic_unit
SET M_ClinicUnitM_ScreeningTemplateID = (
SELECT M_ScreeningTemplateID FROM one_klinik.m_screening_template
WHERE M_ScreeningTemplateCode = 'KHITAN'
)
WHERE M_ClinicUnitCode = 'POLI_KHITAN';
UPDATE one_klinik.m_clinic_unit
SET M_ClinicUnitM_ScreeningTemplateID = (
SELECT M_ScreeningTemplateID FROM one_klinik.m_screening_template
WHERE M_ScreeningTemplateCode = 'DEFAULT'
)
WHERE M_ClinicUnitCode IN ('POLI_UMUM', 'POLI_MCU');
-- ============================================================
-- 4. Update M_ScreeningFormOptions ke format array-of-objects
-- Format per opsi: {"label":"...", "value":false, "id":"oNN"}
-- type=text → options tetap NULL (jawaban bentuk {"value":""})
-- type=single → pilih satu, value jadi true saat dipilih
-- type=multi → bisa lebih dari satu true
-- ============================================================
-- Ya / Tidak (form: 1,2,5,13,14,15,19)
UPDATE one_klinik.m_screening_form
SET M_ScreeningFormOptions = '[{"label":"Ya","value":false,"id":"o01"},{"label":"Tidak","value":false,"id":"o02"}]'
WHERE M_ScreeningFormID IN (1, 2, 5, 13, 14, 15, 19);
-- Ya / Tidak / Tidak Tahu (form: 3,10,11)
UPDATE one_klinik.m_screening_form
SET M_ScreeningFormOptions = '[{"label":"Ya","value":false,"id":"o01"},{"label":"Tidak","value":false,"id":"o02"},{"label":"Tidak Tahu","value":false,"id":"o03"}]'
WHERE M_ScreeningFormID IN (3, 10, 11);
-- Ya / Tidak / Belum Pernah Divaksin (form: 4)
UPDATE one_klinik.m_screening_form
SET M_ScreeningFormOptions = '[{"label":"Ya","value":false,"id":"o01"},{"label":"Tidak","value":false,"id":"o02"},{"label":"Belum Pernah Divaksin","value":false,"id":"o03"}]'
WHERE M_ScreeningFormID = 4;
-- Ya / Tidak / Tidak Berlaku (form: 6)
UPDATE one_klinik.m_screening_form
SET M_ScreeningFormOptions = '[{"label":"Ya","value":false,"id":"o01"},{"label":"Tidak","value":false,"id":"o02"},{"label":"Tidak Berlaku","value":false,"id":"o03"}]'
WHERE M_ScreeningFormID = 6;
-- Layak / Tidak Layak / Tunda (form: 8,20)
UPDATE one_klinik.m_screening_form
SET M_ScreeningFormOptions = '[{"label":"Layak","value":false,"id":"o01"},{"label":"Tidak Layak","value":false,"id":"o02"},{"label":"Tunda","value":false,"id":"o03"}]'
WHERE M_ScreeningFormID IN (8, 20);
-- Ya / Tidak / Dicurigai (form: 12)
UPDATE one_klinik.m_screening_form
SET M_ScreeningFormOptions = '[{"label":"Ya","value":false,"id":"o01"},{"label":"Tidak","value":false,"id":"o02"},{"label":"Dicurigai","value":false,"id":"o03"}]'
WHERE M_ScreeningFormID = 12;
-- Kooperatif / Cukup Kooperatif / Tidak Kooperatif (form: 16)
UPDATE one_klinik.m_screening_form
SET M_ScreeningFormOptions = '[{"label":"Kooperatif","value":false,"id":"o01"},{"label":"Cukup Kooperatif","value":false,"id":"o02"},{"label":"Tidak Kooperatif","value":false,"id":"o03"}]'
WHERE M_ScreeningFormID = 16;

View File

@@ -0,0 +1,5 @@
-- Ganti tipe M_PatientDOB dari DATE ke VARCHAR
-- agar nilai masked (**-**-YYYY) bisa tersimpan sebagai string
-- Nilai asli DOB ada di M_PatientDOB_enc (AES-256-GCM)
ALTER TABLE one_lab.m_patient
MODIFY COLUMN M_PatientDOB VARCHAR(20) NULL DEFAULT NULL;

View File

@@ -0,0 +1,4 @@
-- Ganti tipe Mcu_PreregisterPatientsDOB dari DATE ke VARCHAR
-- agar nilai masked (**-**-YYYY) bisa tersimpan sebagai string
ALTER TABLE one_lab.mcu_preregister_patients
MODIFY COLUMN Mcu_PreregisterPatientsDOB VARCHAR(20) NULL DEFAULT NULL;

View File

@@ -0,0 +1,5 @@
-- Tambah kolom status TTV ke tabel order
-- N = belum diisi, D = sudah selesai diisi
ALTER TABLE one_klinik.`order`
ADD COLUMN `orderIsTTV` CHAR(1) NOT NULL DEFAULT 'N'
AFTER `orderIsScreening`;

View File

@@ -0,0 +1,5 @@
-- Tambah kolom KIPI, observasi 15 menit, dan reaksi alergi ke order_vaccine
ALTER TABLE one_klinik.order_vaccine
ADD COLUMN `orderVaccineKipi` text DEFAULT NULL AFTER `orderVaccineCatatan`,
ADD COLUMN `orderVaccineObservasi15` char(1) NOT NULL DEFAULT 'N' COMMENT 'Y=Sudah N=Belum' AFTER `orderVaccineKipi`,
ADD COLUMN `orderVaccineReaksiAlergi` char(1) NOT NULL DEFAULT 'N' COMMENT 'Y=Ada N=Tidak Ada' AFTER `orderVaccineObservasi15`;

View File

@@ -0,0 +1,7 @@
-- Tambah kolom harga vaksin dari ss_price_mou ke order_vaccine
ALTER TABLE one_klinik.order_vaccine
ADD COLUMN `orderVaccineSsPriceMouID` int(11) DEFAULT NULL COMMENT 'ref ss_price_mou.Ss_PriceMouID (no FK)' AFTER `orderVaccineT_TestID`,
ADD COLUMN `orderVaccineBruto` decimal(15,2) NOT NULL DEFAULT 0 COMMENT 'harga sebelum diskon' AFTER `orderVaccineSsPriceMouID`,
ADD COLUMN `orderVaccineDiscPersen` decimal(10,2) NOT NULL DEFAULT 0 COMMENT 'diskon %' AFTER `orderVaccineBruto`,
ADD COLUMN `orderVaccineDiscRp` decimal(15,2) NOT NULL DEFAULT 0 COMMENT 'diskon Rp' AFTER `orderVaccineDiscPersen`,
ADD COLUMN `orderVaccineTotal` decimal(15,2) NOT NULL DEFAULT 0 COMMENT 'harga setelah diskon' AFTER `orderVaccineDiscRp`;

View File

@@ -0,0 +1,5 @@
-- Ganti kolom petugas penyuntik dari M_DoctorID ke M_StaffID (one_lab.m_staff)
ALTER TABLE one_klinik.order_vaccine
CHANGE COLUMN `orderVaccinePetugasM_DoctorID`
`orderVaccinePetugasM_StaffID` int(11) DEFAULT NULL
COMMENT 'petugas penyuntik FK one_lab.m_staff.M_StaffID';

View File

@@ -0,0 +1,44 @@
-- Tabel lokasi suntikan untuk vaksinasi
CREATE TABLE `one_klinik`.`m_injection_site` (
`M_InjectionSiteID` int(11) NOT NULL AUTO_INCREMENT,
`M_InjectionSiteCode` varchar(30) NOT NULL DEFAULT '',
`M_InjectionSiteName` varchar(100) NOT NULL DEFAULT '',
`M_InjectionSiteIsActive` char(1) NOT NULL DEFAULT 'Y',
`M_InjectionSiteUserID` int(11) DEFAULT NULL,
`M_InjectionSiteCreated` datetime NOT NULL DEFAULT current_timestamp(),
`M_InjectionSiteLastUpdated` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`M_InjectionSiteID`),
UNIQUE KEY `M_InjectionSiteCode` (`M_InjectionSiteCode`),
KEY `M_InjectionSiteIsActive` (`M_InjectionSiteIsActive`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `one_klinik`.`m_injection_site` (M_InjectionSiteCode, M_InjectionSiteName) VALUES
('DELTOID_L', 'Deltoid Kiri'),
('DELTOID_R', 'Deltoid Kanan'),
('THIGH_L', 'Paha Kiri'),
('THIGH_R', 'Paha Kanan'),
('GLUTEAL_L', 'Bokong Kiri'),
('GLUTEAL_R', 'Bokong Kanan'),
('FOREARM_L', 'Lengan Bawah Kiri'),
('FOREARM_R', 'Lengan Bawah Kanan');
-- Tabel rute pemberian vaksin
CREATE TABLE `one_klinik`.`m_route_vaccine` (
`M_RouteVaccineID` int(11) NOT NULL AUTO_INCREMENT,
`M_RouteVaccineCode` varchar(30) NOT NULL DEFAULT '',
`M_RouteVaccineName` varchar(150) NOT NULL DEFAULT '',
`M_RouteVaccineIsActive` char(1) NOT NULL DEFAULT 'Y',
`M_RouteVaccineUserID` int(11) DEFAULT NULL,
`M_RouteVaccineCreated` datetime NOT NULL DEFAULT current_timestamp(),
`M_RouteVaccineLastUpdated` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`M_RouteVaccineID`),
UNIQUE KEY `M_RouteVaccineCode` (`M_RouteVaccineCode`),
KEY `M_RouteVaccineIsActive` (`M_RouteVaccineIsActive`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `one_klinik`.`m_route_vaccine` (M_RouteVaccineCode, M_RouteVaccineName) VALUES
('IM', 'Intramuskular (ke otot)'),
('SC', 'Subkutan (bawah kulit)'),
('ID', 'Intradermal (lapisan kulit)'),
('Oral', 'Diminum'),
('Intranasal', 'Melalui hidung');

View File

@@ -0,0 +1,21 @@
-- Tabel pencatatan tindakan medis per kunjungan
CREATE TABLE `one_klinik`.`order_tindakan` (
`orderTindakanID` int(11) NOT NULL AUTO_INCREMENT,
`orderTindakanOrderID` int(11) NOT NULL DEFAULT 0,
`orderTindakanT_TestID` int(11) NOT NULL DEFAULT 0 COMMENT 'ref one_lab.t_test - jenis tindakan',
`orderTindakanSsPriceMouID` int(11) DEFAULT NULL COMMENT 'ref one_lab.ss_price_mou.Ss_PriceMouID (no FK)',
`orderTindakanBruto` decimal(15,2) NOT NULL DEFAULT 0 COMMENT 'harga sebelum diskon',
`orderTindakanDiscPersen` decimal(10,2) NOT NULL DEFAULT 0 COMMENT 'diskon %',
`orderTindakanDiscRp` decimal(15,2) NOT NULL DEFAULT 0 COMMENT 'diskon Rp',
`orderTindakanTotal` decimal(15,2) NOT NULL DEFAULT 0 COMMENT 'harga setelah diskon',
`orderTindakanM_DoctorID` int(11) DEFAULT NULL COMMENT 'dokter yang melakukan tindakan (no FK)',
`orderTindakanPerformedAt` datetime NOT NULL DEFAULT current_timestamp() COMMENT 'jam dilakukan tindakan',
`orderTindakanCatatan` text DEFAULT NULL,
`orderTindakanIsActive` char(1) NOT NULL DEFAULT 'Y',
`orderTindakanUserID` int(11) DEFAULT NULL,
`orderTindakanCreated` datetime NOT NULL DEFAULT current_timestamp(),
`orderTindakanLastUpdated` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`orderTindakanID`),
KEY `orderTindakanOrderID` (`orderTindakanOrderID`),
KEY `orderTindakanIsActive` (`orderTindakanIsActive`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

View File

@@ -0,0 +1,22 @@
-- Tabel pencatatan pemberian vaksin per kunjungan
CREATE TABLE `one_klinik`.`order_vaccine` (
`orderVaccineID` int(11) NOT NULL AUTO_INCREMENT,
`orderVaccineOrderID` int(11) NOT NULL DEFAULT 0,
`orderVaccineT_TestID` int(11) NOT NULL DEFAULT 0 COMMENT 'FK one_lab.t_test - jenis vaksin',
`orderVaccineBatchNumber` varchar(50) DEFAULT NULL,
`orderVaccineExpiredDate` date DEFAULT NULL,
`orderVaccineDosis` tinyint(3) NOT NULL DEFAULT 1 COMMENT 'dosis ke-',
`orderVaccineInjectionSiteCode` varchar(30) DEFAULT NULL COMMENT 'FK m_injection_site.M_InjectionSiteCode',
`orderVaccineRouteCode` varchar(30) DEFAULT NULL COMMENT 'FK m_route_vaccine.M_RouteVaccineCode',
`orderVaccinePetugasM_DoctorID` int(11) DEFAULT NULL COMMENT 'petugas penyuntik',
`orderVaccineGivenAt` datetime NOT NULL DEFAULT current_timestamp() COMMENT 'tanggal & jam pemberian',
`orderVaccineNextDate` date DEFAULT NULL COMMENT 'tanggal vaksin selanjutnya',
`orderVaccineCatatan` text DEFAULT NULL,
`orderVaccineIsActive` char(1) NOT NULL DEFAULT 'Y',
`orderVaccineUserID` int(11) DEFAULT NULL,
`orderVaccineCreated` datetime NOT NULL DEFAULT current_timestamp(),
`orderVaccineLastUpdated` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`orderVaccineID`),
KEY `orderVaccineOrderID` (`orderVaccineOrderID`),
KEY `orderVaccineIsActive` (`orderVaccineIsActive`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

View File

@@ -0,0 +1,19 @@
-- Tabel jawaban screening untuk template VAKSINASI dan KHITAN
-- Satu baris per pertanyaan per order
-- Template DEFAULT tetap pakai order_screening (lama)
CREATE TABLE IF NOT EXISTS one_klinik.t_screening_answer (
T_ScreeningAnswerID INT(11) NOT NULL AUTO_INCREMENT,
T_ScreeningAnswerOrderID INT(11) NOT NULL,
T_ScreeningAnswerM_ScreeningFormID INT(11) NOT NULL,
T_ScreeningAnswerValue TEXT NULL DEFAULT NULL,
T_ScreeningAnswerIsActive CHAR(1) NOT NULL DEFAULT 'Y',
T_ScreeningAnswerUserID INT(11) NULL DEFAULT NULL,
T_ScreeningAnswerCreated DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
T_ScreeningAnswerLastUpdated DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (T_ScreeningAnswerID),
UNIQUE KEY uk_order_form (T_ScreeningAnswerOrderID, T_ScreeningAnswerM_ScreeningFormID),
KEY idx_T_ScreeningAnswerOrderID (T_ScreeningAnswerOrderID),
CONSTRAINT fk_sa_form FOREIGN KEY (T_ScreeningAnswerM_ScreeningFormID)
REFERENCES m_screening_form (M_ScreeningFormID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COMMENT='Jawaban screening per pertanyaan untuk template VAKSINASI & KHITAN';

View File

@@ -0,0 +1,66 @@
-- Update M_ScreeningFormOptions: id option dibuat unique per form
-- Format id: f{formID}o{optionIndex}, contoh form 1 opsi 1 = f01o01
UPDATE one_klinik.m_screening_form SET M_ScreeningFormOptions =
'[{"label":"Ya","value":false,"id":"f01o01"},{"label":"Tidak","value":false,"id":"f01o02"}]'
WHERE M_ScreeningFormID = 1;
UPDATE one_klinik.m_screening_form SET M_ScreeningFormOptions =
'[{"label":"Ya","value":false,"id":"f02o01"},{"label":"Tidak","value":false,"id":"f02o02"}]'
WHERE M_ScreeningFormID = 2;
UPDATE one_klinik.m_screening_form SET M_ScreeningFormOptions =
'[{"label":"Ya","value":false,"id":"f03o01"},{"label":"Tidak","value":false,"id":"f03o02"},{"label":"Tidak Tahu","value":false,"id":"f03o03"}]'
WHERE M_ScreeningFormID = 3;
UPDATE one_klinik.m_screening_form SET M_ScreeningFormOptions =
'[{"label":"Ya","value":false,"id":"f04o01"},{"label":"Tidak","value":false,"id":"f04o02"},{"label":"Belum Pernah Divaksin","value":false,"id":"f04o03"}]'
WHERE M_ScreeningFormID = 4;
UPDATE one_klinik.m_screening_form SET M_ScreeningFormOptions =
'[{"label":"Ya","value":false,"id":"f05o01"},{"label":"Tidak","value":false,"id":"f05o02"}]'
WHERE M_ScreeningFormID = 5;
UPDATE one_klinik.m_screening_form SET M_ScreeningFormOptions =
'[{"label":"Ya","value":false,"id":"f06o01"},{"label":"Tidak","value":false,"id":"f06o02"},{"label":"Tidak Berlaku","value":false,"id":"f06o03"}]'
WHERE M_ScreeningFormID = 6;
UPDATE one_klinik.m_screening_form SET M_ScreeningFormOptions =
'[{"label":"Layak","value":false,"id":"f08o01"},{"label":"Tidak Layak","value":false,"id":"f08o02"},{"label":"Tunda","value":false,"id":"f08o03"}]'
WHERE M_ScreeningFormID = 8;
UPDATE one_klinik.m_screening_form SET M_ScreeningFormOptions =
'[{"label":"Ya","value":false,"id":"f10o01"},{"label":"Tidak","value":false,"id":"f10o02"},{"label":"Tidak Tahu","value":false,"id":"f10o03"}]'
WHERE M_ScreeningFormID = 10;
UPDATE one_klinik.m_screening_form SET M_ScreeningFormOptions =
'[{"label":"Ya","value":false,"id":"f11o01"},{"label":"Tidak","value":false,"id":"f11o02"},{"label":"Tidak Tahu","value":false,"id":"f11o03"}]'
WHERE M_ScreeningFormID = 11;
UPDATE one_klinik.m_screening_form SET M_ScreeningFormOptions =
'[{"label":"Ya","value":false,"id":"f12o01"},{"label":"Tidak","value":false,"id":"f12o02"},{"label":"Dicurigai","value":false,"id":"f12o03"}]'
WHERE M_ScreeningFormID = 12;
UPDATE one_klinik.m_screening_form SET M_ScreeningFormOptions =
'[{"label":"Ya","value":false,"id":"f13o01"},{"label":"Tidak","value":false,"id":"f13o02"}]'
WHERE M_ScreeningFormID = 13;
UPDATE one_klinik.m_screening_form SET M_ScreeningFormOptions =
'[{"label":"Ya","value":false,"id":"f14o01"},{"label":"Tidak","value":false,"id":"f14o02"}]'
WHERE M_ScreeningFormID = 14;
UPDATE one_klinik.m_screening_form SET M_ScreeningFormOptions =
'[{"label":"Ya","value":false,"id":"f15o01"},{"label":"Tidak","value":false,"id":"f15o02"}]'
WHERE M_ScreeningFormID = 15;
UPDATE one_klinik.m_screening_form SET M_ScreeningFormOptions =
'[{"label":"Kooperatif","value":false,"id":"f16o01"},{"label":"Cukup Kooperatif","value":false,"id":"f16o02"},{"label":"Tidak Kooperatif","value":false,"id":"f16o03"}]'
WHERE M_ScreeningFormID = 16;
UPDATE one_klinik.m_screening_form SET M_ScreeningFormOptions =
'[{"label":"Ya","value":false,"id":"f19o01"},{"label":"Tidak","value":false,"id":"f19o02"}]'
WHERE M_ScreeningFormID = 19;
UPDATE one_klinik.m_screening_form SET M_ScreeningFormOptions =
'[{"label":"Layak","value":false,"id":"f20o01"},{"label":"Tidak Layak","value":false,"id":"f20o02"},{"label":"Tunda","value":false,"id":"f20o03"}]'
WHERE M_ScreeningFormID = 20;

View File

@@ -0,0 +1,26 @@
-- Tabel item order klinik, setara one_lab.t_orderdetailorder
CREATE TABLE `one_klinik`.`order_detail_order` (
`orderDetailOrderID` int(11) NOT NULL AUTO_INCREMENT,
`orderDetailOrderOrderID` int(11) NOT NULL DEFAULT 0 COMMENT 'ref one_klinik.order.orderID',
`orderDetailOrderSsPriceMouID` int(11) DEFAULT NULL COMMENT 'ref one_lab.ss_price_mou.Ss_PriceMouID (no FK)',
`orderDetailOrderT_TestID` int(11) NOT NULL DEFAULT 0,
`orderDetailOrderT_TestName` varchar(255) NOT NULL DEFAULT '',
`orderDetailOrderT_TestSasCode` varchar(25) NOT NULL DEFAULT '',
`orderDetailOrderIsPacket` char(1) NOT NULL DEFAULT 'N',
`orderDetailOrderPacketType` varchar(5) NOT NULL DEFAULT 'PX',
`orderDetailOrderT_PacketID` int(11) NOT NULL DEFAULT 0,
`orderDetailOrderT_PacketName` varchar(255) NOT NULL DEFAULT '',
`orderDetailOrderT_PriceAmount` double NOT NULL DEFAULT 0,
`orderDetailOrderT_PriceDisc` double NOT NULL DEFAULT 0,
`orderDetailOrderT_PriceDiscRp` double NOT NULL DEFAULT 0,
`orderDetailOrderT_PriceSubTotal` double NOT NULL DEFAULT 0,
`orderDetailOrderT_PriceTotal` double NOT NULL DEFAULT 0,
`orderDetailOrderJsonChildren` longtext DEFAULT NULL,
`orderDetailOrderIsActive` char(1) NOT NULL DEFAULT 'Y',
`orderDetailOrderUserID` int(11) DEFAULT NULL,
`orderDetailOrderCreated` datetime NOT NULL DEFAULT current_timestamp(),
`orderDetailOrderLastUpdated` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`orderDetailOrderID`),
KEY `orderDetailOrderOrderID` (`orderDetailOrderOrderID`),
KEY `orderDetailOrderIsActive` (`orderDetailOrderIsActive`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

View File

@@ -0,0 +1,88 @@
-- Stored procedure: hitung total dari 3 tabel dan update orderSubtotal+orderTotal
DROP PROCEDURE IF EXISTS one_klinik.sync_order_total;
DELIMITER $$
CREATE PROCEDURE one_klinik.sync_order_total(IN p_order_id INT)
BEGIN
DECLARE v_total DECIMAL(15,2);
SET v_total = (
COALESCE((SELECT SUM(orderDetailOrderT_PriceTotal)
FROM one_klinik.order_detail_order
WHERE orderDetailOrderOrderID = p_order_id
AND orderDetailOrderIsActive = 'Y'), 0)
+
COALESCE((SELECT SUM(orderVaccineTotal)
FROM one_klinik.order_vaccine
WHERE orderVaccineOrderID = p_order_id
AND orderVaccineIsActive = 'Y'), 0)
+
COALESCE((SELECT SUM(orderTindakanTotal)
FROM one_klinik.order_tindakan
WHERE orderTindakanOrderID = p_order_id
AND orderTindakanIsActive = 'Y'), 0)
);
UPDATE one_klinik.`order`
SET orderSubtotal = v_total,
orderTotal = v_total
WHERE orderID = p_order_id;
END$$
-- ── order_detail_order ────────────────────────────────────────────────────────
DROP TRIGGER IF EXISTS one_klinik.trg_odo_ai$$
CREATE TRIGGER one_klinik.trg_odo_ai
AFTER INSERT ON one_klinik.order_detail_order
FOR EACH ROW
CALL one_klinik.sync_order_total(NEW.orderDetailOrderOrderID)$$
DROP TRIGGER IF EXISTS one_klinik.trg_odo_au$$
CREATE TRIGGER one_klinik.trg_odo_au
AFTER UPDATE ON one_klinik.order_detail_order
FOR EACH ROW
CALL one_klinik.sync_order_total(NEW.orderDetailOrderOrderID)$$
DROP TRIGGER IF EXISTS one_klinik.trg_odo_ad$$
CREATE TRIGGER one_klinik.trg_odo_ad
AFTER DELETE ON one_klinik.order_detail_order
FOR EACH ROW
CALL one_klinik.sync_order_total(OLD.orderDetailOrderOrderID)$$
-- ── order_vaccine ─────────────────────────────────────────────────────────────
DROP TRIGGER IF EXISTS one_klinik.trg_ov_ai$$
CREATE TRIGGER one_klinik.trg_ov_ai
AFTER INSERT ON one_klinik.order_vaccine
FOR EACH ROW
CALL one_klinik.sync_order_total(NEW.orderVaccineOrderID)$$
DROP TRIGGER IF EXISTS one_klinik.trg_ov_au$$
CREATE TRIGGER one_klinik.trg_ov_au
AFTER UPDATE ON one_klinik.order_vaccine
FOR EACH ROW
CALL one_klinik.sync_order_total(NEW.orderVaccineOrderID)$$
DROP TRIGGER IF EXISTS one_klinik.trg_ov_ad$$
CREATE TRIGGER one_klinik.trg_ov_ad
AFTER DELETE ON one_klinik.order_vaccine
FOR EACH ROW
CALL one_klinik.sync_order_total(OLD.orderVaccineOrderID)$$
-- ── order_tindakan ────────────────────────────────────────────────────────────
DROP TRIGGER IF EXISTS one_klinik.trg_ot_ai$$
CREATE TRIGGER one_klinik.trg_ot_ai
AFTER INSERT ON one_klinik.order_tindakan
FOR EACH ROW
CALL one_klinik.sync_order_total(NEW.orderTindakanOrderID)$$
DROP TRIGGER IF EXISTS one_klinik.trg_ot_au$$
CREATE TRIGGER one_klinik.trg_ot_au
AFTER UPDATE ON one_klinik.order_tindakan
FOR EACH ROW
CALL one_klinik.sync_order_total(NEW.orderTindakanOrderID)$$
DROP TRIGGER IF EXISTS one_klinik.trg_ot_ad$$
CREATE TRIGGER one_klinik.trg_ot_ad
AFTER DELETE ON one_klinik.order_tindakan
FOR EACH ROW
CALL one_klinik.sync_order_total(OLD.orderTindakanOrderID)$$
DELIMITER ;

View File

@@ -0,0 +1,84 @@
-- PDP: Radiology/nonlab BIRT header reads decrypted patient data from patient_print_cache.
-- Birt_proxy_nonlab populates this cache before fetching BIRT, then deletes it after streaming.
USE `one_lab`;
DROP PROCEDURE IF EXISTS `sp_rpt_hasil_header_nonLab`;
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_rpt_hasil_header_nonLab`(
IN `PID` int,
IN `username` varchar(100)
)
BEGIN
DELETE FROM patient_print_cache
WHERE ppc_created < NOW() - INTERVAL 5 MINUTE;
SELECT
DATE_FORMAT(T_OrderHeaderDate, "%d-%m-%Y") AS T_OrderHeaderDate,
T_OrderHeaderLabNumber,
CONCAT(M_TitleName, ". ", COALESCE(NULLIF(ppc.ppc_name, ''), M_PatientName)) AS M_PatientName,
m_sexname AS Gender,
M_PatientNoReg,
COALESCE(NULLIF(ppc.ppc_dob, ''), DATE_FORMAT(M_PatientDOB, "%d-%m-%Y")) AS M_PatientDOB,
T_OrderHeaderM_PatientAge,
M_CompanyName AS CorporateName,
COALESCE(NULLIF(ppc.ppc_address, ''), (
SELECT CONCAT(M_PatientAddressDescription, ' ', M_DistrictName, ' ', M_CityName)
FROM m_patientaddress AS p
LEFT JOIN (SELECT regional_cd, regional_nm AS M_KelurahanName, pro_cd, kab_cd, kec_cd FROM regional) reg_kel
ON NULLIF(TRIM(p.M_PatientAddressRegionalCd), '') = reg_kel.regional_cd
LEFT JOIN (SELECT regional_cd, regional_nm AS M_DistrictName FROM regional) reg_kec
ON CONCAT(reg_kel.pro_cd, reg_kel.kab_cd, reg_kel.kec_cd, '000') = reg_kec.regional_cd
LEFT JOIN (SELECT regional_cd, regional_nm AS M_CityName FROM regional) reg_kab
ON CONCAT(reg_kel.pro_cd, reg_kel.kab_cd, '000000') = reg_kab.regional_cd
WHERE M_PatientAddressM_PatientID = M_PatientID
ORDER BY M_PatientAddressM_PatientID
LIMIT 1
)) AS M_PatientAddress,
COALESCE(NULLIF(ppc.ppc_hp, ''), M_PatientHp) AS M_PatientHp,
COALESCE(NULLIF(ppc.ppc_email, ''), M_PatientEmail) AS M_PatientEmail,
'' AS M_PatientAddressCity,
COALESCE(NULLIF(ppc.ppc_address, ''), (
SELECT CONCAT(M_PatientAddressDescription, ' ', M_DistrictName, ' ', M_CityName)
FROM m_patientaddress AS p
LEFT JOIN (SELECT regional_cd, regional_nm AS M_KelurahanName, pro_cd, kab_cd, kec_cd FROM regional) reg_kel
ON NULLIF(TRIM(p.M_PatientAddressRegionalCd), '') = reg_kel.regional_cd
LEFT JOIN (SELECT regional_cd, regional_nm AS M_DistrictName FROM regional) reg_kec
ON CONCAT(reg_kel.pro_cd, reg_kel.kab_cd, reg_kel.kec_cd, '000') = reg_kec.regional_cd
LEFT JOIN (SELECT regional_cd, regional_nm AS M_CityName FROM regional) reg_kab
ON CONCAT(reg_kel.pro_cd, reg_kel.kab_cd, '000000') = reg_kab.regional_cd
WHERE M_PatientAddressM_PatientID = M_PatientID
ORDER BY M_PatientAddressM_PatientID
LIMIT 1
)) AS M_PatientAddressState,
M_CompanyAddress AS CorporateAddress,
M_CompanyEmail,
M_CompanyPhone,
M_CompanyAddressCity,
'' AS CorporateAddressState,
CONCAT(IFNULL(pj.M_DoctorPrefix, ''), ' ', IFNULL(pj.M_DoctorPrefix2, ''), ' ', pj.M_DoctorName, ' ', IFNULL(pj.M_DoctorSufix, ''), ' ', IFNULL(pj.M_DoctorSufix2, '')) AS M_DoctorName,
CONCAT(IFNULL(pjj.M_DoctorPrefix, ''), ' ', IFNULL(pjj.M_DoctorPrefix2, ''), ' ', pjj.M_DoctorName, ' ', IFNULL(pjj.M_DoctorSufix, ''), ' ', IFNULL(pjj.M_DoctorSufix2, '')) AS M_DoctorName2,
CONCAT(COALESCE(NULLIF(ppc.ppc_dob, ''), DATE_FORMAT(M_PatientDOB, "%d-%m-%Y")), ' / ', T_OrderHeaderM_PatientAge) AS Umur,
M_PatientNIP,
M_PatientJob,
M_PatientPosisi,
M_PatientDivisi,
M_PatientLocation,
CONCAT(M_PatientDepartement, ' - ', M_PatientNIP) AS M_PatientDepartement
FROM t_orderheader
JOIN m_patient ON T_OrderHeaderM_PatientID = M_PatientID AND M_PatientIsActive = 'Y'
JOIN m_title ON M_PatientM_TitleID = M_TitleID AND M_TitleIsActive = 'Y'
JOIN m_company ON T_OrderHeaderM_CompanyID = M_CompanyID AND M_CompanyIsActive = 'Y'
LEFT JOIN m_sex ON M_PatientM_SexID = M_SexID
LEFT JOIN m_doctor pjj ON T_OrderHeaderPj2M_DoctorID = pjj.M_DoctorID AND pjj.M_DoctorIsActive = 'Y'
LEFT JOIN m_doctor pj ON T_OrderHeaderPjM_DoctorID = pj.M_DoctorID AND pj.M_DoctorIsActive = 'Y'
JOIN so_resultentry ON So_ResultEntryT_OrderHeaderID = T_OrderHeaderID AND So_ResultEntryIsActive = 'Y'
LEFT JOIN patient_print_cache ppc ON ppc.ppc_order_id = T_OrderHeaderID
WHERE So_ResultEntryID = PID
AND T_OrderHeaderIsActive = 'Y'
GROUP BY T_OrderHeaderID;
END$$
DELIMITER ;

View File

@@ -0,0 +1,34 @@
-- Add M_PatientPhoto AS Photo to sp_rpt_fo_001 so kartu_kontrol PDF can render patient photo
DROP PROCEDURE IF EXISTS `sp_rpt_fo_001`;
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_rpt_fo_001`(IN `PID` int, IN `username` varchar(100))
BEGIN
DELETE FROM patient_print_cache WHERE ppc_created < NOW() - INTERVAL 5 MINUTE;
SELECT
CONCAT(M_TitleName,' ',IFNULL(M_PatientPrefix,''),' ',
COALESCE(NULLIF(ppc.ppc_name,''), M_PatientName),' ',IFNULL(M_PatientSuffix,'')) AS M_PatientName,
COALESCE(NULLIF(ppc.ppc_dob,''), DATE_FORMAT(M_PatientDOB,'%d-%m-%Y')) AS M_PatientDOB,
CONCAT(COALESCE(NULLIF(ppc.ppc_dob,''), DATE_FORMAT(M_PatientDOB,'%d-%m-%Y')),' / ',T_OrderHeaderM_PatientAge,' / ',M_SexCode) AS Umur,
COALESCE(NULLIF(ppc.ppc_hp,''), M_PatientHP) AS M_PatientHP,
COALESCE(NULLIF(ppc.ppc_hp,''), M_PatientPhone) AS M_PatientPhone,
COALESCE(NULLIF(ppc.ppc_email,''), M_PatientEmail) AS M_PatientEmail,
COALESCE(NULLIF(ppc.ppc_address,''),
(SELECT M_PatientAddressDescription FROM m_patientaddress AS p
WHERE M_PatientAddressM_PatientID = M_PatientID
ORDER BY M_PatientAddressM_PatientID LIMIT 1)
) AS M_PatientAddressDescription,
M_PatientNoReg, M_PatientIDNumber, M_PatientNIK, M_PatientPhoto AS Photo,
T_OrderHeaderLabNumber, DATE_FORMAT(T_OrderHeaderDate,'%d-%m-%Y') AS T_OrderHeaderDate,
T_OrderHeaderID, M_CompanyName, M_PatientNote
FROM t_orderheader
LEFT JOIN m_patient ON T_OrderHeaderM_PatientID = M_PatientID
LEFT JOIN m_title ON M_PatientM_TitleID = M_TitleID
LEFT JOIN m_sex ON M_PatientM_SexID = M_SexID
JOIN m_company ON T_OrderHeaderM_CompanyID = M_CompanyID
LEFT JOIN patient_print_cache ppc ON ppc.ppc_order_id = T_OrderHeaderID
WHERE T_OrderHeaderID = PID AND T_OrderHeaderIsActive = 'Y';
END
$$
DELIMITER ;

View File

@@ -0,0 +1,92 @@
-- Fix fn_numbering_klinik: change one.m_branch reference to one_lab.m_branch
-- Caused "Table 'one.m_branch' doesn't exist" error on INSERT into one_klinik.order
DROP FUNCTION IF EXISTS `fn_numbering_klinik`;
DELIMITER $$
CREATE DEFINER=`root`@`localhost` FUNCTION `fn_numbering_klinik`(`type` char(30)) RETURNS varchar(25) CHARSET utf8mb4 COLLATE utf8mb4_general_ci
READS SQL DATA
begin declare number varchar(50);
declare prefix varchar(50);
declare prefix_date varchar(50);
declare sufix varchar(50);
declare counter int;
declare dgt int;
declare rst varchar(5);
declare udt datetime;
select S_NumberingPrefix, S_NumberingPrefixDate, S_NumberingSufix, S_NumberingCounter, S_NumberingDigit, S_NumberingReset,
S_NumberingLastUpdated
into prefix, prefix_date, sufix, counter, dgt, rst, udt
from s_numbering where S_NumberingType = type for update;
if rst = 'D' then
if date_format(udt, '%Y-%m-%d') <> date_format(now(), '%Y-%m-%d') then
set counter = 1;
end if;
elseif rst = 'M' then
if date_format(udt, '%Y-%m') <> date_format(now(), '%Y-%m') then
set counter = 1;
end if;
elseif rst = 'Y' then
if date_format(udt, '%Y') <> date_format(now(), '%Y') then
set counter = 1;
end if;
end if;
set number = '';
if prefix is not null and prefix <> '' then
set number = trim(prefix);
end if;
if prefix_date is not null and prefix_date <> '' then
set number = concat(trim(number),date_format(now(),prefix_date));
if type = 'P' then
set number = concat( prefix,fn_numbering_year(now()));
end if;
if type = 'L' then
set number = fn_get_prefix_nolab( now() );
end if;
/*if type = 'PAY' then
set number = concat( trim(prefix),fn_numbering_year(now()), fn_numbering_month(now()) );
end if;*/
end if;
if rst = 'X' then
set number = counter;
else
if type='PAY' then
/*set @s_counter = lpad(counter,dgt,'0');
set @xternal = (
select numberMapTarget
from number_map
where
numberMapOrigin = @s_counter
limit 0,1
);
set number = concat(trim(number), trim(@xternal) );*/
set number = concat(trim(number), lpad(counter,dgt,'0'));
else
set number = concat(trim(number), lpad(counter,dgt,'0'));
end if;
end if;
if sufix is not null and sufix <> '' then
set number = concat(trim(number),trim(sufix));
end if;
if type = 'K' then
set @branch_code = (select M_BranchCode from one_lab.m_branch where M_BranchIsActive = 'Y'
and M_BranchIsDefault = 'Y' limit 0,1 );
set number = concat(number,@branch_code);
end if;
update s_numbering set S_NumberingCounter = counter + 1, S_NumberingLastUpdated = NOW() where S_NumberingType=type;
return trim(number);
END$$
DELIMITER ;

View File

@@ -0,0 +1,252 @@
# Task: Refactor Workflow Klinik untuk SATUSEHAT Readiness
Saat ini alur klinik:
Registrasi
→ Screening
→ Pemeriksaan Dokter
→ Kasir
Pada menu dokter terdapat:
- Anamnesa
- Pemeriksaan Tanda Vital
- Pemeriksaan Fisik
- Pemeriksaan Penunjang
- Diagnosis
- Tindakan Medis
- Resep
- Saran
Target sistem:
- Klinik Umum
- Vaksinasi
- Khitan
- Integrasi SATUSEHAT
## Perubahan yang harus dibuat
### 1. Master Poli
Buat tabel:
m_clinic_unit
Fields:
- id
- code
- name
- description
- satusehat_location_id
- is_active
Data awal:
- POLI_UMUM
- POLI_VAKSINASI
- POLI_KHITAN
- POLI_MCU
Registrasi harus memilih poli.
---
### 2. Template Screening
Buat sistem screening dinamis.
Table:
m_screening_template
- id
- code
- name
m_screening_question
- id
- template_id
- question
- question_type
- sort_order
- is_required
t_screening_answer
- id
- registration_id
- question_id
- answer
Template awal:
RAWAT_JALAN
- Kesadaran
- Pernapasan
- Nyeri Dada
- Skala Nyeri
- Risiko Jatuh
- Batuk > 2 Minggu
VAKSINASI
- Demam > 38
- Sedang sakit akut
- Riwayat anafilaksis
- Alergi vaksin
- Layak vaksin
KHITAN
- Gangguan pembekuan darah
- Alergi anestesi
- Diabetes
- Layak tindakan
MCU
- gunakan template kosong terlebih dahulu
Poli menentukan template screening yang digunakan.
---
### 3. Pisahkan TTV dari Menu Dokter
Buat modul baru:
t_vital_sign
Fields:
- registration_id
- systolic
- diastolic
- pulse
- respiratory_rate
- temperature
- weight
- height
- bmi
- created_by
- created_at
Workflow:
Registrasi
→ Screening
→ TTV
→ Dokter
Dokter hanya membaca hasil TTV.
---
### 4. Modul Vaksinasi
Buat tabel:
m_vaccine
- id
- code
- name
- kfa_code
- manufacturer
t_vaccination
- id
- registration_id
- vaccine_id
- batch_number
- expired_date
- dose_number
- route
- injection_site
- administered_by
- administration_datetime
- adverse_event_note
Data ini nantinya akan menjadi SATUSEHAT Immunization Resource.
---
### 5. Tindakan Medis Terstruktur
Buat:
m_procedure
- id
- code
- name
- snomed_code
t_medical_procedure
- id
- registration_id
- procedure_id
- performer_id
- note
Contoh master:
- Khitan Klem
- Khitan Laser
- Khitan Stapler
- Khitan Konvensional
Data ini nantinya menjadi SATUSEHAT Procedure Resource.
---
### 6. Master Tenaga Kesehatan
Buat:
m_practitioner
- id
- employee_id
- profession
- name
- satusehat_practitioner_id
Profesi:
- Dokter
- Perawat
- Bidan
Vaksinasi dan tindakan tidak selalu dilakukan dokter.
---
### 7. SATUSEHAT Mapping Preparation
Tambahkan kolom mapping:
ICD10
SNOMED
KFA
untuk:
- diagnosis
- tindakan
- vaksin
- obat
Belum perlu integrasi API SATUSEHAT.
Fokus pada kesiapan data terlebih dahulu.
---
Output yang diharapkan:
- Migration SQL
- ERD
- Repository
- Service Layer
- API Endpoint
- DTO Request/Response
- Unit Test