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;
|
namespace Modules\Webstatement\Jobs;
|
||||||
|
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Queue\{InteractsWithQueue, SerializesModels};
|
||||||
use Illuminate\Foundation\Bus\Dispatchable;
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Support\Facades\{DB, Log, Storage};
|
||||||
use Illuminate\Queue\SerializesModels;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Illuminate\Support\Facades\Storage;
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Modules\Webstatement\Models\AccountBalance;
|
use Modules\Webstatement\Models\{
|
||||||
use Modules\Webstatement\Models\ClosingBalanceReportLog;
|
AccountBalance,
|
||||||
use Modules\Webstatement\Models\ProcessedClosingBalance;
|
ClosingBalanceReportLog,
|
||||||
use Modules\Webstatement\Models\StmtEntry;
|
ProcessedClosingBalance,
|
||||||
use Modules\Webstatement\Models\StmtEntryDetail;
|
StmtEntry,
|
||||||
|
StmtEntryDetail
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Job untuk generate laporan closing balance dengan optimasi performa
|
* Job untuk generate laporan closing balance dengan optimasi performa
|
||||||
@@ -338,12 +336,12 @@ class GenerateClosingBalanceReportJob implements ShouldQueue
|
|||||||
* Membangun query transaksi menggunakan relasi Eloquent murni
|
* 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
|
* Membangun query transaksi dengan menghilangkan duplicate trans_reference dan amount_lcy
|
||||||
*/
|
*/
|
||||||
private function buildTransactionQuery()
|
private function buildTransactionQuery()
|
||||||
{
|
{
|
||||||
Log::info('Building transaction query with duplicate elimination', [
|
Log::info('Building transaction query with effective duplicate elimination', [
|
||||||
'group_name' => $this->groupName,
|
'group_name' => $this->groupName,
|
||||||
'account_number' => $this->accountNumber,
|
'account_number' => $this->accountNumber,
|
||||||
'period' => $this->period
|
'period' => $this->period
|
||||||
@@ -352,13 +350,25 @@ class GenerateClosingBalanceReportJob implements ShouldQueue
|
|||||||
$modelClass = $this->getModelByGroup();
|
$modelClass = $this->getModelByGroup();
|
||||||
$tableName = (new $modelClass)->getTable();
|
$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([
|
$query = $modelClass::select([
|
||||||
DB::raw('MIN(id) as id'), // Ambil ID terkecil untuk setiap group
|
'id',
|
||||||
'trans_reference',
|
'trans_reference',
|
||||||
'booking_date',
|
'booking_date',
|
||||||
'amount_lcy',
|
'amount_lcy',
|
||||||
DB::raw('MIN(date_time) as date_time') // Ambil date_time terkecil untuk konsistensi
|
'date_time'
|
||||||
])
|
])
|
||||||
->with([
|
->with([
|
||||||
'ft' => function($query) {
|
'ft' => function($query) {
|
||||||
@@ -372,44 +382,28 @@ class GenerateClosingBalanceReportJob implements ShouldQueue
|
|||||||
$query->select('id', 'date_time');
|
$query->select('id', 'date_time');
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
->where('account_number', $this->accountNumber)
|
->whereIn('id', $uniqueIds)
|
||||||
->where('booking_date', $this->period)
|
|
||||||
// KUNCI: GroupBy untuk menghilangkan duplicate berdasarkan trans_reference dan amount_lcy
|
|
||||||
->groupBy('trans_reference', 'amount_lcy', 'booking_date')
|
|
||||||
->orderBy('booking_date')
|
->orderBy('booking_date')
|
||||||
->orderBy('date_time');
|
->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,
|
'model_class' => $modelClass,
|
||||||
'table_name' => $tableName
|
'table_name' => $tableName,
|
||||||
|
'unique_transactions' => $uniqueIds->count()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare processed closing balance data dengan validasi duplicate
|
* Prepare processed closing balance data tanpa validasi duplicate (sudah dieliminasi di query)
|
||||||
* Mempersiapkan data closing balance dengan validasi untuk mencegah duplicate
|
* Mempersiapkan data closing balance tanpa perlu validasi duplicate lagi
|
||||||
*/
|
*/
|
||||||
private function prepareProcessedClosingBalanceData($transactions, &$runningBalance, &$sequenceNo): array
|
private function prepareProcessedClosingBalanceData($transactions, &$runningBalance, &$sequenceNo): array
|
||||||
{
|
{
|
||||||
$processedData = [];
|
$processedData = [];
|
||||||
$seenTransactions = []; // Track untuk mencegah duplicate di level aplikasi
|
|
||||||
|
|
||||||
foreach ($transactions as $transaction) {
|
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++;
|
$sequenceNo++;
|
||||||
|
|
||||||
// Process transaction data
|
// Process transaction data
|
||||||
@@ -458,9 +452,8 @@ class GenerateClosingBalanceReportJob implements ShouldQueue
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::info('Processed closing balance data prepared', [
|
Log::info('Processed closing balance data prepared without duplicates', [
|
||||||
'total_records' => count($processedData),
|
'total_records' => count($processedData)
|
||||||
'duplicates_skipped' => count($seenTransactions) - count($processedData)
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return $processedData;
|
return $processedData;
|
||||||
|
|||||||
Reference in New Issue
Block a user