fix(webstatement): perbaiki eliminasi duplicate pada GenerateClosingBalanceReportJob
Mengganti pendekatan eliminasi duplicate dari validasi di level aplikasi menjadi di level database untuk menangani kasus duplikat dengan sequence yang tidak berdekatan. Perubahan yang dilakukan: - Mengimplementasikan subquery untuk mendapatkan ID unik berdasarkan kombinasi `trans_reference`, `amount_lcy`, dan `booking_date` - Menghapus validasi duplicate berbasis array `$seenTransactions` di level aplikasi - Menggunakan `whereIn` untuk filter transaksi berdasarkan hasil subquery ID unik - Menyederhanakan method `prepareProcessedClosingBalanceData` karena data sudah bersih dari duplicate - Menambahkan logging jumlah transaksi unik untuk monitoring - Mengurangi beban proses sejak awal untuk meningkatkan performa
This commit is contained in:
@@ -3,20 +3,18 @@
|
||||
namespace Modules\Webstatement\Jobs;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\{InteractsWithQueue, SerializesModels};
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\{DB, Log, Storage};
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
use Modules\Webstatement\Models\AccountBalance;
|
||||
use Modules\Webstatement\Models\ClosingBalanceReportLog;
|
||||
use Modules\Webstatement\Models\ProcessedClosingBalance;
|
||||
use Modules\Webstatement\Models\StmtEntry;
|
||||
use Modules\Webstatement\Models\StmtEntryDetail;
|
||||
use Modules\Webstatement\Models\{
|
||||
AccountBalance,
|
||||
ClosingBalanceReportLog,
|
||||
ProcessedClosingBalance,
|
||||
StmtEntry,
|
||||
StmtEntryDetail
|
||||
};
|
||||
|
||||
/**
|
||||
* Job untuk generate laporan closing balance dengan optimasi performa
|
||||
@@ -338,12 +336,12 @@ class GenerateClosingBalanceReportJob implements ShouldQueue
|
||||
* Membangun query transaksi menggunakan relasi Eloquent murni
|
||||
*/
|
||||
/**
|
||||
* Build transaction query dengan eliminasi duplicate yang efektif
|
||||
* Build transaction query dengan eliminasi duplicate yang efektif menggunakan subquery
|
||||
* Membangun query transaksi dengan menghilangkan duplicate trans_reference dan amount_lcy
|
||||
*/
|
||||
private function buildTransactionQuery()
|
||||
{
|
||||
Log::info('Building transaction query with duplicate elimination', [
|
||||
Log::info('Building transaction query with effective duplicate elimination', [
|
||||
'group_name' => $this->groupName,
|
||||
'account_number' => $this->accountNumber,
|
||||
'period' => $this->period
|
||||
@@ -352,13 +350,25 @@ class GenerateClosingBalanceReportJob implements ShouldQueue
|
||||
$modelClass = $this->getModelByGroup();
|
||||
$tableName = (new $modelClass)->getTable();
|
||||
|
||||
// PERBAIKAN: Gunakan groupBy untuk benar-benar menghilangkan duplicate
|
||||
// SOLUSI: Gunakan subquery untuk mendapatkan ID unik dari setiap kombinasi trans_reference + amount_lcy
|
||||
$uniqueIds = DB::table($tableName)
|
||||
->select(DB::raw('MIN(id) as min_id'))
|
||||
->where('account_number', $this->accountNumber)
|
||||
->where('booking_date', $this->period)
|
||||
->groupBy('trans_reference', 'amount_lcy', 'booking_date')
|
||||
->pluck('min_id');
|
||||
|
||||
Log::info('Unique transaction IDs identified', [
|
||||
'total_unique_transactions' => $uniqueIds->count()
|
||||
]);
|
||||
|
||||
// Query hanya transaksi dengan ID yang unik
|
||||
$query = $modelClass::select([
|
||||
DB::raw('MIN(id) as id'), // Ambil ID terkecil untuk setiap group
|
||||
'id',
|
||||
'trans_reference',
|
||||
'booking_date',
|
||||
'amount_lcy',
|
||||
DB::raw('MIN(date_time) as date_time') // Ambil date_time terkecil untuk konsistensi
|
||||
'date_time'
|
||||
])
|
||||
->with([
|
||||
'ft' => function($query) {
|
||||
@@ -372,44 +382,28 @@ class GenerateClosingBalanceReportJob implements ShouldQueue
|
||||
$query->select('id', 'date_time');
|
||||
}
|
||||
])
|
||||
->where('account_number', $this->accountNumber)
|
||||
->where('booking_date', $this->period)
|
||||
// KUNCI: GroupBy untuk menghilangkan duplicate berdasarkan trans_reference dan amount_lcy
|
||||
->groupBy('trans_reference', 'amount_lcy', 'booking_date')
|
||||
->whereIn('id', $uniqueIds)
|
||||
->orderBy('booking_date')
|
||||
->orderBy('date_time');
|
||||
|
||||
Log::info('Transaction query with duplicate elimination built successfully', [
|
||||
Log::info('Transaction query with effective duplicate elimination built successfully', [
|
||||
'model_class' => $modelClass,
|
||||
'table_name' => $tableName
|
||||
'table_name' => $tableName,
|
||||
'unique_transactions' => $uniqueIds->count()
|
||||
]);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare processed closing balance data dengan validasi duplicate
|
||||
* Mempersiapkan data closing balance dengan validasi untuk mencegah duplicate
|
||||
* Prepare processed closing balance data tanpa validasi duplicate (sudah dieliminasi di query)
|
||||
* Mempersiapkan data closing balance tanpa perlu validasi duplicate lagi
|
||||
*/
|
||||
private function prepareProcessedClosingBalanceData($transactions, &$runningBalance, &$sequenceNo): array
|
||||
{
|
||||
$processedData = [];
|
||||
$seenTransactions = []; // Track untuk mencegah duplicate di level aplikasi
|
||||
|
||||
foreach ($transactions as $transaction) {
|
||||
// VALIDASI: Cek duplicate di level aplikasi sebagai safety net
|
||||
$duplicateKey = $transaction->trans_reference . '|' . $transaction->amount_lcy;
|
||||
|
||||
if (isset($seenTransactions[$duplicateKey])) {
|
||||
Log::warning('Duplicate transaction detected and skipped', [
|
||||
'trans_reference' => $transaction->trans_reference,
|
||||
'amount_lcy' => $transaction->amount_lcy,
|
||||
'duplicate_key' => $duplicateKey
|
||||
]);
|
||||
continue; // Skip duplicate
|
||||
}
|
||||
|
||||
$seenTransactions[$duplicateKey] = true;
|
||||
$sequenceNo++;
|
||||
|
||||
// Process transaction data
|
||||
@@ -458,9 +452,8 @@ class GenerateClosingBalanceReportJob implements ShouldQueue
|
||||
];
|
||||
}
|
||||
|
||||
Log::info('Processed closing balance data prepared', [
|
||||
'total_records' => count($processedData),
|
||||
'duplicates_skipped' => count($seenTransactions) - count($processedData)
|
||||
Log::info('Processed closing balance data prepared without duplicates', [
|
||||
'total_records' => count($processedData)
|
||||
]);
|
||||
|
||||
return $processedData;
|
||||
|
||||
Reference in New Issue
Block a user