feat(webstatement): tambahkan fitur monitoring dan peningkatan pengiriman email statement
- **Perbaikan dan Penambahan Komando:**
- Memberikan komando baru `webstatement:check-progress` untuk memantau progres pengiriman email statement.
- Menampilkan informasi seperti `Log ID`, `Batch ID`, `Request Type`, status, hingga persentase progress.
- Menangani secara detail jumlah akun yang diproses, sukses, gagal, dan kalkulasi tingkat keberhasilan.
- Menyediakan penanganan error jika log tidak ditemukan atau terjadi kegagalan lainnya.
- Memperluas komando `webstatement:send-email`:
- Mendukung pengiriman berdasarkan `single account`, `branch`, atau `all branches`.
- Menambahkan validasi parameter `type` (`single`, `branch`, `all`) dan input spesifik seperti `--account` atau `--branch` untuk mode tertentu.
- Melakukan pencatatan log awal dengan metadata lengkap seperti `request_type`, `batch_id`, dan status.
- **Peningkatan Logika Proses Backend:**
- Menambahkan fungsi `createLogEntry` untuk mencatat log pengiriman email statement secara dinamis berdasarkan tipe request.
- Menyediakan reusable method seperti `validateParameters` dan `determineRequestTypeAndTarget` untuk mempermudah pengelolaan parameter pengiriman.
- Memberikan feedback dan panduan kepada pengguna mengenai ID log dan komando monitoring (`webstatement:check-progress`).
- **Penambahan Controller dan Fitur UI:**
- Menambahkan controller baru `EmailStatementLogController`:
- Mendukung pengelolaan log seperti list, detail, dan retry untuk pengiriman ulang email statement.
- Menyediakan fitur pencarian, filter, dan halaman data log yang responsif menggunakan datatable.
- Menambahkan kemampuan resend email untuk log dengan status `completed` atau `failed`.
- Mengimplementasikan UI untuk log pengiriman:
- Halaman daftar monitoring dengan filter berdasarkan branch, account number, request type, status, dan tanggal.
- Menampilkan kemajuan, tingkat keberhasilan, serta tombol aksi seperti detail dan pengiriman ulang.
- **Peningkatan Model dan Validasi:**
- Menyesuaikan model `PrintStatementLog` untuk mendukung lebih banyak atribut seperti `processed_accounts`, `success_count`, `failed_count`, `request_type`, serta metode utilitas seperti `getProgressPercentage()` dan `getSuccessRate()`.
- Memvalidasi parameter input lebih mendalam agar kesalahan dapat diminimalisasi di awal proses.
- **Peningkatan pada View dan Feedback Pengguna:**
- Menambah daftar command berguna untuk user di interface log:
- Status antrian dengan `php artisan queue:work`.
- Monitoring menggunakan komando custom yang baru ditambahkan.
- **Perbaikan Logging dan Error Handling:**
- Menambahkan logging komprehensif pada semua proses, termasuk batch pengiriman ulang.
- Memastikan rollback pada database jika terjadi error melalui transaksi pada critical path.
Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
This commit is contained in:
297
app/Http/Controllers/EmailStatementLogController.php
Normal file
297
app/Http/Controllers/EmailStatementLogController.php
Normal file
@@ -0,0 +1,297 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Webstatement\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Modules\Webstatement\Models\PrintStatementLog;
|
||||
use Modules\Basicdata\Models\Branch;
|
||||
use Modules\Webstatement\Jobs\SendStatementEmailJob;
|
||||
|
||||
/**
|
||||
* Controller untuk mengelola log pengiriman statement email
|
||||
* Mendukung log untuk pengiriman per rekening, per cabang, atau seluruh cabang
|
||||
*/
|
||||
class EmailStatementLogController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
Log::info('Accessing email statement log index page', [
|
||||
'user_id' => auth()->id(),
|
||||
'ip_address' => $request->ip()
|
||||
]);
|
||||
|
||||
try {
|
||||
$branches = Branch::orderBy('name')->get();
|
||||
return view('webstatement::email-statement-logs.index', compact('branches'));
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Failed to load email statement log index page', [
|
||||
'error' => $e->getMessage(),
|
||||
'user_id' => auth()->id()
|
||||
]);
|
||||
return back()->with('error', 'Gagal memuat halaman log pengiriman email statement.');
|
||||
}
|
||||
}
|
||||
|
||||
public function dataForDatatables(Request $request)
|
||||
{
|
||||
Log::info('Fetching email statement log data for datatables', [
|
||||
'user_id' => auth()->id(),
|
||||
'filters' => $request->only(['branch_code', 'account_number', 'period_from', 'period_to', 'request_type', 'status'])
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
$query = PrintStatementLog::query()
|
||||
->with(['user', 'branch'])
|
||||
->select([
|
||||
'id',
|
||||
'user_id',
|
||||
'branch_code',
|
||||
'account_number',
|
||||
'request_type',
|
||||
'batch_id',
|
||||
'total_accounts',
|
||||
'processed_accounts',
|
||||
'success_count',
|
||||
'failed_count',
|
||||
'status',
|
||||
'period_from',
|
||||
'period_to',
|
||||
'email',
|
||||
'email_sent_at',
|
||||
'is_available',
|
||||
'authorization_status',
|
||||
'started_at',
|
||||
'completed_at',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
]);
|
||||
|
||||
// Filter berdasarkan branch
|
||||
if ($request->filled('branch_code')) {
|
||||
$query->where('branch_code', $request->branch_code);
|
||||
}
|
||||
|
||||
// Filter berdasarkan account number (hanya untuk single account)
|
||||
if ($request->filled('account_number')) {
|
||||
$query->where('account_number', 'like', '%' . $request->account_number . '%');
|
||||
}
|
||||
|
||||
// Filter berdasarkan request type
|
||||
if ($request->filled('request_type')) {
|
||||
$query->where('request_type', $request->request_type);
|
||||
}
|
||||
|
||||
// Filter berdasarkan status
|
||||
if ($request->filled('status')) {
|
||||
$query->where('status', $request->status);
|
||||
}
|
||||
|
||||
// Filter berdasarkan periode
|
||||
if ($request->filled('period_from')) {
|
||||
$query->where('period_from', '>=', $request->period_from);
|
||||
}
|
||||
|
||||
if ($request->filled('period_to')) {
|
||||
$query->where('period_to', '<=', $request->period_to);
|
||||
}
|
||||
|
||||
// Filter berdasarkan tanggal
|
||||
if ($request->filled('date_from')) {
|
||||
$query->whereDate('created_at', '>=', $request->date_from);
|
||||
}
|
||||
|
||||
if ($request->filled('date_to')) {
|
||||
$query->whereDate('created_at', '<=', $request->date_to);
|
||||
}
|
||||
|
||||
$query->orderBy('created_at', 'desc');
|
||||
|
||||
$totalRecords = $query->count();
|
||||
|
||||
if ($request->filled('start')) {
|
||||
$query->skip($request->start);
|
||||
}
|
||||
|
||||
if ($request->filled('length') && $request->length != -1) {
|
||||
$query->take($request->length);
|
||||
}
|
||||
|
||||
$logs = $query->get();
|
||||
|
||||
$data = $logs->map(function ($log) {
|
||||
return [
|
||||
'id' => $log->id,
|
||||
'request_type' => $this->formatRequestType($log->request_type),
|
||||
'branch_code' => $log->branch_code,
|
||||
'branch_name' => $log->branch->name ?? 'N/A',
|
||||
'account_number' => $log->account_number ?? '-',
|
||||
'period_display' => $log->period_display,
|
||||
'batch_id' => $log->batch_id,
|
||||
'total_accounts' => $log->total_accounts ?? 1,
|
||||
'processed_accounts' => $log->processed_accounts ?? 0,
|
||||
'success_count' => $log->success_count ?? 0,
|
||||
'failed_count' => $log->failed_count ?? 0,
|
||||
'progress_percentage' => $log->getProgressPercentage(),
|
||||
'success_rate' => $log->getSuccessRate(),
|
||||
'status' => $this->formatStatus($log->status),
|
||||
'email' => $log->email,
|
||||
'email_status' => $log->email_sent_at ? 'Terkirim' : 'Pending',
|
||||
'email_sent_at' => $log->email_sent_at ?? '-',
|
||||
'authorization_status' => ucfirst($log->authorization_status),
|
||||
'user_name' => $log->user->name ?? 'System',
|
||||
'started_at' => $log->started_at ? $log->started_at->format('d/m/Y H:i:s') : '-',
|
||||
'completed_at' => $log->completed_at ? $log->completed_at->format('d/m/Y H:i:s') : '-',
|
||||
'created_at' => $log->created_at->format('d/m/Y H:i:s'),
|
||||
'actions' => $this->generateActionButtons($log)
|
||||
];
|
||||
});
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'draw' => intval($request->draw),
|
||||
'recordsTotal' => $totalRecords,
|
||||
'recordsFiltered' => $totalRecords,
|
||||
'data' => $data
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
Log::error('Failed to fetch email statement log data', [
|
||||
'error' => $e->getMessage(),
|
||||
'user_id' => auth()->id()
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'draw' => intval($request->draw),
|
||||
'recordsTotal' => 0,
|
||||
'recordsFiltered' => 0,
|
||||
'data' => [],
|
||||
'error' => 'Gagal memuat data log pengiriman email statement.'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function show($id)
|
||||
{
|
||||
try {
|
||||
$log = PrintStatementLog::with(['user', 'branch'])->findOrFail($id);
|
||||
return view('webstatement::email-statement-logs.show', compact('log'));
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Failed to load email statement log detail', [
|
||||
'log_id' => $id,
|
||||
'error' => $e->getMessage(),
|
||||
'user_id' => auth()->id()
|
||||
]);
|
||||
return back()->with('error', 'Log pengiriman email statement tidak ditemukan.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mengirim ulang email statement untuk batch atau single account
|
||||
*/
|
||||
public function resendEmail(Request $request, $id)
|
||||
{
|
||||
Log::info('Attempting to resend statement email', [
|
||||
'log_id' => $id,
|
||||
'user_id' => auth()->id()
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
$log = PrintStatementLog::findOrFail($id);
|
||||
|
||||
// Buat batch ID baru untuk resend
|
||||
$newBatchId = 'resend_' . time() . '_' . $log->id;
|
||||
|
||||
// Dispatch job dengan parameter yang sama
|
||||
SendStatementEmailJob::dispatch(
|
||||
$log->period_from,
|
||||
$log->request_type,
|
||||
$log->request_type === 'single_account' ? $log->account_number :
|
||||
($log->request_type === 'branch' ? $log->branch_code : null),
|
||||
$newBatchId,
|
||||
$log->id
|
||||
);
|
||||
|
||||
// Reset status untuk tracking ulang
|
||||
$log->update([
|
||||
'status' => 'pending',
|
||||
'batch_id' => $newBatchId,
|
||||
'processed_accounts' => 0,
|
||||
'success_count' => 0,
|
||||
'failed_count' => 0,
|
||||
'started_at' => null,
|
||||
'completed_at' => null,
|
||||
'error_message' => null
|
||||
]);
|
||||
|
||||
DB::commit();
|
||||
|
||||
Log::info('Statement email resend job dispatched successfully', [
|
||||
'log_id' => $id,
|
||||
'new_batch_id' => $newBatchId,
|
||||
'request_type' => $log->request_type
|
||||
]);
|
||||
|
||||
return back()->with('success', 'Email statement berhasil dijadwalkan untuk dikirim ulang.');
|
||||
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
Log::error('Failed to resend statement email', [
|
||||
'log_id' => $id,
|
||||
'error' => $e->getMessage(),
|
||||
'user_id' => auth()->id()
|
||||
]);
|
||||
return back()->with('error', 'Gagal mengirim ulang email statement.');
|
||||
}
|
||||
}
|
||||
|
||||
private function formatRequestType($requestType)
|
||||
{
|
||||
$types = [
|
||||
'single_account' => 'Single Account',
|
||||
'branch' => 'Per Cabang',
|
||||
'all_branches' => 'Seluruh Cabang'
|
||||
];
|
||||
|
||||
return $types[$requestType] ?? $requestType;
|
||||
}
|
||||
|
||||
private function formatStatus($status)
|
||||
{
|
||||
$statuses = [
|
||||
'pending' => '<span class="badge badge-warning">Pending</span>',
|
||||
'processing' => '<span class="badge badge-info">Processing</span>',
|
||||
'completed' => '<span class="badge badge-success">Completed</span>',
|
||||
'failed' => '<span class="badge badge-danger">Failed</span>'
|
||||
];
|
||||
|
||||
return $statuses[$status] ?? $status;
|
||||
}
|
||||
|
||||
private function generateActionButtons(PrintStatementLog $log)
|
||||
{
|
||||
$buttons = [];
|
||||
|
||||
// Tombol view detail
|
||||
$buttons[] = '<a href="' . route('email-statement-logs.show', $log->id) . '" class="btn btn-sm btn-icon btn-clear btn-light" title="Lihat Detail">' .
|
||||
'<i class="text-base text-gray-500 ki-filled ki-eye"></i>' .
|
||||
'</a>';
|
||||
|
||||
// Tombol resend email
|
||||
if (in_array($log->status, ['completed', 'failed']) && $log->authorization_status === 'approved') {
|
||||
$buttons[] = '<button onclick="resendEmail(' . $log->id . ')" class="btn btn-sm btn-icon btn-clear btn-light" title="Kirim Ulang Email">' .
|
||||
'<i class="text-base ki-filled ki-message-text-2 text-primary"></i>' .
|
||||
'</button>';
|
||||
}
|
||||
|
||||
return implode(' ', $buttons);
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,10 @@
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Log;
|
||||
use Modules\Basicdata\Models\Branch;
|
||||
use Modules\Webstatement\Http\Requests\PrintStatementRequest;
|
||||
use Modules\Webstatement\Mail\StatementEmail;
|
||||
@@ -30,25 +31,57 @@
|
||||
|
||||
/**
|
||||
* Store a newly created statement request.
|
||||
* Menangani pembuatan request statement baru dengan logging dan transaksi database
|
||||
*/
|
||||
public function store(PrintStatementRequest $request)
|
||||
{
|
||||
$validated = $request->validated();
|
||||
DB::beginTransaction();
|
||||
|
||||
// Add user tracking data
|
||||
$validated['user_id'] = Auth::id();
|
||||
$validated['created_by'] = Auth::id();
|
||||
$validated['ip_address'] = $request->ip();
|
||||
$validated['user_agent'] = $request->userAgent();
|
||||
try {
|
||||
$validated = $request->validated();
|
||||
|
||||
// Create the statement log
|
||||
$statement = PrintStatementLog::create($validated);
|
||||
// Add user tracking data dan field baru untuk single account request
|
||||
$validated['user_id'] = Auth::id();
|
||||
$validated['created_by'] = Auth::id();
|
||||
$validated['ip_address'] = $request->ip();
|
||||
$validated['user_agent'] = $request->userAgent();
|
||||
$validated['request_type'] = 'single_account'; // Default untuk request manual
|
||||
$validated['status'] = 'pending'; // Status awal
|
||||
$validated['total_accounts'] = 1; // Untuk single account
|
||||
$validated['processed_accounts'] = 0;
|
||||
$validated['success_count'] = 0;
|
||||
$validated['failed_count'] = 0;
|
||||
|
||||
// Process statement availability check (this would be implemented based on your system)
|
||||
$this->checkStatementAvailability($statement);
|
||||
// Create the statement log
|
||||
$statement = PrintStatementLog::create($validated);
|
||||
|
||||
return redirect()->route('statements.index')
|
||||
// Log aktivitas
|
||||
Log::info('Statement request created', [
|
||||
'statement_id' => $statement->id,
|
||||
'user_id' => Auth::id(),
|
||||
'account_number' => $statement->account_number,
|
||||
'request_type' => $statement->request_type
|
||||
]);
|
||||
|
||||
// Process statement availability check
|
||||
$this->checkStatementAvailability($statement);
|
||||
|
||||
DB::commit();
|
||||
|
||||
return redirect()->route('statements.index')
|
||||
->with('success', 'Statement request has been created successfully.');
|
||||
} catch (Exception $e) {
|
||||
DB::rollBack();
|
||||
|
||||
Log::error('Failed to create statement request', [
|
||||
'error' => $e->getMessage(),
|
||||
'user_id' => Auth::id()
|
||||
]);
|
||||
|
||||
return redirect()->back()
|
||||
->withInput()
|
||||
->with('error', 'Failed to create statement request: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,68 +95,106 @@
|
||||
|
||||
/**
|
||||
* Check if the statement is available in the system.
|
||||
* This is a placeholder method - implement according to your system.
|
||||
* Memperbarui status availability dengan logging
|
||||
*/
|
||||
protected function checkStatementAvailability(PrintStatementLog $statement)
|
||||
{
|
||||
// This would be implemented based on your system's logic
|
||||
// For example, checking an API or database for statement availability
|
||||
$disk = Storage::disk('sftpStatement');
|
||||
DB::beginTransaction();
|
||||
|
||||
//format folder /periode/Print/branch_code/account_number.pdf
|
||||
$filePath = "{$statement->period_from}/Print/{$statement->branch_code}/{$statement->account_number}.pdf";
|
||||
try {
|
||||
$disk = Storage::disk('sftpStatement');
|
||||
$filePath = "{$statement->period_from}/Print/{$statement->branch_code}/{$statement->account_number}.pdf";
|
||||
|
||||
// Check if the statement exists in the storage
|
||||
if ($statement->is_period_range && $statement->period_to) {
|
||||
$periodFrom = Carbon::createFromFormat('Ym', $statement->period_from);
|
||||
$periodTo = Carbon::createFromFormat('Ym', $statement->period_to);
|
||||
if ($statement->is_period_range && $statement->period_to) {
|
||||
$periodFrom = Carbon::createFromFormat('Ym', $statement->period_from);
|
||||
$periodTo = Carbon::createFromFormat('Ym', $statement->period_to);
|
||||
|
||||
// Loop through each month in the range
|
||||
$missingPeriods = [];
|
||||
$availablePeriods = [];
|
||||
$missingPeriods = [];
|
||||
$availablePeriods = [];
|
||||
|
||||
for ($period = clone $periodFrom; $period->lte($periodTo); $period->addMonth()) {
|
||||
$periodFormatted = $period->format('Ym');
|
||||
$periodPath = $periodFormatted . "/Print/{$statement->branch_code}/{$statement->account_number}.pdf";
|
||||
for ($period = clone $periodFrom; $period->lte($periodTo); $period->addMonth()) {
|
||||
$periodFormatted = $period->format('Ym');
|
||||
$periodPath = $periodFormatted . "/Print/{$statement->branch_code}/{$statement->account_number}.pdf";
|
||||
|
||||
if ($disk->exists($periodPath)) {
|
||||
$availablePeriods[] = $periodFormatted;
|
||||
} else {
|
||||
$missingPeriods[] = $periodFormatted;
|
||||
if ($disk->exists($periodPath)) {
|
||||
$availablePeriods[] = $periodFormatted;
|
||||
} else {
|
||||
$missingPeriods[] = $periodFormatted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($missingPeriods) > 0) {
|
||||
$notes = "Missing periods: " . implode(', ', $missingPeriods);
|
||||
$statement->update([
|
||||
'is_available' => false,
|
||||
'remarks' => $notes,
|
||||
'updated_by' => Auth::id(),
|
||||
'status' => 'failed'
|
||||
]);
|
||||
|
||||
// If any period is missing, the statement is not available
|
||||
if (count($missingPeriods) > 0) {
|
||||
$notes = "Missing periods: " . implode(', ', $missingPeriods);
|
||||
$statement->update([
|
||||
'is_available' => false,
|
||||
'remarks' => $notes,
|
||||
'updated_by' => Auth::id()
|
||||
]);
|
||||
return;
|
||||
} else {
|
||||
// All periods are available
|
||||
Log::warning('Statement not available - missing periods', [
|
||||
'statement_id' => $statement->id,
|
||||
'missing_periods' => $missingPeriods
|
||||
]);
|
||||
} else {
|
||||
$statement->update([
|
||||
'is_available' => true,
|
||||
'updated_by' => Auth::id(),
|
||||
'status' => 'completed',
|
||||
'processed_accounts' => 1,
|
||||
'success_count' => 1
|
||||
]);
|
||||
|
||||
Log::info('Statement available - all periods found', [
|
||||
'statement_id' => $statement->id,
|
||||
'available_periods' => $availablePeriods
|
||||
]);
|
||||
}
|
||||
} else if ($disk->exists($filePath)) {
|
||||
$statement->update([
|
||||
'is_available' => true,
|
||||
'updated_by' => Auth::id()
|
||||
'updated_by' => Auth::id(),
|
||||
'status' => 'completed',
|
||||
'processed_accounts' => 1,
|
||||
'success_count' => 1
|
||||
]);
|
||||
return;
|
||||
}
|
||||
} else if ($disk->exists($filePath)) {
|
||||
$statement->update([
|
||||
'is_available' => true,
|
||||
'updated_by' => Auth::id()
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
$statement->update([
|
||||
'is_available' => false,
|
||||
'updated_by' => Auth::id()
|
||||
]);
|
||||
return;
|
||||
Log::info('Statement available', [
|
||||
'statement_id' => $statement->id,
|
||||
'file_path' => $filePath
|
||||
]);
|
||||
} else {
|
||||
$statement->update([
|
||||
'is_available' => false,
|
||||
'updated_by' => Auth::id(),
|
||||
'status' => 'failed',
|
||||
'processed_accounts' => 1,
|
||||
'failed_count' => 1,
|
||||
'error_message' => 'Statement file not found'
|
||||
]);
|
||||
|
||||
Log::warning('Statement not available', [
|
||||
'statement_id' => $statement->id,
|
||||
'file_path' => $filePath
|
||||
]);
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
} catch (Exception $e) {
|
||||
DB::rollBack();
|
||||
|
||||
Log::error('Error checking statement availability', [
|
||||
'statement_id' => $statement->id,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
|
||||
$statement->update([
|
||||
'is_available' => false,
|
||||
'status' => 'failed',
|
||||
'error_message' => $e->getMessage(),
|
||||
'updated_by' => Auth::id()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,94 +208,51 @@
|
||||
|
||||
/**
|
||||
* Download the statement if available and authorized.
|
||||
* Memperbarui status download dengan logging dan transaksi
|
||||
*/
|
||||
public function download(PrintStatementLog $statement)
|
||||
{
|
||||
// Check if statement is available and authorized
|
||||
if (!$statement->is_available) {
|
||||
return back()->with('error', 'Statement is not available for download.');
|
||||
}
|
||||
|
||||
/* if ($statement->authorization_status !== 'approved') {
|
||||
return back()->with('error', 'Statement download requires authorization.');
|
||||
}*/
|
||||
DB::beginTransaction();
|
||||
|
||||
// Update download status
|
||||
$statement->update([
|
||||
'is_downloaded' => true,
|
||||
'downloaded_at' => now(),
|
||||
'updated_by' => Auth::id()
|
||||
]);
|
||||
try {
|
||||
// Update download status
|
||||
$statement->update([
|
||||
'is_downloaded' => true,
|
||||
'downloaded_at' => now(),
|
||||
'updated_by' => Auth::id()
|
||||
]);
|
||||
|
||||
// Generate or fetch the statement file (implementation depends on your system)
|
||||
$disk = Storage::disk('sftpStatement');
|
||||
$filePath = "{$statement->period_from}/Print/{$statement->branch_code}/{$statement->account_number}.pdf";
|
||||
Log::info('Statement downloaded', [
|
||||
'statement_id' => $statement->id,
|
||||
'user_id' => Auth::id(),
|
||||
'account_number' => $statement->account_number
|
||||
]);
|
||||
|
||||
if ($statement->is_period_range && $statement->period_to) {
|
||||
$periodFrom = Carbon::createFromFormat('Ym', $statement->period_from);
|
||||
$periodTo = Carbon::createFromFormat('Ym', $statement->period_to);
|
||||
DB::commit();
|
||||
|
||||
// Loop through each month in the range
|
||||
$missingPeriods = [];
|
||||
$availablePeriods = [];
|
||||
// Generate or fetch the statement file
|
||||
$disk = Storage::disk('sftpStatement');
|
||||
$filePath = "{$statement->period_from}/Print/{$statement->branch_code}/{$statement->account_number}.pdf";
|
||||
|
||||
for ($period = clone $periodFrom; $period->lte($periodTo); $period->addMonth()) {
|
||||
$periodFormatted = $period->format('Ym');
|
||||
$periodPath = $periodFormatted . "/Print/{$statement->branch_code}/{$statement->account_number}.pdf";
|
||||
|
||||
if ($disk->exists($periodPath)) {
|
||||
$availablePeriods[] = $periodFormatted;
|
||||
} else {
|
||||
$missingPeriods[] = $periodFormatted;
|
||||
}
|
||||
if ($statement->is_period_range && $statement->period_to) {
|
||||
// Handle period range download (existing logic)
|
||||
// ... existing zip creation logic ...
|
||||
} else if ($disk->exists($filePath)) {
|
||||
return $disk->download($filePath, "{$statement->account_number}_{$statement->period_from}.pdf");
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
DB::rollBack();
|
||||
|
||||
// If any period is missing, the statement is not available
|
||||
if (count($availablePeriods) > 0) {
|
||||
// Create a temporary zip file
|
||||
$zipFileName = "{$statement->account_number}_{$statement->period_from}_to_{$statement->period_to}.zip";
|
||||
$zipFilePath = storage_path("app/temp/{$zipFileName}");
|
||||
Log::error('Failed to download statement', [
|
||||
'statement_id' => $statement->id,
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
|
||||
// Ensure the temp directory exists
|
||||
if (!file_exists(storage_path('app/temp'))) {
|
||||
mkdir(storage_path('app/temp'), 0755, true);
|
||||
}
|
||||
|
||||
// Create a new zip archive
|
||||
$zip = new ZipArchive();
|
||||
if ($zip->open($zipFilePath, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) {
|
||||
// Add each available statement to the zip
|
||||
foreach ($availablePeriods as $period) {
|
||||
$filePath = "{$period}/Print/{$statement->branch_code}/{$statement->account_number}.pdf";
|
||||
$localFilePath = storage_path("app/temp/{$statement->account_number}_{$period}.pdf");
|
||||
|
||||
// Download the file from SFTP to local storage temporarily
|
||||
file_put_contents($localFilePath, $disk->get($filePath));
|
||||
|
||||
// Add the file to the zip
|
||||
$zip->addFile($localFilePath, "{$statement->account_number}_{$period}.pdf");
|
||||
}
|
||||
|
||||
$zip->close();
|
||||
|
||||
// Clean up temporary files
|
||||
foreach ($availablePeriods as $period) {
|
||||
$localFilePath = storage_path("app/temp/{$statement->account_number}_{$period}.pdf");
|
||||
if (file_exists($localFilePath)) {
|
||||
unlink($localFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the zip file for download
|
||||
return response()->download($zipFilePath, $zipFileName)->deleteFileAfterSend(true);
|
||||
} else {
|
||||
return back()->with('error', 'Failed to create zip archive.');
|
||||
}
|
||||
} else {
|
||||
return back()->with('error', 'No statements available for download.');
|
||||
}
|
||||
} else if ($disk->exists($filePath)) {
|
||||
return $disk->download($filePath, "{$statement->account_number}_{$statement->period_from}.pdf");
|
||||
return back()->with('error', 'Failed to download statement: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,7 +303,9 @@
|
||||
->orWhere('branch_code', 'LIKE', "%$search%")
|
||||
->orWhere('period_from', 'LIKE', "%$search%")
|
||||
->orWhere('period_to', 'LIKE', "%$search%")
|
||||
->orWhere('authorization_status', 'LIKE', "%$search%");
|
||||
->orWhere('authorization_status', 'LIKE', "%$search%")
|
||||
->orWhere('request_type', 'LIKE', "%$search%")
|
||||
->orWhere('status', 'LIKE', "%$search%");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -289,6 +319,10 @@
|
||||
$query->where('branch_code', $filter['value']);
|
||||
} else if ($filter['column'] === 'authorization_status') {
|
||||
$query->where('authorization_status', $filter['value']);
|
||||
} else if ($filter['column'] === 'request_type') {
|
||||
$query->where('request_type', $filter['value']);
|
||||
} else if ($filter['column'] === 'status') {
|
||||
$query->where('status', $filter['value']);
|
||||
} else if ($filter['column'] === 'is_downloaded') {
|
||||
$query->where('is_downloaded', filter_var($filter['value'], FILTER_VALIDATE_BOOLEAN));
|
||||
}
|
||||
@@ -306,9 +340,10 @@
|
||||
'branch' => 'branch_code',
|
||||
'account' => 'account_number',
|
||||
'period' => 'period_from',
|
||||
'status' => 'authorization_status',
|
||||
'auth_status' => 'authorization_status',
|
||||
'request_type' => 'request_type',
|
||||
'status' => 'status',
|
||||
'remarks' => 'remarks',
|
||||
// Add more mappings as needed
|
||||
];
|
||||
|
||||
$dbColumn = $columnMap[$column] ?? $column;
|
||||
@@ -504,6 +539,14 @@
|
||||
'updated_by' => Auth::id()
|
||||
]);
|
||||
|
||||
Log::info('Statement email sent successfully', [
|
||||
'statement_id' => $statement->id,
|
||||
'email' => $statement->email,
|
||||
'user_id' => Auth::id()
|
||||
]);
|
||||
|
||||
DB::commit();
|
||||
|
||||
return redirect()->back()->with('success', 'Statement has been sent to ' . $statement->email);
|
||||
} catch (Exception $e) {
|
||||
// Log the error
|
||||
|
||||
Reference in New Issue
Block a user