547 lines
25 KiB
PHP
547 lines
25 KiB
PHP
<?php
|
|
defined('BASEPATH') or exit('No direct script access allowed');
|
|
|
|
/**
|
|
* Pengganti fn_sampling_get_normal, sp_sampling_check_normal_setting,
|
|
* dan sp_sampling_fix_normal_by_orderdetail (MySQL).
|
|
*
|
|
* Alasan: SP/fungsi MySQL membaca M_PatientDOB langsung dari m_patient,
|
|
* yang NULL setelah enkripsi PDP. Library ini decrypt M_PatientDOB_enc
|
|
* di PHP sebelum menghitung usia.
|
|
*/
|
|
class Ibl_sampling_normal
|
|
{
|
|
private $db;
|
|
|
|
public function __construct()
|
|
{
|
|
$CI = &get_instance();
|
|
$this->db = $CI->load->database('onedev', true);
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Public API
|
|
// -------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Cari Nat_NormalValueID sesuai methode, test, sex, dan umur (dalam hari).
|
|
* Urutan prioritas:
|
|
* Type 1 — sex + age range
|
|
* Type 2 — age range saja
|
|
* Type 3 — sex saja
|
|
* Type 4 — fallback
|
|
*/
|
|
public function get_normal_value_id($methodeID, $natTestID, $sexID, $ageInDay)
|
|
{
|
|
$methodeID = intval($methodeID);
|
|
$natTestID = intval($natTestID);
|
|
$sexID = intval($sexID);
|
|
$ageInDay = intval($ageInDay);
|
|
|
|
$min_days = $this->_age_sql('Nat_NormalValueMinAge');
|
|
$max_days = $this->_age_sql('Nat_NormalValueMaxAge');
|
|
|
|
$age_filter = "
|
|
AND (
|
|
(Nat_NormalValueMinAgeInclusive = 'Y' AND ($min_days) <= $ageInDay)
|
|
OR (Nat_NormalValueMinAgeInclusive = 'N' AND ($min_days) < $ageInDay)
|
|
)
|
|
AND (
|
|
(Nat_NormalValueMaxAgeInclusive = 'Y' AND ($max_days) >= $ageInDay)
|
|
OR (Nat_NormalValueMaxAgeInclusive = 'N' AND ($max_days) > $ageInDay)
|
|
)";
|
|
|
|
$base = "FROM nat_normalvalue
|
|
WHERE (Nat_NormalValueValidDate IS NULL OR Nat_NormalValueValidDate < NOW())
|
|
AND Nat_NormalValueIsActive = 'Y'
|
|
AND Nat_NormalValueIsAbnormal = 'N'
|
|
AND Nat_NormalValueNat_MethodeID = $methodeID
|
|
AND Nat_NormalValueNat_TestID = $natTestID
|
|
AND Nat_NormalValueNat_FlagID = 1";
|
|
|
|
$id = $this->_query_one("SELECT Nat_NormalValueID $base
|
|
AND Nat_NormalValueNat_NormalValueTypeID = 1
|
|
AND Nat_NormalValueNat_SexID = $sexID
|
|
$age_filter LIMIT 1");
|
|
if ($id) return $id;
|
|
|
|
$id = $this->_query_one("SELECT Nat_NormalValueID $base
|
|
AND Nat_NormalValueNat_NormalValueTypeID = 2
|
|
$age_filter LIMIT 1");
|
|
if ($id) return $id;
|
|
|
|
$id = $this->_query_one("SELECT Nat_NormalValueID $base
|
|
AND Nat_NormalValueNat_NormalValueTypeID = 3
|
|
AND Nat_NormalValueNat_SexID = $sexID
|
|
LIMIT 1");
|
|
if ($id) return $id;
|
|
|
|
$id = $this->_query_one("SELECT Nat_NormalValueID $base
|
|
AND Nat_NormalValueNat_NormalValueTypeID = 4
|
|
LIMIT 1");
|
|
if ($id) return $id;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Pengganti sp_sampling_check_normal_setting.
|
|
* Mengembalikan array compat dengan call_multi_result_procedure():
|
|
* ok, message, result_sets[0]=summary, [1]=checks, [2]=branches, [3]=candidates
|
|
*/
|
|
public function check_setting_by_order_detail($orderDetailID)
|
|
{
|
|
$orderDetailID = intval($orderDetailID);
|
|
$data = $this->_load_order_detail_data($orderDetailID);
|
|
if ($data === null) {
|
|
return [
|
|
'ok' => false,
|
|
'message' => "T_OrderDetailID {$orderDetailID} tidak ditemukan atau tidak aktif",
|
|
'result_sets' => [],
|
|
];
|
|
}
|
|
|
|
list($sexID, $dobStr, $orderDate, $ageInDay,
|
|
$orderHeaderID, $patientID, $natTestID,
|
|
$row) = $data;
|
|
|
|
$methods = $this->_resolve_method_sources($natTestID);
|
|
list($selID, $selName, $selSource) = $this->_pick_method($methods);
|
|
|
|
$normalValueID = 0;
|
|
if ($selID > 0 && $natTestID > 0 && $sexID > 0 && $ageInDay !== null) {
|
|
$normalValueID = $this->get_normal_value_id($selID, $natTestID, $sexID, $ageInDay);
|
|
}
|
|
|
|
$summary = [[
|
|
'T_OrderDetailID' => $orderDetailID,
|
|
'T_OrderHeaderID' => $orderHeaderID,
|
|
'M_PatientID' => $patientID,
|
|
'M_PatientM_SexID' => $sexID ?: null,
|
|
'M_PatientDOB' => $dobStr ?: null,
|
|
'T_OrderHeaderDate' => $row['order_date'],
|
|
'AgeInDay' => $ageInDay,
|
|
'T_TestID' => intval($row['t_test_id']),
|
|
'T_TestName' => $row['t_test_name'],
|
|
'Nat_TestID' => $natTestID ?: null,
|
|
'Nat_TestCode' => $row['nat_test_code'],
|
|
'Nat_TestName' => $row['nat_test_name'],
|
|
'T_OrderDetailNat_MethodeID'=> intval($row['order_detail_methode_id']),
|
|
'MethodeIDFromPriority' => $methods['priority_id'] ?: null,
|
|
'MethodeNameFromPriority' => $methods['priority_name'],
|
|
'MethodeIDFromInstrument' => $methods['instrument_id'] ?: null,
|
|
'MethodeNameFromInstrument' => $methods['instrument_name'],
|
|
'MethodeIDFromNormalValue' => $methods['normalvalue_id'] ?: null,
|
|
'MethodeNameFromNormalValue'=> $methods['normalvalue_name'],
|
|
'SelectedMethodeID' => $selID,
|
|
'SelectedMethodeName' => $selName,
|
|
'SelectedMethodeSource' => $selSource,
|
|
'FnSamplingGetNormalResult' => $normalValueID,
|
|
]];
|
|
|
|
$nvCount = 0;
|
|
if ($natTestID > 0) {
|
|
$r = $this->db->query(
|
|
"SELECT COUNT(*) AS cnt FROM nat_normalvalue
|
|
WHERE Nat_NormalValueNat_TestID = ?
|
|
AND Nat_NormalValueNat_MethodeID = ?
|
|
AND Nat_NormalValueIsActive = 'Y'
|
|
AND Nat_NormalValueIsAbnormal = 'N'",
|
|
[$natTestID, $selID ?: 0]
|
|
)->row_array();
|
|
$nvCount = intval($r['cnt'] ?? 0);
|
|
}
|
|
|
|
$checks = [
|
|
$this->_chk('ORDER_DETAIL_ACTIVE', true, (string) $orderDetailID, 't_orderdetail aktif harus ditemukan'),
|
|
$this->_chk('PATIENT_SEX', $sexID > 0, (string) ($sexID ?: 'NULL'), 'Dipakai pada type 1 dan type 3'),
|
|
$this->_chk('PATIENT_DOB', $dobStr !== '', ($dobStr ?: 'NULL'), 'DOB dipakai untuk hitung AgeInDay'),
|
|
$this->_chk('ORDER_DATE', !empty($row['order_date']), ($row['order_date'] ?: 'NULL'), 'Tanggal order dipakai untuk hitung AgeInDay'),
|
|
$this->_chk('AGE_IN_DAY', $ageInDay !== null, ($ageInDay !== null ? (string) $ageInDay : 'NULL'), 'Dipakai pada type 1 dan type 2'),
|
|
$this->_chk('NAT_TEST', $natTestID > 0, (string) ($natTestID ?: 'NULL'), 'Harus ada mapping T_TestNat_TestID'),
|
|
$this->_chk('METHOD_PRIORITY', $methods['priority_id'] > 0, (string) ($methods['priority_id'] ?: 'NULL'), 'Sumber metode prioritas pertama'),
|
|
$this->_chk('METHOD_INSTRUMENT', $methods['instrument_id'] > 0, (string) ($methods['instrument_id'] ?: 'NULL'), 'Fallback metode kedua'),
|
|
$this->_chk('METHOD_NORMALVALUE', $methods['normalvalue_id'] > 0, (string) ($methods['normalvalue_id'] ?: 'NULL'), 'Fallback metode ketiga'),
|
|
$this->_chk('SELECTED_METHOD', $selID > 0, (string) ($selID ?: 'NULL'), ($selSource ?: 'Tidak ada metode yang bisa dipakai')),
|
|
$this->_chk('NORMALVALUE_TEST_METHOD_ACTIVE', $nvCount > 0, (string) $nvCount, 'Jumlah nat_normalvalue aktif non-abnormal untuk test + metode terpilih'),
|
|
['check_name' => 'FN_RESULT', 'check_status' => ($normalValueID > 0 ? 'OK' : 'NOT_FOUND'), 'check_value' => (string) $normalValueID, 'check_note' => 'Hasil akhir fn_sampling_get_normal'],
|
|
];
|
|
|
|
$branches = $selID > 0
|
|
? $this->_query_branches($selID, $natTestID, $sexID, $ageInDay)
|
|
: [['branch_name' => 'NO_SELECTED_METHOD', 'matched_count' => 0, 'first_normalvalue_id' => null]];
|
|
$candidates = $natTestID > 0 ? $this->_query_candidates($selID, $natTestID, $sexID, $ageInDay) : [];
|
|
|
|
return [
|
|
'ok' => true,
|
|
'message' => '',
|
|
'result_sets' => [$summary, $checks, $branches, $candidates],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Pengganti sp_sampling_fix_normal_by_orderdetail.
|
|
* Mengembalikan array compat dengan call_multi_result_procedure():
|
|
* ok, message, result_sets[0]=result_row, [1]=order_detail_row
|
|
*/
|
|
public function fix_by_order_detail($orderDetailID)
|
|
{
|
|
$orderDetailID = intval($orderDetailID);
|
|
$data = $this->_load_order_detail_data($orderDetailID);
|
|
if ($data === null) {
|
|
$errRow = [[
|
|
'status' => 'ERR',
|
|
'message' => "T_OrderDetailID {$orderDetailID} tidak ditemukan atau tidak aktif",
|
|
'selected_methode_id' => null,
|
|
'selected_methode_name'=> null,
|
|
'selected_methode_source' => null,
|
|
'nat_normalvalue_id' => null,
|
|
'updated_rows' => 0,
|
|
]];
|
|
return ['ok' => true, 'message' => '', 'result_sets' => [$errRow, []]];
|
|
}
|
|
|
|
list($sexID, $dobStr, $orderDate, $ageInDay,
|
|
$orderHeaderID, $patientID, $natTestID,
|
|
$row) = $data;
|
|
|
|
$methods = $this->_resolve_method_sources($natTestID);
|
|
list($selID, $selName, $selSource) = $this->_pick_method($methods);
|
|
|
|
$normalValueID = 0;
|
|
if ($selID > 0 && $natTestID > 0 && $sexID > 0 && $ageInDay !== null) {
|
|
$normalValueID = $this->get_normal_value_id($selID, $natTestID, $sexID, $ageInDay);
|
|
}
|
|
|
|
if ($normalValueID > 0) {
|
|
$this->db->query(
|
|
"UPDATE t_orderdetail od
|
|
JOIN nat_normalvalue nn ON nn.Nat_NormalValueID = ?
|
|
SET od.T_OrderDetailNat_NormalValueID = nn.Nat_NormalValueID,
|
|
od.T_OrderDetailNormalValueNote = nn.Nat_NormalValueNote,
|
|
od.T_OrderDetailNormalValueDescription = nn.Nat_NormalValueDescription,
|
|
od.T_OrderDetailMinValue = nn.Nat_NormalValueMinValue,
|
|
od.T_OrderDetailMaxValue = nn.Nat_NormalValueMaxValue,
|
|
od.T_OrderDetailMinValueInclusive = nn.Nat_NormalValueMinValueInclusive,
|
|
od.T_OrderDetailMaxValueInclusive = nn.Nat_NormalValueMaxValueInclusive,
|
|
od.T_OrderDetailNat_MethodeID = ?,
|
|
od.T_OrderdetailNat_MethodeName = ?
|
|
WHERE od.T_OrderDetailID = ?
|
|
AND od.T_OrderDetailIsActive = 'Y'",
|
|
[$normalValueID, $selID, $selName, $orderDetailID]
|
|
);
|
|
$updatedRows = $this->db->affected_rows();
|
|
$resultRow = [[
|
|
'status' => 'OK',
|
|
'message' => "Normal value berhasil diupdate untuk T_OrderDetailID {$orderDetailID}",
|
|
'selected_methode_id' => $selID,
|
|
'selected_methode_name'=> $selName,
|
|
'selected_methode_source' => $selSource,
|
|
'nat_normalvalue_id' => $normalValueID,
|
|
'updated_rows' => $updatedRows,
|
|
]];
|
|
} else {
|
|
$resultRow = [[
|
|
'status' => 'NOT_FOUND',
|
|
'message' => "Normal value tidak ditemukan untuk T_OrderDetailID {$orderDetailID}",
|
|
'selected_methode_id' => $selID,
|
|
'selected_methode_name'=> $selName,
|
|
'selected_methode_source' => $selSource,
|
|
'nat_normalvalue_id' => $normalValueID,
|
|
'updated_rows' => 0,
|
|
]];
|
|
}
|
|
|
|
$odRow = $this->db->query(
|
|
"SELECT T_OrderDetailID, T_OrderDetailNat_NormalValueID, T_OrderDetailNat_MethodeID,
|
|
T_OrderdetailNat_MethodeName, T_OrderDetailNormalValueDescription,
|
|
T_OrderDetailMinValue, T_OrderDetailMaxValue,
|
|
T_OrderDetailMinValueInclusive, T_OrderDetailMaxValueInclusive
|
|
FROM t_orderdetail WHERE T_OrderDetailID = ? LIMIT 1",
|
|
[$orderDetailID]
|
|
)->result_array();
|
|
|
|
return ['ok' => true, 'message' => '', 'result_sets' => [$resultRow, $odRow]];
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Private helpers
|
|
// -------------------------------------------------------------------------
|
|
|
|
/** Inline pengganti fn_normal_get_age: konversi kolom usia ke hari di SQL. */
|
|
private function _age_sql($col)
|
|
{
|
|
return "CASE Nat_NormalValueAgeUnit
|
|
WHEN 'HARI' THEN {$col}
|
|
WHEN 'BULAN' THEN {$col} * 30
|
|
WHEN 'TAHUN' THEN {$col} * 365
|
|
ELSE {$col}
|
|
END";
|
|
}
|
|
|
|
/**
|
|
* Ambil data dasar order detail termasuk DOB terenkripsi.
|
|
* Return [sexID, dobStr, orderDate, ageInDay, orderHeaderID, patientID, natTestID, $row]
|
|
* atau null jika tidak ditemukan.
|
|
*/
|
|
private function _load_order_detail_data($orderDetailID)
|
|
{
|
|
$row = $this->db->query(
|
|
"SELECT
|
|
od.T_OrderDetailT_OrderHeaderID AS order_header_id,
|
|
oh.T_OrderHeaderM_PatientID AS patient_id,
|
|
p.M_PatientM_SexID AS sex_id,
|
|
p.M_PatientDOB_enc,
|
|
p.M_PatientDOB,
|
|
DATE(oh.T_OrderHeaderDate) AS order_date,
|
|
od.T_OrderDetailT_TestID AS t_test_id,
|
|
tt.T_TestName AS t_test_name,
|
|
tt.T_TestNat_TestID AS nat_test_id,
|
|
nt.Nat_TestCode AS nat_test_code,
|
|
nt.Nat_TestName AS nat_test_name,
|
|
od.T_OrderDetailNat_MethodeID AS order_detail_methode_id
|
|
FROM t_orderdetail od
|
|
JOIN t_orderheader oh ON oh.T_OrderHeaderID = od.T_OrderDetailT_OrderHeaderID
|
|
JOIN m_patient p ON p.M_PatientID = oh.T_OrderHeaderM_PatientID
|
|
LEFT JOIN t_test tt ON tt.T_TestID = od.T_OrderDetailT_TestID
|
|
LEFT JOIN nat_test nt ON nt.Nat_TestID = tt.T_TestNat_TestID
|
|
WHERE od.T_OrderDetailID = ?
|
|
AND od.T_OrderDetailIsActive = 'Y'
|
|
LIMIT 1",
|
|
[$orderDetailID]
|
|
)->row_array();
|
|
|
|
if (!$row) return null;
|
|
|
|
$dobStr = '';
|
|
if (!empty($row['M_PatientDOB_enc'])) {
|
|
$CI = &get_instance();
|
|
$CI->load->library('ibl_encryptor');
|
|
$dobStr = (string) ($CI->ibl_encryptor->decrypt($row['M_PatientDOB_enc']) ?? '');
|
|
}
|
|
if ($dobStr === '' && !empty($row['M_PatientDOB'])) {
|
|
$dobStr = $row['M_PatientDOB'];
|
|
}
|
|
|
|
$ageInDay = null;
|
|
if ($dobStr !== '' && !empty($row['order_date'])) {
|
|
try {
|
|
$dob = new DateTime($dobStr);
|
|
$oDate = new DateTime($row['order_date']);
|
|
$ageInDay = (int) $oDate->diff($dob)->days;
|
|
} catch (Exception $e) {}
|
|
}
|
|
|
|
return [
|
|
intval($row['sex_id']),
|
|
$dobStr,
|
|
$row['order_date'],
|
|
$ageInDay,
|
|
intval($row['order_header_id']),
|
|
intval($row['patient_id']),
|
|
intval($row['nat_test_id']),
|
|
$row,
|
|
];
|
|
}
|
|
|
|
/** Resolusi metode dari 3 sumber: priority → instrument → normalvalue. */
|
|
private function _resolve_method_sources($natTestID)
|
|
{
|
|
$r = $this->db->query(
|
|
"SELECT mp.M_MethodePriorityNat_MethodeID, nm.Nat_MethodeName
|
|
FROM m_methode_priority mp
|
|
JOIN nat_methode nm ON nm.Nat_MethodeID = mp.M_MethodePriorityNat_MethodeID AND nm.Nat_MethodeIsActive = 'Y'
|
|
JOIN m_instrumentmethode im ON im.M_InstrumentMethodeNat_MethodeID = nm.Nat_MethodeID AND im.M_InstrumentMethodeIsActive = 'Y'
|
|
JOIN nat_instrument ni ON ni.Nat_InstrumentID = im.M_InstrumentMethodeNat_InstrumentID AND ni.Nat_InstrumentIsActive = 'Y'
|
|
WHERE mp.M_MethodePriorityIsActive = 'Y'
|
|
AND mp.M_MethodePriorityNat_TestID = ?
|
|
AND mp.M_MethodePriorityM_DayOfWeekID = DAYOFWEEK(NOW())
|
|
ORDER BY mp.M_MethodePriorityNumber DESC LIMIT 1",
|
|
[$natTestID]
|
|
)->row_array();
|
|
$priorityID = intval($r['M_MethodePriorityNat_MethodeID'] ?? 0);
|
|
$priorityName = $r['Nat_MethodeName'] ?? null;
|
|
|
|
$r = $this->db->query(
|
|
"SELECT im.M_InstrumentMethodeNat_MethodeID, nm.Nat_MethodeName
|
|
FROM m_instrumentmethode im
|
|
JOIN nat_methode nm ON nm.Nat_MethodeID = im.M_InstrumentMethodeNat_MethodeID AND nm.Nat_MethodeIsActive = 'Y'
|
|
JOIN nat_instrument ni ON ni.Nat_InstrumentID = im.M_InstrumentMethodeNat_InstrumentID AND ni.Nat_InstrumentIsActive = 'Y'
|
|
WHERE im.M_InstrumentMethodeNat_TestID = ?
|
|
AND im.M_InstrumentMethodeIsActive = 'Y'
|
|
ORDER BY im.M_InstrumentMethodePriority DESC LIMIT 1",
|
|
[$natTestID]
|
|
)->row_array();
|
|
$instrumentID = intval($r['M_InstrumentMethodeNat_MethodeID'] ?? 0);
|
|
$instrumentName = $r['Nat_MethodeName'] ?? null;
|
|
|
|
$r = $this->db->query(
|
|
"SELECT nn.Nat_NormalValueNat_MethodeID, nm.Nat_MethodeName
|
|
FROM nat_normalvalue nn
|
|
JOIN nat_methode nm ON nm.Nat_MethodeID = nn.Nat_NormalValueNat_MethodeID AND nm.Nat_MethodeIsActive = 'Y'
|
|
WHERE nn.Nat_NormalValueNat_TestID = ?
|
|
AND nn.Nat_NormalValueIsActive = 'Y'
|
|
ORDER BY nn.Nat_NormalValueID LIMIT 1",
|
|
[$natTestID]
|
|
)->row_array();
|
|
$normalID = intval($r['Nat_NormalValueNat_MethodeID'] ?? 0);
|
|
$normalName = $r['Nat_MethodeName'] ?? null;
|
|
|
|
return [
|
|
'priority_id' => $priorityID,
|
|
'priority_name' => $priorityName,
|
|
'instrument_id' => $instrumentID,
|
|
'instrument_name'=> $instrumentName,
|
|
'normalvalue_id' => $normalID,
|
|
'normalvalue_name' => $normalName,
|
|
];
|
|
}
|
|
|
|
/** Pilih metode terbaik dari hasil _resolve_method_sources(). */
|
|
private function _pick_method(array $methods)
|
|
{
|
|
if ($methods['priority_id'] > 0) {
|
|
return [$methods['priority_id'], $methods['priority_name'], 'm_methode_priority'];
|
|
}
|
|
if ($methods['instrument_id'] > 0) {
|
|
return [$methods['instrument_id'], $methods['instrument_name'], 'm_instrumentmethode'];
|
|
}
|
|
if ($methods['normalvalue_id'] > 0) {
|
|
return [$methods['normalvalue_id'], $methods['normalvalue_name'], 'nat_normalvalue'];
|
|
}
|
|
return [0, null, null];
|
|
}
|
|
|
|
/** Hitung matched_count per TYPE (1..4) untuk branch summary. */
|
|
private function _query_branches($methodeID, $natTestID, $sexID, $ageInDay)
|
|
{
|
|
$min = $this->_age_sql('Nat_NormalValueMinAge');
|
|
$max = $this->_age_sql('Nat_NormalValueMaxAge');
|
|
$base = "FROM nat_normalvalue
|
|
WHERE (Nat_NormalValueValidDate IS NULL OR Nat_NormalValueValidDate < NOW())
|
|
AND Nat_NormalValueIsActive = 'Y'
|
|
AND Nat_NormalValueIsAbnormal = 'N'
|
|
AND Nat_NormalValueNat_FlagID = 1
|
|
AND Nat_NormalValueNat_MethodeID = $methodeID
|
|
AND Nat_NormalValueNat_TestID = $natTestID";
|
|
|
|
$ageFilter = "
|
|
AND ((Nat_NormalValueMinAgeInclusive='Y' AND ($min)<=$ageInDay) OR (Nat_NormalValueMinAgeInclusive='N' AND ($min)<$ageInDay))
|
|
AND ((Nat_NormalValueMaxAgeInclusive='Y' AND ($max)>=$ageInDay) OR (Nat_NormalValueMaxAgeInclusive='N' AND ($max)>$ageInDay))";
|
|
|
|
$types = [
|
|
['TYPE_1', "AND Nat_NormalValueNat_NormalValueTypeID=1 AND Nat_NormalValueNat_SexID=$sexID $ageFilter"],
|
|
['TYPE_2', "AND Nat_NormalValueNat_NormalValueTypeID=2 $ageFilter"],
|
|
['TYPE_3', "AND Nat_NormalValueNat_NormalValueTypeID=3 AND Nat_NormalValueNat_SexID=$sexID"],
|
|
['TYPE_4', "AND Nat_NormalValueNat_NormalValueTypeID=4"],
|
|
];
|
|
|
|
$branches = [];
|
|
foreach ($types as list($label, $filter)) {
|
|
$r = $this->db->query("SELECT COUNT(*) AS cnt, MIN(Nat_NormalValueID) AS first_id $base $filter")->row_array();
|
|
$branches[] = [
|
|
'branch_name' => $label,
|
|
'matched_count' => intval($r['cnt'] ?? 0),
|
|
'first_normalvalue_id'=> $r['first_id'] ?? null,
|
|
];
|
|
}
|
|
return $branches;
|
|
}
|
|
|
|
/** Ambil semua kandidat nat_normalvalue dengan kolom diagnostik match/fail. */
|
|
private function _query_candidates($methodeID, $natTestID, $sexID, $ageInDay)
|
|
{
|
|
if (!$natTestID) return [];
|
|
|
|
$min = $this->_age_sql('Nat_NormalValueMinAge');
|
|
$max = $this->_age_sql('Nat_NormalValueMaxAge');
|
|
$a = intval($ageInDay);
|
|
$s = intval($sexID);
|
|
$m = intval($methodeID);
|
|
|
|
$matchMinAge = "(
|
|
(Nat_NormalValueMinAgeInclusive='Y' AND ($min)<=$a)
|
|
OR (Nat_NormalValueMinAgeInclusive='N' AND ($min)<$a))";
|
|
$matchMaxAge = "(
|
|
(Nat_NormalValueMaxAgeInclusive='Y' AND ($max)>=$a)
|
|
OR (Nat_NormalValueMaxAgeInclusive='N' AND ($max)>$a))";
|
|
|
|
$sql = "SELECT
|
|
nn.Nat_NormalValueID,
|
|
nn.Nat_NormalValueNat_TestID,
|
|
nn.Nat_NormalValueNat_MethodeID,
|
|
nm.Nat_MethodeName,
|
|
nn.Nat_NormalValueNat_NormalValueTypeID,
|
|
nn.Nat_NormalValueNat_SexID,
|
|
nn.Nat_NormalValueValidDate,
|
|
nn.Nat_NormalValueMinAge,
|
|
nn.Nat_NormalValueMaxAge,
|
|
nn.Nat_NormalValueAgeUnit,
|
|
nn.Nat_NormalValueMinAgeInclusive,
|
|
nn.Nat_NormalValueMaxAgeInclusive,
|
|
($min) AS MinAgeInDay,
|
|
($max) AS MaxAgeInDay,
|
|
nn.Nat_NormalValueNat_FlagID,
|
|
nn.Nat_NormalValueIsAbnormal,
|
|
nn.Nat_NormalValueIsActive,
|
|
IF((nn.Nat_NormalValueValidDate IS NULL OR nn.Nat_NormalValueValidDate < NOW()),'Y','N') AS MatchValidDate,
|
|
IF(nn.Nat_NormalValueIsActive='Y','Y','N') AS MatchActive,
|
|
IF(nn.Nat_NormalValueIsAbnormal='N','Y','N') AS MatchNotAbnormal,
|
|
IF(nn.Nat_NormalValueNat_FlagID=1,'Y','N') AS MatchFlag,
|
|
IF(nn.Nat_NormalValueNat_TestID=$natTestID,'Y','N') AS MatchNatTest,
|
|
IF($m>0 AND nn.Nat_NormalValueNat_MethodeID=$m,'Y','N') AS MatchSelectedMethod,
|
|
IF(nn.Nat_NormalValueNat_SexID=$s,'Y','N') AS MatchSex,
|
|
IF($matchMinAge,'Y','N') AS MatchMinAge,
|
|
IF($matchMaxAge,'Y','N') AS MatchMaxAge,
|
|
CASE nn.Nat_NormalValueNat_NormalValueTypeID
|
|
WHEN 1 THEN IF(nn.Nat_NormalValueNat_SexID=$s AND $matchMinAge AND $matchMaxAge,'Y','N')
|
|
WHEN 2 THEN IF($matchMinAge AND $matchMaxAge,'Y','N')
|
|
WHEN 3 THEN IF(nn.Nat_NormalValueNat_SexID=$s,'Y','N')
|
|
WHEN 4 THEN 'Y'
|
|
ELSE 'N'
|
|
END AS MatchTypeRule,
|
|
CONCAT_WS('; ',
|
|
IF(NOT(nn.Nat_NormalValueValidDate IS NULL OR nn.Nat_NormalValueValidDate<NOW()),'valid_date_not_passed',NULL),
|
|
IF(nn.Nat_NormalValueIsActive<>'Y','inactive',NULL),
|
|
IF(nn.Nat_NormalValueIsAbnormal<>'N','abnormal_row',NULL),
|
|
IF(nn.Nat_NormalValueNat_FlagID<>1,'flag_not_1',NULL),
|
|
IF(nn.Nat_NormalValueNat_TestID<>$natTestID,'nat_test_mismatch',NULL),
|
|
IF($m>0 AND nn.Nat_NormalValueNat_MethodeID<>$m,'methode_mismatch',NULL),
|
|
IF(nn.Nat_NormalValueNat_NormalValueTypeID IN(1,3) AND nn.Nat_NormalValueNat_SexID<>$s,'sex_mismatch',NULL),
|
|
IF(nn.Nat_NormalValueNat_NormalValueTypeID IN(1,2) AND NOT $matchMinAge,'age_below_min',NULL),
|
|
IF(nn.Nat_NormalValueNat_NormalValueTypeID IN(1,2) AND NOT $matchMaxAge,'age_above_max',NULL)
|
|
) AS FailReason
|
|
FROM nat_normalvalue nn
|
|
LEFT JOIN nat_methode nm ON nm.Nat_MethodeID = nn.Nat_NormalValueNat_MethodeID
|
|
WHERE nn.Nat_NormalValueNat_TestID = $natTestID
|
|
AND nn.Nat_NormalValueIsActive = 'Y'
|
|
AND nn.Nat_NormalValueIsAbnormal = 'N'
|
|
ORDER BY
|
|
CASE WHEN $m>0 AND nn.Nat_NormalValueNat_MethodeID=$m THEN 0 ELSE 1 END,
|
|
nn.Nat_NormalValueNat_MethodeID,
|
|
nn.Nat_NormalValueNat_NormalValueTypeID,
|
|
nn.Nat_NormalValueID";
|
|
|
|
$qry = $this->db->query($sql);
|
|
return $qry ? $qry->result_array() : [];
|
|
}
|
|
|
|
private function _chk($name, $ok, $value, $note)
|
|
{
|
|
return [
|
|
'check_name' => $name,
|
|
'check_status' => $ok ? 'OK' : 'MISSING',
|
|
'check_value' => $value,
|
|
'check_note' => $note,
|
|
];
|
|
}
|
|
|
|
private function _query_one($sql)
|
|
{
|
|
$qry = $this->db->query($sql);
|
|
if (!$qry) return 0;
|
|
$row = $qry->row_array();
|
|
return intval($row['Nat_NormalValueID'] ?? 0);
|
|
}
|
|
}
|