Compare commits

...

21 Commits

Author SHA1 Message Date
Daeng Deni Mardaeni
d9d8eaafcd fix(calc): Fallback hitung likuidasi dari persen x Total NPW
- Jika mig_mst_lpj_tot_nilai_likuidasi kosong, hitung likuidasi = (lpjData['likuidasi']/100) x Total Nilai Pasar Wajar
- Membersihkan input persen (menghapus %/spasi dan mengganti koma menjadi titik)
- Menormalkan Total NPW dari format Rupiah (menghapus Rp, titik, koma) ke angka murni
2025-12-04 11:22:08 +07:00
Daeng Deni Mardaeni
f055cd5573 🧩 fix(print): Perbaiki pembacaan array hub_cadeb & hapus debug
- Memperbaiki logika penentuan status 'sesuai'/'tidak sesuai' dengan membaca key dari array hub_cadeb
- Mengambil label dari array sesuai key yang tersedia dan memberikan fallback aman jika key tidak ada
- Menangani kasus ketika hub_cadeb berupa string ('sesuai'/'tidak sesuai') agar tetap ada output
2025-12-04 11:21:34 +07:00
Daeng Deni Mardaeni
aee8fab832 📏 feat(ui): Tambah auto-suffix m/km pada input jarak lingkungan
- Menambahkan class measure-input dan atribut data-unit pada:
  - jarak_jalan_utama (km)
  - jarak_cbd_point (km)
- Menambahkan script untuk:
  - Membatasi input hanya angka dan koma
  - Menghapus suffix saat fokus dan input
  - Menambahkan suffix otomatis saat blur
  - Menghapus suffix saat submit agar backend menerima angka bersih
- Menyediakan cara mengubah unit ke 'm' dengan mengganti data-unit pada input
2025-12-04 11:20:37 +07:00
Daeng Deni Mardaeni
a72cbe4bd9 🧩 fix(print): Perbaiki pembacaan array hub_cadeb & hapus debug
- Memperbaiki logika penentuan status 'sesuai'/'tidak sesuai' dengan membaca key dari array hub_cadeb
- Mengambil label dari array sesuai key yang tersedia dan memberikan fallback aman jika key tidak ada
- Menangani kasus ketika hub_cadeb berupa string ('sesuai'/'tidak sesuai') agar tetap ada output
2025-12-03 21:30:59 +07:00
Daeng Deni Mardaeni
ea09e8161c 🐛 fix(print): Perbaiki akses offset array dan format angka LPJ
- Memperbaiki akses nilai hubungan penghuni dengan debitur:
  - Jika hub_cadeb_penghuni bertipe array, gunakan key terpilih dari hub_cadeb_penghuni_selected atau hub_cadeb_penghuni_value untuk mengambil label yang benar
  - Jika hub_cadeb_penghuni bertipe scalar/string, tampilkan nilainya langsung
  - Menghindari error “Cannot access offset of type array on array” ketika nilai dan indeks bercampur
- Menormalkan format angka agar aman dari nilai null dan tipe campuran:
  - Total Nilai Pasar Wajar: number_format((float) ($lpjData['total_nilai_pasar_wajar'] ?? $totalNilaiPasarWajar ?? 0), 0, ',', '.')
  - Total Nilai Likuidasi: number_format($permohonan_migrasi->mig_mst_lpj_tot_nilai_likuidasi ?? 0, 0, ',', '.')
- Meningkatkan ketahanan tampilan:
  - Mengurangi potensi undefined index dan memastikan fallback nilai aman ketika data tidak tersedia
  - Menjaga konsistensi output angka di bagian ringkasan nilai
2025-12-03 15:10:12 +07:00
Daeng Deni Mardaeni
f051fa9507 feat(penilai/print-out): generasi baris nilai dinamis, tambah satuan jarak
- Tambah sufiks satuan m pada jarak_jalan_utama di resources/views/penilai/components/analisa/lingkungan.blade.php agar konsisten menampilkan satuan meter
- Refactor perhitungan tabel nilai di resources/views/penilai/components/print-out-sederhana.blade.php menjadi iterasi dinamis menggunakan labelNilai untuk menampilkan baris Tanah/Bangunan berdasarkan ketersediaan data luas_* dan nilai_*_1/_2
- Refactor bagian nilai di resources/views/penilai/components/print-out-standar.blade.php untuk non-MIG ( !$permohonan->is_mig ) menjadi loop dinamis yang sama sehingga konsisten antara “sederhana” dan “standar”
- Pastikan akumulasi totalNilaiPasarWajar menggunakan nilai hasil format yang dibersihkan dari simbol dan pemisah ribuan, tetap menghitung dari nilai_*_2
- Jaga kompatibilitas existing: tetap menghormati npw_tambahan yang dirender setelah blok non-MIG
2025-11-26 17:38:17 +07:00
Daeng Deni Mardaeni
04a657252f feat(surveyor/print-out): tambah template cetak apartemen-kantor, rapikan UI, dan perbaiki binding nilai
- Tambah file resources/views/surveyor/components/print-out/apartemen-kantor.blade.php untuk layout cetak “Analisa Unit” yang menampilkan radio luas unit dan daftar checkbox untuk bentuk, kondisi, posisi, dan view
- Revisi resources/views/surveyor/components/print-out/apartement-kantor.blade.php guna menyeragamkan struktur tabel dan gaya cetak agar konsisten
- Normalisasi urutan dan konsistensi kelas Tailwind di resources/views/surveyor/components/apartemen-kantor.blade.php (penyusunan flex , items-baseline , flex-wrap , gap-* , konsistensi form-label , checkbox , radio )
- Rapi penamaan dan penempatan elemen pesan error <em id="error-*"> dengan susunan kelas seragam
- Sesuaikan grid ( grid-cols-2 md:grid-cols-3 ) dan mt-2 untuk responsivitas yang lebih baik
- Perbaiki binding nilai luas_unit_tidak_sesuai agar mengikuti struktur forminspeksi['luas_unit']['tidak sesuai'] sehingga data konsisten pada saat old value dan penyimpanan ulang
- Tingkatkan keterbacaan markup: urutan atribut kelas diseragamkan, label dan input disusun lebih konsisten untuk aksesibilitas dan UI
2025-11-26 17:26:42 +07:00
Daeng Deni Mardaeni
fc6f18fea9 (validation): Tambahkan pattern validasi koordinat latitude dan longitude
Menambahkan pattern regex untuk validasi input koordinat geografis pada form surveyor untuk memastikan data yang dimasukkan memiliki format yang valid dan sesuai dengan rentang koordinat yang benar.

Perubahan yang dilakukan:

**File yang dimodifikasi:**
1. `Modules/Lpj/resources/views/surveyor/components/pembanding-tanah-bangunan-unit.blade.php`
   - Menambahkan pattern pada input latitude utama: `^-?([1-8]?\d(\.\d+)?|90(\.0+)?)$`
   - Menambahkan pattern pada input longitude utama: `^-?(1[0-7]?\d(\.\d+)?|180(\.0+)?|[1-9]?\d(\.\d+)?)$`
   - Menambahkan pattern pada input latitude pembanding: `^-?([1-8]?\d(\.\d+)?|90(\.0+)?)$`
   - Menambahkan pattern pada input longitude pembanding: `^-?(1[0-7]?\d(\.\d+)?|180(\.0+)?|[1-9]?\d(\.\d+)?)$`

2. `Modules/Lpj/resources/views/surveyor/components/pembanding-kendaraan.blade.php`
   - Menambahkan pattern pada input latitude utama: `^-?([1-8]?\d(\.\d+)?|90(\.0+)?)$`
   - Menambahkan pattern pada input longitude utama: `^-?(1[0-7]?\d(\.\d+)?|180(\.0+)?|[1-9]?\d(\.\d+)?)$`
   - Menambahkan pattern pada input latitude pembanding: `^-?([1-8]?\d(\.\d+)?|90(\.0+)?)$`
   - Menambahkan pattern pada input longitude pembanding: `^-?(1[0-7]?\d(\.\d+)?|180(\.0+)?|[1-9]?\d(\.\d+)?)$`

3. `Modules/Lpj/resources/views/surveyor/components/header.blade.php`
   - Menambahkan pattern pada input latitude: `^-?([1-8]?\d(\.\d+)?|90(\.0+)?)$`
   - Menambahkan pattern pada input longitude: `^-?(1[0-7]?\d(\.\d+)?|180(\.0+)?|[1-9]?\d(\.\d+)?)$`
   - Memperbaiki duplikasi atribut `type="text"` pada input latitude

**Detail Pattern Validasi:**
- **Latitude**: Menerima nilai dari -90 sampai 90 derajat
  - Format: `-?([1-8]?\d(\.\d+)?|90(\.0+)?)`
  - Contoh valid: `-6.1234`, `0.123`, `90.0`, `-90.0`

- **Longitude**: Menerima nilai dari -180 sampai 180 derajat
  - Format: `-?(1[0-7]?\d(\.\d+)?|180(\.0+)?|[1-9]?\d(\.\d+)?)`
  - Contoh valid: `106.1234`, `0.123`, `180.0`, `-180.0`, `-106.1234`

**Manfaat:**
- Mencegah input koordinat yang tidak valid
- Standarisasi format data koordinat di seluruh form surveyor
- Memastikan data yang tersimpan memiliki presisi yang sesuai
- Meningkatkan akurasi data untuk keperluan pemetaan dan analisis lokasi

**Impact:**
- Validasi client-side akan menolak input koordinat yang tidak sesuai format
- Pesan error bawaan browser akan muncul jika format tidak valid
- Tidak ada perubahan pada logic backend (validasi tetap ada di server-side)
- Kompatibel dengan semua browser modern yang support HTML5 pattern
2025-11-20 14:36:05 +07:00
Daeng Deni Mardaeni
8c60320532 (Roles): Tambahkan role EO Appraisal ke berbagai komponen LPJ
## Perubahan Utama:
- 🔧 **Role Management**: Menambahkan role 'EO Appraisal' ke berbagai komponen untuk akses tombol simpan
- 🐛 **Fix Kondisi**: Memperbaiki logika kondisi untuk data MIG (Migrasi) di print-out-sederhana
- 💅 **UI Enhancement**: Konversi table ke div untuk bagian keterangan dengan format yang lebih rapi
- 🎨 **Code Style**: Fix indentation dan whitespace di PermohonanController

## Detail Perubahan:

### File yang Dimodifikasi:

1. **`resources/views/penilai/components/call-report.blade.php`** (Line 507):
   - Menambahkan `'EO Appraisal'` ke array role yang memiliki akses tombol simpan
   - Sebelumnya: `['senior-officer', 'surveyor', 'administrator']`
   - Sekarang: `['senior-officer', 'surveyor', 'administrator','EO Appraisal']`

2. **`resources/views/penilai/components/lpj-sederhana-standar.blade.php`** (Line 47):
   - Menambahkan `'EO Appraisal'` dan `'penilai'` ke role yang dapat menyimpan data
   - Memperluas akses untuk role penilai dan EO Appraisal

3. **`resources/views/penilai/components/memo.blade.php`** (Line 318):
   - Menambahkan `'EO Appraisal'` ke role yang dapat menyimpan memo
   - Memastikan konsistensi akses antar komponen

4. **`resources/views/penilai/components/print-out-sederhana.blade.php`**:
   - **Line 558-580**: Memperbaiki urutan kondisi pengecekan data MIG
     - Memindahkan fallback data tanah dan bangunan ke atas
     - Menambahkan kondisi `@if(!$permohonan->is_mig)` untuk data non-MIG
     - Menjaga data `npw_tambahan` tetap diproses setelahnya
   - **Line 647-700**: Konversi table ke div untuk bagian keterangan
     - Mengganti struktur `<table><tr><td>` menjadi `<div>` dengan styling yang lebih rapi
     - Menambahkan handling untuk berbagai format data (array, string, quoted)
     - Implementasi bullet points yang lebih konsisten
     - Menambahkan fallback message "Tidak ada catatan khusus"

5. **`resources/views/penilai/components/rap-penilai.blade.php`** (Line 72 & 115):
   - Menambahkan `'EO Appraisal'` ke role yang dapat menyimpan data RAP
   - Fix whitespace yang tidak perlu

6. **`resources/views/penilai/components/signature-approval.blade.php`** (Line 117):
   - Fix whitespace dan formatting

7. **`app/Http/Controllers/PermohonanController.php`** (Line 55):
   - Fix indentation yang tidak konsisten
   - Memperbaiki format kode untuk better readability
2025-11-18 17:28:04 +07:00
Daeng Deni Mardaeni
34709b0f8f 🐛 fix(lpj): Perbaikan format Rupiah, role access, dan validasi data
## Ringkasan
Melakukan perbaikan pada helper format Rupiah, akses role user, validasi data MIG, serta penyesuaian tampilan laporan dan dokumentasi.

## Perubahan Detail

### 🔧 Helper Function
**app/Helpers/Lpj.php**:
- Menambahkan parameter opsional `withSymbol` pada fungsi `formatRupiah()` untuk kontrol simbol Rp
- Menambahkan handling untuk menghapus titik (.) dari input number sebelum proses
- Memperbaiki return value untuk null/empty string sesuai parameter `withSymbol`
- Mengganti `str_pad()` dengan `sprintf()` untuk generate random number (lebih efisien)

### 🛠️ Service Layer
**app/Services/PreviewLaporanService.php**:
- Memperbaiki validasi data MIG dengan menambahkan pengecekan `is_mig` flag
- Menambahkan null safety pada property `mig_mst_lpj_tot_nilai_pasar`
- Memperbaiki kondisi logic untuk memo dan validasi nilai pasar

### 🎨 View Components
**resources/views/component/print-out-dokument.blade.php**:
- Memperbaiki syntax Blade dari `@isset` menjadi `isset()` yang lebih proper

**resources/views/debitur/components/debitur.blade.php**:
- Memperbaiki role checking dari `hasRole()` menjadi `hasAnyRole()` untuk multiple roles

**resources/views/debitur/index.blade.php**:
- Menambahkan role 'admin' pada kondisi edit dan delete actions
- Memperbaiki permission checking untuk administrator dan admin

**resources/views/laporan/index.blade.php**:
- Menyederhanakan logic tombol laporan dan resume
- Menghapus logic role-based yang kompleks untuk tombol laporan
- Memperbaiki route URL untuk print-out laporan
- Menghapus function `generateLaporanButton()` yang tidak digunakan

**resources/views/penilai/components/lpj-sederhana-standar.blade.php**:
- Menambahkan role 'penilai' pada permission tombol simpan

**resources/views/penilai/components/print-out-sederhana.blade.php**:
- Memperbaiki tampilan data dokumen dengan menambahkan kolom nomor dokumen
- Mengganti `number_format()` dengan `formatRupiah()` untuk konsistensi format
- Menambahkan fallback untuk data tanah dan bangunan ketika `npw_tambahan` tidak tersedia
- Memperbaiki perhitungan total nilai pasar wajar dengan proper parsing
- Memperbaiki format tampilan nilai likuidasi
- Memperbaiki struktur HTML tabel untuk dokumentasi

**resources/views/penilai/components/signature-approval.blade.php**:
- Memperbaiki route dan parameter untuk approval signature

**resources/views/permohonan/index.blade.php**:
- Menambahkan role 'admin' pada permission actions
2025-11-15 17:01:04 +07:00
Daeng Deni Mardaeni
b2cfffc5d5 feat(lpj): Tambah peran admin, sesuaikan alur status, dan peningkatan UI
Ringkas: perluas akses untuk peran admin , rapikan alur status permohonan/pembayaran/SPK, pindahkan sumber LPJ ke relasi penilai, perbaiki parsing/formatting rupiah, dan tambah konten cetak “Catatan yang Perlu Diperhatikan”.

- Perizinan & akses

  - Izinkan admin melewati filter cabang pada listing Debitur dan Permohonan.
  - Tambah peran admin pada konfigurasi module.json di beberapa menu/fitur.
  - Izinkan admin membuat Debitur dan mengakses aksi yang sebelumnya eksklusif untuk administrator dan pemohon-ao .
- Alur bisnis & status

  - Ubah status setelah proses pembatalan/penanganan pembayaran dari done menjadi proses-laporan agar konsisten dengan alur pelaporan.
  - Nonaktifkan blokir navigasi saat status proses-laporan di PenilaiController (redirect/JSON error dikomentari) agar proses lanjutan tetap bisa diakses bila diperlukan.
  - Setelah generate SPK, set Permohonan.status dan PenawaranTender.status menjadi registrasi-final untuk menandai finalisasi registrasi.
  - Pada pembuatan permohonan, jika pengguna admin , tetapkan status = preregister untuk proses pra-registrasi.
  - Hapus set default branch_id dari PermohonanRequest sehingga pengisian cabang dilakukan eksplisit melalui form (terutama untuk admin).
- Data LPJ & referensi relasi

  - Sumber data LPJ dipindah dari permohonan->penilaian->lpj ke permohonan->penilai->lpj baik di controller ( PenilaianController ) maupun view ( penilaian/otorisator/show.blade.php ) untuk menyesuaikan struktur relasi terbaru.
- Dokumen pembayaran

  - Ubah cara deteksi “Bukti Bayar” dari documents menjadi dokumenjaminan dan ambil detail berdasarkan name = 'Bukti Bayar' , lalu gunakan dokumen_jaminan yang terenkode JSON sebagai sumber pemrosesan berikutnya.
  - Pada UI approval pembayaran, benahi rendering nominal_bayar (hindari pemutusan baris) dan tampilkan tombol otorisator jika status_bayar !== 'sudah_bayar' || !approve_bayar .
- UI & formatting rupiah

  - Perbaiki fungsi calculateTotal() pada form-penilai.blade.php agar parsing angka mendukung pemisah ribuan titik dan desimal koma, serta formatting konsisten dengan id-ID .
  - Aktifkan kembali fallback tampilan status utama di penilai/index.blade.php .
  - Tambahkan blok “Catatan yang Perlu Diperhatikan” pada print-out-sederhana.blade.php , mendukung input string/array dan memformat poin dengan awalan “- ”.
Perubahan berkas (ringkas):

- app/Http/Controllers/DebitureController.php : tambah peran admin pada pengecualian filter cabang.
- app/Http/Controllers/PembayaranController.php : set status = 'proses-laporan' dalam proses terkait pembayaran.
- app/Http/Controllers/PenilaiController.php : longgarkan blokir saat proses-laporan (redirect/JSON error dikomentari).
- app/Http/Controllers/PenilaianController.php : gunakan permohonan->penilai->lpj untuk menghitung NPW.
- app/Http/Controllers/PermohonanController.php :
  - set status = 'preregister' untuk user admin saat create,
  - tambah peran admin pada pengecualian filter cabang,
  - ubah pencarian “Bukti Bayar” ke dokumenjaminan dan gunakan dokumen_jaminan (JSON).
- app/Http/Controllers/SpkController.php : set status = 'registrasi-final' pada Permohonan dan PenawaranTender setelah generate SPK.
- app/Http/Requests/PermohonanRequest.php : hilangkan set default branch_id .
- module.json : tambahkan admin pada beberapa daftar roles .
- resources/views/component/form-penilai.blade.php : dukungan parsing/formatting rupiah dengan pemisah lokal.
- resources/views/debitur/components/debitur.blade.php : perluas akses cabang untuk admin di form Debitur.
- resources/views/debitur/index.blade.php : izinkan admin membuat Debitur.
- resources/views/pembayaran/approval.blade.php : perbaiki render nominal dan visibilitas tombol otorisator.
- resources/views/penilai/components/print-out-sederhana.blade.php : tambah bagian “Catatan yang Perlu Diperhatikan”.
- resources/views/penilai/index.blade.php : gunakan data.status sebagai fallback tampilan status.
- resources/views/penilaian/otorisator/show.blade.php : konsisten gunakan permohonan->penilai->lpj .
- resources/views/permohonan/form.blade.php : penataan ulang kelas Tailwind dan penambahan field Cabang untuk administrator / admin .
2025-11-12 17:42:45 +07:00
Daeng Deni Mardaeni
89329de198 🐛 fix(lpj-views): Amankan akses penilai dan sederhanakan informasi analisa
- Laporan index: gunakan optional chaining untuk akses aman properti penilai

  - Ubah if (data.penilai.resume) menjadi if (data.penilai?.resume) agar tidak error saat penilai null/undefined.
  - Perkuat kondisi pemanggilan generateLaporanButton(...) dengan ekspresi: data.penilai?.type_penilai == 'resume' && !data.penilai?.resume ? type : typePenilaian .
  - Efek: mencegah runtime error (TypeError) saat data belum lengkap, memastikan tombol "Resume" dan "Laporan" hanya muncul pada kondisi valid.
  - Berlaku pada role pemohon-ao dan role lainnya (dua blok kondisi kini seragam dan aman).
- Analisa penilai: sederhanakan tampilan dengan menghapus blok keterangan fakta

  - Hapus tabel "Catatan yang Perlu Diperhatikan" yang merender $forminspeksi['fakta']['keterangan'] (string/array).
  - Alasan: menghindari duplikasi, ketidakpastian tipe (string/array), dan potensi inkonsistensi formatting; konten penting tetap tersedia di bagian lain laporan.
Komentar level fungsi (referensi terkait):

- generateLaporanButton(data, dokumenID, inspeksiId, jenisJaminanID, typeOrResume, typePenilaian)
  - Peran: merender tombol "Laporan" berdasarkan status pembayaran dan kondisi penilai.
  - Perubahan: tidak mengubah implementasi fungsi; memperkuat logika pemanggilan via optional chaining agar parameter typeOrResume ditentukan aman.
2025-11-12 16:20:32 +07:00
Daeng Deni Mardaeni
70dda16699 feat(lpj-seeders): Inisialisasi master referensi, migrasi MIG, dan SQL seeding
- Menata LpjDatabaseSeeder untuk orkestrasi batch, aktifkan MigrationGambarInspeksiSeeder .
- Migrasi domain MIG → LPJ lengkap dengan parseTimestamp , initializeErrorLog , logError .
- Tambah seeders MIG eksternal & tim penilai; normalisasi mapping checkTujuanPenilaian .
- Perluasan master: JFK009–JFK014, TP0007–TP00010, hubungan pemilik, KJPP; TeamsSeeder via SQL.
- MasterDataSurveyorSeeder eksekusi SQL referensi (20+ tabel) via DB::unprepared .
- Tambah puluhan SQL referensi (jenis, kondisi, sarana, posisi, spek, dll).
- Normalisasi data inspeksi (duplikasi key dinamis), serialisasi JSON rapi.
- Logging seragam ke app log + CSV error untuk audit trail.
2025-11-10 21:06:03 +07:00
Daeng Deni Mardaeni
db0b1f6cfc Merge remote-tracking branch 'composer/staging' into staging 2025-11-10 20:48:05 +07:00
Daeng Deni Mardaeni
c153990c52 feat(lpj): Perbaiki ekspor, pencarian, validasi tanggal, transaksi, logging, dan UI
- ActivityController: tambah default order `nomor_registrasi` desc; rapikan komentar & alur sorting
- LaporanHasilPenilaianJaminanInternalExternalController: pencarian debitur case-insensitive via `LOWER(name)`; normalisasi angka LPJ (luas_tanah, nilai_bangunan, likuidasi, NPW); perapihan spacing
- LaporanPenilaiJaminanController: validasi `start_date`/`end_date` dan buat nama file ekspor dinamis via `createNameLaporan`; gunakan `LaporanPenilaiJaminanExport($request)`; helper `getBranchId`
- LaporanPenilaianJaminanController: standarisasi respons JSON datatables; tambah `export(Request)` dengan nama `laporan_penilaian_jaminan_<start>_<end>.xlsx`
- NilaiPlafondController: bungkus proses datatables dalam transaksi DB (commit/rollback) dengan try/catch; tambah logging info/error; rapikan dan standarisasi respons JSON
- PenilaiController: map data pembanding ke `pembanding1/2/3`; tambah `print_out_laporan` dan `showLaporanInspeksi` (penentuan route back); stub `showInspectionReportReview`; perapihan minor
- Views debitur/components/debitur: perbaiki closing textarea, konsistensi event listener `function ()`, rapikan markup error
- Views debitur/components/jaminan: fallback `dokumen_nomor[$index] ?? ''` untuk hindari undefined index
- Views laporan/index: akses aman dengan optional chaining `?.`, fallback tanggal pada `formatDate`, akses `nilaiPlafond` aman
- Views laporan-penilai-jaminan/index + show: JS toggle tab (Laporan vs Hasil Inspeksi), CSS `hidden-tab`, gaya floating button, perapihan
- Views debitur/index: rapikan directive `@if` spacing pada tombol tambah
- Views noc/penyelesaian: perbaiki route key ke `noc.datatables.penyelesaian`
2025-11-10 20:47:56 +07:00
Daeng Deni Mardaeni
42d6e06a48 feat(lpj): perbaikan controller & view penilai, validasi, dan MIG toggle
- Controllers: DokumenJaminan tangani array kosong saat diff legalitas.
- Controllers: Laporan sederhanakan query status list laporan.
- Controllers: PersetujuanPenawaran simpan NOC ke variabel $noc.
- Requests: DebitureRequest longgarkan 'nomor_rekening' max 50.
- Views: Informasi & Lingkungan tampilkan array/string aman dan rapi.
- Views: Header rapikan CSS page-break, nonaktifkan blok PHP komentar.
- Views: Foto Jaminan/Lampiran tambah link unduh & perbaikan layout.
- Views: LPJ sederhana: tombol kondisional saat MIG, include analisa.
- Views: Print-out sederhana kirim parameter ke signature-approval.
2025-11-10 20:01:06 +07:00
Daeng Deni Mardaeni
45f0d387fd feat(lpj): peningkatan model & service inspeksi, penawaran, preview
- Models: Inspeksi tambah 'mig_detail_data_jaminan' pada 'fillable'.
- Models: PersetujuanPenawaran ubah import User, hapus 3 field lama.
- Models: PersetujuanPenawaran tambah relasi 'region' (belongsTo Region).
- Services: PreviewLaporanService tambah 22 item kategori preview.
- Services: SaveFormInspesksiService refaktor parsing action & rules.
- Services: TypeLaporanService tambah helper alamat & lokasi wilayah.
- Services: TypeLaporanService tambahkan updateOrCreate untuk Penilai.
- Services: TypeLaporanService tambah getInspeksi dan stub updatePenilai.
- Cleanup: penataan kode, trimming, kurangi nested kondisi; mohon cek namespace.
2025-11-10 10:09:24 +07:00
Daeng Deni Mardaeni
7f9c58aabe feat(migration): Tambah kolom migrasi & penyesuaian nullable di beberapa tabel
- Tambah kolom mig_*, is_mig, processed_at, nomor_lpj di tabel debitur, permohonan, jaminan, pemilik_jaminan, inspeksi, dan penilai
- Ubah beberapa field (branch_id, user_id, cif, nomor_id) menjadi nullable untuk fleksibilitas migrasi
- Tambah kolom biaya (decimal(15,2)) pada tabel nilai_plafond
- Pastikan semua kolom baru memiliki mekanisme rollback (down method)
- Perbaikan kompatibilitas migrasi data LPJ lama ke skema baru
- Penyesuaian tipe data & default value sesuai kebutuhan integrasi
- Menambahkan komentar sumber data LPJ lama pada beberapa kolom
- Meningkatkan traceability melalui kolom processed_at
- Menandai data hasil migrasi dengan flag is_mig
- Menjaga integritas dan konsistensi antar tabel selama proses migrasi
2025-11-10 09:30:39 +07:00
Daeng Deni Mardaeni
3ce84b89b4 feat(daftar-pustaka): implementasi fitur Daftar Pustaka dengan peningkatan UI/UX & breadcrumb navigation
## 📋 Ringkasan
Implementasi penuh fitur Daftar Pustaka dengan peningkatan UI/UX, dukungan gesture swipe di PDF viewer mobile, serta integrasi breadcrumb untuk navigasi yang lebih intuitif.

## 🔄 Perubahan Utama
- app/Services/DaftarPustakaService.php
  • Refactor method getDaftarPustaka(), hapus handleUpload_()
  • Optimasi filtering & perbaiki format kode

- resources/views/daftar-pustaka/create.blade.php
  • Aktifkan breadcrumb navigation dengan {{ Breadcrumbs::render() }}

- resources/views/daftar-pustaka/index.blade.php
  • Konsolidasi class CSS, perbaikan flex & pagination styling

- resources/views/daftar-pustaka/show.blade.php
  • Tambah gesture swipe (touchstart, touchend) untuk PDF viewer
  • Implementasi handleSwipe() & threshold swipe 50px

- routes/breadcrumbs.php
  • Tambah route breadcrumbs daftar-pustaka (index, show, create)
2025-11-10 09:11:48 +07:00
Daeng Deni Mardaeni
117b344857 git commit -m " refactor(helper): dokumentasi & peningkatan fungsi helper LPJ
## Ringkasan
Refaktor besar pada helper `Modules/Lpj/app/Helpers/Lpj.php` untuk meningkatkan keterbacaan, keamanan, dan maintainability melalui dokumentasi, logging, dan validasi input.

## Perubahan Utama
- Tambah `declare(strict_types=1)` dan type declarations di seluruh fungsi
- Tambah PHPDoc lengkap pada `formatTanggalIndonesia` & `formatRupiah`
- Tambah logging detail (awal fungsi, validasi, keberhasilan, dan kegagalan)
- Validasi input null/kosong serta error handling yang lebih aman
- Bungkus fungsi query DB dalam `DB::transaction` untuk konsistensi data
- Tambah fungsi baru:
  - `parsePembandingMigration()` → membersihkan & memformat data pembanding migrasi
  - `getFilePath()` → resolve path file internal/eksternal
  - `parseTimestamp()` → robust timestamp parser multi-format
- Fix minor linter issue: `strtotime(now())`, `pow(10,3)` → `(int) str_pad(...)`

## Dampak
- Semua fungsi kini memiliki dokumentasi dan validasi lengkap
- Logging terstruktur untuk memudahkan debugging di production
- Peningkatan keamanan dan kestabilan dengan type safety & transaksi DB
- Output lebih konsisten dan mudah dilacak"
2025-11-09 21:36:26 +07:00
Daeng Deni Mardaeni
0d5b6b1529 feat(lpj-module): tambah tampilan laporan inspeksi & refactor detail lokasi
Ringkasan:
- Menambahkan halaman hasil inspeksi dan tampilan cetak laporan.
- Mengekstrak komponen detail lokasi ke partial baru agar reusable.
- Menambahkan null-safe access dan perbaikan binding data di view.
- Merapikan tombol cetak dan navigasi agar konsisten antar halaman.

Perubahan utama:
1. activitydetail.blade.php → ubah tombol print jadi route, tambah null-safe user/branch.
2. detail-lokasi.blade.php (baru) → komponen reusable untuk detail lokasi dengan formatLabel & tanggal.
3. form-penilai.blade.php → refactor luas menggunakan match, hapus fungsi debug & Swal loading.
4. print-out-dokument.blade.php → gunakan partial lpj::component.detail-lokasi untuk detail lokasi.
5. show-laporan-inspeksi.blade.php (baru) → tab 'Laporan' & 'Hasil Inspeksi' + tombol cetak dan back.
6. print-out-sederhana / print-out-standar → penyesuaian tampilan & binding data.
7. signature-approval.blade.php → perbaikan layout area tanda tangan.
8. surveyor/components/* → normalisasi tampilan, validasi gambar, dan penyelarasan fakta/lingkungan.
9. routes/web.php → tambah dan ubah rute untuk laporan inspeksi dan cetak laporan.

Catatan:
- Tidak ada perubahan query database; semua modifikasi bersifat tampilan.
- Logging tambahan untuk observabilitas proses render laporan.
2025-11-09 21:19:58 +07:00
139 changed files with 12221 additions and 3503 deletions

View File

@@ -1,7 +1,10 @@
<?php
declare(strict_types=1);
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Modules\Location\Models\City;
use Modules\Location\Models\District;
use Modules\Location\Models\Province;
@@ -15,29 +18,117 @@
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)
/**
* Format tanggal ke dalam format Bahasa Indonesia
*
* Mengubah tanggal menjadi format yang lebih mudah dibaca dalam Bahasa Indonesia.
* Contoh: "15 Januari 2024" atau "15 Januari 2024 pukul 14.30 WIB"
*
* @param string|mixed $date Tanggal yang akan diformat (string tanggal atau null)
* @param bool $time Apakah akan menampilkan waktu juga (default: false)
* @return string Tanggal yang sudah diformat dalam Bahasa Indonesia
*
* @example
* formatTanggalIndonesia('2024-01-15') // "15 Januari 2024"
* formatTanggalIndonesia('2024-01-15 14:30:00', true) // "15 Januari 2024 pukul 14.30 WIB"
* formatTanggalIndonesia(null) // ""
* formatTanggalIndonesia('invalid-date') // "invalid-date" (return as-is jika error)
*/
function formatTanggalIndonesia($date, $time = false): string
{
Log::debug('Memulai format tanggal Indonesia', [
'date' => $date,
'time' => $time
]);
// Validasi input null atau kosong
if (empty($date)) {
Log::debug('Tanggal kosong, return empty string');
return '';
}
Carbon::setLocale('id');
try {
$waktu = Carbon::parse($date);
if (!$time) {
return $waktu->translatedFormat('d F Y');
$result = $waktu->translatedFormat('d F Y');
Log::debug('Format tanggal berhasil', ['result' => $result]);
return $result;
}
return $waktu->translatedFormat('d F Y') . ' pukul ' . $waktu->format('H.i') . ' WIB';
$result = $waktu->translatedFormat('d F Y') . ' pukul ' . $waktu->format('H.i') . ' WIB';
Log::debug('Format tanggal dengan waktu berhasil', ['result' => $result]);
return $result;
} catch (Throwable $e) {
return $date;
Log::warning('Gagal parse tanggal', [
'date' => $date,
'error' => $e->getMessage()
]);
// Return input as-is jika gagal parse
return (string) $date;
}
}
}
function formatRupiah($number, $decimals = 0)
/**
* Format angka ke dalam format mata uang Rupiah Indonesia
*
* Mengubah angka menjadi format mata uang Rupiah dengan pemisah ribuan
* dan menggunakan koma sebagai pemisah desimal sesuai standar Indonesia.
*
* @param int|float|string $number Angka yang akan diformat (bisa negatif)
* @param int $decimals Jumlah digit desimal (default: 0)
* @return string Angka yang sudah diformat dalam format Rupiah
*
* @example
* formatRupiah(1500000) // "Rp 1.500.000"
* formatRupiah(1500000.50, 2) // "Rp 1.500.000,50"
* formatRupiah(-500000) // "Rp -500.000"
* formatRupiah(0) // "Rp 0"
* formatRupiah(null) // "Rp 0"
*/
function formatRupiah($number, $decimals = 0, $withSymbol = true): string
{
$number = (float) $number;
return 'Rp ' . number_format($number, $decimals, ',', '.');
Log::debug('Memulai format Rupiah', [
'number' => $number,
'decimals' => $decimals,
'withSymbol' => $withSymbol
]);
// Handle null atau kosong
if ($number === null || $number === '') {
Log::debug('Number null atau kosong, return Rp 0');
return $withSymbol ? 'Rp 0' : '0';
}
// Remove dots if present
$number = str_replace('.', '', (string) $number);
// Konversi ke float dan handle error
try {
$number = (float) $number;
} catch (Throwable $e) {
Log::warning('Gagal konversi number ke float', [
'number' => $number,
'error' => $e->getMessage()
]);
return $withSymbol ? 'Rp 0' : '0';
}
// Validasi decimals
$decimals = max(0, (int) $decimals);
$formatted = number_format($number, $decimals, ',', '.');
$result = $withSymbol ? 'Rp ' . $formatted : $formatted;
Log::debug('Format Rupiah berhasil', ['result' => $result]);
return $result;
}
function formatAlamat($alamat)
{
@@ -96,8 +187,6 @@
$query->orWhereNull('dokumen_persetujuan');
},
)->get();
// $sql = DB::getQueryLog();
if (sizeof($query) > 0) {
$allow = false;
@@ -238,9 +327,6 @@
return $hasil;
}
// andy add
function hitungHariKerja($tanggalMulai, $tanggalSelesai)
{
$tanggalMulai = Carbon::parse($tanggalMulai)->startOfDay();
@@ -326,7 +412,8 @@
$day = str_pad(date('d'), 2, '0', STR_PAD_LEFT);
// Generate random numbers
$randomNumber = str_pad(mt_rand(0, pow(10, $randomLength) - 1), $randomLength, '0', STR_PAD_LEFT);
//$randomNumber = str_pad(mt_rand(0, pow(10, $randomLength) - 1), $randomLength, '0', STR_PAD_LEFT);
$randomNumber = sprintf('%0' . $randomLength . 'd', mt_rand(0, pow(10, $randomLength) - 1));
// Concatenate components to create the custom code
return $year . $month . $day . $randomNumber;
@@ -530,15 +617,161 @@
}
}
function formatNotifikasi($notifikasi)
{
$data = json_decode(json_encode($notifikasi->data));
$message = $data->message;
$data = $data->data;
$notifikasi = [
'title' => 'Permohonan : ' . $data->nomor_registrasi,
'message' => $message,
];
return $notifikasi;
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;
}
}
return implode("\n", $cleaned);
}
/**
* get full path to internal storage file or external storage file
*
* @param string $path
* @return string
*/
function getFilePath($path)
{
// 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');

View File

@@ -129,7 +129,7 @@
// Retrieve data from the database
$query = Debiture::query();
if (!Auth::user()->hasAnyRole(['administrator'])) {
if (!Auth::user()->hasAnyRole(['administrator','admin'])) {
$query = $query->where('branch_id', Auth::user()->branch_id);
}

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

@@ -16,7 +16,6 @@ class LaporanController extends Controller
* Display a listing of the resource.
*/
public function __construct(PenilaiController $penilaiController){
$this->penilaiController = $penilaiController;
}
@@ -76,14 +75,8 @@ 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']);
if (Auth::user()->hasAnyRole(['pemohon-ao','pemohon-eo'])) {
$query = $query->where('branch_id', Auth::user()->branch_id);

View File

@@ -4,6 +4,7 @@
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Lpj\Exports\LaporanHasilPenilaianJaminanInternalExternalExport;
use Modules\Lpj\Models\Permohonan;
@@ -60,6 +61,7 @@
$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 . '%');

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'));
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]);
});
// OR check if has penawaran with date in range
$q->orWhereHas('penawaran', function ($q3) use ($startDate, $endDate) {
$q3->whereBetween('tanggal_penilaian_sebelumnya', [$startDate, $endDate]);
});
});
$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($paramsSearch->tanggal_awal) && !empty($paramsSearch->tanggal_akhir)) {
$q->whereBetween('tanggal_permohonan', [$paramsSearch->tanggal_awal, $paramsSearch->tanggal_akhir]);
}
$statusKeywords = explode(',', $search);
foreach ($statusKeywords as $keyword) {
$q->orWhereRelation('penilai', 'type_penilai', 'LIKE', '%' . trim($keyword) . '%');
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 . '%');
});
}
$query->where('status', 'done');
}
// dd($search->search);
// Default sorting if no sort provided
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);
} 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

@@ -6,7 +6,10 @@
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
{
@@ -34,11 +37,19 @@
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 (!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
@@ -60,6 +71,8 @@
$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 . '%');
@@ -156,6 +169,12 @@
public function export(Request $request)
{
return Excel::download(new LaporanPenilaianJaminanExport($request), 'laporan_penilaian_jaminan.xlsx');
$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

@@ -17,152 +17,160 @@
public $user;
/**
* Tampilkan halaman daftar Nilai Plafond.
*
* @return \Illuminate\Contracts\View\View
* Menampilkan halaman daftar Nilai Plafond.
* Log setiap akses dan sebelum return view.
*/
public function index()
{
Log::info('[NilaiPlafondController@index] Return view index nilai_plafond');
return view('lpj::nilai_plafond.index');
Log::info('NilaiPlafondController@index: akses halaman index');
return \view('lpj::nilai_plafond.index');
}
/**
* Simpan data Nilai Plafond baru ke database.
* Menggunakan transaksi untuk menjamin konsistensi data.
*
* @param NilaiPlafondRequest $request
* @return \Illuminate\Http\RedirectResponse
* Menyimpan data Nilai Plafond baru termasuk field biaya.
* Gunakan validasi dari NilaiPlafondRequest, log proses, dan bungkus dengan transaksi DB.
*/
public function store(NilaiPlafondRequest $request)
{
Log::info('NilaiPlafondController@store: mulai proses simpan');
$validate = $request->validated();
if ($validate) {
DB::beginTransaction();
try {
// Save to database
$created = NilaiPlafond::create($validate);
$record = NilaiPlafond::create($validate);
DB::commit();
Log::info('[NilaiPlafondController@store] NilaiPlafond created', ['id' => $created->id, 'payload' => $validate]);
return redirect()
Log::info('NilaiPlafondController@store: simpan berhasil', ['id' => $record->id]);
return \redirect()
->route('basicdata.nilai-plafond.index')
->with('success', 'Nilai Plafond berhasil dibuat');
} catch (Exception $e) {
DB::rollBack();
Log::error('[NilaiPlafondController@store] Failed to create nilai plafond', ['error' => $e->getMessage(), 'payload' => $validate]);
return redirect()
Log::error('NilaiPlafondController@store: simpan gagal', ['error' => $e->getMessage()]);
return \redirect()
->route('basicdata.nilai-plafond.create')
->with('error', 'Gagal membuat Nilai Plafond');
}
}
Log::warning('[NilaiPlafondController@store] Validation failed');
return redirect()
->route('basicdata.nilai-plafond.create')
->with('error', 'Validasi gagal');
}
/**
* Tampilkan form pembuatan Nilai Plafond.
*
* @return \Illuminate\Contracts\View\View
* Menampilkan form pembuatan Nilai Plafond.
* Log akses sebelum return view.
*/
public function create()
{
Log::info('[NilaiPlafondController@create] Return view create nilai_plafond');
return view('lpj::nilai_plafond.create');
Log::info('NilaiPlafondController@create: akses halaman create');
return \view('lpj::nilai_plafond.create');
}
/**
* Tampilkan form edit Nilai Plafond berdasarkan ID.
*
* @param int $id
* @return \Illuminate\Contracts\View\View
* Menampilkan form edit Nilai Plafond berdasarkan ID.
* Gunakan transaksi untuk pembacaan data dan logging.
*/
public function edit($id)
{
Log::info('NilaiPlafondController@edit: mulai proses edit', ['id' => $id]);
DB::beginTransaction();
try {
$nilaiPlafond = NilaiPlafond::find($id);
Log::info('[NilaiPlafondController@edit] Return view edit nilai_plafond', ['id' => $id]);
return view('lpj::nilai_plafond.create', compact('nilaiPlafond'));
DB::commit();
Log::info('NilaiPlafondController@edit: data ditemukan', ['id' => $id]);
return \view('lpj::nilai_plafond.create', compact('nilaiPlafond'));
} catch (Exception $e) {
DB::rollBack();
Log::error('NilaiPlafondController@edit: gagal mengambil data', ['id' => $id, 'error' => $e->getMessage()]);
return \redirect()
->route('basicdata.nilai-plafond.index')
->with('error', 'Gagal mengambil data Nilai Plafond');
}
}
/**
* Update data Nilai Plafond pada database.
* Menggunakan transaksi untuk menjamin konsistensi data.
*
* @param NilaiPlafondRequest $request
* @param int $id
* @return \Illuminate\Http\RedirectResponse
* Memperbarui data Nilai Plafond termasuk field biaya.
* Validasi input, logging, dan gunakan transaksi DB.
*/
public function update(NilaiPlafondRequest $request, $id)
{
Log::info('NilaiPlafondController@update: mulai proses update', ['id' => $id]);
$validate = $request->validated();
if ($validate) {
DB::beginTransaction();
try {
// Update in database
$nilaiPlafond = NilaiPlafond::find($id);
if (!$nilaiPlafond) {
Log::warning('NilaiPlafondController@update: data tidak ditemukan', ['id' => $id]);
DB::rollBack();
return \redirect()
->route('basicdata.nilai-plafond.index')
->with('error', 'Data Nilai Plafond tidak ditemukan');
}
$nilaiPlafond->update($validate);
DB::commit();
Log::info('[NilaiPlafondController@update] NilaiPlafond updated', ['id' => $id, 'payload' => $validate]);
return redirect()
Log::info('NilaiPlafondController@update: update berhasil', ['id' => $id]);
return \redirect()
->route('basicdata.nilai-plafond.index')
->with('success', 'Nilai Plafond berhasil diperbarui');
} catch (Exception $e) {
DB::rollBack();
Log::error('[NilaiPlafondController@update] Failed to update nilai plafond', ['id' => $id, 'error' => $e->getMessage(), 'payload' => $validate]);
return redirect()
Log::error('NilaiPlafondController@update: update gagal', ['id' => $id, 'error' => $e->getMessage()]);
return \redirect()
->route('basicdata.nilai-plafond.edit', $id)
->with('error', 'Gagal memperbarui Nilai Plafond');
}
}
Log::warning('[NilaiPlafondController@update] Validation failed', ['id' => $id]);
return redirect()
->route('basicdata.nilai-plafond.edit', $id)
->with('error', 'Validasi gagal');
}
/**
* Hapus data Nilai Plafond dari database.
* Menggunakan transaksi untuk menjamin konsistensi data.
*
* @param int $id
* @return void
* Menghapus data Nilai Plafond berdasarkan ID.
* Logging setiap langkah dan gunakan transaksi DB.
*/
public function destroy($id)
{
Log::info('NilaiPlafondController@destroy: mulai proses hapus', ['id' => $id]);
DB::beginTransaction();
try {
// Delete from database
$nilaiPlafond = NilaiPlafond::find($id);
if (!$nilaiPlafond) {
DB::rollBack();
Log::warning('NilaiPlafondController@destroy: data tidak ditemukan', ['id' => $id]);
return \response()->json(['success' => false, 'message' => 'Data Nilai Plafond tidak ditemukan']);
}
$nilaiPlafond->delete();
DB::commit();
Log::info('[NilaiPlafondController@destroy] NilaiPlafond deleted', ['id' => $id]);
echo json_encode(['success' => true, 'message' => 'Nilai Plafond berhasil dihapus']);
Log::info('NilaiPlafondController@destroy: hapus berhasil', ['id' => $id]);
return \response()->json(['success' => true, 'message' => 'Nilai Plafond berhasil dihapus']);
} catch (Exception $e) {
DB::rollBack();
Log::error('[NilaiPlafondController@destroy] Failed to delete nilai plafond', ['id' => $id, 'error' => $e->getMessage()]);
echo json_encode(['success' => false, 'message' => 'Gagal menghapus Nilai Plafond']);
Log::error('NilaiPlafondController@destroy: hapus gagal', ['id' => $id, 'error' => $e->getMessage()]);
return \response()->json(['success' => false, 'message' => 'Gagal menghapus Nilai Plafond']);
}
}
/**
* Endpoint data untuk DataTables custom.
* Menyediakan pencarian, sorting, dan pagination.
*
* @param Request $request
* @return \Illuminate\Http\JsonResponse
* Menyediakan data untuk datatables dengan pencarian, sortir, dan paginasi.
* Logging proses dan gunakan transaksi DB untuk konsistensi pembacaan.
*/
public function dataForDatatables(Request $request)
{
Log::info('NilaiPlafondController@dataForDatatables: mulai proses');
if (is_null($this->user) || !$this->user->can('nilai_plafond.view')) {
//abort(403, 'Sorry! You are not allowed to view users.');
}
DB::beginTransaction();
try {
// Retrieve data from the database
$query = NilaiPlafond::query();
@@ -172,8 +180,6 @@
$query->where(function ($q) use ($search) {
$q->where('code', 'LIKE', "%$search%");
$q->orWhere('name', 'LIKE', "%$search%");
// CAST ke TEXT agar LIKE bekerja di PostgreSQL
$q->orWhereRaw('CAST(biaya AS TEXT) LIKE ?', ["%$search%"]);
});
}
@@ -208,15 +214,11 @@
// Calculate the current page number
$currentPage = 0 + 1;
Log::info('[NilaiPlafondController@dataForDatatables] Return datatables payload', [
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
]);
DB::commit();
Log::info('NilaiPlafondController@dataForDatatables: proses selesai, mengembalikan data');
// Return the response data as a JSON object
return response()->json([
return \response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
@@ -225,16 +227,28 @@
'totalCount' => $totalRecords,
'data' => $data,
]);
} catch (Exception $e) {
DB::rollBack();
Log::error('NilaiPlafondController@dataForDatatables: gagal memproses data', ['error' => $e->getMessage()]);
return \response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => 0,
'recordsFiltered' => 0,
'pageCount' => 0,
'page' => 1,
'totalCount' => 0,
'data' => [],
]);
}
}
/**
* Export data Nilai Plafond ke file Excel.
*
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
* Mengekspor data Nilai Plafond ke Excel.
* Log akses sebelum proses download.
*/
public function export()
{
Log::info('[NilaiPlafondController@export] Export nilai_plafond to Excel');
Log::info('NilaiPlafondController@export: mulai proses export');
return Excel::download(new NilaiPlafondExport, 'nilai_plafond.xlsx');
}
}

View File

@@ -245,7 +245,7 @@ class PembayaranController extends Controller
$permohonan->approve_bayar_by = null;
$permohonan->approve_bayar_at = null;
$permohonan->status = 'done';
$permohonan->status = 'proses-laporan';
$permohonan->save();
} else {
$persetujuanPenawaran = PersetujuanPenawaran::create(

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;
}
/**
@@ -154,7 +157,7 @@ class PenilaiController extends Controller
$permohonan = $this->surveyorController->getPermohonanJaminanId($id, $documentId, $jaminanId);
if ($permohonan->status == 'proses-laporan') {
return redirect()->back()->with('error', 'Masih dalam proses laporan');
//return redirect()->back()->with('error', 'Masih dalam proses laporan');
}
$basicData = $this->surveyorController->getCommonData();
@@ -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)
{
@@ -701,6 +698,7 @@ class PenilaiController extends Controller
'lokasi_lengkap' => $data->lokasi_lengkap ?? '',
];
if(isset($dataPembanding)){
// Extract data pembanding
if (isset($dataPembanding['data_pembanding'])) {
foreach ($dataPembanding['data_pembanding'] as $index => $pembanding) {
@@ -713,6 +711,7 @@ class PenilaiController extends Controller
}
}
}
}
// Now create the export
// return response()->json([ 'data' => $fotoForm]);
@@ -842,10 +841,10 @@ class PenilaiController extends Controller
$permohonan = Permohonan::findOrFail($id);
if ($permohonan->status === 'proses-laporan') {
return response()->json([
/*return response()->json([
'success' => false,
'message' => 'Masih proses laporan',
], 400);
], 400);*/
}
if ($permohonan->status === 'proses-paparan') {
@@ -1276,8 +1275,6 @@ class PenilaiController extends Controller
}
}
public function print_out(Request $request)
{
$documentId = $request->query('documentId');
@@ -1393,6 +1390,15 @@ class PenilaiController extends Controller
}
}
public function print_out_laporan($permohonan_id, $document_id, $jaminan_id)
{
// jika tidak ada id kembalikan ke halaman sebelumnya
if (!$permohonan_id || !$document_id || !$jaminan_id) {
return redirect()->back()->with('error', 'Laporan tidak valid');
}
return $this->previewLaporanService->printOutLaporan($permohonan_id, $document_id, $jaminan_id);
}
private function getViewLaporan($tipe)
{
$viewMap = [
@@ -1772,4 +1778,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

@@ -518,7 +518,7 @@ class PenilaianController extends Controller
$status = 'done';
$approvalField = null;
$lpj_ = optional(json_decode($permohonan->penilaian->lpj));
$lpj_ = optional(json_decode($permohonan->penilai->lpj));
$npw = $lpj_->total_nilai_pasar_wajar ?? 0;
$npw = str_replace('.', '', $npw);

View File

@@ -50,6 +50,9 @@
{
$validate = $request->validated();
if ($validate) {
if(auth()->user()->hasRole('admin')){
$validate['status'] = "preregister";
}
try {
// Process file upload
$filePath = null;
@@ -172,7 +175,7 @@
// Retrieve data from the database
$query = Permohonan::query();
if (!Auth::user()->hasAnyRole(['administrator'])) {
if (!Auth::user()->hasAnyRole(['administrator','admin'])) {
$query = $query->where('branch_id', Auth::user()->branch_id);
}
@@ -371,14 +374,21 @@
}
if ($permohonan->status == 'sudah_dibayar') {
$buktiBayar = $permohonan->documents->filter(function ($doc) {
return $doc->detail && $doc->detail->nama === 'Bukti Bayar';
$documents = $permohonan->dokumenjaminan->first(function ($doc) {
return $doc->detail && $doc->detail->contains('name', 'Bukti Bayar');
});
$buktiBayar = $documents->detail->filter(function ($detail) {
return $detail->name == 'Bukti Bayar';
})->first() ?? null;
if ($buktiBayar->isEmpty()) {
return redirect()->route('authorization.show', $id)->with('error', 'Bukti Bayar harus diunggah');
}
$dokumenJaminan = json_decode($buktiBayar->dokumen_jaminan);
$persetujuanPenawaran = PersetujuanPenawaran::firstOrCreate(
['permohonan_id' => $id],
[

View File

@@ -72,7 +72,7 @@
// Save NOC
try {
Noc::updateOrCreate([
$noc = Noc::updateOrCreate([
'permohonan_id' => $persetujuanPenawaran->permohonan_id,
'persetujuan_penawaran_id' => $persetujuanPenawaran->id
],[

View File

@@ -345,6 +345,19 @@ use Illuminate\Support\Facades\Auth;
$content = $pdf->download()->getOriginalContent();
Storage::put('public/'.$newFileNameWithPath,$content);
$permohonanModel = Permohonan::where('nomor_registrasi', $penawaran->nomor_registrasi)->first();
if ($permohonanModel) {
$permohonanModel->status = 'registrasi-final';
$permohonanModel->save();
}
$persetujuanPenawaran = PenawaranTender::where('id', $penawaran->id)->first();
if ($persetujuanPenawaran) {
$persetujuanPenawaran->status = 'registrasi-final';
$persetujuanPenawaran->save();
}
$data1['status'] = 'success';
$data1['spkpenawaran_path'] = $spkpenawaran_path;
$data1['message']['message_success'] = array('Generate SPK PDF successfully');

View File

@@ -20,7 +20,7 @@
'city_code' => 'nullable|exists:cities,code',
'district_code' => 'nullable|exists:districts,code',
'village_code' => 'nullable|exists:villages,code',
'nomor_rekening' => 'nullable|string|max:10',
'nomor_rekening' => 'nullable|string|max:50',
'name' => 'required',
'registered_at' => 'nullable|date',
'npwp' => 'nullable|string|min:15|max:16',

View File

@@ -48,7 +48,6 @@
),
'tanggal_permohonan' => date('Y-m-d'),
'user_id' => auth()->user()->id,
'branch_id' => auth()->user()->branch_id,
'status' => 'order'
]);
}

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

@@ -2,7 +2,7 @@
namespace Modules\Lpj\Models;
use Modules\Usermanagement\Models\User;
use Modules\Usermanagemenet\Models\User;
class PersetujuanPenawaran extends Base
{
@@ -13,9 +13,6 @@
'permohonan_id',
'penawaran_id',
'nomor_proposal_penawaran',
'nomor_tiket',
'nominal_kurang_bayar',
'bukti_ksl_kurang_bayar',
'tanggal_proposal_penawaran',
'biaya_final',
'sla_resume',
@@ -49,6 +46,12 @@
return $this->belongsTo(Permohonan::class, 'permohonan_id');
}
// Relationship with Region
public function region()
{
return $this->belongsTo(Region::class);
}
// Relationship with User (for authorized_by)
public function authorizedBy()
{

View File

@@ -74,6 +74,7 @@ class DaftarPustakaService
return $query->paginate($size, ['*'], 'page', $page);
}
private function handleUpload($file)
{
$today = now();
@@ -85,20 +86,5 @@ class DaftarPustakaService
return $filePath;
}
private function handleUpload_($file)
{
$today = now();
$folderPath = 'daftar_pustaka/' . $today->format('Y/m/d');
if (!file_exists(public_path($folderPath))) {
mkdir(public_path($folderPath), 0755, true);
}
$fileName = $file->getClientOriginalName();
$file->move(public_path($folderPath), $fileName);
return $folderPath . '/' . $fileName;
}
}

View File

@@ -0,0 +1,735 @@
<?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);
$nilaiPasar = $mig_permohonan->mig_mst_lpj_tot_nilai_pasar ?? null;
if(($tipeLaporan->status === 'memo' && $permohonan->mig_permohonan && $permohonan->is_mig) || ($nilaiPasar !== null && $nilaiPasar < 1 && $permohonan->is_mig)){
$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

@@ -4,7 +4,6 @@ namespace Modules\Lpj\Services;
use Modules\Lpj\Models\Inspeksi;
use Illuminate\Http\Request;
use \Illuminate\Support\Facades\Log;
class SaveFormInspesksiService
{
@@ -21,7 +20,6 @@ class SaveFormInspesksiService
$inspeksi->name = $request->input('type');
$processedData = $this->getActionSpecificRules($validatedData, $type, $request, $inspeksi);
Log::info($processedData);
// Merge data lama dengan data baru
$existingData = json_decode($inspeksi->data_form, true) ?: [];
@@ -35,7 +33,6 @@ class SaveFormInspesksiService
'upload_gs'
];
foreach ($fotoTypes as $fotoType) {
if (isset($existingData[$fotoType])) {
$processedData[$fotoType] = $existingData[$fotoType];
@@ -60,7 +57,7 @@ class SaveFormInspesksiService
} catch (\Exception $e) {
return [
'success' => false,
'message' => 'Gagal menyimpan data : '.$e->getMessage(),
'message' => 'Gagal menyimpan data',
'error' => $e->getMessage()
];
}
@@ -88,31 +85,36 @@ class SaveFormInspesksiService
$hasAssetDescriptionRules = false;
$hasFactaData = false;
$actions = array_map('trim', explode(',', $action));
$pisah = array_filter($actions, function($act) use ($allowedActions) {
return isset($allowedActions[$act]);
});
$pisah = array_filter(
explode(',', $action),
function ($act) use ($allowedActions) {
return isset($allowedActions[trim($act)]);
}
);
// dd($pisah);
foreach ($pisah as $act) {
$act = trim($act); // Bersihkan spasi
if($act){
if (isset($allowedActions[$act])) {
$method = $allowedActions[$act];
$actionRules = $this->$method($data, $request, $inspeksi);
$rules = array_merge($rules, $actionRules);
// Cek apakah act memerlukan asset description rules
if($act){
if (in_array($act, ['apartemen-kantor', 'tanah', 'bangunan', 'rap'])) {
$hasAssetDescriptionRules = true;
}
// Cek apakah act memerlukan fakta data
if (in_array($act, ['rap'])) {
$hasFactaData = true;
}
}
}
}
}
if ($hasAssetDescriptionRules) {

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,25 @@
<?php
return new class extends \Illuminate\Database\Migrations\Migration
{
/**
* Tambah kolom biaya pada tabel nilai_plafond.
*/
public function up(): void
{
\Illuminate\Support\Facades\Schema::table('nilai_plafond', function (\Illuminate\Database\Schema\Blueprint $table) {
// PostgreSQL akan memetakan decimal ke numeric
$table->decimal('biaya', 15, 2)->default(0);
});
}
/**
* Menghapus kolom biaya jika dilakukan rollback.
*/
public function down(): void
{
\Illuminate\Support\Facades\Schema::table('nilai_plafond', function (\Illuminate\Database\Schema\Blueprint $table) {
$table->dropColumn('biaya');
});
}
};

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,350 @@
<?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/penilaian.team.fix.new_20251012_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/penilaian.team.fix.new_20251012.csv');
if (!$filePath) {
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/penilaian/penilaian.team.fix.new_20251012.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($row['mig_nomor_registrasi']."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");
}
$idPenilaian = Penilaian::orderBy('id', 'desc')->first()->id;
$data = [
'id' => $idPenilaian+1,
'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']
];
if($nomor_registrasi=='251722'){
Log::info("Data penilaian 251722 : ",$data);
}
// Buat penilaian
$penilaian = Penilaian::updateOrCreate([
'nomor_registrasi' => $nomor_registrasi
],[
'id' => $idPenilaian+1,
'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'],
]);
//DB::commit();
// Buat tim penilaian
$roles = ['surveyor', 'penilai'];
foreach ($roles as $role) {
$idPenilaianTeam = PenilaianTeam::orderBy('id', 'desc')->first()->id;
PenilaianTeam::updateOrCreate([
'penilaian_id' => $penilaian->id
],[
'id' => $idPenilaianTeam+1,
'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)
if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $timestamp)) {
return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString();
}
// Format d/m/Y H:i:s (contoh: 28/4/2017 14:43:43)
if (preg_match('/^\d{1,2}\/\d{1,2}\/\d{4} \d{2}:\d{2}:\d{2}$/', $timestamp)) {
return \Carbon\Carbon::createFromFormat('d/m/Y 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,255 @@
<?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/debitur.latest.csv');
if (!$filePath) {
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/debitures/debitur.latest.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($row['mig_kd_cabang'], '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::updateOrCreate([
'mig_kd_debitur_seq' => (int) strtok($row['mig_kd_debitur_seq'], '.'),
], [
'branch_id' => $branchId,
'name' => $row['name'] ?? '',
'cif' => (int) strtok($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' => (int) strtok($row['mig_kd_debitur_seq'], '.'),
'processed_at' => now(),
'mig_debitur' => json_encode($row),
'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)
if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $timestamp)) {
return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString();
}
// Format d/m/Y H:i:s (contoh: 28/4/2017 14:43:43)
if (preg_match('/^\d{1,2}\/\d{1,2}\/\d{4} \d{2}:\d{2}:\d{2}$/', $timestamp)) {
return \Carbon\Carbon::createFromFormat('d/m/Y 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,356 @@
<?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.jaminan_20251016_error.csv';
/**
* Run the database seeds.
*/
public function run()
{
$this->initializeErrorLog();
// Path ke file csv
$filePath = realpath(__DIR__ . '/csv/detail.dokumen.jaminan_20251016.csv');
if (!$filePath) {
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/detail.dokumen.jaminan_20251016.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;
$nomorJaminan = 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;
$nomorJaminan = $row['mig_nomor_jaminan'] ?? null;
break;
}
}
if (!$debiturId) {
throw new \Exception('Debitur ID tidak ditemukan');
}
// Ambil ID dokumen jaminan
$dokumenJaminanId = $this->getDokumenJaminanId($debiturId,$nomorJaminan, $dokumenJaminanCache);
if (!$dokumenJaminanId) {
throw new \Exception('Dokumen jaminan tidak ditemukan');
}
//dd($debiturId,$nomorJaminan);
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
$detail =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,
]
);
if($nomorJaminan=='253339'){
//dd($debiturId,$nomorJaminan,$legalitasJaminanId, $detail, $dokumenJaminanId);
}
}
// 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,string $nomorLaporan, array &$dokumenJaminanCache)
{
$dokumen = DokumenJaminan::where('mig_kd_debitur_seq', $code)
->where('nomor_lpj', $nomorLaporan)
->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,508 @@
<?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_20251022_error_log.csv';
/**
* Run the database seeds.
*/
public function run()
{
$this->initializeErrorLog();
// Path ke file csv
$filePath = realpath(__DIR__ . '/csv/dokumen_20251022.csv');
if (!$filePath) {
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/dokumen_20251022.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 = DokumenJaminan::updateOrCreate([
'permohonan_id' => $permohonan->id,
'mig_kd_debitur_seq' => $row['mig_kd_debitur_seq'],
'nomor_lpj' => $row['mig_nomor_jaminan']
],[
'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(),
'nomor_lpj' => $row['mig_nomor_jaminan'],
'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
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'] ?? '-';
// DB::rollBack();
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
];*/
$mapping = [
1 => 1,
2 => 17,
3 => 19,
4 => 15,
5 => 18,
6 => 26,
7 => 26,
8 => 26,
9 => 26,
10 => 24,
11 => 28,
12 => 29,
13 => 32,
991001 => 17,
121965631354 => 17,
122267387302 => 13,
122267391891 => 27,
123242566528 => 1,
123391628912 => 18,
123779076991 => 26,
123779092232 => 26,
123837866231 => 19,
124159228236 => 14,
124280447242 => 32,
124385048902 => 30,
124539856281 => 22,
124635294016 => 13,
124963468687 => 18,
125178371127 => 31,
125228814911 => 17,
125749523699 => 27,
126156105725 => 15,
127407367039 => 15,
132065123922 => 32,
138027244724 => 33,
138027246193 => 34,
138027693348 => 35,
138027764236 => 10,
138050882693 => 15,
138050910670 => 20,
138051316169 => 23,
138051517359 => 36,
138051519318 => 37,
138051522331 => 38,
138051601738 => 39,
138051602831 => 40,
138051773783 => 41,
138051776693 => 46,
138051780489 => 42,
164921358499 => 32,
165216289979 => 49,
165216294371 => 49,
173035895092 => 24
];
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)
if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $timestamp)) {
return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString();
}
// Format d/m/Y H:i:s (contoh: 28/4/2017 14:43:43)
if (preg_match('/^\d{1,2}\/\d{1,2}\/\d{4} \d{2}:\d{2}:\d{2}$/', $timestamp)) {
return \Carbon\Carbon::createFromFormat('d/m/Y 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,297 @@
<?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/foto_20251014-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/foto_20251014.csv');
if (!$filePath) {
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/inspeksi/foto_20251014.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::updateOrCreate(
[
'permohonan_id' => $nomorRegis['id'],
'dokument_id' => $nomorRegis['dokument_id']
],
[
'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' => [],
'MAK' => [],
'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('d/m/Y H:i:s', $tgl)->startOfDay();
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);
}
}

File diff suppressed because it is too large Load Diff

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/pembanding_20251016_error.csv';
/**
* Run the database seeds.
*/
public function run()
{
// Path ke file csv
$filePath = realpath(__DIR__ . '/csv/inspeksi/pembanding_20251016.csv');
if (!$filePath) {
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/inspeksi/pembanding_20251016.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 = 300;
$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);
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);
// Update ke tabel inspeksi
// print_r($pembandingJson);
$inspeksi = 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;
}
}
if($row['mig_nomor_lpj']=='251936'){
dd($grouped);
}
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,282 @@
<?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/pemilik_20251002.csv');
if (!$filePath) {
Log::error('File CSV tidak ditemukan: ' . __DIR__ . '/csv/pemilik_20251002.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::updateOrCreate([
'mig_kd_debitur_seq' => $row['mig_kd_debitur_seq'],
],[
'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 {
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)
if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $timestamp)) {
return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString();
}
// Format d/m/Y H:i:s (contoh: 28/4/2017 14:43:43)
if (preg_match('/^\d{1,2}\/\d{1,2}\/\d{4} \d{2}:\d{2}:\d{2}$/', $timestamp)) {
return \Carbon\Carbon::createFromFormat('d/m/Y H:i:s', $timestamp)->toDateTimeString();
}
}
return null;
} catch (\Exception $e) {
Log::error('Gagal memparsing timestamp: ' . $timestamp . '. Pesan: ' . $e->getMessage());
return null;
}
}
}

View File

@@ -0,0 +1,505 @@
<?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\Log;
class MigrationPenilaiSeeder extends Seeder
{
/**
* Run the database seeds.
*/
protected $errorLogFile = __DIR__ . '/csv/penilaian/penilai.fix.latest_error.csv';
public function run()
{
$this->initializeErrorLog();
// Path ke file csv
$filePath = realpath(__DIR__ . '/csv/penilaian/penilai.fix.latest_20251011.csv');
if (!$filePath) {
Log::error('File csv tidak ditemukan: ' . __DIR__ . '/csv/penilaian/penilai.fix.latest_20251011.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
$mig_permohonan = json_decode($nomorRegis['mig_permohonan'],true) ?? '';
$tanggal = $mig_permohonan['mig_mst_lpj_tgl_laporan'] ?? $mig_permohonan['mig_mst_lpj_tgl_oto'] ?? $firstRow['mig_created_at'];
//$tanggal = $firstRow['mig_created_at'];
$nomorD = $nomorRegis['nomor_registrasi'];
$nomorRegistrasi = "PJ-{$nomorD}";
$nomorLaporan = $this->generateNomorLaporan($typePenilai, $nomorLpj, $nomorRegistrasi, $tanggal, $nomorRegis['id']);
// 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,
'mig_permohonan' => $permohonan->mig_permohonan
];
$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_bangunan' => null,
'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) {
// 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
$tanggal_ = $this->parseTimestamp($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
{
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;
}
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,414 @@
<?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/permohonan.2024.2025_error.csv';
public function run()
{
// Bersihkan file error sebelum mulai
$this->initializeErrorLog();
$filePath = realpath(__DIR__ . '/csv/permohonan/permohonan.2024.2025.csv');
if (!$filePath) {
Log::error('File CSV tidak ditemukan: ' . __DIR__ . '/csv/permohonan/permohonan.2024.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 = 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, count($data).' Jumlah kolom tidak sesuai dengan header. Header: '.count($header));
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);
$periksaId = $this->getUserId($row['mig_mst_lpj_user_periksa'], $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 = Permohonan::updateOrCreate([
'nomor_registrasi' => $nomorJaminan,
],[
'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' => $approved1Id['id'] ?? 0,
'approval_eo_at' => $this->parseTimestamp($row['mig_mst_lpj_tgl_approved_1']),
'approval_dd' => $approved2Id['id'] ?? 0,
'approval_dd_at' => $this->parseTimestamp($row['mig_mst_lpj_tgl_approved_2']),
'approval_so' => $periksaId['id'] ?? 0,
'approval_so_at' => $this->parseTimestamp($row['mig_mst_lpj_tgl_periksa']),
// 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'],
'mig_permohonan' => json_encode($row),
'is_mig' => 1
]);
if($permohonan && $nomorJaminan=='253122'){
Log::info($permohonan);
}
$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
{
// Extract the integer part before the decimal
$intCode = (int) $code;
$mapping = [
161337594516 => 1,
161337598118 => 14,
155739382483 => 7,
2 => 9,
153568936592 => 10,
155737674431 => 11,
161337561199 => 12,
1 => 13,
];
return $mapping[$intCode] ?? 0;
}
private function checkTujuanPenilaian($code): int
{
$code = (int) $code;
$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
{
if (!$date) {
return null;
}
try {
// Coba format d/m/Y terlebih dahulu (contoh: 30/1/2025)
return \Carbon\Carbon::createFromFormat('d/m/Y', $date)->toDateString();
} catch (\Exception $e) {
try {
// Fallback ke format Y-m-d jika gagal
return \Carbon\Carbon::createFromFormat('Y-m-d', $date)->toDateString();
} catch (\Exception $e2) {
// If both formats fail, try to parse with Carbon::parse as last resort
try {
return \Carbon\Carbon::parse($date)->toDateString();
} catch (\Exception $e3) {
return null;
}
}
}
}
private function parseTimestamp(?string $timestamp): ?string
{
try {
if (!$timestamp) {
return null;
}
// Cek format d/m/Y H:i:s (contoh: 29/9/2025 17:20:36)
if (preg_match('/^\d{1,2}\/\d{1,2}\/\d{4} \d{1,2}:\d{2}:\d{2}$/', $timestamp)) {
return \Carbon\Carbon::createFromFormat('d/m/Y H:i:s', $timestamp)->toDateTimeString();
}
// 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)
if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $timestamp)) {
return \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $timestamp)->toDateTimeString();
}
// Fallback: coba parsing dengan createFromFormat tambahan atau gunakan parse
return \Carbon\Carbon::parse($timestamp)->toDateTimeString();
} 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

@@ -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

@@ -308,7 +308,8 @@
"permission": "",
"roles": [
"administrator",
"pemohon-ao"
"pemohon-ao",
"admin"
]
},
{
@@ -320,7 +321,8 @@
"permission": "",
"roles": [
"administrator",
"pemohon-ao"
"pemohon-ao",
"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

@@ -210,9 +210,9 @@
user_id: {
title: 'User Pemohon',
render: (item, data) => {
return data.user && data.user.name ? `${data.user.name}` : '-';
},
},
return data?.user?.name ?? data?.mig_nama_ao ?? '-';
}},
branch_id: {
title: 'Cabang Pemohon',

View File

@@ -9,7 +9,7 @@
</h3>
<div class="flex gap-2 items-center">
{!! $customlink ?? '' !!}
{!! $customlink ?? "" !!}
@if (isset($id))
@php
$parameters = isset($id) ? ['id' => $id] : [];
@@ -46,7 +46,7 @@
Pemohon:
</h3>
<span class="text-gray-700 text-2sm">
{{ $permohonan->user->nik }} | {{ $permohonan->user->name }} | {{ $permohonan->user->branch->name }}
{{ $permohonan->user->nik ?? '' }} | {{ $permohonan->user->name ?? '' }} | {{ $permohonan->user->branch->name ?? '' }}
</span>
</div>
@@ -69,6 +69,7 @@
</span>
</div>
@else
<div class="mb-5">
<h3 class="font-medium text-gray-900 text-md">
Tujan Permohonan:
@@ -83,7 +84,7 @@
Nilai Plafond:
</h3>
<span class="text-gray-700 text-2sm">
{{ $permohonan->nilaiPlafond->name }}
{{ $permohonan->nilaiPlafond->name ?? '' }}
</span>
</div>

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

@@ -76,24 +76,17 @@
@foreach ($kategoriUnik as $item)
@php
$luas = match ($item) {
'bangunan' => $forminspeksi['bangunan']['luas_tanah_bagunan']['tidak sesuai'] ??
$forminspeksi['bangunan']['luas_tanah_bagunan']['sesuai'] ?? null,
'tanah' => $forminspeksi['tanah']['luas_tanah']['tidak sesuai'] ??
$forminspeksi['tanah']['luas_tanah']['sesuai'] ?? null,
'apartemen-kantor' => $forminspeksi['luas_unit']['sesuai'] ??
$forminspeksi['luas_unit']['tidak sesuai'] ?? null,
default => null,
};
if ($item === 'bangunan') {
$luas =
$forminspeksi['bangunan']['luas_tanah_bagunan']['tidak sesuai'] ??
($forminspeksi['bangunan']['luas_tanah_bagunan']['sesuai'] ?? null);
} elseif ($item === 'tanah') {
$luas =
$forminspeksi['tanah']['luas_tanah']['tidak sesuai'] ??
($forminspeksi['tanah']['luas_tanah']['sesuai'] ?? null);
} elseif ($item === 'apartemen-kantor') {
$luas =
$forminspeksi['luas_unit']['sesuai'] ??
($forminspeksi['luas_unit']['tidak sesuai'] ?? null);
} else {
$luas = null;
}
$luas = old('luas_' . $item, $lpjData['luas_' . $item] ?? $luas);
$luasKey = 'luas_' . $item;
$nilaiKey1 = 'nilai_' . $item . '_1';
$nilaiKey2 = 'nilai_' . $item . '_2';
@@ -122,7 +115,8 @@
<div class="flex flex-wrap gap-2.5 items-baseline w-full lg:flex-nowrap">
<label class="input">
<i class="">Rp</i>
<input id="{{ $nilaiKey2 }}" type="text" class="w-full currency-format"
<input id="{{ $nilaiKey2 }}" type="text"
class="w-full currency-format"
name="{{ $nilaiKey2 }}"
value="{{ old($nilaiKey2, $lpjData[$nilaiKey2] ?? null) }}">
</label>
@@ -444,13 +438,18 @@
function calculateTotal() {
const parseInput = (value) => {
if (!value) return 0;
return parseFloat(value.replace(/[^0-9]/g, '')) || 0;
// keep the dot as decimal separator, remove thousand separators
const cleaned = value.replace(/[^0-9.,]/g, '').replace(/\./g, '').replace(/,/g, '.');
return parseFloat(cleaned) || 0;
};
// Function to format currency
function formatCurrency(value) {
// Ensure we have a valid number to format
const num = parseFloat(value.replace(/[^0-9]/g, '')) || 0;
//const num = parseFloat(value.replace(/[^0-9]/g, '')) || 0;
//return num.toLocaleString('id-ID');
let num = value.replace(/[^0-9.,]/g, '').replace(/\./g, '').replace(/,/g, '.');
num = parseFloat(num) || 0;
return num.toLocaleString('id-ID');
}
@@ -477,7 +476,6 @@
if (luasInput && nilaiInput && outputElement) {
const luas = parseFloat(luasInput.value.replace(/[^0-9.]/g, '')) || 0;
console.log("a", luas);
const nilai = parseInput(nilaiInput.value);
const hasil = luas * nilai;
@@ -620,24 +618,4 @@
input.value = formattedValue;
}
function showLoadingSwal(message, duration = 5000) {
Swal.fire({
title: message,
allowOutsideClick: false,
didOpen: () => {
Swal.showLoading();
},
timer: duration, // Durasi dalam milidetik
timerProgressBar: true, // Menampilkan progres bar timer
}).then((result) => {
if (result.dismiss === Swal.DismissReason.timer) {
console.log("Dialog loading otomatis ditutup.");
}
});
}
function hideLoadingSwal() {
Swal.close();
}
</script>

View File

@@ -1,41 +1,11 @@
@if (@isset($dokumen))
@if (isset($dokumen))
@foreach ($dokumen->detail as $detail)
@if (!empty($detail->name) && isset($detail->details) && !empty($detail->dokumen_jaminan))
<tr>
<td width="25%"><strong>{{ $detail->name ?? '' }}</strong></td>
</tr>
@endif
@if ($detail->name != 'LOKASI JAMINAN')
@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
@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

@@ -1,11 +1,11 @@
@extends('layouts.main')
@section('breadcrumbs')
{{-- {{ Breadcrumbs::render(request()->route()->getName()) }} --}}
{{ Breadcrumbs::render(request()->route()->getName()) }}
@endsection
@section('content')
<div class="w-full grid gap-5 lg:gap-7.5 mx-auto">
<div class="grid gap-5 mx-auto w-full lg:gap-7.5">
<form
action="{{ isset($daftarPustaka->id) ? route('daftar-pustaka.update', $daftarPustaka->id) : route('daftar-pustaka.store') }}"
method="POST" enctype="multipart/form-data">
@@ -15,18 +15,18 @@
@method('PUT')
@endif
<div class="card border border-agi-100 pb-2.5">
<div class="pb-2.5 border card border-agi-100">
<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">
<div class="flex gap-2 items-center">
<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">
<div class="grid gap-5 card-body">
<div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
<label class="form-label max-w-56">
Judul
</label>
@@ -34,11 +34,11 @@
<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>
<em class="text-sm alert text-danger">{{ $message }}</em>
@enderror
</div>
</div>
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
<label class="form-label max-w-56">
Upload File
</label>
@@ -46,12 +46,12 @@
<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>
<em class="text-sm alert text-danger">{{ $message }}</em>
@enderror
</div>
</div>
@if (isset($daftarPustaka->attachment))
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
<label class="form-label max-w-56">
File
</label>
@@ -64,14 +64,14 @@
</div>
@endif
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
<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">
<select class="w-full select tomselect" name="category_id">
<option value="">Pilih Kategori</option>
@if (isset($categories))
@foreach ($categories as $item)
@@ -83,19 +83,19 @@
@endif
</select>
@error('category_id')
<em class="alert text-danger text-sm">{{ $message }}</em>
<em class="text-sm alert text-danger">{{ $message }}</em>
@enderror
</div>
</div>
<div class="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
<div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
<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>
<em class="text-sm alert text-danger">{{ $message }}</em>
@enderror
</div>
</div>

View File

@@ -1,7 +1,7 @@
@extends('layouts.main')
@section('breadcrumbs')
{{-- {{ Breadcrumbs::render('basicdata.ijin_usaha') }} --}}
{{ Breadcrumbs::render(request()->route()->getName()) }}
@endsection
@section('content')
@@ -15,9 +15,9 @@
</style>
<div class="flex flex-col items-stretch gap-7">
<div class="flex items-center gap-3 w-full">
<div class="input w-full">
<div class="flex flex-col gap-7 items-stretch">
<div class="flex gap-3 items-center w-full">
<div class="w-full input">
<i class="ki-filled ki-magnifier">
</i>
<input id="search" placeholder="Search Daftar Pustaka, Judul" type="text">
@@ -37,8 +37,8 @@
</a>
</div>
<div class="flex flex-wrap items-center gap-5 justify-between mt-3">
<h3 class="text-sm text-mono font-medium">
<div class="flex flex-wrap gap-5 justify-between items-center mt-3">
<h3 class="text-sm font-medium text-mono">
page {{ $page }} of {{ $pageCount }} {{ $limit }} items per page, total
{{ $total }} items.
</h3>
@@ -71,15 +71,15 @@
<div class="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 gap-4 " id="daftar_pustaka_grid">
<div class="grid grid-cols-1 gap-4 md:grid-cols-3 lg:grid-cols-4" id="daftar_pustaka_grid">
@if (isset($daftar_pustaka))
@foreach ($daftar_pustaka as $item)
<div class="card border shadow-none ">
<div class="border shadow-none card">
<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 class="flex overflow-hidden justify-center items-center p-4 w-full h-full">
<div class="flex justify-center items-center text-red-500 rounded">
<i class="text-3xl ki-filled ki-document"></i>
</div>
</div>
</a>
@@ -87,15 +87,15 @@
<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">
<h3 class="font-medium text-gray-900 cursor-pointer text-md hover:text-primary">
{{ $item->judul }}</h3>
<p class="text-2sm text-gray-700">
<p class="text-gray-700 text-2sm">
{{-- 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">
<div class="flex gap-2.5 justify-between items-center mt-2">
<p class="text-xs text-gray-700 rounded-full badge badge-xs badge-outline badge-success">
# {{ $item->category->name }}</p>
@auth
@@ -124,20 +124,20 @@
</div>
<div class="grid grid-cols-1 gap-4 hidden" id="daftar_pustaka_list">
<div class="grid hidden grid-cols-1 gap-4" 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="flex flex-wrap justify-between items-center p-2 card-body pe-5 gap-4.5">
<div class="flex gap-3.5 items-center">
<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 class="flex overflow-hidden justify-center items-center p-4 w-full h-full">
<div class="flex justify-center items-center text-red-500 rounded">
<i class="text-3xl ki-filled ki-document"></i>
</div>
</div>
</a>
@@ -145,12 +145,12 @@
<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">
<a class="text-sm font-medium hover:text-primary 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">
<div class="flex flex-wrap gap-3 items-center">
<span class="gap-1 rounded-full kt-badge kt-badge-warning kt-badge-sm">
<span class="text-xs font-medium text-foreground">
{{ substr($item->deskripsi, 0, 50) }}
</span>
@@ -160,8 +160,8 @@
</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">
<div class="flex gap-1.5 items-center">
<p class="text-xs text-gray-700 rounded-full badge badge-sm badge-outline badge-success">
# {{ $item->category->name }}</p>
@auth
@if (auth()->user()->hasRole(['administrator', 'admin']))
@@ -188,7 +188,7 @@
</div>
<div class="pagination flex gap-2 justify-center mt-5">
<div class="flex gap-2 justify-center mt-5 pagination">
@if ($daftar_pustaka->onFirstPage())
<span class="btn disabled"><i class="ki-filled ki-black-left"></i></span>
@else

View File

@@ -1,63 +1,62 @@
@extends('layouts.main')
@section('breadcrumbs')
{{-- {{ Breadcrumbs::render(request()->route()->getName()) }} --}}
{{ Breadcrumbs::render(request()->route()->getName(), $daftarPustaka) }}
@endsection
@section('content')
<div class="w-full grid gap-5 lg:gap-7.5 mx-auto">
<div class="grid gap-5 mx-auto w-full lg:gap-7.5">
<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="pb-2.5 border card border-agi-100">
<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 class="flex gap-2 items-center">
<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="grid gap-5 card-body">
<div class="min-w-3xl">
<div class="p-4 h-full flex flex-col">
<div class="flex flex-col p-4 h-full">
<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"><span class="path1"></span><span
class="path2"></span></i>
<i class="ki-duotone ki-cloud-download me-1"></i>
Download File
</a>
</div>
@php
@php
$fileExtension = pathinfo($daftarPustaka->attachment, PATHINFO_EXTENSION);
// cek extension
$isPdf = $fileExtension == 'pdf';
$isPdf = strtolower($fileExtension) == 'pdf';
$imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
$isImage = in_array(strtolower($fileExtension), $imageExtensions);
$fileUrl = asset('storage/' . $daftarPustaka->attachment);
@endphp
@if ($isPdf)
<iframe src="{{$fileUrl}}"
width="100%" height="600px" frameborder="0"></iframe>
<canvas id="pdfViewer" class="w-full rounded border touch-pan-y"></canvas>
<div class="flex gap-3 justify-center 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" />
<img src="{{ $fileUrl }}" class="object-contain w-full 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>
<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 class="border border-t"></div>
<div>
{{ $daftarPustaka->deskripsi ?? '' }}
</div>
@@ -67,30 +66,101 @@
</div>
@endsection
{{-- @push('scripts')
<script src="{{ asset('vendor/pdfobject.min.js') }}"></script>
@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 () {
let url = @json($daftarPustaka->attachment);
console.log(url);
const url = @json($fileUrl);
const fileExtension = url.split('.').pop().toLowerCase();
const previewContent = document.getElementById('previewContent');
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';
if (['pdf'].includes(fileExtension)) {
if (window.innerWidth < 768) {
document.getElementById('pdfFrame').style.display = 'block';
document.getElementById('pdfFrame').src = urlStorage;
} else {
PDFObject.embed(urlStorage, "#previewContent");
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;
}
} else if (['jpg', 'jpeg', 'png', 'gif'].includes(fileExtension)) {
previewContent.innerHTML =
`<img src="${url}" alt="Preview" class="max-w-full max-h-full object-contain">`;
});
});
}
function queueRenderPage(num) {
if (pageRendering) {
pageNumPending = num;
} else {
previewContent.innerHTML = '<p class="text-center">Unsupported file type</p>';
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 --}}
@endpush

View File

@@ -1,5 +1,4 @@
<form action="{{ isset($debitur->id) ? route('debitur.update', $debitur->id) : route('debitur.store') }}" method="POST"
id="debitur-form" class="grid gap-5">
<form action="{{ isset($debitur->id) ? route('debitur.update', $debitur->id) : route('debitur.store') }}" method="POST" id="debitur-form" class="grid gap-5">
@if(isset($debitur->id))
<input type="hidden" name="id" value="{{ $debitur->id }}">
@method('PUT')
@@ -11,13 +10,11 @@
<span class="text-danger">*</span>
</label>
<div class="flex flex-wrap items-baseline w-full">
@if (auth()->user()->hasRole(['administrator']))
<select class="input tomselect w-full @error('branch_id') border-danger bg-danger-light @enderror"
name="branch_id" id="branch_id">
@if(auth()->user()->hasAnyRole(['administrator','admin']))
<select class="input tomselect w-full @error('branch_id') border-danger bg-danger-light @enderror" name="branch_id" id="branch_id">
<option value="">Pilih Cabang</option>
@foreach($branches as $branch)
<option value="{{ $branch->id }}"
{{ (isset($debitur) && $branch->id == $debitur->branch_id) || old('branch_id') == $branch->id ? 'selected' : '' }}>
<option value="{{ $branch->id }}" {{ (isset($debitur) && $branch->id == $debitur->branch_id) || (old('branch_id') == $branch->id) ? 'selected' : '' }}>
{{ $branch->name }}
</option>
@endforeach
@@ -39,8 +36,7 @@
</span>
</label>
<div class="flex flex-wrap items-baseline w-full">
<input class="input @error('cif') border-danger bg-danger-light @enderror" type="number" id="cif"
name="cif" value="{{ $debitur->cif ?? '0000000000' }}">
<input class="input @error('cif') border-danger bg-danger-light @enderror" type="number" id="cif" name="cif" value="{{ $debitur->cif ?? '0000000000' }}">
@error('cif')
<em class="text-sm alert text-danger">{{ $message }}</em>
@enderror
@@ -51,8 +47,7 @@
Nomor Rekening
</label>
<div class="flex flex-wrap items-baseline w-full">
<input class="input @error('nomor_rekening') border-danger bg-danger-light @enderror" type="number"
name="nomor_rekening" value="{{ $debitur->nomor_rekening ?? '' }}">
<input class="input @error('nomor_rekening') border-danger bg-danger-light @enderror" type="number" name="nomor_rekening" value="{{ $debitur->nomor_rekening ?? '' }}">
@error('nomor_rekening')
<em class="text-sm alert text-danger">{{ $message }}</em>
@enderror
@@ -66,8 +61,7 @@
</span>
</label>
<div class="flex flex-wrap items-baseline w-full">
<input required class="input @error('name') border-danger bg-danger-light @enderror" type="text"
name="name" value="{{ $debitur->name ?? '' }}">
<input required class="input @error('name') border-danger bg-danger-light @enderror" type="text" name="name" value="{{ $debitur->name ?? '' }}">
@error('name')
<em class="text-sm alert text-danger">{{ $message }}</em>
@enderror
@@ -78,20 +72,18 @@
NPWP
</label>
<div class="flex flex-wrap items-baseline w-full">
<input class="input @error('npwp') border-danger bg-danger-light @enderror" type="number" name="npwp"
value="{{ $debitur->npwp ?? '' }}">
<input class="input @error('npwp') border-danger bg-danger-light @enderror" type="number" name="npwp" value="{{ $debitur->npwp ?? '' }}">
@error('npwp')
<em class="text-sm alert text-danger">{{ $message }}</em>
@enderror
</div>
</div>
<div class="flex hidden flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
<div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
<label class="form-label max-w-56">
Email
</label>
<div class="flex flex-wrap items-baseline w-full">
<input class="input @error('email') border-danger bg-danger-light @enderror" type="email" name="email"
value="{{ $debitur->email ?? '' }}">
<input class="input @error('email') border-danger bg-danger-light @enderror" type="email" name="email" value="{{ $debitur->email ?? '' }}">
@error('email')
<em class="text-sm alert text-danger">{{ $message }}</em>
@enderror
@@ -102,8 +94,7 @@
No Handphone
</label>
<div class="flex flex-wrap items-baseline w-full">
<input class="input @error('phone') border-danger bg-danger-light @enderror" type="number" name="phone"
value="{{ $debitur->phone ?? '' }}">
<input class="input @error('phone') border-danger bg-danger-light @enderror" type="number" name="phone" value="{{ $debitur->phone ?? '' }}">
@error('phone')
<em class="text-sm alert text-danger">{{ $message }}</em>
@enderror
@@ -111,7 +102,7 @@
</div>
<div class="flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap">
<label class="gap-1 form-label max-w-56">
Alamat KTP
Alamat
<span class="text-danger">
*
</span>
@@ -119,13 +110,11 @@
<div class="flex flex-wrap items-baseline w-full">
<div class="flex flex-col gap-2 w-full lg:flex-row">
<div class="flex flex-wrap items-baseline w-full">
<select required id="province_code" name="province_code"
class="select w-full @error('province_code') border-danger bg-danger-light @enderror">
<select required id="province_code" name="province_code" class="select w-full @error('province_code') border-danger bg-danger-light @enderror">
<option value="">Select Province</option>
@foreach($provinces as $province)
@if(isset($debitur))
<option value="{{ $province->code }}"
{{ isset($debitur->province_code) && $debitur->province_code == $province->code ? 'selected' : '' }}>
<option value="{{ $province->code }}" {{ isset($debitur->province_code) && $debitur->province_code == $province->code?'selected' : '' }}>
{{ $province->name }}
</option>
@else
@@ -140,14 +129,12 @@
@enderror
</div>
<div class="flex flex-wrap items-baseline w-full">
<select required id="city_code" name="city_code"
class="select w-full @error('city_code') border-danger bg-danger-light @enderror">
<select required id="city_code" name="city_code" class="select w-full @error('city_code') border-danger bg-danger-light @enderror">
<option value="">Select City</option>
@if(isset($cities))
@foreach($cities as $city)
@if(isset($debitur))
<option value="{{ $city->code }}"
{{ isset($debitur->city_code) && $debitur->city_code == $city->code ? 'selected' : '' }}>
<option value="{{ $city->code }}" {{ isset($debitur->city_code) && $debitur->city_code == $city->code?'selected' : '' }}>
{{ $city->name }}
</option>
@else
@@ -166,14 +153,12 @@
</div>
<div class="flex flex-col gap-2 mt-2 w-full lg:flex-row lg:mt-5">
<div class="flex flex-wrap items-baseline w-full">
<select required id="district_code" name="district_code"
class="select w-full @error('district_code') border-danger bg-danger-light @enderror">
<select required id="district_code" name="district_code" class="select w-full @error('district_code') border-danger bg-danger-light @enderror">
<option value="">Select District</option>
@if(isset($districts))
@foreach($districts as $district)
@if(isset($debitur))
<option value="{{ $district->code }}"
{{ isset($debitur->district_code) && $debitur->district_code == $district->code ? 'selected' : '' }}>
<option value="{{ $district->code }}" {{ isset($debitur->district_code) && $debitur->district_code == $district->code?'selected' : '' }}>
{{ $district->name }}
</option>
@else
@@ -190,14 +175,12 @@
@enderror
</div>
<div class="flex flex-wrap items-baseline w-full">
<select required id="village_code" name="village_code"
class="select w-full @error('district_code') border-danger bg-danger-light @enderror">
<select required id="village_code" name="village_code" class="select w-full @error('district_code') border-danger bg-danger-light @enderror">
<option value="">Select Village</option>
@if(isset($villages))
@foreach($villages as $village)
@if(isset($debitur))
<option value="{{ $village->code }}"
{{ isset($debitur->village_code) && $debitur->village_code == $village->code ? 'selected' : '' }}>
<option value="{{ $village->code }}" {{ isset($debitur->village_code) && $debitur->village_code == $village->code?'selected' : '' }}>
{{ $village->name }}
</option>
@else
@@ -214,17 +197,14 @@
@enderror
</div>
<div class="flex flex-wrap items-baseline w-full">
<input required class="input @error('postal_code') border-danger bg-danger-light @enderror"
type="number" id="postal_code" name="postal_code"
value="{{ $debitur->postal_code ?? '' }}" placeholder="Postal Code">
<input required class="input @error('postal_code') border-danger bg-danger-light @enderror" type="number" id="postal_code" name="postal_code" value="{{ $debitur->postal_code ?? '' }}" placeholder="Postal Code">
@error('postal_code')
<em class="text-sm alert text-danger">{{ $message }}</em>
@enderror
</div>
</div>
<div class="flex flex-row mt-2 w-full lg:mt-5">
<textarea required class="textarea @error('address') border-danger bg-danger-light @enderror" rows="3"
id="address" name="address" placeholder="Alamat Lengkap">{{ $debitur->address ?? '' }}</textarea>
<textarea required class="textarea @error('address') border-danger bg-danger-light @enderror" rows="3" id="address" name="address" placeholder="Alamat Lengkap">{{ $debitur->address ?? '' }}</textarea>
@error('address')
<em class="text-sm alert text-danger">{{ $message }}</em>
@enderror

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

@@ -6,8 +6,7 @@
@section('content')
<div class="grid">
<div class="min-w-full border card border-agi-100 card-grid" data-datatable="false" data-datatable-page-size="10"
data-datatable-state-save="false" id="debitur-table" data-api-url="{{ route('debitur.datatables') }}">
<div class="min-w-full border card border-agi-100 card-grid" data-datatable="false" data-datatable-page-size="10" data-datatable-state-save="false" id="debitur-table" data-api-url="{{ route('debitur.datatables') }}">
<div class="flex-wrap py-5 card-header bg-agi-50">
<h3 class="card-title">
Daftar Debitur
@@ -21,7 +20,7 @@
<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="{{ route('debitur.export') }}"> Export to Excel </a>
@if (auth()->user()->hasAnyRole(['administrator', 'pemohon-ao']))
@if(auth()->user()->hasAnyRole(['administrator', 'pemohon-ao','admin']))
<a class="btn btn-sm btn-primary" href="{{ route('debitur.create') }}"> Tambah Debitur </a>
@endif
</div>
@@ -193,14 +192,14 @@
// Periksa apakah ada setidaknya satu permohonan dengan status yang valid
const hasAnyValidPermohonan = permohonanArray.some(hasValidStatus);
if (hasRole(['administrator']) && hasAnyValidPermohonan || data.permohonan.length < 1) {
if (hasRole(['administrator','admin']) && hasAnyValidPermohonan || data.permohonan.length < 1) {
actionHtml += `
<a class="btn btn-sm btn-icon btn-clear btn-info" href="/debitur/${data.id}/edit">
<i class="ki-outline ki-notepad-edit"></i>
</a>`;
}
if (hasRole(['administrator', 'pemohon-ao']) && data.permohonan.length < 1) {
if (hasRole(['administrator', 'pemohon-ao','admin']) && data.permohonan.length < 1) {
actionHtml += `
<a onclick="deleteData(${data.id})" class="delete btn btn-sm btn-icon btn-clear btn-danger">
<i class="ki-outline ki-trash"></i>

View File

@@ -44,111 +44,119 @@
}
</style>
@endpush
<div class="w-full grid gap-5 lg:gap-7.5 mx-auto">
<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-penilai-jaminan-table"
data-api-url="{{ route('laporan-penilai-jaminan.datatables') }}">
<div class="card-header bg-agi-50 py-5 flex-wrap">
<h3 class="card-title">
Daftar Laporan Penilai Jaminan
</h3>
<div class="flex flex-wrap gap-2 lg:gap-5">
<div class="flex">
<div class="grid gap-5 mx-auto w-full lg:gap-7.5">
<!-- Filter Card -->
<div class="border card border-agi-100">
<div class="py-5 card-header bg-agi-50">
<h3 class="card-title">Filter Laporan</h3>
</div>
<div class="grid gap-4 card-body">
<!-- Search field at the top, full width -->
<div class="flex flex-col w-full">
<label class="mb-1 text-sm font-medium">Pencarian</label>
<label class="input input-sm">
<i class="ki-filled ki-magnifier"></i>
<input placeholder="Search Laporan Penilaian Jaminan" id="search" type="text" value="">
</label>
</div>
<!-- Other filter fields in grid layout -->
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4">
<div class="flex flex-col">
<label class="mb-1 text-base font-medium">Tanggal Awal</label>
<label class="input">
Start Date
<input placeholder="Tanggal Awal" id="tanggal_awal" type="date">
<input placeholder="Tanggal Awal" id="start_date" type="date">
</label>
</div>
<div class="flex">
<div class="flex flex-col">
<label class="mb-1 text-base font-medium">Tanggal Akhir</label>
<label class="input">
End Date
<input placeholder="Tanggal Akhir" id="tanggal_akhir" type="date">
<input placeholder="Tanggal Akhir" id="end_date" type="date">
</label>
</div>
<div class="flex">
<button class="btn btn-primary" id="filter_tanggal">Filter</button>
<div class="flex flex-col">
<label class="mb-1 text-base font-medium">Cabang</label>
<select class="select tomselect" id="branch_filter">
<option value="">Semua Cabang</option>
@foreach (\Modules\Basicdata\Models\Branch::where('status', 1)->get() as $branch)
<option value="{{ $branch->id }}">{{ $branch->name }}</option>
@endforeach
</select>
</div>
<div class="flex">
<label class="input "> <i class="ki-filled ki-magnifier"> </i>
<input placeholder="Search Laporan" id="search" type="text" value="">
</label>
</div>
<div class="flex">
<!-- Custom dropdown for status filter -->
<div class="dropdown" data-dropdown="true" data-dropdown-trigger="click">
<button class="dropdowns-toggle btn btn-light inline-flex justify-between w-full items-center">
Pilih Type Laporan
<i class="ki-outline ki-down dropdown-open:hidden">
</i>
<i class="ki-outline ki-up hidden dropdown-open:block">
</i>
</button>
<div
class="dropdowns-content w-full max-w-56 py-2 absolute mt-2 origin-top-right z-50 bg-white rounded-md shadow-lg ring-1 ring-black ring-opacity-5">
<div class="menu menu-default flex flex-col w-full">
<!-- Checkbox untuk All Status -->
<div class="menu-item">
<label class="menu-link flex items-center px-4 py-2 text-sm text-gray-700">
<input id="select-all" type="checkbox"
class="form-checkbox h-4 w-4 text-blue-600">
<span class="ml-2">All Status</span>
</label>
</div>
<!-- Dinamis Status dari Backend -->
<div class="flex flex-col">
<label class="mb-1 text-base font-medium">Laporan</label>
<select class="select tomselect" name="laporan[]" id="laporan" multiple>
<option value="">Semua Laporan</option>
@php
$status_laporan = [
'Standar',
'Sederhana',
'Memo',
'Resume',
'Call Report',
'RAP',
];
$status_laporan = ['Standar', 'Sederhana', 'Memo', 'Resume', 'Call Report', 'RAP'];
@endphp
@foreach ($status_laporan as $item)
<div class="menu-item">
<label class="menu-link flex items-center px-4 py-2 text-sm text-gray-700">
<input type="checkbox"
class="form-checkbox status-checkbox h-4 w-4 text-blue-600"
value="{{ strtolower($item) }}">
<span class="ml-2">{{ $item }}</span>
</label>
</div>
<option value="{{ strtolower($item) }}">{{ $item }}</option>
@endforeach
</select>
</div>
</div>
</div>
</div>
<div class="flex flex-wrap gap-2.5">
<div class="h-[24px] border border-r-gray-200"></div>
<button class="btn btn-light" id="export-button">
Export Excel
<!-- Buttons row at the bottom -->
<div class="grid grid-cols-1 gap-4 mt-2 md:grid-cols-2">
<button class="btn btn-sm btn-primary" id="filter_tanggal">
<i class="ki-outline ki-filter fs-2 me-1"></i>
Terapkan Filter
</button>
<button class="btn btn-sm btn-light" id="export-btn">
<i class="ki-outline ki-file-down fs-2 me-1"></i>
Export to Excel
</button>
</div>
</div>
</div>
<div class="min-w-full border card border-agi-100 card-grid" data-datatable="false" data-datatable-page-size="10"
data-datatable-state-save="false" id="laporan-penilai-jaminan-table"
data-api-url="{{ route('laporan-penilai-jaminan.datatables') }}">
<div class="flex-wrap py-5 card-header bg-agi-50">
<h3 class="card-title">
Daftar Laporan Penilai Jaminan
</h3>
</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"
<table class="table text-sm font-medium text-gray-700 align-middle table-auto table-border"
data-datatable-table="true">
<thead>
<tr>
<th class="w-14">
<input class="checkbox checkbox-sm" data-datatable-check="true" type="checkbox" />
<input class="checkbox checkbox-sm" data-datatable-check="true" type="checkbox"
id="check-all" />
</th>
<th class="min-w-[150px]" data-datatable-column="nomor_registrasi">
<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="user_id">
<span class="sort"><span class="sort-label">User Pemohon</span>
<span class="sort"><span class="sort-label">Pemohon</span>
<span class="sort-icon"></span>
</span>
</th>
<th class="min-w-[150px]" data-datatable-column="debitur_id">
<span class="sort"><span class="sort-label">Debitur</span>
<span class="sort"><span class="sort-label">Nama Debitur</span>
<span class="sort-icon"></span>
</span>
</th>
@@ -157,29 +165,34 @@
<span class="sort-icon"></span>
</span>
</th>
<th class="min-w-[150px]" data-datatable-column="tujuan_penilaian_id">
<th class="min-w-[150px]" data-datatable-column="jenis_agunan">
<span class="sort"> <span class="sort-label"> Jenis Jaminan </span>
<span class="sort-icon"></span>
</span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[150px]" data-datatable-column="laporan">
<span class="sort"><span class="sort-label">Laporan</span>
<span class="sort-icon"></span>
</span>
</th>
<th class="" data-datatable-column="actions">
<span class="sort"><span class="sort-label">Actions</span>
<span class="sort-icon"></span>
</span>
</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">
class="flex-col gap-3 justify-center font-medium text-gray-600 card-footer md:justify-between md:flex-row text-2sm">
<div class="flex gap-2 items-center">
Show
<select class="select select-sm w-16" data-datatable-size="true" name="perpage"> </select> per
<select class="w-16 select select-sm" data-datatable-size="true" name="perpage"> </select> per
page
</div>
<div class="flex items-center gap-4">
<div class="flex gap-4 items-center">
<span data-datatable-info="true"> </span>
<div class="pagination" data-datatable-pagination="true">
</div>
@@ -191,34 +204,49 @@
<!-- Form tersembunyi untuk export -->
<form id="export-form" action="{{ route('laporan-penilai-jaminan.export') }}" method="GET" class="hidden">
<input type="hidden" name="tanggal_awal" id="export_tanggal_awal">
<input type="hidden" name="tanggal_akhir" id="export_tanggal_akhir">
<input type="hidden" name="start_date" id="export_tanggal_awal">
<input type="hidden" name="end_date" id="export_tanggal_akhir">
<input type="hidden" name="status" id="export_status">
<input type="hidden" name="branch_id" id="export_branch_id">
<input type="hidden" name="laporan" id="export_laporan">
<input type="hidden" name="selected_ids" id="export_selected_ids">
<input type="hidden" name="export_type" id="export_type" value="all">
<input type="hidden" id="export_search" name="search">
</form>
@endsection
@push('scripts')
<script type="module">
const element = document.querySelector('#laporan-penilai-jaminan-table');
const searchInput = document.getElementById('search');
const tanggalAwalInput = document.getElementById('tanggal_awal');
const tanggalAkhirInput = document.getElementById('tanggal_akhir');
const startDateInput = document.getElementById('start_date');
const endDateInput = document.getElementById('end_date');
const branchFilter = document.getElementById('branch_filter');
const laporanFilter = document.getElementById('laporan');
const filterTanggalButton = document.getElementById('filter_tanggal');
const selectAllCheckbox = document.getElementById('select-all');
const exportButton = document.getElementById('export-btn');
const selectAllCheckbox = document.getElementById('check-all');
const statusCheckboxes = document.querySelectorAll('.status-checkbox');
// Export elements
const exportForm = document.getElementById('export-form');
const exportButton = document.getElementById('export-button');
const exportTanggalAwal = document.getElementById('export_tanggal_awal');
const exportTanggalAkhir = document.getElementById('export_tanggal_akhir');
const exportStartDate = document.getElementById('export_tanggal_awal');
const exportEndDate = document.getElementById('export_tanggal_akhir');
const exportBranchId = document.getElementById('export_branch_id');
const exportLaporan = document.getElementById('export_laporan');
const exportStatus = document.getElementById('export_status');
const exportSelectedIds = document.getElementById('export_selected_ids');
const exportType = document.getElementById('export_type');
const exportSearch = document.getElementById('export_search');
const apiUrl = element.getAttribute('data-api-url');
// Simple pagination state management
let currentPage = 1;
let isReturningFromDetail = false;
const dataTableOptions = {
apiEndpoint: apiUrl,
pageSize: 5,
@@ -245,12 +273,24 @@
nomor_registrasi: {
title: 'Nomor Registrasi',
},
tanggal_permohonan: {
title: 'Tanggal Permohonan',
render: (item, data) => {
return data.tanggal_permohonan ? window.formatTanggalIndonesia(data.tanggal_permohonan) :
'-';
},
},
branch: {
title: 'Cabang',
render: (item, data) => {
return data.branch && data.branch.name ? `${data.branch.name}` : '-';
},
},
user_id: {
title: 'User Pemohon',
render: (item, data) => {
return data.user && data.user.name ? `${data.user.name}` : '-';
},
return data?.user?.name ?? data?.mig_nama_ao ?? '-';
}
},
debitur_id: {
title: 'Debitur',
@@ -265,18 +305,18 @@
`${data.tujuan_penilaian.name}` : '-';
},
},
jenis_jaminan_id: {
jenis_agunan: {
title: 'Jenis Jaminan',
render: (item, data) => {
const jenisJaminan = data.dokumenjaminan.map(d => d.jenis_jaminan.name).join(', ');
return jenisJaminan || '-';
}
return data.dokumenjaminan.map((item) => {
return item.jenis_jaminan ? item.jenis_jaminan.name : '-';
}).join(', ');
},
},
laporan: {
title: 'Status',
render: (item, data) => {
let badgeClass = '';
const statusLaporan = data.penilai?.type_penilai || '-';
switch (statusLaporan.toLowerCase()) {
@@ -302,17 +342,114 @@
return `<span class="badge ${badgeClass}">${statusLaporan}</span>`;
},
},
actions: {
title: 'Action',
render: (item, data) => {
const status = data.status;
const dokumenjaminan = data.dokumenjaminan || [];
return `
<div class="flex flex-nowrap gap-1 justify-center">
${
['done'].includes(status) ?
dokumenjaminan.map(dokumen => {
return `
<a class="btn btn-sm btn-primary" href="surveyor/print-out-inspeksi/${data.id}/${dokumen.id}/${dokumen.jenis_jaminan_id}">
<i class="ki-outline ki-printer"></i>Inspeksi
</a>
<a class="btn btn-sm btn-info detail-btn" href="laporan-penilai-jaminan/show/${data.id}/${dokumen.id}/${dokumen.jenis_jaminan_id}">
<i class="ki-filled ki-eye"></i>Lihat
</a>
<a class="btn btn-sm btn-success" href="penilai/print-out-laporan/${data.id}/${dokumen.id}/${dokumen.jenis_jaminan_id}">
<i class="ki-filled ki-printer"></i>Laporan
</a>
`;
}).join('') : ''
}
</div>
`;
}
}
},
};
let dataTable = new KTDataTable(element, dataTableOptions);
const fromDetail = true;
if (fromDetail) {
isReturningFromDetail = true;
console.log('Returning from detail page');
// Remove the parameter from URL
window.history.replaceState({}, document.title, window.location.pathname);
setTimeout(() => {
restoreCurrentPage();
isReturningFromDetail = false;
}, 500);
}
function getCurrentPageFromDOM() {
const activePage = document.querySelector('.pagination .btn.active');
if (activePage) {
const pageText = activePage.textContent.trim();
const pageNum = parseInt(pageText);
return isNaN(pageNum) ? 1 : pageNum;
}
return 1;
}
function saveCurrentPage() {
const page = getCurrentPageFromDOM();
currentPage = page;
sessionStorage.setItem('currentTablePage', currentPage.toString());
}
function restoreCurrentPage() {
const savedPage = sessionStorage.getItem('currentTablePage');
if (savedPage && savedPage !== '1') {
currentPage = parseInt(savedPage);
console.log('Restoring to page:', currentPage);
// Use the goPage method to navigate to the saved page
dataTable.goPage(currentPage);
}
}
// Listen for pagination events to track current page
element.addEventListener('pagination', function(e) {
const page = e.detail.page;
currentPage = page;
console.log('Page changed to:', page);
});
// Alternative: Listen for pagination button clicks
document.addEventListener('click', function(e) {
if (e.target.matches('.pagination .btn') && !e.target.closest('.detail-btn')) {
setTimeout(() => {
currentPage = getCurrentPageFromDOM();
console.log('Current page updated to:', currentPage);
}, 100);
}
});
// Detail page redirection
document.addEventListener('click', function(e) {
if (e.target.closest('.detail-btn')) {
e.preventDefault();
// Save current page before navigating
const currentPageNum = getCurrentPageFromDOM();
currentPage = currentPageNum;
sessionStorage.setItem('currentTablePage', currentPage.toString());
console.log('Saving page before detail navigation:', currentPage);
const link = e.target.closest('.detail-btn');
const href = link.getAttribute('href');
window.location.href = href;
}
});
// Search functionality
searchInput.addEventListener('input', function() {
const searchValue = this.value.trim();
dataTable.search(searchValue, true);
applyDateFilter();
});
// Filter by date range
@@ -321,20 +458,30 @@
});
function applyDateFilter() {
const tanggalAwal = tanggalAwalInput.value;
const tanggalAkhir = tanggalAkhirInput.value;
const startDate = startDateInput.value;
const endDate = endDateInput.value;
const branch = branchFilter.value;
const laporan = Array.from(laporanFilter.selectedOptions).map(option => option.value);
let filters = {};
if (searchInput.value) {
filters.search = searchInput.value;
}
if (tanggalAwal) {
filters.tanggal_awal = tanggalAwal
if (startDate) {
filters.start_date = startDate;
}
if (tanggalAkhir) {
filters.tanggal_akhir = tanggalAkhir
if (endDate) {
filters.end_date = endDate;
}
if (branch) {
filters.branch_id = branch;
}
if (laporan.length > 0) {
filters.laporan = laporan;
}
dataTable.search(filters);
@@ -361,10 +508,8 @@
if (selectedStatuses.length === 0) {
dataTable.search('');
console.log(selectedStatuses);
} else {
dataTable.search(selectedStatuses.join(','), true);
console.log(selectedStatuses);
}
dataTable.reload();
@@ -374,30 +519,33 @@
selectAllCheckbox.checked = allChecked;
}
// Single export button functionality
// Export functionality
exportButton.addEventListener('click', function(e) {
e.preventDefault();
// Check if any rows are selected
const selectedIds = getSelectedRowIds();
// Determine export type based on context
if (selectedIds.length > 0) {
// If rows are selected, export those
exportData({
selected_ids: selectedIds,
export_type: 'selected'
});
} else if (tanggalAwalInput.value && tanggalAkhirInput.value || getSelectedStatuses().length > 0) {
// If filters are applied but no rows selected, export filtered data
} else if (startDateInput.value && endDateInput.value || getSelectedStatuses().length > 0) {
exportData({
tanggal_awal: tanggalAwalInput.value,
tanggal_akhir: tanggalAkhirInput.value,
start_date: startDateInput.value,
end_date: endDateInput.value,
branch_id: branchFilter.value,
laporan: Array.from(laporanFilter.selectedOptions).map(option => option.value),
status: getSelectedStatuses(),
search: searchInput.value,
export_type: 'filtered'
});
} else if (searchInput.value) {
exportData({
search: searchInput.value,
export_type: 'filtered'
});
} else {
// If no selection and no filters, export all
exportData({
export_type: 'all'
});
@@ -405,14 +553,14 @@
});
function exportData(filters = {}) {
// Set filter values in the hidden form
exportTanggalAwal.value = filters.tanggal_awal || '';
exportTanggalAkhir.value = filters.tanggal_akhir || '';
exportStartDate.value = filters.start_date || '';
exportEndDate.value = filters.end_date || '';
exportStatus.value = filters.status ? filters.status.join(',') : '';
exportBranchId.value = filters.branch_id || '';
exportLaporan.value = filters.laporan ? filters.laporan.join(',') : '';
exportSelectedIds.value = filters.selected_ids ? filters.selected_ids.join(',') : '';
exportType.value = filters.export_type || 'all';
// Submit the form
exportSearch.value = filters.search || '';
exportForm.submit();
}
@@ -426,5 +574,12 @@
const checkboxes = document.querySelectorAll('[data-datatable-row-check="true"]:checked');
return Array.from(checkboxes).map(checkbox => checkbox.value);
}
// Save page before leaving (only when not going to detail)
window.addEventListener('beforeunload', function() {
if (!isReturningFromDetail) {
saveCurrentPage();
}
});
</script>
@endpush

View File

@@ -0,0 +1,117 @@
@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="{{ route('laporan-penilai-jaminan.index') }}" 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');
});
});
</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

@@ -151,7 +151,7 @@
user_id: {
title: 'User Pemohon',
render: (item, data) => {
return `${data.user.name}`;
return `${data.user?.name}`;
},
},
tujuan_penilaian_id: {
@@ -180,16 +180,16 @@
jenis_fasilitas_kredit_id: {
title: 'Fasilitas Kredit',
render: (item, data) => {
return `${data.jenis_fasilitas_kredit.name}`;
return `${data.jenis_fasilitas_kredit?.name}`;
}
},
tanggal_survei: {
title: 'Tanggal Survei',
render: (item, data) => {
if (data.penilaian.waktu_penilaian) {
return `${formatDate(new Date(data.penilaian.waktu_penilaian))}`;
if (data.penilaian?.waktu_penilaian) {
return `${formatDate(new Date(data.penilaian?.waktu_penilaian))}`;
}
return `${formatDate(new Date(data.penilaian.created_at))}`;
return `${formatDate(new Date(data.penilaian?.created_at))}`;
},
},
due_date_sla: {
@@ -197,10 +197,10 @@
render: (item, data) => {
const tujuan_penilaian = data.tujuan_penilaian.name;
const tipe_laporan = data.penilai?.type;
const nilai_plafond = data.penilaian.nilaiPlafond?.name;
let waktu_penilaian = new Date(data.penilaian.created_at);
if (data.penilaian.waktu_penilaian) {
waktu_penilaian = new Date(data.penilaian.waktu_penilaian);
const nilai_plafond = data.penilaian?.nilaiPlafond?.name;
let waktu_penilaian = new Date(data.penilaian?.created_at);
if (data.penilaian?.waktu_penilaian) {
waktu_penilaian = new Date(data.penilaian?.waktu_penilaian);
}
if (tujuan_penilaian.name === "RAP") {
@@ -237,47 +237,22 @@
const type = data.penilai?.type || '';
let laporanButton = '';
let resumeButton = '';
let penyelesaian = '';
if (data.penilai.resume) {
if (data.penilai?.resume) {
resumeButton = `
<a href="{{ route('penilai.print-out') }}?permohonanId=${data.id}&documentId=${dokumenID}&inspeksiId=${inspeksiId}&jaminanId=${jenisJaminanID}&statusLpj=0" class="btn btn-sm btn-success">
<a href="penilai/print-out-laporan/${data.id}/${dokumenID}/${jenisJaminanID}" class="btn btn-sm btn-success">
Resume
</a>`;
}
// Logika untuk role pemohon-ao
@if (auth()->user()->hasRole('pemohon-ao'))
if (data.nilai_liquidasi == null) {
laporanButton = `
<a href="laporan/${data.id}" class="btn btn-sm btn-primary">
Laporan
</a>`;
} else if ((data.status_bayar == "sudah_bayar" || data.status_bayar == "tidak_bayar") &&
data.nilai_liquidasi > 0) {
laporanButton = generateLaporanButton(data, dokumenID, inspeksiId, jenisJaminanID,
data.penilai.type_penilai == 'resume' && !data.penilai.resume ? type :
typePenilaian);
}
@else
// Logika untuk role selain pemohon-ao
if (data.status_bayar == "sudah_bayar" || data.status_bayar == "tidak_bayar") {
laporanButton = generateLaporanButton(data, dokumenID, inspeksiId, jenisJaminanID,
data.penilai.type_penilai == 'resume' && !data.penilai.resume ? type :
typePenilaian);
}
@endif
function generateLaporanButton(data, dokumenID, inspeksiId, jenisJaminanID, typeParam) {
return `
<a href="{{ route('penilai.print-out') }}?permohonanId=${data.id}&documentId=${dokumenID}&inspeksiId=${inspeksiId}&jaminanId=${jenisJaminanID}&statusLpj=0&type=${typeParam}" class="btn btn-sm btn-primary">
laporanButton = `
<a href="penilai/print-out-laporan/${data.id}/${dokumenID}/${jenisJaminanID}" class="btn btn-sm btn-primary">
Laporan
</a>`;
}
return `<div class="flex flex-wrap gap-1.5 justify-end"> ${penyelesaian} ${resumeButton} ${laporanButton} </div>`;
return `<div class="flex flex-wrap gap-1.5 justify-end"> ${resumeButton} ${laporanButton} </div>`;
},
}
},

View File

@@ -6,8 +6,7 @@
@section('content')
<div class="grid gap-5 mx-auto w-full lg:gap-7.5">
<div class="min-w-full border card border-agi-100 card-grid" data-datatable="false" data-datatable-page-size="10"
data-datatable-state-save="false" id="noc-table" data-api-url="{{ route('noc.datatables.penyelesaian') }}">
<div class="min-w-full border card border-agi-100 card-grid" data-datatable="false" data-datatable-page-size="10" data-datatable-state-save="false" id="noc-table" data-api-url="{{ route('noc.datatables.penyelesaian') }}">
<div class="flex-wrap py-5 card-header bg-agi-50">
<h3 class="card-title">
Daftar NOC Penyelesaian

View File

@@ -282,8 +282,7 @@
nominal_bayar: {
title: 'Nominal Bayar',
render: (item, data) => {
return data.nominal_bayar ? `${window.formatRupiah(data.nominal_bayar)}` : `${window.formatRu
piah(data.biaya_final)}`;
return data.nominal_bayar ? `${window.formatRupiah(data.nominal_bayar)}` : `${window.formatRupiah(data.biaya_final)}`;
},
},
bukti_bayar: {
@@ -344,7 +343,7 @@ piah(data.biaya_final)}`;
var iconPembayaranOtorisator = '';
if (permohonan) {
if (permohonan.status_bayar !== 'sudah_bayar') {
if (permohonan.status_bayar !== 'sudah_bayar' || !permohonan.approve_bayar) {
iconPembayaranOtorisator = `<a class="btn btn-sm btn-icon btn-clear btn-primary" onclick="handlePembayaran(${permohonan.id},'otorisator')">
<i class="ki-filled ki-double-check"></i>
</a>

View File

@@ -1,5 +1,56 @@
<div class="no-break">
<table style="width: 100%">
@if($permohonan->is_mig)
@if (!empty($forminspeksi['fakta']['keterangan']))
@foreach ($forminspeksi['fakta']['keterangan'] as $key => $item)
<table class="judul" style="width: 100%; ">
<tr>
<td style="width: 100%; border: 1px solid #000; text-align: center;">
{{ $key }}
</td>
</tr>
</table>
<table class="judul" style="width: 100%; ">
<tr>
<td style="width: 100%; text-align: left;">
@if (is_array($item))
@foreach ($item as $data_)
{!! nl2br(e($data_)) !!}<br>
@endforeach
@else
{!! nl2br(e($item)) !!}
@endif
</td>
</tr>
</table>
@endforeach
@endif
@if (!empty($forminspeksi['fakta']['saran']))
@foreach ($forminspeksi['fakta']['saran'] as $key => $item)
<table class="judul" style="width: 100%; ">
<tr>
<td style="width: 100%; border: 1px solid #000; text-align: center;">
SARAN
</td>
</tr>
</table>
<table class="judul" style="width: 100%; ">
<tr>
<td style="width: 100%; text-align: left;">
@if (is_array($item))
@foreach ($item as $data_)
{!! nl2br(e($data_)) !!}<br>
@endforeach
@else
{!! nl2br(e($item)) !!}
@endif
</td>
</tr>
</table>
@endforeach
@endif
@else
<tr>
<td width="25%" style="vertical-align: top;">Informasi Dinas Tata Ruang
</td>
@@ -34,29 +85,6 @@
</td>
</tr>
@if (!empty($forminspeksi['fakta']['keterangan']))
<tr>
<td width="25%" style="vertical-align: top;">Catatan yang Perlu
Diperhatikan</td>
<td width="1%" style="vertical-align: top;">:</td>
<td style="vertical-align: top;">
@php
$keterangan = $forminspeksi['fakta']['keterangan'] ?? '';
if (is_array($keterangan)) {
$keterangan = implode(', ', array_filter($keterangan));
}
@endphp
@if (!empty($keterangan))
<table style="width: 100%; border-collapse: collapse;">
<tr>
<td>{!! nl2br(e($keterangan)) !!}</td>
</tr>
</table>
@endif
</td>
</tr>
@endif
</table>
</div>

View File

@@ -10,10 +10,10 @@
<table style="width: 100%">
@php
$lingkungan = $forminspeksi['lingkungan'];
$fasilitas = $lingkungan['fasilitas_dekat_object'] ?? [];
$fasilitasInput = $lingkungan['fasilitas_dekat_object_input'] ?? [];
@endphp
<tr>
<td style=" width:25%; padding: 2px; vertical-align: top;">Jarak Jalan Utama</td>
<td style=" width:1%; padding: 2px; vertical-align: top;">:</td>
@@ -33,43 +33,52 @@
<tr>
<td style="padding: 2px; vertical-align: top;">Lebar Perkerasan Jalan</td>
<td style="padding: 2px; vertical-align: top;">:</td>
<td style="padding: 2px; vertical-align: top;">{{ $lingkungan['lebar_perkerasan_jalan'] ?? '-' }} m</td>
<td style="padding: 2px; vertical-align: top;">{{ $lingkungan['lebar_perkerasan_jalan'] ?? '-' }}</td>
</tr>
{{-- mulai --}}
<tr>
<td style="padding: 2px; vertical-align: top;">Perkerasan Jalan</td>
<td style="padding: 2px; vertical-align: top;">:
</td>
<td style="padding: 2px; vertical-align: top;">
{{ implode(', ', $lingkungan['perkerasan_jalan']['perkerasan_jalan'] ?? ['-']) }}
{{ implode(', ', $lingkungan['perkerasan_jalan']['perkerasan_jalan'] ?? $lingkungan['perkerasan_jalan'] ?? ['-']) }}
</td>
</tr>
<tr>
<td style="padding: 2px; vertical-align: top;">Lalu Lintas</td>
<td style="padding: 2px; vertical-align: top;">:</td>
<td style="padding: 2px; vertical-align: top;">{{ implode(', ', $lingkungan['lalu_lintas'] ?? ['-']) }}
<td style="padding: 2px; vertical-align: top;">{{
$lingkungan['lalu_lintas']
? (is_array($lingkungan['lalu_lintas'])
? implode(', ', $lingkungan['lalu_lintas'])
: $lingkungan['lalu_lintas'])
: '-'
}}
</td>
</tr>
<tr>
<td style="padding: 2px; vertical-align: top;">Golongan Masyarakat Sekitar</td>
<td style="padding: 2px; vertical-align: top;">:</td>
<td style="padding: 2px; vertical-align: top;">{{ implode(', ', $lingkungan['gol_mas_sekitar'] ?? ['-']) }}
<td style="padding: 2px; vertical-align: top;">{{ implode(', ', $lingkungan['gol_mas_sekitar'] ?? $lingkungan['gol_mas_sekitar'] ?? ['-']) }}
</td>
</tr>
<tr>
<td style="padding: 2px; vertical-align: top;">Tingkat Keramaian</td>
<td style="padding: 2px; vertical-align: top;">:</td>
<td style="padding: 2px; vertical-align: top;">
{{ implode(', ', $lingkungan['tingkat_keramaian'] ?? ['-']) }}
{{ implode(', ', $lingkungan['tingkat_keramaian']['tingkat_keramaian'] ?? $lingkungan['tingkat_keramaian'] ?? ['-']) }}
</td>
</tr>
<tr>
<td style="padding: 2px; vertical-align: top;">Terletak di Area</td>
<td style="padding: 2px; vertical-align: top;">:</td>
<td style="padding: 2px; vertical-align: top;">
{{ implode(', ', $lingkungan['terletak_diarea']['terletak_diarea'] ?? ['-']) }}
{{ implode(', ', $lingkungan['terletak_diarea']['terletak_diarea'] ?? $lingkungan['terletak_diarea'] ?? ['-']) }}
</td>
</tr>
{{-- batas --}}
<tr>
<td style="padding: 2px; vertical-align: top;">Kondisi Bangunan Sekitar</td>
<td style="padding: 2px; vertical-align: top;">:</td>

View File

@@ -271,25 +271,22 @@
<label for="nilai-pasar-1" class="form-label max-w-56">Nilai Pasar Wajar (NPW)</label>
<div class="flex flex-wrap items-baseline w-full">
<input type="text" id="nilai-pasar-1" name="nilai_pasar_kjpp"
class="w-full input nilai-pasar currency-format" placeholder="Masukkan likuidasi"
value="{{ $callReport['nilai_pasar_kjpp'] ?? '' }}">
class="w-full input nilai-pasar currency-format" placeholder="Masukkan likuidasi" value="{{ $callReport['nilai_pasar_kjpp'] ?? '' }}">
</div>
</div>
<div class="flex flex-wrap gap-2.5 items-baseline w-full lg:flex-nowrap">
<label for="likuidasi-1" class="form-label max-w-56">Nilai Likuidasi(%)</label>
<div class="flex flex-wrap items-baseline w-full">
<input type="text" id="likuidasi-1" name="persentase_likuidasi_kjpp"
class="w-full input likuidasi" placeholder="Masukkan likuidasi dalam bentuk persen"
onkeyup="calculateTotal(this)" data-group="1"
value="{{ $callReport['persentase_likuidasi_kjpp'] ?? '' }}">
<input type="text" id="likuidasi-1" name="persentase_likuidasi_kjpp" class="w-full input likuidasi"
placeholder="Masukkan likuidasi dalam bentuk persen" onkeyup="calculateTotal(this)"
data-group="1" value="{{ $callReport['persentase_likuidasi_kjpp'] ?? '' }}">
</div>
</div>
<div class="flex flex-wrap gap-2.5 items-baseline w-full lg:flex-nowrap">
<label for="total-likuidasi-1" class="form-label max-w-56">Total Nilai Likuidasi (NL)</label>
<div class="flex flex-wrap items-baseline w-full">
<input type="text" id="total-likuidasi-1" name="hasil_nilai_likuidasi_kjpp"
class="w-full input total-likuidasi currency-format" placeholder="Hasil perhitungan"
value="{{ $callReport['hasil_nilai_likuidasi_kjpp'] ?? '' }}">
class="w-full input total-likuidasi currency-format" placeholder="Hasil perhitungan" value="{{ $callReport['hasil_nilai_likuidasi_kjpp'] ?? '' }}">
</div>
</div>
</div>
@@ -312,25 +309,22 @@
<label for="nilai-pasar-2" class="form-label max-w-56">Nilai Pasar Wajar (NPW)</label>
<div class="flex flex-wrap items-baseline w-full">
<input type="text" id="nilai-pasar-2" name="nilai_pasar_internal"
class="w-full input nilai-pasar currency-format" placeholder="Masukkan likuidasi"
value="{{ $callReport['nilai_pasar_internal'] ?? '' }}">
class="w-full input nilai-pasar currency-format" placeholder="Masukkan likuidasi" value="{{ $callReport['nilai_pasar_internal'] ?? '' }}">
</div>
</div>
<div class="flex flex-wrap gap-2.5 items-baseline w-full lg:flex-nowrap">
<label for="likuidasi-2" class="form-label max-w-56">Nilai Likuidasi(%)</label>
<div class="flex flex-wrap items-baseline w-full">
<input type="text" id="likuidasi-2" name="persentase_likuidasi_internal"
class="w-full input likuidasi" placeholder="Masukkan likuidasi dalam bentuk persen"
onkeyup="calculateTotal(this)" data-group="2"
value="{{ $callReport['persentase_likuidasi_internal'] ?? '' }}">
<input type="text" id="likuidasi-2" name="persentase_likuidasi_internal" class="w-full input likuidasi"
placeholder="Masukkan likuidasi dalam bentuk persen" onkeyup="calculateTotal(this)"
data-group="2" value="{{ $callReport['persentase_likuidasi_internal'] ?? '' }}">
</div>
</div>
<div class="flex flex-wrap gap-2.5 items-baseline w-full lg:flex-nowrap">
<label for="total-likuidasi-2" class="form-label max-w-56">Total Nilai Likuidasi (NL)</label>
<div class="flex flex-wrap items-baseline w-full">
<input type="text" id="total-likuidasi-2" name="hasil_nilai_likuidasi_internal"
class="w-full input total-likuidasi currency-format" placeholder="Hasil perhitungan"
value="{{ $callReport['hasil_nilai_likuidasi_internal'] ?? '' }}">
class="w-full input total-likuidasi currency-format" placeholder="Hasil perhitungan" value="{{ $callReport['hasil_nilai_likuidasi_internal'] ?? '' }}">
</div>
</div>
</div>
@@ -510,9 +504,8 @@
</div>
<div class="flex gap-2 justify-end" style="margin-right: 20px; margin-top: 20px">
@if (Auth::user()->hasAnyRole(['senior-officer', 'surveyor', 'administrator']))
<button type="button" class="btn btn-primary" id="saveButton" onclick="submitData()"
{{ $permohonan->status == 'proses-paparan' || ($permohonan->status == 'proses-laporan' && Auth::user()->hasAnyRole(['surveyor'])) ? 'disabled' : '' }}>
@if (Auth::user()->hasAnyRole(['senior-officer', 'surveyor', 'administrator','EO Appraisal']))
<button type="button" class="btn btn-primary" id="saveButton" onclick="submitData()" {{ $permohonan->status == 'proses-paparan' || $permohonan->status == 'proses-laporan' && Auth::user()->hasAnyRole(['surveyor']) ? 'disabled' : '' }}>
<i class="ki-filled ki-save-2"></i>
<span id="saveButtonText">Simpan</span>
</button>
@@ -571,25 +564,19 @@
jsonData.lelang_kjpp = document.querySelector('input[name="lelang_kjpp"]')?.value.trim() || "";
// Ambil nilai lainnya
jsonData.nilai_pasar_kjpp = cleanCurrencyValue(document.querySelector('input[name="nilai_pasar_kjpp"]')?.value
.trim() ||
jsonData.nilai_pasar_kjpp = cleanCurrencyValue(document.querySelector('input[name="nilai_pasar_kjpp"]')?.value.trim() ||
"");
jsonData.persentase_likuidasi_kjpp = cleanCurrencyValue(document.querySelector(
'input[name="persentase_likuidasi_kjpp"]')?.value
jsonData.persentase_likuidasi_kjpp = cleanCurrencyValue(document.querySelector('input[name="persentase_likuidasi_kjpp"]')?.value
.trim() || "");
jsonData.hasil_nilai_likuidasi_kjpp = cleanCurrencyValue(document.querySelector(
'input[name="hasil_nilai_likuidasi_kjpp"]')
jsonData.hasil_nilai_likuidasi_kjpp = cleanCurrencyValue(document.querySelector('input[name="hasil_nilai_likuidasi_kjpp"]')
?.value.trim() || "");
jsonData.lelang_internal = document.querySelector('input[name="lelang_internal"]')?.value.trim() || "";
jsonData.nilai_pasar_internal = cleanCurrencyValue(document.querySelector('input[name="nilai_pasar_internal"]')
?.value.trim() ||
jsonData.nilai_pasar_internal = cleanCurrencyValue(document.querySelector('input[name="nilai_pasar_internal"]')?.value.trim() ||
"");
jsonData.persentase_likuidasi_internal = cleanCurrencyValue(document.querySelector(
'input[name="persentase_likuidasi_internal"]')?.value
jsonData.persentase_likuidasi_internal = cleanCurrencyValue(document.querySelector('input[name="persentase_likuidasi_internal"]')?.value
.trim() || "");
jsonData.hasil_nilai_likuidasi_internal = cleanCurrencyValue(document.querySelector(
'input[name="hasil_nilai_likuidasi_internal"]')
jsonData.hasil_nilai_likuidasi_internal = cleanCurrencyValue(document.querySelector('input[name="hasil_nilai_likuidasi_internal"]')
?.value.trim() || "");
return jsonData;

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