diff --git a/app/Jobs/GenerateClosingBalanceReportJob.php b/app/Jobs/GenerateClosingBalanceReportJob.php index 700dc5d..f5d68be 100644 --- a/app/Jobs/GenerateClosingBalanceReportJob.php +++ b/app/Jobs/GenerateClosingBalanceReportJob.php @@ -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;