update
This commit is contained in:
No files matched your search
@@ -605,13 +605,14 @@ class AstmMessageService
|
||||
{
|
||||
$normalizedData = str_replace(["\r\n", "\r"], "\n", $response);
|
||||
$segments = explode("\n", $normalizedData);
|
||||
|
||||
$patient_id = '';
|
||||
$patient_name = '';
|
||||
$accession_number = '';
|
||||
$waktu_periksa = date('d-m-Y H:i:s'); // Default jika tidak ada di ASTM
|
||||
|
||||
// Array untuk menyimpan data terstruktur
|
||||
$parsedResults = [];
|
||||
$hasil_list = []; // Tetap dipertahankan untuk kebutuhan legacy/summary
|
||||
$hasil_list = [];
|
||||
|
||||
foreach ($segments as $rsegmen) {
|
||||
$cekdata = explode('|', $rsegmen);
|
||||
@@ -619,32 +620,37 @@ class AstmMessageService
|
||||
|
||||
$recordType = preg_replace("/[^a-zA-Z]/", "", $cekdata[0]);
|
||||
|
||||
// 1. Parsing Pasien
|
||||
if ($recordType === 'P') {
|
||||
$patient_id = $cekdata[3] ?? ($cekdata[4] ?? '');
|
||||
if (isset($cekdata[5])) {
|
||||
$patient_name = trim(str_replace('^', ' ', $cekdata[5]));
|
||||
$patient_id = !empty($cekdata[3]) ? $cekdata[3] : (!empty($cekdata[4]) ? $cekdata[4] : '');
|
||||
|
||||
$raw_name = isset($cekdata[5]) ? trim(str_replace('^', ' ', $cekdata[5])) : '';
|
||||
$patient_name = !empty(trim($raw_name)) ? $raw_name : $patient_id;
|
||||
}
|
||||
|
||||
// 2. Parsing Accession Number
|
||||
if ($recordType === 'O') {
|
||||
$accession_number = !empty($cekdata[2]) ? $cekdata[2] : $accession_number;
|
||||
// Jika ada waktu di record O (index 6), kita bisa format (opsional)
|
||||
if (!empty($cekdata[6])) {
|
||||
$rawTime = preg_replace('/[^0-9]/', '', $cekdata[6]);
|
||||
if (strlen($rawTime) >= 14) {
|
||||
$waktu_periksa = date('d-m-Y H:i:s', strtotime(substr($rawTime, 0, 14)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($recordType === 'O') {
|
||||
$accession_number = $cekdata[2] ?? '';
|
||||
}
|
||||
|
||||
// 3. Parsing Data Result, Ct, dan EndPt
|
||||
if ($recordType === 'R') {
|
||||
if (isset($cekdata[2]) && isset($cekdata[3])) {
|
||||
$test_info_raw = $cekdata[2];
|
||||
$result_val = trim(str_replace('^', '', $cekdata[3]));
|
||||
|
||||
if ($result_val !== '') {
|
||||
// Pecah test info berdasarkan '^'
|
||||
$test_info = explode('^', $test_info_raw);
|
||||
|
||||
// Pada format GeneXpert: index ke-6 biasanya nama target (FII, FII 20210G, dll)
|
||||
// index ke-7 biasanya penanda tipe data (Ct, EndPt)
|
||||
$target_name = $test_info[6] ?? 'Unknown Target';
|
||||
$metric_type = $test_info[7] ?? 'Result'; // Jika tidak ada, berarti ini Result (POS/NEG)
|
||||
$target_name = !empty($test_info[6]) ? $test_info[6] : 'Unknown Target';
|
||||
$metric_type = (!empty($test_info[7])) ? $test_info[7] : 'Result';
|
||||
|
||||
// Inisialisasi array untuk target ini jika belum ada
|
||||
if (!isset($parsedResults[$target_name])) {
|
||||
$parsedResults[$target_name] = [
|
||||
'Result' => '-',
|
||||
@@ -653,12 +659,11 @@ class AstmMessageService
|
||||
];
|
||||
}
|
||||
|
||||
// Masukkan nilai ke dalam struktur data
|
||||
$parsedResults[$target_name][$metric_type] = $result_val;
|
||||
|
||||
// Untuk summary legacy (kolom organism/additional_result)
|
||||
if ($metric_type === 'Result') {
|
||||
$hasil_list[] = $target_name . ": " . $result_val;
|
||||
if ($metric_type === 'Result' && $result_val !== '') {
|
||||
// Simpan semua result ke dalam list untuk kesimpulan
|
||||
$hasil_list[$target_name] = "<strong>{$target_name}:</strong> {$result_val}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -670,19 +675,50 @@ class AstmMessageService
|
||||
return false;
|
||||
}
|
||||
|
||||
// Buat string kesimpulan DULUAN sebelum membuat HTML
|
||||
$kesimpulan_html = implode(" | ", array_values($hasil_list));
|
||||
$kesimpulan_db = strip_tags($kesimpulan_html); // Versi tanpa tag HTML untuk kolom DB
|
||||
$kesimpulan_safe = substr($kesimpulan_db, 0, 100);
|
||||
|
||||
// ====================================================================
|
||||
// MEMBUAT HTML REPORT & GRAFIK (CHART.JS)
|
||||
// ====================================================================
|
||||
|
||||
// 1. Buat Tabel HTML
|
||||
$reporthtml = '<div class="genexpert-report" style="font-family: Arial, sans-serif;">';
|
||||
$reporthtml .= '<h4 style="margin-bottom:10px;">GeneXpert Assay Result</h4>';
|
||||
$reporthtml .= '<table border="1" cellpadding="5" style="width: 100%; border-collapse: collapse; text-align: left; margin-bottom: 20px;">';
|
||||
$reporthtml .= '<tr style="background-color: #f4f4f4;">
|
||||
// Wrapper Utama
|
||||
$reporthtml = '<div class="genexpert-report" style="font-family: Arial, sans-serif; max-width: 900px; margin: auto; border: 1px solid #ddd; padding: 20px; border-radius: 8px;">';
|
||||
$reporthtml .= '<h3 style="text-align: center; margin-top: 0; color: #2c3e50;">Hasil Pemeriksaan GeneXpert</h3>';
|
||||
$reporthtml .= '<hr style="border: 0; border-top: 2px solid #3498db; margin-bottom: 20px;">';
|
||||
|
||||
// Bagian 1: Identitas Pasien (Grid Table)
|
||||
$reporthtml .= '<table style="width: 100%; margin-bottom: 20px; font-size: 14px; border: none;">';
|
||||
$reporthtml .= '<tr>';
|
||||
$reporthtml .= '<td style="width: 15%; padding: 4px 0;"><strong>No. Reg LIS</strong></td>';
|
||||
$reporthtml .= '<td style="width: 35%; padding: 4px 0;">: ' . htmlspecialchars($accession_number) . '</td>';
|
||||
$reporthtml .= '<td style="width: 15%; padding: 4px 0;"><strong>ID Pasien</strong></td>';
|
||||
$reporthtml .= '<td style="width: 35%; padding: 4px 0;">: ' . htmlspecialchars($patient_id) . '</td>';
|
||||
$reporthtml .= '</tr>';
|
||||
$reporthtml .= '<tr>';
|
||||
$reporthtml .= '<td style="padding: 4px 0;"><strong>Nama Pasien</strong></td>';
|
||||
$reporthtml .= '<td style="padding: 4px 0;">: ' . htmlspecialchars($patient_name) . '</td>';
|
||||
$reporthtml .= '<td style="padding: 4px 0;"><strong>Waktu Tes</strong></td>';
|
||||
$reporthtml .= '<td style="padding: 4px 0;">: ' . htmlspecialchars($waktu_periksa) . '</td>';
|
||||
$reporthtml .= '</tr>';
|
||||
$reporthtml .= '</table>';
|
||||
|
||||
// Bagian 2: Kesimpulan / Hasil Utama
|
||||
$reporthtml .= '<div style="background-color: #f8f9fa; padding: 15px; border-left: 5px solid #2ecc71; margin-bottom: 25px; border-radius: 4px;">';
|
||||
$reporthtml .= '<h4 style="margin: 0 0 10px 0; color: #2c3e50;">Kesimpulan Hasil:</h4>';
|
||||
$reporthtml .= '<p style="margin: 0; font-size: 14px; line-height: 1.6;">' . $kesimpulan_html . '</p>';
|
||||
$reporthtml .= '</div>';
|
||||
|
||||
// Bagian 3: Tabel Detail Analit
|
||||
$reporthtml .= '<h4 style="margin-bottom:10px; color: #2c3e50;">Detail Target / Analit</h4>';
|
||||
$reporthtml .= '<table border="1" cellpadding="8" style="width: 100%; border-collapse: collapse; text-align: left; margin-bottom: 25px; font-size: 13px;">';
|
||||
$reporthtml .= '<tr style="background-color: #ecf0f1; color: #2c3e50;">
|
||||
<th>Target/Analyte</th>
|
||||
<th>Result</th>
|
||||
<th>Ct Value</th>
|
||||
<th>EndPt</th>
|
||||
<th>End Point</th>
|
||||
</tr>';
|
||||
|
||||
$chartLabels = [];
|
||||
@@ -697,7 +733,6 @@ class AstmMessageService
|
||||
<td>{$data['EndPt']}</td>
|
||||
</tr>";
|
||||
|
||||
// Siapkan data untuk grafik (hanya ambil target yang memiliki nilai numerik Ct/EndPt)
|
||||
if (is_numeric($data['Ct']) || is_numeric($data['EndPt'])) {
|
||||
$chartLabels[] = $target;
|
||||
$chartCtData[] = is_numeric($data['Ct']) ? (float)$data['Ct'] : 0;
|
||||
@@ -706,27 +741,25 @@ class AstmMessageService
|
||||
}
|
||||
$reporthtml .= '</table>';
|
||||
|
||||
// 2. Buat Grafik menggunakan Chart.js (Inject Script)
|
||||
// Bagian 4: Grafik Chart.js
|
||||
if (!empty($chartLabels)) {
|
||||
$chartId = 'gxChart_' . preg_replace('/[^a-zA-Z0-9]/', '', $accession_number);
|
||||
$labelsJson = json_encode($chartLabels);
|
||||
$ctJson = json_encode($chartCtData);
|
||||
$endPtJson = json_encode($chartEndPtData);
|
||||
|
||||
// Tambahkan Canvas untuk grafik
|
||||
$reporthtml .= '<h4 style="margin-bottom:10px; color: #2c3e50; text-align: center;">Grafik Amplifikasi</h4>';
|
||||
$reporthtml .= '<div style="width: 100%; max-width: 800px; margin: auto;">';
|
||||
$reporthtml .= '<canvas id="'.$chartId.'"></canvas>';
|
||||
$reporthtml .= '</div>';
|
||||
|
||||
// Tambahkan script Chart.js (asumsi CDN) dan inisialisasi
|
||||
$reporthtml .= "
|
||||
<script src=\"https://cdn.jsdelivr.net/npm/chart.js\"></script>
|
||||
<script>
|
||||
// Gunakan DOMContentLoaded agar script jalan setelah HTML di-render di frontend
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var ctx = document.getElementById('{$chartId}').getContext('2d');
|
||||
new Chart(ctx, {
|
||||
type: 'bar', // Menggunakan kombinasi Bar & Line chart
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: {$labelsJson},
|
||||
datasets: [
|
||||
@@ -745,6 +778,7 @@ class AstmMessageService
|
||||
borderColor: 'rgba(255, 99, 132, 1)',
|
||||
backgroundColor: 'rgba(255, 99, 132, 0.2)',
|
||||
borderWidth: 2,
|
||||
tension: 0.1,
|
||||
yAxisID: 'y1'
|
||||
}
|
||||
]
|
||||
@@ -762,8 +796,8 @@ class AstmMessageService
|
||||
type: 'linear',
|
||||
display: true,
|
||||
position: 'right',
|
||||
title: { display: true, text: 'EndPt' },
|
||||
grid: { drawOnChartArea: false } // Agar garis grid tidak bertumpuk
|
||||
title: { display: true, text: 'End Point' },
|
||||
grid: { drawOnChartArea: false }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -772,15 +806,12 @@ class AstmMessageService
|
||||
</script>
|
||||
";
|
||||
}
|
||||
$reporthtml .= '</div>';
|
||||
$reporthtml .= '</div>'; // End of Wrapper Utama
|
||||
|
||||
// ====================================================================
|
||||
// SIMPAN KE DATABASE
|
||||
// ====================================================================
|
||||
|
||||
$kesimpulan = implode(" | ", $hasil_list);
|
||||
$kesimpulan_safe = substr($kesimpulan, 0, 100);
|
||||
|
||||
try {
|
||||
Periksa::where('nofoto', $accession_number)
|
||||
->whereNotIn('status', ['Selesai', 'Arsip', 'Dibatalkan (Arsip)', 'Batal'])
|
||||
@@ -788,7 +819,6 @@ class AstmMessageService
|
||||
'status' => 'Data GeneXpert di Terima'
|
||||
]);
|
||||
|
||||
|
||||
Riwayat::create([
|
||||
'nofoto' => $accession_number,
|
||||
'jawaban' => $reporthtml,
|
||||
@@ -797,15 +827,14 @@ class AstmMessageService
|
||||
'verifikasi' => '',
|
||||
]);
|
||||
|
||||
$resultSample = ResultSample::firstOrNew(['accession_number' => $accession_number]);
|
||||
$resultSample->sender_name = $alat;
|
||||
$resultSample->patient_id = substr($patient_id, 0, 50);
|
||||
$resultSample->patient_name_first = substr($patient_name, 0, 100);
|
||||
$resultSample->organism = $kesimpulan_safe; // Tetap menyimpan text summary
|
||||
$resultSample->additional_result = json_encode($parsedResults); // Menyimpan JSON utuh agar lebih informatif
|
||||
$resultSample->message_datetime = date('Y-m-d H:i:s');
|
||||
$resultSample = ResultSample::firstOrNew(['accession_number' => $accession_number]);
|
||||
$resultSample->sender_name = $alat;
|
||||
$resultSample->patient_id = substr($patient_id, 0, 50);
|
||||
$resultSample->patient_name_first = substr($patient_name, 0, 100);
|
||||
$resultSample->organism = $kesimpulan_safe; // Disimpan versi plain text
|
||||
$resultSample->additional_result = json_encode($parsedResults);
|
||||
$resultSample->message_datetime = date('Y-m-d H:i:s');
|
||||
$resultSample->save();
|
||||
Log::info("GeneXpert Result Disimpan", ["NoReg" => $accession_number, "Hasil" => $kesimpulan_safe]);
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
Log::error("GeneXpert DB Save Error: " . $e->getMessage());
|
||||
|
||||
Reference in New Issue
Block a user