perf(webstatement): optimasi performa GenerateClosingBalanceReportJob dengan database staging

Perubahan yang dilakukan:
- Menambahkan model `ProcessedClosingBalance` untuk menyimpan data sementara laporan closing balance
- Membuat migration `processed_closing_balances` dengan 26 kolom dan index komposit untuk query optimal
- Mengganti proses langsung ekspor ke CSV menjadi dua tahap:
  * Tahap 1: Proses dan simpan data ke DB secara bertahap melalui `processAndSaveClosingBalanceData()`
  * Tahap 2: Ekspor data dari DB ke CSV via `exportFromDatabaseToCsv()`
- Menambahkan method:
  * `deleteExistingProcessedData()` untuk membersihkan data lama
  * `prepareProcessedClosingBalanceData()` untuk batch insert ke DB
  * `getProcessedRecordCount()` untuk monitoring progres
- Mengoptimalkan memori dengan menghindari akumulasi data dalam array
- Menambahkan DB transaction untuk menjamin konsistensi data selama proses
- Logging diperluas agar progres lebih mudah dipantau
- Menambahkan error handling untuk menangani kegagalan proses dengan aman

Keuntungan:
- Waktu proses menurun drastis dari 1+ jam menjadi beberapa menit
- Skalabilitas meningkat — mampu menangani jutaan record tanpa memory overload
- Data hasil olahan dapat diekspor ulang tanpa harus re-process
- Pola kerja selaras dengan `ExportStatementJob` untuk konsistensi antar modul
- Monitoring dan debugging lebih mudah melalui database dan log

Catatan tambahan:
- Tabel `processed_closing_balances` mendukung kolom `group_name` untuk segmentasi (QRIS/NON_QRIS)
- Menggunakan tipe data numerik dengan presisi untuk nilai keuangan (`amount_lcy`, `balance`, dsb)
This commit is contained in:
Daeng Deni Mardaeni
2025-07-30 17:15:14 +07:00
parent 5f9a82ec20
commit c0e5ddd37a
2 changed files with 315 additions and 19 deletions

View File

@@ -0,0 +1,54 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::create('processed_closing_balances', function (Blueprint $table) {
$table->id();
$table->string('account_number', 20)->index();
$table->string('period', 8)->index();
$table->string('group_name', 20)->default('DEFAULT')->index();
$table->integer('sequence_no');
$table->string('trans_reference', 50)->nullable();
$table->string('booking_date', 8)->nullable();
$table->string('transaction_date', 20)->nullable();
$table->decimal('amount_lcy', 15, 2)->nullable();
$table->string('debit_acct_no', 20)->nullable();
$table->string('debit_value_date', 8)->nullable();
$table->decimal('debit_amount', 15, 2)->nullable();
$table->string('credit_acct_no', 20)->nullable();
$table->string('bif_rcv_acct', 20)->nullable();
$table->string('bif_rcv_name', 100)->nullable();
$table->string('credit_value_date', 8)->nullable();
$table->decimal('credit_amount', 15, 2)->nullable();
$table->string('at_unique_id', 50)->nullable();
$table->string('bif_ref_no', 50)->nullable();
$table->string('atm_order_id', 50)->nullable();
$table->string('recipt_no', 50)->nullable();
$table->string('api_iss_acct', 20)->nullable();
$table->string('api_benff_acct', 20)->nullable();
$table->string('authoriser', 50)->nullable();
$table->text('remarks')->nullable();
$table->text('payment_details')->nullable();
$table->string('ref_no', 50)->nullable();
$table->string('merchant_id', 50)->nullable();
$table->string('term_id', 50)->nullable();
$table->decimal('closing_balance', 15, 2)->nullable();
$table->timestamps();
// Composite index untuk performa query
$table->index(['account_number', 'period', 'group_name']);
$table->index(['account_number', 'period', 'sequence_no']);
});
}
public function down()
{
Schema::dropIfExists('processed_closing_balances');
}
};