Kumpulan perubahan yang udah numpuk di working tree: refactor Setup (Gate/Vehicle/Member), rapihin memberin & stiker, service parking baru (ParkingUtilsServices, NetworkService), model/migration lot-parking & DHCP reservation, dan fitur baru Intercom (controller/model/migration/ view). ReportTransaksiController versi lokal ini WIP (~90%, masih didebug) - versi yang bener ada di server, jadi dikeluarin dari git (ditambahin ke .gitignore) biar gak numpuk nindihin punya server pas git pull di sana. Sekalian keluarin dump mentah tabel softseting (1.8MB, nyasar ke-commit), file .bak, dan arsip ad-hoc (api.tgz, c.zip) yang emang bukan source code. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01EAJc2mrpj2cSTe4oowLPzQ
200 lines
5.7 KiB
PHP
200 lines
5.7 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Parking\Operasional;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Symfony\Component\HttpFoundation\StreamedResponse;
|
|
|
|
class TransaksiParkirController extends Controller
|
|
{
|
|
/**
|
|
* Display a listing of the resource.
|
|
*
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function index()
|
|
{
|
|
return view ('operasional.transaksi-parkir');
|
|
}
|
|
|
|
/**
|
|
* Data transaksi parkir dengan filter pencarian.
|
|
*
|
|
* Filter (semua opsional):
|
|
* - field: id | no_pol | no_barcode, + q: kata kunci
|
|
* - tgl_awal / tgl_akhir (Y-m-d): periode kolom tanggal
|
|
* - status_kendaraan: 1 = masuk, 0 = keluar
|
|
* - status_transaksi: 0 = casual, 3 = member, 32 = denda
|
|
* - export=csv: unduh hasil filter sebagai CSV
|
|
*/
|
|
public function data(Request $request)
|
|
{
|
|
$request->validate([
|
|
'field' => 'nullable|in:id,no_pol,no_barcode',
|
|
'q' => 'nullable|string|max:100',
|
|
'tgl_awal' => 'nullable|date_format:Y-m-d',
|
|
'tgl_akhir' => 'nullable|date_format:Y-m-d|after_or_equal:tgl_awal',
|
|
'status_kendaraan' => 'nullable|in:0,1',
|
|
'status_transaksi' => 'nullable|in:0,3,32',
|
|
'per_page' => 'nullable|integer|min:1|max:500',
|
|
]);
|
|
|
|
$query = $this->filteredQuery($request);
|
|
|
|
if ($request->query('export') === 'csv') {
|
|
return $this->exportCsv($query);
|
|
}
|
|
|
|
$perPage = (int) $request->input('per_page', 50);
|
|
$rows = $query->paginate($perPage);
|
|
|
|
return response()->json([
|
|
'status' => true,
|
|
'data' => $rows->items(),
|
|
'meta' => [
|
|
'current_page' => $rows->currentPage(),
|
|
'per_page' => $rows->perPage(),
|
|
'total' => $rows->total(),
|
|
'last_page' => $rows->lastPage(),
|
|
],
|
|
]);
|
|
}
|
|
|
|
protected function filteredQuery(Request $request)
|
|
{
|
|
$query = DB::table('transaksi_parkir as tp')
|
|
->leftJoin('jenis_mobil as jm', 'jm.id', '=', 'tp.id_kendaraan')
|
|
->select(
|
|
'tp.id',
|
|
'tp.no_pol',
|
|
'tp.no_barcode',
|
|
'tp.id_kendaraan',
|
|
'jm.nama as nama_kendaraan',
|
|
'tp.status',
|
|
'tp.status_transaksi',
|
|
'tp.waktu_masuk',
|
|
'tp.waktu_keluar',
|
|
'tp.tanggal'
|
|
);
|
|
|
|
// 1. Pencarian: id / no_pol / no_barcode
|
|
if ($request->filled('q')) {
|
|
$field = $request->input('field', 'id');
|
|
$query->where("tp.{$field}", 'ILIKE', '%' . $request->input('q') . '%');
|
|
}
|
|
|
|
// 2. Periode awal - akhir (kolom tanggal)
|
|
if ($request->filled('tgl_awal')) {
|
|
$query->whereDate('tp.tanggal', '>=', $request->input('tgl_awal'));
|
|
}
|
|
if ($request->filled('tgl_akhir')) {
|
|
$query->whereDate('tp.tanggal', '<=', $request->input('tgl_akhir'));
|
|
}
|
|
|
|
// 3. Status kendaraan: 1 = masuk, 0 = keluar
|
|
if ($request->filled('status_kendaraan')) {
|
|
$query->where('tp.status', (int) $request->input('status_kendaraan'));
|
|
}
|
|
|
|
// 4. Status transaksi: 0 = casual, 3 = member, 32 = denda
|
|
if ($request->filled('status_transaksi')) {
|
|
$query->where('tp.status_transaksi', (int) $request->input('status_transaksi'));
|
|
}
|
|
|
|
return $query->orderBy('tp.tanggal', 'desc');
|
|
}
|
|
|
|
protected function exportCsv($query): StreamedResponse
|
|
{
|
|
$filename = 'transaksi-parkir-' . now()->format('Ymd-His') . '.csv';
|
|
|
|
return response()->streamDownload(function () use ($query) {
|
|
$out = fopen('php://output', 'w');
|
|
fputcsv($out, ['ID', 'No. Pol', 'Barcode', 'Kendaraan', 'Status Kendaraan', 'Status Transaksi', 'Waktu Masuk', 'Waktu Keluar']);
|
|
$query->chunk(1000, function ($rows) use ($out) {
|
|
foreach ($rows as $r) {
|
|
fputcsv($out, [
|
|
$r->id,
|
|
$r->no_pol,
|
|
$r->no_barcode,
|
|
trim(($r->id_kendaraan ?? '') . ' ' . ($r->nama_kendaraan ?? '')),
|
|
$r->status,
|
|
$r->status_transaksi,
|
|
$r->waktu_masuk,
|
|
$r->waktu_keluar,
|
|
]);
|
|
}
|
|
});
|
|
fclose($out);
|
|
}, $filename, ['Content-Type' => 'text/csv']);
|
|
}
|
|
|
|
/**
|
|
* Show the form for creating a new resource.
|
|
*
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function create()
|
|
{
|
|
//
|
|
}
|
|
|
|
/**
|
|
* Store a newly created resource in storage.
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function store(Request $request)
|
|
{
|
|
//
|
|
}
|
|
|
|
/**
|
|
* Display the specified resource.
|
|
*
|
|
* @param int $id
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function show($id)
|
|
{
|
|
//
|
|
}
|
|
|
|
/**
|
|
* Show the form for editing the specified resource.
|
|
*
|
|
* @param int $id
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function edit($id)
|
|
{
|
|
//
|
|
}
|
|
|
|
/**
|
|
* Update the specified resource in storage.
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @param int $id
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function update(Request $request, $id)
|
|
{
|
|
//
|
|
}
|
|
|
|
/**
|
|
* Remove the specified resource from storage.
|
|
*
|
|
* @param int $id
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function destroy($id)
|
|
{
|
|
//
|
|
}
|
|
}
|