- Tambah routing, breadcrumbs, menu, dan views (index + detail) - Controller: index/show, datatables (filter multi-kolom, sorting, pagination), impor Excel (transaksi + logging) - Import: updateOrCreate by nomor_tiket, normalisasi tanggal & numerik, statistik impor - Migrasi: semua kolom bisnis → string untuk konsistensi input Excel; nomor_tiket unique + index - UX: DataTable dengan filter (tahun, bulan, cost center, status), tombol import, detail tiket BREAKING CHANGE: - Semua kolom bisnis kini bertipe string → perlu sesuaikan casts di model Bucok & filter tanggal/numerik di controller
210 lines
7.8 KiB
PHP
210 lines
7.8 KiB
PHP
<?php
|
|
|
|
namespace Modules\Lpj\Http\Controllers;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use Exception;
|
|
use Illuminate\Http\Request;
|
|
use Maatwebsite\Excel\Facades\Excel;
|
|
use Modules\Lpj\Imports\BucokImport;
|
|
use Modules\Lpj\Models\Bucok;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
/**
|
|
* Controller untuk mengelola data Bucok
|
|
*
|
|
* @package Modules\Lpj\Http\Controllers
|
|
*/
|
|
class BucokController extends Controller
|
|
{
|
|
public $user;
|
|
|
|
/**
|
|
* Menampilkan halaman index bucok
|
|
*
|
|
* @return \Illuminate\View\View
|
|
*/
|
|
public function index()
|
|
{
|
|
return view('lpj::bucok.index');
|
|
}
|
|
|
|
/**
|
|
* Menampilkan detail bucok
|
|
*
|
|
* @param int $id
|
|
* @return \Illuminate\View\View
|
|
*/
|
|
public function show($id)
|
|
{
|
|
$bucok = Bucok::findOrFail($id);
|
|
return view('lpj::bucok.show', compact('bucok'));
|
|
}
|
|
|
|
/**
|
|
* Data untuk datatables dengan server-side processing
|
|
*
|
|
* @param Request $request
|
|
* @return \Illuminate\Http\JsonResponse
|
|
*/
|
|
public function dataForDatatables(Request $request)
|
|
{
|
|
if (is_null($this->user) || !$this->user->can('bucok.view')) {
|
|
// abort(403, 'Sorry! You are not allowed to view bucok.');
|
|
}
|
|
|
|
// Retrieve data from the database
|
|
$query = Bucok::query();
|
|
|
|
// Apply search filter if provided
|
|
if ($request->has('search') && !empty($request->get('search'))) {
|
|
$search = $request->get('search');
|
|
$query->where(function ($q) use ($search) {
|
|
$q->where('nomor_tiket', 'LIKE', "%$search%")
|
|
->orWhere('deskripsi', 'LIKE', "%$search%")
|
|
->orWhere('nomor_coa', 'LIKE', "%$search%")
|
|
->orWhere('nama_coa', 'LIKE', "%$search%")
|
|
->orWhere('cost_center', 'LIKE', "%$search%")
|
|
->orWhere('nama_sub_direktorat', 'LIKE', "%$search%")
|
|
->orWhere('nama_direktorat_cabang', 'LIKE', "%$search%")
|
|
->orWhere('penyelesaian', 'LIKE', "%$search%")
|
|
->orWhere('keterangan_gantung', 'LIKE', "%$search%");
|
|
});
|
|
}
|
|
|
|
// Apply date range filter
|
|
if ($request->has('start_date') && !empty($request->get('start_date'))) {
|
|
$query->whereDate('tanggal', '>=', $request->get('start_date'));
|
|
}
|
|
if ($request->has('end_date') && !empty($request->get('end_date'))) {
|
|
$query->whereDate('tanggal', '<=', $request->get('end_date'));
|
|
}
|
|
|
|
// Apply year filter
|
|
if ($request->has('year') && !empty($request->get('year'))) {
|
|
$query->byYear($request->get('year'));
|
|
}
|
|
|
|
// Apply month filter
|
|
if ($request->has('month') && !empty($request->get('month'))) {
|
|
$query->byMonth($request->get('month'));
|
|
}
|
|
|
|
// Apply cost center filter
|
|
if ($request->has('cost_center') && !empty($request->get('cost_center'))) {
|
|
$query->byCostCenter($request->get('cost_center'));
|
|
}
|
|
|
|
// Apply completion status filter
|
|
if ($request->has('completion_status') && $request->get('completion_status') !== '') {
|
|
$isCompleted = $request->get('completion_status') == '1';
|
|
$query->byCompletionStatus($isCompleted);
|
|
}
|
|
|
|
// Apply sorting if provided
|
|
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
|
|
$order = $request->get('sortOrder');
|
|
$column = $request->get('sortField', 'created_at');
|
|
$query->orderBy($column, $order);
|
|
} else {
|
|
$query->orderBy('created_at', 'desc');
|
|
}
|
|
|
|
// Get the total count of records
|
|
$totalRecords = $query->count();
|
|
|
|
// Apply pagination if provided
|
|
if ($request->has('page') && $request->has('size')) {
|
|
$page = $request->get('page');
|
|
$size = $request->get('size');
|
|
$offset = ($page - 1) * $size; // Calculate the offset
|
|
|
|
$query->skip($offset)->take($size);
|
|
}
|
|
|
|
// Get the filtered count of records
|
|
$filteredRecords = $query->count();
|
|
|
|
// Get the data for the current page with relationships
|
|
$data = $query->get();
|
|
|
|
// Transform data untuk datatables
|
|
$transformedData = $data->map(function ($item) {
|
|
return [
|
|
'id' => $item->id,
|
|
'no' => $item->no,
|
|
'tanggal' => $item->tanggal ? dateFormat($item->tanggal,true) : '-',
|
|
'bulan' => $item->bulan,
|
|
'tahun' => $item->tahun,
|
|
'nomor_tiket' => $item->nomor_tiket,
|
|
'nomor_coa' => $item->nomor_coa,
|
|
'nama_coa' => $item->nama_coa,
|
|
'deskripsi' => $item->deskripsi,
|
|
'nominal' => $item->nominal_formatted,
|
|
'penyelesaian' => $item->penyelesaian,
|
|
'umur_aging' => $item->umur_aging,
|
|
'cost_center' => $item->cost_center,
|
|
'nama_sub_direktorat' => $item->nama_sub_direktorat,
|
|
'nama_direktorat_cabang' => $item->nama_direktorat_cabang,
|
|
'tanggal_penyelesaian' => $item->tanggal_penyelesaian ? dateFormat($item->tanggal_penyelesaian,true) : '-',
|
|
'nominal_penyelesaian' => $item->nominal_penyelesaian_formatted,
|
|
'status_penyelesaian' => $item->status_penyelesaian,
|
|
'status_badge' => $item->status_badge,
|
|
'created_by' => $item->creator?->name ?? '-',
|
|
'created_at' => dateFormat($item->created_at,true)
|
|
];
|
|
});
|
|
|
|
// Calculate the page count
|
|
$pageCount = ceil($totalRecords / ($request->get('size', 10)));
|
|
|
|
// Calculate the current page number
|
|
$currentPage = $request->get('page', 1);
|
|
|
|
// Return the response data as a JSON object
|
|
return response()->json([
|
|
'draw' => $request->get('draw'),
|
|
'recordsTotal' => $totalRecords,
|
|
'recordsFiltered' => $filteredRecords,
|
|
'pageCount' => $pageCount,
|
|
'page' => $currentPage,
|
|
'totalCount' => $totalRecords,
|
|
'data' => $transformedData,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Import data bucok dari Excel
|
|
*
|
|
* @param Request $request
|
|
* @return \Illuminate\Http\RedirectResponse
|
|
*/
|
|
public function import(Request $request)
|
|
{
|
|
$request->validate([
|
|
'file' => 'required|mimes:xlsx,xls,csv|max:10240' // Max 10MB
|
|
]);
|
|
|
|
DB::beginTransaction();
|
|
try {
|
|
Log::info('Importing Bucok data', ['user_id' => Auth::id(), 'filename' => $request->file('file')->getClientOriginalName()]);
|
|
|
|
$import = new BucokImport();
|
|
Excel::import($import, $request->file('file'));
|
|
$statistics = $import->getImportStatistics();
|
|
|
|
DB::commit();
|
|
Log::info('Bucok data imported successfully', ['user_id' => Auth::id()]);
|
|
|
|
return redirect()->back()->with('success', 'Data Bucok berhasil diimport. Total: ' . $statistics['total_processed'] . ', Created: ' . $statistics['created'] . ', Updated: ' . $statistics['updated'] . ', Skipped: ' . $statistics['skipped'] . ', Errors: ' . $statistics['errors']);
|
|
} catch (Exception $e) {
|
|
DB::rollback();
|
|
Log::error('Failed to import Bucok data', ['error' => $e->getMessage(), 'user_id' => Auth::id()]);
|
|
|
|
return redirect()->back()->with('error', 'Gagal import data: ' . $e->getMessage());
|
|
}
|
|
}
|
|
}
|