- **Penambahan Fitur Konfirmasi Email:**
- Menambahkan event listener untuk form submit:
- Menampilkan SweetAlert jika field email telah diisi.
- Mengonfirmasi pengiriman statement ke alamat email yang diisi pengguna.
- Submit form hanya setelah user mengonfirmasi.
- **Optimalisasi Proses Download Statement:**
- Menangani logic download statement dalam rentang periode (period range):
- Mencatat log keberadaan file untuk setiap periode.
- Membuat file ZIP yang berisi semua file statement yang tersedia dalam rentang tersebut.
- Mengelola file sementara untuk proses kompresi dengan pembersihan otomatis.
- Menambahkan log error dan warning untuk file yang hilang dalam rentang periode.
- Mendukung mekanisme download file tunggal untuk periode tertentu.
- Menyesuaikan log dengan detail proses, seperti:
- Informasi periode yang tersedia dan tidak.
- Notifikasi penyelesaian atau kegagalan proses download ZIP.
- Menambahkan logging trace pada exception untuk debugging lebih rinci.
- **Perubahan Validasi Logic:**
- Validasi baru pada `PrintStatementRequest`:
- Menentukan `is_period_range` hanya jika `period_to` berbeda dengan `period_from`.
- **Perbaikan dan Penyesuaian Pengiriman Email:**
- Menambahkan pengecekan field email sebelum menjalankan fungsi kirim email di `PrintStatementController`.
- Mengintegrasikan fungsi `sendEmail` jika terdapat email pada statement.
- **Penambahan Dokumentasi Kode:**
- Menambahkan komentar inline di beberapa bagian:
- Logika konfirmasi email.
- Proses pembuatan ZIP dan penanganan download.
- Menjelaskan tiap langkah operasional untuk mempermudah pemahaman dan debugging.
Perubahan ini mengintegrasikan fitur konfirmasi email yang lebih interaktif, meningkatkan proses download statement berjenjang, serta memperbaiki validasi dan logging pada tiap langkah proses.
Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
780 lines
35 KiB
PHP
780 lines
35 KiB
PHP
<?php
|
|
|
|
namespace Modules\Webstatement\Http\Controllers;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use Carbon\Carbon;
|
|
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 Modules\Basicdata\Models\Branch;
|
|
use Modules\Webstatement\Http\Requests\PrintStatementRequest;
|
|
use Modules\Webstatement\Mail\StatementEmail;
|
|
use Modules\Webstatement\Models\Account;
|
|
use Modules\Webstatement\Models\PrintStatementLog;
|
|
use ZipArchive;
|
|
|
|
class PrintStatementController extends Controller
|
|
{
|
|
/**
|
|
* Display a listing of the statements.
|
|
*/
|
|
public function index(Request $request)
|
|
{
|
|
$branches = Branch::whereNotNull('customer_company')
|
|
->where('code', '!=', 'ID0019999')
|
|
->orderBy('name')
|
|
->get();
|
|
|
|
$branch = Branch::find(Auth::user()->branch_id);
|
|
$multiBranch = session('MULTI_BRANCH') ?? false;
|
|
|
|
return view('webstatement::statements.index', compact('branches', 'branch', 'multiBranch'));
|
|
}
|
|
|
|
/**
|
|
* Store a newly created statement request.
|
|
* Menangani pembuatan request statement baru dengan logging dan transaksi database
|
|
*/
|
|
public function store(PrintStatementRequest $request)
|
|
{
|
|
// Add account verification before storing
|
|
$accountNumber = $request->input('account_number'); // Assuming this is the field name for account number
|
|
// First, check if the account exists and get branch information
|
|
$account = Account::where('account_number', $accountNumber)->first();
|
|
if ($account) {
|
|
$branch_code = $account->branch_code;
|
|
$userBranchId = session('branch_id'); // Assuming branch ID is stored in session
|
|
$multiBranch = session('MULTI_BRANCH');
|
|
|
|
if (!$multiBranch) {
|
|
// Check if account branch matches user's branch
|
|
if ($account->branch_id !== $userBranchId) {
|
|
return redirect()->route('statements.index')
|
|
->with('error', 'Nomor rekening tidak sesuai dengan cabang Anda. Transaksi tidak dapat dilanjutkan.');
|
|
}
|
|
}
|
|
|
|
// Check if account belongs to restricted branch ID0019999
|
|
if ($account->branch_id === 'ID0019999') {
|
|
return redirect()->route('statements.index')
|
|
->with('error', 'Nomor rekening terdaftar pada cabang khusus. Silakan hubungi bagian HC untuk informasi lebih lanjut.');
|
|
}
|
|
|
|
// If all checks pass, proceed with storing data
|
|
// Your existing store logic here
|
|
|
|
} else {
|
|
// Account not found
|
|
return redirect()->route('statements.index')
|
|
->with('error', 'Nomor rekening tidak ditemukan dalam sistem.');
|
|
}
|
|
|
|
DB::beginTransaction();
|
|
|
|
try {
|
|
$validated = $request->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['authorization_status'] = 'approved'; // Status otorisasi awal
|
|
$validated['total_accounts'] = 1; // Untuk single account
|
|
$validated['processed_accounts'] = 0;
|
|
$validated['success_count'] = 0;
|
|
$validated['failed_count'] = 0;
|
|
$validated['branch_code'] = $branch_code; // Awal tidak tersedia
|
|
|
|
// Create the statement log
|
|
$statement = PrintStatementLog::create($validated);
|
|
|
|
// 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);
|
|
|
|
$statement = PrintStatementLog::find($statement->id);
|
|
if($statement->email){
|
|
$this->sendEmail($statement->id);
|
|
}
|
|
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());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Show the form for creating a new statement request.
|
|
*/
|
|
public function create()
|
|
{
|
|
$branches = Branch::orderBy('name')->get();
|
|
return view('webstatement::statements.create', compact('branches'));
|
|
}
|
|
|
|
/**
|
|
* Check if the statement is available in the system.
|
|
* Memperbarui status availability dengan logging
|
|
*/
|
|
protected function checkStatementAvailability(PrintStatementLog $statement)
|
|
{
|
|
DB::beginTransaction();
|
|
|
|
try {
|
|
$disk = Storage::disk('sftpStatement');
|
|
$filePath = "{$statement->period_from}/{$statement->branch_code}/{$statement->account_number}_{$statement->period_from}.pdf";
|
|
|
|
// Log untuk debugging
|
|
Log::info('Checking SFTP file path', [
|
|
'file_path' => $filePath,
|
|
'sftp_root' => config('filesystems.disks.sftpStatement.root'),
|
|
'full_path' => config('filesystems.disks.sftpStatement.root') . '/' . $filePath
|
|
]);
|
|
|
|
if ($statement->is_period_range && $statement->period_to) {
|
|
$periodFrom = Carbon::createFromFormat('Ym', $statement->period_from);
|
|
$periodTo = Carbon::createFromFormat('Ym', $statement->period_to);
|
|
|
|
$missingPeriods = [];
|
|
$availablePeriods = [];
|
|
|
|
for ($period = clone $periodFrom; $period->lte($periodTo); $period->addMonth()) {
|
|
$periodFormatted = $period->format('Ym');
|
|
$periodPath = $periodFormatted . "/{$statement->branch_code}/{$statement->account_number}_{$periodFormatted}.pdf";
|
|
|
|
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'
|
|
]);
|
|
|
|
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(),
|
|
'status' => 'completed',
|
|
'processed_accounts' => 1,
|
|
'success_count' => 1
|
|
]);
|
|
|
|
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()
|
|
]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Display the specified statement.
|
|
*/
|
|
public function show(PrintStatementLog $statement)
|
|
{
|
|
$statement->load(['user', 'branch', 'creator', 'authorizer']);
|
|
return view('webstatement::statements.show', compact('statement'));
|
|
}
|
|
|
|
/**
|
|
* Download the statement if available and authorized.
|
|
* Memperbarui status download dengan logging dan transaksi
|
|
*/
|
|
public function download(PrintStatementLog $statement)
|
|
{
|
|
if (!$statement->is_available) {
|
|
return back()->with('error', 'Statement is not available for download.');
|
|
}
|
|
|
|
DB::beginTransaction();
|
|
|
|
try {
|
|
// Update download status
|
|
$statement->update([
|
|
'is_downloaded' => true,
|
|
'downloaded_at' => now(),
|
|
'updated_by' => Auth::id()
|
|
]);
|
|
|
|
Log::info('Statement downloaded', [
|
|
'statement_id' => $statement->id,
|
|
'user_id' => Auth::id(),
|
|
'account_number' => $statement->account_number
|
|
]);
|
|
|
|
DB::commit();
|
|
|
|
// Generate or fetch the statement file
|
|
$disk = Storage::disk('sftpStatement');
|
|
$filePath = "{$statement->period_from}/{$statement->branch_code}/{$statement->account_number}_{$statement->period_from}.pdf";
|
|
|
|
if ($statement->is_period_range && $statement->period_to) {
|
|
// Log: Memulai proses download period range
|
|
Log::info('Starting period range download', [
|
|
'statement_id' => $statement->id,
|
|
'period_from' => $statement->period_from,
|
|
'period_to' => $statement->period_to
|
|
]);
|
|
|
|
/**
|
|
* Handle period range download dengan membuat zip file
|
|
* yang berisi semua statement dalam rentang periode
|
|
*/
|
|
$periodFrom = Carbon::createFromFormat('Ym', $statement->period_from);
|
|
$periodTo = Carbon::createFromFormat('Ym', $statement->period_to);
|
|
|
|
// Loop through each month in the range
|
|
$missingPeriods = [];
|
|
$availablePeriods = [];
|
|
|
|
for ($period = clone $periodFrom; $period->lte($periodTo); $period->addMonth()) {
|
|
$periodFormatted = $period->format('Ym');
|
|
$periodPath = $periodFormatted . "/{$statement->branch_code}/{$statement->account_number}_{$periodFormatted}.pdf";
|
|
|
|
if ($disk->exists($periodPath)) {
|
|
$availablePeriods[] = $periodFormatted;
|
|
Log::info('Period available for download', [
|
|
'period' => $periodFormatted,
|
|
'path' => $periodPath
|
|
]);
|
|
} else {
|
|
$missingPeriods[] = $periodFormatted;
|
|
Log::warning('Period not available for download', [
|
|
'period' => $periodFormatted,
|
|
'path' => $periodPath
|
|
]);
|
|
}
|
|
}
|
|
|
|
// If any period is available, create a zip and download it
|
|
if (count($availablePeriods) > 0) {
|
|
/**
|
|
* Membuat zip file temporary untuk download
|
|
* dengan semua statement yang tersedia dalam periode
|
|
*/
|
|
$zipFileName = "{$statement->account_number}_{$statement->period_from}_to_{$statement->period_to}.zip";
|
|
$zipFilePath = storage_path("app/temp/{$zipFileName}");
|
|
|
|
// Ensure the temp directory exists
|
|
if (!file_exists(storage_path('app/temp'))) {
|
|
mkdir(storage_path('app/temp'), 0755, true);
|
|
Log::info('Created temp directory for zip files');
|
|
}
|
|
|
|
// Create a new zip archive
|
|
$zip = new ZipArchive();
|
|
if ($zip->open($zipFilePath, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) {
|
|
Log::info('Zip archive created successfully', ['zip_path' => $zipFilePath]);
|
|
|
|
// Add each available statement to the zip
|
|
foreach ($availablePeriods as $period) {
|
|
$periodFilePath = "{$period}/{$statement->branch_code}/{$statement->account_number}_{$period}.pdf";
|
|
$localFilePath = storage_path("app/temp/{$statement->account_number}_{$period}.pdf");
|
|
|
|
try {
|
|
// Download the file from SFTP to local storage temporarily
|
|
file_put_contents($localFilePath, $disk->get($periodFilePath));
|
|
|
|
// Add the file to the zip
|
|
$zip->addFile($localFilePath, "{$statement->account_number}_{$period}.pdf");
|
|
|
|
Log::info('Added file to zip', [
|
|
'period' => $period,
|
|
'local_path' => $localFilePath
|
|
]);
|
|
} catch (Exception $e) {
|
|
Log::error('Failed to add file to zip', [
|
|
'period' => $period,
|
|
'error' => $e->getMessage()
|
|
]);
|
|
}
|
|
}
|
|
|
|
$zip->close();
|
|
Log::info('Zip archive closed successfully');
|
|
|
|
// Return the zip file for download
|
|
$response = response()->download($zipFilePath, $zipFileName)->deleteFileAfterSend(true);
|
|
|
|
// Clean up temporary PDF files
|
|
foreach ($availablePeriods as $period) {
|
|
$localFilePath = storage_path("app/temp/{$statement->account_number}_{$period}.pdf");
|
|
if (file_exists($localFilePath)) {
|
|
unlink($localFilePath);
|
|
Log::info('Cleaned up temporary file', ['file' => $localFilePath]);
|
|
}
|
|
}
|
|
|
|
Log::info('Period range download completed successfully', [
|
|
'statement_id' => $statement->id,
|
|
'available_periods' => count($availablePeriods),
|
|
'missing_periods' => count($missingPeriods)
|
|
]);
|
|
|
|
return $response;
|
|
} else {
|
|
Log::error('Failed to create zip archive', ['zip_path' => $zipFilePath]);
|
|
return back()->with('error', 'Failed to create zip archive for download.');
|
|
}
|
|
} else {
|
|
Log::warning('No statements available for download in period range', [
|
|
'statement_id' => $statement->id,
|
|
'missing_periods' => $missingPeriods
|
|
]);
|
|
return back()->with('error', 'No statements available for download in the specified period range.');
|
|
}
|
|
} else if ($disk->exists($filePath)) {
|
|
/**
|
|
* Handle single period download
|
|
* Download file PDF tunggal untuk periode tertentu
|
|
*/
|
|
Log::info('Single period download', [
|
|
'statement_id' => $statement->id,
|
|
'file_path' => $filePath
|
|
]);
|
|
|
|
return $disk->download($filePath, "{$statement->account_number}_{$statement->period_from}.pdf");
|
|
} else {
|
|
Log::warning('Statement file not found', [
|
|
'statement_id' => $statement->id,
|
|
'file_path' => $filePath
|
|
]);
|
|
return back()->with('error', 'Statement file not found.');
|
|
}
|
|
} catch (Exception $e) {
|
|
DB::rollBack();
|
|
|
|
Log::error('Failed to download statement', [
|
|
'statement_id' => $statement->id,
|
|
'error' => $e->getMessage(),
|
|
'trace' => $e->getTraceAsString()
|
|
]);
|
|
|
|
return back()->with('error', 'Failed to download statement: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Authorize a statement request.
|
|
*/
|
|
public function authorize(Request $request, PrintStatementLog $statement)
|
|
{
|
|
$request->validate([
|
|
'authorization_status' => ['required', Rule::in(['approved', 'rejected'])],
|
|
'remarks' => ['nullable', 'string', 'max:255'],
|
|
]);
|
|
|
|
// Update authorization status
|
|
$statement->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('statements.show', $statement->id)
|
|
->with('success', "Statement request has been {$statusText} successfully.");
|
|
|
|
}
|
|
|
|
/**
|
|
* Provide data for datatables.
|
|
*/
|
|
public function dataForDatatables(Request $request)
|
|
{
|
|
// Check permissions if needed
|
|
// if (!auth()->user()->can('view_statements')) {
|
|
// abort(403, 'Sorry! You are not allowed to view statements.');
|
|
// }
|
|
|
|
// Retrieve data from the database
|
|
$query = PrintStatementLog::query();
|
|
|
|
if (!auth()->user()->hasRole('administrator')) {
|
|
$query->where(function($q) {
|
|
$q->where('user_id', Auth::id())
|
|
->orWhere('branch_code', Auth::user()->branch->code);
|
|
});
|
|
}
|
|
|
|
// 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('account_number', 'LIKE', "%$search%")
|
|
->orWhere('branch_code', 'LIKE', "%$search%")
|
|
->orWhere('period_from', 'LIKE', "%$search%")
|
|
->orWhere('period_to', 'LIKE', "%$search%")
|
|
->orWhere('authorization_status', 'LIKE', "%$search%")
|
|
->orWhere('request_type', 'LIKE', "%$search%")
|
|
->orWhere('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'] === 'branch_code') {
|
|
$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));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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 = [
|
|
'branch' => 'branch_code',
|
|
'account' => 'account_number',
|
|
'period' => 'period_from',
|
|
'auth_status' => 'authorization_status',
|
|
'request_type' => 'request_type',
|
|
'status' => 'status',
|
|
'remarks' => 'remarks',
|
|
];
|
|
|
|
$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; // Calculate the offset
|
|
|
|
$query->skip($offset)->take($size);
|
|
}
|
|
|
|
// Get the filtered count of records
|
|
$filteredRecords = $query->count();
|
|
|
|
// Eager load relationships to avoid N+1 query problems
|
|
$query->with(['user', 'branch', 'authorizer']);
|
|
|
|
// Get the data for the current page
|
|
$data = $query->get()->map(function ($item) {
|
|
// Transform data for frontend if needed
|
|
return [
|
|
'id' => $item->id,
|
|
'branch_code' => $item->branch_code,
|
|
'branch_name' => $item->branch->name ?? 'N/A',
|
|
'account_number' => $item->account_number,
|
|
'period_from' => $item->period_from,
|
|
'period_to' => $item->is_period_range ? $item->period_to : null,
|
|
'authorization_status' => $item->authorization_status,
|
|
'is_available' => $item->is_available,
|
|
'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,
|
|
'remarks' => $item->remarks,
|
|
];
|
|
});
|
|
|
|
// Calculate the page count
|
|
$pageCount = ceil($filteredRecords / ($request->get('size') ?: 1));
|
|
|
|
// 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' => $data,
|
|
]);
|
|
}
|
|
|
|
public function destroy(PrintStatementLog $statement)
|
|
{
|
|
// Delete the statement
|
|
$statement->delete();
|
|
|
|
return response()->json([
|
|
'message' => 'Statement deleted successfully.',
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Send statement to email
|
|
*/
|
|
public function sendEmail($id)
|
|
{
|
|
$statement = PrintStatementLog::findOrFail($id);
|
|
|
|
// Check if statement has email
|
|
if (empty($statement->email)) {
|
|
return redirect()->back()->with('error', 'No email address provided for this statement.');
|
|
}
|
|
|
|
// Check if statement is available
|
|
if (!$statement->is_available) {
|
|
return redirect()->back()->with('error', 'Statement is not available for sending.');
|
|
}
|
|
|
|
try {
|
|
$disk = Storage::disk('sftpStatement');
|
|
$filePath = "{$statement->period_from}/{$statement->branch_code}/{$statement->account_number}_{$statement->period_from}.pdf";
|
|
|
|
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 = [];
|
|
|
|
for ($period = clone $periodFrom; $period->lte($periodTo); $period->addMonth()) {
|
|
$periodFormatted = $period->format('Ym');
|
|
$periodPath = $periodFormatted . "/{$statement->branch_code}/{$statement->account_number}_{$periodFormatted}.pdf";
|
|
|
|
if ($disk->exists($periodPath)) {
|
|
$availablePeriods[] = $periodFormatted;
|
|
} else {
|
|
$missingPeriods[] = $periodFormatted;
|
|
}
|
|
}
|
|
|
|
// If any period is available, create a zip and send it
|
|
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}");
|
|
|
|
// 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}/{$statement->branch_code}/{$statement->account_number}_{$statement->period_from}.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();
|
|
|
|
// Send email with zip attachment
|
|
Mail::to($statement->email)
|
|
->send(new StatementEmail($statement, $zipFilePath, true));
|
|
|
|
// Clean up temporary files
|
|
foreach ($availablePeriods as $period) {
|
|
$localFilePath = storage_path("app/temp/{$statement->account_number}_{$period}.pdf");
|
|
if (file_exists($localFilePath)) {
|
|
unlink($localFilePath);
|
|
}
|
|
}
|
|
|
|
// Delete the zip file after sending
|
|
if (file_exists($zipFilePath)) {
|
|
unlink($zipFilePath);
|
|
}
|
|
} else {
|
|
return redirect()->back()->with('error', 'Failed to create zip archive for email.');
|
|
}
|
|
} else {
|
|
return redirect()->back()->with('error', 'No statements available for sending.');
|
|
}
|
|
} else if ($disk->exists($filePath)) {
|
|
// For single period statements
|
|
$localFilePath = storage_path("app/temp/{$statement->account_number}_{$statement->period_from}.pdf");
|
|
|
|
// Ensure the temp directory exists
|
|
if (!file_exists(storage_path('app/temp'))) {
|
|
mkdir(storage_path('app/temp'), 0755, true);
|
|
}
|
|
|
|
// Download the file from SFTP to local storage temporarily
|
|
file_put_contents($localFilePath, $disk->get($filePath));
|
|
|
|
// Send email with PDF attachment
|
|
Mail::to($statement->email)
|
|
->send(new StatementEmail($statement, $localFilePath, false));
|
|
|
|
// Delete the temporary file
|
|
if (file_exists($localFilePath)) {
|
|
unlink($localFilePath);
|
|
}
|
|
} else {
|
|
return redirect()->back()->with('error', 'Statement file not found.');
|
|
}
|
|
|
|
// Update statement record to mark as emailed
|
|
$statement->update([
|
|
'email_sent_at' => now(),
|
|
'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
|
|
Log::error('Failed to send statement email: ' . $e->getMessage());
|
|
|
|
return redirect()->back()->with('error', 'Failed to send email: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generate or fetch the statement file.
|
|
* This is a placeholder method - implement according to your system.
|
|
*/
|
|
protected function generateStatementFile(PrintStatementLog $statement)
|
|
{
|
|
// This would be implemented based on your system's logic
|
|
// For example, calling an API to generate a PDF or fetching from storage
|
|
|
|
// Placeholder implementation - return a dummy path
|
|
$tempFile = tempnam(sys_get_temp_dir(), 'statement_');
|
|
file_put_contents($tempFile, 'Statement content would go here');
|
|
return $tempFile;
|
|
}
|
|
|
|
/**
|
|
* Send statement to email
|
|
*/
|
|
|
|
/**
|
|
* Generate a filename for the statement download.
|
|
*/
|
|
protected function generateFileName(PrintStatementLog $statement)
|
|
{
|
|
$accountNumber = $statement->account_number;
|
|
|
|
if ($statement->is_period_range) {
|
|
return "statement_{$accountNumber}_{$statement->period_from}_to_{$statement->period_to}.pdf";
|
|
}
|
|
|
|
return "statement_{$accountNumber}_{$statement->period_from}.pdf";
|
|
}
|
|
}
|