parking = $parking; } public function byGate() { return view("report.by-gate"); } public function statistik() { return view("report.statistik"); } /** * Statistik transaksi parkir dipecah per hari / minggu / bulan. * Periode berdasarkan kolom tanggal. Response: rows per periode + ringkasan. */ public function statistikData(Request $request) { $request->validate([ "grup" => "nullable|in:hari,minggu,bulan", "tgl_awal" => "nullable|date_format:Y-m-d", "tgl_akhir" => "nullable|date_format:Y-m-d|after_or_equal:tgl_awal", "status_transaksi" => "nullable|in:0,3,32,-1", "cara" => "nullable|in:tunai,cashless", ]); $grup = $request->input("grup", "hari"); $tglAkhir = $request->input("tgl_akhir", date("Y-m-d")); $tglAwal = $request->input("tgl_awal", date("Y-m-d", strtotime("-29 days", strtotime($tglAkhir)))); // Batas maksimal 370 hari biar query tetap enteng. if ((strtotime($tglAkhir) - strtotime($tglAwal)) / 86400 > 370) { return response()->json(["message" => "Rentang maksimal 370 hari, persempit periodenya."], 422); } $bucket = match ($grup) { "minggu" => "date_trunc('week', tp.tanggal)::date", "bulan" => "date_trunc('month', tp.tanggal)::date", default => "tp.tanggal::date", }; $query = DB::table("transaksi_parkir as tp") ->whereDate("tp.tanggal", ">=", $tglAwal) ->whereDate("tp.tanggal", "<=", $tglAkhir); if ($request->filled("status_transaksi")) { $query->where("tp.status_transaksi", $request->input("status_transaksi")); } if ($request->input("cara") === "tunai") { $query->where(function ($w) { $w->whereNull("tp.cara_bayar")->orWhere("tp.cara_bayar", 0); }); } elseif ($request->input("cara") === "cashless") { $query->where("tp.cara_bayar", 3); } $rows = $query ->selectRaw("({$bucket}) as periode") ->selectRaw("count(*) as transaksi") ->selectRaw("count(case when tp.status = 0 then 1 end) as keluar") ->selectRaw("coalesce(sum(case when tp.status = 0 then tp.bayar_keluar end), 0) as pendapatan") ->selectRaw("coalesce(sum(case when tp.status = 0 and (tp.cara_bayar is null or tp.cara_bayar = 0) then tp.bayar_keluar end), 0) as tunai") ->selectRaw("coalesce(sum(case when tp.status = 0 and tp.cara_bayar = 3 then tp.bayar_keluar end), 0) as cashless") ->groupByRaw($bucket) ->orderBy("periode") ->get(); return response()->json([ "status" => true, "grup" => $grup, "tgl_awal" => $tglAwal, "tgl_akhir" => $tglAkhir, "data" => $rows, "ringkasan" => [ "transaksi" => $rows->sum("transaksi"), "keluar" => $rows->sum("keluar"), "pendapatan" => (float) $rows->sum("pendapatan"), "tunai" => (float) $rows->sum("tunai"), "cashless" => (float) $rows->sum("cashless"), ], ]); } // private function transaksiParkir($isMirror) // { // $mirror = DB::table('parkir_transaksi') // $query = DB::table('transaksi_parkir'); // return $table; // } public function gateData(Request $request) { Log::info($request->all()); $awal = $request->tanggal_mulai; $akhir = $request->tanggal_selesai; $isShift = $request->shift === "on"; $dateBy = $isShift ? "pklogin" : "waktu_keluar"; $paymentMethod = $request->payment_method === "null" ? null : $request->payment_method; // ๐Ÿ”น Base select $select = [ "np.nama as gate", "tp.id_pintu_keluar", "p.nama as petugas", "tp.id_op_keluar", "jm.nama as kendaraan", "tp.status_transaksi", DB::raw("count(*) as jumlah_transaksi"), DB::raw("sum(tp.bayar_keluar) as income_transaksi"), ]; // ๐Ÿ”น Tambah shift kalau aktif if ($isShift) { $select[] = "tp.id_shift_keluar"; } // ๐Ÿ”น Base group $groupBy = ["tp.id_pintu_keluar", "np.nama", "p.nama", "tp.id_op_keluar", "jm.nama", "tp.status_transaksi"]; if ($isShift) { $groupBy[] = "tp.id_shift_keluar"; } // $query = DB::table("transaksi_parkir as tp") $query = $this->parking ->useTableParkir(Auth::user()) ->leftJoin("pegawai as p", "p.nomer", "=", "tp.id_op_keluar") ->leftJoin("nama_pos as np", "np.id", "=", "tp.id_pintu_keluar") ->leftJoin("jenis_mobil as jm", "jm.id", "=", "tp.id_kendaraan") ->select($select) // ๐Ÿ”น Filter tanggal (dynamic field) ->where("tp.status", 0) ->whereBetween($dateBy, [$awal . " 00:00:00", $akhir . " 23:59:59"]) // // ๐Ÿ”น STATUS // ->when($request->status_transaksi, fn($q, $v) => // $q->where('tp.status_transaksi', $v) // ) // ๐Ÿ”น PINTU ->when($request->id_pintu_keluar, fn($q, $v) => $q->whereIn("tp.id_pintu_keluar", (array) $v)) // ๐Ÿ”น Status Transaksi // ->when($request->status_transaksi, function ($q) use ($request) { ->when(isset($request->status_transaksi), function ($q) use ($request) { return match ($request->status_transaksi) { // '0' => $q->whereNotIn('tp.status_transaksi', ['3','-1'])->whereNotNull('alasan'), "0" => $q->where("tp.status_transaksi", "0")->whereNull("alasan"), "3" => $q->where("tp.status_transaksi", "3")->whereNull("alasan"), "-1" => $q->where("tp.status_transaksi", "-1")->whereNotNull("alasan"), "null" => $q->whereNull("alasan"), }; }) // ๐Ÿ”น CARA BAYAR ->when($request->cara_bayar, function ($q) use ($request) { return match ($request->cara_bayar) { "cash" => $q->where("tp.cara_bayar", "!=", 3), "cashless" => $q->where("tp.cara_bayar", 3), default => $q, }; }) ->when($paymentMethod, function ($q) use ($paymentMethod) { return $q->where("tp.rep_bank", $paymentMethod); // return match ($request->payment_method) { // 2 => $q->where('tp.rep_bank', 2), // 3 => $q->where('tp.rep_bank', 3), // 4 => $q->where('tp.rep_bank', 4), // 5 => $q->where('tp.rep_bank', 5), // 9 => $q->where('tp.rep_bank', 9), // default => $q // }; }) // // ๐Ÿ”น PETUGAS // ->when($request->id_op_keluar, fn($q, $v) => // $q->whereIn('tp.id_op_keluar', (array) $v) // ) // // ๐Ÿ”น KENDARAAN // ->when($request->id_kendaraan, fn($q, $v) => // $q->whereIn('tp.id_kendaraan', (array) $v) // ) ->groupBy($groupBy) ->orderBy("tp.id_pintu_keluar") ->when($isShift, fn($q) => $q->orderBy("tp.id_shift_keluar")) ->orderBy("tp.id_op_keluar") ->orderBy("jm.nama") ->orderBy("tp.status_transaksi"); return response()->json([ "byGateData" => $query->get(), ]); } public function allReport() { return view("report.all-report"); } public function allReportData(Request $request) { return response()->json([ "vehicle" => $this->vehicleReport($request), "officer" => $this->reportOfficer($request), "payment" => $this->paymentType($request), ]); } public function vehicleReport(Request $request) { Log::info("== allReportData START =="); Log::info($request->harian); Log::info($request->tanggal); $GlobalParams = SoftSettings::first()->select("namaokasi", "namaperusahaan"); $selectDate = $request->tanggal; $start = microtime(true); $harian = $request->harian ?? 1; $dateNow = "2026-01-25"; $startDate = $selectDate ? $selectDate : $dateNow; $endDate = $selectDate ? $selectDate : $dateNow; Log::info("Tanggal laporan", [ "start" => $startDate, "end" => $endDate, ]); // ========================= // QUERY UTAMA (LEFT JOIN) // ========================= Log::info("Query transaksi dimulai"); if ($harian == 1) { $isReport = "harian"; $dateColumn = ["tp.waktu_masuk", "tp.waktu_keluar"]; $dateInColumn = "tp.waktu_masuk"; $dateOutColumn = "tp.waktu_keluar"; $dateField = "waktu_keluar"; $dateInField = "waktu_masuk"; $dateOutField = "waktu_keluar"; } else { $isReport = "shift"; $dateColumn = ["tp.pmlogin", "tp.pklogin"]; $dateInColumn = "tp.pmlogin"; $dateOutColumn = "tp.pklogin"; $dateInField = "pmlogin"; $dateOutField = "pklogin"; } $transactions = $this->parking ->useTableParkir(Auth::user()) ->leftJoin("jenis_mobil as jm", "jm.id", "=", "tp.id_kendaraan") ->where(function ($q) use ($dateColumn, $dateInField, $dateOutField, $startDate, $endDate, $selectDate) { $q->whereBetween("tp." . $dateInField, [ $startDate . " 00:00:00", $endDate . " 23:59:59", ])->orWhereBetween("tp." . $dateOutField, [$startDate . " 00:00:00", $endDate . " 23:59:59"]); }) ->select( "jm.nama as jenis_mobil", "tp.id_kendaraan", "tp.waktu_masuk", "tp.waktu_keluar", "tp.pmlogin", "tp.pklogin", "tp.status", "tp.bayar_masuk", "tp.bayar_keluar", "id_op_masuk as kasirMasuk", "id_op_keluar as kasirKeluar", "tp.status_transaksi", "tp.cara_bayar", "tp.manual", ) ->get(); Log::info("Query transaksi selesai", [ "rows" => $transactions->count(), "query_time_ms" => round((microtime(true) - $start) * 1000, 2), ]); // ================================================ // ############# REKAP PER KENDARAAN ############ // ================================================ Log::info("Rekap kendaraan dimulai"); $tunai = $transactions ->sortBy("id_kendaraan") ->groupBy("id_kendaraan") ->map(function ($items, $id_kendaraan) use ($dateInField, $dateOutField, $startDate, $endDate) { $start = $startDate . " 00:00:00"; $end = $endDate . " 23:59:59"; // ================================= // 1. Parsing in & Out Transaction // ================================= $masuk = $items->filter(function ($r) use ($startDate, $endDate, $dateInField) { return $r->$dateInField >= $startDate . " 00:00:00" && $r->$dateInField <= $endDate . " 23:59:59"; }); Log::info("Jumlah didapat " . $id_kendaraan . " : " . $masuk->count()); // $masukTrans = $masuk->filter(fn($r) => (int) $r->status === 1); $masukCasual = $masuk->filter( fn($r) => $r->status === 1 && data_get($r, "kasirMasuk") == null && data_get($r, "manual") === null, ); // Log::info("Berdasarkan tanggal transaksi " . $start . " " . $end . " : " . json_encode($masukTrans)); $masukLost = $masuk->filter(fn($r) => (string) data_get($r, "status_transaksi") === "32"); $masukMember = $masukCasual->filter(fn($r) => (string) data_get($r, "status_transaksi") === "3"); $masukManual = $masuk->filter(fn($r) => (string) data_get($r, "kasirMasuk") === null); $masukMix = $masuk->filter(fn($r) => (int) data_get($r, "manual"), 1); $masukMasalah = $masuk->filter(fn($r) => (string) data_get($r, "alasan") !== null); // ====================== // KELUAR // ====================== $keluar = $items->filter(fn($r) => (int) $r->status === 0); // ini rada ngaco $tunai = $keluar->filter(fn($row) => in_array(data_get($row, "cara_bayar"), [null, 0, "0"], true)); $keluarCasual = $tunai->filter( fn($r) => (string) data_get($r, "status_transaksi") === "0" && data_get($r, "id_op_masuk") !== null, ); $keluarMember = $tunai->filter(fn($r) => (string) data_get($r, "status_transaksi") === "3"); $keluarLost = $tunai->filter(fn($r) => (string) data_get($r, "status_transaksi") === "32"); $keluarManual = $tunai->filter(fn($r) => data_get($r, "kasirKeluar") === null); $keluarMix = $tunai->filter(fn($r) => data_get($r, "manual") === 1); $keluarMasalah = $tunai->filter(fn($r) => (string) data_get($r, "status_transaksi") === "-1"); $totalCash = $keluarCasual->sum("bayar_keluar") + $keluarLost->sum("bayar_keluar") + $keluarMember->sum("bayar_keluar") + $keluarManual->sum("bayar_keluar"); return [ "id_kendaraan" => $id_kendaraan, "jenis_mobil" => $items->first()->jenis_mobil, // "total" => "", // "tunaiOut" => $tunai->count(), // ========= MASUK ========= "masuk" => [ "jmlTrans" => [ "jumlah" => $masukCasual->count(), "income" => $masukCasual->sum("bayar_masuk"), ], "casual" => [ "jumlah" => $masuk->count(), "income" => $masukCasual->sum("bayar_masuk"), ], "lostTicket" => [ "jumlah" => $masukLost->count(), "income" => $masukLost->sum("bayar_masuk"), ], "member" => [ "jumlah" => $masukMember->count(), "income" => $masukMember->sum("bayar_masuk"), ], "manual" => [ "jumlah" => $masukManual->count(), "income" => $masukManual->sum("bayar_masuk"), ], "mix" => [ "jumlah" => $masukMix->count(), "income" => $masukMix->sum("bayar_masuk"), ], "masalah" => [ "jumlah" => $masukMasalah->count(), "income" => $masukMasalah->sum("bayar_masuk"), ], ], // ========= KELUAR ========= "keluar" => [ "casual" => [ "jumlah" => $keluarCasual->count(), "income" => $keluarCasual->sum("bayar_keluar"), ], "lost" => [ "jumlah" => $keluarLost->count(), "income" => $keluarLost->sum("bayar_keluar"), ], "member" => [ "jumlah" => $keluarMember->count(), "income" => $keluarMember->sum("bayar_keluar"), ], "manual" => [ "jumlah" => $keluarManual->count(), "income" => $keluarManual->sum("bayar_keluar"), ], "masalah" => [ "jumlah" => $keluarMasalah->count(), "income" => $keluarMasalah->sum("bayar_keluar"), ], ], "totalCash" => $totalCash, ]; }) ->values(); $cashless = $transactions ->sortBy("id_kendaraan") ->groupBy("id_kendaraan") ->map(function ($items, $id_kendaraan) use ($startDate, $endDate, $dateOutField) { // ====================== // PISAH MASUK & KELUAR // ====================== // $masuk = $items->where("status", 1); $masuk = $items->filter(fn($row) => in_array(data_get($row, "cara_bayar"), [null, 0, "0"], true)); // $keluar = $items->where('status', 0); // $nonTunai = $keluar->where('cara_bayar', 3); // ====================== // MASUK // ====================== $masukCasual = $masuk; $masukMember = $masuk->where("status_transaksi", "3"); // ====================== // KELUAR // ====================== // $keluarCasual = $nonTunai->where('status_transaksi', '0'); // $keluarMember = $nonTunai->where('status_transaksi', '3'); // $keluarLost = $nonTunai->where('status_transaksi', '32'); // $keluar = $items->filter(fn($r) => (int) $r->status === 0); // $tunai = $keluar->where('cara_bayar', '!=', 3); $keluar = $items->filter(function ($r) use ($startDate, $endDate, $dateOutField) { return (int) $r->status === 0 && $r->$dateOutField >= $startDate . " 00:00:00" && $r->$dateOutField <= $endDate . " 23:59:59"; }); $nonTunai = $keluar->filter(fn($row) => (string) data_get($row, "cara_bayar") === "3"); $keluarCasual = $nonTunai->filter( fn($r) => (string) data_get($r, "status_transaksi") === "0" && data_get($r, "id_op_masuk") !== null, ); $keluarMember = $nonTunai->filter(fn($r) => (string) data_get($r, "status_transaksi") === "3"); $keluarLost = $nonTunai->filter(fn($r) => (string) data_get($r, "status_transaksi") === "32"); $keluarManual = $nonTunai->filter(fn($r) => data_get($r, "id_op_masuk") === null); $totalCashless = $keluarCasual->sum("bayar_keluar") + $keluarLost->sum("bayar_keluar") + $keluarMember->sum("bayar_keluar") + $keluarManual->sum("bayar_keluar"); // ====================== // PEMBAYARAN (KELUAR) // ====================== return [ "id_kendaraan" => $id_kendaraan, "jenis_mobil" => $items->first()->jenis_mobil, "total" => $items->count(), "nonTunaiOut" => $nonTunai->count(), // ========= MASUK ========= "masuk" => [ "casual" => [ "jumlah" => $masuk->count(), "income" => $masukCasual->sum("bayar_masuk"), ], "member" => [ "jumlah" => $masukMember->count(), "income" => $masukMember->sum("bayar_masuk"), ], ], // ========= KELUAR ========= "keluar" => [ "casual" => [ "jumlah" => $keluarCasual->count(), "income" => $keluarCasual->sum("bayar_keluar"), ], "lost" => [ "jumlah" => $keluarLost->count(), "income" => $keluarLost->sum("bayar_keluar"), ], "member" => [ "jumlah" => $keluarMember->count(), "income" => $keluarMember->sum("bayar_keluar"), ], "manual" => [ "jumlah" => $keluarManual->count(), "income" => $keluarManual->sum("bayar_keluar"), ], ], "totalCashless" => $totalCashless, ]; }) ->values(); // $transactions = DB::table("transaksi_parkir as tp") $transactions = $this->parking ->useTableParkir(Auth::user()) ->leftJoin("jenis_mobil as jm", "jm.id", "=", "tp.id_kendaraan") ->leftJoin("pegawai as pm", "pm.nomer", "=", "tp.id_op_masuk") ->leftJoin("pegawai as pk", "pk.nomer", "=", "tp.id_op_keluar") ->whereDate("waktu_masuk", "<", $dateNow) ->select( "tp.id_kendaraan", "jm.nama as jenis_mobil", DB::raw("SUM(CASE WHEN tp.status = 1 THEN 1 ELSE 0 END) as overnight"), DB::raw("SUM(CASE WHEN tp.status = 3 THEN 1 ELSE 0 END) as onexpired"), ) ->groupBy("tp.id_kendaraan", "jm.nama") ->orderBy("tp.id_kendaraan") // dd($transactions->toSql()); ->get(); $onCheck = $transactions // ->sortBy('id_kendaraan') // ->groupBy('id_kendaraan') ->map(function ($items) { // $overNight = $items->filter(fn ($r) => (int) $r->status === 1); // $onExpired = $items->filter(fn ($r) => (int) $r->status === 3); return [ "id_kendaraan" => $items->id_kendaraan, "jenis_mobil" => $items->jenis_mobil, "overNight" => (int) $items->overnight, "onExpired" => (int) $items->onexpired, ]; }) ->values(); Log::info("Rekap kendaraan selesai", [ "total_kendaraan" => $tunai->count(), ]); Log::info("== allReportData END ==", [ "total_time_ms" => round((microtime(true) - $start) * 1000, 2), ]); return [ // 'date' => $startDate->format('Y-m-d'),รท "location" => $GlobalParams, "date" => $startDate, "reportTime" => $isReport, "tunai" => $tunai, "nontunai" => $cashless, "overNight" => $onCheck, // 'transactions' => $transactions->groupBy('id_kendaraan') ]; } // ==========###################### Begin Laporan per petugas #######################===============// public function reportOfficer(Request $request) { Log::info("== Officer Report START =="); Log::info($request->harian); Log::info($request->tanggal); $selectDate = $request->tanggal; $start = microtime(true); $harian = $request->harian ?? 1; // $selectDate = Carbon::createFromFormat("", $tanggalRequest)->format("Y-m-d"); // $dateNow = Carbon::now()->format('Y-m-d'); $dateNow = "2026-01-25"; // $startDate = Carbon::today()->startOfDay(); // $endDate = Carbon::today()->endOfDay(); // $startDate = $selectDate . ' 00:00:00'; // $endDate = $selectDate . ' 23:59:59'; $startDate = $selectDate ? $selectDate : $dateNow; $endDate = $selectDate ? $selectDate : $dateNow; Log::info("Tanggal laporan", [ "start" => $startDate, "end" => $endDate, ]); // ========================= // QUERY UTAMA (LEFT JOIN) // ========================= Log::info("Query transaksi dimulai"); // $dateColumn = $harian == 1 // ? 'tp.waktu_keluar' // : 'tp.pklogin'; if ($harian == 1) { $dateColumn = ["tp.waktu_masuk", "tp.waktu_keluar"]; $dateColumn = ["tp.waktu_keluar"]; } else { $dateColumn = ["tp.pmlogin", "tp.pklogin"]; $dateColumn = ["tp.pklogin"]; } // $transactions = DB::table("transaksi_parkir as tp") $transactions = $this->parking ->useTableParkir(Auth::user()) ->leftJoin("pegawai as p", "p.nomer", "=", "tp.id_op_keluar") // ->leftJoin("pegawai as pm", "pm.nomer", "=", "tp.id_op_masuk") // ->leftJoin("pegawai as pk", "pk.nomer", "=", "tp.id_op_keluar") ->where(function ($q) use ($dateColumn, $startDate, $endDate, $selectDate) { $q->whereBetween($dateColumn[0], [$startDate . " 00:00:00", $endDate . " 23:59:59"])->orWhereBetween( $dateColumn[0], [$startDate . " 00:00:00", $endDate . " 23:59:59"], ); // $q->whereRaw('DATE(tp.waktu_masuk) = ?', [$selectDate]) // ->orWhereRaw('DATE(tp.waktu_keluar) = ?', [$selectDate]); }) // ->whereNull("id_op_masuk") // ->where("manual", 1) // ->whereRaw("DATE($dateColumn) = ?", [$dateNow]) // ->whereBetween($dateColumn, [$startDate, $endDate]) ->select( "p.nomer as id_petugas", "p.nama as petugas", // "tp.id_kendaraan", // "pm.nama as kasir_masuk", // "pk.nama as kasir_keluar", "tp.id_op_masuk", // โœ… ADA "tp.id_op_keluar", "tp.waktu_masuk", "tp.waktu_keluar", "tp.status", "tp.bayar_masuk", "tp.bayar_keluar", "tp.status_transaksi", "tp.cara_bayar", ) ->get(); // Log::info("Result nya : " . json_encode($transactions)); Log::info("Query transaksi selesai", [ "rows" => $transactions->count(), "query_time_ms" => round((microtime(true) - $start) * 1000, 2), ]); // ========================= // REKAP PER KENDARAAN // ========================= Log::info("Rekap petugas dimulai"); $tunai = $transactions ->sortBy("petugas") ->groupBy("id_op_keluar") ->map(function ($items, $id_op_keluar) { // ====================== // PISAH MASUK & KELUAR // ====================== // $masuk = $items->where('status', 1); $masuk = $items->filter(fn($row) => in_array(data_get($row, "cara_bayar"), [null, 0, "0"], true)); // $keluar = $items->where('status', 0); $keluar = $items->filter(fn($r) => (int) $r->status === 0); // $tunai = $keluar->where('cara_bayar', '!=', 3); // ====================== // MASUK // ====================== // $masukCasual = $masuk->where('status_transaksi', '0'); // $masukMember = $masuk->where('status_transaksi', '3'); // ====================== // KELUAR // ====================== // $keluarCasual = $tunai->where('status_transaksi', '0'); // $keluarMember = $tunai->where('status_transaksi', '3'); // $keluarLost = $tunai->where('status_transaksi', '32'); $tunai = $keluar->filter(fn($row) => in_array(data_get($row, "cara_bayar"), [null, 0, "0"], true)); $keluarCasual = $tunai->filter( fn($r) => (string) data_get($r, "status_transaksi") === "0" && data_get($r, "id_op_masuk") !== null, ); $keluarLost = $tunai->filter(fn($r) => (string) data_get($r, "status_transaksi") === "32"); $keluarMember = $tunai->filter(fn($r) => (string) data_get($r, "status_transaksi") === "3"); $keluarManual = $tunai->filter(fn($r) => data_get($r, "id_op_masuk") === null); $keluarMix = $tunai->filter(fn($r) => data_get($r, "manual") === 1); $keluarMasalah = $tunai->filter(fn($r) => (string) data_get($r, "status_transaksi") === "-1"); // ====================== // PEMBAYARAN (KELUAR) // ====================== // $nonTunai = $keluar->where('cara_bayar', 3); // $tunai = $keluar->where('cara_bayar', '!=', 3); $totalCash = $keluarCasual->sum("bayar_keluar") + $keluarLost->sum("bayar_keluar") + $keluarMember->sum("bayar_keluar") + $keluarManual->sum("bayar_keluar"); Log::info("Transaksi tunai : "); return [ "id_petugas" => $id_op_keluar, "petugas" => $items->first()->petugas, "total" => 0, "tunaiOut" => $tunai->count(), // ========= MASUK ========= "masuk" => [ "casual" => [ "jumlah" => 0, "income" => $masuk->sum("bayar_masuk"), ], // 'member' => [ // 'jumlah' => $masukMember->count(), // 'income' => $masukMember->sum('bayar_masuk'), // ], ], // ========= KELUAR ========= "keluar" => [ "casual" => [ "jumlah" => $keluarCasual->count(), "income" => $keluarCasual->sum("bayar_keluar"), ], "lost" => [ "jumlah" => $keluarLost->count(), "income" => $keluarLost->sum("bayar_keluar"), ], "member" => [ "jumlah" => $keluarMember->count(), "income" => $keluarMember->sum("bayar_keluar"), ], "manual" => [ "jumlah" => $keluarManual->count(), "income" => $keluarManual->sum("bayar_keluar"), ], "masalah" => [ "jumlah" => $keluarMasalah->count(), "income" => $keluarMasalah->sum("bayar_keluar"), ], ], "totalCash" => $totalCash, ]; }) ->values(); $cashless = $transactions ->sortBy("id_op_keluar") ->groupBy("id_op_keluar") ->map(function ($items, $id_op_keluar) { // ====================== // PISAH MASUK & KELUAR // ====================== // $masuk = $items->where('status', 1); $masuk = $items->filter(fn($row) => in_array(data_get($row, "cara_bayar"), [null, 0, "0"], true)); // $keluar = $items->where('status', 0); // $nonTunai = $keluar->where('cara_bayar', 3); $keluar = $items->filter(fn($r) => (int) $r->status === 0); // $tunai = $keluar->where('cara_bayar', '!=', 3); $nonTunai = $keluar->filter(fn($row) => (string) data_get($row, "cara_bayar") === "3"); // ====================== // MASUK // ====================== // $masukCasual = $masuk->where('status_transaksi', '0'); // $masukMember = $masuk->where('status_transaksi', '3'); // ====================== // KELUAR // ====================== // $keluarCasual = $nonTunai->where('status_transaksi', '0'); // $keluarMember = $nonTunai->where('status_transaksi', '3'); // $keluarLost = $nonTunai->where('status_transaksi', '32'); $keluarCasual = $nonTunai->filter( fn($r) => (string) data_get($r, "status_transaksi") === "0" && data_get($r, "id_op_masuk") !== null, ); $keluarMember = $nonTunai->filter(fn($r) => (string) data_get($r, "status_transaksi") === "3"); $keluarLost = $nonTunai->filter(fn($r) => (string) data_get($r, "status_transaksi") === "32"); $keluarManual = $nonTunai->filter(fn($r) => data_get($r, "id_op_masuk") === null); $totalCashless = $keluarCasual->sum("bayar_keluar") + $keluarLost->sum("bayar_keluar") + $keluarMember->sum("bayar_keluar") + $keluarManual->sum("bayar_keluar"); // ====================== // PEMBAYARAN (KELUAR) // ====================== return [ "id_petugas" => $id_op_keluar, "petugas" => $items->first()->petugas, "total" => 0, "nonTunaiOut" => $nonTunai->count(), // ========= MASUK ========= "masuk" => [ "casual" => [ "jumlah" => 0, "income" => $masuk->sum("bayar_masuk"), ], "member" => [ "jumlah" => $masuk->count(), "income" => $masuk->sum("bayar_masuk"), ], ], // ========= KELUAR ========= "keluar" => [ "casual" => [ "jumlah" => $keluarCasual->count(), "income" => $keluarCasual->sum("bayar_keluar"), ], "lost" => [ "jumlah" => $keluarLost->count(), "income" => $keluarLost->sum("bayar_keluar"), ], "member" => [ "jumlah" => $keluarMember->count(), "income" => $keluarMember->sum("bayar_keluar"), ], "manual" => [ "jumlah" => $keluarManual->count(), "income" => $keluarManual->sum("bayar_keluar"), ], ], "totalCashless" => $totalCashless, ]; }) ->values(); // $transactions = DB::table("transaksi_parkir as tp") // ->leftJoin("pegawai as p", "p.nomer", "=", "tp.id_op_keluar") // ->leftJoin("pegawai as pm", "pm.nomer", "=", "tp.id_op_masuk") // ->leftJoin("pegawai as pk", "pk.nomer", "=", "tp.id_op_keluar") // ->whereDate("waktu_masuk", "<", $dateNow) // ->select( // "tp.id_kendaraan", // "p.nama as jenis_mobil", // "tp.id_op_keluar", // "p.nama as petugas", // DB::raw("SUM(CASE WHEN tp.status = 1 THEN 1 ELSE 0 END) as overnight"), // DB::raw("SUM(CASE WHEN tp.status = 3 THEN 1 ELSE 0 END) as onexpired"), // ) // ->groupBy("tp.id_op_keluar", "petugas") // ->orderBy("tp.id_op_keluar", "asc") // ->groupBy("p.nomer", "p.nama") // ->orderBy("p.nomer") // dd($transactions->toSql()); // ->get(); // $onCheck = $transactions // ->sortBy('id_kendaraan') // ->groupBy('id_kendaraan') // ->map(function ($items) { // $overNight = $items->filter(fn ($r) => (int) $r->status === 1); // $onExpired = $items->filter(fn ($r) => (int) $r->status === 3); // return [ // "id_petugas" => $items->id_op_keluar, // "petugas" => $items->petugas, // "overNight" => (int) $items->overnight, // "onExpired" => (int) $items->onexpired, // ]; // }) // ->values(); Log::info("Rekap kendaraan selesai", [ "total_kendaraan" => $tunai->count(), ]); Log::info("== allReportData END ==", [ "total_time_ms" => round((microtime(true) - $start) * 1000, 2), ]); return [ "date" => $startDate, "tunai" => $tunai, "nontunai" => $cashless, ]; } // ========== End Laporan per petugas ===============/// // ==========###################### Begin Laporan per petugas #######################===============// public function paymentType(Request $request) { Log::info("== Officer Report START =="); Log::info($request->harian); Log::info($request->tanggal); $selectDate = $request->tanggal; $start = microtime(true); $harian = $request->harian ?? 1; $dateNow = "2026-01-25"; $startDate = $selectDate ? $selectDate : $dateNow; $endDate = $selectDate ? $selectDate : $dateNow; Log::info("Tanggal laporan", [ "start" => $startDate, "end" => $endDate, ]); // ============= QUERY UTAMA (LEFT JOIN) ========================= Log::info("Query transaksi dimulai"); if ($harian == 1) { // $dateColumn = ["tp.waktu_keluar"]; $dateColumn = ["tp.waktu_masuk", "tp.waktu_keluar"]; } else { // $dateColumn = ["tp.pklogin"]; $dateColumn = ["tp.pmlogin", "tp.pklogin"]; } // $transactions = DB::table("transaksi_parkir as tp") $transactions = $this->parking ->useTableParkir(Auth::user()) // ->leftJoin("pegawai as p", "p.nomer", "=", "tp.id_op_keluar") // ->leftJoin("pegawai as pm", "pm.nomer", "=", "tp.id_op_masuk") // ->leftJoin("pegawai as pk", "pk.nomer", "=", "tp.id_op_keluar") ->where(function ($q) use ($dateColumn, $startDate, $endDate, $selectDate) { $q->whereBetween($dateColumn[0], [$startDate . " 00:00:00", $endDate . " 23:59:59"])->orWhereBetween( $dateColumn[0], [$startDate . " 00:00:00", $endDate . " 23:59:59"], ); // $q->whereRaw('DATE(tp.waktu_masuk) = ?', [$selectDate]) // ->orWhereRaw('DATE(tp.waktu_keluar) = ?', [$selectDate]); }) // ->whereRaw("DATE($dateColumn) = ?", [$dateNow]) // ->whereBetween($dateColumn, [$startDate, $endDate]) ->select( "rep_bank as bankType", // "p.nomer as id_petugas", // "p.nama as petugas", // "tp.id_kendaraan", // "pm.nama as kasir_masuk", // "pk.nama as kasir_keluar", "tp.id_op_masuk", // โœ… ADA "tp.id_op_keluar", "tp.waktu_masuk", "tp.waktu_keluar", "tp.status", "tp.bayar_masuk", "tp.bayar_keluar", "tp.status_transaksi", "tp.cara_bayar", ) ->get(); Log::info("Query transaksi selesai", [ "rows" => $transactions->count(), "query_time_ms" => round((microtime(true) - $start) * 1000, 2), ]); Log::info("Rekap payment dimulai"); $tunai = $transactions ->sortBy("bankType") ->groupBy("bankType") ->map(function ($items, $bankType) { $keluar = $items->filter(fn($r) => (int) $r->status === 0); $tunai = $keluar->filter(fn($row) => in_array(data_get($row, "cara_bayar"), [null, 0, "0"], true)); $keluarCasual = $tunai->filter( fn($r) => (string) data_get($r, "status_transaksi") === "0" && data_get($r, "id_op_masuk") !== null, ); $keluarMember = $tunai->filter(fn($r) => (string) data_get($r, "status_transaksi") === "3"); $keluarLost = $tunai->filter(fn($r) => (string) data_get($r, "status_transaksi") === "32"); $keluarManual = $tunai->filter(fn($r) => data_get($r, "id_op_masuk") === null); $keluarMasalah = $tunai->filter(fn($r) => (string) data_get($r, "status_transaksi") === "-1"); $totalCash = $keluarCasual->sum("bayar_keluar") + $keluarLost->sum("bayar_keluar") + $keluarMember->sum("bayar_keluar") + $keluarManual->sum("bayar_keluar"); Log::info("Transaksi tunai : "); return [ "typePayment" => $bankType, "petugas" => $items->first()->bankType, "total" => $items->count(), "tunaiOut" => $tunai->count(), "masuk" => [ "casual" => [ "jumlah" => 0, "income" => 0, ], ], "keluar" => [ "casual" => [ "jumlah" => $keluarCasual->count(), "income" => $keluarCasual->sum("bayar_keluar"), ], "lost" => [ "jumlah" => $keluarLost->count(), "income" => $keluarLost->sum("bayar_keluar"), ], "member" => [ "jumlah" => $keluarMember->count(), "income" => $keluarMember->sum("bayar_keluar"), ], "manual" => [ "jumlah" => $keluarManual->count(), "income" => $keluarManual->sum("bayar_keluar"), ], "masalah" => [ "jumlah" => $keluarMasalah->count(), "income" => $keluarMasalah->sum("bayar_keluar"), ], ], "totalCash" => $totalCash, ]; }) ->values(); $cashless = $transactions ->sortBy("bankType") ->groupBy("bankType") ->map(function ($items, $bankType) { $keluar = $items->filter(fn($r) => (int) $r->status === 0); $nonTunai = $keluar->filter(fn($row) => (string) data_get($row, "cara_bayar") === "3"); $keluarCasual = $nonTunai->filter( fn($r) => (string) data_get($r, "status_transaksi") === "0" && data_get($r, "id_op_masuk") !== null, ); $keluarMember = $nonTunai->filter(fn($r) => (string) data_get($r, "status_transaksi") === "3"); $keluarLost = $nonTunai->filter(fn($r) => (string) data_get($r, "status_transaksi") === "32"); $keluarManual = $nonTunai->filter(fn($r) => data_get($r, "id_op_masuk") === null); $totalCashless = $keluarCasual->sum("bayar_keluar") + $keluarLost->sum("bayar_keluar") + $keluarMember->sum("bayar_keluar") + $keluarManual->sum("bayar_keluar"); // ====================== // PEMBAYARAN (KELUAR) // ====================== return [ "typePayment" => $bankType, "petugas" => $items->first()->bankType, "total" => $items->count(), "nonTunaiOut" => $nonTunai->count(), "masuk" => [ "casual" => [ "jumlah" => 0, "income" => 0, ], ], "keluar" => [ "casual" => [ "jumlah" => $keluarCasual->count(), "income" => $keluarCasual->sum("bayar_keluar"), ], "lost" => [ "jumlah" => $keluarLost->count(), "income" => $keluarLost->sum("bayar_keluar"), ], "member" => [ "jumlah" => $keluarMember->count(), "income" => $keluarMember->sum("bayar_keluar"), ], "manual" => [ "jumlah" => $keluarManual->count(), "income" => $keluarManual->sum("bayar_keluar"), ], ], "totalCashless" => $totalCashless, ]; }) ->values(); Log::info("Rekap kendaraan selesai", [ "total_kendaraan" => $tunai->count(), ]); Log::info("== allReportData END ==", [ "total_time_ms" => round((microtime(true) - $start) * 1000, 2), ]); return [ "date" => $startDate, "tunai" => $tunai, "nontunai" => $cashless, ]; } // ========== End Laporan payment Type ===============/// }