✨ feat(slik): implementasi sistem import SLIK dengan optimasi memory & timeout handling
- Menambahkan `SlikController.php` dengan method CRUD dan import data SLIK, termasuk logging detail & error handling - Menambahkan `SlikImport.php` dengan Laravel Excel (ToCollection, WithChunkReading, WithBatchInserts, dll.) - Optimasi memory dengan chunk processing (50 baris/chunk) dan batch insert (50 record/batch) - Penanganan timeout menggunakan `set_time_limit` & memory limit configurable via config - Implementasi queue processing untuk file besar (>5MB) dengan progress tracking - Validasi file upload & data baris, skip header dari baris ke-5, serta rollback jika error - Garbage collection otomatis setiap 25 baris, unset variabel tidak terpakai, dan logging usage memory - Error handling komprehensif dengan try-catch, rollback transaksi, hapus file temp, dan logging stack trace - Semua parameter (batch size, chunk size, memory limit, timeout, GC, queue threshold) configurable via config - Diuji pada file besar (>50MB), memory stabil, timeout handling berfungsi, rollback aman, dan progress tracking valid - Catatan: pastikan queue worker berjalan, monitor log progress, sesuaikan config server, dan backup DB sebelum import
This commit is contained in:
190
app/Models/Slik.php
Normal file
190
app/Models/Slik.php
Normal file
@@ -0,0 +1,190 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Lpj\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* Model Slik untuk mengelola data SLIK (Sistem Layanan Informasi Keuangan)
|
||||
*
|
||||
* @property int $id
|
||||
* @property string|null $sandi_bank
|
||||
* @property string|null $tahun
|
||||
* @property string|null $bulan
|
||||
* @property string|null $flag_detail
|
||||
* @property string|null $kode_register_agunan
|
||||
* @property string|null $no_rekening
|
||||
* @property string|null $cif
|
||||
* @property string|null $kolektibilitas
|
||||
* @property string|null $fasilitas
|
||||
* @property string|null $jenis_segmen_fasilitas
|
||||
* @property string|null $status_agunan
|
||||
* @property string|null $jenis_agunan
|
||||
* @property string|null $peringkat_agunan
|
||||
* @property string|null $lembaga_pemeringkat
|
||||
* @property string|null $jenis_pengikatan
|
||||
* @property string|null $tanggal_pengikatan
|
||||
* @property string|null $nama_pemilik_agunan
|
||||
* @property string|null $bukti_kepemilikan
|
||||
* @property string|null $alamat_agunan
|
||||
* @property string|null $lokasi_agunan
|
||||
* @property string|null $nilai_agunan
|
||||
* @property string|null $nilai_agunan_menurut_ljk
|
||||
* @property string|null $tanggal_penilaian_ljk
|
||||
* @property string|null $nilai_agunan_penilai_independen
|
||||
* @property string|null $nama_penilai_independen
|
||||
* @property string|null $tanggal_penilaian_penilai_independen
|
||||
* @property string|null $jumlah_hari_tunggakan
|
||||
* @property string|null $status_paripasu
|
||||
* @property string|null $prosentase_paripasu
|
||||
* @property string|null $status_kredit_join
|
||||
* @property string|null $diasuransikan
|
||||
* @property string|null $keterangan
|
||||
* @property string|null $kantor_cabang
|
||||
* @property string|null $operasi_data
|
||||
* @property string|null $kode_cabang
|
||||
* @property string|null $nama_debitur
|
||||
* @property string|null $nama_cabang
|
||||
* @property string|null $flag
|
||||
*/
|
||||
class Slik extends Base
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* Nama tabel yang digunakan oleh model
|
||||
*/
|
||||
protected $table = 'sliks';
|
||||
|
||||
/**
|
||||
* Field yang dapat diisi secara mass assignment
|
||||
*/
|
||||
protected $fillable = [
|
||||
'sandi_bank',
|
||||
'tahun',
|
||||
'bulan',
|
||||
'flag_detail',
|
||||
'kode_register_agunan',
|
||||
'no_rekening',
|
||||
'cif',
|
||||
'kolektibilitas',
|
||||
'fasilitas',
|
||||
'jenis_segmen_fasilitas',
|
||||
'status_agunan',
|
||||
'jenis_agunan',
|
||||
'peringkat_agunan',
|
||||
'lembaga_pemeringkat',
|
||||
'jenis_pengikatan',
|
||||
'tanggal_pengikatan',
|
||||
'nama_pemilik_agunan',
|
||||
'bukti_kepemilikan',
|
||||
'alamat_agunan',
|
||||
'lokasi_agunan',
|
||||
'nilai_agunan',
|
||||
'nilai_agunan_menurut_ljk',
|
||||
'tanggal_penilaian_ljk',
|
||||
'nilai_agunan_penilai_independen',
|
||||
'nama_penilai_independen',
|
||||
'tanggal_penilaian_penilai_independen',
|
||||
'jumlah_hari_tunggakan',
|
||||
'status_paripasu',
|
||||
'prosentase_paripasu',
|
||||
'status_kredit_join',
|
||||
'diasuransikan',
|
||||
'keterangan',
|
||||
'kantor_cabang',
|
||||
'operasi_data',
|
||||
'kode_cabang',
|
||||
'nama_debitur',
|
||||
'nama_cabang',
|
||||
'flag',
|
||||
];
|
||||
|
||||
/**
|
||||
* Casting tipe data untuk field tertentu
|
||||
*/
|
||||
protected $casts = [
|
||||
'tanggal_pengikatan' => 'date',
|
||||
'tanggal_penilaian_ljk' => 'date',
|
||||
'tanggal_penilaian_penilai_independen' => 'date',
|
||||
'nilai_agunan' => 'decimal:2',
|
||||
'nilai_agunan_menurut_ljk' => 'decimal:2',
|
||||
'nilai_agunan_penilai_independen' => 'decimal:2',
|
||||
'prosentase_paripasu' => 'decimal:2',
|
||||
'jumlah_hari_tunggakan' => 'integer',
|
||||
];
|
||||
|
||||
/**
|
||||
* Accessor untuk format nilai agunan dengan currency Indonesia
|
||||
*/
|
||||
public function getNilaiAgunanFormattedAttribute(): string
|
||||
{
|
||||
return $this->nilai_agunan ? 'Rp ' . number_format($this->nilai_agunan, 0, ',', '.') : 'Rp 0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor untuk format nilai agunan menurut LJK dengan currency Indonesia
|
||||
*/
|
||||
public function getNilaiAgunanMenurutLjkFormattedAttribute(): string
|
||||
{
|
||||
return $this->nilai_agunan_menurut_ljk ? 'Rp ' . number_format($this->nilai_agunan_menurut_ljk, 0, ',', '.') : 'Rp 0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor untuk format nilai agunan penilai independen dengan currency Indonesia
|
||||
*/
|
||||
public function getNilaiAgunanPenilaiIndependenFormattedAttribute(): string
|
||||
{
|
||||
return $this->nilai_agunan_penilai_independen ? 'Rp ' . number_format($this->nilai_agunan_penilai_independen, 0, ',', '.') : 'Rp 0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor untuk status badge berdasarkan status agunan
|
||||
*/
|
||||
public function getStatusBadgeAttribute(): string
|
||||
{
|
||||
$statusClass = match($this->status_agunan) {
|
||||
'Aktif' => 'badge-success',
|
||||
'Tidak Aktif' => 'badge-danger',
|
||||
'Pending' => 'badge-warning',
|
||||
default => 'badge-secondary'
|
||||
};
|
||||
|
||||
return '<span class="badge ' . $statusClass . '">' . ($this->status_agunan ?? 'Unknown') . '</span>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope untuk filter berdasarkan tahun
|
||||
*/
|
||||
public function scopeByYear($query, $year)
|
||||
{
|
||||
return $query->where('tahun', $year);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope untuk filter berdasarkan bulan
|
||||
*/
|
||||
public function scopeByMonth($query, $month)
|
||||
{
|
||||
return $query->where('bulan', $month);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope untuk filter berdasarkan sandi bank
|
||||
*/
|
||||
public function scopeBySandiBank($query, $sandiBank)
|
||||
{
|
||||
return $query->where('sandi_bank', $sandiBank);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope untuk filter berdasarkan kode cabang
|
||||
*/
|
||||
public function scopeByKodeCabang($query, $kodeCabang)
|
||||
{
|
||||
return $query->where('kode_cabang', $kodeCabang);
|
||||
}
|
||||
|
||||
// Method creator() dan editor() sudah disediakan oleh trait Userstamps
|
||||
}
|
||||
Reference in New Issue
Block a user