Split glass report into three tables
This commit is contained in:
@@ -549,6 +549,298 @@ class ReportController extends Controller
|
||||
->pluck('rekapantibiotik.antibiotic')
|
||||
->toArray();
|
||||
}
|
||||
private function getGlassReportHeaders() {
|
||||
$tableC = [
|
||||
'ID Rumah Sakit',
|
||||
'Nama Pasien',
|
||||
'No Rekam Medis',
|
||||
'Jenis Kelamin',
|
||||
'Tanggal Lahir',
|
||||
'Usia',
|
||||
'Ruang Rawat',
|
||||
'Tanggal Pasien Masuk',
|
||||
'Tanggal Pengambilan Spesimen',
|
||||
'Specimen Origin',
|
||||
'Jenis Spesimen',
|
||||
];
|
||||
|
||||
$tableAAntibiotics = [
|
||||
'Cefoxitin',
|
||||
'Oxacillin',
|
||||
'Penicillin',
|
||||
'Ampicillin',
|
||||
'Amoxicillin',
|
||||
'Cefazolin',
|
||||
'Cefuroxime',
|
||||
'Cefixime',
|
||||
'Cefotaxime',
|
||||
'Ceftriaxone',
|
||||
'Ceftazidime',
|
||||
'Cefepime',
|
||||
'Ceftaroline',
|
||||
'Ertapenem',
|
||||
'Imipenem',
|
||||
'Meropenem',
|
||||
'Aztreonam',
|
||||
'Amoxicillin-clavulanate',
|
||||
'Ampicillin-sulbactam',
|
||||
'Piperacillin-tazobactam',
|
||||
'Ceftazidime-avibactam',
|
||||
'Gentamicin',
|
||||
'Amikacin',
|
||||
'Ciprofloxacin',
|
||||
'Levofloxacin',
|
||||
'Moxifloxacin',
|
||||
'Trimethoprim-sulfamethoxazole',
|
||||
'Azithromycin',
|
||||
'Clarithromycin',
|
||||
'Erythromycin',
|
||||
'Clindamycin',
|
||||
'Tetracycline',
|
||||
'Minocycline',
|
||||
'Doxycycline',
|
||||
'Colistin',
|
||||
'Vancomycin',
|
||||
'Linezolid',
|
||||
'Tigecycline',
|
||||
'Daptomycin',
|
||||
'Nitrofurantoin',
|
||||
'Fosfomycin',
|
||||
];
|
||||
|
||||
$tableBAntibiotics = [
|
||||
'Fluconazole',
|
||||
'Voriconazole',
|
||||
'Amphotericin B',
|
||||
'Micafungin',
|
||||
'Caspofungin',
|
||||
'Flucytosine',
|
||||
];
|
||||
|
||||
return [
|
||||
'A' => array_merge($tableC, ['Nama Spesies Bakteri', 'ESBL', 'MRSA'], $tableAAntibiotics),
|
||||
'B' => array_merge($tableC, ['Nama Spesies Jamur'], $tableBAntibiotics),
|
||||
'C' => $tableC,
|
||||
'A_antibiotics' => $tableAAntibiotics,
|
||||
'B_antibiotics' => $tableBAntibiotics,
|
||||
];
|
||||
}
|
||||
private function getGlassReportAntibioticAliases() {
|
||||
return [
|
||||
'Cefoxitin' => ['cefoxitin', 'cefoxitinscreen'],
|
||||
'Oxacillin' => ['oxacillin'],
|
||||
'Penicillin' => ['penicillin', 'benzylpenicillin'],
|
||||
'Ampicillin' => ['ampicillin'],
|
||||
'Amoxicillin' => ['amoxicillin'],
|
||||
'Cefazolin' => ['cefazolin', 'cefazolinurine', 'cefazolinother'],
|
||||
'Cefuroxime' => ['cefuroxime', 'cefuroximeiv', 'cefuroximeoral'],
|
||||
'Cefixime' => ['cefixime'],
|
||||
'Cefotaxime' => ['cefotaxime'],
|
||||
'Ceftriaxone' => ['ceftriaxone'],
|
||||
'Ceftazidime' => ['ceftazidime'],
|
||||
'Cefepime' => ['cefepime'],
|
||||
'Ceftaroline' => ['ceftaroline'],
|
||||
'Ertapenem' => ['ertapenem'],
|
||||
'Imipenem' => ['imipenem'],
|
||||
'Meropenem' => ['meropenem'],
|
||||
'Aztreonam' => ['aztreonam'],
|
||||
'Amoxicillin-clavulanate' => ['amoxicillinclavulanate', 'amoxicillinclavulanicacid'],
|
||||
'Ampicillin-sulbactam' => ['ampicillinsulbactam'],
|
||||
'Piperacillin-tazobactam' => ['piperacillintazobactam'],
|
||||
'Ceftazidime-avibactam' => ['ceftazidimeavibactam'],
|
||||
'Gentamicin' => ['gentamicin'],
|
||||
'Amikacin' => ['amikacin'],
|
||||
'Ciprofloxacin' => ['ciprofloxacin'],
|
||||
'Levofloxacin' => ['levofloxacin'],
|
||||
'Moxifloxacin' => ['moxifloxacin'],
|
||||
'Trimethoprim-sulfamethoxazole' => ['trimethoprimsulfamethoxazole', 'trimetrophimesulfamethoxazole'],
|
||||
'Azithromycin' => ['azithromycin'],
|
||||
'Clarithromycin' => ['clarithromycin'],
|
||||
'Erythromycin' => ['erythromycin'],
|
||||
'Clindamycin' => ['clindamycin'],
|
||||
'Tetracycline' => ['tetracycline', 'tetracyclinescreenonly', 'tetracyclineu'],
|
||||
'Minocycline' => ['minocycline'],
|
||||
'Doxycycline' => ['doxycycline'],
|
||||
'Colistin' => ['colistin'],
|
||||
'Vancomycin' => ['vancomycin'],
|
||||
'Linezolid' => ['linezolid'],
|
||||
'Tigecycline' => ['tigecycline'],
|
||||
'Daptomycin' => ['daptomycin'],
|
||||
'Nitrofurantoin' => ['nitrofurantoin'],
|
||||
'Fosfomycin' => ['fosfomycin'],
|
||||
'Fluconazole' => ['fluconazole'],
|
||||
'Voriconazole' => ['voriconazole'],
|
||||
'Amphotericin B' => ['amphotericinb'],
|
||||
'Micafungin' => ['micafungin'],
|
||||
'Caspofungin' => ['caspofungin'],
|
||||
'Flucytosine' => ['flucytosine'],
|
||||
];
|
||||
}
|
||||
private function normalizeGlassReportValue($value) {
|
||||
return preg_replace('/[^a-z0-9]+/', '', strtolower(strip_tags((string) $value)));
|
||||
}
|
||||
private function pickGlassReportResistanceValue($row, $header) {
|
||||
$rawResistance = $row->resistence ?? $row->resistance ?? null;
|
||||
$rawInterpretation = $row->interpretation ?? null;
|
||||
$resistance = trim((string) $rawResistance);
|
||||
$interpretation = trim((string) $rawInterpretation);
|
||||
|
||||
if ($resistance === '') {
|
||||
return $interpretation;
|
||||
}
|
||||
|
||||
$normalizedResistance = $this->normalizeGlassReportValue($resistance);
|
||||
$normalizedAntibiotic = $this->normalizeGlassReportValue($row->antibiotic ?? '');
|
||||
$normalizedHeader = $this->normalizeGlassReportValue($header);
|
||||
|
||||
if ($normalizedResistance === $normalizedAntibiotic || $normalizedResistance === $normalizedHeader) {
|
||||
return $interpretation;
|
||||
}
|
||||
|
||||
return $resistance;
|
||||
}
|
||||
private function getGlassReportOrigin($row) {
|
||||
if (empty($row->daftar) || empty($row->mulai)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
try {
|
||||
$selisihHari = Carbon::parse($row->daftar)->diffInDays(Carbon::parse($row->mulai));
|
||||
return $selisihHari >= 3 ? 'Hospital Origin' : 'Community Origin';
|
||||
} catch (\Throwable $e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
private function buildGlassReportBaseRow($row) {
|
||||
$jenisSpesimen = trim(implode(' ', array_filter([
|
||||
$row->kd_spesimen ?? '',
|
||||
$row->nm_spesimen ?? '',
|
||||
])));
|
||||
|
||||
return [
|
||||
$row->nmrs ?? '',
|
||||
$row->nmpasien ?? '',
|
||||
$row->noregister ?? '',
|
||||
$row->jkpasien ?? '',
|
||||
$row->tgllahirpasien ?? '',
|
||||
$row->usia ?? '',
|
||||
$row->asalpasien ?? '',
|
||||
$row->daftar ?? '',
|
||||
$row->mulai ?? '',
|
||||
$this->getGlassReportOrigin($row),
|
||||
$jenisSpesimen,
|
||||
];
|
||||
}
|
||||
private function getGlassReportLookups($rows) {
|
||||
$orderIds = $rows->pluck('id')->filter()->values()->all();
|
||||
$accnumbers = $rows->pluck('nofoto')->filter()->values()->all();
|
||||
|
||||
$komponen = DB::table('db_komponenjawaban')
|
||||
->select('accnumber', 'komponen', 'isidata')
|
||||
->whereIn('accnumber', $accnumbers)
|
||||
->whereIn('komponen', ['bakteri', 'id_bakteri01', 'id_bakteri02', 'id_mikroorganisme'])
|
||||
->whereNotNull('isidata')
|
||||
->where('isidata', '!=', '')
|
||||
->get()
|
||||
->groupBy('accnumber');
|
||||
|
||||
$antibiotik = RekapAntibiotik::query()
|
||||
->whereIn('orderid', $orderIds)
|
||||
->get(['orderid', 'antibiotic', 'resistance', 'interpretation'])
|
||||
->groupBy('orderid');
|
||||
|
||||
return [
|
||||
'komponen' => $komponen,
|
||||
'antibiotik' => $antibiotik,
|
||||
];
|
||||
}
|
||||
private function splitGlassReportRows($rows, $lookups) {
|
||||
$headers = $this->getGlassReportHeaders();
|
||||
$aliases = $this->getGlassReportAntibioticAliases();
|
||||
$tables = ['A' => [], 'B' => [], 'C' => []];
|
||||
|
||||
foreach ($rows as $row) {
|
||||
$baseRow = $this->buildGlassReportBaseRow($row);
|
||||
$komponenRows = $lookups['komponen'][$row->nofoto] ?? collect([]);
|
||||
$antibioticRows = $lookups['antibiotik'][$row->id] ?? collect([]);
|
||||
|
||||
$bacterialName = '';
|
||||
$fungalName = '';
|
||||
$foundMorphology = false;
|
||||
|
||||
foreach ($komponenRows as $komponenRow) {
|
||||
$value = trim(strip_tags((string) $komponenRow->isidata));
|
||||
if ($value === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stripos($value, 'Ditemukan morfologi') !== false) {
|
||||
$foundMorphology = true;
|
||||
}
|
||||
|
||||
if (in_array($komponenRow->komponen, ['bakteri', 'id_bakteri01', 'id_bakteri02'], true) && $bacterialName === '' && stripos($value, 'Ditemukan morfologi') === false) {
|
||||
$bacterialName = $value;
|
||||
}
|
||||
|
||||
if ($komponenRow->komponen === 'id_mikroorganisme' && $fungalName === '') {
|
||||
$fungalName = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$antibioticValues = [];
|
||||
foreach ($antibioticRows as $antibioticRow) {
|
||||
$matchedHeader = null;
|
||||
$normalizedAntibiotic = $this->normalizeGlassReportValue($antibioticRow->antibiotic ?? '');
|
||||
$normalizedResistance = $this->normalizeGlassReportValue($antibioticRow->resistance ?? '');
|
||||
|
||||
foreach ($aliases as $header => $variants) {
|
||||
if (in_array($normalizedAntibiotic, $variants, true) || in_array($normalizedResistance, $variants, true)) {
|
||||
$matchedHeader = $header;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($matchedHeader === null || isset($antibioticValues[$matchedHeader])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$antibioticValues[$matchedHeader] = $this->pickGlassReportResistanceValue($antibioticRow, $matchedHeader);
|
||||
}
|
||||
|
||||
$hasJenisSpesimen = trim((string) ($baseRow[10] ?? '')) !== '';
|
||||
if ($bacterialName !== '' && $hasJenisSpesimen) {
|
||||
$tableRow = array_merge($baseRow, [
|
||||
$bacterialName,
|
||||
$row->id_esbl ?? '',
|
||||
$row->id_mrsa ?? '',
|
||||
]);
|
||||
|
||||
foreach ($headers['A_antibiotics'] as $antibioticHeader) {
|
||||
$tableRow[] = $antibioticValues[$antibioticHeader] ?? '';
|
||||
}
|
||||
|
||||
$tables['A'][] = $tableRow;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($foundMorphology || $fungalName !== '') {
|
||||
$tableRow = array_merge($baseRow, [
|
||||
$fungalName !== '' ? $fungalName : 'Ditemukan morfologi',
|
||||
]);
|
||||
|
||||
foreach ($headers['B_antibiotics'] as $antibioticHeader) {
|
||||
$tableRow[] = $antibioticValues[$antibioticHeader] ?? '';
|
||||
}
|
||||
|
||||
$tables['B'][] = $tableRow;
|
||||
continue;
|
||||
}
|
||||
|
||||
$tables['C'][] = $baseRow;
|
||||
}
|
||||
|
||||
return $tables;
|
||||
}
|
||||
public function genGlassReport(Request $request) {
|
||||
$bulan = $request->input('bulan');
|
||||
$tahun = $request->input('tahun');
|
||||
@@ -574,11 +866,16 @@ class ReportController extends Controller
|
||||
// 2. Ambil Data Antibiotik HANYA untuk 50 pasien tersebut
|
||||
$pageIds = $orderbydate->pluck('id')->toArray();
|
||||
$antibiotikLookup = $this->mapAntibiotikData($pageIds);
|
||||
$glassLookups = $this->getGlassReportLookups($orderbydate->getCollection());
|
||||
$glassTables = $this->splitGlassReportRows($orderbydate->getCollection(), $glassLookups);
|
||||
$glassHeaders = $this->getGlassReportHeaders();
|
||||
|
||||
return view('admin.glassreport', [
|
||||
'orderbydate' => $orderbydate,
|
||||
'antibiotikLookup' => $antibiotikLookup, // Kirim array hasil mapping
|
||||
'jsonantibiotik' => $this->listAntibiotik,
|
||||
'glassTables' => $glassTables,
|
||||
'glassHeaders' => $glassHeaders,
|
||||
'bulan' => $bulan,
|
||||
'tahun' => $tahun
|
||||
]);
|
||||
@@ -600,10 +897,12 @@ class ReportController extends Controller
|
||||
|
||||
$response = new StreamedResponse(function() use ($bulan, $tahun) {
|
||||
$handle = fopen('php://output', 'w');
|
||||
|
||||
// Header CSV
|
||||
$staticHeader = ['ID RS', 'Nama Pasien', 'No RM', 'JK', 'Tgl Lahir', 'Usia', 'Ruang', 'Tgl Masuk', 'Tgl Sample', 'Origin', 'Jenis Spesimen', 'Spesies Bakteri', 'ESBL', 'MRSA'];
|
||||
fputcsv($handle, array_merge($staticHeader, $this->listAntibiotik));
|
||||
$headers = $this->getGlassReportHeaders();
|
||||
$tables = [
|
||||
'A' => [],
|
||||
'B' => [],
|
||||
'C' => [],
|
||||
];
|
||||
|
||||
// Query Tanpa Get() tapi Chunk()
|
||||
$query = Periksa::query()->whereYear('daftar', $tahun);
|
||||
@@ -612,39 +911,28 @@ class ReportController extends Controller
|
||||
}
|
||||
|
||||
// Proses per 500 data agar RAM stabil
|
||||
$query->chunk(500, function($rows) use ($handle) {
|
||||
|
||||
// Mapping Antibiotik untuk batch 500 ini saja
|
||||
$chunkIds = $rows->pluck('id')->toArray();
|
||||
$antibiotikLookup = $this->mapAntibiotikData($chunkIds);
|
||||
$query->orderBy('id')->chunk(500, function($rows) use (&$tables) {
|
||||
$lookups = $this->getGlassReportLookups($rows);
|
||||
$chunkTables = $this->splitGlassReportRows($rows, $lookups);
|
||||
|
||||
foreach ($rows as $row) {
|
||||
$csvRow = [
|
||||
$row->id_rs ?? '', // Sesuaikan nama kolom
|
||||
$row->nmpasien,
|
||||
$row->noregister,
|
||||
$row->jkpasien,
|
||||
$row->tgllahirpasien,
|
||||
$row->usia,
|
||||
$row->asalpasien,
|
||||
$row->mulai,
|
||||
$row->daftar,
|
||||
'', // Origin
|
||||
$row->kd_spesimen,
|
||||
$row->nm_spesimen, // Asumsi nama bakteri disini atau kolom lain
|
||||
$row->id_esbl,
|
||||
$row->id_mrsa
|
||||
];
|
||||
|
||||
foreach ($this->listAntibiotik as $headerAntibiotik) {
|
||||
$nilai = $antibiotikLookup[$row->id][$headerAntibiotik] ?? '';
|
||||
$csvRow[] = $nilai;
|
||||
}
|
||||
|
||||
fputcsv($handle, $csvRow);
|
||||
}
|
||||
foreach (['A', 'B', 'C'] as $tableKey) {
|
||||
foreach ($chunkTables[$tableKey] as $tableRow) {
|
||||
$tables[$tableKey][] = $tableRow;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
foreach (['A', 'B', 'C'] as $tableKey) {
|
||||
fputcsv($handle, ['TABEL '.$tableKey]);
|
||||
fputcsv($handle, $headers[$tableKey]);
|
||||
|
||||
foreach ($tables[$tableKey] as $tableRow) {
|
||||
fputcsv($handle, $tableRow);
|
||||
}
|
||||
|
||||
fputcsv($handle, []);
|
||||
}
|
||||
|
||||
fclose($handle);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user