refactor(webstatement): improve ATM card sync logic and error handling

- Update filter untuk query dengan kondisi tambahan pada `crsts` dan pengecualian jenis kartu tertentu.
- Refactor metode `scheduleUpdateBranchCurrencyJobs`:
  - Tambahkan batch process untuk penghematan memori.
  - Log tambahan untuk melacak progres yang lebih jelas.
  - Perbaikan logika penjadwalan job dengan penundaan (delay) dinamis.
  - Penanganan error yang lebih detail dan log pendukung untuk debugging.
- Perbaikan pada controller `KartuAtmController`:
  - Amankan akses properti menggunakan null-safe operator pada data biaya kartu.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
This commit is contained in:
Daeng Deni Mardaeni
2025-05-12 18:28:34 +07:00
parent eaa847e7e7
commit 823ccf0fe7
2 changed files with 87 additions and 27 deletions

View File

@@ -86,7 +86,7 @@
$currentPage = $request->get('page') ?: 1;
$data = $data->map(function ($item) {
$item->fee = $item->biaya->biaya;
$item->fee = $item->biaya?->biaya;
return $item;
});

View File

@@ -182,7 +182,8 @@
->table(self::DB_TABLE)
->select('CRDNO', 'ACCFLAG', 'CRACC1', 'CRACC2', 'CRACC3', 'CRACC4', 'CRACC5', 'CRACCNAM1', 'CRACCNAM2', 'CRACCNAM3', 'CRACCNAM4', 'CRACCNAM5', 'CRSTS', 'CTTYPE', 'CTDESC', 'CRDATE', 'LASTUPDATE')
->join('IST77.CMS_VCARDTYP', 'IST77.CMS_VCARD.CRTYPE', '=', 'IST77.CMS_VCARDTYP.CTTYPE')
->where('crsts', 1)
->where('crsts', '!=',2)
->whereNotIn('cttype',['2','3','6'])
->whereNotNull('ACCFLAG')
->where('ACCFLAG', '>', 0)
->skip($offset)
@@ -252,11 +253,41 @@
*
* @return void
*/
private function scheduleUpdateBranchCurrencyJobs()
: void
/**
* Schedule update branch and currency jobs for cards that need update
*
* @return void
*/
private function scheduleUpdateBranchCurrencyJobs(): void
{
try {
// Ambil semua kartu yang perlu diperbarui branch dan currency
// Process cards in chunks to avoid memory issues
$batchSize = 1000; // Process 1000 cards at a time
$totalProcessed = 0;
$batchNumber = 0;
// Get total count first (without loading all records)
$totalCards = Atmcard::where('crsts', 1)
->whereNotNull('accflag')
->where('accflag', '!=', '')
->where(function ($query) {
$query->whereNull('branch')
->orWhere('branch', '')
->orWhereNull('currency')
->orWhere('currency', '');
})
->count();
Log::info("Total {$totalCards} cards need branch and currency update");
// Update log
$this->syncLog->update([
'sync_notes' => $this->syncLog->sync_notes . "\nTotal {$totalCards} cards need branch and currency update"
]);
// Process in batches
do {
// Get a batch of cards
$cards = Atmcard::where('crsts', 1)
->whereNotNull('accflag')
->where('accflag', '!=', '')
@@ -266,32 +297,61 @@
->orWhereNull('currency')
->orWhere('currency', '');
})
->skip($batchNumber * $batchSize)
->take($batchSize)
->get();
$totalCards = $cards->count();
Log::info("Menjadwalkan {$totalCards} job pembaruan branch dan currency");
$currentBatchCount = $cards->count();
$totalProcessed += $currentBatchCount;
// Update log
if ($currentBatchCount > 0) {
Log::info("Processing batch #{$batchNumber}: {$currentBatchCount} cards (Total processed: {$totalProcessed}/{$totalCards})");
// Schedule jobs for this batch with increasing delay
foreach ($cards as $index => $card) {
// Calculate delay based on batch number and index to spread out job execution
$delay = ($batchNumber * $batchSize + $index) % 300; // Spread over 5 minutes (300 seconds)
// Dispatch job with the card ID instead of the full object to save memory
UpdateAtmCardBranchCurrencyJob::dispatch($card, $this->syncLog->id)
->delay(now()->addSeconds($delay));
}
// Update progress in log every 10 batches
if ($batchNumber % 10 === 0) {
$this->syncLog->update([
'sync_notes' => $this->syncLog->sync_notes . "\nMenjadwalkan {$totalCards} job pembaruan branch dan currency"
'sync_notes' => $this->syncLog->sync_notes . "\nProcessed {$totalProcessed} of {$totalCards} cards for branch and currency update"
]);
}
}
$batchNumber++;
// Free up memory
unset($cards);
// Force garbage collection if PHP version supports it
if (function_exists('gc_collect_cycles')) {
gc_collect_cycles();
}
} while ($currentBatchCount > 0);
Log::info("All {$totalProcessed} branch and currency update jobs have been scheduled");
// Final update to log
$this->syncLog->update([
'sync_notes' => $this->syncLog->sync_notes . "\nAll {$totalProcessed} branch and currency update jobs have been scheduled"
]);
foreach ($cards as $card) {
foreach ($cards as $index => $card) {
UpdateAtmCardBranchCurrencyJob::dispatch($card, $this->syncLog->id)
->delay(now()->addSeconds(1 * ($index + 1)));
}
}
Log::info('Semua job pembaruan branch dan currency telah dijadwalkan');
} catch (Exception $e) {
Log::error('Gagal menjadwalkan job pembaruan branch dan currency: ' . $e->getMessage(), [
Log::error('Failed to schedule branch and currency update jobs: ' . $e->getMessage(), [
'file' => $e->getFile(),
'line' => $e->getLine()
]);
$this->syncLog->update([
'sync_notes' => $this->syncLog->sync_notes . "\nError: Gagal menjadwalkan job pembaruan branch dan currency: " . $e->getMessage()
'sync_notes' => $this->syncLog->sync_notes . "\nError: Failed to schedule branch and currency update jobs: " . $e->getMessage()
]);
}
}