- 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>
761 lines
27 KiB
PHP
761 lines
27 KiB
PHP
<?php
|
|
defined('BASEPATH') or exit('No direct script access allowed');
|
|
|
|
class Ibl_merge_report_gateway
|
|
{
|
|
protected $CI;
|
|
protected $db_onedev;
|
|
|
|
public function __construct()
|
|
{
|
|
$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 = '')
|
|
{
|
|
$order = $this->resolve_order_by_lab_number($labNumber);
|
|
if (!$order) {
|
|
return $this->error('ORDER_NOT_FOUND', 'Nomor lab tidak ditemukan.');
|
|
}
|
|
|
|
return $this->create_merge_request_from_order($order['T_OrderHeaderID'], $creatorUserId, $customName);
|
|
}
|
|
|
|
public function create_merge_request_from_order($orderHeaderId, $creatorUserId, $customName = '')
|
|
{
|
|
$order = $this->get_order_header($orderHeaderId);
|
|
if (!$order) {
|
|
return $this->error('ORDER_NOT_FOUND', 'Order tidak ditemukan.');
|
|
}
|
|
|
|
$composition = $this->compose_merge_request_payload($orderHeaderId, $customName);
|
|
if ($composition['status'] !== 'OK') {
|
|
return $composition;
|
|
}
|
|
|
|
$payloadJson = json_encode($composition['data']['snapshot'], JSON_UNESCAPED_SLASHES);
|
|
$insert = $this->db_onedev->query(
|
|
"INSERT INTO merge_request (
|
|
mergeRequestT_OrderHeaderID,
|
|
mergeRequestPayload,
|
|
mergeRequestCreatedUserID,
|
|
mergeRequestCreated
|
|
) VALUES (?, ?, ?, NOW())",
|
|
array(
|
|
$orderHeaderId,
|
|
$payloadJson,
|
|
$creatorUserId
|
|
)
|
|
);
|
|
|
|
if (!$insert) {
|
|
return $this->error('MERGE_REQUEST_INSERT_FAILED', 'Gagal menyimpan merge request.');
|
|
}
|
|
|
|
$mergeRequestId = (int) $this->db_onedev->insert_id();
|
|
$previewUrl = $this->build_preview_url($mergeRequestId);
|
|
|
|
$goPayload = $this->build_go_payload_from_snapshot(
|
|
$mergeRequestId,
|
|
$orderHeaderId,
|
|
$composition['data']['snapshot']
|
|
);
|
|
|
|
return array(
|
|
'status' => 'OK',
|
|
'data' => array(
|
|
'mergeRequestID' => $mergeRequestId,
|
|
'T_OrderHeaderID' => (int) $orderHeaderId,
|
|
'T_OrderHeaderLabNumber' => $order['T_OrderHeaderLabNumber'],
|
|
'previewUrl' => $previewUrl,
|
|
'snapshot' => $composition['data']['snapshot'],
|
|
'goPayloadPreview' => $goPayload
|
|
)
|
|
);
|
|
}
|
|
|
|
public function compose_merge_request_payload($orderHeaderId, $customName = '')
|
|
{
|
|
$order = $this->get_order_header($orderHeaderId);
|
|
if (!$order) {
|
|
return $this->error('ORDER_NOT_FOUND', 'Order tidak ditemukan.');
|
|
}
|
|
|
|
$summary = $this->get_merge_summary_by_order_id($orderHeaderId);
|
|
if ($summary['status'] !== 'OK') {
|
|
return $summary;
|
|
}
|
|
|
|
if ($summary['data']['available_merge'] !== 'Y') {
|
|
return $this->error('MERGE_NOT_READY', 'Order belum siap untuk merge report.');
|
|
}
|
|
|
|
$sources = array();
|
|
$sourceDedup = array();
|
|
|
|
foreach ($summary['data']['records'] as $group) {
|
|
if (empty($group['group_result_ids'])) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($group['group_result_ids'] as $groupResultId) {
|
|
$groupSources = $this->get_group_sources(
|
|
$order,
|
|
(int) $groupResultId
|
|
);
|
|
|
|
if ($groupSources['status'] !== 'OK') {
|
|
return $groupSources;
|
|
}
|
|
|
|
foreach ($groupSources['data'] as $source) {
|
|
if ($source['relativeUrl'] === '') {
|
|
return $this->error('MERGE_SOURCE_MISSING', 'Salah satu sumber report belum tersedia.');
|
|
}
|
|
|
|
if (isset($sourceDedup[$source['absoluteUrl']])) {
|
|
continue;
|
|
}
|
|
|
|
$sourceDedup[$source['absoluteUrl']] = true;
|
|
$sources[] = $source;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (count($sources) === 0) {
|
|
return $this->error('MERGE_SOURCE_EMPTY', 'Tidak ada sumber report yang bisa digabung.');
|
|
}
|
|
|
|
$fileName = $this->build_merge_filename($order, $customName);
|
|
$snapshot = array(
|
|
'name' => $fileName,
|
|
'T_OrderHeaderID' => (int) $order['T_OrderHeaderID'],
|
|
'T_OrderHeaderLabNumber' => $order['T_OrderHeaderLabNumber'],
|
|
'createdAt' => date('Y-m-d H:i:s'),
|
|
'sources' => $sources
|
|
);
|
|
|
|
return array(
|
|
'status' => 'OK',
|
|
'data' => array(
|
|
'snapshot' => $snapshot,
|
|
'summary' => $summary['data']
|
|
)
|
|
);
|
|
}
|
|
|
|
public function get_merge_summary_by_lab_number($labNumber)
|
|
{
|
|
$order = $this->resolve_order_by_lab_number($labNumber);
|
|
if (!$order) {
|
|
return $this->error('ORDER_NOT_FOUND', 'Nomor lab tidak ditemukan.');
|
|
}
|
|
|
|
return $this->get_merge_summary_by_order_id($order['T_OrderHeaderID']);
|
|
}
|
|
|
|
public function get_merge_summary_by_order_id($orderHeaderId)
|
|
{
|
|
$sql = "SELECT
|
|
T_OrderHeaderID,
|
|
T_OrderDetailID,
|
|
Group_ResultID,
|
|
Nat_GroupName,
|
|
Group_ResultName,
|
|
T_OrderDetailT_TestName,
|
|
T_OrderDetailT_TestIsResult,
|
|
So_ResultEntryID,
|
|
IF(T_OrderPromiseDateTime > NOW(), 'N', 'Y') AS statuspromise,
|
|
DATE_FORMAT(T_OrderPromiseDateTime,'%d-%m-%Y %H:%i') as promise_date
|
|
FROM t_orderheader
|
|
JOIN t_orderdetail ON T_OrderHeaderID = T_OrderDetailT_OrderHeaderID
|
|
AND T_OrderDetailIsActive = 'Y'
|
|
AND T_OrderHeaderID = ?
|
|
AND T_OrderHeaderIsActive = 'Y'
|
|
AND T_OrderDetailT_TestIsResult = 'Y'
|
|
JOIN group_resultdetail ON T_OrderDetailT_TestID = Group_ResultDetailT_TestID
|
|
AND Group_ResultDetailIsActive = 'Y'
|
|
JOIN group_result ON Group_ResultDetailGroup_ResultID = Group_ResultID
|
|
AND Group_ResultIsActive = 'Y'
|
|
JOIN t_orderpromise ON T_OrderHeaderID = T_OrderPromiseT_OrderHeaderID
|
|
AND T_OrderPromiseIsActive = 'Y'
|
|
AND T_OrderDetailT_OrderPromiseID = T_OrderPromiseID
|
|
JOIN t_test ON T_OrderDetailT_TestID = T_TestID
|
|
AND T_TestIsActive = 'Y'
|
|
JOIN nat_group ON T_TestNat_GroupID = Nat_GroupID
|
|
AND Nat_GroupIsActive = 'Y'
|
|
JOIN t_orderdelivery ON T_OrderDeliveryT_OrderHeaderID = T_OrderHeaderID
|
|
AND T_OrderDeliveryM_DeliveryTypeID = 3
|
|
AND T_OrderDeliveryIsActive = 'Y'
|
|
LEFT JOIN so_resultentry ON T_OrderHeaderID = So_ResultEntryT_OrderHeaderID
|
|
AND T_OrderDetailID = So_ResultEntryT_OrderDetailID
|
|
AND So_ResultEntryIsActive = 'Y'
|
|
ORDER BY Nat_GroupID, promise_date";
|
|
|
|
$query = $this->db_onedev->query($sql, array($orderHeaderId));
|
|
if (!$query) {
|
|
return $this->error('MERGE_SUMMARY_FAILED', 'Gagal membaca komposisi merge order.');
|
|
}
|
|
|
|
$rows = $query->result_array();
|
|
if (count($rows) === 0) {
|
|
return $this->error('MERGE_SUMMARY_EMPTY', 'Order tidak memiliki komposisi merge.');
|
|
}
|
|
|
|
$grouped = array();
|
|
foreach ($rows as $row) {
|
|
$groupName = $row['Nat_GroupName'];
|
|
if (!isset($grouped[$groupName])) {
|
|
$grouped[$groupName] = array(
|
|
'group' => $groupName,
|
|
'ohid' => (int) $row['T_OrderHeaderID'],
|
|
'statuspromise' => true,
|
|
'promises' => array(),
|
|
'orderdetailid' => array(),
|
|
'resultnames' => array(),
|
|
'details' => array(),
|
|
'group_result_ids' => array()
|
|
);
|
|
}
|
|
|
|
if ($row['statuspromise'] !== 'Y') {
|
|
$grouped[$groupName]['statuspromise'] = false;
|
|
}
|
|
|
|
if (!in_array($row['promise_date'], $grouped[$groupName]['promises'])) {
|
|
$grouped[$groupName]['promises'][] = $row['promise_date'];
|
|
}
|
|
|
|
$grouped[$groupName]['orderdetailid'][] = (int) $row['T_OrderDetailID'];
|
|
|
|
if (!in_array($row['Group_ResultName'], $grouped[$groupName]['resultnames'])) {
|
|
$grouped[$groupName]['resultnames'][] = $row['Group_ResultName'];
|
|
}
|
|
|
|
if (!in_array((int) $row['Group_ResultID'], $grouped[$groupName]['group_result_ids'])) {
|
|
$grouped[$groupName]['group_result_ids'][] = (int) $row['Group_ResultID'];
|
|
}
|
|
|
|
if (!isset($grouped[$groupName]['details'][$row['Group_ResultName']])) {
|
|
$grouped[$groupName]['details'][$row['Group_ResultName']] = array(
|
|
'name' => $row['Group_ResultName'],
|
|
'resultentryid' => array()
|
|
);
|
|
}
|
|
|
|
if (!is_null($row['So_ResultEntryID'])) {
|
|
$grouped[$groupName]['details'][$row['Group_ResultName']]['resultentryid'][] = (int) $row['So_ResultEntryID'];
|
|
}
|
|
}
|
|
|
|
$records = array();
|
|
$countTotalGroup = count($grouped);
|
|
$countDoneGroup = 0;
|
|
foreach ($grouped as $group) {
|
|
if ($group['statuspromise']) {
|
|
$countDoneGroup++;
|
|
}
|
|
|
|
$detailList = array();
|
|
foreach ($group['details'] as $detail) {
|
|
$detailList[] = $detail;
|
|
}
|
|
$group['details'] = $detailList;
|
|
$records[] = $group;
|
|
}
|
|
|
|
$availableMerge = 'Y';
|
|
if ($countTotalGroup === 1) {
|
|
if ($countDoneGroup < 1) {
|
|
$availableMerge = 'N';
|
|
}
|
|
} elseif ($countTotalGroup >= 2) {
|
|
if ($countDoneGroup < 2 || $countDoneGroup < $countTotalGroup) {
|
|
$availableMerge = 'N';
|
|
}
|
|
}
|
|
|
|
return array(
|
|
'status' => 'OK',
|
|
'data' => array(
|
|
'total' => 0,
|
|
'records' => $records,
|
|
'available_merge' => $availableMerge
|
|
)
|
|
);
|
|
}
|
|
|
|
public function stream_merge_request($mergeRequestId, $labNumber = '')
|
|
{
|
|
$mergeRequest = $this->get_merge_request($mergeRequestId);
|
|
if (!$mergeRequest) {
|
|
return $this->error('MERGE_REQUEST_NOT_FOUND', 'Merge request tidak ditemukan.');
|
|
}
|
|
|
|
$payload = json_decode($mergeRequest['mergeRequestPayload'], true);
|
|
if (!is_array($payload)) {
|
|
return $this->error('MERGE_REQUEST_INVALID', 'Payload merge request tidak valid.');
|
|
}
|
|
|
|
$order = $this->get_order_header($mergeRequest['mergeRequestT_OrderHeaderID']);
|
|
if (!$order) {
|
|
return $this->error('ORDER_NOT_FOUND', 'Order untuk merge request tidak ditemukan.');
|
|
}
|
|
|
|
if ($labNumber !== '') {
|
|
$resolvedOrder = $this->resolve_order_by_lab_number($labNumber);
|
|
if (!$resolvedOrder || (int) $resolvedOrder['T_OrderHeaderID'] !== (int) $mergeRequest['mergeRequestT_OrderHeaderID']) {
|
|
return $this->error('MERGE_REQUEST_ORDER_MISMATCH', 'Merge request tidak terkait dengan nomor lab tersebut.');
|
|
}
|
|
}
|
|
|
|
$goPayload = $this->build_go_payload_from_snapshot(
|
|
(int) $mergeRequest['mergeRequestID'],
|
|
(int) $mergeRequest['mergeRequestT_OrderHeaderID'],
|
|
$payload
|
|
);
|
|
|
|
return $this->call_merge_service($goPayload);
|
|
}
|
|
|
|
public function build_go_payload_from_snapshot($mergeRequestId, $orderHeaderId, array $snapshot)
|
|
{
|
|
$urls = array();
|
|
foreach ($snapshot['sources'] as $source) {
|
|
$urls[] = $this->make_absolute_url($source['relativeUrl']);
|
|
}
|
|
|
|
return array(
|
|
'name' => $snapshot['name'],
|
|
'urls' => $urls,
|
|
'mergeRequestID' => (int) $mergeRequestId,
|
|
'T_OrderHeaderID' => (int) $orderHeaderId
|
|
);
|
|
}
|
|
|
|
public function get_current_user_group_id($userId)
|
|
{
|
|
$query = $this->db_onedev->query(
|
|
"SELECT M_UserM_UserGroupID FROM m_user WHERE M_UserID = ? AND M_UserIsActive = 'Y' LIMIT 1",
|
|
array($userId)
|
|
);
|
|
|
|
if (!$query || $query->num_rows() === 0) {
|
|
return 0;
|
|
}
|
|
|
|
return (int) $query->row()->M_UserM_UserGroupID;
|
|
}
|
|
|
|
public function is_admin_group_allowed($userId)
|
|
{
|
|
$config = $this->get_system_config();
|
|
$allowed = array();
|
|
if (!empty($config['S_SystemsMergeReportAdminGroupIDs'])) {
|
|
foreach (explode(',', $config['S_SystemsMergeReportAdminGroupIDs']) as $value) {
|
|
$value = (int) trim($value);
|
|
if ($value > 0) {
|
|
$allowed[] = $value;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (count($allowed) === 0) {
|
|
return array(
|
|
'status' => 'ERR',
|
|
'code' => 'MERGE_ADMIN_GROUP_NOT_CONFIGURED',
|
|
'message' => 'Akses admin merge report belum dikonfigurasi.'
|
|
);
|
|
}
|
|
|
|
$groupId = $this->get_current_user_group_id($userId);
|
|
if (!in_array($groupId, $allowed)) {
|
|
return array(
|
|
'status' => 'ERR',
|
|
'code' => 'MERGE_ADMIN_FORBIDDEN',
|
|
'message' => 'User group tidak diizinkan mengakses tools merge report.'
|
|
);
|
|
}
|
|
|
|
return array(
|
|
'status' => 'OK',
|
|
'data' => array(
|
|
'groupId' => $groupId,
|
|
'allowedGroupIds' => $allowed
|
|
)
|
|
);
|
|
}
|
|
|
|
public function get_system_config()
|
|
{
|
|
static $config = null;
|
|
if ($config !== null) {
|
|
return $config;
|
|
}
|
|
|
|
$query = $this->db_onedev->query(
|
|
"SELECT
|
|
S_SystemsMergeReportGateway,
|
|
S_SystemIPAddressRegional,
|
|
S_SystemsMergeReportServiceBaseUrl,
|
|
S_SystemsMergeReportServiceSecret,
|
|
S_SystemsMergeReportAdminGroupIDs
|
|
FROM conf_systems
|
|
WHERE S_SystemsIsActive = 'Y'
|
|
LIMIT 1"
|
|
);
|
|
|
|
if ($query && $query->num_rows() > 0) {
|
|
$config = $query->row_array();
|
|
} else {
|
|
$config = array();
|
|
}
|
|
|
|
return $config;
|
|
}
|
|
|
|
protected function get_merge_request($mergeRequestId)
|
|
{
|
|
$query = $this->db_onedev->query(
|
|
"SELECT
|
|
mergeRequestID,
|
|
mergeRequestT_OrderHeaderID,
|
|
mergeRequestPayload,
|
|
mergeRequestCreatedUserID,
|
|
mergeRequestCreated
|
|
FROM merge_request
|
|
WHERE mergeRequestID = ?
|
|
LIMIT 1",
|
|
array($mergeRequestId)
|
|
);
|
|
|
|
if (!$query || $query->num_rows() === 0) {
|
|
return null;
|
|
}
|
|
|
|
return $query->row_array();
|
|
}
|
|
|
|
protected function get_order_header($orderHeaderId)
|
|
{
|
|
$sql = "SELECT
|
|
T_OrderHeaderID,
|
|
T_OrderHeaderLabNumber,
|
|
T_OrderHeaderLabNumberExt,
|
|
DATE(T_OrderHeaderDate) AS order_date,
|
|
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(CONCAT(IFNULL(M_TitleName,''),' ',M_PatientName), ' ', '-'), '.', '_'), '(', ''), ')', ''), '\\'', '') AS patient_name
|
|
FROM t_orderheader
|
|
JOIN m_patient ON T_OrderHeaderM_PatientID = M_PatientID
|
|
LEFT JOIN m_title ON M_PatientM_TitleID = M_TitleID
|
|
WHERE T_OrderHeaderID = ?
|
|
AND T_OrderHeaderIsActive = 'Y'
|
|
LIMIT 1";
|
|
$query = $this->db_onedev->query($sql, array($orderHeaderId));
|
|
if (!$query || $query->num_rows() === 0) {
|
|
return null;
|
|
}
|
|
|
|
return $query->row_array();
|
|
}
|
|
|
|
protected function resolve_order_by_lab_number($labNumber)
|
|
{
|
|
$query = $this->db_onedev->query(
|
|
"SELECT T_OrderHeaderID, T_OrderHeaderLabNumber
|
|
FROM t_orderheader
|
|
WHERE T_OrderHeaderLabNumber = ?
|
|
AND T_OrderHeaderIsActive = 'Y'
|
|
ORDER BY T_OrderHeaderID DESC
|
|
LIMIT 1",
|
|
array($labNumber)
|
|
);
|
|
|
|
if (!$query || $query->num_rows() === 0) {
|
|
return null;
|
|
}
|
|
|
|
return $query->row_array();
|
|
}
|
|
|
|
protected function get_group_sources(array $order, $groupResultId)
|
|
{
|
|
$query = $this->db_onedev->query(
|
|
"SELECT DISTINCT
|
|
Group_ResultID,
|
|
Group_ResultName,
|
|
Group_ResultFlagNonLab,
|
|
IFNULL(T_EmailNonLabUrl,'-') AS EmailNonLabUrl,
|
|
IF(T_EmailNonLabUrl IS NULL AND Group_ResultFlagNonLab = 'Y',' [Belum Pilih Format Hasil]','') AS temail
|
|
FROM t_orderdetail
|
|
JOIN group_resultdetail
|
|
ON Group_ResultDetailT_TestID = T_OrderDetailT_TestID
|
|
AND T_OrderDetailIsActive = 'Y'
|
|
AND Group_ResultDetailIsActive = 'Y'
|
|
AND T_OrderDetailT_OrderHeaderID = ?
|
|
JOIN group_result
|
|
ON Group_ResultDetailGroup_ResultID = Group_ResultID
|
|
AND Group_ResultIsActive = 'Y'
|
|
AND Group_ResultID = ?
|
|
LEFT JOIN t_email_nonlab
|
|
ON T_EmailNonLabT_OrderHeaderID = T_OrderDetailT_OrderHeaderID
|
|
AND T_EmailNonLabType LIKE CONCAT('%', REPLACE(Group_ResultName, 'Elektromedik', 'electromedis'), '%')",
|
|
array($order['T_OrderHeaderID'], $groupResultId)
|
|
);
|
|
|
|
if (!$query) {
|
|
return $this->error('MERGE_SOURCE_QUERY_FAILED', 'Gagal menyusun sumber report.');
|
|
}
|
|
|
|
$rows = $query->result_array();
|
|
$result = array();
|
|
$ts = '&ts=' . time();
|
|
|
|
foreach ($rows as $row) {
|
|
$relativeUrl = '';
|
|
$emailNonLabUrl = str_replace(' ', '', $row['EmailNonLabUrl']);
|
|
if (strpos($emailNonLabUrl, 'fisik') !== false) {
|
|
continue;
|
|
}
|
|
|
|
switch ((int) $row['Group_ResultID']) {
|
|
case 1:
|
|
$relativeUrl = '/birt/frameset?__report=report/onelab/lab/rpt_test_email.rptdesign&__format=pdf&username=admin&PID=' . $order['T_OrderHeaderID'] . $ts;
|
|
break;
|
|
case 2:
|
|
$relativeUrl = '/birt/frameset?__report=report/onelab/lab/rpt_hasil_papsmear_email.rptdesign&__format=pdf&username=admin&PID=' . $order['T_OrderHeaderID'] . $ts;
|
|
break;
|
|
case 3:
|
|
$relativeUrl = '/birt/frameset?__report=report/onelab/lab/rpt_hasil_fna_email.rptdesign&__format=pdf&username=admin&PID=' . $order['T_OrderHeaderID'] . $ts;
|
|
break;
|
|
case 12:
|
|
$relativeUrl = '/birt/frameset?__report=report/onelab/lab/rpt_hasil_lcprep_email.rptdesign&__format=pdf&username=admin&PID=' . $order['T_OrderHeaderID'] . $ts;
|
|
break;
|
|
case 13:
|
|
$relativeUrl = '/birt/frameset?__report=report/onelab/lab/rpt_test_mikro_email.rptdesign&__format=pdf&username=admin&PID=' . $order['T_OrderHeaderID'] . $ts;
|
|
break;
|
|
case 14:
|
|
$relativeUrl = '/birt/frameset?__report=report/onelab/lab/rpt_hasil_cytologi_email.rptdesign&__format=pdf&username=admin&PID=' . $order['T_OrderHeaderID'] . $ts;
|
|
break;
|
|
default:
|
|
$relativeUrl = $emailNonLabUrl;
|
|
break;
|
|
}
|
|
|
|
if ($relativeUrl === '-' || $relativeUrl === '') {
|
|
continue;
|
|
}
|
|
|
|
$result[] = array(
|
|
'groupResultID' => (int) $row['Group_ResultID'],
|
|
'name' => $row['Group_ResultName'],
|
|
'relativeUrl' => $relativeUrl,
|
|
'absoluteUrl' => $this->make_absolute_url($relativeUrl)
|
|
);
|
|
}
|
|
|
|
return array(
|
|
'status' => 'OK',
|
|
'data' => $result
|
|
);
|
|
}
|
|
|
|
public function stream_from_qr_printout($orderHeaderId)
|
|
{
|
|
$query = $this->db_onedev->query(
|
|
"SELECT QR_PrintOutReportURLElectronic
|
|
FROM qr_printout
|
|
WHERE QR_PrintOutT_OrderHeaderID = ?
|
|
AND QR_PrintOutReportURLElectronic != ''
|
|
AND QR_PrintOutIsActive = 1
|
|
ORDER BY QR_PrintOutGroup_ResultID ASC",
|
|
array((int) $orderHeaderId)
|
|
);
|
|
|
|
if (!$query || $query->num_rows() === 0) {
|
|
return $this->error('QR_PRINTOUT_NOT_FOUND', 'Tidak ada URL report di qr_printout untuk order ini.');
|
|
}
|
|
|
|
$urls = array();
|
|
$seen = array();
|
|
foreach ($query->result_array() as $row) {
|
|
$url = trim($row['QR_PrintOutReportURLElectronic']);
|
|
if ($url === '' || isset($seen[$url])) {
|
|
continue;
|
|
}
|
|
$seen[$url] = true;
|
|
$url = str_replace('http://localhost/', 'http://127.0.0.1/', $url);
|
|
$urls[] = $url;
|
|
}
|
|
|
|
if (count($urls) === 0) {
|
|
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,
|
|
'mergeRequestID' => (int) $orderHeaderId,
|
|
'T_OrderHeaderID' => (int) $orderHeaderId,
|
|
);
|
|
|
|
$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)
|
|
{
|
|
$config = $this->get_system_config();
|
|
$baseUrl = isset($config['S_SystemsMergeReportServiceBaseUrl']) ? trim($config['S_SystemsMergeReportServiceBaseUrl']) : '';
|
|
$secret = isset($config['S_SystemsMergeReportServiceSecret']) ? trim($config['S_SystemsMergeReportServiceSecret']) : '';
|
|
|
|
if ($baseUrl === '' || $secret === '') {
|
|
return $this->error('MERGE_SERVICE_NOT_CONFIGURED', 'Konfigurasi merge report service belum lengkap.');
|
|
}
|
|
|
|
$url = rtrim($baseUrl, '/') . '/merge';
|
|
$jsonPayload = json_encode($payload, JSON_UNESCAPED_SLASHES);
|
|
$lastError = array(
|
|
'status' => 'ERR',
|
|
'code' => 'MERGE_SERVICE_FAILED',
|
|
'message' => 'Layanan merge internal gagal memproses permintaan.'
|
|
);
|
|
|
|
for ($attempt = 1; $attempt <= 3; $attempt++) {
|
|
$ch = curl_init($url);
|
|
curl_setopt_array($ch, array(
|
|
CURLOPT_POST => true,
|
|
CURLOPT_POSTFIELDS => $jsonPayload,
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_HEADER => true,
|
|
CURLOPT_HTTPHEADER => array(
|
|
'Content-Type: application/json',
|
|
'X-Internal-Secret: ' . $secret
|
|
),
|
|
CURLOPT_TIMEOUT => 30,
|
|
CURLOPT_CONNECTTIMEOUT => 30
|
|
));
|
|
|
|
$response = curl_exec($ch);
|
|
$curlError = curl_error($ch);
|
|
$httpCode = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
$headerSize = (int) curl_getinfo($ch, CURLINFO_HEADER_SIZE);
|
|
$contentType = (string) curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
|
|
curl_close($ch);
|
|
|
|
if ($response === false || $curlError !== '') {
|
|
$lastError = $this->error('MERGE_SERVICE_TIMEOUT', 'Layanan merge internal melebihi batas waktu.');
|
|
continue;
|
|
}
|
|
|
|
$headers = substr($response, 0, $headerSize);
|
|
$body = substr($response, $headerSize);
|
|
|
|
if ($httpCode >= 200 && $httpCode < 300 && stripos($contentType, 'application/pdf') !== false) {
|
|
return array(
|
|
'status' => 'OK',
|
|
'data' => array(
|
|
'headers' => $headers,
|
|
'contentType' => $contentType,
|
|
'body' => $body,
|
|
'payload' => $payload
|
|
)
|
|
);
|
|
}
|
|
|
|
$lastError = $this->map_service_error($httpCode);
|
|
}
|
|
|
|
return $lastError;
|
|
}
|
|
|
|
protected function map_service_error($httpCode)
|
|
{
|
|
if ($httpCode === 400 || $httpCode === 422) {
|
|
return $this->error('MERGE_SERVICE_REJECTED', 'Komposisi merge report tidak valid.');
|
|
}
|
|
|
|
if ($httpCode === 401 || $httpCode === 403) {
|
|
return $this->error('MERGE_SERVICE_UNAUTHORIZED', 'Layanan merge internal menolak permintaan.');
|
|
}
|
|
|
|
if ($httpCode === 404) {
|
|
return $this->error('MERGE_SOURCE_NOT_FOUND', 'Salah satu sumber report tidak ditemukan.');
|
|
}
|
|
|
|
if ($httpCode === 408 || $httpCode === 504) {
|
|
return $this->error('MERGE_SERVICE_TIMEOUT', 'Layanan merge internal melebihi batas waktu.');
|
|
}
|
|
|
|
return $this->error('MERGE_SERVICE_FAILED', 'Layanan merge internal gagal memproses permintaan.');
|
|
}
|
|
|
|
protected function build_preview_url($mergeRequestId)
|
|
{
|
|
return rtrim($this->get_public_base_url(), '/') . '/report/' . (int) $mergeRequestId;
|
|
}
|
|
|
|
protected function make_absolute_url($url)
|
|
{
|
|
if ($url === '') {
|
|
return '';
|
|
}
|
|
|
|
if (preg_match('/^https?:\/\//i', $url)) {
|
|
return $url;
|
|
}
|
|
|
|
return rtrim($this->get_public_base_url(), '/') . '/' . ltrim($url, '/');
|
|
}
|
|
|
|
protected function get_public_base_url()
|
|
{
|
|
$config = $this->get_system_config();
|
|
if (!empty($config['S_SystemsMergeReportGateway'])) {
|
|
return rtrim($config['S_SystemsMergeReportGateway'], '/');
|
|
}
|
|
|
|
$https = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
|
|
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
|
|
$script = isset($_SERVER['SCRIPT_NAME']) ? dirname($_SERVER['SCRIPT_NAME']) : '';
|
|
$script = trim(str_replace('\\', '/', $script), '/');
|
|
if ($script === '' || $script === '.') {
|
|
return $https . '://' . $host;
|
|
}
|
|
|
|
return $https . '://' . $host . '/' . $script;
|
|
}
|
|
|
|
protected function build_merge_filename(array $order, $customName)
|
|
{
|
|
$name = trim($customName);
|
|
if ($name === '') {
|
|
$name = $order['T_OrderHeaderLabNumber'] . '-' . $order['patient_name'] . '-merge-report.pdf';
|
|
}
|
|
|
|
if (strtolower(substr($name, -4)) !== '.pdf') {
|
|
$name .= '.pdf';
|
|
}
|
|
|
|
return preg_replace('/[^A-Za-z0-9._-]/', '-', $name);
|
|
}
|
|
|
|
protected function error($code, $message)
|
|
{
|
|
return array(
|
|
'status' => 'ERR',
|
|
'code' => $code,
|
|
'message' => $message
|
|
);
|
|
}
|
|
}
|