Merge branch 'new'

# Conflicts:
#	app/Http/Controllers/PrintStatementController.php
#	app/Jobs/GenerateBiayaKartuCsvJob.php
#	app/Jobs/SendStatementEmailJob.php
#	app/Mail/StatementEmail.php
#	resources/views/statements/email.blade.php
#	resources/views/statements/index.blade.php
This commit is contained in:
Daeng Deni Mardaeni
2025-07-08 21:46:55 +07:00
17 changed files with 2241 additions and 1182 deletions

View File

@@ -12,6 +12,7 @@ use Modules\Webstatement\{
Http\Requests\PrintStatementRequest,
Mail\StatementEmail,
Models\PrintStatementLog,
Models\Account,
Models\AccountBalance,
Jobs\ExportStatementPeriodJob
};
@@ -24,9 +25,15 @@ use ZipArchive;
*/
public function index(Request $request)
{
$branches = Branch::orderBy('name')->get();
$branches = Branch::whereNotNull('customer_company')
->where('code', '!=', 'ID0019999')
->orderBy('name')
->get();
return view('webstatement::statements.index', compact('branches'));
$branch = Branch::find(Auth::user()->branch_id);
$multiBranch = session('MULTI_BRANCH') ?? false;
return view('webstatement::statements.index', compact('branches', 'branch', 'multiBranch'));
}
/**
@@ -35,33 +42,67 @@ use ZipArchive;
*/
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['total_accounts'] = 1; // Untuk single account
$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['stmt_sent_type'] = implode(',', $request->input('stmt_sent_type'));
$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(),
'statement_id' => $statement->id,
'user_id' => Auth::id(),
'account_number' => $statement->account_number,
'request_type' => $statement->request_type
'request_type' => $statement->request_type
]);
// Process statement availability check
@@ -69,21 +110,26 @@ use ZipArchive;
if(!$statement->is_available){
$this->printStatementRekening($statement->account_number,$statement->period_from,$statement->period_to,$statement->stmt_sent_type);
}
$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.');
->with('success', 'Statement request has been created successfully.');
} catch (Exception $e) {
DB::rollBack();
Log::error('Failed to create statement request', [
'error' => $e->getMessage(),
'error' => $e->getMessage(),
'user_id' => Auth::id()
]);
return redirect()->back()
->withInput()
->with('error', 'Failed to create statement request: ' . $e->getMessage());
->withInput()
->with('error', 'Failed to create statement request: ' . $e->getMessage());
}
}
@@ -105,19 +151,26 @@ use ZipArchive;
DB::beginTransaction();
try {
$disk = Storage::disk('sftpStatement');
$filePath = "{$statement->period_from}/Print/{$statement->branch_code}/{$statement->account_number}.pdf";
$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);
$periodTo = Carbon::createFromFormat('Ym', $statement->period_to);
$missingPeriods = [];
$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";
$periodPath = $periodFormatted . "/{$statement->branch_code}/{$statement->account_number}_{$periodFormatted}.pdf";
if ($disk->exists($periodPath)) {
$availablePeriods[] = $periodFormatted;
@@ -130,55 +183,55 @@ use ZipArchive;
$notes = "Missing periods: " . implode(', ', $missingPeriods);
$statement->update([
'is_available' => false,
'remarks' => $notes,
'updated_by' => Auth::id(),
'status' => 'failed'
'remarks' => $notes,
'updated_by' => Auth::id(),
'status' => 'failed'
]);
Log::warning('Statement not available - missing periods', [
'statement_id' => $statement->id,
'statement_id' => $statement->id,
'missing_periods' => $missingPeriods
]);
} else {
$statement->update([
'is_available' => true,
'updated_by' => Auth::id(),
'status' => 'completed',
'is_available' => true,
'updated_by' => Auth::id(),
'status' => 'completed',
'processed_accounts' => 1,
'success_count' => 1
'success_count' => 1
]);
Log::info('Statement available - all periods found', [
'statement_id' => $statement->id,
'statement_id' => $statement->id,
'available_periods' => $availablePeriods
]);
}
} else if ($disk->exists($filePath)) {
$statement->update([
'is_available' => true,
'updated_by' => Auth::id(),
'status' => 'completed',
'is_available' => true,
'updated_by' => Auth::id(),
'status' => 'completed',
'processed_accounts' => 1,
'success_count' => 1
'success_count' => 1
]);
Log::info('Statement available', [
'statement_id' => $statement->id,
'file_path' => $filePath
'file_path' => $filePath
]);
} else {
$statement->update([
'is_available' => false,
'updated_by' => Auth::id(),
'status' => 'failed',
'is_available' => false,
'updated_by' => Auth::id(),
'status' => 'failed',
'processed_accounts' => 1,
'failed_count' => 1,
'error_message' => 'Statement file not found'
'failed_count' => 1,
'error_message' => 'Statement file not found'
]);
Log::warning('Statement not available', [
'statement_id' => $statement->id,
'file_path' => $filePath
'file_path' => $filePath
]);
}
@@ -188,14 +241,14 @@ use ZipArchive;
Log::error('Error checking statement availability', [
'statement_id' => $statement->id,
'error' => $e->getMessage()
'error' => $e->getMessage()
]);
$statement->update([
'is_available' => false,
'status' => 'failed',
'is_available' => false,
'status' => 'failed',
'error_message' => $e->getMessage(),
'updated_by' => Auth::id()
'updated_by' => Auth::id()
]);
}
}
@@ -226,33 +279,161 @@ use ZipArchive;
$statement->update([
'is_downloaded' => true,
'downloaded_at' => now(),
'updated_by' => Auth::id()
'updated_by' => Auth::id()
]);
Log::info('Statement downloaded', [
'statement_id' => $statement->id,
'user_id' => Auth::id(),
'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}/Print/{$statement->branch_code}/{$statement->account_number}.pdf";
$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) {
// Handle period range download (existing logic)
// ... existing zip creation logic ...
// 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()
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
return back()->with('error', 'Failed to download statement: ' . $e->getMessage());
@@ -298,6 +479,13 @@ use ZipArchive;
// 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');
@@ -340,13 +528,13 @@ use ZipArchive;
// Map frontend column names to database column names if needed
$columnMap = [
'branch' => 'branch_code',
'account' => 'account_number',
'period' => 'period_from',
'auth_status' => 'authorization_status',
'branch' => 'branch_code',
'account' => 'account_number',
'period' => 'period_from',
'auth_status' => 'authorization_status',
'request_type' => 'request_type',
'status' => 'status',
'remarks' => 'remarks',
'status' => 'status',
'remarks' => 'remarks',
];
$dbColumn = $columnMap[$column] ?? $column;
@@ -430,6 +618,7 @@ use ZipArchive;
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.');
@@ -442,7 +631,7 @@ use ZipArchive;
try {
$disk = Storage::disk('sftpStatement');
$filePath = "{$statement->period_from}/Print/{$statement->branch_code}/{$statement->account_number}.pdf";
$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);
@@ -454,7 +643,7 @@ use ZipArchive;
for ($period = clone $periodFrom; $period->lte($periodTo); $period->addMonth()) {
$periodFormatted = $period->format('Ym');
$periodPath = $periodFormatted . "/Print/{$statement->branch_code}/{$statement->account_number}.pdf";
$periodPath = $periodFormatted . "/{$statement->branch_code}/{$statement->account_number}_{$periodFormatted}.pdf";
if ($disk->exists($periodPath)) {
$availablePeriods[] = $periodFormatted;
@@ -479,7 +668,7 @@ use 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";
$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
@@ -545,8 +734,8 @@ use ZipArchive;
Log::info('Statement email sent successfully', [
'statement_id' => $statement->id,
'email' => $statement->email,
'user_id' => Auth::id()
'email' => $statement->email,
'user_id' => Auth::id()
]);
DB::commit();