Files
lis/htdocs/app/Http/Controllers/ReportController.php
T
2026-04-04 06:58:02 +07:00

1060 lines
34 KiB
PHP

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Poli;
use App\Logbook;
use App\User;
use App\Periksa;
use App\Dokter;
use App\Pasien;
use App\Jadwalperiksa;
use App\Riwayat;
use App\RekapAntibiotik;
use App\Organisms;
use App\RekapPenerimaanSamplePrintHistory;
use DateTime;
use Carbon\Carbon;
use Session;
use Symfony\Component\HttpFoundation\StreamedResponse;
class ReportController extends Controller
{
public function index() {
if (Session::get('previlage') == ''){
return redirect('/login');
} else {
$dokterOptions = Periksa::select('dokter_id', 'nmdokter')
->whereNotNull('dokter_id')
->where('dokter_id', '<>', 0)
->whereNotNull('nmdokter')
->where('nmdokter', '<>', '')
->groupBy('dokter_id', 'nmdokter')
->orderBy('nmdokter', 'ASC')
->get();
return view('admin.report', [
'dokterOptions' => $dokterOptions
]);
}
}
public function rekapPeriksa(Request $request) {
set_time_limit(0);
$bulan = $request->input('bulan');
$tahun = $request->input('tahun');
if ($bulan == 'ALL' OR $bulan == 'Pick Month') {
$orderbydate = Periksa::selectRaw('SUM(id) as jumlah, DATE(daftar) as day')->whereYear('daftar', $tahun)->groupBy(DB::raw('daftar'))->orderBy('daftar', 'ASC')->get();
$bulan = '';
} else {
$tglcari = $tahun . '-' . str_pad($bulan, 2, '0', STR_PAD_LEFT);
$orderbydate = Periksa::selectRaw('SUM(id) as jumlah, DATE(daftar) as day')->where('day', 'LIKE', '%' . $tglcari . '%')->groupBy(DB::raw('daftar'))->orderBy('daftar', 'ASC')->get();
$bulanNames = [
'01' => 'BULAN JANUARI',
'02' => 'BULAN FEBRUARI',
'03' => 'BULAN MARET',
'04' => 'BULAN APRIL',
'05' => 'BULAN MEI',
'06' => 'BULAN JUNI',
'07' => 'BULAN JULI',
'08' => 'BULAN AGUSTUS',
'09' => 'BULAN SEPTEMBER',
'10' => 'BULAN OKTOBER',
'11' => 'BULAN NOVEMBER',
'12' => 'BULAN DESEMBER',
];
$bulan = $bulanNames[$bulan] ?? $bulan;
}
$data = [];
$data['bulan'] = $bulan;
$data['tahun'] = $tahun;
$data['orderbydate']= $orderbydate;
$generatetabel = view('cetak.rekap_periksa_table', $data)->render();
echo $generatetabel;
}
protected static function getPasienData($result) {
return [
'nama' => $result->nmpasien,
'tgl' => $result->tgllahirpasien,
'jk' => $result->jkpasien,
];
}
protected static function updateTotals($totals, $asuransi, $urgensi, $jk) {
if ($jk == 'L') {
$totals['m']++;
} else {
$totals['f']++;
}
if ($asuransi == 'JKN') {
$totals['jkn']++;
} elseif ($asuransi == 'Umum') {
$totals['umum']++;
} elseif ($asuransi == 'TAG') {
$totals['tag']++;
} elseif ($asuransi == 'GCU') {
$totals['gcu']++;
} elseif ($asuransi == 'Billing') {
$totals['bill']++;
} else {
$totals['swasta']++;
}
if ($urgensi == 'Elective') {
$totals['electiv']++;
} else {
$totals['cito']++;
}
return $totals;
}
protected static function mapResultToArray($result) {
$nmpasien = $result->nmpasien;
$tgl = $result->tgllahirpasien;
$jk = $result->jkpasien;
$jenis = $result->reques;
$tlppasien = $result->tlppasien;
$nofoto = $result->nofoto;
$verifikasi = $result->verifikasi;
$tanggal = $result->daftar;
$tanggalfoto = $result->foto;
$asuransi = $result->asuransi;
$urgensi = $result->urgensi;
$from = \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $result->daftar);
if (is_null($verifikasi)){
$verifikasi = '';
$to = '';
$durasi = 'On Progress';
} else {
$to = \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $verifikasi);
$durasi = $to->diffForHumans($from);
}
$arrayttllhr = explode("-", $tgl);
if (isset($arrayttllhr[2])){
$yy = $arrayttllhr[0];
$mm = $arrayttllhr[1];
$dd = $arrayttllhr[2];
$tgllahir = $dd.'-'.$mm.'-'.$yy;
} else { $tgllahir = $tgl; }
$arrayttl = explode(" ", $tanggal);
$tanggal = $arrayttl[0];
if ($jk == 'L') {
$l = '1';
$p = '';
} else {
$l = '';
$p = '1';
}
if ($asuransi == 'JKN') {
$jkn = '1';
$umm = '';
$swasta = '';
$gcu = '';
$tag = '';
$bill = '';
} else if ($asuransi == 'Umum') {
$jkn = '';
$umm = '1';
$swasta = '';
$gcu = '';
$tag = '';
$bill = '';
} else if ($asuransi == 'TAG') {
$jkn = '';
$umm = '';
$swasta = '';
$gcu = '';
$bill = '';
$tag = '1';
} else if ($asuransi == 'GCU') {
$jkn = '';
$umm = '';
$swasta = '';
$gcu = '1';
$tag = '';
$bill = '';
} else if ($asuransi == 'Billing') {
$jkn = '';
$umm = '';
$swasta = '';
$gcu = '';
$bill = '1';
$tag = '';
} else {
$jkn = '';
$umm = '';
$swasta = '1';
$gcu = '';
$tag = '';
$bill = '';
}
if ($urgensi == 'Elective') {
$ele = '1';
$cito = '';
} else {
$ele = '';
$cito = '1';
}
$getjennofoto = explode("-", $nofoto);
$jenis = $getjennofoto[0].' '.$jenis;
return [
'id' => $result->id,
'filefoto' => '<a href="' . url('/') . '/hasil/' . $result->nofoto . '" target="_blank">' . $result->nofoto . '</a>',
'l' => $l,
'p' => $p,
'jenis' => $jenis,
'jkn' => $jkn,
'umm' => $umm,
'gcu' => $gcu,
'tag' => $tag,
'swasta' => $swasta,
'billing' => $bill,
'ele' => $ele,
'cito' => $cito,
'asuransi' => $asuransi,
'nofoto' => $result->nofoto,
'noregister' => $result->noregister,
'nmpasien' => $nmpasien,
'usia' => $result->usia,
'kesimpulan' => $result->kesimpulan,
'ruangan' => $result->ruangan,
'daftar' => $result->daftar,
'created_at' => $result->created_at,
'nmdokter' => $result->nmdokter,
'nmppdssenior' => $result->nmppdssenior,
'nmmiddleppds' => $result->nmmiddleppds,
'nmppdsjunior' => $result->nmppdsjunior,
'nmppdsmiddle2' => $result->nmppdsmiddle2,
'nmppdsjunior2' => $result->nmppdsjunior2,
'diagnosa2' => $result->diagnosa2,
'nmanalis' => $result->nmanalis,
'nmexcutor' => $result->nmexcutor,
'alamatpasien' => $result->alamatpasien,
'tgllahirpasien'=> $tgl,
'jkpasien' => $jk,
'tlppasien' => $tlppasien,
'modality' => $result->modality,
'dlp' => $result->dlp,
'kd_spesimen' => $result->kd_spesimen,
'nm_spesimen' => $result->nm_spesimen,
'status' => $result->status,
'asalpasien' => $result->asalpasien,
'nmrs' => $result->nmrs,
'berat' => $result->berat,
'klinisi' => $result->klinisi,
'klinis' => $result->klinis,
'telpon' => $tlppasien,
'verifikasi' => $result->verifikasi,
'noloket' => $result->noloket,
'foto' => $result->foto,
'export' => $result->export,
'nmdrafter' => $result->nmdrafter,
'tgldraft' => $result->tgldraft,
'baca' => $result->baca,
'nmpembaca' => $result->nmpembaca,
'tgladendum' => $result->tgladendum,
'nmadendum' => $result->nmadendum,
'durasi' => $durasi,
];
}
protected static function getTotalRow($totals) {
return [
'id' => '',
'filefoto' => '',
'noregister'=> '',
'nama' => '<strong>Total</strong>',
'l' => $totals['m'],
'p' => $totals['f'],
'jkn' => $totals['jkn'],
'umm' => $totals['umum'],
'gcu' => $totals['gcu'],
'tag' => $totals['tag'],
'swasta' => $totals['swasta'],
'billing' => $totals['bill'],
'ele' => $totals['electiv'],
'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');
$jenisreport = $request->input('jenisreport');
$dokterId = $request->input('dokter_id');
$tanggalFilter = $request->input('tanggal_filter', 'daftar');
$statusFilter = $request->input('status_filter', 'ALL');
$dateColumn = $tanggalFilter === 'verifikasi' ? 'verifikasi' : 'daftar';
$homebase = url("/");
$arraylist = [];
$limit = $request->input('limit') ?? 500;
$page = $request->input('pagenum') ?? 1;
$order = $request->input('order') ?? 'id desc';
$filterscount = $request->input('filterscount') ?? 0;
if ($jenisreport == 'biorepository'){
if ($bulan == 'ALL'){
$queryBiorepo = DB::table('db_komponenjawaban')
->select('db_komponenjawaban.*',
'periksa.nofoto',
'periksa.noregister',
'periksa.nmpasien',
'periksa.usia',
'periksa.reques',
'periksa.dlp',
'periksa.nm_spesimen',
'periksa.kd_spesimen',
DB::raw("CONCAT('<a href=\"http://10.10.123.218/hasil/', nofoto, '\" target=\"_blank\">Lihat Hasil</a>') as urlhasil"))
->leftJoin('periksa', 'db_komponenjawaban.accnumber', 'periksa.nofoto')
->whereIn('db_komponenjawaban.komponen', ['id_bakteri01', 'id_bakteri02', 'bakteri'])
->where('db_komponenjawaban.isidata', '!=', '')
->where('periksa.daftar', 'LIKE', $tahun.'-%');
if (!empty($dokterId) && $dokterId != 'ALL' && $dokterId != '0') {
$queryBiorepo->where('periksa.dokter_id', $dokterId);
}
$lists = $queryBiorepo->orderBy('periksa.id', 'DESC')->get();
} else {
$queryBiorepo = DB::table('db_komponenjawaban')
->select('db_komponenjawaban.*',
'periksa.nofoto',
'periksa.noregister',
'periksa.nmpasien',
'periksa.usia',
'periksa.reques',
'periksa.dlp',
'periksa.nm_spesimen',
'periksa.kd_spesimen',
DB::raw("CONCAT('<a href=\"http://10.10.123.218/hasil/', nofoto, '\" target=\"_blank\">Lihat Hasil</a>') as urlhasil"))
->leftJoin('periksa', 'db_komponenjawaban.accnumber', 'periksa.nofoto')
->whereIn('db_komponenjawaban.komponen', ['id_bakteri01', 'id_bakteri02', 'bakteri'])
->where('db_komponenjawaban.isidata', '!=', '')
->where('periksa.daftar', 'LIKE', $tahun.'-'.$bulan.'-%');
if (!empty($dokterId) && $dokterId != 'ALL' && $dokterId != '0') {
$queryBiorepo->where('periksa.dokter_id', $dokterId);
}
$lists = $queryBiorepo->orderBy('periksa.id', 'DESC')->get();
}
echo json_encode($lists);
} else {
$query = Periksa::select('id', 'poli_id', 'nofoto', 'noregister', 'nmpasien', 'tlppasien', 'tgllahirpasien', 'usia', 'alamatpasien', 'ktp', 'jkpasien', 'bpjs', 'asuransi', 'urgensi', 'asalpasien', 'klinisi', 'klinis', 'nmanalis', 'nmppdssenior', 'kd_spesimen', 'nm_spesimen', 'dlp', 'diagnosa2', 'mulai', 'verifikasi', 'status', 'reques', 'nmdokter', 'daftar')
->whereYear($dateColumn, $tahun);
if ($bulan !== 'ALL') {
$query->whereMonth($dateColumn, $bulan);
}
if (!empty($dokterId) && $dokterId != 'ALL' && $dokterId != '0') {
$query->where('dokter_id', $dokterId);
}
if ($statusFilter === 'Selesai') {
$query->where('status', 'LIKE', '%Selesai%');
}
/**
* CURSOR → Streaming data, tidak boros memori
*/
$periksaCursor = $query->orderBy($dateColumn, 'ASC')->cursor();
$hasil = [];
/**
* Karena cursor tidak bisa pluck di awal,
* kita kumpulkan accnumber & poli_id sambil streaming
*/
$acc = [];
$poli_ids = [];
foreach ($periksaCursor as $r) {
$acc[] = $r->nofoto;
$poli_ids[] = $r->poli_id;
$hasil[] = $r; // simpan pointer row
}
/** Jika tidak ada data */
if (empty($hasil)) {
return response()->json([]);
}
/**
* Ambil komponen terkait (1 query saja)
*/
$komponen = DB::table('db_komponenjawaban')
->select('accnumber','komponen','isidata')
->whereIn('accnumber', array_unique($acc))
->whereIn('komponen', [
'id_bakteri01','id_bakteri02','bakteri'
])
->get()
->groupBy('accnumber');
/**
* Ambil poli terkait (1 query)
*/
$poli = DB::table('poli')
->select('id','subpoli','modaliti2')
->whereIn('id', array_unique($poli_ids))
->get()
->keyBy('id');
/**
* Proses setiap row → tidak ada map() untuk hemat memori
*/
foreach ($hasil as $row) {
$k = $komponen[$row->nofoto] ?? collect([]);
$row->id_bakteri01 = optional($k->firstWhere('komponen','id_bakteri01'))->isidata;
$row->id_bakteri02 = optional($k->firstWhere('komponen','id_bakteri02'))->isidata;
$row->bakteri = optional($k->firstWhere('komponen','bakteri'))->isidata;
$row->filefoto = "<a href='".url('/hasil/'.$row->nofoto)."'>$row->nofoto</a>";
$p = $poli[$row->poli_id] ?? null;
$row->subpoli = $p->subpoli ?? null;
$row->modaliti2 = $p->modaliti2 ?? '1';
// Hitung status target
if (!empty($row->verifikasi)) {
$selisih = Carbon::parse($row->mulai)->diffInDays($row->verifikasi);
$row->selisih_hari = $selisih;
$row->status_target = ($selisih <= intval($row->modaliti2))
? "MEMENUHI TARGET"
: "TIDAK MEMENUHI TARGET";
} else {
$row->selisih_hari = null;
$row->status_target = "TIDAK ADA HASIL";
}
}
/**
* Return untuk dua mode (rekaptat / data penuh)
*/
if ($jenisreport == 'rekaptat') {
$rekap = collect($hasil)->groupBy('kd_spesimen')->map(function($g){
return [
'jenis_pemeriksaan' => $g->first()->kd_spesimen,
'memenuhi' => $g->where('status_target','MEMENUHI TARGET')->count(),
'tidak_memenuhi' => $g->where('status_target','TIDAK MEMENUHI TARGET')->count(),
'tidak_ada_hasil' => $g->where('status_target','TIDAK ADA HASIL')->count(),
'total' => $g->count(),
];
})->values();
return response()->json($rekap);
}
return response()->json($hasil);
}
}
public function genRekapAntibiotik(Request $request) {
$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);
}
$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) {
$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);
}
// 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');
$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);
}
// komponen Ziehl yang mau dianalisa
$komponenList = [
'id_pewarnaanziehlnielsen',
'id_pewarnaanziehlnielsensewaktu',
'lsg_pewarnaanziehlnielsen',
'lsg_pewarnaanziehlnielsensewaktu'
];
// Nilai Ziehl yang ingin dihitung
$nilaiList = Organisms::where('kelompok', 'Pewarnaan Ziehl Nielsen')->pluck('name')->toArray();
// 1. Ambil periksa sesuai bulan & tahun
if ($bulan == '' OR $bulan == 'ALL'){
$periksa = Periksa::with(['komponen' => function($q) use ($komponenList){
$q->whereIn('komponen', $komponenList);
}])
->whereYear('mulai', $tahun)
->get();
} else {
$periksa = Periksa::with(['komponen' => function($q) use ($komponenList){
$q->whereIn('komponen', $komponenList);
}])
->whereMonth('mulai', $bulan)
->whereYear('mulai', $tahun)
->get();
}
// 2. Ambil distinct kd_spesimen → ini akan jadi kolom
$kdSpesimenList = $periksa
->pluck('kd_spesimen')
->unique()
->values();
// 3. Bangun struktur perhitungan
$rekapLaki = [];
$rekapPerempuan = [];
foreach ($nilaiList as $nilai) {
foreach ($kdSpesimenList as $spesimen) {
// hitung laki-laki
$rekapLaki[$nilai][$spesimen] = $periksa
->where('kd_spesimen', $spesimen)
->where('jkpasien', 'L')
->filter(function($px) use ($nilai, $komponenList){
return $px->komponen
->whereIn('komponen', $komponenList)
->where('isidata', $nilai)
->count() > 0;
})->count();
// hitung perempuan
$rekapPerempuan[$nilai][$spesimen] = $periksa
->where('kd_spesimen', $spesimen)
->where('jkpasien', 'P')
->filter(function($px) use ($nilai, $komponenList){
return $px->komponen
->whereIn('komponen', $komponenList)
->where('isidata', $nilai)
->count() > 0;
})->count();
}
}
$chartL = [];
$chartP = [];
foreach ($nilaiList as $nilai) {
$chartL[] = array_sum($rekapLaki[$nilai]);
$chartP[] = array_sum($rekapPerempuan[$nilai]);
}
return view('cetak.znreport', compact(
'rekapLaki',
'rekapPerempuan',
'kdSpesimenList',
'nilaiList',
'bulan',
'tahun',
'chartL',
'chartP'
));
}
public function genTATreport(Request $request) {
$data = [];
$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);
}
$query = Periksa::select('*');
if ($bulan !== 'ALL') {
$query->whereMonth('mulai', $bulan);
}
$periksa = $query->whereYear('mulai', $tahun)->orderBy('mulai', 'ASC')->get();
if ($periksa->count() == 0) {
return response()->json([]);
}
$accnumbers = $periksa->pluck('nofoto')->toArray();
$komponen = DB::table('db_komponenjawaban')->whereIn('accnumber', $accnumbers)->whereIn('komponen', ['id_bakteri01','id_bakteri02','id_mikroorganisme'])->get()->groupBy('accnumber');
$poli = DB::table('poli')->whereIn('id', $periksa->pluck('poli_id'))->get()->keyBy('id');
$hasil = $periksa->map(function($row) use ($komponen, $poli){
$k = $komponen[$row->nofoto] ?? collect([]);
$row->id_bakteri01 = optional($k->firstWhere('komponen', 'id_bakteri01'))->isidata;
$row->id_bakteri02 = optional($k->firstWhere('komponen', 'id_bakteri02'))->isidata;
$row->bakteri = optional($k->firstWhere('komponen', 'bakteri'))->isidata;
$row->filefoto = "<a href='".url('/hasil/'.$row->nofoto)."'>$row->nofoto</a>";
$p = $poli[$row->poli_id] ?? null;
$row->subpoli = $p->subpoli ?? null;
$target = $p->modaliti2 ?? '1';
$row->modaliti2 = $target;
if (!empty($row->verifikasi)) {
$selisih_hari = Carbon::parse($row->mulai)->diffInDays(Carbon::parse($row->verifikasi));
$target = intval($target);
$hari = intval($selisih_hari);
$row->selisih_hari = $selisih_hari;
if ($hari <= $target) {
$row->status_target = "MEMENUHI TARGET";
} else {
$row->status_target = "TIDAK MEMENUHI TARGET";
}
} else {
$row->selisih_hari = null;
$row->status_target = "TIDAK ADA HASIL";
}
return $row;
});
$rekap = $hasil->groupBy('kd_spesimen')->map(function($group){
return [
'jenis_pemeriksaan' => $group->first()->kd_spesimen,
'memenuhi' => $group->where('status_target', 'MEMENUHI TARGET')->count(),
'tidak_memenuhi' => $group->where('status_target', 'TIDAK MEMENUHI TARGET')->count(),
'tidak_ada_hasil' => $group->where('status_target', 'TIDAK ADA HASIL')->count(),
'total' => $group->count()
];
})->values();
return view('cetak.tatreport', [
'bulan' => $bulan,
'tahun' => $tahun,
'detail' => $hasil,
'rekap' => $rekap
]);
}
public function genRekapPenerimaanSample(Request $request) {
$data = [];
$tanggal = $request->input('tanggal');
$tanggal = str_replace('tanggal=', '', $tanggal);
$query = Periksa::select('*');
$periksa = $query->whereDate('daftar', $tanggal)->orderBy('id', 'ASC')->get();
if ($periksa->count() == 0) {
return response()->json([]);
}
$histories = RekapPenerimaanSamplePrintHistory::whereDate('tanggal', $tanggal)
->orderBy('printed_at', 'DESC')
->orderBy('id', 'DESC')
->get()
->map(function ($h) {
$rowIds = json_decode($h->row_ids, true);
$rowsPayload = json_decode($h->rows_payload, true);
return [
'id' => $h->id,
'printed_by_id' => $h->printed_by_id,
'printed_by_name' => $h->printed_by_name,
'printed_at' => $h->printed_at,
'printed_at_label' => $h->printed_at ? Carbon::parse($h->printed_at)->format('Y-m-d H:i:s') : '-',
'row_ids' => is_array($rowIds) ? $rowIds : [],
'rows_payload' => is_array($rowsPayload) ? $rowsPayload : [],
'total_rows' => is_array($rowIds) ? count($rowIds) : 0,
];
})
->values();
return view('cetak.rekappenerimaansample', [
'tanggal' => $tanggal,
'detail' => $periksa,
'printHistories' => $histories
]);
}
public function markRekapPenerimaanSamplePrinted(Request $request) {
$userId = Session::get('id');
$userNama = Session::get('nama');
if (empty($userId)) {
return response()->json([
'status' => 'error',
'message' => 'Session login tidak valid.'
], 401);
}
$ids = $request->input('ids', []);
if (!is_array($ids) || count($ids) === 0) {
return response()->json([
'status' => 'error',
'message' => 'Data yang dipilih tidak valid.'
], 422);
}
$ids = collect($ids)
->filter(function ($id) {
return is_numeric($id);
})
->map(function ($id) {
return intval($id);
})
->unique()
->values()
->toArray();
if (count($ids) === 0) {
return response()->json([
'status' => 'error',
'message' => 'Data yang dipilih tidak valid.'
], 422);
}
$tanggal = $request->input('tanggal');
$tanggal = !empty($tanggal) ? $tanggal : null;
$printableIds = Periksa::whereIn('id', $ids)
->where(function ($query) {
$query->whereNull('ppdsjunior2')
->orWhere('ppdsjunior2', 0);
})
->pluck('id')
->toArray();
if (count($printableIds) === 0) {
return response()->json([
'status' => 'error',
'message' => 'Semua data yang dipilih sudah pernah dicetak.'
], 422);
}
if (count($printableIds) > 0) {
Periksa::whereIn('id', $printableIds)->update([
'ppdsjunior2' => $userId,
'nmppdsjunior2' => $userNama,
'updated_at' => date('Y-m-d H:i:s'),
]);
}
// Ambil data setelah update supaya payload cetak (petugas) sesuai yang tampil di tabel
$rowsToPrint = Periksa::whereIn('id', $printableIds)
->orderBy('id', 'ASC')
->get()
->map(function ($row) {
$petugas = trim(($row->nmppdsmiddle2 ?? '').' '.($row->nmppdsjunior2 ?? ''));
$status = trim((string)($row->status ?? ''));
if ($status === '') {
$status = '-';
}
return [
'id' => $row->id,
'noregister' => $row->noregister ?? '',
'nmpasien' => $row->nmpasien ?? '',
'nofoto' => $row->nofoto ?? '',
'asalpasien' => $row->asalpasien ?? '',
'daftar' => $row->daftar ?? '',
'reques' => $row->reques ?? '',
'kd_spesimen' => $row->kd_spesimen ?? '',
'nm_spesimen' => $row->nm_spesimen ?? '',
'status' => $status,
'tgldraft' => $row->tgldraft ?? '',
'petugas' => $petugas,
];
})
->values()
->toArray();
$history = RekapPenerimaanSamplePrintHistory::create([
'tanggal' => $tanggal,
'printed_by_id' => $userId,
'printed_by_name' => $userNama,
'printed_at' => Carbon::now()->format('Y-m-d H:i:s'),
'row_ids' => json_encode(array_values($printableIds)),
'rows_payload' => json_encode($rowsToPrint),
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
$historyResponse = [
'id' => $history->id,
'printed_by_id' => $history->printed_by_id,
'printed_by_name' => $history->printed_by_name,
'printed_at' => $history->printed_at,
'printed_at_label' => Carbon::parse($history->printed_at)->format('Y-m-d H:i:s'),
'row_ids' => $printableIds,
'rows_payload' => $rowsToPrint,
'total_rows' => count($printableIds),
];
return response()->json([
'status' => 'success',
'message' => 'Status cetak berhasil diperbarui.',
'affected_ids'=> $printableIds,
'printed_by' => $userNama,
'history' => $historyResponse
]);
}
}