Files
BE_CPONE/application/libraries/Promise.php
2026-04-27 10:26:26 +07:00

441 lines
18 KiB
PHP

<?php
defined("BASEPATH") or exit("No direct script access allowed");
class Promise
{
function __construct()
{
$CI = &get_instance();
$this->db_smartone = $CI->load->database("default", true);
}
function get_schedule_results_grouped($test_ids, $x_datetime, $branch_id, $order_id = null)
{
// Validasi input
if (empty($test_ids) || empty($x_datetime) || empty($branch_id)) {
return array("status" => "ERR", "message" => "Parameter tidak lengkap", "data" => array());
}
// Konversi test_ids ke array integer
if (is_array($test_ids)) {
$test_ids_array = array_map('intval', $test_ids);
} else {
$test_ids_array = array_filter(array_map('intval', array_map('trim', explode(",", $test_ids))));
}
if (empty($test_ids_array)) {
return array("status" => "ERR", "message" => "Test IDs tidak valid", "data" => array());
}
$branch_id_escaped = intval($branch_id);
$test_ids_in = implode(",", $test_ids_array);
// Pre-calculate untuk optimasi
$x_datetime_ts = strtotime($x_datetime);
$time_str = date('H:i', $x_datetime_ts);
$date_str = date('Y-m-d', $x_datetime_ts);
$day_of_week = date('w', $x_datetime_ts); // 0=Sunday, 6=Saturday
$mysql_day_of_week = ($day_of_week == 0) ? 1 : $day_of_week + 1;
// ============================================
// STEP 1: Ambil data test (query sederhana)
// ============================================
$sql = "SELECT
T_TestID,
T_TestName,
T_TestSasCode,
T_TestParentT_TestID,
T_TestNat_TestID,
T_TestIsResult
FROM t_test
WHERE T_TestID IN ({$test_ids_in})
AND T_TestIsActive = 'Y'";
$query = $this->db_smartone->query($sql);
if (!$query) {
return array("status" => "ERR", "message" => "Gagal ambil data test", "data" => array());
}
$tests = $query->result_array();
$test_list = array();
$parent_test_ids = array();
$sas_codes = array();
// Proses test: pisahkan yang result dan yang parent
foreach ($tests as $test) {
if ($test['T_TestIsResult'] == 'Y') {
$test_list[$test['T_TestID']] = $test;
} else {
$parent_test_ids[] = $test['T_TestID'];
$sas_codes[] = $this->db_smartone->escape($test['T_TestSasCode']);
}
}
// Ambil child test dari parent (jika ada)
if (!empty($sas_codes)) {
$sql_parts = array();
foreach ($sas_codes as $sas_code) {
$sql_parts[] = "T_TestSasCode LIKE CONCAT({$sas_code}, '%')";
}
$sql = "SELECT
T_TestID,
T_TestName,
T_TestSasCode,
T_TestParentT_TestID,
T_TestNat_TestID,
T_TestIsResult
FROM t_test
WHERE (" . implode(" OR ", $sql_parts) . ")
AND T_TestIsActive = 'Y'
AND T_TestIsResult = 'Y'";
$query = $this->db_smartone->query($sql);
if ($query) {
$child_tests = $query->result_array();
foreach ($child_tests as $child) {
$test_list[$child['T_TestID']] = $child;
}
}
}
if (empty($test_list)) {
return array("status" => "OK", "message" => "No test found", "data" => array());
}
// ============================================
// STEP 1.5: Ambil T_OrderDetailID jika order_id diberikan (setelah child test ditambahkan)
// ============================================
$order_detail_map = array(); // [test_id => order_detail_id]
if (!empty($order_id)) {
$order_id_escaped = intval($order_id);
// Ambil semua test_ids dari test_list (termasuk child yang baru ditambahkan)
$all_test_ids = array_keys($test_list);
$all_test_ids_in = implode(",", array_map('intval', $all_test_ids));
$sql = "SELECT
T_OrderDetailID,
T_OrderDetailT_TestID AS T_TestID
FROM t_orderdetail
WHERE T_OrderDetailT_OrderHeaderID = {$order_id_escaped}
AND T_OrderDetailT_TestID IN ({$all_test_ids_in})
AND T_OrderDetailIsActive = 'Y'";
$query = $this->db_smartone->query($sql);
if ($query) {
$order_details = $query->result_array();
foreach ($order_details as $od) {
$order_detail_map[$od['T_TestID']] = $od['T_OrderDetailID'];
}
}
}
// ============================================
// STEP 2: Ambil schedule untuk semua test (query sederhana)
// ============================================
$nat_test_ids = array_unique(array_column($test_list, 'T_TestNat_TestID'));
$nat_test_ids_in = implode(",", array_map('intval', $nat_test_ids));
$sql = "SELECT
s.M_ScheduleID,
s.M_ScheduleFlagAtTime,
s.M_ScheduleAtTime,
s.M_ScheduleMinute,
s.M_ScheduleMonth,
s.M_ScheduleWeek,
s.M_ScheduleDay,
s.M_ScheduleHour,
s.M_ScheduleStartHourMinute,
s.M_ScheduleEndHourMinute,
sgt.M_ScheduleGroupTestNat_TestID AS Nat_TestID
FROM m_schedule s
INNER JOIN m_schedulegroup sg ON s.M_ScheduleM_ScheduleGroupID = sg.M_ScheduleGroupID
INNER JOIN m_schedulegrouptest sgt ON sg.M_ScheduleGroupID = sgt.M_ScheduleGroupTestM_ScheduleGroupID
WHERE s.M_ScheduleIsActive = 'Y'
AND sg.M_ScheduleGroupIsActive = 'Y'
AND sgt.M_ScheduleGroupTestIsActive = 'Y'
AND sg.M_ScheduleGroupM_BranchID = {$branch_id_escaped}
AND s.M_ScheduleDayOfWeek = {$mysql_day_of_week}
AND sgt.M_ScheduleGroupTestNat_TestID IN ({$nat_test_ids_in})
AND '{$time_str}' >= s.M_ScheduleStartHourMinute
AND '{$time_str}' <= s.M_ScheduleEndHourMinute";
$query = $this->db_smartone->query($sql);
if (!$query) {
return array("status" => "ERR", "message" => "Gagal ambil schedule", "data" => array());
}
$schedules = $query->result_array();
//$this->order_debug('get_schedule_results_grouped/get_schedule', $this->db_smartone->last_query(), $schedules, "Ambil schedule untuk semua test");
// ============================================
// STEP 3: Proses di PHP - hitung janji hasil untuk setiap test
// ============================================
$test_schedules = array(); // [test_id => [schedule1, schedule2, ...]]
foreach ($test_list as $test_id => $test) {
$test_schedules[$test_id] = array();
// Cari schedule untuk test ini
foreach ($schedules as $schedule) {
if ($schedule['Nat_TestID'] == $test['T_TestNat_TestID']) {
// Hitung janji hasil
if ($schedule['M_ScheduleFlagAtTime'] == 'Y') {
$janji_hasil = $date_str . ' ' . $schedule['M_ScheduleAtTime'] . ':00';
} else {
$janji_hasil_ts = $this->calculate_janji_hasil_ts($x_datetime_ts, $schedule);
$janji_hasil = date('Y-m-d H:i:s', $janji_hasil_ts);
$data_debug = array(
'test_id' => $test_id,
'test_name' => $test['T_TestName'],
'test_nat_test_id' => $test['T_TestNat_TestID'],
'schedule_id' => $schedule['M_ScheduleID'],
'schedule_flag_at_time' => $schedule['M_ScheduleFlagAtTime'],
'schedule_at_time' => $schedule['M_ScheduleAtTime'],
'schedule_month' => $schedule['M_ScheduleMonth'],
'schedule_week' => $schedule['M_ScheduleWeek'],
'schedule_day' => $schedule['M_ScheduleDay'],
'schedule_hour' => $schedule['M_ScheduleHour'],
'schedule_minute' => $schedule['M_ScheduleMinute'],
'schedule_start_hour_minute' => $schedule['M_ScheduleStartHourMinute'],
'schedule_end_hour_minute' => $schedule['M_ScheduleEndHourMinute']
);
//$this->order_debug('get_schedule_results_grouped/loop_schedule', '', $data_debug, "check schedule for test_id: $test_id");
}
// Convert day, hour, minute to total minutes
$tat_menit = ($schedule['M_ScheduleDay'] * 24 * 60) + ($schedule['M_ScheduleHour'] * 60) + $schedule['M_ScheduleMinute'];
$test_schedules[$test_id][] = array(
'ScheduleID' => $schedule['M_ScheduleID'],
'JanjiHasil' => $janji_hasil,
'JanjiHasil_TS' => strtotime($janji_hasil),
'M_ScheduleFlagAtTime' => $schedule['M_ScheduleFlagAtTime'],
'M_ScheduleAtTime' => $schedule['M_ScheduleAtTime'],
'TAT_Menit' => $tat_menit,
'M_ScheduleStartHourMinute' => $schedule['M_ScheduleStartHourMinute'],
'M_ScheduleEndHourMinute' => $schedule['M_ScheduleEndHourMinute']
);
}
}
// Jika tidak ada schedule langsung, cari dari parent atau sibling
if (empty($test_schedules[$test_id]) && !empty($test['T_TestParentT_TestID'])) {
$parent_id = $test['T_TestParentT_TestID'];
// Cari schedule dari parent
foreach ($schedules as $schedule) {
// Cek apakah ada test parent dengan nat_test_id yang sama
foreach ($tests as $parent_test) {
if ($parent_test['T_TestID'] == $parent_id &&
$parent_test['T_TestNat_TestID'] == $schedule['Nat_TestID']) {
// Hitung janji hasil
if ($schedule['M_ScheduleFlagAtTime'] == 'Y') {
$janji_hasil = $date_str . ' ' . $schedule['M_ScheduleAtTime'] . ':00';
} else {
$janji_hasil_ts = $this->calculate_janji_hasil_ts($x_datetime_ts, $schedule);
$janji_hasil = date('Y-m-d H:i:s', $janji_hasil_ts);
}
// Convert day, hour, minute to total minutes
$tat_menit = ($schedule['M_ScheduleDay'] * 24 * 60) + ($schedule['M_ScheduleHour'] * 60) + $schedule['M_ScheduleMinute'];
$test_schedules[$test_id][] = array(
'ScheduleID' => $schedule['M_ScheduleID'],
'JanjiHasil' => $janji_hasil,
'JanjiHasil_TS' => strtotime($janji_hasil),
'M_ScheduleFlagAtTime' => $schedule['M_ScheduleFlagAtTime'],
'M_ScheduleAtTime' => $schedule['M_ScheduleAtTime'],
'TAT_Menit' => $tat_menit,
'M_ScheduleStartHourMinute' => $schedule['M_ScheduleStartHourMinute'],
'M_ScheduleEndHourMinute' => $schedule['M_ScheduleEndHourMinute']
);
break 2; // Break dari kedua loop
}
}
}
// Jika masih tidak ada, cari dari sibling (test lain dengan parent yang sama)
if (empty($test_schedules[$test_id])) {
foreach ($test_list as $sibling_id => $sibling_test) {
if ($sibling_id != $test_id &&
$sibling_test['T_TestParentT_TestID'] == $parent_id) {
// Cari schedule sibling
foreach ($schedules as $schedule) {
if ($sibling_test['T_TestNat_TestID'] == $schedule['Nat_TestID']) {
if ($schedule['M_ScheduleFlagAtTime'] == 'Y') {
$janji_hasil = $date_str . ' ' . $schedule['M_ScheduleAtTime'] . ':00';
} else {
$janji_hasil_ts = $this->calculate_janji_hasil_ts($x_datetime_ts, $schedule);
$janji_hasil = date('Y-m-d H:i:s', $janji_hasil_ts);
}
// Convert day, hour, minute to total minutes
$tat_menit = ($schedule['M_ScheduleDay'] * 24 * 60) + ($schedule['M_ScheduleHour'] * 60) + $schedule['M_ScheduleMinute'];
$test_schedules[$test_id][] = array(
'ScheduleID' => $schedule['M_ScheduleID'],
'JanjiHasil' => $janji_hasil,
'JanjiHasil_TS' => strtotime($janji_hasil),
'M_ScheduleFlagAtTime' => $schedule['M_ScheduleFlagAtTime'],
'M_ScheduleAtTime' => $schedule['M_ScheduleAtTime'],
'TAT_Menit' => $tat_menit,
'M_ScheduleStartHourMinute' => $schedule['M_ScheduleStartHourMinute'],
'M_ScheduleEndHourMinute' => $schedule['M_ScheduleEndHourMinute']
);
break 2;
}
}
}
}
}
// Jika masih tidak ada, default +24 jam
if (empty($test_schedules[$test_id])) {
$janji_hasil_ts = $x_datetime_ts + (24 * 3600);
$test_schedules[$test_id][] = array(
'ScheduleID' => null,
'JanjiHasil' => date('Y-m-d H:i:s', $janji_hasil_ts),
'JanjiHasil_TS' => $janji_hasil_ts,
'M_ScheduleFlagAtTime' => null,
'M_ScheduleAtTime' => null,
'TAT_Menit' => null,
'M_ScheduleStartHourMinute' => null,
'M_ScheduleEndHourMinute' => null
);
}
} elseif (empty($test_schedules[$test_id])) {
// Default +24 jam jika tidak ada schedule
$janji_hasil_ts = $x_datetime_ts + (24 * 3600);
$test_schedules[$test_id][] = array(
'ScheduleID' => null,
'JanjiHasil' => date('Y-m-d H:i:s', $janji_hasil_ts),
'JanjiHasil_TS' => $janji_hasil_ts,
'M_ScheduleFlagAtTime' => null,
'M_ScheduleAtTime' => null,
'TAT_Menit' => null,
'M_ScheduleStartHourMinute' => null,
'M_ScheduleEndHourMinute' => null
);
}
// Ambil schedule dengan janji hasil terbesar (ranking di PHP)
usort($test_schedules[$test_id], function($a, $b) {
return $b['JanjiHasil_TS'] - $a['JanjiHasil_TS'];
});
}
// ============================================
// STEP 4: Grouping berdasarkan tanggal dan jam (di PHP)
// ============================================
$grouped = array(); // [group_key => [tests]]
foreach ($test_schedules as $test_id => $schedules) {
$best_schedule = $schedules[0]; // Sudah di-sort, ambil yang terbesar
$test = $test_list[$test_id];
// Group key: tanggal + jam (tanpa detik)
$janji_ts = $best_schedule['JanjiHasil_TS'];
$group_key = date('Y-m-d H:i', $janji_ts);
if (!isset($grouped[$group_key])) {
$grouped[$group_key] = array(
'JanjiHasil' => $best_schedule['JanjiHasil'],
'JanjiHasil_Tanggal' => date('Y-m-d', $janji_ts),
'JanjiHasil_Waktu' => date('H:i:s', $janji_ts),
'TestIDs' => array(),
'TestNames' => array(),
'OrderDetailIDs' => array(), // Tambahkan untuk optimasi insert
'ScheduleID' => $best_schedule['ScheduleID'],
'M_ScheduleFlagAtTime' => $best_schedule['M_ScheduleFlagAtTime'],
'M_ScheduleAtTime' => $best_schedule['M_ScheduleAtTime'],
'TAT_Menit' => $best_schedule['TAT_Menit'],
'M_ScheduleStartHourMinute' => $best_schedule['M_ScheduleStartHourMinute'],
'M_ScheduleEndHourMinute' => $best_schedule['M_ScheduleEndHourMinute']
);
}
$grouped[$group_key]['TestIDs'][] = $test_id;
$grouped[$group_key]['TestNames'][] = $test['T_TestName'];
// Tambahkan OrderDetailID jika ada
if (!empty($order_detail_map[$test_id])) {
$grouped[$group_key]['OrderDetailIDs'][] = $order_detail_map[$test_id];
}
}
// ============================================
// STEP 5: Format hasil akhir
// ============================================
$results = array();
foreach ($grouped as $group) {
$results[] = array(
'JanjiHasil_Tanggal' => $group['JanjiHasil_Tanggal'],
'JanjiHasil_Waktu' => $group['JanjiHasil_Waktu'],
'JanjiHasil' => $group['JanjiHasil'],
'TestIDs' => implode(',', $group['TestIDs']),
'TestNames' => implode(', ', $group['TestNames']),
'OrderDetailIDs' => !empty($group['OrderDetailIDs']) ? implode(',', $group['OrderDetailIDs']) : null, // Tambahkan OrderDetailIDs
'ScheduleID' => $group['ScheduleID'],
'M_ScheduleFlagAtTime' => $group['M_ScheduleFlagAtTime'],
'M_ScheduleAtTime' => $group['M_ScheduleAtTime'],
'TAT_Menit' => $group['TAT_Menit'],
'M_ScheduleStartHourMinute' => $group['M_ScheduleStartHourMinute'],
'M_ScheduleEndHourMinute' => $group['M_ScheduleEndHourMinute']
);
}
// Sort by tanggal dan waktu
usort($results, function($a, $b) {
$ts_a = strtotime($a['JanjiHasil']);
$ts_b = strtotime($b['JanjiHasil']);
return $ts_a - $ts_b;
});
return $results;
}
/**
* Helper function untuk menghitung janji_hasil_ts berdasarkan schedule
* Memperhitungkan M_ScheduleMonth, M_ScheduleWeek, M_ScheduleDay, M_ScheduleHour, dan M_ScheduleMinute
*
* @param int $base_ts - Base timestamp
* @param array $schedule - Array schedule data
* @return int - Timestamp hasil perhitungan
*/
private function calculate_janji_hasil_ts($base_ts, $schedule)
{
$dt = new DateTime();
$dt->setTimestamp($base_ts);
// Tambahkan M_ScheduleMonth (jika ada)
if (!empty($schedule['M_ScheduleMonth']) && $schedule['M_ScheduleMonth'] > 0) {
$dt->modify('+' . intval($schedule['M_ScheduleMonth']) . ' months');
}
// Tambahkan M_ScheduleWeek (jika ada)
if (!empty($schedule['M_ScheduleWeek']) && $schedule['M_ScheduleWeek'] > 0) {
$dt->modify('+' . intval($schedule['M_ScheduleWeek']) . ' weeks');
}
// Tambahkan M_ScheduleDay (jika ada)
if (!empty($schedule['M_ScheduleDay']) && $schedule['M_ScheduleDay'] > 0) {
$dt->modify('+' . intval($schedule['M_ScheduleDay']) . ' days');
}
// Tambahkan M_ScheduleHour (jika ada)
if (!empty($schedule['M_ScheduleHour']) && $schedule['M_ScheduleHour'] > 0) {
$dt->modify('+' . intval($schedule['M_ScheduleHour']) . ' hours');
}
// Tambahkan M_ScheduleMinute (jika ada)
if (!empty($schedule['M_ScheduleMinute']) && $schedule['M_ScheduleMinute'] > 0) {
$dt->modify('+' . intval($schedule['M_ScheduleMinute']) . ' minutes');
}
return $dt->getTimestamp();
}
}