2025-03-10 14:15:43 +08:00

530 lines
19 KiB
PHP

<?php
namespace App\Controllers;
use CodeIgniter\RESTful\ResourceController;
use CodeIgniter\I18n\Time;
class API_TM extends ResourceController {
public function __construct() {
$this->url_resultSBY = 'http://10.10.4.123:8001/api/webhook/lis?tenant=PadmaSurabaya';
$this->url_resultDPS = 'http://10.10.4.123:8001/api/webhook/lis?tenant=PadmaBali';
$this->url_masterSBY = "http://10.10.4.123:8001/api/webhook/lis-new-master?tenant=PadmaSurabaya";
$this->url_masterDPS = "http://10.10.4.123:8001/api/webhook/lis-new-master?tenant=PadmaBali";
}
public function sendHL7Message($host, $port, $message, $timeout = 5) {
try {
// Create a TCP/IP socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
throw new Exception("socket_create() failed: " . socket_strerror(socket_last_error()));
}
// Set socket options (timeout)
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec" => $timeout, "usec" => 0));
socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array("sec" => $timeout, "usec" => 0));
// Connect to the remote host
$result = socket_connect($socket, $host, $port);
if ($result === false) {
throw new Exception("socket_connect() failed: " . socket_strerror(socket_last_error($socket)));
}
// Add MLLP framing (Minimal Lower Layer Protocol)
$mllpMessage = chr(0x0B) . $message . chr(0x1C) . chr(0x0D);
// Send the message
$bytesSent = socket_write($socket, $mllpMessage, strlen($mllpMessage));
if ($bytesSent === false) {
throw new Exception("socket_write() failed: " . socket_strerror(socket_last_error($socket)));
}
if($bytesSent != strlen($mllpMessage)){
throw new Exception("socket_write() only sent $bytesSent bytes out of ". strlen($mllpMessage));
}
// Read the acknowledgement (optional but recommended)
$ack = socket_read($socket, 8192); // Adjust buffer size as needed
if ($ack === false) {
// Handle cases where no ACK is received within the timeout
throw new Exception("socket_read() failed or timed out: " . socket_strerror(socket_last_error($socket)));
}
//Close the socket
socket_close($socket);
//Basic ACK check. More robust parsing is recommended.
if (strpos($ack, "MSA") !== false) {
return true; // Success (basic ACK check)
} else {
error_log("Unexpected ACK: " . $ack); // Log the unexpected ACK
return false; // Failure (unexpected ACK)
}
} catch (Exception $e) {
error_log("HL7 Sending Error: " . $e->getMessage()); // Log the error
if(isset($socket)){
socket_close($socket); // Ensure socket closure on error
}
return false; // Indicate failure
}
}
public function requests() {
$db = \Config\Database::connect();
$raw = $this->request->getVar();
// log to cm_tm_logs
$data = str_replace("'","''",json_encode($raw));
$sql = "INSERT INTO cmod.dbo.CM_TM_LOGS (URL, METHOD, BODY, LOGDATE) VALUES ('API/REQUESTS', 'POST', '$data', GETDATE())";
$db->query($sql);
$data = array();
$qdata = (array)$raw;
$qpat = (array)$qdata['patient'];
//patdata
$rm = $qpat['rm_number'];
$firstname = str_replace("'","''",$qpat['patient_first_name']);
$lastname = str_replace("'","''",$qpat['patient_last_name']);
$dob = $qpat['patient_dob'];
$dob = str_replace("-","",$dob);
$sex = $qpat['patient_sex'];
$phone = $qpat['patient_phone'];
$sql = "select PATID from cmod.dbo.CM_TM_PATIENTS where PATNUMBER='$rm'";
$query = $db->query($sql);
$results = $query->getResultArray();
if(!isset($results[0])) {
$sql = "INSERT INTO cmod.dbo.CM_TM_PATIENTS (PATNUMBER, FIRSTNAME, LASTNAME, BIRTHDATE, SEX, PHONE ) VALUES ('$rm', '$firstname', '$lastname', '$dob', '$sex', '$phone' )";
$db->query($sql);
$patid = $db->insertID();
} else {
$patid = $results[0]['PATID'];
$sql = "UPDATE cmod.dbo.CM_TM_PATIENTS SET FIRSTNAME='$firstname', LASTNAME='$lastname', BIRTHDATE='$dob', SEX='$sex', PHONE='$phone' where PATID='$patid'";
$db->query($sql);
}
//reqdata
$reffid = $qdata['reference_id'];
$company = $qdata['company_name'];
$loc = $qdata['branch'];
$status = $qdata['status'];
$visitnum = $qpat['visit_number'];
$visitdesc = $qpat['visit_description'];
$visittype = $qpat['visit_type'];
$visitdt = $qpat['visit_date_time'];
$agentname = str_replace("'","''",$qpat['agent_name']);
$doc = str_replace("'","''",$qpat['treating_doctor']);
$createdt = $qdata['created'];
$qant = (array)$qpat['anthropometry'];
$bw = $qant['weight'];
$bh = $qant['height'];
/*
$time = Time::createFromFormat('Y-m-d\TH:i:s.u\Z', $utcdt, 'UTC'); //2024-10-19T00:47:06.424654Z
$time = $time->setTimezone('Asia/Shanghai');
$orderdt = $time->toDateTimeString();
*/
$sql = "select REQID from cmod.dbo.CM_TM_REQUESTS where REFFID='$reffid'";
$query = $db->query($sql);
$results = $query->getResultArray();
if(!isset($results[0])) {
$sql = "INSERT INTO cmod.dbo.CM_TM_REQUESTS (REFFID, REQNUMBER, REQDATE, AGENT, DOC, LOC, PATID, COMPANY, LOGDATE, BW, BH, VISITDESC, VISITTYPE)
VALUES ('$reffid', '$visitnum', '$visitdt', '$agentname', '$doc', '$loc', '$patid', '$company', '$createdt', '$bw', '$bh', '$visitdesc', '$visittype' )";
$db->query($sql);
$reqid = $db->insertID();
} else {
$reqid = $results[0]['REQID'];
$sql = "UPDATE cmod.dbo.CM_TM_REQUESTS SET REQNUMBER='$visitnum', REQDATE='$visitdt', AGENT='$agentname', DOC='$doc', LOC='$loc', PATID='$patid',
COMPANY='$company',LOGDATE='$createdt', BW='$bw', BH='$bh', VISITDESC='$visitdesc', VISITTYPE='$visittype'
where REQID='$reqid'";
$db->query($sql);
}
// tests
$tests = json_decode(json_encode($qpat['tests']), true);;
$string = '';
if($status=='order') { $teststatus = 0;}
else { $teststatus = 1; }
foreach($tests as $test) {
$testcode = $test['service_id'];
$testreffid = $test['test_ref_id'];
$string .= "( '$testreffid', '$reqid', '$testcode', '$teststatus' ),";
}
$string = rtrim($string, ',');
//$sql = "INSERT INTO cmod.dbo.CM_TM_TESTS(REFFID, REQID, HISCODE) VALUES $string";
$sql = "INSERT INTO cmod.dbo.CM_TM_TESTS (REFFTESTID, REQID, HISCODE, TESTSTATUS)
SELECT S.REFFTESTID, S.REQID, S.HISCODE, S.TESTSTATUS FROM ( VALUES $string ) AS S (REFFTESTID, REQID, HISCODE, TESTSTATUS)
WHERE NOT EXISTS ( SELECT 1 FROM cmod.dbo.CM_TM_TESTS T WHERE T.REQID = S.REQID AND T.HISCODE = S.HISCODE );";
$db->query($sql);
$sql = "UPDATE cmod.dbo.CM_TM_TESTS SET TESTSTATUS = S.TESTSTATUS
FROM cmod.dbo.CM_TM_TESTS T
INNER JOIN ( VALUES $string ) AS S (REFFTESTID, REQID, HISCODE, TESTSTATUS)
ON T.REQID = S.REQID AND T.HISCODE = S.HISCODE;";
$db->query($sql);
//sendORM
$this->orm($reqid);
return $this->respond(201);
/*
if( $db->query($sql) ) {
return $this->respond(201);
} else {
$response = [
'errors' => $db->errors(), 'message' => 'Invalid Messages'
];
return $this->fail($response , 409);
}
*/
}
public function orm($reqid) {
$db = \Config\Database::connect();
$sql = "select r.REFFID, r.LOC, p.PATNUMBER, p.FIRSTNAME, p.LASTNAME, p.BIRTHDATE, p.SEX, p.PHONE,
r.REQNUMBER, r.REQDATE, r.AGENT, r.DOC, r.BW, r.BH
from cmod.dbo.CM_TM_REQUESTS r
left join cmod.dbo.CM_TM_PATIENTS p on p.PATID=r.PATID
where r.REQID='$reqid'";
$query = $db->query($sql);
$results = $query->getResultArray();
$res = $results[0];
$reffid = $res['REFFID'];
$patnumber = $res['PATNUMBER'];
$loc = $res['LOC'];
$doc = $res['DOC'];
$firstname = $res['FIRSTNAME'];
$lastname = $res['LASTNAME'];
$dob = $res['BIRTHDATE'];
$sex = substr($res['SEX'],0,1);
$hosp = $res['REQNUMBER'];
$reqdate = $res['REQDATE'];
$time = Time::createFromFormat('Y-m-d\TH:i:s.u\Z', $reqdate, 'UTC'); //2024-10-19T00:47:06.424654Z
$agent = $res['AGENT'];
$bw = $res['BW'];
$bh = $res['BH'];
$phone = $res['PHONE'];
// LOC
if($loc == "PBMC Bali") {
$loc = "PADMA"; $doc = "PBDPS";
$time = $time->setTimezone('Asia/Shanghai');
$reqdate= date_format($time, 'YmdHi');
$port = "8101";
} else {
$loc = "PBSBY"; $doc = "PBSBY";
$time = $time->setTimezone('Asia/Jakarta');
$reqdate= date_format($time, 'YmdHi');
$port = "8201";
}
$orm = "MSH|^~\&|PBMC|TM|TDNL||||ORM^O01^|||2.3||||\r";
$orm .= "PID|1||$patnumber^^^^PATNUMBER||$lastname^$firstname^^^^^L||$dob|$sex||^|^^||$phone^^TELEPHON||||^||||||||||||||||\r";
//$orm .= "PV1|||$loc^^^||||$doc|$doc|||||||||||$hosp|||||||||||||||||||||||||$reqdate||||||||||\r";
$orm .= "PV1|||$loc^^^||||$doc|$doc||||||||||||||||||||||||||||||||||||$reqdate||||||||||\r";
$sql = "select t.TESTSTATUS, m.LISCODE from cmod.dbo.CM_TM_TESTS t
left join cmod.dbo.CM_DICT_MAPPINGS m on m.HISCODE=t.HISCODE
where t.REQID='$reqid'";
$query = $db->query($sql);
$results = $query->getResultArray();
$i = 1;
foreach($results as $qdata) {
$liscode = $qdata['LISCODE'];
$status = $qdata['TESTSTATUS'];
if($liscode != '') {
if($status!=1 || $status !=2) {$status="NW";} else {$status="CA";}
//if($status!='CANCEL') {$status="NW";} else {$status="CA";}
$orm .= "ORC|$status|$reffid||$reffid|||^^^$reqdate|||||$doc|$loc||$reqdate|||||||||\r";
if($i==1) { $orm .= "NTE|1||$hosp|\r"; }
$orm .= "OBR|$i|||$liscode|||||||R|||||$doc|||||||||||||||||||||||||\r";
$i++;
if($liscode=="EGFR") {
$orm .= "OBX||NM|BW||$bw|\r";
}
}
}
//echo "$orm";
//sendHL7Message($host, $port, $message, $timeout = 5);
$this->sendHL7Message( "localhost", $port, $orm, $timeout = 5);
//$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
}
public function create_result_json($accessnumber) {
$db = \Config\Database::connect();
$sql = "select r.HOSTORDERNUMBER, r.SP_HOSPNUMBER, cr.REQNUMBER, cr.LOC, cr.COMPANY, cr.AGENT, cr.VISITDESC, cr.VISITTYPE,
p.PATNUMBER, p.NAME, p.FIRSTNAME, p.BIRTHDATE, p.SEX, p.TELEPHON, r.COLLECTIONDATE, cr.AGENT, cr.DOC, cr.BW, cr.BH
from SP_REQUESTS r
left join cmod.dbo.CM_TM_REQUESTS cr on cr.REFFID=r.HOSTORDERNUMBER
left join PATIENTS p on p.PATID=r.PATID
where r.SP_ACCESSNUMBER='$accessnumber'";
$query = $db->query($sql);
$results = $query->getResultArray();
$visitnumber = $results[0]['REQNUMBER'];
$reffid = $results[0]['HOSTORDERNUMBER'];
$location = $results[0]['LOC'];
$payer_name = $results[0]['AGENT'];
$company = $results[0]['COMPANY'];
$createdt = gmdate('Y-m-d\TH:i:s.v\Z');
$patnumber = substr($results[0]['PATNUMBER'],-9);
$firstname = $results[0]['NAME'];
$lastname = $results[0]['FIRSTNAME'];
$dob = $results[0]['BIRTHDATE'];
$sex = $results[0]['SEX'];
$phone = $results[0]['TELEPHON'];
$visitdesc = $results[0]['VISITDESC'];
$visittype = $results[0]['VISITTYPE'];
$visitdt = $results[0]['COLLECTIONDATE'];
$agent = $results[0]['AGENT'];
if($agent != '') {$bagent = true;}
else {$bagent=false;}
$doctor = $results[0]['DOC'];
$bw = $results[0]['BW'];
$bh = $results[0]['BH'];
$json = [
"reference_id" => "$reffid",
"created" => "$createdt",
"company_name" => $company,
"branch" => $location,
"visit_number" => $visitnumber,
"patient" => [
"rm_number" => $patnumber,
"patient_first_name" => $firstname,
"patient_last_name" => $lastname,
"patient_dob" => $dob,
"patient_sex" => $sex,
"patient_phone" => $phone,
"visit_number" => $visitnumber,
"visit_description"=> $visitdesc,
"visit_date_time" => $visitdt,
"agent_name" => $agent,
"agent" => $bagent,
"treating_doctor" => $doctor,
"visit_type" => $visittype,
"anthropometry" => [
"weight" => $bw,
"height" => $bh,
],
],
"test_results" => [],
"collects" => [],
"receives" => []
];
$sql = "select dc.CHAPID, t.DEPTH as depth_test, dc.FULLTEXT as chap_eng, dc.FULLTEXT as chap_ind, st.FULLTEXT as serum_type,
cdt.TEXT1 as test_eng, cdt.TEXT2 as test_ind, cdt.UNIT as UNITTEXT, cdt.REFFTEXT, t.NOTPRINTABLE, cr.RESSTATUS,
t.TESTORDER, t.RESTYPE as code_type, t.VALIDATIONINITIALS as validator, dt.SHORTTEXT,
RESULT = case when t.RESVALUE is null then tx.FULLTEXT else t.RESVALUE end, ct.REFFTESTID, m.HISCODE, m.LISCODE,
tub.TUBENAME, cr.REFRANGE, dt.TESTCODE, t.TESTORDER, dt.UNITS, cr.RESDATE, cr.USERVAL
from REQUESTS r
left join TESTS t on t.REQUESTID = r.REQUESTID
left join DICT_TESTS dt on dt.ENDVALIDDATE is null and t.TESTID=dt.TESTID
left join DICT_TEXTS tx on tx.TEXTID=t.CODEDRESULTID
left join DICT_CHAPTERS dc on dc.CHAPID=dt.CHAPID and dc.ENDVALIDDATE is null
left join DICT_TEST_SAMPLES ts on ts.TESTID=t.TESTID and dt.TESTID=ts.TESTID
left join DICT_SAMPLES_TYPES st on st.SAMPTYPEID=ts.SAMPTYPEID
left join cmod.dbo.CM_DICT_TESTS cdt on dt.TESTCODE=cdt.TESTCODE
left join cmod.dbo.CM_RESULTS cr on cr.ACCESSNUMBER=r.ACCESSNUMBER and cr.TESTCODE=cdt.TESTCODE and cr.TESTCODE=dt.TESTCODE
left join cmod.dbo.CM_DICT_MAPPINGS m on m.LISCODE=cr.TESTCODE
left join cmod.dbo.CM_TM_REQUESTS cq on cq.REFFID=r.EXTERNALORDERNUMBER
left join cmod.dbo.CM_TM_TESTS ct on ct.HISCODE=m.HISCODE and ct.REQID=cq.REQID
left join cmod.dbo.CM_DICT_TUBES tub on tub.TUBEID=m.TUBEID
where r.ACCESSNUMBER='$accessnumber' and t.NOTPRINTABLE is null ORDER BY t.TESTORDER";
$query = $db->query($sql);
$test_results = $query->getResultArray();
$d0=-1; $d1=-1; $d2=-1; $d3=-1;
foreach ($test_results as $result) {
$refftestid = trim($result['REFFTESTID']);
$testorder = $result['TESTORDER'];
if($refftestid == '') { $refftestid = $accessnumber . str_pad($testorder,3,0, STR_PAD_LEFT); }
$hiscode = $result['HISCODE'];
$tubename = $result['TUBENAME'];
$depth = $result['depth_test'];
$liscode = $result['LISCODE'];
$testcode = $result['TESTCODE'];
$testname = $result['test_eng'];
$sampletype = $result['serum_type'];
$chapter = $result['chap_eng'];
$testresult = $result['RESULT'];
$unit = $result['UNITS'];
$unittext = $result['UNITTEXT'];
$testunit = $unit;
if($unittext != '') { $testunit = $unittext; }
$refrange = $result['REFRANGE'];
$refftext = $result['REFFTEXT'];
$resstatus = $result['RESSTATUS'];
if($resstatus == 'F') { $testsum = 'APPROVE'; }
elseif($resstatus == 'C') { $testsum = 'PENDING'; }
else { $testsum = null; }
if($refftext != '') { $testreff = $refftext; }
else { $testreff = $refrange; }
if($liscode == '') {$liscode = $testcode;}
$resdate = $result['RESDATE'];
if($resdate == "1900-01-01 00:00:00.000") { $resdate =''; }
$userval = $result['USERVAL'];
$username = $result['USERNAME'];
$data = [
"test_ref_id"=> "$refftestid",
"hiscode"=> "$hiscode",
"liscode"=> "$liscode",
"service_name"=> "$testname",
"test_medium"=> "$sampletype",
"test_container"=> "$tubename",
"chapter_type"=> "$chapter",
"test_result"=> "$testresult",
"test_unit"=> "$testunit",
"test_reff" => "$testreff",
"test_summary"=> "$testsum",
"resdate"=> "$resdate",
"userval"=> "$userval",
"username"=> "$username",
];
if ( $depth == 0 || $depth == '' ) { // depth 0
$d0++;
$d1=-1;
$json['test_results'][] = $data;
} else if ($depth == 1) { // depth 1
$d1++;
$d2=-1;
$json['test_results'][$d0]['subtest_results'][] = $data;
} else if ($depth == 2) { // depth 2
$d2++;
$d3=-1;
$json['test_results'][$d0]['subtest_results'][$d1]['subtest_results'][] = $data;
}
}
$sql = "SELECT ds.SHORTTEXT,
FORMAT(tu.COLLECTIONDATE, 'dd-MM-yyyy') AS RECVDATE,
FORMAT(tu.COLLECTIONDATE, 'HH:mm') AS RECVTIME,
FORMAT(ct.COLLECTIONDATE, 'dd-MM-yyyy') AS COLLDATE,
FORMAT(ct.COLLECTIONDATE, 'HH:mm') AS COLLTIME
FROM SP_TUBES tu
LEFT JOIN DICT_SAMPLES_TYPES ds ON ds.SAMPCODE = tu.SAMPLETYPE
LEFT JOIN cmod.dbo.CM_TUBES ct ON ct.SAMPLETYPE = tu.SAMPLETYPE AND ct.ACCESSNUMBER = tu.SP_ACCESSNUMBER
WHERE tu.SP_ACCESSNUMBER = '$accessnumber';";
$query = $db->query($sql);
$samples = $query->getResultArray();
foreach ($samples as $data) {
$sample = $data['SHORTTEXT'];
$recvdate = $data['RECVDATE'];
$recvtime = $data['RECVTIME'];
$colldate = $data['COLLDATE'];
$colltime = $data['COLLTIME'];
$json['collects'][] = [ "sample" => "$sample", "colldate" => "$colldate", "colltime" => "$colltime" ];
$json['receives'][] = [ "sample" => "$sample", "recvdate" => "$recvdate", "recvtime" => "$recvtime" ];
}
return $json;
}
public function sendjson( $method, $url, $message ) {
$client = \Config\Services::curlrequest();
try {
$response = $client->request($method, $url, $message);
if ($response->getStatusCode() == 200) {
print_r($response);
} else {
print_r($response);
}
} catch (\Exception $e) {
//echo "<pre> \n".json_encode($json)."\n";
echo "Error: " . $e->getMessage();
log_message('error', 'API request exception: ' . $e->getMessage());
}
}
public function results_send($accessnumber) {
//$TMBali_bearerToken = file_get_contents('tokens/pbmc_dps.txt');
//$TMSby_bearerToken = file_get_contents('tokens/pbmc_sby.txt');
$json = $this->create_result_json($accessnumber);
$location = $json['branch'];
$headers = [ "Content-Type" => "application/json" ];
if($location == 'PBMC Surabaya') {
//$token = $TMSby_bearerToken;
$url = $this->url_resultSBY;
} else {
//$token = $TMBali_bearerToken;
$url = $this->url_resultDPS;
}
$method = "POST";
$message = [
"headers" => $headers,
"body" => json_encode($json),
"verify" => false
];
echo "<pre>";
//print_r($message);
$this->sendjson($method, $url, $message);
}
public function results_preview($accessnumber) {
$json = $this->create_result_json($accessnumber);
return $this->respond($json);
}
public function oc ($hon, $test) {
$db = \Config\Database::connect();
$sql = "select r.*, p.*, t.* from cmod.dbo.CM_TM_REQUESTS r
left join cmod.dbo.CM_TM_PATIENTS p on r.PATID=p.PATID
left join cmod.dbo.CM_DICT_MAPPINGS m on m.LISCODE='$test'
left join cmod.dbo.CM_TM_TESTS t on t.REQID=r.REQID and t.HISCODE=m.HISCODE
where r.REFFID='$hon' ";
$query = $db->query($sql);
$results = $query->getResultArray();
$visitnumber = $results[0]['REQNUMBER'];
$location = $results[0]['LOC'];
$patnumber = $results[0]['PATNUMBER'];
$firstname = $results[0]['FIRSTNAME'];
$lastname = $results[0]['LASTNAME'];
$hiscode = $results[0]['HISCODE'];
$refftestid = $results[0]['REFFTESTID'];
$method = "POST";
if($location == "PBMC Bali") { $url = $this->url_resultDPS; }
else { $url = $this->url_resultSBY; }
$headers = [ "Content-Type" => "application/json" ];
$json = [
"reference_id" => "$hon",
"company_name" => "Padma Medical Group",
"branch" => "$location",
"status" => "cancel",
"patient" => [
"rm_number" => "$patnumber",
"patient_first_name" => "$firstname",
"patient_last_name" => "$lastname",
"visit_number" => "$visitnumber"
],
"tests" => [
"test_ref_id" => trim($refftestid),
"service_id" => "$hiscode"
]
];
//return $this->respond($json);
$message = [
"headers" => $headers,
"body" => json_encode($json),
"verify" => false
];
$this->sendjson($method, $url, $message);
}
}