This commit is contained in:
Duidev Software
2026-01-02 16:42:43 +07:00
parent 98d6b688e9
commit 4583ac6cd7
4 changed files with 385 additions and 274 deletions
+285 -123
View File
@@ -17,7 +17,7 @@ use App\Organisms;
use DateTime;
use Carbon\Carbon;
use Session;
use Symfony\Component\HttpFoundation\StreamedResponse;
class ReportController extends Controller
{
public function index() {
@@ -263,6 +263,54 @@ class ReportController extends Controller
'cito' => $totals['cito'],
];
}
private $listAntibiotik = [
'Oxacillin-OX',
'Cefoxitin-FOX',
'Benzylpenicillin-P',
'Ampicillin-AM',
'Azithromycin-AZM',
'Erythromycin-ERY',
'Cefazolin-CZO',
'Cefepime-FEP',
'Cefixime-CFM',
'Cefotaxime-CTX',
'Cefuroxime-CXM',
'Ceftazidime-CAZ',
'Ceftriaxone-CRO',
'Ceftazidime/Avibactam-CZA',
'Piperacilin/Tazobactam-TZP',
'Ampicillin/Sulbactam-SAM',
'Amoxicillin/Clavulanate-AMC',
'Cefoperazon/Sulbactam-SCF',
'Aztreonam-ATM',
'Ceftaroline-CPT',
'Ciprofloxacin-CIP',
'Levofloxacin-LEV',
'Moxifloxacin-MFX',
'Clindamycin-CLI',
'Colistin-CS',
'Tetracyclin-TCY',
'Tigecycline-TGC',
'Gentamicin-GM',
'Amikacin-AN',
'Meropenem-MEM',
'Imipenem-IPM',
'Doripenem-DOR',
'Ertapenem-ETP',
'Minocycline-MNO',
'Doxycycline-DOX',
'Spectinomycin-SPT',
'Trimethoprim/Sulfamethoxazole-SXT',
'Fosfomycin-FOS',
'Vancomycin-VAN',
'Linezolid-LNZ',
'Fluconazole',
'Voriconazole',
'Caspofungin',
'Micafungin',
'Amphotericin B',
'Flucytosine'
];
public function report(Request $request) {
$bulan = $request->input('bulan');
$tahun = $request->input('tahun');
@@ -413,141 +461,255 @@ class ReportController extends Controller
}
}
public function genRekapAntibiotik(Request $request) {
$data = [];
$bulan = $request->input('bulan');
$tahun = $request->input('tahun');
if ($tahun == '' OR is_null($tahun)){
$bulan = $request->input('bulan');
$tahun = $request->input('tahun');
if ($tahun == '' OR is_null($tahun)){
$getarray = explode('?', $bulan);
$bulan = $getarray[0] ?? date('m');
$tahun = $getarray[1] ?? date('Y');
$bulan = str_replace('bulan=', '', $bulan);
$tahun = str_replace('tahun=', '', $tahun);
}
if ($bulan == '' OR $bulan == 'ALL' OR $bulan == 'Pick Month') {
$orderbydate = Periksa::whereYear('daftar', $tahun)->get();
$jsonantibiotik = RekapAntibiotik::whereIn('orderid', $orderbydate->pluck('id'))->get()->groupBy('orderid');
} else {
$orderbydate = Periksa::whereMonth('daftar', $bulan)->whereYear('daftar', $tahun)->get();
$jsonantibiotik = RekapAntibiotik::whereIn('orderid', $orderbydate->pluck('id'))->get()->groupBy('orderid');
}
return view('admin.rekapantibiotik', compact('orderbydate', 'jsonantibiotik', 'bulan', 'tahun'));
}
$listAntibiotik = $this->getDynamicAntibioticHeaders($bulan, $tahun);
$query = Periksa::query()->whereYear('daftar', $tahun);
if ($bulan != 'ALL' && $bulan != 'Pick Month') {
$query->whereMonth('daftar', $bulan);
}
// 3. Pagination (50 Data)
$orderbydate = $query->paginate(50);
$orderbydate->appends(['bulan' => $bulan, 'tahun' => $tahun]);
// 4. Mapping Data Antibiotik (Hanya untuk 50 pasien ini)
$pageIds = $orderbydate->pluck('id')->toArray();
$antibiotikLookup = $this->mapAntibiotikData($pageIds);
return view('admin.rekapantibiotik', [
'orderbydate' => $orderbydate,
'antibiotikLookup' => $antibiotikLookup,
'listAntibiotik' => $listAntibiotik, // Kirim header dinamis ke View
'bulan' => $bulan,
'tahun' => $tahun
]);
}
private function mapAntibiotikData($orderIds) {
$raw = RekapAntibiotik::whereIn('orderid', $orderIds)->get();
$lookup = [];
foreach($raw as $row) {
$lookup[$row->orderid][$row->antibiotic] = $row->interpretation;
}
return $lookup;
}
private function getDynamicAntibioticHeaders($bulan, $tahun) {
$query = DB::table('rekapantibiotik')
->join('periksa', 'rekapantibiotik.orderid', '=', 'periksa.id')
->whereYear('periksa.daftar', $tahun);
if ($bulan != 'ALL' && $bulan != 'Pick Month') {
$query->whereMonth('periksa.daftar', $bulan);
}
return $query->distinct()
->orderBy('rekapantibiotik.antibiotic', 'ASC')
->pluck('rekapantibiotik.antibiotic')
->toArray();
}
public function genGlassReport(Request $request) {
$data = [];
$bulan = $request->input('bulan');
$tahun = $request->input('tahun');
if ($tahun == '' OR is_null($tahun)){
$bulan = $request->input('bulan');
$tahun = $request->input('tahun');
if ($tahun == '' OR is_null($tahun)){
$getarray = explode('?', $bulan);
$bulan = $getarray[0] ?? date('m');
$tahun = $getarray[1] ?? date('Y');
$bulan = str_replace('bulan=', '', $bulan);
$tahun = str_replace('tahun=', '', $tahun);
}
if ($bulan == '' OR $bulan == 'ALL' OR $bulan == 'Pick Month') {
$orderbydate = Periksa::whereYear('daftar', $tahun)->get();
$jsonantibiotik = array(
'Oxacillin-OX',
'Cefoxitin-FOX',
'Benzylpenicillin-P',
'Ampicillin-AM',
'Azithromycin-AZM',
'Erythromycin-ERY',
'Cefazolin-CZO',
'Cefepime-FEP',
'Cefixime-CFM',
'Cefotaxime-CTX',
'Cefuroxime-CXM',
'Ceftazidime-CAZ',
'Ceftriaxone-CRO',
'Ceftazidime/Avibactam-CZA',
'Piperacilin/Tazobactam-TZP',
'Ampicillin/Sulbactam-SAM',
'Amoxicillin/Clavulanate-AMC',
'Cefoperazon/Sulbactam-SCF',
'Aztreonam-ATM',
'Ceftaroline-CPT',
'Ciprofloxacin-CIP',
'Levofloxacin-LEV',
'Moxifloxacin-MFX',
'Clindamycin-CLI',
'Colistin-CS', //tidak ada
'Tetracyclin-TCY',
'Tigecycline-TGC', //double
'Gentamicin-GM',
'Amikacin-AN',
'Meropenem-MEM',
'Imipenem-IPM',
'Doripenem-DOR',
'Ertapenem-ETP',
'Minocycline-MNO',
'Doxycycline-DOX',
'Spectinomycin-SPT',
'Tigecycline-TGC', //sama-ini
'Trimethoprim/Sulfamethoxazole-SXT',
'Fosfomycin-FOS',
'Vancomycin-VAN',
'Linezolid-LNZ',
'Fluconazole', //tidak ada
'Voriconazole', //tidak ada
'Caspofungin', //tidak ada
'Micafungin', //tidak ada
'Amphotericin B', //tidak ada
'Flucytosine' //tidak ada
);
} else {
$orderbydate = Periksa::whereMonth('daftar', $bulan)->whereYear('daftar', $tahun)->get();
$jsonantibiotik = array(
'Oxacillin-OX',
'Cefoxitin-FOX',
'Benzylpenicillin-P',
'Ampicillin-AM',
'Azithromycin-AZM',
'Erythromycin-ERY',
'Cefazolin-CZO',
'Cefepime-FEP',
'Cefixime-CFM',
'Cefotaxime-CTX',
'Cefuroxime-CXM',
'Ceftazidime-CAZ',
'Ceftriaxone-CRO',
'Ceftazidime/Avibactam-CZA',
'Piperacilin/Tazobactam-TZP',
'Ampicillin/Sulbactam-SAM',
'Amoxicillin/Clavulanate-AMC',
'Cefoperazon/Sulbactam-SCF',
'Aztreonam-ATM',
'Ceftaroline-CPT',
'Ciprofloxacin-CIP',
'Levofloxacin-LEV',
'Moxifloxacin-MFX',
'Clindamycin-CLI',
'Colistin-CS',
'Tetracyclin-TCY',
'Tigecycline-TGC',
'Gentamicin-GM',
'Amikacin-AN',
'Meropenem-MEM',
'Imipenem-IPM',
'Doripenem-DOR',
'Ertapenem-ETP',
'Minocycline-MNO',
'Doxycycline-DOX',
'Spectinomycin-SPT',
'Tigecycline-TGC',
'Trimethoprim/Sulfamethoxazole-SXT',
'Fosfomycin-FOS',
'Vancomycin-VAN',
'Linezolid-LNZ',
'Fluconazole',
'Voriconazole',
'Caspofungin',
'Micafungin',
'Amphotericin B',
'Flucytosine'
);
}
return view('admin.glassreport', compact('orderbydate', 'jsonantibiotik', 'bulan', 'tahun'));
}
// Query Periksa
$query = Periksa::query()->whereYear('daftar', $tahun);
if ($bulan != 'ALL' && $bulan != 'Pick Month') {
$query->whereMonth('daftar', $bulan);
}
// 1. Ambil Data Pasien (Limit 50 per halaman agar RAM aman)
$orderbydate = $query->paginate(50);
$orderbydate->appends(['bulan' => $bulan, 'tahun' => $tahun]);
// 2. Ambil Data Antibiotik HANYA untuk 50 pasien tersebut
$pageIds = $orderbydate->pluck('id')->toArray();
$antibiotikLookup = $this->mapAntibiotikData($pageIds);
return view('admin.glassreport', [
'orderbydate' => $orderbydate,
'antibiotikLookup' => $antibiotikLookup, // Kirim array hasil mapping
'jsonantibiotik' => $this->listAntibiotik,
'bulan' => $bulan,
'tahun' => $tahun
]);
}
public function exportGlassReport(Request $request) {
// Set memory limit sementara untuk proses export berat, tapi streaming tetap kuncinya
ini_set('memory_limit', '512M');
ini_set('max_execution_time', 300); // 5 menit
$bulan = $request->input('bulan');
$tahun = $request->input('tahun');
// Logic cleaning input...
if (strpos($bulan, 'bulan=') !== false) {
$parts = explode('?', $bulan);
$bulan = str_replace('bulan=', '', $parts[0]);
$tahun = str_replace('tahun=', '', $parts[1] ?? date('Y'));
}
$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));
// Query Tanpa Get() tapi Chunk()
$query = Periksa::query()->whereYear('daftar', $tahun);
if ($bulan != 'ALL' && $bulan != 'Pick Month') {
$query->whereMonth('daftar', $bulan);
}
// 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);
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);
}
});
fclose($handle);
});
$response->headers->set('Content-Type', 'text/csv');
$response->headers->set('Content-Disposition', 'attachment; filename="GlassReport_'.$bulan.'_'.$tahun.'.csv"');
return $response;
}
public function exportRekapAntibiotik(Request $request) {
ini_set('memory_limit', '512M');
ini_set('max_execution_time', 600); // 10 menit jika data besar
$bulan = $request->input('bulan');
$tahun = $request->input('tahun');
if (strpos($bulan, 'bulan=') !== false) {
$parts = explode('?', $bulan);
$bulan = str_replace('bulan=', '', $parts[0]);
$tahun = str_replace('tahun=', '', $parts[1] ?? date('Y'));
}
// 1. Dapatkan Header Dinamis
$listAntibiotik = $this->getDynamicAntibioticHeaders($bulan, $tahun);
$response = new StreamedResponse(function() use ($bulan, $tahun, $listAntibiotik) {
$handle = fopen('php://output', 'w');
// Header Statis
$staticHeaders = [
'No', 'Status', 'No.RM', 'Name', 'Order', 'Gender', 'Date',
'Urgensi', 'Comming From', 'Code', 'Spesimen', 'Finish',
'BHP Media', 'BHP Pot Sputum', 'BHP Pot Urine', 'BHP Oshe',
'BHP Obyek Glass', 'BHP Botol BD', 'BHP Parafilm', 'BHP Tips',
'BHP Cotton Swab', 'BHP Ab Tambahan', 'ESBL', 'MRSA'
];
// Gabung Header Statis + Header Dinamis dari DB
fputcsv($handle, array_merge($staticHeaders, $listAntibiotik));
// Query Utama (Chunking)
$query = Periksa::query()->whereYear('daftar', $tahun);
if ($bulan != 'ALL' && $bulan != 'Pick Month') {
$query->whereMonth('daftar', $bulan);
}
$query->chunk(500, function($rows) use ($handle, $listAntibiotik) {
// Ambil data nilai antibiotik untuk chunk ini
$chunkIds = $rows->pluck('id')->toArray();
$antibiotikLookup = $this->mapAntibiotikData($chunkIds);
foreach ($rows as $row) {
$csvRow = [
$row->noloket,
$row->status,
$row->noregister,
$row->nmpasien,
$row->reques,
$row->jkpasien,
$row->daftar,
$row->urgensi,
$row->asalpasien,
$row->kd_spesimen,
$row->nm_spesimen,
$row->updated_at,
$row->bhp_media,
$row->bhp_potsputum,
$row->bhp_poturine,
$row->bhp_oshe,
$row->bhp_obyekglass,
$row->bhp_botolbd,
$row->bhp_parafilm,
$row->bhp_tips,
$row->bhp_cottonswab,
$row->bhp_antibiotiktambahan,
$row->id_esbl,
$row->id_mrsa
];
// Loop sesuai Header Dinamis
foreach ($listAntibiotik as $headerAb) {
// Cek apakah pasien ini punya nilai utk antibiotik tsb
$val = $antibiotikLookup[$row->id][$headerAb] ?? '';
$csvRow[] = $val;
}
fputcsv($handle, $csvRow);
}
});
fclose($handle);
});
$response->headers->set('Content-Type', 'text/csv');
$response->headers->set('Content-Disposition', 'attachment; filename="RekapAntibiotik_'.$bulan.'_'.$tahun.'.csv"');
return $response;
}
public function genZNreport(Request $request) {
$data = [];
$bulan = $request->input('bulan');