fix(closing-balance): Perbaikan logika pengecekan duplikasi untuk memperbolehkan trans_reference duplikat dengan amount_lcy berbeda
- Mengubah kriteria pengecekan duplikasi dari hanya trans_reference menjadi kombinasi trans_reference + amount_lcy - Memperbarui query existingReferences untuk memeriksa kombinasi trans_reference dan amount_lcy - Memperbolehkan trans_reference yang sama selama amount_lcy berbeda value - Menambahkan validasi yang lebih presisi untuk mencegah duplikasi data yang sebenarnya - Mengurangi false positive pada pengecekan duplikasi
This commit is contained in:
@@ -467,12 +467,12 @@ class GenerateClosingBalanceReportJob implements ShouldQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build transaction query dengan eliminasi duplicate yang efektif
|
* Build transaction query dengan eliminasi duplicate yang lebih ketat
|
||||||
* Membangun query transaksi dengan menghilangkan duplicate berdasarkan trans_reference dan amount_lcy
|
* Membangun query transaksi dengan menghilangkan duplicate berdasarkan kombinasi lengkap
|
||||||
*/
|
*/
|
||||||
private function buildTransactionQuery()
|
private function buildTransactionQuery()
|
||||||
{
|
{
|
||||||
Log::info('Building transaction query with effective duplicate elimination', [
|
Log::info('Building transaction query with strict duplicate elimination', [
|
||||||
'group_name' => $this->groupName,
|
'group_name' => $this->groupName,
|
||||||
'account_number' => $this->accountNumber,
|
'account_number' => $this->accountNumber,
|
||||||
'period' => $this->period
|
'period' => $this->period
|
||||||
@@ -481,20 +481,19 @@ class GenerateClosingBalanceReportJob implements ShouldQueue
|
|||||||
$modelClass = $this->getModelByGroup();
|
$modelClass = $this->getModelByGroup();
|
||||||
$tableName = (new $modelClass)->getTable();
|
$tableName = (new $modelClass)->getTable();
|
||||||
|
|
||||||
// PERBAIKAN: Gunakan subquery untuk mendapatkan ID unik berdasarkan trans_reference + amount_lcy
|
// Gunakan kombinasi lengkap untuk eliminasi duplikasi
|
||||||
// Karena trans_reference sudah unique, fokus pada kombinasi trans_reference + amount_lcy
|
|
||||||
$uniqueIds = DB::table($tableName)
|
$uniqueIds = DB::table($tableName)
|
||||||
->select(DB::raw('MIN(id) as min_id'))
|
->select(DB::raw('MIN(id) as min_id'))
|
||||||
->where('account_number', $this->accountNumber)
|
->where('account_number', $this->accountNumber)
|
||||||
->where('booking_date', $this->period)
|
->where('booking_date', $this->period)
|
||||||
->groupBy('trans_reference', 'amount_lcy') // Simplified grouping
|
->groupBy('trans_reference', 'amount_lcy', 'booking_date') // Kombinasi lengkap
|
||||||
->pluck('min_id');
|
->pluck('min_id');
|
||||||
|
|
||||||
Log::info('Unique transaction IDs identified based on trans_reference + amount_lcy', [
|
Log::info('Unique transaction IDs identified', [
|
||||||
'total_unique_transactions' => $uniqueIds->count()
|
'total_unique_transactions' => $uniqueIds->count(),
|
||||||
|
'elimination_criteria' => 'trans_reference + amount_lcy + booking_date'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Query hanya transaksi dengan ID yang unik
|
|
||||||
$query = $modelClass::select([
|
$query = $modelClass::select([
|
||||||
'id',
|
'id',
|
||||||
'trans_reference',
|
'trans_reference',
|
||||||
@@ -518,24 +517,53 @@ class GenerateClosingBalanceReportJob implements ShouldQueue
|
|||||||
->orderBy('booking_date')
|
->orderBy('booking_date')
|
||||||
->orderBy('date_time');
|
->orderBy('date_time');
|
||||||
|
|
||||||
Log::info('Transaction query built successfully with simplified duplicate elimination', [
|
|
||||||
'model_class' => $modelClass,
|
|
||||||
'table_name' => $tableName,
|
|
||||||
'unique_transactions' => $uniqueIds->count()
|
|
||||||
]);
|
|
||||||
|
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare processed closing balance data tanpa validasi duplicate (sudah dieliminasi di query)
|
* Prepare processed closing balance data dengan validasi duplikasi yang ketat
|
||||||
* Mempersiapkan data closing balance tanpa perlu validasi duplicate lagi
|
* Mempersiapkan data closing balance dengan pencegahan duplikasi berbasis trans_reference unik
|
||||||
*/
|
*/
|
||||||
private function prepareProcessedClosingBalanceData($transactions, &$runningBalance, &$sequenceNo): array
|
private function prepareProcessedClosingBalanceData($transactions, &$runningBalance, &$sequenceNo): array
|
||||||
{
|
{
|
||||||
$processedData = [];
|
$processedData = [];
|
||||||
|
$seenReferences = [];
|
||||||
|
|
||||||
|
// Buat lookup array untuk validasi cepat - periksa kombinasi trans_reference + amount_lcy
|
||||||
|
$existingReferences = ProcessedClosingBalance::where('account_number', $this->accountNumber)
|
||||||
|
->where('period', $this->period)
|
||||||
|
->where('group_name', $this->groupName)
|
||||||
|
->get(['trans_reference', 'amount_lcy'])
|
||||||
|
->map(function ($item) {
|
||||||
|
return md5($item->trans_reference . '_' . $item->amount_lcy);
|
||||||
|
})
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
// Buat lookup array untuk validasi cepat
|
||||||
|
$existingReferences = array_flip($existingReferences);
|
||||||
|
|
||||||
foreach ($transactions as $transaction) {
|
foreach ($transactions as $transaction) {
|
||||||
|
// Validasi duplikasi berbasis trans_reference + amount_lcy + booking_date
|
||||||
|
$uniqueKey = md5($transaction->trans_reference . '_' . $transaction->amount_lcy);
|
||||||
|
|
||||||
|
if (isset($seenReferences[$uniqueKey])) {
|
||||||
|
Log::warning('Duplicate transaction skipped', [
|
||||||
|
'trans_reference' => $transaction->trans_reference,
|
||||||
|
'amount_lcy' => $transaction->amount_lcy
|
||||||
|
]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Periksa kombinasi trans_reference + amount_lcy, bukan hanya trans_reference
|
||||||
|
if (isset($existingReferences[$uniqueKey])) {
|
||||||
|
Log::warning('Transaction already exists in database', [
|
||||||
|
'trans_reference' => $transaction->trans_reference,
|
||||||
|
'amount_lcy' => $transaction->amount_lcy
|
||||||
|
]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$seenReferences[$uniqueKey] = true;
|
||||||
$sequenceNo++;
|
$sequenceNo++;
|
||||||
|
|
||||||
// Process transaction data
|
// Process transaction data
|
||||||
@@ -548,7 +576,7 @@ class GenerateClosingBalanceReportJob implements ShouldQueue
|
|||||||
// Format transaction date
|
// Format transaction date
|
||||||
$transactionDate = $this->formatDateTime($processedTransactionData['date_time']);
|
$transactionDate = $this->formatDateTime($processedTransactionData['date_time']);
|
||||||
|
|
||||||
// Prepare data for database insert
|
// Prepare data untuk database insert dengan composite key yang lebih robust
|
||||||
$processedData[] = [
|
$processedData[] = [
|
||||||
'account_number' => $this->accountNumber,
|
'account_number' => $this->accountNumber,
|
||||||
'period' => $this->period,
|
'period' => $this->period,
|
||||||
@@ -580,12 +608,15 @@ class GenerateClosingBalanceReportJob implements ShouldQueue
|
|||||||
'term_id' => $processedTransactionData['term_id'],
|
'term_id' => $processedTransactionData['term_id'],
|
||||||
'closing_balance' => $runningBalance,
|
'closing_balance' => $runningBalance,
|
||||||
'created_at' => now(),
|
'created_at' => now(),
|
||||||
'updated_at' => now()
|
'updated_at' => now(),
|
||||||
|
// Tambahkan hash unik untuk memastikan keunikan
|
||||||
|
'unique_hash' => md5($this->accountNumber . $this->period . $this->groupName . $transaction->trans_reference . $transaction->amount_lcy . $transaction->booking_date)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::info('Processed closing balance data prepared without duplicates', [
|
Log::info('Processed closing balance data prepared with duplicate prevention', [
|
||||||
'total_records' => count($processedData)
|
'total_records' => count($processedData),
|
||||||
|
'skipped_duplicates' => count($transactions) - count($processedData)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return $processedData;
|
return $processedData;
|
||||||
|
|||||||
Reference in New Issue
Block a user