FHM31052601IBL - populate decrypt cache sebelum semua BIRT/PDF fetch

- Ibl_patient_decrypt: tambah fetch_birt_pdf() + pre_cache_and_get_url()
- Reporturl.php: auto pre-cache sebelum return URL atau fetch PDF
- Rv_patient.php: pre_cache sebelum return URL ke frontend
- tgram/Hasil.php: fetch_birt_pdf() via dl_report()
- Qr_report_uploader.php: populate/delete cache wrapping download_file()
- Ibl_merge_report_gateway.php: populate/delete cache wrapping Go merge service call
- send_email.php: populate_birt_cache() + delete_birt_cache() untuk email attachment

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
sas.fajri
2026-05-31 18:04:36 +07:00
parent a88360b1b1
commit d4ecd7f06d
7 changed files with 118 additions and 16 deletions

View File

@@ -790,6 +790,10 @@ private function get_fallback_report($group_name, $type, $ready_print)
$url = "/birt/{$mode}?__report=report/onelab/{$folder}/{$rpt_name}.rptdesign&__format=pdf&username={$username}&PID={$order_id}&tm={$tm}";
}
// Populate decrypt cache sebelum frontend buka URL ke BIRT
$this->load->library('ibl_patient_decrypt');
$this->ibl_patient_decrypt->pre_cache_and_get_url($url);
$this->sys_ok($url);
}

View File

@@ -6,6 +6,7 @@ class Hasil extends MY_Controller
{
function __construct() {
parent::__construct();
$this->load->library('ibl_patient_decrypt');
}
/* WA ------ */
function update_track() {
@@ -524,14 +525,13 @@ class Hasil extends MY_Controller
}
}
function dl_report($prm, $name) {
$url = "http://localhost/birt/frameset?" ;
$qry = "";
foreach($prm as $k => $v) {
if ($qry != "" ) $qry .= "&";
if ($qry != "") $qry .= "&";
$qry .= $k . "=" . urlencode($v);
}
$url .= $qry ;
$data = file_get_contents($url);
$relative_url = "/birt/frameset?" . $qry;
$data = $this->ibl_patient_decrypt->fetch_birt_pdf($relative_url);
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . $name);
header('Content-Transfer-Encoding: binary');

View File

@@ -8,6 +8,7 @@ class Qr_report_uploader extends MY_Controller
public function __construct()
{
parent::__construct();
$this->load->library('ibl_patient_decrypt');
$this->db_onedev = $this->load->database('onedev', true);
$this->db_log = $this->load->database('one_lab_log', true);
}
@@ -120,7 +121,11 @@ class Qr_report_uploader extends MY_Controller
$orderHeaderID = (int)$row['QR_PrintOutT_OrderHeaderID'];
$reportUrl = $row['QR_PrintOutReportURL'];
// Populate cache sebelum fetch dari BIRT
$cache_id = $this->ibl_patient_decrypt->populate_cache_by_order($orderHeaderID);
$pdfContent = $this->download_file($reportUrl);
$this->ibl_patient_decrypt->delete_cache($cache_id);
if ($pdfContent === false) {
return $this->mark_failed($row, $orderHeaderID, '', 'DOWNLOAD_FAILED');
}

View File

@@ -10,6 +10,7 @@ class Ibl_merge_report_gateway
{
$this->CI = &get_instance();
$this->db_onedev = $this->CI->load->database('onedev', true);
$this->CI->load->library('ibl_patient_decrypt');
}
public function create_merge_request_from_lab_number($labNumber, $creatorUserId, $customName = '')
@@ -593,6 +594,9 @@ class Ibl_merge_report_gateway
return $this->error('QR_PRINTOUT_EMPTY', 'URL report kosong setelah normalisasi.');
}
// Populate decrypt cache sebelum Go merge service fetch PDF dari BIRT
$cache_id = $this->CI->ibl_patient_decrypt->populate_cache_by_order($orderHeaderId);
$payload = array(
'name' => 'merge-' . (int) $orderHeaderId . '.pdf',
'urls' => $urls,
@@ -600,7 +604,12 @@ class Ibl_merge_report_gateway
'T_OrderHeaderID' => (int) $orderHeaderId,
);
return $this->call_merge_service($payload);
$result = $this->call_merge_service($payload);
// Hapus cache setelah merge service selesai
$this->CI->ibl_patient_decrypt->delete_cache($cache_id);
return $result;
}
protected function call_merge_service(array $payload)

View File

@@ -85,6 +85,38 @@ class Ibl_patient_decrypt
$this->db->query("DELETE FROM patient_print_cache WHERE ppc_created < NOW() - INTERVAL 5 MINUTE");
}
// Fetch PDF dari BIRT dengan auto decrypt cache
// Ganti semua file_get_contents($birt_url) dengan ini
public function fetch_birt_pdf($birt_relative_url)
{
// Parse PID dari URL query string
parse_str(parse_url($birt_relative_url, PHP_URL_QUERY) ?? '', $params);
$order_id = intval($params['PID'] ?? 0);
$cache_id = $order_id ? $this->populate_cache_by_order($order_id) : null;
// Build full internal URL ke BIRT server
$full_url = 'http://localhost:8080' . $birt_relative_url;
$context = stream_context_create(['http' => ['timeout' => 120]]);
$pdf = @file_get_contents($full_url, false, $context);
$this->delete_cache($cache_id);
return $pdf;
}
// Populate cache lalu return URL (untuk controller yang return URL ke frontend)
// Cache hidup 5 menit — cukup untuk browser buka BIRT
public function pre_cache_and_get_url($birt_relative_url)
{
parse_str(parse_url($birt_relative_url, PHP_URL_QUERY) ?? '', $params);
$order_id = intval($params['PID'] ?? 0);
if ($order_id) {
$this->populate_cache_by_order($order_id);
}
return $birt_relative_url;
}
private function _insert_cache($order_id, $patient_id, $name, $dob, $hp, $email, $address)
{
$this->db->query(

View File

@@ -55,20 +55,18 @@ class Reporturl
$final_url = str_replace($param_key, $replacement_value, $final_url);
}
// Populate decrypt cache sebelum return URL atau fetch PDF
$CI->load->library('ibl_patient_decrypt');
$CI->ibl_patient_decrypt->pre_cache_and_get_url($final_url);
if($show == 'N'){
return array(true, $final_url);
}
else{
$final_url = 'http'.($_SERVER['HTTPS'] == 'on' ? 's' : '').'://'.$_SERVER['HTTP_HOST'].$final_url;
$response = file_get_contents($final_url);
$pdf = $CI->ibl_patient_decrypt->fetch_birt_pdf($final_url);
header("Content-type: application/pdf");
header(
'Content-Disposition: inline; filename="' .
$output_file_name .
'"'
);
echo ($response);
header('Content-Disposition: inline; filename="' . ($output_file_name ?? 'report.pdf') . '"');
echo $pdf;
}
}

View File

@@ -60,6 +60,58 @@ function download_pdf(string $url)
return $data;
}
// Load ibl_encryptor untuk decrypt PII sebelum fetch PDF dari BIRT
define('BASEPATH', true);
$_env_file = __DIR__ . '/../.env';
if (file_exists($_env_file)) {
foreach (file($_env_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $_l) {
if (strpos(trim($_l), '#') === 0) continue;
[$_k, $_v] = array_map('trim', explode('=', $_l, 2));
if ($_k !== '') $_ENV[$_k] = $_v;
}
}
require __DIR__ . '/../application/libraries/Ibl_encryptor.php';
$_enc = new Ibl_encryptor();
// Populate patient_print_cache sebelum fetch PDF dari BIRT
function populate_birt_cache(PDO $pdo, $enc, string $birt_url): ?int
{
parse_str(parse_url($birt_url, PHP_URL_QUERY) ?? '', $params);
$order_id = intval($params['PID'] ?? 0);
if (!$order_id) return null;
$patient = $pdo->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 = {$order_id} LIMIT 1"
)->fetch(PDO::FETCH_ASSOC);
if (!$patient) return null;
$addr = $pdo->query(
"SELECT M_PatientAddressDescription_enc FROM m_patientaddress
WHERE M_PatientAddressM_PatientID = {$patient['M_PatientID']}
AND M_PatientAddressIsActive = 'Y' AND M_PatientAddressNote = 'Utama' LIMIT 1"
)->fetch(PDO::FETCH_ASSOC);
$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'] ?? '') ?? '';
$pdo->exec("DELETE FROM patient_print_cache WHERE ppc_order_id = {$order_id} OR ppc_created < NOW() - INTERVAL 5 MINUTE");
$stmt = $pdo->prepare("INSERT INTO patient_print_cache (ppc_order_id, ppc_patient_id, ppc_name, ppc_dob, ppc_hp, ppc_email, ppc_address) VALUES (?,?,?,?,?,?,?)");
$stmt->execute([$order_id, $patient['M_PatientID'], $name, $dob, $hp, $email, $address]);
return (int)$pdo->lastInsertId();
}
function delete_birt_cache(PDO $pdo, ?int $cache_id): void
{
if ($cache_id) $pdo->exec("DELETE FROM patient_print_cache WHERE ppc_id = {$cache_id}");
}
function encrypt_pdf(string $input_path, string $password)
{
$output_path = $input_path . '_enc.pdf';
@@ -308,7 +360,9 @@ foreach ($rows as $row) {
log_msg(" Downloading attachment " . ($idx + 1) . " [{$result}]: {$url}");
$cache_id = populate_birt_cache($pdo, $GLOBALS['_enc'], $url);
$pdf = download_pdf($url);
delete_birt_cache($pdo, $cache_id);
if ($pdf === false) {
log_msg(" Download failed, skipping");
continue;