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 . "'"); } }