From 1f4d37370e888b1c760ff1a99c546f5609eab457 Mon Sep 17 00:00:00 2001 From: Daeng Deni Mardaeni Date: Sun, 8 Jun 2025 23:42:25 +0700 Subject: [PATCH] feat(webstatement): tambahkan AtmTransactionReportController untuk pengelolaan laporan transaksi ATM - Menambahkan controller `AtmTransactionReportController` untuk mengelola laporan transaksi ATM. - Fungsi utama yang disediakan: 1. **index**: Menampilkan daftar laporan transaksi ATM. 2. **create**: Menampilkan form untuk permintaan laporan baru. 3. **store**: Menghandle penyimpanan permintaan laporan baru, termasuk validasi input, pembuatan log laporan, dan dispatching job. 4. **show**: Menampilkan detail laporan transaksi ATM berdasarkan log laporan. 5. **download**: Melakukan unduhan file laporan jika telah selesai diproses. 6. **authorize**: Menghandle otorisasi permintaan laporan, termasuk validasi status `approved` atau `rejected`. 7. **dataForDatatables**: Memberikan data laporan untuk tabular dengan filter, sorting, dan pagination. 8. **destroy**: Menghapus laporan transaksi ATM, termasuk file terkait jika ada. 9. **sendEmail**: Mengirim laporan ke email jika laporan dan alamat email tersedia. - Fitur tambahan: - Memastikan validasi input untuk keamanan data pengguna. - Menambahkan updating log laporan seperti status, error, hingga metadata unduhan. - Mendukung pencarian dan filtering data untuk pengelolaan laporan berjumlah besar. - Dispatch job `GenerateAtmTransactionReportJob` untuk menghasilkan laporan transaksi secara background: - Menambahkan log detail jika terjadi kegagalan saat dispatch. - Tujuan pembaruan: - Mempermudah pengelolaan dan pelacakan laporan transaksi ATM. - Menyediakan antarmuka user-friendly untuk pengguna, termasuk validasi dan feedback status laporan. - Meningkatkan fleksibilitas dan efisiensi pengelolaan laporan dengan mendukung filter, sorting, dan job asynchronous. Signed-off-by: Daeng Deni Mardaeni --- .../AtmTransactionReportController.php | 295 ++++++++++++++++++ 1 file changed, 295 insertions(+) create mode 100644 app/Http/Controllers/AtmTransactionReportController.php diff --git a/app/Http/Controllers/AtmTransactionReportController.php b/app/Http/Controllers/AtmTransactionReportController.php new file mode 100644 index 0000000..67157c5 --- /dev/null +++ b/app/Http/Controllers/AtmTransactionReportController.php @@ -0,0 +1,295 @@ +validate([ + 'report_date' => ['required', 'date_format:Y-m-d'], + ]); + + // Convert date to Ymd format for period + $period = Carbon::createFromFormat('Y-m-d', $validated['report_date'])->format('Ymd'); + + // Add user tracking data + $reportData = [ + 'period' => $period, + 'report_date' => $validated['report_date'], + 'user_id' => Auth::id(), + 'created_by' => Auth::id(), + 'ip_address' => $request->ip(), + 'user_agent' => $request->userAgent(), + 'status' => 'pending', + ]; + + // Create the report request log + $reportRequest = AtmTransactionReportLog::create($reportData); + + // Dispatch the job to generate the report + try { + GenerateAtmTransactionReportJob::dispatch($period, $reportRequest->id); + + $reportRequest->update([ + 'status' => 'processing', + 'updated_by' => Auth::id() + ]); + + } catch (Exception $e) { + $reportRequest->update([ + 'status' => 'failed', + 'error_message' => $e->getMessage(), + 'updated_by' => Auth::id() + ]); + } + + return redirect()->route('atm-reports.index') + ->with('success', 'ATM Transaction report request has been created successfully.'); + } + + /** + * Show the form for creating a new report request. + */ + public function create() + { + return view('webstatement::atm-reports.create', compact('branches')); + } + + /** + * Display the specified report request. + */ + public function show(AtmTransactionReportLog $atmReport) + { + $atmReport->load(['user', 'creator', 'authorizer']); + return view('webstatement::atm-reports.show', compact('atmReport')); + } + + /** + * Download the report if available. + */ + public function download(AtmTransactionReportLog $atmReport) + { + // Check if report is available + if ($atmReport->status !== 'completed' || !$atmReport->file_path) { + return back()->with('error', 'Report is not available for download.'); + } + + // Update download status + $atmReport->update([ + 'is_downloaded' => true, + 'downloaded_at' => now(), + 'updated_by' => Auth::id() + ]); + + // Download the file + $filePath = $atmReport->file_path; + if (Storage::exists($filePath)) { + $fileName = "atm_transaction_report_{$atmReport->period}.csv"; + return Storage::download($filePath, $fileName); + } + + return back()->with('error', 'Report file not found.'); + } + + /** + * Authorize a report request. + */ + public function authorize(Request $request, AtmTransactionReportLog $atmReport) + { + $request->validate([ + 'authorization_status' => ['required', Rule::in(['approved', 'rejected'])], + 'remarks' => ['nullable', 'string', 'max:255'], + ]); + + // Update authorization status + $atmReport->update([ + 'authorization_status' => $request->authorization_status, + 'authorized_by' => Auth::id(), + 'authorized_at' => now(), + 'remarks' => $request->remarks, + 'updated_by' => Auth::id() + ]); + + $statusText = $request->authorization_status === 'approved' ? 'approved' : 'rejected'; + + return redirect()->route('atm-reports.show', $atmReport->id) + ->with('success', "ATM Transaction report request has been {$statusText} successfully."); + } + + /** + * Provide data for datatables. + */ + public function dataForDatatables(Request $request) + { + // Retrieve data from the database + $query = AtmTransactionReportLog::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('period', 'LIKE', "%$search%") + ->orWhere('status', 'LIKE', "%$search%") + ->orWhere('authorization_status', 'LIKE', "%$search%"); + }); + } + + // Apply column filters if provided + if ($request->has('filters') && !empty($request->get('filters'))) { + $filters = json_decode($request->get('filters'), true); + + foreach ($filters as $filter) { + if (!empty($filter['value'])) { + if ($filter['column'] === 'status') { + $query->where('status', $filter['value']); + } else if ($filter['column'] === 'authorization_status') { + $query->where('authorization_status', $filter['value']); + } + } + } + } + + // Apply sorting if provided + if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) { + $order = $request->get('sortOrder'); + $column = $request->get('sortField'); + + // Map frontend column names to database column names if needed + $columnMap = [ + 'period' => 'period', + 'status' => 'status', + ]; + + $dbColumn = $columnMap[$column] ?? $column; + $query->orderBy($dbColumn, $order); + } else { + // Default sorting + $query->latest('created_at'); + } + + // 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; + + $query->skip($offset)->take($size); + } + + // Get the filtered count of records + $filteredRecords = $query->count(); + + // Eager load relationships (remove branch since it's not used anymore) + $query->with(['user', 'authorizer']); + + // Get the data for the current page + $data = $query->get()->map(function ($item) { + return [ + 'id' => $item->id, + 'period' => $item->period, + 'report_date' => Carbon::createFromFormat('Ymd', $item->period)->format('Y-m-d'), + 'status' => $item->status, + 'authorization_status' => $item->authorization_status, + 'is_downloaded' => $item->is_downloaded, + 'created_at' => dateFormat($item->created_at, 1, 1), + 'created_by' => $item->user->name ?? 'N/A', + 'authorized_by' => $item->authorizer ? $item->authorizer->name : null, + 'authorized_at' => $item->authorized_at ? $item->authorized_at->format('Y-m-d H:i:s') : null, + 'file_path' => $item->file_path, + ]; + }); + + // Calculate the page count + $pageCount = ceil($filteredRecords / ($request->get('size') ?: 1)); + $currentPage = $request->get('page') ?: 1; + + return response()->json([ + 'draw' => $request->get('draw'), + 'recordsTotal' => $totalRecords, + 'recordsFiltered' => $filteredRecords, + 'pageCount' => $pageCount, + 'page' => $currentPage, + 'totalCount' => $totalRecords, + 'data' => $data, + ]); + } + + /** + * Delete a report request. + */ + public function destroy(AtmTransactionReportLog $atmReport) + { + // Delete the file if exists + if ($atmReport->file_path && Storage::exists($atmReport->file_path)) { + Storage::delete($atmReport->file_path); + } + + // Delete the report request + $atmReport->delete(); + + return response()->json([ + 'message' => 'ATM Transaction report deleted successfully.', + ]); + } + + /** + * Send report to email + */ + public function sendEmail($id) + { + $atmReport = AtmTransactionReportLog::findOrFail($id); + + // Check if report has email + if (empty($atmReport->email)) { + return redirect()->back()->with('error', 'No email address provided for this report.'); + } + + // Check if report is available + if ($atmReport->status !== 'completed' || !$atmReport->file_path) { + return redirect()->back()->with('error', 'Report is not available for sending.'); + } + + try { + // Send email with report attachment + // Implementation depends on your email system + // Mail::to($atmReport->email)->send(new AtmTransactionReportEmail($atmReport)); + + $atmReport->update([ + 'email_sent' => true, + 'email_sent_at' => now(), + 'updated_by' => Auth::id() + ]); + + return redirect()->back()->with('success', 'ATM Transaction report sent to email successfully.'); + } catch (Exception $e) { + Log::error('Failed to send ATM Transaction report email: ' . $e->getMessage()); + return redirect()->back()->with('error', 'Failed to send email: ' . $e->getMessage()); + } + } +}