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.
232 lines
7.8 KiB
PHP
232 lines
7.8 KiB
PHP
<?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');
|
|
}
|
|
}
|
|
} |