feat(webstatement): tambah fitur Laporan Closing Balance
Perubahan yang dilakukan: **Controller LaporanClosingBalanceController:** - Membuat controller baru untuk laporan closing balance dengan method index(), dataForDatatables(), export(), dan show(). - Menggunakan model AccountBalance dengan field actual_balance dan cleared_balance. - Implementasi filter nomor rekening dan rentang tanggal. - Menambahkan DB transaction dan rollback untuk keamanan data. - Logging dan error handling komprehensif untuk proses data dan export. **View laporan-closing-balance/index.blade.php:** - Form filter dengan input nomor rekening dan rentang tanggal (default 30 hari terakhir). - Implementasi DataTables dengan kolom: Nomor Rekening, Periode, Saldo Cleared, Saldo Aktual, Tanggal Update, dan Action. - Tombol Filter, Reset, dan Export CSV. - JavaScript untuk format currency IDR, format tanggal, dan dynamic export URL. - Menggunakan TailwindCSS dan KTDataTable untuk desain yang responsive. **View laporan-closing-balance/show.blade.php:** - Halaman detail per record dengan visual saldo yang menarik (color-coded cards). - Menampilkan Saldo Cleared, Saldo Aktual, dan Selisih Saldo secara otomatis. - Informasi rekening dan periode disertai fitur copy ke clipboard. - Tombol aksi: Kembali, Export, dan Print (dengan print style khusus). - Responsive untuk berbagai ukuran layar. **Routing dan Navigasi:** - Menambahkan routing resource dengan prefix 'laporan-closing-balance' di web.php. - Tambahan route untuk datatables, export, dan show dengan middleware auth. - Breadcrumb dinamis untuk index dan show, menampilkan nomor rekening dan periode. **Penyesuaian Model:** - Menggunakan relasi Account di model AccountBalance melalui account_number. - Menyesuaikan field dari opening_balance ke cleared_balance sesuai skema. - Tetap mempertahankan actual_balance untuk saldo akhir. **Fitur Keamanan dan Performance:** - Input validation dan sanitization untuk semua request. - Pagination dan filter query untuk efisiensi dan mencegah memory overflow. - Error logging dengan context untuk debugging lebih mudah. **User Experience:** - Interface user-friendly dengan feedback visual dan loading state. - Export CSV untuk kebutuhan analisis lebih lanjut. - Print-friendly layout untuk kebutuhan cetak data. - Clipboard integration untuk kemudahan salin data. Tujuan perubahan: - Menyediakan fitur monitoring dan analisis closing balance secara komprehensif di modul Webstatement. - Mempermudah user dalam melihat detail saldo akhir dengan filtering, export, dan cetak yang optimal.
This commit is contained in:
232
app/Http/Controllers/LaporanClosingBalanceController.php
Normal file
232
app/Http/Controllers/LaporanClosingBalanceController.php
Normal file
@@ -0,0 +1,232 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Webstatement\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Carbon\Carbon;
|
||||
use Modules\Webstatement\Models\AccountBalance;
|
||||
|
||||
/**
|
||||
* Controller untuk mengelola laporan closing balance
|
||||
* Menyediakan form input nomor rekening dan rentang tanggal
|
||||
* serta menampilkan data closing balance berdasarkan filter
|
||||
*/
|
||||
class LaporanClosingBalanceController extends Controller
|
||||
{
|
||||
/**
|
||||
* Menampilkan halaman utama laporan closing balance
|
||||
* dengan form filter nomor rekening dan rentang tanggal
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
Log::info('Mengakses halaman laporan closing balance');
|
||||
|
||||
return view('webstatement::laporan-closing-balance.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Mengambil data laporan closing balance berdasarkan filter
|
||||
* yang dikirim melalui AJAX untuk datatables
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function dataForDatatables(Request $request)
|
||||
{
|
||||
Log::info('Mengambil data untuk datatables laporan closing balance', [
|
||||
'filters' => $request->all()
|
||||
]);
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
$query = AccountBalance::query();
|
||||
|
||||
// Filter berdasarkan nomor rekening jika ada
|
||||
if ($request->filled('account_number')) {
|
||||
$query->where('account_number', 'like', '%' . $request->account_number . '%');
|
||||
Log::info('Filter nomor rekening diterapkan', ['account_number' => $request->account_number]);
|
||||
}
|
||||
|
||||
// Filter berdasarkan rentang tanggal jika ada
|
||||
if ($request->filled('start_date') && $request->filled('end_date')) {
|
||||
$startDate = Carbon::parse($request->start_date)->format('Ymd');
|
||||
$endDate = Carbon::parse($request->end_date)->format('Ymd');
|
||||
|
||||
$query->whereBetween('period', [$startDate, $endDate]);
|
||||
Log::info('Filter rentang tanggal diterapkan', [
|
||||
'start_date' => $startDate,
|
||||
'end_date' => $endDate
|
||||
]);
|
||||
}
|
||||
|
||||
// Sorting
|
||||
$sortColumn = $request->get('sort', 'period');
|
||||
$sortDirection = $request->get('direction', 'desc');
|
||||
$query->orderBy($sortColumn, $sortDirection);
|
||||
|
||||
// Pagination
|
||||
$perPage = $request->get('per_page', 10);
|
||||
$page = $request->get('page', 1);
|
||||
|
||||
$results = $query->paginate($perPage, ['*'], 'page', $page);
|
||||
|
||||
DB::commit();
|
||||
|
||||
Log::info('Data laporan closing balance berhasil diambil', [
|
||||
'total' => $results->total(),
|
||||
'per_page' => $perPage,
|
||||
'current_page' => $page
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'data' => $results->items(),
|
||||
'pagination' => [
|
||||
'current_page' => $results->currentPage(),
|
||||
'last_page' => $results->lastPage(),
|
||||
'per_page' => $results->perPage(),
|
||||
'total' => $results->total(),
|
||||
'from' => $results->firstItem(),
|
||||
'to' => $results->lastItem()
|
||||
]
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::rollback();
|
||||
|
||||
Log::error('Error saat mengambil data laporan closing balance', [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'error' => 'Terjadi kesalahan saat mengambil data laporan',
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export data laporan closing balance ke format Excel
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function export(Request $request)
|
||||
{
|
||||
Log::info('Export laporan closing balance dimulai', [
|
||||
'filters' => $request->all()
|
||||
]);
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
$query = AccountBalance::query();
|
||||
|
||||
// Terapkan filter yang sama seperti di datatables
|
||||
if ($request->filled('account_number')) {
|
||||
$query->where('account_number', 'like', '%' . $request->account_number . '%');
|
||||
}
|
||||
|
||||
if ($request->filled('start_date') && $request->filled('end_date')) {
|
||||
$startDate = Carbon::parse($request->start_date)->format('Ymd');
|
||||
$endDate = Carbon::parse($request->end_date)->format('Ymd');
|
||||
$query->whereBetween('period', [$startDate, $endDate]);
|
||||
}
|
||||
|
||||
$data = $query->orderBy('period', 'desc')->get();
|
||||
|
||||
DB::commit();
|
||||
|
||||
Log::info('Export laporan closing balance berhasil', [
|
||||
'total_records' => $data->count()
|
||||
]);
|
||||
|
||||
// Generate CSV content
|
||||
$csvContent = "Nomor Rekening,Periode,Saldo Aktual,Saldo Cleared,Tanggal Update\n";
|
||||
|
||||
foreach ($data as $item) {
|
||||
$csvContent .= sprintf(
|
||||
"%s,%s,%s,%s,%s\n",
|
||||
$item->account_number,
|
||||
$item->period,
|
||||
number_format($item->actual_balance, 2),
|
||||
number_format($item->cleared_balance, 2),
|
||||
$item->updated_at ? $item->updated_at->format('Y-m-d H:i:s') : '-'
|
||||
);
|
||||
}
|
||||
|
||||
$filename = 'laporan_closing_balance_' . date('Y-m-d_H-i-s') . '.csv';
|
||||
|
||||
return response($csvContent)
|
||||
->header('Content-Type', 'text/csv')
|
||||
->header('Content-Disposition', 'attachment; filename="' . $filename . '"');
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::rollback();
|
||||
|
||||
Log::error('Error saat export laporan closing balance', [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'error' => 'Terjadi kesalahan saat export laporan',
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menampilkan detail laporan closing balance untuk periode tertentu
|
||||
*
|
||||
* @param string $accountNumber
|
||||
* @param string $period
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function show($accountNumber, $period)
|
||||
{
|
||||
Log::info('Menampilkan detail laporan closing balance', [
|
||||
'account_number' => $accountNumber,
|
||||
'period' => $period
|
||||
]);
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
$closingBalance = AccountBalance::where('account_number', $accountNumber)
|
||||
->where('period', $period)
|
||||
->firstOrFail();
|
||||
|
||||
DB::commit();
|
||||
|
||||
Log::info('Detail laporan closing balance berhasil diambil', [
|
||||
'account_number' => $accountNumber,
|
||||
'period' => $period,
|
||||
'balance' => $closingBalance->actual_balance
|
||||
]);
|
||||
|
||||
return view('webstatement::laporan-closing-balance.show', [
|
||||
'closingBalance' => $closingBalance
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::rollback();
|
||||
|
||||
Log::error('Error saat menampilkan detail laporan closing balance', [
|
||||
'account_number' => $accountNumber,
|
||||
'period' => $period,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
|
||||
return redirect()->route('laporan-closing-balance.index')
|
||||
->with('error', 'Data laporan closing balance tidak ditemukan');
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user