Files
2026-04-27 10:26:26 +07:00

1417 lines
43 KiB
PHP

<?php
class Ssresource extends MY_Controller
{
var $base_url, $base_consent_url, $base_oauth_url;
var $is_staging, $organizationID;
var $dbname;
var $tz;
/*
Daftar function
1. ss_analyze_patient di gunakan untuk search ihs number pasien dan insert ke one_health.oh_patient_map
curl http://ngagel/one-api/satu_sehat/ssresource/ss_analyze_patient
2. ss_register_all_location di gunakan untuk me-registerkan location ke satu sehat utk LocationID yang masih blank
curl http://ngagel/one-api/satu_sehat/ssresource/ss_register_all_location
3. ss_location_by_id untuk menampilkan data location by id satu sehat
curl http://ngagel/one-api/satu_sehat/ssresource/ss_location_by_id/<LocationID satu sehat>
4. ss_location_in_org untuk menampilkan seluruh location dalam organisasi
curl http://ngagel/one-api/satu_sehat/ssresource/ss_location_in_org
5. ss_submit_encounter di gunakan untuk submit encounter ke satu sehat pada tanggal yang bersangkutan max 10 record sekali proses
curl http://ngagel/one-api/satu_sehat/ss_submit_encounter/<date>/<start>/<limit>
6. ss_encounter_by_id get encounter by satu sehat encounter id
curl http://ngagel/one-api/satu_sehat/ss_encounter_by_id/<encounter id>
7. ss_encounter_by_subject get encounter by satu sehat patient ihs number
curl http://ngagel/one-api/satu_sehat/ss_encounter_by_subject/<patient ihs number>
8. ss_submit_service_request di gunakan untuk submit service request ke satu sehat pada tanggal order header
curl http://ngagel/one-api/satu_sehat/ss_submit_service_request/<date>/<start>/<limit>
9. ss_service_request_by_od_id di gunakan untuk get service request ke satu sehat by T_OrderDetailID
curl http://ngagel/one-api/satu_sehat/ss_service_request_by_od_id/<T_OrderDetailID>
10. ss_specimen_submit
*/
function __construct()
{
parent::__construct();
$this->tz = "+07:00";
$this->is_staging = true;
$this->db_onedev = $this->load->database("default", true);
$this->base_url = "https://api-satusehat.kemkes.go.id/fhir-r4/v1";
$this->base_oauth_url = "https://api-satusehat.kemkes.go.id/oauth2/v1";
$this->base_consent_url = "https://api-satusehat.dto.kemkes.go.id/consent/v1";
$this->dbname = "one_health";
if ($this->is_staging) {
$this->base_url = "https://api-satusehat-stg.kemkes.go.id/fhir-r4/v1";
$this->base_oauth_url = "https://api-satusehat-stg.kemkes.go.id/oauth2/v1";
$this->base_consent_url = "https://api-satusehat-stg.dto.kemkes.go.id/consent/v1";
$this->dbname = "one_health_dev";
}
$this->get_organization_id();
}
//specimen
function ss_specimen_param(
$specimenID,
$specimen_code,
$specimen_display,
$collectedDate,
$receivedDate,
$patientID,
$arr_serviceRequestID
) {
$collectedDate = substr($collectedDate, 0, 10) . "T" .
substr($collectedDate, 11) . $this->tz;
$receivedDate = substr($receivedDate, 0, 10) . "T" .
substr($receivedDate, 11) . $this->tz;
$param = [
"resourceType" => "Specimen",
"identifier" => [
[
"system" => "http://sys-ids.kemkes.go.id/specimen/{$this->organizationID}",
"value" => "$specimenID",
"assigner" => [
"reference" => "Organization/{$this->organizationID}"
]
]
],
"status" => "available",
"type" => [
"coding" => [
[
"system" => "http://snomed.info/sct",
"code" => "$specimen_code",
"display" => "$specimen_display"
]
]
],
"collection" => [
"collectedDateTime" => "$collectedDate",
"extension" => [
[
"url" => "https://fhir.kemkes.go.id/r4/StructureDefinition/CollectorOrganization",
"valueReference" => [
"reference" => "Organization/{$this->organizationID}"
]
]
]
],
"subject" => [
"reference" => "Patient/$patientID",
],
"receivedTime" => "$receivedDate",
];
$param["request"] = [];
foreach ($arr_serviceRequestID as $svc) {
$param["request"][] =
[
"reference" => "ServiceRequest/$svc"
];
}
return $param;
}
function ss_specimen_submit($date = "", $start = 0, $limit = 1)
{
if ($date == "") $date = date("Y-m-d");
$sdate = $date . " 00:00:01";
$edate = $date . " 23:59:59";
//get service_request_id
$sql = "select
T_OrderDetailID,
T_OrderHeaderID,
OHPatientMapIhsNumber patientID,
ServiceRequestResponID,
T_TestT_SampleTypeID,
OHSpecimenMapTypeCode,
OHSpecimenMapTypeDisplay,
max(T_OrderSampleID) T_OrderSampleID,
max( concat(T_OrderSampleSamplingDate, ' ', T_OrderSampleSamplingTime) )
CollectedDateTime,
max( concat(T_OrderSampleReceiveDate, ' ', T_OrderSampleReceiveTime) )
ReceivedDateTime
from t_orderheader
join {$this->dbname}.encounter on T_OrderHeaderID = EncounterT_OrderHeaderID
and T_OrderHeaderDate >= ?
and T_OrderHeaderDate <= ?
and T_OrderHeaderIsActive = 'Y'
join {$this->dbname}.service_request on
T_OrderHeaderID = ServiceRequestT_OrderHeaderID
join t_orderdetail on T_OrderDetailID = ServiceRequestT_OrderDetailID
join {$this->dbname}.oh_patient_map on
T_OrderHeaderM_PatientID = OHPatientMapM_PatientID
join t_test on T_OrderDetailT_TestID = T_TestID
join t_ordersample on T_OrderHeaderID = T_OrderSampleT_OrderHeaderID
and (
T_OrderSampleT_SampleTypeID = T_TestT_SampleTypeID
or
T_OrderSampleT_SampleTypeID = fn_sampletype_from_local(T_TestNat_TestID)
)
and T_OrderSampleIsActive = 'Y'
left join {$this->dbname}.oh_specimen_map
on T_TestT_SampleTypeID = OhSpecimenMapT_SampleTypeID
left join {$this->dbname}.specimen on
T_OrderHeaderID = SpecimenT_OrderHeaderID
and T_OrderSampleID = SpecimenT_OrderSampleID
where SpecimenID is null
group by T_OrderDetailID
order by T_OrderSampleID
limit $start,$limit";
$qry = $this->db->query($sql, [$sdate, $edate]);
if (!$qry) {
echo "Error get ServiceRequest : " . $this->db->error()["message"];
exit;
}
$rows = $qry->result_array();
echo $this->db->last_query();
print_r($rows);
exit;
if (count($rows) == 0) {
echo "No Pending Encounter.\n";
exit;
}
$arr_specimen = [];
foreach ($rows as $r) {
$orderSampleID = $r["T_OrderSampleID"];
$headerID = $r["T_OrderHeaderID"];
$specimenCode = $r["OHSpecimenMapTypeCode"];
$xid = $headerID . "-" . $specimenCode;
if (!in_array($xid, array_keys($arr_specimen))) {
$arr_specimen[$xid] = [
"sampleID" => $orderSampleID,
"headerID" => $headerID,
"patientID" => $r["patientID"],
"specimenCode" => $r["OHSpecimenMapTypeCode"],
"specimenDisplay" => $r["OHSpecimenMapTypeDisplay"],
"serviceRequestID" => $r["ServiceRequestResponID"],
"specimenDisplay" => $r["OHSpecimenMapTypeDisplay"],
"collectedDateTime" => $r["CollectedDateTime"],
"receivedDateTime" => $r["ReceivedDateTime"]
];
$arr_specimen[$xid]["service"] = [];
}
$arr_specimen[$xid]["service"][] = $r["ServiceRequestResponID"];
}
$sql_i = "insert into {$this->dbname}.specimen(SpecimenResponseID,
SpecimenT_OrderHeaderID, SpecimenT_OrderSampleID,
SpecimenJSON,SpecimenStatus)
values(?,?,?,?,'available')";
foreach ($arr_specimen as $sp) {
$param = $this->ss_specimen_param(
$sp["sampleID"],
$sp["specimenCode"],
$sp["specimenDisplay"],
$sp["collectedDateTime"],
$sp["receivedDateTime"],
$sp["patientID"],
$sp["service"]
);
echo "Processing Specimen {$sp["specimenDisplay"]} : {$sp["specimenCode"]} \n";
$service = "/Specimen";
$o_resp = $this->ss_post($service, $param);
$resp = $this->objToArray($o_resp);
print_r($resp);
if (in_array("id", array_keys($resp))) {
echo "Success : Specimen ID {$resp["id"]} \n";
$id = $resp["id"];
$param["id"] = $id;
$qry = $this->db->query($sql_i, [
$id, $sp["headerID"],
$sp["sampleID"], json_encode($param)
]);
if (!$qry) {
echo "ERR : " . $this->db->error()["message"] . "\n";
echo $this->db->last_query();
exit;
}
echo " [Inserted to specimen]\n";
}
}
}
//service_request
function ss_service_request_submit($date = "", $start = 0, $limit = 1)
{
$tz = $this->tz;
if ($date == "") $date = date("Y-m-d");
$sdate = $date . " 00:00:01";
$edate = $date . " 23:59:59";
//get the encounterID 1st
$sql = "select
EncounterID
from t_orderheader
join {$this->dbname}.encounter on T_OrderHeaderID = EncounterT_OrderHeaderID
and T_OrderHeaderDate >= ?
and T_OrderHeaderDate <= ?
and T_OrderHeaderIsActive = 'Y'
limit $start,$limit";
$qry = $this->db->query($sql, [$sdate, $edate]);
if (!$qry) {
echo "Error get ServiceRequest : " . $this->db->error()["message"];
exit;
}
$rows = $qry->result_array();
if (count($rows) == 0) {
echo "No Pending Encounter.\n";
exit;
}
$ids = [];
foreach ($rows as $r) {
$ids[] = $r["EncounterID"];
}
$s_ids = implode(",", $ids);
$sql = "select
T_OrderHeaderID, T_OrderHeaderLabNumber,
EncounterResponseID,
concat('Kunjungan ', M_PatientName, ' pada tanggal ', date(T_OrderHeaderDate))
EncounterName,
OHDoctorMapIHSNumber,
M_PatientName,
OHPatientMapIhsNumber,
fn_get_doctor_fullname(T_OrderHeaderPjM_DoctorID) M_DoctorName,
ifnull(Nat_TestLoincCode, 'x-x') Nat_TestLoincCode,
ifnull(Nat_TestLoincDisplay,'x-x') Nat_TestLoincDisplay,
Nat_TestCode,
Nat_TestName,
T_OrderDetailID,
T_OrderDetailCreated
from t_orderheader
join {$this->dbname}.encounter on T_OrderHeaderID = EncounterT_OrderHeaderID
and EncounterID in ($s_ids)
join {$this->dbname}.oh_patient_map on
OHPatientMapM_PatientID = T_OrderHeaderM_PatientID
join {$this->dbname}.oh_doctor_map on T_OrderHeaderPjM_DoctorID = OHDoctorMapM_DoctorID
join t_orderdetail on T_OrderHeaderID = T_OrderDetailT_OrderHeaderID
and T_OrderDetailIsActive = 'Y'
and T_OrderDetailT_TestIsPrice = 'Y'
join m_patient on T_OrderHeaderM_PatientID = M_PatientID
join t_test on T_OrderDetailT_TestID = T_TestID
join nat_test on T_TestNat_TestID = Nat_TestID
left join {$this->dbname}.service_request on T_OrderHeaderID = ServiceRequestT_OrderHeaderID
and T_OrderDetailID = ServiceRequestT_OrderDetailID
left join nat_test_loinc on Nat_TestID = Nat_TestLoincNat_TestID
where ServiceRequestID is null
";
$qry = $this->db->query($sql, [$sdate, $edate]);
if (!$qry) {
echo "Error get ServiceRequest : " . $this->db->error()["message"];
exit;
}
$rows = $qry->result_array();
$in_complete_order = [];
foreach ($rows as $r) {
$id = $r["T_OrderDetailID"];
$labNo = $r["T_OrderHeaderLabNumber"];
$loincCode = $r["Nat_TestLoincCode"];
$loincName = $r["Nat_TestLoincDisplay"];
$natTestName = $r["Nat_TestName"];
$patientID = $r["OHPatientMapIhsNumber"];
$patientName = $r["M_PatientName"];
$encounterID = $r["EncounterResponseID"];
$encounterName = $r["EncounterName"];
$occurrenceDate = $r["T_OrderDetailCreated"];
$occurrenceDate = substr($occurrenceDate, 0, 10) . "T" . substr($occurrenceDate, 11) . "$tz";
$authoredOnDate = $occurrenceDate;
$practitionerID = $r["OHDoctorMapIHSNumber"];
$practitionerName = $r["M_DoctorName"];
list($staffID, $staffName) = $this->get_staff_service_request($r["T_OrderHeaderID"]);
if ($staffID == "") {
echo "\t\tStaff belum ter-mapping : $labNo - $staffName\n";
continue;
}
if ($loincCode == "x-x") {
echo "\t\tTest belum ter-mapping : $labNo - $natTestName\n";
continue;
}
$in_complete_order[] = $labNo;
}
$sql_i = "INSERT INTO {$this->dbname}.service_request (`ServiceRequestT_OrderHeaderID`, `ServiceRequestT_OrderDetailID`,
`ServiceRequestJSON`, `ServiceRequestResponID` )
VALUES (?, ?, ?, ?)";
foreach ($rows as $r) {
$oh_id = $r["T_OrderHeaderID"];
$id = $r["T_OrderDetailID"];
$labNo = $r["T_OrderHeaderLabNumber"];
$loincCode = $r["Nat_TestLoincCode"];
$loincName = $r["Nat_TestLoincDisplay"];
$natTestName = $r["Nat_TestName"];
$patientID = $r["OHPatientMapIhsNumber"];
$patientName = $r["M_PatientName"];
$encounterID = $r["EncounterResponseID"];
$encounterName = $r["EncounterName"];
$occurrenceDate = $r["T_OrderDetailCreated"];
$occurrenceDate = substr($occurrenceDate, 0, 10) . "T" . substr($occurrenceDate, 11) . "$tz";
$authoredOnDate = $occurrenceDate;
$practitionerID = $r["OHDoctorMapIHSNumber"];
$practitionerName = $r["M_DoctorName"];
list($staffID, $staffName) = $this->get_staff_service_request($r["T_OrderHeaderID"]);
if ($this->is_staging) {
$practitionerID = "N10000001";
$practitionerName = "Dokter Bronsig";
$staffID = "N10000005";
$staffName = "Fatma";
}
if (!in_array($labNo, $in_complete_order)) {
echo "Processing [$id] $labNo | $natTestName | $loincCode \n";
$svc_param = $this->ss_service_request_param(
$id,
$loincCode,
$loincName,
$natTestName,
$patientID,
$encounterID,
$encounterName,
$occurrenceDate,
$authoredOnDate,
$practitionerID,
$practitionerName,
$staffID,
$staffName
);
$o = $this->ss_service_request_by_od_id($id);
if (isset($o["total"]) && $o["total"] > 0) {
$svc_id = $o["entry"][0]["resource"]["id"];
echo "Service Request ID : $svc_id \n";
$svc_param["id"] = $svc_id;
$qry = $this->db->query($sql_i, [$oh_id, $id, json_encode($svc_param), $svc_id]);
if (!$qry) {
echo "Error insert service_request : " . $this->db->error()["message"];
exit;
}
}
$o_resp = $this->ss_post("/ServiceRequest", $svc_param);
$resp = $this->objToArray($o_resp);
if (isset($resp["id"])) {
$svc_id = $resp["id"];
$svc_param["id"] = $svc_id;
$qry = $this->db->query($sql_i, [$oh_id, $id, json_encode($svc_param), $svc_id]);
if (!$qry) {
echo "Error insert service_request $svc_id : " . $this->db->error()["message"];
exit;
}
}
}
}
}
function ss_service_request_by_od_id($od_id)
{
$service = "/ServiceRequest?identifier=http://sys-ids.kemkes.go.id/servicerequest/{$this->organizationID}|$od_id";
$o_resp = $this->ss_get($service);
$resp = $this->objToArray($o_resp);
return $resp;
}
function ss_service_request_by_encounter($encounterID)
{
$service = "/ServiceRequest?encounter=$encounterID";
$o_resp = $this->ss_get($service);
$resp = $this->objToArray($o_resp);
return $resp;
}
function get_staff_service_request($ohID)
{
$sql = "select
OHStaffMapIhsNumber, M_StaffName
from fo_status
join m_user on
FO_StatusT_OrderHeaderID = ?
and FO_StatusM_StatusID = 1
and FO_StatusM_UserID = M_UserID
join m_staff on M_UserM_StaffID = M_StaffID
left join {$this->dbname}.oh_staff_map on
M_StaffIDNumber = OHStaffMapM_StaffNIK
order by Fo_StatusID desc
limit 0,1
";
$qry = $this->db->query($sql, [$ohID]);
if (!$qry) {
echo "Err : " . $this->db->error()["message"];
exit;
}
$rows = $qry->result_array();
if (count($rows) == 0) {
return [false, ""];
}
return [$rows[0]["OHStaffMapIhsNumber"], $rows[0]["M_StaffName"]];
}
/*
*/
function ss_service_request_param(
$orderDetailID,
$natTestLoinc,
$natTestLoincName,
$natTestName,
$patientID,
$encounterID,
$encounterName,
$occurrenceDate,
$authoredOnDate,
$practitionerID,
$practitionerName,
$staffID,
$staffName,
$reasonCode = ""
) {
$param = [
"resourceType" => "ServiceRequest",
"identifier" => [
[
"system" => "http://sys-ids.kemkes.go.id/servicerequest/{$this->organizationID}",
"value" => "$orderDetailID"
]
],
"status" => "active",
"intent" => "original-order",
"priority" => "routine",
"category" => [
[
"coding" => [
[
"system" => "http://snomed.info/sct",
"code" => "108252007",
"display" => "Laboratory procedure"
]
]
]
],
"code" => [
"coding" => [
[
"system" => "http://loinc.org",
"code" => "$natTestLoinc",
"display" => "$natTestLoincName"
]
],
"text" => "$natTestName"
],
"subject" => [
"reference" => "Patient/$patientID"
],
"encounter" => [
"reference" => "Encounter/{$encounterID}",
"display" => "$encounterName"
],
"occurrenceDateTime" => "$occurrenceDate",
"authoredOn" => "$authoredOnDate",
"requester" => [
"reference" => "Practitioner/$practitionerID",
"display" => "$practitionerName"
],
"performer" => [
[
"reference" => "Practitioner/$staffID",
"display" => "$staffName"
]
],
];
if ($reasonCode != "") {
$param["reasonCode"] = [
[
"text" => "$reasonCode"
]
];
}
return $param;
}
//encounter
function ss_encounter_by_id($id)
{
$service = "/Encounter/$id";
$resp = $this->ss_get($service);
print_r($resp);
}
function ss_encounter_by_subject($ihs)
{
$service = "/Encounter?subject=$ihs";
$resp = $this->ss_get($service);
print_r($resp);
}
function ss_submit_encounter($date = "", $start = 0, $limit = 20)
{
if ($date == "") $date = date("Y-m-d");
$sdate = $date . " 00:00:01";
$edate = $date . " 23:59:59";
list($locationID, $locationName) = $this->get_location_encounter();
$sql = "select T_OrderHeaderID,OHDoctorMapIHSNumber, M_DoctorName,
T_OrderHeaderLabNumberExt, T_OrderHeaderDate,
OHPatientMapIhsNumber, M_PatientName
from t_orderheader
join {$this->dbname}.oh_doctor_map
on T_OrderHeaderPjM_DoctorID = OHDoctorMapM_DoctorID
and T_OrderHeaderDate >= ?
and T_OrderHeaderDate <= ?
join m_doctor on T_OrderHeaderPjM_DoctorID = M_DoctorID
join {$this->dbname}.oh_patient_map
on T_OrderHeaderM_PatientID = OHPatientMapM_PatientID
join m_patient on T_OrderHeaderM_PatientID = M_PatientID
left join {$this->dbname}.encounter
on T_OrderHeaderID = EncounterT_OrderHeaderID
where EncounterID is null
limit $start,$limit
";
$qry = $this->db->query($sql, [$sdate, $edate]);
if (!$qry) {
echo "ERR : " . $this->db->error()["message"];
echo $this->db->last_query();
exit;
}
$rows = $qry->result_array();
$service = "/Encounter";
$sql = "insert into {$this->dbname}.encounter (EncounterJSON,
EncounterT_OrderHeaderID,EncounterResponseID,EncounterStatus)
values(?,?,?,?)";
foreach ($rows as $r) {
$odate = $r["T_OrderHeaderDate"];
$xdate = substr($odate, 0, 10) . "T" . substr($odate, 11) . "+07:00";
$param = $this->ss_encounter_param(
$r["OHPatientMapIhsNumber"],
$r["M_PatientName"],
$r["OHDoctorMapIHSNumber"],
$r["M_DoctorName"],
$locationID,
$locationName,
$this->organizationID,
$r["T_OrderHeaderLabNumberExt"],
$xdate
);
echo "Processing " . $r["T_OrderHeaderLabNumberExt"] . "|" . $r["OHPatientMapIhsNumber"] . "\n";
$jresp = $this->ss_post($service, $param);
$resp = $this->objToArray($jresp);
if (is_array($resp) && isset($resp["id"])) {
print_r($resp);
$encounterResponseID = $resp["id"];
$qry = $this->db->query($sql, [
json_encode($param),
$r["T_OrderHeaderID"], $encounterResponseID, "arrived"
]);
if (!$qry) {
echo "ERR : " . $this->db->error()["message"] . "\n";
echo $this->db->last_query();
exit;
}
} else {
echo "ERR : \n";
print_r($resp);
}
}
}
function get_location_encounter()
{
$sql = "select LocationID, LocationName
from {$this->dbname}.location
where LocationIsActive='Y'
and LocationType = 'ENCOUNTER_LAB'
limit 0,1";
$qry = $this->db->query($sql);
if (!$qry) {
return ["", ""];
}
$rows = $qry->result_array();
if (count($rows) == 0) {
return ["", ""];
}
return [$rows[0]["LocationID"], $rows[0]["LocationName"]];
}
//create location
function get_env()
{
if ($this->is_staging) {
echo "Environment is Staging \n";
} else {
echo "Environment is Production \n";
}
}
function change_env()
{
$this->reset_token();
$this->put_token();
}
function ss_location_in_org()
{
$service = "/Location/?organization=$this->organizationID";
$resp = $this->ss_get($service);
print_r($this->objToArray($resp));
}
function ss_location_by_id($id)
{
$service = "/Location/$id";
$resp = $this->ss_get($service);
print_r($this->objToArray($resp));
}
function ss_register_all_location()
{
$sql = "select l.*,
case
when LocationPhysicalTypeCode = 'si' then 1
when LocationPhysicalTypeCode = 'bu' then 2
when LocationPhysicalTypeCode = 'lvl' then 3
when LocationPhysicalTypeCode = 'ro' then 4
end xid
from {$this->dbname}.location l
where trim(LocationID) = ''
order by xid";
$qry = $this->db->query($sql);
if (!$qry) {
echo "ERR : " . $this->db->error()["message"];
exit;
}
$rows = $qry->result_array();
foreach ($rows as $r) {
$code = $r["LocationCode"];
$name = $r["LocationName"];
$description = $r["LocationDescription"];
$type = $r["LocationPhysicalTypeCode"] . "^" . $r["LocationPhysicalTypeDisplay"];
$lat = $r["LocationLatitude"];
$long = $r["LocationLongitude"];
$parentID = $r["LocationParentLocalID"];
$partOf = $this->get_parent_id($parentID);
// echo "$code | $name | $description | $type | $lat | $long | $parentID | $partOf \n";
list($phone, $fax, $email, $url) = $this->get_phone_email($r["LocationLocalID"]);
// echo "$phone | $fax | $email | $url \n";
list($line, $city, $admCode, $postalCode, $rt, $rw) = $this->get_address($r["LocationLocalID"]);
// echo "$line | $city | $admCode | $postalCode| $rt | $rw \n";
// register location
$resp = $this->ss_location_create(
"$code",
$name,
"$description",
"$line",
"$city",
"$postalCode",
"$admCode",
"$rt",
"$rw",
"$phone",
"$type",
$partOf,
$email,
$fax,
$url,
$long,
$lat
);
echo "\nid : " . $resp["id"];
echo "\nname : " . $resp["name"];
if (isset($resp["id"]) && $resp["id"] != "") {
$sql = "update {$this->dbname}.location
set LocationID = ? where LocationLocalID = ?";
$qry = $this->db->query($sql, [$resp["id"], $r["LocationLocalID"]]);
if (!$qry) {
echo "\nERR update location " . $this->db->error()["message"];
exit;
}
} else {
echo "\nError register location : \n";
print_r($resp);
exit;
}
}
}
function get_parent_id($parentID)
{
if ($parentID == 0) return "";
$sql = "select l.*
from {$this->dbname}.location l
where LocationLocalID = ?";
$qry = $this->db->query($sql, [$parentID]);
if (!$qry) {
return "";
}
$rows = $qry->result_array();
if (count($rows) == 0) {
return "";
}
return $rows[0]["LocationID"];
}
function get_address($localID)
{
$sql = "select * from
{$this->dbname}.location_address where LocationAddressLocationLocalID = ?
and LocationAddresIsActive = 'Y'";
$qry = $this->db->query($sql, [$localID]);
if (!$qry) {
echo "ERR : " . $this->db->error()["message"];
exit;
}
$rows = $qry->result_array();
$line = "";
$city = "";
$code = "";
$postalCode = "";
$rt = "";
$rw = "";
foreach ($rows as $r) {
$line = $r["LocationAddresLine"];
$city = $r["LocationAddresCityName"];
$code = $r["LocationAddresVillage"];
$postalCode = $r["LocationAddresPostalCode"];
$rt = $r["LocationAddresRT"];
$rw = $r["LocationAddresRW"];
}
return [$line, $city, $code, $postalCode, $rt, $rw];
}
function get_phone_email($localID)
{
$sql = "select * from
{$this->dbname}.location_telecom where LocationTelecomLocationID = ?
and LocationIsActive = 'Y'";
$qry = $this->db->query($sql, [$localID]);
if (!$qry) {
echo "ERR : " . $this->db->error()["message"];
exit;
}
$rows = $qry->result_array();
$email = "";
$fax = "";
$url = "";
$phone = "";
foreach ($rows as $r) {
$system = $r["LocationSystem"];
switch ($system) {
case "phone":
$phone = $r["LocationValue"];
break;
case "fax":
$fax = $r["LocationValue"];
break;
case "email":
$email = $r["LocationValue"];
break;
case "url":
$url = $r["LocationValue"];
break;
}
}
return [$phone, $fax, $email, $url];
}
function ss_location_create(
$code,
$name,
$description,
$address,
$city,
$kodePos,
$administrativeCode,
$rt,
$rw,
$phone,
$type,
$partOf = "",
$email = "",
$fax = "",
$url = "",
$long = -6.23115426275766,
$lat = 106.83239885393944
) {
$organizationID = $this->organizationID;
list($type_code, $type_display) = explode("^", $type);
$telecom = [];
$telecom[] = ["system" => "phone", "value" => "$phone", "use" => "work"];
if ($fax != "") $telecom[] = ["system" => "fax", "value" => "$fax", "use" => "work"];
if ($email != "") $telecom[] = ["system" => "email", "value" => "$email"];
if ($url != "") $telecom[] = ["system" => "url", "value" => "$url"];
$provCode = substr($administrativeCode, 0, 2);
$cityCode = substr($administrativeCode, 0, 4);
$districtCode = substr($administrativeCode, 0, 7);
$villageCode = substr($administrativeCode, 0, 10);
$data = [
"resourceType" => "Location",
"identifier" => [
[
"system" => "http://sys-ids.kemkes.go.id/location/{$organizationID}",
"value" => "$code",
],
],
"status" => "active",
"name" => "$name",
"description" => "$description",
"mode" => "instance",
"telecom" => $telecom,
"address" => [
"use" => "work",
"line" => [
$address,
],
"city" => "$city",
"postalCode" => "$kodePos",
"country" => "ID",
"extension" => [
[
"url" =>
"https://fhir.kemkes.go.id/r4/StructureDefinition/administrativeCode",
"extension" => [
["url" => "province", "valueCode" => $provCode],
["url" => "city", "valueCode" => $cityCode],
["url" => "district", "valueCode" => "$districtCode"],
["url" => "village", "valueCode" => "$villageCode"],
["url" => "rt", "valueCode" => "$rt"],
["url" => "rw", "valueCode" => "$rw"],
],
],
],
],
"physicalType" => [
"coding" => [
[
"system" =>
"http://terminology.hl7.org/CodeSystem/location-physical-type",
"code" => "$type_code",
"display" => "$type_display",
],
],
],
"position" => [
"longitude" => intval($long),
"latitude" => intval($lat),
"altitude" => 0,
],
"managingOrganization" => ["reference" => "Organization/{$organizationID}"],
];
if ($partOf != "") {
$data["partOf"] = [
"reference" => "Location/$partOf"
];
}
$service = "/Location";
$resp = $this->ss_post($service, $data);
return $this->objToArray($resp);
}
function ss_post($service, $data)
{
$token = $this->get_token();
$authorization = "Authorization: Bearer " . $token;
$xbase_url = $this->base_url;
$url = $xbase_url . "$service";
$ch = curl_init($url);
# Setup request to send json via POST.
$payload = json_encode($data);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', $authorization));
# Return response instead of printing.
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
# Send request.
$result = curl_exec($ch);
curl_close($ch);
# Print response.
$data_rst = json_decode($result);
return $data_rst;
}
function ss_get($service, $debug = "")
{
$token = $this->get_token();
$authorization = "Authorization: Bearer " . $token;
$xbase_url = $this->base_url;
$url = $xbase_url . "$service";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', $authorization));
# Return response instead of printing.
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
# Send request.
$result = curl_exec($ch);
curl_close($ch);
# Print response.
if ($debug != "") {
echo "url : $url \n";
print_r($result);
}
$data_rst = json_decode($result);
return $data_rst;
}
function ss_encounter_param(
$patientIhs,
$patientName,
$dpjpIhs,
$dpjpName,
$locationIhs,
$locationName,
$organizationID,
$orderHeaderNumber,
$dateTime // 2022-06-14T07:00:00+07:00
) {
if ($this->is_staging) {
$dpjpIhs = "N10000001";
$dpjpName = "Dokter Bronsig";
}
$encounterParam = [
"resourceType" => "Encounter",
"status" => "arrived",
"class" => [
"system" => "http://terminology.hl7.org/CodeSystem/v3-ActCode",
"code" => "AMB",
"display" => "ambulatory"
],
"subject" => [
"reference" => "Patient/{$patientIhs}",
"display" => "$patientName"
],
"participant" => [
[
"type" => [
[
"coding" => [
[
"system" => "http://terminology.hl7.org/CodeSystem/v3-ParticipationType",
"code" => "ATND",
"display" => "attender"
]
]
]
],
"individual" => [
"reference" => "Practitioner/{$dpjpIhs}",
"display" => "$dpjpName"
]
]
],
"period" => [
"start" => "$dateTime",
],
"location" => [
[
"location" => [
"reference" => "Location/$locationIhs",
"display" => "$locationName"
]
]
],
"statusHistory" => [
[
"status" => "arrived",
"period" => [
"start" => $dateTime
]
]
],
"serviceProvider" => [
"reference" => "Organization/{$organizationID}"
],
"identifier" => [
[
"system" => "http://sys-ids.kemkes.go.id/encounter/{$organizationID}",
"value" => "$orderHeaderNumber"
]
]
];
return $encounterParam;
}
//analys_patient
function ss_analyze_patient($date = "", $limit = 20)
{
if ($date == "") $date = date("Y-m-d");
$sql = "select M_PatientID, M_PatientIdNumber
from t_orderheader
join m_patient on T_OrderHeaderDate >= ?
and T_OrderHeaderIsActive = 'Y'
and T_OrderHeaderDate <= ?
and T_OrderHeaderDate + interval 30 minute < now()
and T_OrderHeaderM_PatientID = M_PatientID
and M_PatientM_IdTypeID = 1
left join {$this->dbname}.oh_patient_map
on M_PatientID = OHPatientMapM_PatientID
where OHPatientMapM_PatientID is null
limit 0,$limit
";
$sdate = "$date 00:00:01";
$edate = "$date 23:59:59";
$qry = $this->db->query($sql, [$sdate, $edate]);
if (!$qry) {
echo $this->db->error()["message"];
return [];
}
$rows = $qry->result_array();
foreach ($rows as $r) {
$nik = $r["M_PatientIdNumber"];
$patient_id = $r["M_PatientID"];
echo "processing [M_PatientID : $patient_id] : $nik => ";
if (strlen($nik) != 16) {
echo " *invalid nik* len : " . strlen($nik) . "\n";
continue;
}
$ihsNumber = $this->populate_patient_nik($nik);
if (strlen($ihsNumber) > 4) {
echo " $ihsNumber \n";
$rec = ["OHPatientMapM_PatientID" => $patient_id, "OHPatientMapIhsNumber" => $ihsNumber];
$this->insert_or_update("{$this->dbname}.oh_patient_map", $rec, "OHPatientMapM_PatientID");
} else {
echo " *Invalid* $ihsNumber \n";
}
}
}
function insert_or_update($table, $rec, $id_field)
{
$sql = "select count(*) as tot from $table
where $id_field = ?";
$qry = $this->db->query($sql, [$rec[$id_field]]);
if (!$qry) {
echo "Error : " . $this->db->error()["message"];
exit;
}
$rows = $qry->result_array();
if ($rows[0]["tot"] == 0) {
//insert
$sql = "insert into $table (";
$fields = implode(", ", array_keys($rec));
$sql .= $fields . ") values(";
$vals = [];
foreach (array_keys($rec) as $f) {
if (count($vals) > 0) {
$sql .= ", ";
}
$sql .= "?";
$vals[] = $rec[$f];
}
$sql .= ")";
} else {
$sql = "update $table set ";
$vals = [];
foreach (array_keys($rec) as $f) {
if (count($vals) > 0) {
$sql .= ", ";
}
$sql .= "$f = ? ";
$vals[] = $rec[$f];
}
$sql .= " where $id_field = " . $rec[$id_field];
}
$qry = $this->db->query($sql, $vals);
echo $this->db->last_query() . "\n";
}
// Poppulate
function populate_staff($debug = "")
{
$sql = "select * from {$this->dbname}.oh_staff_map
where OHStaffMapIhsNumber= ''
";
$qry = $this->db->query($sql);
if (!$qry) {
echo "Error get staff map: " . $this->db->error()["message"];
exit;
}
$rows = $qry->result_array();
$sqlu = "update {$this->dbname}.oh_staff_map
set OHStaffMapIhsNumber = ? where OHStaffMapM_StaffNIK=?";
foreach ($rows as $r) {
$nik = trim($r["OHStaffMapM_StaffNIK"]);
$result = $this->search_practicioner_by_nik($nik, $debug);
$ihsNumber = $this->parse_nakes_ihs_number($result);
echo "Processing NIK $nik => $ihsNumber";
$qry = $this->db->query($sqlu, [$ihsNumber, $nik]);
if (!$qry) {
echo "\nError update oh_staff_map : " . $this->db->error()["message"];
exit;
}
echo " updated [OK]\n";
}
}
//populate patient
function populate_patient_nik($nik)
{
$result = $this->search_patient_by_nik($nik);
$patientIhsNumber = $this->parse_nakes_ihs_number($result);
return $patientIhsNumber;
}
//populate dokter
function populate_dokter_nik($nik)
{
$result = $this->search_practicioner_by_nik($nik);
$nakesIhsNumber = $this->parse_nakes_ihs_number($result);
echo "Nakes IHS : $nakesIhsNumber";
}
function parse_nakes_ihs_number($result, $debug = "")
{
if (count($result) == 0) return "";
$a_result = $this->objToArray($result);
return $a_result["entry"][0]["resource"]["id"];
}
function search_practicioner_by_nik($nik, $debug = "")
{
$service = "/Practitioner?identifier=https://fhir.kemkes.go.id/id/nik|" . $nik;
$resp = $this->ss_get($service, $debug);
if ($debug != "") {
print_r($resp);
}
return $resp;
}
function search_practicioner_by_nik_old($nik)
{
$token = $this->get_token();
$authorization = "Authorization: Bearer " . $token;
$xbase_url = $this->base_url;
//API URL
$url = $xbase_url . "/Practitioner?identifier=https://fhir.kemkes.go.id/id/nik|" . $nik;
//echo $url;
$ch = curl_init($url);
# Setup request to send json via POST.
//$payload = json_encode($data);
//curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', $authorization));
# Return response instead of printing.
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
# Send request.
$result = curl_exec($ch);
curl_close($ch);
# Print response.
$data_rst = json_decode($result);
return $data_rst;
}
function get_organization_id()
{
$sql = "SELECT organizationID
FROM {$this->dbname}.organization
JOIN m_branch ON organizationM_BranchID = M_BranchID AND M_BranchIsDefault = 'Y' AND M_BranchIsActive = 'Y'
WHERE organizationIsActive = 'Y'";
$qry = $this->db->query($sql);
if (!$qry) {
return;
}
$rows = $qry->result_array();
if (count($rows) > 0) {
$this->organizationID = $rows[0]["organizationID"];
}
}
function get_client_key($debug = "")
{
$sql = "select * from {$this->dbname}.client where clientIsActive = 'Y'";
$qry = $this->db->query($sql);
if (!$qry) {
return [false, "", ""];
}
$rows = $qry->result_array();
if (count($rows) == 0) {
if ($debug != "") {
print_r([false, "", ""]);
}
return [false, "", ""];
}
if ($debug != "") {
print_r([true, $rows[0]["clientKey"], $rows[0]["clientSecret"]]);
}
return [true, $rows[0]["clientKey"], $rows[0]["clientSecret"]];
}
function reset_token()
{
$sql = "delete from {$this->dbname}.token ";
$qry = $this->db->query($sql);
if (!$qry) {
echo "ERR : " . $this->db->error()["message"];
echo " " . $this->db->last_query();
exit;
}
}
function put_token()
{
$auth_url = $this->base_oauth_url;
//api url
$url = $auth_url . "/accesstoken?grant_type=client_credentials";
list($status, $key, $secret) = $this->get_client_key();
$data = [
"client_id" => $key,
"client_secret" => $secret
];
$ch = curl_init($url);
# setup request to send json via post.
$post_data = http_build_query($data);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
// suppress return header
// curl_setopt(
// $ch,
// CURLOPT_HEADER,
// array(
// 'content-type: application/x-www-form-urlencoded'
// )
// );
# return response instead of printing.
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
# send request.
$result = curl_exec($ch);
curl_close($ch);
# print response.
//echo $token_rst->access_token;
if ($result) {
$token_rst = json_decode($result);
$sql = "select count(*) as xcount, tokenID
from {$this->dbname}.token
where
tokenIsActive = 'y'
";
$qry = $this->db_onedev->query($sql);
if (!$qry) {
echo "get count token error";
exit;
}
$rst_count = $qry->row_array();
// print_r($token_rst);
if ($rst_count['xcount'] > 0) {
$sql = "update {$this->dbname}.token set tokenValue = ?, tokenExpired = date_add(now(), interval 50 minute)
where tokenID = ?";
$qry = $this->db_onedev->query($sql, [$token_rst->access_token, $rst_count['tokenID']]);
if (!$qry) {
$this->sys_error_db("refresh token error", $this->db_onedev->last_query());
exit;
}
} else {
$sql = "update {$this->dbname}.token set tokenIsActive = 'N' where tokenIsActive = 'Y'";
$qry = $this->db_onedev->query($sql);
if (!$qry) {
echo "nonactive token error";
exit;
}
$sql = "insert into {$this->dbname}.token(tokenValue,tokenExpired) values(?,date_add(now(), interval 50 minute))";
$qry = $this->db_onedev->query($sql, [$token_rst->access_token]);
if (!$qry) {
echo "insert token error";
exit;
}
}
$sql = "select tokenValue
from {$this->dbname}.token
where
tokenIsActive = 'Y' limit 1
";
$qry = $this->db_onedev->query($sql);
if (!$qry) {
echo "get token error";
exit;
}
return $qry->row()->tokenValue;
}
}
function get_token()
{
$sql = "SELECT COUNT(*) as xcount, tokenValue
FROM {$this->dbname}.token
WHERE tokenIsActive = 'Y' AND NOW() < tokenExpired AND tokenValue IS NOT NULL
";
$qry = $this->db_onedev->query($sql);
if (!$qry) {
echo "select token error";
exit;
}
$data_token = $qry->row_array();
//print_r($data_token);
if ($data_token['xcount'] > 0) {
return $data_token['tokenValue'];
} else {
return $this->put_token();
}
}
function search_patient_by_nik($nik, $debug = "")
{
$service = "/Patient?identifier=https://fhir.kemkes.go.id/id/nik|" . $nik;
$resp = $this->ss_get($service);
if ($debug != "") {
echo "resp : ";
print_r($resp);
}
return $resp;
}
function send_bundle($orderID)
{
$sql = "SELECT *
FROM {$this->dbname}.bundle
WHERE BundleT_orderHeaderID = {$orderID} AND BundleIsActive = 'Y'
LIMIT 1
";
$qry = $this->db_onedev->query($sql);
if (!$qry) {
echo "select bundle error";
exit;
}
$data_blundle = $qry->row_array();
// print_r($data_blundle);
$json_data = json_decode($data_blundle['BundleJSON']);
$json_payload = json_encode($json_data);
$token = $this->get_token();
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api-satusehat-dev.dto.kemkes.go.id/fhir-r4/v1',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => $json_payload,
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json',
'Authorization: Bearer ' . $token
),
));
$response = curl_exec($curl);
curl_close($curl);
//echo $response;
//$json_response = json_encode(json_decode($response));
//echo $json_response;
$sql = "UPDATE {$this->dbname}.bundle SET BundleResponseJSON = '{$response}'
WHERE BundleT_orderHeaderID = {$orderID} AND BundleIsActive = 'Y'
";
$qry = $this->db_onedev->query($sql);
//echo $sql;
if (!$qry) {
echo "update bundle error";
exit;
}
echo $response;
}
protected function objToArray($obj)
{
// Not an object or array
if (!is_object($obj) && !is_array($obj)) {
return $obj;
}
// Parse array
foreach ($obj as $key => $value) {
$arr[$key] = $this->objToArray($value);
}
// Return parsed array
return $arr;
}
}