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:
@@ -55,15 +55,7 @@
|
||||
try {
|
||||
Log::info("Starting export statement job for account: {$this->account_number}, period: {$this->period}");
|
||||
|
||||
// Cek apakah data sudah diproses sebelumnya
|
||||
$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();
|
||||
}
|
||||
$this->processStatementData();
|
||||
|
||||
// Export data yang sudah diproses ke CSV
|
||||
$this->exportToCsv();
|
||||
@@ -75,77 +67,119 @@
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process statement data and save to database
|
||||
*/
|
||||
private function processStatementData()
|
||||
: void
|
||||
private function processStatementData(): void
|
||||
{
|
||||
// Hapus data yang mungkin sudah ada untuk kombinasi account dan period yang sama
|
||||
ProcessedStatement::where('account_number', $this->account_number)
|
||||
->where('period', $this->period)
|
||||
->delete();
|
||||
$accountQuery = [
|
||||
'account_number' => $this->account_number,
|
||||
'period' => $this->period
|
||||
];
|
||||
|
||||
$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;
|
||||
$totalCount = StmtEntry::where('account_number', $this->account_number)
|
||||
->where('booking_date', $this->period)
|
||||
->count();
|
||||
$globalSequence = 0;
|
||||
|
||||
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'])
|
||||
->where('account_number', $this->account_number)
|
||||
->where('booking_date', $this->period)
|
||||
->orderBy('date_time', 'ASC')
|
||||
->orderBy('trans_reference', 'ASC')
|
||||
->chunk($this->chunkSize, function ($entries) use (&$runningBalance, &$globalSequence) {
|
||||
$processedData = [];
|
||||
->where('account_number', $this->account_number)
|
||||
->where('booking_date', $this->period)
|
||||
->orderBy('date_time', 'ASC')
|
||||
->orderBy('trans_reference', 'ASC')
|
||||
->chunk($this->chunkSize, function ($entries) use (&$runningBalance, &$globalSequence) {
|
||||
$processedData = $this->prepareProcessedData($entries, $runningBalance, $globalSequence);
|
||||
|
||||
foreach ($entries as $item) {
|
||||
$globalSequence++; // Increment the global sequence counter
|
||||
$runningBalance += (float) $item->amount_lcy;
|
||||
if (!empty($processedData)) {
|
||||
DB::table('processed_statements')->insert($processedData);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
$transactionDate = Carbon::createFromFormat('YmdHi', $item->booking_date . substr($item->ft?->date_time ?? '0000000000', 6, 4))
|
||||
->format('d/m/Y H:i');
|
||||
} catch (Exception $e) {
|
||||
$transactionDate = Carbon::now()->format('d/m/Y H:i');
|
||||
Log::warning("Error formatting transaction date: " . $e->getMessage());
|
||||
}
|
||||
private function prepareProcessedData($entries, &$runningBalance, &$globalSequence): array
|
||||
{
|
||||
$processedData = [];
|
||||
|
||||
try {
|
||||
$actualDate = Carbon::createFromFormat('ymdHi', $item->ft?->date_time ?? '2505120000')
|
||||
->format('d/m/Y H:i');
|
||||
} catch (Exception $e) {
|
||||
$actualDate = Carbon::now()->format('d/m/Y H:i');
|
||||
Log::warning("Error formatting actual date: " . $e->getMessage());
|
||||
}
|
||||
foreach ($entries as $item) {
|
||||
$globalSequence++;
|
||||
$runningBalance += (float) $item->amount_lcy;
|
||||
|
||||
$processedData[] = [
|
||||
'account_number' => $this->account_number,
|
||||
'period' => $this->period,
|
||||
'sequence_no' => $globalSequence,
|
||||
'transaction_date' => $transactionDate,
|
||||
'reference_number' => $item->trans_reference,
|
||||
'transaction_amount' => $item->amount_lcy,
|
||||
'transaction_type' => $item->amount_lcy < 0 ? 'D' : 'C',
|
||||
'description' => $this->generateNarrative($item),
|
||||
'end_balance' => $runningBalance,
|
||||
'actual_date' => $actualDate,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
];
|
||||
}
|
||||
// var_dump($processedData);
|
||||
// Simpan data dalam batch untuk kinerja yang lebih baik
|
||||
if (!empty($processedData)) {
|
||||
DB::table('processed_statements')->insert($processedData);
|
||||
}
|
||||
});
|
||||
$transactionDate = $this->formatTransactionDate($item);
|
||||
$actualDate = $this->formatActualDate($item);
|
||||
|
||||
$processedData[] = [
|
||||
'account_number' => $this->account_number,
|
||||
'period' => $this->period,
|
||||
'sequence_no' => $globalSequence,
|
||||
'transaction_date' => $transactionDate,
|
||||
'reference_number' => $item->trans_reference,
|
||||
'transaction_amount' => $item->amount_lcy,
|
||||
'transaction_type' => $item->amount_lcy < 0 ? 'D' : 'C',
|
||||
'description' => $this->generateNarrative($item),
|
||||
'end_balance' => $runningBalance,
|
||||
'actual_date' => $actualDate,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
];
|
||||
}
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user