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 {
|
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');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user