Compare commits

...

51 Commits

Author SHA1 Message Date
Daeng Deni Mardaeni
45cebcf325 🔧(services): Selaraskan fallback path foto pada PreviewLaporanService dan tambah logging
- Menyelaraskan resolusi path file foto di PreviewLaporanService dengan logika fallback seperti pada komponen foto:
  - Menggunakan `originalPath = $path['path']` sebagai path utama
  - Jika `statusLpj == 1` dan file asli tidak ditemukan, maka:
    - Ekstrak dua bagian terakhir dari path (contoh: `251051/251051_2_2.png`)
    - Bangun `fallbackPath` dengan pola `surveyor/001/{lastTwoParts}`
  - Tentukan `pathToUse`:
    - Apabila `fallbackPath` ada dan file fallback ditemukan, gunakan `fallbackPath`
    - Jika tidak, tetap gunakan `originalPath`
  - Resolusi final: `storage_path('app/public/' . $pathToUse)`

- Menambahkan logging untuk setiap operasi penting dan setiap titik pengembalian:
  - `Log::warning` saat path kosong terdeteksi dalam daftar paths
  - `Log::info` saat fallback kandidat dibangun dari `originalPath`
  - `Log::warning` saat file tidak ditemukan pada original maupun fallback (dengan menyertakan ketiganya: original, fallback, resolved)
  - `Log::info` saat file berhasil ditambahkan ke daftar unduhan
  - `Log::warning` saat tidak ada file valid setelah resolusi path
  - `Log::info` saat mengunduh single file
  - `Log::info` saat zip file berhasil dibuat (dengan jumlah file)
  - `Log::error` saat zip file gagal dibuat

- Memindahkan logika resolusi path di dalam loop pengolahan `$paths` untuk setiap item:
  - Mengganti setting langsung `storage_path('app/public/' . $path['path'])` dengan resolusi path yang bisa fallback
  - Menjaga struktur kontrol dengan `continue` jika file final tetap tidak ditemukan

- Menambahkan komentar level-fungsi (docblock) pada `previewLaporan`:
  - Menjelaskan tanggung jawab fungsi dalam menghasilkan PDF atau unduhan foto
  - Menjelaskan skenario fallback path dan tujuan mengurangi gambar hilang
  - Mendokumentasikan parameter dan bentuk nilai kembali respons
2025-11-07 10:57:46 +07:00
Daeng Deni Mardaeni
a442f879b7 🔧(services): Perbaikan logika preview laporan dan format saran pada print-out
- **PreviewLaporanService.php**:
  - Menambahkan parsing JSON untuk mig_permohonan sebelum digunakan
  - Memperbaiki kondisi untuk menentukan statusLpj dengan menambahkan validasi nilai pasar < 1
  - Meningkatkan logika penentuan path foto berdasarkan status memo dan nilai total pasar wajar

- **print-out-standar.blade.php**:
  - Memindahkan header tabel 'SARAN' keluar dari loop foreach untuk mencegah duplikasi header
  - Menambahkan format list (ul/li) pada tampilan saran untuk meningkatkan readability
  - Menambahkan margin-top 20px pada section penutup laporan untuk spacing yang lebih baik
  - Memperbaiki struktur HTML dengan wrapping konten saran dalam list item
2025-10-31 10:07:02 +07:00
Daeng Deni Mardaeni
796cb89d21 🔧(penilai): Perbaikan layout dan validasi data pada komponen laporan
- **foto-jaminan.blade.php**: Memindahkan page-break ke awal chunk (kecuali chunk pertama) untuk mencegah page break yang tidak perlu di akhir
- **print-out-sederhana.blade.php**:
  - Menambahkan validasi isset() untuk mencegah error undefined index pada hub_cadeb
  - Menambahkan prefix 'Lain-lain, ' untuk hubungan debitur yang tidak sesuai
  - Menambahkan guard clause untuk mencegah error saat SARANA PELENGKAP DAN LINGKUNGAN tidak ada
  - Menambahkan guard clause untuk ANALISA TANAH DAN BANGUNAN
- **print-out-standar.blade.php**:
  - Menambahkan validasi null check untuk mig_detail_legalitas_jaminan
  - Memperbaiki indentasi dan struktur kode untuk konsistensi

Perubahan ini meningkatkan stabilitas aplikasi dengan mencegah error undefined index dan memperbaiki layout PDF yang dihasilkan dengan penempatan page break yang lebih tepat.
2025-10-30 14:00:49 +07:00
Daeng Deni Mardaeni
fb22d370b5 🔧(penilai): Perbaikan tampilan dan logika fallback foto jaminan
Implementasi berbagai perbaikan pada komponen penilai dan foto jaminan:

**Detail Lokasi (detail-lokasi.blade.php):**
- Menambahkan logika untuk menghindari duplikasi label yang sama
- Implementasi tracking currentKey untuk mencegah label berulang
- Perbaikan tampilan tabel dengan label yang lebih bersih

**Footer (footer.blade.php):**
- Perbaikan indentasi dan formatting kode
- Reorganisasi array customLabels untuk konsistensi
- Perbaikan struktur conditional untuk upload_gs

**Foto Jaminan (foto-jaminan.blade.php):**
- Implementasi sistem fallback path untuk file foto yang tidak ditemukan
- Logika fallback: surveyor/2025/APRIL/26042025/251051/251051_2_2.png → surveyor/001/251051/251051_2_2.png
- Penambahan urutan kategori foto yang diinginkan (BLAD TATA KOTA sebelum FOTO JAMINAN)
- Skip kategori DOKUMEN PENDUKUNG dari tampilan utama
- Perbaikan class ordering (border photo-item)
- Update alt attribute untuk menggunakan pathToUse
- Penambahan debug @dd untuk otherPhotos (sementara)

**Print Out Sederhana (print-out-sederhana.blade.php):**
- Perbaikan tampilan Total Nilai Pasar Wajar dengan colspan yang benar
- Restructuring tabel NPW tambahan dengan width yang tepat
- Perbaikan alignment dan formatting nilai
- Update parameter signature-approval dengan npw
- Perbaikan tampilan Total Nilai Likuidasi
- Penambahan tanda '--' pada SARANA PELENGKAP DAN LINGKUNGAN

**Print Out Standar (print-out-standar.blade.php):**
- Implementasi logika untuk menghindari duplikasi label
- Perbaikan struktur tabel dengan width 100%
- Update tracking currentLabel untuk konsistensi tampilan
2025-10-29 10:50:13 +07:00
Daeng Deni Mardaeni
478c0c8079 🔧(helpers): Tambah fungsi parseTimestamp & perbaiki parsing tanggal
- Tambah fungsi parseTimestamp di app/Helpers/Lpj.php untuk parsing timestamp yang robust
- Gunakan native PHP DateTime & fallback ke Carbon untuk multiple format
- Validasi lengkap day, month, year, hour, minute, second dengan range aman
- Support format: Y-m-d H:i:s, Y-m-d, d/m/Y H:i:s, d/m/Y, d-m-Y, j-n-Y, dll
- Tambah logging detail & trim whitespace untuk reliability tinggi
- Return selalu format Y-m-d H:i:s agar konsisten di seluruh sistem
- signature-approval.blade.php gunakan parseTimestamp() untuk mig_mst_jaminan_tgl_laporan
- Tanggal migrasi kini diparsing & diformat dengan lebih akurat
- Hasil: parsing timestamp konsisten, error handling lebih kuat, dan log lebih informatif
2025-10-28 14:02:50 +07:00
Daeng Deni Mardaeni
73d0d238c0 🔧(penilai): Perbaiki total nilai & signature approval
- Gabungkan header 'Total Nilai Pasar Wajar' dengan colspan=2
- Gunakan nilai likuidasi default 70% & data migrasi mig_mst_lpj_tot_nilai_likuidasi
- Tambah parameter laporan='sederhana' pada include signature-approval
- Perbaiki layout tabel di print-out-sederhana & print-out-standar
- Tambah parsing mig_permohonan dengan json_decode untuk data migrasi
- Sesuaikan width kolom agar tampilan lebih proporsional
- Hilangkan Carbon::createFromFormat & tambah kondisi laporan di signature-approval
- Tampilkan SENIOR OFFICER untuk laporan sederhana, EO untuk standar
2025-10-28 13:40:11 +07:00
Daeng Deni Mardaeni
d6d0ed28b9 🔧(penilai): Perbaiki logika approval & tanggal laporan
- Nonaktifkan filter dokument_id di PreviewLaporanService untuk fleksibilitas
- Tambah kondisi tampilkan DD hanya jika berbeda dengan EO
- Gunakan tanggal mig_mst_jaminan_tgl_laporan sebagai sumber utama
- Perbaiki logika nama & tanggal approval SO
- Gunakan Carbon::createFromFormat untuk parsing tanggal migrasi
- Tambah validasi kondisional agar tidak duplikasi approval
- Rapikan struktur HTML & indentasi signature-approval.blade.php
- Pastikan konsistensi data antara preview service & signature view
- Hasil: tampilan signature lebih akurat & sesuai data migrasi
2025-10-28 12:33:25 +07:00
Daeng Deni Mardaeni
ee828455a9 🗑️(penilai): Menghapus section perhitungan nilai pasar wajar otomatis
Menghapus loop perhitungan nilai pasar wajar otomatis dari labelNilai pada komponen print-out laporan untuk memberikan kontrol manual yang lebih baik.

Perubahan yang dilakukan:

1. Print-out Sederhana (print-out-sederhana.blade.php)
- Menghapus foreach loop untuk labelNilai yang menampilkan perhitungan otomatis
- Menghapus 18 baris kode yang menghandle luas dan nilai per kategori
- Mempertahankan section npw_tambahan dengan perbaikan styling width
- Memperbaiki alignment dan width konsistensi pada tabel

2. Print-out Standar (print-out-standar.blade.php)
- Menghapus foreach loop untuk labelNilai yang sama
- Menghapus 18 baris kode perhitungan otomatis nilai pasar wajar
- Mempertahankan section npw_tambahan dengan styling yang diperbaiki
- Memperbaiki width property pada td element (menambahkan spasi)
2025-10-27 18:18:51 +07:00
Daeng Deni Mardaeni
a6481dd482 🔧(penilai): Perbaiki tampilan laporan & tambah fitur saran
- PreviewLaporanService.php:
  - Aktifkan kembali filter dokument_id untuk query Penilai
  - Tambahkan validasi dokumen ID agar data yang diambil tepat
  - Perbaiki logika pengambilan status LPJ untuk akurasi laporan

- informasi.blade.php:
  - Tambahkan section baru untuk menampilkan data saran dari form inspeksi
  - Implementasi loop untuk menampilkan banyak saran (array/string)
  - Styling tabel saran dengan border & alignment konsisten

- print-out-sederhana.blade.php:
  - Hilangkan koma awal di nilai dengan ltrim() untuk tampilan bersih
  - Konsistensi format antar section laporan

- print-out-standar.blade.php:
  - Tambah field 'Fasilitas Kredit' dan 'Alamat & Telepon Debitur'
  - Perbaiki logika total nilai pasar wajar dengan conditional formatting
  - Tambah section saran yang konsisten dengan komponen lain
  - Hapus semicolon berlebih (syntax fix)

- signature-approval.blade.php:
  - Ubah sumber tanggal dari updated_at ke tanggal_kunjungan untuk akurasi
2025-10-27 15:13:35 +07:00
Daeng Deni Mardaeni
cbf54353f4 (slik): Tambahkan halaman index SLIK untuk admin kredit
- Tambah halaman index SLIK di modul admin kredit untuk manajemen data Sistem Layanan Informasi Keuangan
- Buat tabel data dengan kolom: Sandi Bank, Tahun, No Rekening, CIF, Nama Debitur, Kolektibilitas, Fasilitas, Nilai Agunan, dan Status
- Implementasi pencarian keyword serta filter tahun, bulan, dan status agunan
- Tambahkan tombol aksi 'Detail' untuk melihat data lengkap
- Tambahkan fitur import dari Excel (.xlsx/.xls/.csv) dengan validasi format & file size ≤ 10MB
- Tambahkan fitur export Excel berdasarkan filter aktif
- Tambahkan tombol download template Excel untuk panduan format import
- Implementasi fungsi truncate/hapus semua data SLIK dengan modal konfirmasi
- Tambahkan validasi kombinasi unik (sandi bank, tahun, bulan, no rekening) untuk update data otomatis
- Gunakan KTDataTable dengan server-side processing, layout responsif, dan scroll horizontal
- Tambahkan modal import & modal konfirmasi hapus
- Tambahkan breadcrumbs, event listener untuk pencarian/filter, dan CSRF protection
- Implementasi validasi keamanan file upload dan pesan error/success
2025-10-23 16:59:47 +07:00
Daeng Deni Mardaeni
a701e78982 🔧 fix(LPJ): Perbaikan logika preview laporan dan optimasi import service
Perubahan utama pada PreviewLaporanService.php:
- Mengoptimalkan urutan import dengan mengelompokkan berdasarkan namespace
- Memperbaiki logika tanggal laporan untuk data migrasi dengan fallback ke tgl_create
- Menghapus filter dokument_id pada query LPJ untuk fleksibilitas
- Menambahkan penanganan khusus untuk tipe laporan 'memo' pada data migrasi
- Menambahkan validasi file path untuk download dokumen memo
- Memperbaiki kondisi pengecekan memo untuk non-migrasi data

Perubahan pada print-out-standar.blade.php:
- Menyembunyikan baris header dokumen yang menyebabkan duplikasi tampilan
- Menambahkan fungsi ltrim untuk membersihkan koma di awal nilai data

Perubahan ini meningkatkan stabilitas dan akurasi tampilan preview laporan,\nserta memperbaiki penanganan data migrasi dan memo khusus.
2025-10-23 14:35:12 +07:00
Daeng Deni Mardaeni
6305f93f0f fix(LPJ): Perbaikan label luas unit untuk jenis aset Apartemen
Mengubah label dari 'Luas Tanah' menjadi 'Luas Unit' untuk jenis aset Apartemen:
- Menambahkan kondisi baru untuk mengecek jika jenis aset adalah "Apartemen"
- Mengubah label `$labelNilai['tanah']` menjadi 'Luas Unit' untuk apartemen
- Menambahkan 'apartemen' ke dalam array mapping label dengan nilai 'Luas Unit'
- Memperbaiki indentasi kode untuk konsistensi format
2025-10-22 11:54:28 +07:00
Daeng Deni Mardaeni
6ed4e8ba41 🐛 fix(print): Perbaiki tampilan laporan standar & pembanding migrasi" -m "
- print-out-standar.blade.php: koreksi relasi cabang ke \$permohonan->branch->name
- print-out-standar.blade.php: koreksi tujuan penilaian ke \$permohonan->tujuanPenilaian->name
- print-out-standar.blade.php: perbaiki guard dokumen dengan @if(isset(\$dokumen))
- print-out-standar.blade.php: tambah baris 'Jenis Jaminan' khusus data migrasi (is_mig)
- print-out-standar.blade.php: sembunyikan section tertentu saat is_mig untuk konsistensi
- print-out-standar.blade.php: tampilkan Faktor Positif/Negatif/Lain-lain dari forminspeksi (dukungan array/string) dengan tabel ber-border & nl2br(e())
- print-pembanding.blade.php: render keterangan pembanding pakai {!! nl2br(e(parsePembandingMigration(...))) !!} agar line break tampil
- app/Helpers/Lpj.php: update parsePembandingMigration → pecah konten dengan tanda '#' jadi baris baru, trim, hapus baris kosong
- Konsolidasi formatting (spacing, border tabel) agar output rapi untuk kasus migrasi/non-migrasi
2025-10-21 17:24:20 +07:00
Daeng Deni Mardaeni
6b0022deed 🐛 fix(print): Hapus suffix angka dari key informasi dokumen" -m "
- print-out-sederhana.blade.php: gunakan preg_replace('/_([2-5])$/', '', $key) untuk hapus suffix angka di akhir key
- Pastikan key seperti 'nomor_2', 'tanggal_3', dst. tampil tanpa angka (jadi 'nomor', 'tanggal')
- Penyesuaian dilakukan hanya pada tampilan, tidak mempengaruhi nilai data
- Menangani data migrasi dengan struktur key numerik agar tampil lebih rapi
- Tampilan informasi dokumen jadi lebih bersih, konsisten, dan mudah dibaca
2025-10-20 15:47:10 +07:00
Daeng Deni Mardaeni
ae5a9ce5b7 🐛 fix(signature): Tangani SO/EO sama & perbaiki fallback tanggal migrasi" -m "
- signature-approval.blade.php: tambahkan kondisi SO==EO → render 1 kolom 'Diperiksa dan Menyetujui' (pakai jabatan EO)
- signature-approval.blade.php: bila SO≠EO → render kolom terpisah 'Diperiksa' (SO) & 'Menyetujui' (EO) seperti sebelumnya
- signature-approval.blade.php: jaga konsistensi label/jabatan & area tanda tangan agar tidak redundan
- PreviewLaporanService: ubah urutan fallback tanggal migrasi → tgl_laporan → tgl_oto → null
- PreviewLaporanService: parsing tanggal migrasi via Carbon::createFromFormat('d/m/Y H:i:s') → 'Y-m-d H:i:s'
- Akurasi tanggal laporan meningkat karena tgl_oto merefleksikan tanggal otorisasi/approval
- Tampilan blok signature lebih rapi pada kasus SO/EO sama; hilangkan duplikasi informasi
- Backward-compatible: perilaku SO≠EO & data non-migrasi tidak berubah
2025-10-20 10:47:49 +07:00
Daeng Deni Mardaeni
c8b5fcc9d1 🐛 fix(ui-print): Format nilai pasar wajar & tampilkan fakta migrasi
- Terapkan number_format(ID) (0 desimal, ',' desimal, '.' ribuan) untuk nilai pasar wajar Bagian 1
- print-out-sederhana: format nilai per kategori & nilai perbandingan (Bagian 1)
- print-out-standar: format nilai per kategori, nilai perbandingan (Bagian 1), dan nilai likuidasi
- Tambah section fakta khusus permohonan migrasi (is_mig) dengan tabel 'judul' per kategori
- Support konten fakta sebagai array/string; render dinamis & rapi
- Perbaiki logika tanggal laporan migrasi: fallback tgl_laporan → tgl_create → null
- Parsing tanggal migrasi via Carbon::createFromFormat('d/m/Y H:i:s') → 'Y-m-d H:i:s'
- Jaga konsistensi & keterbacaan angka besar (ribuan–miliaran) di semua laporan
2025-10-20 08:30:31 +07:00
Daeng Deni Mardaeni
2937add646 🐛 fix(ui-print): Format nilai pasar wajar & perbaiki hitung hari kerja migrasi
- Terapkan number_format(ID) untuk nilai pasar wajar (0 desimal, ',' desimal, '.' ribuan)
- print-out-sederhana: format nilai per kategori & nilai perbandingan agar konsisten
- print-out-standar: format nilai per kategori, nilai perbandingan, dan total nilai pasar wajar
- Ganti perhitungan manual floor/diffInDays menjadi fungsi hitungHariKerja() yang akurat
- Parsing tanggal migrasi pakai Carbon::createFromFormat('d/m/Y H:i:s', ...) sebelum dihitung
- Tata ulang tampilan informasi Dinas Tata Ruang: wrapper tabel 'judul', struktur tabel rapi, <br> untuk array
- Inisialisasi $totalNilaiPasarWajar = 0 dan akumulasi nilai kategori + perbandingan dengan fallback kalkulasi
- Pastikan konsistensi format angka di seluruh laporan & fallback bila data backend tidak tersedia
- Uji: verifikasi format ribuan/jutaan, akurasi hari kerja (migrasi/non-migrasi), dan total nilai terhitung benar
2025-10-16 10:04:40 +07:00
Daeng Deni Mardaeni
b83920d8aa 🐛(ui-print): Perbaiki struktur kondisional & penempatan elemen tabel
- Memperbaiki urutan kondisi @if/@else untuk penanganan data alamat pada print-out-sederhana.blade.php
- Memindahkan blok kode ke posisi tabel yang lebih logis dan konsisten
- Menghapus kode komentar dan duplikasi yang tidak digunakan
- Menyesuaikan penempatan baris 'Atas Nama' ke dalam kondisi yang sesuai
- Menata ulang elemen NIB agar berada dalam struktur tabel yang benar
- Memperbaiki indentasi dan format HTML untuk keterbacaan yang lebih baik
- Menjamin konsistensi tampilan print-out untuk berbagai kondisi data
- Mengurangi potensi error dari struktur kondisi yang tidak sinkron
- File diubah: resources/views/penilai/components/print-out-sederhana.blade.php
2025-10-15 08:31:08 +07:00
Daeng Deni Mardaeni
c6596cdea0 feat(ui-penilai): Tambah tampilan legalitas jaminan untuk data migrasi
Perubahan ini menambahkan fitur tampilan legalitas jaminan khusus untuk permohonan migrasi dan memperbaiki penanganan data informasi dinas tata ruang.

## Perubahan Utama:

### 1. Tampilan Legalitas Jaminan Migrasi (print-out-standar.blade.php)
- Menambahkan section khusus untuk menampilkan data legalitas jaminan dari migrasi
- Menggunakan data `mig_detail_legalitas_jaminan` yang di-decode dari JSON
- Menampilkan data dalam format tabel dengan label dan value yang terstruktur
- Menambahkan kondisi `@if ($permohonan->is_mig)` untuk hanya menampilkan pada permohonan migrasi

### 2. Penanganan Data Informasi Dinas Tata Ruang (informasi.blade.php)
- Memperbaiki penanganan data yang bisa berupa array atau string tunggal
- Menambahkan pengecekan `is_array($item)` sebelum melakukan loop
- Menambahkan fallback untuk menampilkan data langsung jika bukan array
- Memastikan tampilan tetap konsisten baik untuk data array maupun string

### 3. Kondisi Tampilan Form Kategori
- Menambahkan kondisi `@if(!$permohonan->is_mig)` untuk menyembunyikan form kategori tertentu pada permohonan migrasi
- Memastikan tampilan yang sesuai untuk jenis permohonan yang berbeda
2025-10-14 14:49:06 +07:00
Daeng Deni Mardaeni
c981237663 (ui-penilai): Konsolidasi tampilan migrasi, fallback user, dan label tanggal penilaian
- Menyesuaikan tampilan & logika untuk data permohonan hasil migrasi (is_mig)
- Tambahkan fallback user untuk SO, EO, dan DD agar nama tetap muncul meski data tidak lengkap
- Ubah label 'Tanggal Survei' menjadi 'Tanggal Penilaian' untuk konsistensi di seluruh halaman
- Perbaiki struktur & border tabel tanda tangan approval, tambahkan bold pada jabatan
- Sesuaikan kondisi tombol laporan agar hanya bergantung pada status_bayar
- Tambahkan logika decode mig_permohonan di print-out-sederhana untuk data migrasi
- Tambahkan fallback AO name dari data migrasi dan perhitungan hari kerja khusus is_mig
- Perbaiki struktur HTML, indentasi, dan formatting di semua view terkait
- File diubah: laporan/index, analisa/informasi, signature-approval, show, print-out-sederhana
2025-10-13 16:46:43 +07:00
Daeng Deni Mardaeni
291811b74a (service): Tambah migrasi tgl_laporan untuk permohonan is_mig & fallback dataPembanding
- Menambahkan logika penyesuaian tanggal laporan untuk permohonan hasil migrasi (is_mig)
- Gunakan mig_mst_jaminan_tgl_laporan jika is_mig = true, fallback ke lpj->created_at jika false
- Tambahkan inisialisasi dataPembanding = '' sebagai default untuk mencegah undefined variable
- Tambahkan variabel mig_permohonan untuk mempermudah akses data hasil migrasi
- Menambahkan logging decode mig_permohonan dan fallback tgl_laporan untuk debugging
- Menjaga konsistensi tanggal laporan antara data migrasi dan data baru
- Meningkatkan stabilitas render preview laporan untuk permohonan tanpa inspeksi
- File yang diubah: app/Services/PreviewLaporanService.php
- Kompatibel dengan Laravel 12, PHP 8.3, PostgreSQL
2025-10-13 16:43:30 +07:00
Daeng Deni Mardaeni
2d8bddff42 ♻️(refactor): Penamaan label, logging komprehensif, transaksi DB, komentar fungsi, dan idempotensi seeder
- Mengubah label 'Tanggal Survei' menjadi 'Tanggal Penilaian' di seluruh view Penilai & komponen cetak
- Menambahkan logging detail di setiap tahap proses (awal, validasi, eksekusi, return) pada controller, service, dan request
- Menerapkan transaksi database (begin, commit, rollback) di operasi tulis untuk konsistensi data (PostgreSQL)
- Menambahkan komentar fungsi (PHPDoc) di semua controller, service, dan model utama
- Menyederhanakan query dan filter laporan pada LaporanController dengan logging tambahan
- Menambahkan idempotensi pada semua seeder dengan updateOrCreate dan normalisasi delimiter CSV
- Meningkatkan robustness parsing timestamp multi-format dan logging batch proses seeding
- Menata ulang tampilan laporan, nilai plafond, dan penilai agar label dan UI konsisten
- Memastikan semua operasi penting tercatat di log dengan konteks user dan parameter penting
2025-10-10 23:48:15 +07:00
majid
be41a815f7 feat(pdf-viewer): implement pdf.js with pagination and swipe controls 2025-07-29 09:57:54 +07:00
majid
c459d1be70 Merge branch 'feature/senior-officer' into lpj-db-migratio 2025-07-21 10:17:51 +07:00
majid
142257d18d feat(laporan-user): refactor user report to display user data instead of permohonan
- Change data source from Permohonan to User model
- Simplify search functionality to only search by name and NIK
- Update table columns to show user information (NIK, name, roles)
- Remove date range filters and complex search conditions
- Add helper function getFilePath to handle storage paths
2025-07-21 10:13:47 +07:00
majid
32eab5f089 Merge branch 'staging' into feature/senior-officer 2025-07-14 09:03:18 +07:00
majid
84933206ee feat: add export functionality and simplify laporan user report
refactor: update laporan user service and views for simplified report
style: improve daftar pustaka views and remove unused code
fix: correct date field names in laporan sla penilai service
2025-07-11 21:16:01 +07:00
majid
1338085481 fix(activity): highlight table row in red when status is "freeze" 2025-07-11 21:09:51 +07:00
majid
3f57d361f9 feat: add export functionality and simplify laporan user report
refactor: update laporan user service and views for simplified report
style: improve daftar pustaka views and remove unused code
fix: correct date field names in laporan sla penilai service
2025-07-11 17:01:50 +07:00
majid
027c698a11 fix: perbaiki navigasi back di halaman laporan penilai dan tampilkan gambar/pdf pada daftar pustaka 2025-07-08 17:04:19 +07:00
majid
05f87f4767 frefactor(daftar-pustaka): replace manual file handling with Laravel Storage 2025-07-08 14:17:45 +07:00
majid
6bb13dbcaf fix(signature): perbaikkan tanda tangan otorisator 2025-07-08 13:39:54 +07:00
majid
02d2e42621 Merge branch 'feature/senior-officer' into lpj-db-migratio 2025-07-08 09:45:57 +07:00
majid
fd7f5fb9c2 feat(daftar-pustaka) : tambah daftar pustaka dan categori pustaka, lihat detail, tambah, edit 2025-07-07 17:27:49 +07:00
majid
dbb930557b Merge branch 'feature/senior-officer' of https://git.putrakuningan.com/daengdeni/lpj into feature/senior-officer 2025-07-07 09:50:44 +07:00
majid
7aeab00535 feat(laporan): tambah tanggal reported, kunjungan, laporan 2025-07-07 09:50:37 +07:00
majid
22e9e6b6a9 feat(print-out): tambah tanggal otorisasi di bagian tanda tangan 2025-07-07 09:44:49 +07:00
majid
e27a34d52f Merge branch 'feature/senior-officer' into lpj-db-migratio 2025-07-03 11:17:48 +07:00
majid
db3ffacebe update service preview laporan and foto jaminan 2025-06-18 10:15:49 +07:00
majid
daed7c5e48 fix: tampilan detail laporan, dan ganti route print out, penambahan service 2025-06-13 09:56:42 +07:00
majid
4405760df4 Merge branch 'staging' into lpj-db-migratio 2025-06-11 10:00:41 +07:00
majid
7ddcc14167 update migration file, dan laporan 2025-06-11 09:55:37 +07:00
majid
f69128e18e feat: penambahan pencarian berdasarkan nama debiture 2025-05-26 11:17:41 +07:00
majid
39424b5df5 fix: update tampilan penilai jaminan 2025-05-23 14:58:13 +07:00
majid
ec22e5f632 fix: update hasil laporan export dan controller 2025-05-23 14:57:15 +07:00
majid
f81cdbb50d Updates user data and improves UI components
Updates user data display across multiple views to handle migrated data.

Improves UI components by adding a detail location component and refining print layouts.
Also, it fixes minor bugs and enhances data presentation in reports and forms.
2025-05-09 14:32:48 +07:00
majid
d1ce5f2d55 fix: handle error tanggal penilaian 2025-05-05 15:47:09 +07:00
majid
2cb68b6d94 fix: perbaikkan export hasil penilai jamianan dan index permohonan 2025-05-05 13:43:35 +07:00
majid
d2b4e380b5 Merge branch 'staging' into lpj-db-migratio 2025-05-05 10:24:01 +07:00
majid
3853b5d6eb fix: perbaikkan tampilan dan print out lpj setalah migrate db old ke db new 2025-05-05 10:13:09 +07:00
majid
bf7e6275e3 feat: add migration and seeder databse lpj old to lpj new 2025-05-05 00:21:46 +07:00
137 changed files with 12544 additions and 4100 deletions

View File

@@ -1,288 +1,305 @@
<?php
namespace Modules\Lpj\Exports;
namespace Modules\Lpj\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithTitle;
use Maatwebsite\Excel\Concerns\WithCustomStartCell;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Events\AfterSheet;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\Branch;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithTitle;
use Maatwebsite\Excel\Concerns\WithCustomStartCell;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Events\AfterSheet;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\Branch;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
class LaporanHasilPenilaianJaminanInternalExternalExport implements FromCollection, WithHeadings, WithMapping, WithTitle, WithCustomStartCell, WithEvents
class LaporanHasilPenilaianJaminanInternalExternalExport implements FromCollection, WithHeadings, WithMapping, WithTitle, WithCustomStartCell, WithEvents
{
protected $request;
public function __construct($request)
{
protected $request;
public function __construct($request)
{
$this->request = $request;
}
public function collection()
{
$query = Permohonan::query();
$query = $query->where('status', 'done');
// Apply date range filter if provided
if ($this->request->has('start_date') || $this->request->has('end_date')) {
$query->whereBetween('tanggal_permohonan', [
$this->request->start_date ?? '1900-01-01',
$this->request->end_date ?? now()->toDateString()
]);
}
// Apply branch filter if provided
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
$query->where('branch_id', $this->request->branch_id);
}
if ($this->request->has('penilai_id') && !empty($this->request->penilai_id)) {
$request = $this->request; // Store in a local variable
$query->whereHas('penilaian._user_penilai.userPenilaiTeam', function($q) use ($request) {
$q->where('user_id', $request->penilai_id);
});
}
// Apply search filter if provided
if ($this->request->has('search') && !empty($this->request->search)) {
$search = $this->request->search;
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search . '%');
$q->orWhere('status', 'LIKE', '%' . $search . '%');
});
}
// Default ordering
$query->orderBy('nomor_registrasi', 'asc');
return $query->get();
}
protected $rowNumber = 0;
public function map($permohonan): array
{
$this->rowNumber++;
$luas_tanah = 0;
$luas_bangunan = 0;
$nilai_tanah = 0;
$nilai_bangunan = 0;
$npw = 0;
$nilai_liquidasi = 0;
if (isset($permohonan->penilai->lpj)) {
$lpj = json_decode($permohonan->penilai->lpj, true);
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
$luas_tanah = $lpj['luas_tanah'] ?? 0;
$luas_bangunan = $lpj['luas_bangunan'] ?? 0;
$nilai_tanah = str_replace('.', '', $lpj['nilai_tanah_2'] ?? 0);
$nilai_bangunan = str_replace('.', '', $lpj['nilai_bangunan_2'] ?? 0);
$nilai_liquidasi = str_replace('.', '', $lpj['likuidasi_nilai_2'] ?? 0);
}
return [
$this->rowNumber,
$permohonan->nomor_registrasi,
$permohonan->tanggal_permohonan,
$permohonan->debiture->branch->name,
$permohonan->creator->name,
$permohonan->debiture->cif,
$permohonan->debiture->name,
$permohonan->jenisPenilaian->name,
$permohonan->tujuanPenilaian->name,
$permohonan->jenisFasilitasKredit->name,
$permohonan->documents->pluck('jenisJaminan.name')->unique()->implode(', '),
$permohonan->documents->map(function ($document) {
return formatAlamat($document);
})->unique()->implode(', '),
$permohonan->documents->flatMap(function ($document) {
return $document->detail->map(function ($detail) {
return (!empty($detail->dokumen_nomor) && is_array($detail->dokumen_nomor))
? ($detail->jenisLegalitasJaminan->name ?? '') . "\n" . implode(', ', $detail->dokumen_nomor)
: null;
});
})->filter()->unique()->implode(', '),
$permohonan->documents->pluck('pemilik.name')->unique()->implode(', '),
$luas_tanah . ' m²',
formatRupiah($nilai_tanah, 2),
$luas_bangunan . ' m²',
formatRupiah($nilai_bangunan, 2),
formatRupiah($permohonan->nilai_njop ?? 0, 2),
formatRupiah($npw, 2),
formatRupiah($nilai_liquidasi, 2),
$permohonan->documents->map(function ($document) {
return formatTanggalIndonesia($document->created_at);
})->first(),
'', // tanggal_spk
'', // nomor_spk
'', // tanggal_rencana_kunjungan
$permohonan->penilaian->tanggal_kunjungan ? formatTanggalIndonesia($permohonan->penilaian->tanggal_kunjungan) : '',
'', // tanggal_delivered
'', // jangka_waktu_sla
($permohonan->approval_dd_at || $permohonan->approval_eo_at) ?
formatTanggalIndonesia($permohonan->approval_dd_at ?? $permohonan->approval_eo_at) : '',
$permohonan->penilaian->tanggal_kunjungan ? formatTanggalIndonesia($permohonan->penilaian->tanggal_kunjungan) : '',
$permohonan->penilaian->_user_penilai->userPenilaiTeam->name ?? '',
$permohonan->penilaian->teams ?? '',
'', // saran
'' // catatan
];
}
public function headings(): array
{
return [
'No',
'Nomor Registrasi',
'Tanggal Permohonan',
'Cabang',
'Pemohon',
'CIF',
'Nama Debitur',
'Jenis Penilaian',
'Tujuan Penilaian',
'Jenis Fasilitas Kredit',
'Jenis Agunan',
'Alamat Agunan',
'Bukti Kepemilikan',
'Nama Pemilik',
'Luas Tanah',
'Nilai Tanah',
'Luas Bangunan',
'Nilai Bangunan',
'Nilai NJOP',
'Nilai Pasar Wajar',
'Nilai Likuidasi',
'Tanggal Dokumen Diterima',
'Tanggal SPK',
'Nomor SPK',
'Tanggal Rencana Kunjungan',
'Tanggal Kunjungan',
'Tanggal Delivered',
'Jangka Waktu SLA',
'Tanggal Laporan',
'Tanggal Review',
'Nama Penilai',
'Nama Team Leader',
'Saran',
'Catatan'
];
}
/**
* @return string
*/
public function title(): string
{
return 'Laporan Hasil Penilaian Jaminan Internal & External';
}
/**
* @return string
*/
public function startCell(): string
{
return 'A7';
}
/**
* @return array
*/
public function registerEvents(): array
{
return [
AfterSheet::class => function(AfterSheet $event) {
// Get the sheet
$sheet = $event->sheet->getDelegate();
// Set the title
$sheet->setCellValue('A1', 'LAPORAN PENILAIAN JAMINAN');
$sheet->getStyle('A1')->getFont()->setBold(true)->setSize(16);
// Merge cells for title
$sheet->mergeCells('A1:AH1');
$sheet->getStyle('A1')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
// Set the branch information if filtered
$branchInfo = '';
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
$branch = Branch::find($this->request->branch_id);
if ($branch) {
$branchInfo = 'Cabang: ' . $branch->name;
$sheet->setCellValue('A2', $branchInfo);
$sheet->mergeCells('A2:AH2');
$sheet->getStyle('A2')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
$sheet->getStyle('A2')->getFont()->setBold(true);
}
}
// Set the period
$startDate = $this->request->start_date ?? '';
$endDate = $this->request->end_date ?? '';
$rowIndex = $branchInfo ? 3 : 2;
if ($startDate && $endDate) {
$startDateFormatted = Carbon::parse($startDate)->format('d F Y');
$endDateFormatted = Carbon::parse($endDate)->format('d F Y');
$sheet->setCellValue('A' . $rowIndex, 'Periode: ' . $startDateFormatted . ' - ' . $endDateFormatted);
} else {
$sheet->setCellValue('A' . $rowIndex, 'Periode: Semua Data');
}
$sheet->mergeCells('A' . $rowIndex . ':AH' . $rowIndex);
$sheet->getStyle('A' . $rowIndex)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
// Set the date of export
$rowIndex++;
$sheet->setCellValue('A' . $rowIndex, 'Tanggal Export: ' . Carbon::now()->format('d F Y H:i:s'));
// Set the user who exported
$rowIndex++;
$userName = Auth::user() ? Auth::user()->name : 'System';
$sheet->setCellValue('A' . $rowIndex, 'Diexport oleh: ' . $userName);
// Add a blank line
$rowIndex++;
$sheet->setCellValue('A' . $rowIndex, '');
// Style the header row
$headerRange = 'A7:' . $sheet->getHighestColumn() . '7';
$sheet->getStyle($headerRange)->getFont()->setBold(true);
$sheet->getStyle($headerRange)->getFill()
->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
->getStartColor()->setARGB('FFCCCCCC');
// Auto-size columns - fixed to handle columns beyond Z
$highestColumn = $sheet->getHighestColumn();
$highestColumnIndex = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($highestColumn);
for ($i = 1; $i <= $highestColumnIndex; $i++) {
$currentColumn = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($i);
$sheet->getColumnDimension($currentColumn)->setAutoSize(true);
}
// Add borders to all cells with data
$dataRange = 'A7:' . $sheet->getHighestColumn() . $sheet->getHighestRow();
$sheet->getStyle($dataRange)->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
// Center align the header row
$sheet->getStyle($headerRange)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
// Set text wrap for header cells
$sheet->getStyle($headerRange)->getAlignment()->setWrapText(true);
},
];
}
$this->request = $request;
}
public function collection()
{
$query = Permohonan::query();
$query = $query->where('status', 'done');
// Apply date range filter if provided
if ($this->request->has('start_date') || $this->request->has('end_date')) {
$startDate = $this->request->start_date ?? '1900-01-01';
$endDate = $this->request->end_date ?? now()->toDateString();
$query->where(function ($q) use ($startDate, $endDate) {
$q->whereHas('penilaian', function ($q2) use ($startDate, $endDate) {
$q2->whereBetween('tanggal_kunjungan', [$startDate, $endDate]);
});
// OR check if has penawaran with date in range
$q->orWhereHas('penawaran', function ($q3) use ($startDate, $endDate) {
$q3->whereBetween('tanggal_penilaian_sebelumnya', [$startDate, $endDate]);
});
});
}
// Apply branch filter if provided
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
$query->where('branch_id', $this->request->branch_id);
}
if ($this->request->has('penilai_id') && !empty($this->request->penilai_id)) {
$request = $this->request; // Store in a local variable
$query->whereHas('penilaian._user_penilai.userPenilaiTeam', function ($q) use ($request) {
$q->where('user_id', $request->penilai_id);
});
}
// Apply search filter if provided
if ($this->request->has('search') && !empty($this->request->search)) {
$search = $this->request->search;
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('debiture', DB::raw('LOWER(name)'), 'LIKE', '%' . strtolower($search) . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search . '%');
$q->orWhere('status', 'LIKE', '%' . $search . '%');
});
}
// Default ordering
$query->orderBy('nomor_registrasi', 'asc');
return $query->get();
}
protected $rowNumber = 0;
public function map($permohonan): array
{
$this->rowNumber++;
$luas_tanah = 0;
$luas_bangunan = 0;
$nilai_tanah = 0;
$nilai_bangunan = 0;
$npw = 0;
$nilai_liquidasi = 0;
if (isset($permohonan->penilai->lpj)) {
$lpj = json_decode($permohonan->penilai->lpj, true);
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
$luas_tanah = $lpj['luas_tanah'] ?? 0;
$luas_bangunan = $lpj['luas_bangunan'] ?? 0;
$nilai_tanah = str_replace('.', '', $lpj['nilai_tanah_2'] ?? 0);
$nilai_bangunan = str_replace('.', '', $lpj['nilai_bangunan_2'] ?? 0);
$nilai_liquidasi = str_replace('.', '', $lpj['likuidasi_nilai_2'] ?? 0);
}
return [
$this->rowNumber,
$permohonan->nomor_registrasi,
$permohonan->tanggal_permohonan ?? '',
$permohonan->debiture->branch->name ?? '',
$permohonan->user->name ?? $permohonan->mig_nama_ao ?? '',
$permohonan->debiture->cif ?? '',
$permohonan->debiture->name ?? '',
$permohonan->tujuanPenilaian->name,
$permohonan->jenisPenilaian->name ?? '',
$permohonan->jenisFasilitasKredit->name,
$permohonan->documents->pluck('jenisJaminan.name')->unique()->implode(', '),
$permohonan->documents->map(function ($document) {
return formatAlamat($document);
})->unique()->implode(', '),
$permohonan->documents->flatMap(function ($document) {
return $document->detail->map(function ($detail) {
return (!empty($detail->dokumen_nomor) && is_array($detail->dokumen_nomor))
? ($detail->jenisLegalitasJaminan->name ?? '') . "\n" . implode(', ', $detail->dokumen_nomor)
: null;
});
})->filter()->unique()->implode(', '),
$permohonan->documents->pluck('pemilik.name')->unique()->implode(', '),
$luas_tanah . ' m²',
formatRupiah($nilai_tanah, 2),
$luas_bangunan . ' m²',
formatRupiah($nilai_bangunan, 2),
formatRupiah($permohonan->nilai_njop ?? 0, 2),
formatRupiah($npw, 2),
formatRupiah($nilai_liquidasi, 2),
$permohonan->documents->map(function ($document) {
return formatTanggalIndonesia($document->created_at);
})->first(),
'', // tanggal_spk
'', // nomor_spk
'', // tanggal_rencana_kunjungan
$permohonan->penilaian && $permohonan->penilaian->tanggal_kunjungan
? formatTanggalIndonesia($permohonan->penilaian->tanggal_kunjungan)
: '',
'', // tanggal_delivered
'', // jangka_waktu_sla
($permohonan->approval_dd_at || $permohonan->approval_eo_at) ?
formatTanggalIndonesia($permohonan->approval_dd_at ?? $permohonan->approval_eo_at) : '',
$permohonan->penilaian && $permohonan->penilaian->tanggal_kunjungan
? formatTanggalIndonesia($permohonan->penilaian->tanggal_kunjungan)
: '',
$permohonan->penilaian->_user_penilai->userPenilaiTeam->name ?? '',
$permohonan->approveSo->name ?? '',
'', // saran
'' // catatan
];
}
public function headings(): array
{
return [
'No',
'Nomor Registrasi',
'Tanggal Permohonan',
'Cabang',
'Pemohon',
'CIF',
'Nama Debitur',
'Jenis Penilaian',
'Tujuan Penilaian',
'Jenis Fasilitas Kredit',
'Jenis Agunan',
'Alamat Agunan',
'Bukti Kepemilikan',
'Nama Pemilik',
'Luas Tanah',
'Nilai Tanah',
'Luas Bangunan',
'Nilai Bangunan',
'Nilai NJOP',
'Nilai Pasar Wajar',
'Nilai Likuidasi',
'Tanggal Dokumen Diterima',
'Tanggal SPK',
'Nomor SPK',
'Tanggal Rencana Kunjungan',
'Tanggal Kunjungan',
'Tanggal Delivered',
'Jangka Waktu SLA',
'Tanggal Laporan',
'Tanggal Review',
'Nama Penilai',
'Nama Team Leader',
'Saran',
'Catatan'
];
}
/**
* @return string
*/
public function title(): string
{
return 'Laporan Hasil Penilaian Jaminan Internal & External';
}
/**
* @return string
*/
public function startCell(): string
{
return 'A7';
}
/**
* @return array
*/
public function registerEvents(): array
{
return [
AfterSheet::class => function (AfterSheet $event) {
// Get the sheet
$sheet = $event->sheet->getDelegate();
// Set the title
$sheet->setCellValue('A1', 'LAPORAN PENILAIAN JAMINAN');
$sheet->getStyle('A1')->getFont()->setBold(true)->setSize(16);
// Merge cells for title
$sheet->mergeCells('A1:AH1');
$sheet->getStyle('A1')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
// Set the branch information if filtered
$branchInfo = '';
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
$branch = Branch::find($this->request->branch_id);
if ($branch) {
$branchInfo = 'Cabang: ' . $branch->name;
$sheet->setCellValue('A2', $branchInfo);
$sheet->mergeCells('A2:AH2');
$sheet->getStyle('A2')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
$sheet->getStyle('A2')->getFont()->setBold(true);
}
}
// Set the period
$startDate = $this->request->start_date ?? '';
$endDate = $this->request->end_date ?? '';
$rowIndex = $branchInfo ? 3 : 2;
if ($startDate && $endDate) {
$startDateFormatted = Carbon::parse($startDate)->format('d F Y');
$endDateFormatted = Carbon::parse($endDate)->format('d F Y');
$sheet->setCellValue('A' . $rowIndex, 'Periode: ' . $startDateFormatted . ' - ' . $endDateFormatted);
} else {
$sheet->setCellValue('A' . $rowIndex, 'Periode: Semua Data');
}
$sheet->mergeCells('A' . $rowIndex . ':AH' . $rowIndex);
$sheet->getStyle('A' . $rowIndex)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
// Set the date of export
$rowIndex++;
$sheet->setCellValue('A' . $rowIndex, 'Tanggal Export: ' . Carbon::now()->format('d F Y H:i:s'));
// Set the user who exported
$rowIndex++;
$userName = Auth::user() ? Auth::user()->name : 'System';
$sheet->setCellValue('A' . $rowIndex, 'Diexport oleh: ' . $userName);
// Add a blank line
$rowIndex++;
$sheet->setCellValue('A' . $rowIndex, '');
// Style the header row
$headerRange = 'A7:' . $sheet->getHighestColumn() . '7';
$sheet->getStyle($headerRange)->getFont()->setBold(true);
$sheet->getStyle($headerRange)->getFill()
->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
->getStartColor()->setARGB('FFCCCCCC');
// Auto-size columns - fixed to handle columns beyond Z
$highestColumn = $sheet->getHighestColumn();
$highestColumnIndex = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($highestColumn);
for ($i = 1; $i <= $highestColumnIndex; $i++) {
$currentColumn = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($i);
$sheet->getColumnDimension($currentColumn)->setAutoSize(true);
}
// Add borders to all cells with data
$dataRange = 'A7:' . $sheet->getHighestColumn() . $sheet->getHighestRow();
$sheet->getStyle($dataRange)->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
// Center align the header row
$sheet->getStyle($headerRange)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
// Set text wrap for header cells
$sheet->getStyle($headerRange)->getAlignment()->setWrapText(true);
},
];
}
}

View File

@@ -2,7 +2,8 @@
namespace Modules\Lpj\Exports;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
@@ -11,167 +12,299 @@ use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use Modules\Lpj\Models\Debiture;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Helpers\Lpj;
use Illuminate\Support\Facades\DB;
class LaporanPenilaiJaminanExport implements FromQuery, WithHeadings, WithMapping, ShouldAutoSize
class LaporanPenilaiJaminanExport implements FromCollection, WithHeadings, WithMapping, ShouldAutoSize
{
protected $tanggalAwal;
protected $tanggalAkhir;
protected $status;
protected $selectedIds;
public function __construct($tanggalAwal = null, $tanggalAkhir = null, $status = null, $selectedIds = null)
protected $request;
public function __construct($request)
{
$this->tanggalAwal = $tanggalAwal;
$this->tanggalAkhir = $tanggalAkhir;
$this->status = $status;
$this->selectedIds = $selectedIds;
$this->request = $request;
}
public function query()
public function collection()
{
$query = Permohonan::query()
->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian', 'dokumenjaminan.jenisJaminan','nilaiPlafond', 'penilai', 'inspeksi']);
$query = Permohonan::query();
$query = $query->where('status', 'done');
// Filter by date range if provided
if ($this->tanggalAwal && $this->tanggalAkhir) {
$query->whereBetween('tanggal_permohonan', [$this->tanggalAwal, $this->tanggalAkhir]);
}
// Apply date range filter if provided
if ($this->request->has('start_date') || $this->request->has('end_date')) {
$startDate = $this->request->start_date ?? '1900-01-01';
$endDate = $this->request->end_date ?? now()->toDateString();
$query->where('status', 'done');
// Filter by status if provided
if ($this->status) {
$types = is_array($this->status) ? $this->status : [$this->status];
$types = array_map('strtolower', $types);
$query->whereHas('penilai', function (Builder $query) use ($types) {
$query->whereIn('type_penilai', $types);
$query->where(function ($q) use ($startDate, $endDate) {
$q->whereHas('penilaian', function ($q2) use ($startDate, $endDate) {
$q2->whereBetween('tanggal_kunjungan', [$startDate, $endDate]);
});
// OR check if has penawaran with date in range
$q->orWhereHas('penawaran', function ($q3) use ($startDate, $endDate) {
$q3->whereBetween('tanggal_penilaian_sebelumnya', [$startDate, $endDate]);
});
});
}
// Filter by laporan type if provided
if ($this->request->has('laporan') && is_array($this->request->laporan) && !empty($this->request->laporan)) {
foreach ($this->request->laporan as $type) {
$query->whereHas('penilai', function ($q) use ($type) {
$q->where('type_penilai', 'LIKE', '%' . $type . '%');
});
}
}
// Apply branch filter if provided
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
$query->where('branch_id', $this->request->branch_id);
}
// Filter by selected IDs if provided
if ($this->selectedIds) {
$selectedIds = is_array($this->selectedIds) ? $this->selectedIds : explode(',', $this->selectedIds);
if ($this->request->has('selected_ids') && !empty($this->request->selected_ids)) {
$selectedIds = is_array($this->request->selected_ids) ? $this->request->selected_ids : explode(',', $this->request->selected_ids);
$query->whereIn('id', $selectedIds);
}
return $query;
// Apply search filter if provided
if ($this->request->has('search') && !empty($this->request->search)) {
$search = $this->request->search;
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('debiture', DB::raw('LOWER(name)'), 'LIKE', '%' . strtolower($search) . '%');
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search . '%');
$q->orWhere('status', 'LIKE', '%' . $search . '%');
});
}
// Default ordering
$query->orderBy('nomor_registrasi', 'asc');
return $query->get();
}
public function map($row): array
protected $rowNumber = 0;
public function map($permohonan): array
{
$this->rowNumber++;
$luas_tanah = 0;
$luas_bangunan = 0;
$nilai_tanah = 0;
$nilai_bangunan = 0;
$npw = 0;
$nilai_liquidasi = 0;
// ambil data alamat dari inspeksi
$alamat_inspeksi = null;
if (isset($permohonan->penilai->lpj)) {
$lpj = json_decode($permohonan->penilai->lpj, true);
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
if ($row->inspeksi) {
$alamat_inspeksi = json_decode($row->inspeksi->data_form, true) ?? null;
$alamat_inspeksi = $alamat_inspeksi['asset']['alamat']['sesuai'] ?? $alamat_inspeksi['asset']['alamat']['tidak sesuai'] ?? [];
$luas_tanah = $lpj['luas_tanah'] ?? 0;
$luas_bangunan = $lpj['luas_bangunan'] ?? 0;
$nilai_tanah = str_replace('.', '', $lpj['nilai_tanah_2'] ?? 0);
$nilai_bangunan = str_replace('.', '', $lpj['nilai_bangunan_2'] ?? 0);
$nilai_liquidasi = str_replace('.', '', $lpj['likuidasi_nilai_2'] ?? 0);
}
$alamat_inspeksi = $alamat_inspeksi['address'] ?? '-';
// ambil data dari table penilai
$fieldPenilai = ['lpj', 'resume', 'memo', 'rap', 'call-report'];
$penilaiCek = null;
// Cari field yang tersedia
foreach ($fieldPenilai as $value) {
if (!empty($row->penilai->$value)) {
$penilaiCek = $row->penilai->$value;
break;
}
}
$decodePenilai = json_decode($penilaiCek, true) ?? [];
// Ambil nilai utama
$luasTanah = $decodePenilai['luas_tanah'] ?? 0;
$nilaiTanah1 = $decodePenilai['nilai_tanah_1'] ?? 0;
$luasBangunan = $decodePenilai['luas_bangunan'] ?? 0;
$nilaiBangunan1 = $decodePenilai['nilai_bangunan_1'] ?? 0;
$totalNilaiPasar = $decodePenilai['total_nilai_pasar_wajar'] ?? 0;
$likuidasi = $decodePenilai['likuidasi'] ?? 0;
// Ambil data npw_tambahan jika ada
$npwTambahan = $decodePenilai['npw_tambahan'] ?? [];
$tambahanDetails = [];
foreach ($npwTambahan as $tambahan) {
$tambahanDetails[] = sprintf(
'%s: Luas: %s, Nilai 1: %s, Nilai 2: %s',
$tambahan['name'] ?? '-',
$tambahan['luas'] ?? 0,
$tambahan['nilai_1'] ?? 0,
$tambahan['nilai_2'] ?? 0
);
}
$tambahanSummary = implode("; ", $tambahanDetails);
// Ambil data penilaian dari table penilaian
$user_penilai = $row->penilaian->userPenilai ?? null;
$user_penilai_name = null;
foreach ($user_penilai as $value) {
if ($value->role == 'penilai') {
$user_penilai_name = $value->user->name;
$nik_penilai = $value->user->nik ?? '-';
break;
}
}
return [
$row->id,
$row->nomor_registrasi,
$row->user->name,
$row->branch->name,
$row->tujuanPenilaian->name,
$row->debiture->name,
$row->penilai->type_penilai ?? '-',
$alamat_inspeksi ?? '-',
$luasTanah,
$luasBangunan,
$nilaiTanah1,
$nilaiBangunan1,
$totalNilaiPasar,
$likuidasi,
$row->laporan->created_at ?? '-',
$user_penilai_name,
$nik_penilai,
$row->created_at,
$this->rowNumber,
$permohonan->nomor_registrasi,
$permohonan->tanggal_permohonan ?? '',
$permohonan->debiture->branch->name ?? '',
$permohonan->user->name ?? $permohonan->mig_nama_ao ?? '',
$permohonan->debiture->cif ?? '',
$permohonan->debiture->name ?? '',
$permohonan->tujuanPenilaian->name,
$permohonan->jenisPenilaian->name ?? '',
$permohonan->jenisFasilitasKredit->name,
$permohonan->documents->pluck('jenisJaminan.name')->unique()->implode(', '),
$permohonan->documents->map(function ($document) {
return formatAlamat($document);
})->unique()->implode(', '),
$permohonan->documents->flatMap(function ($document) {
return $document->detail->map(function ($detail) {
return (!empty($detail->dokumen_nomor) && is_array($detail->dokumen_nomor))
? ($detail->jenisLegalitasJaminan->name ?? '') . "\n" . implode(', ', $detail->dokumen_nomor)
: null;
});
})->filter()->unique()->implode(', '),
$permohonan->documents->pluck('pemilik.name')->unique()->implode(', '),
$luas_tanah . ' m²',
formatRupiah($nilai_tanah, 2),
$luas_bangunan . ' m²',
formatRupiah($nilai_bangunan, 2),
formatRupiah($permohonan->nilai_njop ?? 0, 2),
formatRupiah($npw, 2),
formatRupiah($nilai_liquidasi, 2),
$permohonan->documents->map(function ($document) {
return formatTanggalIndonesia($document->created_at);
})->first(),
'', // tanggal_spk
'', // nomor_spk
'', // tanggal_rencana_kunjungan
$permohonan->penilaian && $permohonan->penilaian->tanggal_kunjungan
? formatTanggalIndonesia($permohonan->penilaian->tanggal_kunjungan)
: '',
'', // tanggal_delivered
'', // jangka_waktu_sla
($permohonan->approval_dd_at || $permohonan->approval_eo_at) ?
formatTanggalIndonesia($permohonan->approval_dd_at ?? $permohonan->approval_eo_at) : '',
$permohonan->penilaian && $permohonan->penilaian->tanggal_kunjungan
? formatTanggalIndonesia($permohonan->penilaian->tanggal_kunjungan)
: '',
$permohonan->penilaian->_user_penilai->userPenilaiTeam->name ?? '',
$permohonan->approveSo->name ?? '',
$permohonan->penilai->type_penilai?? '',
];
}
public function headings(): array
{
return [
'ID',
'No',
'Nomor Registrasi',
'User Pemohon',
'Tanggal Permohonan',
'Cabang',
'Pemohon',
'CIF',
'Nama Debitur',
'Jenis Penilaian',
'Tujuan Penilaian',
'Debitur',
'Jenis Laporan',
'Lokasi Jaminan',
'Jenis Fasilitas Kredit',
'Jenis Agunan',
'Alamat Agunan',
'Bukti Kepemilikan',
'Nama Pemilik',
'Luas Tanah',
'Nilai Tanah',
'Luas Bangunan',
'Harga Tanah',
'Harga Bangunan',
'Nilai Bangunan',
'Nilai NJOP',
'Nilai Pasar Wajar',
'Likuidasi',
'Nilai Likuidasi',
'Tanggal Dokumen Diterima',
'Tanggal SPK',
'Nomor SPK',
'Tanggal Rencana Kunjungan',
'Tanggal Kunjungan',
'Tanggal Delivered',
'Jangka Waktu SLA',
'Tanggal Laporan',
'Tanggal Review',
'Nama Penilai',
'Nik Penilai',
'Created At',
'Nama Team Leader',
'Laporan',
];
}
public function columnFormats(): array
/**
* @return string
*/
public function title(): string
{
return 'Laporan Hasil Penilaian Jaminan Internal & External';
}
/**
* @return string
*/
public function startCell(): string
{
return 'A7';
}
public function registerEvents(): array
{
return [
'A' => NumberFormat::FORMAT_NUMBER,
'C' => NumberFormat::FORMAT_DATE_DATETIME,
'K' => NumberFormat::FORMAT_DATE_DATETIME,
'N' => NumberFormat::FORMAT_DATE_DATETIME
AfterSheet::class => function (AfterSheet $event) {
// Get the sheet
$sheet = $event->sheet->getDelegate();
// Set the title
$sheet->setCellValue('A1', 'LAPORAN PENILAIAN JAMINAN');
$sheet->getStyle('A1')->getFont()->setBold(true)->setSize(16);
// Merge cells for title
$sheet->mergeCells('A1:AH1');
$sheet->getStyle('A1')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
// Set the branch information if filtered
$branchInfo = '';
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
$branch = Branch::find($this->request->branch_id);
if ($branch) {
$branchInfo = 'Cabang: ' . $branch->name;
$sheet->setCellValue('A2', $branchInfo);
$sheet->mergeCells('A2:AH2');
$sheet->getStyle('A2')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
$sheet->getStyle('A2')->getFont()->setBold(true);
}
}
// Set the period
$startDate = $this->request->start_date ?? '';
$endDate = $this->request->end_date ?? '';
$rowIndex = $branchInfo ? 3 : 2;
if ($startDate && $endDate) {
$startDateFormatted = Carbon::parse($startDate)->format('d F Y');
$endDateFormatted = Carbon::parse($endDate)->format('d F Y');
$sheet->setCellValue('A' . $rowIndex, 'Periode: ' . $startDateFormatted . ' - ' . $endDateFormatted);
} else {
$sheet->setCellValue('A' . $rowIndex, 'Periode: Semua Data');
}
$sheet->mergeCells('A' . $rowIndex . ':AH' . $rowIndex);
$sheet->getStyle('A' . $rowIndex)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
// Set the date of export
$rowIndex++;
$sheet->setCellValue('A' . $rowIndex, 'Tanggal Export: ' . Carbon::now()->format('d F Y H:i:s'));
// Set the user who exported
$rowIndex++;
$userName = Auth::user() ? Auth::user()->name : 'System';
$sheet->setCellValue('A' . $rowIndex, 'Diexport oleh: ' . $userName);
// Add a blank line
$rowIndex++;
$sheet->setCellValue('A' . $rowIndex, '');
// Style the header row
$headerRange = 'A7:' . $sheet->getHighestColumn() . '7';
$sheet->getStyle($headerRange)->getFont()->setBold(true);
$sheet->getStyle($headerRange)->getFill()
->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
->getStartColor()->setARGB('FFCCCCCC');
// Auto-size columns - fixed to handle columns beyond Z
$highestColumn = $sheet->getHighestColumn();
$highestColumnIndex = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($highestColumn);
for ($i = 1; $i <= $highestColumnIndex; $i++) {
$currentColumn = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($i);
$sheet->getColumnDimension($currentColumn)->setAutoSize(true);
}
// Add borders to all cells with data
$dataRange = 'A7:' . $sheet->getHighestColumn() . $sheet->getHighestRow();
$sheet->getStyle($dataRange)->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
// Center align the header row
$sheet->getStyle($headerRange)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
// Set text wrap for header cells
$sheet->getStyle($headerRange)->getAlignment()->setWrapText(true);
},
];
}
}

View File

@@ -1,245 +1,260 @@
<?php
namespace Modules\Lpj\Exports;
namespace Modules\Lpj\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithTitle;
use Maatwebsite\Excel\Concerns\WithCustomStartCell;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Events\AfterSheet;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\Branch;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithTitle;
use Maatwebsite\Excel\Concerns\WithCustomStartCell;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Events\AfterSheet;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\Branch;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
class LaporanPenilaianJaminanExport implements FromCollection, WithHeadings, WithMapping, WithTitle, WithCustomStartCell, WithEvents
{
protected $request;
class LaporanPenilaianJaminanExport implements FromCollection, WithHeadings, WithMapping, WithTitle, WithCustomStartCell, WithEvents
public function __construct($request)
{
protected $request;
public function __construct($request)
{
$this->request = $request;
}
public function collection()
{
$query = Permohonan::query();
$query = $query->where('status', 'done');
// Apply date range filter if provided
if ($this->request->has('start_date') || $this->request->has('end_date')) {
$query->whereBetween('tanggal_permohonan', [
$this->request->start_date ?? '1900-01-01',
$this->request->end_date ?? now()->toDateString()
]);
}
// Apply branch filter if provided
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
$query->where('branch_id', $this->request->branch_id);
}
if ($this->request->has('penilai_id') && !empty($this->request->penilai_id)) {
$request = $this->request; // Store in a local variable
$query->whereHas('penilaian._user_penilai.userPenilaiTeam', function($q) use ($request) {
$q->where('user_id', $request->penilai_id);
});
}
// Apply search filter if provided
if ($this->request->has('search') && !empty($this->request->search)) {
$search = $this->request->search;
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search . '%');
$q->orWhere('status', 'LIKE', '%' . $search . '%');
});
}
// Default ordering
$query->orderBy('nomor_registrasi', 'asc');
return $query->with(['debiture.branch'])->get();
}
protected $rowNumber = 0;
public function map($permohonan): array
{
$this->rowNumber++;
$luas_tanah = 0;
$luas_bangunan = 0;
$nilai_tanah = 0;
$nilai_bangunan = 0;
$npw = 0;
$nilai_liquidasi = 0;
if (isset($permohonan->penilai->lpj)) {
$lpj = json_decode($permohonan->penilai->lpj, true);
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
$luas_tanah = $lpj['luas_tanah'] ?? 0;
$luas_bangunan = $lpj['luas_bangunan'] ?? 0;
$nilai_tanah = str_replace('.', '', $lpj['nilai_tanah_2'] ?? 0);
$nilai_bangunan = str_replace('.', '', $lpj['nilai_bangunan_2'] ?? 0);
$nilai_liquidasi = str_replace('.', '', $lpj['likuidasi_nilai_2'] ?? 0);
}
return [
$this->rowNumber,
$permohonan->nomor_registrasi,
$permohonan->tanggal_permohonan,
$permohonan->debiture->branch->name,
$permohonan->debiture->name,
$permohonan->creator->name,
$permohonan->tujuanPenilaian->name,
$permohonan->documents->pluck('jenisJaminan.name')->unique()->implode(', '),
$permohonan->documents->map(function ($document) {
return formatAlamat($document);
})->unique()->implode(', '),
$luas_tanah . ' m²',
formatRupiah($nilai_tanah, 2),
$luas_bangunan . ' m²',
formatRupiah($nilai_bangunan, 2),
($permohonan->approval_dd_at || $permohonan->approval_eo_at) ?
formatTanggalIndonesia($permohonan->approval_dd_at ?? $permohonan->approval_eo_at) : '',
$permohonan->penilaian->tanggal_kunjungan ?
formatTanggalIndonesia($permohonan->penilaian->tanggal_kunjungan) : '',
formatRupiah($npw, 2),
formatRupiah($nilai_liquidasi, 2),
$permohonan->penilaian->_user_penilai->userPenilaiTeam->name,
];
}
public function headings(): array
{
return [
'No',
'Nomor Registrasi',
'Tanggal Permohonan',
'Cabang',
'Nama Debitur',
'Pemohon',
'Tujuan Penilaian',
'Jenis Agunan',
'Alamat Agunan',
'Luas Tanah',
'Nilai Tanah',
'Luas Bangunan',
'Nilai Bangunan',
'Tanggal Laporan',
'Tanggal Review',
'Nilai Pasar Wajar',
'Nilai Likuidasi',
'Nama Penilai',
];
}
/**
* @return string
*/
public function title(): string
{
return 'Laporan Penilaian Jaminan';
}
/**
* @return string
*/
public function startCell(): string
{
return 'A7';
}
/**
* @return array
*/
public function registerEvents(): array
{
return [
AfterSheet::class => function(AfterSheet $event) {
// Get the sheet
$sheet = $event->sheet->getDelegate();
// Set the title
$sheet->setCellValue('A1', 'LAPORAN PENILAIAN JAMINAN');
$sheet->getStyle('A1')->getFont()->setBold(true)->setSize(16);
// Merge cells for title
$sheet->mergeCells('A1:R1');
$sheet->getStyle('A1')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
// Set the branch information if filtered
$branchInfo = '';
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
$branch = Branch::find($this->request->branch_id);
if ($branch) {
$branchInfo = 'Cabang: ' . $branch->name;
$sheet->setCellValue('A2', $branchInfo);
$sheet->mergeCells('A2:R2');
$sheet->getStyle('A2')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
$sheet->getStyle('A2')->getFont()->setBold(true);
}
}
// Set the period
$startDate = $this->request->start_date ?? '';
$endDate = $this->request->end_date ?? '';
$rowIndex = $branchInfo ? 3 : 2;
if ($startDate && $endDate) {
$startDateFormatted = Carbon::parse($startDate)->format('d F Y');
$endDateFormatted = Carbon::parse($endDate)->format('d F Y');
$sheet->setCellValue('A' . $rowIndex, 'Periode: ' . $startDateFormatted . ' - ' . $endDateFormatted);
} else {
$sheet->setCellValue('A' . $rowIndex, 'Periode: Semua Data');
}
$sheet->mergeCells('A' . $rowIndex . ':R' . $rowIndex);
$sheet->getStyle('A' . $rowIndex)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
// Set the date of export
$rowIndex++;
$sheet->setCellValue('A' . $rowIndex, 'Tanggal Export: ' . Carbon::now()->format('d F Y H:i:s'));
// Set the user who exported
$rowIndex++;
$userName = Auth::user() ? Auth::user()->name : 'System';
$sheet->setCellValue('A' . $rowIndex, 'Diexport oleh: ' . $userName);
// Add a blank line
$rowIndex++;
$sheet->setCellValue('A' . $rowIndex, '');
// Style the header row
$headerRange = 'A7:' . $sheet->getHighestColumn() . '7';
$sheet->getStyle($headerRange)->getFont()->setBold(true);
$sheet->getStyle($headerRange)->getFill()
->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
->getStartColor()->setARGB('FFCCCCCC');
// Auto-size columns
foreach(range('A', $sheet->getHighestColumn()) as $column) {
$sheet->getColumnDimension($column)->setAutoSize(true);
}
// Add borders to all cells with data
$dataRange = 'A7:' . $sheet->getHighestColumn() . $sheet->getHighestRow();
$sheet->getStyle($dataRange)->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
// Center align the header row
$sheet->getStyle($headerRange)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
// Set text wrap for header cells
$sheet->getStyle($headerRange)->getAlignment()->setWrapText(true);
},
];
}
$this->request = $request;
}
public function collection()
{
$query = Permohonan::query();
$query = $query->where('status', 'done');
// Apply date range filter if provided
if ($this->request->has('start_date') || $this->request->has('end_date')) {
$startDate = $this->request->start_date ?? '1900-01-01';
$endDate = $this->request->end_date ?? now()->toDateString();
$query->where(function ($q) use ($startDate, $endDate) {
$q->whereHas('penilaian', function ($q2) use ($startDate, $endDate) {
$q2->whereBetween('tanggal_kunjungan', [$startDate, $endDate]);
});
// OR check if has penawaran with date in range
$q->orWhereHas('penawaran', function ($q3) use ($startDate, $endDate) {
$q3->whereBetween('tanggal_penilaian_sebelumnya', [$startDate, $endDate]);
});
});
}
// Apply branch filter if provided
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
$query->where('branch_id', $this->request->branch_id);
}
if ($this->request->has('penilai_id') && !empty($this->request->penilai_id)) {
$request = $this->request; // Store in a local variable
$query->whereHas('penilaian._user_penilai.userPenilaiTeam', function ($q) use ($request) {
$q->where('user_id', $request->penilai_id);
});
}
// Apply search filter if provided
if ($this->request->has('search') && !empty($this->request->search)) {
$search = $this->request->search;
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('debiture', DB::raw('LOWER(name)'), 'LIKE', '%' . strtolower($search) . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search . '%');
$q->orWhere('status', 'LIKE', '%' . $search . '%');
});
}
// Default ordering
$query->orderBy('nomor_registrasi', 'asc');
dd($query->toSql(), $query->getBindings());
return $query->with(['debiture.branch'])->get();
}
protected $rowNumber = 0;
public function map($permohonan): array
{
$this->rowNumber++;
$luas_tanah = 0;
$luas_bangunan = 0;
$nilai_tanah = 0;
$nilai_bangunan = 0;
$npw = 0;
$nilai_liquidasi = 0;
if (isset($permohonan->penilai->lpj)) {
$lpj = json_decode($permohonan->penilai->lpj, true);
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
$luas_tanah = $lpj['luas_tanah'] ?? 0;
$luas_bangunan = $lpj['luas_bangunan'] ?? 0;
$nilai_tanah = str_replace('.', '', $lpj['nilai_tanah_2'] ?? 0);
$nilai_bangunan = str_replace('.', '', $lpj['nilai_bangunan_2'] ?? 0);
$nilai_liquidasi = str_replace('.', '', $lpj['likuidasi_nilai_2'] ?? 0);
}
return [
$this->rowNumber,
$permohonan->nomor_registrasi,
$permohonan->tanggal_permohonan,
$permohonan->debiture->branch->name,
$permohonan->debiture->name,
$permohonan->creator->name,
$permohonan->tujuanPenilaian->name,
$permohonan->documents->pluck('jenisJaminan.name')->unique()->implode(', '),
$permohonan->documents->map(function ($document) {
return formatAlamat($document);
})->unique()->implode(', '),
$luas_tanah . ' m²',
formatRupiah($nilai_tanah, 2),
$luas_bangunan . ' m²',
formatRupiah($nilai_bangunan, 2),
($permohonan->approval_dd_at || $permohonan->approval_eo_at) ?
formatTanggalIndonesia($permohonan->approval_dd_at ?? $permohonan->approval_eo_at) : '',
$permohonan->penilaian->tanggal_kunjungan ?
formatTanggalIndonesia($permohonan->penilaian->tanggal_kunjungan) : '',
formatRupiah($npw, 2),
formatRupiah($nilai_liquidasi, 2),
$permohonan->penilaian->_user_penilai->userPenilaiTeam->name,
];
}
public function headings(): array
{
return [
'No',
'Nomor Registrasi',
'Tanggal Permohonan',
'Cabang',
'Nama Debitur',
'Pemohon',
'Tujuan Penilaian',
'Jenis Agunan',
'Alamat Agunan',
'Luas Tanah',
'Nilai Tanah',
'Luas Bangunan',
'Nilai Bangunan',
'Tanggal Laporan',
'Tanggal Review',
'Nilai Pasar Wajar',
'Nilai Likuidasi',
'Nama Penilai',
];
}
/**
* @return string
*/
public function title(): string
{
return 'Laporan Penilaian Jaminan';
}
/**
* @return string
*/
public function startCell(): string
{
return 'A7';
}
/**
* @return array
*/
public function registerEvents(): array
{
return [
AfterSheet::class => function (AfterSheet $event) {
// Get the sheet
$sheet = $event->sheet->getDelegate();
// Set the title
$sheet->setCellValue('A1', 'LAPORAN PENILAIAN JAMINAN');
$sheet->getStyle('A1')->getFont()->setBold(true)->setSize(16);
// Merge cells for title
$sheet->mergeCells('A1:R1');
$sheet->getStyle('A1')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
// Set the branch information if filtered
$branchInfo = '';
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
$branch = Branch::find($this->request->branch_id);
if ($branch) {
$branchInfo = 'Cabang: ' . $branch->name;
$sheet->setCellValue('A2', $branchInfo);
$sheet->mergeCells('A2:R2');
$sheet->getStyle('A2')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
$sheet->getStyle('A2')->getFont()->setBold(true);
}
}
// Set the period
$startDate = $this->request->start_date ?? '';
$endDate = $this->request->end_date ?? '';
$rowIndex = $branchInfo ? 3 : 2;
if ($startDate && $endDate) {
$startDateFormatted = Carbon::parse($startDate)->format('d F Y');
$endDateFormatted = Carbon::parse($endDate)->format('d F Y');
$sheet->setCellValue('A' . $rowIndex, 'Periode: ' . $startDateFormatted . ' - ' . $endDateFormatted);
} else {
$sheet->setCellValue('A' . $rowIndex, 'Periode: Semua Data');
}
$sheet->mergeCells('A' . $rowIndex . ':R' . $rowIndex);
$sheet->getStyle('A' . $rowIndex)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
// Set the date of export
$rowIndex++;
$sheet->setCellValue('A' . $rowIndex, 'Tanggal Export: ' . Carbon::now()->format('d F Y H:i:s'));
// Set the user who exported
$rowIndex++;
$userName = Auth::user() ? Auth::user()->name : 'System';
$sheet->setCellValue('A' . $rowIndex, 'Diexport oleh: ' . $userName);
// Add a blank line
$rowIndex++;
$sheet->setCellValue('A' . $rowIndex, '');
// Style the header row
$headerRange = 'A7:' . $sheet->getHighestColumn() . '7';
$sheet->getStyle($headerRange)->getFont()->setBold(true);
$sheet->getStyle($headerRange)->getFill()
->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
->getStartColor()->setARGB('FFCCCCCC');
// Auto-size columns
foreach (range('A', $sheet->getHighestColumn()) as $column) {
$sheet->getColumnDimension($column)->setAutoSize(true);
}
// Add borders to all cells with data
$dataRange = 'A7:' . $sheet->getHighestColumn() . $sheet->getHighestRow();
$sheet->getStyle($dataRange)->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
// Center align the header row
$sheet->getStyle($headerRange)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
// Set text wrap for header cells
$sheet->getStyle($headerRange)->getAlignment()->setWrapText(true);
},
];
}
}

View File

@@ -0,0 +1,232 @@
<?php
namespace Modules\Lpj\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithTitle;
use Maatwebsite\Excel\Concerns\WithCustomStartCell;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Events\AfterSheet;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\Branch;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
class LaporanUserLimitExport implements FromCollection, WithHeadings, WithMapping, WithTitle, WithCustomStartCell, WithEvents
{
protected $request;
public function __construct($request)
{
$this->request = $request;
}
public function collection()
{
$query = Permohonan::query();
$query = $query->where('status', 'done');
// Apply date range filter if provided
if ($this->request->has('start_date') || $this->request->has('end_date')) {
$startDate = $this->request->start_date ?? '1900-01-01';
$endDate = $this->request->end_date ?? now()->toDateString();
$query->where(function ($q) use ($startDate, $endDate) {
$q->whereHas('penilaian', function ($q2) use ($startDate, $endDate) {
$q2->whereBetween('tanggal_kunjungan', [$startDate, $endDate]);
});
// OR check if has penawaran with date in range
$q->orWhereHas('penawaran', function ($q3) use ($startDate, $endDate) {
$q3->whereBetween('tanggal_penilaian_sebelumnya', [$startDate, $endDate]);
});
});
}
// Apply branch filter if provided
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
$query->where('branch_id', $this->request->branch_id);
}
if ($this->request->has('penilai_id') && !empty($this->request->penilai_id)) {
$request = $this->request; // Store in a local variable
$query->whereHas('penilaian._user_penilai.userPenilaiTeam', function ($q) use ($request) {
$q->where('user_id', $request->penilai_id);
});
}
// Apply search filter if provided
if ($this->request->has('search') && !empty($this->request->search)) {
$search = $this->request->search;
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('debiture', DB::raw('LOWER(name)'), 'LIKE', '%' . strtolower($search) . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search . '%');
$q->orWhere('status', 'LIKE', '%' . $search . '%');
});
}
// Default ordering
$query->orderBy('nomor_registrasi', 'asc');
return $query->get();
}
protected $rowNumber = 0;
public function map($permohonan): array
{
$this->rowNumber++;
$npw = 0;
if (isset($permohonan->penilai->lpj)) {
$lpj = json_decode($permohonan->penilai->lpj, true);
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
}
return [
$this->rowNumber,
$permohonan->nomor_registrasi,
$permohonan->debiture->branch->name ?? '',
$permohonan->debiture->name ?? '',
$permohonan->user->name ?? $permohonan->mig_nama_ao ?? '',
$permohonan->tanggal_permohonan ?? '',
$permohonan->penilaian->_user_penilai->userPenilaiTeam->name ?? '',
$permohonan->penilaian && $permohonan->penilaian->tanggal_kunjungan
? formatTanggalIndonesia($permohonan->penilaian->tanggal_kunjungan)
: '',
formatRupiah($npw, 2),
];
}
public function headings(): array
{
return [
'No',
'Nomor Registrasi',
'Cabang',
'Nama Debitur',
'Pemohon',
'Tanggal Permohonan',
'Nama Penilai',
'Tanggal Laporan',
'Nilai Pasar Wajar',
];
}
/**
* @return string
*/
public function title(): string
{
return 'Laporan User Limit';
}
/**
* @return string
*/
public function startCell(): string
{
return 'A7';
}
/**
* @return array
*/
public function registerEvents(): array
{
return [
AfterSheet::class => function (AfterSheet $event) {
// Get the sheet
$sheet = $event->sheet->getDelegate();
// Set the title
$sheet->setCellValue('A1', 'LAPORAN PENILAIAN JAMINAN');
$sheet->getStyle('A1')->getFont()->setBold(true)->setSize(16);
// Merge cells for title
$sheet->mergeCells('A1:AH1');
$sheet->getStyle('A1')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
// Set the branch information if filtered
$branchInfo = '';
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
$branch = Branch::find($this->request->branch_id);
if ($branch) {
$branchInfo = 'Cabang: ' . $branch->name;
$sheet->setCellValue('A2', $branchInfo);
$sheet->mergeCells('A2:AH2');
$sheet->getStyle('A2')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
$sheet->getStyle('A2')->getFont()->setBold(true);
}
}
// Set the period
$startDate = $this->request->start_date ?? '';
$endDate = $this->request->end_date ?? '';
$rowIndex = $branchInfo ? 3 : 2;
if ($startDate && $endDate) {
$startDateFormatted = Carbon::parse($startDate)->format('d F Y');
$endDateFormatted = Carbon::parse($endDate)->format('d F Y');
$sheet->setCellValue('A' . $rowIndex, 'Periode: ' . $startDateFormatted . ' - ' . $endDateFormatted);
} else {
$sheet->setCellValue('A' . $rowIndex, 'Periode: Semua Data');
}
$sheet->mergeCells('A' . $rowIndex . ':AH' . $rowIndex);
$sheet->getStyle('A' . $rowIndex)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
// Set the date of export
$rowIndex++;
$sheet->setCellValue('A' . $rowIndex, 'Tanggal Export: ' . Carbon::now()->format('d F Y H:i:s'));
// Set the user who exported
$rowIndex++;
$userName = Auth::user() ? Auth::user()->name : 'System';
$sheet->setCellValue('A' . $rowIndex, 'Diexport oleh: ' . $userName);
// Add a blank line
$rowIndex++;
$sheet->setCellValue('A' . $rowIndex, '');
// Style the header row
$headerRange = 'A7:' . $sheet->getHighestColumn() . '7';
$sheet->getStyle($headerRange)->getFont()->setBold(true);
$sheet->getStyle($headerRange)->getFill()
->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
->getStartColor()->setARGB('FFCCCCCC');
// Auto-size columns - fixed to handle columns beyond Z
$highestColumn = $sheet->getHighestColumn();
$highestColumnIndex = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($highestColumn);
for ($i = 1; $i <= $highestColumnIndex; $i++) {
$currentColumn = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($i);
$sheet->getColumnDimension($currentColumn)->setAutoSize(true);
}
// Add borders to all cells with data
$dataRange = 'A7:' . $sheet->getHighestColumn() . $sheet->getHighestRow();
$sheet->getStyle($dataRange)->getBorders()->getAllBorders()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);
// Center align the header row
$sheet->getStyle($headerRange)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
// Set text wrap for header cells
$sheet->getStyle($headerRange)->getAlignment()->setWrapText(true);
},
];
}
}

View File

@@ -15,6 +15,8 @@
use Modules\Lpj\Models\Penilaian;
use Modules\Lpj\Models\TeamsUsers;
use Modules\Usermanagement\Models\User;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
function formatTanggalIndonesia($date, $time = false)
{
@@ -523,22 +525,167 @@
return '+' . $nomorBaru;
} else if (strpos($nomorHp, '0') === 0) {
$nomorBaru = substr($nomorHp, 0, 5) . "xxxxxx";
return $nomorBaru;
} else {
return "Nomor HP tidak valid";
$nomorBaru = substr($nomorHp, 0, 5) . "xxxxxx";
return $nomorBaru;
} else {
return "Nomor HP tidak valid";
}
}
function parsePembandingMigration($keterangan) {
$keterangan = preg_replace('/[-]{5,}/', '',$keterangan); // Hapus ------
$keterangan = preg_replace('/[.]{5,}/', '',$keterangan); // Hapus .....
$keterangan = preg_replace('/\s+/', ' ',$keterangan);
$keterangan = preg_replace('/\s*\n\s*/', "\n",$keterangan);
// Pecah teks per baris untuk diproses
$lines = explode("\n",$keterangan);
$cleaned = [];
foreach ($lines as $line) {
$line = trim($line);
if (!empty($line)) {
// Format angka dalam format Rp. 123.456.789
$line = preg_replace_callback('/Rp\.\s*([\d.,]+)/', function($matches) {
$angka = str_replace(['.', ','], '', $matches[1]);
return 'Rp. ' . number_format((int)$angka, 0, ',', '.');
}, $line);
// Jika ada tanda pagar (#), pisahkan menjadi baris baru
$line = str_replace('#', "\n#", $line);
$cleaned[] = $line;
}
}
function formatNotifikasi($notifikasi)
return implode("\n", $cleaned);
}
/**
* get full path to internal storage file or external storage file
*
* @param string $path
* @return string
*/
function getFilePath($path)
{
$data = json_decode(json_encode($notifikasi->data));
$message = $data->message;
$data = $data->data;
$notifikasi = [
'title' => 'Permohonan : ' . $data->nomor_registrasi,
'message' => $message,
];
return $notifikasi;
// define base path external storage (use .env) example: 'F:\path\to\storage' in windows
$externalBase = env('EXTERNAL_STORAGE_BASE_PATH', 'F:LPJ/lpj/LPJ Gambar/001/');
$segments = explode('/', $path);
if(strtoupper($segments[0]) === 'SURVEYOR'){
$year = $segments[1];
$month = ucfirst(strtolower($segments[2]));
$date = $segments[3];
$code = $segments[4];
$file = $segments[5] ?? '';
$extenalFullpath = $externalBase . $year . '/' . $month . '/' . $date . '/' . $code . '/' . $file;
if(File::exists($extenalFullpath)){
return $extenalFullpath;
}
}
// if not found in external storage, try to find in internal storage
if (Storage::exists($path)) {
return Storage::url('app/' . $path);
}
return $path;
}
function parseTimestamp(?string $timestamp): ?string
{
if (!$timestamp) {
return null;
}
// Trim whitespace dan normalize
$timestamp = trim($timestamp);
// Log untuk debugging
Log::info('Mencoba parsing timestamp: "' . $timestamp . '"');
// Parsing dengan DateTime native PHP untuk lebih robust
try {
// Pattern untuk format d/m/Y H:i:s
if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2}):(\d{1,2})$/', $timestamp, $matches)) {
$day = (int) $matches[1];
$month = (int) $matches[2];
$year = (int) $matches[3];
$hour = (int) $matches[4];
$minute = (int) $matches[5];
$second = (int) $matches[6];
// Validasi nilai
if ($day >= 1 && $day <= 31 && $month >= 1 && $month <= 12 && $year >= 1900 && $year <= 2100 &&
$hour >= 0 && $hour <= 23 && $minute >= 0 && $minute <= 59 && $second >= 0 && $second <= 59) {
// Buat DateTime object langsung
$dateTime = new \DateTime();
$dateTime->setDate($year, $month, $day);
$dateTime->setTime($hour, $minute, $second);
$result = $dateTime->format('Y-m-d H:i:s');
Log::info('Berhasil parsing dengan DateTime: ' . $timestamp . ' -> ' . $result);
return $result;
}
}
// Pattern untuk format d/m/Y tanpa waktu
if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/', $timestamp, $matches)) {
$day = (int) $matches[1];
$month = (int) $matches[2];
$year = (int) $matches[3];
// Validasi nilai
if ($day >= 1 && $day <= 31 && $month >= 1 && $month <= 12 && $year >= 1900 && $year <= 2100) {
// Buat DateTime object langsung
$dateTime = new \DateTime();
$dateTime->setDate($year, $month, $day);
$dateTime->setTime(0, 0, 0);
$result = $dateTime->format('Y-m-d H:i:s');
Log::info('Berhasil parsing tanpa waktu dengan DateTime: ' . $timestamp . ' -> ' . $result);
return $result;
}
}
} catch (\Exception $e) {
Log::error('Gagal parsing dengan DateTime: ' . $timestamp . '. Error: ' . $e->getMessage());
}
// Fallback ke format Carbon standar untuk format lainnya
$formats = [
'Y-m-d H:i:s',
'Y-m-d',
'd-m-Y H:i:s',
'd-m-Y',
'j-n-Y H:i:s',
'j-n-Y',
];
foreach ($formats as $format) {
try {
$carbon = \Carbon\Carbon::createFromFormat($format, $timestamp);
if ($carbon && $carbon->format($format) === $timestamp) {
// Jika format tidak mengandung waktu, set ke awal hari
if (!str_contains($format, 'H:i:s')) {
$carbon = $carbon->startOfDay();
}
Log::info('Berhasil parsing dengan format ' . $format . ': ' . $timestamp . ' -> ' . $carbon->toDateTimeString());
return $carbon->toDateTimeString();
}
} catch (\Exception $e) {
// Lanjut ke format berikutnya
continue;
}
}
Log::error('Tidak dapat memparsing timestamp dengan format apapun: "' . $timestamp . '"');
return null;
}

View File

@@ -306,6 +306,7 @@ class ActivityController extends Controller
$query = Permohonan::query();
// Apply search filter if provided
$query = $query->orderBy('nomor_registrasi', 'desc');
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
@@ -324,7 +325,9 @@ class ActivityController extends Controller
});
}
// Default sorting if no sort provided
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
@@ -333,20 +336,13 @@ class ActivityController extends Controller
$query->orderBy('nomor_registrasi', 'asc');
}
// Get total count of records before pagination
// Get the total count of records
$totalRecords = $query->count();
// Pagination
if ($request->has('page') && $request->has('size')) {
$page = (int) $request->get('page', 1);
$size = (int) $request->get('size', 10);
$offset = ($page - 1) * $size;
$query->skip($offset)->take($size);
$size = $request->get('size', 10);
if ($size == 0) {
$size = 10;
}
// Get filtered count
$filteredRecords = $query->count();
// Filter by region if user is senior-officer
if ($regionId) {
$query->whereHas('region', function ($q) use ($regionId) {
@@ -361,37 +357,36 @@ class ActivityController extends Controller
});
}
$totalRecords = $query->count();
// Pagination
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = (int) $request->get('page', 1);
$size = (int) $request->get('size', 10);
$offset = ($page - 1) * $size;
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get filtered count
// Get the filtered count of records
$filteredRecords = $query->count();
// Get data with necessary relationships
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian', 'dokumenjaminan','nilaiPlafond'])->get();
// Calculate total pages
$pageCount = ceil($totalRecords / $request->get('size', 10));
// Calculate the page count
$pageCount = ceil($totalRecords / $size);
// Calculate the current page number
$currentPage = max(1, $request->get('page', 1));
// Calculate total pages
$pageCount = ceil($totalRecords / $request->get('size', 10));
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $request->get('page', 1),
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);

View File

@@ -0,0 +1,152 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Modules\Lpj\Models\CategoryDaftarPustaka;
use Modules\Lpj\Http\Requests\CategoryDaftarPustakaRequest;
class CategoryDaftarPustakaController extends Controller
{
public $user;
/**
* Display a listing of the resource.
*/
public function index()
{
return view('lpj::category-daftar-pustaka.index');
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view('lpj::category-daftar-pustaka.create');
}
/**
* Store a newly created resource in storage.
*/
public function store(CategoryDaftarPustakaRequest $request)
{
$validated = $request->validated();
if ($validated) {
try {
CategoryDaftarPustaka::create($validated);
return redirect()->route('category-daftar-pustaka.index')->with('success', 'Data Berhasil Disimpan');
} catch (\Throwable $th) {
return redirect()->route('category-daftar-pustaka.index')->with('error', $th->getMessage());
}
}
}
/**
* Show the specified resource.
*/
public function show($id)
{
$category = CategoryDaftarPustaka::where('id', $id)->first();
return view('lpj::category-daftar-pustaka.show', compact('category'));
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
return view('lpj::category-daftar-pustaka.create', ['category' => CategoryDaftarPustaka::where('id', $id)->first()]);
}
/**
* Update the specified resource in storage.
*/
public function update(CategoryDaftarPustakaRequest $request, $id)
{
$validated = $request->validated();
if ($validated) {
try {
CategoryDaftarPustaka::where('id', $id)->update($validated);
return redirect()->route('category-daftar-pustaka.index')->with('success', 'Data Berhasil Disimpan');
} catch (\Throwable $th) {
return redirect()->route('category-daftar-pustaka.index')->with('error', $th->getMessage());
}
}
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
try {
CategoryDaftarPustaka::where('id', $id)->delete();
return response()->json(['success' => true, 'message' => 'Data Berhasil Dihapus']);
} catch (\Throwable $th) {
return response()->json(['success' => false, 'message' => $th->getMessage()]);
}
}
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('jenis_aset.view')) {
//abort(403, 'Sorry! You are not allowed to view users.');
}
// Retrieve data from the database
$query = CategoryDaftarPustaka::query();
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('code', 'LIKE', "%$search%");
$q->orWhere('name', 'LIKE', "%$search%");
});
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->get();
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = 0 + 1;
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
}

View File

@@ -0,0 +1,129 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Modules\Lpj\Models\CategoryDaftarPustaka;
use Modules\Lpj\Services\DaftarPustakaService;
use Modules\Lpj\Http\Requests\DaftarPustakaRequest;
class DaftarPustakaController extends Controller
{
private $daftarPustaka;
public function __construct()
{
$this->daftarPustaka = app(DaftarPustakaService::class);
}
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$categories = CategoryDaftarPustaka::all();
$daftar_pustaka = $this->daftarPustaka->getAllDaftarPustaka($request);
return view('lpj::daftar-pustaka.index', [
'categories' => $categories,
'daftar_pustaka' => $daftar_pustaka,
'page' => $daftar_pustaka->currentPage(),
'pageCount' => $daftar_pustaka->lastPage(),
'limit' => $daftar_pustaka->perPage(),
'total' => $daftar_pustaka->total(),
]);
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
$categories = CategoryDaftarPustaka::all();
// dd($categories);
return view('lpj::daftar-pustaka.create', compact('categories'));
}
/**
* Store a newly created resource in storage.
*/
public function store(DaftarPustakaRequest $request)
{
$validate = $request->validated();
// dd($validate);
$file = $request->file('attachment');
if ($validate) {
try {
// Save to database
$this->daftarPustaka->storeDaftarPustaka($validate, $file);
return redirect()
->route('daftar-pustaka.index')
->with('success', 'Daftar Pustaka created successfully');
} catch (Exception $e) {
return redirect()
->route('daftar-pustaka.create')
->with('error', 'Failed to create daftar pustaka');
}
}
}
/**
* Show the specified resource.
*/
public function show($id)
{
$daftarPustaka = $this->daftarPustaka->getDaftarPustakaById($id);
$categories = CategoryDaftarPustaka::all();
return view('lpj::daftar-pustaka.show', compact('daftarPustaka', 'categories'));
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
$daftarPustaka = $this->daftarPustaka->getDaftarPustakaById($id);
$categories = CategoryDaftarPustaka::all();
return view('lpj::daftar-pustaka.create', compact('daftarPustaka', 'categories'));
}
/**
* Update the specified resource in storage.
*/
public function update(DaftarPustakaRequest $request, $id)
{
$validate = $request->validated();
if ($validate) {
try {
// Save to database
$file = $request->file('attachment');
$this->daftarPustaka->updateDaftarPustaka($validate, $file, $id);
return redirect()
->route('daftar-pustaka.index')
->with('success', 'Daftar Pustaka updated successfully');
} catch (Exception $e) {
return redirect()
->route('daftar-pustaka.create')
->with('error', 'Failed to update daftar pustaka');
}
}
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
try {
$this->daftarPustaka->deleteDaftarPustaka($id);
return response()->json(['success' => true, 'message' => 'Daftar Pustaka deleted successfully']);
} catch (Exception $e) {
return response()->json(['success' => false, 'message' => 'Failed to delete daftar pustaka']);
}
}
}

View File

@@ -406,7 +406,9 @@
// Remove values from $legalitasJaminan that are in $currentLegalitasJaminan
$legalitasJaminan = array_diff($legalitasJaminan, $currentLegalitasJaminan->pluck('code')->toArray());
$legalitasJaminan = is_array($legalitasJaminan)
? array_diff($legalitasJaminan, $currentLegalitasJaminan->pluck('code')->toArray())
: [];
$legalitas = JenisLegalitasJaminan::whereIn('code', $legalitasJaminan)->get();
}

View File

@@ -75,11 +75,9 @@ class LaporanController extends Controller
}
// Retrieve data from the database
$query = Permohonan::query()->whereIn('status',['proses-laporan','done', 'paparan', 'proses-paparan'])->whereNotNull('approval_so_at')->whereNotNull('approval_eo_at')->where(function ($q) {
$q->whereIn('nilai_plafond_id', [1,4])
->whereNotNull('approval_dd_at')
->orWhereIn('nilai_plafond_id', [2,3]);
});
$query = Permohonan::query()
->whereIn('status',['proses-laporan','done', 'paparan', 'proses-paparan']);
$query = $query->orderBy('nomor_registrasi', 'desc');
// Apply search filter if provided

View File

@@ -1,211 +1,213 @@
<?php
namespace Modules\Lpj\Http\Controllers;
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Lpj\Exports\LaporanHasilPenilaianJaminanInternalExternalExport;
use Modules\Lpj\Models\Permohonan;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Lpj\Exports\LaporanHasilPenilaianJaminanInternalExternalExport;
use Modules\Lpj\Models\Permohonan;
use Illuminate\Support\Facades\DB;
class LaporanHasilPenilaianJaminanInternalExternalController extends Controller
class LaporanHasilPenilaianJaminanInternalExternalController extends Controller
{
public $user;
/**
* Display a listing of the resource.
*/
public function index()
{
public $user;
/**
* Display a listing of the resource.
*/
public function index()
{
return view('lpj::laporan_hasil_penilaian_jaminan_internal_external.index');
}
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('laporan-admin-kredit.view')) {
//abort(403, 'Sorry! You are not allowed to view laporan admin kredit.');
}
// Retrieve data from the database
$query = Permohonan::query();
$query = $query->where('status', 'done');
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = json_decode($request->get('search'));
if (isset($search->start_date) || isset($search->end_date)) {
$query->whereBetween('tanggal_permohonan', [
$search->start_date ?? '1900-01-01',
$search->end_date ?? now()->toDateString()
]);
}
// Filter by branch if provided
if (isset($search->branch_id) && !empty($search->branch_id)) {
$query->where('branch_id', $search->branch_id);
}
if (isset($search->penilai_id) && !empty($search->penilai_id)) {
$query->whereHas('penilaian._user_penilai.userPenilaiTeam', function ($q) use ($search) {
$q->where('user_id', $search->penilai_id);
});
}
if (isset($search->search)) {
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search->search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhere('status', 'LIKE', '%' . $search->search . '%');
});
}
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->with(['debiture.branch'])->get();
$data = $data->map(function ($permohonan) {
$luas_tanah = 0;
$luas_bangunan = 0;
$nilai_tanah = 0;
$nilai_bangunan = 0;
$npw = 0;
$nilai_liquidasi = 0;
if (isset($permohonan->penilai->lpj)) {
$lpj = json_decode($permohonan->penilai->lpj, true);
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
$luas_tanah = $lpj['luas_tanah'] ?? 0;
$luas_bangunan = $lpj['luas_bangunan'] ?? 0;
// Calculate nilai_tanah dynamically by looking for all keys that start with 'nilai_tanah_'
$nilai_tanah = str_replace('.', '', $lpj['nilai_tanah_2'] ?? 0);
$nilai_bangunan = str_replace('.', '', $lpj['nilai_bangunan_2'] ?? 0);
$nilai_liquidasi = str_replace('.', '', $lpj['likuidasi_nilai_2'] ?? 0);
}
return [
'id' => $permohonan->id,
'nomor_registrasi' => $permohonan->nomor_registrasi,
'jenis_penilaian' => $permohonan->jenisPenilaian?->name,
'tujuan_penilaian' => $permohonan->tujuanPenilaian?->name,
'jenis_fasilitas_kredit' => $permohonan->jenisFasilitasKredit?->name,
'branch' => $permohonan->debiture->branch?->name,
'pemohon' => $permohonan->creator?->name,
'cif' => $permohonan->debiture->cif,
'name' => $permohonan->debiture?->name,
'jenis_agunan' => $permohonan->documents?->pluck('jenisJaminan.name')
->unique()
->implode(', '),
'alamat_agunan' => $permohonan->documents?->map(function ($document) {
return formatAlamat($document);
})->unique()->implode(', '),
'bukti_kepemilikan' => (function() use ($permohonan) {
$legalitasItems = $permohonan->documents?->flatMap(function ($document) {
return $document->detail->map(function ($detail) {
// Jika tidak ada jenis legalitas jaminan, lewati
if (empty($detail->jenisLegalitasJaminan)) {
return null;
}
// Hanya tampilkan detail yang memiliki dokumen_jaminan
if (empty($detail->dokumen_jaminan)) {
return null;
}
// Tampilkan nama legalitas jaminan saja
return $detail->jenisLegalitasJaminan->name ?? '';
});
})->filter()->unique()->values()->toArray();
// Buat daftar bernomor
$result = '';
foreach ($legalitasItems as $index => $item) {
$result .= ($index + 1) . '. ' . $item . "\n";
}
return $result;
})(),
'nama_pemilik' => $permohonan->documents?->pluck('pemilik.name')
->unique()
->implode(', '),
'luas_tanah' => $luas_tanah . ' m²',
'nilai_tanah' => formatRupiah($nilai_tanah, 2),
'luas_bangunan' => $luas_bangunan . ' m²',
'nilai_bangunan' => formatRupiah($nilai_bangunan, 2),
'nilai_njop' => formatRupiah($permohonan->nilai_njop, 2),
'nilai_pasar_wajar' => formatRupiah($npw, 2),
'nilai_likuidasi' => formatRupiah($nilai_liquidasi, 2),
'tanggal_documen_diterima' => $permohonan->documents?->map(function ($document) {
return $document->created_at->format('d-m-Y');
}),
'tanggal_spk' => '',
'nomor_spk' => '',
'tanggal_rencana_kunjunagn' => '',
'tanggal_kunjungan' => '',
'taggal_delivered' => '',
'jangka_waktu_sla' => '',
'nama_penilai' => $permohonan->penilaian?->_user_penilai?->userPenilaiTeam?->name,
'nama_team_leader' => $permohonan->penilaian?->teams,
'saran' => '',
'catatan' => '',
'tanggal_permohonan' => $permohonan->tanggal_permohonan,
'tanggal_laporan' => $permohonan->approval_dd_at ?? $permohonan->approval_eo_at ?? '',
'tanggal_review' => $permohonan->penilaian?->tanggal_kunjungan ?? '',
];
});
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = $request->get('page') ?: 1;
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
public function export(Request $request)
{
return Excel::download(new LaporanHasilPenilaianJaminanInternalExternalExport($request), 'laporan_hasil_penilaian_jaminan_internal_external.xlsx');
}
return view('lpj::laporan_hasil_penilaian_jaminan_internal_external.index');
}
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('laporan-admin-kredit.view')) {
//abort(403, 'Sorry! You are not allowed to view laporan admin kredit.');
}
// Retrieve data from the database
$query = Permohonan::query();
$query = $query->where('status', 'done');
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = json_decode($request->get('search'));
if (isset($search->start_date) || isset($search->end_date)) {
$query->whereBetween('tanggal_permohonan', [
$search->start_date ?? '1900-01-01',
$search->end_date ?? now()->toDateString()
]);
}
// Filter by branch if provided
if (isset($search->branch_id) && !empty($search->branch_id)) {
$query->where('branch_id', $search->branch_id);
}
if (isset($search->penilai_id) && !empty($search->penilai_id)) {
$query->whereHas('penilaian._user_penilai.userPenilaiTeam', function ($q) use ($search) {
$q->where('user_id', $search->penilai_id);
});
}
if (isset($search->search)) {
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search->search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('debiture', DB::raw('LOWER(name)'), 'LIKE', '%' . strtolower($search->search) . '%');
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhere('status', 'LIKE', '%' . $search->search . '%');
});
}
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->with(['debiture.branch'])->get();
$data = $data->map(function ($permohonan) {
$luas_tanah = 0;
$luas_bangunan = 0;
$nilai_tanah = 0;
$nilai_bangunan = 0;
$npw = 0;
$nilai_liquidasi = 0;
if (isset($permohonan->penilai->lpj)) {
$lpj = json_decode($permohonan->penilai->lpj, true);
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
$luas_tanah = $lpj['luas_tanah'] ?? 0;
$luas_bangunan = $lpj['luas_bangunan'] ?? 0;
// Calculate nilai_tanah dynamically by looking for all keys that start with 'nilai_tanah_'
$nilai_tanah = str_replace('.', '', $lpj['nilai_tanah_2'] ?? 0);
$nilai_bangunan = str_replace('.', '', $lpj['nilai_bangunan_2'] ?? 0);
$nilai_liquidasi = str_replace('.', '', $lpj['likuidasi_nilai_2'] ?? 0);
}
return [
'id' => $permohonan->id,
'nomor_registrasi' => $permohonan->nomor_registrasi,
'jenis_penilaian' => $permohonan->jenisPenilaian?->name,
'tujuan_penilaian' => $permohonan->tujuanPenilaian?->name,
'jenis_fasilitas_kredit' => $permohonan->jenisFasilitasKredit?->name,
'branch' => $permohonan->debiture->branch?->name,
'pemohon' => $permohonan->creator?->name,
'cif' => $permohonan->debiture->cif,
'name' => $permohonan->debiture?->name,
'jenis_agunan' => $permohonan->documents?->pluck('jenisJaminan.name')
->unique()
->implode(', '),
'alamat_agunan' => $permohonan->documents?->map(function ($document) {
return formatAlamat($document);
})->unique()->implode(', '),
'bukti_kepemilikan' => (function () use ($permohonan) {
$legalitasItems = $permohonan->documents?->flatMap(function ($document) {
return $document->detail->map(function ($detail) {
// Jika tidak ada jenis legalitas jaminan, lewati
if (empty($detail->jenisLegalitasJaminan)) {
return null;
}
// Hanya tampilkan detail yang memiliki dokumen_jaminan
if (empty($detail->dokumen_jaminan)) {
return null;
}
// Tampilkan nama legalitas jaminan saja
return $detail->jenisLegalitasJaminan->name ?? '';
});
})->filter()->unique()->values()->toArray();
// Buat daftar bernomor
$result = '';
foreach ($legalitasItems as $index => $item) {
$result .= ($index + 1) . '. ' . $item . "\n";
}
return $result;
})(),
'nama_pemilik' => $permohonan->documents?->pluck('pemilik.name')
->unique()
->implode(', '),
'luas_tanah' => $luas_tanah . ' m²',
'nilai_tanah' => formatRupiah($nilai_tanah, 2),
'luas_bangunan' => $luas_bangunan . ' m²',
'nilai_bangunan' => formatRupiah($nilai_bangunan, 2),
'nilai_njop' => formatRupiah($permohonan->nilai_njop, 2),
'nilai_pasar_wajar' => formatRupiah($npw, 2),
'nilai_likuidasi' => formatRupiah($nilai_liquidasi, 2),
'tanggal_documen_diterima' => $permohonan->documents?->map(function ($document) {
return $document->created_at->format('d-m-Y');
}),
'tanggal_spk' => '',
'nomor_spk' => '',
'tanggal_rencana_kunjunagn' => '',
'tanggal_kunjungan' => '',
'taggal_delivered' => '',
'jangka_waktu_sla' => '',
'nama_penilai' => $permohonan->penilaian?->_user_penilai?->userPenilaiTeam?->name,
'nama_team_leader' => $permohonan->penilaian?->teams,
'saran' => '',
'catatan' => '',
'tanggal_permohonan' => $permohonan->tanggal_permohonan,
'tanggal_laporan' => $permohonan->approval_dd_at ?? $permohonan->approval_eo_at ?? '',
'tanggal_review' => $permohonan->penilaian?->tanggal_kunjungan ?? '',
];
});
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = $request->get('page') ?: 1;
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
public function export(Request $request)
{
return Excel::download(new LaporanHasilPenilaianJaminanInternalExternalExport($request), 'laporan_hasil_penilaian_jaminan_internal_external.xlsx');
}
}

View File

@@ -9,6 +9,10 @@ use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\StatusPermohonan;
use Modules\Lpj\Exports\LaporanPenilaiJaminanExport;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Lpj\Models\Branch;
use Modules\Lpj\Services\PreviewLaporanService;
use Modules\Lpj\Models\Inspeksi;
use Modules\Lpj\Models\Penilai;
class LaporanPenilaiJaminanController extends Controller
{
@@ -16,59 +20,31 @@ class LaporanPenilaiJaminanController extends Controller
/**
* Display a listing of the resource.
*/
protected $previewLaporanService;
public function __construct(PreviewLaporanService $previewLaporanService)
{
$this->previewLaporanService = $previewLaporanService;
}
public function index()
{
$status_permohonan = StatusPermohonan::all();
return view('lpj::laporan-penilai-jaminan.index', compact('status_permohonan'));
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view('lpj::create');
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Show the specified resource.
*/
public function show($id)
public function show($permohonan_id, $dokumen_id, $jaminan_id)
{
return view('lpj::laporan-penilai-jaminan.show');
$back = route('laporan-penilai-jaminan.index');
return $this->previewLaporanService->previewLaporan($permohonan_id, $dokumen_id, $jaminan_id, $back);
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
return view('lpj::edit');
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
//
}
public function dataForDatatables(Request $request)
{
@@ -93,91 +69,104 @@ class LaporanPenilaiJaminanController extends Controller
// dd($startDate);
// Retrieve data from the database
$query = Permohonan::query();
$query = $query->where('status', 'done')->orderBy('tanggal_permohonan', 'desc');
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$paramsSearch = json_decode($search);
$search = json_decode($request->get('search'));
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%')
->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%')
->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%')
->orWhereRelation('debiture', 'name', 'LIKE', '%' . $search . '%')
->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%')
->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
if (!empty($search->start_date) || !empty($search->end_date)) {
$startDate = $search->start_date ?? '1900-01-01';
$endDate = $search->end_date ?? now()->toDateString();
if (!empty($paramsSearch->tanggal_awal) && !empty($paramsSearch->tanggal_akhir)) {
$q->whereBetween('tanggal_permohonan', [$paramsSearch->tanggal_awal, $paramsSearch->tanggal_akhir]);
$query->where(function ($q) use ($startDate, $endDate) {
$q->whereHas('penilaian', function ($q2) use ($startDate, $endDate) {
$q2->whereBetween('tanggal_kunjungan', [$startDate, $endDate]);
});
// OR check if has penawaran with date in range
$q->orWhereHas('penawaran', function ($q3) use ($startDate, $endDate) {
$q3->whereBetween('tanggal_penilaian_sebelumnya', [$startDate, $endDate]);
});
});
}
if (isset($search->branch_id) && !empty($search->branch_id)) {
$query->where('branch_id', $search->branch_id);
}
if (isset($search->laporan) && is_array($search->laporan) && !empty($search->laporan)) {
foreach ($search->laporan as $type) {
$query->whereHas('penilai', function ($q) use ($type) {
$q->where('type_penilai', 'LIKE', '%' . $type . '%');
});
}
}
$statusKeywords = explode(',', $search);
foreach ($statusKeywords as $keyword) {
$q->orWhereRelation('penilai', 'type_penilai', 'LIKE', '%' . trim($keyword) . '%');
}
});
// dd($search->search);
if (isset($search->search)) {
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search->search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('debiture', DB::raw('LOWER(name)'), 'LIKE', '%' . strtolower($search->search) . '%');
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhere('status', 'LIKE', '%' . $search->search . '%');
});
}
}
$query->where('status', 'done');
// Default sorting if no sort provided
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
} else {
$query->orderBy('nomor_registrasi', 'asc');
}
// Get total count of records before pagination
// Get the total count of records
$totalRecords = $query->count();
// Pagination
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = (int) $request->get('page', 1);
$size = (int) $request->get('size', 10);
$offset = ($page - 1) * $size;
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get filtered count
// Get the filtered count of records
$filteredRecords = $query->count();
$totalRecords = $query->count();
// Pagination
if ($request->has('page') && $request->has('size')) {
$page = (int) $request->get('page', 1);
$size = (int) $request->get('size', 10);
$offset = ($page - 1) * $size;
$query->skip($offset)->take($size);
}
// Get filtered count
$filteredRecords = $query->count();
// Get data with necessary relationships
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian', 'dokumenjaminan.jenisJaminan','nilaiPlafond', 'penilai'])->get();
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian', 'dokumenjaminan.jenisJaminan','nilaiPlafond', 'penilai', 'dokumenjaminan.inspeksi'])->get();
// Calculate total pages
$pageCount = ceil($totalRecords / $request->get('size', 10));
// Calculate the page count
$pageCount = ceil($totalRecords / $size);
// Calculate the current page number
$currentPage = max(1, $request->get('page', 1));
// Calculate total pages
$pageCount = ceil($totalRecords / $request->get('size', 10));
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $request->get('page', 1),
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
@@ -185,15 +174,53 @@ class LaporanPenilaiJaminanController extends Controller
public function export(Request $request)
{
$tanggalAwal = $request->input('tanggal_awal');
$tanggalAkhir = $request->input('tanggal_akhir');
$status = $request->input('status');
$selectedIds = $request->input('selected_ids');
$startDate = $request->input('start_date');
$endDate = $request->input('end_date');
// Validate the date format
if (isset($startDate) && isset($endDate)) {
$startDate = date('Y-m-d', strtotime($startDate));
$endDate = date('Y-m-d', strtotime($endDate));
if ($startDate > $endDate) {
return redirect()->back()->with('error', 'Tanggal awal tidak boleh lebih kecil dari tanggal akhir');
}
}
// name the file
$filename = $this->createNameLaporan($request);
$filename = 'laporan_penilai_jaminan_' . date('YmdHis') . '.xlsx';
return Excel::download(
new LaporanPenilaiJaminanExport($tanggalAwal, $tanggalAkhir, $status, $selectedIds),
new LaporanPenilaiJaminanExport($request),
$filename
);
}
public function createNameLaporan($request)
{
$startDate = $request->start_date ?? null;
$endDate = $request->end_date ?? null;
$branchId = $request->branch_id ?? null;
$laporan = $request->laporan ?? null;
// Initialize filename parts
$parts = ['Laporan Penilai Jaminan'];
if ($startDate && $endDate) {
$parts[] = "{$startDate}_{$endDate}";
}
if ($laporan) {
$parts[] = $laporan;
}
if ($branchId) {
$parts[] = $this->getBranchId($branchId);
}
// Return concatenated filename with extension
return implode('_', $parts) . '.xlsx';
}
public function getBranchId($branchId)
{
$branchesName = Branch::find($branchId)->name ?? null;
return $branchesName;
}
}

View File

@@ -1,161 +1,180 @@
<?php
namespace Modules\Lpj\Http\Controllers;
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Modules\Lpj\Exports\LaporanPenilaianJaminanExport;
use Modules\Lpj\Models\Permohonan;
use Maatwebsite\Excel\Facades\Excel;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Modules\Lpj\Exports\LaporanPenilaianJaminanExport;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\Penilaian;
use Modules\Lpj\Models\PenawaranTender;
use Maatwebsite\Excel\Facades\Excel;
use Illuminate\Support\Facades\DB;
class LaporanPenilaianJaminanController extends Controller
class LaporanPenilaianJaminanController extends Controller
{
public $user;
/**
* Display a listing of the resource.
*/
public function index()
{
public $user;
/**
* Display a listing of the resource.
*/
public function index()
{
return view('lpj::laporan_penilaian_jaminan.index');
}
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('laporan-admin-kredit.view')) {
//abort(403, 'Sorry! You are not allowed to view laporan admin kredit.');
}
// Retrieve data from the database
$query = Permohonan::query();
$query = $query->where('status', 'done');
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = json_decode($request->get('search'));
if (isset($search->start_date) || isset($search->end_date)) {
$query->whereBetween('tanggal_permohonan', [
$search->start_date ?? '1900-01-01',
$search->end_date ?? now()->toDateString()
]);
}
// Filter by branch if provided
if (isset($search->branch_id) && !empty($search->branch_id)) {
$query->where('branch_id', $search->branch_id);
}
if (isset($search->penilai_id) && !empty($search->penilai_id)) {
$query->whereHas('penilaian._user_penilai.userPenilaiTeam', function($q) use ($search) {
$q->where('user_id', $search->penilai_id);
});
}
if (isset($search->search)) {
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search->search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhere('status', 'LIKE', '%' . $search->search . '%');
});
}
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->with(['debiture.branch'])->get();
$data = $data->map(function ($permohonan) {
$luas_tanah = 0;
$luas_bangunan = 0;
$nilai_tanah = 0;
$nilai_bangunan = 0;
$npw = 0;
$nilai_liquidasi = 0;
if (isset($permohonan->penilai->lpj)) {
$lpj = json_decode($permohonan->penilai->lpj, true);
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
$luas_tanah = $lpj['luas_tanah'] ?? 0;
$luas_bangunan = $lpj['luas_bangunan'] ?? 0;
// Calculate nilai_tanah dynamically by looking for all keys that start with 'nilai_tanah_'
$nilai_tanah = str_replace('.', '', $lpj['nilai_tanah_2'] ?? 0);
$nilai_bangunan = str_replace('.', '', $lpj['nilai_bangunan_2'] ?? 0);
$nilai_liquidasi = str_replace('.', '', $lpj['likuidasi_nilai_2'] ?? 0);
}
return [
'id' => $permohonan->id,
'nomor_registrasi' => $permohonan->nomor_registrasi,
'tanggal_permohonan' => $permohonan->tanggal_permohonan,
'branch' => $permohonan->debiture?->branch?->name,
'name' => $permohonan->debiture?->name,
'pemohon' => $permohonan->creator?->name,
'tujuan_penilaian' => $permohonan->tujuanPenilaian?->name,
'jenis_agunan' => $permohonan->documents?->pluck('jenisJaminan.name')->unique()->implode(', '),
'alamat_agunan' => $permohonan->documents?->map(function ($document) {
return formatAlamat($document);
})->unique()->implode(', '),
'luas_tanah' => $luas_tanah . ' m²',
'nilai_tanah' => formatRupiah($nilai_tanah,2),
'luas_bangunan' => $luas_bangunan . ' m²',
'nilai_bangunan' => formatRupiah($nilai_bangunan,2),
'tanggal_laporan' => $permohonan->approval_dd_at ?? $permohonan->approval_eo_at ?? '',
'tanggal_review' => $permohonan->penilaian?->tanggal_kunjungan ?? '',
'nilai_pasar_wajar' => formatRupiah($npw,2),
'nilai_likuidasi' => formatRupiah($nilai_liquidasi,2),
'nama_penilai' => $permohonan->penilaian?->_user_penilai?->userPenilaiTeam?->name,
];
});
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = $request->get('page', 1);
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
public function export(Request $request)
{
return Excel::download(new LaporanPenilaianJaminanExport($request), 'laporan_penilaian_jaminan.xlsx');
}
return view('lpj::laporan_penilaian_jaminan.index');
}
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('laporan-admin-kredit.view')) {
//abort(403, 'Sorry! You are not allowed to view laporan admin kredit.');
}
// Retrieve data from the database
$query = Permohonan::query();
$query = $query->where('status', 'done');
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = json_decode($request->get('search'));
if (!empty($search->start_date) || !empty($search->end_date)) {
$startDate = $search->start_date ?? '1900-01-01';
$endDate = $search->end_date ?? now()->toDateString();
$query->where(function ($q) use ($startDate, $endDate) {
$q->whereHas('penilaian', function ($q2) use ($startDate, $endDate) {
$q2->whereBetween('tanggal_kunjungan', [$startDate, $endDate]);
})
->orWhereHas('penawaran', function ($q3) use ($startDate, $endDate) {
$q3->whereBetween('tanggal_penilaian_sebelumnya', [$startDate, $endDate]);
});
});
}
// Filter by branch if provided
if (isset($search->branch_id) && !empty($search->branch_id)) {
$query->where('branch_id', $search->branch_id);
}
if (isset($search->penilai_id) && !empty($search->penilai_id)) {
$query->whereHas('penilaian._user_penilai.userPenilaiTeam', function ($q) use ($search) {
$q->where('user_id', $search->penilai_id);
});
}
if (isset($search->search)) {
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search->search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('debiture', DB::raw('LOWER(name)'), 'LIKE', '%' . strtolower($search->search) . '%');
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhere('status', 'LIKE', '%' . $search->search . '%');
});
}
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->with(['debiture.branch'])->get();
$data = $data->map(function ($permohonan) {
$luas_tanah = 0;
$luas_bangunan = 0;
$nilai_tanah = 0;
$nilai_bangunan = 0;
$npw = 0;
$nilai_liquidasi = 0;
if (isset($permohonan->penilai->lpj)) {
$lpj = json_decode($permohonan->penilai->lpj, true);
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
$luas_tanah = $lpj['luas_tanah'] ?? 0;
$luas_bangunan = $lpj['luas_bangunan'] ?? 0;
// Calculate nilai_tanah dynamically by looking for all keys that start with 'nilai_tanah_'
$nilai_tanah = str_replace('.', '', $lpj['nilai_tanah_2'] ?? 0);
$nilai_bangunan = str_replace('.', '', $lpj['nilai_bangunan_2'] ?? 0);
$nilai_liquidasi = str_replace('.', '', $lpj['likuidasi_nilai_2'] ?? 0);
}
return [
'id' => $permohonan->id,
'nomor_registrasi' => $permohonan->nomor_registrasi,
'tanggal_permohonan' => $permohonan->tanggal_permohonan,
'branch' => $permohonan->debiture?->branch?->name,
'name' => $permohonan->debiture?->name,
'pemohon' => $permohonan->creator?->name,
'tujuan_penilaian' => $permohonan->tujuanPenilaian?->name,
'jenis_agunan' => $permohonan->documents?->pluck('jenisJaminan.name')->unique()->implode(', '),
'alamat_agunan' => $permohonan->documents?->map(function ($document) {
return formatAlamat($document);
})->unique()->implode(', '),
'luas_tanah' => $luas_tanah . ' m²',
'nilai_tanah' => formatRupiah($nilai_tanah, 2),
'luas_bangunan' => $luas_bangunan . ' m²',
'nilai_bangunan' => formatRupiah($nilai_bangunan, 2),
'tanggal_laporan' => $permohonan->approval_dd_at ?? $permohonan->approval_eo_at ?? '',
'tanggal_review' => $permohonan->penilaian?->tanggal_kunjungan ?? '',
'nilai_pasar_wajar' => formatRupiah($npw, 2),
'nilai_likuidasi' => formatRupiah($nilai_liquidasi, 2),
'nama_penilai' => $permohonan->penilaian?->_user_penilai?->userPenilaiTeam?->name,
];
});
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = $request->get('page', 1);
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
public function export(Request $request)
{
$startDate = $request->start_date;
$endDate = $request->end_date;
// name of the file
$fileName = 'laporan_penilaian_jaminan_' . $startDate . '_' . $endDate . '.xlsx';
return Excel::download(new LaporanPenilaianJaminanExport($request), $fileName);
}
}

View File

@@ -4,6 +4,8 @@ namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Lpj\Exports\LaporanUserLimitExport;
use Modules\Lpj\Services\LaporanUserService;
class LaporanUserController extends Controller
@@ -38,4 +40,12 @@ class LaporanUserController extends Controller
return $this->laporanUserService->dataForDatatables($request);
}
public function export(Request $request)
{
$startDate = $request->start_date;
$endDate = $request->end_date;
// name of the file
$fileName = 'laporan_user_limit' . $startDate . '_' . $endDate . '.xlsx';
return Excel::download(new LaporanUserLimitExport($request), $fileName);
}
}

View File

@@ -26,18 +26,21 @@ use Modules\Lpj\Http\Requests\FormSurveyorRequest;
use Modules\Lpj\Models\Authorization;
use Modules\Lpj\Models\Debiture;
use Modules\Lpj\Services\SaveFormInspesksiService;
use Modules\Lpj\Services\PreviewLaporanService;
class PenilaiController extends Controller
{
public $user;
protected $surveyorController;
protected $inspeksiService;
protected $previewLaporanService;
public function __construct(SurveyorController $surveyorController, SaveFormInspesksiService $inspeksiService)
public function __construct(SurveyorController $surveyorController, SaveFormInspesksiService $inspeksiService, PreviewLaporanService $previewLaporanService)
{
$this->surveyorController = $surveyorController;
$this->inspeksiService = $inspeksiService;
$this->previewLaporanService = $previewLaporanService;
}
/**
@@ -548,13 +551,7 @@ class PenilaiController extends Controller
return view('lpj::penilai.components.call-report', compact('permohonan', 'basicData', 'nomorLaporan', 'forminspeksi', 'cities', 'districts', 'villages', 'cekAlamat', 'callReport'));
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
//
}
public function dataForDatatables(Request $request)
{
@@ -700,15 +697,17 @@ class PenilaiController extends Controller
'lokasi_lengkap' => $data->lokasi_lengkap ?? '',
];
// Extract data pembanding
if (isset($dataPembanding['data_pembanding'])) {
foreach ($dataPembanding['data_pembanding'] as $index => $pembanding) {
if ($index == 0) {
$exportData['pembanding1'] = $pembanding;
} elseif ($index == 1) {
$exportData['pembanding2'] = $pembanding;
} elseif ($index == 2) {
$exportData['pembanding3'] = $pembanding;
if(isset($dataPembanding)){
// Extract data pembanding
if (isset($dataPembanding['data_pembanding'])) {
foreach ($dataPembanding['data_pembanding'] as $index => $pembanding) {
if ($index == 0) {
$exportData['pembanding1'] = $pembanding;
} elseif ($index == 1) {
$exportData['pembanding2'] = $pembanding;
} elseif ($index == 2) {
$exportData['pembanding3'] = $pembanding;
}
}
}
}
@@ -1277,132 +1276,13 @@ class PenilaiController extends Controller
public function print_out(Request $request)
public function print_out_laporan($permohonan_id, $document_id, $jaminan_id)
{
$documentId = $request->query('documentId');
$jaminanId = $request->query('jaminanId');
$permohonanId = $request->query('permohonanId');
$statusLpj = $request->query('statusLpj');
$tipeLaporan = $request->query('type');
$permohonan = $this->surveyorController->getPermohonanJaminanId(
$permohonanId,
$documentId,
$jaminanId
);
$basicData = $this->surveyorController->getCommonData();
$inspeksi = Inspeksi::where('permohonan_id', $permohonanId)->where('dokument_id', $documentId)->first();
$lpj = Penilai::where('permohonan_id', $permohonanId)->where('dokument_id', $documentId)->first();
$nomorLaporan = getNomorLaporan($permohonanId, $documentId);
$tanggalLaporan = $lpj->created_at ?? null;
$forminspeksi = null;
$lpjData = null;
$formFoto = null;
if ($inspeksi) {
$forminspeksi = json_decode($inspeksi->data_form, true);
$formFoto = json_decode($inspeksi->foto_form, true);
// $denahForm = json_decode($data->denah_form, true);
$dataPembanding = json_decode($inspeksi->data_pembanding, true);
}
if ($lpj) {
$lpjData = json_decode($lpj->lpj, true);
$memo = json_decode($lpj->memo, true);
$resumeData = json_decode($lpj->resume, true);
$rap = json_decode($lpj->rap, true);
$report = json_decode($lpj->call_report, true);
}
$inputAddress = $forminspeksi['asset']['alamat']['sesuai'] ?? $forminspeksi['asset']['alamat']['tidak sesuai'] ?? [];
$alamat = [
'address' => $inputAddress['address'] ?? null,
'village_code' => getWilayahName($inputAddress['village_code'] ?? null, 'village'),
'district_code' => getWilayahName($inputAddress['district_code'] ?? null, 'district'),
'city_code' => getWilayahName($inputAddress['city_code'] ?? null, 'city'),
'province_code' => getWilayahName($inputAddress['province_code'] ?? null, 'province')
];
$viewLaporan = $this->getViewLaporan($tipeLaporan);
try {
if ($statusLpj) {
// $pdf = view('lpj::' . $viewLaporan, compact(
$pdf = PDF::loadView('lpj::' . $viewLaporan, compact(
'permohonan',
'forminspeksi',
'lpjData',
'formFoto',
'basicData',
'inspeksi',
'lpj',
'statusLpj',
'alamat',
'dataPembanding',
'nomorLaporan',
'memo',
'resumeData',
'tanggalLaporan',
'rap',
'report'
));
// return $pdf;
$cleanNomorLaporan = str_replace(['/', '\\'], '-', $nomorLaporan);
$pdf->setPaper('A4', 'portrait');
$pdf->set_option('isHtml5ParserEnabled', true);
$pdf->set_option('isPhpEnabled', true);
return response($pdf->output(), 200)
->header('Content-Type', 'application/pdf')
->header('Content-Disposition', 'inline; filename="Laporan_' . $tipeLaporan . '_' . $permohonan->debiture->name . '_' . $cleanNomorLaporan . '.pdf"');
// return $pdf->stream();
} else {
// $pdf = view('lpj::' . $viewLaporan, compact(
$pdf = PDF::loadView('lpj::' . $viewLaporan, compact(
'permohonan',
'forminspeksi',
'lpjData',
'formFoto',
'basicData',
'inspeksi',
'lpj',
'statusLpj',
'alamat',
'dataPembanding',
'nomorLaporan',
'memo',
'resumeData',
'tanggalLaporan',
'rap',
'report'
));
// return $pdf;
$cleanNomorLaporan = str_replace(['/', '\\'], '-', $nomorLaporan);
$pdf->setPaper('A4', 'portrait');
$pdf->set_option('isHtml5ParserEnabled', true);
$pdf->set_option('isPhpEnabled', true);
return $pdf->download('Laporan_' . $tipeLaporan . '_' . $permohonan->debiture->name . '_' . $cleanNomorLaporan . '_data.pdf');
}
} catch (\Exception $e) {
Log::error('PDF generation failed: ' . $e->getMessage());
return response()->json(['error' => 'Failed to generate PDF. Please check the log for details.' . $e->getMessage()], 500);
}
// jika tidak ada id kembalikan ke halaman sebelumnya
if (!$permohonan_id || !$document_id || !$jaminan_id) {
return redirect()->back()->with('error', 'Laporan tidak valid');
}
private function getViewLaporan($tipe)
{
$viewMap = [
'sederhana' => 'penilai.components.print-out-sederhana',
'standar' => 'penilai.components.print-out-standar',
'resume' => 'penilai.components.print-resume',
'memo' => 'penilai.components.print-memo',
'rap' => 'penilai.components.print-out-rap',
'call-report' => 'penilai.components.print-out-call-report'
];
return $viewMap[$tipe] ?? 'penilai.components.print-resume';
return $this->previewLaporanService->printOutLaporan($permohonan_id, $document_id, $jaminan_id);
}
@@ -1429,46 +1309,7 @@ class PenilaiController extends Controller
];
}
public function checkPrintOutLaporan(Request $request)
{
$permohonanId = $request->query('permohonanId');
$documentId = $request->query('documentId');
// Ambil data berdasarkan ID
$statusLpj = Penilai::where('permohonan_id', $permohonanId)
->where('dokument_id', $documentId)
->first();
// Jika data tidak ditemukan, kembalikan status null
if (!$statusLpj) {
return response()->json(['status' => null]);
}
// Tentukan tipe berdasarkan kondisi
$type = $statusLpj->type_penilai ?? null;
if ($type === 'memo') {
return $this->checkDataMemo($type, $statusLpj);
}
if ($type === 'resume') {
return $this->checkDataResume($type, $statusLpj);
}
if ($type === 'standar' || $type === 'sederhana') {
return $this->checkDataLpj($type, $statusLpj);
}
if ($type === 'rap') {
return $this->checkDataRap($type, $statusLpj);
}
// Kembalikan respons dengan tipe yang sesuai
return response()->json(['status' => $type]);
}
public function generateNoLaporan($permohonan, $documentId, $type)
@@ -1508,239 +1349,6 @@ class PenilaiController extends Controller
}
public function checkDataMemo($type, $statusLpj)
{
// Ambil data JSON dari statusLpj
$data = json_decode($statusLpj->memo, true) ?? [];
$validationRules = [
'memo' => [
'kepada',
'dari',
'nomor_memo',
'tanggal',
'perihal',
'jenis_asset_tidak_sesuai',
'lokasi.lokasi',
'lokasi.province_code',
'lokasi.city_code',
'lokasi.district_code',
'lokasi.village_code',
'lokasi.penilai',
'terlampir',
'hasil_survey',
'kesimpulan_saran',
],
];
// Validasi data JSON
if (isset($validationRules[$type])) {
$missingFields = [];
foreach ($validationRules[$type] as $field) {
$keys = explode('.', $field);
$value = $data;
foreach ($keys as $key) {
if (!isset($value[$key])) {
$missingFields[] = $field;
break;
}
$value = $value[$key];
}
}
// Jika ada field yang kosong, kembalikan error
if (!empty($missingFields)) {
return response()->json([
'status' => null,
'message' => "Silahkan lengkapi data memo terlebih dahulu.",
'missing_fields' => $missingFields,
], 400);
}
}
// Jika data valid
return response()->json([
'status' => $type,
'message' => "Data memo valid.",
]);
}
public function checkDataResume($type, $statusLpj)
{
// Ambil data JSON dari statusLpj
$data = json_decode($statusLpj->resume, true) ?? [];
$validationRules = [
'resume' => [
'fisik'
],
];
// Validasi data JSON
if (isset($validationRules[$type])) {
$missingFields = [];
foreach ($validationRules[$type] as $field) {
$keys = explode('.', $field);
$value = $data;
foreach ($keys as $key) {
if (!isset($value[$key])) {
$missingFields[] = $field;
break;
}
$value = $value[$key];
}
// Validasi khusus untuk array fisik dan sesuai_imb
if ($field === 'fisik' || $field === 'sesuai_imb') {
if (empty($value) || !is_array($value)) {
$missingFields[] = $field;
continue;
}
// Validasi struktur data di dalam array
foreach ($value as $item) {
$requiredKeys = ['sertifikat', 'luas_tanah', 'nilai'];
foreach ($requiredKeys as $requiredKey) {
if (!isset($item[$requiredKey])) {
$missingFields[] = $field . '.' . $requiredKey;
}
}
}
}
}
// Jika ada field yang kosong, kembalikan error
if (!empty($missingFields)) {
return response()->json([
'status' => null,
'message' => "Silahkan lengkapi data resume terlebih dahulu.",
'missing_fields' => $missingFields,
], 400);
}
}
// Jika data valid
return response()->json([
'status' => $type,
'message' => "Data resume valid.",
]);
}
public function checkDataLpj($type, $statusLpj)
{
// Ambil data JSON dari statusLpj
$data = json_decode($statusLpj->lpj, true) ?? [];
$validationRules = [
'lpj' => [
'luas_tanah',
'nilai_tanah_1',
'nilai_tanah_2',
'luas_bangunan',
'nilai_bangunan_1',
'nilai_bangunan_2',
'total_nilai_pasar_wajar',
'likuidasi',
'likuidasi_nilai_1',
'likuidasi_nilai_2',
'asuransi_luas_bangunan',
'asuransi_nilai_1',
'asuransi_nilai_2',
'npw_tambahan'
],
];
// Validasi data JSON
if (isset($validationRules[$type])) {
$missingFields = [];
foreach ($validationRules[$type] as $field) {
// Penanganan khusus untuk field yang boleh null
if (in_array($field, ['sarana_pelengkap_penilai', 'nilai_sarana_pelengkap_1', 'nilai_sarana_pelengkap_2'])) {
continue;
}
if (!isset($data[$field])) {
$missingFields[] = $field;
continue;
}
// Validasi khusus untuk npw_tambahan
if ($field === 'npw_tambahan' && is_array($data[$field])) {
foreach ($data[$field] as $index => $item) {
$requiredKeys = ['name', 'luas', 'nilai_1', 'nilai_2'];
foreach ($requiredKeys as $key) {
if (!isset($item[$key])) {
$missingFields[] = "npw_tambahan[$index].$key";
}
}
}
}
}
// Jika ada field yang kosong, kembalikan error
if (!empty($missingFields)) {
return response()->json([
'status' => null,
'message' => "Silahkan lengkapi data LPJ terlebih dahulu.",
'missing_fields' => $missingFields,
], 400);
}
}
// Jika data valid
return response()->json([
'status' => $type,
'message' => "Data LPJ valid.",
]);
}
public function checkDataRap($type, $statusLpj)
{
// Ambil data JSON dari statusLpj
$data = json_decode($statusLpj->rap, true) ?? [];
$requiredFields = [
'dari',
'kepada',
'perihal',
'tanggal',
'nomor_rap'
];
// Cek apakah ada field yang kosong
$missingFields = [];
foreach ($requiredFields as $field) {
if (!isset($data[$field]) || empty($data[$field])) {
$missingFields[] = $field;
}
}
// Jika ada field yang kosong, kembalikan error
if (!empty($missingFields)) {
return response()->json([
'status' => null,
'message' => "Silahkan lengkapi data RAP terlebih dahulu.",
'missing_fields' => $missingFields
], 400);
}
// Jika semua data terisi
return response()->json([
'status' => $type,
'message' => "Data RAP valid."
]);
}
public function revisiSurveyor(Request $request, $id)
{
$permohonan = Permohonan::findOrFail($id);
@@ -1771,4 +1379,24 @@ class PenilaiController extends Controller
'message' => 'Berhasil Revisi Ke surveyor',
], 200);
}
public function showLaporanInspeksi(
$permohonan_id,
$dokumen_id,
$jaminan_id,
Request $request)
{
if ($request->type == 'penilai') {
$back = route('penilai.show', $permohonan_id);
}else{
$back = route('surveyor.show', $permohonan_id);
}
return $this->previewLaporanService->previewLaporan($permohonan_id, $dokumen_id, $jaminan_id, $back);
}
public function showInspectionReportReview($permohonan_id, $dokumen_id, $jaminan_id)
{
}
}

View File

@@ -2718,7 +2718,7 @@ class SurveyorController extends Controller
$fileName = 'inspeksi-' . $namaDebiture . '-data.pdf';
$pdf->set_option('isHtml5ParserEnabled', true);
$pdf->set_option('isPhpEnabled', true);
return $pdf->stream($fileName);
return $pdf->download($fileName);
}
public function approveReschedule(Request $request, $id)

View File

@@ -0,0 +1,33 @@
<?php
namespace Modules\Lpj\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CategoryDaftarPustakaRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*/
public function rules(): array
{
$rules = [
'name' => 'required|max:255',
];
if ($this->method() == 'PUT') {
$rules['code'] = 'required|max:50|unique:category_daftar_pustaka,code,' . $this->id;
} else {
$rules['code'] = 'required|max:50|unique:category_daftar_pustaka,code';
}
return $rules;
}
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace Modules\Lpj\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class DaftarPustakaRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*/
public function rules(): array
{
$rules = [
'judul' => 'required|max:255',
'category_id' => 'required',
'deskripsi' => 'nullable',
];
if ($this->method() == 'PUT') {
$rules['attachment'] = 'nullable|mimes:pdf,jpg,jpeg,png,gif';
} else {
$rules['attachment'] = 'required|mimes:pdf,jpg,jpeg,png,gif';
}
return $rules;
}
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Modules\Lpj\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
// use Modules\Lpj\Database\Factories\CategoryDaftarPustakaFactory;
class CategoryDaftarPustaka extends Model
{
use HasFactory;
protected $table = 'category_daftar_pustaka';
/**
* The attributes that are mass assignable.
*/
protected $fillable = [
'id',
'name',
'code',
];
public function daftarPustaka(){
return $this->hasMany(DaftarPustaka::class);
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace Modules\Lpj\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
// use Modules\Lpj\Database\Factories\DaftarPustakaFactory;
class DaftarPustaka extends Model
{
use HasFactory;
protected $table = 'daftar_pustaka';
/**
* The attributes that are mass assignable.
*/
protected $fillable = [
'id',
'category_id',
'judul',
'attachment',
'deskripsi',
];
public function category(){
return $this->belongsTo(CategoryDaftarPustaka::class);
}
}

View File

@@ -14,7 +14,7 @@ class Inspeksi extends Base
/**
* The attributes that are mass assignable.
*/
protected $fillable = ['data_form', 'foto_form', 'denah_form','permohonan_id', 'name', 'status', 'authorized_status', 'authorized_at', 'authorized_by', 'created_by', 'updated_by', 'deleted_by','dokument_id','data_pembanding'];
protected $fillable = ['data_form', 'foto_form', 'denah_form','permohonan_id', 'name', 'status', 'authorized_status', 'authorized_at', 'authorized_by', 'created_by', 'updated_by', 'deleted_by','dokument_id','data_pembanding','mig_detail_data_jaminan'];
public function permohonan()
{

View File

@@ -0,0 +1,90 @@
<?php
namespace Modules\Lpj\Services;
use Modules\Lpj\Models\DaftarPustaka;
class DaftarPustakaService
{
public function storeDaftarPustaka(array $data, $file)
{
if ($file) {
$data['attachment'] = $this->handleUpload($file);
}
return DaftarPustaka::create($data);
}
public function updateDaftarPustaka($data, $file, $id)
{
// Ambil data inputan yang diperlukan saja
$daftarPustaka = DaftarPustaka::findOrFail($id);
// Jika ada file baru yang diupload
if ($file) {
// (Opsional) Hapus file lama
if ($daftarPustaka->attachment && file_exists(public_path($daftarPustaka->attachment))) {
unlink(public_path($daftarPustaka->attachment));
}
// Upload file baru
$data['attachment'] = $this->handleUpload($file);
}
// Update data
$daftarPustaka->update($data);
return $daftarPustaka;
}
public function deleteDaftarPustaka($id)
{
return DaftarPustaka::where('id', $id)->delete();
}
public function getDaftarPustakaById($id)
{
return DaftarPustaka::where('id', $id)->first();
}
// get all with pagination
public function getAllDaftarPustaka($request)
{
$query = DaftarPustaka::query();
// Filter pencarian
if (!empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->orWhere('judul', 'LIKE', "%$search%");
});
}
// Filter kategori
if (!empty($request->get('category'))) {
$category = explode(',', $request->input('category'));
$query->whereIn('category_id', $category);
}
// Default pagination
$page = (int) $request->get('page', 1);
$size = (int) $request->get('size', 10);
return $query->paginate($size, ['*'], 'page', $page);
}
private function handleUpload($file)
{
$today = now();
$folderPath = 'daftar_pustaka/' . $today->format('Y/m/d');
$fileName = $file->getClientOriginalName();
$filePath = $file->storeAs($folderPath, $fileName, 'public');
return $filePath;
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Modules\Lpj\Services;
use Illuminate\Http\Request;
use Modules\Lpj\Models\Permohonan;
class LaporanBiayaService
{
public function buildDataTableQuery(array $data){
$query = Permohonan::with([
'noc'
]);
if($data['search']){
}
return $query;
}
}

View File

@@ -5,124 +5,119 @@ namespace Modules\Lpj\Services;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\Penilaian;
use Illuminate\Http\Request;
use Carbon\Carbon;
class LaporanSLAPenilaiService
{
public function dataForDatatables(Request $request)
{
// Retrieve data from the database
$query = Permohonan::query();
$query = $query->where('status', 'done');
{
// Retrieve data from the database
$query = Permohonan::query();
$query = $query->where('status', 'done');
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = json_decode($request->get('search'));
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = json_decode($request->get('search'));
if (isset($search->start_date) || isset($search->end_date)) {
$query->whereBetween('tanggal_permohonan', [
$search->start_date ?? '1900-01-01',
$search->end_date ?? now()->toDateString()
]);
}
if (isset($search->penilai_id) && !empty($search->penilai_id)) {
$query->whereHas('penilaian._user_penilai.userPenilaiTeam', function($q) use ($search) {
$q->where('user_id', $search->penilai_id);
});
}
if (isset($search->search)) {
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search->search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhere('status', 'LIKE', '%' . $search->search . '%');
});
}
if (isset($search->start_date) || isset($search->end_date)) {
$query->whereBetween('tanggal_permohonan', [
$search->start_date ?? '1900-01-01',
$search->end_date ?? now()->toDateString()
]);
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
if (isset($search->penilai_id) && !empty($search->penilai_id)) {
$query->whereHas('penilaian._user_penilai.userPenilaiTeam', function ($q) use ($search) {
$q->where('user_id', $search->penilai_id);
});
}
// Get the total count of records
$totalRecords = $query->count();
if (isset($search->search)) {
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search->search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhere('status', 'LIKE', '%' . $search->search . '%');
});
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->with(['debiture.branch'])->get();
$data = $data->map(function ($permohonan) {
$luas_tanah = 0;
$luas_bangunan = 0;
$nilai_tanah = 0;
$nilai_bangunan = 0;
$npw = 0;
$nilai_liquidasi = 0;
if (isset($permohonan->penilai->lpj)) {
$lpj = json_decode($permohonan->penilai->lpj, true);
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
$luas_tanah = $lpj['luas_tanah'] ?? 0;
$luas_bangunan = $lpj['luas_bangunan'] ?? 0;
// Calculate nilai_tanah dynamically by looking for all keys that start with 'nilai_tanah_'
$nilai_tanah = str_replace('.', '', $lpj['nilai_tanah_2'] ?? 0);
$nilai_bangunan = str_replace('.', '', $lpj['nilai_bangunan_2'] ?? 0);
$nilai_liquidasi = str_replace('.', '', $lpj['likuidasi_nilai_2'] ?? 0);
}
return [
'id' => $permohonan->id,
'nomor_registrasi' => $permohonan->nomor_registrasi,
'tanggal_permohonan' => $permohonan->tanggal_permohonan,
'branch' => $permohonan->debiture?->branch?->name,
'name' => $permohonan->debiture?->name,
'pemohon' => $permohonan->creator?->name,
'tujuan_penilaian' => $permohonan->tujuanPenilaian?->name,
'jenis_agunan' => $permohonan->documents?->pluck('jenisJaminan.name')->unique()->implode(', '),
'tanggal_laporan' => $permohonan->approval_dd_at ?? $permohonan->approval_eo_at ?? '',
'tanggal_review' => $permohonan->penilaian?->tanggal_kunjungan ?? '',
'nama_penilai' => $permohonan->penilaian?->_user_penilai?->userPenilaiTeam?->name,
];
});
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = $request->get('page', 1);
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->with(['documents','debiture.branch'])->get();
$data = $data->map(function ($permohonan) {
$tgl_kunjungan = $permohonan->penilaian?->tanggal_kunjungan;
$tgl_otorisator = $permohonan->approval_dd_at ?? $permohonan->approval_eo_at ?? $permohonan->approval_so_at;
$jangkaWaktu = $this->hitungTotalJangkaWaktuSla($tgl_kunjungan, $tgl_otorisator);
return [
'id' => $permohonan->id,
'nomor_registrasi' => $permohonan->nomor_registrasi,
'tanggal_permohonan' => $permohonan->tanggal_permohonan,
'branch' => $permohonan->debiture?->branch?->name,
'name' => $permohonan->debiture?->name,
'pemohon' => $permohonan->creator?->name,
'tujuan_penilaian' => $permohonan->tujuanPenilaian?->name,
'tanggal_laporan' => $permohonan->approval_dd_at ?? $permohonan->approval_eo_at ?? '',
'tanggal_approval' => $permohonan->approval_dd_at ?? $permohonan->approval_eo_at ?? '',
'tanggal_kunjungan' => $permohonan->penilaian?->tanggal_kunjungan ?? '',
'nama_penilai' => $permohonan->penilaian?->_user_penilai?->userPenilaiTeam?->name,
'jangka_waktu' => $jangkaWaktu,
'keterangan' => $permohonan->keterangan
];
});
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = $request->get('page', 1);
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
private function hitungTotalJangkaWaktuSla($tgl_kunjungan,$tgl_otorisator){
$countHariKerja = hitungHariKerja($tgl_kunjungan, $tgl_otorisator);
return $countHariKerja;
}
}

View File

@@ -1,8 +1,10 @@
<?php
namespace Modules\Lpj\Services;
use Modules\Lpj\Models\Permohonan;
use Illuminate\Http\Request;
use Modules\Usermanagement\Models\User;
class LaporanUserService
{
@@ -25,36 +27,15 @@ class LaporanUserService
{
// Retrieve data from the database
$query = Permohonan::query();
$query = $query->where('status', 'done');
$query = User::query();
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = json_decode($request->get('search'));
if (isset($search->start_date) || isset($search->end_date)) {
$query->whereBetween('tanggal_permohonan', [
$search->start_date ?? '1900-01-01',
$search->end_date ?? now()->toDateString()
]);
}
// Filter by branch if provided
if (isset($search->user_id) && !empty($search->user_id)) {
$query->where('user_id', $search->user_id);
}
if (isset($search->search)) {
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search->search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhere('status', 'LIKE', '%' . $search->search . '%');
$q->whereRaw('LOWER(name) LIKE ?', ['%' . strtolower($search) . '%']);
$q->where('nik', 'LIKE', '%' . $search->search . '%');
});
}
}
@@ -82,99 +63,16 @@ class LaporanUserService
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->with(['debiture.branch'])->get();
$data = $query->with(['branch', 'roles'])->get();
$data = $data->map(function ($permohonan) {
$luas_tanah = 0;
$luas_bangunan = 0;
$nilai_tanah = 0;
$nilai_bangunan = 0;
$npw = 0;
$nilai_liquidasi = 0;
if (isset($permohonan->penilai->lpj)) {
$lpj = json_decode($permohonan->penilai->lpj, true);
$npw = str_replace('.', '', $lpj['total_nilai_pasar_wajar'] ?? 0);
$luas_tanah = $lpj['luas_tanah'] ?? 0;
$luas_bangunan = $lpj['luas_bangunan'] ?? 0;
// Calculate nilai_tanah dynamically by looking for all keys that start with 'nilai_tanah_'
$nilai_tanah = str_replace('.', '', $lpj['nilai_tanah_2'] ?? 0);
$nilai_bangunan = str_replace('.', '', $lpj['nilai_bangunan_2'] ?? 0);
$nilai_liquidasi = str_replace('.', '', $lpj['likuidasi_nilai_2'] ?? 0);
}
$data = $data->map(function ($user) {
return [
'id' => $permohonan->id,
'nomor_registrasi' => $permohonan->nomor_registrasi,
'jenis_penilaian' => $permohonan->jenisPenilaian?->name,
'tujuan_penilaian' => $permohonan->tujuanPenilaian?->name,
'jenis_fasilitas_kredit' => $permohonan->jenisFasilitasKredit?->name,
'branch' => $permohonan->debiture->branch?->name,
'pemohon' => $permohonan->creator?->name,
'cif' => $permohonan->debiture->cif,
'name' => $permohonan->debiture?->name,
'jenis_agunan' => $permohonan->documents?->pluck('jenisJaminan.name')
->unique()
->implode(', '),
'alamat_agunan' => $permohonan->documents?->map(function ($document) {
return formatAlamat($document);
})->unique()->implode(', '),
'bukti_kepemilikan' => (function () use ($permohonan) {
$legalitasItems = $permohonan->documents?->flatMap(function ($document) {
return $document->detail->map(function ($detail) {
// Jika tidak ada jenis legalitas jaminan, lewati
if (empty($detail->jenisLegalitasJaminan)) {
return null;
}
// Hanya tampilkan detail yang memiliki dokumen_jaminan
if (empty($detail->dokumen_jaminan)) {
return null;
}
// Tampilkan nama legalitas jaminan saja
return $detail->jenisLegalitasJaminan->name ?? '';
});
})->filter()->unique()->values()->toArray();
// Buat daftar bernomor
$result = '';
foreach ($legalitasItems as $index => $item) {
$result .= ($index + 1) . '. ' . $item . "\n";
}
return $result;
})(),
'nama_pemilik' => $permohonan->documents?->pluck('pemilik.name')
->unique()
->implode(', '),
'luas_tanah' => $luas_tanah . ' m²',
'nilai_tanah' => formatRupiah($nilai_tanah, 2),
'luas_bangunan' => $luas_bangunan . ' m²',
'nilai_bangunan' => formatRupiah($nilai_bangunan, 2),
'nilai_njop' => formatRupiah($permohonan->nilai_njop, 2),
'nilai_pasar_wajar' => formatRupiah($npw, 2),
'nilai_likuidasi' => formatRupiah($nilai_liquidasi, 2),
'tanggal_documen_diterima' => $permohonan->documents?->map(function ($document) {
return $document->created_at->format('d-m-Y');
}),
'tanggal_spk' => '',
'nomor_spk' => '',
'tanggal_rencana_kunjunagn' => '',
'tanggal_kunjungan' => '',
'taggal_delivered' => '',
'jangka_waktu_sla' => '',
'nama_penilai' => $permohonan->penilaian?->_user_penilai?->userPenilaiTeam?->name,
'nama_team_leader' => $permohonan->penilaian?->teams,
'saran' => '',
'catatan' => '',
'tanggal_permohonan' => $permohonan->tanggal_permohonan,
'tanggal_laporan' => $permohonan->approval_dd_at ?? $permohonan->approval_eo_at ?? '',
'tanggal_review' => $permohonan->penilaian?->tanggal_kunjungan ?? '',
'id' => $user->id,
'nik' => $user->nik,
'name' => $user->name,
'level' => $user->roles->pluck('name')->implode(', '),
'approval_limit' => 0,
];
});

View File

@@ -0,0 +1,733 @@
<?php
namespace Modules\Lpj\Services;
use Carbon\Carbon;
use App\Helpers\Lpj;
use Modules\Lpj\Models\Denah;
use Modules\Lpj\Models\Teams;
use Modules\Lpj\Models\Branch;
use Modules\Lpj\Models\Lantai;
use Barryvdh\DomPDF\Facade\Pdf;
use Modules\Lpj\Models\Analisa;
use Modules\Lpj\Models\Penilai;
use Modules\Lpj\Models\Debiture;
use Modules\Lpj\Models\Inspeksi;
use Modules\Lpj\Models\Surveyor;
use Modules\Lpj\Models\ViewUnit;
use Modules\Location\Models\City;
use Modules\Lpj\Models\JenisUnit;
use Modules\Lpj\Models\Penilaian;
use Modules\Lpj\Models\Perizinan;
use Modules\Lpj\Models\BentukUnit;
use Modules\Lpj\Models\JenisKapal;
use Modules\Lpj\Models\LantaiUnit;
use Modules\Lpj\Models\Lingkungan;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\PosisiUnit;
use Illuminate\Support\Facades\Log;
use Modules\Lpj\Models\AnalisaUnit;
use Modules\Lpj\Models\BentukTanah;
use Modules\Lpj\Models\FotoJaminan;
use Modules\Lpj\Models\KonturTanah;
use Modules\Lpj\Models\RuteJaminan;
use Modules\Location\Models\Village;
use Modules\Lpj\Models\AnalisaFakta;
use Modules\Lpj\Models\JenisJaminan;
use Modules\Lpj\Models\JenisPesawat;
use Modules\Lpj\Models\ObjekJaminan;
use Modules\Lpj\Models\SpekBangunan;
use Modules\Lpj\Models\TerletakArea;
use Modules\Location\Models\District;
use Modules\Location\Models\Province;
use Modules\Lpj\Models\ArahMataAngin;
use Modules\Lpj\Models\JenisBangunan;
use Modules\Lpj\Models\PosisiKavling;
use Modules\Lpj\Models\SifatBangunan;
use Modules\Lpj\Models\DokumenJaminan;
use Modules\Lpj\Models\FasilitasObjek;
use Modules\Lpj\Models\JenisKendaraan;
use Modules\Lpj\Models\ModelAlatBerat;
use Modules\Lpj\Models\KetinggianTanah;
use Modules\Lpj\Models\KondisiBangunan;
use Modules\Lpj\Models\LaporanExternal;
use Modules\Lpj\Models\MerupakanDaerah;
use Modules\Lpj\Models\PerkerasanJalan;
use Modules\Lpj\Models\SaranaPelengkap;
use Modules\Lpj\Models\TujuanPenilaian;
use Modules\Lpj\Models\FotoObjekJaminan;
use Modules\Lpj\Models\LaluLintasLokasi;
use Modules\Lpj\Models\TingkatKeramaian;
use Modules\Lpj\Models\AnalisaLingkungan;
use Modules\Lpj\Models\KondisiFisikTanah;
use Modules\Lpj\Models\AnalisaTanahBagunan;
use Modules\Lpj\Models\GolonganMasySekitar;
use Modules\Lpj\Models\SpekBangunanAnalisa;
use Modules\Lpj\Models\DetailDokumenJaminan;
use Modules\Lpj\Models\SpekKategoritBangunan;
use Modules\Lpj\Http\Requests\SurveyorRequest;
use Modules\Lpj\Models\HubunganPemilikJaminan;
use Modules\Lpj\Models\HubunganPenghuniJaminan;
use Modules\Lpj\Models\SpekBagunanAnalisaDetail;
use Modules\Lpj\Jobs\SendJadwalKunjunganEmailJob;
use Modules\Lpj\Http\Requests\FormSurveyorRequest;
class PreviewLaporanService
{
/**
* Preview Laporan dan unduh foto terkait dengan logika fallback path.
*
* Menghasilkan PDF atau paket unduhan foto berdasarkan status laporan.
* Jika file foto asli tidak ditemukan dan status LPJ adalah 1, maka
* sistem akan mencoba menggunakan fallback path dengan pola
* `surveyor/001/{lastTwoParts}` untuk meminimalisir gambar hilang.
*
* @param int $permohonan_id ID Permohonan
* @param int $dokumen_id ID Dokumen
* @param int $jaminan_id ID Jaminan
* @param string $back URL atau rute kembali
* @return \Symfony\Component\HttpFoundation\Response
*/
public function previewLaporan($permohonan_id, $dokumen_id, $jaminan_id, $back)
{
$permohonan = $this->getPermohonanJaminanId(
$permohonan_id,
$dokumen_id,
$jaminan_id
);
// $tipeLaporanResponse = $this->checkPrintOutLaporan($permohonan_id, $document_id);
// $tipeLaporan = $tipeLaporanResponse->getData();
// if (!$tipeLaporan->status) {
// return redirect()->back()->with('error', 'Laporan tidak valid');
// }
$basicData = $this->getCommonData();
$inspeksi = Inspeksi::where('permohonan_id', $permohonan_id)->where('dokument_id', $dokumen_id)->first();
$lpj = Penilai::where('permohonan_id', $permohonan_id)->where('dokument_id', $dokumen_id)->first();
$mig_permohonan = json_decode($permohonan->mig_permohonan);
$nomorLaporan = getNomorLaporan($permohonan_id, $dokumen_id);
$tanggalLaporan = $permohonan->is_mig
? ($mig_permohonan->mig_mst_jaminan_tgl_laporan ?? $mig_permohonan->mig_mst_jaminan_tgl_create ?? null)
: ($lpj->created_at ?? null);
$forminspeksi = null;
$lpjData = null;
$formFoto = null;
// if ($inspeksi) {
$forminspeksi = json_decode($inspeksi?->data_form, true) ?? null;
$formFoto = json_decode($inspeksi?->foto_form, true) ?? null;
// $denahForm = json_decode($data->denah_form, true);
$dataPembanding = json_decode($inspeksi?->data_pembanding, true) ?? null;
// }
// if ($lpj) {
$lpjData = json_decode($lpj?->lpj, true) ?? null;
$memo = json_decode($lpj?->memo, true) ?? null;
$resumeData = json_decode($lpj?->resume, true) ?? null;
$rap = json_decode($lpj?->rap, true);
$report = json_decode($lpj?->call_report, true) ?? null;
// }
$inputAddress = $forminspeksi['asset']['alamat']['sesuai'] ?? $forminspeksi['asset']['alamat']['tidak sesuai'] ?? [];
$alamat = [
'address' => $inputAddress['address'] ?? null,
'village_code' => getWilayahName($inputAddress['village_code'] ?? null, 'village'),
'district_code' => getWilayahName($inputAddress['district_code'] ?? null, 'district'),
'city_code' => getWilayahName($inputAddress['city_code'] ?? null, 'city'),
'province_code' => getWilayahName($inputAddress['province_code'] ?? null, 'province')
];
$statusLpj = 0;
// $viewLaporan = $this->getViewLaporan($tipeLaporan);
return view('lpj::component.show-laporan-inspeksi', compact('permohonan', 'basicData', 'forminspeksi', 'alamat', 'lpjData', 'memo', 'resumeData', 'rap', 'report', 'lpj', 'formFoto', 'nomorLaporan', 'tanggalLaporan', 'dataPembanding', 'inspeksi', 'statusLpj', 'permohonan_id', 'back', ));
}
public function printOutLaporan($permohonan_id, $document_id, $jaminan_id)
{
$tipeLaporanResponse = $this->checkPrintOutLaporan($permohonan_id, $document_id);
$tipeLaporan = $tipeLaporanResponse->getData();
//dd($permohonan_id, $document_id, $tipeLaporan);
if (!$tipeLaporan->status) {
//return redirect()->back()->with('error', 'Laporan tidak valid');
}
$permohonan = $this->getPermohonanJaminanId(
$permohonan_id,
$document_id,
$jaminan_id
);
$basicData = $this->getCommonData();
$inspeksi = Inspeksi::where('permohonan_id', $permohonan_id)->where('dokument_id', $document_id)->first();
$lpj = Penilai::where('permohonan_id', $permohonan_id)->first(); //->where('dokument_id', $document_id)->first();
$mig_permohonan = json_decode($permohonan->mig_permohonan);
$nomorLaporan = getNomorLaporan($permohonan_id, $document_id);
//Carbon::createFromFormat('d/m/Y H:i:s', $mig_permohonan->mig_mst_jaminan_tgl_laporan)->format('Y-m-d H:i:s');
$tanggalLaporan = $permohonan->is_mig
? ($mig_permohonan->mig_mst_jaminan_tgl_laporan
? Carbon::createFromFormat('d/m/Y H:i:s', $mig_permohonan->mig_mst_jaminan_tgl_laporan)->format('Y-m-d H:i:s')
: ($mig_permohonan->mig_mst_jaminan_tgl_oto
? Carbon::createFromFormat('d/m/Y H:i:s', $mig_permohonan->mig_mst_jaminan_tgl_oto)->format('Y-m-d H:i:s')
: null))
: ($lpj->created_at ?? null);
$forminspeksi = null;
$lpjData = null;
$formFoto = null;
$dataPembanding ='';
if ($inspeksi) {
$forminspeksi = json_decode($inspeksi->data_form, true);
$formFoto = json_decode($inspeksi->foto_form, true);
// $denahForm = json_decode($data->denah_form, true);
$dataPembanding = json_decode($inspeksi->data_pembanding, true);
}
if ($lpj) {
$lpjData = json_decode($lpj->lpj, true);
$memo = json_decode($lpj->memo, true);
$resumeData = json_decode($lpj->resume, true);
$rap = json_decode($lpj->rap, true);
$report = json_decode($lpj->call_report, true);
}
$inputAddress = $forminspeksi['asset']['alamat']['sesuai'] ?? $forminspeksi['asset']['alamat']['tidak sesuai'] ?? [];
$inputAddress = $forminspeksi['asset']['alamat']['sesuai'] ?? $forminspeksi['asset']['alamat']['tidak sesuai'] ?? [];
$alamat = [
'address' => $inputAddress['address'] ?? null,
'village_code' => getWilayahName($inputAddress['village_code'] ?? null, 'village'),
'district_code' => getWilayahName($inputAddress['district_code'] ?? null, 'district'),
'city_code' => getWilayahName($inputAddress['city_code'] ?? null, 'city'),
'province_code' => getWilayahName($inputAddress['province_code'] ?? null, 'province')
];
$viewLaporan = $this->getViewLaporan($tipeLaporan->status);
$statusLpj = 1;
$mig_permohonan = json_decode($permohonan->mig_permohonan);
if(($tipeLaporan->status === 'memo' && $permohonan->mig_permohonan) || $mig_permohonan->mig_mst_lpj_tot_nilai_pasar < 1){
$paths = $formFoto['upload_foto'] ?? null;
if (!is_array($paths) || empty($paths)) {
return response()->json(['error' => 'No files to download'], 404);
}
$files = [];
foreach ($paths as $path) {
if (!$path['path']) {
Log::warning('PreviewLaporanService: Path kosong terdeteksi dalam daftar paths.');
continue;
}
// Logika fallback untuk path file
$originalPath = $path['path'];
$fallbackPath = null;
// Jika file asli tidak ditemukan, buat fallback path
if ($statusLpj == 1) {
$fullOriginalPath = storage_path('app/public/' . $originalPath);
if (!file_exists($fullOriginalPath)) {
// Ekstrak bagian akhir path (contoh: 251051/251051_2_2.png)
$pathParts = explode('/', $originalPath);
if (count($pathParts) >= 2) {
$lastTwoParts = array_slice($pathParts, -2);
$fallbackPath = 'surveyor/001/' . implode('/', $lastTwoParts);
Log::info('PreviewLaporanService: Menggunakan fallback path kandidat.', [
'original' => $originalPath,
'fallback' => $fallbackPath,
]);
}
}
}
// Tentukan path yang akan digunakan
$pathToUse = ($fallbackPath && $statusLpj == 1 && file_exists(storage_path('app/public/' . $fallbackPath)))
? $fallbackPath
: $originalPath;
$fullPath = storage_path('app/public/' . $pathToUse);
if (!file_exists($fullPath)) {
Log::warning('PreviewLaporanService: File tidak ditemukan untuk original maupun fallback.', [
'original' => $originalPath,
'fallback' => $fallbackPath,
'resolved' => $pathToUse,
]);
continue;
}
Log::info('PreviewLaporanService: Menambahkan file untuk diunduh.', [
'resolved' => $pathToUse,
'fullPath' => $fullPath,
]);
$files[] = $fullPath;
}
if (empty($files)) {
Log::warning('PreviewLaporanService: Tidak ada file valid ditemukan setelah resolusi path.');
return response()->json(['error' => 'No valid files found'], 404);
}
// For single file, download directly
if (count($files) === 1) {
Log::info('PreviewLaporanService: Mengunduh single file.', ['file' => $files[0]]);
return response()->download($files[0]);
}
// For multiple files, create zip and download
$zipName = 'photos_' . time() . '.zip';
$zipPath = storage_path('app/public/' . $zipName);
$zip = new \ZipArchive();
if ($zip->open($zipPath, \ZipArchive::CREATE) === true) {
foreach ($files as $file) {
$zip->addFile($file, basename($file));
}
$zip->close();
Log::info('PreviewLaporanService: Zip file berhasil dibuat.', ['zip' => $zipPath, 'count' => count($files)]);
return response()->download($zipPath)->deleteFileAfterSend(true);
}
Log::error('PreviewLaporanService: Gagal membuat zip file.');
return response()->json(['error' => 'Failed to create zip file'], 500);
}
try {
$pdf = $this->generatePDF($viewLaporan, compact(
'permohonan',
'forminspeksi',
'lpjData',
'formFoto',
'basicData',
'inspeksi',
'lpj',
'statusLpj',
'alamat',
'dataPembanding',
'nomorLaporan',
'memo',
'resumeData',
'tanggalLaporan',
'rap',
'report'
));
$cleanNomorLaporan = str_replace(['/', '\\'], '-', $nomorLaporan);
$filename = 'Laporan_' . $tipeLaporan->status . '_' . $permohonan->debiture->name . '_' . $cleanNomorLaporan;
return $pdf->download($filename . '_data.pdf');
} catch (\Exception $e) {
Log::error('PDF generation failed: ' . $e->getMessage());
return response()->json(['error' => 'Failed to generate PDF. Please check the log for details.'], 500);
}
}
private function generatePDF(string $viewLaporan, array $data)
{
//return view('lpj::' . $viewLaporan, $data);
$pdf = PDF::loadView('lpj::' . $viewLaporan, $data);
$pdf->setPaper('A4', 'portrait');
$pdf->set_option('isHtml5ParserEnabled', true);
$pdf->set_option('isPhpEnabled', true);
return $pdf;
}
private function getViewLaporan($tipe)
{
$viewMap = [
'sederhana' => 'penilai.components.print-out-sederhana',
'standar' => 'penilai.components.print-out-standar',
'resume' => 'penilai.components.print-resume',
'memo' => 'penilai.components.print-memo',
'rap' => 'penilai.components.print-out-rap',
'call-report' => 'penilai.components.print-out-call-report'
];
return $viewMap[$tipe] ?? 'penilai.components.print-resume';
}
public function checkPrintOutLaporan($permohonan_id, $dokumen_id)
{
// Ambil data berdasarkan ID
$statusLpj = Penilai::where('permohonan_id', $permohonan_id)
//->where('dokument_id', $dokumen_id)
->first();
$permohonan = Permohonan::where('id', $permohonan_id)->first();
// Jika data tidak ditemukan, kembalikan status null
if (!$statusLpj) {
return response()->json(['status' => null]);
}
// Tentukan tipe berdasarkan kondisi
$type = $statusLpj->type_penilai ?? null;
if ($type === 'memo' && $permohonan->is_mig!=1) {
return $this->checkDataMemo($type, $statusLpj);
}
if ($type === 'resume') {
return $this->checkDataResume($type, $statusLpj);
}
if ($type === 'standar' || $type === 'sederhana') {
return $this->checkDataLpj($type, $statusLpj);
}
if ($type === 'rap') {
return $this->checkDataRap($type, $statusLpj);
}
// Kembalikan respons dengan tipe yang sesuai
return response()->json(['status' => $type]);
}
public function checkDataMemo($type, $statusLpj)
{
// Ambil data JSON dari statusLpj
$data = json_decode($statusLpj->memo, true) ?? [];
$validationRules = [
'memo' => [
'kepada',
'dari',
'nomor_memo',
'tanggal',
'perihal',
'jenis_asset_tidak_sesuai',
'lokasi.lokasi',
'lokasi.province_code',
'lokasi.city_code',
'lokasi.district_code',
'lokasi.village_code',
'lokasi.penilai',
'terlampir',
'hasil_survey',
'kesimpulan_saran',
],
];
// Validasi data JSON
if (isset($validationRules[$type])) {
$missingFields = [];
foreach ($validationRules[$type] as $field) {
$keys = explode('.', $field);
$value = $data;
foreach ($keys as $key) {
if (!isset($value[$key])) {
$missingFields[] = $field;
break;
}
$value = $value[$key];
}
}
// Jika ada field yang kosong, kembalikan error
if (!empty($missingFields)) {
return response()->json([
'status' => null,
'message' => "Silahkan lengkapi data memo terlebih dahulu.",
'missing_fields' => $missingFields,
], 400);
}
}
// Jika data valid
return response()->json([
'status' => $type,
'message' => "Data memo valid.",
]);
}
public function checkDataResume($type, $statusLpj)
{
// Ambil data JSON dari statusLpj
$data = json_decode($statusLpj->resume, true) ?? [];
$validationRules = [
'resume' => [
'fisik'
],
];
// Validasi data JSON
if (isset($validationRules[$type])) {
$missingFields = [];
foreach ($validationRules[$type] as $field) {
$keys = explode('.', $field);
$value = $data;
foreach ($keys as $key) {
if (!isset($value[$key])) {
$missingFields[] = $field;
break;
}
$value = $value[$key];
}
// Validasi khusus untuk array fisik dan sesuai_imb
if ($field === 'fisik' || $field === 'sesuai_imb') {
if (empty($value) || !is_array($value)) {
$missingFields[] = $field;
continue;
}
// Validasi struktur data di dalam array
foreach ($value as $item) {
$requiredKeys = ['sertifikat', 'luas_tanah', 'nilai'];
foreach ($requiredKeys as $requiredKey) {
if (!isset($item[$requiredKey])) {
$missingFields[] = $field . '.' . $requiredKey;
}
}
}
}
}
// Jika ada field yang kosong, kembalikan error
if (!empty($missingFields)) {
return response()->json([
'status' => null,
'message' => "Silahkan lengkapi data resume terlebih dahulu.",
'missing_fields' => $missingFields,
], 400);
}
}
// Jika data valid
return response()->json([
'status' => $type,
'message' => "Data resume valid.",
]);
}
public function checkDataLpj($type, $statusLpj)
{
// Ambil data JSON dari statusLpj
$data = json_decode($statusLpj->lpj, true) ?? [];
$validationRules = [
'lpj' => [
'luas_tanah',
'nilai_tanah_1',
'nilai_tanah_2',
'luas_bangunan',
'nilai_bangunan_1',
'nilai_bangunan_2',
'total_nilai_pasar_wajar',
'likuidasi',
'likuidasi_nilai_1',
'likuidasi_nilai_2',
'asuransi_luas_bangunan',
'asuransi_nilai_1',
'asuransi_nilai_2',
'npw_tambahan'
],
];
// Validasi data JSON
if (isset($validationRules[$type])) {
$missingFields = [];
foreach ($validationRules[$type] as $field) {
// Penanganan khusus untuk field yang boleh null
if (in_array($field, ['sarana_pelengkap_penilai', 'nilai_sarana_pelengkap_1', 'nilai_sarana_pelengkap_2'])) {
continue;
}
if (!isset($data[$field])) {
$missingFields[] = $field;
continue;
}
// Validasi khusus untuk npw_tambahan
if ($field === 'npw_tambahan' && is_array($data[$field])) {
foreach ($data[$field] as $index => $item) {
$requiredKeys = ['name', 'luas', 'nilai_1', 'nilai_2'];
foreach ($requiredKeys as $key) {
if (!isset($item[$key])) {
$missingFields[] = "npw_tambahan[$index].$key";
}
}
}
}
}
// Jika ada field yang kosong, kembalikan error
if (!empty($missingFields)) {
return response()->json([
'status' => null,
'message' => "Silahkan lengkapi data LPJ terlebih dahulu.",
'missing_fields' => $missingFields,
], 400);
}
}
// Jika data valid
return response()->json([
'status' => $type,
'message' => "Data LPJ valid.",
]);
}
public function checkDataRap($type, $statusLpj)
{
// Ambil data JSON dari statusLpj
$data = json_decode($statusLpj->rap, true) ?? [];
$requiredFields = [
'dari',
'kepada',
'perihal',
'tanggal',
'nomor_rap'
];
// Cek apakah ada field yang kosong
$missingFields = [];
foreach ($requiredFields as $field) {
if (!isset($data[$field]) || empty($data[$field])) {
$missingFields[] = $field;
}
}
// Jika ada field yang kosong, kembalikan error
if (!empty($missingFields)) {
return response()->json([
'status' => null,
'message' => "Silahkan lengkapi data RAP terlebih dahulu.",
'missing_fields' => $missingFields
], 400);
}
// Jika semua data terisi
return response()->json([
'status' => $type,
'message' => "Data RAP valid."
]);
}
private function getPermohonanJaminanId($id, $dokumentId, $jaminanId)
{
return Permohonan::with([
'user',
'debiture.province',
'debiture.city',
'debiture.district',
'debiture.village',
'branch',
'tujuanPenilaian',
'penilaian',
'penawaran',
'debiture.documents' => function ($query) use ($dokumentId, $jaminanId) {
$query->where('id', $dokumentId)
->where('jenis_jaminan_id', $jaminanId);
}
])->findOrFail($id);
}
public function getCommonData()
{
return [
'branches' => Branch::all(),
'bentukTanah' => BentukTanah::all(),
'konturTanah' => KonturTanah::all(),
'posisiKavling' => PosisiKavling::all(),
'ketinggianTanah' => KetinggianTanah::all(),
'kondisiFisikTanah' => KondisiFisikTanah::all(),
'jenisBangunan' => JenisBangunan::all(),
'kondisiBangunan' => KondisiBangunan::all(),
'sifatBangunan' => SifatBangunan::all(),
'spekKategoriBangunan' => SpekKategoritBangunan::all(),
'spekBangunan' => SpekBangunan::all(),
'saranaPelengkap' => SaranaPelengkap::all(),
'arahMataAngin' => ArahMataAngin::all(),
'lantai' => Lantai::all(),
'viewUnit' => ViewUnit::all(),
'golMasySekitar' => GolonganMasySekitar::all(),
'tingkatKeramaian' => TingkatKeramaian::all(),
'laluLintasLokasi' => LaluLintasLokasi::all(),
'jenisPesawat' => JenisPesawat::all(),
'modelAlatBerat' => ModelAlatBerat::all(),
'jenisKapal' => JenisKapal::all(),
'jenisKendaraan' => JenisKendaraan::all(),
'terletakArea' => TerletakArea::all(),
'posisiUnit' => PosisiUnit::all(),
'bentukUnit' => BentukUnit::all(),
'fasilitasObjek' => FasilitasObjek::all(),
'merupakanDaerah' => MerupakanDaerah::all(),
'jenisUnit' => JenisUnit::all(),
'jenisJaminan' => JenisJaminan::all(),
'hubCadeb' => HubunganPemilikJaminan::all(),
'hubPenghuni' => HubunganPenghuniJaminan::all(),
'perkerasanJalan' => PerkerasanJalan::all(),
'terletakDiArea' => TerletakArea::all(),
'tujuanPenilaian' => TujuanPenilaian::all(),
'perizinan' => Perizinan::all(),
'foto' => FotoObjekJaminan::all()
];
}
private const HEADERS = [
'bentuk-tanah' => ['Bentuk Tanah', 'bentuk-tanah'],
'kontur-tanah' => ['Kontur Tanah', 'kontur-tanah'],
'posisi-kavling' => ['Posisi Kavling', 'posisi-kavling'],
'ketinggian-tanah' => ['Ketinggian Tanah', 'ketinggian-tanah'],
'kondisi-fisik-tanah' => ['Kondisi Fisik Tanah', 'kondisi-fisik-tanah'],
'jenis-bangunan' => ['Jenis Bangunan', 'jenis-bangunan'],
'kondisi-bangunan' => ['Kondisi Bangunan', 'kondisi-bangunan'],
'sifat-bangunan' => ['Sifat Bangunan', 'sifat-bangunan'],
'sarana-pelengkap' => ['Sarana Pelengkap', 'sarana-pelengkap'],
'lalu-lintas-lokasi' => ['Lalu Lintas Depan Lokasi', 'lalu-lintas-lokasi'],
'tingkat-keramaian' => ['Tingkat Keramaian', 'tingkat-keramaian'],
'gol-mas-sekitar' => ['Golongan Masyarakat Sekitar', 'gol-mas-sekitar'],
'spek-kategori-bangunan' => ['Spek Kategori Bangunan', 'spek-kategori-bangunan'],
'spek-bangunan' => ['Spek Bangunan', 'spek-bangunan'],
'lantai-unit' => ['Lantai Unit', 'lantai-unit'],
'view-unit' => ['View Unit', 'view-unit'],
'perkerasan-jalan' => ['Perkerasan jalan', 'perkerasan-jalan'],
'jenis-pesawat' => ['Jenis pesawat', 'jenis-pesawat'],
'model-alat-berat' => ['Model alat berat', 'model-alat-berat'],
'jenis-kapal' => ['Jenis kapal', 'jenis-kapal'],
'jenis-kendaraan' => ['Jenis kendaraan', 'jenis-kendaraan'],
'jenis-unit' => ['Jenis unit', 'jenis-unit'],
'terletak-area' => ['Terletak di Area', 'terletak-area'],
'merupakan-daerah' => ['Merupakan Daerah', 'merupakan-daerah'],
'posisi-unit' => ['Posisi unit', 'posisi-unit'],
'bentuk-unit' => ['Bentuk unit', 'bentuk-unit'],
'fasilitas-objek' => ['Fasilitas Umum Dekat Objek', 'fasilitas-objek'],
'foto-objek-jaminan' => ['Foto Objek Jaminan', 'foto-objek-jaminan'],
'perizinan' => ['Perizinan', 'perizinan'],
];
}

View File

@@ -0,0 +1,107 @@
<?php
namespace Modules\Lpj\Services;
class TypeLaporanService
{
public function handleRequest($type, $permohonanId, $documentId, $jaminanId, $surveyorController)
{
$permohonan = $this->getPermohonanData($surveyorController, $permohonanId, $documentId, $jaminanId);
if ($permohonan->status == 'proses-laporan') {
throw new \Exception('Masih dalam proses laporan');
}
$nomorLaporan = $this->generateNomorLaporan($surveyorController, $permohonan, $documentId, $type);
$inspeksi = $this->getInspeksi($permohonanId, $documentId);
$this->updatePenilai($permohonanId, $documentId, $type);
$debitur = Debiture::find($permohonan->debiture_id);
$forminspeksi = $inspeksi ? json_decode($inspeksi->data_form, true) : null;
$locationCodes = $this->getAlamatData($debitur, $forminspeksi);
$locationData = $this->getLocationData(
$locationCodes['provinceCode'],
$locationCodes['cityCode'],
$locationCodes['districtCode'],
$forminspeksi
);
return [
'permohonan' => $permohonan,
'nomorLaporan' => $nomorLaporan,
'basicData' => $surveyorController->getCommonData(),
'cities' => $locationData['cities'],
'districts' => $locationData['districts'],
'villages' => $locationData['villages'],
'forminspeksi' => $forminspeksi,
];
}
private function getPermohonanData($surveyorController, $permohonanId, $documentId, $jaminanId)
{
return $surveyorController->getPermohonanData($permohonanId, $documentId, $jaminanId);
}
private function generateNomorLaporan($surveyorController, $permohonan, $documentId, $type)
{
return $surveyorController->generateNomorLaporan($permohonan, $documentId, $type);
}
private function getInspeksi($permohonanId, $documentId)
{
return Inspeksi::where('permohonan_id', $permohonanId)
->where('document_id', $documentId)
->first();
}
private function updatePenilai($permohonanId, $documentId, $type)
{
// Logika untuk memperbarui data berdasarkan tipe laporan
}
private function getAlamatData($debitur, $forminspeksi)
{
return [
'provinceCode' => $debitur->province_id ?? $forminspeksi['province'],
'cityCode' => $debitur->city_id ?? $forminspeksi['city'],
'districtCode' => $debitur->district_id ?? $forminspeksi['district'],
];
}
private function getLocationData($provinceCode, $cityCode, $districtCode, $forminspeksi)
{
return [
'cities' => $this->fetchCityData($provinceCode),
'districts' => $this->fetchDistrictData($cityCode),
'villages' => $this->fetchVillageData($districtCode),
];
}
private function fetchCityData($provinceCode)
{
return City::where('province_code', $provinceCode)->get();
}
private function fetchDistrictData($cityCode)
{
return District::where('city_code', $cityCode)->get();
}
private function fetchVillageData($districtCode)
{
return Village::where('district_code', $districtCode)->get();
}
private function updateOrCreatePenilai($permohonan_id, $document_id, $type, $data)
{
return Penilai::updateOrCreate(
[
'permohonan_id' => $permohonan_id,
'dokument_id' => $document_id,
],
[
$type => json_encode($data),
]
);
}
}

View File

@@ -0,0 +1,52 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class () extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('debitures', function (Blueprint $table) {
// nullable
$table->string('cif', 16)
->nullable()
->default('0000000000')
->comment('asal data LPJ.PRM_DEBITUR.KODE_CIF. Pada KODE_CIF ada yang digitnya 16 => 3372040405810002')
->change();
$table->unsignedBigInteger('branch_id')->nullable()->change();
$table->string('nomor_id', 50)->nullable()->change();
$table->unsignedBigInteger('mig_kd_debitur_seq')->nullable()->comment('asal data LPJ.PRM_DEBITUR.KD_DEBITUR_SEQ. Berguna untuk update debitur_id menggunakan KD_DEBITUR_SEQ nya');
$table->timestamp('processed_at')->nullable();
$table->char('is_mig', 1)->nullable()->comment('untuk menandakan row ini dari LPJ OLD');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('debitures', function (Blueprint $table) {
// Kembalikan kolom branch_id agar tidak nullable (asumsi awal NOT NULL)
$table->unsignedBigInteger('branch_id')->nullable(false)->change();
// Kembalikan kolom yang diubah nullable menjadi NOT NULL
$table->string('cif', 10)->nullable(false)->change();
$table->string('nomor_id', 50)->nullable(false)->change();
// Hapus kolom tambahan yang dibuat di up()
$table->dropColumn([
'mig_kd_debitur_seq',
'mig_urut_seq_addr',
'mig_urut_seq_comm',
'processed_at',
'is_mig'
]);
});
}
};

View File

@@ -0,0 +1,47 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class () extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('permohonan', function (Blueprint $table) {
// nullable
$table->unsignedBigInteger('branch_id')->nullable()->change();
$table->unsignedBigInteger('user_id')->nullable()->change();
$table->unsignedBigInteger('mig_kd_debitur_seq')->nullable()->comment('asal data LPJ.PRM_DEBITUR.KD_DEBITUR_SEQ. Berguna untuk update debitur_id menggunakan KD_DEBITUR_SEQ nya');
$table->unsignedBigInteger('nomor_lpj')->nullable();
$table->string('mig_nama_ao')->nullable();
$table->char('is_mig', 1)->nullable()->comment('untuk menandakan row ini dari LPJ OLD');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('permohonan', function (Blueprint $table) {
// Kembalikan kolom branch_id agar tidak nullable (asumsi awal NOT NULL)
$table->unsignedBigInteger('branch_id')->nullable(false)->change();
$table->unsignedBigInteger('user_id')->nullable(false)->change();
// Hapus kolom tambahan yang dibuat di up()
$table->dropColumn([
'mig_kd_debitur_seq',
'nomor_lpj',
'mig_nama_ao',
'is_mig'
]);
});
}
};

View File

@@ -0,0 +1,40 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class () extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('dokumen_jaminan', function (Blueprint $table) {
// nullable
$table->unsignedBigInteger('mig_kd_debitur_seq')->nullable()->comment('asal data LPJ.PRM_DEBITUR.KD_DEBITUR_SEQ. Berguna untuk update debitur_id menggunakan KD_DEBITUR_SEQ nya');
$table->unsignedBigInteger('nomor_lpj')->nullable();
$table->timestamp('processed_at')->nullable();
$table->char('is_mig', 1)->nullable()->comment('untuk menandakan row ini dari LPJ OLD');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('dokumen_jaminan', function (Blueprint $table) {
// Hapus kolom tambahan yang dibuat di up()
$table->dropColumn([
'nomor_lpj',
'mig_kd_debitur_seq',
'processed_at',
'is_mig'
]);
});
}
};

View File

@@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class () extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('pemilik_jaminan', function (Blueprint $table) {
// nullable
$table->unsignedBigInteger('mig_kd_debitur_seq')->nullable()->comment('asal data LPJ.PRM_DEBITUR.KD_DEBITUR_SEQ. Berguna untuk update debitur_id menggunakan KD_DEBITUR_SEQ nya');
$table->timestamp('processed_at')->nullable();
$table->char('is_mig', 1)->nullable()->comment('untuk menandakan row ini dari LPJ OLD');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('pemilik_jaminan', function (Blueprint $table) {
// Hapus kolom tambahan yang dibuat di up()
$table->dropColumn([
'mig_kd_debitur_seq',
'processed_at',
'is_mig'
]);
});
}
};

View File

@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('inspeksi', function (Blueprint $table) {
$table->unsignedBigInteger('nomor_lpj')->nullable();
$table->timestamp('processed_at')->nullable();
$table->char('is_mig', 1)->nullable()->comment('untuk menandakan row ini dari LPJ OLD');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('inspeksi', function (Blueprint $table) {
$table->dropColumn('nomor_lpj');
$table->dropColumn('processed_at');
$table->dropColumn('is_mig');
});
}
};

View File

@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('penilai', function (Blueprint $table) {
$table->unsignedBigInteger('nomor_lpj')->nullable();
$table->timestamp('processed_at')->nullable();
$table->char('is_mig', 1)->nullable()->comment('untuk menandakan row ini dari LPJ OLD');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('penilai', function (Blueprint $table) {
$table->dropColumn('nomor_lpj');
$table->dropColumn('processed_at');
$table->dropColumn('is_mig');
});
}
};

View File

@@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class () extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('category_daftar_pustaka', function (Blueprint $table) {
$table->id();
$table->string('code')->unique()->index();
$table->string('name');
$table->timestamps();
$table->timestamp('authorized_at')->nullable();
$table->char('authorized_status', 1)->nullable();
$table->softDeletes();
$table->unsignedBigInteger('created_by')->nullable();
$table->unsignedBigInteger('updated_by')->nullable();
$table->unsignedBigInteger('deleted_by')->nullable();
$table->unsignedBigInteger('authorized_by')->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('category_daftar_pustaka');
}
};

View File

@@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class () extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('daftar_pustaka', function (Blueprint $table) {
$table->id();
$table->string('judul');
$table->string('attachment')->nullable();
$table->text('deskripsi');
$table->unsignedBigInteger('category_id');
$table->foreign('category_id')->references('id')->on('category_daftar_pustaka');
$table->timestamps();
$table->timestamp('authorized_at')->nullable();
$table->char('authorized_status', 1)->nullable();
$table->softDeletes();
$table->unsignedBigInteger('created_by')->nullable();
$table->unsignedBigInteger('updated_by')->nullable();
$table->unsignedBigInteger('deleted_by')->nullable();
$table->unsignedBigInteger('authorized_by')->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('daftar_pustaka');
}
};

View File

@@ -13,24 +13,25 @@ class HubunganPemilikJaminanSeeder extends Seeder
public function run(): void
{
$hubungan_pemilik_jaminan = [
[
'name' => 'Milik Pribadi'
],
[
'name' => 'Suami/Istri'
],
[
'name' => 'Anak'
],
[
'name' => 'Saudara Kandung'
],
[
'name' => 'Ayah'
],
[
'name' => 'Ibu'
]
['name' => 'Milik Pribadi'],
['name' => 'Suami'],
['name' => 'Anak'],
['name' => 'Saudara'],
['name' => 'Ayah'],
['name' => 'Ibu'],
['name' => 'Nenek'],
['name' => 'Penjual/Developer'],
[ 'name' => 'Kakak/adik kandung'],
[ 'name' => 'Orang tua'],
[ 'name' => 'Mitra Usaha'],
[ 'name' => 'Pihak lain'],
[ 'name' => 'Negara'],
[ 'name' => 'Nenek/kakek'],
[ 'name' => 'Milik Keluarga'],
[ 'name' => 'Kakak/adik Orangtua'],
[ 'name' => 'Istri'],
[ 'name' => 'Pengurus'],
[ 'name' => 'Lain - lain'],
];
foreach ($hubungan_pemilik_jaminan as $hpj) {

View File

@@ -69,6 +69,49 @@ class JenisFasilitasKreditSeeder extends Seeder
'created_at' => now(),
'updated_at' => now()
],
[
'code' => 'JFK009',
'name' => 'UMKM',
'status' => 1,
'created_at' => now(),
'updated_at' => now()
],
[
'code' => 'JFK010',
'name' => 'KORPORASI',
'status' => 1,
'created_at' => now(),
'updated_at' => now()
],
[
'code' => 'JFK011',
'name' => 'KPR 2',
'status' => 1,
'created_at' => now(),
'updated_at' => now()
],
[
'code' => 'JFK012',
'name' => 'KONSUMER',
'status' => 1,
'created_at' => now(),
'updated_at' => now()
],
[
'code' => 'JFK013',
'name' => 'KOMERSIL',
'status' => 1,
'created_at' => now(),
'updated_at' => now()
],
[
'code' => 'JFK014',
'name' => 'KPR REGULER',
'status' => 1,
'created_at' => now(),
'updated_at' => now()
],
]);
}
}

View File

@@ -12,36 +12,50 @@ class LpjDatabaseSeeder extends Seeder
public function run(): void
{
$this->call([
BranchSeeder::class,
CurrencySeeder::class,
HolidayCalendarSeeder::class,
JenisFasilitasKreditSeeder::class,
JenisLegalitasJaminanSeeder::class,
JenisJaminanSeeder::class,
JenisDokumenSeeder::class,
TujuanPenilaianSeeder::class,
NilaiPlatformSeeder::class,
HubunganPemilikJaminanSeeder::class,
HubunganPenghuniJaminanSeeder::class,
ArahMataAnginSeeder::class,
StatusPermohonanSeeder::class,
RegionSeeder::class,
TeamsSeeder::class,
TeamUsersSeeder::class,
JenisPenilaianSeeder::class,
IjinUsahaSeeder::class,
TujuanPenilaianKJPPSeeder::class,
KJPPSeeder::class,
JenisLaporanSeeder::class,
DebitureSeeder::class,
PemilikJaminanSeeder::class,
DokumenJaminanSeeder::class,
DetailDokumenJaminanSeeder::class,
PermohonanSeeder::class,
FotoObjekJaminanSeeder::class,
// BranchSeeder::class,
// CurrencySeeder::class,
// HolidayCalendarSeeder::class,
// JenisFasilitasKreditSeeder::class,
// JenisLegalitasJaminanSeeder::class,
// JenisJaminanSeeder::class,
// JenisDokumenSeeder::class,
// TujuanPenilaianSeeder::class,
// NilaiPlatformSeeder::class,
// HubunganPemilikJaminanSeeder::class,
// HubunganPenghuniJaminanSeeder::class,
// ArahMataAnginSeeder::class,
// StatusPermohonanSeeder::class,
// RegionSeeder::class,
// TeamsSeeder::class,
// TeamUsersSeeder::class,
// MasterDataSurveyorSeeder::class
// JenisPenilaianSeeder::class,
// IjinUsahaSeeder::class,
// TujuanPenilaianKJPPSeeder::class,
// KJPPSeeder::class,
// JenisLaporanSeeder::class,
// DebitureSeeder::class,
// PemilikJaminanSeeder::class,
// DokumenJaminanSeeder::class,
// DetailDokumenJaminanSeeder::class,
// PermohonanSeeder::class,
// FotoObjekJaminanSeeder::class,
// PenawaranSeeder::class,
// DetailPenawaranSeeder::class,
// PenilaianSeeder::class,
// MigrationDebitureSeeder::class,
// MigrationPermohonanSeeder::class,
// MigrationDokumentJaminanSeeder::class,
// MigrationDetailDokumenJaminanSeeder::class,
// MigPenilaianAndPenilainTeamSeeder::class,
// MigrationInpseksiSeeder::class,
MigrationGambarInspeksiSeeder::class,
// MigrationPembandingSeeder::class,
// MigrationPenilaiSeeder::class
// ini untuk penilaian external
// MigExternalPenawaranSeeder::class,
]);
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace Modules\Lpj\Database\Seeders;
use Illuminate\Database\Seeder;
class MasterDataSurveyorSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
$nameTable = [
'fasilitas_objek',
'gol_mas_sekitar',
'jenis_bangunan',
'jenis_kapal',
'jenis_kendaraan',
'jenis_pesawat',
'kondisi_bangunan',
'kondisi_fisik_tanah',
'kontur_tanah',
'lalu_lintas_lokasi',
'lantai',
'merupakan_daerah',
'perkerasan_jalan',
'sifat_bangunan',
'model_alat_berat',
'posisi_kavling',
'posisi_unit',
'tingkat_keramaian',
'sarana_pelengkap',
'spek_kategori_bangunan',
'spek_bangunan',
'terletak_diarea',
'view_unit'
];
foreach ($nameTable as $table) {
DB::unprepared(file_get_contents(__DIR__ . '/sql/' . $table . '.sql'));
}
}
}

View File

@@ -0,0 +1,306 @@
<?php
namespace Modules\Lpj\Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\PenawaranTender;
use Modules\Usermanagement\Models\User;
use Modules\Lpj\Models\Penilaian;
use Modules\Lpj\Models\PenilaianTeam;
class MigExternalPenawaranSeeder extends Seeder
{
protected $errorLogFile = __DIR__ . '/csv/penawaran/mig_penawaran_external_error.csv';
/**
* Run the database seeds.
*/
public function run()
{
// Bersihkan/Inisialisasi file error log
$this->initializeErrorLog();
// Path ke file csv
$filePath = realpath(__DIR__ . '/csv/penawaran/mig_penawaran_external.csv');
if (!$filePath) {
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/permohonan/mig_penawaran_external.csv');
$this->command->error('File csv tidak ditemukan.');
return;
}
if (($handle = fopen($filePath, 'r')) === false) {
Log::error('Gagal membuka file CSV: ' . $filePath);
$this->command->error('Gagal membuka file CSV.');
return;
}
$header = fgetcsv($handle, 0, '~');
$rows = [];
$batchSize = 500; // Ukuran batch
$userDataChace = [];
$nomorRegisCahce = [];
$errorCount = 0; // Inisialisasi variabel errorCount
$errorDebitureIds = []; // Inisialisasi array errorDebitureIds
$totalData = 0;
// Menghitung total data di file CSV
while (($data = fgetcsv($handle, 0, '~')) !== false) {
$totalData++;
}
rewind($handle); // Reset pointer ke awal file
fgetcsv($handle, 0, '~'); // Skip header
$batchCount = 0;
$currentRow = 0;
while (($data = fgetcsv($handle, 0, '~')) !== false) {
if (count($data) != count($header)) {
Log::warning('Baris CSV memiliki jumlah kolom yang tidak sesuai: ' . json_encode($data));
continue;
}
$rows[] = array_combine($header, $data);
$currentRow++;
// Jika sudah mencapai batch size, proses batch
if (count($rows) >= $batchSize) {
$batchCount++;
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
$this->processBatch($rows, $nomorRegisCahce, $userDataChace, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
$rows = [];
}
}
// Proses sisa data jika ada
// print_r($rows[0]);
if (!empty($rows)) {
$batchCount++;
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
$this->processBatch($rows, $nomorRegisCahce, $userDataChace, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
}
fclose($handle);
$this->command->info("Data debiture berhasil dimigrasikan. Total data: {$totalData}, Total batch: {$batchCount}, Total error: {$errorCount}");
}
private function processBatch(
array $rows,
array &$userDataChace,
array &$nomorRegisCahce,
int &$errorCount,
array &$errorDebitureIds,
int $totalData,
int $batchCount,
int $currentRow
) {
$userData = [];
foreach ($rows as $index => $row) {
try {
// Jalankan setiap baris dengan transaksi sendiri
DB::beginTransaction();
// Cek apakah sudah diproses
$existingRecord = PenawaranTender::where('nomor_registrasi', $row['mig_nomor_jaminan'])->first();
if ($existingRecord && $existingRecord->created_at) {
$this->command->info('Data sudah diproses sebelumnya: ' . $row['mig_nomor_jaminan']);
continue;
}
// Ambil nomor registrasi
$nomor_registrasi = $this->getNomorRegistrasiPermohonan($row['mig_nomor_jaminan'], $nomorRegisCahce);
if (!$nomor_registrasi) {
throw new \Exception("Nomor registrasi tidak valid");
}
$userIdUpdate = $this->getUserIdData($row['mig_created_by'] ?? null, $userData)['id'];
$userIdOtorisasi = $this->getUserIdData($row['mig_authorized_by'] ?? null, $userData)['id'];
if (!$userIdUpdate || !$userIdOtorisasi) {
// $this->logError($userIdUpdate, 'Salah satu user tidak ditemukan');
continue;
}
// Mapping field user
$mapUser = [
'created_by' => $userIdUpdate,
'updated_by' => $userIdUpdate,
'authorized_by' => $userIdOtorisasi,
];
// create random code
$tgl = $this->parseTimestamp($row['mig_tgl_penyerahan']);
// ambil nilai tahun terakhir contoh 2023 maka ambil 23
$year = date('y', strtotime($tgl));
// random code berdasarkan tgl contoh NP2300001
$code = 'NP' . $year . str_pad(rand(1, 99999), 5, '0', STR_PAD_LEFT); // outputnya NP2300001:
// Cek apakah kode sudah ada
$existingCode = PenawaranTender::where('code', $code)->first();
if ($existingCode) {
$code = 'NP' . $year . str_pad(rand(1, 99999), 5, '0', STR_PAD_LEFT);
}
// Buat penilaian
$penilaian = PenawaranTender::create([
'code' => $code,
'nama_kjpp_sebelumnya' => $row['mig_nama_kjpp'],
'biaya_kjpp_sebelumnya' => $row['mig_tot_jasa'],
'tanggal_penilaian_sebelumnya' => $this->parseTimestamp($row['mig_tgl_penyerahan']),
'nomor_registrasi' => $nomor_registrasi,
'tujuan_penilaian_kjpp_id' => $this->checkTujuanPenilaian($row['mig_mst_jaminan_kd_tujuan_seq']),
'jenis_laporan_id' => 1,
'start_date' => $this->parseTimestamp($row['mig_tgl_penyerahan']),
'end_date' => $this->parseTimestamp($row['mig_terima_laporan']),
'catatan' => $row['mig_catatan'],
'status' => 'spk',
'created_at' => $this->parseTimestamp($row['mig_created_at']),
'updated_at' => $this->parseTimestamp($row['mig_updated_at']),
'authorized_by' => $mapUser['authorized_by'],
'created_by' => $mapUser['created_by'],
'updated_by' => $mapUser['updated_by'],
]);
// Commit transaksi
DB::commit();
$this->command->info('Proses data penilaian ' . $row['mig_nomor_jaminan'] . ' (' . ($index + 1) . '/' . count($rows) . ')');
} catch (\Exception $e) {
// Rollback jika ada error
DB::rollBack();
Log::error('Error pada baris: ' . json_encode($row) . '. Pesan: ' . $e->getMessage());
$errorCount++;
$errorDebitureIds[] = $row['mig_team_id'] ?? '-';
$this->logError($row['mig_team_id'] ?? '-', $e->getMessage());
continue;
}
}
$this->command->info("Batch {$batchCount} selesai. Total error: " . count($errorDebitureIds));
}
private function getNomorRegistrasiPermohonan($nomor_registrasi_id, $nomorRegisCahce)
{
if (isset($nomorRegisCahce[$nomor_registrasi_id])) {
return $nomorRegisCahce[$nomor_registrasi_id];
}
$nomorRegis = Permohonan::where('nomor_registrasi', $nomor_registrasi_id)->first();
if (!$nomorRegis) {
return null;
}
$nomorRegisCahce[$nomor_registrasi_id] = $nomorRegis->nomor_registrasi;
return $nomorRegis->nomor_registrasi;
}
private function getUserIdData(?string $code, array &$cache): array
{
if (!$code) {
return ['id' => null, 'branch_id' => null];
}
if (isset($cache[$code])) {
return $cache[$code];
}
$user = User::where('nik', $code)->first();
if ($user) {
$cache[$code] = ['id' => $user->id, 'branch_id' => $user->branch_id];
return $cache[$code];
}
return ['id' => null, 'branch_id' => null];
}
private function getUserId($mig_user_id, $userDataChace)
{
if (isset($userDataChace[$mig_user_id])) {
return $userDataChace[$mig_user_id];
}
$userId = User::where('nik', $mig_user_id)->first();
if (!$userId) {
return null;
}
$userDataChace[$mig_user_id] = $userId->id;
return $userId->id;
}
private function parseTimestamp(?string $timestamp): ?string
{
try {
if ($timestamp) {
// Cek jika format hanya tanggal (Y-m-d)
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $timestamp)) {
return \Carbon\Carbon::createFromFormat('Y-m-d', $timestamp)
->startOfDay()
->toDateTimeString();
}
// Format lengkap (Y-m-d H:i:s)
return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString();
}
return null;
} catch (\Exception $e) {
Log::error('Gagal memparsing timestamp: ' . $timestamp . '. Pesan: ' . $e->getMessage());
return null;
}
}
private function initializeErrorLog()
{
// Jika file lama ada, hapus
if (file_exists($this->errorLogFile)) {
unlink($this->errorLogFile);
}
// Buat file baru dengan header
$handle = fopen($this->errorLogFile, 'w');
fputcsv($handle, ['mig_kd_debitur_seq', 'Error']);
fclose($handle);
}
private function logError(string $kode, string $message)
{
// Catat ke log
Log::error("Error migrasi debiture [$kode]: $message");
// Tulis ke file error
$handle = fopen($this->errorLogFile, 'a');
fputcsv($handle, [$kode, $message]);
fclose($handle);
}
private function checkTujuanPenilaian($code): int
{
$mapping = [
1 => 7,
2 => 5,
3 => 8,
6 => 6,
];
return $mapping[$code] ?? 7;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,313 @@
<?php
namespace Modules\Lpj\Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Modules\Basicdata\Models\Branch;
use Modules\Lpj\Models\Penilaian;
use Modules\Usermanagement\Models\User;
use Modules\Lpj\Models\PenilaianTeam;
use Modules\Lpj\Models\Permohonan;
class MigPenilaianAndPenilainTeamSeeder extends Seeder
{
protected $errorLogFile = __DIR__ . '/csv/penilaian/mig_penilaian_and_team_error.csv';
/**
* Run the database seeds.
*/
public function run()
{
// Bersihkan/Inisialisasi file error log
$this->initializeErrorLog();
// Path ke file csv
$filePath = realpath(__DIR__ . '/csv/penilaian/mig_penilaian_and_team.csv');
if (!$filePath) {
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/penilaian/mig_penilaian_and_team.csv');
$this->command->error('File csv tidak ditemukan.');
return;
}
if (($handle = fopen($filePath, 'r')) === false) {
Log::error('Gagal membuka file CSV: ' . $filePath);
$this->command->error('Gagal membuka file CSV.');
return;
}
$header = fgetcsv($handle, 0, '~');
$rows = [];
$batchSize = 500; // Ukuran batch
$userDataChace = [];
$nomorRegisCahce = [];
$errorCount = 0; // Inisialisasi variabel errorCount
$errorDebitureIds = []; // Inisialisasi array errorDebitureIds
$totalData = 0;
// Menghitung total data di file CSV
while (($data = fgetcsv($handle, 0, '~')) !== false) {
$totalData++;
}
rewind($handle); // Reset pointer ke awal file
fgetcsv($handle, 0, '~'); // Skip header
$batchCount = 0;
$currentRow = 0;
while (($data = fgetcsv($handle, 0, '~')) !== false) {
if (count($data) != count($header)) {
Log::warning('Baris CSV memiliki jumlah kolom yang tidak sesuai: ' . json_encode($data));
continue;
}
$rows[] = array_combine($header, $data);
$currentRow++;
// Jika sudah mencapai batch size, proses batch
if (count($rows) >= $batchSize) {
$batchCount++;
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
$this->processBatch($rows, $nomorRegisCahce, $userDataChace, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
$rows = [];
}
}
// Proses sisa data jika ada
// print_r($rows[0]);
if (!empty($rows)) {
$batchCount++;
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
$this->processBatch($rows, $nomorRegisCahce, $userDataChace, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
}
fclose($handle);
$this->command->info("Data debiture berhasil dimigrasikan. Total data: {$totalData}, Total batch: {$batchCount}, Total error: {$errorCount}");
}
private function processBatch(
array $rows,
array &$userDataChace,
array &$nomorRegisCahce,
int &$errorCount,
array &$errorDebitureIds,
int $totalData,
int $batchCount,
int $currentRow
) {
$userData = [];
foreach ($rows as $index => $row) {
try {
// Jalankan setiap baris dengan transaksi sendiri
DB::beginTransaction();
// Cek apakah sudah diproses
$existingRecord = Penilaian::where('nomor_registrasi', $row['mig_nomor_registrasi'])->first();
if ($existingRecord && $existingRecord->created_at) {
$this->command->info('Data sudah diproses sebelumnya: ' . $row['mig_nomor_registrasi']);
continue;
}
// Ambil nomor registrasi
$nomor_registrasi = $this->getNomorRegistrasiPermohonan($row['mig_nomor_registrasi'], $nomorRegisCahce);
if (!$nomor_registrasi) {
throw new \Exception("Nomor registrasi tidak valid");
}
// Ambil user ID
$userId = $this->getUserId($row['mig_user_id'], $userDataChace);
if (!$userId) {
// $this->logError($row['mig_user_id'], 'Salah satu user tidak ditemukan');
throw new \Exception($row['mig_user_id'] . " User tidak ditemukan");
continue;
}
$userIdUpdate = $this->getUserIdData($row['mig_created_by'] ?? null, $userData)['id'];
$userIdOtorisasi = $this->getUserIdData($row['mig_authorized_by'] ?? null, $userData)['id'];
if (!$userIdUpdate || !$userIdOtorisasi) {
// $this->logError($userIdUpdate, 'Salah satu user tidak ditemukan');
continue;
}
// Mapping field user
$mapUser = [
'created_by' => $userIdUpdate,
'updated_by' => $userIdUpdate,
'authorized_by' => $userIdOtorisasi,
];
// Ambil team ID
$teamId = $this->checkTeams($row['mig_team_id']);
if (!$teamId) {
throw new \Exception("Team tidak ditemukan");
}
// Buat penilaian
$penilaian = Penilaian::create([
'nomor_registrasi' => $nomor_registrasi,
'jenis_penilaian_id' => 1,
'tanggal_kunjungan' => $this->parseTimestamp($row['mig_tanggal_kunjungan']) ?? now(),
'waktu_penilaian' => $this->parseTimestamp($row['mig_waktu_penilaian']),
'status' => 'done',
'keterangan' => null,
'created_at' => $this->parseTimestamp($row['mig_created_at']),
'updated_at' => $this->parseTimestamp($row['mig_updated_at']),
'authorized_by' => $mapUser['authorized_by'],
'created_by' => $mapUser['created_by'],
'updated_by' => $mapUser['updated_by'],
]);
// Buat tim penilaian
$roles = ['surveyor', 'penilai'];
foreach ($roles as $role) {
PenilaianTeam::create([
'penilaian_id' => $penilaian->id,
'user_id' => $userId,
'role' => $role,
'team_id' => $teamId,
'created_at' => $this->parseTimestamp($row['mig_created_at']),
'updated_at' => $this->parseTimestamp($row['mig_updated_at']),
]);
}
// Commit transaksi
DB::commit();
$this->command->info('Proses data penilaian ' . $row['mig_nomor_lpj'] . ' (' . ($index + 1) . '/' . count($rows) . ')');
} catch (\Exception $e) {
// Rollback jika ada error
DB::rollBack();
Log::error('Error pada baris: ' . json_encode($row) . '. Pesan: ' . $e->getMessage());
$errorCount++;
$errorDebitureIds[] = $row['mig_team_id'] ?? '-';
$this->logError($row['mig_team_id'] ?? '-', $e->getMessage());
continue;
}
}
$this->command->info("Batch {$batchCount} selesai. Total error: " . count($errorDebitureIds));
}
private function getNomorRegistrasiPermohonan($nomor_registrasi_id, $nomorRegisCahce)
{
if (isset($nomorRegisCahce[$nomor_registrasi_id])) {
return $nomorRegisCahce[$nomor_registrasi_id];
}
$nomorRegis = Permohonan::where('nomor_registrasi', $nomor_registrasi_id)->first();
if (!$nomorRegis) {
return null;
}
$nomorRegisCahce[$nomor_registrasi_id] = $nomorRegis->nomor_registrasi;
return $nomorRegis->nomor_registrasi;
}
private function getUserIdData(?string $code, array &$cache): array
{
if (!$code) {
return ['id' => null, 'branch_id' => null];
}
if (isset($cache[$code])) {
return $cache[$code];
}
$user = User::where('nik', $code)->first();
if ($user) {
$cache[$code] = ['id' => $user->id, 'branch_id' => $user->branch_id];
return $cache[$code];
}
return ['id' => null, 'branch_id' => null];
}
private function getUserId($mig_user_id, $userDataChace)
{
if (isset($userDataChace[$mig_user_id])) {
return $userDataChace[$mig_user_id];
}
$userId = User::where('nik', $mig_user_id)->first();
if (!$userId) {
return null;
}
$userDataChace[$mig_user_id] = $userId->id;
return $userId->id;
}
private function checkTeams($code): int
{
$mapping = [
'01' => 1,
'02' => 2,
'04' => 4,
'07' => 5,
'06' => 3,
];
return $mapping[(string)$code] ?? 1;
}
private function parseTimestamp(?string $timestamp): ?string
{
try {
if ($timestamp) {
// Cek jika format hanya tanggal (Y-m-d)
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $timestamp)) {
return \Carbon\Carbon::createFromFormat('Y-m-d', $timestamp)
->startOfDay()
->toDateTimeString();
}
// Format lengkap (Y-m-d H:i:s)
return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString();
}
return null;
} catch (\Exception $e) {
Log::error('Gagal memparsing timestamp: ' . $timestamp . '. Pesan: ' . $e->getMessage());
return null;
}
}
private function initializeErrorLog()
{
// Jika file lama ada, hapus
if (file_exists($this->errorLogFile)) {
unlink($this->errorLogFile);
}
// Buat file baru dengan header
$handle = fopen($this->errorLogFile, 'w');
fputcsv($handle, ['mig_kd_debitur_seq', 'Error']);
fclose($handle);
}
private function logError(string $kode, string $message)
{
// Catat ke log
Log::error("Error migrasi debiture [$kode]: $message");
// Tulis ke file error
$handle = fopen($this->errorLogFile, 'a');
fputcsv($handle, [$kode, $message]);
fclose($handle);
}
}

View File

@@ -0,0 +1,246 @@
<?php
namespace Modules\Lpj\Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Modules\Basicdata\Models\Branch;
use Modules\Lpj\Models\Debiture;
use Modules\Usermanagement\Models\User;
class MigrationDebitureSeeder extends Seeder
{
protected $errorLogFile = __DIR__ . '/csv/debitures/error_migration.csv';
/**
* Run the database seeds.
*/
public function run()
{
// Bersihkan/Inisialisasi file error log
$this->initializeErrorLog();
// Path ke file csv
$filePath = realpath(__DIR__ . '/csv/debitures/mig_debiture.csv');
if (!$filePath) {
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/debitures/mig_debiture.csv');
$this->command->error('File csv tidak ditemukan.');
return;
}
if (($handle = fopen($filePath, 'r')) === false) {
Log::error('Gagal membuka file CSV: ' . $filePath);
$this->command->error('Gagal membuka file CSV.');
return;
}
$header = fgetcsv($handle, 0, '~');
$rows = [];
$batchSize = 500;
$userData = [];
$branchCache = [];
$totalData = 0;
// Hitung total baris
while (($data = fgetcsv($handle, 0, '~')) !== false) {
$totalData++;
}
rewind($handle);
fgetcsv($handle, 0, '~'); // Lewati header
$currentRow = 0;
$batchCount = 0;
while (($data = fgetcsv($handle, 0, '~')) !== false) {
if (count($data) != count($header)) {
$this->logError($data[0] ?? '-', 'Jumlah kolom tidak sesuai');
continue;
}
$rows[] = array_combine($header, $data);
$currentRow++;
if (count($rows) >= $batchSize) {
$batchCount++;
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
$this->processBatch($rows, $branchCache, $userData);
$rows = [];
}
}
// print_r($rows);
if (!empty($rows)) {
$batchCount++;
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
$this->processBatch($rows, $branchCache, $userData);
}
fclose($handle);
$this->command->info("Data debiture berhasil dimigrasikan. Total data: {$totalData}, Total batch: {$batchCount}");
}
private function processBatch(array $rows, array &$branchCache, array &$userData)
{
foreach ($rows as $index => $row) {
try {
$kode = $row['mig_kd_debitur_seq'] ?? '-';
// Cek apakah sudah diproses sebelumnya
$existingRecord = Debiture::where('mig_kd_debitur_seq', $kode)->first();
if ($existingRecord && $existingRecord->processed_at) {
$this->command->info("Data sudah diproses sebelumnya: $kode");
continue;
}
// Ambil branch_id
$branchId = $this->getBranchId($row['mig_kd_cabang'] ?? null, $branchCache);
if (!$branchId) {
$this->logError($kode, 'Cabang tidak ditemukan');
continue;
}
// Ambil user IDs berdasarkan NIK
$userIdUpdate = $this->getUserId($row['mig_user_update'] ?? null, $userData)['id'];
$userIdOtorisasi = $this->getUserId($row['mig_user_oto'] ?? null, $userData)['id'];
// if (!$userIdUpdate || !$userIdOtorisasi) {
// $this->logError($kode, 'Salah satu user tidak ditemukan');
// continue;
// }
// Mapping field user
$mapUser = [
'created_by' => $userIdUpdate,
'updated_by' => $userIdUpdate,
'authorized_by' => $userIdOtorisasi,
];
// Parsing nomor HP
$nomorHp = !empty($row['mig_phone']) ? preg_replace('/[^0-9]/', '', $row['mig_phone']) : null;
$email = !empty($row['email']) ? $row['email'] : null;
$nomorId = !empty($row['nomor_id']) ? $row['nomor_id'] : null;
// Parsing waktu
$authorizedAt = $this->parseTimestamp($row['mig_tgl_oto'] ?? null);
$createdAt = $this->parseTimestamp($row['created_at'] ?? null);
$updatedAt = $this->parseTimestamp($row['updated_at'] ?? null);
if (!$createdAt || !$updatedAt) {
$this->logError($kode, 'Gagal parsing created_at / updated_at');
continue;
}
// Simpan data
Debiture::create([
'branch_id' => $branchId,
'name' => $row['name'] ?? '',
'cif' => $row['cif'] ?: '0000000000',
'phone' => $nomorHp,
'nomor_id' => $nomorId,
'email' => $email,
'npwp' => null,
'address' => $row['address'] ?? null,
'authorized_at' => $authorizedAt,
'authorized_by' => $mapUser['authorized_by'],
'created_by' => $mapUser['created_by'] ?? null,
'updated_by' => $mapUser['updated_by'] ?? null,
'created_at' => $createdAt,
'updated_at' => $updatedAt,
'mig_kd_debitur_seq' => $row['mig_kd_debitur_seq'],
'processed_at' => now(),
'is_mig' => 1
]);
$this->command->info("Proses data debiture $kode (" . ($index + 1) . '/' . count($rows) . ')');
} catch (\Exception $e) {
$this->logError($row['mig_kd_debitur_seq'] ?? '-', "Error eksepsi: " . $e->getMessage());
}
}
}
private function getBranchId(?string $code, array &$cache): ?int
{
if (!$code) return null;
if (isset($cache[$code])) {
return $cache[$code];
}
$branch = Branch::where('code', $code)->first();
if ($branch) {
$cache[$code] = $branch->id;
return $branch->id;
}
return null;
}
private function getUserId(?string $code, array &$cache): array
{
if (!$code) return ['id' => null, 'branch_id' => null];
if (isset($cache[$code])) {
return $cache[$code];
}
$user = User::where('nik', $code)->first();
if ($user) {
$cache[$code] = ['id' => $user->id, 'branch_id' => $user->branch_id];
return $cache[$code];
}
return ['id' => null, 'branch_id' => null];
}
private function parseTimestamp(?string $timestamp): ?string
{
try {
if ($timestamp) {
// Cek jika format hanya tanggal (Y-m-d)
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $timestamp)) {
return \Carbon\Carbon::createFromFormat('Y-m-d', $timestamp)
->startOfDay()
->toDateTimeString();
}
// Format lengkap (Y-m-d H:i:s)
return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString();
}
return null;
} catch (\Exception $e) {
Log::error('Gagal memparsing timestamp: ' . $timestamp . '. Pesan: ' . $e->getMessage());
return null;
}
}
private function initializeErrorLog()
{
// Jika file lama ada, hapus
if (file_exists($this->errorLogFile)) {
unlink($this->errorLogFile);
}
// Buat file baru dengan header
$handle = fopen($this->errorLogFile, 'w');
fputcsv($handle, ['mig_kd_debitur_seq', 'Error']);
fclose($handle);
}
private function logError(string $kode, string $message)
{
// Catat ke log
Log::error("Error migrasi debiture [$kode]: $message");
// Tulis ke file error
$handle = fopen($this->errorLogFile, 'a');
fputcsv($handle, [$kode, $message]);
fclose($handle);
}
}

View File

@@ -0,0 +1,345 @@
<?php
namespace Modules\Lpj\Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Modules\Lpj\Models\Debiture;
use Modules\Location\Models\City;
use Modules\Location\Models\District;
use Modules\Location\Models\Province;
use Modules\Location\Models\Village;
use Modules\Lpj\Models\DokumenJaminan;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\JenisJaminan;
use Modules\Lpj\Models\JenisLegalitasJaminan;
use Modules\Lpj\Models\PemilikJaminan;
use Modules\Lpj\Models\DetailDokumenJaminan;
use Illuminate\Support\Facades\Log;
class MigrationDetailDokumenJaminanSeeder extends Seeder
{
protected $errorLogFile = __DIR__ . '/csv/detail-dokumen/mig_detail_dokument_external_error.csv';
/**
* Run the database seeds.
*/
public function run()
{
$this->initializeErrorLog();
// Path ke file csv
$filePath = realpath(__DIR__ . '/csv/detail-dokumen/mig_detail_dokument_external.csv');
if (!$filePath) {
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/detail-dokumen/mig_detail_dokument_external.csv');
$this->command->error('File csv tidak ditemukan.');
return;
}
if (($handle = fopen($filePath, 'r')) === false) {
Log::error('Gagal membuka file CSV: ' . $filePath);
$this->command->error('Gagal membuka file CSV.');
return;
}
$header = fgetcsv($handle, 0, '~');
$rows = [];
$batchSize = 1000; // Ukuran batch
$permohonanCache = [];
$jenisJaminanCache = [];
$dokumenJaminanCache = [];
$provinceCache = [];
$cityCache = [];
$districtCache = [];
$subdistrictCache = [];
$totalData = 0;
$errorCount = 0;
$errorDebitureIds = [];
$hubunganPemilikCache = [];
// Menghitung total data di file CSV
while (($data = fgetcsv($handle, 0, '~')) !== false) {
$totalData++;
}
rewind($handle); // Reset pointer ke awal file
fgetcsv($handle, 0, '~'); // Skip header
$batchCount = 0;
$currentRow = 0;
// Membaca setiap baris dalam CSV
while (($data = fgetcsv($handle, 0, '~')) !== false) {
if (count($data) != count($header)) {
Log::warning('Baris CSV memiliki jumlah kolom yang tidak sesuai: ' . json_encode($data));
$errorCount++;
$errorDebitureIds[] = $data[0] ?? 'ID tidak valid'; // Menyimpan ID yang error
continue;
}
$rows[] = array_combine($header, $data);
$currentRow++;
// print_r($rows);
if (count($rows) >= $batchSize) {
$errorDebitureIds[] = $data[0] ?? 'ID tidak valid'; // Menyimpan ID yang error
$this->processBatch($rows, $permohonanCache, $jenisJaminanCache, $dokumenJaminanCache, $batchCount, $currentRow, $totalData, $errorCount, $errorDebitureIds);
$rows = [];
}
}
// print_r($rows[0]);
if (!empty($rows)) {
$this->processBatch($rows, $permohonanCache, $jenisJaminanCache, $dokumenJaminanCache, $batchCount, $currentRow, $totalData, $errorCount, $errorDebitureIds);
}
fclose($handle);
$this->command->info('Data debiture berhasil dimigrasikan.');
}
private function processBatch(
array $rows,
array &$permohonanCache,
array &$jenisJaminanCache,
array &$dokumenJaminanCache,
int $batchCount,
int $currentRow,
int $totalData,
int &$errorCount,
array &$errorDebitureIds
) {
$groupedRows = $this->groupRowsByNomorLaporanAndKeterangan($rows);
// print_r($groupedRows);
foreach ($groupedRows as $nomorLaporan => $dataPerGrup) {
// print_r($dataPerGrup);
try {
// Ambil salah satu baris untuk referensi (misal baris pertama dari grup)
$firstRow = reset($dataPerGrup)['details'] ? reset($dataPerGrup) : reset($dataPerGrup);
$debiturId = null;
// Cari debitur ID dari salah satu field
foreach ($rows as $row) {
if ($row['mig_nomor_laporan'] == $nomorLaporan) {
$debiturId = $row['mig_kd_debitur_seq'] ?? null;
break;
}
}
if (!$debiturId) {
throw new \Exception('Debitur ID tidak ditemukan');
}
// Ambil ID dokumen jaminan
$dokumenJaminanId = $this->getDokumenJaminanId($debiturId, $dokumenJaminanCache);
if (!$dokumenJaminanId) {
throw new \Exception('Dokumen jaminan tidak ditemukan');
}
foreach ($dataPerGrup as $groupKey => $rowData) {
// Ambil legalitas jaminan ID berdasarkan grup keterangan
$legalitasJaminanId = $this->getLegalitasJaminanId($groupKey, $jenisJaminanCache);
if (!$legalitasJaminanId) {
throw new \Exception("Legalitas jaminan tidak ditemukan untuk grup: {$groupKey}");
}
// Simpan ke database
DetailDokumenJaminan::updateOrCreate(
[
'name' => $groupKey,
'dokumen_jaminan_id' => $dokumenJaminanId,
],
[
'details' => json_encode($rowData['details']),
'jenis_legalitas_jaminan_id' => $legalitasJaminanId,
'dokumen_jaminan' => !empty($rowData['documents']) ? json_encode($rowData['documents']) : null,
'dokumen_nomor' => $nomorLaporan,
'keterangan' => $groupKey,
]
);
}
// Info progress
$this->command->info("Proses data detail dokumen (Nomor Laporan: {$nomorLaporan}, batch ke: {$batchCount}, total dari: {$currentRow}/{$totalData})");
} catch (\Exception $e) {
Log::error("Error pada nomor laporan {$nomorLaporan}: " . $e->getMessage());
$this->logError($debiturId ?? '-', $e->getMessage());
$errorDebitureIds[] = $debiturId ?? '-';
$errorCount++;
}
}
}
private function groupRowsByNomorLaporann(array $rows): array
{
$grouped = [];
foreach ($rows as $row) {
$nomorJaminan = $row['mig_nomor_laporan'] ?? null;
if (!empty($nomorJaminan)) {
$grouped[$nomorJaminan][] = $row;
}
}
return $grouped;
}
// private function groupRowsByNomorLaporanAndKeterangan(array $rows): array
// {
// $groupedByNomorLaporan = $this->groupRowsByNomorLaporann($rows);
// $finalGrouped = [];
// foreach ($groupedByNomorLaporan as $nomorLaporan => $rowList) {
// $groupedByGrpKeterangan = [];
// // Urutkan berdasarkan mig_urutan_sub (ascending)
// usort($rowList, function ($a, $b) {
// return $a['mig_urutan_sub'] <=> $b['mig_urutan_sub'];
// });
// foreach ($rowList as $row) {
// $grpKeterangan = $row['mig_grp_keterangan'] ?? 'UNKNOWN_GROUP';
// if (!isset($groupedByGrpKeterangan[$grpKeterangan])) {
// $groupedByGrpKeterangan[$grpKeterangan] = [
// 'details' => [],
// 'documents' => []
// ];
// }
// $keyKeterangan = $row['mig_key_keterangan'] ?? 'UNKNOWN_KEY';
// $value = $row['mig_nilai'] ?? null;
// // Jika belum ada detail, inisialisasi sebagai array asosiatif
// if (empty($groupedByGrpKeterangan[$grpKeterangan]['details'])) {
// $groupedByGrpKeterangan[$grpKeterangan]['details'][] = [];
// }
// // Masukkan ke dalam object tunggal (bukan item baru)
// if ($value !== null) {
// $lastIndex = count($groupedByGrpKeterangan[$grpKeterangan]['details']) - 1;
// $groupedByGrpKeterangan[$grpKeterangan]['details'][$lastIndex][$keyKeterangan] = $value;
// }
// // Tambahkan dokumen jika ada
// $urlFile = $row['mig_url_file'] ?? null;
// if (!empty($urlFile)) {
// $groupedByGrpKeterangan[$grpKeterangan]['documents'][] = $urlFile;
// }
// }
// $finalGrouped[$nomorLaporan] = $groupedByGrpKeterangan;
// }
// // print_r($finalGrouped);
// return $finalGrouped;
// }
private function groupRowsByNomorLaporanAndKeterangan(array $rows): array
{
$groupedByNomorLaporan = $this->groupRowsByNomorLaporann($rows);
$finalGrouped = [];
foreach ($groupedByNomorLaporan as $nomorLaporan => $rowList) {
$groupedByGrpKeterangan = [];
// Urutkan berdasarkan mig_urutan_sub
usort($rowList, function ($a, $b) {
return $a['mig_urutan_sub'] <=> $b['mig_urutan_sub'];
});
foreach ($rowList as $row) {
$grpKeterangan = $row['mig_grp_keterangan'] ?? 'UNKNOWN_GROUP';
$keyKeterangan = $row['mig_key_keterangan'] ?? 'UNKNOWN_KEY';
$value = $row['mig_nilai'] ?? null;
if (!isset($groupedByGrpKeterangan[$grpKeterangan])) {
$groupedByGrpKeterangan[$grpKeterangan] = [
'details' => [],
'documents' => []
];
}
// Masukkan sebagai object baru ke dalam details
if ($value !== null) {
$groupedByGrpKeterangan[$grpKeterangan]['details'][] = [
$keyKeterangan => $value
];
}
// Dokumen tetap masuk sebagai array string
$urlFile = $row['mig_url_file'] ?? null;
if (!empty($urlFile)) {
$groupedByGrpKeterangan[$grpKeterangan]['documents'][] = $urlFile;
}
}
$finalGrouped[$nomorLaporan] = $groupedByGrpKeterangan;
}
return $finalGrouped;
}
private function getDokumenJaminanId(string $code, array &$dokumenJaminanCache)
{
if (isset($dokumenJaminanCache[$code])) {
return $dokumenJaminanCache[$code];
}
$dokumen = DokumenJaminan::where('mig_kd_debitur_seq', $code)->first();
if ($dokumen) {
$dokumenJaminanCache[$code] = $dokumen->id;
return $dokumen->id;
}
}
private function getLegalitasJaminanId(string $code, array &$legalitasJaminanCache)
{
if (isset($legalitasJaminanCache[$code])) {
return $legalitasJaminanCache[$code];
}
$legalitas = JenisLegalitasJaminan::whereRaw('LOWER(name) = ?', [strtolower($code)])->first();
if ($legalitas) {
$legalitasJaminanCache[$code] = $legalitas->id;
return $legalitas->id;
}
return null;
}
private function initializeErrorLog()
{
$file = $this->errorLogFile;
if (file_exists($file)) {
unlink($file); // Hapus file lama
}
$handle = fopen($file, 'w');
fputcsv($handle, ['mig_kd_debitur_seq', 'Error']);
fclose($handle);
}
private function logError(string $kode, string $message)
{
Log::error("Error migrasi dokumen jaminan [$kode]: $message");
$handle = fopen($this->errorLogFile, 'a');
fputcsv($handle, [$kode, $message]);
fclose($handle);
}
}

View File

@@ -0,0 +1,441 @@
<?php
namespace Modules\Lpj\Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Modules\Lpj\Models\Debiture;
use Modules\Location\Models\City;
use Modules\Location\Models\District;
use Modules\Location\Models\Province;
use Modules\Location\Models\Village;
use Modules\Lpj\Models\DokumenJaminan;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\JenisJaminan;
use Modules\Lpj\Models\PemilikJaminan;
use Modules\Lpj\Models\HubunganPemilikJaminan;
use Illuminate\Support\Facades\Log;
class MigrationDokumentJaminanSeeder extends Seeder
{
protected $errorLogFile = __DIR__ . '/csv/dokumen-pemilik/mig_pemilik_dan_dokument_external_error_log.csv';
/**
* Run the database seeds.
*/
public function run()
{
$this->initializeErrorLog();
// Path ke file csv
$filePath = realpath(__DIR__ . '/csv/dokumen-pemilik/mig_pemilik_dan_dokument_external.csv');
if (!$filePath) {
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/dokumen-pemilik/mig_pemilik_dan_dokument_external.csv');
$this->command->error('File csv tidak ditemukan.');
return;
}
if (($handle = fopen($filePath, 'r')) === false) {
Log::error('Gagal membuka file CSV: ' . $filePath);
$this->command->error('Gagal membuka file CSV.');
return;
}
$header = fgetcsv($handle, 0, '~');
$rows = [];
$batchSize = 1000; // Ukuran batch
$permohonanCache = [];
$jenisJaminanCache = [];
$pemilikJaminanCache = [];
$provinceCache = [];
$cityCache = [];
$districtCache = [];
$subdistrictCache = [];
$totalData = 0;
$errorCount = 0;
$errorDebitureIds = [];
$hubunganPemilikCache = [];
// Menghitung total data di file CSV
while (($data = fgetcsv($handle, 0, '~')) !== false) {
$totalData++;
}
rewind($handle); // Reset pointer ke awal file
fgetcsv($handle, 0, '~'); // Skip header
$batchCount = 0;
$currentRow = 0;
// Membaca setiap baris dalam CSV
while (($data = fgetcsv($handle, 0, '~')) !== false) {
if (count($data) != count($header)) {
Log::warning('Baris CSV memiliki jumlah kolom yang tidak sesuai: ' . json_encode($data));
$errorCount++;
$errorDebitureIds[] = $data[0] ?? 'ID tidak valid'; // Menyimpan ID yang error
continue;
}
$rows[] = array_combine($header, $data);
$currentRow++;
// print_r($rows);
if (count($rows) >= $batchSize) {
$errorDebitureIds[] = $data[0] ?? 'ID tidak valid'; // Menyimpan ID yang error
$this->processBatch($rows, $permohonanCache, $jenisJaminanCache, $pemilikJaminanCache, $provinceCache, $cityCache, $districtCache, $subdistrictCache, $batchCount, $currentRow, $totalData, $errorCount, $errorDebitureIds, $hubunganPemilikCache);
$rows = [];
}
}
// print_r($rows[0]);
if (!empty($rows)) {
$this->processBatch($rows, $permohonanCache, $jenisJaminanCache, $pemilikJaminanCache, $provinceCache, $cityCache, $districtCache, $subdistrictCache, $batchCount, $currentRow, $totalData, $errorCount, $errorDebitureIds, $hubunganPemilikCache);
}
fclose($handle);
$this->command->info('Data debiture berhasil dimigrasikan.');
}
/**
* Proses batch data.
*/
private function processBatch(
array $rows,
array &$permohonanCache,
array &$jenisJaminanCache,
array &$pemilikJaminanCache,
array &$provinceCache,
array &$cityCache,
array &$districtCache,
array &$subdistrictCache,
int $batchCount,
int $currentRow,
int $totalData,
int &$errorCount,
array &$errorDebitureIds,
array &$hubunganPemilikCache
) {
foreach ($rows as $index => $row) {
try {
// Jalankan transaksi per-baris
DB::beginTransaction();
// Cari permohonan
$permohonan = Permohonan::where('nomor_registrasi', $row['mig_nomor_jaminan'])->first();
if (empty($permohonan)) {
throw new \Exception('Missing debiture_id' . $row['mig_nomor_jaminan']);
continue;
}
// Pastikan permohonan_id belum digunakan di dokumen_jaminan
$existingDokumen = DokumenJaminan::where('permohonan_id', $permohonan->id)->first();
if ($existingDokumen) {
throw new \Exception("permohonan_id {$permohonan->id} sudah digunakan di dokumen_jaminan");
continue;
}
// Ambil lokasi
// jika external silahkan matikan ini
$proviceCode = $this->getProvinceCode($row['mig_province_name'], $provinceCache);
$cityCode = $this->getCityCode($row['mig_city_name'], $cityCache);
$districtCode = $this->getDistrictCode($row['mig_district_name'], $districtCache);
$subdistrict = $this->getSubdistrictCode($row['mig_village_name'], $subdistrictCache, $districtCache);
// $hubunganPemilik = $this->getHubunganPemilikJaminanId($row['mig_hubungan_pemilik_jaminan'], $hubunganPemilikCache);
$pemilik_jaminan_name = $this->getDebitureId($row['mig_kd_debitur_seq'], $pemilikJaminanCache);
// Buat Pemilik Jaminan
$pemilik_jaminan = PemilikJaminan::updateOrCreate([
'debiture_id' => $permohonan->debiture_id,
'hubungan_pemilik_jaminan_id' => 1,
// 'name' => $row['name'],
'name' => $pemilik_jaminan_name,
'detail_sertifikat' => null,
'npwp' => null,
'nomor_id' => null,
'email' => null,
'phone' => null,
// jika external silahkan matikan ini
'province_code' => $proviceCode,
'city_code' => $cityCode,
'district_code' => $districtCode,
'village_code' => $subdistrict['code'],
'postal_code' => $subdistrict['postal_code'],
'address' => $row['address'],
'created_at' => $this->parseTimestamp($row['created_at']),
'updated_at' => $this->parseTimestamp($row['updated_at']),
'mig_kd_debitur_seq' => $row['mig_kd_debitur_seq'],
'processed_at' => now(),
'is_mig' => 1
]);
// Buat Dokumen Jaminan
DokumenJaminan::updateOrCreate([
'debiture_id' => $permohonan->debiture_id,
'permohonan_id' => $permohonan->id,
'jenis_jaminan_id' => $this->getJaminanId($row['mig_jenis_seq']),
'pemilik_jaminan_id' => $pemilik_jaminan->id,
// jika external silahkan matikan ini
// 'province_code' => $proviceCode,
// 'city_code' => $cityCode,
// 'district_code' => $districtCode,
// 'village_code' => $subdistrict['code'],
// 'postal_code' => $subdistrict['postal_code'],
'address' => $row['address'],
'created_at' => $this->parseTimestamp($row['created_at']),
'updated_at' => $this->parseTimestamp($row['updated_at']),
'mig_kd_debitur_seq' => $row['mig_kd_debitur_seq'],
'processed_at' => now(),
'is_mig' => 1
]);
// Commit jika semua sukses
DB::commit();
$this->command->info("Proses dokumen jaminan: " . $row['mig_kd_debitur_seq'] . "Batch: {$batchCount} Baris: {$currentRow} Total: {$totalData} Error: {$errorCount}");
} catch (\Exception $e) {
// Rollback hanya untuk baris ini
DB::rollBack();
Log::error("Error pada baris: " . json_encode($row) . ". Pesan: " . $e->getMessage());
$this->logError($row['mig_kd_debitur_seq'] ?? '-', $e->getMessage());
$errorDebitureIds[] = $row['mig_kd_debitur_seq'] ?? '-';
continue;
}
}
$this->command->info("Batch {$batchCount} selesai. Total error: " . count($errorDebitureIds));
}
// private function getPermohonanId($code,$cache)
// {
// if (isset($cache[$code])) {
// return $cache[$code];
// }
// $permohonan = Permohonan::where('mig_kd_debitur_seq', $code)->where('nomor_registrasi', $mig_nomor_jaminan)->first();
// if ($permohonan) {
// $cache[$code] = $permohonan;
// return $permohonan;
// }
// return null;
// }
private function getJaminanId($code): ?int
{
$mapping = [
7 => 17,
8 => 13,
6 => 32,
1 => 17,
2 => 26,
3 => 27,
4 => 50,
5 => 21,
138051314724 => 23,
138027243057 => 34,
138027664224 => 35,
138027738489 => 10,
138051485796 => 48,
138051492883 => 47,
138051515419 => 40,
138051753311 => 41,
138051754843 => 46,
138051759078 => 42,
138051480538 => 45,
123382184742 => 18,
138051483711 => 44,
991 => 52
];
return $mapping[$code] ?? 17;
}
private function getPemilikJaminanId(string $code, array &$cache): ?int
{
if (isset($cache[$code])) {
return $cache[$code];
}
$jaminan = PemilikJaminan::where('mig_kd_debitur_seq', $code)->first();
if ($jaminan) {
$cache[$code] = $jaminan->id;
return $jaminan->id;
}
return 1;
}
private function getDebitureId(string $code, array &$cache): ?string
{
if (isset($cache[$code])) {
return $cache[$code];
}
$debiture = Debiture::where('mig_kd_debitur_seq', $code)->first();
if ($debiture) {
$cache[$code] = $debiture->name;
return $debiture->name;
}
return null;
}
private function getProvinceCode(string $name, array &$cache): ?string
{
$normalizedName = strtolower($name);
if (isset($cache[$normalizedName])) {
return $cache[$normalizedName];
}
$province = Province::whereRaw('LOWER(name) = ?', [strtolower($name)])->first();
if ($province) {
$cache[$normalizedName] = $province->code;
return $province->code;
}
return null;
}
private function getCityCode(string $name, array &$cache): ?string
{
$normalizedName = strtolower($name);
if (isset($cache[$normalizedName])) {
return $cache[$normalizedName];
}
$city = City::whereRaw('LOWER(name) = ?', [strtolower($name)])->first();
if ($city) {
$cache[$normalizedName] = $city->code;
return $city->code;
}
return null;
}
private function getDistrictCode(string $name, array &$cache): ?string
{
$normalizedName = strtolower($name);
if (isset($cache[$normalizedName])) {
return $cache[$normalizedName];
}
$district = District::whereRaw('LOWER(name) = ?', [strtolower($name)])->first();
if ($district) {
$cache[$normalizedName] = $district->code;
return $district->code;
}
return null;
}
private function getSubdistrictCode(string $name, array &$cache, array &$districtCache): ?array
{
$normalizedName = strtolower($name);
// Pastikan cache menyimpan array, bukan hanya kode
if (isset($cache[$normalizedName])) {
return $cache[$normalizedName];
}
// Ambil subdistrict dari database
$subdistrict = Village::whereRaw('LOWER(name) = ?', [$normalizedName])->first();
// Jika ditemukan, simpan ke dalam cache sebagai array lengkap
if ($subdistrict) {
$cache[$normalizedName] = [
'code' => $subdistrict->code,
'postal_code' => $subdistrict->postal_code
];
return $cache[$normalizedName];
}
// Jika tidak ditemukan, kembalikan null
return [
'code' => null,
'postal_code' => null
];
}
private function getHubunganPemilikJaminanId(string $code, array &$cache): ?int
{
if (isset($cache[$code])) {
return $cache[$code];
}
$jaminan = HubunganPemilikJaminan::whereRaw('LOWER(name) = ?', [strtolower($code)])->first();
if ($jaminan) {
$cache[$code] = $jaminan->id;
return $jaminan->id;
}
return null;
}
/**
* Mengonversi nilai TIMESTAMP menjadi format datetime yang valid.
*/
private function parseTimestamp(?string $timestamp): ?string
{
try {
if ($timestamp) {
// Cek jika format hanya tanggal (Y-m-d)
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $timestamp)) {
return \Carbon\Carbon::createFromFormat('Y-m-d', $timestamp)
->startOfDay()
->toDateTimeString();
}
// Format lengkap (Y-m-d H:i:s)
return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString();
}
return null;
} catch (\Exception $e) {
Log::error('Gagal memparsing timestamp: ' . $timestamp . '. Pesan: ' . $e->getMessage());
return null;
}
}
private function initializeErrorLog()
{
$file = $this->errorLogFile;
if (file_exists($file)) {
unlink($file); // Hapus file lama
}
$handle = fopen($file, 'w');
fputcsv($handle, ['mig_kd_debitur_seq', 'Error']);
fclose($handle);
}
private function logError(string $kode, string $message)
{
Log::error("Error migrasi dokumen jaminan [$kode]: $message");
$handle = fopen($this->errorLogFile, 'a');
fputcsv($handle, [$kode, $message]);
fclose($handle);
}
}

View File

@@ -0,0 +1,292 @@
<?php
namespace Modules\Lpj\Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Modules\Lpj\Models\Inspeksi;
use Modules\Basicdata\Models\Branch;
use Modules\Lpj\Models\DokumenJaminan;
use Modules\Lpj\Models\Permohonan;
use DateTime;
class MigrationGambarInspeksiSeeder extends Seeder
{
/**
* Run the database seeds.
*/
protected $errorLogFile = __DIR__ . '/csv/inspeksi/mig_inspeksi_foto_20253_error.csv';
/**
* Migrasi data gambar inspeksi dari file csv ke tabel inspeksi_gambar
*
* @return void
*/
public function run()
{
$this->initializeErrorLog();
// Path ke file csv
$filePath = realpath(__DIR__ . '/csv/inspeksi/mig_inspeksi_foto_20253.csv');
if (!$filePath) {
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/inspeksi/mig_inspeksi_foto_20253.csv');
$this->command->error('File csv tidak ditemukan.');
return;
}
if (($handle = fopen($filePath, 'r')) === false) {
Log::error('Gagal membuka file CSV: ' . $filePath);
$this->command->error('Gagal membuka file CSV.');
return;
}
$header = fgetcsv($handle, 0, '~');
$rows = [];
$batchSize = 500;
$userData = [];
$branchCache = []; // <-- Gunakan sebagai cache
$totalData = 0;
while (($data = fgetcsv($handle, 0, '~')) !== false) {
$totalData++;
}
rewind($handle);
fgetcsv($handle, 0, '~'); // Skip header
$batchCount = 0;
$currentRow = 0;
$errorCount = 0;
$errorDebitureIds = [];
while (($data = fgetcsv($handle, 0, '~')) !== false) {
if (count($data) != count($header)) {
Log::warning('Baris CSV memiliki jumlah kolom yang tidak sesuai: ' . json_encode($data));
continue;
}
$rows[] = array_combine($header, $data);
$currentRow++;
if (count($rows) >= $batchSize) {
$batchCount++;
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
$this->processBatch($rows, $branchCache, $userData, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
$rows = [];
}
}
// info_harga_laporan_202505021522.csv
// print_r($rows[0]);
if (!empty($rows)) {
$batchCount++;
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
$this->processBatch($rows, $branchCache, $userData, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
}
fclose($handle);
$this->command->info("Data debiture berhasil dimigrasikan. Total data: {$totalData}, Total batch: {$batchCount}");
}
private function processBatch(array $rows, array &$branchCache, array &$userData, int &$errorCount, array &$errorDebitureIds, int $totalData, int $batchCount, int $currentRow)
{
// Kelompokkan berdasarkan mig_nomor_jaminan
$groupedRows = $this->groupRowsByJaminan($rows);
foreach ($groupedRows as $nomorJaminan => $groupRows) {
try {
// Ambil informasi permohonan dan dokument_id
$nomorRegis = $this->getNomorRegistrasiPermohonan($nomorJaminan, $branchCache);
if (!$nomorRegis) {
Log::warning("Nomor registrasi tidak ditemukan untuk nomor jaminan: {$nomorJaminan}");
$errorCount++;
$errorDebitureIds[] = $nomorJaminan;
continue;
}
// Bangun JSON foto_form
$fotoJson = $this->checkFoto($groupRows);
Inspeksi::where('permohonan_id', $nomorRegis['id'])
->where('dokument_id', $nomorRegis['dokument_id'])
->whereNotNull('data_form')
->update([
'foto_form' => $fotoJson,
'updated_at' => now()
]);
$this->command->info("Berhasil update foto_form untuk nomor jaminan: {$nomorJaminan}");
} catch (\Exception $e) {
Log::error("Error pada nomor jaminan {$nomorJaminan}: " . $e->getMessage());
$errorCount++;
$errorDebitureIds[] = $nomorJaminan;
continue;
}
}
}
private function groupRowsByJaminan(array $rows): array
{
$grouped = [];
foreach ($rows as $row) {
$nomorJaminan = $row['mig_nomor_jaminan'] ?? null;
if (!empty($nomorJaminan)) {
$grouped[$nomorJaminan][] = $row;
}
}
return $grouped;
}
private function checkFoto(array $rows)
{
// Inisialisasi kelompok untuk tiap kategori
$kategoriPrioritas = [
'PETA LOKASI' => [],
'GAMBAR SITUASI / SURAT UKUR' => [],
'FOTO JAMINAN' => [],
'lainnya' => []
];
foreach ($rows as $row) {
// Ambil kolom penting
$namaFoto = trim($row['mig_nama_gambar'] ?? '');
$pathFoto = trim($row['mig_url_gambar'] ?? '');
$kategori = trim($row['mig_kategori'] ?? 'lainnya');
$urutan = (int)($row['mig_urutan_gambar'] ?? 999);
$tgl = trim($row['mig_tgl'] ?? '');
$nomorLpj = trim($row['mig_nomor_laporan'] ?? '');
if (empty($pathFoto) || empty($tgl)) {
continue; // Lewati jika tidak lengkap
}
try {
$tanggal = \Carbon\Carbon::createFromFormat('Y-m-d', $tgl);
if (!$tanggal) {
throw new \Exception("Tanggal tidak valid");
}
} catch (\Exception $e) {
continue; // Lewati jika tanggal tidak valid
}
$tahun = $tanggal->format('Y');
$bulanAngka = $tanggal->format('n');
$bulanNama = [
1 => 'JANUARI', 2 => 'FEBRUARI', 3 => 'MARET',
4 => 'APRIL', 5 => 'MEI', 6 => 'JUNI',
7 => 'JULI', 8 => 'AGUSTUS', 9 => 'SEPTEMBER',
10 => 'OKTOBER', 11 => 'NOVEMBER', 12 => 'DESEMBER'
][(int)$bulanAngka] ?? 'UNKNOWN';
$tanggalFormat = $tanggal->format('dmY');
if (empty($namaFoto)) {
$namaFoto = basename($pathFoto) ?: 'image.jpg';
}
// Gunakan '/' sebagai separator path
$finalPath = "surveyor/{$tahun}/{$bulanNama}/{$tanggalFormat}/{$nomorLpj}/{$pathFoto}";
$fotoItem = [
'urutan' => $urutan,
'name' => $namaFoto,
'path' => $finalPath,
'category' => $kategori,
'sub' => null,
'description' => '',
'created_by' => null,
'created_at' => null
];
// Masukkan ke dalam kelompok kategori
if (isset($kategoriPrioritas[$kategori])) {
$kategoriPrioritas[$kategori][] = $fotoItem;
} else {
$kategoriPrioritas['lainnya'][] = $fotoItem;
}
}
// Urutkan masing-masing kategori berdasarkan urutan
foreach ($kategoriPrioritas as &$kelompok) {
usort($kelompok, function ($a, $b) {
return $a['urutan'] <=> $b['urutan'];
});
}
// Gabungkan dengan urutan prioritas: PETA LOKASI -> GAMBAR SITUASI -> FOTO JAMINAN -> lainnya
$finalFotos = array_merge(
$kategoriPrioritas['PETA LOKASI'],
$kategoriPrioritas['GAMBAR SITUASI / SURAT UKUR'],
$kategoriPrioritas['FOTO JAMINAN'],
$kategoriPrioritas['lainnya']
);
// Hapus indeks 'urutan'
$finalFotos = array_map(function ($foto) {
unset($foto['urutan']);
return $foto;
}, $finalFotos);
return json_encode([
'upload_foto' => $finalFotos
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
}
private function getNomorRegistrasiPermohonan($nomor_jaminan_id, array &$cache)
{
// Cek apakah sudah ada di cache
if (isset($cache[$nomor_jaminan_id])) {
return $cache[$nomor_jaminan_id];
}
// Cari di tabel Permohonan berdasarkan nomor registrasi
$permohonan = Permohonan::where('nomor_registrasi', $nomor_jaminan_id)->first();
if (!$permohonan) {
// Tidak ditemukan
$cache[$nomor_jaminan_id] = null;
return null;
}
// Cari dokument jaminan terkait
$dokumenJaminan = DokumenJaminan::where('permohonan_id', $permohonan->id)->first();
// Simpan hasil ke cache
$result = [
'id' => $permohonan->id,
'dokument_id' => $dokumenJaminan ? $dokumenJaminan->id : null
];
$cache[$nomor_jaminan_id] = $result;
return $result;
}
private function initializeErrorLog()
{
$file = $this->errorLogFile;
if (file_exists($file)) {
unlink($file); // Hapus file lama
}
$handle = fopen($file, 'w');
fputcsv($handle, ['mig_kd_debitur_seq', 'Error']);
fclose($handle);
}
private function logError(string $kode, string $message)
{
Log::error("Error migrasi dokumen jaminan [$kode]: $message");
$handle = fopen($this->errorLogFile, 'a');
fputcsv($handle, [$kode, $message]);
fclose($handle);
}
}

View File

@@ -0,0 +1,858 @@
<?php
namespace Modules\Lpj\Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Modules\Lpj\Models\Inspeksi;
use Modules\Basicdata\Models\Branch;
use Modules\Lpj\Models\DokumenJaminan;
use Modules\Lpj\Models\Permohonan;
use Modules\Location\Models\City;
use Modules\Location\Models\District;
use Modules\Location\Models\Province;
use Modules\Location\Models\Village;
// Load file helper
require_once __DIR__ . '/MigInspeksiHelper.php';
class MigrationInpseksiSeeder extends Seeder
{
protected $errorLogFile = __DIR__ . '/csv/inspeksi/mig_inspeksi_2025_error.csv';
// protected $fielKesimpulan = ;
/**
* Run the database seeds.
*/
public function run()
{
$this->initializeErrorLog();
// Path ke file csv
$filePath = realpath(__DIR__ . '/csv/inspeksi/mig_inspeksi_2025.csv');
if (!$filePath) {
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/inspeksi/mig_inspeksi_2025.csv');
$this->command->error('File csv tidak ditemukan.');
return;
}
if (($handle = fopen($filePath, 'r')) === false) {
Log::error('Gagal membuka file CSV: ' . $filePath);
$this->command->error('Gagal membuka file CSV.');
return;
}
$header = fgetcsv($handle, 0, '~');
$rows = [];
$batchSize = 500;
$userData = [];
$branchCache = []; // <-- Gunakan sebagai cache
$totalData = 0;
while (($data = fgetcsv($handle, 0, '~')) !== false) {
$totalData++;
}
rewind($handle);
fgetcsv($handle, 0, '~'); // Skip header
$batchCount = 0;
$currentRow = 0;
$errorCount = 0;
$errorDebitureIds = [];
while (($data = fgetcsv($handle, 0, '~')) !== false) {
if (count($data) != count($header)) {
Log::warning('Baris CSV memiliki jumlah kolom yang tidak sesuai: ' . json_encode($data));
continue;
}
$rows[] = array_combine($header, $data);
$currentRow++;
if (count($rows) >= $batchSize) {
$batchCount++;
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
$this->processBatch($rows, $branchCache, $userData, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
$rows = [];
}
}
if (!empty($rows)) {
$batchCount++;
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
$this->processBatch($rows, $branchCache, $userData, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
}
fclose($handle);
$this->command->info("Data debiture berhasil dimigrasikan. Total data: {$totalData}, Total batch: {$batchCount}");
}
private function processBatch(
array $rows,
array &$branchCache,
array &$debitureCache,
int &$errorCount,
array &$errorDebitureIds,
int $totalData,
int $batchCount,
int $currentRow
) {
// Kelompokkan baris berdasarkan mig_nomor_jaminan
$groupedData = $this->groupRowsByJaminan($rows);
foreach ($groupedData as $nomorJaminan => $groupRows) {
try {
// Ambil informasi permohonan
$nomorRegis = $this->getNomorRegistrasiPermohonan($nomorJaminan, $branchCache);
if (!$nomorRegis) {
Log::warning("Nomor registrasi tidak ditemukan untuk nomor jaminan: {$nomorJaminan}");
$errorCount++;
$errorDebitureIds[] = $nomorJaminan;
continue;
}
// Cek apakah sudah ada data
$existingRecord = Inspeksi::where('permohonan_id', $nomorRegis['id'])
->where('dokument_id', $nomorRegis['dokument_id'])
->whereNotNull('data_form')
->first();
if ($existingRecord) {
$this->command->info("Data untuk nomor jaminan {$nomorJaminan} sudah ada. Lewati...");
continue;
}
// Ambil baris pertama untuk created_at/updated_at
$firstRow = reset($groupRows);
// Bangun JSON lengkap
$dataFormJson = $this->buildFullDataForm($groupRows);
$jenisJaminan = $this->checkJenisJaminan($groupRows[0]['mig_name'] ?? '');
if (!$dataFormJson) {
Log::warning("Data form kosong untuk nomor jaminan: {$nomorJaminan}");
$errorCount++;
$errorDebitureIds[] = $nomorJaminan;
continue;
}
// Simpan ke database hanya sekali per grup
Inspeksi::create([
'name' => $jenisJaminan,
'data_form' => $dataFormJson,
'foto_form' => null,
'data_pembanding' => null,
'permohonan_id' => $nomorRegis['id'] ?? null,
'dokument_id' => $nomorRegis['dokument_id'] ?? null,
'created_at' => $this->parseTimestamp($firstRow['created_at'] ?? null),
'updated_at' => $this->parseTimestamp($firstRow['updated_at'] ?? null),
'nomor_lpj' => $nomorJaminan,
'processed_at' => now(),
'is_mig' => 1
]);
$this->command->info("Berhasil simpan data inspeksi untuk nomor jaminan: {$nomorJaminan}");
} catch (\Exception $e) {
Log::error("Error pada nomor jaminan {$nomorJaminan}: " . $e->getMessage());
$errorCount++;
$errorDebitureIds[] = $nomorJaminan;
continue;
}
}
}
private function groupRowsByJaminan(array $rows): array
{
$grouped = [];
foreach ($rows as $row) {
$nomorJaminan = $row['mig_nomor_jaminan'] ?? null;
if (!empty($nomorJaminan)) {
$grouped[$nomorJaminan][] = $row;
}
}
return $grouped;
}
private function getNomorRegistrasiPermohonan($nomor_jaminan_id, array &$cache)
{
// Cek apakah sudah ada di cache
if (isset($cache[$nomor_jaminan_id])) {
return $cache[$nomor_jaminan_id];
}
// Cari di tabel Permohonan berdasarkan nomor registrasi
$permohonan = Permohonan::where('nomor_registrasi', $nomor_jaminan_id)->first();
if (!$permohonan) {
// Tidak ditemukan
$cache[$nomor_jaminan_id] = null;
return null;
}
// Cari dokument jaminan terkait
$dokumenJaminan = DokumenJaminan::where('permohonan_id', $permohonan->id)->first();
// Simpan hasil ke cache
$result = [
'id' => $permohonan->id,
'dokument_id' => $dokumenJaminan ? $dokumenJaminan->id : null
];
$cache[$nomor_jaminan_id] = $result;
return $result;
}
private function buildFullDataForm(array $rows)
{
if (empty($rows)) {
return null;
}
$jenisJaminan = $rows[0]['mig_name'] ?? null;
if (!$jenisJaminan) {
return null;
}
try {
$jsonResult = $this->checkBuildJson($jenisJaminan, $rows);
// Validasi apakah hasil JSON valid
json_decode($jsonResult);
return $jsonResult;
} catch (\Exception $e) {
Log::error("Gagal build JSON untuk jenis jaminan {$jenisJaminan}: " . $e->getMessage());
return null;
}
}
private function loadKesimpulanByNomorLpj($nomorLpj)
{
$filePath = realpath(__DIR__ . '/csv/inspeksi/mig_inspeksi_kesimpulan_2025.csv');
if (!$filePath || !$nomorLpj) {
return [];
}
if (($handle = fopen($filePath, 'r')) === false) {
Log::error("Gagal membuka file CSV kesimpulan: " . $filePath);
return [];
}
$header = fgetcsv($handle, 0, '~');
$result = [];
while (($data = fgetcsv($handle, 0, '~')) !== false) {
if (count($data) != count($header)) {
continue;
}
$row = array_combine($header, $data);
if ($row['mig_nomor_lpj'] === $nomorLpj) {
$result[] = $row;
}
}
// print_r($result);
fclose($handle);
return $result;
}
private function checkLingkungan($rows)
{
$dataToInsertJson = [];
// Inisialisasi struktur lingkungan
$lingkungan = [
'jarak_jalan_utama' => null,
'jalan_linkungan' => null,
'jarak_cbd_point' => null,
'nama_cbd_point' => null,
'lebar_perkerasan_jalan' => null,
'perkerasan_jalan' => ['perkerasan_jalan' => [], 'lainnya' => null],
'lalu_lintas' => null,
'gol_mas_sekitar' => [],
'tingkat_keramaian' => [],
'terletak_diarea' => ['terletak_diarea' => [], 'lainnya' => null],
'disekitar_lokasi' => null,
'kondisi_bagunan_disekitar_lokasi' => null,
'sifat_bagunan_disekitar_lokasi' => null,
'dekat_makam' => 'tidak',
'jarak_makam' => null,
'nama_makam' => null,
'dekat_tps' => 'tidak',
'jarak_tps' => null,
'nama_tps' => null,
'dekat_lainnya' => null,
'merupakan_daerah' => [],
'fasilitas_dekat_object' => [],
'fasilitas_dekat_object_input' => [
'Tempat Ibadah' => null,
'Rumah Sakit' => null,
'Sekolah' => null,
'Kantor Pemerintahan' => null,
'Stasiun Kereta' => null,
'Terminal Bus' => null,
'Bandara' => null,
'Pos Polisi' => null,
'Lainnya' => null
]
];
foreach ($rows as $row) {
$name = trim($row['name']);
$value = !empty($row['mig_name_keterangan_lain']) ? $row['mig_name_keterangan_lain'] : $row['mig_name_keterangan'];
switch ($name) {
case 'Lebar jalan dimuka lokasi':
$lingkungan['lebar_perkerasan_jalan'] = $row['mig_name_keterangan_lain'];
break;
case 'Lapisan perkerasan jalan dari':
if ($value === 'Lainnya') {
$lingkungan['perkerasan_jalan']['perkerasan_jalan'][] = $value;
$lingkungan['perkerasan_jalan']['lainnya'] = $row['mig_name_keterangan_lain'];
} else {
$lingkungan['perkerasan_jalan']['perkerasan_jalan'][] = $value;
}
break;
case 'Lalulintas didepan lokasi':
$lingkungan['lalu_lintas'] = $value;
break;
case 'Golongan Masyarakat sekitar':
$lingkungan['gol_mas_sekitar'][] = $value;
break;
case 'Dengan kondisi':
$lingkungan['tingkat_keramaian'][] = $value;
break;
case 'Terletak didaerah':
if ($value === 'Lainnya') {
$lingkungan['terletak_diarea']['terletak_diarea'][] = $value;
$lingkungan['terletak_diarea']['lainnya'] = $row['mig_name_keterangan_lain'];
} else {
$lingkungan['terletak_diarea']['terletak_diarea'][] = $value;
}
break;
case 'Disekitar lokasi':
$lingkungan['disekitar_lokasi'] = $value === 'Telah ada bangunan' ? 'sesuai' : 'tidak sesuai';
break;
case 'Merupakan daerah':
$lingkungan['merupakan_daerah'][] = $value;
break;
case 'Fasilitas umum dekat lokasi':
$lingkungan['fasilitas_dekat_object'][] = $value;
if (isset($lingkungan['fasilitas_dekat_object_input'][$value])) {
$lingkungan['fasilitas_dekat_object_input'][$value] = $value;
} elseif ($value === 'Pasar / Swalayan') {
$lingkungan['fasilitas_dekat_object_input']['Lainnya'] = 'pasar';
}
break;
}
}
// Isi default jika kosong
if (empty($lingkungan['fasilitas_dekat_object'])) {
$lingkungan['fasilitas_dekat_object'] = [];
}
// Masukkan ke array JSON
$dataToInsertJson[] = json_encode([
'lingkungan' => $lingkungan
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
return $dataToInsertJson;
}
private function checkAsset(array $rows)
{
$dataToInsertJson = [];
// Ambil baris pertama saja
$firstRow = reset($rows);
if (!$firstRow) {
return [];
}
// Inisialisasi variabel dari baris pertama
$hubCadeb = null;
$hubPenghuni = null;
$jenisAsset = null;
// Ambil data utama dari baris pertama
$pihakBank = $firstRow['mig_pihak_bank'] ?? null;
$debiturPerwakilan = $firstRow['mig_debiture_perwakilan'] ?? null;
$address = $firstRow['address'] ?? null;
// Kode wilayah
$provinceCache = []; // cache untuk helper
$cityCache = [];
$districtCache = [];
$subdistrictCache = [];
$proviceCode = $this->getProvinceCode($firstRow['mig_village_name'] ?? '', $provinceCache);
$cityCode = $this->getCityCode($firstRow['mig_city_name'] ?? '', $cityCache);
$districtCode = $this->getDistrictCode($firstRow['mig_district_name'] ?? '', $districtCache);
$subdistrict = $this->getSubdistrictCode($firstRow['mig_province_name'] ?? '', $subdistrictCache, $districtCache);
// Proses hubungan pemilik/penghuni & jenis asset dari seluruh rows
foreach ($rows as $row) {
$name = trim($row['name'] ?? '');
$keySesuaiORTidak = !empty($row['mig_name_keterangan_lain']) ? 'sesuai' : 'tidak sesuai';
$value = !empty($row['mig_name_keterangan_lain'])
? $row['mig_name_keterangan_lain']
: $row['mig_name_keterangan'] ?? null;
switch ($name) {
case 'Hubungan Pemilik Jaminan dengan Debitur':
$hubCadeb = [
$keySesuaiORTidak => $value
];
break;
case 'Hubungan Penghuni Jaminan dengan Debitur':
$hubPenghuni = [
$keySesuaiORTidak => $value
];
break;
case 'Jenis Bangunan':
$jenisAsset = [
$keySesuaiORTidak => $value
];
break;
}
}
// Isi default jika kosong
if (empty($hubCadeb)) {
$hubCadeb = ["tidak sesuai" => null];
}
if (empty($hubPenghuni)) {
$hubPenghuni = ["tidak sesuai" => null];
}
if (empty($jenisAsset)) {
$jenisAsset = ["sesuai" => null];
}
// Bangun struktur JSON
$asset = [
"debitur_perwakilan" => $debiturPerwakilan,
"jenis_asset" => $jenisAsset,
"alamat" => [
"sesuai" => [
"address" => $address,
"village_code" => $subdistrict['code'],
"district_code" => $districtCode,
"city_code" => $cityCode,
"province_code" => $proviceCode
]
],
"hub_cadeb" => $hubCadeb,
"hub_cadeb_penghuni" => $hubPenghuni,
"pihak_bank" => $pihakBank,
"kordinat_lng" => null,
"kordinat_lat" => null
];
// Masukkan ke array JSON
$dataToInsertJson[] = json_encode([
"asset" => $asset
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
return $dataToInsertJson;
}
private function checkKesimpulan($rows)
{
$dataToInsertJson = [];
$fakta = [
'fakta_positif' => [],
'fakta_negatif' => [],
'rute_menuju' => null,
'batas_batas' => ["Utara", "Timur", "Selatan", "Barat"],
'batas_batas_input' => [
"Utara" => null,
"Timur Laut" => null,
"Timur" => null,
"Tenggara" => null,
"Selatan" => null,
"Barat Daya" => null,
"Barat" => null,
"Barat Laut" => null,
"Utara Timur Laut" => null,
"Timur Timur Laut" => null,
"Timur Tenggara" => null,
"Selatan Tenggara" => null,
"Selatan Barat Daya" => null,
"Barat Barat Daya" => null,
"Barat Barat Laut" => null,
"Utara Barat Laut" => null
],
'kondisi_lingkungan' => [],
'kondisi_lain_bangunan' => [],
'informasi_dokument' => [],
'peruntukan' => null,
'kdb' => null,
'kdh' => null,
'gsb' => null,
'max_lantai' => null,
'klb' => null,
'gss' => null,
'pelebaran_jalan' => null,
'nama_petugas' => null,
'keterangan' => [],
'saran' => []
];
foreach ($rows as $row) {
$jenis = trim($row['mig_keterangan']); // misal: Fakta Positif, Fakta Negatif, dll
$keterangan = trim($row['mig_kesimpulan']);
switch ($jenis) {
case 'Faktor Positif':
$fakta['fakta_positif'][] = $keterangan;
break;
case 'Faktor Negatif':
$fakta['fakta_negatif'][] = $keterangan;
break;
case 'Rute Menuju':
$fakta['rute_menuju'] = $keterangan;
break;
case 'Kondisi Lingkungan':
$fakta['kondisi_lingkungan'][] = $keterangan;
break;
case 'Kondisi Bangunan':
$fakta['kondisi_lain_bangunan'][] = $keterangan;
break;
case 'Lain - lain':
$fakta['informasi_dokument'][] = $keterangan;
break;
case 'CATATAN YANG PERLU DIPERHATIKAN':
$fakta['keterangan'][] = $keterangan;
break;
case 'Catatan':
$fakta['keterangan'][] = $keterangan;
break;
case 'Saran':
$fakta['saran'][] = $keterangan;
break;
}
}
$dataToInsertJson[] = json_encode([
'fakta' => $fakta
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
return $dataToInsertJson;
}
private function parseTimestamp(?string $timestamp): ?string
{
try {
if ($timestamp) {
// Cek jika format hanya tanggal (Y-m-d)
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $timestamp)) {
return \Carbon\Carbon::createFromFormat('Y-m-d', $timestamp)
->startOfDay()
->toDateTimeString();
}
// Format lengkap (Y-m-d H:i:s)
return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString();
}
return null;
} catch (\Exception $e) {
Log::error('Gagal memparsing timestamp: ' . $timestamp . '. Pesan: ' . $e->getMessage());
return null;
}
}
private function getProvinceCode(string $name, array &$cache): ?string
{
$normalizedName = strtolower($name);
if (isset($cache[$normalizedName])) {
return $cache[$normalizedName];
}
$province = Province::whereRaw('LOWER(name) = ?', [strtolower($name)])->first();
if ($province) {
$cache[$normalizedName] = $province->code;
return $province->code;
}
return null;
}
private function getCityCode(string $name, array &$cache): ?string
{
$normalizedName = strtolower($name);
if (isset($cache[$normalizedName])) {
return $cache[$normalizedName];
}
$city = City::whereRaw('LOWER(name) = ?', [strtolower($name)])->first();
if ($city) {
$cache[$normalizedName] = $city->code;
return $city->code;
}
return null;
}
private function getDistrictCode(string $name, array &$cache): ?string
{
$normalizedName = strtolower($name);
if (isset($cache[$normalizedName])) {
return $cache[$normalizedName];
}
$district = District::whereRaw('LOWER(name) = ?', [strtolower($name)])->first();
if ($district) {
$cache[$normalizedName] = $district->code;
return $district->code;
}
return null;
}
private function getSubdistrictCode(string $name, array &$cache, array &$districtCache): ?array
{
$normalizedName = strtolower($name);
// Pastikan cache menyimpan array, bukan hanya kode
if (isset($cache[$normalizedName])) {
return $cache[$normalizedName];
}
// Ambil subdistrict dari database
$subdistrict = Village::whereRaw('LOWER(name) = ?', [$normalizedName])->first();
// Jika ditemukan, simpan ke dalam cache sebagai array lengkap
if ($subdistrict) {
$cache[$normalizedName] = [
'code' => $subdistrict->code,
'postal_code' => $subdistrict->postal_code
];
return $cache[$normalizedName];
}
// Jika tidak ditemukan, kembalikan null
return [
'code' => null,
'postal_code' => null
];
}
private function initializeErrorLog()
{
$file = $this->errorLogFile;
// Hapus file lama jika ada
if (file_exists($file)) {
unlink($file);
}
// Buat file baru dengan header
$handle = fopen($file, 'w');
fputcsv($handle, ['mig_mst_jaminan_nomor_jaminan', 'Error']);
fclose($handle);
}
private function logError($nomorJaminan, string $message)
{
Log::error("Error migrasi permohonan [$nomorJaminan]: $message");
// Tulis ke file error
$handle = fopen($this->errorLogFile, 'a');
fputcsv($handle, [$nomorJaminan, $message]);
}
public function checkJenisJaminan($input)
{
$input = trim($input);
switch ($input) {
case 'Tanah dan Bangunan eks KPR-BPPN':
return 'tanah, bangunan, lingkungan, fakta, informasi';
case 'Pabrik':
return 'tanah, bangunan, lingkungan, fakta, informasi';
case 'Kapal Laut':
return 'kapal-laut';
case 'Tanah dan/atau Bangunan':
return 'tanah, bangunan';
case 'Kendaraan Bermotor':
return 'kendaraan-';
case 'Mesin-mesin dan Peralatan':
return 'mesin';
case 'Barang Dagangan/FEO':
return 'barang-dagangan';
case 'Pesawat Udara':
return 'pesawat-udara';
case 'Alat Berat':
return 'alat-berat';
case 'Deposito':
return 'deposito';
case 'Rekening Giro / Tabungan':
return 'rekening-giro-tabungan';
case 'Emas':
return 'emas';
case 'Jaminan Pribadi / Personal Guarantee':
return 'jaminan-pribadi';
case 'Jaminan Perusahaan / Corporate Guarantee':
return 'jaminan-perusahaan';
case 'Resi Gudang':
return 'resi-gudang';
case 'Surat Berharga dan Saham':
return 'surat-berharga-saham';
case 'Tanah dan Bangunan (KerjaSama)':
return 'tanah-bangunan-kerja-sama';
case 'Tanah Kavling (Kerjasama)':
return 'tanah-kavling';
case 'Persediaan Barang / Barang Dagangan':
return 'persediaan-barang';
case 'Apartemen':
return 'apartemen';
case 'Tagihan / Piutang Dagang':
return 'tagihan-piutang';
case 'Tanah dan/atau Bangunan KPR - SEDERHANA':
return 'tanah-bangunan-kpr-sederhana';
default:
return 'lainnya';
}
}
public function checkBuildJson($input, $rows = [])
{
$input = trim($input);
// Pastikan rows selalu array
if (!is_array($rows)) {
$rows = [$rows];
}
switch ($input) {
case 'Tanah dan Bangunan eks KPR-BPPN':
case 'Pabrik':
case 'Tanah dan/atau Bangunan':
case 'Apartemen':
case 'Tanah dan/atau Bangunan KPR - SEDERHANA':
$assetJson = json_decode($this->checkAsset($rows)[0] ?? '', true);
$tanahJson = json_decode(buildInspeksiTanah($rows)[0] ?? '', true);
$bangunanJson = json_decode(buildInspeksiBangunan($rows)[0] ?? '', true);
$lingkunganJson = json_decode($this->checkLingkungan($rows)[0] ?? '', true);
$nomorLpj = $rows[0]['mig_nomor_lpj'] ?? null;
$kesimpulanRows = $this->loadKesimpulanByNomorLpj($nomorLpj);
$faktaJson = [];
if (!empty($kesimpulanRows)) {
$faktaResult = $this->checkKesimpulan($kesimpulanRows);
$faktaJson = json_decode($faktaResult[0] ?? '', true)['fakta'] ?? [];
}
return json_encode([
'asset' => $assetJson['asset'] ?? [],
'tanah' => $tanahJson['tanah'] ?? [],
'bangunan' => $bangunanJson['bangunan'] ?? [],
'lingkungan' => $lingkunganJson['lingkungan'] ?? [],
'fakta' => $faktaJson
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
case 'Kapal Laut':
$kapal = createInspeksiKapal($rows);
return json_encode($kapal, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
case 'Kendaraan Bermotor':
$kendaraan = createInspeksiKendaraan($rows);
return json_encode($kendaraan, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
case 'Mesin-mesin dan Peralatan':
$mesin = createInspeksiMesin($rows);
return json_encode($mesin, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
case 'Pesawat Udara':
$pesawat = createInspeksiPesawat($rows);
return json_encode($pesawat, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
case 'Alat Berat':
$alatBerat = createInspeksiAlatBerat($rows);
return json_encode($alatBerat, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
case 'Barang Dagangan/FEO':
case 'Deposito':
case 'Rekening Giro / Tabungan':
case 'Emas':
case 'Jaminan Pribadi / Personal Guarantee':
case 'Jaminan Perusahaan / Corporate Guarantee':
case 'Resi Gudang':
case 'Surat Berharga dan Saham':
case 'Persediaan Barang / Barang Dagangan':
case 'Tagihan / Piutang Dagang':
return json_encode([
'status' => 'pending',
'message' => 'Fungsi untuk "' . $input . '" belum diimplementasikan.',
'data' => $rows
]);
case 'Tanah dan Bangunan (KerjaSama)':
case 'Tanah Kavling (Kerjasama)':
$pesawat = buildRapJsonData($rows);
return json_encode($pesawat, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
default:
return json_encode([
'status' => 'unknown',
'message' => 'Jenis aset tidak dikenali: ' . $input,
'data' => $rows
]);
}
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Modules\Lpj\Database\Seeders;
use Illuminate\Database\Seeder;
class MigrationLaporanSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
// $this->call([]);
}
}

View File

@@ -0,0 +1,225 @@
<?php
namespace Modules\Lpj\Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Modules\Lpj\Models\Inspeksi;
use Modules\Basicdata\Models\Branch;
use Modules\Lpj\Models\DokumenJaminan;
use Modules\Lpj\Models\Permohonan;
class MigrationPembandingSeeder extends Seeder
{
protected $errorLogFile = __DIR__ . '/csv/inspeksi/mig_pembanding_2025_error.csv';
/**
* Run the database seeds.
*/
public function run()
{
// Path ke file csv
$filePath = realpath(__DIR__ . '/csv/inspeksi/mig_pembanding_2025.csv');
if (!$filePath) {
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/inspeksi/mig_pembanding_2025.csv');
$this->command->error('File csv tidak ditemukan.');
return;
}
if (($handle = fopen($filePath, 'r')) === false) {
Log::error('Gagal membuka file CSV: ' . $filePath);
$this->command->error('Gagal membuka file CSV.');
return;
}
$header = fgetcsv($handle, 0, '~');
$rows = [];
$batchSize = 500;
$userData = [];
$branchCache = []; // <-- Gunakan sebagai cache
$totalData = 0;
while (($data = fgetcsv($handle, 0, '~')) !== false) {
$totalData++;
}
rewind($handle);
fgetcsv($handle, 0, '~'); // Skip header
$batchCount = 0;
$currentRow = 0;
$errorCount = 0;
$errorDebitureIds = [];
while (($data = fgetcsv($handle, 0, '~')) !== false) {
if (count($data) != count($header)) {
Log::warning('Baris CSV memiliki jumlah kolom yang tidak sesuai: ' . json_encode($data));
continue;
}
$rows[] = array_combine($header, $data);
$currentRow++;
if (count($rows) >= $batchSize) {
$batchCount++;
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
$this->processBatch($rows, $branchCache, $userData, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
$rows = [];
}
}
// info_harga_laporan_202505021522.csv
// print_r($rows[0]);
if (!empty($rows)) {
$batchCount++;
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
$this->processBatch($rows, $branchCache, $userData, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
}
fclose($handle);
$this->command->info("Data debiture berhasil dimigrasikan. Total data: {$totalData}, Total batch: {$batchCount}");
}
private function processBatch(array $rows, array &$branchCache, array &$userData, int &$errorCount, array &$errorDebitureIds, int $totalData, int $batchCount, int $currentRow)
{
// Kelompokkan berdasarkan mig_nomor_lpj
$groupedRows = $this->groupRowsByJaminan($rows);
print_r($groupedRows);
foreach ($groupedRows as $nomorLpj => $groupRows) {
try {
// Dapatkan info permohonan untuk update inspeksi
$nomorRegis = $this->getNomorRegistrasiPermohonan($nomorLpj, $branchCache);
if (!$nomorRegis) {
Log::warning("Nomor registrasi tidak ditemukan untuk nomor LPJ: {$nomorLpj}");
$errorCount++;
$errorDebitureIds[] = $nomorLpj;
continue;
}
// Bangun JSON data pembanding
$pembandingJson = $this->checkPembanding($groupRows);
print_r($pembandingJson);
// Update ke tabel inspeksi
// print_r($pembandingJson);
Inspeksi::where('permohonan_id', $nomorRegis['id'])
->where('dokument_id', $nomorRegis['dokument_id'])
->update([
'data_pembanding' => $pembandingJson,
'updated_at' => now()
]);
$this->command->info("Berhasil update data_pembanding untuk nomor LPJ: {$nomorLpj}");
} catch (\Exception $e) {
Log::error("Error pada nomor LPJ {$nomorLpj}: " . $e->getMessage());
$errorCount++;
$errorDebitureIds[] = $nomorLpj;
continue;
}
}
}
private function groupRowsByJaminan(array $rows): array
{
$grouped = [];
foreach ($rows as $row) {
$nomorJaminan = $row['mig_nomor_lpj'] ?? null;
if (!empty($nomorJaminan)) {
$grouped[$nomorJaminan][] = $row;
}
}
return $grouped;
}
private function checkPembanding(array $rows)
{
$pembandingList = [];
foreach ($rows as $row) {
// Pastikan kolom penting tersedia
$urutan = (int)($row['mig_urutan'] ?? 999);
$pembanding = trim($row['mig_pembanding'] ?? '');
// CUKUP VALIDASI PEMBANDING SAJA
if (empty($pembanding)) {
continue;
}
$pembandingList[] = [
'urutan' => $urutan,
'keterangan' => $pembanding,
];
}
// Urutkan berdasarkan urutan
usort($pembandingList, function ($a, $b) {
return $a['urutan'] <=> $b['urutan'];
});
// Hapus indeks 'urutan'
$finalPembanding = array_map(function ($item) {
unset($item['urutan']);
return $item;
}, $pembandingList);
return json_encode([
'data_pembanding' => $finalPembanding
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
}
private function getNomorRegistrasiPermohonan($nomor_jaminan_id, array &$cache)
{
if (isset($cache[$nomor_jaminan_id])) {
return $cache[$nomor_jaminan_id];
}
$permohonan = Permohonan::where('nomor_lpj', $nomor_jaminan_id)->first();
if (!$permohonan) {
$cache[$nomor_jaminan_id] = null;
return null;
}
$dokumenJaminan = DokumenJaminan::where('permohonan_id', $permohonan->id)->first();
$result = [
'id' => $permohonan->id,
'dokument_id' => $dokumenJaminan ? $dokumenJaminan->id : null
];
$cache[$nomor_jaminan_id] = $result;
return $result;
}
private function initializeErrorLog()
{
$file = $this->errorLogFile;
// Hapus file lama jika ada
if (file_exists($file)) {
unlink($file);
}
// Buat file baru dengan header
$handle = fopen($file, 'w');
fputcsv($handle, ['mig_mst_jaminan_nomor_jaminan', 'Error']);
fclose($handle);
}
private function logError($nomorJaminan, string $message)
{
Log::error("Error migrasi permohonan [$nomorJaminan]: $message");
// Tulis ke file error
$handle = fopen($this->errorLogFile, 'a');
fputcsv($handle, [$nomorJaminan, $message]);
}
}

View File

@@ -0,0 +1,264 @@
<?php
namespace Modules\Lpj\Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Modules\Lpj\Models\HubunganPemilikJaminan;
use Modules\Lpj\Models\Debiture;
use Modules\Lpj\Models\PemilikJaminan;
use Modules\Basicdata\Models\Branch;
use Modules\Usermanagement\Models\User;
use Illuminate\Support\Facades\Log;
use Modules\Location\Models\Province;
use Modules\Location\Models\City;
use Modules\Location\Models\District;
use Modules\Location\Models\Village;
class MigrationPemilikJaminanSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run()
{
$filePath = realpath(__DIR__ . '/csv/mig_dokument_dan_pemilik.csv');
if (!$filePath) {
Log::error('File CSV tidak ditemukan: ' . __DIR__ . '/csv/pemilik.csv');
$this->command->error('File CSV tidak ditemukan.');
return;
}
if (($handle = fopen($filePath, 'r')) === false) {
Log::error('Gagal membuka file CSV: ' . $filePath);
$this->command->error('Gagal membuka file CSV.');
return;
}
$header = fgetcsv($handle, 0, '~');
$rows = [];
$batchSize = 100; // Ukuran batch
$branchCache = [];
$debitureCache = [];
$hubunganPemilikCache = [];
$provinceCache = [];
$cityCache = [];
$districtCache = [];
$subdistrictCache = [];
while (($data = fgetcsv($handle, 0, '~')) !== false) {
if (count($data) != count($header)) {
Log::warning('Baris CSV memiliki jumlah kolom yang tidak sesuai: ' . json_encode($data));
continue;
}
$rows[] = array_combine($header, $data);
if (count($rows) >= $batchSize) {
$this->processBatch($rows, $branchCache, $debitureCache, $hubunganPemilikCache, $provinceCache, $cityCache, $districtCache, $subdistrictCache);
$rows = [];
}
}
// print_r($rows);
if (!empty($rows)) {
$this->processBatch($rows, $branchCache, $debitureCache, $hubunganPemilikCache, $provinceCache, $cityCache, $districtCache, $subdistrictCache);
}
fclose($handle);
$this->command->info('Data permohonan berhasil dimigrasikan.');
}
private function processBatch(array $rows, array &$branchCache, array &$debitureCache, array &$hubunganPemilikCache, array &$provinceCache, array &$cityCache, array &$districtCache, array &$subdistrictCache)
{
foreach ($rows as $index => $row) {
$debitureId = $this->getDebiturId($row['mig_kd_debitur_seq'], $debitureCache);
if (!$debitureId) {
Log::warning('Debitur tidak ditemukan untuk kode: ' . $row['mig_kd_debitur_seq']);
continue;
}
$hubunganPemilik = $this->getHubunganPemilikId($row['mig_hubungan_pemilik_jaminan'], $hubunganPemilikCache);
$proviceCode = $this->getProvinceCode($row['mig_province_name'], $provinceCache);
$cityCode = $this->getCityCode($row['mig_city_name'], $cityCache);
$districtCode = $this->getDistrictCode($row['mig_district_name'], $districtCache);
$subdistrictCode = $this->getSubdistrictCode($row['mig_village_name'], $subdistrictCache, $districtCache);
PemilikJaminan::create([
'debiture_id' => $debitureId,
'hubungan_pemilik_jaminan_id' => $hubunganPemilik,
'name' => $row['name'],
'detail_sertifikat' => null,
'npwp' => null,
'nomor_id' => null,
'email' => null,
'phone' => null,
'province_code' => $proviceCode,
'city_code' => $cityCode,
'district_code' => $districtCode,
'village_code' => $subdistrictCode['code'],
'postal_code' => $subdistrictCode['postal_code'],
'address' => $row['address'],
'created_at' => $this->parseTimestamp($row['created_at']),
'updated_at' => $this->parseTimestamp($row['updated_at']),
'mig_kd_debitur_seq' => $row['mig_kd_debitur_seq'],
'processed_at' => now(),
'is_mig' => 1
]);
$this->command->info('Proses data Pemilik Jaminan ' . $row['name'] . ' (' . ($index + 1) . '/' . count($rows) . ')');
}
}
private function getDebiturId(string $code, array &$cache): ?int
{
if (isset($cache[$code])) {
return $cache[$code];
}
$debitur = Debiture::where('mig_kd_debitur_seq', $code)->first();
if ($debitur) {
$cache[$code] = $debitur->id;
return $debitur->id;
}
return null;
}
private function getHubunganPemilikId(string $name, array &$cache): ?int
{
// Normalisasi nama
$normalizedName = strtolower(trim($name));
// Cek cache untuk menghindari query berulang
if (isset($cache[$normalizedName])) {
return $cache[$normalizedName];
}
// Query database dengan pengamanan tambahan
$hubunganPemilik = HubunganPemilikJaminan::whereRaw('LOWER(name) = ?', [$normalizedName])
->whereNull('deleted_at') // Tambahkan ini jika Anda menggunakan soft deletes
->first();
// Jika data ditemukan, simpan dalam cache
if ($hubunganPemilik) {
$cache[$normalizedName] = $hubunganPemilik->id;
return $hubunganPemilik->id;
}
// Default jika data tidak ditemukan
$cache[$normalizedName] = 1; // Cache nilai default untuk menghindari query berulang
return 1;
}
private function getProvinceCode(string $name, array &$cache): ?string
{
$normalizedName = strtolower($name);
if (isset($cache[$normalizedName])) {
return $cache[$normalizedName];
}
$province = Province::whereRaw('LOWER(name) = ?', [strtolower($name)])->first();
if ($province) {
$cache[$normalizedName] = $province->code;
return $province->code;
}
return null;
}
private function getCityCode(string $name, array &$cache): ?string
{
$normalizedName = strtolower($name);
if (isset($cache[$normalizedName])) {
return $cache[$normalizedName];
}
$city = City::whereRaw('LOWER(name) = ?', [strtolower($name)])->first();
if ($city) {
$cache[$normalizedName] = $city->code;
return $city->code;
}
return null;
}
private function getDistrictCode(string $name, array &$cache): ?string
{
$normalizedName = strtolower($name);
if (isset($cache[$normalizedName])) {
return $cache[$normalizedName];
}
$district = District::whereRaw('LOWER(name) = ?', [strtolower($name)])->first();
if ($district) {
$cache[$normalizedName] = $district->code;
return $district->code;
}
return null;
}
private function getSubdistrictCode(string $name, array &$cache, array &$districtCache): ?array
{
$normalizedName = strtolower($name);
// Pastikan cache menyimpan array, bukan hanya kode
if (isset($cache[$normalizedName])) {
return $cache[$normalizedName];
}
// Ambil subdistrict dari database
$subdistrict = Village::whereRaw('LOWER(name) = ?', [$normalizedName])->first();
// Jika ditemukan, simpan ke dalam cache sebagai array lengkap
if ($subdistrict) {
$cache[$normalizedName] = [
'code' => $subdistrict->code,
'postal_code' => $subdistrict->postal_code
];
return $cache[$normalizedName];
}
// Jika tidak ditemukan, kembalikan null
return [
'code' => null,
'postal_code' => null
];
}
private function parseDate(?string $date): ?string
{
try {
return $date ? \Carbon\Carbon::createFromFormat('Y-m-d', $date)->toDateString() : null;
} catch (\Exception $e) {
Log::error('Gagal memparsing tanggal: ' . $date);
return null;
}
}
private function parseTimestamp(?string $timestamp): ?string
{
try {
return $timestamp ? \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString() : null;
} catch (\Exception $e) {
Log::error('Gagal memparsing timestamp: ' . $timestamp);
return null;
}
}
}

View File

@@ -0,0 +1,435 @@
<?php
namespace Modules\Lpj\Database\Seeders;
use Illuminate\Database\Seeder;
use Modules\Lpj\Models\DokumenJaminan;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\Penilai;
use Modules\Lpj\Models\Laporan;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class MigrationPenilaiSeeder extends Seeder
{
/**
* Run the database seeds.
*/
protected $errorLogFile = __DIR__ . '/csv/penilai-laporan/mig_penilai_error.csv';
public function run()
{
$this->initializeErrorLog();
// Path ke file csv
$filePath = realpath(__DIR__ . '/csv/penilai-laporan/mig_penilai.csv');
if (!$filePath) {
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/penilai-laporan/mig_penilai.csv');
$this->command->error('File csv tidak ditemukan.');
return;
}
if (($handle = fopen($filePath, 'r')) === false) {
Log::error('Gagal membuka file CSV: ' . $filePath);
$this->command->error('Gagal membuka file CSV.');
return;
}
$header = fgetcsv($handle, 0, '~');
$rows = [];
$batchSize = 500;
$userData = [];
$branchCache = []; // <-- Gunakan sebagai cache
$totalData = 0;
while (($data = fgetcsv($handle, 0, '~')) !== false) {
$totalData++;
}
rewind($handle);
fgetcsv($handle, 0, '~'); // Skip header
$batchCount = 0;
$currentRow = 0;
$errorCount = 0;
$errorDebitureIds = [];
while (($data = fgetcsv($handle, 0, '~')) !== false) {
if (count($data) != count($header)) {
Log::warning('Baris CSV memiliki jumlah kolom yang tidak sesuai: ' . json_encode($data));
continue;
}
$rows[] = array_combine($header, $data);
$currentRow++;
if (count($rows) >= $batchSize) {
$batchCount++;
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
$this->processBatch($rows, $branchCache, $userData, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
$rows = [];
}
}
// info_harga_laporan_202505021522.csv
// print_r($rows);
if (!empty($rows)) {
$batchCount++;
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
$this->processBatch($rows, $branchCache, $userData, $errorCount, $errorDebitureIds, $totalData, $batchCount, $currentRow);
}
fclose($handle);
$this->command->info("Data debiture berhasil dimigrasikan. Total data: {$totalData}, Total batch: {$batchCount}");
}
private function processBatch(array $rows, array &$branchCache, array &$userData, int &$errorCount, array &$errorDebitureIds, int $totalData, int $batchCount, int $currentRow)
{
// Kelompokkan berdasarkan mig_nomor_lpj
$groupedRows = $this->groupRowsByLpj($rows);
foreach ($groupedRows as $nomorLpj => $groupRows) {
try {
// Ambil informasi permohonan dan dokument_id
$nomorRegis = $this->getNomorRegistrasiPermohonan($nomorLpj, $branchCache);
if (!$nomorRegis) {
Log::warning("Nomor registrasi tidak ditemukan untuk nomor LPJ: {$nomorLpj}");
$errorCount++;
$errorDebitureIds[] = $nomorLpj;
continue;
}
// Dapatkan type_penilai (misal: standar, sederhana)
$firstRow = reset($groupRows);
$typePenilai = $this->checkTypePenilai($firstRow['mig_kode_jenis_laporan'] ?? '');
if (!$typePenilai) {
Log::warning("Tidak ada jenis laporan valid untuk nomor LPJ: {$nomorLpj}");
$errorCount++;
$errorDebitureIds[] = $nomorLpj;
continue;
}
// Bangun JSON type_penilai
$penilaiJson = $this->cekJenisPenilai($groupRows);
// Simpan ke tabel Penilai
// print_r(json_decode($penilaiJson, true));
// Mapping field JSON berdasarkan tipe penilaian
$fillableFieldMap = [
'memo' => 'memo',
'standar' => 'lpj',
'sederhana' => 'lpj',
'call_report' => 'call_report',
'rap' => 'rap',
'resume' => 'resume'
];
$fieldToUpdate = $fillableFieldMap[$typePenilai] ?? null;
if (!$fieldToUpdate) {
Log::warning("Field tidak dikenali untuk tipe: {$typePenilai}");
$errorCount++;
$errorDebitureIds[] = $nomorLpj;
continue;
}
// NO: 001/241917/LPJ/PJ-2251/VII/24
// 001 => kode cabang
// 241917 => nomor lpj
// LPJ => jenis laporan
// PJ-2251 => nomor registrasi ambil nilai akhirnnya 242251
// VII => bulan
// 24 => tahun
// Generate nomor_laporan
$tanggal = $firstRow['mig_crated_at'];
$nomorD = $nomorRegis['nomor_registrasi'];
$nomorRegistrasi = "PJ-{$nomorD}";
$nomorLaporan = $this->generateNomorLaporan($typePenilai, $nomorLpj, $nomorRegistrasi, $tanggal);
// Simpan atau update ke tabel Penilai
$penilaiLP = Penilai::updateOrCreate(
[
'permohonan_id' => $nomorRegis['id'],
'dokument_id' => $nomorRegis['dokument_id']
],
[
'type' => $typePenilai,
$fieldToUpdate => $penilaiJson,
'type_penilai' => $typePenilai,
'created_at' => $this->parseTimestamp($tanggal),
'updated_at' => $this->parseTimestamp($tanggal),
]
);
// Simpan ke tabel Laporan
Laporan::updateOrCreate(
[
'permohonan_id' => $penilaiLP->permohonan_id,
'dokumen_jaminan_id' => $penilaiLP->dokument_id
],
[
'nomor_laporan' => $nomorLaporan,
'created_at' => $this->parseTimestamp($tanggal),
'updated_at' => $this->parseTimestamp($tanggal)
]
);
$this->command->info("Berhasil simpan data penilai untuk nomor LPJ: {$nomorLpj}");
} catch (\Exception $e) {
Log::error("Error pada nomor LPJ {$nomorLpj}: " . $e->getMessage());
$errorCount++;
$errorDebitureIds[] = $nomorLpj;
continue;
}
}
}
private function getNomorRegistrasiPermohonan($nomorLpj, array &$cache)
{
if (isset($cache[$nomorLpj])) {
return $cache[$nomorLpj];
}
$permohonan = Permohonan::where('nomor_lpj', $nomorLpj)->first();
if (!$permohonan) {
$cache[$nomorLpj] = null;
return null;
}
$dokumenJaminan = DokumenJaminan::where('permohonan_id', $permohonan->id)->first();
$result = [
'id' => $permohonan->id,
'dokument_id' => $dokumenJaminan ? $dokumenJaminan->id : null,
'nomor_registrasi' => $permohonan->nomor_registrasi
];
$cache[$nomorLpj] = $result;
return $result;
}
private function groupRowsByLpj(array $rows): array
{
$grouped = [];
foreach ($rows as $row) {
$nomorLpj = $row['mig_nomor_lpj'] ?? null;
if (!empty($nomorLpj)) {
$grouped[$nomorLpj][] = $row;
}
}
return $grouped;
}
private function checkTypePenilai($type)
{
$data = [
'MAK' => 'memo',
'STD' => 'standar',
'SPL' => 'sederhana',
'RHP' => 'call-report',
'RAP' => 'rap',
'PRG' => 'resume',
];
return $data[$type];
}
private function cekJenisPenilai(array $groupRows)
{
// Urutkan grup berdasarkan mig_urutan_seq
usort($groupRows, function ($a, $b) {
return ($a['mig_urutan_seq'] ?? 999) <=> ($b['mig_urutan_seq'] ?? 999);
});
// Inisialisasi struktur JSON
$penilaiJson = [
'luas_tanah' => null,
'nilai_tanah_1' => null,
'nilai_tanah_2' => null,
'sarana_pelengkap_penilai' => null,
'nilai_sarana_pelengkap_1' => null,
'nilai_sarana_pelengkap_2' => null,
'total_nilai_pasar_wajar' => null,
'likuidasi' => null,
'likuidasi_nilai_1' => null,
'likuidasi_nilai_2' => null,
'asuransi_luas_bangunan' => null,
'asuransi_nilai_1' => null,
'asuransi_nilai_2' => "0",
'npw_tambahan' => []
];
// Ambil mainRow (urutan pertama)
$mainRow = null;
foreach ($groupRows as $row) {
if (($row['mig_urutan_seq'] ?? '') == 1) {
$mainRow = $row;
break;
}
}
// Jika tidak ada mainRow, ambil baris pertama sebagai fallback
if (!$mainRow && !empty($groupRows[0])) {
$mainRow = $groupRows[0];
}
if ($mainRow) {
$penilaiJson['total_nilai_pasar_wajar'] = $mainRow['mig_nilai_total_nilai_pasar'] ?? null;
$penilaiJson['likuidasi'] = $mainRow['mig_nilai_likudasi'] ?? null;
// Hitung likuidasi nilai 2 jika ada total dan persen likuidasi
$totalPasarWajar = (int)str_replace('.', '', $mainRow['mig_nilai_total_nilai_pasar'] ?? 0);
$persenLikuidasi = (int)($mainRow['mig_nilai_likudasi'] ?? 0);
$penilaiJson['likuidasi_nilai_1'] = $mainRow['mig_nilai_total_nilai_pasar'] ?? null;
$penilaiJson['likuidasi_nilai_2'] = number_format(
$totalPasarWajar * ($persenLikuidasi / 100),
0,
'',
''
);
// Isi data utama hanya untuk urutan 1
$penilaiJson['luas_tanah'] = $mainRow['mig_nilai_satuan'] ?? null;
$penilaiJson['nilai_tanah_1'] = $mainRow['mig_harga_satuan'] ?? null;
$penilaiJson['nilai_tanah_2'] = number_format(
(int)str_replace('.', '', $mainRow['mig_nilai_satuan'] ?? 0) *
(int)str_replace('.', '', $mainRow['mig_harga_satuan'] ?? 0),
0,
'',
''
);
}
// Proses tambahan (urutan > 1)
foreach ($groupRows as $row) {
// Skip baris dengan urutan_seq = 1 karena sudah diproses
if (($row['mig_urutan_seq'] ?? '') == 1) {
continue;
}
// Hanya proses jika mig_urutan_seq ada
$urutan = $row['mig_urutan_seq'] ?? '';
if (empty($urutan)) {
continue;
}
// Tambahkan ke npw_tambahan
$penilaiJson['npw_tambahan'][] = [
'name' => $row['mig_keterangan'] ?? 'Luas Bangunan Tambahan',
'luas' => $row['mig_nilai_satuan'] ?? null,
'nilai_1' => $row['mig_harga_satuan'] ?? null,
'nilai_2' => number_format(
(int)str_replace('.', '', $row['mig_nilai_satuan'] ?? 0) *
(int)str_replace('.', '', $row['mig_harga_satuan'] ?? 0),
0,
'',
''
)
];
}
// Kosongkan npw_tambahan jika kosong
if (empty($penilaiJson['npw_tambahan'])) {
$penilaiJson['npw_tambahan'] = [];
}
return json_encode($penilaiJson, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
}
private function convertToRoman($month)
{
$roman = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X', 'XI', 'XII'];
return $month >= 1 && $month <= 12 ? $roman[$month - 1] : '';
}
private function generateNomorLaporan($typePenilai, $nomorLpj, $nomorRegistrasi, $tanggal)
{
// Mapping type_penilai ke singkatan laporan
$laporanMap = [
'memo' => 'MEMO',
'standar' => 'LPJ',
'sederhana' => 'LPJ',
'call_report' => 'CALL',
'rap' => 'RAP',
'resume' => 'RESUME'
];
// Dapatkan tahun dan bulan dari tanggal
$date = \Carbon\Carbon::parse($tanggal);
$kodeCabang = '001'; // bisa diambil dari user atau parameter lain jika dinamis
$tahun = substr($date->year, -2); // 2024 → 24
$bulan = $this->convertToRoman($date->month); // 7 → VII
// Format akhir nomor registrasi (PJ-XXX)
$nomorDebiturAkhir = substr($nomorRegistrasi, -4); // PJ-2251 → 2251
return sprintf(
"%s/%s/%s/%s/%s/%s",
$kodeCabang,
$nomorLpj,
$laporanMap[$typePenilai] ?? strtoupper($typePenilai),
"PJ-" . $nomorDebiturAkhir,
$bulan,
$tahun
);
}
private function parseTimestamp(?string $timestamp): ?string
{
try {
if ($timestamp) {
// Cek jika format hanya tanggal (Y-m-d)
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $timestamp)) {
return \Carbon\Carbon::createFromFormat('Y-m-d', $timestamp)
->startOfDay()
->toDateTimeString();
}
// Format lengkap (Y-m-d H:i:s)
return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString();
}
return null;
} catch (\Exception $e) {
Log::error('Gagal memparsing timestamp: ' . $timestamp . '. Pesan: ' . $e->getMessage());
return null;
}
}
private function initializeErrorLog()
{
$file = $this->errorLogFile;
if (file_exists($file)) {
unlink($file); // Hapus file lama
}
$handle = fopen($file, 'w');
fputcsv($handle, ['mig_kd_debitur_seq', 'Error']);
fclose($handle);
}
private function logError(string $kode, string $message)
{
Log::error("Error migrasi dokumen jaminan [$kode]: $message");
$handle = fopen($this->errorLogFile, 'a');
fputcsv($handle, [$kode, $message]);
fclose($handle);
}
}

View File

@@ -0,0 +1,376 @@
<?php
namespace Modules\Lpj\Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\Debiture;
use Modules\Basicdata\Models\Branch;
use Modules\Usermanagement\Models\User;
class MigrationPermohonanSeeder extends Seeder
{
protected $errorLogFile = __DIR__ . '/csv/permohonan/mig_permohonan_extenal_error.csv';
public function run()
{
// Bersihkan file error sebelum mulai
$this->initializeErrorLog();
$filePath = realpath(__DIR__ . '/csv/permohonan/mig_permohonan_external.csv');
if (!$filePath) {
Log::error('File CSV tidak ditemukan: ' . __DIR__ . '/csv/permohonan/mig_permohonan_external.csv');
$this->command->error('File CSV tidak ditemukan.');
return;
}
if (($handle = fopen($filePath, 'r')) === false) {
Log::error('Gagal membuka file CSV: ' . $filePath);
$this->command->error('Gagal membuka file CSV.');
return;
}
$header = fgetcsv($handle, 0, '~');
$rows = [];
$batchSize = 1000;
$branchCache = [];
$debitureCache = [];
$totalData = 0;
$currentRow = 0;
$batchCount = 0;
// Hitung total data
while (fgetcsv($handle, 0, '~') !== false) {
$totalData++;
}
rewind($handle);
fgetcsv($handle, 0, '~'); // Lewati header
while (($data = fgetcsv($handle, 0, '~')) !== false) {
if (count($data) != count($header)) {
$nomorJaminan = $data[array_search('mig_mst_jaminan_nomor_jaminan', $header)] ?? '-';
$this->logError($nomorJaminan, 'Jumlah kolom tidak sesuai');
continue;
}
$rows[] = array_combine($header, $data);
$currentRow++;
// print_r($rows);
if (count($rows) >= $batchSize) {
$batchCount++;
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
$this->processBatch($rows, $branchCache, $debitureCache, $totalData, $batchCount);
$rows = [];
}
}
// print_r($rows);
if (!empty($rows)) {
$batchCount++;
$this->command->info("Memproses batch ke-{$batchCount} ({$currentRow}/{$totalData})");
$this->processBatch($rows, $branchCache, $debitureCache, $totalData, $batchCount);
}
fclose($handle);
$this->command->info("Migrasi selesai. Total data diproses: $totalData.");
}
private function processBatch(array $rows, array &$branchCache, array &$debitureCache, int $totalData, int $batchCount)
{
$userData = [];
foreach ($rows as $index => $row) {
try {
$nomorJaminan = $row['mig_mst_jaminan_nomor_jaminan'] ?? '-';
// Cek apakah sudah diproses
$existingRecord = Permohonan::where('nomor_registrasi', $row['mig_mst_jaminan_nomor_jaminan'])->first();
if ($existingRecord && $existingRecord->processed_at) {
$this->command->info("Data sudah diproses: $nomorJaminan");
continue;
}
// Ambil branch_id
$branchId = $this->getBranchId($row['mig_mst_jaminan_kd_cabang'] ?? null, $branchCache);
// if (!$branchId) {
// $this->logError($branchId, 'Cabang tidak ditemukan');
// continue;
// }
// Ambil Debitur ID
$debitureId = $this->getDebiturId($row['mig_mst_jaminan_kd_debitur_seq'], $debitureCache);
if (!$debitureId) {
$this->logError($nomorJaminan, 'Debitur tidak ditemukan');
continue;
}
// Ambil User IDs
$userId = $this->getUserId($row['mig_mst_jaminan_nama_ao'], $branchCache, true);
// jika external matikan
// $approved1Id = $this->getUserId($row['mig_mst_lpj_user_approved_1'], $branchCache, false);
// $approved2Id = $this->getUserId($row['mig_mst_lpj_user_approved_2'], $branchCache, false);
// // Ambil user IDs berdasarkan NIK
$userIdUpdate = $this->getUserIdData($row['mig_mst_jaminan_user_create'] ?? null, $userData)['id'];
$userIdOtorisasi = $this->getUserIdData($row['mig_mst_jaminan_user_oto'] ?? null, $userData)['id'];
// jika external matikan
// if (!$userIdUpdate || !$userIdOtorisasi) {
// $this->logError($userIdUpdate, 'Salah satu user tidak ditemukan');
// continue;
// }
// Mapping field user
$mapUser = [
'created_by' => $userIdUpdate,
'updated_by' => $userIdUpdate,
'authorized_by' => $userIdOtorisasi,
];
// jika external matikan
// if (!$userId || !$approved1Id || !$approved2Id) {
// $this->logError($userId, 'Salah satu user tidak ditemukan');
// continue;
// }
// Mapping data
$jenisFasilitas = $this->checkJenisFasilitas($row['mig_mst_jaminan_kd_jenis_fas_seq']);
$tujuanPenilaian = $this->checkTujuanPenilaian($row['mig_mst_jaminan_kd_tujuan_seq']);
$regionId = $this->checkRegion($row['mig_mst_kode_kelompok_region']);
$nomor_lpj = isset($row['mig_mst_lpj_nomor_lpj']) ? $row['mig_mst_lpj_nomor_lpj'] : '';
$nomor_lpj = is_numeric($nomor_lpj) ? (int)$nomor_lpj : 0;
$jenisPenilaian = $row['mig_internal_or_external'] == 1 ? 2 : 1;
// Simpan data
Permohonan::create([
'nomor_registrasi' => $nomorJaminan,
'tanggal_permohonan' => $this->parseDate($row['tanggal_permohonan']),
'user_id' => $userId['id'],
'branch_id' => $branchId,
'tujuan_penilaian_id' => $tujuanPenilaian,
'debiture_id' => $debitureId,
'jenis_fasilitas_kredit_id' => $jenisFasilitas,
'nilai_plafond_id' => 2,
'status' => 'done',
// jika external matikan
// 'approval_eo' => $approved2Id['id'] ?? 0,
// 'approval_eo_at' => $this->parseTimestamp($row['mig_mst_lpj_tgl_approved_2']),
// 'approval_dd' => 0,
// 'approval_dd_at' => null,
// 'approval_so' => $approved1Id['id'] ?? 0,
// 'approval_so_at' => $this->parseTimestamp($row['mig_mst_lpj_tgl_approved_1']),
// end external matikan
'keterangan' => $row['mig_mst_jaminan_catatan'] ?? null,
'status_bayar' => 'sudah_bayar',
'created_at' => $this->parseTimestamp($row['mig_mst_jaminan_tgl_create']),
'updated_at' => $this->parseTimestamp($row['mig_mst_jaminan_tgl_update']),
'mig_kd_debitur_seq' => $row['mig_mst_jaminan_kd_debitur_seq'],
'nomor_lpj' => $nomor_lpj,
'region_id' => $regionId,
'jenis_penilaian_id' => $jenisPenilaian,
'authorized_by' => $mapUser['authorized_by'],
'created_by' => $mapUser['created_by'],
'updated_by' => $mapUser['updated_by'],
'mig_nama_ao' => $row['mig_mst_jaminan_nama_ao'],
'is_mig' => 1
]);
$this->command->info("Proses data permohonan $nomorJaminan (" . ($index + 1) . '/' . count($rows) . " pada batch ke-$batchCount)");
} catch (\Exception $e) {
$nomorJaminan = $row['mig_mst_jaminan_nomor_jaminan'] ?? '-';
$this->logError($nomorJaminan, "Error eksepsi: " . $e->getMessage());
continue;
}
}
}
private function getUserIdData(?string $code, array &$cache): array
{
if (!$code) {
return ['id' => null, 'branch_id' => null];
}
if (isset($cache[$code])) {
return $cache[$code];
}
$user = User::where('nik', $code)->first();
if ($user) {
$cache[$code] = ['id' => $user->id, 'branch_id' => $user->branch_id];
return $cache[$code];
}
return ['id' => null, 'branch_id' => null];
}
private function getUserId(string $value, array &$cache, bool $includeBranch = false): ?array
{
if (isset($cache[$value])) {
return $cache[$value];
}
$user = null;
if ($includeBranch) {
$user = User::whereRaw('LOWER(name) = ?', [strtolower($value)])->first();
} else {
$user = User::where('nik', $value)->first();
}
if ($user) {
$result = ['id' => $user->id];
if ($includeBranch) {
$result['branch_id'] = $user->branch_id;
}
$cache[$value] = $result;
return $result;
}
return ['id' => null, 'branch_id' => null];
}
private function getDebiturId(string $code, array &$cache): ?int
{
if (isset($cache[$code])) {
return $cache[$code];
}
$debitur = Debiture::where('mig_kd_debitur_seq', $code)->first();
if ($debitur) {
$cache[$code] = $debitur->id;
return $debitur->id;
}
return null;
}
private function getBranchId(?string $code, array &$cache): ?int
{
if (!$code) {
return null;
}
if (isset($cache[$code])) {
return $cache[$code];
}
$branch = Branch::where('code', $code)->first();
if ($branch) {
$cache[$code] = $branch->id;
return $branch->id;
}
return null;
}
private function checkJenisFasilitas($code): int
{
$mapping = [
161337594516 => 1,
161337598118 => 14,
155739382483 => 7,
2 => 9,
153568936592 => 10,
155737674431 => 11,
161337561199 => 12,
1 => 13,
];
return $mapping[$code] ?? 0;
}
private function checkTujuanPenilaian($code): int
{
$mapping = [
1 => 1,
2 => 2,
3 => 9,
4 => 10,
5 => 8,
6 => 3,
];
return $mapping[$code] ?? 1;
}
private function checkRegion($code): int
{
$mapping = [
'01' => 1,
'02' => 2,
'04' => 3,
'07' => 4,
'06' => 5,
];
return $mapping[$code] ?? 1;
}
private function parseDate(?string $date): ?string
{
try {
return $date ? \Carbon\Carbon::createFromFormat('Y-m-d', $date)->toDateString() : null;
} catch (\Exception $e) {
return null;
}
}
private function parseTimestamp(?string $timestamp): ?string
{
try {
if ($timestamp) {
// Cek jika format hanya tanggal (Y-m-d)
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $timestamp)) {
return \Carbon\Carbon::createFromFormat('Y-m-d', $timestamp)
->startOfDay()
->toDateTimeString();
}
// Format lengkap (Y-m-d H:i:s)
return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString();
}
return null;
} catch (\Exception $e) {
Log::error('Gagal memparsing timestamp: ' . $timestamp . '. Pesan: ' . $e->getMessage());
return null;
}
}
private function initializeErrorLog()
{
$file = $this->errorLogFile;
// Hapus file lama jika ada
if (file_exists($file)) {
unlink($file);
}
// Buat file baru dengan header
$handle = fopen($file, 'w');
fputcsv($handle, ['mig_mst_jaminan_nomor_jaminan', 'Error']);
fclose($handle);
}
private function logError($nomorJaminan, string $message)
{
Log::error("Error migrasi permohonan [$nomorJaminan]: $message");
// Tulis ke file error
$handle = fopen($this->errorLogFile, 'a');
fputcsv($handle, [$nomorJaminan, $message]);
fclose($handle);
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Modules\Lpj\Database\Seeders;
use Illuminate\Database\Seeder;
class PosisiKavlingSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
// $this->call([]);
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Modules\Lpj\Database\Seeders;
use Illuminate\Database\Seeder;
class PosisiUnitSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
// $this->call([]);
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Modules\Lpj\Database\Seeders;
use Illuminate\Database\Seeder;
class SaranaPelengkapSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
// $this->call([]);
}
}

View File

@@ -4,7 +4,7 @@ namespace Modules\Lpj\Database\Seeders;
use Illuminate\Database\Seeder;
use Modules\Lpj\Models\Teams;
use Illuminate\Support\Facades\DB;
class TeamsSeeder extends Seeder
{
/**
@@ -12,14 +12,6 @@ class TeamsSeeder extends Seeder
*/
public function run(): void
{
Teams::insert([
[
'regions_id' => 1,
'code' => 'T01',
'name' => 'Team 1',
'created_at' => now(),
'updated_at' => now()
]
]);
DB::unprepared(file_get_contents(__DIR__ . '/sql/teams.sql'));
}
}

View File

@@ -40,7 +40,36 @@ class TujuanPenilaianKJPPSeeder extends Seeder
'status' => 1,
'created_at' => now(),
'updated_at' => now()
]
],
[
'code' => 'TPK05',
'name' => 'Penilaian Ulang Jaminan / Review Tahunan',
'status' => 1,
'created_at' => now(),
'updated_at' => now()
],
[
'code' => 'TPK06',
'name' => 'Lelang',
'status' => 1,
'created_at' => now(),
'updated_at' => now()
],
[
'code' => 'TPK07',
'name' => 'Permohonan Baru',
'status' => 1,
'created_at' => now(),
'updated_at' => now()
],
[
'code' => 'TPK08',
'name' => 'Penambahan Fasilitas / Jaminan',
'status' => 1,
'created_at' => now(),
'updated_at' => now()
],
]);
}
}

View File

@@ -60,7 +60,38 @@ class TujuanPenilaianSeeder extends Seeder
'created_at' => now(),
'updated_at' => now(),
'deleted_at' => null,
],
[
'code' => 'TP0007',
'name' => 'Jual Beli',
'status' => 1,
'created_at' => now(),
'updated_at' => now(),
'deleted_at' => null,
],
[
'code' => 'TP0008',
'name' => 'KPR eks BPPN',
'status' => 1,
'created_at' => now(),
'updated_at' => now(),
'deleted_at' => null,
],
[
'code' => 'TP0009',
'name' => 'Penambahan Fasilitas / Jaminan',
'status' => 1,
'created_at' => now(),
'updated_at' => now()
],
[
'code' => 'TP00010',
'name' => 'Penukaran Jaminan',
'status' => 1,
'created_at' => now(),
'updated_at' => now()
]
]);
}
}

View File

@@ -0,0 +1,10 @@
INSERT INTO `fasilitas_objek` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'FU001', 'Tempat Ibadah', 1, NULL, '2024-11-28 18:57:35', '2024-11-28 18:57:35', NULL, NULL, NULL, NULL, NULL, NULL),
(2, 'FU002', 'Rumah Sakit', 1, NULL, '2024-11-28 18:57:50', '2024-11-28 18:57:50', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'FU003', 'Sekolah', 1, NULL, '2024-11-28 18:58:05', '2024-11-28 18:58:05', NULL, NULL, NULL, NULL, NULL, NULL),
(4, 'FU004', 'Kantor Pemerintahan', 1, NULL, '2024-11-28 18:58:27', '2024-11-28 18:58:27', NULL, NULL, NULL, NULL, NULL, NULL),
(5, 'FU005', 'Stasiun Kereta', 1, NULL, '2024-11-28 18:58:49', '2024-11-28 18:58:49', NULL, NULL, NULL, NULL, NULL, NULL),
(6, 'FU006', 'Terminal Bus', 1, NULL, '2024-11-28 18:59:09', '2024-11-28 18:59:09', NULL, NULL, NULL, NULL, NULL, NULL),
(7, 'FU007', 'Bandara', 1, NULL, '2024-11-28 18:59:26', '2024-11-28 18:59:26', NULL, NULL, NULL, NULL, NULL, NULL),
(8, 'FU009', 'Pos Polisi', 1, NULL, '2024-11-28 18:59:50', '2024-11-28 18:59:50', NULL, NULL, NULL, NULL, NULL, NULL),
(9, 'FU010', 'Lainnya', 1, NULL, '2024-11-28 19:00:07', '2024-11-28 19:00:07', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,4 @@
INSERT INTO `gol_mas_sekitar` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'GMS001', 'Menengah', 1, NULL, '2024-11-05 00:36:23', '2024-11-05 00:36:23', NULL, NULL, NULL, NULL, NULL, NULL),
(2, 'GMS002', 'Menengah Bawah', 1, NULL, '2024-11-05 00:36:35', '2024-11-05 00:36:35', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'GMS003', 'Menengah Atas', 1, NULL, '2024-11-05 00:36:48', '2024-11-05 00:36:48', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,6 @@
INSERT INTO `jenis_bangunan` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'JB001', 'Rumah', 1, NULL, '2024-11-04 21:43:16', '2024-11-04 21:43:16', NULL, NULL, NULL, NULL, NULL, NULL),
(2, 'JB002', 'Ruko', 1, NULL, '2024-11-04 21:43:28', '2024-11-04 21:43:28', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'JB003', 'Gudang', 1, NULL, '2024-11-04 21:43:41', '2024-11-04 21:43:41', NULL, NULL, NULL, NULL, NULL, NULL),
(4, 'JB004', 'Pabrik', 1, NULL, '2024-11-04 21:43:53', '2024-11-04 21:43:53', NULL, NULL, NULL, NULL, NULL, NULL),
(5, 'JB005', 'Lainnya', 1, NULL, '2024-11-04 21:44:08', '2024-11-04 21:44:08', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -1,29 +1,44 @@
INSERT INTO jenis_jaminan VALUES
(1, 'JJ001', 'Tanah', 'tanah', '[\"tanah\", \"lingkungan\", \"fakta\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ005\",\"JLJ006\",\"JLJ022\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(2, 'JJ002', 'Unit Apartemen', 'unit-apartemen', '[\"apartemen-kantor\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ006\",\"JLJ007\",\"JLJ022\",\"JLJ024\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'JJ003', 'Kawasan Industrial / Komersil / Residensial - Perumahan', 'kawasan-industrial-komersil-residensial-perumahan', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ006\",\"JLJ007\",\"JLJ008\",\"JLJ022\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(4, 'JJ004', 'Mall', 'mall', 'null', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ006\",\"JLJ007\",\"JLJ009\",\"JLJ012\",\"JLJ013\",\"JLJ014\",\"JLJ015\",\"JLJ021\",\"JLJ022\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(5, 'JJ005', 'Pabrik', 'pabrik', 'null', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ006\",\"JLJ007\",\"JLJ009\",\"JLJ011\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(6, 'JJ006', 'Emas dan Perak', 'emas-dan-perak', 'null', '[\"JLJ001\",\"JLJ007\",\"JLJ014\",\"JLJ022\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(7, 'JJ007', 'Alat Berat', 'alat-berat', 'null', '[\"JLJ004\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(8, 'JJ008', 'Rumah Tinggal', 'rumah-tinggal', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ006\",\"JLJ007\",\"JLJ009\",\"JLJ024\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(9, 'JJ009', 'Full Properti', 'full-properti', '[\"tanah\", \"bangunan\", \"informasi\"]', '[\"JLJ001\",\"JLJ006\",\"JLJ007\",\"JLJ009\"]', 1, '2024-12-06 09:16:02', '2024-12-10 22:07:46', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(10, 'JJ010', 'Gudang', 'gudang', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ007\",\"JLJ009\",\"JLJ024\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(11, 'JJ011', 'Unit Kios', 'unit-kios', '[\"apartemen-kantor\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ007\",\"JLJ009\",\"JLJ024\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(12, 'JJ012', 'Gedung Mall', 'gedung-mall', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ007\",\"JLJ009\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(13, 'JJ013', 'Tanah Bangunan', 'tanah-bangunan', '[\"tanah\", \"bangunan\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ005\",\"JLJ007\",\"JLJ009\",\"JLJ022\",\"JLJ024\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(14, 'JJ014', 'Apartemen', 'apartemen', '[\"apartemen-kantor\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ022\",\"JLJ024\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(15, 'JJ015', 'Ruko', 'ruko', '[\"tanah\", \"bangunan\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ007\",\"JLJ022\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(16, 'JJ016', 'Mesin Tekstil', 'mesin-tekstil', '[\"mesin\"]', '[\"JLJ011\",\"JLJ022\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(17, 'JJ017', 'Mesin', 'mesin', '[\"mesin\"]', '[\"JLJ011\",\"JLJ022\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(18, 'JJ018', 'Mesin Tenun Tekstil', 'mesin-tenun-tekstil', '[\"mesin\"]', '[\"JLJ011\",\"JLJ022\"]', 1, '2024-12-06 09:16:02', '2024-12-06 09:16:02', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(19, 'JJ019', 'Penilaian Bisnis', 'penilaian-bisnis', '[\"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ007\",\"JLJ014\"]', 1, '2024-12-10 02:34:01', '2024-12-10 02:34:01', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(20, 'JJ020', 'Penilaian Tanah dan Bangunan', 'penilaian-tanah-dan-bangunan', '[\"tanah\", \"bangunan\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ007\"]', 1, '2024-12-10 02:34:54', '2024-12-10 02:34:54', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(21, 'JJ021', 'Penilaian Mesin', 'penilaian-mesin', '[\"mesin\"]', '[\"JLJ011\",\"JLJ022\"]', 1, '2024-12-10 03:00:13', '2024-12-10 03:00:13', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(22, 'JJ022', 'Penilian Kapal dan Pesawat', 'penilian-kapal-dan-pesawat', '[\"kapal\", \"pesawat\"]', '[\"JLJ011\",\"JLJ022\"]', 1, '2024-12-10 03:01:00', '2024-12-10 03:01:00', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(23, 'JJ023', 'Tanah Kosong', 'tanah-kosong', '[\"tanah\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ007\",\"JLJ022\"]', 1, '2024-12-10 03:18:24', '2024-12-10 03:18:24', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(24, 'JJ024', 'Tanah Kosong untuk dikembangkan', 'tanah-kosong-untuk-dikembangkan', '[\"tanah\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ007\",\"JLJ022\"]', 1, '2024-12-10 03:19:03', '2024-12-10 03:19:03', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(25, 'JJ025', 'Bisnis', 'bisnis', '[\"informasi\", \"lingkungan\"]', '[\"JLJ001\",\"JLJ007\"]', 1, '2024-12-10 22:09:26', '2024-12-10 22:09:26', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(26, 'JJ026', 'Properti Sederhana', 'properti-sederhana', '[\"lingkungan\", \"tanah\"]', '[\"JLJ001\",\"JLJ007\"]', 1, '2024-12-10 22:10:01', '2024-12-10 22:10:01', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(27, 'JJ027', 'Bangunan', 'bangunan', '[\"bangunan\"]', '[\"JLJ003\",\"JLJ007\"]', 1, '2024-12-12 08:13:41', '2024-12-12 08:13:41', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(28, 'JJ028', 'Kendaraan Bermotor', 'kendaraan-bermotor', '[\"kendaraan\"]', '[\"JLJ022\"]', 1, '2024-12-12 08:15:51', '2024-12-12 08:15:51', NULL, NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `jenis_jaminan` (`id`, `code`, `name`, `slug`, `form_kategori`, `jenis_legalitas_jaminan_id`, `status`, `created_at`, `updated_at`, `authorized_at`, `authorized_status`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`, `authorized_by`) VALUES
(1, 'JJ001', 'Tanah kosong', 'tanah-kosong', '[\"tanah\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ005\",\"JLJ006\",\"JLJ022\"]', NULL, NULL, '2024-12-20 00:15:07', NULL, 't', NULL, NULL, 1, NULL, NULL),
(2, 'JJ002', 'Unit Apartemen', 'unit-apartemen', '[\"apartemen-kantor\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ006\",\"JLJ007\",\"JLJ022\",\"JLJ024\"]', NULL, NULL, '2024-12-03 03:38:02', NULL, 'r', NULL, NULL, 1, NULL, NULL),
(3, 'JJ003', 'Kawasan Industrial / Komersil / Residensial - Perumahan', 'kawasan-industrial-komersil-residensial-perumahan', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ005\",\"JLJ007\",\"JLJ008\",\"JLJ009\",\"JLJ022\",\"JLJ024\",\"JLJ039\",\"JLJ040\"]', NULL, NULL, '2025-03-10 19:34:58', NULL, 'k', NULL, NULL, 1, NULL, NULL),
(4, 'JJ004', 'Unit Kios', 'unit-kios', '[\"tanah\", \"bangunan\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ006\",\"JLJ007\",\"JLJ009\",\"JLJ010\",\"JLJ022\"]', NULL, NULL, '2024-12-03 01:57:55', NULL, 'g', '2024-12-03 01:57:55', NULL, 1, 1, NULL),
(6, 'JJ005', 'Mall', 'mall', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ006\",\"JLJ007\",\"JLJ009\",\"JLJ012\",\"JLJ013\",\"JLJ014\",\"JLJ015\",\"JLJ021\",\"JLJ022\"]', 1, '2024-09-11 00:51:36', '2024-12-16 19:48:40', NULL, NULL, NULL, 1, 1, NULL, NULL),
(7, 'JJ006', 'Pabrik', 'pabrik', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ006\",\"JLJ007\",\"JLJ009\",\"JLJ011\"]', 1, '2024-10-23 22:27:56', '2024-12-16 19:48:54', NULL, NULL, NULL, 1, 1, NULL, NULL),
(8, 'JJ007', 'Emas dan Perak', 'emas-dan-perak', NULL, '[\"JLJ008\",\"JLJ014\",\"JLJ022\"]', 1, '2024-12-02 02:40:42', '2024-12-02 02:40:58', NULL, NULL, '2024-12-02 02:40:58', 4, 4, 4, NULL),
(9, 'JJ008', 'Emas dan Perak', 'emas-dan-perak', NULL, '[\"JLJ008\",\"JLJ014\",\"JLJ022\"]', 1, '2024-12-02 02:41:39', '2024-12-02 02:47:44', NULL, NULL, '2024-12-02 02:47:44', 4, 4, 4, NULL),
(10, 'JJ009', 'Emas dan Perak', 'emas-dan-perak', NULL, '[\"JLJ001\",\"JLJ007\",\"JLJ014\",\"JLJ022\"]', 1, '2024-12-02 02:49:32', '2024-12-02 02:49:32', NULL, NULL, NULL, 4, 4, NULL, NULL),
(11, 'JJ010', 'Alat Berat', 'alat-berat', 'null', '[\"JLJ004\",\"JLJ011\"]', 1, '2024-12-03 00:59:14', '2024-12-30 23:36:25', NULL, NULL, '2024-12-30 23:36:25', 1, 1, 1, NULL),
(12, 'JJ011', 'Rumah Tinggal', 'rumah-tinggal', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ004\",\"JLJ006\",\"JLJ007\",\"JLJ009\",\"JLJ022\",\"JLJ024\"]', 1, '2024-12-03 01:12:23', '2024-12-19 00:11:01', NULL, NULL, NULL, 1, 1, NULL, NULL),
(13, 'JJ012', 'Pabrik', 'pabrik', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ006\",\"JLJ007\",\"JLJ009\"]', 1, '2024-12-03 01:55:14', '2024-12-03 01:55:14', NULL, NULL, NULL, 1, 1, NULL, NULL),
(14, 'JJ013', 'Gudang', 'gudang', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ007\",\"JLJ009\",\"JLJ022\",\"JLJ024\"]', 1, '2024-12-03 01:56:09', '2025-01-22 02:13:30', NULL, NULL, NULL, 1, 1, NULL, NULL),
(15, 'JJ014', 'Unit Kios', 'unit-kios', '[\"apartemen-kantor\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ007\",\"JLJ009\",\"JLJ024\"]', 1, '2024-12-03 01:58:32', '2024-12-03 04:20:22', NULL, NULL, NULL, 1, 1, NULL, NULL),
(16, 'JJ015', 'Gedung Mall', 'gedung-mall', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ007\",\"JLJ009\"]', 1, '2024-12-03 01:59:41', '2024-12-03 01:59:41', NULL, NULL, NULL, 1, 1, NULL, NULL),
(17, 'JJ016', 'Tanah Bangunan', 'tanah-bangunan', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ005\",\"JLJ007\",\"JLJ009\",\"JLJ022\",\"JLJ024\",\"JLJ039\",\"JLJ040\"]', 1, '2024-12-03 02:01:20', '2025-03-10 19:35:15', NULL, NULL, NULL, 1, 1, NULL, NULL),
(18, 'JJ017', 'Apartemen', 'apartemen', '[\"apartemen-kantor\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ022\",\"JLJ024\"]', 1, '2024-12-03 04:24:14', '2024-12-03 22:35:05', NULL, NULL, NULL, 1, 1, NULL, NULL),
(19, 'JJ018', 'Ruko/Rukan', 'rukorukan', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ007\",\"JLJ022\"]', 1, '2024-12-03 19:33:17', '2024-12-16 01:54:36', NULL, NULL, NULL, 1, 1, NULL, NULL),
(20, 'JJ019', 'Unit Kantor', 'unit-kantor', '[\"apartemen-kantor\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ005\"]', 1, '2024-12-16 01:56:38', '2024-12-16 19:51:00', NULL, NULL, NULL, 1, 1, NULL, NULL),
(21, 'JJ020', 'Pesawat', 'pesawat', '[\"pesawat\"]', '[\"JLJ001\",\"JLJ004\"]', 1, '2024-12-16 01:58:21', '2024-12-16 01:58:21', NULL, NULL, NULL, 1, 1, NULL, NULL),
(22, 'JJ021', 'SPBU', 'spbu', '[\"tanah\", \"bangunan\", \"lingkungan\", \"fakta\", \"informasi\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ005\"]', 1, '2024-12-16 01:59:22', '2024-12-16 01:59:22', NULL, NULL, NULL, 1, 1, NULL, NULL),
(23, 'JJ022', 'Alat Berat', 'alat-berat', '[\"alat-berat\"]', '[\"JLJ004\",\"JLJ006\",\"JLJ011\"]', 1, '2024-12-30 23:37:10', '2024-12-30 23:45:54', NULL, NULL, NULL, 1, 1, NULL, NULL),
(24, 'JJ023', 'Lainnya', 'lainnya', '[\"tanah\", \"bangunan\"]', '[\"JLJ001\",\"JLJ007\"]', 1, '2025-03-05 21:30:11', '2025-03-05 21:30:11', NULL, NULL, NULL, 1, 1, NULL, NULL),
(25, 'JJ024', 'Hotel', 'hotel', '[\"bangunan\", \"tanah\"]', '[\"JLJ001\",\"JLJ003\",\"JLJ006\",\"JLJ007\",\"JLJ008\",\"JLJ009\",\"JLJ011\",\"JLJ013\",\"JLJ014\",\"JLJ015\",\"JLJ016\",\"JLJ017\",\"JLJ020\",\"JLJ021\",\"JLJ022\",\"JLJ024\",\"JLJ028\",\"JLJ036\"]', 1, '2025-03-09 02:01:45', '2025-03-09 02:01:45', NULL, NULL, NULL, 1, 1, NULL, NULL),
(26, 'JJ025', 'Kendaraan', 'kendaraan', '[\"kendaraan\"]', 'null', 1, '2025-04-18 05:42:13', '2025-04-18 05:42:13', NULL, NULL, NULL, 1, 1, NULL, NULL),
(27, 'JJ026', 'Mesin', 'mesin', 'null', 'null', 1, '2025-04-18 05:45:21', '2025-04-18 05:45:21', NULL, NULL, NULL, 1, 1, NULL, NULL),
(28, 'JJ027', 'Barang Elektronik', 'barang-elektronik', 'null', 'null', 1, '2025-04-18 05:47:28', '2025-04-18 05:47:28', NULL, NULL, NULL, 1, 1, NULL, NULL),
(29, 'JJ028', 'Furniture', 'furniture', 'null', 'null', 1, '2025-04-18 05:49:22', '2025-04-18 05:49:22', NULL, NULL, NULL, 1, 1, NULL, NULL),
(30, 'JJ029', 'Perlengkapan', 'perlengkapan', 'null', 'null', 1, '2025-04-18 05:51:00', '2025-04-18 05:51:00', NULL, NULL, NULL, 1, 1, NULL, NULL),
(31, 'JJ030', 'Persediaan Barang', 'persediaan-barang', 'null', 'null', 1, '2025-04-18 05:52:08', '2025-04-18 05:52:08', NULL, NULL, NULL, 1, 1, NULL, NULL),
(32, 'JJ031', 'Kapal', 'kapal', 'null', 'null', 1, '2025-04-18 05:53:26', '2025-04-18 05:53:26', NULL, NULL, NULL, 1, 1, NULL, NULL),
(33, 'JJ032', 'Deposito Berjangka', 'deposito-berjangka', 'null', 'null', 1, '2025-04-18 05:57:44', '2025-04-18 05:57:44', NULL, NULL, NULL, 1, 1, NULL, NULL),
(34, 'JJ033', 'Sertifikat Deposito', 'sertifikat-deposito', 'null', 'null', 1, '2025-04-18 05:58:57', '2025-04-18 05:58:57', NULL, NULL, NULL, 1, 1, NULL, NULL),
(35, 'JJ034', 'Rekening Giro / Tabungan', 'rekening-giro-tabungan', 'null', 'null', 1, '2025-04-18 05:59:56', '2025-04-18 05:59:56', NULL, NULL, NULL, 1, 1, NULL, NULL),
(36, 'JJ035', 'Barang Dagangan', 'barang-dagangan', 'null', 'null', 1, '2025-04-18 06:03:51', '2025-04-18 06:03:51', NULL, NULL, NULL, 1, 1, NULL, NULL),
(37, 'JJ036', 'Piutang Dagang', 'piutang-dagang', 'null', 'null', 1, '2025-04-18 06:04:59', '2025-04-18 06:04:59', NULL, NULL, NULL, 1, 1, NULL, NULL),
(38, 'JJ037', 'Jaminan Pribadi', 'jaminan-pribadi', 'null', 'null', 1, '2025-04-18 06:05:57', '2025-04-18 06:05:57', NULL, NULL, NULL, 1, 1, NULL, NULL),
(39, 'JJ038', 'Jaminan Perusahaan', 'jaminan-perusahaan', 'null', 'null', 1, '2025-04-18 06:06:53', '2025-04-18 06:06:53', NULL, NULL, NULL, 1, 1, NULL, NULL),
(40, 'JJ039', 'Resi Gudang', 'resi-gudang', 'null', 'null', 1, '2025-04-18 06:07:41', '2025-04-18 06:07:41', NULL, NULL, NULL, 1, 1, NULL, NULL),
(41, 'JJ040', 'Surat Berharga dan Saham', 'surat-berharga-dan-saham', 'null', 'null', 1, '2025-04-18 06:08:32', '2025-04-18 06:08:32', NULL, NULL, NULL, 1, 1, NULL, NULL),
(42, 'JJ041', 'Tanah Kavling (Kerjasama)', 'tanah-kavling-kerjasama', 'null', 'null', 1, '2025-04-18 06:09:31', '2025-04-18 06:09:31', NULL, NULL, NULL, 1, 1, NULL, NULL);

View File

@@ -0,0 +1,10 @@
INSERT INTO `jenis_kapal` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'JK001', 'Fishing Boat', 1, NULL, '2024-11-28 18:33:01', '2024-11-28 18:33:01', NULL, NULL, NULL, NULL, NULL, NULL),
(2, 'JK002', 'Tugboat', 1, NULL, '2024-11-28 18:33:55', '2024-11-28 18:33:55', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'JK003', 'Tongkang', 1, NULL, '2024-11-28 18:34:15', '2024-11-28 18:34:15', NULL, NULL, NULL, NULL, NULL, NULL),
(4, 'JK004', 'Self Propelled Oil Barge', 1, NULL, '2024-11-28 18:34:30', '2024-11-28 18:34:30', NULL, NULL, NULL, NULL, NULL, NULL),
(5, 'JK005', 'Dredger', 1, NULL, '2024-11-28 18:34:49', '2024-11-28 18:34:49', NULL, NULL, NULL, NULL, NULL, NULL),
(6, 'JK006', 'General Cargo', 1, NULL, '2024-11-28 18:35:09', '2024-11-28 18:35:09', NULL, NULL, NULL, NULL, NULL, NULL),
(7, 'JK007', 'Container Ship', 1, NULL, '2024-11-28 18:35:35', '2024-11-28 18:35:35', NULL, NULL, NULL, NULL, NULL, NULL),
(8, 'JK008', 'Oli Tangker', 1, NULL, '2024-11-28 18:36:04', '2024-11-28 18:36:04', NULL, NULL, NULL, NULL, NULL, NULL),
(9, 'JK009', 'Passenger Ship', 1, NULL, '2024-11-28 18:36:40', '2024-11-28 18:36:40', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,7 @@
INSERT INTO `jenis_kendaraan` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'JK001', 'Mobil Penumpang', 1, NULL, '2024-11-28 02:18:01', '2024-11-28 02:18:01', NULL, NULL, NULL, NULL, NULL, NULL),
(2, 'JK002', 'Mobil Bus', 1, NULL, '2024-11-28 02:18:15', '2024-11-28 02:18:15', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'JK003', 'Mobil Barang', 1, NULL, '2024-11-28 02:18:36', '2024-11-28 02:18:36', NULL, NULL, NULL, NULL, NULL, NULL),
(4, 'JK004', 'Sepeda Motor', 1, NULL, '2024-11-28 02:18:51', '2024-11-28 02:18:51', NULL, NULL, NULL, NULL, NULL, NULL),
(5, 'JK005', 'Kendaraan Khusus', 1, NULL, '2024-11-28 02:19:18', '2024-11-28 02:19:18', NULL, NULL, NULL, NULL, NULL, NULL),
(6, 'JK006', 'Truk', 1, NULL, '2024-11-28 02:19:34', '2024-11-28 02:19:34', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -21,4 +21,33 @@ INSERT INTO `jenis_legalitas_jaminan` (`code`, `created_at`, `custom_field`, `cu
('JLJ020', '2024-12-06 09:04:50', NULL, NULL, NULL, 'Rate Kamar pertipe, Jumlah Kamar, Luas Kamar Pertipe', 'rate-kamar-pertipe-jumlah-kamar-luas-kamar-pertipe', 1, '2024-12-06 09:04:50'),
('JLJ021', '2024-12-06 09:04:50', NULL, NULL, NULL, 'Analisis Kompetitor', 'analisis-kompetitor', 1, '2024-12-06 09:04:50'),
('JLJ022', '2024-12-06 09:04:50', NULL, NULL, NULL, 'Bukti Bayar', 'bukti-bayar', 1, '2024-12-06 09:04:50'),
('JLJ024', '2024-12-06 09:04:50', NULL, NULL, NULL, 'PPJB', 'ppjb', 1, '2024-12-06 09:04:50');
('JLJ024', '2024-12-06 09:04:50', NULL, NULL, NULL, 'PPJB', 'ppjb', 1, '2024-12-06 09:04:50'),
('JLJ025', '2024-12-06 09:04:50', NULL, NULL, NULL, 'LOKASI JAMINAN', 'lokasi-jaminan', 1, '2024-12-06 09:04:50'),
('JLJ026', '2024-12-06 09:04:50', NULL, NULL, NULL, 'KEPEMILIKAN', 'kepemilikan', 1, '2024-12-06 09:04:50'),
('JLJ027', '2024-12-06 09:04:50', NULL, NULL, NULL, 'STATUS KEPEMILIKAN, HUBUNGAN DAN PENGHUNI', 'status-kepemilikan-hubungan-dan-penghuni', 1, '2024-12-06 09:04:50'),
('JLJ028', '2024-12-06 09:04:50', NULL, NULL, NULL, 'ANALISA TANAH DAN BANGUNAN', 'analisa-tanah-dan-bangunan', 1, '2024-12-06 09:04:50'),
('JLJ029', '2024-12-06 09:04:50', NULL, NULL, NULL, 'SARANA PELENGKAP DAN LINGKUNGAN', 'sarana-pelengkap-dan-lingkungan', 1, '2024-12-06 09:04:50'),
('JLJ030', '2024-12-06 09:04:50', NULL, NULL, NULL, 'STATUS PEMILIKAN', 'status-pemilikan', 1, '2024-12-06 09:04:50'),
('JLJ031', '2024-12-06 09:04:50', NULL, NULL, NULL, 'KONDISI DAN SARANA PELENGKAP KENDARAAN', 'kondisi-dan-sarana-pelengkap-kendaraan', 1, '2024-12-06 09:04:50'),
('JLJ032', '2024-12-06 09:04:50', NULL, NULL, NULL, 'BARANG YANG DIPERIKSA', 'barang-yang-diperiksa', 1, '2024-12-06 09:04:50'),
('JLJ033', '2024-12-06 09:04:50', NULL, NULL, NULL, 'LOKASI, TEMPAT DAN STATUS TEMPAT PENYIMPANAN BARANG', 'lokasi-tempat-dan-status-tempat-penyimpanan-barang', 1, '2024-12-06 09:04:50'),
('JLJ034', '2024-12-06 09:04:50', NULL, NULL, NULL, 'KONDISI DAN DOKUMENTASI PENYIMPANAN BARANG', 'kondisi-dan-dokumentasi-penyimpanan-barang', 1, '2024-12-06 09:04:50'),
('JLJ035', '2024-12-06 09:04:50', NULL, NULL, NULL, 'KONDISI / SISTEM PENGAMANAN DAN LINGKUNGAN TEMPAT PENYIMPANAN BARANG', 'kondisi-sistem-pengamanan-dan-lingkungan-tempat-penyimpanan-barang', 1, '2024-12-06 09:04:50'),
('JLJ036', '2024-12-06 09:04:50', NULL, NULL, NULL, 'KONDISI MESIN', 'kondisi-mesin', 1, '2024-12-06 09:04:50'),
('JLJ037', '2024-12-06 09:04:50', NULL, NULL, NULL, 'CATATAN', 'catatan', 1, '2024-12-06 09:04:50'),
('JLJ038', '2024-12-06 09:04:50', NULL, NULL, NULL, 'EMAS', 'emas', 1, '2024-12-06 09:04:50'),
('JLJ039', '2024-12-06 09:04:50', NULL, NULL, NULL, 'ALAT BERAT', 'alat-berat', 1, '2024-12-06 09:04:50'),
('JLJ040', '2024-12-06 09:04:50', NULL, NULL, NULL, 'DEPOSITO', 'deposito', 1, '2024-12-06 09:04:50'),
('JLJ041', '2024-12-06 09:04:50', NULL, NULL, NULL, 'BARANG DAGANGAN', 'barang-dagangan', 1, '2024-12-06 09:04:50'),
('JLJ042', '2024-12-06 09:04:50', NULL, NULL, NULL, 'PIUTANG DAGANG', 'piutang-dagang', 1, '2024-12-06 09:04:50'),
('JLJ043', '2024-12-06 09:04:50', NULL, NULL, NULL, 'JAMINAN PRIBADI', 'jaminan-pribadi', 1, '2024-12-06 09:04:50'),
('JLJ044', '2024-12-06 09:04:50', NULL, NULL, NULL, 'JAMINAN PERUSAHAAN', 'jaminan-perusahaan', 1, '2024-12-06 09:04:50'),
('JLJ045', '2024-12-06 09:04:50', NULL, NULL, NULL, 'RESI GUDANG', 'resi-gudang', 1, '2024-12-06 09:04:50'),
('JLJ046', '2024-12-06 09:04:50', NULL, NULL, NULL, 'Surat Berharga dan Saham', 'surat-berharga-dan-saham', 1, '2024-12-06 09:04:50'),
('JLJ047', '2024-12-06 09:04:50', NULL, NULL, NULL, 'Tanah dan Bangunan (Kerjasama)', 'tanah-dan-bangunan-kerjasama', 1, '2024-12-06 09:04:50'),
('JLJ048', '2024-12-06 09:04:50', NULL, NULL, NULL, 'Tanah Kavling (Kerjasama)', 'tanah-kavling-kerjasama', 1, '2024-12-06 09:04:50'),
('JLJ049', '2024-12-06 09:04:50', NULL, NULL, NULL, 'JENIS KAPAL DAN STATUS KEPEMILIKAN', 'jenis-kapal-dan-status-kepemilikan', 1, '2024-12-06 09:04:50'),
('JLJ050', '2024-12-06 09:04:50', NULL, NULL, NULL, 'KONDISI DAN SARANA PELENGKAP KAPAL', 'kondisi-dan-sarana-pelengkap-kapal', 1, '2024-12-06 09:04:50'),
('JLJ051', '2024-12-06 09:04:50', NULL, NULL, NULL, 'REKENING GIRO / TABUNGAN', 'rekening-giro-tabungan', 1, '2024-12-06 09:04:50'),
('JLJ052', '2024-12-06 09:04:50', NULL, NULL, NULL, 'DATA TANAH', 'data-tanah', 1, '2024-12-06 09:04:50'),
('JLJ053', '2024-12-06 09:04:50', NULL, NULL, NULL, 'DATA BANGUNAN', 'data-bangunan', 1, '2024-12-06 09:04:50');

View File

@@ -0,0 +1,7 @@
INSERT INTO `jenis_pesawat` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'JP001', 'Penumpang Komersil', 1, NULL, '2024-11-28 18:37:59', '2024-11-28 18:37:59', NULL, NULL, NULL, NULL, NULL, NULL),
(2, 'JP002', 'Milliter', 1, NULL, '2024-11-28 18:38:13', '2024-11-28 18:38:13', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'JP003', 'Cargo', 1, NULL, '2024-11-28 18:38:26', '2024-11-28 18:38:26', NULL, NULL, NULL, NULL, NULL, NULL),
(4, 'JP004', 'Helikopter', 1, NULL, '2024-11-28 18:38:39', '2024-11-28 18:38:39', NULL, NULL, NULL, NULL, NULL, NULL),
(5, 'JP005', 'Pribadi', 1, NULL, '2024-11-28 18:38:56', '2024-11-28 18:38:56', NULL, NULL, NULL, NULL, NULL, NULL),
(6, 'JP006', 'Lainnya', 1, NULL, '2024-11-28 18:39:13', '2024-11-28 18:39:13', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,2 @@
INSERT INTO `jenis_unit` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'JU001', 'H', 1, NULL, '2024-11-28 18:54:44', '2024-11-28 18:54:44', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,5 @@
INSERT INTO `ketinggian_tanah` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(2, 'KT001', 'Sama Dengan Jalan', 1, NULL, '2024-11-05 00:28:23', '2024-11-05 00:28:23', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'KT002', 'Lebih Tinggi', 1, NULL, '2024-11-05 00:28:50', '2024-11-25 21:20:57', NULL, NULL, NULL, NULL, NULL, NULL),
(4, 'KT004', 'Lebih Rendah', 1, NULL, '2024-11-05 00:31:20', '2024-11-25 21:21:05', NULL, NULL, NULL, NULL, NULL, NULL),
(5, 'KT005', 'Bervariasi', 1, NULL, '2024-11-05 00:31:48', '2024-11-05 00:31:48', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,7 @@
INSERT INTO `kondisi_bangunan` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(2, 'KB001', 'Cukup Terawat', 1, NULL, '2024-11-05 00:32:53', '2024-11-05 00:32:53', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'KB002', 'Kurang Terawat', 1, NULL, '2024-11-05 00:33:08', '2024-11-05 00:33:08', NULL, NULL, NULL, NULL, NULL, NULL),
(4, 'KB003', 'Tidak Terawat', 1, NULL, '2024-11-05 00:33:24', '2024-11-05 00:33:24', NULL, NULL, NULL, NULL, NULL, NULL),
(5, 'KB004', 'Hancur/Tidak Layak Ditinggali', 1, NULL, '2024-11-05 00:33:55', '2024-11-05 00:33:55', NULL, NULL, NULL, NULL, NULL, NULL),
(6, 'KB005', 'Terawat', 1, NULL, '2025-03-07 02:47:03', '2025-03-07 02:47:03', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,5 @@
INSERT INTO `kondisi_fisik_tanah` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'KFT001', 'Tanah Darat', 1, NULL, '2024-11-04 21:41:58', '2024-11-04 21:41:58', NULL, NULL, NULL, NULL, NULL, NULL),
(2, 'KFT002', 'Sawah', 1, NULL, '2024-11-04 21:42:11', '2024-11-04 21:42:11', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'KFT003', 'Urukan', 1, NULL, '2024-11-04 21:42:24', '2024-11-04 21:42:24', NULL, NULL, NULL, NULL, NULL, NULL),
(4, 'KFT004', 'Bukit', 1, NULL, '2024-11-04 21:42:38', '2024-11-04 21:42:38', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,5 @@
INSERT INTO `kontur_tanah` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'KT001', 'Rata', 1, NULL, '2024-11-04 21:31:11', '2024-11-04 21:31:11', NULL, NULL, NULL, NULL, NULL, NULL),
(2, 'KT002', 'Tidak Rata', 1, NULL, '2024-11-04 21:31:25', '2024-11-04 21:31:25', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'KT003', 'Berbukit', 1, NULL, '2024-11-04 21:37:07', '2024-11-04 21:37:07', NULL, NULL, NULL, NULL, NULL, NULL),
(4, 'KT004', 'Bergelombang', 1, NULL, '2024-11-04 21:37:27', '2024-11-04 21:37:27', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,4 @@
INSERT INTO `lalu_lintas_lokasi` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'LD001', 'Satu Arah', 1, NULL, '2025-01-22 23:23:31', '2025-01-22 23:23:31', NULL, NULL, NULL, NULL, NULL, NULL),
(2, 'LD002', 'Dua Arah - Satu Jalur', 1, NULL, '2025-01-22 23:23:46', '2025-01-22 23:23:46', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'LD003', 'Dua Arah - Dua Jalur', 1, NULL, '2025-01-22 23:24:04', '2025-01-22 23:24:04', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,4 @@
INSERT INTO `lantai` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'LU001', 'Rendah', 1, NULL, '2024-11-05 02:06:00', '2024-11-05 02:06:00', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'LU003', 'Tinggi', 1, NULL, '2024-11-05 02:06:35', '2024-11-05 02:06:35', NULL, NULL, NULL, NULL, NULL, NULL),
(4, 'LU002', 'Menengah', 1, NULL, '2024-11-05 02:07:02', '2024-11-05 02:07:02', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,4 @@
INSERT INTO `merupakan_daerah` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'MD001', 'Bebas Banjir', 1, NULL, '2024-11-28 18:56:17', '2024-11-28 18:56:17', NULL, NULL, NULL, NULL, NULL, NULL),
(2, 'MD002', 'Rawan Banjir', 1, NULL, '2024-11-28 18:56:37', '2024-11-28 18:56:37', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'MD003', 'Sering Banjir', 1, NULL, '2024-11-28 18:56:56', '2024-11-28 18:56:56', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,3 @@
INSERT INTO `model_alat_berat` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'MA001', 'Excavator', 1, NULL, '2024-11-28 02:13:48', '2024-11-28 02:13:48', NULL, NULL, NULL, NULL, NULL, NULL),
(2, 'MA002', 'Grader', 1, NULL, '2024-11-28 02:14:02', '2024-11-28 02:14:02', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,8 @@
INSERT INTO `perkerasan_jalan` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'PJ001', 'Aspal', 1, NULL, '2024-12-09 02:25:15', '2024-12-09 02:25:15', NULL, NULL, NULL, NULL, NULL, NULL),
(2, 'PJ002', 'Beton', 1, NULL, '2024-12-09 02:25:28', '2024-12-09 02:25:28', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'PJ003', 'Conblock', 1, NULL, '2024-12-09 02:25:44', '2024-12-09 02:25:44', NULL, NULL, NULL, NULL, NULL, NULL),
(4, 'PJ004', 'Sirtu', 1, NULL, '2024-12-09 02:25:56', '2024-12-09 02:25:56', NULL, NULL, NULL, NULL, NULL, NULL),
(5, 'PJ006', 'Belum ada perkerasan', 1, NULL, '2024-12-09 02:26:13', '2024-12-09 02:26:13', NULL, NULL, NULL, NULL, NULL, NULL),
(6, 'PJ007', 'Semen', 1, NULL, '2024-12-20 00:23:31', '2024-12-20 00:23:31', NULL, NULL, NULL, NULL, NULL, NULL),
(7, 'PJ008', 'Lainnya', 1, NULL, '2024-12-20 00:23:45', '2024-12-20 00:23:45', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,6 @@
INSERT INTO `posisi_kavling` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'PK001', 'Badan', 1, NULL, '2024-11-04 21:38:18', '2024-11-04 21:38:18', NULL, NULL, NULL, NULL, NULL, NULL),
(2, 'PK002', 'Pojok', 1, NULL, '2024-11-04 21:38:29', '2024-11-04 21:38:29', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'PK003', 'Hook', 1, NULL, '2024-11-04 21:38:38', '2024-11-04 21:38:38', NULL, NULL, NULL, NULL, NULL, NULL),
(4, 'PK004', 'Kuldesak', 1, NULL, '2024-11-04 21:38:59', '2024-11-04 21:38:59', NULL, NULL, NULL, NULL, NULL, NULL),
(5, 'PK005', 'Lainnya', 1, NULL, '2024-11-04 21:39:47', '2024-11-04 21:39:47', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,4 @@
INSERT INTO `posisi_unit` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'PU001', 'Tengah/Badan', 1, NULL, '2024-12-09 18:28:41', '2024-12-09 18:28:41', NULL, NULL, NULL, NULL, NULL, NULL),
(2, 'PU002', 'Pojok', 1, NULL, '2024-12-09 18:28:58', '2024-12-09 18:28:58', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'PU003', 'Tusuk Sate', 1, NULL, '2024-12-09 18:29:14', '2024-12-09 18:29:14', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,10 @@
INSERT INTO `sarana_pelengkap` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'SP001', 'Pagar', 1, NULL, '2024-11-04 21:53:34', '2024-11-04 21:53:34', NULL, NULL, NULL, NULL, NULL, NULL),
(2, 'SP002', 'Perkerasan', 1, NULL, '2024-11-04 21:53:50', '2024-11-04 21:53:50', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'SP003', 'Kanopi', 1, NULL, '2024-11-04 21:54:13', '2024-11-04 21:54:13', NULL, NULL, NULL, NULL, NULL, NULL),
(5, 'SP004', 'Air', 1, NULL, '2024-11-04 21:54:57', '2024-11-04 21:54:57', NULL, NULL, NULL, NULL, NULL, NULL),
(6, 'SP005', 'Listrik', 1, NULL, '2024-11-04 21:55:13', '2024-11-04 21:55:13', NULL, NULL, NULL, NULL, NULL, NULL),
(7, 'SP006', 'kolam renang', 1, NULL, '2024-12-15 19:25:09', '2024-12-15 19:25:09', NULL, NULL, NULL, NULL, NULL, NULL),
(8, 'SP007', 'carport', 1, NULL, '2024-12-15 19:25:58', '2024-12-15 19:25:58', NULL, NULL, NULL, NULL, NULL, NULL),
(9, 'SP008', 'teras', 1, NULL, '2024-12-15 19:26:38', '2024-12-15 19:26:38', NULL, NULL, NULL, NULL, NULL, NULL),
(10, 'SP009', 'Lainnya', 1, NULL, '2024-12-15 19:26:50', '2024-12-15 19:26:50', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,4 @@
INSERT INTO `sifat_bangunan` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'SB001', 'Permanen', 1, NULL, '2024-11-05 00:09:46', '2024-11-05 00:09:46', NULL, NULL, NULL, NULL, NULL, NULL),
(2, 'SB002', 'Semi Permanen', 1, NULL, '2024-11-05 00:10:03', '2024-11-05 00:10:03', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'SB003', 'Tidak Permanen', 1, NULL, '2024-11-05 00:10:22', '2024-11-05 00:10:22', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,70 @@
INSERT INTO `spek_bangunan` (`id`, `code`, `name`, `spek_kategori_bangunan_id`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'SPB001', 'Tapak Beton', 3, 1, NULL, '2024-11-05 20:22:33', '2024-11-05 20:22:33', NULL, NULL, NULL, NULL, NULL, NULL),
(4, 'SPB002', 'Batu Kali', 3, 1, NULL, '2024-11-05 20:39:42', '2024-11-05 20:39:42', NULL, NULL, NULL, NULL, NULL, NULL),
(5, 'SPB003', 'Lainnya', 3, 1, NULL, '2024-11-05 20:39:58', '2024-11-05 20:39:58', NULL, NULL, NULL, NULL, NULL, NULL),
(6, 'SPB004', 'Beton Bertulang', 4, 1, NULL, '2024-11-05 20:40:43', '2024-11-05 20:40:43', NULL, NULL, NULL, NULL, NULL, NULL),
(7, 'SPB005', 'Lainnya', 4, 1, NULL, '2024-11-05 20:41:01', '2024-11-05 20:41:01', NULL, NULL, NULL, NULL, NULL, NULL),
(8, 'SPB006', 'Dak Beton', 5, 1, NULL, '2024-11-05 20:42:12', '2024-11-05 20:42:12', NULL, NULL, NULL, NULL, NULL, NULL),
(9, 'SPB007', 'Kayu (Atap Asbes)', 5, 1, NULL, '2024-11-05 21:25:05', '2024-11-05 21:25:05', NULL, NULL, NULL, NULL, NULL, NULL),
(10, 'SPB008', 'Kayu (Atap Genteng)', 5, 1, NULL, '2024-11-05 21:25:36', '2024-11-05 21:25:36', NULL, NULL, NULL, NULL, NULL, NULL),
(11, 'SPB009', 'Baja Ringan (Atap Asbes)', 5, 1, NULL, '2024-11-05 21:26:28', '2024-11-05 21:26:28', NULL, NULL, NULL, NULL, NULL, NULL),
(12, 'SPB010', 'Baja Ringan (Atap Genteng)', 5, 1, NULL, '2024-11-05 21:28:43', '2024-11-05 21:28:43', NULL, NULL, NULL, NULL, NULL, NULL),
(13, 'SPB011', 'Lainnya', 5, 1, NULL, '2024-11-05 21:29:07', '2024-11-05 21:29:07', NULL, NULL, NULL, NULL, NULL, NULL),
(15, 'SPB012', 'Asbes', 6, 1, NULL, '2024-11-05 21:30:39', '2024-11-05 21:30:39', NULL, NULL, NULL, NULL, NULL, NULL),
(16, 'SPB013', 'Dak Beton', 6, 1, NULL, '2024-11-05 21:39:28', '2024-11-05 21:39:28', NULL, NULL, NULL, NULL, NULL, NULL),
(17, 'SPB014', 'Fibreglass', 6, 1, NULL, '2024-11-05 21:42:05', '2024-11-05 21:42:05', NULL, NULL, NULL, NULL, NULL, NULL),
(18, 'SPB015', 'Ganteng Tanah Liat', 6, 1, NULL, '2024-11-05 21:42:27', '2024-11-05 21:42:27', NULL, NULL, NULL, NULL, NULL, NULL),
(19, 'SPB016', 'Genteng Beton', 6, 1, NULL, '2024-11-05 21:42:46', '2024-11-05 21:42:46', NULL, NULL, NULL, NULL, NULL, NULL),
(20, 'SPB017', 'Genteng Metal', 6, 1, NULL, '2024-11-05 21:43:16', '2024-11-05 21:43:16', NULL, NULL, NULL, NULL, NULL, NULL),
(21, 'SPB018', 'Seng Gelombang', 6, 1, NULL, '2024-11-05 21:43:48', '2024-11-05 21:43:48', NULL, NULL, NULL, NULL, NULL, NULL),
(22, 'SPB019', 'Spandek', 6, 1, NULL, '2024-11-05 21:44:21', '2024-11-05 21:44:21', NULL, NULL, NULL, NULL, NULL, NULL),
(23, 'SPB020', 'PVC', 6, 1, NULL, '2024-11-05 21:44:37', '2024-11-05 21:44:37', NULL, NULL, NULL, NULL, NULL, NULL),
(24, 'SPB021', 'Genteng Keramik', 6, 1, NULL, '2024-11-05 21:44:58', '2024-11-05 21:44:58', NULL, NULL, NULL, NULL, NULL, NULL),
(25, 'SPB022', 'Lainnya', 6, 1, NULL, '2024-11-05 21:45:15', '2024-11-05 21:45:15', NULL, NULL, NULL, NULL, NULL, NULL),
(26, 'SPB023', 'Asbes', 7, 1, NULL, '2024-11-05 21:45:57', '2024-11-05 21:45:57', NULL, NULL, NULL, NULL, NULL, NULL),
(27, 'SPB024', 'Beton Ekspos', 7, 1, NULL, '2024-11-05 21:46:30', '2024-11-05 21:46:30', NULL, NULL, NULL, NULL, NULL, NULL),
(28, 'SPB025', 'GRC', 7, 1, NULL, '2024-11-05 21:46:46', '2024-11-05 21:46:46', NULL, NULL, NULL, NULL, NULL, NULL),
(29, 'SPB026', 'Gypsum', 7, 1, NULL, '2024-11-05 21:46:59', '2024-11-05 21:46:59', NULL, NULL, NULL, NULL, NULL, NULL),
(30, 'SPB027', 'Triplek', 7, 1, NULL, '2024-11-05 21:47:19', '2024-11-05 21:47:19', NULL, NULL, NULL, NULL, NULL, NULL),
(31, 'SPB028', 'Lambreserring', 7, 1, NULL, '2024-11-05 21:47:57', '2024-11-05 21:47:57', NULL, NULL, NULL, NULL, NULL, NULL),
(32, 'SPB029', 'Lainnya', 7, 1, NULL, '2024-11-05 21:48:11', '2024-11-05 21:48:11', NULL, NULL, NULL, NULL, NULL, NULL),
(34, 'SPB031', 'Batako', 8, 1, NULL, '2024-11-05 21:49:34', '2024-11-05 21:49:34', NULL, NULL, NULL, NULL, NULL, NULL),
(35, 'SPB032', 'Bata Merah', 8, 1, NULL, '2024-11-05 21:49:49', '2024-11-05 21:49:49', NULL, NULL, NULL, NULL, NULL, NULL),
(36, 'SPB033', 'Bata Ringan', 8, 1, NULL, '2024-11-05 21:50:06', '2024-11-05 21:50:06', NULL, NULL, NULL, NULL, NULL, NULL),
(37, 'SPB034', 'Gypsumboard 2 Muka', 8, 1, NULL, '2024-11-05 21:50:39', '2024-11-05 21:50:39', NULL, NULL, NULL, NULL, NULL, NULL),
(38, 'SPB035', 'Rooster Bata', 8, 1, NULL, '2024-11-05 21:50:58', '2024-11-05 21:50:58', NULL, NULL, NULL, NULL, NULL, NULL),
(39, 'SPB036', 'Lainnya', 8, 1, NULL, '2024-11-05 21:51:37', '2024-11-05 21:51:37', NULL, NULL, NULL, NULL, NULL, NULL),
(41, 'SPB038', 'Dilapisi Cat', 9, 1, NULL, '2024-11-05 21:52:34', '2024-11-05 21:52:34', NULL, NULL, NULL, NULL, NULL, NULL),
(42, 'SPB039', 'Dilapis Batu Alam', 9, 1, NULL, '2024-11-05 21:53:02', '2024-11-05 21:53:02', NULL, NULL, NULL, NULL, NULL, NULL),
(43, 'SPB040', 'Dilapis Keramik', 9, 1, NULL, '2024-11-05 21:54:44', '2024-11-05 21:54:44', NULL, NULL, NULL, NULL, NULL, NULL),
(44, 'SPB041', 'Dilapis Marmer Lokal', 9, 1, NULL, '2024-11-05 21:55:04', '2024-11-05 21:55:04', NULL, NULL, NULL, NULL, NULL, NULL),
(45, 'SPB042', 'Dilapis Marmer Import', 9, 1, NULL, '2024-11-05 21:55:26', '2024-11-05 21:55:26', NULL, NULL, NULL, NULL, NULL, NULL),
(46, 'SPB043', 'Dilapis Granit', 9, 1, NULL, '2024-11-05 21:57:24', '2024-11-05 21:57:24', NULL, NULL, NULL, NULL, NULL, NULL),
(47, 'SPB044', 'Dilapis Wallpaper', 9, 1, NULL, '2024-11-05 21:57:43', '2024-11-05 21:57:43', NULL, NULL, NULL, NULL, NULL, NULL),
(48, 'SPB045', 'Lainnya', 9, 1, NULL, '2024-11-05 21:58:00', '2024-11-05 21:58:00', NULL, NULL, NULL, NULL, NULL, NULL),
(49, 'SPB046', 'Pintu Panil', 10, 1, NULL, '2024-11-05 21:58:32', '2024-11-05 21:58:32', NULL, NULL, NULL, NULL, NULL, NULL),
(50, 'SPB048', 'Pintu Kayu Panil', 10, 1, NULL, '2024-11-05 21:59:45', '2024-11-05 21:59:45', NULL, NULL, NULL, NULL, NULL, NULL),
(51, 'SPB049', 'Pntu Kayu Double Triplek', 10, 1, NULL, '2024-11-05 22:00:16', '2024-11-05 22:00:16', NULL, NULL, NULL, NULL, NULL, NULL),
(52, 'SPB050', 'Pntu Kaca RK Alumunium', 10, 1, NULL, '2024-11-05 22:01:13', '2024-11-05 22:01:13', NULL, NULL, NULL, NULL, NULL, NULL),
(53, 'SPB051', 'Pntu Kaca RK Alumunium', 10, 1, NULL, '2024-11-05 23:08:03', '2024-11-05 23:08:03', NULL, NULL, NULL, NULL, NULL, NULL),
(54, 'SPB052', 'Pintu Kaca Tempered Floor', 10, 1, NULL, '2024-11-05 23:08:39', '2024-11-05 23:08:39', NULL, NULL, NULL, NULL, NULL, NULL),
(55, 'SPB053', 'Pntu KM UPVC/PVC', 10, 1, NULL, '2024-11-05 23:09:10', '2024-11-05 23:09:10', NULL, NULL, NULL, NULL, NULL, NULL),
(56, 'SPB054', 'Pintu Garasi Kayu', 10, 1, NULL, '2024-11-05 23:09:46', '2024-11-05 23:09:46', NULL, NULL, NULL, NULL, NULL, NULL),
(57, 'SPB055', 'Pintu Garasi Besi', 10, 1, NULL, '2024-11-05 23:10:09', '2024-11-05 23:10:09', NULL, NULL, NULL, NULL, NULL, NULL),
(58, 'SPB056', 'Jendela Kaca RK Kayu', 10, 1, NULL, '2024-11-05 23:10:39', '2024-11-05 23:10:39', NULL, NULL, NULL, NULL, NULL, NULL),
(59, 'SPB057', 'Jendela Kaca RK Alumunium', 10, 1, NULL, '2024-11-05 23:13:05', '2024-11-05 23:13:05', NULL, NULL, NULL, NULL, NULL, NULL),
(60, 'SPB058', 'Jendela Kaca Stopsol 8mm Curtail w All', 10, 1, NULL, '2024-11-05 23:14:32', '2024-11-05 23:14:32', NULL, NULL, NULL, NULL, NULL, NULL),
(61, 'SPB059', 'Jendela Kaca Tempered Frameless', 10, 1, NULL, '2024-11-05 23:15:57', '2024-11-05 23:15:57', NULL, NULL, NULL, NULL, NULL, NULL),
(62, 'SPB060', 'Lainnya', 10, 1, NULL, '2024-11-05 23:20:37', '2024-11-05 23:20:37', NULL, NULL, NULL, NULL, NULL, NULL),
(63, 'SPB061', 'Granit/Homogenus Tile', 11, 1, NULL, '2024-11-05 23:21:51', '2024-11-05 23:21:51', NULL, NULL, NULL, NULL, NULL, NULL),
(64, 'SPB062', 'Granit Import', 11, 1, NULL, '2024-11-05 23:22:19', '2024-11-05 23:22:19', NULL, NULL, NULL, NULL, NULL, NULL),
(65, 'SPB063', 'Karpet', 11, 1, NULL, '2024-11-05 23:22:41', '2024-11-05 23:22:41', NULL, NULL, NULL, NULL, NULL, NULL),
(66, 'SPB064', 'Keramik', 11, 1, NULL, '2024-11-05 23:23:11', '2024-11-05 23:23:11', NULL, NULL, NULL, NULL, NULL, NULL),
(67, 'SPB065', 'Marmer Import', 11, 1, NULL, '2024-11-05 23:24:26', '2024-11-05 23:24:26', NULL, NULL, NULL, NULL, NULL, NULL),
(68, 'SPB066', 'Mozaik', 11, 1, NULL, '2024-11-05 23:24:43', '2024-11-05 23:24:43', NULL, NULL, NULL, NULL, NULL, NULL),
(69, 'SPB067', 'Rabat Beton (Semen Ekspose)', 11, 1, NULL, '2024-11-05 23:25:10', '2024-11-05 23:25:10', NULL, NULL, NULL, NULL, NULL, NULL),
(70, 'SPB068', 'Parkit Jati', 11, 1, NULL, '2024-11-05 23:27:59', '2024-11-05 23:27:59', NULL, NULL, NULL, NULL, NULL, NULL),
(71, 'SPB069', 'Teraso', 11, 1, NULL, '2024-11-05 23:28:14', '2024-11-05 23:28:14', NULL, NULL, NULL, NULL, NULL, NULL),
(72, 'SPB070', 'Vynil', 11, 1, NULL, '2024-11-05 23:28:42', '2024-11-05 23:28:42', NULL, NULL, NULL, NULL, NULL, NULL),
(73, 'SPB071', 'Lainnya', 11, 1, NULL, '2024-11-05 23:29:29', '2024-11-05 23:29:29', NULL, NULL, NULL, NULL, NULL, NULL),
(74, 'SPB030', 'Baja', 4, 1, NULL, '2024-12-29 21:45:39', '2024-12-29 21:45:39', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,10 @@
INSERT INTO `spek_kategori_bangunan` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(3, 'KB001', 'Pondasi', 1, NULL, '2024-11-05 01:10:30', '2024-11-05 01:10:30', NULL, NULL, NULL, NULL, NULL, NULL),
(4, 'KB002', 'Struktur', 1, NULL, '2024-11-05 01:10:56', '2024-11-05 01:10:56', NULL, NULL, NULL, NULL, NULL, NULL),
(5, 'KB003', 'Rangka Atap', 1, NULL, '2024-11-05 01:11:20', '2024-11-05 01:11:20', NULL, NULL, NULL, NULL, NULL, NULL),
(6, 'KB004', 'Tutup Atap', 1, NULL, '2024-11-05 01:11:38', '2024-11-05 01:11:38', NULL, NULL, NULL, NULL, NULL, NULL),
(7, 'KB005', 'Plafond', 1, NULL, '2024-11-05 01:11:56', '2024-11-05 01:11:56', NULL, NULL, NULL, NULL, NULL, NULL),
(8, 'KB006', 'Dinding', 1, NULL, '2024-11-05 01:45:06', '2024-11-05 01:45:06', NULL, NULL, NULL, NULL, NULL, NULL),
(9, 'KB007', 'Pelapis Dinding', 1, NULL, '2024-11-05 01:45:36', '2024-11-05 01:45:36', NULL, NULL, NULL, NULL, NULL, NULL),
(10, 'KB008', 'Pintu Jendela', 1, NULL, '2024-11-05 01:46:06', '2024-11-05 01:46:06', NULL, NULL, NULL, NULL, NULL, NULL),
(11, 'KB009', 'Lantai', 1, NULL, '2024-11-05 01:46:46', '2024-11-05 01:46:46', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,6 @@
INSERT INTO `teams` (`id`, `regions_id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 1, 'T01', 'Team 1', NULL, NULL, '2024-09-18 23:48:39', '2024-09-18 23:48:39', NULL, NULL, NULL, NULL, NULL, NULL),
(2, 2, 'T02', 'Team 2', NULL, NULL, '2024-10-30 20:41:34', '2024-10-30 20:41:34', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 5, 'T05', 'Tim 5', NULL, NULL, '2024-10-30 22:09:17', '2024-10-30 23:44:26', NULL, NULL, NULL, NULL, NULL, NULL),
(4, 3, 'T03', 'Team 3', NULL, NULL, '2024-10-30 23:24:56', '2024-10-30 23:24:56', NULL, NULL, NULL, NULL, NULL, NULL),
(5, 4, 'T04', 'Team 4', NULL, NULL, '2024-10-30 23:42:27', '2024-10-30 23:42:27', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,5 @@
INSERT INTO `terletak_area` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'TA001', 'Perumahan', 1, NULL, '2024-11-28 18:30:19', '2024-11-28 18:30:19', NULL, NULL, NULL, NULL, NULL, NULL),
(2, 'TA002', 'Pemukiman', 1, NULL, '2024-11-28 18:30:35', '2024-11-28 18:30:35', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'TA003', 'Komersil', 1, NULL, '2024-11-28 18:30:54', '2024-11-28 18:30:54', NULL, NULL, NULL, NULL, NULL, NULL),
(4, 'TA004', 'Lainnya', 1, NULL, '2024-11-28 18:31:09', '2024-11-28 18:31:09', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,4 @@
INSERT INTO `tingkat_keramaian` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'TK001', 'Ramai', 1, NULL, '2024-11-05 00:30:18', '2024-11-05 00:30:18', NULL, NULL, NULL, NULL, NULL, NULL),
(2, 'TK002', 'Cukup Ramai', 1, NULL, '2024-11-05 00:31:12', '2024-11-05 00:31:12', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'TK003', 'Sepi', 1, NULL, '2024-11-05 00:32:17', '2024-11-05 00:32:17', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -0,0 +1,6 @@
INSERT INTO `view_unit` (`id`, `code`, `name`, `status`, `authorized_status`, `created_at`, `updated_at`, `authorized_at`, `authorized_by`, `deleted_at`, `created_by`, `updated_by`, `deleted_by`) VALUES
(1, 'VU001', 'Kota', 1, NULL, '2024-11-05 02:08:37', '2024-11-05 02:08:37', NULL, NULL, NULL, NULL, NULL, NULL),
(2, 'VU002', 'Laut', 1, NULL, '2024-11-05 02:09:44', '2024-11-05 02:09:44', NULL, NULL, NULL, NULL, NULL, NULL),
(3, 'VU003', 'Kolam Renang', 1, NULL, '2024-11-05 02:10:04', '2024-11-05 02:10:04', NULL, NULL, NULL, NULL, NULL, NULL),
(4, 'VU004', 'Lainnya', 1, NULL, '2024-11-05 02:10:19', '2024-11-05 02:10:19', NULL, NULL, NULL, NULL, NULL, NULL);

View File

@@ -607,6 +607,23 @@
"EO Appraisal",
"senior-officer"
]
},
{
"title": "Daftar Pustaka",
"path": "daftar-pustaka",
"icon": "ki-filled ki-filter-tablet text-lg text-primary",
"classes": "",
"attributes": [],
"permission": "",
"roles": [
"administrator",
"pemohon-ao",
"pemohon-eo",
"admin",
"DD Appraisal",
"EO Appraisal",
"senior-officer"
]
}
],
"master": [
@@ -1149,6 +1166,17 @@
"administrator",
"admin"
]
},
{
"title": "Kategori Daftar Pustaka",
"path": "category-daftar-pustaka",
"classes": "",
"attributes": [],
"permission": "",
"roles": [
"administrator",
"admin"
]
}
]
}

View File

@@ -38,7 +38,7 @@
Pemohon:
</h3>
<span class="text-2sm text-gray-700">
{{ $permohonan->user->nik }} | {{ $permohonan->user->name }} | {{ $permohonan->user->branch->name }}
{{ $permohonan->user->nik ?? '' }} | {{ $permohonan->user->name ?? '' }} | {{ $permohonan->user->branch->name ?? '' }}
</span>
</div>
@@ -85,7 +85,7 @@
<a href="{{ route('surveyor.print_out_inspeksi', ['permohonan_id' => $permohonan->id, 'dokument_id' => $dokumen->id, 'jenis_jaminan_id' => $dokumen->jenis_jaminan_id ]) }}" class="btn btn-light">
<i class="ki-filled ki-printer"></i> Hasil Inspeksi
</a>
<a class="btn btn-success" onclick="checkLaporan('{{ $permohonan->id }}', '{{ $dokumen->id }}', '{{ $inspeksiId }}', {{ $dokumen->jenis_jaminan_id }}, 0 )">
<a class="btn btn-success" href="{{ route('penilai.print-out-laporan', ['permohonan_id' => $permohonan->id, 'dokument_id' => $dokumen->id, 'jenis_jaminan_id' => $dokumen->jenis_jaminan_id ]) }}">
<i class="ki-filled ki-printer"></i> Print Laporan
</a>
</div>
@@ -100,4 +100,4 @@
</div>
</div>
@endsection
@include('lpj::surveyor.js.utils')
{{-- @include('lpj::surveyor.js.utils') --}}

View File

@@ -208,11 +208,11 @@
title: 'Tanggal Permohonan'
},
user_id: {
title: 'User Pemohon',
render: (item, data) => {
return data.user && data.user.name ? `${data.user.name}` : '-';
},
},
title: 'User Pemohon',
render: (item, data) => {
return data?.user?.name ?? data?.mig_nama_ao ?? '-';
}},
branch_id: {
title: 'Cabang Pemohon',
@@ -264,34 +264,64 @@
title: 'Action',
render: (item, data) => {
const status = data.status; // Anggap status berada di dalam objek data
const dokumenjaminan = data.dokumenjaminan || [];
const dokumenjaminan = data.dokumenjaminan || [];
return `
return `
<div class="flex flex-nowrap justify-center">
<a class="btn btn-sm btn-icon btn-clear btn-warning" href="activity/${data.id}/show" title="Lihat Detail">
<a class="btn btn-sm btn-icon ${status === 'freeze' ? 'btn-light' : 'btn-warning btn-clear'}" href="activity/${data.id}/show" title="Lihat Detail">
<i class="ki-outline ki-eye"></i>
</a>
${
['survey', 'done', 'proses-laporan', 'laporan', 'paparan'].includes(status) ?
dokumenjaminan.map(dokumen => {
return `
<a class="btn btn-sm btn-icon btn-clear btn-info" href="surveyor/print-out-inspeksi/${data.id}/${dokumen.id}/${dokumen.jenis_jaminan_id}" title="Print Inspeksi Permohonan">
<i class="ki-outline ki-printer"></i>
</a>
`;
<a class="btn btn-sm btn-icon btn-clear btn-info" href="surveyor/print-out-inspeksi/${data.id}/${dokumen.id}/${dokumen.jenis_jaminan_id}" title="Print Inspeksi Permohonan">
<i class="ki-outline ki-printer"></i>
</a>
`;
}).join('') : ''
}
</div>
`;
},
},
},
},
}
};
let dataTable = new KTDataTable(element, dataTableOptions);
function highlightFreezeRows() {
const table = document.querySelector('#permohonan-table table[data-datatable-table="true"]');
if (!table) return;
const rows = table.querySelectorAll('tbody tr');
rows.forEach(row => {
const statusCell = row.cells[7];
if (!statusCell) return;
const statusText = statusCell.textContent.trim().toLowerCase();
if (statusText === 'freeze') {
row.classList.add('bg-red-400', 'text-white');
} else {
row.classList.remove('bg-red-400', 'text-white');
}
});
}
// Polling setiap 1 detik untuk sementara
setInterval(() => {
highlightFreezeRows();
}, 500);
searchInput.addEventListener('input', function() {
const searchValue = this.value.trim();
dataTable.search(searchValue, true);

View File

@@ -0,0 +1,64 @@
@extends('layouts.main')
@section('breadcrumbs')
{{-- {{ Breadcrumbs::render(request()->route()->getName()) }} --}}
@endsection
@section('content')
<div class="w-full grid gap-5 lg:gap-7.5 mx-auto">
<form
action="{{ isset($category->id) ? route('category-daftar-pustaka.update', $category->id) : route('category-daftar-pustaka.store') }}"
method="POST">
@csrf
@if (isset($category->id))
@method('PUT')
<input type="text" name="id" value="{{ $category->id }}" hidden class="hidden">
@endif
<div class="card border border-agi-100 pb-2.5">
<div class="card-header bg-agi-50" id="basic_settings">
<h3 class="card-title">
Tambah
</h3>
<div class="flex items-center gap-2">
<a href="{{ route('category-daftar-pustaka.index') }}" class="btn btn-xs btn-info"><i
class="ki-filled ki-exit-left"></i> Back</a>
</div>
</div>
<div class="card-body grid gap-5">
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label class="form-label max-w-56">
Code
</label>
<div class="flex flex-wrap items-baseline w-full">
<input class="input @error('code') border-danger bg-danger-light @enderror" type="text"
name="code" value="{{ $category->code ?? old('code') }}"
{{ isset($category->id) ? 'readonly' : '' }}>
@error('code')
<em class="alert text-danger text-sm">{{ $message }}</em>
@enderror
</div>
</div>
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label class="form-label max-w-56">
Name
</label>
<div class="flex flex-wrap items-baseline w-full">
<input class="input input-file @error('name') border-danger bg-danger-light @enderror"
type="text" name="name" value="{{ $category->name ?? old('name') }}">
@error('name')
<em class="alert text-danger text-sm">{{ $message }}</em>
@enderror
</div>
</div>
<div class="flex justify-end">
<button type="submit" class="btn btn-primary">
Save
</button>
</div>
</div>
</div>
</form>
</div>
@endsection

View File

@@ -0,0 +1,147 @@
@extends('layouts.main')
@section('breadcrumbs')
{{-- {{ Breadcrumbs::render('basicdata.jenis-aset') }} --}}
@endsection
@section('content')
<div class="grid">
<div class="card border border-agi-100 card-grid min-w-full" data-datatable="false" data-datatable-page-size="10" data-datatable-state-save="false" id="category-daftar-pustaka-table" data-api-url="{{ route('category-daftar-pustaka.datatables') }}">
<div class="card-header bg-agi-50 py-5 flex-wrap">
<h3 class="card-title">
Daftar Kategori Daftar Pustaka
</h3>
<div class="flex flex-wrap gap-2 lg:gap-5">
<div class="flex">
<label class="input input-sm"> <i class="ki-filled ki-magnifier"> </i>
<input placeholder="Search Kategori Daftar Pustaka" id="search" type="text" value="">
</label>
</div>
<div class="flex flex-wrap gap-2.5">
<div class="h-[24px] border border-r-gray-200"></div>
<a class="btn btn-sm btn-light" href=""> Export to Excel </a>
<a class="btn btn-sm btn-primary" href="{{ route('category-daftar-pustaka.create') }}"> Tambah Kategori </a>
</div>
</div>
</div>
<div class="card-body">
<div class="scrollable-x-auto">
<table class="table table-auto table-border align-middle text-gray-700 font-medium text-sm" data-datatable-table="true">
<thead>
<tr>
<th class="w-14">
<input class="checkbox checkbox-sm" data-datatable-check="true" type="checkbox"/>
</th>
<th class="min-w-[250px]" data-datatable-column="code">
<span class="sort"> <span class="sort-label"> Code </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[250px]" data-datatable-column="name">
<span class="sort"> <span class="sort-label"> Name </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[50px] text-center" data-datatable-column="actions">Action</th>
</tr>
</thead>
</table>
</div>
<div class="card-footer justify-center md:justify-between flex-col md:flex-row gap-3 text-gray-600 text-2sm font-medium">
<div class="flex items-center gap-2">
Show
<select class="select select-sm w-16" data-datatable-size="true" name="perpage"> </select> per page
</div>
<div class="flex items-center gap-4">
<span data-datatable-info="true"> </span>
<div class="pagination" data-datatable-pagination="true">
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
@push('scripts')
<script type="text/javascript">
function deleteData(data) {
Swal.fire({
title: 'Are you sure?',
text: "You won't be able to revert this!",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
}).then((result) => {
if (result.isConfirmed) {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
}
});
$.ajax(`category-daftar-pustaka/${data}`, {
type: 'DELETE'
}).then((response) => {
swal.fire('Deleted!', 'User has been deleted.', 'success').then(() => {
window.location.reload();
});
}).catch((error) => {
console.error('Error:', error);
Swal.fire('Error!', 'An error occurred while deleting the file.', 'error');
});
}
})
}
</script>
<script type="module">
const element = document.querySelector('#category-daftar-pustaka-table ');
const searchInput = document.getElementById('search');
const apiUrl = element.getAttribute('data-api-url');
const dataTableOptions = {
apiEndpoint: apiUrl,
pageSize: 5,
columns: {
select: {
render: (item, data, context) => {
const checkbox = document.createElement('input');
checkbox.className = 'checkbox checkbox-sm';
checkbox.type = 'checkbox';
checkbox.value = data.id.toString();
checkbox.setAttribute('data-datatable-row-check', 'true');
return checkbox.outerHTML.trim();
},
},
code: {
title: 'Code',
},
name: {
title: 'Name',
},
actions: {
title: 'Status',
render: (item, data) => {
return `<div class="flex flex-nowrap justify-center">
<a class="btn btn-sm btn-icon btn-clear btn-info" href="category-daftar-pustaka/${data.id}/edit">
<i class="ki-outline ki-notepad-edit"></i>
</a>
<a onclick="deleteData(${data.id})" class="delete btn btn-sm btn-icon btn-clear btn-danger">
<i class="ki-outline ki-trash"></i>
</a>
</div>`;
},
}
},
};
let dataTable = new KTDataTable(element, dataTableOptions);
// Custom search functionality
searchInput.addEventListener('input', function () {
const searchValue = this.value.trim();
dataTable.search(searchValue, true);
});
</script>
@endpush

View File

@@ -46,7 +46,7 @@
Pemohon:
</h3>
<span class="text-2sm text-gray-700">
{{ $permohonan->user->nik }} | {{ $permohonan->user->name }} | {{ $permohonan->user->branch->name }}
{{ $permohonan->user->nik ?? '' }} | {{ $permohonan->user->name ?? '' }} | {{ $permohonan->user->branch->name ?? '' }}
</span>
</div>
@@ -84,7 +84,7 @@
Nilai Plafond:
</h3>
<span class="text-2sm text-gray-700">
{{ $permohonan->nilaiPlafond->name }}
{{ $permohonan->nilaiPlafond->name ?? '' }}
</span>
</div>
@@ -293,7 +293,7 @@
<tr>
<td>
<span class="text-2xs text-gray-600 uppercase pl-3">
{{ $loop->index+1 }}. Nomor : {{ $dokumen_nomor[$index] }}
{{ $loop->index+1 }}. Nomor : {{ $dokumen_nomor[$index] ?? '' }}
</span>
</td>
<td class="text-left">

View File

@@ -0,0 +1,33 @@
@if (is_array($details) && count($details) > 0)
@php $currentKey = ''; @endphp
@foreach ($details as $value)
@foreach ($value as $key => $item)
@if (!empty($item))
<tr>
<td style="padding: 2px; width:25%;">
@if ($currentKey !== $key)
{{ formatLabel($key) }}
@endif
@php
if ($currentKey !== $key) {
$currentKey = $key;
}
@endphp
</td>
<td style="width:1%; padding: 2px; vertical-align: top;">:</td>
<td style="padding: 2px;">
@if (strpos(strtolower($key), 'tanggal') !== false)
{{ formatTanggalIndonesia($item) }}
@else
{{ $item }}
@if ($key == 'luas_bangunan' || $key == 'luas_tanah')
<span></span>
@endif
@endif
</td>
</tr>
@endif
@endforeach
@endforeach
@endif

View File

@@ -1,41 +1,16 @@
@if (@isset($dokumen))
@foreach ($dokumen->detail as $detail)
@if (!empty($detail->name) && isset($detail->details) && !empty($detail->dokumen_jaminan))
{{-- @if (!empty($detail->name) && isset($detail->details) && !empty($detail->dokumen_jaminan))
<tr>
<td width="25%"><strong>{{ $detail->name ?? '' }}</strong></td>
</tr>
@endif
@if (isset($detail->details))
@php
$details = json_decode($detail->details, true);
@endphp
@if (is_array($details) && count($details) > 0)
@foreach ($details as $value)
@if (is_array($value))
@foreach ($value as $key => $item)
@if (!empty($item))
<tr>
<td style="padding: 2px;">
{{ formatLabel($key) }}
</td>
<td style="width:1%; padding: 2px; vertical-align: top;">:</td>
<td style="padding: 2px;">
@if (strpos(strtolower($key), 'tanggal') !== false)
{{ formatTanggalIndonesia($item) }}
@else
{{ $item }}
@if ($key == 'luas_bangunan' || $key == 'luas_tanah')
<span></span>
@endif
@endif
</td>
</tr>
@endif
@endforeach
@endif
@endforeach
@endif --}}
@if ($detail->name != 'LOKASI JAMINAN')
@if (isset($detail->details))
@php
$details = json_decode($detail->details, true);
@endphp
@include('lpj::component.detail-lokasi', ['details' => $details])
@endif
@endif
@endforeach

View File

@@ -0,0 +1,132 @@
@extends('layouts.main')
@section('breadcrumbs')
{{-- {{ Breadcrumbs::render(request()->route()->getName()) }} --}}
@endsection
@section('content')
<div class="w-full grid gap-5 lg:gap-7.5 mx-auto">
<div class="card">
<div class="card-header py-5 flex-wrap">
<div class="card-title flex flex-row gap-1.5">
<button id="tab-laporan" class="btn btn-sm btn-primary">Laporan</button>
<button id="tab-hasil" class="btn btn-sm btn-light">Hasil Inspeksi</button>
</div>
<div class="flex items-wrap gap-2.5">
{{-- <a href="{{ $back ?? route()->previous()}}" class="btn btn-xs btn-info"><i
class="ki-filled ki-exit-left"></i>
Back</a> --}}
<a id="back-button" class="btn btn-xs btn-info">
<i class="ki-filled ki-exit-left"></i> Back
</a>
</div>
</div>
</div>
<div class="card-body">
@php
$permohonan_id = request()->segment(3);
$dokumen_id = request()->segment(4);
$jenis_jaminan_id = request()->segment(5);
@endphp
<div id="laporan" class="tab-content">
<div class="floating-button">
<a href="penilai/print-out-laporan/{{ $permohonan_id }}/{{ $dokumen_id }}/{{ $jenis_jaminan_id }}" class="btn btn-primary">
Cetak Laporan
<i class="ki-filled ki-printer"></i>
</a>
</div>
@php
$laporan = [
'sederhana' => 'lpj::penilai.components.print-out-sederhana',
'standar' => 'lpj::penilai.components.print-out-standar',
'resume' => 'lpj::penilai.components.print-resume',
'memo' => 'lpj::penilai.components.print-memo',
'rap' => 'lpj::penilai.components.print-out-rap',
'call-report' => 'penilai.components.print-out-call-report',
];
@endphp
@if (array_key_exists($lpj->type_penilai, $laporan))
@include($laporan[$lpj->type_penilai])
@else
<p>Tipe laporan tidak ditemukan.</p>
@endif
</div>
<div id="hasil-inspeksi" class="tab-content hidden-tab">
<div class="floating-button">
<a href="surveyor/print-out-inspeksi/{{ $permohonan_id }}/{{ $dokumen_id }}/{{ $jenis_jaminan_id }}"
class="btn btn-primary">
Cetak Laporan
<i class="ki-filled ki-printer"></i>
</a>
</div>
@include('lpj::surveyor.components.print-out.main')
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const tabLaporan = document.getElementById('tab-laporan');
const tabHasil = document.getElementById('tab-hasil');
const laporanContent = document.getElementById('laporan');
const hasilContent = document.getElementById('hasil-inspeksi');
tabLaporan.addEventListener('click', () => {
tabLaporan.classList.add('btn-primary');
tabLaporan.classList.remove('btn-light');
tabHasil.classList.add('btn-light');
tabHasil.classList.remove('btn-primary');
laporanContent.classList.remove('hidden-tab');
hasilContent.classList.add('hidden-tab');
});
tabHasil.addEventListener('click', () => {
tabHasil.classList.add('btn-primary');
tabHasil.classList.remove('btn-light');
tabLaporan.classList.add('btn-light');
tabLaporan.classList.remove('btn-primary');
laporanContent.classList.add('hidden-tab');
hasilContent.classList.remove('hidden-tab');
});
});
document.getElementById('back-button').addEventListener('click', function(e) {
e.preventDefault();
console.log('Back button clicked', window.history.length);
if (window.history.length > 1) {
window.history.back();
} else {
window.location.href = "{{ $back ?? route()->previous()}}";
}
});
</script>
<style>
.hidden-tab {
display: none;
}
.floating-button {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 1000;
}
.floating-button .btn {
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
border-radius: 50px;
padding: 10px 20px;
}
.floating-button .btn:hover {
transform: scale(1.05);
transition: transform 0.2s ease-in-out;
}
</style>
{{-- @include('lpj::surveyor.js.utils') --}}
@endsection

View File

@@ -0,0 +1,113 @@
@extends('layouts.main')
@section('breadcrumbs')
{{-- {{ Breadcrumbs::render(request()->route()->getName()) }} --}}
@endsection
@section('content')
<div class="w-full grid gap-5 lg:gap-7.5 mx-auto">
<form
action="{{ isset($daftarPustaka->id) ? route('daftar-pustaka.update', $daftarPustaka->id) : route('daftar-pustaka.store') }}"
method="POST" enctype="multipart/form-data">
@csrf
@if (isset($daftarPustaka->id))
<input type="hidden" name="id" value="{{ $daftarPustaka->id }}">
@method('PUT')
@endif
<div class="card border border-agi-100 pb-2.5">
<div class="card-header bg-agi-50" id="basic_settings">
<h3 class="card-title">
{{ isset($daftarPustaka->id) ? 'Edit' : 'Tambah' }} Daftar Pustaka
</h3>
<div class="flex items-center gap-2">
<a href="{{ route('daftar-pustaka.index') }}" class="btn btn-xs btn-info"><i
class="ki-filled ki-exit-left"></i> Back</a>
</div>
</div>
<div class="card-body grid gap-5">
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label class="form-label max-w-56">
Judul
</label>
<div class="flex flex-wrap items-baseline w-full">
<input class="input @error('judul') border-danger bg-danger-light @enderror" type="text"
name="judul" value="{{ $daftarPustaka->judul ?? old('judul') }}">
@error('judul')
<em class="alert text-danger text-sm">{{ $message }}</em>
@enderror
</div>
</div>
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label class="form-label max-w-56">
Upload File
</label>
<div class="flex flex-wrap items-baseline w-full">
<input class="input @error('attachment') border-danger bg-danger-light @enderror" type="file"
name="attachment">
@error('attachment')
<em class="alert text-danger text-sm">{{ $message }}</em>
@enderror
</div>
</div>
@if (isset($daftarPustaka->attachment))
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label class="form-label max-w-56">
File
</label>
<div class="flex flex-wrap items-baseline w-full">
{{-- ambil nama file pathnya hilangkan --}}
<a href="{{ asset('storage/' .$daftarPustaka->attachment) }}" class="badge badge-outline badge-md badge-info">{{ basename($daftarPustaka->attachment) }} &nbsp;
<i class="ki-filled ki-cloud-download"></i>
</a>
</div>
</div>
@endif
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label class="form-label max-w-56">
Kategori
</label>
<div class="flex flex-wrap items-baseline w-full">
<select class="select tomselect w-full" name="category_id">
<option value="">Pilih Kategori</option>
@if (isset($categories))
@foreach ($categories as $item)
<option value="{{ $item->id }}"
{{ old('category_id', $daftarPustaka->category_id ?? '') == $item->id ? 'selected' : '' }}>
{{ $item->name }}
</option>
@endforeach
@endif
</select>
@error('category_id')
<em class="alert text-danger text-sm">{{ $message }}</em>
@enderror
</div>
</div>
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<label class="form-label max-w-56">
Deskripsi
</label>
<div class="flex flex-wrap items-baseline w-full">
<textarea name="deskripsi" class="textarea" id="" cols="30" rows="10">{{ $daftarPustaka->deskripsi ?? old('deskripsi') }}</textarea>
@error('deskripsi')
<em class="alert text-danger text-sm">{{ $message }}</em>
@enderror
</div>
</div>
<div class="flex justify-end">
<button type="submit" class="btn btn-primary">
{{ isset($daftarPustaka->id) ? 'Update' : 'Simpan' }}
</button>
</div>
</div>
</div>
</form>
</div>
@endsection

View File

@@ -0,0 +1,296 @@
@extends('layouts.main')
@section('breadcrumbs')
{{-- {{ Breadcrumbs::render('basicdata.ijin_usaha') }} --}}
@endsection
@section('content')
<style>
@media (max-width: 768px) {
#previewContent {
height: 400px;
overflow: auto;
}
}
</style>
<div class="flex flex-col items-stretch gap-7">
<div class="flex items-center gap-3 w-full">
<div class="input w-full">
<i class="ki-filled ki-magnifier">
</i>
<input id="search" placeholder="Search Daftar Pustaka, Judul" type="text">
<span class="badge badge-outline -me-1.5">
K
</span>
</div>
<!--Filter-->
<a class="btn btn-info" id="search_filter" onclick="filterSearch()">
<i class="ki-filled ki-filter">
</i>
Filter
</a>
<a class="btn btn-light" id="reset_filter" onclick="resetFilter()">
<i class="ki-filled ki-arrow-circle-left"></i>
Reset Filter
</a>
</div>
<div class="flex flex-wrap items-center gap-5 justify-between mt-3">
<h3 class="text-sm text-mono font-medium">
page {{ $page }} of {{ $pageCount }} {{ $limit }} items per page, total
{{ $total }} items.
</h3>
<div class="flex gap-2.5">
<select id="category_id" name="category_id" class="select tomselect w-[300px]" multiple>
<option value="" selected disabled>Filter by Category</option>
@foreach ($categories as $item)
<option value="{{ $item->id }}">{{ $item->name }}</option>
@endforeach
</select>
<div class="flex toggle-group" data-kt-tabs="true" data-kt-tabs-initialized="true">
<a class="btn btn-icon active selected" data-kt-tab-toggle="#daftar_pustaka_grid" onclick="showGrid()"
href="javascript:void(0)">
<i class="ki-filled ki-category"></i>
</a>
<a class="btn btn-icon" data-kt-tab-toggle="#daftar_pustaka_list" onclick="showList()"
href="javascript:void(0)">
<i class="ki-filled ki-row-horizontal"></i>
</a>
@if (auth()->user()->hasRole(['administrator', 'admin']))
<a href="{{ route('daftar-pustaka.create') }}" class="btn btn-primary">
<i class="ki-filled ki-plus"></i>
Tambah
</a>
@endif
</div>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 gap-4 " id="daftar_pustaka_grid">
@if (isset($daftar_pustaka))
@foreach ($daftar_pustaka as $item)
<div class="card border shadow-none ">
<a class="show-pustaka h-[300px] bg-gray-200 w-full block" href="{{ route('daftar-pustaka.show', $item->id) }}"
data-url="{{ $item->attachment }}">
<div class="p-4 h-full w-full flex items-center justify-center overflow-hidden">
<div class=" text-red-500 flex items-center justify-center rounded">
<i class="ki-filled ki-document text-3xl"></i>
</div>
</div>
</a>
<div class="card-body">
<a href="{{ route('daftar-pustaka.show', $item->id) }}">
<h3 class="text-md font-medium text-gray-900 hover:text-primary cursor-pointer">
{{ $item->judul }}</h3>
<p class="text-2sm text-gray-700">
{{-- batasi panjang deskripsi 50 --}}
{{ substr($item->deskripsi, 0, 50) }}
</p>
</a>
<div class="flex justify-between items-center gap-2.5 mt-2">
<p class="badge rounded-full badge-xs badge-outline badge-success text-xs text-gray-700">
# {{ $item->category->name }}</p>
@auth
@if (auth()->user()->hasRole(['administrator', 'admin']))
<div>
<a class="btn btn-xs btn-danger" onclick="deleteData({{ $item->id }})">
<i class="ki-filled ki-trash">
</i>
Hapus
</a>
<a class="btn btn-xs btn-info"
href="{{ route('daftar-pustaka.edit', $item->id) }}">
<i class="ki-filled ki-pencil">
</i>
Edit
</a>
</div>
@endif
@endauth
</div>
</div>
</div>
@endforeach
@endif
</div>
<div class="grid grid-cols-1 gap-4 hidden" id="daftar_pustaka_list">
@if (isset($daftar_pustaka))
@foreach ($daftar_pustaka as $item)
<div class="card">
<div class="card-body flex items-center flex-wrap justify-between p-2 pe-5 gap-4.5">
<div class="flex items-center gap-3.5">
<div
class="card bg-gray-200 flex items-center justify-center bg-accent/50 h-[70px] w-[90px] shadow-none">
<a class="show-pustaka h-[90px] w-full block"
href="{{ route('daftar-pustaka.show', $item->id) }}"
data-url="{{ $item->attachment }}">
<div class="p-4 h-full w-full flex items-center justify-center overflow-hidden">
<div class=" text-red-500 flex items-center justify-center rounded">
<i class="ki-filled ki-document text-3xl"></i>
</div>
</div>
</a>
</div>
<a href="{{ route('daftar-pustaka.show', $item->id) }}">
<div class="flex flex-col gap-2 cursor-pointer">
<div class="flex items-center mt-1">
<a class="hover:text-primary text-sm font-medium text-mono leading-5.5">
{{ $item->judul }}
</div>
</a>
<div class="flex items-center flex-wrap gap-3">
<span class="kt-badge kt-badge-warning kt-badge-sm rounded-full gap-1">
<span class="text-xs font-medium text-foreground">
{{ substr($item->deskripsi, 0, 50) }}
</span>
</span>
</div>
</div>
</a>
</div>
<div class="flex items-center gap-1.5">
<p class="badge rounded-full badge-sm badge-outline badge-success text-xs text-gray-700">
# {{ $item->category->name }}</p>
@auth
@if (auth()->user()->hasRole(['administrator', 'admin']))
<div>
<a class="btn btn-sm btn-danger" onclick="deleteData({{ $item->id }})">
<i class="ki-filled ki-trash">
</i>
Hapus
</a>
<a class="btn btn-sm btn-info"
href="{{ route('daftar-pustaka.edit', $item->id) }}">
<i class="ki-filled ki-pencil">
</i>
Edit
</a>
</div>
@endif
@endauth
</div>
</div>
</div>
@endforeach
@endif
</div>
<div class="pagination flex gap-2 justify-center mt-5">
@if ($daftar_pustaka->onFirstPage())
<span class="btn disabled"><i class="ki-filled ki-black-left"></i></span>
@else
<a href="{{ $daftar_pustaka->previousPageUrl() }}" class="btn">
<i class="ki-filled ki-black-left"></i>
</a>
@endif
@foreach ($daftar_pustaka->getUrlRange(1, $daftar_pustaka->lastPage()) as $page => $url)
<a href="{{ $url }}" class="btn {{ $page == $daftar_pustaka->currentPage() ? 'active' : '' }}">
{{ $page }}
</a>
@endforeach
@if ($daftar_pustaka->hasMorePages())
<a href="{{ $daftar_pustaka->nextPageUrl() }}" class="btn">
<i class="ki-filled ki-black-right"></i>
</a>
@else
<span class="btn disabled"><i class="ki-filled ki-black-right"></i></span>
@endif
</div>
</div>
@endsection
@push('scripts')
<script type="text/javascript">
function deleteData(data) {
Swal.fire({
title: 'Are you sure?',
text: "You won't be able to revert this!",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, delete it!'
}).then((result) => {
if (result.isConfirmed) {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
}
});
$.ajax(`daftar-pustaka/${data}`, {
type: 'DELETE'
}).then((response) => {
swal.fire('Deleted!', 'User has been deleted.', 'success').then(() => {
window.location.reload();
});
}).catch((error) => {
console.error('Error:', error);
Swal.fire('Error!', 'An error occurred while deleting the file.', 'error');
});
}
})
}
function showGrid() {
document.getElementById("daftar_pustaka_grid").classList.remove("hidden");
document.getElementById("daftar_pustaka_grid").classList.add("active");
document.getElementById("daftar_pustaka_list").classList.add("hidden");
document.getElementById("daftar_pustaka_list").classList.remove("active");
// Update button active class
document.querySelectorAll(".toggle-group a").forEach(btn => btn.classList.remove("selected", "active"));
event.currentTarget.classList.add("selected", "active");
}
function showList() {
document.getElementById("daftar_pustaka_list").classList.remove("hidden");
document.getElementById("daftar_pustaka_list").classList.add("active");
document.getElementById("daftar_pustaka_grid").classList.add("hidden");
document.getElementById("daftar_pustaka_grid").classList.remove("active");
// Update button active class
document.querySelectorAll(".toggle-group a").forEach(btn => btn.classList.remove("selected", "active"));
event.currentTarget.classList.add("selected", "active");
}
function filterSearch() {
const search = document.getElementById('search')?.value || '';
const select = document.getElementById('category_id');
const selectedCategories = Array.from(select.selectedOptions).map(option => option.value);
const categoryParam = selectedCategories.join(',');
const url = "{{ route('daftar-pustaka.index') }}?search=" + encodeURIComponent(search) + "&category=" +
encodeURIComponent(categoryParam);
window.location.href = url;
}
function resetFilter() {
const url = "{{ route('daftar-pustaka.index') }}";
window.location.href = url;
}
</script>
@endpush

View File

@@ -0,0 +1,165 @@
@extends('layouts.main')
@section('breadcrumbs')
@endsection
@section('content')
<div class="w-full grid gap-5 lg:gap-7.5 mx-auto">
<form
action="{{ isset($daftarPustaka->id) ? route('daftar-pustaka.update', $daftarPustaka->id) : route('daftar-pustaka.store') }}"
method="POST">
@csrf
<div class="card border border-agi-100 pb-2.5">
<div class="card-header bg-agi-50" id="basic_settings">
<h3 class="card-title">
{{ $daftarPustaka->judul ?? '' }}
</h3>
<div class="flex items-center gap-2">
<a href="{{ route('daftar-pustaka.index') }}" class="btn btn-xs btn-info">
<i class="ki-filled ki-exit-left"></i> Back
</a>
</div>
</div>
<div class="card-body grid gap-5">
<div class="min-w-3xl">
<div class="p-4 h-full flex flex-col">
<div class="flex justify-between items-center mb-4">
<a href="{{ asset('storage/' . $daftarPustaka->attachment) }}" class="btn btn-primary btn-sm">
<i class="ki-duotone ki-cloud-download me-1"></i>
Download File
</a>
</div>
@php
$fileExtension = pathinfo($daftarPustaka->attachment, PATHINFO_EXTENSION);
$isPdf = strtolower($fileExtension) == 'pdf';
$imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
$isImage = in_array(strtolower($fileExtension), $imageExtensions);
$fileUrl = asset('storage/' . $daftarPustaka->attachment);
@endphp
@if ($isPdf)
<canvas id="pdfViewer" class="w-full border rounded touch-pan-y"></canvas>
<div class="flex justify-center gap-3 mt-3">
<button type="button" id="prevPage" class="btn btn-primary btn-sm">Previous</button>
<span>Page: <span id="pageNum">1</span> / <span id="pageCount">0</span></span>
<button type="button" id="nextPage" class="btn btn-primary btn-sm">Next</button>
</div>
@elseif ($isImage)
<img src="{{ $fileUrl }}" class="w-full object-contain rounded" />
@else
<p class="text-red-500">File tidak bisa ditampilkan, silakan
<a href="{{ $fileUrl }}" class="text-blue-500 underline" download>unduh di sini</a>.
</p>
@endif
</div>
</div>
<div class="border border-t"></div>
<div>
{{ $daftarPustaka->deskripsi ?? '' }}
</div>
</div>
</div>
</form>
</div>
@endsection
@push('scripts')
<!-- PDF.js CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
const url = @json($fileUrl);
if (url.endsWith('.pdf')) {
const pdfjsLib = window['pdfjs-dist/build/pdf'];
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';
let pdfDoc = null;
let pageNum = 1;
let pageRendering = false;
let pageNumPending = null;
const scale = 1.3;
const canvas = document.getElementById('pdfViewer');
const ctx = canvas.getContext('2d');
function renderPage(num) {
pageRendering = true;
pdfDoc.getPage(num).then(function (page) {
const viewport = page.getViewport({ scale: scale });
canvas.height = viewport.height;
canvas.width = viewport.width;
const renderContext = {
canvasContext: ctx,
viewport: viewport
};
const renderTask = page.render(renderContext);
renderTask.promise.then(function () {
pageRendering = false;
document.getElementById('pageNum').textContent = num;
if (pageNumPending !== null) {
renderPage(pageNumPending);
pageNumPending = null;
}
});
});
}
function queueRenderPage(num) {
if (pageRendering) {
pageNumPending = num;
} else {
renderPage(num);
}
}
function onPrevPage() {
if (pageNum <= 1) return;
pageNum--;
queueRenderPage(pageNum);
}
function onNextPage() {
if (pageNum >= pdfDoc.numPages) return;
pageNum++;
queueRenderPage(pageNum);
}
document.getElementById('prevPage').addEventListener('click', onPrevPage);
document.getElementById('nextPage').addEventListener('click', onNextPage);
// Swipe gesture
let touchStartX = 0;
let touchEndX = 0;
canvas.addEventListener('touchstart', function (e) {
touchStartX = e.changedTouches[0].screenX;
});
canvas.addEventListener('touchend', function (e) {
touchEndX = e.changedTouches[0].screenX;
handleSwipe();
});
function handleSwipe() {
const swipeThreshold = 50; // min distance for swipe
if (touchEndX < touchStartX - swipeThreshold) {
onNextPage();
} else if (touchEndX > touchStartX + swipeThreshold) {
onPrevPage();
}
}
pdfjsLib.getDocument(url).promise.then(function (pdfDoc_) {
pdfDoc = pdfDoc_;
document.getElementById('pageCount').textContent = pdfDoc.numPages;
renderPage(pageNum);
});
}
});
</script>
@endpush

View File

@@ -95,7 +95,7 @@
@foreach($dokumen_jaminan as $index => $dokumen)
<div class="flex items-center justify-between flex-wrap my-2.5 gap-2">
<span class="text-2xs text-gray-600 uppercase pl-3">
{{ $loop->index+1 }}. Nomor : {{ $dokumen_nomor[$index] }}
{{ $loop->index+1 }}. Nomor : {{ $dokumen_nomor[$index] ?? '' }}
</span>
<div>
@if(in_array(Auth::user()->roles[0]->name,['administrator','pemohon-eo']))

View File

@@ -44,15 +44,6 @@
@endforeach
</select>
</div>
<div class="flex flex-col">
<label class="text-base font-medium mb-1">Penilai</label>
<select class="select tomselect" id="penilai_filter">
<option value="">Semua Penilai</option>
@foreach(\MOdules\Usermanagement\Models\User::role(['penilai','surveyor'])->get() as $penilai)
<option value="{{ $penilai->id }}">{{ $penilai->name }}</option>
@endforeach
</select>
</div>
</div>
<!-- Buttons row at the bottom -->
@@ -73,7 +64,7 @@
<div class="card border border-agi-100 card-grid min-w-full" data-datatable="false" data-datatable-page-size="10" data-datatable-state-save="false" id="laporan-hasil-penilaian-jaminan-internal-external-table" data-api-url="{{ route('laporan-hasil-penilaian-jaminan-internal-external.data') }}">
<div class="card-header bg-agi-50 py-5 flex-wrap">
<h3 class="card-title">
Laporan Hasil Penilaian Jaminan Internal & External
Rekap Penyelesaian External
</h3>
</div>
@@ -89,130 +80,53 @@
<span class="sort"> <span class="sort-label"> Nomor Registrasi </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="tanggal_permohonan">
<span class="sort"> <span class="sort-label"> Tanggal Permohonan </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="branch">
<span class="sort"> <span class="sort-label"> Cabang </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="pemohon">
<span class="sort"> <span class="sort-label"> Pemohon </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="cif">
<span class="sort"> <span class="sort-label"> CIF </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="name">
<th class="min-w-[150px]" data-datatable-column="name">
<span class="sort"> <span class="sort-label"> Nama Debitur </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="tanggal_permohonan">
<span class="sort"> <span class="sort-label"> Tanggal KSL </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="pemohon">
<span class="sort"> <span class="sort-label"> Nomor KSL </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="cif">
<span class="sort"> <span class="sort-label"> Nominal KSL </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="jenis_penilaian">
<span class="sort"> <span class="sort-label"> Jenis Penilaian </span>
<span class="sort"> <span class="sort-label">Tanggal Penyelesaian </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="tujuan_penilaian">
<span class="sort"> <span class="sort-label"> Tujuan Penilaian </span>
<span class="sort"> <span class="sort-label"> Nominal Penyelesaian </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="jenis_fasilitas_kredit">
<span class="sort"> <span class="sort-label"> Jenis Fasilitas Kredit </span>
<span class="sort"> <span class="sort-label"> No. Rekening (Tujuan Akhir) </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="jenis_fasilitas_kredit">
<span class="sort"> <span class="sort-label"> Sisa KSL </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="jenis_agunan">
<span class="sort"> <span class="sort-label"> Jenis Agunan </span>
<span class="sort"> <span class="sort-label"> Memo </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="alamat_agunan">
<span class="sort"> <span class="sort-label"> Alamat Agunan </span>
<span class="sort"> <span class="sort-label"> Status</span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="bukti_kepemilikan">
<span class="sort"> <span class="sort-label"> Bukti Kepemilikan </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="nama_pemilik">
<span class="sort"> <span class="sort-label"> Nama Pemilik </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="luas_tanah">
<span class="sort"> <span class="sort-label"> Luas Tanah </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="nilai_tanah">
<span class="sort"> <span class="sort-label"> Nilai Tanah </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="luas_bangunan">
<span class="sort"> <span class="sort-label"> Luas Bangunan </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="nilai_bangunan">
<span class="sort"> <span class="sort-label"> Nilai Bangunan </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="nilai_njop">
<span class="sort"> <span class="sort-label"> Nilai NJOP </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="nilai_pasar_wajar">
<span class="sort"> <span class="sort-label"> Nilai Pasar Wajar </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="nilai_likuidasi">
<span class="sort"> <span class="sort-label"> Nilai Likuidasi </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="tanggal_documen_diterima">
<span class="sort"> <span class="sort-label"> Tanggal Dokumen Diterima </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="tanggal_spk">
<span class="sort"> <span class="sort-label"> Tanggal SPK </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="nomor_spk">
<span class="sort"> <span class="sort-label"> Nomor SPK </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="tanggal_rencana_kunjunagn">
<span class="sort"> <span class="sort-label"> Tanggal Rencana Kunjungan </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="tanggal_kunjungan">
<span class="sort"> <span class="sort-label"> Tanggal Kunjungan </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="taggal_delivered">
<span class="sort"> <span class="sort-label"> Tanggal Delivered </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="jangka_waktu_sla">
<span class="sort"> <span class="sort-label"> Jangka Waktu SLA </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="tanggal_laporan">
<span class="sort"> <span class="sort-label"> Tanggal Laporan </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="tanggal_review">
<span class="sort"> <span class="sort-label"> Tanggal Review </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="nama_penilai">
<span class="sort"> <span class="sort-label"> Nama Penilai </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="nama_team_leader">
<span class="sort"> <span class="sort-label"> Nama Team Leader </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="saran">
<span class="sort"> <span class="sort-label"> Saran </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="catatan">
<span class="sort"> <span class="sort-label"> Catatan </span>
<span class="sort-icon"> </span> </span>
@@ -266,144 +180,41 @@
nomor_registrasi: {
title: 'Nomor Registrasi',
},
tanggal_permohonan: {
branch: {
title: 'Cabang',
},
name: {
title: 'Nama Debitur',
},
tanggal_ksl: {
title: 'Tanggal Permohonan',
render: (item, data) => {
return data.tanggal_permohonan ? window.formatTanggalIndonesia(data.tanggal_permohonan) : '-';
},
},
branch: {
title: 'Cabang',
},
pemohon: {
title: 'Pemohon',
},
cif: {
nomor_ksl: {
title: 'CIF',
},
name: {
title: 'Nama Debitur',
},
jenis_penilaian: {
nominal_ksl: {
title: 'Jenis Penilaian',
},
tujuan_penilaian: {
tanggal_penyelesaian: {
title: 'Tujuan Penilaian',
},
jenis_fasilitas_kredit: {
nominal_penyelesaian: {
title: 'Jenis Fasilitas Kredit',
},
jenis_agunan: {
nomor_rekening: {
title: 'Nomor Rekening',
},
sisa_ksl: {
title: 'Jenis Agunan',
},
alamat_agunan: {
title: 'Alamat Agunan',
memo: {
title: 'Memo',
},
bukti_kepemilikan: {
title: 'Bukti Kepemilikan',
render: (item, data) => {
if (data.bukti_kepemilikan) {
// Ganti karakter baris baru dengan tag <br> untuk HTML
return data.bukti_kepemilikan.split('\n').join('<br>');
}
return '-';
},
},
nama_pemilik: {
title: 'Nama Pemilik',
},
luas_tanah: {
title: 'Luas Tanah',
},
nilai_tanah: {
title: 'Nilai Tanah',
render: (item, data) => {
return data.nilai_tanah ?? '-';
},
},
luas_bangunan: {
title: 'Luas Bangunan',
},
nilai_bangunan: {
title: 'Nilai Bangunan',
render: (item, data) => {
return data.nilai_bangunan ?? '-';
},
},
nilai_njop: {
title: 'Nilai NJOP',
render: (item, data) => {
return data.nilai_njop ?? '-';
},
},
nilai_pasar_wajar: {
title: 'Nilai Pasar Wajar',
render: (item, data) => {
return data.nilai_pasar_wajar ?? '-';
},
},
nilai_likuidasi: {
title: 'Nilai Likuidasi',
render: (item, data) => {
return data.nilai_likuidasi ?? '-';
},
},
tanggal_documen_diterima: {
title: 'Tanggal Dokumen Diterima',
render: (item, data) => {
return data.tanggal_documen_diterima ? window.formatTanggalIndonesia(data.tanggal_documen_diterima) : '-';
},
},
tanggal_spk: {
title: 'Tanggal SPK',
render: (item, data) => {
return data.tanggal_spk ? window.formatTanggalIndonesia(data.tanggal_spk) : '-';
},
},
nomor_spk: {
title: 'Nomor SPK',
},
tanggal_rencana_kunjunagn: {
title: 'Tanggal Rencana Kunjungan',
render: (item, data) => {
return data.tanggal_rencana_kunjunagn ? window.formatTanggalIndonesia(data.tanggal_rencana_kunjunagn) : '-';
},
},
tanggal_kunjungan: {
title: 'Tanggal Kunjungan',
render: (item, data) => {
return data.tanggal_kunjungan ? window.formatTanggalIndonesia(data.tanggal_kunjungan) : '-';
},
},
taggal_delivered: {
title: 'Tanggal Delivered',
render: (item, data) => {
return data.taggal_delivered ? window.formatTanggalIndonesia(data.taggal_delivered) : '-';
},
},
jangka_waktu_sla: {
title: 'Jangka Waktu SLA',
},
tanggal_laporan: {
title: 'Tanggal Laporan',
render: (item, data) => {
return data.tanggal_laporan ? window.formatTanggalIndonesia(data.tanggal_laporan) : '-';
},
},
tanggal_review: {
title: 'Tanggal Review',
render: (item, data) => {
return data.tanggal_review ? window.formatTanggalIndonesia(data.tanggal_review) : '-';
},
},
nama_penilai: {
title: 'Nama Penilai',
},
nama_team_leader: {
title: 'Nama Team Leader',
},
saran: {
title: 'Saran',
status: {
title: 'Status',
},
catatan: {
title: 'Catatan',

Some files were not shown because too many files have changed in this diff Show More