fix(webstatement): optimasi proses pengelolaan statement dan perbaikan logika pemrosesan data

- Menghilangkan pengecekan data yang sebelumnya diproses dengan memindahkan logika perbandingan jumlah data ke dalam fungsi `processStatementData`.
- Menambahkan beberapa fungsi baru untuk memisahkan logika ke dalam unit yang lebih kecil:
  1. `getTotalEntryCount`: Menghitung total jumlah data berdasarkan kriteria akun dan periode.
  2. `getExistingProcessedCount`: Menghitung jumlah data yang sudah diproses.
  3. `deleteExistingProcessedData`: Menghapus data hasil proses sebelumnya jika ada ketidaksesuaian jumlah.
  4. `processAndSaveStatementEntries`: Memproses dan menyimpan data dalam batch untuk efisiensi memori.
  5. `prepareProcessedData`: Menyiapkan array data hasil pemrosesan sebelum disimpan ke database.
  6. `formatTransactionDate`: Memformat tanggal transaksi dengan logika fallback pada error parsing.
  7. `formatActualDate`: Memformat tanggal aktual dengan fallback dan logging untuk error parsing.
- Memperbaiki logika pemrosesan data statement:
  - Menambahkan validasi jumlah data yang diproses untuk menghindari duplikasi atau penghapusan data yang tidak semestinya.
  - Menghapus semua data hasil proses sebelumnya untuk satu kombinasi akun dan periode hanya jika terjadi ketidaksesuaian jumlah data.
- Menggunakan chunk batch untuk memproses data dengan lebih efisien, mengurangi penggunaan memori, dan meningkatkan kestabilan aplikasi.
- Menyempurnakan logging untuk memberikan informasi lebih rinci terkait proses pemrosesan data dan mengantisipasi error.
- Mengubah format data waktu pada proses narasi dengan fallback yang lebih aman guna mencegah kegagalan parsing.
- Menambahkan penghapusan data lama sebelum proses penyimpanan ulang guna memastikan konsistensi.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
This commit is contained in:
Daeng Deni Mardaeni
2025-05-23 21:28:39 +07:00
parent 9f0ee812a9
commit 57463f2429

View File

@@ -55,15 +55,7 @@
try { try {
Log::info("Starting export statement job for account: {$this->account_number}, period: {$this->period}"); Log::info("Starting export statement job for account: {$this->account_number}, period: {$this->period}");
// Cek apakah data sudah diproses sebelumnya $this->processStatementData();
$existingData = ProcessedStatement::where('account_number', $this->account_number)
->where('period', $this->period)
->exists();
if (!$existingData) {
// Jika belum ada data yang diproses, lakukan pemrosesan
$this->processStatementData();
}
// Export data yang sudah diproses ke CSV // Export data yang sudah diproses ke CSV
$this->exportToCsv(); $this->exportToCsv();
@@ -75,77 +67,119 @@
} }
} }
/** private function processStatementData(): void
* Process statement data and save to database
*/
private function processStatementData()
: void
{ {
// Hapus data yang mungkin sudah ada untuk kombinasi account dan period yang sama $accountQuery = [
ProcessedStatement::where('account_number', $this->account_number) 'account_number' => $this->account_number,
->where('period', $this->period) 'period' => $this->period
->delete(); ];
$totalCount = $this->getTotalEntryCount($accountQuery);
$existingDataCount = $this->getExistingProcessedCount($accountQuery);
// Hanya proses jika data belum lengkap diproses
if ($existingDataCount !== $totalCount) {
$this->deleteExistingProcessedData($accountQuery);
$this->processAndSaveStatementEntries($totalCount);
}
}
private function getTotalEntryCount(array $criteria): int
{
return StmtEntry::where('account_number', $criteria['account_number'])
->where('booking_date', $criteria['period'])
->count();
}
private function getExistingProcessedCount(array $criteria): int
{
return ProcessedStatement::where('account_number', $criteria['account_number'])
->where('period', $criteria['period'])
->count();
}
private function deleteExistingProcessedData(array $criteria): void
{
ProcessedStatement::where('account_number', $criteria['account_number'])
->where('period', $criteria['period'])
->delete();
}
private function processAndSaveStatementEntries(int $totalCount): void
{
$runningBalance = (float) $this->saldo; $runningBalance = (float) $this->saldo;
$totalCount = StmtEntry::where('account_number', $this->account_number) $globalSequence = 0;
->where('booking_date', $this->period)
->count();
Log::info("Processing {$totalCount} statement entries for account: {$this->account_number}"); Log::info("Processing {$totalCount} statement entries for account: {$this->account_number}");
// Track the global sequence number across chunks
$globalSequence = 0;
// Proses data dalam chunk untuk mengurangi penggunaan memori
StmtEntry::with(['ft', 'transaction']) StmtEntry::with(['ft', 'transaction'])
->where('account_number', $this->account_number) ->where('account_number', $this->account_number)
->where('booking_date', $this->period) ->where('booking_date', $this->period)
->orderBy('date_time', 'ASC') ->orderBy('date_time', 'ASC')
->orderBy('trans_reference', 'ASC') ->orderBy('trans_reference', 'ASC')
->chunk($this->chunkSize, function ($entries) use (&$runningBalance, &$globalSequence) { ->chunk($this->chunkSize, function ($entries) use (&$runningBalance, &$globalSequence) {
$processedData = []; $processedData = $this->prepareProcessedData($entries, $runningBalance, $globalSequence);
foreach ($entries as $item) { if (!empty($processedData)) {
$globalSequence++; // Increment the global sequence counter DB::table('processed_statements')->insert($processedData);
$runningBalance += (float) $item->amount_lcy; }
});
}
try { private function prepareProcessedData($entries, &$runningBalance, &$globalSequence): array
$transactionDate = Carbon::createFromFormat('YmdHi', $item->booking_date . substr($item->ft?->date_time ?? '0000000000', 6, 4)) {
->format('d/m/Y H:i'); $processedData = [];
} catch (Exception $e) {
$transactionDate = Carbon::now()->format('d/m/Y H:i');
Log::warning("Error formatting transaction date: " . $e->getMessage());
}
try { foreach ($entries as $item) {
$actualDate = Carbon::createFromFormat('ymdHi', $item->ft?->date_time ?? '2505120000') $globalSequence++;
->format('d/m/Y H:i'); $runningBalance += (float) $item->amount_lcy;
} catch (Exception $e) {
$actualDate = Carbon::now()->format('d/m/Y H:i');
Log::warning("Error formatting actual date: " . $e->getMessage());
}
$processedData[] = [ $transactionDate = $this->formatTransactionDate($item);
'account_number' => $this->account_number, $actualDate = $this->formatActualDate($item);
'period' => $this->period,
'sequence_no' => $globalSequence, $processedData[] = [
'transaction_date' => $transactionDate, 'account_number' => $this->account_number,
'reference_number' => $item->trans_reference, 'period' => $this->period,
'transaction_amount' => $item->amount_lcy, 'sequence_no' => $globalSequence,
'transaction_type' => $item->amount_lcy < 0 ? 'D' : 'C', 'transaction_date' => $transactionDate,
'description' => $this->generateNarrative($item), 'reference_number' => $item->trans_reference,
'end_balance' => $runningBalance, 'transaction_amount' => $item->amount_lcy,
'actual_date' => $actualDate, 'transaction_type' => $item->amount_lcy < 0 ? 'D' : 'C',
'created_at' => now(), 'description' => $this->generateNarrative($item),
'updated_at' => now(), 'end_balance' => $runningBalance,
]; 'actual_date' => $actualDate,
} 'created_at' => now(),
// var_dump($processedData); 'updated_at' => now(),
// Simpan data dalam batch untuk kinerja yang lebih baik ];
if (!empty($processedData)) { }
DB::table('processed_statements')->insert($processedData);
} return $processedData;
}); }
private function formatTransactionDate($item): string
{
try {
return Carbon::createFromFormat(
'YmdHi',
$item->booking_date . substr($item->ft?->date_time ?? '0000000000', 6, 4)
)->format('d/m/Y H:i');
} catch (Exception $e) {
Log::warning("Error formatting transaction date: " . $e->getMessage());
return Carbon::now()->format('d/m/Y H:i');
}
}
private function formatActualDate($item): string
{
try {
return Carbon::createFromFormat(
'ymdHi',
$item->ft?->date_time ?? '2505120000'
)->format('d/m/Y H:i');
} catch (Exception $e) {
Log::warning("Error formatting actual date: " . $e->getMessage());
return Carbon::now()->format('d/m/Y H:i');
}
} }
/** /**