Files
BE_IBL/application/libraries/Ibl_sampling_normal.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);
}
}