Compare commits

...

4 Commits

Author SHA1 Message Date
Daeng Deni Mardaeni
47bf23302f refactor(webstatement): ganti namespace trait Userstamps untuk kompatibilitas
- Mengganti pemanggilan trait `Userstamps` dari `Wildside\Userstamps\Userstamps` menjadi `Mattiverse\Userstamps\Traits\Userstamps`:
  - Update dilakukan pada file `Modules/Webstatement/app/Models/Base.php`.
  - Perubahan ini memastikan penggunaan namespace yang sesuai dan kompatibel dengan library yang terbaru.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
2025-06-05 16:50:18 +07:00
Daeng Deni Mardaeni
d85954bdf2 feat(webstatement): tambahkan pengaturan tujuan output dan unggah ke SFTP untuk combine PDF
- Memperbarui `CombinePdfJob`:
  - Menambahkan parameter baru `outputDestination`, `branchCode`, dan `period` pada constructor untuk pengaturan tujuan output.
  - Menambahkan opsi tujuan output ke `local` atau `sftp` pada proses combine PDF.
  - Menambahkan metode baru `uploadToSftp` untuk mengunggah file PDF hasil gabungan ke SFTP.
  - Mengatur jalur unggahan SFTP ke `combine/{period}/{branchCode}/{filename}`.
  - Menambahkan log informasi terkait jalur dan status unggahan file PDF ke SFTP.

- Memperbarui `CombinePdfController`:
  - Menambahkan konfigurasi `output_destination` untuk menentukan tujuan output (`local` atau `sftp`).
  - Memperbarui pemanggilan `CombinePdfJob::dispatch` dengan parameter baru untuk konfigurasi output dan SFTP.
  - Menyesuaikan log dan respons untuk mencerminkan tujuan output yang disetel.

- Tujuan pembaruan ini:
  - Memungkinkan pengaturan flexibel tujuan penyimpanan file PDF ke lokal atau SFTP.
  - Menyediakan log yang lebih informatif terkait proses combine PDF dan unggahan SFTP.
  - Mempermudah integrasi dan pengelolaan file PDF dengan pengaturan jalur dan periodisasi yang jelas.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
2025-06-05 11:37:09 +07:00
Daeng Deni Mardaeni
db99465690 feat(webstatement): tambahkan konfigurasi sumber file r23 dan optimalkan log combine PDF
- Memperbarui fungsi `combinePdfs` di `CombinePdfController`:
  - Menambahkan konfigurasi sumber file `r23` dengan opsi `local` atau `sftp`.
  - Memindahkan logika pencarian file `r23` ke dalam pengaturan berbasis konfigurasi:
    - Jika menggunakan `local`, sistem mencari file `r23` dalam penyimpanan lokal.
    - Jika menggunakan `sftp`, sistem mengunduh file `r23` dari SFTP dan menyimpannya ke direktori sementara.
  - Menambahkan log informasi untuk menentukan sumber file `r23` yang digunakan (`local` atau `sftp`).
  - Merubah pencatatan log yang sebelumnya statis menjadi dinamis berdasarkan konfigurasi.

- Menyesuaikan pengelolaan jalur file `r23`:
  - Menambahkan jalur sementara untuk penyimpanan file hasil unduhan SFTP.
  - Memisahkan logika jalur file lokal dan file unduhan berdasarkan konfigurasi.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
2025-06-05 11:31:31 +07:00
Daeng Deni Mardaeni
df5d0c420b feat(webstatement): optimalkan logika combine PDF dan pengaturan password dinamis
- Memperbarui fungsi `combinePdfs` di `CombinePdfController`:
  - Menambahkan dukungan pengunduhan file `r23` dari SFTP dan penyimpanan sementara ke direktori lokal.
  - Mengubah filter `branch_code` dari `ID0010001` menjadi `ID0010052` untuk pemrosesan akun.
  - Menambahkan log peringatan dan error untuk mengelola skenario file yang tidak ditemukan atau error saat unduhan dari SFTP.

- Memperkenalkan logika baru untuk pengaturan password dinamis pada file PDF:
  - Menambahkan metode `generatePassword` untuk menghasilkan password berdasarkan data customers.
  - Format password: kombinasi `ddMmmyyyyXX` (contoh: 05Oct202585), menggunakan tanggal yang relevan dan 2 digit terakhir nomor rekening.
  - Handling fallback ke nomor rekening jika tidak ada data tanggal yang tersedia.
  - Menambahkan validasi parsing tanggal untuk menghindari error format.

- Tujuan pembaruan ini:
  - Memastikan proses combine PDF lebih fleksibel dengan pengunduhan file dari SFTP.
  - Meningkatkan keamanan PDF dengan pengaturan password dinamis berdasarkan data customers.
  - Mempermudah troubleshooting dengan penambahan log yang lebih informatif terkait proses file dan password.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
2025-06-05 11:19:25 +07:00
3 changed files with 163 additions and 23 deletions

View File

@@ -5,9 +5,11 @@ namespace Modules\Webstatement\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
use Modules\Webstatement\Jobs\CombinePdfJob;
use Modules\Webstatement\Models\Account;
use Carbon\Carbon;
class CombinePdfController extends Controller
{
@@ -27,11 +29,17 @@ class CombinePdfController extends Controller
*/
public function combinePdfs($period)
{
// Configuration: Set r23 file source - 'local' or 'sftp'
$file_r23 = 'local'; // Change this to 'sftp' to use SFTP for r23 files
// Configuration: Set output destination - 'local' or 'sftp'
$output_destination = 'local'; // Change this to 'sftp' to upload combined PDFs to SFTP
// Get period from request or use current period
$period = $period ?? date('Ym');
// Get all accounts
$accounts = Account::where('branch_code','ID0010001')->get();
// Get all accounts with customer relation
$accounts = Account::where('branch_code','ID0010052')->get();
$processedCount = 0;
$skippedCount = 0;
$errorCount = 0;
@@ -41,41 +49,76 @@ class CombinePdfController extends Controller
$accountNumber = $account->account_number;
// Define file paths
$r14Path = storage_path("app/STMT/r14/{$period}/{$branchCode}/{$accountNumber}_{$period}.pdf");
$r23Path = storage_path("app/STMT/r23/{$period}/{$branchCode}/{$accountNumber}_{$period}.pdf");
$r14Path = storage_path("app/r14/{$accountNumber}_{$period}.pdf");
// Define r23 paths based on configuration
$r23LocalPath = storage_path("app/r23/{$accountNumber}.1.pdf");
$r23SftpPath = "r23/{$accountNumber}.1.pdf";
// Define temporary path for r23 file downloaded from SFTP
$tempDir = storage_path("app/temp/{$period}");
if (!File::exists($tempDir)) {
File::makeDirectory($tempDir, 0755, true);
}
$r23TempPath = "{$tempDir}/{$accountNumber}_r23.pdf";
$outputDir = storage_path("app/combine/{$period}/{$branchCode}");
$outputFilename = "{$accountNumber}_{$period}.pdf";
// Check if files exist
// Check if r14 file exists locally
$r14Exists = File::exists($r14Path);
$r23Exists = File::exists($r23Path);
// Check for r23 file based on configuration
$r23Exists = false;
$r23FinalPath = null;
if ($file_r23 === 'local') {
// Use local r23 files
if (File::exists($r23LocalPath)) {
$r23Exists = true;
$r23FinalPath = $r23LocalPath;
Log::info("Found r23 file locally for account {$accountNumber}");
}
} elseif ($file_r23 === 'sftp') {
// Use SFTP r23 files
try {
if (Storage::disk('sftpStatement')->exists($r23SftpPath)) {
$r23Content = Storage::disk('sftpStatement')->get($r23SftpPath);
File::put($r23TempPath, $r23Content);
$r23Exists = true;
$r23FinalPath = $r23TempPath;
Log::info("Downloaded r23 file for account {$accountNumber} from SFTP");
}
} catch (\Exception $e) {
Log::error("Error downloading r23 file from SFTP for account {$accountNumber}: {$e->getMessage()}");
}
}
// Skip if neither file exists
if (!$r14Exists && !$r23Exists) {
Log::warning("No PDF files found for account {$accountNumber}");
//Log::warning("No PDF files found for account {$accountNumber}");
$skippedCount++;
continue;
}
// If both files exist, combine them
if ($r14Exists && $r23Exists) {
Log::info("Combining PDFs for account {$accountNumber}");
$pdfFiles = [$r14Path, $r23Path];
// Prepare file list for processing
$pdfFiles = [];
if ($r14Exists) {
$pdfFiles[] = $r14Path;
}
// If only one file exists, just apply password protection
else {
Log::info("Applying password protection to single PDF for account {$accountNumber}");
$pdfFile = $r14Exists ? $r14Path : $r23Path;
$pdfFiles = [$pdfFile];
if ($r23Exists) {
$pdfFiles[] = $r23FinalPath;
}
try {
// Use the account number as password
$password = $accountNumber;
// Generate password based on customer relation data
$password = $this->generatePassword($account);
// Dispatch job to combine PDFs or apply password protection
CombinePdfJob::dispatch($pdfFiles, $outputDir, $outputFilename, $password);
CombinePdfJob::dispatch($pdfFiles, $outputDir, $outputFilename, $password, $output_destination, $branchCode, $period);
$processedCount++;
Log::info("Queued PDF processing for account {$accountNumber} - r14: local, r23: {$file_r23}, output: {$output_destination}, password: {$password}");
} catch (\Exception $e) {
Log::error("Error processing PDF for account {$accountNumber}: {$e->getMessage()}");
$errorCount++;
@@ -83,11 +126,65 @@ class CombinePdfController extends Controller
}
return response()->json([
'message' => 'PDF combination process has been queued',
'message' => "PDF combination process has been queued (r14: local, r23: {$file_r23}, output: {$output_destination})",
'processed' => $processedCount,
'skipped' => $skippedCount,
'errors' => $errorCount,
'period' => $period
]);
}
/**
* Generate password based on customer relation data
* Format: date+end 2 digit account_number
* Example: 05Oct202585
*
* @param Account $account
* @return string
*/
private function generatePassword(Account $account)
{
$customer = $account->customer;
$accountNumber = $account->account_number;
// Get last 2 digits of account number
$lastTwoDigits = substr($accountNumber, -2);
// Determine which date to use based on sector
$dateToUse = null;
if ($customer && $customer->sector) {
$firstDigitSector = substr($customer->sector, 0, 1);
if ($firstDigitSector === '1') {
// Use date_of_birth if available, otherwise birth_incorp_date
$dateToUse = $customer->date_of_birth ?: $customer->birth_incorp_date;
} else {
// Use birth_incorp_date for sector > 1
$dateToUse = $customer->birth_incorp_date;
}
}
// If no date found, fallback to account number
if (!$dateToUse) {
Log::warning("No date found for account {$accountNumber}, using account number as password");
return $accountNumber;
}
try {
// Parse the date and format it
$date = Carbon::parse($dateToUse);
$day = $date->format('d');
$month = $date->format('M'); // 3-letter month abbreviation
$year = $date->format('Y');
// Format: ddMmmyyyyXX (e.g., 05Oct202585)
$password = $day . $month . $year . $lastTwoDigits;
return $password;
} catch (\Exception $e) {
Log::error("Error parsing date for account {$accountNumber}: {$e->getMessage()}");
return $accountNumber; // Fallback to account number
}
}
}

View File

@@ -10,6 +10,7 @@ use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\File;
use Owenoj\PDFPasswordProtect\Facade\PDFPasswordProtect;
use Webklex\PDFMerger\Facades\PDFMergerFacade as PDFMerger;
@@ -21,6 +22,9 @@ class CombinePdfJob implements ShouldQueue
protected $outputPath;
protected $outputFilename;
protected $password;
protected $outputDestination;
protected $branchCode;
protected $period;
/**
* Create a new job instance.
@@ -29,13 +33,19 @@ class CombinePdfJob implements ShouldQueue
* @param string $outputPath Directory where the combined PDF will be saved
* @param string $outputFilename Filename for the combined PDF
* @param string $password Password to protect the PDF
* @param string $outputDestination Output destination: 'local' or 'sftp'
* @param string $branchCode Branch code for SFTP path
* @param string $period Period for SFTP path
*/
public function __construct(array $pdfFiles, string $outputPath, string $outputFilename, string $password)
public function __construct(array $pdfFiles, string $outputPath, string $outputFilename, string $password, string $outputDestination = 'local', string $branchCode = '', string $period = '')
{
$this->pdfFiles = $pdfFiles;
$this->outputPath = $outputPath;
$this->outputFilename = $outputFilename;
$this->password = $password;
$this->outputDestination = $outputDestination;
$this->branchCode = $branchCode;
$this->period = $period;
}
/**
@@ -86,10 +96,43 @@ class CombinePdfJob implements ShouldQueue
Log::info("PDF password protection applied successfully.");
}
Log::info("PDFs combined successfully. Output file: {$fullPath}");
// Handle output destination
if ($this->outputDestination === 'sftp') {
$this->uploadToSftp($fullPath);
}
Log::info("PDFs combined successfully. Output file: {$fullPath}, Destination: {$this->outputDestination}");
} catch (Exception $e) {
Log::error("Error combining PDFs: " . $e->getMessage());
throw $e;
}
}
/**
* Upload the combined PDF to SFTP server
*
* @param string $localFilePath
*/
private function uploadToSftp(string $localFilePath): void
{
try {
// Define SFTP path: combine/{period}/{branchCode}/{filename}
$sftpPath = "combine/{$this->period}/{$this->branchCode}/{$this->outputFilename}";
// Read the local file content
$fileContent = File::get($localFilePath);
// Upload to SFTP
Storage::disk('sftpStatement')->put($sftpPath, $fileContent);
Log::info("Combined PDF uploaded to SFTP: {$sftpPath}");
// Optionally, remove the local file after successful upload
// File::delete($localFilePath);
} catch (\Exception $e) {
Log::error("Error uploading combined PDF to SFTP: {$e->getMessage()}");
throw $e;
}
}
}

View File

@@ -6,7 +6,7 @@
use Illuminate\Database\Eloquent\SoftDeletes;
use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\LogsActivity;
use Wildside\Userstamps\Userstamps;
use Mattiverse\Userstamps\Traits\Userstamps;
/**