1301 Commits

Author SHA1 Message Date
Daeng Deni Mardaeni
6378ba0f98 ⚙️ feat(LpjServiceProvider): Konfigurasi scheduling otomatis untuk cleanup inspeksi
Menambahkan registrasi commands dan scheduling untuk cleanup data inspeksi dengan konfigurasi multi-server dan logging

- Register 3 command cleanup: CleanupInspeksiDataCommand, CleanupSingleInspeksiCommand, dan CleanupInspeksiStatusCommand
- Daily cleanup scheduling setiap jam 02:00 dengan opsi --force dan withoutOverlapping()
- Weekly backup cleanup setiap minggu pukul 03:00 pada hari minggu
- Multi-server support dengan onOneServer() untuk environment clustered
- Background execution dengan runInBackground() untuk performa optimal
- Dedicated logging ke storage/logs/cleanup-inspeksi.log dan cleanup-inspeksi-weekly.log
- Service binding untuk BankDataService dengan dependency injection
- Modular structure dengan namespace dan module path yang terorganisir
2025-12-09 15:42:43 +07:00
Daeng Deni Mardaeni
2c8136dcf3 🔧 feat(SurveyorController): Tambahkan cleanup inspeksi otomatis pada method show
Menambahkan fungsi cleanupInspeksiData() untuk membersihkan data inspeksi lama secara otomatis saat menampilkan detail permohonan

- Method cleanupInspeksiData() dipanggil otomatis di method show() line 112
- Implementasi cleanup berbasis created_by dengan grouping data
- Soft delete data inspeksi tanpa dokument_id jika ada data lengkap dengan dokument_id
- Transaction handling dengan DB::beginTransaction() dan DB::rollback() untuk konsistensi data
- Comprehensive logging untuk audit trail setiap operasi cleanup
- Error handling individual per data dengan continue pada exception
- Validasi mutual exclusion antara data dengan dan tanpa dokument_id
- Integrasi dengan Auth::id() untuk tracking user yang melakukan akses
2025-12-09 15:40:33 +07:00
Daeng Deni Mardaeni
3315e1d4b6 📚 docs(Console README): Tambahkan dokumentasi lengkap untuk console commands cleanup inspeksi
Membuat dokumentasi komprehensif untuk semua command cleanup dengan contoh penggunaan dan troubleshooting guide

- Dokumentasi untuk 3 command utama: lpj:cleanup-inspeksi, lpj:cleanup-single-inspeksi, dan lpj:cleanup-inspeksi-status
- Usage examples untuk setiap command dengan berbagai opsi (--sync, --force, --dry-run, --detailed)
- Penjelasan alur kerja cleanup (identifikasi → proses → logging → transaction)
- Informasi scheduling otomatis (setiap hari jam 2 pagi dan mingguan)
- Lokasi log files untuk monitoring dan troubleshooting
- Troubleshooting guide untuk command tidak muncul, data tidak ter-cleanup, dan performance issues
- Best practices untuk data besar dengan mode queue vs sync
2025-12-09 15:38:35 +07:00
Daeng Deni Mardaeni
37fb5c90d5 🧹 feat(CleanupInspeksiDataCommand): Implementasi command utama untuk batch cleanup data inspeksi
Membuat artisan command utama untuk cleanup data inspeksi secara batch dengan fitur preview, filter, dan progress tracking

- Command signature: `lpj:cleanup-inspeksi` dengan opsi --permohonan-id, --sync, --dry-run, dan --force
- Method getCleanupData() untuk query data yang memenuhi kriteria cleanup menggunakan DB::table
- Method displayPreview() untuk menampilkan tabel preview data yang akan di-cleanup
- Method runCleanup() dengan progress bar untuk tracking progress batch processing
- Validasi mutual exclusion antara --dry-run dan --sync untuk mencegah konflik
- Konfirmasi interaktif sebelum proses (dapat di-skip dengan --force)
- Support mode sync (direct execution) dan async (queue dispatch)
- Error handling per permohonan dengan continue pada exception
- Comprehensive logging dengan context options dan error details
- Hitungan total data yang dihapus dan jumlah error untuk reporting
2025-12-09 15:38:28 +07:00
Daeng Deni Mardaeni
ff994a7c95 🧹 feat(CleanupSingleInspeksiCommand): Tambahkan command untuk cleanup inspeksi per permohonan
Membuat artisan command untuk cleanup data inspeksi secara spesifik untuk 1 permohonan dan user tertentu dengan opsi sync/async

- Command signature: `lpj:cleanup-single-inspeksi` dengan required arguments permohonan-id dan created-by
- Opsi --sync untuk eksekusi synchronous dan --force untuk skip konfirmasi
- Validasi input permohonanId dan createdBy harus angka positif
- Integrasi dengan InspeksiCleanupService untuk cleanupSync() dan cleanupAsync()
- Konfirmasi interaktif sebelum proses (dapat di-skip dengan --force)
- Comprehensive logging dengan context permohonan_id dan created_by
- Error handling dengan try-catch dan return Command::SUCCESS/FAILURE
- Informasi mode eksekusi (Synchronous vs Queue) ditampilkan ke user
- Pesan sukses yang jelas untuk monitoring progress di log
2025-12-09 15:35:52 +07:00
Daeng Deni Mardaeni
a2275758b1 🔍 feat(CleanupInspeksiStatusCommand): Tambahkan command untuk monitoring status data inspeksi
Membuat artisan command untuk cek status data yang memerlukan cleanup dengan opsi filter dan detail view

- Command signature: `lpj:cleanup-inspeksi-status` dengan opsi --permohonan-id, --created-by, dan --detailed
- Method showGeneralStats() untuk statistik umum data (total, aktif, terhapus, dengan/tanpa dokument_id)
- Method showCleanupStats() untuk identifikasi data yang perlu cleanup berdasarkan permohonan_id dan created_by
- Method showDetailedData() untuk menampilkan 20 data terbaru dengan relasi permohonan dan dokument
- Query optimization dengan DB::table dan raw SQL untuk performa optimal
- Error handling dengan try-catch dan logging ke Laravel Log
- Tampilan tabel yang informatif dengan format number_format untuk angka besar
- Support filter berdasarkan permohonan_id dan created_by untuk analisis spesifik
- Limit 20 data untuk mencegah overload memory pada dataset besar
2025-12-09 15:34:47 +07:00
Daeng Deni Mardaeni
783250d99a 🧪 test(CleanupInspeksiDataJobTest): Implementasi unit test lengkap untuk cleanup job
Membuat suite test yang mencakup semua skenario penting untuk CleanupInspeksiDataJob dengan RefreshDatabase trait

- 6 test cases yang mencakup success dan failure scenarios
- Penggunaan RefreshDatabase trait untuk isolasi data test
- Penggunaan factory models untuk pembuatan data test otomatis
- Validasi soft delete pada data inspeksi lama tanpa dokument_id
- Pencegahan penghapusan data dengan created_by berbeda
- Handling exception dan rollback transaction
- Logging error pada method failed
- PHPDoc dokumentasi untuk setiap test case
- Integrasi dengan model Permohonan, DokumenJaminan, dan Inspeksi
2025-12-09 15:32:35 +07:00
Daeng Deni Mardaeni
19057c7e81 🎮 controller(InspeksiController): Implementasi controller dengan integrasi cleanup service
Membuat controller contoh yang menunjukkan best practices penggunaan InspeksiCleanupService dengan automatic cleanup trigger pada create dan update operations

- Dependency injection InspeksiCleanupService melalui constructor
- Method store() dengan automatic cleanup trigger saat dokument_id tersedia
- Method update() dengan cleanup trigger hanya saat dokument_id berubah dari null
- Method cleanup() untuk eksekusi manual cleanup dengan pilihan sync/async
- Validasi request yang komprehensif untuk semua method
- Database transaction handling dengan proper rollback pada error
- Logging informatif untuk audit trail setiap operasi
- Error handling dengan try-catch dan response JSON yang konsisten
- Response format yang standar dengan status code HTTP yang tepat
- PHPDoc dokumentasi untuk setiap method dengan parameter dan return type
2025-12-09 15:27:48 +07:00
Daeng Deni Mardaeni
9dfb8727dc 🔧 service(InspeksiCleanupService): Implementasi service layer untuk manajemen cleanup data inspeksi
Membuat service layer yang menyediakan interface fleksibel untuk menjalankan cleanup data inspeksi secara async/sync dengan error handling dan logging komprehensif

- Implementasi pattern service layer untuk separation of concerns
- Method utama cleanupInspeksiData dengan parameter sync untuk fleksibilitas eksekusi
- Method wrapper cleanupAsync() untuk eksekusi asynchronous default
- Method wrapper cleanupSync() untuk eksekusi synchronous langsung
- Error handling dengan try-catch dan re-throw exception untuk propagasi error
- Logging informatif untuk setiap proses cleanup (mulai, selesai, error)
- Integrasi dengan CleanupInspeksiDataJob untuk delegasi proses bisnis
- Parameter lengkap: permohonanId, createdBy, dokumentId, dan sync mode
- Dokumentasi PHPDoc yang komprehensif untuk setiap method
- Menggunakan Laravel dispatch() untuk queue management yang optimal
2025-12-09 15:24:44 +07:00
Daeng Deni Mardaeni
bef7bcfa8f 🗑️ job(CleanupInspeksiDataJob): Menambahkan fungsi untuk cleanup data inspeksi dengan queueable retry dan transaction aman
Menambahkan exponential backoff (60, 120, 300 detik), timeout 5 menit, dan logging rinci untuk audit cleanup data inspeksi tanpa dokument_id

- Implementasi job queue dengan retry otomatis menggunakan exponential backoff strategy
- Tambahkan timeout 5 menit untuk mencegah hanging jobs
- Gunakan database transaction untuk memastikan atomicity operasi soft delete
- Logging komprehensif untuk audit trail proses cleanup
- Validasi data lengkap (dengan dokument_id) sebelum proses cleanup
- Soft delete data lama tanpa dokument_id hanya jika data baru tersedia
- Pencegahan penghapusan data yang baru saja ditemukan dengan kondisi where('id', '!=', $newInspeksi->id)
- Error handling dengan rollback transaction dan re-throw exception untuk retry mechanism
- Dokumentasi kode yang jelas dengan PHPDoc untuk setiap method
- Menggunakan Laravel best practices dengan ShouldQueue, Dispatchable, InteractsWithQueue, Queueable, SerializesModels traits
2025-12-09 15:22:37 +07:00
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
2db123a386 🧩 feat(penilaian, otorisator): gunakan ambang NPW untuk approval dan rapikan UI
- Terapkan logika berbasis NPW (total_nilai_pasar_wajar) dari JSON LPJ untuk menentukan status approval pada PenilaianController (sekitar baris 517–533).
- Senior Officer: status selesai jika NPW ≤ 1.000.000.000, selain itu masuk proses-laporan.
- EO Appraisal: status selesai jika NPW ≤ 5.000.000.000, selain itu masuk proses-laporan.
- DD Appraisal: tetap status selesai.
- Ambil NPW dari json_decode($permohonan->penilaian->lpj) dan hilangkan pemisah ribuan dengan str_replace('.', '', $npw) .
- Tampilkan tombol Otorisator di tampilan resources/views/penilaian/otorisator/show.blade.php berdasarkan ambang NPW:
  - EO: tombol muncul jika NPW > 1.000.000.000.
  - DD: tombol muncul jika NPW > 5.000.000.000.
- Rapikan kelas Tailwind pada komponen card, header, body, grid dan fleksibelitas layout agar konsisten (reorder class, penyesuaian urutan dan semantik).
- Perbaiki urutan icon dan teks pada tombol aksi agar konsisten (mis. mr-2 ki-filled ki-eye ).
2025-11-10 17:27:23 +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
1dd4f8167e 🧩 feat(noc-controller): perluas filter pencarian NOC dengan relasi permohonan, debitur, jenis penilaian, dan nomor tiket
Ringkasan perubahan:
- Tambah filter orWhereRelation('permohonan', 'nomor_registrasi', 'LIKE', ...) untuk mencocokkan nomor_registrasi dari permohonan.
- Tambah filter orWhereRelation('permohonan.debiture','name', 'LIKE', ...) agar pencarian mencakup nama debitur.
- Tambah filter orWhereRelation('permohonan.jenisPenilaian', 'name', 'LIKE', ...) untuk dukungan jenis penilaian terkait.
- Tambah filter orWhere('nomor_tiket', 'LIKE', ...) untuk pencarian berdasarkan nomor_tiket.
2025-11-10 08:39:00 +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
Daeng Deni Mardaeni
535be2cff3 feat(permohonan): otomasi PersetujuanPenawaran & NOC saat sudah dibayar, tambah validasi Bukti Bayar,
- PersetujuanPenawaran: ubah logika pembuatan menjadi firstOrCreate untuk mencegah duplikasi dan menjaga idempotensi.
- Validasi Bukti Bayar: wajib unggah dokumen “Bukti Bayar” saat status sudah_dibayar ; blokir proses jika dokumen tidak ditemukan.
- Simpan Bukti Bayar ke PersetujuanPenawaran: ambil dari koleksi dokumen jaminan, set ke field bukti_bayar .
- NOC otomatis: updateOrCreate NOC berdasarkan permohonan_id dan persetujuan_penawaran_id ; logging error bila gagal.
- Pengalihan aman: redirect terarah dengan pesan error pada kondisi validasi gagal atau kegagalan pembuatan NOC.
2025-11-08 11:45:10 +07:00
Daeng Deni Mardaeni
1a67eb2000 feat(penilai-resume): tambah fallback route 'Back' dan perluas akses 'penilai',
- Tambah fallback default 'index' untuk parameter type pada tombol Back agar tetap berfungsi saat request('header') tidak tersedia.
- Perluas akses tombol Simpan ke peran penilai dan sesuaikan logika disable saat status tertentu.
2025-11-06 14:34:57 +07:00
Daeng Deni Mardaeni
e8ef9c0932 feat(lpj): Perluas akses peran dan rapikan UI Penilai/Surveyor
- Tambah peran `senior-officer` pada konfigurasi module untuk memperluas akses.
- Rapikan penamaan dan urutan kelas Tailwind pada komponen Penilai & Surveyor.
- Perjelas label dan placeholder: “Pihak Bank (Selain Appraisal)” agar tidak ambigu.
- Perkuat navigasi Penilai: Back button juga tersedia untuk peran `penilai`.
2025-11-06 14:26:09 +07:00
Daeng Deni Mardaeni
81f165c9d0 🐛 fix(penilai): Selaraskan sumber data alamat di Resume dan Show
Ringkasan:
- Perbaiki pemanggilan `formatAlamat` agar menggunakan objek yang benar di halaman Penilai.
- Hindari ketidaksesuaian data alamat dengan mengganti referensi model yang tidak tepat.
- Dampak: tampilan alamat pada komponen Resume dan halaman Show kini akurat.
2025-11-05 17:05:31 +07:00
Daeng Deni Mardaeni
25011d1798 feat(lpj): Tingkatkan kontrol akses, query pembayaran, upload, dan UI
- Izinkan penghapusan dokumen jaminan untuk status 'order'/'revisi'
- Longgarkan guard admin sementara (comment response 403) pada aksi hapus
- Tambah transaksi DB saat hapus dokumen (begin/commit/rollback)
- Sesuaikan filter daftar pembayaran; hilangkan blok where `belum_bayar`/`jenis_penilaian=1`
- Tambah metode `handleUpload()` dengan `storeAs` ke disk `public`
- Rap-penilai: tambah tombol Back; peran 'penilai' diizinkan menyimpan
- Authorization: rapikan kelas Tailwind dan validasi keterangan saat revisi
- Persetujuan penawaran: gunakan optional chaining saat render nominal bayar
- Surveyor/tanah: gunakan `detail` alih-alih `details` saat hitung luas
- Komponen lampiran-dokumen: perbaiki atribut `textarea` dan penataan id
2025-11-05 16:46:52 +07:00
Daeng Deni Mardaeni
e773b82218 (lpj/nilai-plafond): Tambah field biaya, validasi, transaksi DB, ekspor, dan tampilan
- Menambahkan kolom biaya ke seluruh alur Nilai Plafond (model, request, controller, views, export, dan migrasi)
- Update model NilaiPlafond agar field biaya bisa di-mass assign ($fillable)
- Tambah validasi baru 'biaya' (nullable|numeric|min:0) di NilaiPlafondRequest
- Terapkan transaksi DB (beginTransaction, commit, rollback) pada store/update/destroy di controller
- Tambahkan kolom biaya ke view create, edit, dan datatable index dengan format Rupiah dan tooltip nilai mentah
- Tambah header & mapping kolom biaya di NilaiPlafondExport agar muncul di hasil export Excel
- Tambah migrasi kolom biaya bertipe decimal(15,2) nullable dengan rollback support
- Tambahkan logging detail (Log::info & Log::error) di setiap proses utama controller
- Pastikan pencarian kolom biaya pada datatables menggunakan CAST ke TEXT untuk kompatibilitas PostgreSQL
2025-10-03 10:23:21 +07:00
Daeng Deni Mardaeni
04ee3a0c48 🔧(permohonan): Perbaiki logika pembuatan PersetujuanPenawaran dan update label menu
- Menambahkan pengecekan `status_bayar == 'belum_bayar'` sebelum membuat record PersetujuanPenawaran
- Mencegah pembuatan PersetujuanPenawaran jika status pembayaran sudah 'sudah_bayar'
- Memastikan logika bisnis hanya membuat PersetujuanPenawaran untuk permohonan belum dibayar
- Mengoptimalkan query database untuk mengurangi operasi CREATE yang tidak perlu
- Memperbaiki struktur dan indentasi kode di PermohonanController agar lebih mudah dibaca
- Mengubah label menu dari "Data Debitur" menjadi "Data Permohonan" di module.json
- Menyelaraskan istilah menu dengan konten dan fungsi halaman
- Meningkatkan konsistensi data dan efisiensi sistem
- Memperbaiki UX dengan label menu yang lebih relevan dan mudah dipahami
2025-09-30 17:08:29 +07:00
Daeng Deni Mardaeni
10b5a6c96c (persetujuan-penawaran): Tambah fitur tampilan file dan perbaiki logika persetujuan penawaran
- Menambahkan auto-fill nominal_bayar dengan nilai biaya_final pada create persetujuan
- Memperbaiki query datatables dengan filter status penawaran lebih spesifik
- Menambahkan whereHas untuk memastikan hanya status 'persetujuan-penawaran' yang ditampilkan
- Menambahkan preview file upload (persetujuan_penawaran, surat_representasi, bukti_bayar)
- Menggunakan Storage::url() untuk generate URL file dengan keamanan optimal
- Menambahkan ikon eye dan badge untuk tampilan preview file
- Memperbaiki fallback nominal_bayar agar otomatis menggunakan biaya_final
- Merapikan struktur HTML dan urutan class Tailwind CSS di index dan form blade
- Mengoptimalkan AJAX request structure dan error handling agar lebih stabil
2025-09-30 17:06:30 +07:00
Daeng Deni Mardaeni
3aca1d46c2 🧹(surveyor): Optimasi import statements dan perbaikan tampilan detail surveyor
- Menghapus lebih dari 20 import statements yang tidak digunakan di SurveyorController
- Membersihkan import RedirectResponse, JsonResponse, Response, dan helper tidak relevan
- Menghapus model lama seperti Surveyor, Analisa, dan AnalisaFakta yang tidak digunakan
- Menambahkan import PermohonanHistory untuk fitur catatan revisi survey
- Menambahkan query untuk mengambil catatan revisi terbaru dari PermohonanHistory
- Menampilkan catatan revisi dengan filter status 'revisi-survey' menggunakan latest()
- Mereorganisasi urutan class Tailwind CSS pada detail.blade.php agar lebih konsisten
- Memperbaiki struktur HTML dan indentasi untuk meningkatkan readability
- Mengoptimalkan error handling dan conditional rendering di view untuk tampilan lebih bersih
2025-09-30 17:01:52 +07:00
Daeng Deni Mardaeni
db55471111 🎨(pembayaran): Perbaiki logika status pembayaran dan optimasi tampilan approval
- Memperbaiki nested condition untuk jenis_penilaian_id == 2 pada PembayaranController
- Memindahkan logika status 'spk' ke blok else yang sesuai
- Menyempurnakan flow status pembayaran agar konsisten dan bebas konflik
- Menghindari benturan status antara 'proses-laporan' dan 'spk'
- Menyusun ulang class Tailwind CSS pada approval.blade.php agar konsisten dan rapi
- Memperbaiki struktur HTML dan layout card untuk meningkatkan readability dan responsivitas
- Menambahkan fallback nominal_bayar dari biaya_final untuk keandalan data
- Mengoptimalkan tampilan tombol action berdasarkan status_bayar dengan null-checking
- Menambahkan fallback values untuk data kosong serta perbaikan spacing & alignment
- Meningkatkan UX dan accessibility agar approval page lebih user-friendly dan stabil
2025-09-30 16:57:44 +07:00
Daeng Deni Mardaeni
112262d7d6 🎨 feat(ui-noc): tambah field nomor rekening lebih bayar & perbaikan styling konsistensi Tailwind
- Form NOC: tambah field nomor rekening lebih bayar (input number, readonly jika ada memo, hidden default, support old value & error handling)
- Foto Lampiran: ubah layout jadi grid 4 kolom dengan shadow & hover effect, perbaikan urutan class Tailwind & judul kategori lebih prominent
- Foto Lampiran: optimasi class container (relative, overflow-hidden, flex) & perbaikan spacing array $fotoTypes
- LPJ Sederhana Standar: konsistensi class grid/flex/input-group, role 'penilai' ditambahkan untuk akses tombol simpan, perbaikan kondisi disabled button
- Resume: optimasi class grid, flex, card-body, card-title, text, dan konsistensi urutan Tailwind di seluruh komponen
- Konsistensi class: perbaikan di form, foto-lampiran, lpj-standar, resume agar mengikuti urutan Tailwind (layout → sizing → styling)
- Struktur HTML: dirapikan untuk layout yang lebih responsif & semantik, dengan grid/flex yang lebih optimal
- UX: tampilan foto lebih rapi, form lebih mudah digunakan, role-based access lebih jelas, field tambahan untuk kebutuhan bisnis
- Dampak: data NOC lebih lengkap (tracking rekening lebih bayar), styling konsisten, UX meningkat, kode lebih maintainable
2025-09-26 10:57:06 +07:00
Daeng Deni Mardaeni
a1b9b7af86 🎨 refactor(ui): perbaikan styling form penilai & optimasi dashboard role-based
- Form Penilai: hapus spasi ganda di class CSS input currency/currency-format
- Konsistensi class Tailwind: gunakan "w-full currency" & "w-full currency-format"
- Hapus console.log tidak perlu, tambah debug log untuk parsing luas
- Optimasi parsing input luas dengan parseFloat + regex sanitasi numerik
- Dashboard: tambahkan pembatasan akses berdasarkan role (!penilai, !surveyor, !pemohon-ao, !pemohon-eo)
- Perbaiki struktur HTML & urutan class Tailwind (grid, flex, spacing, alignment)
- Optimalkan layout header, stats cards, & tabel dengan class yang konsisten
- Hapus class CSS redundan & perbaiki konsistensi penamaan
- Tingkatkan keamanan & UX dengan role-based access + struktur HTML lebih maintainable
2025-09-26 10:55:27 +07:00
Daeng Deni Mardaeni
e3540a1dd6 🔧 refactor(controller): perbaikan akses role & logika pembayaran NOC
- Tambah filter `branch_id` untuk role `pemohon-ao` & `pemohon-eo` di LaporanController, PembatalanController, dan PembayaranController
- Pastikan user hanya dapat mengakses data sesuai branch untuk mencegah data lintas cabang
- Perbaikan pencarian Bucok di NocController dengan tambahan kondisi `orWhere(permohonan_id)`
- Tambah null safety untuk update Bucok & akses relasi branch/debiture
- Filter untuk hindari duplikasi NOC yang sudah punya `memo_penyelesaian`
- Komentari kondisi approval kompleks di LaporanController sementara waktu
- Tambah penggunaan null safety operator (`?->`) & fallback tanggal ke `created_at` NOC
- Rapikan import: hapus unused imports, tambah `Auth` facade, perbaikan urutan
- Tambah handling data: `created_at` timestamp saat buat NOC, fallback value untuk tanggal Bucok, default value kosong untuk null safety
2025-09-26 10:52:20 +07:00
Daeng Deni Mardaeni
cd97d184ce 🔧 refactor(menu): reorganisasi struktur menu & perbaikan akses role
- Reorganisasi urutan menu, memindahkan "Laporan Penilaian Jaminan" ke posisi pertama & memperbaiki penamaan menu (SO, LPJ, Monitoring, Tender → Permohonan KJPP, dll.)
- Ubah path "laporan-penilaian-jaminan" menjadi "laporan" untuk konsistensi URL
- Pindahkan menu "Data Debitur" sebelum "Permohonan" & "Pembatalan" ke bawah dengan akses terbatas
- Perbaikan role permissions: hapus `admin` & `senior-officer` dari menu tertentu, tambahkan `penilai` & `surveyor` ke menu Penilaian
- Batasi akses menu "Pembatalan" hanya untuk `administrator` & `pemohon-ao`
- Update ActivityController: tambah role `penilai` pada filter user
- Update LaporanPermohonanController: filter status `done` agar hanya tampil permohonan selesai
- Update PermohonanController: hapus kondisi `jenis_penilaian_id` pada logika pembuatan PersetujuanPenawaran, gunakan `Auth::id()` konsisten
- Validasi DebitureRequest: ubah max karakter `nomor_rekening` dari 50 → 10, serta perbaikan indentasi & format JSON di `module.json`
2025-09-26 10:49:18 +07:00
Daeng Deni Mardaeni
929c56b079 feat(slik): tambah fitur export data SLIK ke Excel
- Tambah class `SlikExport` dengan implementasi Laravel Excel (WithMapping, WithHeadings, ColumnFormats, FromCollection)
- Method `collection()`, `map()`, `headings()`, `columnFormats()` untuk data mapping, header, dan formatting
- Format kolom: text untuk ID/kode, number untuk nilai agunan, date (d/m/Y) untuk tanggal
- Tambah method `export()` di `SlikController` dengan logging, error handling, dan filename timestamp
- Optimasi performa: chunking data, batch insert, memory monitoring (current & peak usage)
- Logging lengkap: start, jumlah records, success (filename & peak memory), error trace
- Integrasi route: GET `/slik/export` → `SlikController@export` (name: slik.export)
- Dependensi: gunakan `maatwebsite/excel`, pastikan package & write permission tersedia
- Dampak: export Excel lebih cepat, format user-friendly, audit trail lebih lengkap
2025-09-22 15:25:13 +07:00
Daeng Deni Mardaeni
388b65696f 🔧 refactor(permissions): pembersihan role & perbaikan UI form
- Hapus role `pemohon-ao` & `pemohon-eo` dari module.json pada semua menu (dashboard, laporan, permohonan, dsb.)
- Rapikan indentasi role `administrator` dan streamline permissions untuk akses kontrol yang lebih sederhana
- Tambahkan konsistensi role yang dipertahankan: administrator, admin, AO/EO Appraisal, DD Appraisal, Penilai, Surveyor
- Perbaiki class ordering pada input file & error message di `debitur.blade.php` agar sesuai konvensi Tailwind
- Perbaiki struktur div container di `debitur.blade.php` (`flex flex-wrap gap-2.5 items-baseline lg:flex-nowrap`)
- Perbaiki formatting input file & textarea pada `persetujuan_penawaran/form.blade.php` dengan multi-line untuk readability
- Rapikan class ordering error message di form penawaran (`text-sm alert text-danger`)
- Standarisasi formatting & konsistensi layout antar form untuk UX lebih rapi
2025-09-22 15:23:01 +07:00
Daeng Deni Mardaeni
ba9089e2ac 🔧 refactor(pembayaran): perbaikan struktur kode & integrasi Bucok dengan Permohonan
- Tambahkan validasi parameter `type` pada PembayaranController untuk mencegah error runtime
- Refactor nested conditions & perbaikan indentasi agar kode lebih readable dan maintainable
- Update model Bucok: tambah field `nomor_registrasi` & `permohonan_id` ke fillable serta relasi dengan Permohonan
- Integrasi logika pembayaran: auto update/create Bucok dengan data Permohonan & default nominal_bayar
- Implementasi conditional update berdasarkan ketersediaan nomor_tiket untuk sinkronisasi data
- Tambahkan migration baru: kolom nomor_registrasi & permohonan_id di tabel bucoks, dengan foreign key dan index
- Pastikan rollback migration tersedia via method down() untuk keamanan schema
- Optimasi query dengan index baru & penggunaan updateOrCreate untuk hindari duplikasi data
2025-09-22 11:35:07 +07:00
Daeng Deni Mardaeni
20d0061d42 feat(permohonan): auto-create PersetujuanPenawaran untuk jenis penilaian tertentu
- Import model PersetujuanPenawaran ke PermohonanController
- Tambah pengecekan jenis_penilaian_id == 1 setelah update permohonan
- Implementasi auto-create record PersetujuanPenawaran jika belum ada
- Simpan permohonan_id dan created_by (auth()->id()) pada record baru
- Gunakan where()->first() untuk cek existing record sebelum create
- Tambahkan logika di dalam try-catch agar konsisten dengan error handling
- Pastikan duplicate record dicegah untuk menjaga integritas data
- File dimodifikasi: app/Http/Controllers/PermohonanController.php
- Dampak: mempercepat workflow, kurangi manual input, tingkatkan konsistensi data
2025-09-22 10:46:58 +07:00
Daeng Deni Mardaeni
4bef7cdafd feat(laporan-admin-kredit): tambah kolom kolektibilitas & keterangan pada index dan export Excel
- Tambah kolom "Kolektibilitas" (min-w 150px) & "Keterangan" (min-w 200px) di tabel index laporan admin kredit
- Dukungan sorting & filtering pada kedua kolom baru dengan integrasi DataTable
- Implementasi truncation keterangan >50 karakter dengan suffix "..." dan fallback "-" jika kosong
- Responsive design di tabel index agar tetap readable di berbagai layar
- Mapping data export Excel ditambahkan field kolektibilitas & keterangan (posisi kolom N & O)
- Update heading Excel: tambah header "Kolektibilitas" & "Keterangan", geser "Created At" ke kolom P
- Tambah format Excel: FORMAT_TEXT untuk kolektibilitas & keterangan, FORMAT_DATE_DATETIME untuk created_at
- Dampak: informasi laporan admin kredit lebih lengkap, mendukung analisis kolektibilitas & dokumentasi tambahan
2025-09-22 09:12:52 +07:00
Daeng Deni Mardaeni
bf728972b5 (laporan-admin-kredit): tambah kolom keterangan & kolektibilitas
- Tambah field `keterangan` (TEXT) & `kolektibilitas` (VARCHAR 10) pada tabel laporan_admin_kredit
- Update model LaporanAdminKredit dengan fillable baru
- Tambah dropdown kolektibilitas (1-5: Lancar, DPK, Kurang Lancar, Diragukan, Macet) di form
- Tambah textarea keterangan dengan old() support untuk validasi
- Validasi: `keterangan` nullable|string, `kolektibilitas` nullable|string|in:1..5
- Update controller: simpan field baru dengan DB transaction & error handling
- Migration baru untuk menambah kolom `keterangan` & `kolektibilitas`
- UI/UX: konsistensi styling, responsive grid layout, placeholder informatif
- Testing: form simpan & validasi berhasil, migration jalan tanpa error
2025-09-22 09:12:42 +07:00
Daeng Deni Mardaeni
dfd2a82b42 🎨(view): Refaktor dan optimasi tampilan detail jaminan dengan perbaikan CSS & struktur kode
- Konsistensi urutan class CSS mengikuti standar Tailwind (layout → sizing → typography → colors)
- Perbaikan indentasi, spacing, whitespace, dan formatting string ("" → '')
- Penyusunan ulang struktur HTML dengan alignment & spacing yang lebih rapi
- Optimalisasi Blade template: perbaikan kondisi `@if (isset($penawaran))` & closing tag
- Standarisasi penggunaan grid layout dan urutan class grid (contoh: `grid grid-cols-1 gap-5 xl:grid-cols-2`)
- Konsistensi typography classes (`font-normal text-gray-700 text-2sm`) dan urutan color classes
- Refaktor struktur tabel: perbaikan class ordering, cell formatting, dan spacing kolom
- Penyusunan ulang komponen accordion dengan indentasi & struktur konten yang konsisten
- Konsistensi class pada tombol accordion & link structure untuk meningkatkan maintainability
2025-09-21 21:19:56 +07:00
Daeng Deni Mardaeni
c4bb3bea28 🔧(backend): Perbaikan & optimasi controller serta view untuk modul penilai dan surveyor
- PenilaiController: tambah eager loading relasi `penawaran` untuk kurangi N+1 query
- RegistrasiFinalController: ubah filter status dari `spk` → `registrasi-final`
- SurveyorController: perbaiki pengecekan jenisPenilaian dengan `in_array` (support External/Eksternal, case-insensitive)
- SurveyorController: ubah field `tanggal_laporan` → `tgl_final_laporan` sesuai DB baru
- SurveyorController: sanitasi koordinat lat/lon dengan menghapus koma untuk valid format
- SurveyorController: perbaiki exception handling (`Exeception` → `\Exception`, `$th` → `$e`, tambah namespace lengkap)
- SurveyorController: konsistensi penggunaan `Auth::user()` alih-alih `auth()->user()`
- View pembayaran/index.blade.php: tambahkan safe navigation `data.debiture?.name` untuk hindari null error
- View penilai/index.blade.php: cleanup baris kosong & perbaiki logika status pakai `data.penawaran?.status`
2025-09-21 21:17:19 +07:00
Daeng Deni Mardaeni
006dd44c64 🎨 refactor(form-penilai): rapikan struktur CSS dan formatting kode
- Reorder CSS class sesuai standar Tailwind (layout → sizing → styling)
- Perbaiki indentasi, spacing, dan line breaks untuk readability
- Ganti `else if` menjadi `elseif` pada PHP conditional
- Rapikan multi-line assignment pada nilai luas apartemen-kantor
- Update contoh class: `input w-full` → `w-full input`, `card-title uppercase` → `uppercase card-title`
- Rapikan class ordering pada container flex & grid
- Perbaiki class di button: `btn btn-primary btn-sm mt-5` → `mt-5 btn btn-primary btn-sm`
- Konsistensi class ordering di dynamic HTML generation (JavaScript)
- Fokus pada konsistensi visual tanpa mengubah tampilan UI
2025-09-19 10:18:30 +07:00
Daeng Deni Mardaeni
698935d06f 🔧 refactor(laporan): rapikan logika role pemohon-ao di index laporan
- Gabungkan blok kondisional @if pemohon-ao menjadi satu blok dengan else if
- Perbaiki struktur kode untuk menghindari error "Undefined constant data"
- Tambah komentar untuk memperjelas logika bisnis role-based
- Optimasi kondisi nilai_liquidasi dan status_bayar agar lebih efisien
- Rapikan line breaking dan indentasi parameter generateLaporanButton
- Hapus duplikasi logika pemohon-ao → kode lebih maintainable
- Pisahkan logika role pemohon-ao dan role lain agar lebih jelas
- Konsistensi formatting dan readability di Blade template
- Pastikan tombol laporan tampil sesuai role & kondisi tanpa error JS
2025-09-19 09:22:20 +07:00
Daeng Deni Mardaeni
564c7ccac4 🔧 refactor(laporan): perbaiki URL routing edit laporan admin kredit
- Ubah URL dari `laporan-admin-kredit/${data.id}/edit` → `admin-kredit/laporan/${data.id}/edit`
- Perbaiki konsistensi routing pattern agar sesuai dengan definisi route
- Pastikan tombol edit laporan admin kredit mengarah ke halaman edit yang benar
- Konsistensi routing mencegah error 404 dan meningkatkan UX
2025-09-19 09:17:01 +07:00
Daeng Deni Mardaeni
2b5556410d 🔧 refactor(laporan): kontrol akses role, optimasi query, dan perbaikan UI
- Tambah role `pemohon-ao` & `pemohon-eo` untuk upload lampiran di LampiranDokumen.php
- Implementasi kontrol akses role di lampiran-dokumen.blade.php & laporan/index.blade.php (logika khusus nilai_liquidasi)
- Modifikasi query di LaporanController.php: hapus filter approval_eo_at & optimasi kondisi WHERE
- Perbaikan formatting query dengan indentasi lebih rapi & maintainable
- Standardisasi urutan class CSS di beberapa Blade (activity/index, penilaian/otorisator/index-sla & index)
- Pisahkan logika generateLaporanButton jadi function terpisah di laporan/index.blade.php
- Perbaikan tampilan tombol laporan berbasis role + cleanup baris kosong & indentasi
- Konsistensi UI/UX: responsive design lebih baik, interface clean & styling konsisten dengan Tailwind
- Tingkatkan security & maintainability: granular role access, query lebih efisien, code lebih terstruktur
2025-09-19 09:10:06 +07:00
Daeng Deni Mardaeni
ee7c8ce97f 🔧 refactor(inspeksi): gunakan updateOrCreate & perbaikan kode
- Ganti `Inspeksi::create()` → `updateOrCreate()` di PenilaiController (2x) & SurveyorController (1x) dengan kondisi upsert (permohonan_id + dokument_id)
- Tambah logging di SaveFormInspesksiService.php (`Log::info`) untuk debugging & validasi action kosong
- Perbaiki error handling dengan pesan lebih informatif `'Gagal menyimpan data : '.$e->getMessage()`
- Refaktor parsing action memakai array_map & array_filter agar lebih efisien
- Rapikan kode: hapus baris kosong tidak perlu & improve readability
- Perbaiki urutan class CSS di beberapa Blade view (rap-penilai, penilai/index, surveyor/inspeksi)
- Perbaiki XSS di rap-penilai.blade.php dengan `{!! json_encode($dokumen->address ?? '') !!}`
- Tingkatkan integritas database: cegah duplikasi data inspeksi via updateOrCreate()
- Tambah keamanan & maintainability: logging, validasi input, perbaikan format, serta pembersihan kode lama
2025-09-19 09:06:12 +07:00
Daeng Deni Mardaeni
17f7482080 ♻️ refactor(js): pindahkan fungsi loading SweetAlert ke global scope dan perbaiki bug
- Memindahkan fungsi showLoadingSwal() dan hideLoadingSwal() ke resources/assets/js/app.js
- Menambahkan fitur timer dan progress bar pada fungsi global loading
- Menghapus duplikasi fungsi showLoadingSwal() dari penilai/index.blade.php (~18 baris)
- Menghapus duplikasi fungsi dari penilaian/otorisator/index-sla.blade.php (~18 baris)
- Menghapus duplikasi fungsi dari penilaian/otorisator/index.blade.php (~18 baris)
- Menghapus duplikasi fungsi dari penilaian/paparan-so.blade.php (~18 baris)
- Memperbaiki syntax error tag HTML di surveyor/components/informasi.blade.php
- Membersihkan duplikasi fungsi & memperbaiki escape string di surveyor/js/utils.blade.php
- Mengurangi ±90 baris kode duplikat, meningkatkan maintainability & UX (loading dialog lebih informatif)
2025-09-19 09:01:20 +07:00
Daeng Deni Mardaeni
6d137ad51c 🔧 refactor(laporan-slik): Perbaikan controller dan routing untuk laporan SLIK
- Mengubah nama method datatables menjadi dataForDatatables untuk konsistensi penamaan
- Menambahkan method show untuk menampilkan detail laporan SLIK individual
- Memperbaiki struktur response datatables dengan format yang lebih lengkap dan konsisten
- Menambahkan filter tambahan untuk sandi_bank dan kolektibilitas pada datatables
- Mengimplementasikan sorting dan pagination yang lebih robust
- Menambahkan error handling yang komprehensif dengan logging
- Memperbaiki transformasi data dengan penambahan field kolektibilitas_badge dan created_by
- Mengupdate routing untuk menambahkan route show laporan SLIK
- Menambahkan breadcrumb untuk halaman laporan SLIK dan detail
- Mengubah role akses dari 'noc' menjadi 'adk' pada module.json
- Memperbaiki format tanggal menggunakan helper dateFormat
- Menambahkan penanganan exception dengan fallback response yang proper
- Mengoptimalkan query dengan penambahan filter yang lebih spesifik
- Memperbaiki struktur response JSON untuk kompatibilitas dengan frontend datatables
2025-09-17 15:24:27 +07:00
Daeng Deni Mardaeni
6c004812a9 🎨 feat(slik): Implementasi fitur pindah data SLIK ke laporan dan perbaikan UI
- Menambahkan tombol "SLIK" pada halaman index dan show untuk memindahkan data ke laporan SLIK
- Mengimplementasikan fungsi moveToLaporan() dengan konfirmasi SweetAlert dan proses AJAX
- Melakukan migrasi framework CSS dari Bootstrap ke TailwindCSS pada laporan-slik/show.blade.php
- Memperbaiki struktur layout dengan grid system TailwindCSS yang responsif
- Mengupdate breadcrumbs dengan styling dan route names yang benar
- Menghapus fitur truncate data SLIK dari interface untuk keamanan data
- Memperbaiki route names dari admin-kredit.laporan-slik menjadi laporan-slik
- Mengoptimasi tombol Export dengan penghapusan parameter ID yang tidak diperlukan
- Menambahkan konfigurasi import SLIK di .env.example untuk optimasi performa
- Memperbaiki template download link dengan class styling yang konsisten
- Mengimplementasikan error handling yang komprehensif dengan user feedback
- Menambahkan auto-reload DataTable setelah operasi pemindahan data berhasil
- Melakukan redesign card layout dengan pembagian "Data Debitur" dan "Data Fasilitas"
- Menambahkan feedback visual dengan disable tombol setelah berhasil dipindahkan
- Mengoptimasi konfigurasi DataTable dengan reload functionality
- Menambahkan breadcrumb routes untuk laporan SLIK dengan struktur hierarki
- Mengimplementasikan progress tracking untuk monitoring proses import
- Memperbaiki JavaScript dengan pemisahan fungsi dan penambahan variabel global
- Menstandarisasi framework CSS untuk konsistensi visual
- Mengimplementasikan responsive design yang lebih baik
2025-09-17 15:19:28 +07:00
Daeng Deni Mardaeni
d932559849 feat(slik): implementasi fitur laporan SLIK dengan integrasi SweetAlert
- Menambahkan tombol aksi "Pindahkan ke Laporan SLIK" pada halaman index & detail
- Integrasi SweetAlert2 untuk konfirmasi, loading state, dan notifikasi sukses/gagal
- Implementasi auto-refresh DataTable setelah pemindahan berhasil
- Disable tombol otomatis setelah sukses untuk mencegah duplikasi data
- LaporanSlikController: method store() dengan transaksi DB & auto-delete dari tabel sliks
- Routing baru untuk index, datatables, store, dan export laporan SLIK
- Penyesuaian views (index & show) dengan tombol, script SweetAlert, dan feedback visual
- Proteksi keamanan: CSRF token, validasi input, transaksi DB, dan error logging
- Testing checklist: pindahkan data, refresh tabel, disable tombol, error handling, responsif mobile/desktop
2025-09-17 13:02:58 +07:00
Daeng Deni Mardaeni
c3c40fdc27 feat(laporan-slik): implementasi sistem laporan SLIK
- Menambahkan tabel `laporan_slik` (47 kolom, index, audit trail, status aktif/non-aktif)
- Membuat model `LaporanSlik` dengan fillable lengkap, relasi ke Slik & User, accessor agunan/status badge
- Menambahkan controller `LaporanSlikController` dengan method store(), datatables(), export()
- store(): validasi strict, cek duplikasi, copy data dari Slik ke laporan, hapus data asal
- datatables(): filter search/tahun/bulan/status, pagination, sorting, JSON response standar
- export(): ekspor Excel dengan filter sama, nama file otomatis timestamp, error handling
- Integrasi sistem: transaksi DB aman, logging detail, support bulk operations, memory optimisasi
- UX: SweetAlert, DataTable real-time, loading state, error message jelas, auto-reload
- Security & performa: validasi input, XSS & SQLi prevention, index optimization, siap rate limiting
2025-09-17 13:00:24 +07:00
Daeng Deni Mardaeni
41262e0317 feat(slik): migrasi route SLIK ke group admin-kredit
Mengubah struktur route SLIK agar sesuai dengan arsitektur admin-kredit dengan menambahkan prefix admin-kredit pada semua route.

- Menambahkan route SLIK lengkap dalam group admin-kredit di routes/web.php
- Memperbarui breadcrumb SLIK untuk menggunakan prefix admin-kredit di routes/breadcrumbs.php
- Memperbarui semua referensi route di view index.blade.php:
  * Breadcrumbs: slik → admin-kredit.slik
  * Route datatables: slik.datatables → admin-kredit.slik.datatables
  * Route import: slik.import → admin-kredit.slik.import
  * Route export: slik.export → admin-kredit.slik.export
  * Route download template: admin-kredit.slik.download-template
  * Route JavaScript: slik.show → admin-kredit.slik.show
- Memperbarui referensi route di view show.blade.php:
  * Breadcrumbs: slik → admin-kredit.slik.show
  * Tombol kembali: slik.index → admin-kredit.slik.index
- Menambahkan link download template Excel di modal import
2025-09-16 17:18:31 +07:00
Daeng Deni Mardaeni
2a1ecfd9e2 feat(slik): tambahkan fitur detail SLIK dengan tampilan responsive
Menambahkan fitur detail SLIK yang menampilkan informasi lengkap debitur dengan desain yang responsive dan user-friendly.
- Menambahkan kolom "Kolektibilitas" dan "Fasilitas" pada tabel DataTable
- Menghapus filter tahun, bulan, dan status yang tidak digunakan
- Menambahkan tombol "Detail" untuk setiap baris data
- Memperbaiki responsive design dengan CSS khusus untuk mobile
- Menambahkan class `min-w-[1200px]` untuk memastikan tabel dapat discroll horizontal
- Memperbarui konfigurasi DataTable untuk menampilkan kolom baru
- Menambahkan fungsi JavaScript `showDetail()` untuk redirect ke halaman detail
- Menghapus modal detail yang tidak digunakan lagi
- Memperbaiki styling dengan Tailwind CSS untuk konsistensi
- Membuat halaman detail baru dengan layout yang responsive
- Menampilkan informasi lengkap debitur dalam format card yang terorganisir
- Menggunakan grid layout 2 kolom untuk desktop dan 1 kolom untuk mobile
- Menampilkan data dalam kategori: Data Debitur, Data Fasilitas, dan Informasi Tambahan
- Menambahkan tombol kembali untuk navigasi mudah
- Menggunakan Tailwind CSS untuk styling yang konsisten dengan halaman index
- Responsive design yang optimal untuk semua ukuran layar
2025-09-16 16:24:32 +07:00
Daeng Deni Mardaeni
20833213b1 feat(slik): implementasi sistem import SLIK dengan optimasi memory & timeout handling
- Menambahkan `SlikController.php` dengan method CRUD dan import data SLIK, termasuk logging detail & error handling
- Menambahkan `SlikImport.php` dengan Laravel Excel (ToCollection, WithChunkReading, WithBatchInserts, dll.)
- Optimasi memory dengan chunk processing (50 baris/chunk) dan batch insert (50 record/batch)
- Penanganan timeout menggunakan `set_time_limit` & memory limit configurable via config
- Implementasi queue processing untuk file besar (>5MB) dengan progress tracking
- Validasi file upload & data baris, skip header dari baris ke-5, serta rollback jika error
- Garbage collection otomatis setiap 25 baris, unset variabel tidak terpakai, dan logging usage memory
- Error handling komprehensif dengan try-catch, rollback transaksi, hapus file temp, dan logging stack trace
- Semua parameter (batch size, chunk size, memory limit, timeout, GC, queue threshold) configurable via config
- Diuji pada file besar (>50MB), memory stabil, timeout handling berfungsi, rollback aman, dan progress tracking valid
- Catatan: pastikan queue worker berjalan, monitor log progress, sesuaikan config server, dan backup DB sebelum import
2025-09-16 11:54:39 +07:00
Daeng Deni Mardaeni
81159983cf 🔧 refactor(noc): Integrasi Bucok & pembersihan kode NocController
- Tambah import model Bucok di NocController
- Refactor method update(): hapus variabel & logic status usang
- Update otomatis Bucok setelah NOC disimpan (nominal, tanggal, status)
- Gunakan where()->first() untuk cari record Bucok berdasarkan nomor_tiket
- Hapus 26 baris komentar dead code & filter whereHas('noc') di penyelesaian()
- Perbaiki formatting, indentasi, dan tambah blank line untuk readability
- Gunakan fallback tanggal penyelesaian (date('Y-m-d')) jika kosong
- Terapkan null coalescing operator (??) untuk handle nilai null
- Sinkronisasi status penyelesaian NOC ↔️ Bucok & kode lebih bersih
2025-09-16 09:44:31 +07:00
Daeng Deni Mardaeni
bc35785c9c feat(pembayaran): Integrasi otomatis dengan Bucok saat persetujuan penawaran dibuat
- Tambah import model `Modules\Lpj\Models\Bucok` di PembayaranController
- Perbaiki spacing dan assignment `nomor_tiket` agar konsisten
- Simpan instance NOC ke variabel `$noc` setelah create
- Buat record Bucok otomatis dengan `updateOrCreate` berdasarkan nomor_tiket
- Mapping field tanggal (hari, bulan, tahun) menggunakan Carbon
- Isi default penyelesaian = 'Belum Selesai' dan mapping nominal ke Bucok
- Gunakan relasi `$noc->branch?->name` untuk nama sub_direktorat & cabang
- Implementasi safe navigation operator untuk hindari null error
- Pastikan konsistensi data & sinkronisasi pembayaran dengan Bucok
2025-09-16 09:36:45 +07:00
Daeng Deni Mardaeni
041ca943c9 feat(noc): Implementasi total nominal diterima pada halaman penyelesaian
- Hitung total nominal diterima dari semua data yang difilter (bukan hanya halaman aktif)
- Tambahkan field `totalNominalDiterima` pada response JSON DataTable
- Parsing string currency ke numeric value untuk perhitungan akurat
- Tampilkan total di footer tabel dengan format Rupiah (IDR)
- Integrasi real-time backend (NocController) dan frontend (Blade + JS)
- Update otomatis via event listener DataTable saat data berubah atau difilter
- Styling footer dengan TailwindCSS untuk highlight nominal
- Validasi dan fallback aman (0) bila data tidak tersedia
- Transparansi & efisiensi monitoring keuangan secara real-time
2025-09-15 15:39:00 +07:00
Daeng Deni Mardaeni
312861a933 feat(noc): implementasi perhitungan total nominal diterima pada pembayaran
- Hitung total nominal diterima dari semua data yang difilter (bukan hanya halaman aktif)
- Tampilkan total dalam format currency Indonesia (IDR) di footer tabel
- Integrasi backend (NocController) dan frontend (Blade + JS) secara real-time
- Update otomatis via event listener DataTable saat data berubah atau difilter
- Validasi dan parsing currency string dengan aman, casting ke float untuk akurasi
- Tambahkan field totalNominalDiterima pada response JSON DataTable
- Footer tabel dengan styling TailwindCSS (text-green-600, font-bold) untuk highlight
- UX lebih transparan: user langsung melihat total pembayaran yang diterima
- Performa terjaga: minimal DOM manipulation, native Intl.NumberFormat, efisien pada filter
2025-09-15 15:30:16 +07:00
Daeng Deni Mardaeni
96657de512 feat(api,noc): Tambah API pencarian debitur dan perbaikan filter jenis penilaian
- API Debitur Controller: method search() (min 2 karakter), getByCode(), transaksi DB, logging, response JSON konsisten
- Batasi hasil pencarian maksimal 20 item untuk performa optimal
- Support pencarian berdasarkan CIF dan nama debitur
- Tambah import JenisPenilaian di NocController
- Perbaiki method penyelesaian() untuk mengirim data jenisPenilaians ke view
- Tambahkan filter nama jenis penilaian di dataForDatatablesPenyelesaian() dan kolom jenis_penilaian pada response tabel
- Update UI view penyelesaian: dropdown dinamis, kolom sortable, integrasi DataTable, perbaikan layout
- Validasi input & keamanan: transaction handling, logging, conditional debug response, SQL injection protection
- Peningkatan UX: autocomplete search, filter responsif, pesan error informatif, loading state, format response konsisten
2025-09-15 14:46:29 +07:00
Daeng Deni Mardaeni
4ad11593d5 feat(noc): Tambahkan filter jenis penilaian pada halaman pembayaran NOC
Fitur baru ini menambahkan kemampuan filter berdasarkan jenis penilaian pada halaman pembayaran NOC dengan integrasi penuh ke DataTable dan database. Perubahan meliputi:
- Penambahan query jenis penilaian aktif di controller
- Filter whereRelation pada `dataForDatatablesPembayaran()`
- Dropdown dinamis jenis penilaian di view pembayaran
- Event listener JavaScript untuk filter real-time
- Opsi reset "Semua Jenis Penilaian"
- Validasi input client & server dengan XSS protection
- Optimasi query dengan relasi `permohonan.jenisPenilaian`
- Tampilan UI responsive dan konsisten dengan desain existing
- Peningkatan UX untuk pencarian data pembayaran lebih akurat dan efisien
2025-09-15 14:40:40 +07:00
Daeng Deni Mardaeni
d851ab58bc 🔧 fix(noc): Perbaiki validasi dan logika NOC untuk mendukung pembayaran tanpa permohonan
- Ubah validasi permohonan_id dari required menjadi nullable di NocRequest
- Hapus pesan error required untuk permohonan_id di validation messages
- Tambahkan logika kondisional di NocController->store() untuk updateOrCreate berdasarkan keberadaan permohonan_id
- Perbaiki null safety dengan operator ?-> di form.blade.php untuk akses nested properties
- Update logika status pembayar untuk mendukung pembayaran dengan nomor_tiket
- Tambahkan kondisi khusus untuk menentukan status bayar berdasarkan nomor_tiket
- Perbaiki formatting dan spacing di controller untuk readability
2025-09-15 13:58:40 +07:00
Daeng Deni Mardaeni
c08e050815 feat: Tambah kolom nomor tiket dan perbaiki null safety NOC
- Tambahkan kolom 'nomor_tiket' di tabel NOC (index, pembayaran, penyelesaian)
- Perbaiki null safety dengan operator ?-> untuk mencegah error
- Update model Noc: ganti fillable dengan guarded, tambah relasi debiture & branch
- Hapus filter whereDoesntHave untuk memo_penyelesaian (commented out)
- Tambah fallback data dari noc->debiture dan noc->branch
- Perbaiki sorting dengan ->values() untuk reset array keys
- Update view pembayaran.blade.php dengan kolom nomor tiket
2025-09-15 12:52:14 +07:00
Daeng Deni Mardaeni
4aeecf6a97 (pembayaran): Implementasi fitur create pembayaran baru dengan autocomplete debitur
- Menambahkan method create() di PembayaranController untuk menampilkan form pembayaran baru
- Menambahkan logika create pembayaran di method store() dengan validasi type 'create'
- Menambahkan penyimpanan data pembayaran baru ke tabel persetujuan_penawaran dan noc
- Menambahkan upload bukti bayar dengan penyimpanan ke storage public
- Menambahkan migration untuk kolom branch_id di tabel noc
- Menambahkan view create.blade.php dengan form pembayaran lengkap dan autocomplete debitur
- Menambahkan validasi JavaScript untuk format file dan ukuran maksimal 2MB
- Menambahkan TomSelect untuk pencarian debitur dengan AJAX real-time
- Menambahkan integrasi dengan API debitur search untuk autocomplete
- Memperbaiki method edit() untuk mendukung parameter tiket dalam pencarian persetujuan penawaran
- Mengubah query dataForDatatables untuk mendukung data dari persetujuan_penawaran dan permohonan
- Menambahkan mapping data yang fleksibel untuk menampilkan informasi dari berbagai sumber
- Menambahkan field nomor_tiket, nominal_bayar, dan catatan pada form create
- Menambahkan validasi client-side untuk memastikan file upload sesuai format
- Menambahkan relasi branch_id pada tabel noc untuk tracking cabang pembuat
- Menambahkan redirect ke pembayaran.index setelah berhasil menyimpan pembayaran baru
- Menambahkan import PhpParser\Node\Expr\Cast\Object_ (perlu dibersihkan)
- Mengoptimalkan query dengan eager loading dan mapping data yang efisien
- Menambahkan support untuk pembayaran tanpa permohonan (standalone payment)
- Menambahkan field is_permohonan untuk membedakan jenis pembayaran
- Menambahkan validasi dan error handling yang komprehensif
2025-09-15 11:32:59 +07:00
Daeng Deni Mardaeni
1caa7ebfdd (pembayaran): Implementasi fitur pengembalian lebih bayar
- Menambahkan method editLebih() di PembayaranController untuk menampilkan form pengembalian lebih bayar
- Menambahkan logika pengembalian lebih bayar di method store() dengan validasi type 'lebih_bayar'
- Menambahkan penyimpanan bukti KSL lebih bayar dengan upload file ke storage
- Menambahkan update bukti KSL ke tabel noc untuk pengembalian lebih bayar
- Menambahkan filter bukti_ksl_lebih_bayar null pada query dataForDatatablesLebih untuk menampilkan data yang belum diproses
- Menambahkan validasi file upload untuk bukti_ksl_lebih_bayar dengan format pdf,jpg,jpeg,png maksimal 2MB
- Menambahkan view form-lebih.blade.php dengan tampilan detail pembayaran dan form pengembalian
- Menambahkan validasi JavaScript untuk memastikan format dan ukuran file yang diupload
- Menambahkan route pembayaran/{pembayaran}/lebih untuk mengakses form pengembalian lebih bayar
- Mengubah link action di lebih.blade.php dari edit ke lebih untuk mengarahkan ke form pengembalian
- Menambahkan redirect ke pembayaran.lebih.index setelah berhasil menyimpan pengembalian
- Menambahkan field catatan opsional untuk memberikan keterangan tambahan pada proses pengembalian
- Menambahkan validasi client-side untuk memastikan file yang diupload sesuai format dan ukuran
- Menambahkan informasi detail pembayaran yang komprehensif di form pengembalian
- Menambahkan styling yang konsisten dengan form kurang bayar untuk user experience yang baik
2025-09-15 08:08:10 +07:00
Daeng Deni Mardaeni
8666a0c58b (pembayaran): Implementasi fitur pelunasan kurang bayar
- Menambahkan method editKurang() di PembayaranController untuk menampilkan form pelunasan kurang bayar
- Menambahkan logika pelunasan kurang bayar di method store() dengan validasi type 'kurang_bayar'
- Menambahkan penyimpanan bukti KSL kurang bayar dengan upload file ke storage
- Menambahkan update nominal pelunasan dan bukti KSL ke tabel noc dan persetujuan_penawaran
- Menambahkan filter bukti_ksl_kurang_bayar null pada query dataForDatatablesKurang untuk menampilkan data yang belum dilunasi
- Menambahkan validasi file upload untuk bukti_ksl_kurang_bayar dengan format pdf,doc,docx maksimal 10MB
- Menambahkan kolom nominal_pelunasan dan debiture_id pada migration persetujuan_penawaran
- Menambahkan view form-kurang.blade.php dengan tampilan detail pembayaran dan form pelunasan
- Menambahkan validasi JavaScript untuk memastikan nominal pelunasan tidak melebihi nominal kurang bayar
- Menambahkan route pembayaran/{pembayaran}/kurang untuk mengakses form pelunasan kurang bayar
- Mengubah link action di kurang.blade.php dari edit ke kurang untuk mengarahkan ke form pelunasan
- Menambahkan redirect ke pembayaran.kurang.index setelah berhasil menyimpan pelunasan
- Menambahkan rollback migration untuk menghapus kolom yang ditambahkan jika diperlukan
2025-09-15 08:04:49 +07:00
Daeng Deni Mardaeni
99bc711954 🐛 fix(otorisasipenawaran): perbaiki route generation dengan parameter kosong
- Ganti parameter kosong ('') dengan placeholder ':id' pada route helper
- Implementasi JavaScript replace() untuk substitusi parameter dinamis
- Perbaiki fungsi otorisasiPenawaranKJPP di editextjs.blade.php
- Meningkatkan keamanan dan konsistensi route generation
- Menghindari error Laravel route dengan parameter kosong
- Kompatibel dengan Laravel route caching mechanism
- Menjaga konsistensi dengan perbaikan pada modul prosespenawaran
2025-09-13 11:54:35 +07:00
Daeng Deni Mardaeni
627d7f9b40 🐛 fix(prosespenawaran): perbaiki route generation dengan parameter kosong
- Ganti parameter kosong ('') dengan placeholder ':id' pada route helper
- Implementasi JavaScript replace() untuk substitusi parameter dinamis
- Perbaiki fungsi updateulang dan updateKJPPStatus di editeulangxtjs.blade.php
- Meningkatkan keamanan dan konsistensi route generation
- Menghindari error Laravel route dengan parameter kosong
- Kompatibel dengan Laravel route caching mechanism
2025-09-13 11:54:17 +07:00
Daeng Deni Mardaeni
8a5bf21982 feat(pembayaran): implementasi pembayaran kurang & lebih bayar dengan role management
- Tambah method kurang() & lebih() di PembayaranController untuk halaman khusus
- Implementasi dataForDatatablesKurang() & dataForDatatablesLebih() untuk listing data
- Optimasi query dengan filter status + mapping nominal ke format rupiah
- Cleanup code: hapus import & komentar tidak dipakai, rapikan indentasi
- Update module.json: ubah akses menu pembayaran ke "pemohon-ao", tambahkan role "admin" untuk menu NOC
- Tambah route pembayaran/datatables-kurang & pembayaran/datatables-lebih di routes/registrasi.php
- Filtering & sorting data konsisten dengan pagination DataTables
- Format tampilan data finansial distandarisasi (rupiah 2 desimal)
2025-09-12 10:17:42 +07:00
Daeng Deni Mardaeni
2433aacfbc feat(noc): implementasi sistem pembayaran dengan tracking nomor tiket dan status kurang/lebih bayar
- Tambah field `nomor_tiket`, `nominal_kurang_bayar`, `bukti_ksl_kurang_bayar`, `nomor_rekening_lebih_bayar`, `bukti_ksl_lebih_bayar` di tabel `persetujuan_penawaran` & `noc`
- Update model `Noc` & `PersetujuanPenawaran` dengan fillable baru + migrasi database
- Update validasi di `NocRequest` & `PersetujuanPenawaranRequest` (nomor tiket, bukti KSL, kurang bayar, string max length)
- Restructure menu pembayaran dengan submenu *Kurang Bayar* & *Lebih Bayar*
- Tambah kolom "Nomor Tiket" di tabel & DataTable pembayaran
- Perbaikan tampilan: formatting, CSS, responsive layout, display cabang (code - name)
- Tambah routes `pembayaran.kurang.index` & `pembayaran.lebih.index` + integrasi controller
- Update `module.json` untuk menu, permission, roles, icon, dan styling
2025-09-12 09:23:13 +07:00
Daeng Deni Mardaeni
ba29f5ee8e feat(noc): implementasi logika conditional checkbox status pembayaran
- Menambahkan fungsi `updateCheckboxStatus()` untuk evaluasi kondisi real-time.
- Checkbox otomatis disabled jika total_harus_bayar = nominal_bayar = total_pembukuan.
- Checkbox **status_kurang_bayar** aktif jika nominal/pembukuan < total_harus_bayar.
- Checkbox **status_lebih_bayar** aktif jika nominal/pembukuan > total_harus_bayar.
- Menambahkan event listeners pada field nominal_bayar dan total_pembukuan.
- Memastikan initial state dicek saat halaman dimuat.
- Menambahkan logging untuk debugging dan monitoring.
- Meningkatkan UX dengan mencegah input data tidak logis.
2025-09-12 08:56:01 +07:00
Daeng Deni Mardaeni
eb784a982f feat(pembayaran): tambah field nomor tiket dan perbaiki formatting form
- Menambahkan field input **nomor_tiket** setelah `nomor_registrasi` untuk konsistensi.
- Menambahkan validasi dan error handling khusus untuk field **nomor_tiket**.
- Memperbaiki struktur form dengan indentasi dan penamaan konsisten.
- Mengoptimalkan penggunaan **TailwindCSS** untuk responsivitas dan maintainability.
- Menambahkan placeholder **"Nomor Tiket"** untuk meningkatkan UX.
- Menggunakan **old()** atau data permohonan sebagai value default.
- Memperbaiki error styling, spacing, dan alignment untuk tampilan form yang rapi.
2025-09-11 22:18:46 +07:00
Daeng Deni Mardaeni
2173a36564 feat & 🐛 fix(persetujuan-penawaran): Tambah field nomor_tiket dan perbaiki namespace serta relasi model
###  Fitur Baru
- Menambahkan field `nomor_tiket` pada model **PersetujuanPenawaran** ke dalam `$fillable`.
- Membuat migration untuk menambahkan kolom `nomor_tiket` (VARCHAR 100, nullable) di tabel `persetujuan_penawaran`.
- Menambahkan validasi dan custom error messages untuk field `nomor_tiket` pada **PersetujuanPenawaranRequest**.
- Menempatkan `nomor_tiket` setelah `nomor_proposal_penawaran` untuk konsistensi.
- Implementasi rollback pada migration untuk menjaga keamanan database.
- Menambahkan komentar dokumentasi pada migration untuk mempermudah maintenance.
- Validation rules: `nullable|string|max:100` dengan pesan error dalam Bahasa Indonesia.
- Field ini mendukung tracking dan identifikasi tiket setiap persetujuan penawaran.
- Mengikuti pola dan konvensi sistem yang sudah ada agar konsisten.

### 🐛 Perbaikan Bug
- Memperbaiki typo namespace dari **Usermanagemenet** menjadi **Usermanagement**.
- Menghapus import **Region** yang tidak ada di codebase.
- Menghapus relasi `region()` karena model **Region** tidak ditemukan.
- Mempertahankan relasi valid seperti `penawaran`, `permohonan`, `authorizedBy`, dan `noc`.
- Menyelesaikan error *"Undefined type"* pada baris 53 dan 59.
- Membersihkan kode dengan menghapus dependency yang tidak ada.
- Menyesuaikan namespace **User** agar konsisten dengan struktur modul **Usermanagement**.
- Model kini lebih stabil, bersih, dan bebas dari error diagnostic.
2025-09-11 22:03:58 +07:00
Daeng Deni Mardaeni
ee079a8aa8 🔧 fix(surveyor): perbaiki fungsi calculateTotalLuas untuk mendukung format koma desimal
- Menambahkan logika menghapus format ribuan (titik) sebelum perhitungan luas.
- Mengonversi koma menjadi titik untuk parsing **float** dengan benar.
- Menggunakan **toLocaleString('id-ID')** untuk hasil sesuai format Indonesia.
- Mendukung input angka dengan format Indonesia dan internasional.
2025-09-11 09:44:35 +07:00
Daeng Deni Mardaeni
b4aba1a02a 🔧 fix(noc): Perbaiki validasi field opsional dan kondisi query memo
- Menambahkan **null coalescing operator** pada field `catatan_noc` agar tidak error bila kosong.
- Mengubah default field status pembayaran NOC menjadi string `'0'` untuk konsistensi.
- Menonaktifkan validasi approval di `MemoController` agar semua data NOC dapat tampil.
- Mencegah error validasi ketika field opsional tidak diisi pada form.
- Memastikan tampilan memo lebih lengkap tanpa batasan kondisi approval.
2025-09-11 09:43:50 +07:00
Daeng Deni Mardaeni
32baffe636 feat(bucok)!: tambah modul Bucok end-to-end + impor updateOrCreate
- Tambah routing, breadcrumbs, menu, dan views (index + detail)
- Controller: index/show, datatables (filter multi-kolom, sorting, pagination), impor Excel (transaksi + logging)
- Import: updateOrCreate by nomor_tiket, normalisasi tanggal & numerik, statistik impor
- Migrasi: semua kolom bisnis → string untuk konsistensi input Excel; nomor_tiket unique + index
- UX: DataTable dengan filter (tahun, bulan, cost center, status), tombol import, detail tiket

BREAKING CHANGE:
- Semua kolom bisnis kini bertipe string → perlu sesuaikan casts di model Bucok & filter tanggal/numerik di controller
2025-08-19 11:30:19 +07:00
Daeng Deni Mardaeni
19fb39b02f feat(noc): implementasi mutual exclusive selection untuk status kurang dan lebih bayar
- Menambahkan JavaScript untuk mutual exclusive selection antara status kurang bayar dan lebih bayar
- Hanya satu status yang bisa dipilih pada satu waktu untuk mencegah konflik data
- Implementasi fungsi resetFields() untuk membersihkan field yang tidak dipilih
- Menambahkan event handler untuk toggle visibility field berdasarkan pilihan status
- Menambahkan logging untuk tracking perubahan status pembayaran
- Field nominal dan bukti pengembalian otomatis direset ketika status berubah
- Mempertahankan UI existing dengan checkbox namun menambahkan logika mutual exclusive
- Menambahkan validasi client-side untuk mencegah input data yang tidak konsisten
- Support untuk readonly mode ketika memo penyelesaian sudah ada
- Implementasi function-level comments untuk dokumentasi kode
2025-07-31 13:24:18 +07:00
Daeng Deni Mardaeni
bc7fef05f6 feat(noc): tambah field total pembukuan dan perbaiki label form
Menambahkan field total_pembukuan ke dalam sistem NOC untuk mendukung pencatatan pembukuan yang lebih akurat.

Perubahan yang dilakukan:
- Menambahkan migration untuk field total_pembukuan di tabel noc dengan tipe decimal(10,2)
- Menambahkan total_pembukuan ke dalam fillable array di model Noc
- Mengintegrasikan field total_pembukuan ke dalam NocController untuk proses store dan update
- Menambahkan input field "Jumlah Pembukuan" di form NOC dengan validasi error handling
- Mengubah label "Nominal Bayar" menjadi "Jumlah Yang Harus Disetor" untuk kejelasan
- Mengubah label "Nominal Diterima" menjadi "Jumlah Yang Disetor" untuk konsistensi
- Mengubah title menu dari "Pembayaran" menjadi "Pembukuan" di module.json
- Menambahkan readonly attribute pada field total_pembukuan ketika sudah ada memo
- Mengimplementasikan old() helper untuk mempertahankan nilai input saat validation error
- Menambahkan placeholder text "Masukkan total pembukuan" untuk user guidance
2025-07-30 11:17:10 +07:00
Daeng Deni Mardaeni
4d8b72e33a fix datatable noc 2025-07-22 09:09:19 +07:00
Daeng Deni Mardaeni
cf0059fe66 feat(memo): implementasi jenis penilaian dinamis dan perbaikan checkbox pada memo penyelesaian
Perubahan yang dilakukan:
- Menghapus validasi input pada method `preview()` untuk mendukung fleksibilitas data preview
- Mengganti eager loading dari `tujuanPenilaian` menjadi `jenisPenilaian` agar sesuai dengan kebutuhan data dinamis
- Menambahkan method chaining `->get()` pada akhir query untuk memastikan eksekusi query yang benar
- Menambahkan field `jenisPenilaian` ke dalam memoData agar template dapat menampilkan instruksi pembayaran secara dinamis
- Mengimplementasikan checkbox visual yang disabled dengan hidden input untuk tetap mengirim data saat form submit
- Memisahkan antara checkbox untuk tampilan (disabled) dan input data (hidden) untuk meningkatkan UX
- Mengubah lebar label dari 80px menjadi 200px pada template PDF dan preview untuk layout yang lebih baik
- Mengganti informasi jaminan menjadi statis "Tanah & Bangunan" pada template PDF dan preview
- Menambahkan conditional rendering untuk menampilkan instruksi pembayaran sesuai dengan jenis penilaian (Internal/KJPP)
- Menyesuaikan layout dan formatting pada template PDF dan preview agar lebih konsisten secara visual
- Menambahkan logika text dinamis untuk jenis penilaian pada bagian instruksi pembayaran
- Mengoptimalkan struktur query agar lebih efisien dan menghindari duplikasi

Tujuan perubahan:
- Mendukung proses memo penyelesaian dengan jenis penilaian yang lebih fleksibel (Internal/KJPP)
- Meningkatkan pengalaman pengguna dengan tampilan checkbox yang jelas namun tetap menyimpan data dengan aman
- Menyederhanakan layout dan formatting agar lebih profesional dan konsisten di preview maupun PDF
- Memastikan proses generate memo berjalan sesuai kebutuhan bisnis dengan instruksi pembayaran yang tepat
2025-07-17 16:05:56 +07:00
Daeng Deni Mardaeni
d7e5df569a feat(memo): tambah filter jenis penilaian dan perbaiki fungsi clear checkbox pada datatable memo
Perubahan yang dilakukan:
- Menambahkan dropdown filter "Jenis Penilaian" (Internal/External) pada halaman index memo penyelesaian
- Mengimplementasikan filter gabungan menggunakan separator '|' untuk kombinasi filter dan search
- Memperbaiki fungsi clearSelectedCheckboxes dengan selector '#memo-table thead input[type="checkbox"]' agar lebih spesifik
- Menambahkan event listener untuk filter jenis penilaian yang terintegrasi dengan fungsi search datatable
- Mengupdate MemoController untuk memisahkan parameter filter menjadi jenis penilaian dan search term menggunakan explode('|')
- Menambahkan log untuk debugging filter dan proses checkbox
- Memodifikasi tampilan dengan class `gap-2` pada container filter untuk spacing yang lebih baik
- Menambahkan console.log pada fungsi handleCheckboxChange untuk tracking interaksi user
- Memperbaiki error handling pada fungsi clearSelectedCheckboxes untuk memastikan checkbox ter-reset dengan benar
- Menampilkan jumlah item terpilih pada tombol "Create Memo" untuk meningkatkan feedback user

Tujuan perubahan:
- Mempermudah pengguna dalam memfilter data berdasarkan jenis penilaian langsung di datatable memo
- Memastikan fungsi checkbox selection berjalan dengan konsisten dan lebih robust
- Meningkatkan user experience dengan feedback visual yang lebih jelas saat filter dan selection digunakan
- Menyederhanakan interaksi user sekaligus menjaga akurasi proses pembuatan memo penyelesaian
2025-07-17 15:16:58 +07:00
Daeng Deni Mardaeni
cd46a3b0dc feat(memo): tambahkan kembali checkbox selection dengan status disabled
Perubahan yang dilakukan:
- Menambahkan kembali kolom checkbox "select-all" di header tabel dengan atribut disabled
- Menambahkan kembali input checkbox di setiap baris permohonan dengan status disabled
- Menjaga struktur tabel tetap konsisten dengan design system yang ada
- Mempertahankan value checkbox untuk kebutuhan form submission meskipun tidak interaktif
- Menggunakan class `checkbox-sm` untuk ukuran checkbox yang sesuai tampilan

Tujuan perubahan:
- Memberikan indikasi visual bahwa semua permohonan dianggap sudah terpilih secara otomatis
- Memastikan user memahami bahwa selection tidak perlu dilakukan secara manual
- Meningkatkan konsistensi UI sekaligus menjaga flow proses pembuatan memo penyelesaian
- Menyederhanakan interaksi user dengan feedback visual yang jelas tanpa menghilangkan elemen penting
2025-07-17 14:49:09 +07:00
Daeng Deni Mardaeni
3486b97aee refactor(memo): hapus checkbox selection
Perubahan yang dilakukan:
- Menghapus kolom checkbox "select-all" dari header tabel pada halaman create memo penyelesaian
- Menghapus input checkbox di setiap baris permohonan dalam tabel untuk menghilangkan fitur selection
- Menyederhanakan tampilan tabel menjadi daftar permohonan tanpa opsi pilih banyak
- Memperbaiki user experience dengan interface yang lebih bersih dan sederhana
- Mengurangi kompleksitas form dengan menghilangkan proses multiple selection
2025-07-17 14:44:00 +07:00
Daeng Deni Mardaeni
dc6e326122 refactor(memo): perbaiki indentasi dan komentar sementara filter NOC
Perubahan yang dilakukan:
- Memperbaiki indentasi pada loop foreach untuk update NOC dan permohonan agar lebih readable
- Mengomentari sementara kondisi whereHas('noc') pada dataForDatatables untuk keperluan pengujian
- Merapikan struktur kode pada method storeMemopenyelesaian agar lebih konsisten dan mudah dipahami
- Menambahkan konsistensi formatting pada blok kode update NOC untuk meningkatkan maintainability
- Memastikan logging tetap aktif untuk kebutuhan audit dan tracking perubahan data
- Menjaga integritas proses dengan tetap menggunakan database transaction (commit/rollback)

Tujuan perubahan:
- Meningkatkan keterbacaan dan konsistensi kode di MemoController
- Mempermudah proses debugging dan pengujian dengan menonaktifkan filter NOC sementara
- Memastikan struktur kode tetap rapih dan mudah dikelola tanpa mengubah logika bisnis utama
2025-07-17 14:28:21 +07:00
Daeng Deni Mardaeni
4459b70271 feat(memo): tambah tombol download PDF dan disable checkbox untuk memo selesai
- Menambahkan field memo_penyelesaian_pdf_path ke tabel noc untuk menyimpan path file PDF
- Membuat migrasi baru untuk menambahkan field PDF path ke tabel noc
- Menambahkan field memo_penyelesaian_pdf_path ke model Noc dalam fillable array
- Memodifikasi fungsi generatePdf di MemoController untuk menyimpan path PDF ke database
- Menambahkan route baru memo.download-pdf untuk download file PDF memo penyelesaian
- Membuat method downloadPdf di MemoController dengan validasi file dan error handling
- Memodifikasi kolom select di datatables untuk disable checkbox jika sudah ada memo
- Menambahkan tooltip pada checkbox yang disabled untuk memberikan informasi kepada user
- Memodifikasi kolom actions untuk menampilkan tombol download PDF jika memo sudah ada
- Menampilkan informasi nomor memo dan tanggal memo di kolom actions
- Memodifikasi fungsi handleCheckboxChange untuk mengabaikan checkbox yang disabled
- Menambahkan styling untuk tombol download dengan icon dan warna yang sesuai
- Menambahkan logging untuk tracking aktivitas download PDF memo penyelesaian
- Menambahkan validasi keberadaan file di storage sebelum mengizinkan download
- Menggunakan Storage facade untuk operasi file yang lebih aman dan konsisten
2025-07-17 13:47:53 +07:00
Daeng Deni Mardaeni
57dece449c feat(memo): filter datatables hanya tampilkan permohonan dengan NOC
Menambahkan filter pada datatables memo penyelesaian agar hanya menampilkan permohonan yang sudah memiliki NOC.

Perubahan yang dilakukan:
- Menambahkan kondisi whereHas('noc') pada query dataForDatatables
  - Memastikan hanya permohonan dengan relasi NOC yang ditampilkan
  - Filtering dilakukan langsung di level database untuk efisiensi
  - Konsisten dengan logika bisnis memo penyelesaian

- Update MemoController:
  - Memodifikasi fungsi dataForDatatables di baris 184-193
  - Menambahkan ->whereHas('noc') setelah kondisi filter existing
  - Mempertahankan semua parameter request dan struktur response yang sudah ada
  - Logging tetap aktif untuk kebutuhan audit dan monitoring

Tujuan perubahan:
- Menjamin konsistensi proses memo penyelesaian hanya pada permohonan yang sudah memiliki NOC
- Menghindari proses memo pada data yang belum lengkap
- Menjaga data integrity dengan relasi yang lebih jelas antara permohonan dan NOC
- Meningkatkan efisiensi query dengan filtering langsung di database
2025-07-17 13:21:41 +07:00
Daeng Deni Mardaeni
5e7368ebcf feat(memo): tambah field memo penyelesaian ke tabel NOC dan update generatePdf
Menambahkan penyimpanan data memo penyelesaian ke tabel NOC dan memperbarui fungsi generatePdf di MemoController agar lebih terintegrasi.

Perubahan yang dilakukan:
- Menambahkan migrasi untuk field baru di tabel NOC:
  - memo_penyelesaian_number: nomor memo penyelesaian
  - memo_penyelesaian_date: tanggal memo
  - memo_penyelesaian_payment_date: tanggal pembayaran
  - memo_penyelesaian_pdf_path: path file PDF memo
  - memo_penyelesaian_created_at: timestamp pembuatan memo

- Update model NOC:
  - Menambahkan field baru ke $fillable array untuk mass assignment
  - Menambahkan casting untuk field date dan datetime agar otomatis diconvert oleh Eloquent
  - Mempertahankan struktur model dan relasi yang sudah ada

- Update MemoController:
  - Mengubah proses penyimpanan memo dari tabel permohonan ke tabel NOC
  - Menambahkan pencarian NOC berdasarkan permohonan_id
  - Menyimpan semua informasi memo penyelesaian langsung ke NOC
  - Tetap memperbarui status permohonan agar proses bisnis tetap berjalan
  - Menambahkan logging untuk mempermudah monitoring dan debugging
  - Menggunakan DB transaction untuk menjaga konsistensi data

Struktur data memo penyelesaian:
- Disimpan secara terpusat di tabel NOC sebagai source of truth
- Memiliki relasi langsung dengan tabel permohonan untuk referensi data
- Menyimpan path PDF memo untuk akses file yang lebih mudah
- Menyediakan timestamp lengkap untuk kebutuhan audit trail

Tujuan perubahan:
- Memusatkan data memo penyelesaian di tabel NOC untuk kemudahan query dan reporting
- Menjamin konsistensi data dengan mekanisme transaction
- Memperjelas struktur relasi antara memo penyelesaian dan permohonan
- Memudahkan proses tracking, pelaporan, dan audit memo penyelesaian
2025-07-17 13:03:32 +07:00
Daeng Deni Mardaeni
cbdd4bd99e fix(memo): Sinkronisasi layout PDF memo dengan preview dan perbaikan section tanda tangan
Melakukan sinkronisasi tampilan memo penyelesaian antara preview dan PDF serta memperbaiki struktur layout bagian tanda tangan untuk kompatibilitas PDF.

Perubahan yang dilakukan:
- Menyesuaikan header dan logo dengan ukuran yang sama (53.55px) untuk preview dan PDF.
- Mengubah judul memo menjadi "Memo Instruksi Penyelesaian Rekening Escrow / KSL Penilai Jaminan".
- Menyesuaikan informasi memo (Kepada, Dari, Perihal) agar konsisten antara preview dan PDF.
- Menggunakan format tabel yang konsisten untuk detail memo dan lampiran.
- Menambahkan daftar lampiran dengan kolom Nomor Registrasi dan AO sesuai format preview.
- Mengimplementasikan fungsi `terbilang()` untuk konversi angka ke teks dalam lampiran.
- Menyesuaikan font size, spacing, dan styling agar seragam di semua output.
- Menambahkan page break yang presisi antara halaman memo utama dan lampiran.

Perbaikan section tanda tangan:
- Mengganti struktur flexbox dengan table layout pada bagian tanda tangan untuk stabilitas PDF.
- Menggunakan 3 kolom dengan lebar 33.33% untuk pembagian tanda tangan yang rata.
- Menambahkan `vertical-align: top` untuk posisi tanda tangan yang konsisten secara vertikal.
- Menambahkan padding horizontal agar antar kolom tanda tangan tidak saling berdekatan.
- Memastikan garis tanda tangan tetap center dengan `margin: auto`.
- Mengoptimalkan layout agar kompatibel dengan berbagai PDF viewer dan environment printing.

Tujuan perubahan:
- Menjamin konsistensi tampilan antara preview di aplikasi dan file PDF yang dihasilkan.
- Memastikan dokumen tercetak rapi, profesional, dan sesuai dengan format dokumen resmi perbankan.
- Meningkatkan kompatibilitas layout untuk berbagai perangkat dan proses cetak.
2025-07-17 11:41:21 +07:00
Daeng Deni Mardaeni
d0cc62f8c0 feat(memo): Perbaiki tampilan preview memo dengan logo resmi dan format A4
Memperbaiki tampilan preview memo penyelesaian agar sesuai dengan standar dokumen resmi bank.

Perubahan yang dilakukan:
- Mengganti logo placeholder AGI dengan logo resmi Bank Artha Graha Internasional.
- Mengubah layout dari card-based menjadi full-width format A4 untuk preview, print, dan PDF.
- Menambahkan header controls dengan class `no-print` agar tersembunyi saat dicetak atau di-generate PDF.
- Memperbaiki struktur header bank dengan logo dan nama perusahaan yang proper.
- Menyesuaikan judul memo menjadi lebih compact dan professional.
- Memperbaiki struktur tabel informasi memo dengan penggunaan inline styling untuk konsistensi PDF.
- Menambahkan helper `dateFormat()` untuk penulisan tanggal yang lebih rapi.
- Memperbaiki posisi tanda tangan agar lebih proporsional dan sesuai format resmi.
- Menambahkan class `page-memo` untuk styling halaman memo secara khusus.
- Menyempurnakan responsive design dengan flex layout yang lebih baik.
- Menambahkan path logo: `assets/media/images/logo-arthagraha.png` untuk keperluan cetak dan PDF.
- Memperbaiki typography dan spacing agar sesuai dengan standar dokumen resmi.
- Menambahkan kontrol print-friendly menggunakan class `no-print`.

Tujuan perubahan:
- Menjamin tampilan memo penyelesaian sesuai standar corporate identity bank.
- Memastikan output PDF dan print preview konsisten dengan dokumen resmi.
- Meningkatkan profesionalitas tampilan dan mempermudah proses administrasi.
2025-07-17 10:30:02 +07:00
Daeng Deni Mardaeni
0c2c0c9e20 feat(memo): Tambah halaman preview dan PDF memo penyelesaian
Menambahkan fitur preview memo penyelesaian sebelum data disimpan ke database, untuk memastikan user dapat memeriksa kembali detail permohonan dan biaya terkait.

Perubahan pada Controller:
- Menambahkan method `preview()` di MemoController untuk menampilkan halaman preview memo penyelesaian.
- Menambahkan method `generatePdf()` untuk menghasilkan PDF resmi memo dengan format sesuai standar bank.
- Mengimplementasikan validasi input lengkap sebelum proses preview dan PDF generation.
- Mengintegrasikan helper fungsi terbilang untuk konversi total biaya ke dalam format huruf.

Perubahan pada View:
- Menambahkan view `preview.blade.php` sebagai template resmi memo penyelesaian dengan layout AGI header, informasi memo, daftar permohonan, total biaya PJ, dan tanda tangan.
- Menampilkan tabel daftar permohonan terlampir dengan informasi debitur, cabang, AO, dan nominal biaya PJ.
- Menyediakan fitur print preview dengan styling khusus untuk pencetakan dokumen resmi.
- Menambahkan UI interaktif untuk mempermudah navigasi sebelum menyimpan data.

Perubahan pada Form Create:
- Mengubah alur form `create.blade.php` agar mengarahkan ke halaman preview terlebih dahulu sebelum penyimpanan.
- Menambahkan tombol untuk melanjutkan proses ke simpan atau kembali ke pengisian form.

Routing dan Navigasi:
- Menambahkan route baru `memo.preview` untuk preview dan `memo.generate-pdf` untuk generate PDF memo penyelesaian.
- Menambahkan breadcrumb untuk halaman preview agar navigasi lebih jelas.

Fitur Tambahan:
- Implementasi JavaScript untuk interaksi form preview, print action, dan konfirmasi user.
- Penambahan fitur terbilang untuk memudahkan verifikasi nominal dalam format teks.
- Penanganan error secara komprehensif dengan logging dan rollback pada transaksi jika terjadi kesalahan.
- Menjamin data tetap konsisten meskipun user hanya melakukan preview tanpa menyimpan.

Tujuan Perubahan:
- Memberikan fasilitas preview agar user dapat memverifikasi data sebelum menyimpan memo penyelesaian.
- Memastikan output memo dalam format PDF resmi yang sesuai dengan template bank.
- Meningkatkan user experience dan mengurangi potensi kesalahan input sebelum proses finalisasi.
- Mempermudah proses cetak memo dengan fitur print-friendly dan PDF yang siap dikirim atau diarsipkan.
2025-07-17 09:55:06 +07:00
Daeng Deni Mardaeni
274addb069 refactor(memo): Sesuaikan struktur form dan tambahkan kalkulasi Total Biaya PJ
Melakukan refactor dan penyesuaian form memo penyelesaian agar lebih sesuai dengan kebutuhan bisnis, serta menambahkan fitur perhitungan otomatis Total Biaya PJ.

Perubahan pada Form Input:
- Mengubah field "Judul Memo" menjadi "Nomor Memo" untuk identifikasi memo yang lebih spesifik.
- Menghapus field "Isi Memo" karena tidak relevan dengan proses bisnis saat ini.
- Menambahkan field "Tanggal Pembayaran" untuk tracking proses pembayaran.
- Mengatur "Tanggal Memo" menjadi otomatis mengikuti tanggal hari ini dan disimpan sebagai hidden field untuk keperluan audit.
- Menambahkan field readonly "Total Biaya PJ" untuk menampilkan akumulasi biaya dari NOC terkait permohonan yang dipilih.

Perubahan pada Controller:
- Mengupdate validasi request agar sesuai dengan field baru: `memo_number`, `payment_date`, dan `permohonan_ids`.
- Menghapus validasi `memo_content` karena field tersebut tidak lagi digunakan.
- Menambahkan method `getTotalBiayaPJ()` untuk endpoint AJAX yang menghitung total biaya PJ secara real-time.
- Menggunakan relasi model `Noc` dan `Permohonan` untuk menghitung sum dari `nominal_bayar`.
- Mengupdate method `create()` agar langsung menghitung total biaya PJ saat form dibuka.
- Tetap menggunakan DB transaction untuk memastikan integritas data.

Perubahan pada Database Schema:
- Mengganti field `memo_penyelesaian_title` menjadi `memo_penyelesaian_number`.
- Menghapus field `memo_penyelesaian_content`.
- Menambahkan field baru `memo_penyelesaian_payment_date` untuk menyimpan tanggal pembayaran.
- Mempertahankan field `memo_penyelesaian_date` sebagai audit trail.

Perubahan pada View:
- Menambahkan field readonly "Total Biaya PJ" dengan format mata uang Rupiah.
- Menambahkan icon kalkulator dan styling sesuai dengan tema form.
- Menggunakan AJAX untuk menghitung total biaya PJ ketika user memilih atau mengubah permohonan secara dinamis.
- Menampilkan pesan error dan feedback user secara jelas jika terjadi masalah saat perhitungan.

Routing dan API:
- Menambahkan route `memo.total-biaya-pj` sebagai endpoint untuk kalkulasi biaya PJ berbasis AJAX.
- Tetap menggunakan route resource untuk operasi CRUD memo penyelesaian.

Keamanan dan Validasi:
- Implementasi CSRF protection untuk AJAX request.
- Validasi `permohonan_ids` harus berupa array yang valid dan terfilter dengan baik.
- Penanganan error yang komprehensif baik di sisi controller maupun client-side.

Peningkatan User Experience:
- Form menjadi lebih sederhana, efisien, dan fokus pada input yang memang dibutuhkan oleh proses bisnis.
- Real-time feedback saat memilih permohonan sehingga user langsung mengetahui total biaya PJ.
- Layout form tetap responsive dan mudah digunakan di berbagai perangkat.
- Memberikan pengalaman yang konsisten dengan desain aplikasi lainnya.

Tujuan Perubahan:
- Menyederhanakan proses pembuatan memo penyelesaian sesuai kebutuhan operasional terbaru.
- Memastikan proses input lebih cepat dan akurat dengan kalkulasi otomatis Total Biaya PJ.
- Mengurangi potensi kesalahan input dan mempercepat workflow divisi terkait.
- Meningkatkan maintainability dan konsistensi kode dengan standar sistem yang ada.
2025-07-17 09:41:20 +07:00
Daeng Deni Mardaeni
5c3a93c49b feat(lpj): implementasi fitur Memo Penyelesaian dengan controller, view, dan routing lengkap
Perubahan yang dilakukan:

**Controller MemoController:**
- Menambahkan MemoController untuk mengelola memo penyelesaian permohonan.
- Method index() untuk menampilkan daftar permohonan yang bisa dipilih.
- Method create() untuk form pembuatan memo dengan pemilihan data bulk.
- Method store() untuk menyimpan memo dan mengupdate status permohonan terkait.
- Method show() untuk menampilkan detail memo yang telah dibuat.
- Method dataForDatatables() untuk API datatables dengan filter, search, dan pagination.
- Implementasi DB transaction untuk menjaga integritas data.
- Logging dan error handling komprehensif di setiap method.

**View Template:**
- index.blade.php: Tabel data permohonan dengan fitur checkbox selection (bulk).
- create.blade.php: Form pembuatan memo dari data yang dipilih.
- show.blade.php: Halaman detail memo penyelesaian.
- Menggunakan Bootstrap untuk styling dan interaksi dinamis dengan JavaScript.
- Validasi client-side untuk memastikan data sesuai sebelum dikirim.

**Routing dan Navigasi:**
- Menambahkan route resource untuk operasi CRUD Memo.
- Menambahkan route khusus untuk datatables API dan bulk create.
- Integrasi menu "Memo Penyelesaian" di navigasi utama aplikasi.
- Role-based access control untuk keamanan akses fitur.

**Integrasi Data:**
- Menggunakan model Permohonan sebagai sumber data utama dengan eager loading.
- Relasi dengan tabel user, debitur, branch, dan tujuan penilaian.
- Menambahkan status management untuk mempermudah tracking progress permohonan.

**Keamanan dan Validasi:**
- Validasi input baik di sisi controller maupun client-side.
- CSRF protection dan XSS prevention untuk menjaga keamanan aplikasi.
- Permission checking sesuai level user.

**Performance dan UX:**
- Pagination dan query optimization untuk performa lebih baik.
- Caching strategi untuk data yang sering diakses.
- Interface yang intuitif, dengan loading state dan feedback message.
- Responsive design untuk desktop dan mobile.
- Shortcut keyboard untuk efisiensi power user.

**Teknis dan Testing:**
- Struktur kode mengikuti Laravel best practice dan design pattern.
- Siap untuk unit test dan integration test.
- Logging lengkap untuk monitoring dan debugging.
- Error scenario handling dan fallback yang robust.

Tujuan perubahan:
- Menyediakan fitur pengelolaan memo penyelesaian permohonan secara bulk dengan user experience yang optimal dan performa efisien.
2025-07-15 10:05:22 +07:00
putrakuningan
36ac1370d7 Merge pull request 'feature/senior-officer' (#146) from feature/senior-officer into staging
Reviewed-on: #146
2025-07-14 09:08:54 +07:00
majid
3eb402ae08 feat: add export functionality and simplify laporan user report
refactor: update laporan user service and views for simplified report
style: improve daftar pustaka views and remove unused code
fix: correct date field names in laporan sla penilai service
2025-07-14 09:08:54 +07:00
majid
07589370df fix(activity): highlight table row in red when status is "freeze" 2025-07-14 09:08:54 +07:00
majid
8220466f03 feat(daftar-pustaka) : tambah daftar pustaka dan categori pustaka, lihat detail, tambah, edit 2025-07-14 09:08:54 +07:00
majid
5c57b9cb58 feat(laporan): tambah tanggal reported, kunjungan, laporan 2025-07-14 09:08:54 +07:00
majid
a72515bc30 feat(print-out): tambah tanggal otorisasi di bagian tanda tangan 2025-07-14 09:08:54 +07:00
Daeng Deni Mardaeni
e79b8c6449 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-07-03 11:53:28 +07:00
majid
e63f9e7359 Merge branch 'feature/senior-officer' of https://git.putrakuningan.com/daengdeni/lpj into feature/senior-officer 2025-07-03 11:17:02 +07:00
majid
d0f3ffa93a Merge branch 'feature/dashboard-laporan' into feature/senior-officer 2025-07-03 11:13:36 +07:00
majid
37874aff3a Merge branch 'staging' into feature/senior-officer 2025-07-03 11:12:56 +07:00
majid
44ff9d4ac6 feat(breadcrumbs): tambahkan breadcrumbs pada halaman laporan SLA, debiture, user, dan monitoring; perbarui route laporan SLA, debiture, user, dan monitoring 2025-07-03 11:11:01 +07:00
majid
5e8f979d05 feat(laporan-sla-penilai): tambah laporan sla penilai 2025-07-03 10:25:36 +07:00
majid
ae15e1983f feat(rekap-monitoring-so) : tambah rekap monitoring so 2025-07-03 09:51:57 +07:00
Daeng Deni Mardaeni
28513100f4 refactor(noc, views): optimalkan kode, perbaiki konsistensi format, dan refactor tampilan
- **Controller (NocController)**:
  - Perbaikan nama route pada **index()** dari `noc.pembayaran` menjadi `noc.pembayaran.index`.
  - Menghapus komentar kode tak terpakai pada logika update **status permohonan** di metode penyimpanan.

- **Blade Views**:
  - Perbaikan konsistensi atribut HTML dan struktur elemen di berbagai template: `index.blade.php`, `pembayaran.blade.php`, dan `form.blade.php`.
  - Penghapusan spasi yang tidak diperlukan dan optimasi indentasi pada atribut elemen seperti `class`, `data-*`, dan lainnya.
  - Perbaikan label input dan placeholder untuk keterbacaan dan kesesuaian desain.
  - Penyelarasan nama variabel dan logika validasi berdasarkan kondisi file dan data yang ada.

- **Form NOC**:
  - Penyesuaian form handling untuk berbagai atribut seperti `status_pembayar`, `nominal_bayar`, dan `bukti_ksl`.
  - Penyesuaian aksi form untuk **update** atau **store** tergantung kondisi form.

- **Datatables**:
  - Pengoptimalan tabel untuk hierarki atribut dan nilai default seperti pagination, sorting, atau data filtering.
2025-07-03 09:46:47 +07:00
majid
e72e82ea55 feat(laporan-user): tambah laporan users pemohon 2025-07-03 09:14:38 +07:00
majid
47bf7ab59b feat(laporan-debiture) : tambah laporan debiture 2025-07-03 09:04:24 +07:00
majid
4ee42f38b9 feat:(laporan) tambah rekap harian so dan biaya internal dan external 2025-07-02 09:47:24 +07:00
majid
60dd90a9ed Merge branch 'staging' into feature/dashboard-laporan 2025-06-20 09:17:00 +07:00
majid
3f979aef05 feat(dashboard/rekap-so): penambahan dashboard, rekap so 2025-06-20 09:12:50 +07:00
Daeng Deni Mardaeni
4bb808b341 feat(noc): tambahkan fitur baru untuk pengelolaan NOC pembayaran dan penyelesaian
- Menambahkan metode baru pada `NocController` untuk mendukung pengelolaan NOC pembayaran dan penyelesaian.
    - `pembayaran()` untuk menampilkan daftar NOC Pembayaran.
    - `penyelesaian()` untuk menampilkan daftar NOC Penyelesaian.
- Menambahkan fitur baru datatables untuk pembayaran dan penyelesaian:
    - `dataForDatatablesPembayaran()` untuk filter pembayaran tanpa memo penyelesaian.
    - `dataForDatatablesPenyelesaian()` untuk filter penyelesaian dengan memo penyelesaian.
- Memperbarui routing untuk mendukung fitur baru:
    - `noc/pembayaran` untuk daftar pembayaran.
    - `noc/penyelesaian` untuk daftar penyelesaian.
    - Tambah endpoint datatables baru: `/noc/datatables/pembayaran` dan `/noc/datatables/penyelesaian`.
- Menambahkan file blade baru untuk menampilkan daftar NOC pembayaran dan penyelesaian:
    - `pembayaran.blade.php`.
    - `penyelesaian.blade.php`.
- Menambahkan breadcrumbs untuk fitur pembayaran dan penyelesaian:
    - `noc.pembayaran` dan `noc.penyelesaian`.
- Update `module.json` untuk mendukung UI navigasi baru pada NOC:
    - Tambahkan submenu "Pembayaran" dan "Penyelesaian".
    - Ubah ikon menu NOC dari `ki-two-credit-cart` menjadi `ki-briefcase`.
- Menambahkan validasi, filter, dan sorting baru untuk datatables pembayaran dan penyelesaian.
- Mengoptimalkan tabel datatables sehingga mendukung input pencarian, sorting, dan download file terkait bukti pembayaran atau memo penyelesaian.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
2025-06-12 11:59:50 +07:00
putrakuningan
887478c751 Merge pull request 'fix: simpan penilai dan so dan print standar dan sederhana' (#144) from feature/senior-officer into staging
Reviewed-on: #144
2025-05-23 13:48:17 +07:00
majid
2708dead53 fix: save penilai dan so, perbaikan print sederhana dan standar 2025-05-23 13:48:17 +07:00
majid
644f1da871 Merge branch 'staging' into feature/senior-officer 2025-05-22 11:26:05 +07:00
majid
e32c73cdb2 fix: save penilai dan so, perbaikan print sederhana dan standar 2025-05-22 11:25:08 +07:00
Daeng Deni Mardaeni
40c3d84efc Merge branch 'feature/senior-officer' into staging 2025-05-22 10:18:32 +07:00
majid
760a0cb85d fix: hapus 'u' yang tidak diperlukan di file prit-out-sederhana 2025-05-21 14:38:50 +07:00
majid
0f8774a37c fix: update dokumentId and fix save penilai rap 2025-05-21 14:31:59 +07:00
majid
fa659ff115 fix: perbaikan form-penilai,inspeksi denah - ubah dokument ke documentId, dan print-out-sederhana berdasarkan kategori form 2025-05-21 14:10:36 +07:00
putrakuningan
fdfe591c39 Merge pull request 'Fix Navigation Button back and Update Document Id Handling' (#142) from feature/senior-officer into staging
Reviewed-on: #142
2025-05-21 11:08:31 +07:00
majid
7aae88ce85 fix navigation buttons back, in file memo, rap-penilai, resume, sla, show, and header 2025-05-21 11:08:31 +07:00
majid
8fbc02bfff fix: update dokumentId and fix save penilai rap 2025-05-21 11:08:31 +07:00
majid
0e4c8760f8 Merge branch 'staging' into feature/senior-officer 2025-05-21 10:59:40 +07:00
majid
320dba9d9c fix navigation buttons back, in file memo, rap-penilai, resume, sla, show, and header 2025-05-21 10:57:25 +07:00
majid
6ddf78d2b0 fix: update dokumentId and fix save penilai rap 2025-05-21 10:30:18 +07:00
putrakuningan
79e66226b0 Merge pull request 'feature/senior-officer' (#141) from feature/senior-officer into staging
Reviewed-on: #141
2025-05-20 17:27:41 +07:00
majid
500118d787 fix: perbaikkan update surveyor dan penilai 2025-05-20 17:27:41 +07:00
majid
ade4ffcad4 fix: perbaikkan update surveyor dan penilai 2025-05-20 14:10:52 +07:00
majid
08b71604ec Merge branch 'staging' into feature/senior-officer 2025-05-20 13:02:07 +07:00
Daeng Deni Mardaeni
e731e9cea0 fix(laporan-penilaian): perbaiki logika paginasi dan tambahkan kontrol pagination di view
- Ubah logika default nilai parameter halaman ketika tidak ada input dari request.
- Tambahkan elemen kontrol pagination dan jumlah data per halaman di tampilan UI.
- Pastikan data table kembali ke halaman pertama saat melakukan ekspor data.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
2025-05-07 13:31:34 +07:00
Daeng Deni Mardaeni
980b4e8e9f feat(noc): tambah fitur penyelesaian dan memo penyelesaian NOC
- Menambahkan relasi `noc` pada data laporan.
- Memperbarui logika `update` NOC untuk memproses memo penyelesaian.
- Menambahkan tombol "Penyelesaian" pada halaman laporan jika data NOC belum selesai.
- Memperbaiki pengecekan keberadaan file memo dengan disk publik.
- Mengimplementasikan view dan form baru untuk input memo penyelesaian pada NOC.
- Menambahkan routing dan breadcrumbs untuk proses penyelesaian memo NOC.
- Menambahkan validasi dan penyimpanan file memo penyelesaian.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
2025-05-07 10:29:02 +07:00
Daeng Deni Mardaeni
8158f3058f feat(noc): tambahkan fitur bukti bayar dan nominal diterima
- Menambahkan kolom "Bukti Bayar" dan "Nominal Diterima" pada tampilan daftar noc.
- Menambahkan input untuk bukti bayar dan nominal diterima pada form noc.
- Mengubah logika pengecekan input file bukti KSL agar sesuai kondisi.
- Memperbaiki placeholder dan label form untuk konsistensi.
- Memperbaiki render data bukti bayar pada tabular untuk mendukung tindakan download atau lihat file.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
2025-05-07 09:19:41 +07:00
Daeng Deni Mardaeni
eea49b7943 feat(noc): tambah fitur penyelesaian NOC
- Tambah atribut baru: `tanggal_pembayaran`, `memo_penyelesaian`, `bukti_penyelesaian`, dan `nominal_penyelesaian`.
- Update logika penyimpanan dan update data NOC dengan atribut baru.
- Tambah validasi dan handling untuk memproses pembayaran dan penyelesaian NOC.
- Update form NOC untuk mendukung input penyelesaian, termasuk file memo dan bukti penyelesaian.
- Update tampilan tabel data untuk menampilkan atribut baru di halaman index NOC.
- Tambah logika untuk memeriksa keberadaan memo penyelesaian di view form NOC.
- Penyesuaian endpoint dan logika dalam controller untuk mendukung penyelesaian data NOC.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
2025-05-06 13:41:36 +07:00
Daeng Deni Mardaeni
5e8067ad72 feat(noc): tambahkan integrasi dan validasi data NOC
- Tambahkan model NOC ke NocController, PersetujuanPenawaranController, dan validasi pada NocRequest.
- Implementasi penyimpanan data NOC menggunakan `updateOrCreate` di beberapa alur proses.
- Tambahkan properti baru `catatan_noc` pada model, migrasi database, dan form terkait.
- Revisi aturan validasi pada NocRequest dan PersetujuanPenawaranRequest.
- Tingkatkan tampilan form NOC dengan penanganan file upload dan pratinjau file yang sudah diunggah.
- Perbaikan beberapa nama properti seperti `status_bayar` menjadi `status_pembayar`.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
2025-05-05 14:13:54 +07:00
majid
e85ed55598 Merge branch 'staging' into feature/senior-officer 2025-05-05 13:43:56 +07:00
Daeng Deni Mardaeni
7f6c702683 refactor(controllers): perbaikan struktur kode controllers Permohonan dan Penilai
- Reformat kode untuk meningkatkan keterbacaan, termasuk penghapusan spasi kosong yang tidak diperlukan.
- Penyesuaian indentasi dan konsistensi format import pada `PermohonanController`.
- Optimasi fungsi data handling pada fungsi-fungsi terkait permohonan seperti `update`, `destroy`, `dataForDatatables`, dan `dataForAuthorization`.
- Penyesuaian pemetaan data output dalam format JSON pada datatables.
- Penghapusan elemen komentar yang tidak relevan atau redundant.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
2025-05-05 11:39:05 +07:00
Daeng Deni Mardaeni
e6d05cc4aa feat(noc): tambahkan fitur Noc untuk pengelolaan data penyelesaian
- Menambahkan model baru untuk tabel `noc` beserta relasinya pada `Permohonan` dan `PersetujuanPenawaran`.
- Menambahkan migrasi untuk membuat tabel `noc` di database.
- Memodifikasi logika dan format data pada `NocController` untuk mendukung data terkait `noc`.
- Mendefinisikan relasi baru di model `Permohonan` dan `PersetujuanPenawaran` untuk mendukung fitur `noc`.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
2025-05-05 11:37:51 +07:00
Daeng Deni Mardaeni
4ebc700283 refactor(Lpj): optimalkan kode untuk peningkatan efisiensi
- Ganti `isNumeric` dengan `ctype_digit` dan hapus fungsi `isNumeric` yang tidak diperlukan.
- Simplifikasi fungsi `onRomawi` dengan memanfaatkan fungsi `convertToRoman`.
- Hapus fungsi `holidays` karena tidak digunakan lagi dalam kode.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
2025-05-05 11:35:32 +07:00
Daeng Deni Mardaeni
121d099402 refactor(migrations): hapus dan perbaiki struktur tabel database
- Menghapus migration `create_currencies_table` dan `create_label_name_inspeksi_table` yang tidak digunakan.
- Menambahkan `timestamps` dan `softDeletes` pada beberapa tabel untuk peningkatan konsistensi dan fitur auditing.
- Mengubah `authorized_status` dari wajib menjadi nullable di beberapa tabel untuk fleksibilitas data.
2025-05-04 20:39:59 +07:00
Daeng Deni Mardaeni
54668820b1 refactor(models): ubah inheritance model ke base class
- Mengubah inheritance pada semua model di `Modules/Lpj` dari `Model` ke `Base` untuk konsistensi struktur.
- Menghapus model `SLA` beserta migrasi terkait karena tidak lagi digunakan.
2025-05-04 20:17:56 +07:00
Daeng Deni Mardaeni
d63108dea1 refactor(noc): optimalkan kode dan penyederhanaan logika dalam controller dan view
- Perbaiki dan konsistenkan penulisan conditional pada `NocController`.
- Sederhanakan logika pengambilan dan mapping data di controller.
- Hapus penggunaan fungsi render di view untuk data yang sudah diolah di controller.
- Refactor partial query logic di `PembayaranController` untuk efisiensi.
2025-05-04 05:53:05 +07:00
Daeng Deni Mardaeni
5cdc4b08b3 feat(laporan-hasil-penilaian): tambahkan render untuk kolom bukti kepemilikan
- Menambahkan fungsi render untuk kolom bukti kepemilikan pada tabel laporan hasil penilaian.
- Mengganti karakter baris baru dengan tag <br> untuk menampilkan data dalam format HTML.
- Menyediakan nilai default '-' jika tidak ada bukti kepemilikan yang tersedia.
2025-04-23 22:43:08 +07:00
Daeng Deni Mardaeni
dd11f467fa fix(laporan-hasil-penilaian): perbaiki penanganan nilai null pada kolom data
- Mengubah cara penanganan nilai null untuk kolom nilai_tanah, nilai_bangunan, nilai_njop, nilai_pasar_wajar, dan nilai_likuidasi.
- Menggunakan operator nullish coalescing (??) untuk menampilkan '-' jika nilai tidak ada.
2025-04-23 16:04:14 +07:00
Daeng Deni Mardaeni
49b13e6689 feat(laporan-penilaian): tambahkan filter penilai untuk mencakup surveyor
- Mengubah opsi filter penilai untuk menampilkan pengguna dengan peran 'penilai' dan 'surveyor'.
- Memperluas fungsionalitas pemfilteran pada laporan penilaian jaminan.
2025-04-23 16:01:13 +07:00
Daeng Deni Mardaeni
b9d0d9f03b feat(laporan-hasil-penilaian): tambahkan filter penilai pada laporan hasil penilaian jaminan internal dan eksternal
- Menambahkan filter untuk memilih penilai pada halaman laporan hasil penilaian.
- Memperbarui logika kueri untuk menyertakan filter penilai saat mengambil data.
- Memperbaiki tampilan dan struktur HTML untuk mendukung filter baru.
- Menambahkan fungsionalitas untuk menerapkan filter dan mengupdate tabel data secara dinamis.
2025-04-23 15:51:19 +07:00
Daeng Deni Mardaeni
0972f3fcff feat(laporan-hasil-penilaian): tambahkan filter penilai pada laporan penilaian jaminan
- Menambahkan filter untuk memilih penilai pada halaman laporan penilaian jaminan.
- Memperbarui query untuk menyertakan filter penilai saat mengambil data.
- Memperbaiki tampilan dengan menambahkan elemen input untuk filter penilai.
2025-04-23 15:51:03 +07:00
Daeng Deni Mardaeni
d251c7655d feat(laporan-hasil-penilaian): tambahkan halaman laporan hasil penilaian jaminan internal dan eksternal
- Menambahkan rute dan breadcrumb untuk halaman laporan hasil penilaian jaminan internal dan eksternal.
- Membuat tampilan baru dengan tabel untuk menampilkan data laporan.
- Menyediakan fungsionalitas pencarian dan filter berdasarkan tanggal dan cabang.
- Menambahkan opsi untuk mengekspor laporan ke Excel.
2025-04-23 13:28:34 +07:00
Daeng Deni Mardaeni
afbdad43db feat(laporan-hasil-penilaian): tambahkan rute dan breadcrumb untuk laporan hasil penilaian jaminan internal dan eksternal
- Menambahkan breadcrumb untuk 'Laporan Hasil Penilaian Jaminan Internal External'.
- Menambahkan rute baru untuk 'laporan-hasil-penilaian-jaminan-internal-external' dengan metode:
  - dataForDatatables
  - export
  - index
2025-04-23 13:28:20 +07:00
Daeng Deni Mardaeni
886a382f57 feat(export): tambahkan fungsionalitas ekspor laporan hasil penilaian jaminan internal dan eksternal
- Menambahkan kelas LaporanHasilPenilaianJaminanInternalExternalExport untuk mengelola ekspor data.
- Mengimplementasikan metode collection untuk mengambil data permohonan dengan filter.
- Menambahkan metode map untuk memetakan data permohonan ke format yang sesuai untuk ekspor.
- Menyediakan judul dan heading untuk laporan yang diekspor.
- Mengatur format dan gaya untuk laporan yang dihasilkan.
2025-04-23 13:28:03 +07:00
Daeng Deni Mardaeni
c1c37f5716 feat(laporan-hasil-penilaian): tambahkan controller untuk laporan hasil penilaian jaminan internal dan eksternal
- Menambahkan method index untuk menampilkan halaman laporan.
- Menambahkan method dataForDatatables untuk mengambil dan memfilter data permohonan.
- Menambahkan method export untuk mengunduh laporan dalam format Excel.
- Mengimplementasikan pencarian dan pengurutan data berdasarkan parameter yang diberikan.
2025-04-23 13:27:41 +07:00
Daeng Deni Mardaeni
89957190c7 feat(permohonan): tambahkan kolom dan pencarian untuk Nomor LPJ Lama
- Menambahkan kolom "Nomor LPJ Lama" pada tabel permohonan.
- Memperbarui fungsi pencarian untuk mencakup "Nomor LPJ Lama".
2025-04-23 12:52:47 +07:00
Daeng Deni Mardaeni
0167919542 feat(laporan-penilaian-jaminan): perbarui tanggal laporan dan tanggal review
- Menambahkan logika untuk menampilkan tanggal laporan berdasarkan approval.
- Memperbarui tanggal review dengan tanggal kunjungan dari penilaian.
2025-04-23 11:29:01 +07:00
Daeng Deni Mardaeni
b3ccf3bb8f feat(laporan-penilaian-jaminan): tambahkan fungsionalitas ekspor laporan penilaian jaminan
- Menambahkan judul dan informasi cabang pada laporan.
- Menyertakan periode dan tanggal ekspor di laporan.
- Menambahkan informasi pengguna yang melakukan ekspor.
- Memperbaiki format dan gaya header pada laporan.
- Mengatur auto-size kolom dan menambahkan border pada sel data.
2025-04-23 11:23:09 +07:00
Daeng Deni Mardaeni
d434680f0e feat(laporan-penilaian-jaminan): tambahkan menu untuk laporan penilaian jaminan
- Menambahkan entri menu baru untuk "Laporan Penilaian Jaminan".
- Menetapkan path dan ikon untuk menu baru.
- Mengatur peran yang diperlukan untuk mengakses laporan.
2025-04-23 10:43:46 +07:00
Daeng Deni Mardaeni
53c86a79d0 feat(laporan-permohonan): perbaiki query dan aktifkan breadcrumbs
- Mengubah query pada metode collection untuk menggunakan Permohonan::query() alih-alih Permohonan::with().
- Mengaktifkan tampilan breadcrumbs pada halaman laporan permohonan.
2025-04-23 10:41:54 +07:00
Daeng Deni Mardaeni
f7b851d295 feat(laporan-penilaian-jaminan): tambahkan tampilan dan fungsionalitas untuk laporan penilaian jaminan
- Menambahkan struktur tampilan untuk laporan penilaian jaminan.
- Menyediakan filter berdasarkan tanggal dan cabang.
- Menambahkan fungsionalitas pencarian untuk laporan.
- Menyediakan opsi ekspor laporan ke Excel.
- Mengimplementasikan tabel data dengan kolom yang relevan.
2025-04-23 10:39:32 +07:00
Daeng Deni Mardaeni
baf0000a3f feat(laporan-penilaian-jaminan): tambahkan rute dan breadcrumb untuk laporan penilaian jaminan
- Menambahkan breadcrumb untuk 'Laporan Penilai Jaminan' yang mengacu pada 'Laporan'.
- Menambahkan rute baru untuk 'laporan-penilaian-jaminan' dengan metode untuk data, ekspor, dan indeks.
2025-04-23 10:39:17 +07:00
Daeng Deni Mardaeni
5b50a36a60 feat(laporan-penilaian-jaminan): tambahkan ekspor laporan penilaian jaminan
- Membuat kelas LaporanPenilaianJaminanExport untuk mengekspor data penilaian jaminan.
- Menambahkan filter berdasarkan tanggal, cabang, dan pencarian untuk query.
- Mengimplementasikan metode collection, map, dan headings untuk format ekspor.
2025-04-23 10:36:27 +07:00
Daeng Deni Mardaeni
45f911cef9 feat(laporan-admin-kredit): tambahkan controller untuk laporan penilaian jaminan
- Menambahkan LaporanPenilaianJaminanController untuk mengelola laporan penilaian jaminan.
- Implementasi fungsi index untuk menampilkan halaman laporan.
- Menambahkan fungsi dataForDatatables untuk mengambil dan memfilter data permohonan.
- Menyediakan fungsi export untuk mengunduh laporan dalam format Excel.
2025-04-23 10:36:03 +07:00
Daeng Deni Mardaeni
aa3efd6015 feat(laporan-admin-kredit): optimalkan query permohonan
- Menghapus eager loading pada relasi yang tidak diperlukan.
- Mempercepat pengambilan data permohonan dengan status 'done'.
2025-04-23 10:35:32 +07:00
Daeng Deni Mardaeni
fd21a5b86f feat(lpj): perbarui fungsi dan struktur kode
- Mengatur ulang urutan penggunaan namespace untuk konsistensi.
- Memperbaiki penanganan kesalahan pada fungsi formatTanggalIndonesia.
- Menambahkan logika untuk memeriksa rentang tanggal aktif pada fungsi checkActiveDateRangePenawaran.
- Memperbaiki dan menyederhanakan logika pada fungsi checkKelengkapanDetailKJPP.
- Memperbarui fungsi generateLpjUniqueCode untuk menghasilkan kode unik dengan format yang lebih baik.
- Menyempurnakan fungsi formatNotifikasi untuk menampilkan pesan yang lebih informatif.
2025-04-23 09:26:42 +07:00
Daeng Deni Mardaeni
d1744b07ec feat(permohonan): hapus notifikasi saat membuat permohonan
- Menghapus kode yang mengirim notifikasi kepada pengguna setelah permohonan dibuat.
- Memperbaiki alur penyimpanan data dengan mengurangi ketergantungan pada notifikasi.
2025-04-23 09:26:33 +07:00
Daeng Deni Mardaeni
10aa59d65d feat(permohonan): tambahkan fungsi notifikasi saat membuat riwayat permohonan
- Menambahkan pemanggilan fungsi createNotification setelah membuat riwayat permohonan.
- Mengimplementasikan logika untuk mengirim notifikasi kepada pengguna terkait status 'order'.
- Menggunakan kelas PermohonanNotif untuk mengirim pesan notifikasi.
2025-04-23 09:26:08 +07:00
Daeng Deni Mardaeni
2506b6115c feat(notifikasi): tambahkan pesan pada notifikasi permohonan
- Menambahkan properti message pada kelas PermohonanNotif.
- Memperbarui konstruktor untuk menerima parameter message.
- Memperbarui metode toArray untuk menyertakan message dalam representasi array notifikasi.
2025-04-23 09:25:42 +07:00
Daeng Deni Mardaeni
acfc282e25 feat(notifikasi): tambahkan kelas PermohonanNotif untuk notifikasi permohonan
- Menambahkan kelas PermohonanNotif yang mengimplementasikan notifikasi di Laravel.
- Menggunakan saluran pengiriman 'mail' dan 'database'.
- Menyediakan metode untuk mengirim representasi email dan array dari notifikasi.
2025-04-22 13:58:23 +07:00
Daeng Deni Mardaeni
ffb24b8cd6 feat(notifikasi): tambahkan fungsi formatNotifikasi untuk permohonan
- Menambahkan fungsi formatNotifikasi untuk memformat data notifikasi.
- Menggunakan json_decode untuk mengubah data menjadi objek.
- Menghasilkan array notifikasi dengan judul dan pesan berdasarkan status permohonan.
2025-04-22 13:58:23 +07:00
Daeng Deni Mardaeni
d4c70fba00 feat(permohonan): tambahkan notifikasi saat permohonan dibuat
- Menambahkan penggunaan notifikasi PermohonanNotif untuk memberitahukan pengguna saat permohonan baru dibuat.
- Mengambil pengguna yang membuat permohonan menggunakan ID dari kolom created_by.
2025-04-22 13:58:23 +07:00
Daeng Deni Mardaeni
7b14c16af1 fix(Base): tambahkan trait Notifiable pada model Base
- Menambahkan trait Notifiable untuk mendukung notifikasi dalam model Base.
- Memastikan model dapat mengirimkan notifikasi sesuai kebutuhan aplikasi.
2025-04-22 13:58:23 +07:00
Daeng Deni Mardaeni
fc466f6087 Merge branch 'staging' of http://10.0.7.60:83/daengdeni/lpj into staging 2025-04-22 10:07:18 +07:00
putrakuningan
1e8ce1d6d9 Merge pull request 'feature/senior-officer' (#140) from feature/senior-officer into staging
Reviewed-on: #140
2025-04-22 09:53:18 +07:00
majid
589e06dc00 fix(print-out): perbaikkan fungsi cetak laporan 2025-04-22 09:53:18 +07:00
majid
7936c3e275 fix(print-out): perbaikkan print out foto dan print out resume 2025-04-22 09:53:18 +07:00
majid
5e946cdfa7 fix(penilai):perbaikkan otorisasi paparan dibawah < 2M 2025-04-22 09:53:18 +07:00
majid
b53b94e27d fix(surveyor):perbaikkan hapus foto 2025-04-22 09:53:18 +07:00
majid
6f8db74159 fix(print-out): perbaikkan fungsi cetak laporan 2025-04-21 16:37:33 +07:00
majid
43b086f3ea fix(print-out): perbaikkan print out foto dan print out resume 2025-04-21 15:59:56 +07:00
Daeng Deni Mardaeni
e28da750c7 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-04-17 19:30:26 +07:00
majid
55036bf581 fix(penilai):perbaikkan otorisasi paparan dibawah < 2M 2025-04-17 19:01:46 +07:00
majid
27633cef7a fix(surveyor):perbaikkan hapus foto 2025-04-17 15:33:34 +07:00
Daeng Deni Mardaeni
23aa158cc2 Merge remote-tracking branch 'composer/feature/senior-officer' into staging
# Conflicts:
#	resources/views/surveyor/components/foto.blade.php
2025-04-17 13:50:32 +07:00
majid
25889577c8 fix(foto): hapus / 2025-04-17 13:23:42 +07:00
putrakuningan
bcb4246ee9 Merge pull request 'feature/senior-officer' (#139) from feature/senior-officer into staging
Reviewed-on: #139
2025-04-17 10:12:39 +07:00
majid
a5902305d0 fix(surveyor): perbaikkan upload foto mengunakan kamera dan upload file foto 2025-04-17 10:12:39 +07:00
majid
4647e75733 fix(penilai): rename nama file apartement-kantor ke apartemen-kantor 2025-04-17 10:12:39 +07:00
majid
2e07d526a8 fix(surveyor/penilai):perbaikkan pengambilan key luas unit dan handle foto di informasi 2025-04-17 10:12:39 +07:00
majid
d9c3f12ee6 fix(surveyor): perbaikkan upload foto mengunakan kamera dan upload file foto 2025-04-17 10:04:34 +07:00
majid
f5c2ea3ba4 fix(penilai): rename nama file apartement-kantor ke apartemen-kantor 2025-04-16 22:53:48 +07:00
majid
c2c998e48c fix(surveyor/penilai):perbaikkan pengambilan key luas unit dan handle foto di informasi 2025-04-16 21:34:24 +07:00
Daeng Deni Mardaeni
1c1eee8e3a feat(laporan-pembatalan): tambahkan fitur laporan pembatalan
- Menambahkan entri menu untuk "Laporan Pembatalan" di module.json.
- Menambahkan rute untuk laporan pembatalan di web.php.
- Menghubungkan rute dengan LaporanPembatalanController untuk mengelola data laporan.
2025-04-14 09:16:47 +07:00
Daeng Deni Mardaeni
8e081e6968 feat(laporan-pembatalan): tambahkan fitur ekspor laporan pembatalan
- Menambahkan kelas LaporanPembatalanExport untuk mengelola ekspor data laporan pembatalan.
- Mengimplementasikan filter pencarian berdasarkan nomor registrasi, nama pemohon, dan nama cabang.
- Menyediakan opsi untuk memfilter berdasarkan rentang tanggal, status, dan cabang.
- Menyusun data yang diekspor dengan format yang sesuai untuk laporan.
2025-04-14 09:16:30 +07:00
Daeng Deni Mardaeni
15e75c286c feat(laporan-pembatalan): tambahkan fitur laporan pembatalan
- Menambahkan controller LaporanPembatalanController untuk mengelola laporan pembatalan.
- Menyediakan metode untuk menampilkan halaman laporan dan mengekspor data ke Excel.
- Mengimplementasikan filter pencarian berdasarkan tanggal, cabang, dan status.
- Menyediakan pagination dan sorting untuk data laporan.
- Menambahkan tampilan blade untuk laporan pembatalan dengan elemen UI yang diperlukan.
2025-04-14 09:16:07 +07:00
Daeng Deni Mardaeni
f227093c95 refactor(permohonan-pembatalan): perbaiki relasi dan nama metode
- Menghapus import yang tidak digunakan untuk model Permohonan.
- Mengganti nama metode 'creator' menjadi 'user' untuk konsistensi.
- Menambahkan metode 'authorizedUser' untuk relasi dengan pengguna yang mengotorisasi.
2025-04-14 09:15:27 +07:00
Daeng Deni Mardaeni
a38b09d1a8 feat(laporan-admin-kredit): tambahkan fitur edit dan update laporan admin kredit
- Menambahkan metode edit untuk menampilkan formulir pengeditan laporan admin kredit.
- Menambahkan metode update untuk memvalidasi dan memperbarui laporan admin kredit.
- Memperbarui rute untuk mendukung pengeditan dan pembaruan laporan admin kredit.
- Menambahkan breadcrumb untuk navigasi ke halaman edit laporan admin kredit.
- Memperbarui tampilan index untuk menambahkan tombol aksi edit.
2025-04-11 11:04:11 +07:00
Daeng Deni Mardaeni
4b0e651cf5 feat(laporan): tambah filter branch pada laporan permohonan
Menambahkan fitur filter berdasarkan cabang pada laporan permohonan:
- Mengimplementasikan filter branch pada controller LaporanPermohonanController
- Mengimplementasikan filter branch pada export LaporanPermohonanExport
- Menambahkan dropdown filter cabang pada halaman index
- Mengimplementasikan filter cabang pada JavaScript untuk datatable
- Menambahkan parameter branch_id pada URL ekspor data
- Memastikan filter cabang berfungsi baik pada tampilan datatable maupun pada ekspor data
2025-04-09 11:02:18 +07:00
Daeng Deni Mardaeni
105bd1ce4b feat(laporan): tambah filter status pada laporan permohonan
Menambahkan fitur filter berdasarkan status pada laporan permohonan:
- Menambahkan filter status yang diambil dari model StatusPermohonan
- Mengimplementasikan filter status pada controller LaporanPermohonanController
- Mengimplementasikan filter status pada export LaporanPermohonanExport
- Memastikan filter status berfungsi baik pada tampilan datatable maupun pada ekspor data
2025-04-09 10:49:35 +07:00
Daeng Deni Mardaeni
0f6efabeb3 feat(bank-data): tambahkan filter tahun pada data bank
- Menambahkan dropdown untuk memilih tahun pada halaman data bank.
- Memperbarui logika kueri untuk menyaring data berdasarkan tahun yang dipilih.
2025-04-09 10:26:53 +07:00
Daeng Deni Mardaeni
22f6e3c8b2 feat(laporan): tambah fitur laporan permohonan
Menambahkan fitur laporan permohonan dengan kemampuan ekspor data ke Excel dan filtering yang komprehensif.

- Membuat view laporan_permohonan/index.blade.php untuk menampilkan daftar permohonan dalam format datatable
- Mengimplementasikan LaporanPermohonanController dengan method index, dataForDatatables, dan export
- Menambahkan fitur filter berdasarkan tanggal (start_date dan end_date) untuk memudahkan pencarian data berdasarkan rentang waktu
- Mengimplementasikan fitur pencarian global yang dapat mencari di berbagai kolom termasuk nomor_registrasi, tanggal, pemohon, cabang, dll
- Membuat LaporanPermohonanExport class yang mengimplementasikan FromCollection, WithHeadings, dan WithMapping
- Menyesuaikan export data agar konsisten dengan filter yang diterapkan pada datatable
- Menerapkan role-based filtering sehingga hanya administrator yang dapat melihat semua data
- Mengoptimalkan query dengan eager loading untuk meningkatkan performa
- Menambahkan pagination dan sorting untuk meningkatkan user experience
- Menyesuaikan tampilan status dengan badge yang berbeda warna sesuai dengan statusnya
2025-04-09 10:19:08 +07:00
Daeng Deni Mardaeni
5fa1526f1e feat(bank-data): tambahkan kategori default pada data pembanding
- Menambahkan field 'kategori' pada data pembanding.
- Menggunakan nilai default 'data_pembanding' jika kategori tidak tersedia.
2025-04-08 11:23:01 +07:00
Daeng Deni Mardaeni
6eed0f3635 feat(bank-data): tambahkan logika untuk menyimpan data objek penilaian dan data pembanding
- Menambahkan validasi untuk koordinat sebelum menyimpan data objek penilaian.
- Menggunakan metode updateOrCreate untuk menyimpan data objek penilaian dan data pembanding.
- Memperbaiki penanganan nilai default untuk beberapa atribut saat menyimpan data.
- Menambahkan logging untuk koordinat yang tidak valid.
2025-04-08 11:17:14 +07:00
Daeng Deni Mardaeni
4e9c4cea0f fix(bank-data): perbaiki logika penyimpanan data pembanding
- Menambahkan kategori 'data_pembanding' saat menyimpan data ke BankData.
- Memperbaiki penanganan koordinat yang tidak valid dengan logging.
- Memastikan data yang diambil dari request diolah dengan benar sebelum disimpan.
2025-04-08 09:39:11 +07:00
Daeng Deni Mardaeni
548956d403 feat(bank-data): tambahkan filter kategori dan sumber pada tabel bank data
- Menambahkan dropdown untuk memilih kategori pada form filter.
- Menambahkan kolom sumber pada tabel bank data.
- Mengatur warna marker pada peta berdasarkan kategori.
2025-04-08 09:38:51 +07:00
Daeng Deni Mardaeni
159dea6573 fix(migration): perbaiki fungsi down pada migrasi tabel permohonan
- Memastikan bahwa perubahan pada enum 'status_bayar' di fungsi down dilakukan dalam konteks tabel 'permohonan'.
- Menghindari kesalahan dengan menambahkan fungsi Schema::table di dalam fungsi down.
2025-04-08 09:38:06 +07:00
Daeng Deni Mardaeni
5bcc3f7e53 feat(migration): tambahkan kolom kategori pada tabel bank_data
- Menambahkan kolom 'kategori' dengan tipe enum pada tabel 'bank_data'.
- Nilai yang diizinkan untuk kolom ini adalah 'data_pembanding', 'penilaian', dan 'input'.
- Nilai default untuk kolom ini adalah 'data_pembanding'.
2025-04-08 09:36:57 +07:00
Daeng Deni Mardaeni
188fda91ce Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-04-01 05:29:54 +07:00
majid
573b2e2c74 fix(penilai): perbaikkan inputan total nilai pasar jika unit apartement 2025-03-27 10:25:22 +07:00
majid
0cf3f27a13 fix(eo):perbaikkan tombol back di eo mengarah ke penilai 2025-03-27 09:27:17 +07:00
Daeng Deni Mardaeni
8c8b7aa7c5 Merge remote-tracking branch 'composer/staging' into staging 2025-03-26 15:24:37 +07:00
putrakuningan
10cf04e05c Merge pull request 'feature/senior-officer' (#138) from feature/senior-officer into staging
Reviewed-on: #138
2025-03-26 15:15:55 +07:00
majid
1b87f62b36 fix(laporan-penilai-jaminan): perbaikkan filter tanggal dan stype llaporan 2025-03-26 15:15:55 +07:00
majid
c8183fd3c1 fix(surveyor): optimasi save data inpeksi 2025-03-26 15:15:55 +07:00
majid
e087b81655 fix(surveyor):perbaikkan save untuk unit apartement 2025-03-26 15:15:55 +07:00
majid
2a671842e4 Merge branch 'staging' into feature/senior-officer 2025-03-26 15:04:50 +07:00
majid
b1aa7bf42c fix(laporan-penilai-jaminan): perbaikkan filter tanggal dan stype llaporan 2025-03-26 15:01:19 +07:00
majid
fcbf2ba979 fix(surveyor): optimasi save data inpeksi 2025-03-26 11:07:54 +07:00
Daeng Deni Mardaeni
b8864ded0c fix(authorization): perbaiki pengecekan nilai keterangan
- Ubah metode akses nilai keterangan dari `keterangan.value()` menjadi `keterangan.value` untuk memperbaiki kesalahan dalam validasi form.
- Pastikan pesan kesalahan ditampilkan dengan benar jika keterangan tidak diisi.
2025-03-26 09:56:03 +07:00
majid
f644002c79 fix(surveyor):perbaikkan save untuk unit apartement 2025-03-26 09:34:40 +07:00
Daeng Deni Mardaeni
891e05c400 fix(surveyor): hapus link dan script flatpickr yang tidak digunakan
- Menghapus referensi stylesheet dan script flatpickr dari file index.blade.php
- Memperbaiki kebersihan kode dengan menghilangkan dependensi yang tidak diperlukan
2025-03-26 08:33:02 +07:00
Daeng Deni Mardaeni
686dec7727 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-03-26 08:31:56 +07:00
majid
1b8df943d5 fix(otorisator):perbaikkan otor paparan berdasakan nilai plafond 2025-03-25 13:29:11 +07:00
majid
2df46f1396 fix(header):perbaikkan ukuran text hubungan pemilik jaminan 2025-03-25 12:24:34 +07:00
Daeng Deni Mardaeni
825cc9c5f9 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-03-25 10:59:58 +07:00
majid
12a13c5264 fix(so):perbaikkan otorisator sesuai limit 2025-03-25 10:07:27 +07:00
majid
ee2e5e81e0 fix(surveyor):perbaikkan surveyor jadwal 2025-03-25 09:38:02 +07:00
Daeng Deni Mardaeni
a95d2de9bd fix(pdfviewer): perbarui sumber skrip PDFObject
- Mengganti URL CDN untuk PDFObject dengan asset lokal.
- Memastikan pemuatan skrip lebih cepat dan dapat diandalkan.

fix(inspeksi): perbarui sumber skrip signature pad

- Mengganti URL untuk signature pad dengan asset lokal.
- Meningkatkan keandalan pemuatan skrip.
2025-03-25 09:21:43 +07:00
Daeng Deni Mardaeni
6035400e96 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-03-25 09:03:49 +07:00
Daeng Deni Mardaeni
4178621b2c fix(inspeksi): perbarui sumber skrip signature pad
- Mengganti URL CDN untuk signature pad dengan asset lokal.
- Meningkatkan kecepatan pemuatan halaman dengan mengurangi ketergantungan eksternal.
2025-03-25 09:02:22 +07:00
majid
46167baf92 Merge branch 'staging' into feature/senior-officer 2025-03-25 08:44:13 +07:00
Daeng Deni Mardaeni
94e49a4cc3 fix(permohonan): perbarui logika dan tampilan status bayar
- Menambahkan opsi "tidak_bayar" pada status bayar.
- Memperbarui logika validasi untuk status bayar di form permohonan.
- Mengubah logika tampilan laporan berdasarkan status bayar.
- Memperbarui migrasi untuk mengubah kolom status bayar di tabel permohonan.
2025-03-24 15:09:03 +07:00
Daeng Deni Mardaeni
7d15d60b32 fix(permohonan): perbaikan logika akses pada halaman otorisasi permohonan
- Menambahkan filter berdasarkan branch_id untuk pengguna yang bukan administrator.
- Memastikan pengguna hanya dapat mengakses data yang relevan dengan cabang mereka.
2025-03-24 11:48:14 +07:00
Daeng Deni Mardaeni
b79ccac892 fix(debitur): perbaikan logika akses dan tampilan pada halaman debitur
- Menambahkan logika untuk membatasi akses data berdasarkan cabang pengguna.
- Mengubah relasi pada model Debiture dari hasOne menjadi hasMany untuk permohonan.
- Memperbarui tampilan untuk menampilkan dropdown cabang hanya untuk pengguna dengan peran administrator.
- Menambahkan input tersembunyi untuk cabang pengguna yang bukan administrator.
- Memperbarui logika di halaman index untuk memeriksa peran pengguna.
2025-03-22 16:39:16 +07:00
Daeng Deni Mardaeni
9f51a2cf4e fix(debitur): perbaikan logika akses dan tampilan pada halaman debitur
- Menambahkan relasi 'permohonan' pada query data debitur.
- Memperbaiki akses ke nomor registrasi pada dokumen jaminan.
- Mengatur tampilan tombol 'Tambah Debitur' berdasarkan peran pengguna.
- Menambahkan logika untuk memeriksa peran dan status permohonan sebelum menampilkan tombol aksi.
2025-03-22 16:29:41 +07:00
Daeng Deni Mardaeni
138b811314 fix(permohonan): perbaikan tampilan dan logika akses pada halaman permohonan
- Menambahkan kondisi untuk menampilkan tombol "Tambah Permohonan" hanya untuk pengguna dengan peran 'administrator' dan 'pemohon-ao'.
- Memperbaiki indentasi dan format HTML untuk tabel permohonan.
- Mengoptimalkan logika untuk menampilkan aksi berdasarkan status permohonan dan peran pengguna.
- Memperbaiki penanganan event input untuk pencarian data.
2025-03-22 16:29:08 +07:00
putrakuningan
e351e5c0df Merge pull request 'fix(sla): perbaikkan freeze penilai' (#137) from feature/senior-officer into staging
Reviewed-on: #137
2025-03-21 08:08:08 +01:00
majid
52f86c4f86 fix(sla): perbaikkan freeze penilai 2025-03-21 08:08:08 +01:00
majid
db0ba8cc40 fix(sla): perbaikkan freeze penilai 2025-03-21 13:55:45 +07:00
putrakuningan
fbd8805b84 Merge pull request 'feature/senior-officer' (#136) from feature/senior-officer into staging
Reviewed-on: #136
2025-03-21 05:28:37 +01:00
majid
d5a4c019cb fix(so) : perbaikkan assigment atar region dan rejecte freeze 2025-03-21 10:37:19 +07:00
majid
b6e71ac865 fix(memo): perbaikkan upload foto di memo, foto existing hilang ketika upload ulang 2025-03-21 09:55:43 +07:00
majid
850074ee7e fix(otorisator): ubah permohonan id 2025-03-20 15:35:45 +07:00
majid
bb052decae Merge branch 'staging' into feature/senior-officer 2025-03-20 11:15:20 +07:00
majid
977d53d696 fix(otorisator): perbaikkan otorisator pelaporan dan handle id assigment 2025-03-20 11:14:21 +07:00
Daeng Deni Mardaeni
9b88a601c5 fix(bankdata): perbaiki validasi dan penanganan data pembanding
- Menghapus trim pada kordinat_lat dan kordinat_lng.
- Menambahkan validasi untuk memastikan kordinat tidak null atau kosong.
- Memastikan nilai numerik untuk tahun, luas tanah, luas bangunan, harga, dan diskon.
- Menambahkan validasi untuk harga_penawaran.
2025-03-20 10:54:26 +07:00
Daeng Deni Mardaeni
cb9a650bc4 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-03-20 10:27:22 +07:00
majid
57e66642ef Merge branch 'staging' into feature/senior-officer 2025-03-20 10:23:37 +07:00
majid
155fe5f011 fix(pembanding): handle kordinat di data pembanding dan tampilan actifity team 2025-03-20 10:22:35 +07:00
majid
bfc9b989ef fix(so): perbaikkan revisi laporan so 2025-03-20 08:49:35 +07:00
Daeng Deni Mardaeni
5e50138d8e fix(otorisator): perbaikan kondisi approval pada tampilan otorisator
- Mengubah kondisi untuk memeriksa status approval dari `null` menjadi `0` untuk:
  - Senior Officer
  - EO Appraisal
  - DD Appraisal
2025-03-19 15:35:50 +07:00
majid
3430423749 fix(laporan) perbaikkan output laporan 2025-03-19 15:19:41 +07:00
majid
fa4a97a2cb fix(laporan) perbaikkan output laporan 2025-03-19 11:07:43 +07:00
putrakuningan
47b585062b Merge pull request 'feature/senior-officer' (#133) from feature/senior-officer into staging
Reviewed-on: #133
2025-03-19 04:10:30 +01:00
majid
39c5214075 fix(surveyor/penilai): perbaikan satuan luas tanah, bangunan dan penambahan total luas di denah 2025-03-19 04:10:30 +01:00
majid
0a25a32fc8 fix(surveyor): perbaikkan back halaman inspeksi dan otor paparan 2025-03-19 04:10:30 +01:00
majid
3c429a71c8 fix(surveyor/penilai): perbaikan satuan luas tanah, bangunan dan penambahan total luas di denah 2025-03-19 09:26:52 +07:00
majid
fcdcfd2757 fix(surveyor): perbaikkan back halaman inspeksi dan otor paparan 2025-03-19 08:51:12 +07:00
Daeng Deni Mardaeni
fe5f643906 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-03-18 14:41:05 +07:00
majid
f9cbc43110 Merge branch 'fix/save-penilai' into feature/senior-officer 2025-03-18 14:34:01 +07:00
majid
23c85c1539 feat(laporan-penilai-jaminan): penambahan fiture laporan penilai jaminan 2025-03-18 14:33:43 +07:00
Daeng Deni Mardaeni
644cd75522 fix(bank-data): perbaiki logika koordinat dan pembaruan pagination
- Memperbaiki pemanggilan koordinat dengan menggunakan variabel lokal.
- Menambahkan fungsi untuk memperbarui informasi pagination pada tampilan.
- Memastikan halaman saat ini tidak melebihi jumlah halaman yang tersedia.
2025-03-18 12:10:32 +07:00
Daeng Deni Mardaeni
8647063b4b fix(bank-data): perbaiki logika pemanggilan tanggal pencarian
- Memperbaiki kesalahan dalam pemanggilan parameter tanggal mulai pada metode betweenDates.
- Menggunakan nilai yang benar dari $search['start_date'] untuk memastikan pencarian tanggal berfungsi dengan baik.
2025-03-18 10:54:52 +07:00
Daeng Deni Mardaeni
1cb38ba9dd feat(bank-data): tambahkan logika untuk memasukkan data pembanding
- Mengambil data inspeksi dan memproses data pembanding.
- Memvalidasi koordinat sebelum menyimpan ke dalam database.
- Menggunakan metode updateOrCreate untuk menyimpan data bank.
- Menambahkan logging untuk koordinat yang tidak valid.
2025-03-18 09:39:10 +07:00
Daeng Deni Mardaeni
ea2f303ea4 feat(bank-data): tambahkan fitur galeri foto dan modal untuk gambar
- Menambahkan dukungan untuk menampilkan foto objek bank.
- Menambahkan modal untuk memperbesar gambar saat diklik.
- Memperbarui tampilan untuk menampilkan foto utama dan thumbnail.
- Memperbaiki lebar konten info window untuk menyesuaikan dengan gambar.
2025-03-18 08:45:31 +07:00
Daeng Deni Mardaeni
7cc687814f feat(bank-data): tambahkan tombol untuk mendapatkan petunjuk arah
- Menambahkan tombol "Get Directions" di tampilan data bank.
- Mengimplementasikan fungsi getDirections untuk membuka Google Maps dengan rute dari lokasi pengguna ke lokasi tujuan.
- Menggunakan geolocation API untuk mendapatkan lokasi pengguna saat ini.
2025-03-18 08:17:30 +07:00
majid
51d68b5c03 Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into staging 2025-03-18 08:17:27 +07:00
Daeng Deni Mardaeni
992d748a2a feat(bank-data): perbarui format alamat dan tambahkan relasi lokasi
- Memperbaiki fungsi formatAlamat untuk menggunakan kode pos dari desa.
- Menambahkan relasi ke model BankData untuk desa, distrik, kota, dan provinsi.
- Memperbarui controller BankDataController untuk menyertakan alamat dalam data yang diformat.
- Memperbarui tampilan untuk menampilkan informasi alamat dengan format yang lebih baik.
2025-03-18 08:13:55 +07:00
Daeng Deni Mardaeni
047e543d8d feat(bank-data): tambahkan info window untuk marker peta
- Menambahkan array untuk menyimpan info window.
- Membuat konten info window yang menampilkan detail aset.
- Menambahkan event listener untuk marker agar info window terbuka saat marker diklik.
- Menutup semua info window yang terbuka saat marker baru diklik.
2025-03-18 07:25:27 +07:00
Daeng Deni Mardaeni
6befc5faa7 feat(bank-data): tambahkan entri untuk data bank di module.json
- Menambahkan entri baru untuk pengelolaan data bank.
- Mengatur izin akses hanya untuk peran administrator.
- Memperbarui struktur module.json untuk mencakup data bank.
2025-03-18 07:19:58 +07:00
Daeng Deni Mardaeni
3a54b20f84 feat(bank-data): tambahkan controller dan route untuk pengelolaan data bank
- Menambahkan BankDataController untuk mengelola operasi CRUD pada data bank.
- Mengimplementasikan metode untuk menampilkan, membuat, memperbarui, dan menghapus data bank.
- Menambahkan route untuk mengakses data bank dan mengintegrasikan dengan datatables.
- Memperbarui breadcrumbs untuk menambahkan navigasi ke halaman data bank.
2025-03-18 07:19:46 +07:00
Daeng Deni Mardaeni
14e9435684 feat(bank-data): tambahkan layanan untuk pengelolaan data bank
- Menambahkan kelas BankDataService untuk mengelola data bank.
- Menyediakan metode untuk mendapatkan, membuat, memperbarui, dan menghapus data bank.
- Mengikat BankDataService di LpjServiceProvider untuk penggunaan di seluruh aplikasi.
2025-03-18 07:19:16 +07:00
Daeng Deni Mardaeni
8a7dccc784 feat(bank-data): tambahkan request validasi untuk data bank
- Menambahkan kelas BankDataRequest untuk menangani validasi input data bank.
- Mengatur aturan validasi untuk berbagai field seperti alamat, kode desa, dan harga.
- Memastikan bahwa semua field bersifat nullable dan memiliki batasan yang sesuai.
2025-03-18 07:19:07 +07:00
Daeng Deni Mardaeni
7e027680ab feat(bank-data): tambahkan model dan migrasi untuk tabel bank_data
- Menambahkan model BankData untuk mengelola data bank.
- Membuat migrasi untuk tabel bank_data dengan kolom yang diperlukan.
- Menyediakan scope untuk memfilter data berdasarkan jenis aset, desa, distrik, kota, provinsi, dan tanggal.
2025-03-18 07:18:30 +07:00
putrakuningan
ddbd98127e Merge pull request 'feature/senior-officer' (#132) from feature/senior-officer into staging
Reviewed-on: #132
2025-03-17 08:59:47 +01:00
majid
65818ab063 fix(surveyor/penilai): perbaikkan jadwal kunjungan dan print out memo 2025-03-17 08:59:47 +01:00
majid
f2dda625f4 fix(penilai):perbaikkan untuk penilaian unit apartement 2025-03-17 08:59:47 +01:00
majid
adfc1b3cec fix(surveyor/penilai): perbaikkan jadwal kunjungan dan print out memo 2025-03-17 14:54:43 +07:00
Daeng Deni Mardaeni
5c00c22b5e feat(spk): hapus pemanggilan script SweetAlert2
- Menghapus pemanggilan script SweetAlert2 dari view SPK.
- Memastikan tidak ada ketergantungan yang tidak perlu pada library eksternal.
2025-03-17 14:27:09 +07:00
Daeng Deni Mardaeni
e34f5f67f5 feat(laporanAdminKredit): perbarui logika pengolahan data permohonan
- Tambahkan variabel npw untuk menyimpan nilai pasar wajar.
- Modifikasi pengambilan nama jenis legalitas jaminan untuk menyertakan nomor dokumen jika tersedia.
2025-03-17 13:25:47 +07:00
majid
afea3ac60f Merge branches 'feature/senior-officer' and 'staging' of https://git.putrakuningan.com/daengdeni/lpj into staging 2025-03-17 13:10:35 +07:00
Daeng Deni Mardaeni
a0fe45dff7 feat(laporanAdminKredit): tambahkan model Permohonan pada controller
- Menambahkan import model Permohonan ke dalam LaporanAdminKreditController.
- Memastikan integrasi yang lebih baik dengan data permohonan saat memperbarui laporan admin kredit.
2025-03-17 13:09:05 +07:00
Daeng Deni Mardaeni
48a8623aa2 feat(laporanAdminKredit): tambahkan logika untuk memperbarui laporan admin kredit
- Mengambil data permohonan dengan relasi yang diperlukan.
- Memproses setiap permohonan untuk menyiapkan data laporan.
- Menggunakan updateOrCreate untuk menyimpan atau memperbarui laporan admin kredit.
- Menyediakan pagination untuk tampilan laporan.
2025-03-17 13:07:23 +07:00
majid
80c3eaa30a fix(penilai):perbaikkan untuk penilaian unit apartement 2025-03-17 13:05:43 +07:00
Daeng Deni Mardaeni
b2d5747a11 feat(pembatalan): perbarui logika otorisasi dan perbaikan tampilan
- Tambahkan atribut otorisasi pada model pembatalan.
- Perbarui tampilan untuk menampilkan status pembatalan yang benar.
- Perbaiki logika validasi pada form otorisasi.
- Ubah path pada module.json untuk konsistensi.
2025-03-17 12:34:13 +07:00
Daeng Deni Mardaeni
4a5a3ffaf0 feat(permohonan): tambahkan logika untuk mengunggah lampiran
- Menambahkan pemeriksaan untuk file lampiran pada permohonan.
- Menggunakan metode storeAs untuk menyimpan file dengan nama unik.
- Memastikan file disimpan di direktori 'permohonan_attachments' dengan akses publik.
2025-03-17 12:34:13 +07:00
Daeng Deni Mardaeni
941847d460 feat(config): tambahkan konfigurasi proyek untuk IDE
- Menambahkan file konfigurasi VCS untuk Git.
- Menambahkan pengaturan tema material untuk proyek.
- Menambahkan konfigurasi PHP dan alat analisis statis.
- Menghapus file .DS_Store yang tidak perlu.
2025-03-17 12:34:13 +07:00
Daeng Deni Mardaeni
7cd4c0a9b7 feat(penilaian): tambahkan logika untuk menyimpan laporan admin kredit
- Menambahkan pemanggilan model LaporanAdminKredit untuk menyimpan data ketika status permohonan adalah 'done'.
- Mengambil data dari permohonan dan penilaian untuk disimpan dalam laporan.
- Menambahkan relasi baru pada model Penilaian untuk mendapatkan informasi penilai.
2025-03-17 12:34:13 +07:00
Daeng Deni Mardaeni
c5f18bbf50 feat(helper): perbarui fungsi formatRupiah untuk mendukung desimal
- Menambahkan parameter $decimals pada fungsi formatRupiah.
- Memungkinkan format angka dengan jumlah desimal yang ditentukan.
2025-03-17 12:34:13 +07:00
Daeng Deni Mardaeni
31245457cd feat(laporan-admin-kredit): tambahkan filter tanggal pada laporan admin kredit
- Menambahkan input untuk tanggal awal dan tanggal akhir di tampilan laporan.
- Memperbarui logika pencarian untuk mendukung filter berdasarkan rentang tanggal.
- Menambahkan fungsi untuk menerapkan semua filter secara bersamaan.
2025-03-17 12:34:13 +07:00
Daeng Deni Mardaeni
831561b83b feat(laporan-admin-kredit): tambahkan fitur ekspor laporan admin kredit
- Menambahkan kelas LaporanAdminKreditExport untuk mengelola ekspor data ke Excel.
- Menambahkan metode export pada LaporanAdminKreditController untuk mengunduh laporan.
- Memperbarui tampilan untuk menambahkan tautan ekspor ke Excel.
- Menghapus kolom aksi yang tidak diperlukan dari tabel.
2025-03-17 12:34:13 +07:00
Daeng Deni Mardaeni
05b64f94e2 feat(laporan-admin-kredit): tambahkan fitur laporan admin kredit
- Menambahkan model LaporanAdminKredit.
- Menambahkan controller LaporanAdminKreditController dengan metode untuk menampilkan dan mengelola data.
- Menambahkan rute untuk laporan admin kredit.
- Menambahkan breadcrumb untuk navigasi laporan admin kredit.
- Menambahkan migrasi untuk tabel laporan_admin_kredit.
- Menambahkan relasi di model Debiture untuk laporan admin kredit.
2025-03-17 12:34:13 +07:00
putrakuningan
5d4ec11af8 Merge pull request 'fix(penilai): perbaikkan data double di table penilai -> hapus field inspeksi id dan perbaikkan format tanggal' (#131) from feature/senior-officer into staging
Reviewed-on: #131
2025-03-17 04:49:46 +01:00
majid
bbb0e006e7 fix(penilai): perbaikkan data double di table penilai -> hapus field inspeksi id dan perbaikkan format tanggal 2025-03-17 10:42:08 +07:00
majid
8f1c91827c Merge branch 'staging' into feature/senior-officer 2025-03-14 16:29:35 +07:00
majid
3ee55149fa fix(surveyor): perbaiikan save pembanding kendaraan 2025-03-14 14:30:38 +07:00
majid
05d63fe6eb Merge branch 'fix/save-penilai' into feature/senior-officer 2025-03-14 14:02:33 +07:00
majid
6fd0f35934 fix(surveyor):perbaikkan alamat 2025-03-14 11:23:55 +07:00
majid
ea18cf2fba Merge branch 'staging' into fix/save-penilai 2025-03-14 10:40:16 +07:00
majid
aa8f184b38 fix(penilai): perbaikkan helper total luas tanah, bangunan, dan handle error key pembanding 2025-03-14 10:12:14 +07:00
Daeng Deni Mardaeni
5f9ebc3b13 refactor(routes): hapus route destroy untuk jenis lampiran
- Menghapus route untuk menghapus jenis lampiran dari file routes/web.php.
- Memperbarui query pada PenilaianController untuk memuat relasi lampiran dokumen dan jenis lampiran.
2025-03-14 10:05:47 +07:00
Daeng Deni Mardaeni
9210cae2db feat(migration): ubah kolom jenis_lampiran_id menjadi nullable
- Mengubah kolom jenis_lampiran_id pada tabel lampiran_dokumen agar dapat bernilai null.
- Memastikan integritas data saat penghapusan jenis lampiran dengan opsi onDelete cascade.
2025-03-14 09:42:21 +07:00
Daeng Deni Mardaeni
950c547045 feat(migration): tambahkan foreign key jenis_lampiran_id pada tabel lampiran_dokumen
- Mengubah kolom jenis_lampiran_id menjadi foreign key yang terhubung dengan tabel jenis_lampiran.
- Menggunakan metode foreignIdFor untuk mendefinisikan relasi dan mengatur onDelete menjadi cascade.
2025-03-14 09:40:23 +07:00
Daeng Deni Mardaeni
ed8a60aa53 feat(lampiran-dokumen): tambahkan jenis lampiran pada upload dokumen
- Menambahkan validasi untuk 'jenis_lampiran_id' pada metode upload.
- Memperbarui atribut yang dapat diisi pada model LampiranDokumen.
- Menambahkan relasi jenisLampiran pada model LampiranDokumen.
- Membuat migrasi untuk menambahkan kolom 'jenis_lampiran_id' pada tabel lampiran_dokumen.
- Menghapus bagian tampilan yang tidak diperlukan dan menggantinya dengan komponen yang ada.
2025-03-14 09:37:18 +07:00
Daeng Deni Mardaeni
68f8059745 Merge remote-tracking branch 'origin/feature/senior-officer' into staging 2025-03-14 09:24:04 +07:00
Daeng Deni Mardaeni
f14a0c6343 feat(jenis-lampiran): tambahkan fitur jenis lampiran
- Menambahkan model JenisLampiran dengan relasi ke LampiranDokumen.
- Membuat migrasi untuk tabel jenis_lampiran.
- Menambahkan rute dan kontroler untuk operasi CRUD jenis lampiran.
- Menambahkan permintaan validasi untuk jenis lampiran.
- Menambahkan tampilan untuk membuat dan mengedit jenis lampiran.
- Menambahkan breadcrumb untuk navigasi jenis lampiran.
- Menambahkan fitur ekspor data jenis lampiran ke Excel.
2025-03-14 09:23:35 +07:00
majid
c00b21cfda Merge branch 'staging' into feature/senior-officer 2025-03-14 09:21:32 +07:00
majid
a3b3793fcd fix(penilai/so): prbaikkan pindah penilai dan tambah filter role penilai 2025-03-14 08:49:40 +07:00
majid
a5bd5417b7 fix(penilai): perbaikkan tampilan detail penilai 2025-03-13 11:33:49 +07:00
majid
addbfde055 fix(surveyor): perbaikkan urutan data desc di surveyor 2025-03-13 11:16:44 +07:00
majid
ff928b6257 fix(penilai): perbaikkan urutan data di menu penilai, dan perbaikkan waktu print sederhana 2025-03-13 11:14:47 +07:00
Daeng Deni Mardaeni
eb8b67a11f Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-03-13 10:10:36 +07:00
majid
fde792e56c fix(penilai/surveyor): perbaikkan luas tanah, wkatu berjalan, tanggal survey dan ganti print out standard ke standar 2025-03-13 10:02:16 +07:00
majid
a4d0a5d942 fix(alamat): perbaikkan alamat 2025-03-13 09:11:44 +07:00
majid
2a980a39f4 Merge branch 'feature/senior-officer' into fix/save-penilai 2025-03-13 08:29:33 +07:00
majid
67cffeb4af fix(surveyor): perbaikkan param hitung total luas di apartement 2025-03-13 08:28:48 +07:00
Daeng Deni Mardaeni
417f451ec9 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-03-13 08:06:20 +07:00
majid
1e485014f6 Merge branch 'staging' into feature/senior-officer 2025-03-13 07:58:31 +07:00
majid
e0691aa1b3 Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into staging 2025-03-13 07:58:02 +07:00
putrakuningan
c863a96214 Merge pull request 'fix(penilai): perbaikkan luas tanah, bangunan, dan print out sederhana, dan rap' (#129) from feature/senior-officer into staging
Reviewed-on: #129
2025-03-12 01:48:55 +01:00
majid
01de1b5b5e fix(penilai/surveyor): perbaikkan print out laporan judul di tengah dan tanggal submit surveyor/penilai 2025-03-12 01:48:55 +01:00
majid
72f7a13897 fix(penilai/so): perbaikkan menu sla unfreeze 2025-03-12 01:48:55 +01:00
majid
e2465c98fa fix(penilai/surveyor): perbaikkan print out laporan judul di tengah dan tanggal submit surveyor/penilai 2025-03-12 01:27:05 +07:00
majid
ad5181f22e Merge branches 'feature/senior-officer' and 'staging' of https://git.putrakuningan.com/daengdeni/lpj into staging 2025-03-12 01:01:08 +07:00
majid
a12c566fbd fix(penilai/so): perbaikkan menu sla unfreeze 2025-03-12 00:57:33 +07:00
Daeng Deni Mardaeni
b692ba87f8 fix(lpj): perbaiki penamaan dan logika tanggal
- Mengubah logika penentuan tanggal saat ini untuk mematuhi aturan yang berlaku.
- Menambahkan tampilan baru untuk LPJ sederhana dan standar.
- Memperbaiki penamaan rute dari 'standard' menjadi 'standar' untuk konsistensi.
- Memperbaiki akses data debitur dengan menggunakan optional chaining.
2025-03-11 21:18:49 +07:00
Daeng Deni Mardaeni
bea0c2cf78 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-03-11 13:53:56 +07:00
majid
df3e59e5c6 fix(route): ganti nama class standard ke standar 2025-03-11 13:44:03 +07:00
Daeng Deni Mardaeni
6e9006838d fix(lampiran_dokumen): tambahkan peran surveyor untuk akses file
- Memperbarui kondisi pengecekan peran pengguna untuk menyertakan 'surveyor'.
- Memastikan pengguna dengan peran surveyor dapat mengakses fungsionalitas terkait lampiran dokumen.
2025-03-11 13:36:06 +07:00
majid
ef7a47ebb9 fix(penilai): perbaikkan luas tanah, bangunan, dan print out sederhana, dan rap 2025-03-11 13:15:51 +07:00
majid
727c7a0dca Merge branch 'staging' into feature/senior-officer 2025-03-11 11:51:50 +07:00
majid
5a8b93b5f7 fix(penilai): perbaikkan keterangan freeze dan ubah name kjjp ke kjpp, handle key foto memo 2025-03-11 11:51:01 +07:00
Daeng Deni Mardaeni
06e12225b2 fix(print): perbaiki format tanggal dan optimalkan tampilan alamat
- Menambahkan format tanggal Indonesia untuk field yang mengandung 'tanggal'.
- Mengoptimalkan tampilan alamat dengan menggunakan loop untuk mengurangi duplikasi kode.
2025-03-11 11:46:17 +07:00
Daeng Deni Mardaeni
059f58842e fix(dokumen): perbaiki logika penyimpanan dokumen jaminan
- Tambahkan pengecekan untuk menentukan apakah semua file telah dihapus.
- Sesuaikan logika penyimpanan dokumen dan nomor dokumen berdasarkan kondisi file yang ada.
- Perbaiki tampilan tombol hapus file agar selalu ditampilkan.
2025-03-11 10:48:35 +07:00
Daeng Deni Mardaeni
ce792474c6 fix(dokumen): perbaiki logika penyimpanan dan penghapusan dokumen jaminan
- Memperbaiki penyimpanan dokumen baru yang diupload.
- Menangani penghapusan dokumen dari storage jika file dihapus.
- Menambahkan logika untuk memperbarui nomor dokumen yang tidak diubah.
- Memastikan detail dokumen yang diupload disimpan dengan benar.
- Menambahkan tombol untuk menghapus input file jika lebih dari satu.
2025-03-11 10:35:25 +07:00
majid
0dee937f07 perbaikkan alat berat 2025-03-10 16:14:32 +07:00
Daeng Deni Mardaeni
ea4d784182 fix(detail-jaminan): tambahkan peran 'surveyor' untuk akses form upload lampiran
- Memperbarui kondisi pengecekan peran pengguna untuk menyertakan 'surveyor'.
- Memastikan pengguna dengan peran 'surveyor' dapat mengakses form upload lampiran.
2025-03-10 15:23:27 +07:00
Daeng Deni Mardaeni
446703e9f3 fix(penilai): perbaiki penamaan 'External' menjadi 'Eksternal'
- Mengubah label 'Laporan External' menjadi 'Laporan Eksternal' untuk konsistensi bahasa.
- Memastikan penggunaan istilah yang tepat dalam tampilan laporan.
2025-03-10 14:49:59 +07:00
Daeng Deni Mardaeni
28f3b83695 fix(lampiran_dokumen): perbaiki logika penyimpanan lampiran dokumen
- Memperbaiki pengecekan peran pengguna untuk menyimpan lampiran.
- Menyederhanakan pengambilan keterangan dari fileData.
- Memastikan keterangan disimpan dengan benar saat membuat entri baru.
2025-03-10 14:46:05 +07:00
majid
1450b8e2c8 fix(surveyor): penambahan print out alat berat, kendaraan, mesin dan pesawat 2025-03-10 14:32:39 +07:00
Daeng Deni Mardaeni
73f0dd4dd6 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-03-10 14:08:22 +07:00
Daeng Deni Mardaeni
900de88ddd fix(penilai): perbaiki logika penilaian dan tampilan
- Memperbaiki logika penilaian untuk akurasi yang lebih baik.
- Menyempurnakan tampilan antarmuka agar lebih responsif.
- Menghilangkan elemen yang tidak diperlukan untuk meningkatkan pengalaman pengguna.
2025-03-10 14:08:13 +07:00
majid
25e7016486 fix(penilai): perbaikkan print out dokument jaminan 2025-03-10 13:57:31 +07:00
Daeng Deni Mardaeni
b79b65ea6c fix(surveyor): perbaiki logika pembaruan laporan eksternal
- Memperbarui status permohonan menjadi 'survey-completed' setelah validasi berhasil.
- Menambahkan kondisi untuk hanya membuat atau memperbarui laporan eksternal jika jenis penilaian adalah 'External'.
- Menggunakan relasi 'jenisPenilaian' untuk mendapatkan informasi yang diperlukan.
2025-03-10 13:43:10 +07:00
Daeng Deni Mardaeni
f864c227de Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-03-10 13:11:08 +07:00
majid
559c02afb1 fix(penilai): perbaikkan dokumen jaminan tidak tampil jika kosong, footer nama cabang di hilangkan, dan perbaikkan tanggal permohonan, kunjungan 2025-03-10 12:47:32 +07:00
Daeng Deni Mardaeni
ac667c2862 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-03-10 11:13:47 +07:00
majid
02d5e88a4e fix(penilai/so): perbaikkan nilai npw dan team activity pindah user atau region 2025-03-10 11:11:20 +07:00
majid
16a321c27b Merge branch 'staging' into feature/senior-officer 2025-03-10 10:41:52 +07:00
Daeng Deni Mardaeni
bd801d3235 Merge remote-tracking branch 'composer/feature/senior-officer' into staging
# Conflicts:
#	app/Helpers/Lpj.php
2025-03-10 10:41:19 +07:00
majid
3dcf833035 fix(penilai) : perbaikan nomor laporan dan tanggal laporan 2025-03-10 10:40:19 +07:00
Daeng Deni Mardaeni
de6e7ad732 feat(permohonan): tambahkan relasi laporanExternal dan perbarui query show
- Menambahkan method laporanExternal pada model Permohonan untuk mendefinisikan relasi dengan LaporanExternal.
- Memperbarui query pada method show di PenilaiController untuk menyertakan relasi jenisPenilaian dan laporanExternal.
2025-03-10 10:37:19 +07:00
Daeng Deni Mardaeni
18b1e37cee Merge remote-tracking branch 'origin/feature/senior-officer' into staging 2025-03-10 10:14:12 +07:00
Daeng Deni Mardaeni
e8e86186e7 feat(activity): tambahkan fitur upload lampiran dokumen
- Menambahkan bagian baru untuk lampiran dokumen pada detail aktivitas.
- Memperbarui pengecekan peran pengguna untuk mengizinkan admin mengupload lampiran.
- Mengorganisir tampilan lampiran dokumen dengan opsi untuk melihat dan mengunduh.
2025-03-10 10:11:43 +07:00
majid
2573616612 fix(surveyor): perbaikkan print out surveyor border di hilangkan 2025-03-10 10:06:42 +07:00
Daeng Deni Mardaeni
8d1dacb334 fix(penawaran): perbaiki konversi luas tanah dan bangunan menjadi integer
- Mengubah konversi luas tanah dan bangunan dari string ke integer.
- Memastikan nilai yang diakumulasi adalah angka yang valid.
- Meningkatkan keakuratan perhitungan luas dalam tampilan email dan surat tender.
2025-03-10 10:05:21 +07:00
Daeng Deni Mardaeni
06ea38fa5f fix(detail-jaminan): perbaiki pengecekan peran pengguna
- Mengubah pengecekan peran pengguna dari 'penilai' menjadi 'Penilai' untuk konsistensi.
- Menambahkan peran 'penilai' dalam pengecekan untuk memastikan akses yang tepat.
2025-03-10 08:56:36 +07:00
Daeng Deni Mardaeni
ee0419578e fix(Lpj): perbaiki nilai default untuk created_at
- Menambahkan nilai default "-" jika created_at tidak tersedia.
- Memastikan fungsi getNomorLaporan mengembalikan nilai yang konsisten.
2025-03-10 08:44:04 +07:00
Daeng Deni Mardaeni
2210f41337 fix(tender): ubah redirect untuk email penawaran
- Mengganti redirect dari route spesifik ke redirect kembali.
- Memastikan pesan sukses dan error tetap ditampilkan setelah pengiriman email.
2025-03-10 07:54:30 +07:00
Daeng Deni Mardaeni
106fd2514b fix(penawaran): ubah nilai awal luas tanah dan bangunan menjadi 0
- Mengubah nilai awal variabel luas tanah dan bangunan dari string kosong menjadi 0.
- Perubahan ini dilakukan di beberapa file tampilan untuk konsistensi data.
2025-03-10 07:46:58 +07:00
Daeng Deni Mardaeni
1ac775c224 Merge remote-tracking branch 'origin/feature/senior-officer' into staging 2025-03-10 07:40:22 +07:00
Daeng Deni Mardaeni
4464943dd0 fix(detail-jaminan): perbaiki tampilan dokumen jaminan
- Menambahkan pengecekan untuk memastikan dokumen jaminan ada sebelum ditampilkan.
- Memperbaiki struktur HTML untuk memastikan elemen ditampilkan dengan benar.
2025-03-10 07:40:13 +07:00
Daeng Deni Mardaeni
c572f061e3 fix(penawaran): ubah nilai awal luas tanah dan bangunan menjadi string kosong
- Mengubah nilai awal dari `null` menjadi string kosong (`""`) pada beberapa file.
- Memastikan konsistensi dalam penanganan data saat memproses detail dokumen.
- Meningkatkan kejelasan dan menghindari potensi kesalahan saat memanipulasi data.
2025-03-10 07:39:39 +07:00
majid
c8a1e401c8 Merge branch 'staging' into feature/senior-officer 2025-03-10 04:26:12 +07:00
majid
117e82765c fix(penilai) : perbaikkan , tampilan tanggal permohonan, konfirmasi kunjunagan, laporan, dan survey, ganti nama tempat ke peta lokasi 2025-03-10 04:19:34 +07:00
majid
c37ac7e120 fix(surveyor):perbaikkan print out nama wakil debitur jika lebih dari satu maka ke bawah 2025-03-10 04:03:36 +07:00
majid
2043335042 fix(surveyor) : penambahan tombol switch objek penilaian, tambah luas fisik bangunan, dan print out linkungan 2025-03-10 03:58:48 +07:00
putrakuningan
ac9c5f8666 Merge pull request 'fix(penilai): perbaikkan nama judul lampiran' (#128) from feature/senior-officer into staging
Reviewed-on: #128
2025-03-09 12:23:34 +01:00
majid
ca11e59ae1 fix(penilai): perbaikkan nama judul lampiran 2025-03-09 12:23:34 +01:00
majid
83203bf43a fix(penilai): perbaikkan nama judul lampiran 2025-03-09 18:15:43 +07:00
Daeng Deni Mardaeni
b2a4aca049 fix(pembayaran): hapus pembuatan laporan eksternal di PembayaranController
- Menghapus kode yang membuat entri LaporanExternal di PembayaranController.
- Memindahkan logika pembuatan LaporanExternal ke SurveyorController.
2025-03-09 15:22:34 +07:00
Daeng Deni Mardaeni
73bbd87bfb Merge remote-tracking branch 'origin/feature/senior-officer' into staging 2025-03-09 12:34:25 +07:00
Daeng Deni Mardaeni
08cc816fb6 fix(laporan-external): perbaiki penamaan properti tujuan penilaian
- Mengubah penamaan properti dari `tujuanPenilaianKjpp` menjadi `tujuan_penilaian_kjpp` pada tampilan laporan eksternal.
- Memastikan konsistensi dalam penggunaan nama properti di seluruh aplikasi.
2025-03-09 12:33:51 +07:00
majid
a2cd9a4e55 Merge branch 'fix/save-penilai' into feature/senior-officer 2025-03-09 12:26:24 +07:00
majid
4b8a080ed5 fix(penilai):perbaikkan printout sederhana dan tanah 2025-03-09 12:25:58 +07:00
Daeng Deni Mardaeni
9d0e2225a3 fix(lampiran-dokumen): perbaiki bug pada proses upload lampiran
- Memperbaiki masalah yang menyebabkan kegagalan saat mengupload lampiran.
- Menambahkan validasi untuk memastikan format file yang diupload sesuai.
- Meningkatkan respons server untuk memberikan informasi yang lebih jelas kepada pengguna.
2025-03-09 11:25:34 +07:00
Daeng Deni Mardaeni
39dabbaeb5 fix(lampiran-dokumen): perbaiki respons upload dan delete lampiran
- Mengubah respons dari JSON menjadi redirect dengan pesan sukses atau error.
- Menambahkan konfirmasi sebelum menghapus lampiran untuk pengguna dengan peran administrator.
- Memperbaiki tampilan link download dan view lampiran agar lebih terstruktur.
2025-03-09 11:10:01 +07:00
Daeng Deni Mardaeni
33667ede21 feat(lampiran-dokumen): tambahkan fitur upload, download, dan delete lampiran dokumen
- Menambahkan controller LampiranDokumenController untuk mengelola lampiran dokumen.
- Menambahkan model LampiranDokumen untuk interaksi dengan tabel lampiran_dokumen.
- Membuat migrasi untuk tabel lampiran_dokumen dengan kolom yang diperlukan.
- Menambahkan rute untuk mengupload, mendownload, dan menghapus lampiran dokumen.
- Memperbarui tampilan detail-jaminan untuk menampilkan dan mengelola lampiran dokumen.
2025-03-09 10:49:51 +07:00
majid
f068c6b2d1 fix(surveyor) : hapus baris kode yang tidak perlu 2025-03-09 05:14:43 +07:00
majid
b29998bcbc Merge branch 'staging' into fix/save-penilai 2025-03-09 05:12:47 +07:00
Daeng Deni Mardaeni
9619b74695 feat(jenis-legalitas-jaminan): tambahkan endpoint untuk mengambil custom fields
- Menambahkan metode `getCustomFields` pada `JenisLegalitasJaminanController` untuk mengembalikan custom fields berdasarkan ID.
- Memperbarui tampilan untuk menggunakan ID jenis legalitas jaminan saat menambahkan input file.
- Mengubah fungsi `addFileInput` untuk menerima ID jenis legalitas jaminan dan mengambil custom fields yang relevan.
- Memperbarui rute untuk menambahkan endpoint baru yang mengarah ke metode `getCustomFields`.
2025-03-08 21:27:25 +07:00
Daeng Deni Mardaeni
7d7e19cdce Merge branch 'staging-temp' into staging 2025-03-08 18:34:52 +07:00
Daeng Deni Mardaeni
c77a95addf fix(penawaran): perbaiki pengolahan luas tanah dan bangunan pada dokumen
- Mengubah cara pengambilan dan penjumlahan luas tanah dan bangunan.
- Memastikan nilai luas tanah dan bangunan ditampilkan dengan benar.
- Mengoptimalkan pengolahan data detail dokumen untuk meningkatkan kejelasan.
2025-03-08 18:34:17 +07:00
Daeng Deni Mardaeni
a87bec22d0 fix(dokumen_jaminan): perbaiki pengambilan dan penyimpanan data dokumen jaminan
- Memperbaiki pengecekan kondisi saat mengambil detail dokumen.
- Menambahkan penanganan untuk file yang diupload dan yang tidak diubah.
- Memastikan nomor dokumen selalu diperbarui, baik saat file diubah atau tidak.
- Menghapus dokumen yang tidak ada lagi dari daftar jika ada perubahan.
2025-03-08 18:34:17 +07:00
majid
340dce7ed7 fix(penilai/surveyor): perbaikkan print out dokument jaminan 2025-03-08 18:34:17 +07:00
Daeng Deni Mardaeni
d52edb9481 fix(dokumen_jaminan): perbaiki pengambilan data detail dokumen
- Memperbaiki logika pengambilan data 'details' pada Dokumen Jaminan.
- Mengubah cara pengolahan data luas tanah dan luas bangunan untuk akurasi.
- Memperbaiki tampilan data pada email dan komponen jaminan.
2025-03-08 18:33:40 +07:00
Daeng Deni Mardaeni
5932192d92 fix(dokumen): perbaikan pengambilan detail dokumen jaminan
- Memperbaiki pengambilan data `details` pada `DokumenJaminanController`.
- Mengubah indeks pengambilan `custom_field` dari `$value` menjadi `$key`.
- Memperbaiki tampilan detail dokumen jaminan di view `jaminan.blade.php`.
- Menambahkan penanganan untuk menampilkan nomor dokumen dan detail yang sesuai.
2025-03-08 18:33:40 +07:00
Daeng Deni Mardaeni
211e44f804 fix(penawaran): perbaiki pengolahan luas tanah dan bangunan pada dokumen
- Mengubah cara pengambilan dan penjumlahan luas tanah dan bangunan.
- Memastikan nilai luas tanah dan bangunan ditampilkan dengan benar.
- Mengoptimalkan pengolahan data detail dokumen untuk meningkatkan kejelasan.
2025-03-08 17:52:02 +07:00
Daeng Deni Mardaeni
bc281e3512 fix(dokumen_jaminan): perbaiki pengambilan dan penyimpanan data dokumen jaminan
- Memperbaiki pengecekan kondisi saat mengambil detail dokumen.
- Menambahkan penanganan untuk file yang diupload dan yang tidak diubah.
- Memastikan nomor dokumen selalu diperbarui, baik saat file diubah atau tidak.
- Menghapus dokumen yang tidak ada lagi dari daftar jika ada perubahan.
2025-03-08 17:47:11 +07:00
putrakuningan
3101cca619 Merge pull request 'feature/senior-officer' (#126) from feature/senior-officer into staging
Reviewed-on: #126
2025-03-08 08:55:46 +01:00
majid76
a9edbe6838 fix(surveyor): perbaikan nama tanda tangan dan free text lainnya 2025-03-08 08:55:46 +01:00
majid76
a227b8ec29 fix(surveyor): perbaikkan upload foto data pembanding 2025-03-08 08:55:46 +01:00
majid
0976794aa2 fix(penilai): perbaikkan save penilai dan free text jenis asset lainnya 2025-03-08 08:55:46 +01:00
majid
b24f55e4b4 fix(surveyor): perbaikkan jenis asset dan pergantian argis per region 2025-03-08 08:55:46 +01:00
majid76
ef5ae2e161 fix(surveyor): perbaikan nama tanda tangan dan free text lainnya 2025-03-08 14:48:50 +07:00
majid76
e546c5241d Merge branch 'staging' into feature/senior-officer 2025-03-08 14:17:46 +07:00
majid76
e3f668fdc8 fix(surveyor): perbaikkan upload foto data pembanding 2025-03-08 14:11:19 +07:00
majid
0956f5a4a9 fix(penilai): perbaikkan save penilai dan free text jenis asset lainnya 2025-03-08 03:36:34 +07:00
majid
935529562a fix(penilai/surveyor): perbaikkan print out dokument jaminan 2025-03-08 01:12:52 +07:00
putrakuningan
ad3dce4922 Merge pull request 'feature/senior-officer' (#125) from feature/senior-officer into staging
Reviewed-on: #125
2025-03-07 11:27:39 +01:00
majid
a29e72f5cc fix(penilai): perbaikkan save penilai dan foto lampiran, kembali ke back 2025-03-07 11:27:39 +01:00
majid
0c33c1e070 fix(penilai): perbaikkan save laporan di penilai 2025-03-07 11:27:39 +01:00
majid
5300254a6d Merge remote-tracking branch 'origin/staging-temp' into fix/sertipikat-pemohon-surveyor 2025-03-07 17:19:24 +07:00
majid
d16c625991 fix(surveyor): perbaikkan jenis asset dan pergantian argis per region 2025-03-07 17:15:00 +07:00
Daeng Deni Mardaeni
dd46a02626 feat(laporan_external): tambahkan relasi jenis jaminan pada data laporan
- Memperbarui query untuk mengambil data jenis jaminan dari relasi dokumen jaminan.
- Menambahkan relasi 'permohonan.dokumenjaminan.jenisjaminan' pada pengambilan data.
2025-03-07 16:54:57 +07:00
Daeng Deni Mardaeni
03d28479c4 fix(dokumen_jaminan): perbaiki pengambilan data detail dokumen
- Memperbaiki logika pengambilan data 'details' pada Dokumen Jaminan.
- Mengubah cara pengolahan data luas tanah dan luas bangunan untuk akurasi.
- Memperbaiki tampilan data pada email dan komponen jaminan.
2025-03-07 16:50:09 +07:00
majid
7398753351 Merge branch 'staging' into feature/senior-officer 2025-03-07 16:08:35 +07:00
majid
16a805e853 fix(penilai): perbaikkan save penilai dan foto lampiran, kembali ke back 2025-03-07 16:08:01 +07:00
Daeng Deni Mardaeni
e1bb30c768 feat(laporan_external): tambahkan kolom jenis jaminan pada tabel
- Menambahkan kolom "Jenis Jaminan" pada tampilan tabel laporan eksternal.
- Memperbarui logika untuk menampilkan jenis jaminan dari data permohonan.
2025-03-07 14:32:23 +07:00
Daeng Deni Mardaeni
32c4c7e57b fix(laporan_external): perbaiki pengambilan data dan update tampilan tabel
- Mengubah query untuk mengambil data dengan relasi yang lebih lengkap.
- Menambahkan kolom 'Nama Debitur' dan 'Tujuan Penilaian' pada tampilan tabel.
- Menghapus kolom yang tidak diperlukan untuk menyederhanakan tampilan.
2025-03-07 14:28:31 +07:00
Daeng Deni Mardaeni
ae59500b1e Merge remote-tracking branch 'composer/feature/senior-officer' into staging
# Conflicts:
#	resources/views/penilai/show.blade.php
2025-03-07 14:11:18 +07:00
majid
69de63648f fix(penilai): perbaikkan save laporan di penilai 2025-03-07 14:07:51 +07:00
majid
50ce815ac1 fix(surveyor) :hilakan tobol save luas tanah, bagunna, ubah message ke keterangan 2025-03-07 13:40:33 +07:00
Daeng Deni Mardaeni
3c7302c857 fix(spk): perbaiki logika pembaruan SLA
- Validasi input SLA untuk memastikan nilai yang diterima adalah integer dan lebih dari 0.
- Mengubah cara pengambilan data Permohonan berdasarkan nomor registrasi dari PenawaranTender.
2025-03-07 13:34:25 +07:00
majid
3e9d9e3769 Merge branch 'staging' into fix/sertipikat-pemohon-surveyor 2025-03-07 11:26:42 +07:00
putrakuningan
3f8ea222e1 Merge pull request 'feature/senior-officer' (#123) from feature/senior-officer into staging
Reviewed-on: #123
2025-03-07 05:25:44 +01:00
majid
1376a92020 fix(surveyor): perbaikkan proses jadwal dan hapus nib di form inspeksi 2025-03-07 05:25:44 +01:00
majid
f12432dfc5 fix(penilai): print out laporan 2025-03-07 05:25:44 +01:00
majid
796b6fab92 fix(surveyor): perbaikkan foto dan print out hasil inspeksi 2025-03-07 05:25:44 +01:00
Daeng Deni Mardaeni
cf6e008502 fix(registrasi): perbaiki logika penanganan jenis penilaian
- Menambahkan variabel untuk menyimpan ID jenis penilaian.
- Memperbaiki kondisi untuk menampilkan atau menyembunyikan div region berdasarkan jenis penilaian.
- Mengatur nilai jenis laporan sesuai dengan jenis penilaian yang dipilih.
2025-03-07 11:23:42 +07:00
majid
426ca5ebb2 Merge branch 'staging' into feature/senior-officer 2025-03-07 11:18:52 +07:00
majid
345cbbe22c fix(surveyor): perbaikkan proses jadwal dan hapus nib di form inspeksi 2025-03-07 11:17:31 +07:00
Daeng Deni Mardaeni
b319abbabb fix(permohonan): perbaiki tampilan keterangan pada form dan index
- Menambahkan registrasi_catatan ke dalam tampilan keterangan pada form permohonan.
- Memperbarui logika render keterangan di index untuk menyertakan registrasi_catatan jika ada.
2025-03-07 11:06:20 +07:00
majid
85711db4d5 Merge branch 'staging' into feature/senior-officer 2025-03-07 10:48:46 +07:00
majid
3e6613f955 fix(penilai): print out laporan 2025-03-07 10:46:24 +07:00
majid
69e888c6d4 fix(surveyor): perbaikkan foto dan print out hasil inspeksi 2025-03-07 10:11:26 +07:00
Daeng Deni Mardaeni
e830ededf2 fix(spk): perbaiki margin pada tampilan KJPP
- Menghapus margin-left pada elemen KJPP di file documentSPK.blade.php
- Menghapus margin-left pada elemen KJPP di file edit.blade.php
2025-03-07 10:00:45 +07:00
Daeng Deni Mardaeni
d089419cfb feat(registrasi): tambahkan pilihan jenis laporan pada halaman registrasi
- Menambahkan dropdown untuk memilih jenis laporan.
- Opsi yang tersedia: Sederhana dan Standar.
- Memperbaiki struktur HTML untuk meningkatkan keterbacaan.
2025-03-07 09:55:00 +07:00
Daeng Deni Mardaeni
f7c85fc24e feat(penilai): tambahkan fitur unggah foto dan simpan memo dengan foto
- Menambahkan metode `uploadTempPhoto` untuk mengunggah foto sementara.
- Menambahkan metode `storeMemoWithPhotos` untuk menyimpan memo beserta foto.
- Memperbarui rute untuk mendukung pengunggahan foto dan penyimpanan memo.
- Memperbarui tampilan untuk menampilkan foto yang sudah ada dan mengubah ID dropzone.
2025-03-07 09:53:55 +07:00
Daeng Deni Mardaeni
5d380f1a68 fix(activity): perbaiki pengambilan data pada ActivityController
- Mengaktifkan kembali pengambilan data dengan relasi yang diperlukan.
- Memastikan data yang diambil mencakup relasi 'user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian', 'dokumenjaminan', dan 'nilaiPlafond'.
2025-03-07 09:39:30 +07:00
Daeng Deni Mardaeni
a048bea26e fix(activity): perbaiki logika perhitungan tanggal SLA dan paparan
- Memperbaiki perhitungan tanggal selesai berdasarkan hari tambahan.
- Menambahkan logika untuk menghitung hari kerja berikutnya.
- Mengubah nama kolom pada tampilan dari "Due Date SLA" menjadi "SLA Laporan" dan "Paparan" menjadi "SLA Paparan".
- Menambahkan detail dokumen pada query di LaporanController.
2025-03-07 09:21:14 +07:00
putrakuningan
dc98c7dd63 Merge pull request 'fix(surveyor):perbaikkan print out form inspeksi dan penambahan helper nama detail jaminan, dan form penilaian lpj' (#122) from feature/senior-officer into staging
Reviewed-on: #122
2025-03-07 02:36:58 +01:00
majid
6a188e1983 fix(surveyor):perbaikkan print out form inspeksi dan penambahan helper nama detail jaminan, dan form penilaian lpj 2025-03-07 02:36:58 +01:00
Daeng Deni Mardaeni
704f52392f fix(penilaian): perbaiki logika otorisasi dan penanganan dataHeader
- Memperbaiki logika untuk mendapatkan otorisasi berdasarkan jenis laporan.
- Menambahkan pengecekan untuk memastikan $permohonan->authorization->approve_so ada sebelum digunakan.
- Memperbarui fungsi handleRejection untuk menerima parameter dataHeader.
2025-03-07 08:01:41 +07:00
majid
5fa6f2c9ef fix(surveyor):perbaikkan print out form inspeksi dan penambahan helper nama detail jaminan, dan form penilaian lpj 2025-03-07 07:37:16 +07:00
Daeng Deni Mardaeni
2cba48afa9 feat(laporan): tambahkan format tanggal dan perhitungan due date SLA
- Menambahkan fungsi formatDate untuk menampilkan tanggal dalam format Indonesia.
- Menambahkan logika perhitungan due date SLA berdasarkan tujuan penilaian dan tipe laporan.
- Memperbarui render tanggal survei dan due date SLA di tabel laporan.
2025-03-06 18:50:17 +07:00
Daeng Deni Mardaeni
ec457b24b7 fix(penilai): perbaiki perbandingan string untuk tujuan penilaian dan tipe laporan
- Mengubah operator perbandingan dari `==` menjadi `===` untuk tujuan penilaian.
- Mengubah operator perbandingan dari `==` menjadi `===` untuk tipe laporan.
- Mengubah operator perbandingan dari `==` menjadi `===` untuk nilai plafon.
2025-03-06 18:50:08 +07:00
Daeng Deni Mardaeni
50babb212f feat(penilai): tambahkan logika perhitungan due date SLA berdasarkan tujuan penilaian
- Menambahkan variabel tujuan_penilaian untuk menentukan jenis penilaian.
- Memperbarui logika perhitungan due date SLA untuk tujuan penilaian "RAP".
- Memastikan perhitungan waktu penilaian tetap berlaku untuk tipe laporan "sederhana" dan "standar".
2025-03-06 18:46:09 +07:00
Daeng Deni Mardaeni
a1e98090a8 feat(penilai): tambahkan kolom jenis laporan dan perhitungan due date SLA
- Menambahkan kolom "Jenis Laporan" pada tampilan daftar penilai.
- Memperbarui logika perhitungan due date SLA berdasarkan tipe laporan dan nilai plafond.
- Menyertakan relasi 'penilai' dan 'nilaiPlafond' dalam query untuk pengambilan data.
2025-03-06 18:17:02 +07:00
Daeng Deni Mardaeni
f9764b6819 feat(registrasi): tambahkan pilihan jenis laporan pada form registrasi
- Menambahkan dropdown untuk memilih jenis laporan (sederhana, standar) di form registrasi.
- Memperbarui data Penilai berdasarkan jenis laporan yang dipilih saat registrasi diperbarui.
2025-03-06 17:50:30 +07:00
Daeng Deni Mardaeni
99343fee34 fix(otorisator): perbaiki ID yang digunakan dalam fungsi otorisator
- Mengubah parameter ID yang digunakan dalam fungsi otorisator untuk memastikan data yang tepat dikirim.
- Memperbaiki referensi ID dari permohonan ke authorization untuk konsistensi.
2025-03-06 16:35:12 +07:00
Daeng Deni Mardaeni
1474f6af74 fix(form-penilai): perbaiki ID input dan tambahkan penanganan null
- Mengubah ID input dari 'luas_npw_' menjadi 'ls_npw_' untuk konsistensi.
- Menambahkan penanganan null pada elemen telepon di informasi pembanding.
- Memastikan bahwa elemen total nilai pasar wajar diperbarui dengan benar.
2025-03-06 15:54:56 +07:00
majid
d37ebeff3c Merge branch 'staging' into feature/senior-officer 2025-03-06 13:13:49 +07:00
majid
2c3f507c03 fix(penilai): penambahan edit data pembanding, dan perbaikkan lihat detail penilai 2025-03-06 13:11:45 +07:00
Daeng Deni Mardaeni
d9c8e380f2 feat(dokumen): tambahkan fitur hapus detail dokumen
- Menambahkan metode `clearDetail` pada `DokumenJaminanController` untuk menghapus detail dokumen.
- Menghapus file terkait saat detail dihapus.
- Menambahkan tombol untuk menghapus detail pada tampilan dokumen.
- Mengimplementasikan konfirmasi penghapusan menggunakan SweetAlert.
- Menambahkan rute baru untuk mengakses metode `clearDetail`.
2025-03-06 11:59:16 +07:00
Daeng Deni Mardaeni
876dd3fbe8 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-03-06 11:29:04 +07:00
Daeng Deni Mardaeni
e56ed2f0aa fix(otorisasipenawaran): hapus elemen card yang tidak diperlukan
- Menghapus div card border yang tidak digunakan.
- Memperbaiki tampilan layout pada halaman otorisasi penawaran.
2025-03-06 11:28:33 +07:00
majid
7cc75c56ae fix(surveyor): perbaikan alamat di surveyor 2025-03-06 11:26:53 +07:00
Daeng Deni Mardaeni
bf71037516 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-03-06 11:03:36 +07:00
majid
0289eb35a2 fix(surveyor) :perbaikkan alamat dan luas unit 2025-03-06 10:56:21 +07:00
Daeng Deni Mardaeni
d4e46594c4 fix(detail-jaminan): perbarui format alamat pemilik
- Mengganti tampilan alamat pemilik dengan fungsi formatAlamat.
- Mengurangi kompleksitas kode dengan menghilangkan beberapa baris.
2025-03-06 10:47:20 +07:00
majid
5c6b22c122 fix(surveyor): ubah variable key luas unit 2025-03-06 10:46:29 +07:00
Daeng Deni Mardaeni
cf278e0fd6 fix(penawaran_ulang): sembunyikan tombol kirim email
- Mengubah kelas tombol kirim email menjadi 'hidden' untuk menyembunyikannya dari tampilan.
- Memastikan tampilan antarmuka lebih bersih dengan menyembunyikan elemen yang tidak diperlukan.
2025-03-06 10:29:46 +07:00
Daeng Deni Mardaeni
d4ce908394 fix(laporan_external): perbarui kolom pada tabel laporan eksternal
- Menambahkan nullable pada kolom tgl_final_laporan dan nilai terkait.
- Menambahkan kolom baru untuk file_resume dan file_laporan.
2025-03-06 10:23:50 +07:00
Daeng Deni Mardaeni
bd391bacec fix(registrasi): hapus field SLA dari form registrasi
- Menghapus field SLA dari tampilan form registrasi.
- Memperbarui validasi untuk tidak lagi memerlukan SLA.
- Menyesuaikan penanganan data di controller dan JavaScript.
2025-03-06 10:13:31 +07:00
Daeng Deni Mardaeni
adbe57e709 feat(pembayaran): tambahkan pembuatan laporan eksternal
- Menambahkan logika untuk membuat laporan eksternal setelah pembaruan data permohonan.
- Menggunakan model LaporanExternal untuk menyimpan data laporan.
- Memastikan bahwa laporan mencakup ID permohonan dan nomor registrasi.
2025-03-06 10:13:08 +07:00
Daeng Deni Mardaeni
dd5271a40b feat(laporan_external): tambahkan fitur laporan eksternal
- Menambahkan entri untuk Laporan External di module.json.
- Menambahkan breadcrumb untuk Laporan External di breadcrumbs.php.
- Membuat migrasi untuk tabel laporan_externals.
- Menambahkan rute untuk Laporan External di web.php.
- Memperbarui validasi di LaporanExternalRequest untuk mendukung nullable fields.
- Mengimplementasikan LaporanExternalController untuk menangani operasi CRUD.
2025-03-06 09:56:59 +07:00
Daeng Deni Mardaeni
38b22bce38 feat(laporan_external): tambahkan fitur laporan eksternal
- Menambahkan controller LaporanExternalController untuk mengelola laporan eksternal.
- Menambahkan request LaporanExternalRequest untuk validasi data laporan eksternal.
- Menambahkan model LaporanExternal untuk interaksi dengan database.
- Menambahkan migrasi untuk tabel laporan_externals dengan kolom yang diperlukan.
2025-03-06 08:41:03 +07:00
Daeng Deni Mardaeni
ff4d48704f fix(spk): perbaiki tampilan dan penanganan data KJPP
- Menambahkan prefiks "KJPP" pada nama KJPP di tampilan.
- Memperbaiki penanganan peran pengguna untuk 'DD Appraisal' menjadi 'DD Operation 2'.
2025-03-06 08:12:18 +07:00
Daeng Deni Mardaeni
0933a874dc fix(otorisasipenawaran): perbaiki tampilan dan penanganan data penawaran
- Menambahkan relasi permohonan dan tujuan penilaian KJPP pada metode show.
- Memperbarui tampilan detail jaminan untuk menampilkan nomor penawaran dan tujuan penilaian KJPP.
- Menggunakan komponen untuk menyederhanakan kode dan meningkatkan keterbacaan.
2025-03-06 08:08:00 +07:00
Daeng Deni Mardaeni
14ac13551b fix(spk): perbaiki penanganan data dan tampilan KJPP
- Tambahkan penanganan default untuk waktu penilaian yang mungkin null.
- Ubah tampilan nama KJPP di dokumen SPK dan halaman edit untuk menambahkan label "KJPP".
- Ganti pengambilan nama dan peran creator persetujuan penawaran dengan fungsi getUser untuk meningkatkan keterbacaan.
2025-03-06 07:48:29 +07:00
Daeng Deni Mardaeni
90be8d5730 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-03-06 07:47:54 +07:00
majid
6814113cbf Merge remote-tracking branch 'origin/temp' into fix/sertipikat-pemohon-surveyor 2025-03-06 05:28:30 +07:00
majid
65bfa9eeec fix(pemohon/survey): penambahan resedule di awal pemohon dan resedule suveyor, dan perbaikkan tolak paparan, dan perbaikkan struktur foto 2025-03-06 05:16:48 +07:00
majid
3f3c384f9a fix(so): perbaikan team activity total task 2025-03-05 23:04:04 +07:00
Daeng Deni Mardaeni
73d76a000d fix(dokumen): perbaikan pengambilan detail dokumen jaminan
- Memperbaiki pengambilan data `details` pada `DokumenJaminanController`.
- Mengubah indeks pengambilan `custom_field` dari `$value` menjadi `$key`.
- Memperbaiki tampilan detail dokumen jaminan di view `jaminan.blade.php`.
- Menambahkan penanganan untuk menampilkan nomor dokumen dan detail yang sesuai.
2025-03-05 16:25:43 +07:00
putrakuningan
e9ec75219a Merge pull request 'feature/senior-officer' (#118) from feature/senior-officer into staging
Reviewed-on: #118
2025-03-05 10:02:07 +01:00
majid
50029c6b07 fix(so):perbaikkan revisi laporan 2025-03-05 15:57:27 +07:00
majid
40fc1166ba fix(permohona/so):perbaikan resedule dan revisi paparan 2025-03-05 15:53:20 +07:00
majid
dd5f0f94b5 Merge branch 'staging' into feature/senior-officer 2025-03-05 15:19:52 +07:00
majid
1a770820cf fix(pemohon): perbaikan resedule jadwal di pemohon 2025-03-05 15:18:58 +07:00
putrakuningan
93c5058afa Merge pull request 'feature/senior-officer' (#116) from feature/senior-officer into staging
Reviewed-on: #116
2025-03-05 08:49:09 +01:00
majid
3ac83aa7fe fix(surveyor/so): perbaikkan back di surveyor, luas denah decimal dan revisi di so 2025-03-05 08:49:09 +01:00
Daeng Deni Mardaeni
16aabd5da0 fix(permohonan): ubah status_bayar menjadi nullable dan perbaiki tampilan form
- Mengubah validasi 'status_bayar' dari 'required' menjadi 'nullable'.
- Menambahkan ID wrapper untuk 'status_bayar' di form.
- Menyembunyikan atau menampilkan wrapper 'status_bayar' berdasarkan kondisi tertentu.
2025-03-05 14:37:52 +07:00
majid
6d925bb15b Merge branch 'staging' into feature/senior-officer 2025-03-05 14:33:36 +07:00
majid
23afbc7ece fix(surveyor/so): perbaikkan back di surveyor, luas denah decimal dan revisi di so 2025-03-05 14:31:55 +07:00
Daeng Deni Mardaeni
81727e0f52 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-03-05 14:29:12 +07:00
majid
976dab7566 Merge branch 'staging' into feature/senior-officer 2025-03-05 13:35:12 +07:00
majid
05bf9e2af0 fix(surveyor): perbaikan print out hasil inspeksi 2025-03-05 13:33:02 +07:00
Daeng Deni Mardaeni
d813fb10e1 fix(spk): hapus tampilan SLA dari komponen
- Menghapus elemen SLA dari tampilan komponen SPK.
- Memastikan tampilan lebih bersih dan fokus pada fungsi utama.
2025-03-05 12:56:47 +07:00
Daeng Deni Mardaeni
4a05b9e903 feat(spk): tambahkan fitur pembaruan SLA
- Menambahkan metode updateSla pada SpkController untuk memperbarui SLA.
- Memvalidasi input SLA agar wajib diisi dan berupa angka positif.
- Mengupdate tampilan untuk meminta input SLA sebelum membuat SPK.
- Menambahkan rute baru untuk pembaruan SLA di registrasi.php.
2025-03-05 12:55:57 +07:00
Daeng Deni Mardaeni
42ed13e0ef fix(tender): perbaiki validasi dan tampilan biaya KJPP sebelumnya
- Menghapus aturan numeric pada biaya_kjpp_sebelumnya
- Mengubah input biaya_kjpp_sebelumnya menjadi hidden
- Menambahkan tombol untuk mengirim email pada tampilan proses penawaran
2025-03-05 11:52:50 +07:00
Daeng Deni Mardaeni
74872076e4 refactor(spk): optimalkan pengambilan data penawaran
- Mengubah query untuk mengambil data penawaran dengan menggunakan eager loading.
- Menambahkan relasi baru pada model PenawaranTender untuk penilaian dan persetujuan.
- Memperbaiki tampilan pada dokumen SPK dan halaman edit dengan mengurangi duplikasi kode.
2025-03-05 11:18:02 +07:00
majid
cc28ace415 fix(surveyor/penilai) : perbaikan edit foto, tanda tangan dan report laporan di penilai 2025-03-05 10:17:47 +07:00
Daeng Deni Mardaeni
e52fd8243f fix(dokumen): perbaikan dan penambahan tipe custom field
- Menambahkan dukungan untuk berbagai tipe custom field: text, number, date, textarea, dan select.
- Memperbaiki cara pengambilan nilai custom field dari detail.
- Mengoptimalkan penggunaan variabel untuk meningkatkan keterbacaan kode.
2025-03-05 10:03:46 +07:00
Daeng Deni Mardaeni
1aeb96f8b5 fix(custom_fields): tambahkan opsi tipe custom field baru
- Menambahkan opsi 'date' dan 'number' pada validasi tipe custom field.
- Memperbarui tampilan dropdown untuk mencakup opsi baru.
2025-03-05 10:03:34 +07:00
Daeng Deni Mardaeni
14d6052c4e fix(custom_fields): perbaikan opsi dropdown untuk jenis custom field
- Memperbaiki nilai opsi dropdown untuk jenis custom field.
- Menambahkan opsi 'Date' ke dalam dropdown.
- Memastikan opsi yang benar dipilih berdasarkan nilai yang ada.
2025-03-05 09:33:11 +07:00
majid
f1f345707a fix(surveyor/penilai): perbaikkan data pembanding dan tambah tombol freaze di penilai 2025-03-05 05:15:50 +07:00
Daeng Deni Mardaeni
0bca2e2bf2 fix(laporan): perbaikan format dan konten laporan
- Memperbaiki kesalahan dalam format laporan LPJ
- Menambahkan informasi yang hilang pada paparan SO
- Memperbaiki struktur call report untuk kejelasan
2025-03-04 21:34:55 +07:00
Daeng Deni Mardaeni
dd7df6f898 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-03-04 13:31:51 +07:00
putrakuningan
5c7c4ce739 Merge pull request 'feature/senior-officer' (#114) from feature/senior-officer into staging
Reviewed-on: #114
2025-03-04 07:30:53 +01:00
majid
cf45ac7cbe fix(penilai):perbaikkan laporan lpj, paparan so, call report 2025-03-04 07:30:53 +01:00
majid
107726efe7 fix(surveyor): perbaikkan print out surveyor 2025-03-04 07:30:53 +01:00
majid
3ba43b8579 fix(surveyor): perbaikan luas tanah, bangunan, unit not found 2025-03-04 07:30:53 +01:00
Daeng Deni Mardaeni
fe3b1bebce fix(prosespenawaran): perbaiki penanganan data dan tampilan
- Menambahkan pengambilan data Permohonan berdasarkan nomor registrasi pada metode show.
- Memperbaiki tampilan dengan menggunakan komponen detail-jaminan untuk menampilkan data proses penawaran.
- Menghapus kode yang tidak diperlukan untuk meningkatkan kebersihan kode.
2025-03-04 13:30:21 +07:00
majid
ad3ef0883b fix(penilai):perbaikkan laporan lpj, paparan so, call report 2025-03-04 13:23:28 +07:00
majid
8d696cd51a fix(surveyor): perbaikkan print out surveyor 2025-03-04 10:40:07 +07:00
majid
e12114c3e4 fix(surveyor): perbaikan luas tanah, bangunan, unit not found 2025-03-04 09:36:15 +07:00
Daeng Deni Mardaeni
16c799e512 fix(pemilik_jaminan/form, permohonan/print): ubah label 'Address' menjadi 'Alamat'
- Mengganti label 'Address' menjadi 'Alamat' pada form pemilik jaminan.
- Mengupdate label 'Address' menjadi 'Alamat' pada halaman cetak permohonan.
2025-03-04 09:20:47 +07:00
Daeng Deni Mardaeni
ef035b76c0 Merge remote-tracking branch 'composer/staging' into staging 2025-03-04 09:13:40 +07:00
Daeng Deni Mardaeni
4cec4f2e42 fix(debitur): ubah label 'Address' menjadi 'Alamat'
- Mengganti label 'Address' dengan 'Alamat' pada komponen debitur dan dokumen.
- Memastikan konsistensi penggunaan bahasa dalam antarmuka pengguna.
2025-03-04 09:13:19 +07:00
daengdeni
5a6cf46f9e fix(permohonan/index): perbaiki penanganan data debitur
- Tambahkan optional chaining pada akses nama debitur untuk mencegah error jika data debitur tidak ada.
- Perbarui beberapa bagian kode untuk menggunakan debitur dengan aman saat menghapus dan menyetujui jadwal kunjungan.
2025-03-04 08:40:00 +07:00
daengdeni
68bca67899 fix(permohonan/index): perbaiki penanganan data pada reschedule jadwal survey
- Mengubah parameter yang dikirim ke fungsi surveyorRescheduleJadwalSurvey menjadi string
- Memastikan data yang dikirim tidak mengalami kesalahan format
2025-03-04 08:37:54 +07:00
majid
5c4eb4eebb Merge branch 'staging' into feature/senior-officer 2025-03-03 15:51:49 +07:00
majid
b8dbda153e fix(so/dd/eo/penilai): perbaikan otorisasi untuk paparan, pelaporan, penambahan revisi pembayaran, data pembading dan ubah class bg-agi-50 ke light:bg-agi-50 2025-03-03 15:48:03 +07:00
Daeng Deni Mardaeni
97109250c9 fix(dokumen_jaminan): tambahkan validasi sebelum menghapus dokumen jaminan
- Memastikan hanya administrator yang dapat menghapus dokumen jaminan.
- Menambahkan pengecekan untuk memastikan dokumen jaminan ada sebelum dihapus.
- Menambahkan validasi untuk mencegah penghapusan dokumen jaminan yang terkait dengan permohonan aktif.
- Menggunakan transaksi database untuk menjaga konsistensi data saat menghapus dokumen dan detailnya.
2025-03-03 15:44:00 +07:00
Daeng Deni Mardaeni
3c5e4a7df6 fix(debiture): tambahkan validasi sebelum menghapus debitur
- Periksa apakah pengguna adalah administrator sebelum menghapus debitur.
- Pastikan debitur ditemukan sebelum melakukan penghapusan.
- Cek apakah debitur memiliki permohonan aktif untuk mencegah penghapusan.
- Kembalikan respons JSON yang sesuai untuk setiap kondisi.
2025-03-03 15:43:39 +07:00
Daeng Deni Mardaeni
e55184591c Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-03-03 09:27:28 +07:00
majid
f928cf1d76 fix(surveyoe/penilai/so/dd/eo): penambahan akses menu dd, eo di resume dan laporan, penambahan tanggal data di data pembanding dan properti sejenis di rap 2025-03-03 09:09:22 +07:00
majid
bfc515f3ed perbaikkan foto dan tanah 2025-03-03 08:11:53 +07:00
Daeng Deni Mardaeni
e968cefe0d Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-03-03 08:00:55 +07:00
majid76
8c08b46c8f fix(penilai/surveyor): perbaikkan activity, form inspeksi, print out inspeksi dan laporan, ganti nama detail penilai ke detail penilaian 2025-03-03 01:27:44 +07:00
majid
f65b9bec23 Ffix(surveyor/penilai): perbaikkan edit foto dan call report 2025-03-01 10:25:50 +07:00
Daeng Deni Mardaeni
d51f9f902c Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-02-28 16:46:57 +07:00
putrakuningan
9a6223ac26 Merge pull request 'feature/senior-officer' (#113) from feature/senior-officer into staging
Reviewed-on: #113
2025-02-28 09:37:56 +01:00
majid
2efcf7d85c fix(so): perbaikkan view laporan di so 2025-02-28 09:37:56 +01:00
majid
025cb3d5b8 Merge branch 'staging' into feature/senior-officer 2025-02-28 15:35:43 +07:00
majid
85644362a9 fix(so): perbaikkan view laporan di so 2025-02-28 15:33:58 +07:00
putrakuningan
33162704e8 Merge pull request 'feature/senior-officer' (#112) from feature/senior-officer into staging
Reviewed-on: #112
2025-02-28 07:43:05 +01:00
majid
25735d205f fix(penilai/surveyor): perbaikkan call report, button camera, dan inspeksi berdasarkan dokument 2025-02-28 07:43:05 +01:00
majid
5389cd1d3a Merge branch 'staging' into feature/senior-officer 2025-02-28 13:37:24 +07:00
majid
2793e397b0 fix(penilai/surveyor): perbaikkan call report, button camera, dan inspeksi berdasarkan dokument 2025-02-28 13:35:42 +07:00
Daeng Deni Mardaeni
476106a58c Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-02-28 09:53:28 +07:00
majid
f253d0c14c fix(so/penilai/surveyor) : perbaikkan print out, lampiran, send email jadwal, otorisator, dan typo 2025-02-28 02:29:24 +07:00
Daeng Deni Mardaeni
cc500bfcac fix(spk): perbaiki pengolahan dokumen jaminan
- Mengubah referensi dari $data->debiture->documents menjadi $data->dokumenjaminan.
- Memperbaiki logika pengulangan untuk menampilkan dokumen jaminan.
- Menambahkan pengecekan untuk memastikan detail dokumen jaminan ditampilkan dengan benar.
2025-02-27 15:47:08 +07:00
Daeng Deni Mardaeni
03b0ba4ac0 fix(spk): perbaiki tampilan dokumen jaminan
- Memperbaiki kondisi pengecekan ID dokumen jaminan.
- Menambahkan tampilan nama detail dokumen jaminan jika ada.
- Memperbaiki format tampilan nomor dokumen dengan pemisah koma.
2025-02-27 15:38:32 +07:00
Daeng Deni Mardaeni
f6bae680af fix(spk): perbaiki pengolahan data dokumen jaminan
- Memperbaiki relasi data dokumen jaminan pada controller.
- Mengubah penghitungan total aset untuk menggunakan dokumen jaminan yang benar.
- Memperbarui tampilan untuk menampilkan dokumen jaminan dengan benar.
2025-02-27 15:26:24 +07:00
Daeng Deni Mardaeni
2759fdc8d9 fix(penawaran): perbaiki tampilan opsi pada form edit
- Menambahkan jenis kantor pada opsi yang ditampilkan.
- Menampilkan nama kota tanpa awalan 'KOTA', 'KAB.', atau 'KAB' jika jenis kantor adalah 'Kantor Cabang'.
2025-02-27 14:08:57 +07:00
Daeng Deni Mardaeni
e08130132f Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-02-27 13:19:05 +07:00
Daeng Deni Mardaeni
222ada0f0c fix(tender): perbaiki pengolahan email kantor
- Mengubah cara pengolahan email dari string menjadi koleksi untuk menghindari duplikasi.
- Memastikan bahwa detail email yang diambil dari JSON diproses dengan benar.
- Menambahkan validasi untuk memastikan bahwa detail email adalah array sebelum diakses.
2025-02-27 13:18:41 +07:00
Daeng Deni Mardaeni
e6b6ad6e2c fix(penawaran): perbaiki pengolahan email kantor
- Mengubah struktur penyimpanan email dari array menjadi Set untuk menghindari duplikasi.
- Memastikan semua email dari detail_email_kantor ditambahkan dengan benar.
- Mengonversi Set kembali menjadi array sebelum validasi email.
2025-02-27 13:17:44 +07:00
majid
7fd77dde57 penambaha sentuh tanahku 2025-02-27 12:55:37 +07:00
majid
b8a492e842 fix(so/dd/eo/penilai) : perbaikan otorisator pelaporan dan print out sedehana dan standar 2025-02-27 12:15:55 +07:00
majid
fbabb2efaa Merge branch 'staging' into feature/senior-officer 2025-02-27 10:20:03 +07:00
majid
2a475a9ea7 fix(so/penilai) : perbaikkan paparan dan resume 2025-02-27 10:18:31 +07:00
Daeng Deni Mardaeni
ecbeb15d2f fix(penilai): perbaikan query status 2025-02-26 14:52:51 +07:00
majid
6102205900 perbaikan status 2025-02-26 14:46:21 +07:00
majid
a8be1591c3 fix(survey/penilai) : perbaikkan print resume dan resume 2025-02-26 14:45:05 +07:00
majid
94fc66a48f fix(penilai/so) : perbaikkan nilai resume dan sla activity 2025-02-26 12:08:55 +07:00
majid
88bd409d42 fix(so): perbaikan filter laporan 2025-02-26 10:56:15 +07:00
majid
222cbd8df8 delete file data.json 2025-02-26 10:07:34 +07:00
majid
77189701d6 fix(surveyor): perbaikkan upload foto duplikat 2025-02-26 09:38:52 +07:00
majid
3d7da22ac0 fix(penilai): perbaikan lpj standart dan sederhana 2025-02-26 06:27:39 +07:00
majid
18ec35f272 Merge branch 'staging' into feature/senior-officer 2025-02-26 05:13:39 +07:00
majid
7766d127e0 fix(suveyor/penilai/so): perbaikan print out, form survey dan laporan dan paparan 2025-02-26 05:07:25 +07:00
Daeng Deni Mardaeni
9d29cb3540 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-02-25 13:53:23 +07:00
Daeng Deni Mardaeni
009cdf2955 fix(pembatalan): perbaiki akses data permohonan dengan optional chaining
- Menggunakan optional chaining untuk menghindari error jika data permohonan tidak ada.
- Memperbaiki pengambilan nomor registrasi, nama debitur, dan cabang.
2025-02-25 13:51:43 +07:00
majid
2045da36d8 Merge branch 'staging' into feature/senior-officer 2025-02-25 08:51:02 +07:00
majid
dfa364cdd8 fix(survyor/penilai): perbaikan view print-resume, lampiran, foto-lampiran, foto, header, main dan controller penilai dan surveyor 2025-02-25 08:50:03 +07:00
Daeng Deni Mardaeni
d068593177 fix(dokumen): perbaiki pengalihan rute setelah menambahkan dokumen jaminan
- Memperbaiki rute pengalihan setelah berhasil menambahkan dokumen jaminan.
- Menambahkan parameter 'pemrohonan_id' pada rute pengalihan untuk memastikan data yang tepat dikirim.
- Memperbaiki penanganan kesalahan dengan mengarahkan kembali ke halaman pembuatan dokumen jaminan dengan pesan kesalahan yang lebih informatif.
2025-02-24 15:41:18 +07:00
Daeng Deni Mardaeni
058fe71173 fix(dokumen): perbaiki input field jenis legalitas jaminan
- Mengubah parameter yang digunakan dalam fungsi getCustomFieldInput
- Mengganti item.id dengan item.jenis_legalitas_jaminan_id
2025-02-24 15:29:36 +07:00
Daeng Deni Mardaeni
cb05fa3178 fix(permohonan): perbaiki penanganan catatan ditolak pada reschedule jadwal survey
- Mengubah cara pengiriman catatan ditolak dengan menggunakan JSON.stringify.
- Memastikan catatan ditolak dapat diparse kembali di fungsi surveyorRescheduleJadwalSurvey.
2025-02-24 15:02:42 +07:00
Daeng Deni Mardaeni
fb77198ca3 fix(laporan): perbaiki relasi dokumen pada laporan
- Mengubah relasi dokumen dari 'debiture.documents.inspeksi' menjadi 'documents.inspeksi' untuk memperbaiki akses data.
- Memastikan data yang diambil sesuai dengan struktur relasi yang benar.
2025-02-24 13:56:32 +07:00
Daeng Deni Mardaeni
7e6482f095 fix(laporan): perbaiki akses data dokumen pada laporan
- Mengubah akses data dari `data.debiture?.documents` menjadi `data.documents` untuk konsistensi.
- Memastikan bahwa ID inspeksi, dokumen, dan jenis jaminan diambil dengan benar dari struktur data yang diperbarui.
2025-02-24 13:50:54 +07:00
putrakuningan
42f4a27c54 Merge pull request 'fix(surveyor/penilai): perbaikkan pembanding dan call report' (#103) from feature/senior-officer into staging
Reviewed-on: #103
2025-02-24 02:49:03 +01:00
majid
e4cec2a9a2 fix(surveyor/penilai): perbaikkan pembanding dan call report 2025-02-23 01:36:34 +07:00
majid
7c6f50265c Merge branch 'staging' into feature/senior-officer 2025-02-21 09:28:28 +07:00
majid
49d1b1ef75 fix(penilai/surveyor): perbaiki ukuran textarea menjadi 10 baris dan penambahan denah di lampiran 2025-02-21 09:27:42 +07:00
putrakuningan
410fd6c991 Merge pull request 'feature/senior-officer' (#101) from feature/senior-officer into staging
Reviewed-on: #101
2025-02-20 11:12:16 +01:00
majid
fbb8af6fc2 perbaikan status pregister dan revisi 2025-02-20 17:08:09 +07:00
majid
28295f5b85 fix(so): perbaikan assigment bisa pindah region, dan perbaikan call report dan revisi dokumen admin dari so 2025-02-20 16:54:39 +07:00
majid
61c5690e38 perbaikan signature di print out 2025-02-19 17:34:13 +07:00
majid
fa921add45 perbaikan print out call report 2025-02-18 16:14:52 +07:00
majid
e19d5af09a Merge branch 'staging' into feature/senior-officer 2025-02-17 13:49:26 +07:00
majid
21a3f560e9 perbaikan status survey dan pelaporan 2025-02-17 13:47:18 +07:00
putrakuningan
d924454547 Merge pull request 'perbaikan form inspeksi dan ganti surveyor' (#99) from feature/senior-officer into staging
Reviewed-on: #99
2025-02-17 06:09:46 +01:00
majid
f626aeecfe perbaikan form inspeksi dan ganti surveyor 2025-02-17 12:07:26 +07:00
majid
f567e3da40 Merge branch 'staging' into feature/senior-officer 2025-02-17 10:05:54 +07:00
Daeng Deni Mardaeni
968adae26f fix(print-resume): perbaiki validasi dan format tampilan nilai
- Mengubah cara menampilkan nilai dan total likuidasi agar lebih jelas.
- Mengganti penggunaan operator null coalescing dengan pengecekan isset untuk menghindari tampilan kosong.
- Memperbaiki struktur HTML untuk bagian penilai dan pejabat terkait.
2025-02-17 10:00:11 +07:00
e328852ffe Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2025-02-17 09:21:36 +07:00
putrakuningan
25a652621d Merge pull request 'feature/senior-officer' (#98) from feature/senior-officer into staging
Reviewed-on: #98
2025-02-14 11:35:58 +01:00
majid
a846c22479 perbaikan validasi input nilai likuidasi percent resume 2025-02-14 11:35:58 +01:00
majid
3318e1c91a Merge branch 'staging' into feature/senior-officer 2025-02-14 17:33:41 +07:00
majid
4c4f3dd70b perbaikan validasi input nilai likuidasi percent resume 2025-02-14 17:33:02 +07:00
putrakuningan
8586745b82 Merge pull request 'tender' (#87) from tender into staging
Reviewed-on: #87
2025-02-14 10:21:24 +01:00
64e615760c Mengubah di method KirimEmailTenderAll untuk mengirimkan beberapa KJPP terkait 2025-02-14 10:21:24 +01:00
putrakuningan
6a159a9015 Merge pull request 'perbaikan back halaman di otorisator so dan penambahan nilai likuidasi di resume' (#97) from feature/senior-officer into staging
Reviewed-on: #97
2025-02-14 10:20:04 +01:00
majid
2cb2b7981c perbaikan back halaman di otorisator so dan penambahan nilai likuidasi di resume 2025-02-14 16:16:41 +07:00
05557433d0 Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2025-02-14 08:51:10 +07:00
majid
d2805bdb2f Merge branch 'staging' into feature/senior-officer 2025-02-13 20:21:12 +07:00
majid
7269d2e954 fix(penilai): perbaikan urutan alamat pada print out 2025-02-13 20:20:36 +07:00
putrakuningan
776bff338f Merge pull request 'fix(penilai): perbaikan format nilai rupiah diresume' (#95) from feature/senior-officer into staging
Reviewed-on: #95
2025-02-13 11:51:37 +01:00
majid
27ef923c27 fix(penilai): perbaikan format nilai rupiah diresume 2025-02-13 11:51:37 +01:00
majid
295b2fa183 fix(penilai): perbaikan format nilai rupiah diresume 2025-02-13 17:43:55 +07:00
putrakuningan
259f63917e Merge pull request 'feature/senior-officer' (#94) from feature/senior-officer into staging
Reviewed-on: #94
2025-02-13 09:44:18 +01:00
majid
3b3765a53f fix(surveyor): perbaikan filter data revisi dan data pembanding 2025-02-13 15:14:10 +07:00
majid
5a4c8ab3a4 tambahan satuan luas di denah 2025-02-13 13:40:30 +07:00
majid
90249b83e1 fix(surveyor): tambah nama desa dan ganti n/a ke angak 0 2025-02-13 13:21:02 +07:00
571e19f11c Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2025-02-13 08:53:18 +07:00
majid
51bc603fe7 Merge branch 'staging' into feature/senior-officer 2025-02-12 18:05:01 +07:00
majid
c860daa1d5 feat(pemohon): menambahkan fitur reschedule jadwal kunjungan
fix(surveyor): memperbaiki nama placeholder dan call report
2025-02-12 18:03:05 +07:00
c6b9003429 Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2025-02-12 11:45:36 +07:00
putrakuningan
c4ce75789d Merge pull request 'feature/senior-officer' (#92) from feature/senior-officer into staging
Reviewed-on: #92
2025-02-11 09:35:17 +01:00
majid
874d101b21 fix(surveyorr): perbaikan upload foto dan pembanding 2025-02-11 09:35:17 +01:00
majid
ffd8f72c74 fix(surveyor): perbaikan upload foto 2025-02-11 09:35:17 +01:00
majid
2d99b6ab7a Merge branch 'staging' into feature/senior-officer 2025-02-11 15:29:39 +07:00
majid
7ba4b4b2b4 fix(surveyorr): perbaikan upload foto dan pembanding 2025-02-11 15:28:48 +07:00
majid
30e41c1cab fix(surveyor): perbaikan upload foto 2025-02-11 11:55:42 +07:00
ee5c6207bd Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2025-02-11 10:59:07 +07:00
putrakuningan
b35a33587b Merge pull request 'feature/senior-officer' (#91) from feature/senior-officer into staging
Reviewed-on: #91
2025-02-11 02:50:05 +01:00
majid
05dfaf2c83 hapus inputan nomor nib di penilai 2025-02-10 23:18:18 +07:00
majid
4ef7c01e29 fix(surveyor): perbaikan tanda tangan, print out sederhana dan print hasil surveyor 2025-02-10 23:15:42 +07:00
30178c5179 Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2025-02-07 14:18:13 +07:00
majid
50367edca4 Merge branch 'staging' into feature/senior-officer 2025-02-07 14:07:18 +07:00
majid
5afcc52063 ubah @include untuk komponen foto ke foto-jaminan di Penilai 2025-02-07 14:06:17 +07:00
728dacf936 Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2025-02-07 13:36:36 +07:00
putrakuningan
fc4d668e6f Merge pull request 'fix(print-out): perbaikan print out foto dan sederhana dan standard' (#89) from feature/senior-officer into staging
Reviewed-on: #89
2025-02-07 05:37:35 +01:00
majid
36a8b0bb15 fix(print-out): perbaikan print out foto dan sederhana dan standard 2025-02-07 11:25:55 +07:00
7ad38849f2 Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2025-02-07 09:31:11 +07:00
majid
7c6059d479 fix(surveyor dan penilai): perbaikan upload foto dan print out 2025-02-07 07:29:49 +07:00
majid
8fc5f6ec0b Merge remote-tracking branch 'origin/feature/senior-officer' into surveyor 2025-02-06 14:53:05 +07:00
majid
ac326c0a49 fix view foto jaminan 2025-02-06 14:48:45 +07:00
3ab59dfbdc Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2025-02-06 13:45:24 +07:00
23e117279f Mengubah di method KirimEmailTenderAll untuk mengirimkan beberapa KJPP terkait 2025-02-06 13:44:19 +07:00
majid
a5e9f5df0a Merge branch 'staging' into feature/senior-officer 2025-02-06 11:58:56 +07:00
majid
441e2319b1 fix(surveyor) : perbaikan data table surveyor 2025-02-06 11:58:08 +07:00
majid
8f2555c0a0 perbaikan foto 2025-02-06 11:38:35 +07:00
Daeng Deni Mardaeni
e4ca3d7987 fix(pemohonan): perbaiki pemanggilan dokumen pada berbagai komponen
- Mengubah pemanggilan dokumen dari $permohonan->debiture->documents menjadi $permohonan->documents di beberapa file.
- Memastikan konsistensi dalam akses data dokumen di seluruh aplikasi.
2025-02-06 11:32:12 +07:00
2cc70d9163 Perbaiki Skrip untuk Pemanggilan Dokumen Jaminan 2025-02-06 10:34:28 +07:00
majid
e650cda8fc Merge branch 'staging' into feature/senior-officer 2025-02-05 15:18:55 +07:00
majid
821324e8a1 fix(print-out) : perbaikan print out rap, sederhana, standar dan perbaikan tanda tangan dan name informasi rap 2025-02-05 15:18:05 +07:00
Daeng Deni Mardaeni
28d579d65d fix(penilaian): perbaiki urutan parameter pada fungsi revisiLaporan
- Mengubah urutan parameter pada fungsi revisiLaporan di PenilaianController.
- Memperbaiki URL pada permintaan AJAX di tampilan show.blade.php.
2025-02-05 15:03:31 +07:00
Daeng Deni Mardaeni
1b32105603 fix(laporan): perbaiki logika penentuan type penilaian pada tombol laporan
- Menambahkan variabel type untuk mengambil type dari data penilai.
- Memperbaiki logika untuk menampilkan tombol laporan berdasarkan type penilai.
- Memastikan tombol laporan mengarah ke URL yang benar sesuai dengan type penilaian.
2025-02-05 14:18:57 +07:00
Daeng Deni Mardaeni
80c6c82ad1 fix(laporan): tambahkan type penilaian pada URL laporan
- Menambahkan parameter type pada URL laporan untuk mencakup type penilaian.
- Menghapus log console yang tidak diperlukan.
2025-02-05 13:59:18 +07:00
Daeng Deni Mardaeni
7c4a2659dd Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-02-05 13:58:22 +07:00
majid
97ad08bc56 perbaikan upload foto 2025-02-05 13:27:21 +07:00
majid
ac431a3c3c fix(penilai): perbaikan nomor laporan memo 2025-02-04 14:05:46 +07:00
majid
165042db38 fix(print-out): perbaikan foto 2025-02-04 13:33:16 +07:00
Daeng Deni Mardaeni
9e2a9b32d8 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-02-04 10:45:06 +07:00
majid
075567f84c Merge branch 'staging' into feature/senior-officer 2025-02-04 10:40:45 +07:00
majid
c23a8f8c29 fix(penilai): perbaikan nomor laporan 2025-02-04 10:39:58 +07:00
Daeng Deni Mardaeni
b260151f4c Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-02-04 10:26:26 +07:00
majid
37959a9dae Merge branch 'staging' into feature/senior-officer 2025-02-04 10:20:45 +07:00
majid
41cae8b8f4 fix(penilai): perbaikan lihat data ketika status peoses paparan, dan penambahan print out inspeksi surveyor 2025-02-04 10:19:25 +07:00
Daeng Deni Mardaeni
c17541dbc8 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-02-04 09:01:15 +07:00
majid
a200c1ec52 penambahan kirim email, dan perbaikan print out 2025-02-04 08:45:52 +07:00
Daeng Deni Mardaeni
d6e1586b4b feat(dokumen_jaminan): tambahkan custom fields pada legalitas jaminan
- Menambahkan pengambilan custom fields jika tersedia pada legalitas jaminan.
- Memastikan custom fields disertakan dalam data legalitas baru yang dibuat.
2025-02-03 14:04:55 +07:00
Daeng Deni Mardaeni
a7cd063be9 feat(tender): tambahkan informasi pengguna pada email penawaran
- Mengambil informasi pengguna yang sedang login.
- Menyimpan informasi pengguna dalam job pengiriman email.
- Mengupdate tampilan email untuk menampilkan informasi pengguna.
2025-02-03 13:28:07 +07:00
Daeng Deni Mardaeni
9e6ae1f5ad fix(tender): perbaiki pengambilan informasi pengguna
- Mengubah cara pengambilan informasi pengguna untuk meningkatkan konsistensi.
- Menggunakan variabel $user untuk menyimpan informasi pengguna yang terautentikasi.
2025-02-03 13:23:23 +07:00
Daeng Deni Mardaeni
108c30e4e1 feat(email): tambahkan informasi pengguna pada email penawaran
- Menambahkan properti user ke dalam data yang dikirimkan ke view.
- Memungkinkan pengiriman informasi pengguna sebagai cc dan bcc.
2025-02-03 13:22:03 +07:00
Daeng Deni Mardaeni
7e5d336469 feat(email): tambahkan informasi pengguna pada email penawaran
- Menambahkan parameter user pada konstruktor SendPenawaranKJPPEmail.
- Mengupdate data yang dikirimkan ke view untuk menyertakan informasi pengguna sebagai cc dan bcc.
- Menggunakan auth()->user() untuk mendapatkan informasi pengguna yang sedang login di TenderController.
2025-02-03 13:20:33 +07:00
Daeng Deni Mardaeni
561bf7237e feat(tender): tambahkan informasi pengguna pada email penawaran
- Menambahkan parameter pengguna pada konstruktor SendPenawaranKJPPTenderJob.
- Mengupdate pengambilan data pengguna di TenderController.
- Memperbarui tampilan email untuk menampilkan tanda tangan dan nama pengguna yang benar.
2025-02-03 13:16:55 +07:00
majid
9bdbd77f73 fix(surveyor): update key dokument jaminan 2025-01-31 13:56:53 +07:00
majid
d5311a944d feat(print-out): hasil inspeksi surveyor 2025-01-31 02:32:55 +07:00
majid
d8f0996184 Merge branch 'staging' into feature/senior-officer 2025-01-30 21:44:06 +07:00
majid
56bb085ed5 fix(penilai):perbaikan save penilai untuk so 2025-01-30 21:42:53 +07:00
Daeng Deni Mardaeni
33cbf385e6 fix(dokumen): perbaiki pengambilan nama custom field
- Mengubah cara pengambilan nama custom field dari objek JSON.
- Memastikan nilai input terisi dengan benar berdasarkan nama custom field.
2025-01-30 21:19:05 +07:00
Daeng Deni Mardaeni
a7f2115b56 fix(dokumen): hapus pengambilan luas tanah yang tidak diperlukan
- Menghapus baris yang mengambil nilai luas tanah dari custom field.
- Memastikan tampilan dokumen lebih bersih dan relevan.
2025-01-30 21:12:41 +07:00
Daeng Deni Mardaeni
115baf7552 fix(helpers): perbaiki penamaan kelas customField menjadi CustomField
- Mengubah penamaan kelas dari customField menjadi CustomField untuk konsistensi.
- Memastikan penggunaan huruf kapital pada nama kelas sesuai dengan konvensi PSR-1.
2025-01-30 21:11:52 +07:00
Daeng Deni Mardaeni
8da0880819 fix(models): perbaiki penamaan kelas customField menjadi CustomField
- Mengubah penamaan kelas dari `customField` menjadi `CustomField` untuk konsistensi penamaan.
- Memperbaiki referensi di beberapa file controller dan request yang menggunakan penamaan yang salah.
2025-01-30 21:07:31 +07:00
Daeng Deni Mardaeni
ad3d3e900d feat(jenis-legalitas-jaminan): perbaiki tampilan checkbox untuk jenis legalitas jaminan
- Memperbaiki struktur HTML untuk bagian jenis legalitas jaminan.
- Mengoptimalkan penggunaan checkbox dengan penataan ulang kode.
- Menjaga fungsionalitas checkbox tetap utuh saat menyimpan data.
2025-01-30 20:50:32 +07:00
Daeng Deni Mardaeni
cae62db0df fix(penawaran): perbaiki pengambilan luas tanah dan luas bangunan
- Sederhanakan kondisi untuk memeriksa dan mengambil nilai luas tanah dan luas bangunan.
- Ganti penggunaan notasi objek dengan notasi akses langsung untuk meningkatkan keterbacaan.
- Hapus kondisi yang tidak perlu untuk meningkatkan efisiensi kode.
2025-01-30 20:50:16 +07:00
Daeng Deni Mardaeni
b9d6e5a95b feat(dokumen-jaminan): perbaiki pengambilan custom field
- Memperbaiki pengambilan custom field pada dokumen jaminan.
- Mengubah logika untuk mendapatkan custom field berdasarkan ID yang benar.
- Menambahkan pengambilan custom fields yang terkait dengan jenis legalitas jaminan.
2025-01-30 20:50:00 +07:00
Daeng Deni Mardaeni
92d0aff9f8 feat(custom-field): tambahkan fungsi untuk mendapatkan custom field
- Menambahkan fungsi getCustomField untuk mengambil custom field berdasarkan ID atau nama.
- Memperbarui penggunaan model customField di file Lpj.php.
2025-01-30 20:49:34 +07:00
Daeng Deni Mardaeni
d746f53941 feat(jenis-legalitas-jaminan): tambahkan dukungan untuk custom fields
- Menambahkan kolom 'custom_fields' pada tabel 'jenis_legalitas_jaminan'.
- Memperbarui model untuk mengizinkan pengisian 'custom_fields' sebagai array.
- Memperbarui request untuk validasi 'custom_fields' sebagai array.
- Memperbarui controller untuk mengambil dan mengirimkan custom fields saat membuat dan mengedit jenis legalitas jaminan.
2025-01-30 16:34:37 +07:00
Daeng Deni Mardaeni
18cbb0bbc5 feat(custom-field): tambahkan kolom label dan urutan prioritas
- Menambahkan kolom 'label' pada tabel custom_fields.
- Menambahkan kolom 'urutan_prioritas' pada tabel custom_fields.
- Memperbarui model CustomField untuk menyertakan kolom baru.
- Memperbarui form input untuk label dan urutan prioritas di tampilan create dan index.
- Menambahkan validasi untuk label dan urutan prioritas di CustomFieldRequest.
2025-01-30 16:14:48 +07:00
Daeng Deni Mardaeni
b8a84bb7e1 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-01-30 15:55:12 +07:00
Daeng Deni Mardaeni
32de93ef9f feat(custom-field): tambahkan fitur custom field
- Menambahkan model CustomField dengan atribut mass assignable.
- Membuat request validation untuk custom field.
- Menambahkan route dan breadcrumb untuk custom field.
- Membuat migration untuk tabel custom_fields.
- Menambahkan export functionality untuk custom field.
- Membuat view untuk menambah dan mengedit custom field.
2025-01-30 15:54:52 +07:00
majid
541ea8e94c Merge branch 'staging' into feature/senior-officer 2025-01-30 15:04:37 +07:00
majid
edb5a65fbf feat(surveyor): penambahan handout form inspeksi 2025-01-30 15:03:10 +07:00
Daeng Deni Mardaeni
a43c65e4c2 feat(penilaian): tambahkan kolom jenis laporan pada tabel
- Menambahkan kolom "Jenis Laporan" di tampilan otorisator.
- Memperbarui controller untuk menyertakan data penilai.
2025-01-30 14:50:29 +07:00
majid
44a1424349 perbaikan otorisator dd rap dan print out rap 2025-01-24 17:21:58 +07:00
majid
99fb76c5bc perbaikan nomor laporan di memo dan rap 2025-01-24 16:08:33 +07:00
majid
76209b31b5 Merge branch 'staging' into feature/senior-officer 2025-01-24 15:48:28 +07:00
majid
74701c092d fix(LaporanController ) : laporan memo dan print out rap 2025-01-24 15:47:12 +07:00
Daeng Deni Mardaeni
81e4ccca3c Merge remote-tracking branch 'origin/feature/senior-officer' into staging 2025-01-24 14:14:21 +07:00
majid
201003e020 perbaikan rap dan nilai otomatis likudasi menu laporan 2025-01-24 13:42:17 +07:00
Daeng Deni Mardaeni
0c6a4d65dc Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-01-24 09:55:36 +07:00
majid
152718526b Merge branch 'staging' into feature/senior-officer 2025-01-24 09:47:48 +07:00
majid
dffaadda3b feat(signature): penambahan tanda tangan di surveyor 2025-01-24 09:44:59 +07:00
Daeng Deni Mardaeni
84932aa6f2 Merge remote-tracking branch 'composer/feature/senior-officer' into staging
# Conflicts:
#	resources/views/penilai/components/print-resume.blade.php
#	resources/views/surveyor/components/header.blade.php
2025-01-24 09:42:49 +07:00
majid
a1282fbdca fix(print-out): perbaikan prit out, resume, memo, standard, sedehana dan rap 2025-01-24 07:47:12 +07:00
Daeng Deni Mardaeni
ebcf0a9a5a fix(print-resume, header): perbaiki penanganan tanggal dan nomor NIB
- Menambahkan pengecekan untuk memastikan tanggal kunjungan dan tanggal resume tidak menghasilkan error jika tidak ada data.
- Memperbaiki penanganan nilai default untuk nomor NIB agar tidak menampilkan nilai null.
2025-01-23 17:00:50 +07:00
Daeng Deni Mardaeni
ef76bb2654 Merge remote-tracking branch 'origin/feature/senior-officer' into staging 2025-01-23 16:21:34 +07:00
majid
09edabffdd perbaikan report rap dan dan penambahan no nib di pritn out sederhana 2025-01-23 16:20:39 +07:00
Daeng Deni Mardaeni
c0b125b481 feat(penilaian): tambahkan fitur tanggal paparan dan otorisasi
- Menambahkan kolom tanggal paparan pada tampilan laporan.
- Memperbarui model Permohonan untuk menambahkan relasi otorisasi.
- Memperbaiki logika otorisasi pada tampilan paparan.
- Memperbaiki penanganan tombol untuk melihat data paparan.
2025-01-23 13:33:48 +07:00
Daeng Deni Mardaeni
4c3d39a7ae feat(penilai): tambahkan fitur upload file paparan
- Menambahkan metode edit untuk menampilkan form upload file paparan.
- Menambahkan metode storePaparan untuk menyimpan file paparan ke database.
- Membuat migrasi untuk menambahkan kolom file_paparan pada tabel penilai.
- Menambahkan tampilan edit.blade.php untuk form upload.
- Memperbarui tampilan show.blade.php untuk mengarahkan ke form edit.
- Menambahkan breadcrumb untuk navigasi ke halaman upload file paparan.
- Memperbarui rute untuk mendukung pengeditan dan penyimpanan file paparan.
2025-01-23 11:37:10 +07:00
majid
91464d92fe Merge branch 'staging' into feature/senior-officer 2025-01-23 11:03:22 +07:00
majid
0f6ce6ef4a perbaikan upload foto dan print out rap, standard dan resume 2025-01-23 11:00:48 +07:00
Daeng Deni Mardaeni
348df64afc Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-01-23 09:56:16 +07:00
majid
0fa1563cf3 perbaikan output sederhana, standard 2025-01-23 07:19:52 +07:00
Daeng Deni Mardaeni
c29f73cbce fix(dokumen): perbaiki pengambilan nilai permohonan_id
- Mengubah nilai yang diambil untuk permohonan_id dari $document->id menjadi $document->permohonan_id.
- Memastikan bahwa nilai yang tepat digunakan dalam input tersembunyi untuk permohonan_id.
2025-01-22 18:17:58 +07:00
Daeng Deni Mardaeni
dbfbf126bb feat(laporan): tambahkan relasi penilai pada data laporan
- Menambahkan relasi 'penilai' pada query pengambilan data laporan.
- Memperbaiki referensi 'resume' dari 'penilaian' menjadi 'penilai' di tampilan.
2025-01-22 17:01:41 +07:00
Daeng Deni Mardaeni
1bfa6e942d fix(laporan): perbaiki tampilan tombol resume dan label
- Menambahkan kondisi untuk menampilkan tombol resume hanya jika data penilaian tersedia.
- Memperbaiki label tombol dari 'Input NL' menjadi 'Laporn'.
2025-01-22 16:56:35 +07:00
Daeng Deni Mardaeni
83778741a2 Merge remote-tracking branch 'origin/feature/senior-officer' into staging 2025-01-22 16:12:01 +07:00
majid
b18c25819e fix(print-out) : prbaikan tampilan memo, resume, sederhana, standard, rap 2025-01-22 16:10:30 +07:00
Daeng Deni Mardaeni
2d9cd4e1cb feat(penilai): tambahkan kolom dan fungsionalitas status
- Menambahkan kolom 'Status' pada tabel di halaman index penilai.
- Mengimplementasikan render untuk menampilkan status dengan format badge.
- Mengubah urutan default query menjadi berdasarkan 'updated_at' jika tidak ada parameter sort yang diberikan.
2025-01-22 14:56:42 +07:00
Daeng Deni Mardaeni
84a212a505 fix(penilai): tambahkan status 'paparan' pada kondisi render aksi
- Memperbarui kondisi render aksi untuk menyertakan status 'paparan'.
- Memastikan bahwa tombol aksi ditampilkan untuk status yang baru ditambahkan.
2025-01-22 14:42:51 +07:00
Daeng Deni Mardaeni
e00825320c fix(penilai): perbaiki query untuk status
- Menambahkan status 'paparan' pada kondisi whereRaw.
- Memastikan query mencakup semua status yang relevan.
2025-01-22 14:36:39 +07:00
Daeng Deni Mardaeni
c560a015b4 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-01-22 13:40:03 +07:00
Daeng Deni Mardaeni
df6f7c7fd0 fix(penilai): tambahkan status 'paparan' pada query
- Memperbarui query untuk menyertakan status 'paparan' dalam filter status.
2025-01-22 13:37:44 +07:00
majid
c0aafdd827 Merge branch 'staging' into feature/senior-officer 2025-01-22 13:28:09 +07:00
majid
833af13491 penambahan DISCLAIMER print otu dan pengecekan jika laporan belum di isi 2025-01-22 13:26:45 +07:00
daengdeni
ea4ecd26c5 fix(otorisator): perbarui pesan sukses otorisasi
- Menghapus detail tambahan dari pesan sukses otorisasi.
- Memastikan pesan lebih ringkas dan jelas bagi pengguna.
2025-01-22 11:40:04 +07:00
daengdeni
dc6b9f0b21 feat(penilai): tambahkan logika untuk memperbarui status permohonan
- Menambahkan pemanggilan Authorization::updateOrCreate untuk memperbarui status permohonan.
- Mengatur jenis permohonan menjadi 'paparan' dan request menjadi 'paparan'.
- Memastikan data permohonan diperbarui dengan benar sebelum dikirim untuk proses lebih lanjut.
2025-01-22 10:51:53 +07:00
daengdeni
ff3565f735 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-01-22 09:15:45 +07:00
majid
850534f1e2 Merge branch 'staging' into feature/senior-officer 2025-01-22 09:09:15 +07:00
majid
575ea3fdce fix(penilai): perbaikan output resume,memo dan update upload foto directory by nomor registrasi 2025-01-22 09:06:10 +07:00
Daeng Deni Mardaeni
15c5ccbf39 fix(otorisator): perbaiki logika otorisasi pada tampilan otorisator
- Memperbaiki kondisi otorisasi untuk peran administrator dan DD Appraisal.
- Mengubah pengecekan dari `approval_dd` menjadi `approve_dd` untuk konsistensi.
- Memastikan logika tetap sesuai dengan persyaratan yang ada.
2025-01-22 08:04:18 +07:00
Daeng Deni Mardaeni
b46f791ab2 fix(PenilaianController): perbaiki logika otorisasi untuk peran administrator
- Menambahkan kondisi untuk peran 'administrator' dalam logika otorisasi.
- Memperbaiki pembaruan status berdasarkan persetujuan yang diberikan oleh peran yang berbeda.
- Memastikan bahwa semua peran yang relevan dapat memperbarui status dengan benar.
2025-01-22 07:57:19 +07:00
Daeng Deni Mardaeni
5203033ba5 fix(otorisator): perbaiki tampilan dan logika otorisator
- Menghapus tombol otorisator untuk peran 'administrator' dan 'DD Appraisal' pada tampilan 'paparan'.
- Memperbaiki format penanganan keterangan dan tanggal paparan.
2025-01-22 07:49:22 +07:00
Daeng Deni Mardaeni
aa75b70c52 fix(PenilaianController): perbaiki pengambilan data otorisasi
- Mengubah metode pengambilan data otorisasi dari `find` menjadi `where` dan `first` untuk memastikan hanya data yang sesuai dengan `permohonan_id` yang diambil.
- Memperbaiki potensi masalah saat mengambil data otorisasi berdasarkan ID.
2025-01-22 07:46:17 +07:00
Daeng Deni Mardaeni
771cc4cb98 fix(PenilaianController): perbaiki pengambilan data otorisasi
- Menambahkan pengambilan data otorisasi berdasarkan ID pada tampilan 'Paparan'.
- Memastikan data otorisasi yang ditampilkan mencakup informasi pengguna.
2025-01-22 07:36:54 +07:00
Daeng Deni Mardaeni
8ddf7c9abe fix(Permohonan): perbaiki pengolahan keterangan registrasi catatan
- Menambahkan logika untuk menggabungkan keterangan dengan registrasi catatan jika ada.
- Memastikan keterangan tidak kosong sebelum ditambahkan ke dalam string.
2025-01-22 07:34:22 +07:00
Daeng Deni Mardaeni
7558d1a574 fix(PenilaianController): perbaiki logika otorisasi dan pembaruan status
- Menambahkan penanganan untuk konteks 'Paparan' pada otorisasi.
- Memperbaiki kesalahan penamaan variabel dari 'nulai_plafond_id' menjadi 'nilai_plafond_id'.
- Memperbarui status otorisasi berdasarkan peran pengguna.
- Menambahkan pembaruan status permohonan untuk konteks 'paparan'.
2025-01-22 07:33:58 +07:00
Daeng Deni Mardaeni
6e6611c02c fix(SLAController): tambahkan filter jenis 'sla' pada query Authorization
- Memperbarui query Authorization untuk hanya mengambil data dengan jenis 'sla'.
- Menambahkan logika untuk pencarian berdasarkan parameter yang diberikan.
2025-01-22 07:00:03 +07:00
Daeng Deni Mardaeni
fde505a5b2 fix(form): perbaiki tampilan form input
- Memperbaiki kesalahan tampilan pada elemen input.
2025-01-21 15:10:17 +07:00
Daeng Deni Mardaeni
b2b8c0e9cd fix(informasi): perbaiki tampilan foto tempat
- Memastikan foto tempat ditampilkan dengan benar jika merupakan array.
- Menambahkan kondisi untuk menangani kasus ketika foto tempat tidak ada.
2025-01-21 15:08:48 +07:00
Daeng Deni Mardaeni
a4ca00c88b fix(history-permohonan): perbaiki tampilan catatan aktivitas
- Menambahkan kondisi untuk menampilkan label 'Catatan' hanya jika ada keterangan.
- Memastikan tampilan lebih bersih saat tidak ada keterangan yang tersedia.
2025-01-21 14:49:06 +07:00
Daeng Deni Mardaeni
edbe452f8b fix(form): perbaiki tampilan textarea keterangan
- Mengubah cara menampilkan catatan registrasi pada textarea.
- Menambahkan newline sebelum keterangan penilaian jika ada catatan registrasi.
2025-01-21 14:48:15 +07:00
Daeng Deni Mardaeni
6d4d172ccf fix(history-permohonan): tambahkan label 'Catatan' pada keterangan aktivitas
- Memperjelas informasi dengan menambahkan label 'Catatan' sebelum keterangan aktivitas.
- Meningkatkan keterbacaan dan pemahaman pengguna terhadap informasi yang ditampilkan.
2025-01-21 14:44:58 +07:00
Daeng Deni Mardaeni
5211f9a337 fix(form): perbaiki kesalahan penamaan variabel
- Mengubah penamaan variabel 'registrasi_catatatn' menjadi 'registrasi_catatan' pada textarea.
2025-01-21 14:38:50 +07:00
Daeng Deni Mardaeni
9a25aaed8c fix(form): perbaiki kesalahan penamaan variabel dan tampilkan foto tempat
- Memperbaiki penamaan variabel dari 'registrasi_cat' menjadi 'registrasi_catatatn' pada textarea.
- Menambahkan pengecekan untuk memastikan 'forminspeksi' ada sebelum menampilkan foto tempat.
- Memastikan foto tempat hanya ditampilkan jika ada dalam array.
2025-01-21 14:37:19 +07:00
Daeng Deni Mardaeni
9db44f8855 fix(surveyor): perbaiki tampilan foto tempat
- Menambahkan pengecekan untuk memastikan foto tempat ditampilkan hanya jika ada.
- Menghindari tampilan elemen gambar yang tidak perlu saat tidak ada foto.
2025-01-21 12:57:01 +07:00
putrakuningan
2aa9267c12 Merge pull request 'perbaikan tampilan memo tidak tampil di so' (#75) from feature/senior-officer into staging
Reviewed-on: #75
2025-01-21 06:38:29 +01:00
majid
86e6e5e7bf perbaikan pembanding input bangunan 2025-01-21 06:38:29 +01:00
majid
0dd375494e perbaikan foto tempat 2025-01-21 06:38:29 +01:00
Daeng Deni Mardaeni
51203e987e Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-01-21 12:36:45 +07:00
majid
d101db1043 Merge branch 'staging' into feature/senior-officer 2025-01-21 12:32:55 +07:00
majid
27be516a67 perbaikan pembanding input bangunan 2025-01-21 12:30:49 +07:00
majid
60b2fac278 perbaikan foto tempat 2025-01-21 12:23:51 +07:00
majid
a60a8c7ec4 fix(so): tampilan memo tidak tampil 2025-01-21 12:11:04 +07:00
Daeng Deni Mardaeni
88a74597fa Merge remote-tracking branch 'origin/feature/senior-officer' into staging 2025-01-21 11:58:14 +07:00
majid
9cb50c4110 fix(surveyor):perbaikan image preview 2025-01-21 11:50:12 +07:00
Daeng Deni Mardaeni
04eba570e5 Merge remote-tracking branch 'origin/feature/senior-officer' into staging 2025-01-20 15:24:22 +07:00
majid
08c296fd50 fix(surveyor): perbaikan foto objek jaminan jika belum di isi di inspeksi foto 2025-01-20 15:20:12 +07:00
Daeng Deni Mardaeni
0a38319d98 feat(jaminan): tambahkan tampilan detail jaminan
- Menambahkan pengecekan untuk menampilkan detail jaminan jika tersedia.
- Menggunakan json_decode untuk mengurai data detail.
- Menampilkan setiap detail dalam format yang rapi dengan pemisah.
2025-01-20 15:17:04 +07:00
Daeng Deni Mardaeni
7c9b73b2bc Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-01-20 15:00:00 +07:00
Daeng Deni Mardaeni
4ac772ced4 fix(dokumen): perbaiki penamaan input custom_field
- Mengubah format penamaan input custom_field untuk memastikan konsistensi.
- Memperbaiki penggunaan tanda kurung pada penamaan agar sesuai dengan standar.
2025-01-20 14:59:53 +07:00
majid
73255420f1 fix(surveyor): perbaikan alamat 2025-01-20 14:56:24 +07:00
majid
b2d4806036 Merge branches 'feature/senior-officer' and 'staging' of 2025-01-20 12:31:44 +07:00
majid
532d48c66f perbaikan data pembanding dan print out resume 2025-01-20 11:53:06 +07:00
Daeng Deni Mardaeni
f7f4adc6b0 fix(surveyor): perbaiki pengambilan data luas tanah bangunan
- Memastikan data luas tanah bangunan diambil hanya jika 'bangunan' ada dalam $inspectionData.
- Menghindari kesalahan jika 'bangunan' tidak ada dengan menambahkan pemeriksaan isset.
2025-01-20 11:50:36 +07:00
Daeng Deni Mardaeni
6f182e7229 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-01-20 10:13:12 +07:00
majid
6cd79cce8b Merge branch 'staging' into feature/senior-officer 2025-01-20 10:09:29 +07:00
majid
e794d3babc perbaikan tanggal kunjungan surveyor 2025-01-20 10:08:18 +07:00
Daeng Deni Mardaeni
4d5d2625e5 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-01-18 06:18:29 +07:00
majid
0b56403436 penambahanan otorisari paparan 2025-01-17 10:51:09 +07:00
Daeng Deni Mardaeni
578537704a Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-01-16 19:35:07 +07:00
majid
e6adcd8185 perbaikan laporan belum bayar lansung mengarah ke resume dan urutan tampilan foto 2025-01-16 14:32:14 +07:00
Daeng Deni Mardaeni
669c9a0ae4 fix(penilaian): perbaiki tampilan textarea keterangan
- Mengubah nilai default textarea keterangan untuk menampilkan registrasi_cat dari permohonan.
- Memastikan keterangan yang ada tetap ditampilkan jika tersedia.
2025-01-16 11:56:52 +07:00
Daeng Deni Mardaeni
972c1b5fd8 fix(pdfviewer): perbaiki ukuran modal tampilan PDF dan gambar
- Mengubah lebar modal dari 1500px menjadi 1280px
- Mengubah tinggi modal dari 1200px menjadi 768px
2025-01-16 11:23:33 +07:00
Daeng Deni Mardaeni
b852587ace fix(controller): perbaiki pencarian nomor registrasi
- Mengubah query pencarian untuk menggunakan orWhereRelation pada beberapa controller.
- Menghapus beberapa kondisi pencarian yang tidak diperlukan.
- Memastikan pencarian nomor registrasi dapat dilakukan dengan lebih efisien.
2025-01-16 11:20:50 +07:00
daengdeni
b0eab49755 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-01-15 16:50:34 +07:00
majid
1e2b6f21ae perbaikan url query param surveyor dan perbaikan tampilan team activity 2025-01-15 16:06:51 +07:00
daengdeni
a37a65f3d7 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2025-01-15 10:36:38 +07:00
majid
47bf238196 perbaikan upadte assign team activity jika berhalangan by region dan team 2025-01-15 10:12:07 +07:00
majid
f8bd3836db perbaikan team activity di so 2025-01-15 07:27:33 +07:00
majid
144a31a960 Merge branch 'staging' into feature/senior-officer 2025-01-14 09:53:19 +07:00
majid
1d0aff2893 penambahan field rap 2025-01-14 09:51:35 +07:00
majid
76c1a74c3a penambahan lampiran foto dokumen dan paparan di so dan ganti unit di jenis jaminan ruko rukan 2025-01-14 09:50:25 +07:00
Daeng Deni Mardaeni
65f3c60ae9 feat(view): tambahkan kolom Status Bayar pada tampilan progres aktivitas
- Menambahkan kolom "Status Bayar" pada tabel progres aktivitas.
- Mengimplementasikan rendering status bayar dengan kelas CSS untuk menandai status.
- Memperbaiki format tampilan status untuk konsistensi visual.
2025-01-14 09:44:10 +07:00
Daeng Deni Mardaeni
eff324614d fix(view): hapus elemen nilai NJOP yang tidak diperlukan
- Menghapus bagian yang menampilkan nilai NJOP dari beberapa tampilan:
  - detail-jaminan.blade.php
  - print.blade.php
  - show.blade.php
- Memperbaiki tampilan dengan mengurangi elemen yang tidak relevan.
2025-01-14 09:27:39 +07:00
Daeng Deni Mardaeni
f198fff803 fix(view): perbaiki format dan penamaan elemen dalam tampilan otorisator
- Mengubah urutan kelas CSS untuk konsistensi.
- Menambahkan kolom 'Penilai' pada tabel.
- Memperbaiki render data untuk kolom 'Penilai'.
- Menyusun ulang elemen footer untuk tata letak yang lebih baik.
2025-01-14 09:23:42 +07:00
Daeng Deni Mardaeni
7b60a8413e fix(controller): perbaiki format dan penamaan fungsi dalam PenilaianController
- Memperbaiki penamaan dan format pada penggunaan model Penilai.
- Menyempurnakan relasi data yang diambil dalam query.
- Memperbaiki format string dalam beberapa bagian kode untuk konsistensi.
2025-01-14 09:23:29 +07:00
Daeng Deni Mardaeni
5e7cdcd164 fix(models): perbaiki format dan penamaan fungsi dalam model PenilaianTeam
- Memperbaiki format array $fillable untuk konsistensi.
- Menmbahkan relasi 'user' untuk mempermudah pemanggilan.
- Menambahkan spasi dan format yang lebih baik pada fungsi.
2025-01-14 09:22:58 +07:00
majid
090bb618b1 perbaikan kertas kerja 2025-01-13 11:19:58 +07:00
majid
c3809ca06d perbaikan print out standard 2025-01-13 11:16:23 +07:00
majid
0f4a0a12ee perbaikan data pembanding 2025-01-13 10:48:07 +07:00
majid
8db7e5d654 perbaikan update data lpj standar dan sederhana 2025-01-13 06:20:16 +07:00
majid
6289a752e0 perbaikan activity team so dan logo bag 2025-01-11 08:54:24 +07:00
majid
c1b573a275 perbaikan print out memo, resume, rap , standard dan sederhana 2025-01-10 15:53:58 +07:00
majid
e84bce7034 perbaikan nomor laporan, dan penambahan button revisi laporan di so 2025-01-09 17:01:35 +07:00
majid
9c5c91ae9c penambahan pengecekan jika laporan belum ada tidak bisa melakukan reported ke so 2025-01-09 10:56:47 +07:00
majid
a74f5bff5f perbaikan laporan penilai dan print out 2025-01-09 10:18:52 +07:00
majid
029260bcef perbaikan pembanding kendaraan, alat berat, pesawat, kapal, print out dan ukuran foto pada objek jaminan 2025-01-08 13:53:18 +07:00
majid
92ac480c9b perbaikan laporan berdasarkan form inspeksi di so dan penilai dan perbaikan tambah data di jenis jaminan 2025-01-08 07:42:10 +07:00
majid
fcc53a7111 perbaikan diskon data pembanding, luas tanah, bangunan, apartement di form inspeksi 2025-01-06 16:30:11 +07:00
majid
a74f3a1865 Merge branch 'staging' into feature/senior-officer 2025-01-06 14:27:48 +07:00
majid
e4f48dbc40 update print out sederhana, resume, memo dan paparan dan penambahan breadcrumbs 2025-01-06 14:26:28 +07:00
majid
a22addeb50 tambah info status pembayaran di penilai 2025-01-05 00:46:28 +07:00
Daeng Deni Mardaeni
f4721bdf29 Merge remote-tracking branch 'composer/feature/senior-officer' into staging
# Conflicts:
#	app/Http/Controllers/SurveyorController.php
#	resources/views/surveyor/index.blade.php
2025-01-03 18:03:08 +07:00
majid
b7767fbc92 perabaikan team activity, form inspeksi rap,laporan memo, rap, resume dan penambahan basic data perizinan 2025-01-03 16:49:20 +07:00
Daeng Deni Mardaeni
76d9de791d Revert "Update daftar dokumen yang dikecualikan"
This reverts commit b3f30f1a0b.
2025-01-03 05:24:55 +07:00
Daeng Deni Mardaeni
b3f30f1a0b Update daftar dokumen yang dikecualikan
- Menambahkan "List Jaminan" ke dalam daftar dokumen yang dikecualikan di file `edit.blade.php` dan `documentSPK.blade.php`.
- Perubahan ini memastikan dokumen tersebut tidak ditampilkan sesuai kebutuhan aplikasi.
2025-01-03 05:20:13 +07:00
Daeng Deni Mardaeni
0d1d1f58b2 Tambah fitur otorisasi SLA
- Menambahkan view baru untuk otorisasi SLA (`sla.blade.php` dan `index-sla.blade.php`).
- Menambahkan route baru untuk data datatables SLA (`sla.datatables`).
- Mengupdate controller (`PenilaianController`, `SLAController`) untuk mendukung alur otorisasi SLA.
- Menyesuaikan model `Authorization` guna kebutuhan SLA.
2025-01-01 22:53:07 +07:00
Daeng Deni Mardaeni
ec247a70ab Refactor Surveyor module and update form handling
- Ubah ID elemen HTML di halaman Surveyor
- Perbarui textarea dan validasi terkait dengan "alasan"
- Refaktor dan optimalkan code untuk SurveyorController
- Tambahkan konstanta, properti, dan metode baru untuk mengatur inspeksi, denah, serta data permohonan
- Perbaiki struktur data dengan menambah model dan atribut terkait
2025-01-01 22:00:51 +07:00
Daeng Deni Mardaeni
ee52f70633 Tambah tabel dan model Authorization
- Menambahkan migrasi untuk tabel "authorizations" guna menyimpan data otorisasi terkait permohonan.
- Membuat model Authorization dengan relasi ke tabel Permohonan dan Users.
- Menyediakan cast dan properti fillable untuk mempermudah manipulasi data.
2025-01-01 22:00:23 +07:00
Daeng Deni Mardaeni
002882fe2f Tambahkan pengecekan untuk pengecualian nomor dokumen
- Menambahkan variabel `$shouldExcludeNomor` untuk memeriksa apakah nomor dokumen perlu dikecualikan.
- Loop pengecekan ditambahkan untuk membandingkan `dokumen_nomor` dengan excludedDocuments.
- Hanya menampilkan nomor dokumen jika tidak masuk dalam daftar pengecualian.
2025-01-01 21:35:17 +07:00
Daeng Deni Mardaeni
d665a17ded Perbarui logika pengecualian dokumen pada tampilan SPK
- Menambahkan logika untuk mengecualikan dokumen tertentu seperti "Bukti Bayar" dan "NPWP".
- Memastikan dokumen yang dikecualikan tidak ditampilkan pada tampilan edit SPK dan documentSPK.
2025-01-01 21:28:18 +07:00
Daeng Deni Mardaeni
cd1185a559 Update logika tampilan status dan relasi data di Permohonan
- Menambahkan logika untuk menampilkan pesan "Lengkapi Aset Jaminan" ketika dokumen belum lengkap di tampilan status.
- Memperbaiki query untuk menyertakan relasi 'documents' dalam data Permohonan.
2025-01-01 21:25:05 +07:00
Daeng Deni Mardaeni
8a69970542 Tambahkan validasi dan relasi dokumen jaminan pada permohonan
- Menambahkan pengecekan keberadaan dokumen jaminan saat membuat atau memperbarui permohonan.
- Menambahkan relasi `has('documents')` pada query permohonan untuk memastikan hanya data yang memiliki dokumen terkait yang ditampilkan.
- Menambahkan tampilan nomor permohonan di komponen dokumen pada view.
- Merapikan dan memperbaiki format kode pada berbagai fungsi controller.
2025-01-01 20:48:04 +07:00
majid
64ba6cf71e Merge branch 'staging' into feature/senior-officer 2025-01-01 19:51:27 +07:00
majid
b2287838b7 perbaikan fominspeksi upload foto 2025-01-01 19:48:26 +07:00
Daeng Deni Mardaeni
fc5f02de43 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-31 17:14:43 +07:00
majid
08de0eeb00 perbaikan name objek null 2024-12-31 17:10:13 +07:00
Daeng Deni Mardaeni
7156e4ba64 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-31 16:41:41 +07:00
majid
0a5afe39e0 perbaikan print out standart 2024-12-31 16:41:06 +07:00
Daeng Deni Mardaeni
cba3dee0b4 Perbaiki logika looping dan penanganan data pada komponen memo
- Mengubah struktur pengaksesan array pada `$formFoto['rute_menuju_lokasi']` untuk memastikan data di-looping dengan benar.
- Menambahkan pengecekan keberadaan key `path` sebelum menampilkan gambar untuk menghindari error.
2024-12-31 15:33:49 +07:00
Daeng Deni Mardaeni
1dc7ee3724 Perbaiki penggunaan data di komponen memo
- Ganti 'name_rute' menjadi 'name' untuk menampilkan nama
- Perbarui path gambar dari 'foto_rute' menjadi 'path'
2024-12-31 15:21:37 +07:00
Daeng Deni Mardaeni
f9b20bc18b Perbaiki potensi error pada penamaan rute
- Menambahkan pengecekan null pada properti `name_rute` agar mencegah error ketika data tidak tersedia.
- Memastikan aplikasi tetap berjalan lancar meski properti `name_rute` kosong.
2024-12-31 15:19:35 +07:00
majid
f490d337a4 Merge branch 'staging' into feature/senior-officer 2024-12-31 14:43:04 +07:00
majid
bf982a3990 update inputan luas tanah, bangunan, unit 2024-12-31 14:42:04 +07:00
Daeng Deni Mardaeni
d84c292e9b "Perbaiki format kode dan penyesuaian indentation"
- Merapikan kode dengan memperbaiki indentation agar lebih konsisten.
- Tidak ada perubahan logika atau fungsionalitas pada file `edit.blade.php`.
- Meningkatkan keterbacaan kode untuk pengembangan selanjutnya.
2024-12-31 14:32:42 +07:00
Daeng Deni Mardaeni
cbf5d8a983 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-31 14:19:58 +07:00
majid
0d54a2590f tambah nama debiture di proses penawaran 2024-12-31 14:18:46 +07:00
Daeng Deni Mardaeni
f84fa70087 Update label dari "Nomor" menjadi "Nama Dokumen"
- Mengubah label di beberapa bagian form pada dokumen.blade.php.
- Label "Nomor" diganti menjadi "Nama Dokumen" untuk meningkatkan kejelasan fungsi input.
2024-12-31 14:10:41 +07:00
Daeng Deni Mardaeni
1d8a7180ab Tambahkan relasi 'jenisPenilaian' dan perbaiki akses data nullable
- Menambahkan relasi 'jenisPenilaian' pada PenilaianController untuk memastikan data lengkap.
- Memperbaiki akses data nullable pada view index.blade.php untuk menghindari error saat data kosong.
2024-12-31 14:07:34 +07:00
Daeng Deni Mardaeni
d21c198f4a Perbaiki logika pemrosesan data pada file create.blade.php
- Tambahkan pemrosesan ulang untuk `form_kategori` agar lebih robust dalam menangani JSON kosong atau tidak valid.
- Perbarui logika untuk validasi `jenis_legalitas_jaminan_id` agar memastikan data terdecode dengan benar sebelum digunakan.
2024-12-31 13:44:27 +07:00
Daeng Deni Mardaeni
3e0c43420e Perbaiki potensi error saat menampilkan nama objek
- Menambahkan fallback nilai kosong ("") jika 'name_objek' tidak tersedia.
- Mencegah error undefined index pada komponen memo.
2024-12-31 13:34:44 +07:00
Daeng Deni Mardaeni
cfa8c3eb8a Perbaiki penanganan data null pada foto lampiran
- Tambahkan default nilai kosong ("") untuk variabel `name_objek` jika null.
- Hapus spasi berlebih dalam struktur HTML untuk meningkatkan kerapihan kode.
2024-12-31 13:33:15 +07:00
putrakuningan
d97e0bea38 Merge pull request 'ganti tujuan_penilaian jadi tujuan_penilaian_kjpp' (#70) from feature/senior-officer into staging
Reviewed-on: #70
2024-12-31 06:07:30 +00:00
majid
5352687713 ganti tujuan_penilaian jadi tujuan_penilaian_kjpp 2024-12-31 13:05:01 +07:00
majid
1e6f12d3a4 perbaikan tampilan di penilai 2024-12-31 12:04:39 +07:00
majid
5b21243f3b Merge branch 'staging' into feature/senior-officer 2024-12-31 11:31:28 +07:00
majid
345fe30710 perbaikan denah bisa banyak 2024-12-31 11:30:35 +07:00
Daeng Deni Mardaeni
7970bde74b Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-31 10:33:09 +07:00
majid
81be786844 update nilai npw beradasarkan jaminan 2024-12-31 10:16:09 +07:00
Daeng Deni Mardaeni
483c69e8f1 Tambahkan fitur input dan pengelolaan Nilai Liquidasi
- Menambahkan kolom "nilai_liquidasi" pada tabel "permohonan" melalui migrasi baru.
- Memperbarui LaporanController untuk menyimpan dan menampilkan data Nilai Liquidasi.
- Menambahkan tampilan halaman input Nilai Liquidasi dengan validasi dan perhitungan otomatis.
- Memodifikasi tampilan daftar laporan untuk menunjukkan status Nilai Liquidasi.
- Menambahkan relasi baru pada model Permohonan untuk mengakses data Penilai.
2024-12-31 09:49:27 +07:00
Daeng Deni Mardaeni
848f103631 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-31 09:00:15 +07:00
majid
800d0c2496 perbaikan laporan so , form inspksi alat berat, kendaraan dan mesin 2024-12-31 07:56:41 +07:00
Daeng Deni Mardaeni
e933daaa41 Update margin bawah tabel di halaman progres aktivitas
- Mengubah kelas margin dari `my-4` menjadi `mb-4` untuk tabel.
- Penyesuaian memastikan konsistensi tampilan margin bawah tabel.
2024-12-30 21:11:35 +07:00
Daeng Deni Mardaeni
2230a2349e Perbarui logika filter dan tampilan laporan serta otorisasi
- Menambahkan logika filter tambahan pada status permohonan di `LaporanController`.
- Memperbaiki render button berdasarkan kondisi `status_bayar` di `laporan/index.blade.php`.
- Menambahkan relasi baru untuk data penilaian di `PenilaianController`.
- Memperbaiki validasi nilai plafon pada fitur otorisasi di `otorisator/index.blade.php`.
- Menambahkan kondisi dinamis untuk data persetujuan EO dan DD di `otorisator/show.blade.php`.
2024-12-30 17:44:51 +07:00
majid
676619f5df perbaikan tampilan informasi harga di print out 2024-12-30 15:51:16 +07:00
Daeng Deni Mardaeni
f05051c4c8 Merge remote-tracking branch 'composer/feature/senior-officer' into staging
# Conflicts:
#	app/Http/Controllers/PenilaianController.php
#	resources/views/penilai/components/lpj-sederhana-standard.blade.php
2024-12-30 15:16:26 +07:00
majid
abd218739d perbaikan laporan so dan team activity 2024-12-30 15:11:26 +07:00
Daeng Deni Mardaeni
cfc2585fa4 Tambahkan menu baru untuk otorisasi pembatalan permohonan
- Menambahkan menu "Otorisasi Pembatalan Permohonan" dengan path `otorisator.pembatalan` dan peran untuk "administrator", "senior-officer", dan "pemohon-eo".
- Menghapus entri duplikat menu terkait otorisasi pembatalan dengan peran yang tidak sesuai.
2024-12-30 14:10:06 +07:00
Daeng Deni Mardaeni
3ee901e3b0 Update judul menu otorisasi
- Mengubah judul menu pada module.json untuk menambahkan konteks "Otorisasi".
- Judul yang diperbarui: "Permohonan" menjadi "Otorisasi Permohonan", "Pembayaran" menjadi "Otorisasi Pembayaran", dan lainnya.
- Perubahan bertujuan untuk meningkatkan kejelasan dan konsistensi dalam penamaan menu.
2024-12-30 13:53:47 +07:00
Daeng Deni Mardaeni
2ae41c33cd Refactor logika update status permohonan dan penawaran
- Memindahkan logika update status permohonan dan penawaran dari `PersetujuanPenawaranController` ke `PembayaranController`.
- Menambahkan validasi pada proses update untuk mengatur kondisi berdasarkan jenis_penilaian_id.
- Membersihkan kode yang tidak diperlukan pada `PersetujuanPenawaranController`.
2024-12-30 13:49:13 +07:00
Daeng Deni Mardaeni
5dc194c97a "Perbaiki logika pengecekan pada approval pembayaran
- Tambahkan validasi null pada properti 'approve_bayar' untuk menghindari error.
- Perbaiki referensi properti 'approve_bayar_by' pada pengecekan otorisasi pembayaran."
2024-12-30 13:33:53 +07:00
Daeng Deni Mardaeni
6066e1ee91 Perbaiki logika validasi pada approval pembayaran
- Mengubah validasi untuk memastikan objek `permohonan` tidak null sebelum digunakan.
- Menambahkan perlakuan default saat `permohonan` tidak tersedia.
2024-12-30 13:31:42 +07:00
Daeng Deni Mardaeni
d14363d27c Perbaiki logika render data pada approval pembayaran
- Tambahkan pengecekan `data.penawaran` sebagai alternatif jika `data.permohonan` tidak ada.
- Mengatasi kemungkinan error ketika data permohonan tidak tersedia.
2024-12-30 13:29:25 +07:00
Daeng Deni Mardaeni
5a296ed6ed Perbaiki logika pengecekan data pada approval pembayaran
- Tambahkan kondisi pengecekan untuk data penawaran.
- Pastikan variabel `permohonan` terisi benar saat data penawaran tersedia.
2024-12-30 13:28:10 +07:00
Daeng Deni Mardaeni
72806d8a4f Tambah kolom "Jenis Penilaian" pada fitur Penilaian
- Menambah relasi `jenisPenilaian` pada controller untuk pengambilan data.
- Menambahkan kolom "Jenis Penilaian" di tabel tampilan penilaian pada file Blade.
- Menyesuaikan logika render untuk menampilkan data "Jenis Penilaian".
2024-12-30 11:46:45 +07:00
Daeng Deni Mardaeni
2612082454 Perbaiki logika render dan optimasi query pada RegistrasiFinal
- Menambahkan pengecekan null pada kolom tujuan_penilaian_kjpp di file Blade untuk menghindari error.
- Mengubah query di controller dengan menggunakan query builder agar lebih efisien dan readable.
- Menambahkan left join untuk mendapatkan nama tujuan penilaian langsung dalam query.
2024-12-30 11:46:03 +07:00
Daeng Deni Mardaeni
dfc5c73695 Perbarui logika dan tampilan halaman persetujuan pembayaran
- Mengubah nama kolom pada tabel: "Bukti KSL" menjadi "Bukti Bayar", "Tanggal Penyelesaian" menjadi "Keterangan".
- Menambahkan validasi kosong untuk data penawaran jika permohonan tidak ditemukan.
- Memperbaiki fungsi render untuk menangani data permohonan dan penawaran secara kondisional.
- Menghapus tombol aksi yang tidak relevan dan menyederhanakan elemen tombol dalam tabel.
2024-12-30 11:45:27 +07:00
Daeng Deni Mardaeni
7766d92f99 Ubah status permohonan dan penawaran menjadi 'spk'
- Mengubah nilai status permohonan dari 'noc' menjadi 'spk'.
- Memperbarui status penawaran tender terkait dari 'noc' menjadi 'spk'.
- Penyesuaian dilakukan pada `PersetujuanPenawaranController`.
2024-12-30 11:45:07 +07:00
Daeng Deni Mardaeni
418d6858af Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-30 11:09:44 +07:00
majid
4e89280a23 perbaikan print out di menu laporan 2024-12-30 10:01:49 +07:00
Daeng Deni Mardaeni
b9bf8bbee9 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-30 09:43:46 +07:00
Daeng Deni Mardaeni
2bd165a952 Ubah class input dari "currency-format" ke "currency"
- Mengganti semua class input yang sebelumnya "currency-format" menjadi "currency" pada file data-pembanding.blade.php dan lpj-sederhana-standard.blade.php.
- Perubahan dilakukan untuk meningkatkan konsistensi dan kesesuaian dengan penamaan class yang digunakan.
2024-12-30 09:43:16 +07:00
majid
f60a4c558e prbaikan output foto di laporan dan penilai dan surveyor by region 2024-12-30 09:28:06 +07:00
majid
fa0a864a10 Merge branch 'staging' into feature/senior-officer 2024-12-29 22:20:22 +07:00
majid
ea4d5bde64 perbaikan error laporan 2024-12-29 22:19:32 +07:00
Daeng Deni Mardaeni
637b894b49 Perbaiki logika validasi data penawaran
- Mengubah kondisi pengecekan pada data penawaran di beberapa kolom.
- Memastikan data ditampilkan dengan benar meskipun permohonan tidak tersedia.
2024-12-29 21:42:14 +07:00
Daeng Deni Mardaeni
21d1b6cd56 Perbaiki logika render data pada tabel NOC
- Tambahkan pengecekan kondisi untuk memastikan properti `penawaran.permohonan` ada sebelum diakses.
- Tambahkan default return berupa string kosong ('') jika kedua kondisi tidak terpenuhi.
- Meningkatkan keandalan dan mencegah potensi error pada render data.
2024-12-29 21:40:58 +07:00
Daeng Deni Mardaeni
86ad165caa Perbarui struktur menu di module.json
- Memindahkan item "otorisator" ke struktur menu terpisah.
- Mengubah ikon pada beberapa menu untuk konsistensi visual.
- Menambahkan atribut ikon pada menu "Otorisasi Penawaran", "Pembayaran", "Pelaporan", "Pembatalan", dan "SLA".
- Memastikan peran (roles) tetap konsisten pada semua item menu.
2024-12-29 21:13:54 +07:00
Daeng Deni Mardaeni
c02c0cacc4 Filter data permohonan berdasarkan cabang pengguna non-administrator
- Menambahkan pengecekan role pengguna menggunakan `Auth`.
- Membatasi data permohonan hanya untuk cabang yang sesuai dengan pengguna non-administrator.
- Menghindari akses data lintas cabang untuk meningkatkan keamanan dan relevansi data.
2024-12-29 20:41:22 +07:00
Daeng Deni Mardaeni
785f9bf1d9 Refactor struktur menu otorisasi
- Menggabungkan menu "Otorisator", "Otorisasi Tender", "Approval Pembayaran", dan "Authorization" menjadi satu entitas dengan sub-menu sesuai peran.
- Memperbarui akses peran pada setiap sub-menu untuk memastikan hak akses yang sesuai.
- Menghapus redundansi pada menu dan menyederhanakan struktur navigasi.
2024-12-29 20:32:53 +07:00
Daeng Deni Mardaeni
b52abe7773 Perbaiki dan tambahkan fungsi data tambahan di resume
- Ganti penggunaan `forminspeksi` ke `resumeData` untuk konsistensi data.
- Tambahkan dukungan data tambahan dengan input baru untuk `sertifikat`, `luas_tanah`, `luas_bangunan`, dan `nilai`.
- Perbarui script JavaScript untuk menangani data tambahan dan meningkatkan logika pengolahan data JSON.
- Revisi label kesimpulan dari "SESUAI IMB" menjadi "Tambahan".
2024-12-29 15:15:05 +07:00
majid
c3362821c3 perbaikan laporan 2024-12-29 14:10:05 +07:00
majid
371de00add update foto bisa kamera dan gallery 2024-12-29 12:03:35 +07:00
majid
ac622759f9 Merge branch 'staging' into feature/senior-officer 2024-12-29 11:50:28 +07:00
majid
e5fee57d0b penambahan inputan dekat lainnya,pihak bank dan buka galery foto dimobile 2024-12-29 11:49:22 +07:00
Daeng Deni Mardaeni
121b5df9df Update format and display additional city info for KJPP dropdown
- Mengubah tanda pemisah dari "||" menjadi "|" pada daftar KJPP.
- Menambahkan informasi kota untuk KJPP dengan jenis "Kantor Cabang".
- Membersihkan nama kota dengan menghapus prefix seperti "KOTA", "KAB.", atau "KAB".
2024-12-29 10:37:42 +07:00
Daeng Deni Mardaeni
837f9fc098 Refactor handling data memo dan penyesuaian form lokasi
- Memperbaiki struktur data `memo` menjadi objek `lokasi` untuk konsistensi penanganan data.
- Menambahkan properti tambahan pada objek `lokasi`, seperti `tanggal_survey` dan `penilai`.
- Memperbarui logika query terkait kota, kecamatan, dan kelurahan berdasarkan struktur baru.
- Mengubah atribut form dan placeholder untuk mencocokkan perubahan struktur data.
2024-12-29 09:21:16 +07:00
Daeng Deni Mardaeni
970ecff9dc Perbaiki validasi dan tambahkan pesan default untuk rute lokasi
- Menambahkan validasi tambahan untuk memastikan `rute_menuju_lokasi` adalah array sebelum melakukan iterasi.
- Menambahkan pesan default "No route information available" jika data rute tidak tersedia.
2024-12-29 09:09:39 +07:00
majid
3dee218090 Merge branch 'staging' into feature/senior-officer 2024-12-29 06:18:48 +07:00
majid
44197cb2b5 Merge branch 'feature/senior-officer' of https://git.putrakuningan.com/daengdeni/lpj into feature/senior-officer 2024-12-29 06:12:02 +07:00
majid
e62524e683 perbaikan foto dan penambahan basic data foto objek jaminan, print-out 2024-12-29 06:10:45 +07:00
Daeng Deni Mardaeni
026eb1115b Refactor card styles for consistency across views
- Menambahkan border dan background pada elemen card dengan class `border-agi-100` dan `bg-agi-50`.
- Perubahan berlaku di berbagai file blade untuk meningkatkan konsistensi UI.
2024-12-28 17:09:32 +07:00
Daeng Deni Mardaeni
516fd580e2 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-28 08:49:54 +07:00
majid
9a24751f65 update view laporan di so 2024-12-28 07:27:00 +07:00
Daeng Deni Mardaeni
934be4dc71 Integrasikan data memo ke form memo penilai
- Memperbaiki binding data memo ke input form mengenai memo penilai.
- Menambahkan logika untuk menampilkan pilihan kota, kecamatan, dan kelurahan berdasarkan provinsi, kota, dan kecamatan yang dipilih.
- Menyesuaikan tampilan memo dengan data dari database, termasuk hasil survey, kesimpulan saran, dan file terlampir.
- Melakukan perbaikan minor pada struktur kode untuk konsistensi.
2024-12-27 17:20:24 +07:00
Daeng Deni Mardaeni
ce3fcd39b0 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-27 16:55:33 +07:00
majid
2005f546c5 update foto lantai 2024-12-27 16:52:02 +07:00
Daeng Deni Mardaeni
722b6d0e72 Perbaiki pengecekan file kertas kerja penilai
- Menambahkan validasi untuk memastikan `$penilai` dan `$penilai->kertas_kerja` tidak null.
- Menghindari potensi error ketika data `kertas_kerja` tidak tersedia.
2024-12-27 16:29:43 +07:00
Daeng Deni Mardaeni
37eb6ac929 Perbaiki render data tabel penilai
- Tambahkan pengecekan null untuk beberapa field (debitur, branch, user, tujuan_penilaian, jenis_fasilitas_kredit) agar mencegah error saat data tidak tersedia.
- Pastikan tampilkan '-' jika data terkait tidak ada.
2024-12-27 16:11:12 +07:00
Daeng Deni Mardaeni
8e2a241671 Perbaiki render data tabel penilai
- Tambahkan pengecekan null untuk beberapa field (debitur, branch, user, tujuan_penilaian, jenis_fasilitas_kredit) agar mencegah error saat data tidak tersedia.
- Pastikan tampilkan '-' jika data terkait tidak ada.
2024-12-27 16:09:02 +07:00
Daeng Deni Mardaeni
df4b6ad545 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-27 15:59:14 +07:00
majid
78184094f6 update foto jaminan dan laporan preview 2024-12-27 15:58:31 +07:00
Daeng Deni Mardaeni
198ad87ea2 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-27 14:08:12 +07:00
majid
b70b3b730f perbaikan print out dan penambahan nomor laporan 2024-12-27 11:29:55 +07:00
Daeng Deni Mardaeni
daedd5321b Add "Nomor Permohonan" field to jaminan component
- Menambahkan field baru "Nomor Permohonan" pada komponen jaminan.
- Menambahkan pemisah garis menggunakan border-dashed untuk meningkatkan keterbacaan.
2024-12-27 09:44:11 +07:00
Daeng Deni Mardaeni
66b8a9053b Perbaiki validasi, logika, dan tampilan terkait dokumen jaminan
- Menambahkan validasi untuk `permohonan_id` pada `DokumenJaminanRequest`.
- Memperbaiki logika penggabungan parameter query untuk rute tertentu.
- Merapikan formatting kode pada tampilan blade, termasuk elemen HTML dan JavaScript.
- Mengatasi beberapa bug minor terkait aksi dan tampilan dokumen jaminan.
2024-12-27 09:36:07 +07:00
majid
66d0226d55 update header printout standart 2024-12-27 09:00:27 +07:00
Daeng Deni Mardaeni
407306e085 Merge remote-tracking branch 'composer/feature/senior-officer' into staging
# Conflicts:
#	resources/views/surveyor/components/tanah.blade.php
2024-12-27 08:50:01 +07:00
majid76
decca9be29 update print out laporan 2024-12-27 04:16:01 +07:00
Daeng Deni Mardaeni
b329b0d6f2 Perbaiki perintah update composer pada Jenkinsfile
- Mengganti package dari "daengdeni/lpj:staging" menjadi "daengdeni/lpj-module:dev-staging".
- Penyesuaian ini diperlukan agar sesuai dengan struktur dan branch terbaru pada repository.
2024-12-25 22:41:43 +07:00
Daeng Deni Mardaeni
b4ca344d0f Update Jenkinsfile untuk perintah checkout
- Mengubah direktori dari `${env.WORKDIR}` ke `${env.DASHBOARD}`
- Mengganti proses git checkout dan pull dengan perintah `composer update daengdeni/lpj:staging`
- Penyederhanaan langkah untuk manajemen dependensi
2024-12-25 22:39:34 +07:00
Daeng Deni Mardaeni
de3d8791bb Perbarui Jenkinsfile untuk memperbaiki proses build
- Mengganti penggunaan sshagent dengan `withEnv` untuk mendukung konfigurasi GIT_SSH_COMMAND.
- Memperbaiki direktori build dari WORKDIR ke DASHBOARD.
2024-12-25 22:23:30 +07:00
Daeng Deni Mardaeni
6941895b0e Update Jenkinsfile for Git SSH and Credentials Setup
- Menambahkan `GIT_SSH_COMMAND` untuk mendukung SSH kustom dengan private key.
- Menggunakan `sshagent` dengan kredensial `putra_pass` untuk proses checkout dan pull.
- Memperbaiki proses integrasi dengan Git yang lebih aman dan terstruktur.
2024-12-25 22:21:06 +07:00
Daeng Deni Mardaeni
9fcede4dc6 Refactor Jenkinsfile untuk optimasi pipeline
- Menambahkan variabel lingkungan DASHBOARD dan WORKDIR untuk penyederhanaan path.
- Menggunakan fungsi `dir` untuk memastikan konteks direktori kerja pada tahap 'Checkout' dan 'Build Assets'.
- Menghilangkan duplikasi perintah penggantian direktori manual.
2024-12-25 21:38:19 +07:00
Daeng Deni Mardaeni
b06016aa41 Perbaiki proses checkout di Jenkinsfile
- Mengganti langkah `checkout scm`
2024-12-25 21:33:18 +07:00
Daeng Deni Mardaeni
7298bc8b19 Tambah Jenkinsfile untuk pipeline CI/CD
- Menambahkan file Jenkinsfile baru
- Memasukkan tahap-tahap pipeline seperti Checkout dan Build Assets
- Menyertakan konfigurasi environment untuk PHP dan Composer
- Membersihkan workspace setelah pipeline selesai
2024-12-25 21:28:38 +07:00
Daeng Deni Mardaeni
092ecba7f1 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-25 18:01:49 +07:00
majid
7c55d7624e perbaikan print out dan foto 2024-12-25 09:25:42 +07:00
Daeng Deni Mardaeni
c15e08e7c5 Tambahkan validasi form untuk data debitur
- Menambahkan properti `id` pada elemen form untuk mempermudah manipulasi DOM.
- Menandai field wajib dengan tanda bintang (*) dan memastikan validasi untuk field yang diperlukan.
- Menambahkan script JavaScript untuk validasi input form secara dinamis, termasuk cek keberadaan data dan memberikan feedback error real-time.
- Menambahkan event listener untuk memastikan semua field tervalidasi sebelum pengiriman form.
2024-12-25 07:52:19 +07:00
Daeng Deni Mardaeni
98f6e9cf3c Tambahkan kolom "Debitur" pada tabel surveyor
- Menambahkan kolom baru dengan judul "Debitur" di tabel pada halaman surveyor.
- Data diambil dari properti `debiture.name` atau ditampilkan sebagai "N/A" jika tidak tersedia.
2024-12-24 14:56:11 +07:00
Daeng Deni Mardaeni
6e64109077 Update render logic for table fields to handle null values
- Menambahkan pengecekan null untuk beberapa field seperti user, branch, tujuan penilaian, dan jenis fasilitas kredit.
- Mencegah error dengan menampilkan 'N/A' jika data tidak tersedia.
2024-12-24 14:54:47 +07:00
Daeng Deni Mardaeni
5738269bff Perbaiki penugasan variabel di komponen tanah
- Memperbaiki kesalahan penugasan variabel `$hadap_mata_angin` pada kondisi fallback.
- Menghindari potensi bug dengan memastikan nilai default tertulis dengan benar.
2024-12-24 14:48:04 +07:00
Daeng Deni Mardaeni
f9f9f455ed Perbaiki logika pengolahan data luas tanah
- Menambahkan pengecekan jenis data untuk variabel `luas` sebelum mengakses detailnya.
- Mencegah potensi error dengan mengatur default value `luas_tanah` menjadi 'N/A' jika data tidak valid.
2024-12-24 14:40:21 +07:00
Daeng Deni Mardaeni
baeb38c47d Perbaiki logika dan format pada komponen tanah
- Menambahkan validasi array pada penghitungan luas tanah.
- Memperbaiki format dan konsistensi kode pada radio button, checkbox, dan input field.
- Mengoptimalkan toggle visibility untuk elemen dinamis (e.g., input "lainnya").
- Menyesuaikan struktur form untuk meningkatkan keterbacaan dan maintainability.
2024-12-24 14:36:36 +07:00
Daeng Deni Mardaeni
cf75f63c20 Setel input harga diskon menjadi readonly
- Menambahkan atribut `readonly` pada input `harga_diskon` dan `harga_diskon_pembanding` untuk mencegah pengeditan langsung.
- Menghapus pembatas nilai maksimum 100 pada event listener input diskon pembanding.
2024-12-24 14:20:29 +07:00
Daeng Deni Mardaeni
5893050e84 Perbaiki pengecekan variabel pada komponen foto lampiran
- Mengganti pengecekan `isset($formFoto)` menjadi `isset($formFoto['rute_menuju_lokasi'])`
- Memastikan data yang diakses lebih spesifik untuk menghindari potensi error.
2024-12-24 14:08:51 +07:00
majid
017d6a85b8 Merge branch 'staging' into feature/senior-officer 2024-12-24 13:48:58 +07:00
majid
27269e1b46 update print out 2024-12-24 13:45:06 +07:00
Daeng Deni Mardaeni
163eee5b8c Perbaiki logika pengecekan form foto
- Mengubah kondisi pengecekan dari `isset($formFoto)` menjadi `isset($formFoto['rute_menuju_lokasi'])`.
- Memastikan data `rute_menuju_lokasi` tersedia sebelum melakukan iterasi untuk menampilkan foto.
2024-12-24 13:29:27 +07:00
Daeng Deni Mardaeni
f3da3ad7f8 Tambah logging untuk penanganan error saat generate PDF
- Menambahkan fungsi try-catch di `PenilaiController` untuk menangani kesalahan saat proses pembuatan file PDF.
- Menggunakan `Illuminate\Support\Facades\Log` untuk mencatat error yang terjadi.
- Memperbaiki format dan layout pada file blade `print-out.blade.php` agar lebih konsisten.
2024-12-24 12:58:20 +07:00
Daeng Deni Mardaeni
b20baafe0f Merge remote-tracking branch 'composer/feature/senior-officer' into staging
# Conflicts:
#	resources/views/penilaian/otorisator/show.blade.php
2024-12-24 11:56:47 +07:00
Daeng Deni Mardaeni
7dfda9ffb6 Update role-based query conditions in controllers
- Menambahkan pengecekan peran 'administrator' sebelum menerapkan filter pada relasi `penilaian.userPenilai`.
- Memastikan hanya pengguna non-administrator yang dibatasi berdasarkan `user_id` dan `role`.
2024-12-24 11:51:48 +07:00
majid
1ecc82b243 update lokasi otomatis dan print out 2024-12-24 11:51:00 +07:00
Daeng Deni Mardaeni
78635b6295 Perbarui pesan sukses otorisasi
- Menambahkan informasi "Menunggu Approval EO dan atau DD" pada pesan sukses otorisasi di halaman index dan show.
- Memastikan pengguna memahami proses lanjutan setelah otorisasi.
2024-12-24 11:33:56 +07:00
Daeng Deni Mardaeni
d1668cf044 Tambahkan fitur persetujuan pada otorisator
- Ditambahkan relasi baru di model Permohonan untuk persetujuan SO, EO, dan DD.
- Modifikasi PenilaianController untuk menyertakan data relasi persetujuan.
- Perbaikan dan penyesuaian tampilan tabel dengan kolom persetujuan.
- Tambahkan logika tombol otorisator berdasarkan peran pengguna dan status persetujuan.
- Update tampilan detail permohonan dengan informasi persetujuan.
2024-12-24 11:30:49 +07:00
Daeng Deni Mardaeni
97cb88371e Tambah role baru untuk akses modul
- Menambahkan role "EO Appraisal" dan "DD Appraisal" pada daftar roles di module.json.
- Memperluas aksesibilitas modul untuk peran-peran tersebut.
2024-12-24 10:47:14 +07:00
Daeng Deni Mardaeni
b8f8a3f2bf Perbaiki pengaturan canvas dan hapus elemen gambar yang tidak terpakai
- Modifikasi ukuran canvas agar sesuai dengan rasio video (portrait/landscape).
- Tambahkan logika untuk menampilkan kontrol editor dan menyembunyikan kontrol kamera.
- Sesuaikan ulang ukuran canvas menggambar agar sinkron dengan ukuran canvas utama.
- Hapus elemen gambar pratinjau yang tidak lagi digunakan di komponen foto.
2024-12-24 10:01:25 +07:00
majid
310fdff0ed Merge remote-tracking branch 'origin/staging' into feature/senior-officer 2024-12-24 08:54:20 +07:00
majid
889251a931 perbaikan tampilan print out 2024-12-24 08:45:46 +07:00
Daeng Deni Mardaeni
1dbd45a27d Tambahkan fitur data untuk laporan datatables
- Menambahkan metode `dataForDatatables` di `LaporanController` untuk keperluan pencarian, pengurutan, dan paginasi data laporan.
- Memperbarui view `laporan/index.blade.php` agar mendukung penggunaan datatables untuk menampilkan data laporan dengan kolom baru.
- Menambahkan route baru untuk akses endpoint datatables laporan.
- Memodifikasi `module.json` dengan menggabungkan menu "Resume" dan "Laporan" menjadi satu menu "Resume dan Laporan".
2024-12-23 23:10:54 +07:00
Daeng Deni Mardaeni
afe0563361 Tambah kolom approval pada tabel permohonan
- Menambahkan kolom approval_eo, approval_dd, dan approval_so beserta timestamp terkait di tabel permohonan.
- Memperluas fungsionalitas model dan controller untuk mendukung kolom approval baru.
2024-12-23 22:46:42 +07:00
Daeng Deni Mardaeni
d465a3ea7d Perbarui peran akses pada module.json
- Tambahkan role "EO Appraisal" dan "DD Appraisal" pada konfigurasi akses.
- Hapus entri duplikat untuk otorisasi pembayaran.
- Optimalkan struktur JSON agar lebih efisien.
2024-12-23 22:46:25 +07:00
Daeng Deni Mardaeni
2f2de48607 Tambahkan fungsi getUser dan perbaiki format kode
- Menambahkan fungsi `getUser` untuk mendapatkan data pengguna berdasarkan ID.
- Memperbaiki format kode dengan menghapus spasi dan karakter yang tidak diperlukan.
- Menambahkan penggunaan model `User` di file `Lpj.php`.
2024-12-23 22:46:13 +07:00
Daeng Deni Mardaeni
50d9b39f07 "Tambah fitur approval pembayaran dan pembaruan konvensi data"
- Implementasi fitur approval untuk pembayaran dengan tampilan antarmuka baru.
- Penyesuaian teks konfirmasi pada proses persetujuan pembayaran.
- Penambahan relasi `approveBayar` pada model `Permohonan`.
- Perbaikan logika status pada proses pembaruan permohonan dan penawaran.
- Penyesuaian data output pada JSON respons untuk otorisasi pembayaran.
2024-12-23 21:12:10 +07:00
Daeng Deni Mardaeni
6d9f5f6d28 Tambahkan relasi permohonan dan pembaruan logika tampilan
- Menambahkan kolom dan relasi `permohonan_id` pada model, request, dan database terkait.
- Memperbarui logika rendering di tampilan untuk mendukung data dari relasi `permohonan`.
- Menambahkan fitur baru di menu `Approval Pembayaran` dengan pengaturan role dan icon spesifik.
2024-12-23 20:13:17 +07:00
Daeng Deni Mardaeni
c90535b5ba Tambahkan fitur pembayaran dan perbaikan tampilan terkait
- Tambah file migration untuk update tabel `persetujuan_penawaran` dengan relasi baru.
- Tambah fungsi baru di controller pembayaran: `edit`, `store`, `update`, dan `approval`.
- Perbarui view daftar pembayaran dan tambahkan form pembayaran baru.
- Tambah endpoint dan breadcrumbs untuk fitur pembayaran di routes.
2024-12-23 20:12:56 +07:00
Andy Chaerudin
bbe44ff3fa Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into andydev 2024-12-23 18:39:55 +07:00
Andy Chaerudin
fb59e0830c menambahkan Feature Pembayaran di Admin LPJ 2024-12-23 18:39:42 +07:00
Daeng Deni Mardaeni
8ddbb8c63c Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-23 16:55:56 +07:00
majid
886e75da82 update print out 2024-12-23 16:27:49 +07:00
Daeng Deni Mardaeni
ab21e31633 Update tampilan status dan aksi pada halaman pembatalan
- Menambahkan kelas `flex justify-center` pada render status untuk memastikan tampilan sejajar di tengah.
- Menambahkan atribut `title="Detail Pembatalan"` pada tombol aksi untuk memberikan informasi tambahan.
2024-12-23 16:16:27 +07:00
Daeng Deni Mardaeni
f358d3ea9e Merge remote-tracking branch 'composer/staging' into staging 2024-12-23 15:59:48 +07:00
Daeng Deni Mardaeni
069cf18a8b Transformasi nama debitur menjadi huruf kapital
- Mengubah rendering nama debitur agar ditampilkan dalam huruf kapital.
- Memastikan konsistensi format tampilan pada kolom "Debitur".
2024-12-23 15:59:09 +07:00
putrakuningan
65a13f383a Merge pull request 'perbaikan inputan data kjpp kantor cabang, dan tujuan penilaian' (#67) from feature/senior-officer into staging
Reviewed-on: #67
2024-12-23 08:50:22 +00:00
majid
41b6f96ef7 perbaikan inputan data kjpp kantor cabang, dan tujuan penilaian 2024-12-23 08:50:22 +00:00
Daeng Deni Mardaeni
87b3337502 Sembunyikan elemen status bayar di formulir persetujuan penawaran
- Menambahkan kelas "hidden" pada div elemen status bayar.
- Elemen tidak lagi terlihat di tampilan pengguna.
2024-12-23 15:44:43 +07:00
Daeng Deni Mardaeni
ba029a89a6 Tambahkan fitur pembatalan permohonan
- Menambahkan controller, view, dan route untuk mengelola pembatalan permohonan.
- Memperbarui tampilan daftar permohonan dan menyesuaikan elemen UI terkait pembatalan.
- Integrasi logika validasi dan penyimpanan data pembatalan.
- Membuat endpoint datatable untuk kelola data pembatalan permohonan.
2024-12-23 15:44:31 +07:00
majid
f5ef883a0d perbaikan inputan data kjpp kantor cabang, dan tujuan penilaian 2024-12-23 15:44:17 +07:00
Daeng Deni Mardaeni
e5d4874af1 Tambah fitur pembatalan permohonan
- Menambahkan model, migration, dan relasi untuk tabel pembatalan permohonan.
- Mengubah fungsi delete menjadi pembatalan permohonan dengan konfirmasi pengguna.
- Menambahkan route baru untuk form dan proses pembatalan permohonan.
- Menyediakan form input alasan dan file pendukung untuk pembatalan permohonan.
- Memperbarui tampilan, fungsi controller, dan breadcrumbs terkait pembatalan permohonan.
2024-12-23 15:43:53 +07:00
Daeng Deni Mardaeni
8dde09bcfa Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-23 10:37:52 +07:00
Andy Chaerudin
c1a62a147a Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into andydev 2024-12-23 09:52:54 +07:00
Andy Chaerudin
72837004d7 menyamakan staging 2024-12-23 09:52:44 +07:00
majid76
5a0564acfb perbaikan kertas kerja, dan form inspeksi 2024-12-23 07:20:37 +07:00
Daeng Deni Mardaeni
32f62e4d24 Perbaiki typo pada class badge
- Memperbaiki penulisan "bagde-outline" menjadi "badge-outline" di beberapa case pada file `index.blade.php`.
- Menghindari potensi kesalahan tampilan akibat typo pada class CSS.
2024-12-22 21:15:31 +07:00
Daeng Deni Mardaeni
8c46123853 Perbaiki logika render badge pada tabel tujuan penilaian
- Mengganti penggunaan `if-else` dengan `switch-case` untuk menyederhanakan logika.
- Menambahkan kode spesifik (`code`) untuk setiap tipe tujuan penilaian.
- Menambahkan badge baru untuk beberapa tipe tujuan penilaian dengan desain dan warna spesifik.
2024-12-22 21:10:44 +07:00
Daeng Deni Mardaeni
efba1aa953 Perbaiki tampilan status pada history permohonan
- Menghilangkan baris kosong yang tidak perlu pada blok kode case 'order'.
- Menambahkan fungsi `str_replace` untuk mengganti tanda strip (-) dengan spasi pada tampilan status aktivitas.
- Meningkatkan keterbacaan status aktivitas pada komponen history permohonan.
2024-12-22 20:51:00 +07:00
Daeng Deni Mardaeni
0d4b6270ec Tambahkan badge berdasarkan tujuan penilaian
- Menambahkan badge dengan warna berbeda untuk setiap jenis tujuan penilaian (baru, revaluasi aset, lainnya).
- Meningkatkan kejelasan tampilan data di halaman permohonan untuk mempermudah identifikasi.
2024-12-22 20:47:21 +07:00
Daeng Deni Mardaeni
25e45a458e Update ikon modul dengan warna dan style baru
- Menambahkan warna pada ikon untuk meningkatkan visualisasi dan diferensiasi.
- Mengganti beberapa ikon agar lebih sesuai dengan fungsi modul terkait.
- Menghapus modul "Pembatalan" dari daftar.
2024-12-22 16:15:41 +07:00
majid
b62b15839f penambahan no hp di data pembanding 2024-12-21 08:20:13 +07:00
Daeng Deni Mardaeni
c0bf6d6be0 Tingkatkan ukuran halaman data pada tabel
- Mengubah `data-datatable-page-size` dari 5 menjadi 10 di berbagai file Blade.
- Perubahan ini bertujuan untuk menampilkan lebih banyak data di setiap halaman tabel untuk meningkatkan pengalaman pengguna.
2024-12-21 05:26:11 +07:00
Daeng Deni Mardaeni
f22bdd9d9c Update tabel permohonan: jumlah data per halaman & format tanggal
- Ubah jumlah data yang ditampilkan per halaman dari 5 menjadi 10.
- Tambahkan format tanggal Indonesia untuk kolom "Tanggal Permohonan".
2024-12-21 05:21:57 +07:00
Daeng Deni Mardaeni
b52fa5db7a Tambahkan fitur kontrol pagination di tampilan tabel
- Menambahkan opsi "Show per page" untuk memilih jumlah data yang ditampilkan per halaman.
- Menambahkan elemen informasi data dan navigasi pagination di bagian footer tabel.
- Perubahan diterapkan pada file `noc/index.blade.php` dan `persetujuan_penawaran/index.blade.php`.
2024-12-21 05:21:36 +07:00
Daeng Deni Mardaeni
15651f889b Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-20 16:32:53 +07:00
majid
aa4a3405c1 perbaikan error lpj sederhana 2024-12-20 16:31:14 +07:00
majid
01408bbac3 perbaikan foto objek jaminan ketika di update tidak hilang 2024-12-20 16:25:54 +07:00
majid
145b677dbc perbaikan submit surveyor tidak bisa submit 2024-12-20 16:08:11 +07:00
Daeng Deni Mardaeni
46fad96f7a Merge remote-tracking branch 'composer/feature/senior-officer' into staging
# Conflicts:
#	resources/views/component/kertas-kerja.blade.php
2024-12-20 15:32:18 +07:00
majid
639bdfed98 perbaikan preview foto numpuk di form inspeksi 2024-12-20 15:30:38 +07:00
Daeng Deni Mardaeni
4b9685f14c Perbaiki logika tombol "Buat SPK"
- Tambahkan pengecekan status data sebelum menampilkan tombol "Buat SPK".
- Tombol hanya ditampilkan jika status data adalah "spk".
2024-12-20 15:13:52 +07:00
Daeng Deni Mardaeni
5fde58d00c Refactor data rendering and query structures in SPK
- Mengubah struktur query untuk mengambil data dari relasi yang lebih sesuai.
- Memperbaiki atribut render di view agar lebih konsisten dengan struktur data baru.
- Membersihkan logika yang tidak digunakan, termasuk format data untuk tanggal, biaya, dan path dokumen.
- Mengoptimalkan fungsi download dengan menggunakan ID langsung dari PenawaranTender.
2024-12-20 15:09:47 +07:00
majid
a9d9173208 update check id button submit 2024-12-20 14:54:18 +07:00
putrakuningan
c71dcdbdf5 Merge pull request 'feature/senior-officer' (#66) from feature/senior-officer into staging
Reviewed-on: #66
2024-12-20 07:03:18 +00:00
majid
f155dd6ff4 perbaikan kertas kerja, paparan, dan lampiran 2024-12-20 07:03:18 +00:00
majid
e05e8b8b48 Ganti nama worksheet ke Pembuatan Laporan 2024-12-20 07:03:18 +00:00
majid
5bc4d54f3d perbaikana perhitungan npw dan nl otomatis, dan perbaikan otorisator 2024-12-20 07:03:18 +00:00
majid
3598a2d0eb Merge branch 'staging' into feature/senior-officer 2024-12-20 13:33:29 +07:00
majid
575e794e44 perbaikan kertas kerja, paparan, dan lampiran 2024-12-20 13:31:01 +07:00
Daeng Deni Mardaeni
f3faa6b0ab Perbaiki logika iterasi untuk legalitas dalam komponen dokumen
- Tambahkan pengecekan "if" untuk memastikan data "legalitas" ada sebelum iterasi dilakukan.
- Susun ulang struktur iterasi untuk memastikan rendering elemen sesuai dengan kondisi data.
- Kurangi kemungkinan error saat "legalitas" bernilai null atau undefined.
2024-12-20 11:25:52 +07:00
Daeng Deni Mardaeni
f5119e188a Perbaiki logika validasi jenis legalitas jaminan
- Tambahkan pengecekan null untuk menghindari error ketika `_jenisJaminan` kosong.
- Perbaiki pengolahan data pada `legalitasJaminan` dan `currentLegalitasJaminan` agar lebih aman.
- Pastikan variabel `legalitas` hanya diisi jika `_jenisJaminan` valid.
2024-12-20 11:24:26 +07:00
Daeng Deni Mardaeni
4bc8346f77 Perbaiki bug pada input custom_field
- Tambahkan nilai default kosong ('') untuk mencegah error jika $custom_field tidak terdefinisi.
- Memastikan form tetap berfungsi tanpa memicu kesalahan saat input data.
2024-12-20 11:21:27 +07:00
Daeng Deni Mardaeni
ad92a6512f Urutkan permohonan berdasarkan nomor registrasi secara descending
- Menambahkan pengurutan data permohonan berdasarkan nomor registrasi secara descending agar data terbaru muncul lebih dahulu.
2024-12-20 11:21:19 +07:00
Daeng Deni Mardaeni
95ccb98d99 Update perhitungan SLA pada SpkController
- Mengubah logika perhitungan `sla_resume_text` menjadi `ceil($data->sla/2)` dan `sla_final_text` menjadi `$data->sla`.
- Mengomentari kode sebelumnya yang menggunakan nilai dari `penawaran->persetujuan`.
2024-12-20 09:45:52 +07:00
Daeng Deni Mardaeni
7bf13b78b3 Perbaiki logika penamaan dan visibilitas accordion detail jaminan
- Tambahkan logika untuk menampilkan judul "Jaminan" tanpa nomor jika hanya ada satu dokumen.
- Ubah default state accordion menjadi 'active' jika hanya terdapat satu dokumen.
- Sesuaikan kelas CSS untuk visibilitas konten accordion berdasarkan jumlah dokumen.
2024-12-20 09:15:16 +07:00
Daeng Deni Mardaeni
43226a2e93 Add Debiture column to Registrasi Final table
- Menambahkan kolom "Debiture" pada tabel di halaman Registrasi Final.
- Memperluas data query untuk memuat data "permohonan.debiture" pada controller.
- Mengimplementasikan render data "Debiture" untuk ditampilkan.
2024-12-20 09:15:09 +07:00
Daeng Deni Mardaeni
2c3b5c998e Hapus kolom dan form SLA Resume & SLA Final
- Menghapus kolom SLA Resume dan SLA Final dari tabel di `index.blade.php`.
- Menghapus input form SLA Resume dan SLA Final pada `form.blade.php`.
- Memperbaiki path file dokumen persetujuan pada tabel agar menggunakan folder `storage`.
2024-12-20 09:01:13 +07:00
Daeng Deni Mardaeni
409718d96a "Perbaiki dan Refactor Komponen Address pada Halaman Dokumen
- Menghapus duplikasi kode terkait pengelolaan alamat (province, city, district, village, postal code, address).
- Penempatan ulang elemen-elemen form untuk meningkatkan keterbacaan dan efisiensi."
2024-12-20 08:58:54 +07:00
majid
3522bab943 Ganti nama worksheet ke Pembuatan Laporan 2024-12-20 07:48:12 +07:00
majid
b9f2e5dcf4 perbaikana perhitungan npw dan nl otomatis, dan perbaikan otorisator 2024-12-20 07:11:41 +07:00
Daeng Deni Mardaeni
f91969f95a Tambahkan fitur NOC
- Buat migrasi untuk kolom `bukti_ksl` dan `catatan_noc` pada tabel `persetujuan_penawaran`.
- Tambahkan halaman index dan form NOC untuk pengelolaan data.
- Implementasikan controller dan request validation baru untuk NOC.
- Ubah logika status penawaran pada `PersetujuanPenawaranController`.
- Tambahkan route, breadcrumbs, dan menu modul untuk NOC.
2024-12-19 15:25:31 +07:00
Daeng Deni Mardaeni
cec2214e01 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-19 14:51:48 +07:00
majid
8cc0f32410 update activity paparan 2024-12-19 14:49:37 +07:00
Daeng Deni Mardaeni
95e21148bc Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-19 14:47:25 +07:00
majid
76400bc43f perbaikan activity 2024-12-19 14:44:55 +07:00
Daeng Deni Mardaeni
b426d91fc7 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-19 13:30:20 +07:00
majid
5744dffe90 perabaikan hub cadeb penghuni dan penambahan title pesan swall jadwal, nama debitur, form inspeksi denah dinamis 2024-12-19 13:29:08 +07:00
Daeng Deni Mardaeni
fdf79f9be0 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-19 11:49:40 +07:00
majid
879d36b740 perbaikan form inspeksi pergantian colom jenis_jaminan_id ke dokument_id 2024-12-19 11:47:44 +07:00
Daeng Deni Mardaeni
a51900d82a Tambahkan field nominal_bayar untuk persetujuan penawaran
- Menambahkan validasi dan atribut 'nominal_bayar' pada request dan model.
- Menampilkan input 'nominal_bayar' di form persetujuan penawaran.
- Memperbarui tampilan dan data tabel untuk mendukung kolom 'nominal_bayar'.
2024-12-19 11:25:44 +07:00
majid
90fb197b94 perbaikan konfilk lpj 2024-12-19 11:04:56 +07:00
majid
f23f119d0d Merge branch 'staging' into feature/senior-officer 2024-12-19 10:51:07 +07:00
majid
ea5f8dd335 perbaikan lampiran dokument, dan memo, lpj sederhana dan standart, resume 2024-12-19 10:14:34 +07:00
a416dfcf9c Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2024-12-18 17:11:56 +07:00
putrakuningan
f7f59dbfab Merge pull request 'feature/senior-officer' (#64) from feature/senior-officer into staging
Reviewed-on: #64
2024-12-18 10:06:11 +00:00
majid
7553b7d4b6 update memo, lpj, resume, dan perbaikan form inspeksi 2024-12-18 10:06:11 +00:00
majid
c1929e5db5 Merge branch 'staging' into feature/senior-officer 2024-12-18 17:00:02 +07:00
majid
27e53431d0 update memo, lpj, resume, dan perbaikan form inspeksi 2024-12-18 16:58:32 +07:00
Daeng Deni Mardaeni
85d256c6b5 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-18 14:56:46 +07:00
Daeng Deni Mardaeni
33acb29e55 Update roles in module.json
- Menghapus peran "pemohon-ao", "pemohon-eo", "surveyor", dan "senior-officer" dari beberapa entri.
- Menambahkan peran "admin" untuk menggantikan peran yang dihapus dan mengkonsolidasikan akses.
- Memperbaiki konsistensi peran untuk berbagai entitas dan atribut dalam file.
2024-12-18 14:56:31 +07:00
majid
eaffe2805f perbaikan tampilan basic data (batas batas, saran pelengkap, dan fasilitas dekat objek) 2024-12-18 11:05:25 +07:00
c5d31c7d56 Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2024-12-18 09:01:36 +07:00
majid
562f1fb846 update kertas kerja, resume, dan lpj 2024-12-17 07:39:20 +07:00
majid
5f9e2b3f14 Merge branch 'staging' into feature/senior-officer 2024-12-16 15:41:10 +07:00
majid
41552f695c perbaikan alamat, foto pembading, diskon, dan perbaikan tampilan kjjp 2024-12-16 15:36:59 +07:00
majid76
a602f83d44 perbikan alamat di form inspeksi 2024-12-16 07:34:02 +07:00
510df4ea4c Memperbaiki create, edit, dan show pada kjpp basic data ketika data nya itu ada yang salah masukin maka mempertahankan isi nya ketika di validasi 2024-12-14 07:06:54 +07:00
majid
ab7150a97f perbaikan form inspeksi bagian unit, dan kertas kerja 2024-12-14 04:23:14 +07:00
0673000ad4 Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2024-12-13 14:21:20 +07:00
Daeng Deni Mardaeni
88975f3cc8 Perbaiki pengolahan data JSON pada KJPPController dan tampilan email di show.blade.php
- Mengubah cara pengolahan data JSON di `KJPPController` untuk menghindari kesalahan pada struktur data.
- Menyesuaikan akses properti JSON di `show.blade.php` agar lebih sesuai dengan data yang diterima.
- Memastikan data ditampilkan secara konsisten dan mencegah error runtime.
2024-12-13 14:00:46 +07:00
Daeng Deni Mardaeni
9fb176751c fix error detail 2024-12-13 11:06:33 +07:00
putrakuningan
eabf65a55f Merge pull request 'update isi tabel jenis jaminan di database local' (#62) from tender into staging
Reviewed-on: #62
2024-12-13 02:04:13 +00:00
b5c8b6aad3 Revert "Memperbaiki KJPP Basic data dari create, edit, dan show yang bug"
This reverts commit 967be7019d.
2024-12-13 02:04:13 +00:00
909460018b Revert "Menghapus kolom yang mengandung detail pada tabel kjpp"
This reverts commit 907240e003.
2024-12-13 02:04:13 +00:00
7392481903 update isi tabel jenis jaminan di database local 2024-12-13 02:04:13 +00:00
a0ed6d163d Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2024-12-13 09:00:45 +07:00
6e64f86521 Revert "Memperbaiki KJPP Basic data dari create, edit, dan show yang bug"
This reverts commit 967be7019d.
2024-12-13 08:56:24 +07:00
2c8a9a9caf Revert "Menghapus kolom yang mengandung detail pada tabel kjpp"
This reverts commit 907240e003.
2024-12-13 08:55:06 +07:00
9f1a480357 update isi tabel jenis jaminan di database local 2024-12-13 08:31:42 +07:00
Daeng Deni Mardaeni
478eaf89a1 Merge remote-tracking branch 'composer/feature/senior-officer' into staging
# Conflicts:
#	database/seeders/KJPPSeeder.php
2024-12-13 07:40:16 +07:00
Daeng Deni Mardaeni
9eb6e26435 Merge remote-tracking branch 'composer/tender' into staging 2024-12-13 07:38:36 +07:00
majid
3c5b372f7d Merge branch 'staging' into feature/senior-officer 2024-12-12 21:26:37 +07:00
majid
f7eec3720e update seeder kjpp dan export kertas kerja 2024-12-12 21:25:06 +07:00
967be7019d Memperbaiki KJPP Basic data dari create, edit, dan show yang bug 2024-12-12 15:30:44 +07:00
907240e003 Menghapus kolom yang mengandung detail pada tabel kjpp 2024-12-12 08:20:14 +07:00
majid
bb1ad785a5 update data pemanding dan otorisator, pembuatan seeder kjpp mengunakan exel 2024-12-11 17:34:51 +07:00
7b2f9e34a3 Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2024-12-11 17:18:07 +07:00
putrakuningan
de2e998730 Merge pull request 'andydev' (#60) from andydev into staging
Reviewed-on: #60
2024-12-11 10:01:00 +00:00
Andy Chaerudin
7b2dc53eae Perbaikan title pada icon Approve Jadwal Kunjungan 2024-12-11 10:01:00 +00:00
Andy Chaerudin
614abd01ac Melengkapi feature Approve Jadwal Kunjungan yang di berikan Surveyor 2024-12-11 10:01:00 +00:00
Andy Chaerudin
5932d67fce Perbaikan title pada icon Approve Jadwal Kunjungan 2024-12-11 15:16:04 +07:00
Andy Chaerudin
02bf6c5baa Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into andydev 2024-12-11 12:07:52 +07:00
Andy Chaerudin
3f2b0b2a7e Melengkapi feature Approve Jadwal Kunjungan yang di berikan Surveyor 2024-12-11 12:07:34 +07:00
5b50209ba5 Menambahkan data KJPP, Ijin Usaha dan Jenis Jaminan sementara part 3 2024-12-11 08:46:10 +07:00
5ff333808a Menaikkan data KJPP part 2 2024-12-11 08:40:11 +07:00
putrakuningan
dfe1e98d80 Merge pull request 'fix: handle empty jenis_aset_id array in KJPP data display' (#58) from tender into staging
Reviewed-on: #58
2024-12-10 09:50:55 +00:00
9da106fedc fix: handle empty jenis_aset_id array in KJPP data display
This commit addresses the issue where an empty jenis_aset_id array would cause an error in the KJPP data display. It adds a check to ensure the array is not empty before iterating through it, and displays a "-" message if the array is empty.

The changes made are:

1. Added a check for !empty(json_decode($kjpp->jenis_aset_id, true)) inside the @if condition.
2. This ensures that the array is not empty before attempting to loop through it.
3. If the array is empty, a "-" message is displayed instead.

This fix ensures a more robust and user-friendly display of the KJPP data, handling both populated and empty jenis_aset_id arrays gracefully.
2024-12-10 09:50:55 +00:00
7fb839efed fix: handle empty jenis_aset_id array in KJPP data display
This commit addresses the issue where an empty jenis_aset_id array would cause an error in the KJPP data display. It adds a check to ensure the array is not empty before iterating through it, and displays a "-" message if the array is empty.

The changes made are:

1. Added a check for !empty(json_decode($kjpp->jenis_aset_id, true)) inside the @if condition.
2. This ensures that the array is not empty before attempting to loop through it.
3. If the array is empty, a "-" message is displayed instead.

This fix ensures a more robust and user-friendly display of the KJPP data, handling both populated and empty jenis_aset_id arrays gracefully.
2024-12-10 16:48:01 +07:00
Daeng Deni Mardaeni
0bf78e1f67 Merge remote-tracking branch 'composer/staging' into staging 2024-12-10 16:31:00 +07:00
Daeng Deni Mardaeni
3f6708e53c Merge remote-tracking branch 'composer/tender' into staging
# Conflicts:
#	routes/breadcrumbs.php
2024-12-10 16:29:14 +07:00
9bef2c6641 fitur(kjpp): Tambah validasi dan migrasi modul Lpj > KJPP
- Perbarui kontroler KJPP untuk jenis_aset_id kalau kosong maka isi array kosong jika tidak isi array yang saya isi
- Modifikasi aturan validasi permintaan KJPP di bagian jenis_aset_id supaya bisa diisi kosong
- Buat migrasi untuk memperbarui struktur tabel KJPP yang jenis_aset_id menjadi nullable
2024-12-10 16:25:16 +07:00
putrakuningan
bc52b9c528 Merge pull request 'feature/senior-officer' (#56) from feature/senior-officer into staging
Reviewed-on: #56
2024-12-10 09:04:55 +00:00
Andy Chaerudin
ba9a155280 Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into andydev 2024-12-10 10:24:18 +07:00
majid
5dc95d3339 update message di assigment 2024-12-10 10:07:41 +07:00
majid
b7b668321f Merge branch 'staging' into feature/senior-officer 2024-12-10 09:04:10 +07:00
majid
a4139c1e19 update denah bisa upload pdf 2024-12-10 08:55:30 +07:00
majid
bccc89f794 update informasi dokument 2024-12-10 08:37:47 +07:00
majid
1e91212d19 perbaikan view unit tidak muncul dan tambah foto depan objek 2024-12-10 07:42:31 +07:00
majid
10b672918b perbaikan alamat data pembanding 2024-12-10 07:22:23 +07:00
Daeng Deni Mardaeni
4af0a3c80f Format kode breadcrumbs untuk konsistensi
Mengubah format dan penempatan kode pada file routes/breadcrumbs.php untuk menjaga konsistensi dan meningkatkan keterbacaan. Indentasi yang konsisten diterapkan di seluruh blok kode untuk memastikan struktur kode lebih teratur dan mudah dipahami.
2024-12-09 16:11:25 +07:00
majid
95b57b78f6 update Breadcrumb not found surveyor.inspeksi 2024-12-09 16:07:28 +07:00
Daeng Deni Mardaeni
c49e1336d0 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-09 16:04:26 +07:00
Daeng Deni Mardaeni
cc4f56e30c Refactor code formatting for header component
Melakukan refactoring pada file `header.blade.php` untuk memperbaiki pengaturan indentasi dan konsistensi gaya penulisan. Perubahan ini bertujuan untuk meningkatkan keterbacaan kode dengan menjaga standar format yang konsisten, seperti menyesuaikan spasi dan garis baru yang tidak diperlukan. Tidak ada perubahan fungsional dalam kode.
2024-12-09 16:03:11 +07:00
majid
69b8f4f90b uncommet window location data inspeksi dan foto 2024-12-09 16:01:30 +07:00
Daeng Deni Mardaeni
69bd4f599a Merge branch 'feature/senior-officer' into staging 2024-12-09 16:01:08 +07:00
majid
055f8a67ae Merge branch 'staging' into feature/senior-officer 2024-12-09 15:57:03 +07:00
majid
4ed2afda72 perbaikan form inspeksi dan 2024-12-09 15:49:44 +07:00
putrakuningan
96f99306dc Merge pull request 'andydev' (#54) from andydev into staging
Reviewed-on: #54
2024-12-09 07:33:38 +00:00
Andy Chaerudin
2a36bce0a1 Perbaikan pada menampilkan file PDF SPK 2024-12-09 07:33:38 +00:00
Andy Chaerudin
640b1b800a Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into andydev 2024-12-09 14:29:53 +07:00
Andy Chaerudin
5f662b22f4 Perbaikan pada menampilkan file PDF SPK 2024-12-09 14:29:41 +07:00
putrakuningan
d6d2799485 Merge pull request 'andydev' (#53) from andydev into staging
Reviewed-on: #53
2024-12-09 07:00:44 +00:00
Andy Chaerudin
3140801317 Perbaikan pengecekan file PDF SPK 2024-12-09 07:00:44 +00:00
Andy Chaerudin
7afaa53d1f Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into andydev 2024-12-09 13:48:09 +07:00
Andy Chaerudin
4aa8475929 Perbaikan pengecekan file PDF SPK 2024-12-09 13:47:53 +07:00
putrakuningan
f494f160c7 Merge pull request 'andydev' (#52) from andydev into staging
Reviewed-on: #52
2024-12-09 03:28:49 +00:00
Andy Chaerudin
4d54b001c1 Penambahan code di method store dan show, untuk mengakomodasi perubahan di table penawaran 2024-12-09 03:28:49 +00:00
Andy Chaerudin
0cca391d3d Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into andydev 2024-12-09 10:22:13 +07:00
Andy Chaerudin
fd1a57b0ee Penambahan code di method store dan show, untuk mengakomodasi perubahan di table penawaran 2024-12-09 10:21:52 +07:00
Daeng Deni Mardaeni
c599f7e713 Merge remote-tracking branch 'composer/andydev' into staging 2024-12-09 09:12:14 +07:00
d799fdd658 Menambahkan Seeder pada Module LPJ part 1 2024-12-09 09:10:27 +07:00
a52c4a1bbd Memperbaiki redirect ke halaman otorisasi penawaran ketika status nay bukan tender 2024-12-09 09:10:27 +07:00
bc8e618bda Memperbaiki style pada preview surat tender all dan surat tender kjpp 2024-12-09 09:10:26 +07:00
5a9e04c1d0 Dispatch nya taruh di luar dan akan di cek apakah bisa di kirim ataupun tidak 2024-12-09 09:10:20 +07:00
434ebf6cea Memperbaiki custom field yang dinamis 2024-12-09 09:10:20 +07:00
229efeacc1 Memperbaiki untuk jenis legalitas jaminan dibuat dinamis 2024-12-09 09:10:20 +07:00
006784fe06 Menambahkan fitur log pada saat kirim tender dari semua KJPP 2024-12-09 09:09:59 +07:00
6229dc09d8 Mengubah kirim surat tender dari setiap kjpp ketika berhasil dikirim maka panggil send penawaran kjpp tender job yang bekerja kalau gagal tidak usah dipanggil 2024-12-09 09:09:59 +07:00
81a9fac7c8 perbaiki looping pada kirim surat tender kjpp pada saat gagal kirim 2024-12-09 09:09:59 +07:00
0ba9b8f6e7 Menambahkan kalau gagal ke kirim surat tender dari setiap kjpp yang kita klik maka update pesan error nya jika tidak ada pesan nya baru tambah pesan error nya 2024-12-09 09:09:44 +07:00
736ad4fcfa Menambahkan log ketika di kirim surat tender dari setiap kjpp 2024-12-09 09:06:44 +07:00
Daeng Deni Mardaeni
65f1c6975a Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-09 08:40:06 +07:00
majid76
2d45e03095 perbaikan basic data di form inspeksi tidak muncul 2024-12-09 07:28:50 +07:00
majid
b645682de8 update form foto 2024-12-07 14:30:25 +07:00
a3068e9223 Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2024-12-06 17:40:51 +07:00
c84d94efd9 Menambahkan Seeder pada Module LPJ part 1 2024-12-06 17:38:58 +07:00
Daeng Deni Mardaeni
8f04e926f6 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-06 16:50:43 +07:00
majid
e28d5ff9a4 update menu penilai lpj dan perbaikan data pembanding 2024-12-06 16:48:31 +07:00
5b892d6d7d Memperbaiki redirect ke halaman otorisasi penawaran ketika status nay bukan tender 2024-12-06 14:35:07 +07:00
d486cd735a Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2024-12-05 16:09:57 +07:00
Daeng Deni Mardaeni
81e1d13cff Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-05 14:47:35 +07:00
majid
e83cd4b167 penambahan route memo, dan lpj 2024-12-05 14:46:43 +07:00
Daeng Deni Mardaeni
cdb095c848 Merge remote-tracking branch 'composer/feature/senior-officer' into staging
# Conflicts:
#	resources/views/penilai/show.blade.php
2024-12-05 14:40:59 +07:00
Daeng Deni Mardaeni
6be675de20 Perbaiki Format Alamat dalam Tampilan Penilai
Mengubah pemanggilan fungsi `formatAlamat` untuk menyesuaikan parameter yang benar dalam tampilan `show.blade.php` dari modul Penilai. Sebelumnya, parameter yang diberikan adalah `address` dari objek `debiture`, diubah menjadi hanya `debiture` untuk menyesuaikan dengan definisi fungsi `formatAlamat`. Perubahan ini memastikan alamat ditampilkan dengan benar dan konsisten dalam aplikasi.
2024-12-05 14:37:19 +07:00
Daeng Deni Mardaeni
9b3858abbe Simplifikasi Penampilan Alamat
Menggunakan fungsi `formatAlamat` untuk menyederhanakan format tampilan alamat pada halaman penilai. Ini mencakup penghapusan rincian manual dalam tampilan untuk meningkatkan keterbacaan dan pemeliharaan kode. Fungsi ini menangani detail seperti nama kelurahan, kecamatan, kota, dan kode pos, memastikan konsistensi dalam penampilan alamat di seluruh aplikasi.
2024-12-05 14:32:29 +07:00
majid
d1f5093ad9 perbaikan alamat di menu show penilai 2024-12-05 14:32:05 +07:00
Andy Chaerudin
2c008a202f Perbaikan conflict helper 2024-12-05 12:01:55 +07:00
Andy Chaerudin
ccb552cc1e Perbaikan status penawaran pada otorisasi penawaran, 20241205 arahkan ke persetujuan-penawaran 2024-12-05 11:58:22 +07:00
majid
6692eef319 penambahan filter by status untuk jumlah task 2024-12-05 11:07:29 +07:00
6f59dfc85c Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2024-12-05 09:10:18 +07:00
majid
13f3065a01 Merge branch 'staging' into feature/senior-officer 2024-12-05 01:38:23 +07:00
majid
d797b0d2c0 update preview foto dan alamat surveyor 2024-12-05 01:34:16 +07:00
Daeng Deni Mardaeni
08746d3262 Refactor perhitungan total tugas
Mengubah metode perhitungan total tugas pada tampilan progres aktivitas dengan memanfaatkan fungsi `countPermohonanForUser`. Perubahan ini bertujuan untuk menyederhanakan kode dan meningkatkan keterbacaan dengan menghilangkan logika filter yang kompleks dan menggantinya dengan pemanggilan fungsi yang lebih ringkas.
2024-12-04 20:55:28 +07:00
Daeng Deni Mardaeni
994da39fd7 Simplifikasi Fungsi progres_activity di ActivityController
Menggabungkan beberapa baris kode untuk menyederhanakan dan meningkatkan efisiensi pengambilan data di fungsi progres_activity. Inisialisasi variabel disingkat dan penggunaan metode chaining diterapkan untuk query Eloquent. Selain itu, penyaringan peran juga disederhanakan dengan menggunakan fungsi lambda.
2024-12-04 20:55:28 +07:00
Daeng Deni Mardaeni
d1b200d9ca Tambahkan fungsionalitas perhitungan permohonan berdasarkan pengguna
Menambahkan fungsi `countPermohonanForUser` ke dalam file `Lpj.php` untuk menghitung jumlah permohonan yang terkait dengan pengguna tertentu melalui relasi `userPenilai`. Selain itu, menambahkan penggunaan model `Penilaian`
2024-12-04 20:55:28 +07:00
putrakuningan
1b25b0b4f3 Merge pull request 'andydev' (#46) from andydev into staging
Reviewed-on: #46
2024-12-04 09:50:02 +00:00
Andy Chaerudin
e0f78f851f Perbaikan helper onLastnumberCodePenawaran 2024-12-04 09:50:02 +00:00
Andy Chaerudin
bab76df6db Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into andydev 2024-12-04 16:17:32 +07:00
Andy Chaerudin
e779ec308e Perbaikan helper onLastnumberCodePenawaran 2024-12-04 16:16:55 +07:00
majid
405dc82ac6 uncomment fungsi submit inspeksi 2024-12-04 13:35:33 +07:00
majid
ab0b402884 Merge branch 'staging' into feature/senior-officer 2024-12-04 13:19:21 +07:00
majid
c603a99c0d update kertas kerja dan column name table inspeksi 2024-12-04 12:08:14 +07:00
Daeng Deni Mardaeni
20e249c48d fix The GET method is not supported for route surveyor/storeAproved/25. Supported methods: PUT 2024-12-04 04:12:35 +00:00
Daeng Deni Mardaeni
d34753b981 Fix Update Jenis Jaminan 2024-12-03 15:50:07 +07:00
majid
280ed97a50 update data pembading surveyor 2024-12-03 15:00:18 +07:00
Daeng Deni Mardaeni
d31419797a Perbarui tabel persetujuan_penawaran: modifikasi kolom sla_resume dan sla_final
- Ubah kolom sla_resume dan sla_final menjadi tipe string yang dapat bernilai null dalam metode up()
- Kembalikan kolom sla_resume dan sla_final ke tipe datetime yang tidak boleh null dalam metode down()
- Perbaiki typo: 'sls_resume' menjadi 'sla_resume' dalam metode down()
2024-12-03 09:33:49 +07:00
Daeng Deni Mardaeni
02105ac727 Hapus pemanggilan fungsi hitungHariKerja pada field SLA di SpkController
- Mengganti pemanggilan fungsi `hitungHariKerja` untuk field `sla_resume` dan `sla_final` dengan nilai langsung dari model `persetujuan`.
- Membersihkan baris kosong dan spasi berlebih di beberapa bagian kode untuk meningkatkan keterbacaan.
- Perubahan ini bertujuan untuk menyederhanakan logika pengolahan data SLA dan menjaga konsistensi dengan validasi baru.
2024-12-03 09:31:27 +07:00
Daeng Deni Mardaeni
8e7b0623e5 Ubah input field SLA Resume dan SLA Final di form.blade.php menjadi tipe number
- Mengganti tipe input untuk `sla_resume` dan `sla_final` dari `date` menjadi `number`.
- Menyesuaikan nilai default input dengan data lama atau data dari model `$persetujuanPenawaran`.
- Perubahan ini dilakukan untuk mencerminkan validasi baru yang menggunakan tipe numeric pada field SLA.
2024-12-03 09:28:54 +07:00
Daeng Deni Mardaeni
e1eb6c3f67 Hapus logika render custom untuk field SLA Resume dan SLA Final di index.blade.php
- Menghapus fungsi `render` pada field `sla_resume` dan `sla_final` yang sebelumnya memformat tanggal secara khusus.
- Field `sla_resume` dan `sla_final` sekarang hanya menampilkan judul tanpa logika tambahan.
2024-12-03 09:28:01 +07:00
Daeng Deni Mardaeni
6c8dcc609b Perbarui aturan validasi untuk field SLA di PersetujuanPenawaranRequest
- Mengubah validasi field `sla_resume` dan `sla_final` dari `date` menjadi `numeric` dengan nilai minimum 0.
- Menghapus pesan validasi terkait batasan tanggal (`sla_resume.date` dan `sla_final.date`) serta validasi urutan (`sla_final.after_or_equal`).
- Menyesuaikan pesan kesalahan untuk field SLA agar sesuai dengan aturan validasi baru yang menggunakan tipe numeric.
2024-12-03 09:24:02 +07:00
Daeng Deni Mardaeni
4f126f4ac2 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-12-02 16:46:59 +07:00
Daeng Deni Mardaeni
a692d626c2 Merge remote-tracking branch 'composer/staging' into staging 2024-12-02 16:46:37 +07:00
Daeng Deni Mardaeni
84dcfbb8b7 Refactor(JenisJaminanRequest): Perbarui persiapan data sebelum validasi
- Tambahkan pengkodean JSON untuk form_kategori
2024-12-02 16:46:19 +07:00
putrakuningan
ecb772b8a8 Merge pull request 'feature/senior-officer' (#48) from feature/senior-officer into staging
Reviewed-on: #48
2024-12-02 07:22:55 +00:00
majid76
701c36f603 update insert data json ke table ispeksi 2024-12-02 07:22:55 +00:00
majid
0631eb71e0 update export basic data dan tampilan awal form surveyor 2024-12-02 07:22:55 +00:00
majid76
9502329fef update insert data json ke table ispeksi 2024-12-02 07:11:08 +07:00
majid
8287ce3963 update export basic data dan tampilan awal form surveyor 2024-11-29 22:16:04 +07:00
Daeng Deni Mardaeni
8ac566c9b2 Fix Breadcrumb 2024-11-28 16:47:10 +07:00
33079825a6 Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2024-11-28 16:14:49 +07:00
Daeng Deni Mardaeni
40ac84d168 Fix Duplicate Breadcrumb 2024-11-28 12:41:05 +07:00
Daeng Deni Mardaeni
8ee8c3e61b Merge remote-tracking branch 'composer/staging' into staging
# Conflicts:
#	routes/breadcrumbs.php
2024-11-28 11:40:19 +07:00
Daeng Deni Mardaeni
19231f293b Merge remote-tracking branch 'composer/andydev' into staging 2024-11-28 11:35:59 +07:00
putrakuningan
ffaf049772 Merge pull request 'Menambahkan fitur Kirim Surat Tender All dan ada yang saya sedikit perbaiki dari Kirim Surat Tender dari Setiap KJPP' (#47) from tender into staging
Reviewed-on: #47
2024-11-28 04:35:31 +00:00
2e086c9fea Memperbaiki style pada preview surat tender all dan surat tender kjpp 2024-11-28 04:35:31 +00:00
e0d9c5c983 Dispatch nya taruh di luar dan akan di cek apakah bisa di kirim ataupun tidak 2024-11-28 04:35:31 +00:00
f54d7c4438 Memperbaiki custom field yang dinamis 2024-11-28 04:35:31 +00:00
31028d0bd4 Memperbaiki untuk jenis legalitas jaminan dibuat dinamis 2024-11-28 04:35:31 +00:00
11bcd877d5 Menambahkan fitur log pada saat kirim tender dari semua KJPP 2024-11-28 04:35:31 +00:00
99d40b1cf0 Mengubah kirim surat tender dari setiap kjpp ketika berhasil dikirim maka panggil send penawaran kjpp tender job yang bekerja kalau gagal tidak usah dipanggil 2024-11-28 04:35:31 +00:00
42539fb402 perbaiki looping pada kirim surat tender kjpp pada saat gagal kirim 2024-11-28 04:35:31 +00:00
e980446dfe Menambahkan kalau gagal ke kirim surat tender dari setiap kjpp yang kita klik maka update pesan error nya jika tidak ada pesan nya baru tambah pesan error nya 2024-11-28 04:35:31 +00:00
majid76
b52ffa5106 Merge branch 'staging' into feature/senior-officer 2024-11-28 11:25:20 +07:00
majid76
a2c7df7af3 update form inspeksi dan so bisa ambil alih 2024-11-28 11:16:45 +07:00
Andy Chaerudin
17a67feca2 Feature Generate SPK PDF, handle variable Jangka Waktu dan handle perubahan jenis laporan 2024-11-28 10:59:08 +07:00
majid
b7a60abd3e update form 2024-11-27 09:08:04 +07:00
majid
107b1ca590 update basic data surveyor 2024-11-25 16:40:14 +07:00
fbf6032e5a Memperbaiki style pada preview surat tender all dan surat tender kjpp 2024-11-25 16:22:30 +07:00
Andy Chaerudin
b1c667cefc Perbaikan Conflict SPK, Perubahan penyimpanan SPK PDF (awalnya di tabel permohonan.dokumen, menjadi penawaran.spk_dokumen_path) 2024-11-25 16:10:52 +07:00
Andy Chaerudin
f8415939ea Feature Registrasi menambahkan inputan SLA (kebutuhan SPK PDF), Feature SPK menambahkan parameter SLA generate number SPK 2024-11-25 11:14:31 +07:00
318e9b3a07 Dispatch nya taruh di luar dan akan di cek apakah bisa di kirim ataupun tidak 2024-11-25 10:14:59 +07:00
2e2fc28dbc Memperbaiki custom field yang dinamis 2024-11-22 18:11:23 +07:00
96cb77e417 Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2024-11-22 17:50:13 +07:00
3b549b48e3 Memperbaiki untuk jenis legalitas jaminan dibuat dinamis 2024-11-22 17:46:56 +07:00
Daeng Deni Mardaeni
fc93b98ec3 Perbaiki pengecekan dan konsistensi formatting pada custom fields
Tambahkan pengecekan null untuk `custom_field` sebelum mem-parsing JSON `detail->details` dan perbaiki konsistensi format pada pengecekan dokumen jaminan. Hal ini memastikan tidak ada kesalahan saat field tersebut tidak ada.
2024-11-22 15:33:42 +07:00
65acfba4fe Menambahkan fitur log pada saat kirim tender dari semua KJPP 2024-11-22 09:54:44 +07:00
8956919459 Mengubah kirim surat tender dari setiap kjpp ketika berhasil dikirim maka panggil send penawaran kjpp tender job yang bekerja kalau gagal tidak usah dipanggil 2024-11-22 09:35:07 +07:00
ca2033a3a6 perbaiki looping pada kirim surat tender kjpp pada saat gagal kirim 2024-11-22 09:17:52 +07:00
f7e2407ecd Menambahkan kalau gagal ke kirim surat tender dari setiap kjpp yang kita klik maka update pesan error nya jika tidak ada pesan nya baru tambah pesan error nya 2024-11-22 09:14:54 +07:00
5d6773d879 Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2024-11-22 08:31:04 +07:00
Daeng Deni Mardaeni
d3d5208a90 Tambah fungsi 'hitungHariKerja' di app.js
Menambahkan fungsi `hitungHariKerja` untuk menghitung jumlah hari kerja antara dua tanggal, dengan memperhitungkan hari libur dan akhir pekan. Fungsi ini tersedia secara global melalui `window.hitungHariKerja`.
2024-11-21 18:42:29 +07:00
Daeng Deni Mardaeni
fb026079ef Hapus konfigurasi Vite dan simpan jalur aset saja
Konfigurasi Vite dan plugin Laravel dihapus dari vite.config.js. Sekarang hanya tersisa konstanta `paths` yang berisi jalur aset.
2024-11-21 18:42:21 +07:00
Daeng Deni Mardaeni
ac684ca260 Perbaiki format kode dan refaktor fungsi
Melakukan perbaikan pada format penulisan kode untuk meningkatkan keterbacaan dan konsistensi. Memindahkan logika terkait tanggal libur dalam fungsi `countHariKerja` ke fungsi terpisah `holidays` agar lebih modular dan mudah dikelola.
2024-11-21 18:38:31 +07:00
Daeng Deni Mardaeni
da80715bca Merge remote-tracking branch 'composer/andydev' into staging
# Conflicts:
#	resources/views/spk/documentSPK.blade.php
#	resources/views/spk/edit.blade.php
2024-11-21 15:21:55 +07:00
Daeng Deni Mardaeni
e6e2a12729 Perbarui placeholder dengan data dinamis
Ganti placeholder statis dengan data dinamis menggunakan variabel dari objek `$penawaran`. Hal ini memungkinkan penarikan data langsung dari objek untuk nomor proposal, tanggal proposal, dan perhitungan hari kerja untuk SLA resume dan final, sehingga lebih akurat dan mengurangi risiko kesalahan informasi.
2024-11-21 14:25:02 +07:00
Andy Chaerudin
c08b93aa81 Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into andydev 2024-11-21 13:25:52 +07:00
Andy Chaerudin
3b616f21ba Perbaikan CONFLICT (content): Merge conflict in app/Http/Controllers/OtorisasiPenawaranController.php 2024-11-21 13:25:44 +07:00
Daeng Deni Mardaeni
d4662d413f Perbaiki metode show dan pembaruan status permohonan
Metode `show` sekarang mengubah status permohonan menjadi 'tender' dan memperbaiki parameter inputnya. Selain itu, tambahkan pembaruan `status_bayar` pada objek `permohonan` saat status diubah menjadi 'spk'. Juga, perbaiki kondisi pembatalan pada tampilan `index.blade.php`.
2024-11-21 13:21:26 +07:00
Daeng Deni Mardaeni
41687dfdd6 Tambah fitur unggah dokumen dan update status permohonan
Menambahkan fitur untuk mengunggah dokumen persetujuan penawaran, surat representasi, dan bukti bayar saat menyimpan persetujuan penawaran. Sekaligus mengupdate status permohonan terkait menjadi 'spk'. Menambahkan tampilan baru untuk formulir persetujuan penawaran dan memperbarui breadcrumb untuk mendukung halaman baru ini.
2024-11-21 13:00:57 +07:00
Daeng Deni Mardaeni
43caa255a1 Refactor Models PersetujuanPenawaran dan PenawaranTender
Menghapus beberapa use statements yang tidak digunakan lagi di PersetujuanPenawaran.php. Menambahkan fields baru dan memperbarui tipe casting pada beberapa fields yang sudah ada. Mengoreksi relasi belongsTo pada PenawaranTender.php agar sesuai dengan parameter yang benar.
2024-11-21 13:00:28 +07:00
Daeng Deni Mardaeni
79ded6f451 Perbarui validasi dan pesan dalam PersetujuanPenawaranRequest
Mengubah beberapa aturan validasi, memperbarui namespace, dan menambahkan validasi serta pesan untuk file baru seperti `file_persetujuan_penawaran`, `surat_representasi`, dan `bukti_bayar`. Selain itu, memperbaiki beberapa pesan kesalahan khusus dan menambahkan pesan baru untuk status pembayaran.
2024-11-21 13:00:16 +07:00
Daeng Deni Mardaeni
050b49af2d Tambah kolom created_by dan updated_by pada tabel persetujuan_penawaran
Menambahkan dua kolom baru, `created_by` dan `updated_by`, pada tabel `persetujuan_penawaran` untuk menyimpan informasi pengguna yang membuat dan memperbarui data. Kolom-kolom ini bersifat nullable. Selain itu, menyediakan metode untuk menghapus kolom tersebut jika diperlukan.
2024-11-21 12:59:59 +07:00
Daeng Deni Mardaeni
2afa04a82e Perbarui tabel persetujuan_penawaran
Menghapus kolom attachment dan menambahkan kolom file_persetujuan_penawaran, surat_representasi, dan bukti_bayar pada tabel persetujuan_penawaran. Juga menghapus foreign key 'region_id' yang terkait dengan kolom attachment.
2024-11-21 12:59:41 +07:00
Andy Chaerudin
f6e0081d94 Menambahkan feature -Tombol Penawaran Ulang- (berguna untuk antisipasi perpanjang waktu penawaran dan lainnya). Dan menerapkannya di flow Otorisasi Tender, Proses Penawaran, dan Proses Penawaran Ulang 2024-11-21 12:39:46 +07:00
Daeng Deni Mardaeni
9c0fb13837 Tambah Kolom Dokumen Persetujuan dan Proses Data
Menambahkan kolom baru "Dokumen Persetujuan" pada tampilan tabel persetujuan penawaran untuk dapat mengunduh dokumen terkait. Juga menambahkan fungsi JavaScript "prosesData" yang menggunakan Swal untuk konfirmasi persetujuan atau pengembalian data penawaran untuk dikaji ulang. Fungsi render untuk beberapa kolom diperbarui untuk menampilkan data dengan format yang lebih sesuai.
2024-11-21 11:19:21 +07:00
Daeng Deni Mardaeni
d2c2436212 Tambah relasi persetujuan ke model PenawaranTender
Menambahkan fungsi `persetujuan` untuk menghubungkan model `PenawaranTender` dengan model `PersetujuanPenawaran` menggunakan relasi `belongsTo`. Hal ini memungkinkan pengambilan data persetujuan terkait penawaran tender.
2024-11-21 11:19:02 +07:00
Daeng Deni Mardaeni
666419507f Tambah halaman daftar persetujuan penawaran
Buat berkas `index.blade.php` untuk menampilkan daftar persetujuan penawaran dengan tabel yang mendukung pencarian dan ekspor ke Excel. Halaman ini juga mencakup pengelolaan melalui kolom-kolom seperti nomor registrasi, nama debitur, nomor proposal, tanggal proposal, biaya final, SLA resume, SLA final, dan catatan. Menyertakan interaksi seperti pengeditan melalui aksi pada setiap baris tabel.
2024-11-20 22:48:52 +07:00
Daeng Deni Mardaeni
5fdbe4fc25 Ubah relasi penawaranTender dari hasMany ke belongsTo
Mengganti metode `penawaranTender` dalam model `Permohonan` dari `hasMany` menjadi `belongsTo`. Perubahan ini diperlukan untuk mencocokkan struktur relasi database yang benar antara `Permohonan` dan `PenawaranTender` berdasarkan `nomor_registrasi`.
2024-11-20 22:48:43 +07:00
Daeng Deni Mardaeni
c41e7da05f Tambah relasi detail pada model PenawaranTender
Menambahkan fungsi relasi "detail" untuk menghubungkan model PenawaranTender dengan PenawaranDetailTender berdasarkan kondisi status 1. Relasi ini menggunakan belongTo untuk mendapatkan detail penawaran yang berstatus aktif.
2024-11-20 22:48:36 +07:00
Daeng Deni Mardaeni
254274b40f Refactor OtorisasiPenawaranController indentation and formatting
Merubah indentation dan formatting pada file OtorisasiPenawaranController.php untuk meningkatkan keterbacaan kode. Perubahan ini meliputi perbaikan penempatan namespace, import statements, dan penyesuaian indentasi method-method dalam controller tersebut tanpa mengubah logika bisnis.
2024-11-20 22:48:18 +07:00
Daeng Deni Mardaeni
08ebcb740c Tambah menu "Persetujuan Penawaran"
Menu baru "Persetujuan Penawaran" dengan role "administrator" dan "pemohon-ao" telah ditambahkan ke file `module.json`. Ini memberikan kemampuan tambahan kepada pengguna untuk mengakses fungsi persetujuan penawaran yang sebelumnya tidak tersedia.
2024-11-20 22:47:49 +07:00
Daeng Deni Mardaeni
793d80270b Tambah breadcrumb persetujuan penawaran
Menambahkan jalur breadcrumb baru untuk halaman persetujuan penawaran di dalam file `breadcrumbs.php`. Hal ini akan memudahkan navigasi ke halaman persetujuan penawaran melalui breadcrumb.
2024-11-20 22:47:38 +07:00
Daeng Deni Mardaeni
cc88d9af3f Refactor and streamline web route imports
Mengubah urutan dan format import controller agar lebih rapi dan terstruktur. Hal ini melibatkan merapikan dan menyusun ulang urutan import serta memperbaiki format penulisan route middleware dan grouping agar lebih konsisten. Perubahan ini tidak mengubah fungsi utama dari routing namun meningkatkan keterbacaan dan pengelolaan kode.
2024-11-20 22:47:15 +07:00
Daeng Deni Mardaeni
e696604be6 Tambahkan PersetujuanPenawaranController
Menambahkan `PersetujuanPenawaranController` untuk mengelola persetujuan penawaran.
Controller ini mencakup operasi CRUD dasar (Create, Read, Update, Delete) serta menyediakan fitur pencarian dan paginasi melalui metode `dataForDatatables`.
Metode-metode ini memudahkan interaksi pengguna dengan data persetujuan penawaran, memastikan data valid, dan mengelola otorisasi pengguna.
2024-11-20 22:47:01 +07:00
Daeng Deni Mardaeni
f2ed8321e1 Tambah request validasi PersetujuanPenawaranRequest
Menambahkan file request baru bernama PersetujuanPenawaranRequest untuk melakukan validasi terhadap data persetujuan penawaran. Meliputi aturan validasi, pesan kustom untuk kesalahan validasi, serta pengaturan otorisasi. File ini akan memastikan data yang diterima sesuai dengan yang diharapkan sebelum diproses lebih lanjut.
2024-11-20 22:46:50 +07:00
Daeng Deni Mardaeni
d4dc39b47e Tambah model PersetujuanPenawaran
Menambahkan file model baru PersetujuanPenawaran.php dalam module LPJ. Model ini mencakup relasi dengan tabel PenawaranTender, Region, dan User, serta mendefinisikan properti yang dapat diisi dan tipe data yang sesuai dalam tabel 'persetujuan_penawaran'.
2024-11-20 22:46:36 +07:00
Daeng Deni Mardaeni
f62c1a9389 Perbarui skema persetujuan_penawaran
Menambahkan migrasi untuk membuat beberapa kolom dalam tabel `persetujuan_penawaran` menjadi nullable dan mengubah nama kolom `sls_resume` menjadi `sla_resume`. Perubahan-perubahan ini mencakup setting nullable untuk beberapa kolom seperti `nomor_proposal_penawaran`, `tanggal_proposal_penawaran`, `biaya_final`, `sla_resume`, `sla_final`, `catatan`, `attachment`, `region_id`, dan `status`, serta mengembalikan perubahan tersebut pada metode `down`.
2024-11-20 22:46:27 +07:00
15d70c8df2 Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2024-11-20 17:40:35 +07:00
putrakuningan
b41b130bf1 Merge pull request 'Menambahkan log ketika di kirim surat tender dari setiap kjpp' (#45) from tender into staging
Reviewed-on: #45
2024-11-20 10:37:15 +00:00
264642795d Menambahkan log ketika di kirim surat tender dari setiap kjpp 2024-11-20 10:37:15 +00:00
7dcc538eee Menambahkan log ketika di kirim surat tender dari setiap kjpp 2024-11-20 17:35:06 +07:00
putrakuningan
7482ed67c6 Merge pull request 'feature/senior-officer' (#44) from feature/senior-officer into staging
Reviewed-on: #44
2024-11-20 10:11:56 +00:00
majid
102f0e07ae Merge branch 'staging' into feature/senior-officer 2024-11-20 17:07:03 +07:00
majid
deaf9e8e1b update form inspeksi and basic data inspeksi 2024-11-20 17:04:15 +07:00
Daeng Deni Mardaeni
212d6b3ae9 Merge remote-tracking branch 'composer/andydev' into staging 2024-11-20 15:36:38 +07:00
Daeng Deni Mardaeni
c7411ec240 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-11-20 15:36:15 +07:00
Andy Chaerudin
b81357ed87 Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into andydev 2024-11-20 14:54:23 +07:00
Andy Chaerudin
5aaecb5c4f penggabungan feature Data Penawaran ke dalam feature Proses Penawaran. Dan merapihkan tampilan index 2024-11-20 14:49:48 +07:00
ec8ae3b960 Membuat kirim surat tender part 2 2024-11-20 10:56:00 +07:00
6c7fe4669b Memperbaiki fungsi yang redudansi pada formatTanggalIndonesia ketika kirim email tender 2024-11-20 09:01:19 +07:00
91e921ca6d Memperbaiki fungsi yang redudansi pada formatTanggalIndonesia 2024-11-20 08:53:49 +07:00
6ae35315b3 Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2024-11-20 08:25:53 +07:00
17ca3b2e50 Menambahkan fitur kirim email tender part 1 2024-11-20 08:24:59 +07:00
Daeng Deni Mardaeni
973bfbbc75 Pisahkan tampilan history aktivitas menjadi komponen terpisah
Memindahkan tampilan history aktivitas dari file detail-jaminan.blade.php ke file baru bernama history-permohonan.blade.php dan menghubungkannya menggunakan include. Pendekatan ini membuat kode lebih modular dan lebih mudah di-maintain.
2024-11-19 15:21:21 +07:00
Daeng Deni Mardaeni
085d3a876e Update formatTanggalIndonesia function calls
Mengubah pemanggilan fungsi formatTanggalIndonesia dengan penambahan parameter kedua yang bernilai true pada dua file Blade, yaitu surat_tender_download.blade.php dan surat_tender.blade.php. Ini untuk memastikan format tanggal disesuaikan dengan kebutuhan aplikasi.
2024-11-19 15:14:17 +07:00
Daeng Deni Mardaeni
d66107ec1e Perbarui fungsi formatTanggalIndonesia dengan opsi waktu
Fungsi `formatTanggalIndonesia` diperbarui untuk menerima parameter opsional `$time`. Jika `$time` bernilai `false`, fungsi akan mengembalikan format tanggal tanpa waktu. Namun, jika bernilai `true`, fungsi akan menyertakan waktu dalam format hasilnya. Fungsi `formatTanggalIndonesia2` dihapus untuk menyederhanakan dan mengurangi redundansi kode.
2024-11-19 15:14:00 +07:00
Daeng Deni Mardaeni
a999dfbdd6 Tambahkan fitur riwayat aktivitas pada halaman detail jaminan
Menambahkan komponen tampilan untuk menampilkan riwayat aktivitas permohonan jaminan. Fitur ini termasuk tampilan ikon status, deskripsi, nama pembuat, tanggal, dan link unduhan lampiran jika tersedia. Penambahan ini akan memudahkan pengguna dalam melacak aktivitas yang terjadi pada setiap permohonan jaminan.
2024-11-19 15:11:32 +07:00
Daeng Deni Mardaeni
c49bc3ddb3 Format kode dan tambahkan relasi histories
Mengformat ulang kode model Permohonan untuk konsistensi indentasi dan keterbacaan. Menambahkan relasi `histories` untuk menghubungkan dengan model PermohonanHistory, berguna untuk melacak riwayat perubahan permohonan.
2024-11-19 15:11:12 +07:00
Daeng Deni Mardaeni
d48bef9e67 Tambahkan use statement untuk User
Menambahkan deklarasi `use` untuk model `User` di `PermohonanHistory.php`. Hal ini diperlukan untuk memastikan bahwa referensi terhadap model `User` dalam file ini dikenali oleh sistem.
2024-11-19 15:11:00 +07:00
Daeng Deni Mardaeni
631d589386 Update PermohonanController: Hapus pengolahan file dan histori setelah update permohonan
Telah dilakukan pembersihan pada kode dengan menghapus logika pengolahan file dan pembuatan histori setelah proses update permohonan. Perubahan ini diharapkan menyederhanakan fungsi update di dalam PermohonanController serta mengurangi beban pemrosesan yang tidak diperlukan.
2024-11-19 15:10:48 +07:00
majid
7e70608ba4 Merge branch 'staging' into feature/senior-officer 2024-11-19 11:00:58 +07:00
majid
d03eed23c3 Merge branch 'feature/senior-officer' of https://git.putrakuningan.com/daengdeni/lpj into feature/senior-officer 2024-11-19 10:58:13 +07:00
majid
d51fd932e7 update semua form inspeksi 2024-11-19 10:50:21 +07:00
Daeng Deni Mardaeni
9af9c343d1 Perbaiki pengelolaan dokumen pada History Permohonan
Mengganti field 'attachment' menjadi 'dokumen' pada model Permohonan dan mengupdate referensi terkait di view dan service. Juga menambahkan dukungan multipart/form-data pada form. Perubahan ini memperbaiki manajemen file yang diunggah dan memastikan integritas data terlindungi saat memperbarui permohonan.
2024-11-18 14:18:34 +07:00
majid
a79dd22311 udate form kendaraan 2024-11-16 07:45:02 +07:00
putrakuningan
77cc5a4b24 Merge pull request 'perbaiki bug yang permohonan show' (#41) from tender into staging
Reviewed-on: #41
2024-11-15 08:31:49 +00:00
5afd104d15 memperbaiki show permohonan yang typo 2024-11-15 08:31:49 +00:00
7db25c2226 memperbaiki show permohonan yang typo 2024-11-15 15:16:59 +07:00
Daeng Deni Mardaeni
38a8fb2d7d Tambah model HolidayCalendar dan fungsi hitungHariKerja
Menambahkan file model HolidayCalendar dan fungsi hitungHariKerja ke dalam helper Lpj.php untuk menghitung jumlah hari kerja antara dua tanggal dengan mengabaikan akhir pekan dan hari libur yang tercatat dalam HolidayCalendar.
2024-11-15 13:48:49 +07:00
5b548e5071 Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2024-11-15 13:47:24 +07:00
Daeng Deni Mardaeni
28d987927f Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-11-14 20:38:06 +07:00
rustam76
b8fb8bd09a update status table assingment 2024-11-14 10:43:45 +00:00
majid
15b3e6d3cb update show data status registari final 2024-11-14 17:14:36 +07:00
putrakuningan
1aed2a20ba Merge pull request 'Memperbaiki bug pada menu tender penawaran dan penawaran ulang dan memperbaiki tampilan download surat tender' (#40) from tender into staging
Reviewed-on: #40
2024-11-14 09:46:07 +00:00
60a0d5468b memperbaiki style pada download pdf surat tender 2024-11-14 09:46:07 +00:00
318ccb6f79 menghapus tombol detail pada tambah penawaran tender 2024-11-14 09:46:07 +00:00
6f5c886f74 Memperbaiki kontroller tender untuk memeriksa apakah nomor registrasi itu ada di tabel penawaran kalau tidak maka kembali ke halaman create 2024-11-14 09:46:07 +00:00
Daeng Deni Mardaeni
7d0d759096 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-11-14 16:42:07 +07:00
majid
506a3fefd1 update status assingment (proses_penawaran) 2024-11-14 16:40:30 +07:00
5e0e96063b Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2024-11-14 15:57:58 +07:00
8a97d2d109 memperbaiki style pada download pdf surat tender 2024-11-14 15:52:58 +07:00
2296fd0e19 menghapus tombol detail pada tambah penawaran tender 2024-11-14 15:49:07 +07:00
7f57155de7 Memperbaiki kontroller tender untuk memeriksa apakah nomor registrasi itu ada di tabel penawaran kalau tidak maka kembali ke halaman create 2024-11-14 15:46:32 +07:00
Daeng Deni Mardaeni
e239381dfe Perbaiki pengecekan unggah file revisi
Tambahkan kondisi pengecekan apakah tombol "revisi" ditekan saat memvalidasi pengunggahan file revisi. Ini memastikan pesan kesalahan muncul hanya jika pengguna mencoba mengirimkan tanpa mengunggah file revisi ketika tombol "revisi" ditekan.
2024-11-14 15:33:29 +07:00
Daeng Deni Mardaeni
e11b01f0aa Perbarui roles pada module.json
Tambahkan "EO Appraisal" dan "DD Appraisal" ke roles untuk otorisasi terkait. Hal ini memungkinkan user dengan roles tersebut untuk mengakses fitur-fitur yang sebelumnya hanya bisa diakses oleh "administrator" dan "admin". Menghapus whitespace yang tidak diperlukan untuk menjaga konsistensi.
2024-11-14 15:16:38 +07:00
e11743f3fe Menambahkan route yang hilang pada show proses penawaran, set data proses penawaran, edit proses penawaran 2024-11-14 11:32:47 +07:00
65b92d8e4d membuat fitur download surat tender dalam bentuk pdf selesai 2024-11-14 10:52:13 +07:00
majid
1cd97f2ddd Merge branch 'staging' into feature/senior-officer 2024-11-14 08:43:20 +07:00
44a783b38b Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2024-11-14 08:32:29 +07:00
putrakuningan
c0070b1381 Merge pull request 'update form surveyor' (#38) from feature/senior-officer into staging
Reviewed-on: #38
2024-11-13 20:16:26 +00:00
majid
3f8475f418 update form apartemen dan foto 2024-11-13 20:16:26 +00:00
majid
d3d918b838 update form data surveyor 2024-11-13 20:16:26 +00:00
Daeng Deni Mardaeni
4eba7f893a Refactor and optimize RegistrasiController
Menghapus komentar yang tidak diperlukan, merapikan kode, dan menambahkan dependensi yang hilang. Perubahan ini juga mencakup optimalisasi pengambilan data serta perbaikan penanganan permintaan AJAX pada metode setData dan update.
2024-11-14 03:15:45 +07:00
Daeng Deni Mardaeni
02c04a4346 Tambah fungsi unggah lampiran dan riwayat permohonan
Menambahkan fungsi untuk mengunggah lampiran saat membuat dan memperbarui permohonan, serta mencatat riwayat perubahan permohonan dengan menggunakan PermohonanHistoryService. Fitur ini memastikan file lampiran tersimpan dengan benar dan perubahan terhadap permohonan terdokumentasi.
2024-11-14 03:14:26 +07:00
Daeng Deni Mardaeni
187282fe9f Perbarui metode bulkDownload untuk penanganan file lebih baik
Tambahkan pengelompokan dokumen berdasarkan jenis jaminan dalam folder terstruktur, log peringatan untuk file yang hilang, dan bersihkan nama folder untuk kompatibilitas.
2024-11-14 03:14:07 +07:00
Daeng Deni Mardaeni
0601936ca5 Tingkatkan include pada detail view
Menambahkan parameter `backLink` pada include `detail-jaminan` di file `surveyor/detail.blade.php` untuk mengarahkan kembali ke index surveyor. Perubahan ini bertujuan untuk memperbaiki navigasi kembali bagi pengguna.
2024-11-14 03:13:41 +07:00
Daeng Deni Mardaeni
5785bf6324 Hapus Detail Data Permohonan dan Debitur
Menghapus tampilan detail data permohonan dan debitur dari form penilaian untuk menyederhanakan antarmuka pengguna. Mengubah @include komponen detail-jaminan dengan menambahkan parameter backLink.
2024-11-14 03:13:07 +07:00
Daeng Deni Mardaeni
7ac9ca5922 Tambah informasi plafon, status bayar, dan nilai NJOP pada tampilan registrasi final
Telah ditambahkan tiga informasi penting yang sebelumnya tidak ada: plafon, status bayar, dan nilai NJOP. Ini bertujuan untuk memberikan detail lebih lengkap mengenai permohonan. Beberapa bagian terkait informasi debitur telah dihapus untuk memperbaiki tampilan dan fokus pada informasi yang lebih relevan. Selain itu, komponen detail jaminan sekarang menyertakan opsi `backLink` dan `hidePermohonan`.
2024-11-14 03:12:36 +07:00
Daeng Deni Mardaeni
ba2bb1220a Hapus detail data permohonan dan debitur
Telah dihapus tampilan detail data permohonan, debitur, dan biaya dari halaman registrasi. Detail jaminan masih disertakan dengan penambahan tautan kembali ke indeks registrasi. Perubahan ini bertujuan menyederhanakan tampilan halaman dan mengurangi informasi yang tidak diperlukan.
2024-11-14 03:12:18 +07:00
Daeng Deni Mardaeni
abf17c9b8a Hapus detail permohonan dan debitur
Menghapus semua informasi detail terkait permohonan dan debitur dari tampilan halaman. Penyesuaian juga dilakukan pada komponen detail jaminan dengan menambahkan link kembali ke 'permohonan.index'.
2024-11-14 03:11:44 +07:00
Daeng Deni Mardaeni
c0de927d15 Hapus detail permohonan dan debitur
Menghapus semua informasi detail terkait permohonan dan debitur dari tampilan halaman. Penyesuaian juga dilakukan pada komponen detail jaminan dengan menambahkan link kembali ke 'authorization.index'.
2024-11-14 03:09:07 +07:00
Daeng Deni Mardaeni
9641ee6bb9 Tambahkan relasi permohonan di model Debiture
Menambahkan fungsi `permohonan` untuk relasi one-to-one antara model Debiture dan Permohonan guna mempermudah akses data permohonan terkait.
2024-11-14 03:08:37 +07:00
Daeng Deni Mardaeni
dc1356f234 Tambah informasi detail permohonan dan debitur
Menambahkan tampilan informasi detail permohonan termasuk nomor registrasi, pemohon, tujuan permohonan, nilai plafond, status bayar, dan nilai NJOP. Juga menambahkan tampilan detail debitur yang mencakup nama, email, telepon, alamat lengkap, cabang, CIF, nomor rekening, dan NPWP pada halaman 'detail-jaminan.blade.php'.
2024-11-14 03:07:59 +07:00
majid
4ed858b7e7 update form apartemen dan foto 2024-11-14 00:08:45 +07:00
majid
32ab6fdcf0 Merge branch 'staging' into feature/senior-officer 2024-11-13 22:15:13 +07:00
majid
947cccfeac update form data surveyor 2024-11-13 22:12:51 +07:00
2900d3158d Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2024-11-13 18:10:49 +07:00
c1f66b23c3 membuat fitur download surat tender dalam bentuk pdf part 1 2024-11-13 18:07:57 +07:00
Daeng Deni Mardaeni
1ae4d4acab Merge remote-tracking branch 'composer/tender' into staging 2024-11-13 17:18:56 +07:00
Daeng Deni Mardaeni
1614387654 Merge remote-tracking branch 'composer/feature/senior-officer' into staging
# Conflicts:
#	database/migrations/2024_11_08_081149_create_permohonan_histories_table.php
2024-11-13 17:18:28 +07:00
Daeng Deni Mardaeni
287798c266 Merge remote-tracking branch 'composer/andydev' into staging 2024-11-13 17:10:54 +07:00
Daeng Deni Mardaeni
de00c6dfa2 Tambahkan field 'details' ke dalam DokumenJaminanController
Field 'details' ditambahkan dalam array data pada DokumenJaminanController.
Field ini akan diisi dengan nilai dari 'custom_field' jika ada, atau string kosong jika tidak.
Perubahan diterapkan pada dua lokasi berbeda di dalam file controller.
2024-11-13 17:09:40 +07:00
Daeng Deni Mardaeni
a0bf63a2ab Perbaiki proses penambahan file ke dalam zip
Tambahkan pengecekan eksistensi 'dokumen_jaminan' sebelum memproses penambahan file ke dalam arsip zip untuk mencegah error. Hal ini menghindari kasus di mana dokumen_jaminan tidak ada atau null.
2024-11-13 17:09:40 +07:00
Daeng Deni Mardaeni
93bdec5616 Tambah log historis pada Permohonan
Integrasi `PermohonanHistoryService` untuk mencatat log historis setiap pembuatan dan pembaruan permohonan. Penambahan ini mencakup pemrosesan unggahan file lampiran, pengambilan keterangan, dan pencatatan status permohonan sebelum dan sesudah perubahan.
2024-11-13 17:09:40 +07:00
Daeng Deni Mardaeni
88f1b40683 Tambah fitur riwayat permohonan
Menambahkan migrasi database, model, dan service untuk mencatat riwayat setiap permohonan. Migrasi menciptakan tabel `permohonan_histories` dengan menyimpan detail tentang status, keterangan, perubahan permohonan (sebelum dan sesudah), dan informasi file terkait. Model `PermohonanHistory` mengatur relasi dengan model `Permohonan` dan `User`. Service `PermohonanHistoryService` menangani pembuatan riwayat baru serta penanganan file terkait dan error handling yang memadai.
2024-11-13 17:09:40 +07:00
Daeng Deni Mardaeni
92f8da6c5f Tambahkan fitur unggah file revisi
Menambahkan elemen input untuk unggah file revisi pada halaman otorisasi permohonan serta validasi pada berkas unggahan. Apabila tidak ada berkas yang diunggah, akan muncul pesan kesalahan yang meminta pengguna untuk mengunggah berkas revisi. Juga ditambahkan event listener untuk menghilangkan pesan kesalahan setelah berkas diunggah.
2024-11-13 17:09:40 +07:00
Daeng Deni Mardaeni
ad03847bff Tambah validasi untuk catatan pada tombol Revisi
Menambahkan validasi pada tombol "Revisi" agar memastikan bahwa kolom catatan tidak kosong sebelum formulir dikirim. Jika kolom catatan kosong, pesan kesalahan akan ditampilkan kepada pengguna.
2024-11-13 17:09:40 +07:00
Daeng Deni Mardaeni
f4239a2d40 Sesuaikan input file untuk menerima .pdf dan gambar
Setiap input file pada form dokumen telah disesuaikan agar hanya menerima file bertipe .pdf dan file gambar (image/*). Ini memastikan bahwa hanya tipe file yang diinginkan yang dapat diunggah, meningkatkan validitas dan keamanan data yang diproses.
2024-11-13 17:09:40 +07:00
Daeng Deni Mardaeni
2ef55f8df5 **Tambahkan dukungan pratinjau untuk gambar dan file PDF**
Modal pratinjau sekarang mendukung gambar (JPG, JPEG, PNG, GIF) selain PDF.
Refaktor kode untuk menangani berbagai jenis file dan perubahan elemen HTML terkait untuk mendukung fungsi baru.
2024-11-13 17:09:40 +07:00
Daeng Deni Mardaeni
acf121cc2c Tambahkan fitur download dan penutupan modal PDF dengan tombol Escape
Memperbarui tampilan modal untuk menyertakan tombol download PDF dan menutupi modal ketika tombol Escape ditekan. Penyesuaian elemen dalam modal untuk mengatur tata letak yang lebih baik dan menambah event listener untuk menangani penutupan modal saat klik di luar isi modal.
2024-11-13 17:09:40 +07:00
ce1df671f7 Memperbaiki tampilan pada show KJPP 2024-11-13 17:09:40 +07:00
6287165266 Menyelesaikan fitur Basic Data KJPP untuk menambahkan lebih dari satu email kantor, pic reviewer, pic admin, pic marketing 2024-11-13 17:09:40 +07:00
c4f869efd3 Mengubah tampilan pada edit dan create email kantor, PIC Reviewer, PIC Admin, PIC Marketing pada Menu Basic Data -> KJPP part 1 2024-11-13 17:09:40 +07:00
Daeng Deni Mardaeni
0ee821bf46 Perbaiki tampilan status bayar
Mengubah tampilan teks status bayar pada authorization permohonan agar lebih mencolok. Jika statusnya "belum_bayar", teks akan tampil dengan ukuran lebih besar dan warna merah serta dalam huruf kapital; jika tidak, teks akan berwarna hijau dengan huruf kapital.
2024-11-13 17:09:40 +07:00
Daeng Deni Mardaeni
00031b366d Tambah informasi Nilai Plafond dan Status Bayar di halaman autorizasi
Menambahkan dua div baru untuk menampilkan informasi Nilai Plafond dan Status Bayar di dalam halaman peninjauan permohonan autorizasi. Div pertama menampilkan Nilai Plafond dengan format teks medium berwarna abu-abu. Div kedua menampilkan Status Bayar dengan teks yang dikapitalisasi dan menghilangkan underscores.
2024-11-13 17:09:40 +07:00
rustam76
8122b49be6 update file index.blade.php 2024-11-13 17:09:40 +07:00
majid
265e878955 update tampilan team activity 2024-11-13 17:09:40 +07:00
Daeng Deni Mardaeni
20842fa3e0 Update jaminan document display logic
Menambahkan logika baru untuk penanganan dokumen jaminan. Sekarang, jika dokumen jaminan ada lebih dari satu, setiap dokumen akan ditampilkan secara terpisah dengan opsi download dan preview untuk masing-masing dokumen. Sebelumnya, hanya ada satu tautan download dan preview per kategori jaminan.
2024-11-13 17:09:40 +07:00
Daeng Deni Mardaeni
1b9d1bf0b3 Tambah kondisi baru dalam logika dokumenJaminan
Menambahkan beberapa kondisi baru pada fungsi render untuk menangani kasus di mana dokumenJaminan bertipe string dan dokumenNomor null, serta variasi lain yang melibatkan tipe array dan string untuk kombinasi dokumenJaminan dan dokumenNomor. Kondisi ini memastikan penanganan berbagai bentuk data dengan benar sebelum menampilkan elemen DOM yang sesuai.
2024-11-13 17:09:40 +07:00
Daeng Deni Mardaeni
5e6a144b67 Tambah kolom "dokumen_nomor" ke DokumenJaminan
Menambahkan kolom dokumen_nomor pada DokumenJaminan untuk mendukung penyimpanan nomor dokumen yang terkait dengan setiap dokumen jaminan. Pembaruan ini mencakup perubahan pada controller untuk memproses kolom baru dan penyesuaian pada tampilan untuk menampilkan serta mengunduh dokumen berdasarkan nomor ini.
2024-11-13 17:09:40 +07:00
Andy Chaerudin
1e137ae1dc Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into andydev 2024-11-13 16:41:27 +07:00
Andy Chaerudin
2acad72e0e penggabungan feature proses penawaran dan feature proses penawaran ulang, dan terkait keinginan user 2024-11-13 16:40:52 +07:00
Daeng Deni Mardaeni
9b0371dc7a Tambahkan field 'details' ke dalam DokumenJaminanController
Field 'details' ditambahkan dalam array data pada DokumenJaminanController.
Field ini akan diisi dengan nilai dari 'custom_field' jika ada, atau string kosong jika tidak.
Perubahan diterapkan pada dua lokasi berbeda di dalam file controller.
2024-11-13 15:06:14 +07:00
majid76
8e9e5e4843 update form foto 2024-11-13 07:34:39 +07:00
majid
edf293b203 update form foto inspeksi 2024-11-12 17:40:46 +07:00
e2061a3f5d Mengubah urutan berdasarkan Nomor KJPP secara ascending 2024-11-12 10:27:44 +07:00
majid76
d0390d3f9f update form inspeksi menggunakan json 2024-11-12 07:13:33 +07:00
majid
a809828b80 update form inspeksi (tanah, bangunan, dan unit apartement) 2024-11-11 17:24:22 +07:00
486f0d758b Menambahkan fitur nama pimpinan bisa lebih dari satu 2024-11-11 16:25:23 +07:00
majid76
1f033a6f25 update form inspeksi tanah dan bagunan 2024-11-11 07:29:18 +07:00
5b5e45baf6 Merge branch 'staging' of https://git.putrakuningan.com/daengdeni/lpj into tender 2024-11-11 06:16:35 +07:00
Daeng Deni Mardaeni
a02359a797 Perbaiki proses penambahan file ke dalam zip
Tambahkan pengecekan eksistensi 'dokumen_jaminan' sebelum memproses penambahan file ke dalam arsip zip untuk mencegah error. Hal ini menghindari kasus di mana dokumen_jaminan tidak ada atau null.
2024-11-09 05:17:23 +07:00
majid
edd005e132 update form surveyor 2024-11-09 00:55:11 +07:00
Daeng Deni Mardaeni
ac80537ab5 Tambah log historis pada Permohonan
Integrasi `PermohonanHistoryService` untuk mencatat log historis setiap pembuatan dan pembaruan permohonan. Penambahan ini mencakup pemrosesan unggahan file lampiran, pengambilan keterangan, dan pencatatan status permohonan sebelum dan sesudah perubahan.
2024-11-08 19:54:02 +07:00
Daeng Deni Mardaeni
f3297988ff Tambah fitur riwayat permohonan
Menambahkan migrasi database, model, dan service untuk mencatat riwayat setiap permohonan. Migrasi menciptakan tabel `permohonan_histories` dengan menyimpan detail tentang status, keterangan, perubahan permohonan (sebelum dan sesudah), dan informasi file terkait. Model `PermohonanHistory` mengatur relasi dengan model `Permohonan` dan `User`. Service `PermohonanHistoryService` menangani pembuatan riwayat baru serta penanganan file terkait dan error handling yang memadai.
2024-11-08 19:53:15 +07:00
majid
a4d49c7078 Merge branch 'feature/senior-officer' of https://git.putrakuningan.com/daengdeni/lpj into feature/senior-officer 2024-11-08 16:15:28 +07:00
majid
df68c70127 update assingment 2024-11-08 16:14:46 +07:00
Daeng Deni Mardaeni
70344ff310 Tambahkan fitur unggah file revisi
Menambahkan elemen input untuk unggah file revisi pada halaman otorisasi permohonan serta validasi pada berkas unggahan. Apabila tidak ada berkas yang diunggah, akan muncul pesan kesalahan yang meminta pengguna untuk mengunggah berkas revisi. Juga ditambahkan event listener untuk menghilangkan pesan kesalahan setelah berkas diunggah.
2024-11-08 15:00:49 +07:00
Daeng Deni Mardaeni
5adb00f04c Tambah validasi untuk catatan pada tombol Revisi
Menambahkan validasi pada tombol "Revisi" agar memastikan bahwa kolom catatan tidak kosong sebelum formulir dikirim. Jika kolom catatan kosong, pesan kesalahan akan ditampilkan kepada pengguna.
2024-11-08 14:25:28 +07:00
Daeng Deni Mardaeni
86a49ea4d0 Sesuaikan input file untuk menerima .pdf dan gambar
Setiap input file pada form dokumen telah disesuaikan agar hanya menerima file bertipe .pdf dan file gambar (image/*). Ini memastikan bahwa hanya tipe file yang diinginkan yang dapat diunggah, meningkatkan validitas dan keamanan data yang diproses.
2024-11-07 23:14:59 +07:00
Daeng Deni Mardaeni
991fda7ccb **Tambahkan dukungan pratinjau untuk gambar dan file PDF**
Modal pratinjau sekarang mendukung gambar (JPG, JPEG, PNG, GIF) selain PDF.
Refaktor kode untuk menangani berbagai jenis file dan perubahan elemen HTML terkait untuk mendukung fungsi baru.
2024-11-07 23:11:41 +07:00
Daeng Deni Mardaeni
aa41da8a68 Tambahkan fitur download dan penutupan modal PDF dengan tombol Escape
Memperbarui tampilan modal untuk menyertakan tombol download PDF dan menutupi modal ketika tombol Escape ditekan. Penyesuaian elemen dalam modal untuk mengatur tata letak yang lebih baik dan menambah event listener untuk menangani penutupan modal saat klik di luar isi modal.
2024-11-07 21:31:46 +07:00
putrakuningan
a3de0bf8de Merge pull request 'tender' (#35) from tender into staging
Reviewed-on: #35
2024-11-07 10:22:40 +00:00
a3e9ba5633 Memperbaiki tampilan pada show KJPP 2024-11-07 10:22:40 +00:00
a326f4c4e5 Menyelesaikan fitur Basic Data KJPP untuk menambahkan lebih dari satu email kantor, pic reviewer, pic admin, pic marketing 2024-11-07 10:22:40 +00:00
669c2483f8 Mengubah tampilan pada edit dan create email kantor, PIC Reviewer, PIC Admin, PIC Marketing pada Menu Basic Data -> KJPP part 1 2024-11-07 10:22:40 +00:00
Daeng Deni Mardaeni
d277d7ced1 Perbaiki tampilan status bayar
Mengubah tampilan teks status bayar pada authorization permohonan agar lebih mencolok. Jika statusnya "belum_bayar", teks akan tampil dengan ukuran lebih besar dan warna merah serta dalam huruf kapital; jika tidak, teks akan berwarna hijau dengan huruf kapital.
2024-11-07 17:14:42 +07:00
Daeng Deni Mardaeni
4de7e6b741 Tambah informasi Nilai Plafond dan Status Bayar di halaman autorizasi
Menambahkan dua div baru untuk menampilkan informasi Nilai Plafond dan Status Bayar di dalam halaman peninjauan permohonan autorizasi. Div pertama menampilkan Nilai Plafond dengan format teks medium berwarna abu-abu. Div kedua menampilkan Status Bayar dengan teks yang dikapitalisasi dan menghilangkan underscores.
2024-11-07 17:09:34 +07:00
Daeng Deni Mardaeni
b3572210ea Merge branch 'feature/senior-officer' into staging 2024-11-07 16:46:04 +07:00
rustam76
de4d33e3db update file index.blade.php 2024-11-07 09:43:40 +00:00
Daeng Deni Mardaeni
9b1d869c84 Merge remote-tracking branch 'composer/feature/senior-officer' into staging 2024-11-07 16:40:35 +07:00
majid
7e425d10e6 update tampilan team activity 2024-11-07 16:32:27 +07:00
Daeng Deni Mardaeni
3f21b90c6d Update jaminan document display logic
Menambahkan logika baru untuk penanganan dokumen jaminan. Sekarang, jika dokumen jaminan ada lebih dari satu, setiap dokumen akan ditampilkan secara terpisah dengan opsi download dan preview untuk masing-masing dokumen. Sebelumnya, hanya ada satu tautan download dan preview per kategori jaminan.
2024-11-07 16:26:17 +07:00
Daeng Deni Mardaeni
7baf5e4520 Tambah kondisi baru dalam logika dokumenJaminan
Menambahkan beberapa kondisi baru pada fungsi render untuk menangani kasus di mana dokumenJaminan bertipe string dan dokumenNomor null, serta variasi lain yang melibatkan tipe array dan string untuk kombinasi dokumenJaminan dan dokumenNomor. Kondisi ini memastikan penanganan berbagai bentuk data dengan benar sebelum menampilkan elemen DOM yang sesuai.
2024-11-07 15:49:33 +07:00
646 changed files with 91814 additions and 11972 deletions

42
Jenkinsfile vendored Normal file
View File

@@ -0,0 +1,42 @@
pipeline {
agent any
environment {
PHP_VERSION = '8.1'
COMPOSER_HOME = "${WORKSPACE}/.composer"
DASHBOARD = '/var/www/lpj'
WORKDIR = '/var/www/lpj/Modules/Lpj'
GIT_SSH_COMMAND = 'ssh -i ~/.ssh/for_gitea -o StrictHostKeyChecking=no'
}
stages {
stage('Checkout') {
steps {
dir("${env.DASHBOARD}") {
sh "composer update daengdeni/lpj-module:dev-staging"
}
}
}
stage('Build Assets') {
steps {
dir("${env.DASHBOARD}") {
sh "npm install"
sh "npm run build"
}
}
}
}
post {
always {
cleanWs()
}
success {
echo 'The pipeline has succeeded!'
}
failure {
echo 'The pipeline has failed.'
}
}
}

View File

@@ -0,0 +1,228 @@
<?php
namespace Modules\Lpj\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Modules\Lpj\Jobs\CleanupInspeksiDataJob;
use Modules\Lpj\Models\Inspeksi;
use Modules\Lpj\Services\InspeksiCleanupService;
class CleanupInspeksiDataCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'lpj:cleanup-inspeksi
{--permohonan-id= : ID permohonan yang akan di-cleanup (opsional)}
{--sync : Jalankan secara synchronous}
{--dry-run : Tampilkan preview tanpa menjalankan cleanup}
{--force : Jalankan tanpa konfirmasi}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Cleanup data inspeksi lama yang tidak memiliki dokument_id';
/**
* Execute the console command.
*/
public function handle(): int
{
Log::info('CleanupInspeksiDataCommand: Memulai proses cleanup data inspeksi', [
'options' => $this->options()
]);
try {
$permohonanId = $this->option('permohonan-id');
$sync = $this->option('sync');
$dryRun = $this->option('dry-run');
$force = $this->option('force');
// Validasi opsi
if ($dryRun && $sync) {
$this->error('Opsi --dry-run dan --sync tidak dapat digunakan bersamaan.');
return Command::FAILURE;
}
// Tampilkan header
$this->info('=== Cleanup Data Inspeksi ===');
$this->newLine();
// Ambil data yang akan di-cleanup
$cleanupData = $this->getCleanupData($permohonanId);
if ($cleanupData->isEmpty()) {
$this->info('Tidak ada data yang perlu di-cleanup.');
return Command::SUCCESS;
}
// Tampilkan preview data
$this->displayPreview($cleanupData);
if ($dryRun) {
$this->info('Mode dry-run: Tidak ada perubahan yang dilakukan.');
return Command::SUCCESS;
}
// Konfirmasi jika tidak force
if (!$force && !$this->confirm('Lanjutkan dengan cleanup?')) {
$this->info('Cleanup dibatalkan.');
return Command::SUCCESS;
}
// Jalankan cleanup
$this->runCleanup($cleanupData, $sync);
$this->info('Proses cleanup selesai.');
return Command::SUCCESS;
} catch (\Exception $e) {
Log::error('CleanupInspeksiDataCommand: Terjadi error saat proses cleanup', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
$this->error('Terjadi kesalahan: ' . $e->getMessage());
return Command::FAILURE;
}
}
/**
* Ambil data yang akan di-cleanup
*/
private function getCleanupData(?int $permohonanId = null)
{
$this->info('Mencari data yang akan di-cleanup...');
$query = DB::table('inspeksi as i')
->select(
'i.permohonan_id',
'i.created_by',
DB::raw('COUNT(CASE WHEN i.dokument_id IS NOT NULL AND i.deleted_at IS NULL THEN 1 END) as new_data_count'),
DB::raw('COUNT(CASE WHEN i.dokument_id IS NULL AND i.deleted_at IS NULL THEN 1 END) as old_data_count')
)
->whereNull('i.deleted_at')
->groupBy('i.permohonan_id', 'i.created_by');
if ($permohonanId) {
$query->where('i.permohonan_id', $permohonanId);
}
$results = $query->havingRaw('new_data_count > 0 AND old_data_count > 0')
->get();
return $results;
}
/**
* Tampilkan preview data
*/
private function displayPreview($cleanupData): void
{
$this->info('Data yang akan di-cleanup:');
$this->table(
['Permohonan ID', 'Created By', 'Data Baru', 'Data Lama'],
$cleanupData->map(function ($item) {
return [
$item->permohonan_id,
$item->created_by,
$item->new_data_count,
$item->old_data_count
];
})->toArray()
);
$totalPermohonan = $cleanupData->count();
$totalOldData = $cleanupData->sum('old_data_count');
$this->info("Total permohonan: {$totalPermohonan}");
$this->info("Total data lama yang akan dihapus: {$totalOldData}");
$this->newLine();
}
/**
* Jalankan cleanup
*/
private function runCleanup($cleanupData, bool $sync): void
{
$this->info('Memulai proses cleanup...');
$this->newLine();
$progressBar = $this->output->createProgressBar($cleanupData->count());
$progressBar->setFormat('Processing: %current%/%max% [%bar%] %percent:3s%% %message%');
$progressBar->start();
$totalDeleted = 0;
$totalErrors = 0;
foreach ($cleanupData as $data) {
try {
$progressBar->setMessage("Permohonan ID: {$data->permohonan_id}");
// Ambil data baru untuk mendapatkan dokument_id
$newInspeksi = Inspeksi::where('permohonan_id', $data->permohonan_id)
->where('created_by', $data->created_by)
->whereNotNull('dokument_id')
->whereNull('deleted_at')
->first();
if (!$newInspeksi) {
$this->warn("Tidak ditemukan data baru untuk permohonan {$data->permohonan_id}");
$progressBar->advance();
continue;
}
// Jalankan cleanup
if ($sync) {
// Jalankan sync
$job = new CleanupInspeksiDataJob(
$data->permohonan_id,
$data->created_by,
$newInspeksi->dokument_id
);
$job->handle();
} else {
// Dispatch ke queue
CleanupInspeksiDataJob::dispatch(
$data->permohonan_id,
$data->created_by,
$newInspeksi->dokument_id
);
}
$totalDeleted += $data->old_data_count;
} catch (\Exception $e) {
Log::error('CleanupInspeksiDataCommand: Error pada permohonan', [
'permohonan_id' => $data->permohonan_id,
'created_by' => $data->created_by,
'error' => $e->getMessage()
]);
$this->error("Error pada permohonan {$data->permohonan_id}: {$e->getMessage()}");
$totalErrors++;
}
$progressBar->advance();
}
$progressBar->finish();
$this->newLine();
$this->newLine();
// Tampilkan hasil
$this->info('=== Hasil Cleanup ===');
$this->info("Data lama yang dihapus: {$totalDeleted}");
$this->info("Error: {$totalErrors}");
if (!$sync) {
$this->info('Job telah di-dispatch ke queue. Monitor progress di log.');
}
}
}

View File

@@ -0,0 +1,192 @@
<?php
namespace Modules\Lpj\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Modules\Lpj\Models\Inspeksi;
class CleanupInspeksiStatusCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'lpj:cleanup-inspeksi-status
{--permohonan-id= : Filter berdasarkan permohonan ID}
{--created-by= : Filter berdasarkan user ID}
{--detailed : Tampilkan detail data}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Cek status data inspeksi yang memerlukan cleanup';
/**
* Execute the console command.
*/
public function handle(): int
{
try {
$permohonanId = $this->option('permohonan-id');
$createdBy = $this->option('created-by');
$detailed = $this->option('detailed');
$this->info('=== Status Data Inspeksi ===');
$this->newLine();
// Ambil statistik umum
$this->showGeneralStats();
// Ambil data yang memerlukan cleanup
$this->showCleanupStats($permohonanId, $createdBy);
if ($detailed) {
$this->showDetailedData($permohonanId, $createdBy);
}
return Command::SUCCESS;
} catch (\Exception $e) {
Log::error('CleanupInspeksiStatusCommand: Terjadi error', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
$this->error('Terjadi kesalahan: ' . $e->getMessage());
return Command::FAILURE;
}
}
/**
* Tampilkan statistik umum
*/
private function showGeneralStats(): void
{
$this->info('Statistik Umum:');
$totalData = Inspeksi::count();
$activeData = Inspeksi::whereNull('deleted_at')->count();
$deletedData = Inspeksi::whereNotNull('deleted_at')->count();
$dataWithDokument = Inspeksi::whereNotNull('dokument_id')->count();
$dataWithoutDokument = Inspeksi::whereNull('dokument_id')->count();
$this->table(
['Metrik', 'Jumlah'],
[
['Total Data', number_format($totalData)],
['Data Aktif', number_format($activeData)],
['Data Terhapus (Soft)', number_format($deletedData)],
['Data dengan Dokument ID', number_format($dataWithDokument)],
['Data tanpa Dokument ID', number_format($dataWithoutDokument)],
]
);
$this->newLine();
}
/**
* Tampilkan statistik cleanup
*/
private function showCleanupStats(?int $permohonanId = null, ?int $createdBy = null): void
{
$this->info('Data yang Memerlukan Cleanup:');
$query = DB::table('inspeksi as i')
->select(
'i.permohonan_id',
'i.created_by',
DB::raw('COUNT(CASE WHEN i.dokument_id IS NOT NULL AND i.deleted_at IS NULL THEN 1 END) as new_data_count'),
DB::raw('COUNT(CASE WHEN i.dokument_id IS NULL AND i.deleted_at IS NULL THEN 1 END) as old_data_count'),
DB::raw('MIN(i.created_at) as oldest_data'),
DB::raw('MAX(i.created_at) as newest_data')
)
->whereNull('i.deleted_at')
->groupBy('i.permohonan_id', 'i.created_by');
if ($permohonanId) {
$query->where('i.permohonan_id', $permohonanId);
}
if ($createdBy) {
$query->where('i.created_by', $createdBy);
}
$results = $query->havingRaw('new_data_count > 0 AND old_data_count > 0')
->orderBy('old_data_count', 'desc')
->limit(20)
->get();
if ($results->isEmpty()) {
$this->info('Tidak ada data yang memerlukan cleanup.');
return;
}
$this->table(
['Permohonan ID', 'Created By', 'Data Baru', 'Data Lama', 'Data Terlama', 'Data Terbaru'],
$results->map(function ($item) {
return [
$item->permohonan_id,
$item->created_by,
$item->new_data_count,
$item->old_data_count,
$item->oldest_data,
$item->newest_data,
];
})->toArray()
);
$totalPermohonan = $results->count();
$totalOldData = $results->sum('old_data_count');
$this->info("Total permohonan yang perlu cleanup: {$totalPermohonan}");
$this->info("Total data lama yang akan dihapus: {$totalOldData}");
$this->newLine();
}
/**
* Tampilkan detail data
*/
private function showDetailedData(?int $permohonanId = null, ?int $createdBy = null): void
{
$this->info('Detail Data (20 data terbaru):');
$query = Inspeksi::with(['permohonan', 'dokument'])
->whereNull('deleted_at');
if ($permohonanId) {
$query->where('permohonan_id', $permohonanId);
}
if ($createdBy) {
$query->where('created_by', $createdBy);
}
$data = $query->orderBy('created_at', 'desc')
->limit(20)
->get();
if ($data->isEmpty()) {
$this->info('Tidak ada data untuk ditampilkan.');
return;
}
$this->table(
['ID', 'Permohonan ID', 'Created By', 'Dokument ID', 'Status', 'Created At'],
$data->map(function ($item) {
return [
$item->id,
$item->permohonan_id,
$item->created_by,
$item->dokument_id ?? '-',
$item->status,
$item->created_at,
];
})->toArray()
);
}
}

View File

@@ -0,0 +1,99 @@
<?php
namespace Modules\Lpj\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
use Modules\Lpj\Jobs\CleanupInspeksiDataJob;
use Modules\Lpj\Services\InspeksiCleanupService;
class CleanupSingleInspeksiCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'lpj:cleanup-single-inspeksi
{permohonan-id : ID permohonan yang akan di-cleanup}
{created-by : ID user yang membuat data}
{--sync : Jalankan secara synchronous}
{--force : Jalankan tanpa konfirmasi}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Cleanup data inspeksi untuk 1 permohonan dan user tertentu';
/**
* Execute the console command.
*/
public function handle(): int
{
Log::info('CleanupSingleInspeksiCommand: Memulai proses cleanup', [
'permohonan_id' => $this->argument('permohonan-id'),
'created_by' => $this->argument('created-by'),
'sync' => $this->option('sync')
]);
try {
$permohonanId = (int) $this->argument('permohonan-id');
$createdBy = (int) $this->argument('created-by');
$sync = $this->option('sync');
$force = $this->option('force');
// Validasi input
if ($permohonanId <= 0) {
$this->error('Permohonan ID harus angka positif.');
return Command::FAILURE;
}
if ($createdBy <= 0) {
$this->error('Created By harus angka positif.');
return Command::FAILURE;
}
// Tampilkan info
$this->info('=== Cleanup Single Inspeksi ===');
$this->info("Permohonan ID: {$permohonanId}");
$this->info("Created By: {$createdBy}");
$this->info("Mode: " . ($sync ? 'Synchronous' : 'Queue'));
$this->newLine();
// Konfirmasi jika tidak force
if (!$force && !$this->confirm('Lanjutkan dengan cleanup?')) {
$this->info('Cleanup dibatalkan.');
return Command::SUCCESS;
}
// Jalankan cleanup
$cleanupService = new InspeksiCleanupService();
if ($sync) {
$this->info('Menjalankan cleanup secara synchronous...');
$cleanupService->cleanupSync($permohonanId, $createdBy);
$this->info('Cleanup selesai.');
} else {
$this->info('Mengirim job ke queue...');
$cleanupService->cleanupAsync($permohonanId, $createdBy);
$this->info('Job telah di-dispatch ke queue.');
$this->info('Monitor progress di log.');
}
return Command::SUCCESS;
} catch (\Exception $e) {
Log::error('CleanupSingleInspeksiCommand: Terjadi error saat proses cleanup', [
'permohonan_id' => $this->argument('permohonan-id'),
'created_by' => $this->argument('created-by'),
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
$this->error('Terjadi kesalahan: ' . $e->getMessage());
return Command::FAILURE;
}
}
}

123
app/Console/README.md Normal file
View File

@@ -0,0 +1,123 @@
# Console Commands untuk Cleanup Data Inspeksi
## Daftar Command
### 1. `lpj:cleanup-inspeksi`
Command utama untuk cleanup data inspeksi secara batch.
**Usage:**
```bash
php artisan lpj:cleanup-inspeksi [options]
```
**Options:**
- `--permohonan-id=ID` - Filter berdasarkan permohonan ID (opsional)
- `--sync` - Jalankan secara synchronous
- `--dry-run` - Tampilkan preview tanpa menjalankan cleanup
- `--force` - Jalankan tanpa konfirmasi
**Contoh Penggunaan:**
```bash
# Preview data yang akan di-cleanup
php artisan lpj:cleanup-inspeksi --dry-run
# Cleanup semua data (dengan konfirmasi)
php artisan lpj:cleanup-inspeksi
# Cleanup untuk permohonan tertentu
php artisan lpj:cleanup-inspeksi --permohonan-id=123 --force
# Jalankan secara sync
php artisan lpj:cleanup-inspeksi --sync --force
```
### 2. `lpj:cleanup-single-inspeksi`
Command untuk cleanup 1 permohonan dan user tertentu.
**Usage:**
```bash
php artisan lpj:cleanup-single-inspeksi <permohonan-id> <created-by> [options]
```
**Arguments:**
- `permohonan-id` - ID permohonan yang akan di-cleanup (required)
- `created-by` - ID user yang membuat data (required)
**Options:**
- `--sync` - Jalankan secara synchronous
- `--force` - Jalankan tanpa konfirmasi
**Contoh Penggunaan:**
```bash
# Cleanup untuk permohonan 123 oleh user 456
php artisan lpj:cleanup-single-inspeksi 123 456
# Jalankan secara sync tanpa konfirmasi
php artisan lpj:cleanup-single-inspeksi 123 456 --sync --force
```
### 3. `lpj:cleanup-inspeksi-status`
Command untuk mengecek status data inspeksi dan melihat statistik cleanup.
**Usage:**
```bash
php artisan lpj:cleanup-inspeksi-status [options]
```
**Options:**
- `--permohonan-id=ID` - Filter berdasarkan permohonan ID
- `--created-by=ID` - Filter berdasarkan user ID
- `--detailed` - Tampilkan detail data
**Contoh Penggunaan:**
```bash
# Lihat statistik umum
php artisan lpj:cleanup-inspeksi-status
# Filter berdasarkan permohonan
php artisan lpj:cleanup-inspeksi-status --permohonan-id=123
# Tampilkan detail data
php artisan lpj:cleanup-inspeksi-status --detailed
```
## Scheduling
Command cleanup otomatis dijalankan setiap hari jam 2 pagi dan setiap minggu. Konfigurasi scheduling ada di `LpjServiceProvider.php`.
## Monitoring
Semua aktivitas cleanup dicatat di log file:
- `storage/logs/laravel.log` - Log umum
- `storage/logs/cleanup-inspeksi.log` - Log cleanup harian
- `storage/logs/cleanup-inspeksi-weekly.log` - Log cleanup mingguan
## Alur Kerja Cleanup
1. **Identifikasi**: Cari data inspeksi yang memiliki:
- Data baru dengan `dokument_id` (tidak null)
- Data lama tanpa `dokument_id` (null)
- Sama `permohonan_id` dan `created_by`
2. **Proses**: Soft delete data lama menggunakan Laravel SoftDeletes
3. **Logging**: Catat setiap operasi untuk audit trail
4. **Transaction**: Gunakan DB transaction untuk konsistensi data
## Troubleshooting
### Command tidak muncul
Pastikan service provider sudah diregister dengan benar:
```bash
php artisan list | grep lpj
```
### Data tidak ter-cleanup
- Cek log untuk error
- Pastikan ada data yang memenuhi kriteria
- Gunakan `--dry-run` untuk preview
- Gunakan `--detailed` untuk melihat detail data
### Performance
Untuk data besar, gunakan mode queue (default) daripada `--sync`

View File

@@ -0,0 +1,63 @@
<?php
namespace Modules\Lpj\Emails;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendJadwalKunjunganEmail extends Mailable
{
/**
* ID Penilaian.
*
* @var string
*/
public $id;
/**
* Waktu Penilaian.
*
* @var string
*/
public $waktu_penilaian;
/**
* Deskripsi Penilaian.
*
* @var string
*/
public $deskripsi_penilaian;
/**
* Create a new message instance.
*
* @param array $emailData
* @return void
*/
public function __construct(array $emailData)
{
// Validasi data yang diterima
if (!isset($emailData['emailData']['id']) ||
!isset($emailData['emailData']['waktu_penilaian']) ||
!isset($emailData['emailData']['deskripsi_penilaian'])) {
throw new \InvalidArgumentException("Data email tidak lengkap.");
}
$this->id = $emailData['emailData']['id'];
$this->waktu_penilaian = $emailData['emailData']['waktu_penilaian'];
$this->deskripsi_penilaian = $emailData['emailData']['deskripsi_penilaian'];
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->subject('Jadwal Kunjungan Penilaian Resmi')
->view('lpj::emails.jadwal-kunjungan');
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace Modules\Lpj\Emails;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
// use Illuminate\Contracts\Queue\ShouldQueue;
class SendPenawaranKJPPEmail extends Mailable
{
use Queueable, SerializesModels;
// Tambahkan properti untuk data yang akan dikirimkan ke view
public $dp1;
public $penawaran;
public $permohonan;
public $villages;
public $districts;
public $cities;
public $provinces;
public $user; // Tambahkan user ke data yang dikirimkan ke view, sebagai cc dan bcc
/**
* Create a new message instance.
*/
public function __construct($dp1, $penawaran, $permohonan, $villages, $districts, $cities, $provinces, $user)
{
// Assign data yang diterima ke properti
$this->dp1 = $dp1;
$this->penawaran = $penawaran;
$this->permohonan = $permohonan;
$this->villages = $villages;
$this->districts = $districts;
$this->cities = $cities;
$this->provinces = $provinces;
$this->user = $user; // Tambahkan user ke data yang dikirimkan ke view, sebagai cc dan bcc
}
/**
* Build the message.
*/
public function build(): self
{
// Kirim data ke view
return $this->view('lpj::penawaran.kirimEmailKJPP')
->with([
'dp1' => $this->dp1,
'penawaran' => $this->penawaran,
'permohonan' => $this->permohonan,
'villages' => $this->villages,
'districts' => $this->districts,
'cities' => $this->cities,
'provinces' => $this->provinces,
'user' => $this->user // Tambahkan user ke data yang dikirimkan ke view, sebagai cc dan bcc
]);
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace Modules\Lpj\Emails;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
// use Illuminate\Contracts\Queue\ShouldQueue;
class SendPenawaranTenderEmail extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*/
public function __construct()
{
//
}
/**
* Build the message.
*/
public function build(): self
{
return $this->view('lpj::penawaran.kirimEmail');
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace Modules\Lpj\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
class BasicDataSurveyorExport implements WithColumnFormatting, WithHeadings, FromCollection, withMapping
{
protected $model;
public function __construct($model)
{
$this->model = $model;
}
public function collection()
{
return $this->model::all();
}
public function map($row)
: array
{
return [
$row->id,
$row->code,
$row->name,
$row->created_at
];
}
public function headings()
: array
{
return [
'ID',
'Code',
'Name',
'Created At'
];
}
public function columnFormats()
: array
{
return [
'A' => NumberFormat::FORMAT_NUMBER,
'D' => NumberFormat::FORMAT_DATE_DATETIME
];
}
}

View File

@@ -0,0 +1,49 @@
<?php
namespace Modules\Lpj\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Modules\Lpj\Models\CustomField;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
class CustomFieldExport implements WithColumnFormatting, WithHeadings, FromCollection, WithMapping
{
public function collection()
{
return CustomField::all();
}
public function map($row): array
{
return [
$row->id,
$row->name,
$row->type,
$row->created_at,
$row->updated_at,
];
}
public function headings(): array
{
return [
'ID',
'Name',
'Type',
'Created At',
'Updated At',
];
}
public function columnFormats(): array
{
return [
'A' => NumberFormat::FORMAT_NUMBER,
'D' => NumberFormat::FORMAT_DATE_DDMMYYYY,
'E' => NumberFormat::FORMAT_DATE_DDMMYYYY,
];
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace Modules\Lpj\app\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use Modules\Lpj\app\Models\JenisLampiran;
class JenisLampiranExport implements WithColumnFormatting, WithHeadings, FromCollection, WithMapping
{
public function collection()
{
return JenisLampiran::all();
}
public function map($row): array
{
return [
$row->id,
$row->nama,
$row->deskripsi,
$row->created_at
];
}
public function headings(): array
{
return [
'ID',
'Nama',
'Deskripsi',
'Created At'
];
}
public function columnFormats(): array
{
return [
'A' => NumberFormat::FORMAT_NUMBER,
'D' => NumberFormat::FORMAT_DATE_DATETIME
];
}
}

View File

@@ -0,0 +1,339 @@
<?php
namespace Modules\Lpj\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithStyles;
use Maatwebsite\Excel\Concerns\WithColumnWidths;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Events\AfterSheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
class KertasKerjaExport implements FromCollection, WithHeadings, WithStyles, WithColumnWidths, WithEvents
{
// use Illuminate\Contracts\View\View;
// use Maatwebsite\Excel\Concerns\FromView;
// class KertasKerjaExport implements FromView
// {
protected $data;
public function __construct($data)
{
$this->data = $data;
}
// public function view(): View
// {
// return view('lpj::component.kertas-kerja', [
// 'data' => $this->data,
// ]);
// }
public function collection()
{
// $rows = [];
// $nomor = 1;
$fields = [
'jenis_aset' => 'Jenis Aset',
'luas_tanah' => 'Luas Tanah (M²)',
'luas_bangunan' => 'Luas Bangunan (M²)',
'harga' => 'Harga Transaksi/Penawaran',
'tanggal_penawaran' => 'Tanggal Penawaran/Transaksi',
'diskon' => 'Diskon %',
'esitmasi_harga' => 'Esitmasi Harga Transaksi (Rp)',
'no_telepon' => 'Telepon Contact Person',
'nama_nara_sumbr' => 'Nama Nara Sumber',
'status_nara_sumbr' => 'Status Nara Sumber',
'waktu_transaksi' => 'Waktu Transaksi/Penawaran',
'alamat' => 'Alamat Titik Gps',
'jalan' => 'Jalan',
'desa' => 'Desa/Kelurahan',
'kecamatan' => 'Kecamatan',
'kabupaten' => 'Kabupaten',
'provinsi' => 'Provinsi',
'jarak_pembanding' => 'Jarak Pembanding dengan Objek',
'elevasi' => 'Estimasi Ranking Tanah',
'peruntukan' => 'Estiamsi Rangkin Bangunan'
];
$rows = [];
$nomor = 1;
// Add general asset information
$rows[] = ['No.', 'Uraian', 'Objek Penilaian', 'Data Pembanding 1', 'Data Pembanding 2', 'Data Pembanding 3'];
foreach ($this->data['objek'] as $key => $value) {
$rows[] = [
$nomor++,
$key,
$value,
$this->data['pembanding1'][$key] ?? '',
$this->data['pembanding2'][$key] ?? '',
$this->data['pembanding3'][$key] ?? ''
];
}
// B. Perhitungan Penyesuaian
$rows[] = [''];
$rows[] = [''];
$rows[] = ['B. Estimasi Nilai Tanah Pembanding dengan Teknik Penyisaan Tanah untuk mendapatkan per meter persegi estimasi Nilai Tanah Pembanding'];
$rows[] = ['No.','Uraian', 'Objek Penilaian', 'Data Pembanding 1', 'Data Pembanding 2', 'Data Pembanding 3'];
$nostimasi = 1;
$filedEstimasi = [
'estimasi' => 'Estimasi Biaya Pengganti Baru Bangunan (Rp)',
'estimasi_spl' => 'Estimasi Biaya Pengganti Baru SPL (Rp)',
'penyusutan' => 'Penyusutan Fisik Banguna',
'a' => 'a. rincian ttipe bangunan (MAPPI)',
'b' => 'b. umur ekonomis (MAPPI)',
'c' => 'c. estimasi Tahun tahun visual dengan mempertimbangkan renovasi',
'd' => 'd. Sehingga sisa umur efektif',
'e' => 'e. kondisi bagunan',
'f' => 'f.sehinggan penyusutan fisik',
'penyusutan_fungsi' => 'Penyusutan fungsi Bangunan (%)',
'penyusutan_ekonomi' => 'Penyusutan Ekonomi Bangunan (%)',
'total_penyusutan' => 'Total Penyusutan (%)',
'estimasi_nilai' => 'Estimasi Nilai Bangunan dan SPL (Rp)',
'estimasi_tanah' => 'Estimasi Nilai Tanah Pembanding (Rp)',
'estimasi_nilai' => 'Estimasi Nilai Tanah Pembanding (Rp)',
];
foreach ($filedEstimasi as $key => $label) {
$rows[] = [
$nostimasi++,
$label,
$this->data['estimasi'][$key] ?? '',
$this->data['estimasi1'][$key] ?? '',
$this->data['estimasi2'][$key] ?? '',
$this->data['estimasi3'][$key] ?? ''
];
}
$row[] = [''];
$row[] = [''];
$rows[] = ['INDIKASI NILAI TANAHATAS OBJEK PENILAIAN'];
$indikasi=[
'luas_tanah' => 'Luas Tanah ',
'indikasi_per' => 'INDIKASI TANAH PER M2 (RP/M2)',
'indikasi_total' => 'INDIKASI TANAH TOTAL(RP)',
'varian' => 'VARIANT(%)',
];
foreach ($indikasi as $key => $label) {
$rows[] = [
$label,
$this->data['indikasi'][$key] ?? '',
];
}
// C. Peta Lokasi
$rows[] = [''];
$rows[] = [''];
$rows[] = ['C. Peta Lokasi'];
$rows[] = [$this->data['foto_objek']['foto_objek_peta'] ?? ''];
// D. Foto Objek dan Data Pembanding
$rows[] = [''];
$rows[] = ['D. Foto Objek dan Data Pembanding'];
$rows[] = [
$this->data['foto_objek1']['foto_objek'] ?? '',
$this->data['foto_objek2']['foto_objek'] ?? '',
'', '', ''
];
// E. Foto Objek
$rows[] = [''];
$rows[] = ['E. Foto Objek'];
$rows[] = [
$this->data['foto']['foto_objek'] ?? '',
$this->data['foto']['foto_objek'] ?? '',
'', '', ''
];
return collect($rows);
}
public function headings(): array
{
return [
['KERTAS KERJA PENILAIAN'],
['Pendekatan Pasar'],
['Metode Perbandingan Data Pasar'],
['Tanggal Penilaian: ' . ($this->headerInfo['tanggal_penilaian'] ?? '')],
['Nama Pemilik Aset: ' . ($this->headerInfo['nama_pemilik'] ?? '')],
['Nama Pemberi Tugas: ' . ($this->headerInfo['nama_pemberi_tugas'] ?? '')],
['Lokasi: ' . ($this->headerInfo['lokasi_lengkap'] ?? '')],
];
}
public function registerEvents(): array
{
return [
AfterSheet::class => function (AfterSheet $event) {
// Styling untuk header utama
// Styling untuk setiap section header
$sectionRows = [10, 34, 56, 46, 52]; // Sesuaikan dengan posisi setiap section
foreach ($sectionRows as $row) {
$event->sheet->getStyle("A{$row}:F{$row}")->getFill()
->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
->getStartColor()->setRGB('E2EFDA');
}
// Merge cells untuk headers
$event->sheet->mergeCells('A1:E1');
$event->sheet->mergeCells('A2:E2');
$event->sheet->mergeCells('A4:E4');
$event->sheet->mergeCells('A5:E5');
$event->sheet->mergeCells('A6:E6');
$event->sheet->mergeCells('A7:E7');
$event->sheet->mergeCells('A8:E8');
// Alignment
$event->sheet->getStyle('A1:E8')->getAlignment()
->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_LEFT);
$this->insertImages($event->sheet);
}
];
}
public function columnWidths(): array
{
return [
'A' => 5,
'B' => 30,
'C' => 30,
'D' => 30,
'E' => 30,
'F' => 30,
];
}
public function styles(Worksheet $sheet)
{
return [
// Style for the main header
// Style for section headers
10 => ['font' => ['bold' => true]], // A. Informasi Umum
34 => ['font' => ['bold' => true]], // B. Estimasi Nilai Tanah
35 => ['font' => ['bold' => true]], // C. Peta Lokasi
57 => ['font' => ['bold' => true]], // D. Foto Objek dan Pembanding
60 => ['font' => ['bold' => true]], // E. Foto Objek
// Default styling for columns
'A:J' => [
'alignment' => ['horizontal' => 'left', 'vertical' => 'center'],
'wrapText' => true,
],
// Style for other sections (like photo and map sections)
// Style for the other headers
'A11:F11' => [
'font' => ['bold' => true],
'fill' => ['fillType' => 'solid', 'color' => ['rgb' => 'E2EFDA']],
'borders' => [
'allBorders' => [
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN
]
]
],
'A12:F31' => [
'borders' => [
'allBorders' => [
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN
]
]
],
'A35:F35' => [
'font' => ['bold' => true],
'fill' => ['fillType' => 'solid', 'color' => ['rgb' => 'E2EFDA']],
'borders' => [
'allBorders' => [
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN
]
]
],
'A35:F49' => [
'borders' => [
'allBorders' => [
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN
]
]
],
// end header
];
}
protected function insertImages($sheet)
{
ini_set('max_execution_time', '300');
$worksheet = $sheet->getDelegate();
// Insert images for pembanding1
if (!empty($this->data['pembanding1']['foto_objek'])) {
$drawing = new Drawing();
$drawing->setName('Pembanding 1');
$drawing->setDescription('Foto Objek Pembanding 1');
$drawing->setPath(storage_path('app/public/' . $this->data['pembanding1']['foto_objek'])); // Adjust path as needed
$drawing->setHeight(90);
$drawing->setCoordinates('C' . (count($this->collection()) + 2)); // Adjust coordinates as needed
$drawing->setWorksheet($worksheet);
}
// Repeat for pembanding2 and pembanding3
if (!empty($this->data['pembanding2']['foto_objek'])) {
$drawing = new Drawing();
$drawing->setName('Pembanding 2');
$drawing->setDescription('Foto Objek Pembanding 2');
$drawing->setPath(storage_path('app/public/' . $this->data['pembanding2']['foto_objek'])); // Adjust path as needed
$drawing->setHeight(90);
$drawing->setCoordinates('C' . (count($this->collection()) + 4)); // Adjust coordinates as needed
$drawing->setWorksheet($worksheet);
}
if (!empty($this->data['pembanding3']['foto_objek'])) {
$drawing = new Drawing();
$drawing->setName('Pembanding 3');
$drawing->setDescription('Foto Objek Pembanding 3');
$drawing->setPath(storage_path('app/public/' . $this->data['pembanding3']['foto_objek'])); // Adjust path as needed
$drawing->setHeight(90);
$drawing->setCoordinates('C' . (count($this->collection()) + 6)); // Adjust coordinates as needed
$drawing->setWorksheet($worksheet);
}
// Insert images for foto_objek
foreach ($this->data['foto_objek'] as $index => $foto) {
if (!empty($foto['foto_objek'])) {
$drawing = new Drawing();
$drawing->setName($foto['name_objek']);
$drawing->setDescription($foto['deskripsi_objek']);
$drawing->setPath(storage_path('app/public/' . $foto['foto_objek'])); // Adjust path as needed
$drawing->setHeight(90);
$drawing->setCoordinates('C' . (count($this->collection()) + (8 + $index * 2))); // Adjust coordinates as needed
$drawing->setWorksheet($worksheet);
}
}
}
}

View File

@@ -0,0 +1,76 @@
<?php
namespace Modules\Lpj\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Modules\Lpj\Models\LaporanAdminKredit;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
class LaporanAdminKreditExport implements WithColumnFormatting, WithHeadings, FromCollection, WithMapping
{
public function collection()
{
return LaporanAdminKredit::with('debiture')->get();
}
public function map($row): array
{
return [
$row->id,
$row->debiture->cif,
$row->debiture->name,
$row->debiture->branch->name,
$row->kode_register_t24,
$row->jenis_agunan,
$row->bukti_kepemilikan,
$row->alamat_agunan,
$row->nama_pemilik,
$row->tanggal_kunjungan,
$row->nilai_pasar_wajar,
$row->nilai_likuidasi,
$row->nama_penilai,
$row->kolektibilitas,
$row->keterangan,
$row->created_at
];
}
public function headings(): array
{
return [
'ID',
'CIF',
'Nama Debitur',
'Cabang',
'Kode Register T24',
'Jenis Agunan',
'Bukti Kepemilikan',
'Alamat Agunan',
'Nama Pemilik',
'Tanggal Kunjungan',
'Nilai Pasar Wajar',
'Nilai Likuidasi',
'Nama Penilai',
'Kolektibilitas',
'Keterangan',
'Created At'
];
}
public function columnFormats(): array
{
return [
'A' => NumberFormat::FORMAT_NUMBER,
'B' => NumberFormat::FORMAT_NUMBER,
'J' => NumberFormat::FORMAT_DATE_DDMMYYYY,
'K' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1,
'L' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1,
'N' => NumberFormat::FORMAT_TEXT, // Kolektibilitas
'O' => NumberFormat::FORMAT_TEXT, // Keterangan
'P' => NumberFormat::FORMAT_DATE_DATETIME, // Created At (moved from M to P)
];
}
}

View File

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

View File

@@ -0,0 +1,102 @@
<?php
namespace Modules\Lpj\Exports;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Modules\Lpj\Models\PermohonanPembatalan;
class LaporanPembatalanExport implements FromCollection, WithHeadings, WithMapping
{
protected $request;
public function __construct(Request $request)
{
$this->request = $request;
}
public function collection()
{
$query = PermohonanPembatalan::where('status', 'batal');
if (!Auth::user()->hasAnyRole(['administrator'])) {
$query = $query->whereHas('permohonan', function ($q) {
$q->where('branch_id', Auth::user()->branch_id);
});
}
// Apply search filter if provided
if ($this->request->has('search') && !empty($this->request->get('search'))) {
$search = $this->request->get('search');
$query->where(function ($q) use ($search) {
$q->whereHas('permohonan', function ($subq) use ($search) {
$subq->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
$subq->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%');
$subq->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
});
$q->orWhere('alasan', 'LIKE', '%' . $search . '%');
$q->orWhere('status', 'LIKE', '%' . $search . '%');
});
}
// Filter by date range if provided
if ($this->request->has('start_date') || $this->request->has('end_date')) {
$query->whereBetween('created_at', [
$this->request->get('start_date') ?? '1900-01-01',
$this->request->get('end_date') ?? now()->toDateString()
]);
}
// Filter by status if provided
if ($this->request->has('status') && !empty($this->request->get('status'))) {
$query->where('status', $this->request->get('status'));
}
// Filter by branch if provided
if ($this->request->has('branch_id') && !empty($this->request->get('branch_id'))) {
$query->whereHas('permohonan', function ($q) {
$q->where('branch_id', $this->request->get('branch_id'));
});
}
return $query->orderBy('created_at', 'desc')
->get();
}
public function headings(): array
{
return [
'No. Registrasi',
'Tanggal Permohonan',
'Tanggal Pembatalan',
'Cabang',
'Pemohon',
'Debitur',
'Alasan Pembatalan',
'Status',
'Diajukan Oleh',
'Disetujui Oleh',
'Tanggal Disetujui'
];
}
public function map($pembatalan): array
{
return [
$pembatalan->permohonan->nomor_registrasi ?? '-',
$pembatalan->permohonan->tanggal_permohonan ? date('d-m-Y', strtotime($pembatalan->permohonan->tanggal_permohonan)) : '-',
date('d-m-Y', strtotime($pembatalan->created_at)),
$pembatalan->permohonan->branch->name ?? '-',
$pembatalan->permohonan->user->name ?? '-',
$pembatalan->permohonan->debiture->name ?? '-',
$pembatalan->alasan_pembatalan,
$pembatalan->status,
$pembatalan->user->name ?? '-',
$pembatalan->authorized_by ? $pembatalan->authorizedUser->name : '-',
$pembatalan->authorized_at ? formatTanggalIndonesia(strtotime($pembatalan->authorized_at),1) : '-'
];
}
}

View File

@@ -0,0 +1,177 @@
<?php
namespace Modules\Lpj\Exports;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Illuminate\Database\Eloquent\Builder;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use Modules\Lpj\Models\Debiture;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Helpers\Lpj;
class LaporanPenilaiJaminanExport implements FromQuery, WithHeadings, WithMapping, ShouldAutoSize
{
protected $tanggalAwal;
protected $tanggalAkhir;
protected $status;
protected $selectedIds;
public function __construct($tanggalAwal = null, $tanggalAkhir = null, $status = null, $selectedIds = null)
{
$this->tanggalAwal = $tanggalAwal;
$this->tanggalAkhir = $tanggalAkhir;
$this->status = $status;
$this->selectedIds = $selectedIds;
}
public function query()
{
$query = Permohonan::query()
->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian', 'dokumenjaminan.jenisJaminan','nilaiPlafond', 'penilai', 'inspeksi']);
// Filter by date range if provided
if ($this->tanggalAwal && $this->tanggalAkhir) {
$query->whereBetween('tanggal_permohonan', [$this->tanggalAwal, $this->tanggalAkhir]);
}
$query->where('status', 'done');
// Filter by status if provided
if ($this->status) {
$types = is_array($this->status) ? $this->status : [$this->status];
$types = array_map('strtolower', $types);
$query->whereHas('penilai', function (Builder $query) use ($types) {
$query->whereIn('type_penilai', $types);
});
}
// Filter by selected IDs if provided
if ($this->selectedIds) {
$selectedIds = is_array($this->selectedIds) ? $this->selectedIds : explode(',', $this->selectedIds);
$query->whereIn('id', $selectedIds);
}
return $query;
}
public function map($row): array
{
// ambil data alamat dari inspeksi
$alamat_inspeksi = null;
if ($row->inspeksi) {
$alamat_inspeksi = json_decode($row->inspeksi->data_form, true) ?? null;
$alamat_inspeksi = $alamat_inspeksi['asset']['alamat']['sesuai'] ?? $alamat_inspeksi['asset']['alamat']['tidak sesuai'] ?? [];
}
$alamat_inspeksi = $alamat_inspeksi['address'] ?? '-';
// ambil data dari table penilai
$fieldPenilai = ['lpj', 'resume', 'memo', 'rap', 'call-report'];
$penilaiCek = null;
// Cari field yang tersedia
foreach ($fieldPenilai as $value) {
if (!empty($row->penilai->$value)) {
$penilaiCek = $row->penilai->$value;
break;
}
}
$decodePenilai = json_decode($penilaiCek, true) ?? [];
// Ambil nilai utama
$luasTanah = $decodePenilai['luas_tanah'] ?? 0;
$nilaiTanah1 = $decodePenilai['nilai_tanah_1'] ?? 0;
$luasBangunan = $decodePenilai['luas_bangunan'] ?? 0;
$nilaiBangunan1 = $decodePenilai['nilai_bangunan_1'] ?? 0;
$totalNilaiPasar = $decodePenilai['total_nilai_pasar_wajar'] ?? 0;
$likuidasi = $decodePenilai['likuidasi'] ?? 0;
// Ambil data npw_tambahan jika ada
$npwTambahan = $decodePenilai['npw_tambahan'] ?? [];
$tambahanDetails = [];
foreach ($npwTambahan as $tambahan) {
$tambahanDetails[] = sprintf(
'%s: Luas: %s, Nilai 1: %s, Nilai 2: %s',
$tambahan['name'] ?? '-',
$tambahan['luas'] ?? 0,
$tambahan['nilai_1'] ?? 0,
$tambahan['nilai_2'] ?? 0
);
}
$tambahanSummary = implode("; ", $tambahanDetails);
// Ambil data penilaian dari table penilaian
$user_penilai = $row->penilaian->userPenilai ?? null;
$user_penilai_name = null;
foreach ($user_penilai as $value) {
if ($value->role == 'penilai') {
$user_penilai_name = $value->user->name;
$nik_penilai = $value->user->nik ?? '-';
break;
}
}
return [
$row->id,
$row->nomor_registrasi,
$row->user->name,
$row->branch->name,
$row->tujuanPenilaian->name,
$row->debiture->name,
$row->penilai->type_penilai ?? '-',
$alamat_inspeksi ?? '-',
$luasTanah,
$luasBangunan,
$nilaiTanah1,
$nilaiBangunan1,
$totalNilaiPasar,
$likuidasi,
$row->laporan->created_at ?? '-',
$user_penilai_name,
$nik_penilai,
$row->created_at,
];
}
public function headings(): array
{
return [
'ID',
'Nomor Registrasi',
'User Pemohon',
'Cabang',
'Tujuan Penilaian',
'Debitur',
'Jenis Laporan',
'Lokasi Jaminan',
'Luas Tanah',
'Luas Bangunan',
'Harga Tanah',
'Harga Bangunan',
'Nilai Pasar Wajar',
'Likuidasi',
'Tanggal Laporan',
'Nama Penilai',
'Nik Penilai',
'Created At',
];
}
public function columnFormats(): array
{
return [
'A' => NumberFormat::FORMAT_NUMBER,
'C' => NumberFormat::FORMAT_DATE_DATETIME,
'K' => NumberFormat::FORMAT_DATE_DATETIME,
'N' => NumberFormat::FORMAT_DATE_DATETIME
];
}
}

View File

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

View File

@@ -0,0 +1,98 @@
<?php
namespace Modules\Lpj\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Modules\Lpj\Models\Permohonan;
use Illuminate\Support\Facades\Auth;
class LaporanPermohonanExport implements FromCollection, WithHeadings, WithMapping
{
protected $request;
public function __construct($request)
{
$this->request = $request;
}
public function collection()
{
$query = Permohonan::query();
// Apply role-based filtering
if (!Auth::user()->hasAnyRole(['administrator'])) {
$query->where('branch_id', Auth::user()->branch_id);
}
// Apply date range filter if provided
if ($this->request->has('start_date') || $this->request->has('end_date')) {
$query->whereBetween('tanggal_permohonan', [
$this->request->start_date ?? '1900-01-01',
$this->request->end_date ?? now()->toDateString()
]);
}
// Apply status filter if provided
if ($this->request->has('status') && !empty($this->request->status)) {
$query->where('status', $this->request->status);
}
// Apply branch filter if provided
if ($this->request->has('branch_id') && !empty($this->request->branch_id)) {
$query->where('branch_id', $this->request->branch_id);
}
// Apply search filter if provided
if ($this->request->has('search') && !empty($this->request->search)) {
$search = $this->request->search;
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search . '%');
$q->orWhere('status', 'LIKE', '%' . $search . '%');
});
}
// Default ordering
$query->orderBy('nomor_registrasi', 'asc');
return $query->get();
}
public function map($permohonan): array
{
return [
$permohonan->id,
$permohonan->nomor_registrasi,
$permohonan->tanggal_permohonan,
$permohonan->user ? $permohonan->user->name : '',
$permohonan->branch ? $permohonan->branch->name : '',
$permohonan->tujuanPenilaian ? $permohonan->tujuanPenilaian->name : '',
$permohonan->jenisFasilitasKredit ? $permohonan->jenisFasilitasKredit->name : '',
$permohonan->jenisPenilaian ? $permohonan->jenisPenilaian->name : '',
$permohonan->status,
];
}
public function headings(): array
{
return [
'ID',
'Nomor Registrasi',
'Tanggal Permohonan',
'Pemohon',
'Cabang',
'Tujuan Penilaian',
'Jenis Fasilitas Kredit',
'Jenis Penilaian',
'Status',
];
}
}

View File

@@ -0,0 +1,117 @@
<?php
namespace Modules\Lpj\Exports;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithStyles;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
class LaporanSlikExport implements FromQuery, WithHeadings, WithMapping, WithStyles
{
protected $query;
public function __construct($query)
{
$this->query = $query;
}
public function query()
{
return $this->query;
}
public function headings(): array
{
return [
'Sandi Bank',
'Kode Kantor',
'Kode Cabang',
'Tahun',
'Bulan',
'No Rekening',
'CIF',
'Nama Debitur',
'NPWP',
'No KTP',
'No Telp',
'Alamat',
'Kode Pos',
'Kode Kab/Kota',
'Kode Negara Domisili',
'Kode Jenis',
'Kode Sifat',
'Kode Valuta',
'Baki Debet',
'Kolektibilitas',
'Tanggal Mulai',
'Tanggal Jatuh Tempo',
'Tanggal Selesai',
'Tanggal Restrukturisasi',
'Kode Sebab Macet',
'Tanggal Macet',
'Kode Kondisi',
'Tanggal Kondisi',
'Nilai Agunan',
'Jenis Agunan',
'Kode Agunan',
'Peringkat Agunan',
'Fasilitas',
'Status Agunan',
'Tanggal Lapor',
'Status',
'Tanggal Dibuat',
];
}
public function map($laporanSlik): array
{
return [
$laporanSlik->sandi_bank,
$laporanSlik->kode_kantor,
$laporanSlik->kode_cabang,
$laporanSlik->tahun,
$laporanSlik->bulan,
$laporanSlik->no_rekening,
$laporanSlik->cif,
$laporanSlik->nama_debitur,
$laporanSlik->npwp,
$laporanSlik->no_ktp,
$laporanSlik->no_telp,
$laporanSlik->alamat,
$laporanSlik->kode_pos,
$laporanSlik->kode_kab_kota,
$laporanSlik->kode_negara_domisili,
$laporanSlik->kode_jenis,
$laporanSlik->kode_sifat,
$laporanSlik->kode_valuta,
$laporanSlik->baki_debet,
$laporanSlik->kolektibilitas,
$laporanSlik->tanggal_mulai,
$laporanSlik->tanggal_jatuh_tempo,
$laporanSlik->tanggal_selesai,
$laporanSlik->tanggal_restrukturisasi,
$laporanSlik->kode_sebab_macet,
$laporanSlik->tanggal_macet,
$laporanSlik->kode_kondisi,
$laporanSlik->tanggal_kondisi,
$laporanSlik->nilai_agunan,
$laporanSlik->jenis_agunan,
$laporanSlik->kode_agunan,
$laporanSlik->peringkat_agunan,
$laporanSlik->fasilitas,
$laporanSlik->status_agunan,
$laporanSlik->tanggal_lapor,
$laporanSlik->status,
$laporanSlik->created_at->format('d/m/Y H:i'),
];
}
public function styles(Worksheet $sheet)
{
return [
1 => ['font' => ['bold' => true]],
];
}
}

View File

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

View File

@@ -24,6 +24,7 @@
$row->id,
$row->code,
$row->name,
$row->biaya,
$row->created_at
];
}
@@ -35,6 +36,7 @@
'ID',
'Code',
'Name',
'Biaya',
'Created At'
];
}
@@ -44,7 +46,8 @@
{
return [
'A' => NumberFormat::FORMAT_NUMBER,
'D' => NumberFormat::FORMAT_DATE_DATETIME
'D' => NumberFormat::FORMAT_NUMBER_00,
'E' => NumberFormat::FORMAT_DATE_DATETIME
];
}
}

185
app/Exports/SlikExport.php Normal file
View File

@@ -0,0 +1,185 @@
<?php
namespace Modules\Lpj\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Modules\Lpj\Models\Slik;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
/**
* Export class untuk data SLIK (Sistem Layanan Informasi Keuangan)
*
* Class ini menangani export data SLIK ke format Excel dengan:
* - Mapping data sesuai struktur SLIK
* - Format kolom yang sesuai (text, number, date)
* - Header yang informatif
*/
class SlikExport implements WithColumnFormatting, WithHeadings, FromCollection, WithMapping
{
/**
* Mengambil collection data SLIK untuk di-export
*
* @return \Illuminate\Support\Collection
*/
public function collection()
{
return Slik::orderBy('created_at', 'desc')->get();
}
/**
* Mapping data SLIK untuk setiap baris dalam Excel
*
* @param \Modules\Lpj\Models\Slik $row
* @return array
*/
public function map($row): array
{
return [
$row->id, // A - ID
$row->sandi_bank, // B - Sandi Bank
$row->tahun, // C - Tahun
$row->bulan, // D - Bulan
$row->flag_detail, // E - Flag Detail
$row->kode_register_agunan, // F - Kode Register Agunan
$row->no_rekening, // G - No Rekening
$row->cif, // H - CIF
$row->kolektibilitas, // I - Kolektibilitas
$row->fasilitas, // J - Fasilitas
$row->jenis_segmen_fasilitas, // K - Jenis Segmen Fasilitas
$row->status_agunan, // L - Status Agunan
$row->jenis_agunan, // M - Jenis Agunan
$row->peringkat_agunan, // N - Peringkat Agunan
$row->lembaga_pemeringkat, // O - Lembaga Pemeringkat
$row->jenis_pengikatan, // P - Jenis Pengikatan
$row->tanggal_pengikatan, // Q - Tanggal Pengikatan
$row->nama_pemilik_agunan, // R - Nama Pemilik Agunan
$row->bukti_kepemilikan, // S - Bukti Kepemilikan
$row->alamat_agunan, // T - Alamat Agunan
$row->lokasi_agunan, // U - Lokasi Agunan
$row->nilai_agunan, // V - Nilai Agunan
$row->nilai_agunan_menurut_ljk, // W - Nilai Agunan Menurut LJK
$row->tanggal_penilaian_ljk, // X - Tanggal Penilaian LJK
$row->nilai_agunan_penilai_independen, // Y - Nilai Agunan Penilai Independen
$row->nama_penilai_independen, // Z - Nama Penilai Independen
$row->tanggal_penilaian_penilai_independen, // AA - Tanggal Penilaian Penilai Independen
$row->jumlah_hari_tunggakan, // AB - Jumlah Hari Tunggakan
$row->status_paripasu, // AC - Status Paripasu
$row->prosentase_paripasu, // AD - Prosentase Paripasu
$row->status_kredit_join, // AE - Status Kredit Join
$row->diasuransikan, // AF - Diasuransikan
$row->keterangan, // AG - Keterangan
$row->kantor_cabang, // AH - Kantor Cabang
$row->operasi_data, // AI - Operasi Data
$row->kode_cabang, // AJ - Kode Cabang
$row->nama_debitur, // AK - Nama Debitur
$row->nama_cabang, // AL - Nama Cabang
$row->flag, // AM - Flag
$row->created_at, // AN - Created At
];
}
/**
* Header kolom untuk Excel
*
* @return array
*/
public function headings(): array
{
return [
'ID',
'Sandi Bank',
'Tahun',
'Bulan',
'Flag Detail',
'Kode Register Agunan',
'No Rekening',
'CIF',
'Kolektibilitas',
'Fasilitas',
'Jenis Segmen Fasilitas',
'Status Agunan',
'Jenis Agunan',
'Peringkat Agunan',
'Lembaga Pemeringkat',
'Jenis Pengikatan',
'Tanggal Pengikatan',
'Nama Pemilik Agunan',
'Bukti Kepemilikan',
'Alamat Agunan',
'Lokasi Agunan',
'Nilai Agunan',
'Nilai Agunan Menurut LJK',
'Tanggal Penilaian LJK',
'Nilai Agunan Penilai Independen',
'Nama Penilai Independen',
'Tanggal Penilaian Penilai Independen',
'Jumlah Hari Tunggakan',
'Status Paripasu',
'Prosentase Paripasu',
'Status Kredit Join',
'Diasuransikan',
'Keterangan',
'Kantor Cabang',
'Operasi Data',
'Kode Cabang',
'Nama Debitur',
'Nama Cabang',
'Flag',
'Created At',
];
}
/**
* Format kolom untuk Excel
*
* @return array
*/
public function columnFormats(): array
{
return [
'A' => NumberFormat::FORMAT_NUMBER, // ID
'B' => NumberFormat::FORMAT_TEXT, // Sandi Bank
'C' => NumberFormat::FORMAT_TEXT, // Tahun
'D' => NumberFormat::FORMAT_TEXT, // Bulan
'E' => NumberFormat::FORMAT_TEXT, // Flag Detail
'F' => NumberFormat::FORMAT_TEXT, // Kode Register Agunan
'G' => NumberFormat::FORMAT_TEXT, // No Rekening
'H' => NumberFormat::FORMAT_TEXT, // CIF
'I' => NumberFormat::FORMAT_TEXT, // Kolektibilitas
'J' => NumberFormat::FORMAT_TEXT, // Fasilitas
'K' => NumberFormat::FORMAT_TEXT, // Jenis Segmen Fasilitas
'L' => NumberFormat::FORMAT_TEXT, // Status Agunan
'M' => NumberFormat::FORMAT_TEXT, // Jenis Agunan
'N' => NumberFormat::FORMAT_TEXT, // Peringkat Agunan
'O' => NumberFormat::FORMAT_TEXT, // Lembaga Pemeringkat
'P' => NumberFormat::FORMAT_TEXT, // Jenis Pengikatan
'Q' => NumberFormat::FORMAT_DATE_DDMMYYYY, // Tanggal Pengikatan
'R' => NumberFormat::FORMAT_TEXT, // Nama Pemilik Agunan
'S' => NumberFormat::FORMAT_TEXT, // Bukti Kepemilikan
'T' => NumberFormat::FORMAT_TEXT, // Alamat Agunan
'U' => NumberFormat::FORMAT_TEXT, // Lokasi Agunan
'V' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1, // Nilai Agunan
'W' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1, // Nilai Agunan Menurut LJK
'X' => NumberFormat::FORMAT_DATE_DDMMYYYY, // Tanggal Penilaian LJK
'Y' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1, // Nilai Agunan Penilai Independen
'Z' => NumberFormat::FORMAT_TEXT, // Nama Penilai Independen
'AA' => NumberFormat::FORMAT_DATE_DDMMYYYY, // Tanggal Penilaian Penilai Independen
'AB' => NumberFormat::FORMAT_NUMBER, // Jumlah Hari Tunggakan
'AC' => NumberFormat::FORMAT_TEXT, // Status Paripasu
'AD' => NumberFormat::FORMAT_PERCENTAGE_00, // Prosentase Paripasu
'AE' => NumberFormat::FORMAT_TEXT, // Status Kredit Join
'AF' => NumberFormat::FORMAT_TEXT, // Diasuransikan
'AG' => NumberFormat::FORMAT_TEXT, // Keterangan
'AH' => NumberFormat::FORMAT_TEXT, // Kantor Cabang
'AI' => NumberFormat::FORMAT_TEXT, // Operasi Data
'AJ' => NumberFormat::FORMAT_TEXT, // Kode Cabang
'AK' => NumberFormat::FORMAT_TEXT, // Nama Debitur
'AL' => NumberFormat::FORMAT_TEXT, // Nama Cabang
'AM' => NumberFormat::FORMAT_TEXT, // Flag
'AN' => NumberFormat::FORMAT_DATE_DATETIME, // Created At
];
}
}

View File

@@ -1,110 +1,777 @@
<?php
declare(strict_types=1);
use Carbon\Carbon;
use Modules\Lpj\Models\PenawaranDetailTender;
use Modules\Lpj\Models\PenawaranTender;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
function formatTanggalIndonesia($date)
{
$carbonDate = Carbon::parse($date);
$indonesianMonths = [
'Januari',
'Februari',
'Maret',
'April',
'Mei',
'Juni',
'Juli',
'Agustus',
'September',
'Oktober',
'November',
'Desember',
];
$month = $indonesianMonths[$carbonDate->month - 1];
return $carbonDate->format('d') . ' ' . $month . ' ' . $carbonDate->format('Y');
}
use Carbon\Carbon;
use Modules\Location\Models\City;
use Modules\Location\Models\District;
use Modules\Location\Models\Province;
use Modules\Location\Models\Village;
use Modules\Lpj\Models\CustomField;
use Modules\Lpj\Models\HolidayCalendar;
use Modules\Lpj\Models\JenisDokumen;
use Modules\Lpj\Models\Laporan;
use Modules\Lpj\Models\PenawaranDetailTender;
use Modules\Lpj\Models\PenawaranTender;
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;
/**
* 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
]);
function formatRupiah($number)
{
$number = (float) $number;
return 'Rp ' . number_format($number, 2, ',', '.');
}
// Validasi input null atau kosong
if (empty($date)) {
Log::debug('Tanggal kosong, return empty string');
return '';
}
Carbon::setLocale('id');
function formatAlamat($alamat)
{
return ($alamat->address ? $alamat->address . ', ' : '') .
(isset($alamat->village) ? $alamat->village->name . ', ' : '') .
(isset($alamat->city) ? $alamat->city->name . ', ' : '') .
(isset($alamat->province) ? $alamat->province->name . ', ' : '') .
($alamat->postal_code ?? '');
}
try {
$waktu = Carbon::parse($date);
// andy add
function checkActiveDateRangePenawaran($id)
{
$penawaran = PenawaranTender::find($id);
if (!$time) {
$result = $waktu->translatedFormat('d F Y');
Log::debug('Format tanggal berhasil', ['result' => $result]);
return $result;
}
$start_date = strtotime($penawaran->start_date);
$end_date = strtotime($penawaran->end_date);
$todays_date = strtotime(now());
$result = $waktu->translatedFormat('d F Y') . ' pukul ' . $waktu->format('H.i') . ' WIB';
Log::debug('Format tanggal dengan waktu berhasil', ['result' => $result]);
return $result;
$allow = true;
if ($todays_date >= $start_date && $todays_date <= $end_date) {
//Penawaran dibuka
$allow = true;
} else {
if ($todays_date < $start_date) {
//Penawaran Belum dibuka
$allow = true;
} else {
//Penawaran sudah ditutup
$allow = false;
} catch (Throwable $e) {
Log::warning('Gagal parse tanggal', [
'date' => $date,
'error' => $e->getMessage()
]);
// Return input as-is jika gagal parse
return (string) $date;
}
}
return $allow;
}
/**
* 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
{
Log::debug('Memulai format Rupiah', [
'number' => $number,
'decimals' => $decimals,
'withSymbol' => $withSymbol
]);
function checkKelengkapanDetailKJPP($id)
{
$allow = true;
// DB::enableQueryLog();
// detail_penawaran apakah isian biaya_penawaran, attachment, dokumen_persetujuan sudah lengkap?
$query = PenawaranDetailTender::select('id')
->where('penawaran_id', '=', $id)
->where(function ($query) {
$query->orWhere('biaya_penawaran', '', "");
$query->orWhereNull('biaya_penawaran');
// Handle null atau kosong
if ($number === null || $number === '') {
Log::debug('Number null atau kosong, return Rp 0');
return $withSymbol ? 'Rp 0' : '0';
}
$query->orWhere('attachment', '', "");
$query->orWhereNull('attachment');
// Remove dots if present
$number = str_replace('.', '', (string) $number);
$query->orWhere('dokumen_persetujuan', '', "");
$query->orWhereNull('dokumen_persetujuan');
})->get();
// $sql = DB::getQueryLog();
// 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);
if (sizeof($query) > 0) {
$allow = false;
$formatted = number_format($number, $decimals, ',', '.');
$result = $withSymbol ? 'Rp ' . $formatted : $formatted;
Log::debug('Format Rupiah berhasil', ['result' => $result]);
return $result;
}
return $allow;
}
// convert
function convertSlug($slug) {
$words = explode('-', $slug);
foreach ($words as $index => $word) {
$words[$index] = strtoupper($word);
function formatAlamat($alamat)
{
return ($alamat->address ? $alamat->address . ', ' : '') . (isset($alamat->village) ? $alamat->village->name . ', ' : '') . (isset($alamat->city) ? $alamat->city->name . ', ' : '') . (isset($alamat->province) ? $alamat->province->name . ', ' : '') . ($alamat->village->postal_code ?? '');
}
return implode(' ', $words);
}
// andy add
// andy add
function checkActiveDateRangePenawaran($id)
{
$penawaran = PenawaranTender::find($id);
$start_date = strtotime($penawaran->start_date);
$end_date = strtotime($penawaran->end_date);
$todays_date = strtotime(now());
//$todays_date = strtotime("+1 day", strtotime(now()));
$allow = true;
if ($todays_date >= $start_date && $todays_date <= $end_date) {
//Penawaran dibuka
$allow = true;
} else {
if ($todays_date < $start_date) {
//Penawaran Belum dibuka
$allow = true;
} else {
//Penawaran sudah ditutup
$allow = false;
}
}
return $allow;
}
function checkKelengkapanDetailKJPP($id)
{
$allow = true;
// DB::enableQueryLog();
// detail_penawaran apakah isian biaya_penawaran, attachment, dokumen_persetujuan sudah lengkap?
$query = PenawaranDetailTender::select('id')->where('penawaran_id', '=', $id)->where('status', '=', 1)->where(
function ($query) {
// no_proposal
$query->orWhere('no_proposal', '', "");
$query->orWhereNull('no_proposal');
// tgl_proposal
$query->orWhere('tgl_proposal', '', "");
$query->orWhereNull('tgl_proposal');
$query->orWhere('biaya_penawaran', '', "");
$query->orWhereNull('biaya_penawaran');
$query->orWhere('attachment', '', "");
$query->orWhereNull('attachment');
$query->orWhere('dokumen_persetujuan', '', "");
$query->orWhereNull('dokumen_persetujuan');
},
)->get();
if (sizeof($query) > 0) {
$allow = false;
}
return $allow;
}
// convert
function convertSlug($slug)
{
$words = explode('-', $slug);
foreach ($words as $index => $word) {
$words[$index] = strtoupper($word);
}
return implode(' ', $words);
}
// generate last penawaran.code
function onLastnumberCodePenawaran()
: string
{
// ambil code terakhir
$maxCode = PenawaranTender::max('code');
// chek data penawaran terakhir --> mengurutkan data berdasarkan kolom `created_at` secara DESC
// $penawaran = PenawaranTender::latest()->first();
$penawaran = PenawaranTender::where('code', '=', $maxCode)->first();
$code_penawaran_last = '';
// nomor di set 0001
$noUrutAkhirString = sprintf("%04s", 1);
if ($penawaran) {
$isNum = substr($maxCode, 2); // memastikan string ke 3 s/d 8 adalan numiric
$isNP = substr($maxCode, 0, 2);
if ((8 == strlen($maxCode)) && ("NP" == $isNP) && (ctype_digit($isNum))) {
$code_penawaran_last = substr($maxCode, -4);
$year_penawaran_last = Carbon::parse($penawaran->created_at)->year;
$year_now = Carbon::now()->year;
if ($year_now == $year_penawaran_last) {
$noUrutAkhirString = sprintf("%04s", abs($code_penawaran_last + 1));
}
// jika ternyata tahun tdk sama (kurang dari tahun sekarang), maka nomor di set 0001
}
}
return 'NP' . Carbon::now()->format('y') . $noUrutAkhirString;
}
// generate last penawaran.no_spk
function onLastnumberCodePenawaranSPK($jenis_laporan_code)
: string
{
// 20241124_001 ==> spk_no_core
// XXX / PJ / JKT / MONTH-ROM / FR|SR / 2024
// 001 / PJ / JKT / XI / FR / 2024
$maxCode = PenawaranTender::max('spk_no_core');
$penawaran = PenawaranTender::where('spk_no_core', '=', $maxCode)->first();
$no_spk_penawaran_last = '';
$year_penawaran_last = '';
$year_now = Carbon::now()->year;
// nomor di set 001
$noUrutAkhirString = sprintf("%03s", 1);
if ($penawaran) {
$no_spk_penawaran_last = substr($maxCode, -3);
$year_penawaran_last = substr($maxCode, 0, 4);
if ($year_now == $year_penawaran_last) {
$noUrutAkhirString = sprintf("%03s", abs($no_spk_penawaran_last + 1));
}
// jika ternyata tahun tdk sama (kurang dari tahun sekarang), maka nomor di set 001
}
$month = onRomawi(Carbon::now()->month);
$lastSPK = $noUrutAkhirString . ' / PJ / JKT / ' . $month . ' / ' . $jenis_laporan_code . ' / ' . $year_now;
return $lastSPK;
}
function onRomawi(int $bln)
: string
{
return convertToRoman($bln);
}
function penyebut($nilai)
{
$nilai = abs($nilai);
$huruf = [
"",
"satu",
"dua",
"tiga",
"empat",
"lima",
"enam",
"tujuh",
"delapan",
"sembilan",
"sepuluh",
"sebelas"
];
$temp = "";
if ($nilai < 12) {
$temp = " " . $huruf[$nilai];
} else if ($nilai < 20) {
$temp = penyebut($nilai - 10) . " belas";
} else if ($nilai < 100) {
$temp = penyebut($nilai / 10) . " puluh" . penyebut($nilai % 10);
} else if ($nilai < 200) {
$temp = " seratus" . penyebut($nilai - 100);
} else if ($nilai < 1000) {
$temp = penyebut($nilai / 100) . " ratus" . penyebut($nilai % 100);
} else if ($nilai < 2000) {
$temp = " seribu" . penyebut($nilai - 1000);
} else if ($nilai < 1000000) {
$temp = penyebut($nilai / 1000) . " ribu" . penyebut($nilai % 1000);
} else if ($nilai < 1000000000) {
$temp = penyebut($nilai / 1000000) . " juta" . penyebut($nilai % 1000000);
} else if ($nilai < 1000000000000) {
$temp = penyebut($nilai / 1000000000) . " milyar" . penyebut(fmod($nilai, 1000000000));
} else if ($nilai < 1000000000000000) {
$temp = penyebut($nilai / 1000000000000) . " trilyun" . penyebut(fmod($nilai, 1000000000000));
}
return $temp;
}
function terbilang($nilai)
{
if ($nilai < 0) {
$hasil = "minus " . trim(penyebut($nilai));
} else {
$hasil = trim(penyebut($nilai));
}
return $hasil;
}
function hitungHariKerja($tanggalMulai, $tanggalSelesai)
{
$tanggalMulai = Carbon::parse($tanggalMulai)->startOfDay();
$tanggalSelesai = Carbon::parse($tanggalSelesai)->endOfDay();
$hariKerja = 0;
$tanggalSekarang = $tanggalMulai->copy();
while ($tanggalSekarang <= $tanggalSelesai) {
// Cek apakah hari ini bukan Sabtu atau Minggu dan bukan hari libur
if (!$tanggalSekarang->isWeekend() && !in_array($tanggalSekarang->format('Y-m-d'), holidays())) {
$hariKerja++;
}
$tanggalSekarang->addDay();
}
return $hariKerja;
}
function countPermohonanForUser($userId)
{
$validStatuses = [
'assign',
'survey-completed',
'proses-laporan',
'paparan',
'proses-paparan',
'revisi-laporan',
'revisi-paparan',
'survey',
'proses-survey',
'request-reschedule',
'reschedule',
'rejected-reschedule',
'approved-reschedule',
'revisi-survey',
'revisi-pembayaran'
];
$result = Penilaian::whereHas('userPenilai', function ($query) use ($userId) {
$query->where('user_id', $userId);
})
->whereHas('permohonan', function ($query) use ($validStatuses) {
$query->whereIn('status', $validStatuses);
})
->get()
->groupBy(function ($item) {
// Pastikan mengakses properti dari model yang valid
return $item->userPenilai->first()->user_id . '-' . $item->permohonan->id;
})
->map(function ($group) {
return [
'statuses' => $group->pluck('permohonan.status')->unique()->values()->all(),
];
});
return $result->count();
}
function getMaxFileSize($jenis)
{
$jenisDokumen = JenisDokumen::where('name', $jenis)->first();
if (!$jenisDokumen) {
return 2048;
}
//konversi ke KB (1 MB = 1024 KB)
$maxSizeInKB = (int) $jenisDokumen->max_size * 1024;
return $maxSizeInKB;
}
function getUser($userId)
{
return User::find($userId);
}
function generateLpjUniqueCode($randomLength = 6)
{
$year = date('y');
$month = str_pad(date('m'), 2, '0', STR_PAD_LEFT);
$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 = sprintf('%0' . $randomLength . 'd', mt_rand(0, pow(10, $randomLength) - 1));
// Concatenate components to create the custom code
return $year . $month . $day . $randomNumber;
}
function checkRegionUserName($userId)
{
$region = TeamsUsers::where('user_id', $userId)->first();
if ($region) {
return $region->team->regions->name;
} else {
return null;
}
}
function getNomorLaporan($permohonanId, $documentId, $type = 'nomor_laporan')
{
$laporan = Laporan::where([
'permohonan_id' => $permohonanId,
'dokumen_jaminan_id' => $documentId,
])->first();
if (!$laporan) {
return $type == 'nomor_laporan' ? '-' : null;
}
return $type == 'nomor_laporan' ? $laporan->nomor_laporan : $laporan->created_at;
}
function getCustomField($param)
{
if (is_numeric($param)) {
$field = CustomField::find($param);
} else {
$field = CustomField::where(['name' => $param])->first();
}
if ($field) {
return $field;
} else {
return null;
}
}
function getWilayahName($code, $type)
{
try {
$wilayah = null;
if (!$code) {
return null;
}
switch ($type) {
case 'province':
$wilayah = Province::where('code', $code)->first();
return $wilayah ? $wilayah->name : null;
case 'city':
$wilayah = City::where('code', $code)->first();
return $wilayah ? $wilayah->name : null;
case 'district':
$wilayah = District::where('code', $code)->first();
return $wilayah ? $wilayah->name : null;
case 'village':
$wilayah = Village::where('code', $code)->first();
return $wilayah ? $wilayah->name : null;
default:
return null;
}
} catch (Exception $e) {
return null;
}
}
function formatLabel($key)
{
static $labelCache = [];
if (isset($labelCache[$key])) {
return $labelCache[$key];
}
$customLabel = CustomField::where('name', $key)->first();
$labelCache[$key] = $customLabel->label ?? ucwords(str_replace('_', ' ', $key));
return $labelCache[$key];
}
function calculateSLA($permohonan, $type)
{
if (!$type) {
return null;
}
$nilai_plafond = in_array($permohonan->nilai_plafond_id, [2, 3]);
$nilai_plafond_2 = in_array($permohonan->nilai_plafond_id, [1]);
$slaMap = [
'resume' => $nilai_plafond ? 2 : null,
'paparan' => $nilai_plafond ? 2 : null,
'standard' => $nilai_plafond ? 3 : null,
'sederhana' => $nilai_plafond ? 2 : null,
'paparan' => $nilai_plafond_2 ? 3 : null,
'rap' => 3,
'memo' => $nilai_plafond ? 1 : null
];
if ($type === 'paparan' && isset($permohonan->tujuanPenilaian->name) && $permohonan->tujuanPenilaian->name === 'rap') {
return 2;
}
return $slaMap[$type] ?? null;
}
/**
* Menghitung total nilai berdasarkan key dan jenis legalitas.
*
* @param array $detailsArray
* @param string $key
* @param int $jenisLegalitas
*
* @return int
*/
function calculateTotalLuas($detailsArray, $key, $jenisLegalitas, $defaultJenisLegalitas, $fallbackJenisLegalitas)
{
$total = 0;
if ($detailsArray) {
foreach ($detailsArray as $item) {
if (isset($item->jenis_legalitas_jaminan_id) && $item->jenis_legalitas_jaminan_id === $jenisLegalitas) {
$details = json_decode($item->details, true);
if (is_array($details)) {
foreach ($details as $detail) {
if (isset($detail[$key])) {
$total += (int) $detail[$key];
}
}
}
}
}
// Jika total masih 0, gunakan jenis jaminan ppjb
if ($total === 0) {
foreach ($detailsArray as $item) {
if (isset($item->jenis_legalitas_jaminan_id) && $item->jenis_legalitas_jaminan_id === $defaultJenisLegalitas) {
$details = json_decode($item->details, true);
if (is_array($details)) {
foreach ($details as $detail) {
if (isset($detail[$key]) && $detail[$key] !== null) {
$total += (int) $detail[$key];
}
}
}
}
}
}
// jika total masih kosong juga maka gunakan ppb
if ($total === 0 && $fallbackJenisLegalitas !== null) {
foreach ($detailsArray as $item) {
if (isset($item->jenis_legalitas_jaminan_id) && $item->jenis_legalitas_jaminan_id === $fallbackJenisLegalitas) {
$details = json_decode($item->details, true);
if (is_array($details)) {
foreach ($details as $detail) {
if (isset($detail[$key]) && $detail[$key] !== null) {
$total += (int) $detail[$key];
}
}
}
}
}
}
}
return $total > 0 ? $total : 0;
}
function ubahNomorHp($nomorHp)
{
$nomorHp = preg_replace('/\D/', '', $nomorHp);
if (strpos($nomorHp, '62') === 0) {
$nomorBaru = substr($nomorHp, 0, 5) . "xxxxx";
return '+' . $nomorBaru;
} else if (strpos($nomorHp, '0') === 0) {
$nomorBaru = substr($nomorHp, 0, 5) . "xxxxxx";
return $nomorBaru;
} else {
return "Nomor HP tidak valid";
}
}
function parsePembandingMigration($keterangan) {
$keterangan = preg_replace('/[-]{5,}/', '',$keterangan); // Hapus ------
$keterangan = preg_replace('/[.]{5,}/', '',$keterangan); // Hapus .....
$keterangan = preg_replace('/\s+/', ' ',$keterangan);
$keterangan = preg_replace('/\s*\n\s*/', "\n",$keterangan);
// Pecah teks per baris untuk diproses
$lines = explode("\n",$keterangan);
$cleaned = [];
foreach ($lines as $line) {
$line = trim($line);
if (!empty($line)) {
// Format angka dalam format Rp. 123.456.789
$line = preg_replace_callback('/Rp\.\s*([\d.,]+)/', function($matches) {
$angka = str_replace(['.', ','], '', $matches[1]);
return 'Rp. ' . number_format((int)$angka, 0, ',', '.');
}, $line);
// Jika ada tanda pagar (#), pisahkan menjadi baris baru
$line = str_replace('#', "\n#", $line);
$cleaned[] = $line;
}
}
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

@@ -4,14 +4,18 @@ namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Exception;
use Carbon\Carbon;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\Penilaian;
use Modules\Lpj\Models\TeamsUsers;
use Modules\Lpj\Models\PenilaianTeam;
use Modules\Lpj\Models\StatusPermohonan;
use Modules\Lpj\Exports\PermohonanExport;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Lpj\Models\Teams;
use Illuminate\Support\Facades\DB;
class ActivityController extends Controller
{
@@ -32,43 +36,204 @@ class ActivityController extends Controller
public function progres_activity()
{
// Ambil user yang sedang login
$user = auth()->user();
$roles = $user->load('roles');
// Ambil user yang sedang login dengan roles
$user = auth()->user()->load('roles');
// Inisialisasi regionId dan teamId sebagai null agar bisa dinamis
$regionId = null;
$teamId = null;
// Inisialisasi regionId dan teamId
$regionId = $teamId = null;
if ($roles->roles->pluck('name')->contains('senior-officer')) {
$userTeam = TeamsUsers::with('team')
->where('user_id', $user->id)
->first();
if ($user->roles->pluck('name')->contains('senior-officer')) {
$userTeam = TeamsUsers::with('team')->firstWhere('user_id', $user->id);
$regionId = $userTeam?->team->regions_id;
$teamId = $userTeam?->teams_id;
}
$teamsActivity = TeamsUsers::with(['user', 'team', 'team.regions', 'user.roles'])
->whereHas('team', function ($q) use ($regionId, $teamId) {
if ($regionId) {
$q->where('regions_id', $regionId);
}
if ($teamId) {
$q->where('id', $teamId); // Hanya tim yang sama
}
$q->when($regionId, fn ($q) => $q->where('regions_id', $regionId))
->when($teamId, fn ($q) => $q->where('id', $teamId));
})
->where('user_id', '!=', $user->id)
->whereHas('user.roles', function ($query) {
// Filter hanya peran 'surveyor' atau 'surveyor-penilai'
$query->whereIn('name', ['surveyor', 'surveyor-penilai']);
})
->whereHas('user.roles', fn ($q) => $q->whereIn('name', ['surveyor', 'surveyor-penilai','penilai']))
->get();
return view('lpj::activity.progres_activity.index', compact('teamsActivity'));
$teamId = is_array($teamId) ? $teamId : [$teamId];
$teamPenilai = Teams::with(['regions', 'teamsUsers', 'teamsUsers.user'])->whereNotIn(
'id',
$teamId
)->get();
return view('lpj::activity.progres_activity.index', compact('teamsActivity', 'teamPenilai'));
}
public function updateTeamAssingment(Request $request)
{
try {
// dd($request->all());
$validatedData = $request->validate([
'id' => 'required|integer', // penilaian_id
'team_member_id' => 'nullable|integer',
'region_id' => 'nullable|integer',
'permohonan_id' => 'required|integer',
'user_id' => 'required|integer',
'team_id' => 'required|integer',
'penugasan' => 'required|string',
], [
'team_member_id.required_without' => 'Field team harus diisi.',
'.required_without' => 'Field harus diisi.',
]);
$penilaianId = $validatedData['id'];
$teamMemberId = $validatedData['team_member_id'] ?? null;
$regionId = $validatedData['region_id'] ?? null;
$permohonanId = $validatedData['permohonan_id'];
$userId = $validatedData['user_id'];
$teamId = $validatedData['team_id'];
$penugasan = $validatedData['penugasan'];
// Cek apakah permohonan ada
$permohonan = Permohonan::findOrFail($permohonanId);
// Validasi status permohonan
// if ($permohonan->status !== 'assign' && $permohonan->status !== 'proses-survey' && $permohonan->status !== 'survey' && $permohonan->status !== 'proses-laporan') {
// return response()->json([
// 'status' => 'error',
// 'message' => 'Tidak dapat mengganti tim, status permohonan tidak memungkinkan.',
// ]);
// }
// Ambil tim berdasarkan penilaian_id dan user_id
if ($penugasan === 'sama') {
$teams = PenilaianTeam::where('penilaian_id', $penilaianId)
->where('user_id', $userId)
->get();
// Cek apakah tim ditemukan
if ($teams->isEmpty()) {
return response()->json([
'status' => 'error',
'message' => 'Data tim tidak ditemukan.',
]);
}
// Mulai transaksi
DB::beginTransaction();
$updated = false;
$status_permohonan = $permohonan->status;
// Proses update berdasarkan region_id
if ($regionId) {
foreach ($teams as $team) {
if ($team->role === 'surveyor') {
$team->update([
'team_id' => $regionId,
'user_id' => null,
'status' => $status_permohonan,
]);
$permohonan->update([
'status' => 'reassign'
]);
$updated = true;
}
if ($team->role === 'penilai') {
$team->update([
'team_id' => $regionId,
'user_id' => null,
'status' => $status_permohonan
]);
$permohonan->update([
'status' => 'reassign',
'region_id' => $regionId,
]);
$updated = true;
}
}
}
// Proses update berdasarkan team_member_id
if ($teamMemberId) {
foreach ($teams as $team) {
if ($team->role === 'surveyor' || $team->role === 'penilai') {
$team->update(['user_id' => $teamMemberId]);
$updated = true;
}
}
}
}
if ($penugasan === 'surveyor' || $penugasan === 'penilai') {
$teams = PenilaianTeam::where('penilaian_id', $penilaianId)
->where('user_id', $userId)
->where('role', $penugasan)
->first();
// Cek apakah tim ditemukan
if (!$teams) {
return response()->json([
'status' => 'error',
'message' => 'Data tim tidak ditemukan.',
]);
}
// Mulai transaksi
DB::beginTransaction();
$updated = false;
// Proses update berdasarkan region_id
if ($regionId) {
$teams->update([
'team_id' => $regionId,
'user_id' => null
]);
$permohonan->update([
'status' => $status_permohonan,
'region_id' => $regionId,
]);
$updated = true;
}
// Proses update berdasarkan team_member_id
if ($teamMemberId) {
$teams->update(['user_id' => $teamMemberId]);
$updated = true;
}
}
if ($updated) {
DB::commit();
return response()->json([
'status' => 'success',
'message' => 'Data tim berhasil diperbarui.',
]);
}
DB::rollBack();
return response()->json([
'status' => 'error',
'message' => 'Tidak ada perubahan yang dilakukan.',
]);
} catch (\Throwable $th) {
// Rollback transaksi jika terjadi error
DB::rollBack();
return response()->json([
'status' => 'error',
'message' => 'Terjadi kesalahan: ' . $th->getMessage(),
], 500);
}
}
public function senior()
{
@@ -128,10 +293,20 @@ class ActivityController extends Controller
// abort(403, 'Sorry! You are not allowed to view users.');
}
$userRole = $user->roles->pluck('name')->first();
$regionId = null;
// If user is senior-officer, get their regionId
if ($userRole === 'senior-officer') {
$userTeam = TeamsUsers::with('team')->firstWhere('user_id', $user->id);
$regionId = $userTeam?->team->regions_id;
}
// Retrieve data from the database
$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) {
@@ -150,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');
@@ -173,22 +350,39 @@ class ActivityController extends Controller
// Get filtered count
$filteredRecords = $query->count();
// Get data
$data = null;
$userRole = $user->roles[0]->name ?? null;
if (in_array($userRole, ['surveyor', 'surveyor-penilai'])) {
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian',])
->whereHas('penilaian.userPenilai', function ($q) use ($user) {
$q->where('user_id', $user->id);
})
->get();
} else {
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian'])
->get();
// Filter by region if user is senior-officer
if ($regionId) {
$query->whereHas('region', function ($q) use ($regionId) {
$q->where('region_id', $regionId);
});
}
// Filter for specific roles
if (in_array($userRole, ['surveyor', 'penilai'])) {
$query->whereHas('penilaian.userPenilai', function ($q) use ($user) {
$q->where('user_id', $user->id);
});
}
$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','nilaiPlafond'])->get();
// Calculate total pages
$pageCount = ceil($totalRecords / $request->get('size', 10));
@@ -237,10 +431,36 @@ class ActivityController extends Controller
'permohonan.debiture',
'permohonan.tujuanPenilaian',
'permohonan.debiture.documents.jenisJaminan',
'userPenilai'
'userPenilai' => function ($query) use ($id) {
$query->where('user_id', $id);
},
'permohonan.penilai',
'permohonan.approveEo',
'permohonan.approveDd',
'permohonan.approveSo',
])
->whereHas('userPenilai', function ($q) use ($id) {
$q->where('user_id', $id);
})
->whereHas('permohonan', function ($q) {
$q->whereIn('status', [
'assign',
'survey-completed',
'proses-laporan',
'paparan',
'proses-paparan',
'revisi-laporan',
'revisi-paparan',
'survey',
'proses-survey',
'request-reschedule',
'reschedule',
'rejected-reschedule',
'approved-reschedule',
'revisi-survey',
'revisi-pembayaran'
]);
});
@@ -271,6 +491,104 @@ class ActivityController extends Controller
// Ambil data dengan pagination
$data = $query->skip($offset)->take($size)->get();
$data = $data->map(function ($item) {
$jeniAsset = null;
$statusPembayaran = trim(strtolower($item->permohonan->status_bayar ?? ''));
$tujuanPenilaian = $item->permohonan->tujuanPenilaian->name ?? null;
$plafond = $item->permohonan->nilaiPlafond->name ?? null;
$now = Carbon::now();
$type_report = $item->permohonan->penilai->type ?? "";
$hari = $hariPaparan = 0;
if ($type_report == "sederhana") {
$hari = 2;
$item->paparan = 'Tidak Ada';
} else {
if ($plafond == '< 2M') {
$item->paparan = 'Tidak Ada';
$hari = 3;
} elseif ($plafond == '2 M - 5 M') {
$hari = 3;
$hariPaparan = 2;
} else {
$hari = 5;
$hariPaparan = 3;
}
}
if ($tujuanPenilaian == 'RAP') {
$hari = 2;
$hariPaparan = 2;
}
if ($item->permohonan && $item->permohonan->debiture) {
$jeniAsset = $item->permohonan->debiture->documents->first() ?? null;
}
/*$hariTambahan = 0;
if ($tujuanPenilaian == 'RAP') {
$hariTambahan = 2;
} else {
if ($statusPembayaran == 'sudah_bayar') {
$hariTambahan = 1; // H+1 untuk yang sudah bayar
} else {
$hariTambahan = 2; // H+2 untuk yang belum bayar
}
}*/
$tanggalMulai = $item->waktu_penilaian;
if ($tanggalMulai) {
if (!$tanggalMulai instanceof Carbon) {
$tanggalMulai = Carbon::parse($tanggalMulai);
}
$hariKerjaBerikutnya = hitungHariKerja($tanggalMulai->toDateString(), $tanggalMulai->copy()->addDays(1));
$hariKerjaBerikutnya = max($hariKerjaBerikutnya, 1);
$tanggalMulai = $tanggalMulai->copy()->addDays($hariKerjaBerikutnya);
// Konversi string tanggal ke objek Carbon jika belum
if (!$tanggalMulai instanceof Carbon) {
$tanggalMulai = Carbon::parse($tanggalMulai);
}
// Hitung tanggal selesai berdasarkan hari tambahan
$tanggalSelesai = $tanggalMulai->copy()->addDays($hari);
$tanggalPaparan = $tanggalMulai->copy()->addDays($hariPaparan);
// Hitung hari kerja
$hariKerja = hitungHariKerja($tanggalMulai->toDateString(), $tanggalSelesai->toDateString());
$hariKerja = max($hariKerja, $hari);
$hariKerjaPaparan = hitungHariKerja($tanggalMulai->toDateString(), $tanggalPaparan->toDateString());
$hariKerjaPaparan = max($hariKerjaPaparan, $hariPaparan);
// Set due date SLA
$dueDateSla = $tanggalMulai->copy()->addDays($hariKerja);
$dueDateSlaPaparan = $tanggalMulai->copy()->addDays($hariKerjaPaparan);
// Cek apakah sudah melewati due date
/*if ($now->greaterThan($dueDateSla)) {
$item->due_date_sla = null;
} else {
$item->due_date_sla = $dueDateSla->toDateString();
}*/
$item->due_date_sla = $dueDateSla->toDateString();
$item->paparan = $dueDateSlaPaparan->toDateString();
} else {
$item->due_date_sla = null;
$item->paparan = null;
}
return $item;
});
$filteredRecords = $data->count();
$pageCount = ceil($totalRecords / $size);

View File

@@ -0,0 +1,183 @@
<?php
namespace Modules\Lpj\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Exception;
use Modules\Lpj\Models\Debiture;
/**
* Controller untuk API pencarian debitur
* Digunakan untuk autocomplete search pada form pembayaran
*/
class DebiturController extends Controller
{
/**
* Pencarian debitur untuk autocomplete
*
* @param Request $request
* @return JsonResponse
*/
public function search(Request $request): JsonResponse
{
try {
// Log aktivitas pencarian
Log::info('API Debitur Search - Request', [
'query' => $request->get('q'),
'user_id' => Auth::id()
]);
$query = $request->get('q', '');
// Validasi minimal 2 karakter untuk pencarian
if (strlen($query) < 2) {
return response()->json([
'success' => false,
'message' => 'Minimal 2 karakter untuk pencarian',
'data' => []
], 400);
}
// Mulai database transaction
DB::beginTransaction();
try {
// Query pencarian debitur
// Asumsi tabel debitur dengan kolom: id, code, nama, alamat
$debiturs = Debiture::query()
->select('id', 'cif', 'name', 'address')
->whereAny(['cif','name'], 'LIKE', "%{$query}%")
->orderBy('name', 'asc')
->limit(20) // Batasi hasil maksimal 20
->get();
// Format data untuk TomSelect
$formattedData = $debiturs->map(function($debitur) {
return [
'id' => $debitur->id,
'kode_debitur' => $debitur->cif,
'name' => $debitur->name,
'address' => $debitur->address
];
});
DB::commit();
// Log hasil pencarian
Log::info('API Debitur Search - Success', [
'query' => $query,
'results_count' => $formattedData->count(),
'user_id' => Auth::id()
]);
return response()->json([
'success' => true,
'message' => 'Data debitur berhasil ditemukan',
'data' => $formattedData
]);
} catch (Exception $e) {
DB::rollback();
throw $e;
}
} catch (Exception $e) {
// Log error
Log::error('API Debitur Search - Error', [
'query' => $request->get('q'),
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
'user_id' => Auth::id()
]);
return response()->json([
'success' => false,
'message' => 'Terjadi kesalahan saat mencari data debitur',
'error' => config('app.debug') ? $e->getMessage() : 'Internal Server Error'
], 500);
}
}
/**
* Get detail debitur berdasarkan code
*
* @param Request $request
* @return JsonResponse
*/
public function getByCode(Request $request): JsonResponse
{
try {
$code = $request->get('code');
if (empty($code)) {
return response()->json([
'success' => false,
'message' => 'Code debitur harus diisi',
'data' => null
], 400);
}
// Log aktivitas get detail
Log::info('API Debitur GetByCode - Request', [
'code' => $code,
'user_id' => Auth::id()
]);
DB::beginTransaction();
try {
$debitur = DB::table('debitur')
->select('id', 'code', 'nama', 'alamat', 'telepon', 'email')
->where('code', $code)
->where('status', 'aktif')
->first();
if (!$debitur) {
DB::rollback();
return response()->json([
'success' => false,
'message' => 'Debitur tidak ditemukan',
'data' => null
], 404);
}
DB::commit();
Log::info('API Debitur GetByCode - Success', [
'code' => $code,
'debitur_id' => $debitur->id,
'user_id' => Auth::id()
]);
return response()->json([
'success' => true,
'message' => 'Data debitur berhasil ditemukan',
'data' => $debitur
]);
} catch (Exception $e) {
DB::rollback();
throw $e;
}
} catch (Exception $e) {
Log::error('API Debitur GetByCode - Error', [
'code' => $request->get('code'),
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
'user_id' => Auth::id()
]);
return response()->json([
'success' => false,
'message' => 'Terjadi kesalahan saat mengambil data debitur',
'error' => config('app.debug') ? $e->getMessage() : 'Internal Server Error'
], 500);
}
}
}

View File

@@ -0,0 +1,311 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Log;
use Modules\Location\Models\Province;
use Modules\Lpj\Http\Requests\BankDataRequest;
use Modules\Lpj\Models\BankData;
use Modules\Lpj\Models\Inspeksi;
use Modules\Lpj\Models\JenisJaminan;
use Modules\Lpj\Services\BankDataService;
class BankDataController extends Controller
{
protected $bankDataService;
protected $user;
public function __construct(BankDataService $bankDataService)
{
$this->bankDataService = $bankDataService;
}
public function index(Request $request)
{
$provinces = Province::all();
$jenisJaminan = JenisJaminan::all();
//insert data pembanding
$inspeksi = Inspeksi::all();
foreach ($inspeksi as $item) {
if (isset($item->data_pembanding)) {
$data_pembanding = json_decode($item->data_pembanding);
$objekPenilaian = $data_pembanding->objek_penilaian;
if (isset($objekPenilaian)) {
$_lat = $objekPenilaian->kordinat_lat;
$_lng = $objekPenilaian->kordinat_lng;
if (!empty($_lat) && !empty($_lng) && $_lng !== null && $_lat !== null && $_lat !== '' && $_lng !== '') {
$_lat = floatval($_lat);
$_lng = floatval($_lng);
if ($_lat >= -90 && $_lat <= 90 && $_lng >= -180 && $_lng <= 180) {
$_data = [
'address' => $objekPenilaian->address,
'village_code' => $objekPenilaian->village_code,
'district_code' => $objekPenilaian->district_code,
'city_code' => $objekPenilaian->city_code,
'province_code' => $objekPenilaian->province_code,
'tahun' => $item->created_at->format('Y'),
//
'luas_tanah' => isset($objekPenilaian->luas_tanah) && is_numeric($objekPenilaian->luas_tanah) ? $objekPenilaian->luas_tanah : 0,
'luas_bangunan' => isset($objekPenilaian->luas_bangunan) && is_numeric($objekPenilaian->luas_bangunan) ? $objekPenilaian->luas_bangunan : 0,
//
'tahun_bangunan' => isset($objekPenilaian->tahun_bangunan) && is_numeric($objekPenilaian->tahun_bangunan) ? $objekPenilaian->tahun_bangunan : 0,
//
'harga' => isset($objekPenilaian->harga) && is_numeric($objekPenilaian->harga) ? $objekPenilaian->harga : 0,
'harga_diskon' => isset($objekPenilaian->harga_diskon) && is_numeric($objekPenilaian->harga_diskon) ? $objekPenilaian->harga_diskon : 0,
'diskon' => isset($objekPenilaian->diskon) && is_numeric(str_replace(',', '.', $objekPenilaian->diskon)) ? str_replace(',', '.', $objekPenilaian->diskon) : 0,
'total' => isset($objekPenilaian->total) && is_numeric($objekPenilaian->total) ? $objekPenilaian->total : 0,
'harga_penawaran' => isset($objekPenilaian->harga_penawaran) && is_numeric($objekPenilaian->harga_penawaran) ? $objekPenilaian->harga_penawaran : 0,
'nama_nara_sumber' => $objekPenilaian->nama_nara_sumber,
'peruntukan' => $objekPenilaian->peruntukan ?? "",
//
'penawaran' => $objekPenilaian->penawaran ?? "",
//
'telepon' => $objekPenilaian->telepon ?? "",
'hak_properti' => $objekPenilaian->hak_properti ?? "",
'jenis_aset' => $objekPenilaian->jenis_aset ?? "",
'foto_objek' => $objekPenilaian->foto_objek ?? "",
'tanggal' => $objekPenilaian->tanggal ?? null,
'kategori' => 'penilaian',
];
BankData::updateOrCreate(
[
'kordinat_lat' => $_lat,
'kordinat_lng' => $_lng,
'kategori' => 'penilaian'
],
$_data
);
}
} else {
// Invalid coordinates
Log::warning("Invalid coordinates: Lat: $_lat, Lng: $_lng");// Do something to handle this situation, such as logging an error or skipping the record
}
}
foreach ($data_pembanding->data_pembanding as $dataPembanding) {
$lat = $dataPembanding->kordinat_lat;
$lng = $dataPembanding->kordinat_lng;
if (!empty($lat) && !empty($lng) && $lng !== null && $lat !== null && $lat !== '' && $lng !== '') {
$lat = floatval($lat);
$lng = floatval($lng);
if ($lat >= -90 && $lat <= 90 && $lng >= -180 && $lng <= 180) {
$data = [
'address' => $dataPembanding->address,
'village_code' => $dataPembanding->village_code,
'district_code' => $dataPembanding->district_code,
'city_code' => $dataPembanding->city_code,
'province_code' => $dataPembanding->province_code,
'tahun' => isset($dataPembanding->tahun) && is_numeric($dataPembanding->tahun) ? $dataPembanding->tahun : 0,
'luas_tanah' => isset($dataPembanding->luas_tanah) && is_numeric($dataPembanding->luas_tanah) ? $dataPembanding->luas_tanah : 0,
'luas_bangunan' => isset($dataPembanding->luas_bangunan) && is_numeric($dataPembanding->luas_bangunan) ? $dataPembanding->luas_bangunan : 0,
'tahun_bangunan' => isset($dataPembanding->tahun_bangunan) && is_numeric($dataPembanding->tahun_bangunan) ? $dataPembanding->tahun_bangunan : 0,
'harga' => isset($dataPembanding->harga) && is_numeric($dataPembanding->harga) ? $dataPembanding->harga : 0,
'harga_diskon' => isset($dataPembanding->harga_diskon) && is_numeric($dataPembanding->harga_diskon) ? $dataPembanding->harga_diskon : 0,
'diskon' => isset($dataPembanding->diskon) && is_numeric(str_replace(',', '.', $dataPembanding->diskon)) ? str_replace(',', '.', $dataPembanding->diskon) : 0,
'total' => isset($dataPembanding->total) && is_numeric($dataPembanding->total) ? $dataPembanding->total : 0,
'harga_penawaran' => isset($dataPembanding->harga_penawaran) && is_numeric($dataPembanding->harga_penawaran) ? $dataPembanding->harga_penawaran : 0,
'nama_nara_sumber' => $dataPembanding->nama_nara_sumber,
'peruntukan' => $dataPembanding->peruntukan,
'penawaran' => $dataPembanding->penawaran,
'telepon' => $dataPembanding->telepon,
'hak_properti' => $dataPembanding->hak_properti,
'jenis_aset' => $dataPembanding->jenis_aset,
'foto_objek' => $dataPembanding->foto_objek,
'tanggal' => $dataPembanding->tanggal,
'kategori' => 'data_pembanding',
];
BankData::updateOrCreate(
[
'kordinat_lat' => $lat,
'kordinat_lng' => $lng,
'kategori' => 'data_pembanding'
],
$data
);
}
} else {
// Invalid coordinates
Log::warning("Invalid coordinates: Lat: $lat, Lng: $lng");// Do something to handle this situation, such as logging an error or skipping the record
}
}
}
}
return view('lpj::bank-data.index', compact('provinces', 'jenisJaminan'));
}
public function create()
{
return view('lpj::bank-data.create');
}
public function store(BankDataRequest $request)
{
$data = $request->validated();
$bankData = $this->bankDataService->createBankData($data);
return redirect()
->route('lpj.bank-data.show', $bankData->id)
->with('success', 'Bank data created successfully.');
}
public function show($id)
{
$bankData = $this->bankDataService->findBankData($id);
return view('lpj::bank-data.show', compact('bankData'));
}
public function edit($id)
{
$bankData = $this->bankDataService->findBankData($id);
return view('lpj::bank-data.edit', compact('bankData'));
}
public function update(BankDataRequest $request, $id)
{
$data = $request->validated();
$bankData = $this->bankDataService->updateBankData($id, $data);
return redirect()
->route('lpj.bank-data.show', $bankData->id)
->with('success', 'Bank data updated successfully.');
}
public function destroy($id)
{
$this->bankDataService->deleteBankData($id);
return redirect()->route('lpj.bank-data.index')->with('success', 'Bank data deleted successfully.');
}
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('bank-data.view')) {
//abort(403, 'Sorry! You are not allowed to view bank data.');
}
// Retrieve data from the database
$query = BankData::query();
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$search = json_decode($search, true);
if (is_array($search)) {
if ($search['province_code']) {
$query->ofProvince($search['province_code']);
}
if ($search['kategori']) {
$query->where('kategori', $search['kategori']);
}
if ($search['city_code']) {
$query->ofCity($search['city_code']);
}
if ($search['district_code']) {
$query->ofDistrict($search['district_code']);
}
if ($search['village_code']) {
$query->ofVillage($search['village_code']);
}
if ($search['jenis_asset']) {
$query->ofAssetType($search['jenis_asset']);
}
if ($search['tahun']) {
$query->where('tahun', $search['tahun']);
}
if ($search['start_date'] && $search['end_date']) {
$query->betweenDates($search['start_date'], $search['end_date']);
}
} else {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('jenis_aset', 'LIKE', '%' . $search . '%');
});
}
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->get();
// Format the data as needed
$formattedData = $data->map(function ($item) {
return [
'id' => $item->id,
'jenis_aset' => $item->jenis_aset,
'tanggal' => $item->tanggal ? $item->tanggal->format('d-m-Y') : '-',
'tahun' => $item->tahun,
'luas_tanah' => $item->luas_tanah,
'luas_bangunan' => $item->luas_bangunan,
'harga' => $item->harga,
'sumber' => $item->kategori ? ucwords(str_replace('_', ' ', $item->kategori)) : '-',
'kategori' => $item->kategori ?? 'data_pembanding',
'nilai_pasar' => $item->nilai_pasar,
'location' => $item->kordinat_lat . ', ' . $item->kordinat_lng,
'address' => formatAlamat($item),
'photos' => json_decode($item->foto_objek, true) ?: [$item->foto_objek],
// Add more fields as needed
];
});
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = $request->get('page', 1);
// Ensure current page doesn't exceed page count
$currentPage = min($currentPage, $pageCount);
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $formattedData,
]);
}
}

View File

@@ -0,0 +1,209 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Exception;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Lpj\Imports\BucokImport;
use Modules\Lpj\Models\Bucok;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
/**
* Controller untuk mengelola data Bucok
*
* @package Modules\Lpj\Http\Controllers
*/
class BucokController extends Controller
{
public $user;
/**
* Menampilkan halaman index bucok
*
* @return \Illuminate\View\View
*/
public function index()
{
return view('lpj::bucok.index');
}
/**
* Menampilkan detail bucok
*
* @param int $id
* @return \Illuminate\View\View
*/
public function show($id)
{
$bucok = Bucok::findOrFail($id);
return view('lpj::bucok.show', compact('bucok'));
}
/**
* Data untuk datatables dengan server-side processing
*
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('bucok.view')) {
// abort(403, 'Sorry! You are not allowed to view bucok.');
}
// Retrieve data from the database
$query = Bucok::query();
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('nomor_tiket', 'LIKE', "%$search%")
->orWhere('deskripsi', 'LIKE', "%$search%")
->orWhere('nomor_coa', 'LIKE', "%$search%")
->orWhere('nama_coa', 'LIKE', "%$search%")
->orWhere('cost_center', 'LIKE', "%$search%")
->orWhere('nama_sub_direktorat', 'LIKE', "%$search%")
->orWhere('nama_direktorat_cabang', 'LIKE', "%$search%")
->orWhere('penyelesaian', 'LIKE', "%$search%")
->orWhere('keterangan_gantung', 'LIKE', "%$search%");
});
}
// Apply date range filter
if ($request->has('start_date') && !empty($request->get('start_date'))) {
$query->whereDate('tanggal', '>=', $request->get('start_date'));
}
if ($request->has('end_date') && !empty($request->get('end_date'))) {
$query->whereDate('tanggal', '<=', $request->get('end_date'));
}
// Apply year filter
if ($request->has('year') && !empty($request->get('year'))) {
$query->byYear($request->get('year'));
}
// Apply month filter
if ($request->has('month') && !empty($request->get('month'))) {
$query->byMonth($request->get('month'));
}
// Apply cost center filter
if ($request->has('cost_center') && !empty($request->get('cost_center'))) {
$query->byCostCenter($request->get('cost_center'));
}
// Apply completion status filter
if ($request->has('completion_status') && $request->get('completion_status') !== '') {
$isCompleted = $request->get('completion_status') == '1';
$query->byCompletionStatus($isCompleted);
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField', 'created_at');
$query->orderBy($column, $order);
} else {
$query->orderBy('created_at', 'desc');
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page with relationships
$data = $query->get();
// Transform data untuk datatables
$transformedData = $data->map(function ($item) {
return [
'id' => $item->id,
'no' => $item->no,
'tanggal' => $item->tanggal ? dateFormat($item->tanggal,true) : '-',
'bulan' => $item->bulan,
'tahun' => $item->tahun,
'nomor_tiket' => $item->nomor_tiket,
'nomor_coa' => $item->nomor_coa,
'nama_coa' => $item->nama_coa,
'deskripsi' => $item->deskripsi,
'nominal' => $item->nominal_formatted,
'penyelesaian' => $item->penyelesaian,
'umur_aging' => $item->umur_aging,
'cost_center' => $item->cost_center,
'nama_sub_direktorat' => $item->nama_sub_direktorat,
'nama_direktorat_cabang' => $item->nama_direktorat_cabang,
'tanggal_penyelesaian' => $item->tanggal_penyelesaian ? dateFormat($item->tanggal_penyelesaian,true) : '-',
'nominal_penyelesaian' => $item->nominal_penyelesaian_formatted,
'status_penyelesaian' => $item->status_penyelesaian,
'status_badge' => $item->status_badge,
'created_by' => $item->creator?->name ?? '-',
'created_at' => dateFormat($item->created_at,true)
];
});
// Calculate the page count
$pageCount = ceil($totalRecords / ($request->get('size', 10)));
// Calculate the current page number
$currentPage = $request->get('page', 1);
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $transformedData,
]);
}
/**
* Import data bucok dari Excel
*
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function import(Request $request)
{
$request->validate([
'file' => 'required|mimes:xlsx,xls,csv|max:10240' // Max 10MB
]);
DB::beginTransaction();
try {
Log::info('Importing Bucok data', ['user_id' => Auth::id(), 'filename' => $request->file('file')->getClientOriginalName()]);
$import = new BucokImport();
Excel::import($import, $request->file('file'));
$statistics = $import->getImportStatistics();
DB::commit();
Log::info('Bucok data imported successfully', ['user_id' => Auth::id()]);
return redirect()->back()->with('success', 'Data Bucok berhasil diimport. Total: ' . $statistics['total_processed'] . ', Created: ' . $statistics['created'] . ', Updated: ' . $statistics['updated'] . ', Skipped: ' . $statistics['skipped'] . ', Errors: ' . $statistics['errors']);
} catch (Exception $e) {
DB::rollback();
Log::error('Failed to import Bucok data', ['error' => $e->getMessage(), 'user_id' => Auth::id()]);
return redirect()->back()->with('error', 'Gagal import data: ' . $e->getMessage());
}
}
}

View File

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

View File

@@ -0,0 +1,153 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Exception;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Lpj\Exports\CustomFieldExport;
use Modules\Lpj\Http\Requests\CustomFieldRequest;
use Modules\Lpj\Models\CustomField;
class CustomFieldController extends Controller
{
public $user;
public function index()
{
return view('lpj::custom_fields.index');
}
public function store(CustomFieldRequest $request)
{
$validate = $request->validated();
if ($validate) {
try {
// Save to database
CustomField::create($validate);
return redirect()
->route('basicdata.custom-field.index')
->with('success', 'Custom Field created successfully');
} catch (Exception $e) {
return redirect()
->route('basicdata.custom-field.create')
->with('error', $e->getMessage());
}
}
}
public function create()
{
$urutan_prioritas = CustomField::max('urutan_prioritas')+1;
return view('lpj::custom_fields.create', compact('urutan_prioritas'));
}
public function edit($id)
{
$customField = CustomField::find($id);
$urutan_prioritas = $customField->urutan_prioritas ?? CustomField::max('urutan_prioritas')+1;
return view('lpj::custom_fields.create', compact('customField', 'urutan_prioritas' ));
}
public function update(CustomFieldRequest $request, $id)
{
$validate = $request->validated();
if ($validate) {
try {
// Update in database
$customField = CustomField::find($id);
$customField->update($validate);
return redirect()
->route('basicdata.custom-field.index')
->with('success', 'Custom Field updated successfully');
} catch (Exception $e) {
return redirect()
->route('basicdata.custom-field.edit', $id)
->with('error', 'Failed to update custom field');
}
}
}
public function destroy($id)
{
try {
// Delete from database
$customField = CustomField::find($id);
$customField->delete();
echo json_encode(['success' => true, 'message' => 'Custom Field deleted successfully']);
} catch (Exception $e) {
echo json_encode(['success' => false, 'message' => 'Failed to delete custom field']);
}
}
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('custom_fields.view')) {
//abort(403, 'Sorry! You are not allowed to view custom fields.');
}
// Retrieve data from the database
$query = CustomField::query();
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('name', 'LIKE', "%$search%");
$q->orWhere('label', 'LIKE', "%$search%");
$q->orWhere('type', 'LIKE', "%$search%");
});
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->get();
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = 0 + 1;
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
public function export()
{
return Excel::download(new CustomFieldExport, 'custom_fields.xlsx');
}
}

View File

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

View File

@@ -0,0 +1,36 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Modules\Lpj\Services\DashboardService;
class DashboardController extends Controller
{
public $dashboardService;
public function __construct(DashboardService $dashboardService)
{
$this->dashboardService = $dashboardService;
}
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
// nilai default
$start_date = $request->input('start_date', now()->startOfYear()->format('Y-m-d'));
$end_date = $request->input('end_date', now()->format('Y-m-d'));
$validate = $request->validate([
'start_date' => 'nullable|date_format:Y-m-d',
'end_date' => 'nullable|date_format:Y-m-d',
]);
$dashboard = $this->dashboardService->getDashboardData($start_date, $end_date);
// dd($dashboard);
return view('lpj::dashboard.index', compact('dashboard'));
}
}

View File

@@ -19,6 +19,7 @@
use Modules\Lpj\Models\JenisJaminan;
use Modules\Lpj\Models\JenisLegalitasJaminan;
use Modules\Lpj\Models\PemilikJaminan;
use Illuminate\Support\Facades\Auth;
class DebitureController extends Controller
{
@@ -93,13 +94,29 @@
public function destroy($id)
{
try {
// Delete from database
// Periksa apakah pengguna adalah administrator
if (!auth()->user()->hasRole('administrator')) {
return response()->json(['success' => false, 'message' => 'Hanya administrator yang dapat menghapus debitur'], 403);
}
// Temukan debitur
$debitur = Debiture::find($id);
if (!$debitur) {
return response()->json(['success' => false, 'message' => 'Debitur tidak ditemukan'], 404);
}
// Periksa apakah debitur memiliki permohonan aktif
if ($debitur->permohonan()->exists()) {
return response()->json(['success' => false, 'message' => 'Tidak dapat menghapus debitur yang masih memiliki permohonan aktif'], 400);
}
// Hapus dari database
$debitur->delete();
echo json_encode(['success' => true, 'message' => 'Debitur deleted successfully']);
return response()->json(['success' => true, 'message' => 'Debitur berhasil dihapus']);
} catch (Exception $e) {
echo json_encode(['success' => false, 'message' => 'Failed to delete debitur']);
return response()->json(['success' => false, 'message' => 'Gagal menghapus debitur: ' . $e->getMessage()], 500);
}
}
@@ -112,6 +129,10 @@
// Retrieve data from the database
$query = Debiture::query();
if (!Auth::user()->hasAnyRole(['administrator','admin'])) {
$query = $query->where('branch_id', Auth::user()->branch_id);
}
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
@@ -151,7 +172,7 @@
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->with('branch')->get();
$data = $query->with(['branch','permohonan'])->get();
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));

View File

@@ -4,15 +4,19 @@
use App\Http\Controllers\Controller;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\UploadedFile;
use Log;
use Modules\Location\Models\City;
use Modules\Location\Models\District;
use Modules\Location\Models\Province;
use Modules\Location\Models\Village;
use Modules\Lpj\Http\Requests\DokumenJaminanRequest;
use Modules\Lpj\Models\CustomField;
use Modules\Lpj\Models\Debiture;
use Modules\Lpj\Models\DetailDokumenJaminan;
use Modules\Lpj\Models\DokumenJaminan;
@@ -20,6 +24,7 @@
use Modules\Lpj\Models\JenisJaminan;
use Modules\Lpj\Models\JenisLegalitasJaminan;
use Modules\Lpj\Models\PemilikJaminan;
use Modules\Lpj\Models\Permohonan;
use ZipArchive;
class DokumenJaminanController extends Controller
@@ -31,6 +36,13 @@
{
$debitur = Debiture::find($id);
$documents = DokumenJaminan::with('pemilik', 'detail')->where('debiture_id', $id)->get();
if (request()->get('permohonan_id') !== null) {
$permohonan_id = request()->get('permohonan_id');
$documents = DokumenJaminan::with('pemilik', 'detail')
->where('debiture_id', $id)
->where('permohonan_id', $permohonan_id)
->get();
}
return view(
'lpj::debitur.edit',
@@ -79,6 +91,7 @@
'jenis_legalitas_jaminan_id' => $value,
'name' => $request->name[$key],
'keterangan' => $request->keterangan[$key],
'details' => isset($request->custom_field[$key]) ? json_encode($request->custom_field[$key]) : ''
];
$dokumenJaminan = [];
@@ -92,7 +105,7 @@
$file_name,
);
$dokumenJaminan[] = 'jaminan/' . $debitur->id . '/' . $document->id . '/' . $file_name;
$dokumenNomor[] = $request->dokumen_nomor[$key][$index] ?? '';
$dokumenNomor[] = $request->dokumen_nomor[$key][$index] ?? '-';
}
}
}
@@ -107,13 +120,13 @@
}
DB::commit();
return redirect()->route('debitur.jaminan.index', $id)->with(
return redirect()->route('debitur.jaminan.index',['id'=>$id,'pemrohonan_id' => $validate['permohonan_id'] ])->with(
'success',
'Dokumen Jaminan berhasil ditambahkan',
);
} catch (Exception $e) {
DB::rollBack();
return redirect()->route('debitur.jaminan.index', $id)->with('error', 'ggl' . $e->getMessage());
return redirect()->route('debitur.jaminan.create',['id'=>$id,'pemrohonan_id' => $validate['permohonan_id'] ])->with('error', $e->getMessage());
}
}
}
@@ -126,7 +139,10 @@
$jenisLegalitasJaminan = JenisLegalitasJaminan::all();
$pemilikJaminan = PemilikJaminan::where('debiture_id', $id)->get();
$hubunganPemilik = HubunganPemilikJaminan::all();
$permohonan = null;
if(request()->get('permohonan_id')) {
$permohonan = Permohonan::where('id', request()->get('permohonan_id'))->first();
}
return view(
'lpj::debitur.jaminan',
compact(
@@ -136,6 +152,7 @@
'jenisLegalitasJaminan',
'pemilikJaminan',
'hubunganPemilik',
'permohonan'
),
);
}
@@ -145,7 +162,6 @@
$debitur = Debiture::find($id);
$validate = $request->validated();
if ($validate) {
try {
DB::beginTransaction();
@@ -234,67 +250,119 @@
'jenis_legalitas_jaminan_id' => $value,
'name' => $request->name[$key],
'keterangan' => $request->keterangan[$key],
'details' => isset($request->custom_field[$key]) ? json_encode(array_values($request->custom_field[$key])) : ''
];
$dokumenJaminan = [];
$dokumenNomor=[];
$dokumenNomor = [];
if (isset($request->dokumen_jaminan[$key]) && is_array($request->dokumen_jaminan[$key])) {
foreach ($request->dokumen_jaminan[$key] as $index => $file) {
if ($file) {
if ($file instanceof \Illuminate\Http\UploadedFile) {
// Jika file baru diupload
$file_name = $file->getClientOriginalName();
$file->storeAs(
'public/jaminan/' . $debitur->id . '/' . $document->id . '/',
$file_name,
);
$dokumenJaminan[] = 'jaminan/' . $debitur->id . '/' . $document->id . '/' . $file_name;
$dokumenNomor[] = $request->dokumen_nomor[$key][$index] ?? '';
} elseif (is_string($file) && !empty($file)) {
// Jika file tidak diubah, gunakan path yang sudah ada
$dokumenJaminan[] = $file;
} else {
// Jika file kosong atau null, tambahkan placeholder atau skip
$dokumenJaminan[] = null; // atau skip dengan continue;
}
// Selalu update dokumen_nomor, baik file diubah atau tidak
$dokumenNomor[] = $request->dokumen_nomor[$key][$index] ?? '-';
}
}
// Setelah loop, periksa apakah ada dokumen yang dihapus
$existingDetail = $existingDetails->get($request->detail_dokumen_jaminan_id[$key] ?? null);
if ($existingDetail) {
$existingDokumen = json_decode($existingDetail->dokumen_jaminan, true) ?? [];
$existingNomor = json_decode($existingDetail->dokumen_nomor, true) ?? [];
$newDokumenJaminan = [];
$newDokumenNomor = [];
$allFilesDeleted = true;
foreach ($existingDokumen as $index => $existingFile) {
if (isset($request->dokumen_jaminan[$key][$index])) {
$allFilesDeleted = false;
$file = $request->dokumen_jaminan[$key][$index];
if ($file instanceof \Illuminate\Http\UploadedFile) {
// File baru diupload
$file_name = $file->getClientOriginalName();
$file->storeAs('public/jaminan/' . $debitur->id . '/' . $document->id . '/', $file_name);
$newDokumenJaminan[] = 'jaminan/' . $debitur->id . '/' . $document->id . '/' . $file_name;
$newDokumenNomor[] = $request->dokumen_nomor[$key][$index] ?? '-';
} elseif (is_string($file) && !empty($file)) {
// File tidak diubah
$newDokumenJaminan[] = $existingFile;
$newDokumenNomor[] = $request->dokumen_nomor[$key][$index] ?? $existingNomor[$index];
}
} else {
// File dihapus, hapus dari storage jika ada
if (Storage::exists('public/' . $existingFile)) {
Storage::delete('public/' . $existingFile);
}
}
}
// Tambahkan file baru yang mungkin ditambahkan
foreach ($request->dokumen_jaminan[$key] ?? [] as $index => $file) {
if ($file instanceof UploadedFile) {
$allFilesDeleted = false;
$file_name = $file->getClientOriginalName();
$path = 'jaminan/' . $debitur->id . '/' . $document->id . '/' . $file_name;
if (!in_array($path, $newDokumenJaminan)) {
$file->storeAs('public/' . dirname($path), $file_name);
$newDokumenJaminan[] = $path;
$newDokumenNomor[] = $request->dokumen_nomor[$key][$index] ?? '-';
}
} elseif (is_string($file) && !empty($file) && !in_array($file, $newDokumenJaminan)) {
$allFilesDeleted = false;
$newDokumenJaminan[] = $file;
$newDokumenNomor[] = $request->dokumen_nomor[$key][$index] ?? '-';
}
}
if ($allFilesDeleted) {
$dokumenJaminan = [];
$dokumenNomor = [];
} else {
$dokumenJaminan = $newDokumenJaminan;
$dokumenNomor = $newDokumenNomor;
}
}
if (!empty($dokumenJaminan)) {
$detailData['dokumen_jaminan'] = json_encode($dokumenJaminan);
$detailData['dokumen_nomor'] = json_encode($dokumenNomor);
$detailData['dokumen_nomor'] = json_encode($dokumenNomor);
} else if(empty($dokumenJaminan)){
$detailData['dokumen_jaminan'] = null;
$detailData['dokumen_nomor'] = null;
}
if (isset($request->detail_dokumen_jaminan_id[$key])) {
$detailId = $request->detail_dokumen_jaminan_id[$key];
$detailDocument = $existingDetails->get($detailId);
if ($detailDocument) {
// Merge new files with existing ones
if (!empty($dokumenJaminan)) {
$existingFiles = json_decode(
$detailDocument->dokumen_jaminan,
true,
) ?: [];
$existingNomor = json_decode(
$detailDocument->dokumen_nomor,
true,
) ?: [];
$mergedFiles = array_merge($existingFiles, $dokumenJaminan);
$mergedNomor = array_merge($existingNomor, $dokumenNomor);
$detailData['dokumen_jaminan'] = json_encode($mergedFiles);
$detailData['dokumen_nomor'] = json_encode($mergedNomor);
}
$detailDocument->update($detailData);
$existingDetails->forget($detailId);
}
$detailDocument->update($detailData);
} else {
DetailDokumenJaminan::create($detailData);
}
}
}
// Delete any remaining existing details that weren't updated
foreach ($existingDetails as $detail) {
$files = json_decode($detail->dokumen_jaminan, true) ?: [];
foreach ($files as $file) {
Storage::delete('public/' . $file);
}
$detail->delete();
}
DB::commit();
return redirect()->route('debitur.jaminan.index', $id)->with(
'success',
@@ -310,7 +378,8 @@
public function edit(
$id,
$jaminan,
) {
)
{
$document = DokumenJaminan::find($jaminan);
$details = DetailDokumenJaminan::where('dokumen_jaminan_id', $document->id)->get();
@@ -324,19 +393,25 @@
$jenisJaminan = JenisJaminan::all();
$jenisLegalitasJaminan = JenisLegalitasJaminan::all();
$_jenisJaminan = JenisJaminan::find($document->jenis_jaminan_id);
$legalitasJaminan = json_decode($_jenisJaminan->jenis_legalitas_jaminan_id, true);
$_jenisJaminan = JenisJaminan::find($document->jenis_jaminan_id);
$currentLegalitasJaminan = JenisLegalitasJaminan::whereIn(
'id',
$document->detail->pluck('jenis_legalitas_jaminan_id')->toArray(),
)->get();
$legalitas = '';
if ($_jenisJaminan) {
$legalitasJaminan = json_decode($_jenisJaminan->jenis_legalitas_jaminan_id, true);
$currentLegalitasJaminan = JenisLegalitasJaminan::whereIn(
'id',
$document->detail->pluck('jenis_legalitas_jaminan_id')->toArray(),
)->get();
// Remove values from $legalitasJaminan that are in $currentLegalitasJaminan
$legalitasJaminan = array_diff($legalitasJaminan, $currentLegalitasJaminan->pluck('code')->toArray());
// Remove values from $legalitasJaminan that are in $currentLegalitasJaminan
$legalitasJaminan = is_array($legalitasJaminan)
? array_diff($legalitasJaminan, $currentLegalitasJaminan->pluck('code')->toArray())
: [];
$legalitas = JenisLegalitasJaminan::whereIn('code', $legalitasJaminan)->get();
$legalitas = JenisLegalitasJaminan::whereIn('code', $legalitasJaminan)->get();
}
$pemilikJaminan = PemilikJaminan::where('debiture_id', $document->debiture_id)->get();
$hubunganPemilik = HubunganPemilikJaminan::all();
@@ -363,25 +438,48 @@
public function destroy(
$id,
$jaminan_id,
) {
)
{
try {
// Periksa apakah pengguna adalah admin
if (!auth()->user()->hasRole('administrator')) {
//return response()->json(['success' => false, 'message' => 'Hanya administrator yang dapat menghapus dokumen jaminan'], 403);
}
$jaminan = DokumenJaminan::find($jaminan_id);
if (!$jaminan) {
return response()->json(['success' => false, 'message' => 'Dokumen Jaminan tidak ditemukan'], 404);
}
// Periksa apakah dokumen jaminan terkait dengan permohonan aktif
if ($jaminan->permohonan()->exists() && !in_array($jaminan->permohonan->status,['order','revisi'])) {
// return response()->json(['success' => false, 'message' => 'Tidak dapat menghapus dokumen jaminan yang terkait dengan permohonan aktif'], 400);
}
DB::beginTransaction();
$details = DetailDokumenJaminan::where('dokumen_jaminan_id', $jaminan->id)->get();
foreach ($details as $detail) {
Storage::delete('public/' . $detail->dokumen_jaminan);
$detail->delete();
}
$jaminan->delete();
echo json_encode(['success' => true, 'message' => 'Dokumen Jaminan deleted successfully']);
DB::commit();
return response()->json(['success' => true, 'message' => 'Dokumen Jaminan berhasil dihapus']);
} catch (Exception $e) {
echo json_encode(['success' => false, 'message' => 'Failed to delete Dokumen Jaminan']);
DB::rollBack();
return response()->json(['success' => false, 'message' => 'Gagal menghapus Dokumen Jaminan: ' . $e->getMessage()], 500);
}
}
public function bulkDownload()
{
$dokumenIds = request()->get('jaminan'); // Expecting an array of dokumen_jaminan_id
$documents = DetailDokumenJaminan::where('dokumen_jaminan_id', $dokumenIds)->get();
$documents = DokumenJaminan::where('id', $dokumenIds)->with(['jenisJaminan', 'detail', 'debiture'])->get();
if ($documents->isEmpty()) {
return redirect()->back()->with('error', 'No documents found for the provided IDs.');
}
@@ -392,17 +490,25 @@
if ($zip->open($zipFilePath, ZipArchive::CREATE) === true) {
foreach ($documents as $document) {
$files = is_array(json_decode($document->dokumen_jaminan)) ? json_decode(
$document->dokumen_jaminan,
) : [$document->dokumen_jaminan];
$jenisJaminan = $document->permohonan->nomor_registrasi ?? 'Uncategorized';
$folderName = $this->sanitizeFolderName($jenisJaminan);
foreach ($files as $file) {
$filePath = storage_path('app/public/' . $file);
if (file_exists($filePath)) {
$zip->addFile($filePath, basename($filePath));
} else {
// Log or display an error message for missing files
return redirect()->back()->with('error', 'File not found: ' . $filePath);
foreach ($document->detail as $detail) {
if ($detail->dokumen_jaminan) {
$folderJaminanName = $this->sanitizeFolderName($detail->jenisLegalitasJaminan->name ?? 'Uncategorized');
$files = is_array(json_decode($detail->dokumen_jaminan))
? json_decode($detail->dokumen_jaminan)
: [$detail->dokumen_jaminan];
foreach ($files as $file) {
$filePath = storage_path('app/public/' . $file);
if (file_exists($filePath)) {
$zip->addFile($filePath, $folderName . '/' . $folderJaminanName . '/' . basename($filePath));
} else {
// Log or display an error message for missing files
Log::warning('File not found: ' . $filePath);
}
}
}
}
}
@@ -419,7 +525,13 @@
'Content-Type' => 'application/zip',
'Content-Disposition' => 'attachment; filename="' . $zipFileName . '"',
'Content-Length' => filesize($zipFilePath),
])->deleteFileAfterSend(false);
])->deleteFileAfterSend(true);
}
private function sanitizeFolderName($name)
{
// Remove any characters that are not allowed in folder names
return preg_replace('/[^a-zA-Z0-9_\-]/', '_', $name);
}
@@ -444,7 +556,8 @@
public function getLegalitasJaminan($id = 10, $jenisJaminanId = 1)
: JsonResponse {
: JsonResponse
{
$jenisJaminan = JenisJaminan::findOrFail($jenisJaminanId);
$legalitasJaminan = $jenisJaminan->jenis_legalitas_jaminan_id;
$newLegalitasJaminan = JenisLegalitasJaminan::whereIn('code', json_decode($legalitasJaminan, true))->get();
@@ -461,6 +574,12 @@
foreach ($document->detail as $detail) {
// Only include existing legalitas if its id is in the new set
if (in_array($detail->jenis_legalitas_jaminan_id, $newLegalitasIds)) {
$customFields = [];
if($detail->jenisLegalitasJaminan->custom_fields) {
$customFields = CustomField::whereIn('id', $detail->jenisLegalitasJaminan->custom_fields)
->get();
}
$existingLegalitas[] = [
'id' => $detail->id,
'jenis_legalitas_jaminan_id' => $detail->jenis_legalitas_jaminan_id,
@@ -468,10 +587,11 @@
'dokumen_jaminan' => json_decode(
$detail->dokumen_jaminan,
) ?? $detail->dokumen_jaminan,
'dokumen_nomor' => json_decode(
'dokumen_nomor' => json_decode(
$detail->dokumen_nomor,
) ?? $detail->dokumen_nomor,
'custom_field' => $detail->jenisLegalitasJaminan->custom_field,
'custom_fields' => $customFields,
'custom_field_type' => $detail->jenisLegalitasJaminan->custom_field_type,
'details' => $detail->details,
'keterangan' => $detail->keterangan,
@@ -484,14 +604,20 @@
foreach ($newLegalitasJaminan as $legalitas) {
if (!Collection::make($existingLegalitas)->contains('jenis_legalitas_jaminan_id', $legalitas->id)) {
$customFields = [];
if($legalitas->custom_fields) {
$customFields = CustomField::whereIn('id', $legalitas->custom_fields)->get();
}
$newLegalitas[] = [
'id' => null,
'jenis_legalitas_jaminan_id' => $legalitas->id,
'name' => $legalitas->name,
'dokumen_jaminan' => null,
'dokumen_nomor' => null,
'dokumen_nomor' => null,
'custom_field' => $legalitas->custom_field,
'custom_field_type' => $legalitas->custom_field_type,
'custom_fields' => $customFields,
'details' => null,
'keterangan' => null,
'is_existing' => false,
@@ -502,4 +628,40 @@
$combinedLegalitas = array_merge($existingLegalitas, $newLegalitas);
return response()->json($combinedLegalitas);
}
public function clearDetail(Request $request)
{
try {
DB::beginTransaction();
$detailId = $request->input('detail_id');
$detail = DetailDokumenJaminan::findOrFail($detailId);
// Delete associated files
if ($detail->dokumen_jaminan) {
$dokumen_jaminan = is_array(json_decode($detail->dokumen_jaminan))
? json_decode($detail->dokumen_jaminan)
: [$detail->dokumen_jaminan];
foreach ($dokumen_jaminan as $dokumen) {
if (Storage::exists($dokumen)) {
Storage::delete($dokumen);
}
}
}
// Delete the detail record
$detail->delete();
DB::commit();
return response()->json(['success' => true, 'message' => 'Detail berhasil dihapus']);
} catch (\Exception $e) {
DB::rollBack();
return response()->json([
'success' => false,
'message' => 'Gagal menghapus detail: ' . $e->getMessage()
], 500);
}
}
}

View File

@@ -0,0 +1,239 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Modules\Lpj\Models\Inspeksi;
use Modules\Lpj\Services\InspeksiCleanupService;
/**
* Controller contoh untuk menunjukkan penggunaan InspeksiCleanupService
*
* Controller ini berisi contoh method untuk membuat dan update data inspeksi
* dengan otomatis menjalankan cleanup data lama yang tidak memiliki dokument_id
*/
class InspeksiController extends Controller
{
protected InspeksiCleanupService $cleanupService;
public function __construct(InspeksiCleanupService $cleanupService)
{
$this->cleanupService = $cleanupService;
}
/**
* Contoh method untuk membuat data inspeksi baru
*
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function store(Request $request)
{
$validated = $request->validate([
'permohonan_id' => 'required|integer|exists:permohonan,id',
'dokument_id' => 'nullable|integer|exists:dokumen_jaminan,id',
'data_form' => 'required|json',
'foto_form' => 'nullable|json',
'denah_form' => 'nullable|json',
'name' => 'required|string|max:255',
'status' => 'required|string|max:50',
]);
DB::beginTransaction();
try {
// Buat data inspeksi baru
$inspeksi = Inspeksi::create(array_merge($validated, [
'created_by' => Auth::id(),
'updated_by' => Auth::id(),
]));
Log::info('InspeksiController: Data inspeksi berhasil dibuat', [
'inspeksi_id' => $inspeksi->id,
'permohonan_id' => $inspeksi->permohonan_id,
'dokument_id' => $inspeksi->dokument_id,
'created_by' => $inspeksi->created_by
]);
// Commit transaksi utama
DB::commit();
// Jalankan cleanup secara async jika ada dokument_id
// Ini akan menghapus data lama yang tidak memiliki dokument_id
if ($inspeksi->dokument_id) {
Log::info('InspeksiController: Memulai cleanup data lama', [
'permohonan_id' => $inspeksi->permohonan_id,
'created_by' => $inspeksi->created_by,
'dokument_id' => $inspeksi->dokument_id
]);
// Dispatch job cleanup secara async
$this->cleanupService->cleanupAsync(
$inspeksi->permohonan_id,
$inspeksi->created_by,
$inspeksi->dokument_id
);
}
return response()->json([
'success' => true,
'message' => 'Data inspeksi berhasil dibuat',
'data' => $inspeksi->load(['permohonan', 'dokument'])
], 201);
} catch (\Exception $e) {
DB::rollBack();
Log::error('InspeksiController: Gagal membuat data inspeksi', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
return response()->json([
'success' => false,
'message' => 'Gagal membuat data inspeksi: ' . $e->getMessage()
], 500);
}
}
/**
* Contoh method untuk update data inspeksi
*
* @param Request $request
* @param int $id
* @return \Illuminate\Http\JsonResponse
*/
public function update(Request $request, $id)
{
$validated = $request->validate([
'dokument_id' => 'nullable|integer|exists:dokumen_jaminan,id',
'data_form' => 'required|json',
'foto_form' => 'nullable|json',
'denah_form' => 'nullable|json',
'name' => 'required|string|max:255',
'status' => 'required|string|max:50',
]);
DB::beginTransaction();
try {
$inspeksi = Inspeksi::findOrFail($id);
// Simpan data lama untuk logging
$oldDokumentId = $inspeksi->dokument_id;
// Update data
$inspeksi->update(array_merge($validated, [
'updated_by' => Auth::id(),
]));
Log::info('InspeksiController: Data inspeksi berhasil diupdate', [
'inspeksi_id' => $inspeksi->id,
'permohonan_id' => $inspeksi->permohonan_id,
'old_dokument_id' => $oldDokumentId,
'new_dokument_id' => $inspeksi->dokument_id,
'updated_by' => $inspeksi->updated_by
]);
// Commit transaksi utama
DB::commit();
// Jalankan cleanup jika dokument_id berubah dari null ke ada nilai
if (!$oldDokumentId && $inspeksi->dokument_id) {
Log::info('InspeksiController: Dokument ID berubah dari null, memulai cleanup', [
'inspeksi_id' => $inspeksi->id,
'permohonan_id' => $inspeksi->permohonan_id,
'created_by' => $inspeksi->created_by,
'new_dokument_id' => $inspeksi->dokument_id
]);
// Dispatch job cleanup secara async
$this->cleanupService->cleanupAsync(
$inspeksi->permohonan_id,
$inspeksi->created_by,
$inspeksi->dokument_id
);
}
return response()->json([
'success' => true,
'message' => 'Data inspeksi berhasil diupdate',
'data' => $inspeksi->load(['permohonan', 'dokument'])
]);
} catch (\Exception $e) {
DB::rollBack();
Log::error('InspeksiController: Gagal update data inspeksi', [
'inspeksi_id' => $id,
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
return response()->json([
'success' => false,
'message' => 'Gagal update data inspeksi: ' . $e->getMessage()
], 500);
}
}
/**
* Contoh method untuk menjalankan cleanup secara manual
*
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function cleanup(Request $request)
{
$validated = $request->validate([
'permohonan_id' => 'required|integer|exists:permohonan,id',
'created_by' => 'required|integer|exists:users,id',
'sync' => 'boolean', // Opsional, default false (async)
]);
try {
$permohonanId = $validated['permohonan_id'];
$createdBy = $validated['created_by'];
$sync = $validated['sync'] ?? false;
Log::info('InspeksiController: Menjalankan cleanup manual', [
'permohonan_id' => $permohonanId,
'created_by' => $createdBy,
'sync' => $sync
]);
if ($sync) {
// Jalankan secara sync
$this->cleanupService->cleanupSync($permohonanId, $createdBy);
return response()->json([
'success' => true,
'message' => 'Cleanup selesai dijalankan secara synchronous'
]);
} else {
// Dispatch ke queue
$this->cleanupService->cleanupAsync($permohonanId, $createdBy);
return response()->json([
'success' => true,
'message' => 'Cleanup job berhasil di-dispatch ke queue'
]);
}
} catch (\Exception $e) {
Log::error('InspeksiController: Gagal menjalankan cleanup manual', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
return response()->json([
'success' => false,
'message' => 'Gagal menjalankan cleanup: ' . $e->getMessage()
], 500);
}
}
}

View File

@@ -0,0 +1,172 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Lpj\Exports\JenisLampiranExport;
use Modules\Lpj\Http\Requests\JenisLampiranRequest;
use Modules\Lpj\Models\JenisLampiran;
class JenisLampiranController extends Controller
{
public function index()
{
$jenisLampirans = JenisLampiran::all();
return view('lpj::jenis_lampiran.index', compact('jenisLampirans'));
}
public function store(JenisLampiranRequest $request)
{
DB::beginTransaction();
try {
$validated = $request->validated();
$validated['created_by'] = Auth::id();
$jenisLampiran = JenisLampiran::create($validated);
DB::commit();
return redirect()
->route('basicdata.jenis-lampiran.index')
->with('success', 'Jenis Lampiran berhasil ditambahkan.');
} catch (Exception $e) {
DB::rollBack();
return redirect()
->back()
->with('error', 'Gagal menambahkan Jenis Lampiran: ' . $e->getMessage())
->withInput();
}
}
public function create()
{
return view('lpj::jenis_lampiran.create');
}
public function show($id)
{
$jenisLampiran = JenisLampiran::findOrFail($id);
return view('lpj::jenis_lampiran.show', compact('jenisLampiran'));
}
public function edit($id)
{
$jenisLampiran = JenisLampiran::findOrFail($id);
return view('lpj::jenis_lampiran.create', compact('jenisLampiran'));
}
public function update(JenisLampiranRequest $request, $id)
{
DB::beginTransaction();
try {
$jenisLampiran = JenisLampiran::findOrFail($id);
$validated = $request->validated();
$validated['updated_by'] = Auth::id();
$jenisLampiran->update($validated);
DB::commit();
return redirect()
->route('basicdata.jenis-lampiran.index')
->with('success', 'Jenis Lampiran berhasil diperbarui.');
} catch (Exception $e) {
DB::rollBack();
return redirect()
->back()
->with('error', 'Gagal memperbarui Jenis Lampiran: ' . $e->getMessage())
->withInput();
}
}
public function destroy($id)
{
DB::beginTransaction();
try {
$jenisLampiran = JenisLampiran::findOrFail($id);
$jenisLampiran->deleted_by = Auth::id();
$jenisLampiran->save();
$jenisLampiran->delete();
DB::commit();
echo json_encode(['success' => true, 'message' => 'Jenis Lampiran berhasil dihapus.']);
} catch (Exception $e) {
DB::rollBack();
echo json_encode([
'success' => false,
'message' => 'Gagal menghapus Jenis Lampiran: ' . $e->getMessage()
]);
}
}
public function dataForDatatables(Request $request)
{
// Retrieve data from the database
$query = JenisLampiran::query();
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('nama', 'LIKE', "%$search%")
->orWhere('deskripsi', 'LIKE', "%$search%");
});
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->get();
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = $request->get('page', 1);
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
public function export()
{
if (is_null($this->user) || !$this->user->can('jenis_lampiran.export')) {
abort(403, 'Sorry! You are not allowed to export jenis lampiran.');
}
return Excel::download(new JenisLampiranExport, 'jenis_lampiran.xlsx');
}
}

View File

@@ -8,6 +8,7 @@
use Maatwebsite\Excel\Facades\Excel;
use Modules\Lpj\Exports\JenisLegalitasJaminanExport;
use Modules\Lpj\Http\Requests\JenisLegalitasJaminanRequest;
use Modules\Lpj\Models\CustomField;
use Modules\Lpj\Models\JenisLegalitasJaminan;
class JenisLegalitasJaminanController extends Controller
@@ -40,13 +41,15 @@
public function create()
{
return view('lpj::jenis_legalitas_jaminan.create');
$customFields = CustomField::orderBy('urutan_prioritas', 'asc')->get();
return view('lpj::jenis_legalitas_jaminan.create',compact('customFields'));
}
public function edit($id)
{
$jenisLegalitasJaminan = JenisLegalitasJaminan::find($id);
return view('lpj::jenis_legalitas_jaminan.create', compact('jenisLegalitasJaminan'));
$customFields = CustomField::orderBy('urutan_prioritas', 'asc')->get();
return view('lpj::jenis_legalitas_jaminan.create', compact('jenisLegalitasJaminan', 'customFields'));
}
public function update(JenisLegalitasJaminanRequest $request, $id)
@@ -147,4 +150,16 @@
{
return Excel::download(new JenisLegalitasJaminanExport, 'jenis_legalitas_jaminan.xlsx');
}
public function getCustomFields($id)
{
$jenisLegalitasJaminan = JenisLegalitasJaminan::findOrFail($id);
if(!$jenisLegalitasJaminan->custom_fields) {
return response()->json([]);
}
$customFields = CustomField::whereIn('id', $jenisLegalitasJaminan->custom_fields)->get();
return response()->json($customFields);
}
}

View File

@@ -44,8 +44,13 @@ class KJPPController extends Controller
// Combine KJPP number with branch code
$fullKjppNumber = $kjppNumber;
$detailJoinEmailKantor = json_encode([]);
$detailJoinPimpinan = json_encode([]);
$detailJoinPicReviewer = json_encode([]);
$detailJoinPicAdmin = json_encode([]);
$detailJoinPicMarketing = json_encode([]);
return view('lpj::kjpp.create', compact('ijin_usaha', 'jenis_aset', 'provinces', 'fullKjppNumber'));
return view('lpj::kjpp.create', compact('ijin_usaha', 'jenis_aset', 'provinces', 'fullKjppNumber', 'detailJoinEmailKantor', 'detailJoinPimpinan', 'detailJoinPicReviewer', 'detailJoinPicAdmin', 'detailJoinPicMarketing'));
}
/**
@@ -55,8 +60,11 @@ class KJPPController extends Controller
{
$validated = $request->validated();
if ($validated) {
$detailEmailKantor = [];
$detailNamaPimpinan = [];
$detailNomorPicPimpinan = [];
$detailNamaPicReviewer = [];
$detailNomorHpPicReviewer = [];
$detailNamaPicAdmin = [];
@@ -65,6 +73,8 @@ class KJPPController extends Controller
$detailNomorHpPicMarketing = [];
$emailKantor = $request->input('detail_email_kantor.email_kantor', []);
$namaPimpinan = $request->input('detail_nama_pimpinan.nama_pimpinan', []);
$nomorHpPimpinan = $request->input('detail_nomor_hp_pimpinan.nomor_hp_pimpinan', []);
$namaPicReviewer = $request->input('detail_nama_pic_reviewer.nama_pic_reviewer', []);
$nomorHpPicReviewer = $request->input('detail_nomor_hp_pic_reviewer.nomor_hp_pic_reviewer', []);
$namaPicAdmin = $request->input('detail_nama_pic_admin.nama_pic_admin', []);
@@ -73,58 +83,56 @@ class KJPPController extends Controller
$nomorHpPicMarketing = $request->input('detail_nomor_hp_pic_marketing.nomor_hp_pic_marketing', []);
foreach ($emailKantor as $value) {
$detailEmailKantor[] = [
'email_kantor' => $value
];
$detailEmailKantor[] = $value;
}
// Encode to JSON and store
$detailEmailKantorJson = json_encode($detailEmailKantor);
// Process detail_nama_pimpinan
foreach ($namaPimpinan as $value) {
$detailNamaPimpinan[] = $value;
}
$detailNamaPimpinanJson = json_encode($detailNamaPimpinan);
// Process detail_nomor_pic_pimpinan
foreach ($nomorHpPimpinan as $value) {
$detailNomorPicPimpinan[] = $value;
}
$detailNomorPicPimpinanJson = json_encode($detailNomorPicPimpinan);
// Process detail_nama_pic_reviewer
foreach ($namaPicReviewer as $value) {
$detailNamaPicReviewer[] = [
'nama_pic_reviewer' => $value
];
$detailNamaPicReviewer[] = $value;
}
$detailNamaPicReviewerJson = json_encode($detailNamaPicReviewer);
// Process detail_nomor_hp_pic_reviewer
foreach ($nomorHpPicReviewer as $value) {
$detailNomorHpPicReviewer[] = [
'nomor_hp_pic_reviewer' => $value
];
$detailNomorHpPicReviewer[] = $value;
}
$detailNomorHpPicReviewerJson = json_encode($detailNomorHpPicReviewer);
// Process detail_nama_pic_admin
foreach ($namaPicAdmin as $value) {
$detailNamaPicAdmin[] = [
'nama_pic_admin' => $value
];
$detailNamaPicAdmin[] = $value;
}
$detailNamaPicAdminJson = json_encode($detailNamaPicAdmin);
// Process detail_nomor_hp_pic_admin
foreach ($nomorHpPicAdmin as $value) {
$detailNomorHpPicAdmin[] = [
'nomor_hp_pic_admin' => $value
];
$detailNomorHpPicAdmin[] = $value;
}
$detailNomorHpPicAdminJson = json_encode($detailNomorHpPicAdmin);
// Process detail_nama_pic_marketing
foreach ($namaPicMarketing as $value) {
$detailNamaPicMarketing[] = [
'nama_pic_marketing' => $value
];
$detailNamaPicMarketing[] = $value;
}
$detailNamaPicMarketingJson = json_encode($detailNamaPicMarketing);
// Process detail_nomor_hp_pic_marketing
foreach ($nomorHpPicMarketing as $value) {
$detailNomorHpPicMarketing[] = [
'nomor_hp_pic_marketing' => $value
];
$detailNomorHpPicMarketing[] = $value;
}
$detailNomorHpPicMarketingJson = json_encode($detailNomorHpPicMarketing);
@@ -141,6 +149,8 @@ class KJPPController extends Controller
}
$validated['detail_email_kantor'] = $detailEmailKantorJson;
$validated['detail_nama_pimpinan'] = $detailNamaPimpinanJson;
$validated['detail_nomor_hp_pimpinan'] = $detailNomorPicPimpinanJson;
$validated['detail_nama_pic_reviewer'] = $detailNamaPicReviewerJson;
$validated['detail_nomor_hp_pic_reviewer'] = $detailNomorHpPicReviewerJson;
$validated['detail_nama_pic_admin'] = $detailNamaPicAdminJson;
@@ -148,7 +158,11 @@ class KJPPController extends Controller
$validated['detail_nama_pic_marketing'] = $detailNamaPicMarketingJson;
$validated['detail_nomor_hp_pic_marketing'] = $detailNomorHpPicMarketingJson;
$validated['ijin_usaha_id'] = json_encode($validated['ijin_usaha_id']);
$validated['jenis_aset_id'] = json_encode($validated['jenis_aset_id']);
if (empty($validated['jenis_aset_id'])) {
$validated['jenis_aset_id'] = json_encode([]);
} else {
$validated['jenis_aset_id'] = json_encode($validated['jenis_aset_id']);
}
// Tambahkan nama file ke data yang divalidasi
$validated['attachment'] = $filename;
@@ -181,6 +195,8 @@ class KJPPController extends Controller
$districts = District::where('code', $kjpp->district_code)->get();
$villages = Village::where('code', $kjpp->village_code)->get();
$detailEmailKantor = json_decode($kjpp->detail_email_kantor);
$detailNamaPimpinan = json_decode($kjpp->detail_nama_pimpinan);
$detailNomorHpPimpinan = json_decode($kjpp->detail_nomor_hp_pimpinan);
$detailNamaPicReviewer = json_decode($kjpp->detail_nama_pic_reviewer);
$detailNomorHpPicReviewer = json_decode($kjpp->detail_nomor_hp_pic_reviewer);
$detailNamaPicAdmin = json_decode($kjpp->detail_nama_pic_admin);
@@ -188,28 +204,42 @@ class KJPPController extends Controller
$detailNamaPicMarketing = json_decode($kjpp->detail_nama_pic_marketing);
$detailNomorHpPicMarketing = json_decode($kjpp->detail_nomor_hp_pic_marketing);
$detailJoinEmailKantor = json_encode(array_map(function ($email) {
return [
'email_kantor' => $email
];
}, $detailEmailKantor));
$detailJoinPimpinan = json_encode(array_map(function ($nama, $nomor) {
return [
'nama_pimpinan' => $nama,
'nomor_hp_pimpinan' => $nomor
];
}, $detailNamaPimpinan, $detailNomorHpPimpinan));
$detailJoinPicReviewer = json_encode(array_map(function ($nama, $nomor) {
return [
'nama_pic_reviewer' => $nama->nama_pic_reviewer,
'nomor_hp_pic_reviewer' => $nomor->nomor_hp_pic_reviewer
'nama_pic_reviewer' => $nama,
'nomor_hp_pic_reviewer' => $nomor
];
}, $detailNamaPicReviewer, $detailNomorHpPicReviewer));
$detailJoinPicAdmin = json_encode(array_map(function ($nama, $nomor) {
return [
'nama_pic_admin' => $nama->nama_pic_admin,
'nomor_hp_pic_admin' => $nomor->nomor_hp_pic_admin
'nama_pic_admin' => $nama,
'nomor_hp_pic_admin' => $nomor
];
}, $detailNamaPicAdmin, $detailNomorHpPicAdmin));
$detailJoinPicMarketing = json_encode(array_map(function ($nama, $nomor) {
return [
'nama_pic_marketing' => $nama->nama_pic_marketing,
'nomor_hp_pic_marketing' => $nomor->nomor_hp_pic_marketing
'nama_pic_marketing' => $nama,
'nomor_hp_pic_marketing' => $nomor
];
}, $detailNamaPicMarketing, $detailNomorHpPicMarketing));
return view('lpj::kjpp.show', compact('jenis_jaminan', 'ijin_usahas', 'ijin_usaha', 'kjpp', 'provinces', 'cities', 'districts', 'villages', 'detailEmailKantor', 'detailJoinPicReviewer', 'detailJoinPicAdmin', 'detailJoinPicMarketing'));
return view('lpj::kjpp.show', compact('jenis_jaminan', 'ijin_usahas', 'ijin_usaha', 'kjpp', 'provinces', 'cities', 'districts', 'villages', 'detailJoinEmailKantor', 'detailJoinPicReviewer', 'detailJoinPicAdmin', 'detailJoinPicMarketing', 'detailJoinPimpinan'));
}
/**
@@ -225,6 +255,8 @@ class KJPPController extends Controller
$districts = District::where('city_code', $kjpp->city_code)->get();
$villages = Village::where('district_code', $kjpp->district_code)->get();
$detailEmailKantor = json_decode($kjpp->detail_email_kantor);
$detailNamaPimpinan = json_decode($kjpp->detail_nama_pimpinan);
$detailNomorHpPimpinan = json_decode($kjpp->detail_nomor_hp_pimpinan);
$detailNamaPicReviewer = json_decode($kjpp->detail_nama_pic_reviewer);
$detailNomorHpPicReviewer = json_decode($kjpp->detail_nomor_hp_pic_reviewer);
$detailNamaPicAdmin = json_decode($kjpp->detail_nama_pic_admin);
@@ -232,28 +264,42 @@ class KJPPController extends Controller
$detailNamaPicMarketing = json_decode($kjpp->detail_nama_pic_marketing);
$detailNomorHpPicMarketing = json_decode($kjpp->detail_nomor_hp_pic_marketing);
$detailJoinEmailKantor = json_encode(array_map(function ($email) {
return [
'email_kantor' => $email
];
}, $detailEmailKantor));
$detailJoinPimpinan = json_encode(array_map(function ($nama, $nomor) {
return [
'nama_pimpinan' => $nama,
'nomor_hp_pimpinan' => $nomor
];
}, $detailNamaPimpinan, $detailNomorHpPimpinan));
$detailJoinPicReviewer = json_encode(array_map(function ($nama, $nomor) {
return [
'nama_pic_reviewer' => $nama->nama_pic_reviewer,
'nomor_hp_pic_reviewer' => $nomor->nomor_hp_pic_reviewer
'nama_pic_reviewer' => $nama,
'nomor_hp_pic_reviewer' => $nomor
];
}, $detailNamaPicReviewer, $detailNomorHpPicReviewer));
$detailJoinPicAdmin = json_encode(array_map(function ($nama, $nomor) {
return [
'nama_pic_admin' => $nama->nama_pic_admin,
'nomor_hp_pic_admin' => $nomor->nomor_hp_pic_admin
'nama_pic_admin' => $nama,
'nomor_hp_pic_admin' => $nomor
];
}, $detailNamaPicAdmin, $detailNomorHpPicAdmin));
$detailJoinPicMarketing = json_encode(array_map(function ($nama, $nomor) {
return [
'nama_pic_marketing' => $nama->nama_pic_marketing,
'nomor_hp_pic_marketing' => $nomor->nomor_hp_pic_marketing
'nama_pic_marketing' => $nama,
'nomor_hp_pic_marketing' => $nomor
];
}, $detailNamaPicMarketing, $detailNomorHpPicMarketing));
return view('lpj::kjpp.create', compact('kjpp', 'ijin_usaha', 'jenis_aset', 'provinces', 'cities', 'districts', 'villages', 'detailJoinPicReviewer', 'detailJoinPicAdmin', 'detailJoinPicMarketing', 'detailEmailKantor'));
return view('lpj::kjpp.create', compact('kjpp', 'ijin_usaha', 'jenis_aset', 'provinces', 'cities', 'districts', 'villages', 'detailJoinPicReviewer', 'detailJoinPicAdmin', 'detailJoinPicMarketing', 'detailJoinEmailKantor', 'detailJoinPimpinan'));
}
/**
@@ -267,6 +313,8 @@ class KJPPController extends Controller
if ($validated) {
$detailEmailKantor = [];
$detailNamaPimpinan = [];
$detailNomorHpPimpinan = [];
$detailNamaPicReviewer = [];
$detailNomorHpPicReviewer = [];
$detailNamaPicAdmin = [];
@@ -275,6 +323,8 @@ class KJPPController extends Controller
$detailNomorHpPicMarketing = [];
$emailKantor = $request->input('detail_email_kantor.email_kantor', []);
$namaPimpinan = $request->input('detail_nama_pimpinan.nama_pimpinan', []);
$nomorHpPimpinan = $request->input('detail_nomor_hp_pimpinan.nomor_hp_pimpinan', []);
$namaPicReviewer = $request->input('detail_nama_pic_reviewer.nama_pic_reviewer', []);
$nomorHpPicReviewer = $request->input('detail_nomor_hp_pic_reviewer.nomor_hp_pic_reviewer', []);
$namaPicAdmin = $request->input('detail_nama_pic_admin.nama_pic_admin', []);
@@ -283,58 +333,56 @@ class KJPPController extends Controller
$nomorHpPicMarketing = $request->input('detail_nomor_hp_pic_marketing.nomor_hp_pic_marketing', []);
foreach ($emailKantor as $value) {
$detailEmailKantor[] = [
'email_kantor' => $value
];
$detailEmailKantor[] = $value;
}
// Encode to JSON and store
$detailEmailKantorJson = json_encode($detailEmailKantor);
// Process detail_nama_pimpinan
foreach ($namaPimpinan as $value) {
$detailNamaPimpinan[] = $value;
}
$detailNamaPimpinanJson = json_encode($detailNamaPimpinan);
// Process detail_nomor_hp_pimpinan
foreach ($nomorHpPimpinan as $value) {
$detailNomorHpPimpinan[] = $value;
}
$detailNomorHpPimpinanJson = json_encode($detailNomorHpPimpinan);
// Process detail_nama_pic_reviewer
foreach ($namaPicReviewer as $value) {
$detailNamaPicReviewer[] = [
'nama_pic_reviewer' => $value
];
$detailNamaPicReviewer[] = $value;
}
$detailNamaPicReviewerJson = json_encode($detailNamaPicReviewer);
// Process detail_nomor_hp_pic_reviewer
foreach ($nomorHpPicReviewer as $value) {
$detailNomorHpPicReviewer[] = [
'nomor_hp_pic_reviewer' => $value
];
$detailNomorHpPicReviewer[] = $value;
}
$detailNomorHpPicReviewerJson = json_encode($detailNomorHpPicReviewer);
// Process detail_nama_pic_admin
foreach ($namaPicAdmin as $value) {
$detailNamaPicAdmin[] = [
'nama_pic_admin' => $value
];
$detailNamaPicAdmin[] = $value;
}
$detailNamaPicAdminJson = json_encode($detailNamaPicAdmin);
// Process detail_nomor_hp_pic_admin
foreach ($nomorHpPicAdmin as $value) {
$detailNomorHpPicAdmin[] = [
'nomor_hp_pic_admin' => $value
];
$detailNomorHpPicAdmin[] = $value;
}
$detailNomorHpPicAdminJson = json_encode($detailNomorHpPicAdmin);
// Process detail_nama_pic_marketing
foreach ($namaPicMarketing as $value) {
$detailNamaPicMarketing[] = [
'nama_pic_marketing' => $value
];
$detailNamaPicMarketing[] = $value;
}
$detailNamaPicMarketingJson = json_encode($detailNamaPicMarketing);
// Process detail_nomor_hp_pic_marketing
foreach ($nomorHpPicMarketing as $value) {
$detailNomorHpPicMarketing[] = [
'nomor_hp_pic_marketing' => $value
];
$detailNomorHpPicMarketing[] = $value;
}
$detailNomorHpPicMarketingJson = json_encode($detailNomorHpPicMarketing);
@@ -359,6 +407,8 @@ class KJPPController extends Controller
}
$validated['detail_email_kantor'] = $detailEmailKantorJson;
$validated['detail_nama_pimpinan'] = $detailNamaPimpinanJson;
$validated['detail_nomor_hp_pimpinan'] = $detailNomorHpPimpinanJson;
$validated['detail_nama_pic_reviewer'] = $detailNamaPicReviewerJson;
$validated['detail_nomor_hp_pic_reviewer'] = $detailNomorHpPicReviewerJson;
$validated['detail_nama_pic_admin'] = $detailNamaPicAdminJson;
@@ -366,8 +416,11 @@ class KJPPController extends Controller
$validated['detail_nama_pic_marketing'] = $detailNamaPicMarketingJson;
$validated['detail_nomor_hp_pic_marketing'] = $detailNomorHpPicMarketingJson;
$validated['ijin_usaha_id'] = json_encode($validated['ijin_usaha_id']);
$validated['jenis_aset_id'] = json_encode($validated['jenis_aset_id']);
if (empty($validated['jenis_aset_id'])) {
$validated['jenis_aset_id'] = json_encode([]);
} else {
$validated['jenis_aset_id'] = json_encode($validated['jenis_aset_id']);
}
// Perbarui data di database
KJPP::where('id', $id)->update($validated);
@@ -409,8 +462,8 @@ class KJPPController extends Controller
//abort(403, 'Sorry! You are not allowed to view users.');
}
// Retrieve data from the database
$query = KJPP::query();
// Retrieve data from the database order by code ascending
$query = KJPP::query()->orderBy('code', 'asc');
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
@@ -445,7 +498,7 @@ class KJPPController extends Controller
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->get();
$data = $query->with('city')->get();
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));

View File

@@ -0,0 +1,45 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Modules\Lpj\Models\LampiranDokumen;
class LampiranDokumenController extends Controller
{
public function download($id)
{
$lampiran = LampiranDokumen::findOrFail($id);
return Storage::download($lampiran->path_file, $lampiran->nama_file);
}
public function upload(Request $request)
{
$request->validate([
'permohonan_id' => 'required|exists:permohonan,id',
'jenis_lampiran_id' => 'required|exists:jenis_lampiran,id',
'nama_file' => 'nullable|string|max:255',
'file' => 'required|file|max:10240',
'keterangan' => 'nullable|string|max:255',
]);
$lampiran = LampiranDokumen::uploadLampiran($request->all());
if ($lampiran) {
return redirect()->back()->with('success', 'Lampiran uploaded successfully');
} else {
return redirect()->back()->with('error', 'Unauthorized or upload failed');
}
}
public function delete(LampiranDokumen $lampiran)
{
if ($lampiran->deleteLampiran()) {
return redirect()->back()->with('success', 'Lampiran deleted successfully');
} else {
return redirect()->back()->with('error', 'Unauthorized or delete failed');
}
}
}

View File

@@ -0,0 +1,185 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Lpj\Exports\LaporanAdminKreditExport;
use Modules\Lpj\Models\LaporanAdminKredit;
use Modules\Lpj\Models\Permohonan;
class LaporanAdminKreditController extends Controller
{
public $user;
/**
* Display a listing of the resource.
*/
public function index()
{
$permohonan = Permohonan::where(['status' => 'done'])->get();
foreach ($permohonan as $_permohonan) {
$npw = 0;
if (isset($_permohonan->penilai->lpj)) {
$npw = json_decode($_permohonan->penilai->lpj, true);
$npw = $npw['total_nilai_pasar_wajar'] ?? 0;
}
$dataAdk = [
'jenis_agunan' => $_permohonan->documents->pluck('jenisJaminan.name')->unique()->implode(', '),
'alamat_agunan' => $_permohonan->documents->map(function ($document) {
return formatAlamat($document);
})->unique()->implode(', '),
'nama_pemilik' => $_permohonan->documents->pluck('pemilik.name')->unique()->implode(', '),
'tanggal_kunjungan' => $_permohonan->penilaian->tanggal_kunjungan,
'nama_penilai' => $_permohonan->penilaian->_user_penilai->userPenilaiTeam->name,
'nilai_likuidasi' => $_permohonan->nilai_liquidasi,
'nilai_pasar_wajar' => str_replace('.', '', $npw),
'bukti_kepemilikan' => $_permohonan->documents->flatMap(function ($document) {
return $document->detail->map(function ($detail) {
return (!empty($detail->dokumen_nomor) && is_array($detail->dokumen_nomor))
? ($detail->jenisLegalitasJaminan->name ?? '') . "\n" . implode(', ', $detail->dokumen_nomor)
: null;
});
})->filter()->unique()->implode(', '),
];
LaporanAdminKredit::updateOrCreate([
'debiture_id' => $_permohonan->debiture_id,
], $dataAdk);
}
$laporans = LaporanAdminKredit::with('debiture')->paginate(10);
return view('lpj::laporan_admin_kredit.index', compact('laporans'));
}
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('laporan-admin-kredit.view')) {
//abort(403, 'Sorry! You are not allowed to view laporan admin kredit.');
}
// Retrieve data from the database
$query = LaporanAdminKredit::query();
if ($request->has('tanggal_awal') && $request->has('tanggal_akhir')) {
$query->whereBetween('tanggal_kunjungan', [$request->tanggal_awal, $request->tanggal_akhir]);
}
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$search_ = json_decode($search);
if (isset($search_->search)) {
$query->where(function ($q) use ($search_) {
$q->where('kode_register_t24', 'LIKE', '%' . $search_->search . '%')
->orWhere('jenis_agunan', 'LIKE', '%' . $search_->search . '%')
->orWhere('nama_pemilik', 'LIKE', '%' . $search_->search . '%')
->orWhereHas('debiture', function ($query) use ($search_) {
$query->where('name', 'LIKE', '%' . $search_->search . '%');
});
});
}
if (isset($search_->tanggal_awal) && isset($search_->tanggal_akhir)) {
$query->whereBetween('tanggal_kunjungan', [$search_->tanggal_awal, $search_->tanggal_akhir]);
}
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->with(['debiture.branch'])->get();
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = $request->get('page', 1);
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
public function export()
{
return Excel::download(new LaporanAdminKreditExport, 'laporan_admin_kredit.xlsx');
}
public function edit($id)
{
$laporanAdminKredit = LaporanAdminKredit::with('debiture.branch')->find($id);
return view('lpj::laporan_admin_kredit.form', compact('laporanAdminKredit'));
}
public function update(Request $request, $id)
{
$request->validate([
'kode_register_t24' => 'nullable',
'cif' => 'required',
'keterangan' => 'nullable|string',
'kolektibilitas' => 'nullable|string|in:1,2,3,4,5',
]);
try {
$laporanAdminKredit = LaporanAdminKredit::find($id);
// Update only the editable fields
$laporanAdminKredit->update([
'kode_register_t24' => $request->kode_register_t24,
'keterangan' => $request->keterangan,
'kolektibilitas' => $request->kolektibilitas,
'updated_by' => Auth::id(),
]);
// Update CIF in the debiture table if needed
if ($laporanAdminKredit->debiture) {
$laporanAdminKredit->debiture->update([
'cif' => $request->cif,
'updated_by' => Auth::id(),
]);
}
return redirect()
->route('admin-kredit.laporan.index')
->with('success', 'Laporan Admin Kredit updated successfully');
} catch (Exception $e) {
return redirect()
->route('admin-kredit.laporan.edit', $id)
->with('error', 'Failed to update Laporan Admin Kredit');
}
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class LaporanBiayaInternalExternalController extends Controller
{
/**
* Display a listing of the resource.
*/
public function showLaporanBiayaInternal()
{
return view('lpj::laporan-biaya.internal');
}
public function showLaporanBiayaExternal()
{
return view('lpj::laporan-biaya.external');
}
}

View File

@@ -2,15 +2,29 @@
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Modules\Lpj\Models\Permohonan;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Modules\Lpj\Http\Controllers\PenilaiController;
class LaporanController extends Controller
{
public $user;
public $penilaiController;
/**
* Display a listing of the resource.
*/
public function __construct(PenilaiController $penilaiController){
$this->penilaiController = $penilaiController;
}
public function index()
{
return view('lpj::laporan.index');
}
public function sederhana_index()
{
return view('lpj::laporan.sederhana_index');
@@ -24,11 +38,109 @@ class LaporanController extends Controller
/**
* Show the specified resource.
*/
public function show($id) {}
public function show($id) {
$permohonan = Permohonan::with([
'penilai',
'dokumenjaminan',
])->find($id);
if ($permohonan->penilai->type_penilai == 'memo') {
return $this->penilaiController->print_out($request = new Request(['documentId' => $permohonan->penilai->dokument_id, 'jaminanId' => $permohonan->dokumenjaminan[0]->jenis_jaminan_id, 'permohonanId' => $permohonan->id, 'statusLpj' => 1, 'type' => 'memo']));
}
if ($permohonan->penilai->type_penilai == 'rap') {
return $this->penilaiController->print_out($request = new Request(['documentId' => $permohonan->penilai->dokument_id, 'jaminanId' => $permohonan->dokumenjaminan[0]->jenis_jaminan_id, 'permohonanId' => $permohonan->id, 'statusLpj' => 1, 'type' => 'rap']));
}
return view('lpj::laporan.show', compact('permohonan'));
}
/**
* Store form inspeksi.
*/
public function store(Request $request) {}
public function store(Request $request) {
$permohonan = Permohonan::find($request->permohonan_id);
if($request->nilai_liquidasi) {
$permohonan->nilai_liquidasi = $request->liquidasi;
$permohonan->save();
return redirect()->route('laporan.index')->with('success', 'Nilai Liquidasi updated successfully');
}
}
public function update(Request $request, $id) {}
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('debitur.view')) {
//abort(403, 'Sorry! You are not allowed to view users.');
}
// Retrieve data from the database
$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);
}
$query = $query->orderBy('nomor_registrasi', 'desc');
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('debiture', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
$q->orWhere('status', 'LIKE', '%' . $search . '%');
});
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
$size = $request->get('size', 10);
if ($size == 0) {
$size = 10;
}
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian','jenisFasilitasKredit', 'documents.inspeksi','penilai','documents.detail','noc'])->get();
// Calculate the page count
$pageCount = ceil($totalRecords / $size);
// Calculate the current page number
$currentPage = max(1, $request->get('page', 1));
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Modules\Lpj\Models\Debiture;
use Modules\Lpj\Services\LaporanDebitureService;
class LaporanDebitureController extends Controller
{
private $laporanDebitureService;
public function __construct()
{
$this->laporanDebitureService = app(LaporanDebitureService::class);
}
/**
* Display a listing of the resource.
*/
public function index()
{
$debiture = Debiture::all();
return view('lpj::laporan-debiture.index', compact('debiture'));
}
public function dataTableForDebiture(Request $request)
{
return $this->laporanDebitureService->dataForDatatables($request);
}
}

View File

@@ -0,0 +1,173 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Modules\Lpj\Models\LaporanExternal;
use Modules\Lpj\Http\Requests\LaporanExternalRequest;
use Modules\Lpj\Models\Permohonan;
class LaporanExternalController extends Controller
{
public $user;
/**
* Display a listing of the resource.
*/
public function index()
{
$laporanExternals = LaporanExternal::with('permohonan')->paginate(10);
return view('lpj::laporan_external.index', compact('laporanExternals'));
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view('lpj::laporan_external.create');
}
/**
* Store a newly created resource in storage.
*/
public function store(LaporanExternalRequest $request)
{
$validatedData = $request->validated();
if ($request->hasFile('file_resume')) {
$validatedData['file_resume'] = $request->file('file_resume')->store('laporan_external/resume', 'public');
}
if ($request->hasFile('file_laporan')) {
$validatedData['file_laporan'] = $request->file('file_laporan')->store('laporan_external/laporan', 'public');
}
LaporanExternal::create($validatedData);
return redirect()->route('laporan-external.index')->with('success', 'Laporan External berhasil ditambahkan.');
}
/**
* Show the specified resource.
*/
public function show(LaporanExternal $laporanExternal)
{
return view('lpj::laporan_external.show', compact('laporanExternal'));
}
/**
* Show the form for editing the specified resource.
*/
public function edit(LaporanExternal $laporanExternal)
{
$permohonan = Permohonan::find($laporanExternal->permohonan_id);
return view('lpj::laporan_external.create', compact('laporanExternal','permohonan'));
}
/**
* Update the specified resource in storage.
*/
public function update(LaporanExternalRequest $request, LaporanExternal $laporanExternal)
{
$validatedData = $request->validated();
if ($request->hasFile('file_resume')) {
$validatedData['file_resume'] = $request->file('file_resume')->store('laporan_external/resume', 'public');
}
if ($request->hasFile('file_laporan')) {
$validatedData['file_laporan'] = $request->file('file_laporan')->store('laporan_external/laporan', 'public');
}
$laporanExternal->update($validatedData);
return redirect()->route('laporan-external.index')->with('success', 'Laporan External berhasil diperbarui.');
}
/**
* Remove the specified resource from storage.
*/
public function destroy(LaporanExternal $laporanExternal)
{
$laporanExternal->delete();
return redirect()->route('laporan-external.index')->with('success', 'Laporan External berhasil dihapus.');
}
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('jenis_aset.view')) {
//abort(403, 'Sorry! You are not allowed to view users.');
}
// Retrieve data from the database
$query = LaporanExternal::query();
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('nomor_laporan', 'LIKE', "%$search%")
->orWhere('tanggal_laporan', 'LIKE', "%$search%")
->orWhereHas('permohonan', function($q) use ($search) {
$q->where('nomor_permohonan', 'LIKE', "%$search%");
})
->orWhere('tgl_final_laporan', 'LIKE', "%$search%")
->orWhere('nilai_pasar', 'LIKE', "%$search%")
->orWhere('indikasi_nilai_likuidasi', 'LIKE', "%$search%")
->orWhere('indikasi_nilai_pasar_tanah', 'LIKE', "%$search%")
->orWhere('estimasi_harga_tanah', 'LIKE', "%$search%")
->orWhere('estimasi_harga_bangunan', 'LIKE', "%$search%")
->orWhere('indikasi_nilai_pasar_bangunan', 'LIKE', "%$search%")
->orWhere('indikasi_nilai_pasar_sarana_pelengkap', 'LIKE', "%$search%")
->orWhere('indikasi_nilai_pasar_mesin', 'LIKE', "%$search%")
->orWhere('indikasi_nilai_pasar_kendaraan_alat_berat', 'LIKE', "%$search%")
->orWhere('file_resume', 'LIKE', "%$search%")
->orWhere('file_laporan', 'LIKE', "%$search%");
});
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->with(['permohonan.debiture','permohonan.penawaran.tujuanPenilaianKjpp','permohonan.dokumenjaminan.jenisjaminan'])->get();
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = 0 + 1;
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
}

View File

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

View File

@@ -0,0 +1,43 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Modules\Lpj\Services\LaporanMonitoringSoService;
class LaporanMonitoringSoController extends Controller
{
private $laporanMonitoringSoService;
public function __construct(LaporanMonitoringSoService $laporanMonitoringSoService)
{
$this->laporanMonitoringSoService = $laporanMonitoringSoService;
}
/**
* Display a listing of the resource.
*/
public function index()
{
$user = auth()->user()->load('roles');
$result = $this->laporanMonitoringSoService->progresPengerjaanLaporan($user);
return view('lpj::laporan-monitoring.index', compact('result'));
}
/**
* Show details data.
* @return Response
*/
public function show($id){
return view('lpj::laporan-monitoring.show', compact('id'));
}
public function dataForDatatablePenilai(Request $request, $id){
return $this->laporanMonitoringSoService->showDetailsPermohonan($request, $id);
}
}

View File

@@ -0,0 +1,140 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Lpj\Exports\LaporanPembatalanExport;
use Modules\Lpj\Models\PermohonanPembatalan;
class LaporanPembatalanController extends Controller
{
public $user;
public function index()
{
return view('lpj::laporan_pembatalan.index');
}
public function export(Request $request)
{
return Excel::download(new LaporanPembatalanExport($request), 'laporan_pembatalan.xlsx');
}
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('debitur.view')) {
//abort(403, 'Sorry! You are not allowed to view users.');
}
// Retrieve data from the database
$query = PermohonanPembatalan::query();
if (!Auth::user()->hasAnyRole(['administrator'])) {
$query = $query->whereHas('permohonan', function ($q) {
$q->where('branch_id', Auth::user()->branch_id);
});
}
$query = $query->orderBy('created_at', 'desc');
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = json_decode($request->get('search'));
if (isset($search->start_date) || isset($search->end_date)) {
$query->whereBetween('created_at', [
$search->start_date ?? '1900-01-01',
$search->end_date ?? now()->toDateString()
]);
}
// Filter by branch if provided
if (isset($search->branch_id) && !empty($search->branch_id)) {
$query->whereHas('permohonan', function ($q) use ($search) {
$q->where('branch_id', $search->branch_id);
});
}
if (isset($search->search)) {
$query->where(function ($q) use ($search) {
$q->whereHas('permohonan', function ($subq) use ($search) {
$subq->where('nomor_registrasi', 'LIKE', '%' . $search->search . '%');
$subq->orWhereRelation('user', 'name', 'LIKE', '%' . $search->search . '%');
$subq->orWhereRelation('branch', 'name', 'LIKE', '%' . $search->search . '%');
});
$q->orWhere('alasan_pembatalan', 'LIKE', '%' . $search->search . '%');
$q->orWhere('status', 'LIKE', '%' . $search->search . '%');
});
}
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
$size = $request->get('size', 10);
if ($size == 0) {
$size = 10;
}
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->get();
$data = $data->map(function ($item) {
return [
'id' => $item->id,
'nomor_registrasi' => $item->permohonan->nomor_registrasi ?? '-',
'tanggal_permohonan' => $item->permohonan->tanggal_permohonan ? date('d-m-Y', strtotime($item->permohonan->tanggal_permohonan)) : '-',
'tanggal_pembatalan' => date('d-m-Y', strtotime($item->created_at)),
'cabang' => $item->permohonan->branch->name ?? '-',
'pemohon' => $item->permohonan->user->name ?? '-',
'debitur' => $item->permohonan->debiture->name ?? '-',
'alasan_pembatalan' => $item->alasan_pembatalan,
'status' => $item->status,
'diajukan_oleh' => $item->user->name ?? '-',
'disetujui_oleh' => $item->authorized_by ? $item->authorizedUser->name : '-',
'tanggal_disetujui' => $item->authorized_at ? formatTanggalIndonesia(strtotime($item->authorized_at),1) : '-'
];
});
// Calculate the page count
$pageCount = ceil($totalRecords / $size);
// Calculate the current page number
$currentPage = max(1, $request->get('page', 1));
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
}

View File

@@ -0,0 +1,226 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
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
{
public $user;
/**
* 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 specified resource.
*/
public function show($permohonan_id, $dokumen_id, $jaminan_id)
{
$back = route('laporan-penilai-jaminan.index');
return $this->previewLaporanService->previewLaporan($permohonan_id, $dokumen_id, $jaminan_id, $back);
}
public function dataForDatatables(Request $request)
{
$user = auth()->user();
// Check permissions
if (is_null($this->user) || !$this->user->can('debitur.view')) {
// abort(403, 'Sorry! You are not allowed to view users.');
}
$userRole = $user->roles->pluck('name')->first();
$regionId = null;
// If user is senior-officer, get their regionId
if ($userRole === 'senior-officer') {
$userTeam = TeamsUsers::with('team')->firstWhere('user_id', $user->id);
$regionId = $userTeam?->team->regions_id;
}
$paramsSearch = null;
// 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 = 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]);
});
});
}
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 . '%');
});
}
}
// dd($search->search);
if (isset($search->search)) {
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search->search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('debiture', DB::raw('LOWER(name)'), 'LIKE', '%' . strtolower($search->search) . '%');
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhere('status', 'LIKE', '%' . $search->search . '%');
});
}
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get data with necessary relationships
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian', 'dokumenjaminan.jenisJaminan','nilaiPlafond', 'penilai', 'dokumenjaminan.inspeksi'])->get();
// Calculate the page count
$pageCount = ceil($totalRecords / $size);
// Calculate the current page number
$currentPage = max(1, $request->get('page', 1));
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
public function export(Request $request)
{
$startDate = $request->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);
return Excel::download(
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

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

View File

@@ -0,0 +1,125 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\StatusPermohonan;
use Modules\Lpj\Exports\LaporanPermohonanExport;
use Maatwebsite\Excel\Facades\Excel;
use Illuminate\Support\Facades\Auth;
class LaporanPermohonanController extends Controller
{
public $user;
public function index()
{
return view('lpj::laporan_permohonan.index');
}
public function export(Request $request)
{
return Excel::download(new LaporanPermohonanExport($request), 'laporan_permohonan.xlsx');
}
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('debitur.view')) {
//abort(403, 'Sorry! You are not allowed to view users.');
}
// Retrieve data from the database
$query = Permohonan::query();
$query->where('status','done');
if (!Auth::user()->hasAnyRole(['administrator'])) {
$query = $query->where('branch_id', Auth::user()->branch_id);
}
$query = $query->orderBy('nomor_registrasi', 'desc');
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = json_decode($request->get('search'));
if (isset($search->start_date) || isset($search->end_date)) {
$query->whereBetween('tanggal_permohonan', [
$search->start_date ?? '1900-01-01',
$search->end_date ?? now()->toDateString()
]);
}
// Filter by status if provided
if (isset($search->status) && !empty($search->status)) {
$query->where('status', $search->status);
}
// Filter by branch if provided
if (isset($search->branch_id) && !empty($search->branch_id)) {
$query->where('branch_id', $search->branch_id);
}
if(isset($search->search)) {
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search->search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('jenisFasilitasKredit', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhereRelation('jenisPenilaian', 'name', 'LIKE', '%' . $search->search . '%');
$q->orWhere('status', 'LIKE', '%' . $search->search . '%');
});
}
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
$size = $request->get('size', 10);
if ($size == 0) {
$size = 10;
}
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'penilaian','documents','jenisFasilitasKredit', 'jenisPenilaian'])->get();
// Calculate the page count
$pageCount = ceil($totalRecords / $size);
// Calculate the current page number
$currentPage = max(1, $request->get('page', 1));
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Modules\Lpj\Services\LaporanSLAPenilaiService;
class LaporanSLAPenilaiController extends Controller
{
private $laporanSLAPenilaiService;
public function __construct()
{
$this->laporanSLAPenilaiService = app(LaporanSLAPenilaiService::class);
}
/**
* Display a listing of the resource.
*/
public function index()
{
return view('lpj::laporan-sla-penilai.index');
}
public function dataForDatatableSLaPenilai(Request $request)
{
return $this->laporanSLAPenilaiService->dataForDatatables($request);
}
}

View File

@@ -0,0 +1,304 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Lpj\Models\LaporanSlik;
use Modules\Lpj\Models\Slik;
use Modules\Lpj\Exports\LaporanSlikExport;
class LaporanSlikController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
return view('lpj::laporan-slik.index');
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request): JsonResponse
{
try {
$request->validate([
'slik_id' => 'required|exists:sliks,id'
]);
$slik = Slik::findOrFail($request->slik_id);
// Cek apakah data sudah ada di laporan_slik
$existing = LaporanSlik::where('slik_id', $slik->id)->first();
if ($existing) {
return response()->json([
'success' => false,
'message' => 'Data sudah ada di laporan SLIK'
], 422);
}
// Copy data dari tabel slik ke laporan_slik
$laporanSlik = LaporanSlik::create([
'slik_id' => $slik->id,
'sandi_bank' => $slik->sandi_bank,
'kode_kantor' => $slik->kode_kantor,
'kode_cabang' => $slik->kode_cabang,
'tahun' => $slik->tahun,
'bulan' => $slik->bulan,
'no_rekening' => $slik->no_rekening,
'cif' => $slik->cif,
'kode_jenis' => $slik->kode_jenis,
'kode_jenis_ket' => $slik->kode_jenis_ket,
'kode_sifat' => $slik->kode_sifat,
'kode_sifat_ket' => $slik->kode_sifat_ket,
'kode_valuta' => $slik->kode_valuta,
'kode_valuta_ket' => $slik->kode_valuta_ket,
'baki_debet' => $slik->baki_debet,
'kolektibilitas' => $slik->kolektibilitas,
'kolektibilitas_ket' => $slik->kolektibilitas_ket,
'tanggal_mulai' => $slik->tanggal_mulai,
'tanggal_jatuh_tempo' => $slik->tanggal_jatuh_tempo,
'tanggal_selesai' => $slik->tanggal_selesai,
'tanggal_restrukturisasi' => $slik->tanggal_restrukturisasi,
'kode_sebab_macet' => $slik->kode_sebab_macet,
'kode_sebab_macet_ket' => $slik->kode_sebab_macet_ket,
'tanggal_macet' => $slik->tanggal_macet,
'kode_kondisi' => $slik->kode_kondisi,
'kode_kondisi_ket' => $slik->kode_kondisi_ket,
'tanggal_kondisi' => $slik->tanggal_kondisi,
'nilai_agunan' => $slik->nilai_agunan,
'nilai_agunan_ket' => $slik->nilai_agunan_ket,
'jenis_agunan' => $slik->jenis_agunan,
'kode_agunan' => $slik->kode_agunan,
'kode_agunan_ket' => $slik->kode_agunan_ket,
'peringkat_agunan' => $slik->peringkat_agunan,
'peringkat_agunan_ket' => $slik->peringkat_agunan_ket,
'nama_debitur' => $slik->nama_debitur,
'npwp' => $slik->npwp,
'no_ktp' => $slik->no_ktp,
'no_telp' => $slik->no_telp,
'kode_kab_kota' => $slik->kode_kab_kota,
'kode_kab_kota_ket' => $slik->kode_kab_kota_ket,
'kode_negara_domisili' => $slik->kode_negara_domisili,
'kode_negara_domisili_ket' => $slik->kode_negara_domisili_ket,
'kode_pos' => $slik->kode_pos,
'alamat' => $slik->alamat,
'fasilitas' => $slik->fasilitas,
'status_agunan' => $slik->status_agunan,
'tanggal_lapor' => $slik->tanggal_lapor,
'status' => 'active',
'created_by' => auth()->id(),
'updated_by' => auth()->id(),
]);
// Hapus data dari tabel slik setelah berhasil dipindahkan
$slik->delete();
return response()->json([
'success' => true,
'message' => 'Data berhasil dipindahkan ke laporan SLIK',
'data' => $laporanSlik
]);
} catch (\Exception $e) {
Log::error('Error moving SLIK to laporan: ' . $e->getMessage());
return response()->json([
'success' => false,
'message' => 'Terjadi kesalahan saat memindahkan data'
], 500);
}
}
/**
* Data untuk datatables dengan server-side processing
*
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function dataForDatatables(Request $request)
{
try {
// Retrieve data from the database
$query = LaporanSlik::query();
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('sandi_bank', 'LIKE', "%$search%")
->orWhere('no_rekening', 'LIKE', "%$search%")
->orWhere('cif', 'LIKE', "%$search%")
->orWhere('nama_debitur', 'LIKE', "%$search%")
->orWhere('fasilitas', 'LIKE', "%$search%")
->orWhere('status_agunan', 'LIKE', "%$search%");
});
}
// Apply year filter
if ($request->has('year') && !empty($request->get('year'))) {
$query->where('tahun', $request->get('year'));
}
// Apply month filter
if ($request->has('month') && !empty($request->get('month'))) {
$query->where('bulan', $request->get('month'));
}
// Apply sandi bank filter
if ($request->has('sandi_bank') && !empty($request->get('sandi_bank'))) {
$query->where('sandi_bank', $request->get('sandi_bank'));
}
// Apply kolektibilitas filter
if ($request->has('kolektibilitas') && !empty($request->get('kolektibilitas'))) {
$query->where('kolektibilitas', $request->get('kolektibilitas'));
}
// Apply status filter
if ($request->has('status') && !empty($request->get('status'))) {
$query->where('status', $request->get('status'));
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField', 'created_at');
$query->orderBy($column, $order);
} else {
$query->orderBy('created_at', 'desc');
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->get();
// Transform data untuk datatables
$transformedData = $data->map(function ($item) {
return [
'id' => $item->id,
'sandi_bank' => $item->sandi_bank,
'tahun' => $item->tahun,
'bulan' => $item->bulan,
'no_rekening' => $item->no_rekening,
'cif' => $item->cif,
'nama_debitur' => $item->nama_debitur,
'kolektibilitas' => $item->kolektibilitas,
'kolektibilitas_badge' => $item->kolektibilitas_badge ?? '',
'fasilitas' => $item->fasilitas,
'nilai_agunan' => $item->nilai_agunan_formatted ?? '',
'status_agunan' => $item->status_agunan,
'status_badge' => $item->status_badge ?? '',
'created_by' => $item->creator?->name ?? '-',
'created_at' => dateFormat($item->created_at, true) ?? $item->created_at->format('d/m/Y H:i')
];
});
// Calculate the page count
$pageCount = ceil($totalRecords / ($request->get('size', 10)));
// Calculate the current page number
$currentPage = $request->get('page', 1);
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $transformedData,
]);
} catch (\Exception $e) {
Log::error('Error in laporan slik datatables: ' . $e->getMessage());
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => 0,
'recordsFiltered' => 0,
'pageCount' => 0,
'page' => 1,
'totalCount' => 0,
'data' => [],
]);
}
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\View\View
*/
public function show($id)
{
try {
$laporanSlik = LaporanSlik::findOrFail($id);
return view('lpj::laporan-slik.show', compact('laporanSlik'));
} catch (\Exception $e) {
Log::error('Error showing laporan slik: ' . $e->getMessage());
return back()->with('error', 'Data tidak ditemukan');
}
}
/**
* Export laporan SLIK to Excel
*/
public function export(Request $request)
{
try {
$query = LaporanSlik::query();
// Apply filters
if ($request->has('search') && $request->search) {
$search = $request->search;
$query->where(function($q) use ($search) {
$q->where('nama_debitur', 'like', "%{$search}%")
->orWhere('no_rekening', 'like', "%{$search}%")
->orWhere('cif', 'like', "%{$search}%");
});
}
if ($request->has('year') && $request->year) {
$query->where('tahun', $request->year);
}
if ($request->has('month') && $request->month) {
$query->where('bulan', $request->month);
}
if ($request->has('status') && $request->status) {
$query->where('status', $request->status);
}
$filename = 'laporan-slik-' . now()->format('Y-m-d-His') . '.xlsx';
return Excel::download(new LaporanSlikExport($query), $filename);
} catch (\Exception $e) {
Log::error('Error exporting laporan slik: ' . $e->getMessage());
return back()->with('error', 'Gagal export data: ' . $e->getMessage());
}
}
}

View File

@@ -0,0 +1,51 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Lpj\Exports\LaporanUserLimitExport;
use Modules\Lpj\Services\LaporanUserService;
class LaporanUserController extends Controller
{
private $laporanUserService;
public function __construct(LaporanUserService $laporanUserService)
{
$this->laporanUserService = $laporanUserService;
}
/**
* Display a listing of the resource.
*/
public function index()
{
// $user = $this->laporanUserService->getUserPemohon();
return view('lpj::laporan-user.index');
}
public function searchUserPemohon(Request $request)
{
$search = $request->get('search');
$user = $this->laporanUserService->getUserPemohon($search);
return response()->json($user);
}
public function dataTableForUserPemohon(Request $request)
{
return $this->laporanUserService->dataForDatatables($request);
}
public function export(Request $request)
{
$startDate = $request->start_date;
$endDate = $request->end_date;
// name of the file
$fileName = 'laporan_user_limit' . $startDate . '_' . $endDate . '.xlsx';
return Excel::download(new LaporanUserLimitExport($request), $fileName);
}
}

View File

@@ -0,0 +1,558 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use Exception;
use Modules\Lpj\Models\Noc;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Modules\Lpj\Models\Permohonan;
use Illuminate\Support\Facades\Log;
use App\Http\Controllers\Controller;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Support\Facades\Storage;
class MemoController extends Controller
{
public $user;
/**
* Menampilkan halaman index memo penyelesaian
*
* @return \Illuminate\View\View
*/
public function index()
{
Log::info('MemoController: Mengakses halaman index memo penyelesaian');
return view('lpj::memo.index');
}
/**
* Menampilkan form untuk membuat memo penyelesaian dengan data yang dipilih
*
* @param Request $request
* @return \Illuminate\View\View
*/
public function create(Request $request)
{
Log::info('MemoController: Mengakses halaman create memo penyelesaian');
$selectedIds = $request->get('selected_ids', []);
// Pastikan $selectedIds selalu berupa array
if (is_string($selectedIds)) {
$selectedIds = explode(',', $selectedIds);
}
// Filter array untuk menghilangkan nilai kosong
$selectedIds = array_filter($selectedIds, function($id) {
return !empty(trim($id));
});
$permohonanList = [];
$totalBiayaPJ = 0;
if (!empty($selectedIds) && count($selectedIds) > 0) {
try {
$permohonanList = Permohonan::with([
'user',
'debiture',
'branch',
'tujuanPenilaian',
'penilaian',
'jenisFasilitasKredit',
'documents.inspeksi',
'penilai',
'documents.detail',
'noc'
])->whereIn('id', $selectedIds)->get();
// Hitung total biaya PJ dari nominal_bayar di tabel NOC
$totalBiayaPJ = Noc::whereIn('permohonan_id', $selectedIds)
->sum('nominal_bayar');
Log::info('MemoController: Total Biaya PJ dihitung: ' . $totalBiayaPJ);
} catch (Exception $e) {
Log::error('MemoController: Error saat mengambil data permohonan - ' . $e->getMessage());
return redirect()->back()->with('error', 'Terjadi kesalahan saat memuat data');
}
}
return view('lpj::memo.create', compact('permohonanList', 'totalBiayaPJ'));
}
/**
* Menyimpan memo penyelesaian yang telah dibuat
*
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(Request $request)
{
Log::info('MemoController: Memulai proses penyimpanan memo penyelesaian');
DB::beginTransaction();
try {
// Validasi input
$request->validate([
'permohonan_ids' => 'required|array',
'permohonan_ids.*' => 'exists:permohonan,id',
'memo_number' => 'required|string|max:255',
'payment_date' => 'required|date',
'memo_date' => 'required|date'
]);
$permohonanIds = $request->permohonan_ids;
$memoNumber = $request->memo_number;
$paymentDate = $request->payment_date;
$memoDate = $request->memo_date;
// Update status permohonan yang dipilih
foreach ($permohonanIds as $permohonanId) {
$permohonan = Permohonan::find($permohonanId);
if ($permohonan) {
$permohonan->status = 'memo-penyelesaian';
$permohonan->memo_penyelesaian_number = $memoNumber;
$permohonan->memo_penyelesaian_date = $memoDate;
$permohonan->memo_penyelesaian_payment_date = $paymentDate;
$permohonan->memo_penyelesaian_created_at = now();
//$permohonan->save();
Log::info('MemoController: Berhasil update permohonan ID: ' . $permohonanId);
}
}
DB::commit();
Log::info('MemoController: Berhasil menyimpan memo penyelesaian untuk ' . count($permohonanIds) . ' permohonan');
return redirect()->route('memo.index')
->with('success', 'Memo penyelesaian berhasil dibuat untuk ' . count($permohonanIds) . ' permohonan');
} catch (Exception $e) {
DB::rollback();
Log::error('MemoController: Error saat menyimpan memo penyelesaian - ' . $e->getMessage());
return redirect()->back()
->withInput()
->with('error', 'Terjadi kesalahan saat menyimpan memo penyelesaian: ' . $e->getMessage());
}
}
/**
* Menampilkan detail memo penyelesaian
*
* @param int $id
* @return \Illuminate\View\View
*/
public function show($id)
{
Log::info('MemoController: Mengakses detail memo penyelesaian ID: ' . $id);
$permohonan = Permohonan::with([
'user',
'debiture',
'branch',
'tujuanPenilaian',
'penilaian',
'jenisFasilitasKredit',
'documents.inspeksi',
'penilai',
'documents.detail',
'noc'
])->findOrFail($id);
return view('lpj::memo.show', compact('permohonan'));
}
/**
* Mengambil data untuk datatables pada halaman memo penyelesaian
*
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function dataForDatatables(Request $request)
{
Log::info('MemoController: Mengambil data untuk datatables');
if (is_null($this->user) || !$this->user->can('debitur.view')) {
Log::warning('MemoController: User tidak memiliki permission untuk melihat data');
// abort(403, 'Sorry! You are not allowed to view users.');
}
// Mengambil data dari database dengan kondisi yang sama seperti LaporanController
$query = Permohonan::query()
->whereIn('status', ['proses-laporan', 'done', 'paparan', 'proses-paparan', 'memo-penyelesaian'])
/*->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]);
})*/
->whereHas('noc'); // Hanya tampilkan permohonan yang memiliki NOC
$query = $query->orderBy('nomor_registrasi', 'desc');
// Apply search filter jika ada
if ($request->has('search') && !empty($request->get('search'))) {
$searchParams = explode('|', $request->get('search'));
$filterJenisPenilaian = $searchParams[0] ?? '';
$searchTerm = $searchParams[1] ?? '';
// Filter berdasarkan jenis penilaian
if (!empty($filterJenisPenilaian)) {
$query->where('jenis_penilaian_id', $filterJenisPenilaian);
Log::info('Applied jenis penilaian filter', ['filter' => $filterJenisPenilaian]);
}
$query->where(function ($q) use ($searchTerm) {
$q->where('nomor_registrasi', 'LIKE', '%' . $searchTerm . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $searchTerm . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $searchTerm . '%');
$q->orWhereRelation('debiture', 'name', 'LIKE', '%' . $searchTerm . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $searchTerm . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $searchTerm . '%');
$q->orWhere('status', 'LIKE', '%' . $searchTerm . '%');
});
}
// Apply sorting jika ada
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Mendapatkan total count records
$totalRecords = $query->count();
$size = $request->get('size', 10);
if ($size == 0) {
$size = 10;
}
// Apply pagination jika ada
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size;
$query->skip($offset)->take($size);
}
// Mendapatkan filtered count records
$filteredRecords = $query->count();
// Mendapatkan data untuk halaman saat ini
$data = $query->with([
'user',
'debiture',
'branch',
'tujuanPenilaian',
'jenisPenilaian',
'penilaian',
'jenisFasilitasKredit',
'documents.inspeksi',
'penilai',
'documents.detail',
'noc'
])->get();
// Menghitung page count
$pageCount = ceil($totalRecords / $size);
// Menghitung current page number
$currentPage = max(1, $request->get('page', 1));
Log::info('MemoController: Berhasil mengambil data datatables - Total: ' . $totalRecords . ', Filtered: ' . $filteredRecords);
// Return response data sebagai JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
/**
* Mengambil total biaya PJ berdasarkan permohonan yang dipilih
*
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function getTotalBiayaPJ(Request $request)
{
Log::info('MemoController: Mengambil total biaya PJ');
try {
$permohonanIds = $request->get('permohonan_ids', []);
// Pastikan $permohonanIds selalu berupa array
if (is_string($permohonanIds)) {
$permohonanIds = explode(',', $permohonanIds);
}
// Filter array untuk menghilangkan nilai kosong
$permohonanIds = array_filter($permohonanIds, function($id) {
return !empty(trim($id));
});
$totalBiayaPJ = 0;
if (!empty($permohonanIds) && count($permohonanIds) > 0) {
// Hitung total biaya PJ dari nominal_bayar di tabel NOC
$totalBiayaPJ = \Modules\Lpj\Models\Noc::whereIn('permohonan_id', $permohonanIds)
->sum('nominal_bayar');
}
Log::info('MemoController: Total Biaya PJ berhasil dihitung: ' . $totalBiayaPJ);
return response()->json([
'success' => true,
'total_biaya_pj' => $totalBiayaPJ,
'total_biaya_pj_formatted' => 'Rp ' . number_format($totalBiayaPJ, 0, ',', '.')
]);
} catch (Exception $e) {
Log::error('MemoController: Error saat menghitung total biaya PJ - ' . $e->getMessage());
return response()->json([
'success' => false,
'message' => 'Terjadi kesalahan saat menghitung total biaya PJ'
], 500);
}
}
/**
* Menampilkan preview memo penyelesaian sebelum menyimpan
*
* @param Request $request
* @return \Illuminate\View\View
*/
public function preview(Request $request)
{
Log::info('MemoController: Mengakses halaman preview memo penyelesaian');
$permohonanIds = $request->permohonan_ids;
$memoNumber = $request->memo_number;
$paymentDate = $request->payment_date;
$memoDate = $request->memo_date;
try {
// Ambil data permohonan yang dipilih
$permohonanList = Permohonan::with([
'user',
'debiture',
'branch',
'penilaian',
'jenisPenilaian',
'jenisFasilitasKredit',
'documents.inspeksi',
'penilai',
'documents.detail',
'noc'
])->whereIn('id', $permohonanIds);
// Hitung total biaya PJ dari nominal_bayar di tabel NOC
$totalBiayaPJ = Noc::whereIn('permohonan_id', $permohonanIds)
->sum('nominal_bayar');
// Data untuk template memo
$memoData = [
'memo_number' => $memoNumber,
'memo_date' => $memoDate,
'payment_date' => $paymentDate,
'total_biaya_pj' => $totalBiayaPJ,
'permohonan_list' => $permohonanList->get(),
'debitur_count' => $permohonanList->get()->count(),
'jaminan_info' => $this->getJaminanInfo($permohonanList->get()),
'jenisPenilaian' => $permohonanList->pluck('jenis_penilaian_id')->first()
];
$permohonanList= $permohonanList->get();
Log::info('MemoController: Data preview memo berhasil disiapkan');
return view('lpj::memo.preview', compact('memoData', 'permohonanList', 'totalBiayaPJ'));
} catch (Exception $e) {
Log::error('MemoController: Error saat menyiapkan preview memo - ' . $e->getMessage());
return redirect()->back()
->withInput()
->with('error', 'Terjadi kesalahan saat menyiapkan preview memo: ' . $e->getMessage());
}
}
/**
* Generate PDF memo penyelesaian dan simpan ke database
*
* @param Request $request
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function generatePdf(Request $request)
{
Log::info('MemoController: Memulai generate PDF memo penyelesaian');
DB::beginTransaction();
try {
// Validasi input
$permohonanIds = $request->permohonan_ids;
$memoNumber = $request->memo_number;
$paymentDate = $request->payment_date;
$memoDate = $request->memo_date;
// Ambil data permohonan yang dipilih
$permohonanList = Permohonan::with([
'user',
'debiture',
'branch',
'penilaian',
'jenisPenilaian',
'jenisFasilitasKredit',
'documents.inspeksi',
'penilai',
'documents.detail',
'noc'
])->whereIn('id', $permohonanIds);
// Hitung total biaya PJ dari nominal_bayar di tabel NOC
$totalBiayaPJ = Noc::whereIn('permohonan_id', $permohonanIds)
->sum('nominal_bayar');
// Data untuk template memo
$memoData = [
'memo_number' => $memoNumber,
'memo_date' => $memoDate,
'payment_date' => $paymentDate,
'total_biaya_pj' => $totalBiayaPJ,
'permohonan_list' => $permohonanList->get(),
'debitur_count' => $permohonanList->get()->count(),
'jaminan_info' => $this->getJaminanInfo($permohonanList->get()),
'jenisPenilaian' => $permohonanList->pluck('jenis_penilaian_id')->first()
];
$permohonanList= $permohonanList->get();
// Generate PDF dari template
$pdf = Pdf::loadView('lpj::memo.pdf-template', compact('memoData', 'permohonanList', 'totalBiayaPJ'))
->setPaper('a4', 'portrait')
->setOptions([
'defaultFont' => 'Times-Roman',
'isRemoteEnabled' => true,
'isHtml5ParserEnabled' => true,
'isPhpEnabled' => true,
'dpi' => 150,
'defaultPaperSize' => 'a4',
'chroot' => public_path(),
]);
// Nama file PDF
$fileName = 'memo-penyelesaian-' . str_replace(['/', ' '], ['-', '-'], $memoNumber) . '-' . date('Y-m-d-H-i-s') . '.pdf';
$filePath = 'memo-penyelesaian/' . $fileName;
// Simpan PDF ke storage
Storage::disk('public')->put($filePath, $pdf->output());
// Update status permohonan yang dipilih
// Update data di tabel NOC untuk setiap permohonan
foreach ($permohonanIds as $permohonanId) {
// Cari NOC berdasarkan permohonan_id
$noc = Noc::where('permohonan_id', $permohonanId)->first();
if ($noc) {
// Update field memo penyelesaian di tabel NOC
$noc->memo_penyelesaian = $filePath;
$noc->memo_penyelesaian_number = $memoNumber;
$noc->memo_penyelesaian_date = $memoDate;
$noc->memo_penyelesaian_payment_date = $paymentDate;
$noc->memo_penyelesaian_created_at = now();
$noc->save();
Log::info('MemoController: Berhasil update NOC untuk permohonan ID: ' . $permohonanId);
} else {
Log::warning('MemoController: NOC tidak ditemukan untuk permohonan ID: ' . $permohonanId);
}
}
DB::commit();
Log::info('MemoController: Berhasil generate PDF dan menyimpan memo penyelesaian untuk ' . count($permohonanIds) . ' permohonan');
// Return PDF untuk download
return $pdf->download('memo-penyelesaian-' . $memoNumber . '.pdf');
} catch (Exception $e) {
DB::rollback();
Log::error('MemoController: Error saat generate PDF memo penyelesaian - ' . $e->getMessage());
return redirect()->back()
->with('error', 'Terjadi kesalahan saat generate PDF memo penyelesaian: ' . $e->getMessage())
->withInput();
}
}
/**
* Helper function untuk mendapatkan informasi jaminan
*
* @param $permohonanList
* @return string
*/
private function getJaminanInfo($permohonanList)
{
$jaminanTypes = [];
foreach ($permohonanList as $permohonan) {
if ($permohonan->tujuanPenilaian) {
$jaminanTypes[] = $permohonan->tujuanPenilaian->name;
}
}
$uniqueJaminan = array_unique($jaminanTypes);
return implode(' & ', $uniqueJaminan);
}
/**
* Download PDF memo penyelesaian
*
* @param int $id - ID permohonan
* @return \Illuminate\Http\Response
*/
public function downloadPdf($id)
{
Log::info('MemoController: Download PDF memo penyelesaian untuk permohonan ID: ' . $id);
try {
// Cari NOC berdasarkan permohonan_id
$noc = Noc::where('permohonan_id', $id)->first();
if (!$noc || !$noc->memo_penyelesaian) {
Log::warning('MemoController: PDF memo penyelesaian tidak ditemukan untuk permohonan ID: ' . $id);
return redirect()->back()->with('error', 'File PDF memo penyelesaian tidak ditemukan.');
}
// Cek apakah file ada di storage
if (!Storage::disk('public')->exists($noc->memo_penyelesaian)) {
Log::warning('MemoController: File PDF tidak ada di storage: ' . $noc->memo_penyelesaian);
return redirect()->back()->with('error', 'File PDF tidak ditemukan di server.');
}
// Download file
$fileName = 'memo-penyelesaian-' . $noc->memo_penyelesaian_number . '.pdf';
Log::info('MemoController: Berhasil download PDF memo penyelesaian: ' . $fileName);
return Storage::disk('public')->download($noc->memo_penyelesaian, $fileName);
} catch (Exception $e) {
Log::error('MemoController: Error saat download PDF memo penyelesaian - ' . $e->getMessage());
return redirect()->back()->with('error', 'Terjadi kesalahan saat mengunduh file PDF.');
}
}
}

View File

@@ -5,6 +5,8 @@
use App\Http\Controllers\Controller;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Lpj\Exports\NilaiPlafondExport;
use Modules\Lpj\Http\Requests\NilaiPlafondRequest;
@@ -14,137 +16,239 @@
{
public $user;
/**
* Menampilkan halaman daftar Nilai Plafond.
* Log setiap akses dan sebelum return view.
*/
public function index()
{
return view('lpj::nilai_plafond.index');
Log::info('NilaiPlafondController@index: akses halaman index');
return \view('lpj::nilai_plafond.index');
}
/**
* 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
NilaiPlafond::create($validate);
return redirect()
$record = NilaiPlafond::create($validate);
DB::commit();
Log::info('NilaiPlafondController@store: simpan berhasil', ['id' => $record->id]);
return \redirect()
->route('basicdata.nilai-plafond.index')
->with('success', 'Jenis Aset created successfully');
->with('success', 'Nilai Plafond berhasil dibuat');
} catch (Exception $e) {
return redirect()
DB::rollBack();
Log::error('NilaiPlafondController@store: simpan gagal', ['error' => $e->getMessage()]);
return \redirect()
->route('basicdata.nilai-plafond.create')
->with('error', 'Failed to create nilai plafond');
->with('error', 'Gagal membuat Nilai Plafond');
}
}
}
/**
* Menampilkan form pembuatan Nilai Plafond.
* Log akses sebelum return view.
*/
public function create()
{
return view('lpj::nilai_plafond.create');
Log::info('NilaiPlafondController@create: akses halaman create');
return \view('lpj::nilai_plafond.create');
}
/**
* Menampilkan form edit Nilai Plafond berdasarkan ID.
* Gunakan transaksi untuk pembacaan data dan logging.
*/
public function edit($id)
{
$nilaiPlafond = NilaiPlafond::find($id);
return view('lpj::nilai_plafond.create', compact('nilaiPlafond'));
Log::info('NilaiPlafondController@edit: mulai proses edit', ['id' => $id]);
DB::beginTransaction();
try {
$nilaiPlafond = NilaiPlafond::find($id);
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');
}
}
/**
* 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);
return redirect()
DB::commit();
Log::info('NilaiPlafondController@update: update berhasil', ['id' => $id]);
return \redirect()
->route('basicdata.nilai-plafond.index')
->with('success', 'Jenis Aset updated successfully');
->with('success', 'Nilai Plafond berhasil diperbarui');
} catch (Exception $e) {
return redirect()
DB::rollBack();
Log::error('NilaiPlafondController@update: update gagal', ['id' => $id, 'error' => $e->getMessage()]);
return \redirect()
->route('basicdata.nilai-plafond.edit', $id)
->with('error', 'Failed to update nilai plafond');
->with('error', 'Gagal memperbarui Nilai Plafond');
}
}
}
/**
* 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);
$nilaiPlafond->delete();
if (!$nilaiPlafond) {
DB::rollBack();
Log::warning('NilaiPlafondController@destroy: data tidak ditemukan', ['id' => $id]);
return \response()->json(['success' => false, 'message' => 'Data Nilai Plafond tidak ditemukan']);
}
echo json_encode(['success' => true, 'message' => 'Jenis Aset deleted successfully']);
$nilaiPlafond->delete();
DB::commit();
Log::info('NilaiPlafondController@destroy: hapus berhasil', ['id' => $id]);
return \response()->json(['success' => true, 'message' => 'Nilai Plafond berhasil dihapus']);
} catch (Exception $e) {
echo json_encode(['success' => false, 'message' => 'Failed to delete nilai plafond']);
DB::rollBack();
Log::error('NilaiPlafondController@destroy: hapus gagal', ['id' => $id, 'error' => $e->getMessage()]);
return \response()->json(['success' => false, 'message' => 'Gagal menghapus Nilai Plafond']);
}
}
/**
* 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.');
}
// Retrieve data from the database
$query = NilaiPlafond::query();
DB::beginTransaction();
try {
// Retrieve data from the database
$query = NilaiPlafond::query();
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('code', 'LIKE', "%$search%");
$q->orWhere('name', 'LIKE', "%$search%");
});
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('code', 'LIKE', "%$search%");
$q->orWhere('name', 'LIKE', "%$search%");
});
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->get();
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = 0 + 1;
DB::commit();
Log::info('NilaiPlafondController@dataForDatatables: proses selesai, mengembalikan data');
// Return the response data as a JSON object
return \response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
} 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' => [],
]);
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->get();
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = 0 + 1;
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
/**
* Mengekspor data Nilai Plafond ke Excel.
* Log akses sebelum proses download.
*/
public function export()
{
Log::info('NilaiPlafondController@export: mulai proses export');
return Excel::download(new NilaiPlafondExport, 'nilai_plafond.xlsx');
}
}

View File

@@ -0,0 +1,427 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Modules\Lpj\Http\Requests\NocRequest;
use Modules\Lpj\Models\Bucok;
use Modules\Lpj\Models\Noc;
use Modules\Lpj\Models\PersetujuanPenawaran;
use Modules\Lpj\Models\JenisPenilaian;
class NocController extends Controller
{
public $user;
/**
* Display a listing of the resource.
*/
public function index()
{
return redirect()->route('noc.pembayaran.index');
}
public function pembayaran()
{
$persetujuanPenawarans = PersetujuanPenawaran::all();
$jenisPenilaians = JenisPenilaian::get();
return view('lpj::noc.pembayaran', compact('persetujuanPenawarans', 'jenisPenilaians'));
}
public function penyelesaian()
{
$persetujuanPenawarans = PersetujuanPenawaran::all();
$jenisPenilaians = JenisPenilaian::get();
return view('lpj::noc.penyelesaian', compact('persetujuanPenawarans', 'jenisPenilaians'));
}
/**
* Store a newly created resource in storage.
*/
/**
* Store a newly created resource in storage.
*/
/**
* Store a newly created resource in storage.
*/
public function store(NocRequest $request)
{
$validated = $request->validated();
$validated['updated_by'] = Auth::id();
if (request()->get('status_bayar') == "sudah_bayar") {
$validated['status'] = '1';
}
$dataNoc = [
'nominal_bayar' => $validated['nominal_bayar'],
'total_pembukuan' => $validated['total_pembukuan'],
'tanggal_pembayaran' => $validated['tanggal_pembayaran'] ?? date('Y-m-d'),
'status_bayar' => $validated['nominal_bayar'] < $validated['total_harus_bayar'] ? false : true,
'catatan_noc' => $validated['catatan_noc'] ?? '',
'status_kurang_bayar' => $validated['status_kurang_bayar'] ?? '0',
'status_lebih_bayar' => $validated['status_lebih_bayar'] ?? '0',
'nominal_kurang_bayar' => $validated['nominal_kurang_bayar'] ?? '0',
'nominal_lebih_bayar' => $validated['nominal_lebih_bayar'] ?? '0',
'bukti_pengembalian' => $validated['bukti_pengembalian'] ?? '',
];
if($validated['permohonan_id']){
$noc = Noc::updateOrCreate(
[
'permohonan_id' => $validated['permohonan_id'],
'persetujuan_penawaran_id' => $validated['persetujuan_penawaran_id'],
],
$dataNoc,
);
} else {
$noc = Noc::updateOrCreate(
[
'persetujuan_penawaran_id' => $validated['persetujuan_penawaran_id'],
],
$dataNoc,
);
}
$folderPath = 'noc/' . request()->get('persetujuan_penawaran_id') . '/bukti_ksl/';
if ($request->hasFile('bukti_ksl')) {
$noc->bukti_ksl = $request->file('bukti_ksl')->store(
$folderPath,
'public',
);
}
$noc->save();
$bucok = Bucok::where('nomor_tiket', $noc->nomor_tiket)->orWhere('permohonan_id', $noc->permohonan_id)->first();
if($bucok){
$bucok->nominal_penyelesaian = $noc->total_pembukuan ?? '';
$bucok->tanggal_penyelesaian = $noc->tanggal_pembayaran ?? date('Y-m-d');
$bucok->penyelesaian = 'Selesai';
$bucok->save();
}
return redirect()
->route('noc.index')->with('success', 'NOC berhasil disimpan.');
}
/**
* Update the specified resource in storage.
*/
public function update(NocRequest $request, PersetujuanPenawaran $persetujuanPenawaran)
{
$validated = $request->validated();
if($request->get('is_memo')){
$memo = Noc::find($request->get('is_memo'));
$folderPath = 'noc/' . request()->get('persetujuan_penawaran_id') . '/memo_penyelesaian/';
if ($request->hasFile('memo_penyelesaian')) {
$memo->memo_penyelesaian = $request->file('memo_penyelesaian')->store(
$folderPath,
'public',
);
}
$memo->catatan_noc = $validated['catatan_noc'];
$memo->save();
return redirect()
->route('laporan.index')->with('success', 'Memo Penyelesaian updated successfully');
}
$dataNoc = [
'total_pembukuan' => $validated['total_pembukuan'],
'nominal_penyelesaian' => $validated['nominal_penyelesaian'],
'tanggal_penyelesaian' => $validated['tanggal_penyelesaian'] ?? date('Y-m-d'),
'status_pelunasan' => ((int)$validated['nominal_bayar'] + (int)$validated['nominal_penyelesaian']) === (int)$validated['total_harus_bayar'] ? true : false,
'catatan_noc' => $validated['catatan_noc'],
];
$noc = Noc::updateOrCreate(
[
'permohonan_id' => $validated['permohonan_id'],
'permohonan_id' => $validated['permohonan_id'],
'persetujuan_penawaran_id' => $validated['persetujuan_penawaran_id'],
],
$dataNoc,
);
$folderPath = 'noc/' . request()->get('persetujuan_penawaran_id') . '/bukti_penyelesaian/';
if ($request->hasFile('bukti_penyelesaian')) {
$noc->bukti_penyelesaian = $request->file('bukti_penyelesaian')->store(
$folderPath,
'public',
);
}
$noc->save();
return redirect()
->route('noc.index')->with('success', 'NOC updated successfully');
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view('lpj::noc.create');
}
/**
* Display the specified resource.
*/
public function show(Noc $noc) {
return view('lpj::noc.memo', compact('noc'));
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
$persetujuanPenawaran = PersetujuanPenawaran::where('id', $id)->first();
return view('lpj::noc.form', compact('persetujuanPenawaran'));
}
/**
* Remove the specified resource from storage.
*/
public function destroy(PersetujuanPenawaran $persetujuanPenawaran)
{
$persetujuanPenawaran->delete();
return redirect()
->route('noc.index')->with('success', 'Persetujuan Penawaran deleted successfully');
}
public function dataForDatatables(Request $request)
{
// Redirect to pembayaran datatables by default
return $this->dataForDatatablesPembayaran($request);
}
public function dataForDatatablesPembayaran(Request $request)
{
if (is_null($this->user) || !$this->user->can('noc.view')) {
//abort(403, 'Sorry! You are not allowed to view persetujuan penawaran.');
}
// Retrieve data from the database
$query = PersetujuanPenawaran::query();
// Filter for pembayaran (where memo_penyelesaian is null)
/*$query->whereDoesntHave('noc', function($q) {
$q->whereNotNull('memo_penyelesaian');
});*/
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->orWhereRelation('penawaran', 'nomor_registrasi', 'LIKE', '%' . $search . '%')
->orWhereRelation('permohonan', 'nomor_registrasi', 'LIKE', '%' . $search . '%')
->orWhereRelation('permohonan.debiture','name', 'LIKE', '%' . $search . '%')
->orWhereRelation('permohonan.jenisPenilaian', 'name', 'LIKE', '%' . $search . '%')
->orWhere('nomor_tiket', 'LIKE', '%' . $search . '%');
});
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->get();
$data = $data->map(function ($persetujuanPenawaran) {
return [
'id' => $persetujuanPenawaran->id,
'nomor_registrasi' => $persetujuanPenawaran->permohonan?->nomor_registrasi ?? $persetujuanPenawaran->penawaran?->nomor_registrasi,
'nomor_tiket' => $persetujuanPenawaran->nomor_tiket ?? '',
'nama_debitur' => $persetujuanPenawaran?->permohonan?->debiture->name ?? $persetujuanPenawaran->penawaran?->permohonan?->debiture->name ?? $persetujuanPenawaran->noc?->debiture->name,
'kode_cabang' => $persetujuanPenawaran?->permohonan?->branch->code ?? $persetujuanPenawaran->penawaran?->permohonan?->branch->code ?? $persetujuanPenawaran->noc?->branch->code,
'cabang' => $persetujuanPenawaran?->permohonan?->branch->name ?? $persetujuanPenawaran->penawaran?->permohonan?->branch->name ?? $persetujuanPenawaran->noc?->branch->name,
'tanggal_pembayaran' => dateFormat(
$persetujuanPenawaran->noc->tanggal_pembayaran ?? $persetujuanPenawaran->noc?->created_at,
true,
),
'nominal_bayar' => currencyFormat($persetujuanPenawaran->nominal_bayar ?? 0,
),
'nominal_diterima' => currencyFormat(
$persetujuanPenawaran->noc->nominal_bayar ?? 0,
),
'jenis_penilaian' => $persetujuanPenawaran->permohonan?->jenisPenilaian?->name ?? "",
'bukti_ksl' => $persetujuanPenawaran->noc->bukti_ksl ?? $persetujuanPenawaran->bukti_ksl ?? null,
'bukti_bayar' => $persetujuanPenawaran->bukti_bayar ?? null,
'updated_at' => dateFormat($persetujuanPenawaran->updated_at, true),
];
})->sortBy('updated_at', 1)->values();
// Calculate total nominal diterima from all filtered data (not just current page)
$totalNominalDiterima = $data->sum(function ($item) {
// Extract numeric value from formatted currency string
$nominal = str_replace(['Rp', '.', ',00'], '', $item['nominal_diterima']);
return (float) $nominal;
});
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = $request->get('page', 1);
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'totalNominalDiterima' => $totalNominalDiterima,
'data' => $data,
]);
}
public function dataForDatatablesPenyelesaian(Request $request)
{
if (is_null($this->user) || !$this->user->can('noc.view')) {
//abort(403, 'Sorry! You are not allowed to view persetujuan penawaran.');
}
// Retrieve data from the database
$query = PersetujuanPenawaran::query();
// Filter for penyelesaian (where memo_penyelesaian is not null)
$query->whereDoesntHave('noc', function($q) {
$q->whereNotNull('memo_penyelesaian');
});
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->orWhereRelation('penawaran', 'nomor_registrasi', 'LIKE', '%' . $search . '%')
->orWhereRelation('permohonan', 'nomor_registrasi', 'LIKE', '%' . $search . '%')
->orWhereRelation('permohonan.debiture','name', 'LIKE', '%' . $search . '%')
->orWhereRelation('permohonan.jenisPenilaian', 'name', 'LIKE', '%' . $search . '%')
->orWhere('nomor_tiket', 'LIKE', '%' . $search . '%'); $q->orWhereRelation('penawaran', 'nomor_registrasi', 'LIKE', '%' . $search . '%')
->orWhereRelation('permohonan', 'nomor_registrasi', 'LIKE', '%' . $search . '%')
->orWhereRelation('permohonan.debiture','name', 'LIKE', '%' . $search . '%')
->orWhereRelation('permohonan.jenisPenilaian', 'name', 'LIKE', '%' . $search . '%')
->orWhere('nomor_tiket', 'LIKE', '%' . $search . '%');
});
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->get();
$data = $data->map(function ($persetujuanPenawaran) {
return [
'id' => $persetujuanPenawaran->id,
'nomor_registrasi' => $persetujuanPenawaran->permohonan?->nomor_registrasi ?? $persetujuanPenawaran->penawaran?->nomor_registrasi ?? '',
'nomor_tiket' => $persetujuanPenawaran->nomor_tiket ?? '',
'nama_debitur' => $persetujuanPenawaran->permohonan?->debiture?->name ?? $persetujuanPenawaran->penawaran?->permohonan?->debiture?->name ?? $persetujuanPenawaran->noc?->debiture?->name,
'kode_cabang' => $persetujuanPenawaran?->permohonan?->branch?->code ?? $persetujuanPenawaran->penawaran?->permohonan?->branch?->code ?? $persetujuanPenawaran->noc?->branch?->code ?? '',
'cabang' => $persetujuanPenawaran->permohonan?->branch?->name ?? $persetujuanPenawaran->penawaran?->permohonan?->branch?->name ?? $persetujuanPenawaran->noc?->branch?->name ?? '',
'tanggal_pembayaran' => dateFormat(
$persetujuanPenawaran->noc->tanggal_pembayaran ?? $persetujuanPenawaran->noc?->created_at,
true,
),
'nominal_bayar' => currencyFormat($persetujuanPenawaran->nominal_bayar ?? 0,
),
'nominal_diterima' => currencyFormat(
$persetujuanPenawaran->noc->nominal_bayar ?? 0,
),
'jenis_penilaian' => $persetujuanPenawaran->permohonan?->jenisPenilaian?->name ?? "",
'bukti_ksl' => $persetujuanPenawaran->noc->bukti_ksl ?? $persetujuanPenawaran->bukti_ksl ?? null,
'bukti_bayar' => $persetujuanPenawaran->bukti_bayar ?? null,
'memo_penyelesaian' => $persetujuanPenawaran->noc->memo_penyelesaian ?? $persetujuanPenawaran->memo_penyelesaian ?? null,
'nominal_penyelesaian' => currencyFormat(
$persetujuanPenawaran->noc->nominal_penyelesaian ?? $persetujuanPenawaran->nominal_penyelesaian ?? 0,
),
'bukti_penyelesaian' => $persetujuanPenawaran->noc->bukti_penyelesaian ?? $persetujuanPenawaran->bukti_penyelesaian ?? null,
'tanggal_penyelesaian' => $persetujuanPenawaran->noc?->tanggal_penyelesaian ? dateFormat(
$persetujuanPenawaran->noc?->tanggal_penyelesaian,
true) : '-',
'updated_at' => dateFormat($persetujuanPenawaran->updated_at, true),
];
})->sortBy('updated_at', 1)->values();
// Calculate total nominal diterima from all filtered data (not just current page)
$totalNominalDiterima = $data->sum(function ($item) {
// Extract numeric value from formatted currency string
$nominal = str_replace(['Rp', '.', ',00'], '', $item['nominal_diterima']);
return (float) $nominal;
});
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = $request->get('page', 1);
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'totalNominalDiterima' => $totalNominalDiterima,
'data' => $data,
]);
}
}

View File

@@ -1,290 +1,431 @@
<?php
namespace Modules\Lpj\Http\Controllers;
namespace Modules\Lpj\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use Exception;
use Maatwebsite\Excel\Facades\Excel;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\DB;
use Modules\Lpj\Models\KJPP;
use Modules\Lpj\Models\PenawaranDetailTender;
use Modules\Lpj\Models\PenawaranDetailTenderLog;
use Modules\Lpj\Models\PenawaranTender;
use App\Http\Controllers\Controller;
use Carbon\Carbon;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Lpj\Models\KJPP;
use Modules\Lpj\Models\PenawaranDetailTender;
use Modules\Lpj\Models\PenawaranDetailTenderLog;
use Modules\Lpj\Models\PenawaranTender;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\Permohonan;
class OtorisasiPenawaranController extends Controller
{
public $user;
/**
* Display a listing of the resource.
*/
public function index()
class OtorisasiPenawaranController extends Controller
{
// dd('hai otorisasi');
return view('lpj::otorisasipenawaran.index');
}
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('debitur.view')) {
//abort(403, 'Sorry! You are not allowed to view users.');
public $user;
/**
* Display a listing of the resource.
*/
public function index()
{
// dd('hai otorisasi');
return view('lpj::otorisasipenawaran.index');
}
// Retrieve data from the database
$query =PenawaranTender::query()
->select('penawaran.*',DB::raw("CONCAT(DATE_FORMAT(penawaran.start_date, '%d %M %Y'), ' - ', DATE_FORMAT(penawaran.end_date, '%d %M %Y')) AS date_range"), 'tujuan_penilaian_kjpp.name as tujuan_penilaian_kjpp_name')
->leftJoin('tujuan_penilaian_kjpp', 'tujuan_penilaian_kjpp.id','=','penawaran.tujuan_penilaian_kjpp_id')
->where('penawaran.status','=','proposal-tender')
->withCount('penawarandetails');
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
$q->orWhere('status', 'LIKE', '%' . $search . '%');
});
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
//$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian'])->get();
$data = $query->get();
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = 0 + 1;
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data
]);
}
public function edit($id)
{
return view('lpj::otorisasipenawaran.edit', compact('id'));
}
public function setData(Request $request): JsonResponse
{
$data = array();
$penawaran = array();
$penawrandetails = array();
$penawarandetailLogs = array();
if (request()->ajax()) {
$id = $request->id;
$penawaran = PenawaranTender::where('status','=','proposal-tender')->find($id);
if ($penawaran) {
$penawarandetailLogs = PenawaranDetailTenderLog::where('penawaran_id',$id)
->leftJoin('kjpp', 'kjpp.id', '=', 'detail_penawaran_logs.kjpp_rekanan_id')
->select('detail_penawaran_logs.*', DB::raw("DATE_FORMAT(detail_penawaran_logs.created_at, '%d-%m-%Y %H:%i') AS created_at2"),'kjpp.code AS kjpp_code', 'kjpp.name AS kjpp_name')
->get();
$penawrandetails = PenawaranDetailTender::where('penawaran_id','=',$id)
->leftJoin('kjpp', 'kjpp.id', '=', 'detail_penawaran.kjpp_rekanan_id')
->select('detail_penawaran.*', 'kjpp.code AS kjpp_code', 'kjpp.name AS kjpp_name')
->where('detail_penawaran.status','=',1)
->get();
if(sizeof($penawarandetailLogs)>0)
{
$h=0;
foreach($penawarandetailLogs as $obj1)
{
if($obj1->dokumen_persetujuan && Storage::disk('public')->exists($obj1->dokumen_persetujuan))
{
$penawarandetailLogs_path = Storage::url($obj1->dokumen_persetujuan);
$penawarandetailLogs[$h]->dokumen_persetujuan = $penawarandetailLogs_path;
}
$h++;
}
}
$i=0;
foreach($penawrandetails as $obj)
{
if($obj->dokumen_persetujuan && Storage::disk('public')->exists($obj->dokumen_persetujuan))
{
$penawrandetails_path = Storage::url($obj->dokumen_persetujuan);
$penawrandetails[$i]->dokumen_persetujuan = $penawrandetails_path;
}
$i++;
}
$penawaranString = "";
if($penawaran->status)
{
$penawaranString = convertSlug($penawaran->status);
$penawaran->status = $penawaranString;
}
$kjpp=null;
$kjpp = KJPP::pluck('name', 'id');
$data['penawaran'] = $penawaran;
$data['penawrandetails'] = $penawrandetails;
$data['penawarandetailLogs'] = $penawarandetailLogs;
$data['status'] = 'success';
$data['message']['message_success'] = array("data successfully found");
} else {
$data['status'] = 'error';
$data['penawaran'] = null;
$data['penawrandetails'] = null;
$data['message']['message_data'] = array("data not found");
}
} else {
$data['status'] = 'error';
$data['message']['message_ajax'] = array("no ajax request");
}
return response()->json($data);
}
public function otorisasiPenawaranKJPP(Request $request, $id): JsonResponse
{
$data = array();
$dataDetailPenawaranLog=[];
if (request()->ajax()) {
// cek masa aktif penawaran
$detailpenawaran = PenawaranDetailTender::find($id);
$penawaran = PenawaranTender::findOrFail($detailpenawaran->penawaran_id);
$checkActiveDateRange = checkActiveDateRangePenawaran($detailpenawaran->penawaran_id);
// cek masa aktif penawaran
if($checkActiveDateRange)
{
DB::beginTransaction();
try {
// update status KJPP yg tidak terpilih menjadi 2 -> kalah
// update status Penawaran menjadi SPK
// update status Permohonan menjadi SPK
// insert detail_permohonan_log
PenawaranDetailTender::where('status', 1)
->where('penawaran_id', $request->penawaran_id)
->whereNotIn('id', [$id])
->update(['status' => 2,
'updated_by' => Auth::id(),
'updated_at' => now()
]);
PenawaranTender::where('id', $request->penawaran_id)
->update(['status'=>'spk',
'nama_kjpp_sebelumnya'=>$request->kjppName,
'biaya_kjpp_sebelumnya'=>$request->biaya_penawaran,
'tanggal_penilaian_sebelumnya'=>now(),
'authorized_status'=>1,
'authorized_at'=>now(),
'authorized_by'=>Auth::id(),
'updated_by' => Auth::id(),
'updated_at' => now()
]);
Permohonan::where('nomor_registrasi',$request->noReg)
->update(['status'=>'spk',
'updated_by' => Auth::id(),
'updated_at' => now()
]);
// log
$detailPenawaran = PenawaranDetailTender::where('penawaran_id', $request->penawaran_id)->get();
if(sizeof($detailPenawaran)>0)
{
foreach ($detailPenawaran as $model) {
array_push($dataDetailPenawaranLog, [
'detail_penawaran_id' =>$model->id,
'kjpp_rekanan_id' =>$model->kjpp_rekanan_id,
'penawaran_id' =>$model->penawaran_id,
'biaya_penawaran' =>$model->biaya_penawaran,
'attachment' =>$model->attachment,
'dokumen_persetujuan' =>$model->dokumen_persetujuan,
'status' =>$model->status,
'authorized_status' =>$model->authorized_status,
'authorized_at' =>$model->authorized_at,
'authorized_at' =>$model->authorized_at,
'created_at' =>$model->created_at,
'updated_at' =>$model->updated_at,
'deleted_at' =>$model->deleted_at,
'created_by' =>$model->created_by,
'updated_by' =>$model->updated_by,
'deleted_by' =>$model->deleted_by
]);
}
PenawaranDetailTenderLog::insert($dataDetailPenawaranLog);
}
// log
DB::commit();
$data['status'] = 'success';
$data['message']['message_success'] = array('Otorisasi Penawaran KJPP '.$request->kjppName.' successfully');
} catch (Exception $e) {
DB::rollBack();
$data['status'] = 'error';
$data['message']['message_error'] = array("Otorisasi Penawaran KJPP failed..");
}
}
else
{
$data['status'] = 'error';
$data['message'] ['active_date_range'] = array("Penawaran sudah di tutup");
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('debitur.view')) {
//abort(403, 'Sorry! You are not allowed to view users.');
}
} else {
$data['status'] = 'error';
$data['message']['message_ajax'] = array("no ajax request");
}
return response()->json($data);
}
// Retrieve data from the database
$query = PenawaranTender::query()->select(
'penawaran.*',
'debitures.name as debitures_name',
'permohonan.tanggal_permohonan',
'users.name as user_pemohon',
'branches.name as branches_name',
'tujuan_penilaian.name as tujuan_penilaian_name',
'tujuan_penilaian_kjpp.name as tujuan_penilaian_kjpp_name',
)->leftJoin('permohonan', 'permohonan.nomor_registrasi', '=', 'penawaran.nomor_registrasi')->leftJoin(
'debitures',
'debitures.id',
'=',
'permohonan.debiture_id',
)->leftJoin('users', 'users.id', '=', 'permohonan.user_id')->leftJoin(
'branches',
'branches.id',
'=',
'permohonan.branch_id',
)->leftJoin('tujuan_penilaian', 'tujuan_penilaian.id', '=', 'permohonan.tujuan_penilaian_id')->leftJoin(
'tujuan_penilaian_kjpp',
'tujuan_penilaian_kjpp.id',
'=',
'penawaran.tujuan_penilaian_kjpp_id',
)->where('penawaran.status', '=', 'proposal-tender')->withCount('penawarandetails');
public function show($id)
{
$prosespenawaran = PenawaranTender::find($id);
return view('lpj::otorisasipenawaran.show', compact('id','prosespenawaran'));
}
}
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
$q->orWhere('status', 'LIKE', '%' . $search . '%');
});
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
//$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian'])->get();
$data = $query->get();
// format date
$i = 0;
foreach ($data as $obj) {
// tanggal_permohonan
if ($obj->tanggal_permohonan) {
$data[$i]->tanggal_permohonan = Carbon::parse($obj->tanggal_permohonan)->format('d M Y');
}
// date_range
$data[$i]->date_range = "-";
if ($obj->start_date && $obj->end_date) {
$data[$i]->date_range = Carbon::parse($obj->start_date)->format('d M Y') . ' - ' . Carbon::parse(
$obj->end_date,
)->format('d M Y');
}
$i++;
}
// format date
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = 0 + 1;
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
public function edit($id)
{
// id ==> penawaran.id
return view('lpj::otorisasipenawaran.edit', compact('id'));
}
public function setData(Request $request): JsonResponse
{
$data = [];
$penawaran = [];
$penawrandetails = [];
$penawarandetailLogs = [];
if (request()->ajax()) {
$id = $request->id;
$penawaran = PenawaranTender::where('status','=','proposal-tender')->find($id);
if ($penawaran) {
$penawarandetailLogs = PenawaranDetailTenderLog::where('penawaran_id',$id)
->leftJoin('kjpp', 'kjpp.id', '=', 'detail_penawaran_logs.kjpp_rekanan_id')
->select('detail_penawaran_logs.*', DB::raw("DATE_FORMAT(detail_penawaran_logs.created_at, '%d-%m-%Y %H:%i') AS created_at2"),'kjpp.code AS kjpp_code', 'kjpp.name AS kjpp_name')
->get();
$penawrandetails = PenawaranDetailTender::where('penawaran_id','=',$id)
->leftJoin('kjpp', 'kjpp.id', '=', 'detail_penawaran.kjpp_rekanan_id')
->select('detail_penawaran.*', 'kjpp.code AS kjpp_code', 'kjpp.name AS kjpp_name')
->where('detail_penawaran.status','=',1)
->get();
if(sizeof($penawarandetailLogs)>0)
{
$h=0;
foreach($penawarandetailLogs as $obj1)
{
// tgl_proposal
if ($obj1->tgl_proposal) {
$penawarandetailLogs[$h]->tgl_proposal = Carbon::parse($obj1->tgl_proposal)->format('d M Y');
}
if($obj1->dokumen_persetujuan && Storage::disk('public')->exists($obj1->dokumen_persetujuan))
{
$penawarandetailLogs_path = Storage::url($obj1->dokumen_persetujuan);
$penawarandetailLogs[$h]->dokumen_persetujuan = $penawarandetailLogs_path;
}
$h++;
}
}
$i=0;
foreach($penawrandetails as $obj)
{
// tgl_proposal
if ($obj->tgl_proposal) {
$penawrandetails[$i]->tgl_proposal = Carbon::parse($obj->tgl_proposal)->format('d M Y');
}
if($obj->dokumen_persetujuan && Storage::disk('public')->exists($obj->dokumen_persetujuan))
{
$penawrandetails_path = Storage::url($obj->dokumen_persetujuan);
$penawrandetails[$i]->dokumen_persetujuan = $penawrandetails_path;
}
$i++;
}
$penawaranString = "";
if($penawaran->status)
{
$penawaranString = convertSlug($penawaran->status);
$penawaran->status = $penawaranString;
}
$kjpp=null;
$kjpp = KJPP::pluck('name', 'id');
$data['penawaran'] = $penawaran;
$data['penawrandetails'] = $penawrandetails;
$data['penawarandetailLogs'] = $penawarandetailLogs;
$data['status'] = 'success';
$data['message']['message_success'] = array("data successfully found");
} else {
$data['status'] = 'error';
$data['penawaran'] = null;
$data['penawrandetails'] = null;
$data['message']['message_data'] = array("data not found");
}
} else {
$data['status'] = 'error';
$data['message']['message_ajax'] = array("no ajax request");
}
return response()->json($data);
}
public function otorisasiPenawaranKJPP(Request $request, $id): JsonResponse
{
$data = [];
$dataDetailPenawaranLog = [];
if (request()->ajax()) {
// cek masa aktif penawaran
$detailpenawaran = PenawaranDetailTender::find($id);
$penawaran = PenawaranTender::findOrFail($detailpenawaran->penawaran_id);
$checkActiveDateRange = checkActiveDateRangePenawaran($detailpenawaran->penawaran_id);
// cek masa aktif penawaran
if($checkActiveDateRange)
{
DB::beginTransaction();
try {
// update status KJPP yg tidak terpilih menjadi 2 -> kalah
// update status Penawaran menjadi persetujuan-penawaran (20241205)
// update status Permohonan menjadi persetujuan-penawaran (20241205)
// insert detail_permohonan_log
PenawaranDetailTender::where('status', 1)
->where('penawaran_id', $request->penawaran_id)
->whereNotIn('id', [$id])
->update(['status' => 2,
'updated_by' => Auth::id(),
'updated_at' => now()
]);
// 20241205 arahkan ke persetujuan-penawaran
PenawaranTender::where('id', $request->penawaran_id)
->update(['status'=>'persetujuan-penawaran',
'nama_kjpp_sebelumnya'=>$request->kjppName,
'biaya_kjpp_sebelumnya'=>$request->biaya_penawaran,
'tanggal_penilaian_sebelumnya'=>now(),
'authorized_status'=>1,
'authorized_at'=>now(),
'authorized_by'=>Auth::id(),
'updated_by' => Auth::id(),
'updated_at' => now()
]);
Permohonan::where('nomor_registrasi',$request->noReg)
->update(['status'=>'persetujuan-penawaran',
'updated_by' => Auth::id(),
'updated_at' => now()
]);
// log
$detailPenawaran = PenawaranDetailTender::where('penawaran_id', $request->penawaran_id)->get();
if(sizeof($detailPenawaran)>0)
{
foreach ($detailPenawaran as $model) {
array_push($dataDetailPenawaranLog, [
'detail_penawaran_id' =>$model->id,
'kjpp_rekanan_id' =>$model->kjpp_rekanan_id,
'penawaran_id' =>$model->penawaran_id,
'no_proposal' =>$model->no_proposal,
'tgl_proposal' =>$model->tgl_proposal,
'biaya_penawaran' =>$model->biaya_penawaran,
'attachment' =>$model->attachment,
'dokumen_persetujuan' =>$model->dokumen_persetujuan,
'status' =>$model->status,
'authorized_status' =>$model->authorized_status,
'authorized_at' =>$model->authorized_at,
'authorized_at' =>$model->authorized_at,
'created_at' =>$model->created_at,
'updated_at' =>$model->updated_at,
'deleted_at' =>$model->deleted_at,
'created_by' =>$model->created_by,
'updated_by' =>$model->updated_by,
'deleted_by' =>$model->deleted_by
]);
}
PenawaranDetailTenderLog::insert($dataDetailPenawaranLog);
}
// log
DB::commit();
$data['status'] = 'success';
$data['message']['message_success'] = array('Otorisasi Penawaran KJPP '.$request->kjppName.' successfully');
} catch (Exception $e) {
DB::rollBack();
$data['status'] = 'error';
$data['message']['message_error'] = array("Otorisasi Penawaran KJPP failed..");
}
}
else
{
$data['status'] = 'error';
$data['message']['message_error'] = array("Penawaran sudah di tutup");
}
} else {
$data['status'] = 'error';
$data['message']['message_error'] = array("no ajax request");
}
return response()->json($data);
}
public function show($id)
{
$prosespenawaran = PenawaranTender::with(['permohonan','tujuanPenilaianKjpp'])->find($id);
$permohonan = $prosespenawaran->permohonan;
return view('lpj::otorisasipenawaran.show', compact('id','prosespenawaran','permohonan'));
}
public function penawaranulang(Request $request, $id): JsonResponse
{
// $id ==> penawaran.id
$data = [];
$dataDetailPenawaranLog=[];
if (request()->ajax()) {
DB::beginTransaction();
try {
// update detail_penawaran => detail_penawaran.status = 1 (untuk all KJPP)
// update penawaran => penawaran.status ="tender", penawaran.updated_at, penawaran.updated_by
// update permohonan => permohonan.status ="tender", permohonan.updated_at, permohonan.updated_by
// insert detail_permohonan_log
PenawaranDetailTender::where('penawaran_id', $id)
->update(['status' => 1,
'updated_by' => Auth::id(),
'updated_at' => now()
]);
PenawaranTender::where('id', $id)
->update(['status'=>'tender',
'updated_by' => Auth::id(),
'updated_at' => now()
]);
Permohonan::where('nomor_registrasi',$request->noReg)
->update(['status'=>'tender',
'updated_by' => Auth::id(),
'updated_at' => now()
]);
$detailPenawaran = PenawaranDetailTender::where('penawaran_id', $id)
->distinct()
->get();
// log
if(sizeof($detailPenawaran)>0)
{
foreach ($detailPenawaran as $model) {
array_push($dataDetailPenawaranLog, [
'detail_penawaran_id' =>$model->id,
'kjpp_rekanan_id' =>$model->kjpp_rekanan_id,
'penawaran_id' =>$model->penawaran_id,
'no_proposal' =>$model->no_proposal,
'tgl_proposal' =>$model->tgl_proposal,
'biaya_penawaran' =>$model->biaya_penawaran,
'attachment' =>$model->attachment,
'dokumen_persetujuan' =>$model->dokumen_persetujuan,
'status' =>$model->status,
'authorized_status' =>$model->authorized_status,
'authorized_at' =>$model->authorized_at,
'authorized_at' =>$model->authorized_at,
'created_at' =>$model->created_at,
'updated_at' =>$model->updated_at,
'deleted_at' =>$model->deleted_at,
'created_by' =>$model->created_by,
'updated_by' =>$model->updated_by,
'deleted_by' =>$model->deleted_by
]);
}
PenawaranDetailTenderLog::insert($dataDetailPenawaranLog);
}
// log
DB::commit();
$data['detailPenawaran'] = $detailPenawaran;
$data['status'] = 'success';
$data['message']['message_success'] = array('Penawaran ulang successfully');
} catch (Exception $e) {
DB::rollBack();
$data['status'] = 'error';
$data['message']['message_error'] = array("Penawaran ulang failed..");
}
} else {
$data['status'] = 'error';
$data['message']['message_error'] = array("no ajax request");
}
return response()->json($data);
}
}

View File

@@ -0,0 +1,143 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Exception;
use Illuminate\Http\Request;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\PermohonanPembatalan;
use Modules\Lpj\Services\PermohonanHistoryService;
use Illuminate\Support\Facades\Auth;
class PembatalanController extends Controller
{
public $user;
protected $historyService;
public function __construct(PermohonanHistoryService $historyService)
{
$this->historyService = $historyService;
}
public function index()
{
return view('lpj::pembatalan.index');
}
public function edit($id)
{
$pembatalan = PermohonanPembatalan::with(['permohonan.debiture','permohonan.branch'])->find($id);
return view(
'lpj::pembatalan.form',
compact(
'pembatalan'
),
);
}
public function update(Request $request, $id)
{
$pembatalan = PermohonanPembatalan::findOrFail($id);
$permohonan = Permohonan::find($pembatalan->permohonan_id);
$beforeRequest = $permohonan->toArray();
try {
// Update Permohonan Pembatalan
if($request->status=='approved'){
$pembatalan->status = 'approved';
$pembatalan->authorized_at = now();
$pembatalan->authorized_by = auth()->user()->id;
$pembatalan->authorized_status = 1;
$pembatalan->save();
$permohonan->status = 'batal';
$permohonan->save();
} else{
$pembatalan->status = 'rejected';
$pembatalan->authorized_at = now();
$pembatalan->authorized_by = auth()->user()->id;
$pembatalan->authorized_status = 3;
$pembatalan->save();
}
return redirect()
->route('pembatalan.index')->with('success', 'Permohonan Pembatalan updated successfully');
} catch (Exception $e) {
return redirect()
->route('pembatalan.edit', $id)->with('error', 'Failed to update permohonan Pembatalan');
}
}
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('debitur.view')) {
//abort(403, 'Sorry! You are not allowed to view users.');
}
// Retrieve data from the database
$query = PermohonanPembatalan::query();
if (Auth::user()->hasAnyRole(['pemohon-ao','pemohon-eo'])) {
$query = $query->whereRelation('permohonan', 'branch_id', Auth::user()->branch_id);
}
$query = $query->orderBy('created_at', 'desc');
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->orWhereRelation('permohonan', 'nomor_registrasi', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('permohonan.debiture', 'name', 'LIKE', '%' . $search . '%');
$q->orWhere('alasan_pembatalan', 'LIKE', '%' . $search . '%');
$q->orWhere('status', 'LIKE', '%' . $search . '%');
});
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
$size = $request->get('size', 10);
if ($size == 0) {
$size = 10;
}
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->with(['permohonan.debiture','permohonan.branch','creator'])->get();
// Calculate the page count
$pageCount = ceil($totalRecords / $size);
// Calculate the current page number
$currentPage = max(1, $request->get('page', 1));
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
}

View File

@@ -0,0 +1,618 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use Exception;
use Modules\Lpj\Models\Noc;
use Illuminate\Http\Request;
use Modules\Lpj\Models\Bucok;
use Illuminate\Http\JsonResponse;
use Modules\Lpj\Models\Permohonan;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Modules\Lpj\Models\PenawaranTender;
use Modules\Lpj\Models\PersetujuanPenawaran;
use Modules\Lpj\Http\Requests\PersetujuanPenawaranRequest;
class PembayaranController extends Controller
{
public $user;
public function index()
{
return view('lpj::pembayaran.index');
}
public function kurang(){
return view('lpj::pembayaran.kurang');
}
public function lebih(){
return view('lpj::pembayaran.lebih');
}
public function approval()
{
return view('lpj::pembayaran.approval');
}
public function dataApprovalForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('noc.view')) {
//abort(403, 'Sorry! You are not allowed to view persetujuan penawaran.');
}
// Retrieve data from the database
$query = PersetujuanPenawaran::query();
if (Auth::user()->hasAnyRole(['pemohon-ao','pemohon-eo'])) {
$query = $query->whereRelation('permohonan', 'branch_id', Auth::user()->branch_id);
}
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->orWhereRelation('penawaran', 'nomor_registrasi', 'LIKE', '%' . $search . '%');
});
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query
->with(
[
'penawaran.permohonan.user',
'penawaran.permohonan.debiture',
'penawaran.permohonan.branch',
'permohonan.debiture',
'permohonan.branch',
'permohonan.user',
'permohonan.approveBayar',
'penawaran.permohonan.approveBayar',
'penawaran.detail',
'penawaran.persetujuan',
],
)->get();
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = $request->get('page', 1);
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
public function create(){
return view('lpj::pembayaran.create');
}
public function edit($id)
{
$req = request()->all();
if(isset($req['tiket'])){
$persetujuanPenawaran = PersetujuanPenawaran::find($id);
$permohonan = Permohonan::find($persetujuanPenawaran?->permohonan_id);
} else {
$permohonan = Permohonan::find($id);
$persetujuanPenawaran = PersetujuanPenawaran::where('permohonan_id', $permohonan->id)->first();
}
return view('lpj::pembayaran.form', compact('permohonan', 'persetujuanPenawaran'));
}
public function editKurang($id){
$noc = Noc::find($id);
$permohonan = Permohonan::find($noc->permohonan_id);
$persetujuanPenawaran = PersetujuanPenawaran::where('permohonan_id', $permohonan->id)->first();
return view('lpj::pembayaran.form-kurang', compact('noc','permohonan','persetujuanPenawaran'));
}
public function editLebih($id){
$noc = Noc::find($id);
$permohonan = Permohonan::find($noc->permohonan_id);
$persetujuanPenawaran = PersetujuanPenawaran::where('permohonan_id', $permohonan->id)->first();
return view('lpj::pembayaran.form-lebih', compact('noc','permohonan','persetujuanPenawaran'));
}
public function store(PersetujuanPenawaranRequest $request)
{
$req = request()->all();
if(isset($req['type'])){
if($req['type'] == 'create'){
$data = [
'nomor_tiket' => $req['nomor_tiket'] ?? '',
'nominal_bayar' => $req['nominal_bayar'] ?? '',
'catatan' => $req['catatan'] ?? ''
];
if(request()->hasFile('bukti_bayar')){
$folderPath = 'persetujuan_penawaran/bukti_bayar/' . $req['nomor_tiket'];
$data['bukti_bayar'] = $request->file('bukti_bayar')->store($folderPath, 'public');
}
$persetujuanPenawaran = PersetujuanPenawaran::create($data);
$noc = [
'persetujuan_penawaran_id' => $persetujuanPenawaran->id,
'nomor_tiket' => $req['nomor_tiket'] ?? '',
'debiture_id' => $req['debitur_id'] ?? '',
'branch_id' => Auth::user()->branch_id,
];
$noc = Noc::create($noc);
$bucok = [
'tanggal_penuh' => $persetujuanPenawaran->created_at ?? $noc->created_at,
'tanggal' => $persetujuanPenawaran->created_at?->format('d') ?? $noc->created_at?->format('d'),
'bulan' => $persetujuanPenawaran->created_at?->format('m') ?? $noc->created_at?->format('m'),
'tahun' => $persetujuanPenawaran->created_at?->format('Y') ?? $noc->created_at?->format('Y'),
'nomor_tiket' => $req['nomor_tiket'] ?? '',
'nominal' => $req['nominal_bayar'] ?? '',
'nominal_berjalan' => $req['nominal_bayar'] ?? '',
'penyelesaian' => 'Belum Selesai',
'nama_sub_direktorat' => $noc->branch?->name ?? '',
'nama_direktorat_cabang' => $noc->branch?->name ?? '',
];
Bucok::updateOrCreate([
'nomor_tiket' => $req['nomor_tiket'] ?? '',
], $bucok);
return redirect()
->route('pembayaran.index')->with('success', 'Pembayaran berhasil disimpan.');
}
if($req['type'] == 'kurang_bayar'){
$noc = Noc::find($req['noc_id']);
$noc->nominal_pelunasan = $req['nominal_pelunasan'];
if (request()->hasFile('bukti_ksl_kurang_bayar')) {
$folderPath = 'persetujuan_penawaran/bukti_ksl_kurang_bayar/' . $req['noc_id'];
$noc->bukti_ksl_kurang_bayar = $request->file('bukti_ksl_kurang_bayar')->store($folderPath, 'public');
}
$noc->save();
$persetujuanPenawaran = PersetujuanPenawaran::find($noc->persetujuan_penawaran_id);
$persetujuanPenawaran->bukti_ksl_kurang_bayar = $noc->bukti_ksl_kurang_bayar;
$persetujuanPenawaran->nominal_kurang_bayar = $req['nominal_pelunasan'];
$persetujuanPenawaran->save();
return redirect()
->route('pembayaran.kurang.index')->with('success', 'Pelunasan Kurang Bayar berhasil disimpan.');
}
if($req['type'] == 'lebih_bayar'){
$noc = Noc::find($req['noc_id']);
if (request()->hasFile('bukti_ksl_lebih_bayar')) {
$folderPath = 'persetujuan_penawaran/bukti_ksl_lebih_bayar/' . $req['noc_id'];
$noc->bukti_ksl_lebih_bayar = $request->file('bukti_ksl_lebih_bayar')->store($folderPath, 'public');
}
$noc->save();
return redirect()
->route('pembayaran.lebih.index')->with('success', 'Pengembalian Lebih Bayar berhasil disimpan.');
}
}
$validated = $request->validated();
$validated['nominal_bayar'] = $req['nominal_bayar'] ?? 0;
$validated['created_by'] = Auth::id();
$validated['created_at'] = now();
$validated['status'] = '0';
$persetujuanPenawaran = PersetujuanPenawaran::where('permohonan_id', $validated['permohonan_id'] ?? null)->first();
$permohonan = Permohonan::find(request()->get('permohonan_id'));
if ($persetujuanPenawaran) {
$persetujuanPenawaran->fill($validated);
if ($request->hasFile('bukti_bayar')) {
$folderPath = 'persetujuan_penawaran/' . $validated['penawaran_id'];
$persetujuanPenawaran->bukti_bayar = $request->file('bukti_bayar')->store($folderPath, 'public');
}
$persetujuanPenawaran->save();
$permohonan->approve_bayar_by = null;
$permohonan->approve_bayar_at = null;
$permohonan->status = 'proses-laporan';
$permohonan->save();
} else {
$persetujuanPenawaran = PersetujuanPenawaran::create(
$validated
);
if(isset($validated['nomor_tiket'])){
$noc = Noc::where('nomor_tiket',$validated['nomor_tiket'])->first();
if($noc){
$noc->persetujuan_penawaran_id = $persetujuanPenawaran->id;
$noc->permohonan_id = $validated['permohonan_id'];
$noc->save();
}
}
$folderPath = 'persetujuan_penawaran/' . $validated['penawaran_id'];
if ($request->hasFile('bukti_bayar')) {
$persetujuanPenawaran->bukti_bayar = $request->file('bukti_bayar')->store($folderPath, 'public');
}
$persetujuanPenawaran->save();
}
$bucok = [
'tanggal_penuh' => $persetujuanPenawaran->created_at ?? $validated['created_at'],
'tanggal' => $persetujuanPenawaran->created_at?->format('d') ?? $validated['created_at']?->format('d'),
'bulan' => $persetujuanPenawaran->created_at?->format('m') ?? $validated['created_at']?->format('m'),
'tahun' => $persetujuanPenawaran->created_at?->format('Y') ?? $validated['created_at']?->format('Y'),
'nomor_tiket' => $req['nomor_tiket'] ?? '',
'nominal' => $req['nominal_bayar'] ?? '',
'nominal_berjalan' => $req['nominal_bayar'] ?? '',
'penyelesaian' => 'Belum Selesai',
'nama_sub_direktorat' => $noc->branch?->name ?? '',
'nama_direktorat_cabang' => $noc->branch?->name ?? '',
'permohonan_id' => $permohonan->id,
'nomor_registrasi' => $permohonan->nomor_registrasi,
];
if(isset($req['nomor_tiket']) && $req['nomor_tiket'] !=''){
Bucok::updateOrCreate([
'nomor_registrasi' => $permohonan->nomor_registrasi,
'nomor_tiket' => $req['nomor_tiket'],
], $bucok);
} else {
Bucok::updateOrCreate([
'nomor_registrasi' => $permohonan->nomor_registrasi
], $bucok);
}
// Update the status of the related permohonan to 'spk'
if ($permohonan) {
$permohonan->status_bayar = request()->get('status_bayar');
$permohonan->save();
// andy add, update status penawaran.status='spk'
// $penawaran = PenawaranTender::where('nomor_registrasi',$permohonan->nomor_registrasi)->first();
PenawaranTender::where('nomor_registrasi', $permohonan->nomor_registrasi)->update([
'status' => 'noc',
'updated_by' => Auth::id(),
'updated_at' => now(),
]);
// andy add, update status penawaran.status='spk'
}
return redirect()
->route('pembayaran.index')->with('success', 'Pembayaran berhasil disimpan.');
}
public function update(Request $request, $id): JsonResponse
{
// init
$data = [];
$output = [];
$tindakan = null;
if (request()->ajax()) {
try {
$data = [
'approve_bayar_by' => Auth::id(),
'approve_bayar_at' => now(),
];
if ($request->keterangan) {
$data['approve_keterangan_bayar'] = $request->keterangan;
}
$output['data'] = $data;
// Update the status of the related permohonan to 'spk'
$permohonan = Permohonan::find($id);
if ($permohonan) {
if ($request->type === 'revisi') {
$data['status'] = 'revisi-pembayaran';
$data['status_bayar'] = 'belum_bayar';
} else {
$data['status_bayar'] = 'sudah_bayar';
$data['status'] = 'proses-laporan';
if ($permohonan->jenis_penilaian_id == 2) {
$data['status_bayar'] = 'sudah_bayar';
$data['status'] = 'spk';
}
}
if ($permohonan->jenis_penilaian_id == 1) {
unset(
$data['approval_so'],
$data['approval_so_at'],
$data['approval_eo'],
$data['approval_eo_at'],
$data['approval_dd'],
$data['approval_dd_at'],
$data['keterangan']
);
}
$permohonan->update($data);
if ($permohonan->jenis_penilaian_id == 2) {
PenawaranTender::where('nomor_registrasi', $permohonan->nomor_registrasi)->update([
'status' => 'spk',
'updated_by' => Auth::id(),
'updated_at' => now(),
]);
}
}
$output['status'] = 'success';
$output['message'] = ['Otorisasi' . $permohonan->nomor_registrasi . 'berhasil di lakukan'];
} catch (Exception $e) {
$output['status'] = 'error';
$output['message'] = ['Otorisasi gagal di lakukan.'];
}
}
return response()->json($output);
}
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('debitur.view')) {
// abort(403, 'Sorry! You are not allowed to view users.');
}
$query = PersetujuanPenawaran::query();
if (Auth::user()->hasAnyRole(['pemohon-ao','pemohon-eo'])) {
$query = $query->whereRelation('permohonan', 'branch_id', Auth::user()->branch_id);
}
/*$query->where(function($q) {
$q->whereRelation('permohonan', function($query) {
$query->where('status_bayar', 'belum_bayar')
->where('jenis_penilaian_id', 1);
});
});*/
$query->orWhereRelation('permohonan','status_bayar','revisi-pembayaran');
$query->orWhere(function($q) {
$q->where('permohonan_id',null);
$q->where('nomor_tiket','!=',null);
});
// Pencarian berdasarkan parameter search
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
}
// Sorting berdasarkan sortField dan sortOrder
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Hitung total records
$totalRecords = $query->count();
// Pagination (default page size 10)
$size = $request->get('size', 10);
if ($size == 0) {
$size = 10;
}
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page', 1);
$offset = ($page - 1) * $size;
$query->skip($offset)->take($size);
}
// Filtered records
$filteredRecords = $query->count();
// Ambil data dengan relasi
$data = $query->get();
$data = $data->map(function ($item) {
return [
'id' => $item->permohonan?->id ?? $item->id,
'nomor_registrasi' => $item->permohonan?->nomor_registrasi,
'nomor_tiket' => $item->nomor_tiket ?? '',
'debiture' => $item->permohonan?->debiture ?? $item->noc?->debiture,
'user' => $item->permohonan?->user ?? $item->creator,
'status_bayar' => $item->permohonan?->status_bayar ?? ($item->nomor_tiket ? 'Sudah Bayar' : ''),
'tanggal_permohonan' => $item->permohonan?->tanggal_permohonan ?? '',
'branch' => $item->permohonan?->branch ?? $item->noc?->branch,
'is_permohonan' => $item->permohonan ?? ''
];
});
// Hitung jumlah halaman
$pageCount = ceil($totalRecords / $size);
// Ambil current page
$currentPage = max(1, $request->get('page', 1));
// Return JSON response
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
public function dataForDatatablesKurang(Request $request)
{
if (is_null($this->user) || !$this->user->can('debitur.view')) {
// abort(403, 'Sorry! You are not allowed to view users.');
}
$query = Noc::query()->where(function ($query) {
$query->where(['status_kurang_bayar' => '1'])
->where('bukti_ksl_kurang_bayar',null);
});
// Sorting berdasarkan sortField dan sortOrder
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Hitung total records
$totalRecords = $query->count();
// Pagination (default page size 10)
$size = $request->get('size', 10);
if ($size == 0) {
$size = 10;
}
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page', 1);
$offset = ($page - 1) * $size;
$query->skip($offset)->take($size);
}
// Filtered records
$filteredRecords = $query->count();
// Ambil data dengan relasi
$data = $query->get();
$data = $data->map(function ($item) {
return [
'id' => $item->id,
'permohonan' => $item->permohonan,
'pemohon' => $item->permohonan->user,
'branch' => $item->permohonan->branch,
'debiture' => $item->permohonan->debiture,
'nominal_kurang_bayar' => formatRupiah($item->nominal_kurang_bayar,2)
];
});
// Hitung jumlah halaman
$pageCount = ceil($totalRecords / $size);
// Ambil current page
$currentPage = max(1, $request->get('page', 1));
// Return JSON response
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
public function dataForDatatablesLebih(Request $request)
{
if (is_null($this->user) || !$this->user->can('debitur.view')) {
// abort(403, 'Sorry! You are not allowed to view users.');
}
$query = Noc::query()->where(function ($query) {
$query->where(['status_lebih_bayar' => '1'])
->where('bukti_ksl_lebih_bayar',null);
});
// Sorting berdasarkan sortField dan sortOrder
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Hitung total records
$totalRecords = $query->count();
// Pagination (default page size 10)
$size = $request->get('size', 10);
if ($size == 0) {
$size = 10;
}
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page', 1);
$offset = ($page - 1) * $size;
$query->skip($offset)->take($size);
}
// Filtered records
$filteredRecords = $query->count();
// Ambil data dengan relasi
$data = $query->get();
$data = $data->map(function ($item) {
return [
'id' => $item->id,
'permohonan' => $item->permohonan,
'pemohon' => $item->permohonan->user,
'branch' => $item->permohonan->branch,
'debiture' => $item->permohonan->debiture,
'nominal_lebih_bayar' => formatRupiah($item->nominal_lebih_bayar,2)
];
});
// Hitung jumlah halaman
$pageCount = ceil($totalRecords / $size);
// Ambil current page
$currentPage = max(1, $request->get('page', 1));
// Return JSON response
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -5,22 +5,42 @@ namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Modules\Lpj\Http\Requests\PenilaianRequest;
use Modules\Lpj\Models\Authorization;
use Modules\Lpj\Models\JenisPenilaian;
use Modules\Lpj\Models\LaporanAdminKredit;
use Modules\Lpj\Models\Penilaian;
use Modules\Lpj\Models\PenilaianTeam;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\StatusPermohonan;
use Modules\Lpj\Models\Teams;
use Modules\Lpj\Models\Inspeksi;
use Modules\Lpj\Models\Penilai;
use Modules\Lpj\Models\Regions;
use Modules\Lpj\Models\TeamsUsers;
use Modules\Location\Models\Province;
use Modules\Location\Models\City;
use Modules\Location\Models\District;
use Modules\Location\Models\Village;
use Modules\Usermanagement\Models\User;
use Illuminate\Support\Facades\Auth;
use Modules\Lpj\Http\Controllers\SurveyorController;
use Modules\Lpj\Http\Controllers\PenilaiController;
use Modules\Lpj\Http\Requests\FormSurveyorRequest;
class PenilaianController extends Controller
{
public $user;
protected $surveyorController;
protected $penilaiController;
public function __construct(SurveyorController $surveyorController, PenilaiController $penilaiController)
{
$this->surveyorController = $surveyorController;
$this->penilaiController = $penilaiController;
}
/**
* Display a listing of the resource.
*/
@@ -43,12 +63,12 @@ class PenilaianController extends Controller
try {
DB::beginTransaction();
$penilaian = Penilaian::create($validatedData);
$penilaian = Penilaian::create($validatedData);
$validatedData['penilaian_id'] = $penilaian->id;
$teams_ids = [];
$user_ids = [];
$roles = [];
$user_ids = [];
$roles = [];
if ($validatedData['surveyor_id'] === 'pilih_dari_region') {
$surveyor_region_id = $validatedData['surveyor_region_id'];
@@ -62,20 +82,28 @@ class PenilaianController extends Controller
}
$teams_ids[] = $surveyor_region_id;
$user_ids[] = null;
$roles[] = 'surveyor';
$user_ids[] = null;
$roles[] = 'surveyor';
} else {
$permohonan = Permohonan::where('nomor_registrasi', $request->nomor_registrasi)->first();
$teams_ids[] = $validatedData['teams_id'];
$permohonan = Permohonan::where('nomor_registrasi', $request->nomor_registrasi)->first();
if (isset($validatedData['penilai_surveyor_id'])) {
$user_ids[] = $validatedData['penilai_surveyor_id'];
if ($validatedData['penilai_surveyor_id'] == 'pilih_dari_region') {
$teams_ids[] = $validatedData['surveyor_penilai_region_id'];
$user_ids[] = null;
} else {
$teams_ids[] = $validatedData['teams_id'];
$user_ids[] = $validatedData['penilai_surveyor_id'];
}
} else {
$teams_ids[] = $validatedData['teams_id'];
$user_ids[] = $validatedData['surveyor_id'];
}
$roles[] = 'surveyor';
}
if ($validatedData['penilai_id'] === 'pilih_dari_region') {
@@ -90,33 +118,46 @@ class PenilaianController extends Controller
}
$teams_ids[] = $penilaian_region_id;
$user_ids[] = null;
$roles[] = 'penilai';
$user_ids[] = null;
$roles[] = 'penilai';
} else {
$permohonan = Permohonan::where('nomor_registrasi', $request->nomor_registrasi)->first();
$teams_ids[] = $validatedData['teams_id'];
$permohonan = Permohonan::where('nomor_registrasi', $request->nomor_registrasi)->first();
if (isset($validatedData['penilai_surveyor_id'])) {
$user_ids[] = $validatedData['penilai_surveyor_id'];
}else {
if ($validatedData['penilai_surveyor_id'] == 'pilih_dari_region') {
$permohonan->update([
'region_id' => $validatedData['surveyor_penilai_region_id'],
]);
$teams_ids[] = $validatedData['surveyor_penilai_region_id'];
$user_ids[] = null;
} else {
$teams_ids[] = $validatedData['teams_id'];
$user_ids[] = $validatedData['penilai_surveyor_id'];
}
} else {
$teams_ids[] = $validatedData['teams_id'];
$user_ids[] = $validatedData['penilai_id'];
}
$roles[] = 'penilai';
}
// dd($validatedData['penilai_region_id'],$validatedData['teams_id']);
foreach ($teams_ids as $key => $teams_id) {
PenilaianTeam::create([
'penilaian_id' => $validatedData['penilaian_id'],
'team_id' => $teams_id,
'user_id' => $user_ids[$key],
'role' => $roles[$key],
'team_id' => $teams_id,
'user_id' => $user_ids[$key],
'role' => $roles[$key],
]);
}
if ($validatedData['surveyor_id'] === 'pilih_dari_region' || $validatedData['penilai_id'] === 'pilih_dari_region') {
$status = 'registered';
if ($validatedData['surveyor_id'] === 'pilih_dari_region' || $validatedData['penilai_id'] === 'pilih_dari_region' || $validatedData['penilai_surveyor_id'] === 'pilih_dari_region') {
$status = 'reassign';
} else {
$status = 'assign';
}
@@ -126,11 +167,12 @@ class PenilaianController extends Controller
]);
DB::commit();
return redirect()->route('penilaian.index')->with('success', 'Penilaian berhasil disimpan');
return response()->json(['success' => true, 'message' => 'Data berhasil di-assign.'], 200);
} catch (Exception $e) {
dd($e);
DB::rollBack();
return redirect()->route('penilaian.index')->with('error', $e->getMessage());
return response()->json(['error' => $e->getMessage()]);
}
}
}
@@ -152,6 +194,8 @@ class PenilaianController extends Controller
DB::beginTransaction();
$penilaian = Penilaian::where('nomor_registrasi', $request->nomor_registrasi)->first();
$surveyTeam = null;
$penilaiTeam = null;
$penilaianId = $penilaian->id;
$penilainTeam = PenilaianTeam::where('penilaian_id', $penilaianId)->get();
@@ -161,28 +205,39 @@ class PenilaianController extends Controller
if ($item->role === 'surveyor' && $item->user_id === null) {
$item->update([
'user_id' => $request->surveyor_id,
'role' => 'surveyor',
'role' => 'surveyor',
]);
$surveyTeam = $item->team_id;
}
if ($item->role === 'penilai' && $item->user_id === null) {
$item->update([
'user_id' => $request->penilai_id,
'role' => 'penilai',
'role' => 'penilai',
]);
}
if ($item->role === 'penilai' && $surveyTeam) {
$penilaiTeam = $item->team_id;
}
}
$permohonan = Permohonan::where('nomor_registrasi', $request->nomor_registrasi);
if ($surveyTeam && $penilaiTeam) {
$permohonan->update([
'region_id' => $penilaiTeam,
]);
}
$permohonan->update([
'status' => 'assign',
]);
DB::commit();
return redirect()->route('penilaian.index')->with('success', 'Penilaian berhasil disimpan');
return response()->json(['success' => true, 'message' => 'Data berhasil di-assign.'], 200);
} catch (Exception $e) {
DB::rollBack();
return redirect()->route('penilaian.index')->with('error', $e->getMessage());
return response()->json(['success' => false, 'error' => $e->getMessage()]);
}
}
@@ -202,55 +257,59 @@ class PenilaianController extends Controller
])->findOrFail($id);
$idPenilaian = $permohonan->jenis_penilaian_id;
$idRegion = $permohonan->region_id;
$idRegion = $permohonan->region_id;
$jenisPenilaian = JenisPenilaian::find($idPenilaian);
$userTeam = Teams::with(['regions', 'teamsUsers.user'])
->whereHas('regions', function ($q) use ($idRegion) {
$q->where('id', $idRegion);
})
->get();
$userTeam = Teams::with(['regions', 'teamsUsers.user'])->whereHas('regions', function ($q) use ($idRegion) {
$q->where('id', $idRegion);
})->get();
$teamPenilai = $userTeam->flatMap(function ($team) {
return $team->teamsUsers->filter(function ($teamUser) {
return $teamUser->user->roles->contains(function ($role) {
return $role->name === 'surveyor' || $role->name === 'surveyor-penilai';
return $role->name === 'surveyor' || $role->name === 'penilai' || $role->name === 'administrator';
});
})->map(function ($teamUser) {
return $teamUser->user;
});
})->unique('id');
$existingTeamIds = $teamPenilai->pluck('id')->toArray();
$existingTeamIds = $userTeam->pluck('id')->toArray();
$updateTeamPenilai = Teams::with(['regions', 'teamsUsers', 'teamsUsers.user'])
->whereNotIn('id', $existingTeamIds)
->get();
$updateTeamPenilai = Teams::with(['regions', 'teamsUsers', 'teamsUsers.user'])->whereNotIn(
'id',
$existingTeamIds,
)->get();
$regionName = null;
foreach ($userTeam as $item) {
$regionName = $item->regions;
}
// $regionName = $userTeam->first()?->regions->name;
$penilaian = Penilaian::where('nomor_registrasi', $permohonan->nomor_registrasi)->first();
$penilaianTeam = collect();
if ($penilaian && $penilaian->id) {
$penilaianTeam = PenilaianTeam::where('penilaian_id', $penilaian->id)->get();
}
// return response()->json([
// 'penilaianTeam' => $penilaianTeam
// ]);
// dd($penilaianTeam);
return view('lpj::penilaian.form', compact('permohonan', 'teamPenilai', 'jenisPenilaian', 'penilaian', 'regionName', 'updateTeamPenilai', 'penilaianTeam'));
return view(
'lpj::penilaian.form',
compact(
'permohonan',
'teamPenilai',
'jenisPenilaian',
'penilaian',
'regionName',
'updateTeamPenilai',
'penilaianTeam',
),
);
}
/**
* Remove the specified resource from storage.
*/
@@ -259,9 +318,7 @@ class PenilaianController extends Controller
{
$validatedData = $request->validated();
if ($validatedData) {
try {
if (isset($validatedData['dokumen']) && $request->hasFile('dokumen')) {
$file_name = $validatedData['dokumen']->getClientOriginalName();
$validatedData['dokumen']->storeAs('public/dokumen_revisi', $file_name);
@@ -269,8 +326,8 @@ class PenilaianController extends Controller
$dataToUpdate = [
'keterangan' => $validatedData['keterangan'],
'dokumen' => 'dokumen_revisi/' . $file_name,
'status' => 'revisi',
'dokumen' => 'dokumen_revisi/' . $file_name,
'status' => 'revisi',
];
@@ -285,12 +342,9 @@ class PenilaianController extends Controller
}
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('debitur.view')) {
}
$query = Permohonan::query();
@@ -308,10 +362,15 @@ class PenilaianController extends Controller
});
}
$query->whereRaw('LOWER(status) = ?', ['registered']);
$query->whereHas('region.teams.teamsUsers.user', function ($q) {
$q->where('id', Auth::user()->id);
});
$query->whereIn('status', ['registered', 'registrasi-final', 'reassign']);
if (Auth::user()->roles[0]->name !== 'administrator') {
$query->whereHas('region.teams.teamsUsers.user', function ($q) {
$q->where('id', Auth::user()->id);
});
}
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
@@ -334,7 +393,10 @@ class PenilaianController extends Controller
}
$filteredRecords = $query->count();
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian', 'region.teams.teamsUsers.user'])->get();
$data = $query->with(
['user', 'debiture', 'branch', 'tujuanPenilaian', 'jenisPenilaian', 'region.teams.teamsUsers.user',
]
)->get();
$pageCount = ceil($totalRecords / $size);
@@ -351,70 +413,301 @@ class PenilaianController extends Controller
}
public function otorisator(Request $request)
{
$type = $request->route('type');
$headers = [
'pelaporan' => 'Pelaporan',
'pembayaran' => 'Pembayaran',
'pembatalan' => 'Pembatalan',
'sla' => 'SLA',
'paparan' => 'Paparan'
];
$type = $request->route('type');
$header = '';
$regions = Regions::all();
switch ($type) {
case 'pelaporan':
$header = 'Pelaporan';
break;
case 'pembayaran':
$header = 'Pembayaran';
break;
case 'pembatalan':
$header = 'Pembatalan';
break;
case 'sla':
$header = 'SLA';
break;
$header = $headers[$type] ?? 'Pelaporan';
switch ($header) {
case 'SLA':
return view('lpj::penilaian.otorisator.index-sla', compact('header'));
case 'Paparan':
return view('lpj::penilaian.paparan-so', compact('header'));
default:
$header = 'Pelaporan';
break;
return view('lpj::penilaian.otorisator.index', compact('header', 'regions'));
}
return view('lpj::penilaian.otorisator.index', compact('header'));
}
public function show($id)
public function show($id, $type)
{
$headers = [
'Pelaporan' => 'Pelaporan',
'Pembayaran' => 'Pembayaran',
'Pembatalan' => 'Pembatalan',
'SLA' => 'SLA',
'Paparan' => 'Paparan'
];
$header = $headers[$type] ?? 'Pelaporan';
$authorization = null;
if ($header === 'SLA') {
$authorization = Authorization::with(['user','permohonan.lampiranDokumen.jenisLampiran'])->find($id);
$permohonan = Permohonan::with(['lampiranDokumen.jenisLampiran'])->find($authorization->permohonan_id);
} else {
$permohonan = Permohonan::with(['lampiranDokumen.jenisLampiran'])->find($id);
}
if ($header === 'SLA') {
return view('lpj::penilaian.otorisator.sla', compact('permohonan', 'header', 'authorization'));
}
if ($header === 'Paparan') {
$authorization = Authorization::with(['user'])->where('permohonan_id', $id)->first();
return view('lpj::penilaian.otorisator.show', compact('permohonan', 'header', 'authorization'));
}
return view('lpj::penilaian.otorisator.show', compact('permohonan', 'header', 'authorization'));
}
public function otorisatorUpdate(Request $request, $id, $context)
{
if ($context === 'Freze SLA' || $context === 'Unfreeze SLA') {
$authorization = Authorization::with(['user'])->find($id);
if (!$authorization) {
return response()->json([
'message' => 'Data authorization SLA tidak ditemukan.',
], 404);
}
$permohonan = Permohonan::find($authorization->permohonan_id);
} elseif ($context === 'Paparan') {
$authorization = Authorization::with(['user'])->find($id);
if (!$authorization) {
return response()->json([
'message' => 'Data authorization Paparan tidak ditemukan.',
], 404);
}
$permohonan = Permohonan::find($authorization->permohonan_id);
} else {
$permohonan = Permohonan::find($id);
}
if (!$permohonan) {
return response()->json([
'message' => 'Data permohonan tidak ditemukan.',
], 404);
}
switch (strtolower($context)) {
case 'pembayaran':
$newStatus = $permohonan->status_bayar === 'sudah_bayar' ? 'belum_bayar' : 'sudah_bayar';
$permohonan->update([
'status_bayar' => $newStatus,
'keterangan' => $request->keterangan,
]);
break;
case 'pembatalan':
$permohonan->update([
'status' => 'batal',
'keterangan' => $request->keterangan,
]);
break;
case 'pelaporan':
$role = Auth::user()->roles[0]->name;
$status = 'done';
$approvalField = null;
$lpj_ = optional(json_decode($permohonan->penilai->lpj));
$npw = $lpj_->total_nilai_pasar_wajar ?? 0;
$npw = str_replace('.', '', $npw);
if ($role === 'senior-officer') {
$approvalField = 'approval_so';
$status = $npw <=1000000000 ? 'done' : 'proses-laporan';
} elseif ($role === 'EO Appraisal') {
$approvalField = 'approval_eo';
$status = $npw <=5000000000 ? 'done' : 'proses-laporan';
} elseif ($role === 'DD Appraisal') {
$approvalField = 'approval_dd';
$status = 'done';
}
if ($status == 'done' && $permohonan->status_bayar === 'sudah_bayar' && $permohonan->penilai->type_penilai === 'standar' || $permohonan->penilai->type_penilai === 'sederhana') {
$_permohonan = Permohonan::with(['documents.jenisJaminan','penilaian._user_penilai','penilai','documents.detail.jenisLegalitasJaminan'])->find($permohonan->id);
if (isset($_permohonan->penilai->lpj)) {
$npw = json_decode($_permohonan->penilai->lpj, true);
$npw = $npw['total_nilai_pasar_wajar'] ?? 0;
}
$dataAdk = [
'debiture_id' => $_permohonan->debiture_id,
'jenis_agunan' => $_permohonan->documents->pluck('jenisJaminan.name')->unique()->implode(', '),
'alamat_agunan' => $_permohonan->documents->map(function ($document) {
return formatAlamat($document);
})->unique()->implode(', '),
'nama_pemilik' => $_permohonan->documents->pluck('pemilik.name')->unique()->implode(', '),
'tanggal_kunjungan' => $_permohonan->penilaian->tanggal_kunjungan,
'nama_penilai' => $_permohonan->penilaian->_user_penilai->userPenilaiTeam->name,
'nilai_likuidasi' => $_permohonan->nilai_liquidasi,
'nilai_pasar_wajar' => str_replace('.', '', $npw),
'bukti_kepemilikan' => $_permohonan->documents->flatMap(function ($document) {
return $document->detail->map(function ($detail) {
return $detail->jenisLegalitasJaminan->name ?? null;
});
})->filter()->unique()->implode(', '),
];
LaporanAdminKredit::create($dataAdk);
}
if ($approvalField) {
$this->updatePermohonan($permohonan, $status, $approvalField, $request->keterangan);
}
break;
case 'freze sla':
if (Auth::user()->roles[0]->name === 'senior-officer' || Auth::user()->roles[0]->name === 'administrator' && $authorization->approve_so === null) {
$authorization->update([
'status' => '3',
'status_so' => '1',
'approve_so' => Auth::user()->id,
'approve_so_at' => now(),
'keterangan_so' => $request->message,
]);
} elseif (Auth::user()->roles[0]->name === 'EO Appraisal' || Auth::user()->roles[0]->name === 'administrator' && $authorization->approve_so && $authorization->approve_eo === null) {
$status = '2';
if (in_array($permohonan->nilai_plafond_id, [1, 2])) {
$status = '1';
$permohonan->update([
'status' => $authorization->request
]);
}
$authorization->update([
'status' => $status,
'status_eo' => '1',
'approve_eo' => Auth::user()->id,
'approve_eo_at' => now(),
'keterangan_eo' => $request->message,
]);
} elseif (Auth::user()->roles[0]->name === 'DD Appraisal' || Auth::user()->roles[0]->name === 'administrator' && $authorization->approve_so && $authorization->approve_eo && $authorization->approve_dd === null) {
$authorization->update([
'status' => '1',
'status_dd' => '1',
'approve_dd' => Auth::user()->id,
'approve_dd_at' => now(),
'keterangan_dd' => $request->message,
]);
$permohonan->update([
'status' => $authorization->request
]);
}
break;
case 'paparan':
if (Auth::user()->roles[0]->name === 'senior-officer' || Auth::user()->roles[0]->name === 'administrator' && $authorization->approve_so === null) {
$status = '3';
if (in_array($permohonan->nilai_plafond_id, [3])) {
$status = '1';
$permohonan->update([
'status' => $authorization->request
]);
}
$authorization->update([
'status' => $status,
'status_so' => '1',
'approve_so' => Auth::user()->id,
'approve_so_at' => now(),
'keterangan_so' => $request->keterangan,
]);
$permohonan->update([
'tanggal_paparan' => $request->tanggalPaparan,
'keterangan' => $request->keterangan
]);
} elseif (Auth::user()->roles[0]->name === 'EO Appraisal') {
$status = '2';
if (in_array($permohonan->nilai_plafond_id, [1,2, 3])) {
$status = '1';
$permohonan->update([
'status' => $authorization->request
]);
}
$authorization->update([
'status' => $status,
'status_eo' => '1',
'approve_eo' => Auth::user()->id,
'approve_eo_at' => now(),
'keterangan_eo' => $request->keterangan,
]);
} elseif (Auth::user()->roles[0]->name === 'DD Appraisal' || Auth::user()->roles[0]->name === 'administrator' && $authorization->approve_so && $authorization->approve_dd === null) {
$authorization->update([
'status' => '1',
'status_dd' => '1',
'approve_dd' => Auth::user()->id,
'approve_dd_at' => now(),
'keterangan_dd' => $request->keterangan,
]);
$permohonan->update([
'status' => 'paparan'
]);
}
break;
case 'unfreeze sla':
$authorization->update([
'request' => 'unfreeze-sla',
]);
$permohonan->update([
'status' => 'unfreeze-sla',
]);
break;
default:
return response()->json([
'message' => 'Konteks otorisasi tidak valid.',
], 400);
}
return response()->json([
'message' => 'Otorisasi berhasil dilakukan.',
'data' => $permohonan,
]);
}
public function updatePermohonan($permohonan, $status, $approvalField, $message)
{
$permohonan = Permohonan::find($id);
return view('lpj::penilaian.otorisator.show', compact('permohonan'));
$permohonan->update([
'status' => $status,
$approvalField => Auth::user()->id,
"{$approvalField}_at" => now(),
'keterangan' => $message,
]);
}
public function dataForAuthorization(Request $request, $otorisator)
{
if (is_null($this->user) || !$this->user->can('debitur.view')) {
// abort(403, 'Sorry! You are not allowed to view users.');
}
$status = '';
switch ($otorisator) {
case 'Pelaporan':
$status = 'proses paparan';
break;
case 'Pembayaran':
$status = 'proses';
break;
case 'Pembatalan':
$status = 'order';
break;
default:
$status = '';
break;
}
// Tentukan status berdasarkan otorisator
$status = match ($otorisator) {
'Pelaporan' => 'proses-laporan',
'Pembayaran' => 'proses',
'Pembatalan' => 'batal',
'SLA' => 'request-freeze',
'Paparan' => 'proses-paparan',
default => '',
};
$query = Permohonan::query();
@@ -422,6 +715,7 @@ class PenilaianController extends Controller
// Pencarian berdasarkan parameter search
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
@@ -429,6 +723,7 @@ class PenilaianController extends Controller
$q->orWhereRelation('debiture', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('region', 'name', 'LIKE', '%' . $search . '%');
$q->orWhere('status', 'LIKE', '%' . $search . '%');
});
}
@@ -437,11 +732,41 @@ class PenilaianController extends Controller
if (!empty($otorisator)) {
if ($status == 'proses') {
$query->whereIn('status_bayar', ['sudah_bayar', 'belum_bayar']);
} else {
} elseif ($status == 'proses-laporan') {
$query->whereRaw('LOWER(status) = ?', [strtolower($status)]);
} elseif ($status == 'batal') {
$query->whereRaw('LOWER(status) = ?', [strtolower($status)]);
} elseif ($status == 'request-freeze') {
$query->whereRaw('LOWER(status) = ?', [strtolower($status)]);
} elseif ($status == 'proses-paparan') {
$query->whereRaw('LOWER(status) IN (?, ?)', ['proses-paparan', 'paparan']);
}
}
// Filter berdasarkan region user yang login
// if ($status == 'proses-laporan') {
// $requestedRegion = $request->get('search');
// if ($requestedRegion) {
// $query->whereHas('region', function ($q) use ($requestedRegion) {
// $q->where('name', $requestedRegion);
// });
// } else {
// $query->whereHas('region.teams.teamsUsers', function ($q) {
// $q->where('user_id', Auth::id());
// });
// }
// } else {
if (Auth::user()->hasRole('senior-officer')) {
$query->whereHas('region.teams.teamsUsers', function ($q) {
$q->where('user_id', Auth::id());
});
}
// }
// Sorting berdasarkan sortField dan sortOrder
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
@@ -469,7 +794,25 @@ class PenilaianController extends Controller
$filteredRecords = $query->count();
// Ambil data dengan relasi
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian'])->get();
$data = $query->with([
'user',
'debiture',
'branch',
'tujuanPenilaian',
'nilaiPlafond',
'penilaian.userPenilai' => function ($q) {
$q->where('role', 'penilai')->with(['user', 'team.regions']);
},
'penilai',
'approveSo',
'approveEo',
'approveDd',
'authorization.approveSo',
'authorization.approveEo',
'authorization.approveDd'
])->get();
// Hitung jumlah halaman
$pageCount = ceil($totalRecords / $size);
@@ -489,5 +832,191 @@ class PenilaianController extends Controller
]);
}
public function view_laporan(Request $request)
{
$id = $request->permohonanId;
$documentId = $request->query('documentId');
$jaminanId = $request->query('jaminanId');
$permohonan = $this->surveyorController->getPermohonanJaminanId($id, $documentId, $jaminanId);
$basicData = $this->surveyorController->getCommonData();
$provinces = Province::all();
$inspeksi = Inspeksi::where('permohonan_id', $id)->where('dokument_id', $documentId)->first();
$lpj = Penilai::where('permohonan_id', $id)
->where('dokument_id', $documentId)
->first();
$penilai = $lpj;
$forminspeksi = null;
$lpjData = null;
if ($inspeksi) {
$forminspeksi = json_decode($inspeksi->data_form, true);
}
$nomorLaporan = $this->penilaiController->generateNoLaporan($permohonan, $documentId, $lpj->type_penilai);
$formFoto = $formPeta = $cities = $districts = $villages = $memo = null;
if ($lpj) {
$lpjData = json_decode($lpj->lpj, true);
$resumeData = json_decode($lpj->resume, true);
$callReport = json_decode($lpj->call_report, true);
if (isset($lpj->memo)) {
$memo = json_decode($lpj->memo);
}
if (isset($memo->lokasi->province_code)) {
$cities = City::where('province_code', $memo->lokasi->province_code)->get();
}
if (isset($memo->lokasi->city_code)) {
$districts = District::where('city_code', $memo->lokasi->city_code)->get();
}
if (isset($memo->lokasi->district_code)) {
$villages = Village::where('district_code', $memo->lokasi->district_code)->get();
}
$rap = json_decode($lpj->rap, true);
}
if (empty($lpj->type_penilai)) {
return redirect()->back()->with('error', 'Masih diproses');
}
$viewLaporan = $this->getViewLaporan($lpj->type_penilai);
if (empty($viewLaporan)) {
return redirect()->back()->with('error', 'Laporan belum dibuat');
}
return view('lpj::' . $viewLaporan, compact('permohonan', 'forminspeksi', 'basicData', 'inspeksi', 'lpjData', 'provinces', 'resumeData', 'rap', 'memo', 'cities', 'districts', 'villages', 'formFoto', 'formPeta', 'nomorLaporan', 'penilai', 'callReport'));
}
private function getViewLaporan($tipe)
{
$viewMap = [
'sederhana' => 'penilai.components.lpj-sederhana-standar',
'standar' => 'penilai.components.lpj-sederhana-standar',
'resume' => 'penilai.components.resume',
'memo' => 'penilai.components.memo',
'rap' => 'penilai.components.rap-penilai',
'call-report' => 'penilai.components.call-report',
];
return $viewMap[$tipe] ?? '';
}
public function storePenilaiLaporan(Request $request)
{
DB::beginTransaction();
try {
$validatedRequest = app(FormSurveyorRequest::class);
$this->surveyorController->store($validatedRequest);
$data = [
'luas_tanah_penilai' => $request->input('luas_tanah_penilai'),
'nilai_tanah_1' => $request->input('nilai_tanah_1'),
'nilai_tanah_2' => $request->input('nilai_tanah_2'),
'luas_bangunan_penilai' => $request->input('luas_bangunan_penilai'),
'nilai_bangunan_1' => $request->input('nilai_bangunan_1'),
'nilai_bangunan_2' => $request->input('nilai_bangunan_2'),
'sarana_pelengkap_penilai' => $request->input('sarana_pelengkap_penilai'),
'nilai_sarana_pelengkap_1' => $request->input('nilai_sarana_pelengkap_1'),
'nilai_sarana_pelengkap_2' => $request->input('nilai_sarana_pelengkap_2'),
'total_nilai_pasar_wajar' => $request->input('total_nilai_pasar_wajar'),
'likuidasi' => $request->input('likuidasi'),
'likuidasi_nilai_1' => $request->input('likuidasi_nilai_1'),
'likuidasi_nilai_2' => $request->input('likuidasi_nilai_2'),
'asuransi_luas_bangunan' => $request->input('asuransi_luas_bangunan'),
'asuransi_nilai_1' => $request->input('asuransi_nilai_1'),
'asuransi_nilai_2' => $request->input('asuransi_nilai_2'),
];
// Update atau buat data baru
Penilai::updateOrCreate(
[
'permohonan_id' => $request->permohonanId,
'dokument_id' => $request->documentId,
],
[
'lpj' => json_encode($data),
]
);
DB::commit();
return response()->json([
'success' => true,
'message' => 'Berhasil Update Laporan penilai',
'data' => $request->all(),
], 200);
} catch (\Throwable $e) {
DB::rollBack();
return response()->json([
'success' => false,
'message' => 'Terjadi kesalahan',
'error' => $e->getMessage()
], 500);
}
}
public function revisiLaporan(Request $request, $id)
{
// dd($id);
if ($request->dataHeader == 'Paparan' || $request->dataHeader == 'Freze SLA') {
$authorization = Authorization::find($id);
$permohonan = Permohonan::find($authorization->permohonan_id);
} else {
$permohonan = Permohonan::find($id);
$userRole = Auth::user()->roles[0]->name;
}
if ($permohonan->status === 'proses-paparan') {
if ($authorization) {
$authorization->delete();
}
$status = 'revisi-paparan';
} elseif ($permohonan->status === 'request-freeze') {
if ($authorization) {
$authorization->delete();
}
$status = 'reject-freeze';
} elseif ($permohonan->status === 'proses-laporan' && $userRole === 'senior-officer') {
$status = 'revisi-laporan';
} elseif ($permohonan->status === 'proses-laporan' && $userRole === 'EO Appraisal') {
$permohonan->update([
'approval_so' => 0,
'approval_so_at' => null,
]);
$status = 'revisi-laporan';
} elseif ($permohonan->status === 'proses-laporan' && $userRole === 'DD Appraisal') {
$permohonan->update([
'approval_so' => 0,
'approval_so_at' => null,
'approval_eo' => 0,
'approval_eo_at' => null,
]);
$status = 'revisi-laporan';
} else {
return response()->json([
'success' => false,
'message' => 'Tidak ada tindakan yang dapat dilakukan untuk status saat ini.',
], 400);
}
// Perbarui status dan informasi lainnya
$permohonan->update([
'status' => $status,
'keterangan' => $request->keterangan,
'submitted_at' => now(),
]);
return response()->json([
'success' => true,
'message' => 'Berhasil Revisi Laporan penilai.',
], 200);
}
}

View File

@@ -3,9 +3,11 @@
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Barryvdh\DomPDF\Facade\Pdf;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Location\Models\City;
use Modules\Location\Models\District;
@@ -18,13 +20,26 @@
use Modules\Lpj\Models\DokumenJaminan;
use Modules\Lpj\Models\JenisFasilitasKredit;
use Modules\Lpj\Models\NilaiPlafond;
use Modules\Lpj\Models\Penilaian;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\PermohonanPembatalan;
use Modules\Lpj\Models\PersetujuanPenawaran;
use Modules\Lpj\Models\StatusPermohonan;
use Modules\Lpj\Models\TujuanPenilaian;
use Modules\Lpj\Services\PermohonanHistoryService;
use Modules\Lpj\Models\Noc;
class PermohonanController extends Controller
{
public $user;
public $user;
protected $historyService;
public function __construct(PermohonanHistoryService $historyService)
{
$this->historyService = $historyService;
}
public function index()
{
@@ -35,9 +50,42 @@
{
$validate = $request->validated();
if ($validate) {
if(auth()->user()->hasRole('admin')){
$validate['status'] = "preregister";
}
try {
// Process file upload
$filePath = null;
if ($request->hasFile('attachment')) {
$file = $request->file('attachment');
$fileName = time() . '_' . $file->getClientOriginalName();
$filePath = $file->storeAs('permohonan_attachments', $fileName, 'public');
}
// Get keterangan if provided
$keterangan = $request->input('keterangan') ?? null;
// Save to database
Permohonan::create($validate);
$permohonan = Permohonan::create($validate);
// Create history
$this->historyService->createHistory(
$permohonan,
$validate['status'],
$keterangan,
[], // beforeRequest is empty for new permohonan
$permohonan->toArray(),
$filePath,
);
$documents = DokumenJaminan::where('permohonan_id', $permohonan->id)->get();
if (count($documents) < 1) {
return redirect()->route(
'debitur.jaminan.create',
array_merge(['permohonan_id' => $permohonan->id], ['id' => $permohonan->debiture->id]),
)->with('success', 'Permohonan created successfully, Lengkapi data jaminan terlebih dahulu');
}
return redirect()
->route('permohonan.index')->with('success', 'Permohonan created successfully');
} catch (Exception $e) {
@@ -105,27 +153,6 @@
);
}
public function update(PermohonanRequest $request, $id)
{
$validate = $request->validated();
if ($validate) {
try {
// Update in database
$permohonan = Permohonan::find($id);
if ($permohonan->status == 'revisi') {
$validate['status'] = 'order';
}
$permohonan->update($validate);
return redirect()
->route('permohonan.index')->with('success', 'Permohonan updated successfully');
} catch (Exception $e) {
return redirect()
->route('permohonan.edit', $id)->with('error', 'Failed to update permohonan');
}
}
}
public function destroy($id)
{
try {
@@ -148,6 +175,126 @@
// Retrieve data from the database
$query = Permohonan::query();
if (!Auth::user()->hasAnyRole(['administrator','admin'])) {
$query = $query->where('branch_id', Auth::user()->branch_id);
}
$query = $query->orderBy('nomor_registrasi', 'desc');
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
$q->orWhere('mig_mst_lpj_nomor_jaminan', 'LIKE', '%' . $search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('debiture', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
$q->orWhere('status', 'LIKE', '%' . $search . '%');
});
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
$size = $request->get('size', 10);
if ($size == 0) {
$size = 10;
}
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->get();
$data = $data->map(function ($item) {
return [
'id' => $item->id,
'nomor_registrasi' => $item->nomor_registrasi,
'mig_mst_lpj_nomor_jaminan' => $item->mig_mst_lpj_nomor_jaminan,
'tanggal_permohonan' => $item->tanggal_permohonan ? dateFormat(
$item->tanggal_permohonan,
) : null,
'pemohon' => $item->user->name ?? 'N/A',
'branch' => $item->branch->name ?? 'N/A',
'debiture' => [
'name' => $item->debiture->name,
],
'tujuan_penilaian' => [
'code' => $item->tujuanPenilaian->code ?? null,
'name' => $item->tujuanPenilaian->name ?? null,
],
'status' => $item->status,
'documents' => count($item->documents),
'keterangan' => $item->keterangan,
'penilaian' => [
'id' => $item->penilaian->id ?? null,
'waktu_penilaian' => $item->penilaian->waktu_penilaian ?? null,
'rejected_note' => $item->penilaian->rejected_note ?? null,
'authorized_status' => $item->penilaian->authorized_status ?? null,
],
'registrasi_catatan' => $item->registrasi_catatan,
];
});
// Calculate the page count
$pageCount = ceil($totalRecords / $size);
// Calculate the current page number
$currentPage = max(1, $request->get('page', 1));
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
public function export()
{
return Excel::download(new PermohonanExport(), 'permohonan.xlsx');
}
public function authorization()
{
return view('lpj::permohonan.authorization.index');
}
public function dataForAuthorization(Request $request)
{
if (is_null($this->user) || !$this->user->can('debitur.view')) {
//abort(403, 'Sorry! You are not allowed to view users.');
}
// Retrieve data from the database
$query = Permohonan::query()->with('documents')->has('documents', '>', 0)->where('status', '=', 'order');
if (!Auth::user()->hasAnyRole(['administrator'])) {
$query = $query->where('branch_id', Auth::user()->branch_id);
}
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
@@ -205,83 +352,6 @@
]);
}
public function export()
{
return Excel::download(new PermohonanExport, 'permohonan.xlsx');
}
public function authorization()
{
return view('lpj::permohonan.authorization.index');
}
public function dataForAuthorization(Request $request)
{
if (is_null($this->user) || !$this->user->can('debitur.view')) {
//abort(403, 'Sorry! You are not allowed to view users.');
}
// Retrieve data from the database
$query = Permohonan::query();
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('debiture', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('tujuanPenilaian', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('branch', 'name', 'LIKE', '%' . $search . '%');
$q->orWhere('status', 'LIKE', '%' . $search . '%');
});
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian'])->where('status', '=', 'order')->get(
);
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = 0 + 1;
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
public function showAuthorization($id)
{
$permohonan = Permohonan::find($id);
@@ -295,6 +365,55 @@
$permohonan->status = $request->status;
$permohonan->keterangan = $request->keterangan;
$permohonan->save();
if ($permohonan->status_bayar == 'belum_bayar') {
PersetujuanPenawaran::firstOrCreate(
['permohonan_id' => $id],
['created_by' => Auth::id()]
);
}
if ($permohonan->status == 'sudah_dibayar') {
$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],
[
'created_by' => Auth::id(),
'bukti_bayar' => $buktiBayar->first()->dokumen_jaminan[0],
]
);
try {
Noc::updateOrCreate([
'permohonan_id' => $persetujuanPenawaran->permohonan_id,
'persetujuan_penawaran_id' => $persetujuanPenawaran->id
],[
'bukti_bayar' => $persetujuanPenawaran->bukti_bayar,
]);
} catch (\Exception $e) {
\Log::error('Failed to create or update NOC: ' . $e->getMessage());
return redirect()
->route('persetujuan-penawaran.index')
->with('error', 'Persetujuan Penawaran berhasil disimpan tetapi gagal membuat NOC: ' . $e->getMessage());
}
}
} catch (Exception $e) {
return redirect()->route('authorization.show', $id)->with('error', 'Failed to update permohonan');
}
@@ -317,4 +436,139 @@
// $pdf = Pdf::loadView('lpj::permohonan.print', compact('permohonan'));
// return $pdf->stream();
}
public function showPembatalan($id)
{
$permohonan = Permohonan::with(['pembatalan', 'debiture'])->findOrFail($id);
return view('lpj::permohonan.pembatalan-form', compact('permohonan'));
}
public function pembatalan(Request $request)
{
// Validate the request
$validatedData = $request->validate([
'permohonan_id' => 'required|exists:permohonan,id',
'alasan_pembatalan' => 'required|string',
'file_pembatalan' => 'required|file|mimes:pdf,doc,docx|max:2048',
]);
// Handle file upload
if ($request->hasFile('file_pembatalan')) {
$file = $request->file('file_pembatalan');
$filename = time() . '_' . $file->getClientOriginalName();
$filePath = $file->storeAs('pembatalan', $filename, 'public');
$validatedData['file_pembatalan'] = $filePath;
}
// Add created_by
$validatedData['created_by'] = auth()->id();
// Create new PermohonanPembatalan
$pembatalan = PermohonanPembatalan::create($validatedData);
return redirect()->route('permohonan.index')->with('success', 'Pembatalan Permohonan Menunggu Approval');
}
public function storeAproved(Request $request, $id)
: JsonResponse {
$data = [];
if (request()->ajax()) {
try {
$penilaian = Penilaian::findOrFail($id);
$penilaian->update([
'authorized_status' => 1,
]);
$permohonan = Permohonan::findOrFail($request->permohonan_id);
$permohonan->update([
'status' => 'proses-survey',
]);
$data['status'] = 'success';
$data['message'] = 'Jadwal ' . $request->noReg . ' berhasil di aprove';
} catch (Exception $e) {
$data['status'] = 'error';
$data['message'] = 'Gagal membuat jadwal: ' . $e->getMessage();
}
} else {
$data['status'] = 'error';
$data['message'] = "no ajax request";
}
return response()->json($data);
}
public function update(PermohonanRequest $request, $id)
{
$permohonan = Permohonan::findOrFail($id);
$beforeRequest = $permohonan->toArray();
$validate = $request->validated();
if ($validate) {
try {
// Update in database
if ($permohonan->status == 'revisi') {
$validate['status'] = 'order';
}
$permohonan->update($validate);
$documents = DokumenJaminan::where('permohonan_id', $permohonan->id)->get();
if (count($documents) < 1) {
return redirect()->route(
'debitur.jaminan.create',
array_merge(['permohonan_id' => $permohonan->id], ['id' => $permohonan->debiture->id]),
)->with('success', 'Permohonan created successfully, Lengkapi data jaminan terlebih dahulu');
}
return redirect()
->route('permohonan.index')->with('success', 'Permohonan updated successfully');
} catch (Exception $e) {
return redirect()
->route('permohonan.edit', $id)->with('error', 'Failed to update permohonan');
}
}
}
public function storeRescheduleSurvey(Request $request, $id)
{
try {
$validatedData = $request->validate([
'permohonan_id' => 'required|exists:permohonan,id',
'penilaian_id' => 'nullable',
'nomor_registrasi' => 'required',
'reschedule_note' => 'required',
'reschedule_date' => 'required',
'keterangan' => 'required',
]);
DB::beginTransaction();
$permohonan = Permohonan::findOrFail($request->permohonan_id);
$permohonan->update([
'status' => 'request-reschedule',
]);
$penilaian = Penilaian::findOrFail($id);
$penilaian->update([
'reschedule_date' => $request->reschedule_date,
'reschedule_note' => $request->reschedule_note,
]);
DB::commit();
return response()->json([
'status' => 'success',
'message' => 'Proses request reschedule permohonan Nomor registrasi ' . $request->nomor_registrasi . ' berhasil',
]);
} catch (Exception $e) {
DB::rollBack();
return response()->json([
'status' => 'error',
'message' => 'Gagal membuat request reschedule: ' . $e->getMessage(),
]);
}
}
}

View File

@@ -0,0 +1,261 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Modules\Lpj\Http\Requests\PersetujuanPenawaranRequest;
use Modules\Lpj\Models\Noc;
use Modules\Lpj\Models\PenawaranDetailTender;
use Modules\Lpj\Models\PenawaranDetailTenderLog;
use Modules\Lpj\Models\PenawaranTender;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\PersetujuanPenawaran;
class PersetujuanPenawaranController extends Controller
{
public $user;
/**
* Display a listing of the resource.
*/
public function index()
{
$persetujuanPenawarans = PersetujuanPenawaran::all();
return view('lpj::persetujuan_penawaran.index', compact('persetujuanPenawarans'));
}
/**
* Store a newly created resource in storage.
*/
/**
* Store a newly created resource in storage.
*/
/**
* Store a newly created resource in storage.
*/
public function store(PersetujuanPenawaranRequest $request)
{
$validated = $request->validated();
$validated['created_by'] = Auth::id();
$validated['status'] = '0';
$validated['nominal_bayar'] = $validated['biaya_final'];
$persetujuanPenawaran = PersetujuanPenawaran::updateOrCreate(
['penawaran_id' => $validated['penawaran_id']],
$validated,
);
$folderPath = 'persetujuan_penawaran/' . $validated['penawaran_id'];
if ($request->hasFile('file_persetujuan_penawaran')) {
$persetujuanPenawaran->file_persetujuan_penawaran = $request->file('file_persetujuan_penawaran')->store(
$folderPath,
'public',
);
}
if ($request->hasFile('surat_representasi')) {
$persetujuanPenawaran->surat_representasi = $request->file('surat_representasi')->store(
$folderPath,
'public',
);
}
if ($request->hasFile('bukti_bayar')) {
$persetujuanPenawaran->bukti_bayar = $request->file('bukti_bayar')->store($folderPath, 'public');
}
$persetujuanPenawaran->save();
// Save NOC
try {
$noc = Noc::updateOrCreate([
'permohonan_id' => $persetujuanPenawaran->permohonan_id,
'persetujuan_penawaran_id' => $persetujuanPenawaran->id
],[
'bukti_bayar' => $persetujuanPenawaran->bukti_bayar,
]);
} catch (\Exception $e) {
\Log::error('Failed to create or update NOC: ' . $e->getMessage());
return redirect()
->route('persetujuan-penawaran.index')
->with('error', 'Persetujuan Penawaran berhasil disimpan tetapi gagal membuat NOC: ' . $e->getMessage());
}
return redirect()
->route('persetujuan-penawaran.index')->with('success', 'Persetujuan Penawaran berhasil disimpan.');
}
/**
* Update the specified resource in storage.
*/
public function update(PersetujuanPenawaranRequest $request, PersetujuanPenawaran $persetujuanPenawaran)
{
$validated = $request->validated();
$validated['updated_by'] = Auth::id();
$persetujuanPenawaran->update($validated);
return redirect()
->route('persetujuan-penawaran.index')->with('success', 'Persetujuan Penawaran updated successfully');
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view('lpj::persetujuan_penawaran.create');
}
/**
* Display the specified resource.
*/
public function show($id)
{
$permohonan = Permohonan::find($id);
$permohonan->status = 'tender';
$dataDetailPenawaranLog = [];
// andy add update status penawaran
// update detail_penawaran => detail_penawaran.status = 1 (untuk all KJPP)
// update penawaran => penawaran.status ="tender", penawaran.updated_at, penawaran.updated_by
// update permohonan => permohonan.status ="tender", permohonan.updated_at, permohonan.updated_by
// insert detail_permohonan_log
$penawaran = PenawaranTender::where('nomor_registrasi', $permohonan->nomor_registrasi)->first();
// dd($penawaran->id);
PenawaranDetailTender::where('penawaran_id', $penawaran->id)->update([
'status' => 1,
'updated_by' => Auth::id(),
'updated_at' => now(),
]);
PenawaranTender::where('id', $penawaran->id)->update([
'status' => 'tender',
'updated_by' => Auth::id(),
'updated_at' => now(),
]);
$detailPenawaran = PenawaranDetailTender::where('penawaran_id', $penawaran->id)->distinct()->get();
// log
if (sizeof($detailPenawaran) > 0) {
foreach ($detailPenawaran as $model) {
array_push($dataDetailPenawaranLog, [
'detail_penawaran_id' => $model->id,
'kjpp_rekanan_id' => $model->kjpp_rekanan_id,
'penawaran_id' => $model->penawaran_id,
'no_proposal' => $model->no_proposal,
'tgl_proposal' => $model->tgl_proposal,
'biaya_penawaran' => $model->biaya_penawaran,
'attachment' => $model->attachment,
'dokumen_persetujuan' => $model->dokumen_persetujuan,
'status' => $model->status,
'authorized_status' => $model->authorized_status,
'authorized_at' => $model->authorized_at,
'authorized_at' => $model->authorized_at,
'created_at' => $model->created_at,
'updated_at' => $model->updated_at,
'deleted_at' => $model->deleted_at,
'created_by' => $model->created_by,
'updated_by' => $model->updated_by,
'deleted_by' => $model->deleted_by,
]);
}
PenawaranDetailTenderLog::insert($dataDetailPenawaranLog);
}
// log
// andy add update status penawaran
return $permohonan->save();
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
$permohonan = Permohonan::with(['debiture', 'penawaranTender.detail'])->find($id);
$persetujuanPenawaran = PersetujuanPenawaran::where('permohonan_id', $id)->first();
return view('lpj::persetujuan_penawaran.form', compact('permohonan', 'persetujuanPenawaran'));
}
/**
* Remove the specified resource from storage.
*/
public function destroy(PersetujuanPenawaran $persetujuanPenawaran)
{
$persetujuanPenawaran->delete();
return redirect()
->route('persetujuan-penawaran.index')->with('success', 'Persetujuan Penawaran deleted successfully');
}
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('persetujuan_penawaran.view')) {
//abort(403, 'Sorry! You are not allowed to view persetujuan penawaran.');
}
// Retrieve data from the database
//$query = Permohonan::query()->where(['status' => 'persetujuan-penawaran']);
$query = Permohonan::query()
->where(['status' => 'persetujuan-penawaran'])
->whereHas('penawaranTender', function ($q) {
$q->where('status', 'persetujuan-penawaran');
});
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', "%$search%");
});
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page
$data = $query->with(['debiture', 'penawaranTender.detail', 'penawaranTender.persetujuan'])->get();
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
// Calculate the current page number
$currentPage = $request->get('page', 1);
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
}

View File

@@ -5,6 +5,7 @@ namespace Modules\Lpj\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use App\Http\Controllers\Controller;
use Carbon\Carbon;
use Exception;
use Maatwebsite\Excel\Facades\Excel;
use Illuminate\Http\JsonResponse;
@@ -12,11 +13,17 @@ use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\DB;
use Modules\Lpj\Http\Requests\ProsesPenawaranRequest;
use Modules\Lpj\Models\JenisLaporan;
use Modules\Lpj\Models\KJPP;
use Modules\Lpj\Models\PenawaranDetailTender;
use Modules\Lpj\Models\PenawaranDetailTenderLog;
use Modules\Lpj\Models\PenawaranTender;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\StatusPermohonan;
use Modules\Lpj\Models\TujuanPenilaian;
use Modules\Lpj\Models\TujuanPenilaianKJPP;
class ProsesPenawaranController extends Controller
{
@@ -38,16 +45,60 @@ class ProsesPenawaranController extends Controller
}
// Retrieve data from the database
$query = PenawaranTender::query()->where('status', '=', 'tender')->withCount('penawarandetails');
// $query = PenawaranTender::query()->whereIn('status', ['tender', 'proposal-tender'])->withCount('penawarandetails');
// penawaran need union with permohonan
$query = PenawaranTender::query()->whereIn('penawaran.status', ['tender', 'proposal-tender'])
->select('penawaran.id',
'penawaran.nomor_registrasi',
'penawaran.code as penawaran_code',
'penawaran.start_date',
'penawaran.end_date',
'penawaran.status as statusnya',
'debitures.name as debitures_name',
'permohonan.tanggal_permohonan',
'users.name as user_pemohon',
'branches.name as branches_name',
'tujuan_penilaian.name as tujuan_penilaian_name',
'tujuan_penilaian_kjpp.name as tujuan_penilaian_kjpp_name'
)
->withCount('penawarandetails')
->leftJoin('permohonan', 'permohonan.nomor_registrasi', '=', 'penawaran.nomor_registrasi')
->leftJoin('users', 'users.id', '=', 'permohonan.user_id')
->leftJoin('branches', 'branches.id', '=', 'permohonan.branch_id')
->leftJoin('tujuan_penilaian', 'tujuan_penilaian.id','=','permohonan.tujuan_penilaian_id')
->leftJoin('debitures', 'debitures.id', '=', 'permohonan.debiture_id')
->leftJoin('tujuan_penilaian_kjpp', 'tujuan_penilaian_kjpp.id', '=', 'penawaran.tujuan_penilaian_kjpp_id');
$permohonanQuery = Permohonan::whereIn('permohonan.status', ['registered'])->where('permohonan.jenis_penilaian_id', '=', 2)
->select('permohonan.id',
'permohonan.nomor_registrasi',
DB::raw('"" as penawaran_code'),
DB::raw('"" as start_date'),
DB::raw('"" as end_date'),
'permohonan.status as statusnya',
'debitures.name as debitures_name',
'permohonan.tanggal_permohonan',
'users.name as user_pemohon',
'branches.name as branches_name',
'tujuan_penilaian.name as tujuan_penilaian_name',
DB::raw('"" as tujuan_penilaian_kjpp_name'),
DB::raw('"-" as penawarandetails_count'))
->leftJoin('users', 'users.id', '=', 'permohonan.user_id')
->leftJoin('branches', 'branches.id', '=', 'permohonan.branch_id')
->leftJoin('debitures', 'debitures.id', '=', 'permohonan.debiture_id')
->leftJoin('tujuan_penilaian', 'tujuan_penilaian.id','=','permohonan.tujuan_penilaian_id');
$query->union($permohonanQuery);
// penawaran need union with permohonan
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('tujuanPenilaianKJPP', 'name', 'LIKE', '%' . $search . '%');
$q->orWhere('status', 'LIKE', '%' . $search . '%');
$q->where('penawaran.nomor_registrasi', 'LIKE', '%' . $search . '%');
//$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
//$q->orWhereRelation('tujuanPenilaianKJPP', 'name', 'LIKE', '%' . $search . '%');
//$q->orWhere('status', 'LIKE', '%' . $search . '%');
});
}
@@ -74,8 +125,29 @@ class ProsesPenawaranController extends Controller
$filteredRecords = $query->count();
// Get the data for the current page
//$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian'])->get();
$data = $query->with(['tujuanPenilaianKjpp','permohonan','permohonan.debiture'])->get();
// $data = $query->with(['tujuanPenilaianKjpp','permohonan','permohonan.debiture'])->get();
$data = $query->get();
// format date
$i = 0;
foreach ($data as $obj) {
// tanggal_permohonan
if ($obj->tanggal_permohonan) {
$data[$i]->tanggal_permohonan = Carbon::parse($obj->tanggal_permohonan)->format('d M Y');
}
// date_range
$data[$i]->date_range = "-";
if ($obj->start_date && $obj->end_date)
{
$data[$i]->date_range = Carbon::parse($obj->start_date)->format('d M Y') . ' - ' .
Carbon::parse($obj->end_date)->format('d M Y');
}
$i++;
}
// format date
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
@@ -97,6 +169,7 @@ class ProsesPenawaranController extends Controller
public function edit($id)
{
// $id => penawaran.id
return view('lpj::prosespenawaran.edit', compact('id'));
}
@@ -108,7 +181,7 @@ class ProsesPenawaranController extends Controller
if (request()->ajax()) {
$id = $request->id;
$penawaran = PenawaranTender::find($id);
$penawaran = PenawaranTender::with('permohonan.debiture')->find($id);
$penawrandetails = PenawaranDetailTender::where('penawaran_id','=',$id)
->leftJoin('kjpp', 'kjpp.id', '=', 'detail_penawaran.kjpp_rekanan_id')
->select('detail_penawaran.*', 'kjpp.code AS kjpp_code', 'kjpp.name AS kjpp_name')
@@ -126,7 +199,18 @@ class ProsesPenawaranController extends Controller
}
$i++;
}
DB::enableQueryLog();
$kjpps = KJPP::whereNotIn('id', function($query) use ($id) {
$query->select('kjpp_rekanan_id')
->from('detail_penawaran')
->where('penawaran_id', '=', $id)
->where('status','=',1); // status=1 (masih aktif)
})
->select('id', 'name', 'code') // Pilih beberapa kolom sekaligus
->get();
$sql=DB::getQueryLog();
$data['sql'] = $sql;
$data['kjpps'] = $kjpps;
$data['penawaran'] = $penawaran;
$data['penawrandetails'] = $penawrandetails;
$data['status'] = 'success';
@@ -150,23 +234,26 @@ class ProsesPenawaranController extends Controller
*/
public function update(Request $request, $id): JsonResponse
{
// $id => detail_penawaran.id
// init
$data = array();
$dataPenawaranDetail = array();
if (request()->ajax()) {
$validator = ProsesPenawaranController::rulesEditnya($request, $id);
if ($validator['fails']) {
$data['message'] = $validator['errors'];
$data['status'] = 'error';
}
else
$penawarandetail = PenawaranDetailTender::find($id);
// cek masa aktif penawaran
$checkActiveDateRange = checkActiveDateRangePenawaran($penawarandetail->penawaran_id);
// cek status (penawaran.status = tender)
$penawaran = PenawaranTender::find($penawarandetail->penawaran_id);
if($checkActiveDateRange && ('tender'==$penawaran->status))
{
try {
$dataPenawaranDetail = ['updated_by' => Auth::id(),
'updated_at' => now(),
'biaya_penawaran' => str_replace(".","",$request->biaya_penawaran)
'updated_at' => now(),
'no_proposal' => $request->no_proposal,
'tgl_proposal' => $request->tgl_proposal,
'biaya_penawaran' => str_replace(".","",$request->biaya_penawaran)
];
if ($request->hasFile('dokumen_persetujuan'))
@@ -186,13 +273,6 @@ class ProsesPenawaranController extends Controller
$newFileNameWithPath = $folderPath . $newFileName;
$dataPenawaranDetail['attachment'] = $myFile;
$dataPenawaranDetail['dokumen_persetujuan'] = $newFileNameWithPath;
$penawarandetail = PenawaranDetailTender::findOrFail($id);
$penawarandetail->update($dataPenawaranDetail);
$data['detailpenawaran_id'] = $id;
$data['status'] = 'success';
$data['message'] ['message_success'] = array('Proses Penawarn KJPP successfully');
}
else
{
@@ -200,19 +280,24 @@ class ProsesPenawaranController extends Controller
$data['message'] ['check_file_jenis'] = array("Silahkan upload file pdf");
}
}
else
{
$data['status'] = 'error';
$data['message'] ['check_file'] = array("Silahkan upload file");
}
$penawarandetail = PenawaranDetailTender::findOrFail($id);
$penawarandetail->update($dataPenawaranDetail);
$data['detailpenawaran_id'] = $id;
$data['status'] = 'success';
$data['message'] ['message_success'] = array('Proses Penawarn KJPP successfully');
} catch (Exception $e) {
$data['status'] = 'error';
$data['message'] ['message_error_try_catch'] = array('Proses Penawarn KJPP failed.');
}
}
else
{
$data['status'] = 'error';
$data['message']['active_date_range'] = array("Penawaran sudah di tutup");
}
} else {
$data['status'] = 'error';
@@ -250,15 +335,17 @@ class ProsesPenawaranController extends Controller
*/
public function updateAll(Request $request, $id): JsonResponse
{
// $id = penawaran.id
// init
$data = array();
$dataPermohonan = array();
$dataPenawaran = array();
$penawaran = PenawaranTender::find($id);
$checkActiveDateRange = checkActiveDateRangePenawaran($id);
// cek masa aktif penawaran
if($checkActiveDateRange)
$checkActiveDateRange = checkActiveDateRangePenawaran($id);
// cek status (penawaran.status = tender)
$penawaran = PenawaranTender::find($id);
if($checkActiveDateRange && ('tender'==$penawaran->status))
{
$checkKelengkapanDetailKJPP = checkKelengkapanDetailKJPP($id);
@@ -307,27 +394,41 @@ class ProsesPenawaranController extends Controller
public function updateKJPPStatus(Request $request, $id): JsonResponse
{
// $id => detail_penawaran.id
// init
$data = array();
$dataDetailPenawaran = array();
try {
$detailpenawaran = PenawaranDetailTender::findOrFail($id);
$data['id']=$id;
$detailpenawaran = PenawaranDetailTender::find($id);
// cek masa aktif penawaran
$checkActiveDateRange = checkActiveDateRangePenawaran($detailpenawaran->penawaran_id);
// cek status (penawaran.status = tender)
$penawaran = PenawaranTender::find($detailpenawaran->penawaran_id);
if($checkActiveDateRange && ('tender'==$penawaran->status))
{
try {
$dataDetailPenawaran = ['status' => '0',
'updated_by' => Auth::id(),
'updated_at' => now()
];
// $data['id']=$id;
$detailpenawaran->update($dataDetailPenawaran);
$dataDetailPenawaran = ['status' => '0',
'updated_by' => Auth::id(),
'updated_at' => now()
];
$data['status'] = 'success';
$data['message'] ['message_success'] = array('Sukses delete Penawaran KJPP '.$request->kjppName);
} catch (Exception $e) {
$detailpenawaran->update($dataDetailPenawaran);
$data['status'] = 'success';
$data['message'] ['message_success'] = array('Sukses delete Penawaran KJPP '.$request->kjppName);
} catch (Exception $e) {
$data['status'] = 'error';
$data['message'] ['message_error'] = array("Gagal delete Penawaran KJPP ".$request->kjppName);
}
}
else
{
$data['status'] = 'error';
$data['message'] ['message_error_try_catch'] = array("Gagal delete Penawaran KJPP ".$request->kjppName);
$data['message']['message_error'] = array("Penawaran sudah di tutup");
}
return response()->json($data);
@@ -336,6 +437,596 @@ class ProsesPenawaranController extends Controller
public function show($id)
{
$prosespenawaran = PenawaranTender::find($id);
return view('lpj::prosespenawaran.show', compact('id', 'prosespenawaran'));
$permohonan = "";
if($prosespenawaran){
$permohonan = Permohonan::where('nomor_registrasi',$prosespenawaran->nomor_registrasi)->first();
}
return view('lpj::prosespenawaran.show', compact('id', 'prosespenawaran','permohonan'));
}
public function updateDraft(Request $request, $id): JsonResponse
{
// $id = penawaran.id
// init
$data = array();
$dataPenawaranDetail = array();
$failed = 0;
// cek masa aktif penawaran
$checkActiveDateRange = checkActiveDateRangePenawaran($id);
// cek status (penawaran.status = tender)
$penawaran = PenawaranTender::find($id);
if($checkActiveDateRange && ('tender'==$penawaran->status))
{
DB::beginTransaction();
try
{
// update detail_penawaran
$detail_penawaran_ids = $request->input('prosespenawaran_penawarandetail_id', []);
$no_proposals = $request->input('prosespenawaran_no_proposal', []);
$tgl_proposals = $request->input('prosespenawaran_tgl_proposal', []);
$biaya_penawarans = $request->input('prosespenawaran_biayaPenawaran', []);
$dokumen_penawarans = $request->file('prosespenawaran_dokumenPersetujuan');
$tot_kjpp = sizeof($detail_penawaran_ids);
if($tot_kjpp>0)
{
// loop
for($i=0;$i<$tot_kjpp;$i++)
{
$detail_penawaran_id= $detail_penawaran_ids[$i];
$dataPenawaranDetail = [
'no_proposal' => $no_proposals[$i],
'tgl_proposal' => $tgl_proposals[$i],
'biaya_penawaran' => str_replace(".","",$biaya_penawarans[$i]), // 'biaya_penawaran' => str_replace(".","",$request->biaya_penawaran)
'updated_by' => Auth::id(),
'updated_at' => now(),
];
$penawarandetail = PenawaranDetailTender::find($detail_penawaran_id);
if ($dokumen_penawarans)
{
if (is_array($dokumen_penawarans) && array_key_exists($i, $dokumen_penawarans))
{
$file_tmp = $dokumen_penawarans[$i];
if($file_tmp->isValid())
{
$folderPath = 'uploads/penawaran/';
$myFile=$file_tmp->getClientOriginalName(); // nama file with extension
$file_name = pathinfo($myFile, PATHINFO_FILENAME); // nama file without extension
$extension = $file_tmp->getClientOriginalExtension();
// kjppID_penawaranID_namaFile_userID_time
$newFileName = $penawarandetail->kjpp_rekanan_id.'_'.$penawarandetail->penawaran_id.'_'.$file_name.'_'.Auth::user()->id."_".time() .'.'. $extension;
Storage::disk('public')->put($folderPath.'/'.$newFileName,file_get_contents($file_tmp));
$newFileNameWithPath = $folderPath . $newFileName;
$dataPenawaranDetail['attachment'] = $myFile;
$dataPenawaranDetail['dokumen_persetujuan'] = $newFileNameWithPath;
}
}
}
$checkStatus = $penawarandetail->update($dataPenawaranDetail);
if(!$checkStatus)
$failed++;
}
if($failed>0)
{
DB::rollBack();
$data['status'] = 'error';
$data['message'] ['message_error'] = array('Proses Draft Penawaran KJPP failed');
}
else
{
DB::commit();
$data['status'] = 'success';
$data['message'] ['message_success'] = array('Proses Draft Penawaran KJPP successfully');
}
}
else
{
$data['status'] = 'error';
$data['message'] ['message_error'] = array('Data inti tidak ada.');
}
}
catch (Exception $e)
{
// dd($e);
DB::rollBack();
$data['status'] = 'error';
$data['message'] ['message_error_try_catch'] = array('Proses Draft Penawaran KJPP failed.');
}
}
else
{
$data['status'] = 'error';
$data['message']['active_date_range'] = array("Penawaran sudah di tutup");
}
return response()->json($data);
}
public function store(Request $request): JsonResponse
{
// init
$data = array();
// $data['request']=$request->all();
$dataPenawaranDetail = array();
// cek masa aktif penawaran
$checkActiveDateRange = checkActiveDateRangePenawaran($request->penawaran_id);
// cek status (penawaran.status = tender)
$penawaran = PenawaranTender::find($request->penawaran_id);
if($checkActiveDateRange && ('tender'==$penawaran->status))
{
try
{
$dataPenawaranDetail = [
'penawaran_id' => $request->penawaran_id,
'kjpp_rekanan_id' => $request->kjpp_id,
'created_by' => Auth::id(),
'created_at' => Carbon::now()
];
PenawaranDetailTender::create($dataPenawaranDetail);
$data['status'] = 'success';
$data['message'] ['message_success'] = array('Proses Tambah KJPP successfully');
}
catch (Exception $e)
{
// dd($e);
$data['status'] = 'error';
$data['message'] ['message_error_try_catch'] = array('Proses Tambah KJPP failed.');
}
}
else
{
$data['status'] = 'error';
$data['message']['active_date_range'] = array("Penawaran sudah di tutup");
}
return response()->json($data);
}
public function editulang($id)
{
// id ==> penawaran.id
return view('lpj::prosespenawaran.editulang', compact('id'));
}
public function setDataUlang(Request $request): JsonResponse
{
$data = array();
$penawaran = array();
$penawrandetails = array();
if (request()->ajax()) {
$id = $request->id;
$penawaran = PenawaranTender::with('permohonan.debiture')->where('status','=','proposal-tender')->find($id);
if ($penawaran) {
$penawrandetails = PenawaranDetailTender::where('penawaran_id','=',$id)
->leftJoin('kjpp', 'kjpp.id', '=', 'detail_penawaran.kjpp_rekanan_id')
->select('detail_penawaran.*', 'kjpp.code AS kjpp_code', 'kjpp.name AS kjpp_name')
->where('detail_penawaran.status','=',1)
->get();
$i=0;
foreach($penawrandetails as $obj)
{
if($obj->dokumen_persetujuan && Storage::disk('public')->exists($obj->dokumen_persetujuan))
{
$penawrandetails_path = Storage::url($obj->dokumen_persetujuan);
$penawrandetails[$i]['dokumen_persetujuan']=$penawrandetails_path;
}
$i++;
}
$penawaranString = "";
if($penawaran->status)
{
$penawaranString = convertSlug($penawaran->status);
$penawaran->status = $penawaranString;
}
$kjpps = KJPP::whereNotIn('id', function($query) use ($id) {
$query->select('kjpp_rekanan_id')
->from('detail_penawaran')
->where('penawaran_id', '=', $id)
->where('status','=',1); // status=1 (masih aktif)
})
->select('id', 'name', 'code') // Pilih beberapa kolom sekaligus
->get();
$data['kjpps'] = $kjpps;
$data['penawaran'] = $penawaran;
$data['penawrandetails'] = $penawrandetails;
$data['status'] = 'success';
$data['message']['message_success'] = array("data successfully found");
} else {
$data['status'] = 'error';
$data['penawaran'] = null;
$data['penawrandetails'] = null;
$data['message']['message_data'] = array("data not found");
}
} else {
$data['status'] = 'error';
$data['message']['message_ajax'] = array("no ajax request");
}
return response()->json($data);
}
public function updateKJPPStatusUlang(Request $request, $id): JsonResponse
{
// message menggunakan SweetAlert2
// init
$data = array();
$dataDetailPenawaran = array();
// cek masa aktif penawaran
$detailpenawaran = PenawaranDetailTender::find($id);
$checkActiveDateRange = checkActiveDateRangePenawaran($detailpenawaran->penawaran_id);
// cek masa aktif penawaran
// cek apakah blm di approve (penawaran.status = proposal-tender)
$penawaran = PenawaranTender::find($detailpenawaran->penawaran_id);
// cek apakah blm di approve (penawaran.status = proposal-tender)
if($checkActiveDateRange && ('proposal-tender'==$penawaran->status))
{
try {
$data['id']=$id;
$dataDetailPenawaran = ['status' => '0',
'updated_by' => Auth::id(),
'updated_at' => now()
];
$detailpenawaran->update($dataDetailPenawaran);
$data['status'] = 'success';
$data['message'] ['message_success'] = array('Sukses delete Penawaran KJPP '.$request->kjppName);
} catch (Exception $e) {
$data['status'] = 'error';
$data['message'] ['message_error_try_catch'] = array("Gagal delete Penawaran KJPP ".$request->kjppName);
// $data['message']['message_error'] = array("Gagal delete Penawaran KJPP ".$request->kjppName);
}
}
else
{
$data['status'] = 'error';
$data['message']['active_date_range'] = array("Penawaran sudah di tutup");
// $data['message']['message_error'] = array("Penawaran sudah di tutup");
}
return response()->json($data);
}
public function updateulang(Request $request, $id): JsonResponse
{
// id ==> detail_penawaran.id
// init
$data = array();
$dataDetailPenawaranLog = array();
$dataDetailPenawaran = array();
$pleaseCommit= true;
if (request()->ajax()) {
$validator = ProsesPenawaranController::rulesEditUlangnya($request, $id);
if ($validator['fails']) {
$data['message'] = $validator['errors'];
$data['status'] = 'error';
}
else
{
// cek masa aktif penawaran
$detailpenawaran = PenawaranDetailTender::find($id);
$checkActiveDateRange = checkActiveDateRangePenawaran($detailpenawaran->penawaran_id);
// cek masa aktif penawaran
// cek apakah blm di approve (penawaran.status = proposal-tender)
$penawaran = PenawaranTender::find($detailpenawaran->penawaran_id);
// cek apakah blm di approve (penawaran.status = proposal-tender)
if($checkActiveDateRange && ('proposal-tender'==$penawaran->status))
{
DB::beginTransaction();
try {
$dataDetailPenawaranLog = [
'detail_penawaran_id' =>$detailpenawaran->id,
'kjpp_rekanan_id' =>$detailpenawaran->kjpp_rekanan_id,
'penawaran_id' =>$detailpenawaran->penawaran_id,
'biaya_penawaran' =>$detailpenawaran->biaya_penawaran,
'no_proposal' =>$detailpenawaran->no_proposal,
'tgl_proposal' =>$detailpenawaran->tgl_proposal,
'attachment' =>$detailpenawaran->attachment,
'dokumen_persetujuan' =>$detailpenawaran->dokumen_persetujuan,
'status' =>$detailpenawaran->status,
'authorized_status' =>$detailpenawaran->authorized_status,
'authorized_at' =>$detailpenawaran->authorized_at,
'authorized_at' =>$detailpenawaran->authorized_at,
'created_at' =>$detailpenawaran->created_at,
'updated_at' =>$detailpenawaran->updated_at,
'deleted_at' =>$detailpenawaran->deleted_at,
'created_by' =>$detailpenawaran->created_by,
'updated_by' =>$detailpenawaran->updated_by,
'deleted_by' =>$detailpenawaran->deleted_by
];
PenawaranDetailTenderLog::create($dataDetailPenawaranLog);
$biaya_penawaran="";
if($request->biaya_penawaran)
$biaya_penawaran= str_replace(".","",$request->biaya_penawaran);
$dataDetailPenawaran = ['updated_by' => Auth::id(),
'updated_at' => now(),
'no_proposal' => $request->no_proposal,
'tgl_proposal' => $request->tgl_proposal,
'biaya_penawaran' => $biaya_penawaran
];
if ($request->hasFile('dokumen_persetujuan'))
{
$file_tmp = $request->file('dokumen_persetujuan');
$folderPath = 'uploads/penawaran/';
if ($file_tmp->isValid())
{
$myFile=$file_tmp->getClientOriginalName(); // nama file with extension
$file_name = pathinfo($myFile, PATHINFO_FILENAME); // nama file without extension
$extension = $file_tmp->getClientOriginalExtension();
// kjppID_penawaranID_namaFile_userID_time
$newFileName = $request->kjpp_rekanan_id.'_'.$id.'_'.$file_name.'_'.Auth::user()->id."_".time() .'.'. $extension;
Storage::disk('public')->put($folderPath.'/'.$newFileName,file_get_contents($file_tmp));
$newFileNameWithPath = $folderPath . $newFileName;
$dataDetailPenawaran['attachment'] = $myFile;
$dataDetailPenawaran['dokumen_persetujuan'] = $newFileNameWithPath;
}
else
{
$pleaseCommit=false;
$data['status'] = 'error';
$data['message']['check_file_jenis'] = array("Silahkan upload file pdf");
}
}
else
{
$data['status'] = 'error';
$data['message']['check_file'] = array("Silahkan upload file");
}
$detailpenawaran->update($dataDetailPenawaran);
if($pleaseCommit)
{
DB::commit();
$data['id'] = $id;
$data['detailpenawaran'] = $detailpenawaran;
$data['status'] = 'success';
$data['message']['message_success'] = array('Proses Penawarn KJPP Ulang successfully');
}
else
{
DB::rollBack();
$data['status'] = 'error';
$data['message']['message_error'] = array("Proses Penawarn KJPP Ulang failed..");
}
} catch (Exception $e) {
DB::rollBack();
$data['status'] = 'error';
$data['message']['message_error_try_catch'] = array('Proses Penawarn KJPP Ulang failed.');
}
}
else
{
$data['status'] = 'error';
$data['message']['active_date_range'] = array("Penawaran sudah di tutup");
}
}
} else {
$data['status'] = 'error';
$data['message']['message_ajax'] = array("no ajax request");
}
return response()->json($data);
}
public function rulesEditUlangnya($request, $id)
{
$validateIt = [
// 'name' diambil dari definisi parameter yang di kirim pada POST Data
'no_proposal' => 'required',
'tgl_proposal' => 'required',
'biaya_penawaran' => 'required',
'dokumen_persetujuan' => 'required|file|mimes:pdf'
];
$messageIt = [
'no_proposal.required' => 'Silahkan isi No Proposal',
'tgl_proposal.required' => 'Silahkan isi Tanggal Penawaran',
'biaya_penawaran.required' => 'Silahkan isi Biaya Penawaran',
'dokumen_persetujuan.required' => 'Silahkan isi dokumen',
'dokumen_persetujuan.file' => 'Silahkan isi file',
'dokumen_persetujuan.mimes' => 'Silahkan upload pdf'
];
$validator = Validator::make($request->all(), $validateIt, $messageIt);
$data['fails'] = $validator->fails();
$data['errors'] = $validator->errors();
return $data;
}
public function storeUlang(Request $request): JsonResponse
{
// init
$data = array();
// $data['request']=$request->all();
$dataDetailPenawaran = array();
// cek masa aktif penawaran
$checkActiveDateRange = checkActiveDateRangePenawaran($request->penawaran_id);
// cek masa aktif penawaran
// cek apakah blm di approve (penawaran.status = proposal-tender)
$penawaran = PenawaranTender::find($request->penawaran_id);
// cek apakah blm di approve (penawaran.status = proposal-tender)
if($checkActiveDateRange && ('proposal-tender'==$penawaran->status))
{
try
{
$biaya_penawaran="";
if($request->biaya_penawaran)
$biaya_penawaran= str_replace(".","",$request->biaya_penawaran);
$dataDetailPenawaran = [
'kjpp_rekanan_id' => $request->kjpp_rekanan_id,
'no_proposal' => $request->no_proposal,
'tgl_proposal' => $request->tgl_proposal,
'biaya_penawaran' => $biaya_penawaran,
'penawaran_id' => $request->penawaran_id,
'created_by' => Auth::id(),
'created_at' => Carbon::now()
];
if ($request->hasFile('dokumen_persetujuan'))
{
$file_tmp = $request->file('dokumen_persetujuan');
$folderPath = 'uploads/penawaran/';
if ($file_tmp->isValid())
{
$myFile=$file_tmp->getClientOriginalName(); // nama file with extension
$file_name = pathinfo($myFile, PATHINFO_FILENAME); // nama file without extension
$extension = $file_tmp->getClientOriginalExtension();
// kjppID_penawaranID_namaFile_userID_time
$newFileName = $request->kjpp_rekanan_id.'_'.$request->penawaran_id.'_'.$file_name.'_'.Auth::user()->id."_".time() .'.'. $extension;
Storage::disk('public')->put($folderPath.'/'.$newFileName,file_get_contents($file_tmp));
$newFileNameWithPath = $folderPath . $newFileName;
$dataDetailPenawaran['attachment'] = $myFile;
$dataDetailPenawaran['dokumen_persetujuan'] = $newFileNameWithPath;
}
else
{
$pleaseCommit=false;
$data['status'] = 'error';
$data['message']['check_file_jenis'] = array("Silahkan upload file pdf");
}
}
else
{
$data['status'] = 'error';
$data['message']['check_file'] = array("Silahkan upload file");
}
PenawaranDetailTender::create($dataDetailPenawaran);
$data['status'] = 'success';
$data['message'] ['message_success'] = array('Proses Tambah KJPP Ulang successfully');
}
catch (Exception $e)
{
dd($e);
$data['status'] = 'error';
$data['message'] ['message_error_try_catch'] = array('Proses Tambah KJPP Ulang failed.');
}
}
else
{
$data['status'] = 'error';
$data['message']['active_date_range'] = array("Penawaran sudah di tutup");
}
return response()->json($data);
}
// merger permohonan
/**
* Show the form for creating a new resource.
*/
public function createPenawaran($id)
{
// id ==> permohonan.id
$permohonan = Permohonan::find($id);
// dd($permohonan);
$status = StatusPermohonan::all();
$tujuan_penilaian_kjpp = TujuanPenilaianKJPP::all();
$jenis_laporan = JenisLaporan::all();
$kjpp = KJPP::all();
return view('lpj::prosespenawaran.createPenawaran', compact('id', 'status', 'tujuan_penilaian_kjpp', 'jenis_laporan', 'kjpp', 'permohonan'));
}
public function storePenawaran(ProsesPenawaranRequest $request, $id)
{
$validated = $request->validated();
DB::beginTransaction();
try {
$permohonan = Permohonan::find($id);
$userId = Auth::user()->id;
$validated['nomor_registrasi'] = $permohonan->nomor_registrasi;
$validated['status'] = 'tender';
$validated['updated_by'] = $userId; // Updating the record
$validated['end_date'] = $request->input('end_date') . ' 23:59:59';
$permohonan->update($validated);
// Adding created_by for the new penawaran record
$validated['created_by'] = $userId;
$validated['code'] = onLastnumberCodePenawaran();
$penawaran = PenawaranTender::create($validated);
$kjpps = $request->input('kjpp', []);
foreach ($kjpps as $kjpp) {
PenawaranDetailTender::create([
'penawaran_id' => $penawaran->id,
'kjpp_rekanan_id' => $kjpp,
'created_by' => $userId, // Set created_by for details
'updated_by' => $userId
]);
}
// Commit the transaction
DB::commit();
return redirect()
->route('tender.prosespenawaran.index')
->with('success', 'Data Penawaran created successfully');
} catch (Exception $e) {
DB::rollBack();
return redirect()
->route('tender.prosespenawaran.createPenawaran', $id)
->with('error', 'Validation failed: ' . $e);
}
}
public function showPermohonan($id)
{
// $id => permohonan.id
$permohonan = Permohonan::find($id);
return view('lpj::prosespenawaran.showPermohonan', compact('id', 'permohonan'));
}
// merger permohonan
}

View File

@@ -117,8 +117,8 @@ class ProsesPenawaranUlangController extends Controller
$penawrandetails = array();
if (request()->ajax()) {
$id = $request->id;
$penawaran = PenawaranTender::where('status','=','proposal-tender')->find($id);
$id = $request->id;
$penawaran = PenawaranTender::with('permohonan.debiture')->where('status','=','proposal-tender')->find($id);
if ($penawaran) {
$penawrandetails = PenawaranDetailTender::where('penawaran_id','=',$id)

View File

@@ -4,28 +4,17 @@
use App\Http\Controllers\Controller;
use Exception;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;
// use Modules\Location\Models\City;
// use Modules\Location\Models\District;
// use Modules\Location\Models\Province;
// use Modules\Location\Models\Village;
// use Modules\Lpj\Exports\DebitureExport;
// use Modules\Lpj\Http\Requests\DebitureRequest;
// use Modules\Lpj\Http\Requests\DokumenJaminanRequest;
// use Modules\Lpj\Models\Branch;
// use Modules\Lpj\Models\Debiture;
// use Modules\Lpj\Models\DokumenJaminan;
// use Modules\Lpj\Models\JenisJaminan;
// use Modules\Lpj\Models\JenisLegalitasJaminan;
// use Modules\Lpj\Models\PemilikJaminan;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\JenisPenilaian;
use Modules\Lpj\Models\Regions;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Validator;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Lpj\Models\Debiture;
use Modules\Lpj\Models\DokumenJaminan;
use Modules\Lpj\Models\JenisPenilaian;
use Modules\Lpj\Models\Penilai;
use Modules\Lpj\Models\Permohonan;
use Modules\Lpj\Models\Regions;
class RegistrasiController extends Controller
{
@@ -43,7 +32,9 @@
}
// Retrieve data from the database
$query = Permohonan::query()->where('status','=','preregister');
$query = Permohonan::query()
->whereIn('status', ['preregister', 'revisi']);
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
@@ -101,152 +92,174 @@
'data' => $data,
]);
}
public function edit($id)
{
return view('lpj::registrasi.edit', compact('id'));
}
public function setData(Request $request): JsonResponse
public function setData(Request $request)
: JsonResponse
{
$data = array();
$datas = array();
$data = [];
$datas = [];
if (request()->ajax()) {
$id = $request->id;
$id = $request->id;
$datas = Permohonan::find($id);
if ($datas) {
$jenisPenilaians=null;
$regions=null;
$regions=Regions::pluck('name', 'id');
$jenisPenilaians=JenisPenilaian::pluck('name', 'id');
$data['status'] = 'success';
$data['regions'] = $regions;
$data['jenisPenilaians'] = $jenisPenilaians;
$data['datas'] = $datas;
$data['message'] ['message_success'] = array("data successfully found");
$jenisPenilaians = null;
$regions = null;
$regions = Regions::pluck('name', 'id');
$jenisPenilaians = JenisPenilaian::pluck('name', 'id');
$data['status'] = 'success';
$data['regions'] = $regions;
$data['jenisPenilaians'] = $jenisPenilaians;
$data['datas'] = $datas;
$data['message'] ['message_success'] = ["data successfully found"];
} else {
$data['status'] = 'error';
$data['datas'] = null;
$data['message'] ['message_data'] = array("data not found");
$data['status'] = 'error';
$data['datas'] = null;
$data['message'] ['message_data'] = ["data not found"];
}
} else {
$data['status'] = 'error';
$data['message'] ['message_ajax'] = array("no ajax request");
$data['status'] = 'error';
$data['message']['message_ajax'] = ["no ajax request"];
}
return response()->json($data);
}
public function update(Request $request, $id): JsonResponse
public function show($id)
{
$permohonan = Permohonan::find($id);
$debitur = Debiture::find($permohonan->debiture_id);
$documents = DokumenJaminan::with('pemilik', 'detail')->where('permohonan_id', $id)->get();
return view('lpj::registrasi.show', compact('id', 'permohonan', 'documents', 'debitur'));
}
public function storeRevisi(Request $request, $id)
{
try {
$permohonan = Permohonan::find($id);
$permohonan->update([
'status' => 'registered'
]);
return redirect()->route('registrasi.index')->with('success', 'Submit Revision successfully');
} catch (Exception $e) {
return redirect()
->route('registrasi.index')
->with('error', 'Failed to create permohonan' . $e->getMessage());
}
}
public function update(Request $request, $id)
: JsonResponse
{
// init
$data = array();
$dataku = array();
$data = [];
$dataku = [];
$tindakan = null;
if (request()->ajax()) {
$validator = RegistrasiController::rulesEditnya($request, $id);
if ($validator['fails']) {
$data['message'] = $validator['errors'];
$data['status'] = 'error';
}
else
{
$data['status'] = 'error';
} else {
try {
$tindakan = $request->tindakan;
$dataku = [
'registrasi_by' => Auth::id(),
'registrasi_at' => now(),
];
$tindakan=$request->tindakan;
$dataku = ['registrasi_by' => Auth::id(),
'registrasi_at' => now()
];
if($tindakan==0)
{
$dataku['jenis_penilaian_id'] =$request->jenis_penilaian;
$dataku['region_id'] =$request->region;
$dataku['status'] = 'registered';
if($request->catatan2)
$dataku['registrasi_catatan'] =$request->catatan2;
}
else
{
$dataku['registrasi_catatan'] =$request->catatan;
$dataku['status'] = 'revisi';
if ($tindakan == 0) {
$dataku['jenis_penilaian_id'] = $request->jenis_penilaian;
$dataku['region_id'] = $request->region;
$dataku['status'] = 'registered';
if ($request->catatan2) {
$dataku['registrasi_catatan'] = $request->catatan2;
}
} else {
$dataku['registrasi_catatan'] = $request->catatan;
$dataku['status'] = 'revisi';
}
$data['dataku'] =$dataku;
$data['dataku'] = $dataku;
$modal = Permohonan::find($id);
$modal->update($dataku);
//
$data['status'] = 'success';
$data['message'] ['message_success'] = array('Regitrasi '.$modal->nomor_registrasi.' successfully');
if ($modal && $request->jenis_laporan) {
foreach ($modal->documents as $document) {
Penilai::updateOrCreate(
[
'permohonan_id' => $id,
'dokument_id' => $document->id
],
['type' => $request->jenis_laporan]
);
}
}
//
$data['status'] = 'success';
$data['message'] ['message_success'] = ['Regitrasi ' . $modal->nomor_registrasi . ' successfully'];
} catch (Exception $e) {
$data['status'] = 'error';
$data['message'] ['message_try_catch'] = array('Regitrasi updated failed.');
$data['status'] = 'error';
$data['message'] ['message_try_catch'] = ['Regitrasi updated failed.'];
}
}
} else {
$data['status'] = 'error';
$data['message'] ['message_ajax'] = array("no ajax request");
$data['status'] = 'error';
$data['message'] ['message_ajax'] = ["no ajax request"];
}
return response()->json($data);
}
public function rulesEditnya($request, $id)
{
$tindakan=null;
$jenis_penilaian=null;
$validate_catatan='';
$tindakan=$request->tindakan;
$jenis_penilaian=$request->jenis_penilaian;
$tindakan = null;
$jenis_penilaian = null;
$validate_catatan = '';
$tindakan = $request->tindakan;
$jenis_penilaian = $request->jenis_penilaian;
$validateIt = [
// 'name' diambil dari definisi parameter yang di kirim pada POST Data
'tindakan' => 'required',
];
$messageIt = [
'tindakan.required' => 'Silahkan pilih Tindakan'
'tindakan.required' => 'Silahkan pilih Tindakan',
];
if($tindakan==0)
{
$validateIt['jenis_penilaian'] = ['required'];
$messageIt ['jenis_penilaian.required']= 'Silahkan pilih Jenis Penilaian';
if ($tindakan == 0) {
$validateIt['jenis_penilaian'] = ['required'];
$messageIt ['jenis_penilaian.required'] = 'Silahkan pilih Jenis Penilaian';
// INTERNAL
if(1==$jenis_penilaian)
{
$validateIt['region'] = ['required'];
$messageIt ['region.required']= 'Silahkan pilih Region';
// INTERNAL
if (1 == $jenis_penilaian) {
$validateIt['region'] = ['required'];
$messageIt ['region.required'] = 'Silahkan pilih Region';
}
}
elseif($tindakan==1)
{
$validateIt['catatan'] = ['required'];
$messageIt ['catatan.required']= 'Silahkan isi Catatan';
} else if ($tindakan == 1) {
$validateIt['catatan'] = ['required'];
$messageIt ['catatan.required'] = 'Silahkan isi Catatan';
}
$validator = Validator::make($request->all(), $validateIt, $messageIt);
$data['fails'] = $validator->fails();
$data['fails'] = $validator->fails();
$data['errors'] = $validator->errors();
return $data;
}
public function show($id)
{
$permohonan = Permohonan::find($id);
return view('lpj::registrasi.show', compact('id','permohonan'));
}
}

View File

@@ -46,21 +46,19 @@
}
// Retrieve data from the database
$query = PenawaranTender::with(['permohonan', 'tujuanPenilaianKjpp'])->whereHas(
'permohonan',
function ($q) {
$q->where('status', '=', 'spk');
},
)->withCount('penawarandetails');
$query =PenawaranTender::query()
->select('penawaran.*', 'tujuan_penilaian_kjpp.name as tujuan_penilaian_kjpp_name')
->leftJoin('tujuan_penilaian_kjpp', 'tujuan_penilaian_kjpp.id','=','penawaran.tujuan_penilaian_kjpp_id')
->where('penawaran.status','=','registrasi-final')
->withCount('penawarandetails');
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
$q->orWhere('status', 'LIKE', '%' . $search . '%');
//$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
//$q->orWhere('status', 'LIKE', '%' . $search . '%');
});
}
@@ -88,7 +86,7 @@
// Get the data for the current page
//$data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian'])->get();
$data = $query->with(['permohonan'])->get();
$data = $query->with(['permohonan.debiture'])->get();
// dd($data);
$i = 0;
foreach ($data as $obj) {
@@ -134,10 +132,10 @@
public function show($id)
{
$permohonan = Permohonan::find($id);
if ($permohonan->dokumen) {
$pdfSPK_path = Storage::url($permohonan->dokumen);
$permohonan->dokumen = $pdfSPK_path;
$permohonan->dokumen = '| <a download href="' . $pdfSPK_path . '" class="badge badge-sm badge-outline" target="_blank">Dokumen SPK.pdf &nbsp;&nbsp;<i class="ki-filled ki-cloud-download"></i></a>';
$document = PenawaranTender::where('nomor_registrasi','=',$permohonan->nomor_registrasi)->first();
if ($document) {
$pdfSPK_path = Storage::url($document->spk_dokumen_path);
$permohonan->pdfSPK_path = '| <a download href="' . $pdfSPK_path . '" class="badge badge-sm badge-outline" target="_blank">Dokumen SPK.pdf &nbsp;&nbsp;<i class="ki-filled ki-cloud-download"></i></a>';
}
return view('lpj::registrasifinal.show', compact('id', 'permohonan'));
@@ -145,7 +143,15 @@
public function edit($id)
{
return view('lpj::registrasifinal.edit', compact('id'));
$doc_pdf='';
$permohonan = Permohonan::find($id);
$document = PenawaranTender::where('nomor_registrasi','=',$permohonan->nomor_registrasi)->first();
if ($document) {
$pdfSPK_path = Storage::url($document->spk_dokumen_path);
$doc_pdf = '<a download href="' . $pdfSPK_path . '" class="badge badge-sm badge-outline" target="_blank">Dokumen SPK.pdf &nbsp;&nbsp;<i class="ki-filled ki-cloud-download"></i></a>';
}
return view('lpj::registrasifinal.edit', compact('id','doc_pdf'));
}
public function setData(Request $request)

View File

@@ -0,0 +1,22 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Modules\Lpj\Models\TujuanPenilaian;
class RekapHarianSoController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
$total_laporan_debitur = 0;
$tujuan_penilaian = TujuanPenilaian::all();
return view('lpj::rekap-harian-so.index', compact('tujuan_penilaian', 'total_laporan_debitur'));
}
}

View File

@@ -4,9 +4,11 @@ namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Modules\Lpj\Models\Authorization;
class SLAController extends Controller
{
public $user;
/**
* Display a listing of the resource.
*/
@@ -62,4 +64,72 @@ class SLAController extends Controller
{
//
}
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('debitur.view')) {
// abort(403, 'Sorry! You are not allowed to view users.');
}
$query = Authorization::query()->with('permohonan.debiture', 'user', 'approveSo', 'approveEo', 'approveDd')->where('jenis', 'sla')->where('request', 'freeze');
// Pencarian berdasarkan parameter search
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->orWhereRelation('permohonan', 'nomor_registrasi', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('permohonan', 'tanggal_permohonan', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('user', 'name', 'LIKE', '%' . $search . '%');
$q->orWhereRelation('permohonan.debiture', 'name', 'LIKE', '%' . $search . '%');
$q->orWhere('status', 'LIKE', '%' . $search . '%');
});
}
// Sorting berdasarkan sortField dan sortOrder
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
$query->orderBy($column, $order);
}
// Hitung total records
$totalRecords = $query->count();
// Pagination (default page size 10)
$size = $request->get('size', 10);
if ($size == 0) {
$size = 10;
}
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page', 1);
$offset = ($page - 1) * $size;
$query->skip($offset)->take($size);
}
// Filtered records
$filteredRecords = $query->count();
// Ambil data dengan relasi
$data = $query->get();
// Hitung jumlah halaman
$pageCount = ceil($totalRecords / $size);
// Ambil current page
$currentPage = max(1, $request->get('page', 1));
// Return JSON response
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $data,
]);
}
}

View File

@@ -0,0 +1,548 @@
<?php
namespace Modules\Lpj\Http\Controllers;
use App\Http\Controllers\Controller;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Lpj\Exports\SlikExport;
use Modules\Lpj\Imports\SlikImport;
use Modules\Lpj\Models\Slik;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
/**
* Controller untuk mengelola data Slik
*
* Menangani operasi CRUD dan import data Slik dari file Excel
* dengan fitur server-side processing untuk datatables
*
* @package Modules\Lpj\Http\Controllers
*/
class SlikController extends Controller
{
public $user;
/**
* Constructor
*/
public function __construct()
{
$this->user = Auth::user();
}
/**
* Menampilkan halaman index slik
*
* @return \Illuminate\View\View
*/
public function index()
{
return view('lpj::slik.index');
}
/**
* Menampilkan detail slik
*
* @param int $id
* @return \Illuminate\View\View
*/
public function show($id)
{
$slik = Slik::findOrFail($id);
return view('lpj::slik.show', compact('slik'));
}
/**
* Data untuk datatables dengan server-side processing
*
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function dataForDatatables(Request $request)
{
// Authorization check dapat ditambahkan sesuai kebutuhan
// if (is_null($this->user)) {
// abort(403, 'Unauthorized access.');
// }
// Retrieve data from the database
$query = Slik::query();
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('sandi_bank', 'LIKE', "%$search%")
->orWhere('no_rekening', 'LIKE', "%$search%")
->orWhere('cif', 'LIKE', "%$search%")
->orWhere('nama_debitur', 'LIKE', "%$search%")
->orWhere('nama_cabang', 'LIKE', "%$search%")
->orWhere('jenis_agunan', 'LIKE', "%$search%")
->orWhere('nama_pemilik_agunan', 'LIKE', "%$search%")
->orWhere('alamat_agunan', 'LIKE', "%$search%")
->orWhere('lokasi_agunan', 'LIKE', "%$search%");
});
}
// Apply year filter
if ($request->has('year') && !empty($request->get('year'))) {
$query->byYear($request->get('year'));
}
// Apply month filter
if ($request->has('month') && !empty($request->get('month'))) {
$query->byMonth($request->get('month'));
}
// Apply sandi bank filter
if ($request->has('sandi_bank') && !empty($request->get('sandi_bank'))) {
$query->where('sandi_bank', $request->get('sandi_bank'));
}
// Apply kolektibilitas filter
if ($request->has('kolektibilitas') && !empty($request->get('kolektibilitas'))) {
$query->where('kolektibilitas', $request->get('kolektibilitas'));
}
// Apply jenis agunan filter
if ($request->has('jenis_agunan') && !empty($request->get('jenis_agunan'))) {
$query->where('jenis_agunan', $request->get('jenis_agunan'));
}
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField', 'created_at');
$query->orderBy($column, $order);
} else {
$query->orderBy('created_at', 'desc');
}
// Get the total count of records
$totalRecords = $query->count();
// Apply pagination if provided
if ($request->has('page') && $request->has('size')) {
$page = $request->get('page');
$size = $request->get('size');
$offset = ($page - 1) * $size; // Calculate the offset
$query->skip($offset)->take($size);
}
// Get the filtered count of records
$filteredRecords = $query->count();
// Get the data for the current page with relationships
$data = $query->get();
// Transform data untuk datatables
$transformedData = $data->map(function ($item) {
return [
'id' => $item->id,
'sandi_bank' => $item->sandi_bank,
'tahun' => $item->tahun,
'bulan' => $item->bulan,
'no_rekening' => $item->no_rekening,
'cif' => $item->cif,
'nama_debitur' => $item->nama_debitur,
'kolektibilitas' => $item->kolektibilitas,
'kolektibilitas_badge' => $item->kolektibilitas_badge,
'fasilitas' => $item->fasilitas,
'jenis_agunan' => $item->jenis_agunan,
'nama_pemilik_agunan' => $item->nama_pemilik_agunan,
'nilai_agunan' => $item->nilai_agunan_formatted,
'nilai_agunan_ljk' => $item->nilai_agunan_ljk_formatted,
'alamat_agunan' => $item->alamat_agunan,
'lokasi_agunan' => $item->lokasi_agunan,
'nama_cabang' => $item->nama_cabang,
'kode_cabang' => $item->kode_cabang,
'created_by' => $item->creator?->name ?? '-',
'created_at' => dateFormat($item->created_at, true)
];
});
// Calculate the page count
$pageCount = ceil($totalRecords / ($request->get('size', 10)));
// Calculate the current page number
$currentPage = $request->get('page', 1);
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'recordsTotal' => $totalRecords,
'recordsFiltered' => $filteredRecords,
'pageCount' => $pageCount,
'page' => $currentPage,
'totalCount' => $totalRecords,
'data' => $transformedData,
]);
}
/**
* Import data slik dari Excel dengan optimasi memory dan progress tracking
*
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function import(Request $request)
{
Log::info('SlikController: Starting import process with optimizations', [
'user_id' => Auth::id(),
'request_size' => $request->header('Content-Length'),
'has_file' => $request->hasFile('file'),
'memory_limit' => ini_get('memory_limit'),
'max_execution_time' => ini_get('max_execution_time')
]);
// Validasi file upload dengan logging detail dan error handling komprehensif
try {
// Cek apakah ada file yang diupload
if (!$request->hasFile('file')) {
Log::error('SlikController: Tidak ada file yang diupload', [
'user_id' => Auth::id(),
'files_count' => count($request->allFiles()),
'request_data' => $request->all()
]);
throw ValidationException::withMessages(['file' => 'Tidak ada file yang diupload.']);
}
$file = $request->file('file');
// Cek apakah file valid
if (!$file->isValid()) {
$error = $file->getError();
$errorMessage = match($error) {
UPLOAD_ERR_INI_SIZE => 'File terlalu besar (melebihi upload_max_filesize).',
UPLOAD_ERR_FORM_SIZE => 'File terlalu besar (melebihi MAX_FILE_SIZE).',
UPLOAD_ERR_PARTIAL => 'File hanya terupload sebagian.',
UPLOAD_ERR_NO_FILE => 'Tidak ada file yang diupload.',
UPLOAD_ERR_NO_TMP_DIR => 'Direktori temp tidak tersedia.',
UPLOAD_ERR_CANT_WRITE => 'Gagal menulis file ke disk.',
UPLOAD_ERR_EXTENSION => 'Upload dibatalkan oleh ekstensi PHP.',
default => 'Error upload tidak diketahui: ' . $error
};
Log::error('SlikController: File upload tidak valid', [
'error' => $error,
'error_message' => $errorMessage,
'user_id' => Auth::id(),
'file_info' => [
'name' => $file->getClientOriginalName(),
'size' => $file->getSize(),
'mime' => $file->getMimeType()
]
]);
throw ValidationException::withMessages(['file' => $errorMessage]);
}
$maxFileSize = config('import.slik.max_file_size', 50) * 1024; // dalam KB
$request->validate([
'file' => 'required|file|mimes:xlsx,xls|max:' . $maxFileSize
]);
Log::info('SlikController: Validasi file berhasil');
} catch (\Illuminate\Validation\ValidationException $e) {
Log::error('SlikController: Validasi file gagal', [
'errors' => $e->errors(),
'user_id' => Auth::id(),
'request_size' => $request->header('Content-Length')
]);
throw $e;
}
try {
$uploadedFile = $request->file('file');
$originalName = $uploadedFile->getClientOriginalName();
$fileSize = $uploadedFile->getSize();
Log::info('SlikController: Memulai import data Slik', [
'user_id' => Auth::id(),
'filename' => $originalName,
'filesize' => $fileSize,
'filesize_mb' => round($fileSize / 1024 / 1024, 2),
'mime_type' => $uploadedFile->getMimeType(),
'extension' => $uploadedFile->getClientOriginalExtension()
]);
// Generate unique import ID
$importId = uniqid('slik_import_');
$userId = Auth::id() ?? 1;
// Cek apakah menggunakan queue processing untuk file besar
$useQueue = config('import.slik.queue.enabled', false) && $fileSize > (5 * 1024 * 1024); // > 5MB
// Pastikan direktori temp ada
$tempDir = storage_path('app/temp');
if (!file_exists($tempDir)) {
mkdir($tempDir, 0755, true);
Log::info('SlikController: Direktori temp dibuat', ['path' => $tempDir]);
}
// Simpan file sementara dengan nama unik
$tempFileName = 'slik_import_' . time() . '_' . uniqid() . '.' . $uploadedFile->getClientOriginalExtension();
$tempFilePath = $tempDir . '/' . $tempFileName;
Log::info('SlikController: Memindahkan file ke temp', [
'temp_path' => $tempFilePath,
'use_queue' => $useQueue
]);
// Pindahkan file ke direktori temp
$uploadedFile->move($tempDir, $tempFilePath);
// Verifikasi file berhasil dipindahkan
if (!file_exists($tempFilePath)) {
throw new Exception('File gagal dipindahkan ke direktori temp');
}
Log::info('SlikController: File berhasil dipindahkan', [
'file_size' => filesize($tempFilePath)
]);
if ($useQueue) {
Log::info('SlikController: Menggunakan queue processing untuk file besar', [
'import_id' => $importId,
'file_size_mb' => round($fileSize / 1024 / 1024, 2)
]);
// Dispatch job ke queue
\Modules\Lpj\Jobs\ProcessSlikImport::dispatch($tempFilePath, $userId, $importId);
return redirect()->back()->with('success', 'Import sedang diproses di background. ID: ' . $importId);
}
// Import langsung untuk file kecil
Log::info('SlikController: Processing file directly', [
'import_id' => $importId,
'file_size_mb' => round($fileSize / 1024 / 1024, 2)
]);
// Set optimasi memory untuk import langsung
$memoryLimit = config('import.slik.memory_limit', 256);
ini_set('memory_limit', $memoryLimit . 'M');
ini_set('max_execution_time', config('import.slik.timeout', 30000));
// Enable garbage collection jika diizinkan
if (config('import.slik.enable_gc', true)) {
gc_enable();
}
// Proses import menggunakan SlikImport class
Log::info('SlikController: Memulai proses Excel import');
$import = new SlikImport();
Excel::import($import, $tempFilePath);
Log::info('SlikController: Excel import selesai');
// Force garbage collection setelah selesai
if (config('import.slik.enable_gc', true)) {
gc_collect_cycles();
}
// Hapus file temporary setelah import
if (file_exists($tempFilePath)) {
unlink($tempFilePath);
Log::info('SlikController: File temp berhasil dihapus');
}
Log::info('SlikController: Data Slik berhasil diimport', [
'user_id' => Auth::id(),
'import_id' => $importId
]);
return redirect()->back()->with('success', 'Data Slik berhasil diimport dari file Excel.');
} catch (Exception $e) {
// Hapus file temporary jika ada error
if (isset($tempFilePath) && file_exists($tempFilePath)) {
unlink($tempFilePath);
Log::info('SlikController: File temp dihapus karena error');
}
Log::error('SlikController: Gagal import data Slik', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
'user_id' => Auth::id(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'memory_usage' => memory_get_usage(true)
]);
return redirect()->back()->with('error', 'Gagal import data Slik: ' . $e->getMessage());
}
}
/**
* Menampilkan halaman form import
*
* @return \Illuminate\View\View
*/
public function importForm()
{
return view('lpj::slik.import');
}
/**
* Download template Excel untuk import
*
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function downloadTemplate()
{
$templatePath = resource_path('metronic/slik.xlsx');
if (!file_exists($templatePath)) {
return redirect()->back()->with('error', 'Template file tidak ditemukan.');
}
return response()->download($templatePath, 'template_slik.xlsx');
}
/**
* Get import progress
*
* @param string $importId
* @return \Illuminate\Http\JsonResponse
*/
public function progress(string $importId)
{
try {
$progressService = new \Modules\Lpj\Services\ImportProgressService();
$progress = $progressService->getProgress($importId);
if (!$progress) {
return response()->json([
'success' => false,
'message' => 'Progress import tidak ditemukan'
], 404);
}
return response()->json([
'success' => true,
'progress' => $progress
]);
} catch (\Exception $e) {
Log::error('SlikController: Error getting progress', [
'import_id' => $importId,
'error' => $e->getMessage()
]);
return response()->json([
'success' => false,
'message' => 'Gagal mendapatkan progress: ' . $e->getMessage()
], 500);
}
}
/**
* Export data SLIK ke Excel
*
* Method ini menangani export data SLIK ke format Excel dengan:
* - Logging aktivitas export
* - Error handling yang proper
* - Format Excel yang sesuai dengan struktur SLIK
*
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function export()
{
try {
Log::info('SLIK Export: Memulai proses export data SLIK', [
'user_id' => Auth::id(),
'timestamp' => now(),
'memory_usage' => memory_get_usage(true) / 1024 / 1024 . ' MB'
]);
// Hitung total data yang akan di-export
$totalData = Slik::count();
Log::info('SLIK Export: Informasi data export', [
'total_records' => $totalData,
'user_id' => Auth::id(),
'timestamp' => now()
]);
// Generate nama file dengan timestamp
$filename = 'slik_export_' . date('Y-m-d_H-i-s') . '.xlsx';
// Proses export menggunakan SlikExport class
$export = Excel::download(new SlikExport(), $filename);
Log::info('SLIK Export: Berhasil generate file export', [
'filename' => $filename,
'total_records' => $totalData,
'user_id' => Auth::id(),
'timestamp' => now(),
'memory_peak' => memory_get_peak_usage(true) / 1024 / 1024 . ' MB'
]);
return $export;
} catch (\Exception $e) {
Log::error('SLIK Export: Gagal melakukan export data SLIK', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
'user_id' => Auth::id(),
'timestamp' => now(),
'memory_usage' => memory_get_usage(true) / 1024 / 1024 . ' MB'
]);
return response()->json([
'success' => false,
'message' => 'Gagal melakukan export data SLIK: ' . $e->getMessage()
], 500);
}
}
/**
* Truncate all SLIK data
*
* @return \Illuminate\Http\JsonResponse
*/
public function truncate()
{
try {
DB::beginTransaction();
Log::info('SLIK Truncate: Memulai proses truncate data SLIK', [
'user_id' => Auth::id(),
'timestamp' => now()
]);
// Truncate tabel SLIK
Slik::truncate();
DB::commit();
Log::info('SLIK Truncate: Berhasil menghapus semua data SLIK', [
'user_id' => Auth::id(),
'timestamp' => now()
]);
return response()->json([
'success' => true,
'message' => 'Semua data SLIK berhasil dihapus'
]);
} catch (\Exception $e) {
DB::rollback();
Log::error('SLIK Truncate: Gagal menghapus data SLIK', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
'user_id' => Auth::id(),
'timestamp' => now()
]);
return response()->json([
'success' => false,
'message' => 'Gagal menghapus data SLIK: ' . $e->getMessage()
], 500);
}
}
}

View File

@@ -34,17 +34,20 @@ use Illuminate\Support\Facades\Auth;
}
// Retrieve data from the database
$query =Permohonan::query()->with(['penawaran','penawaran.tujuanPenilaianKjpp'])
->where('permohonan.status','=','spk');
// $query =Permohonan::query()->with(['penawaran','penawaran.tujuanPenilaianKjpp'])->where('permohonan.status','=','spk');
// $data = $query->with(['user', 'debiture', 'branch', 'tujuanPenilaian','penilaian'])->get();
//$query =Permohonan::query()->with(['user', 'debiture', 'branch', 'tujuanPenilaian','penilaian','penawaran','penawaran.tujuanPenilaianKjpp'])->where('permohonan.status','=','spk');
$query = PenawaranTender::query()->with(['permohonan.user', 'permohonan.debiture', 'permohonan.branch', 'permohonan.tujuanPenilaian','permohonan.penilaian','tujuanPenilaianKjpp']);
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('nomor_registrasi', 'LIKE', '%' . $search . '%');
$q->orWhere('penawaran.tanggal_permohonan', 'LIKE', '%' . $search . '%');
$q->orWhere('status', 'LIKE', '%' . $search . '%');
$q->whereRelation('permohonan','nomor_registrasi', 'LIKE', '%' . $search . '%');
//$q->orWhere('tanggal_permohonan', 'LIKE', '%' . $search . '%');
//$q->orWhere('status', 'LIKE', '%' . $search . '%');
});
}
@@ -78,6 +81,11 @@ use Illuminate\Support\Facades\Auth;
$i=0;
foreach($data as $obj)
{
// tanggal_permohonan
if ($obj->permohonan->tanggal_permohonan) {
$data[$i]->permohonan->tanggal_permohonan = Carbon::parse($obj->permohonan->tanggal_permohonan)->format('d M Y');
}
if($obj->tanggal_penilaian_sebelumnya)
{
$data[$i]->tanggal_penilaian_sebelumnya = Carbon::parse($obj->tanggal_penilaian_sebelumnya)->format('d F Y H:i:s');
@@ -92,22 +100,21 @@ use Illuminate\Support\Facades\Auth;
// date_range
if($obj->start_date && $obj->end_date)
{
$data[$i]->date_range = Carbon::parse($obj->start_date)->format('d M Y').' - '.Carbon::parse($obj->end_date)->format('d M Y');
$data[$i]->date_range = Carbon::parse($obj->start_date)->format('d M Y').' - '.
Carbon::parse($obj->end_date)->format('d M Y');
}
// data dokumen_spk
if($obj->dokumen)
// data spk_dokumen_path
if($obj->spk_dokumen_path)
{
$spkpenawaran_path = Storage::url($obj->dokumen);
// dd($spkpenawaran_path);
$data[$i]->dokumen = $spkpenawaran_path;
$spk_dokumen_path = Storage::url($obj->spk_dokumen_path);
$data[$i]->spk_dokumen_path = $spk_dokumen_path;
}
$i++;
}
// Calculate the page count
$pageCount = ceil($totalRecords / $request->get('size'));
@@ -141,17 +148,17 @@ use Illuminate\Support\Facades\Auth;
public function edit($id)
{
$penawaran = PenawaranTender::leftJoin('detail_penawaran', 'detail_penawaran.penawaran_id','=','penawaran.id')
->leftJoin('jenis_laporan', 'jenis_laporan.id','=','penawaran.jenis_laporan_id')
->leftJoin('kjpp', 'kjpp.id','=','detail_penawaran.kjpp_rekanan_id')
->where('detail_penawaran.status','=',1)
->where('penawaran.id','=', $id)
->select('penawaran.*', 'detail_penawaran.attachment as attachmentku',
'detail_penawaran.biaya_penawaran as detail_penawaran_biaya_penawaran',
'kjpp.name as kjpp_name',
'kjpp.address as kjpp_address',
'jenis_laporan.name as jenis_laporan_name'
)->first();
$penawaran = PenawaranTender::with(['jenisLaporan','tujuanPenilaianKjpp','detail.kjpp','penilaian','persetujuan_penawaran'])->where('id',$id)->first();
$penawaran->attachmentku = $penawaran->detail->attachment;
$penawaran->detail_penawaran_no_proposal = $penawaran->detail->no_proposal;
$penawaran->detail_penawaran_tgl_proposal = $penawaran->detail->tgl_proposal;
$penawaran->detail_penawaran_biaya_penawaran = $penawaran->detail->biaya_penawaran;
$penawaran->kjpp_name = $penawaran->detail->kjpp->name;
$penawaran->kjpp_address = $penawaran->detail->kjpp->address;
$penawaran->jenis_laporan_name = $penawaran->jenisLaporan->name;
$penawaran->jenis_laporan_code = $penawaran->jenisLaporan->code;
$penawaran->tujuan_penilaian_kjpp_name = $penawaran->tujuanPenilaianKjpp->name;
$penawaran->penilaian_waktu_penilain = $penawaran->penilaian->waktu_penilaian ?? "";
$permohonan = Permohonan::where('nomor_registrasi','=',$penawaran->nomor_registrasi)
->leftJoin('dokumen_jaminan', 'dokumen_jaminan.permohonan_id','=','permohonan.id')
@@ -159,35 +166,100 @@ use Illuminate\Support\Facades\Auth;
->select('permohonan.*', 'jenis_jaminan.name as jenis_jaminan_name',
'dokumen_jaminan.address as dokumen_jaminan_address');
$data = $permohonan->with(['user', 'debiture', 'branch', 'tujuanPenilaian'])->first();
$data = $permohonan->with(['user', 'debiture', 'branch', 'tujuanPenilaian','dokumenjaminan.detail'])->first();
return view('lpj::spk.edit', compact('data', 'penawaran'));
if($penawaran->detail_penawaran_tgl_proposal)
$penawaran->detail_penawaran_tgl_proposal = Carbon::parse($penawaran->detail_penawaran_tgl_proposal)->format('d F Y');
// generate no spk
$spk_no_last=$penawaran->spk_no;
if(!$spk_no_last)
{
$spk_no_last = onLastnumberCodePenawaranSPK($penawaran->jenis_laporan_code);
$penawaran->spk_no = $spk_no_last;
}
// pengecekan perubahan jenis report
$array_no_last = explode("/",$spk_no_last);
$jenis_report_old=trim($array_no_last[4]);
if($jenis_report_old!=$penawaran->jenis_laporan_code)
{
$penawaran->spk_no=str_replace($jenis_report_old,$penawaran->jenis_laporan_code,$spk_no_last);
}
// pengecekan perubahan jenis report
// generate no spk
// Jangka Waktu
// date_start (penilaian.waktu_penilain + 1 day) - date_end (persetujuan_penawaran.sla_final)
$jangka_waktu='';
// Jangka Waktu
$persetujuan_no_proposal = $penawaran->detail_penawaran_no_proposal;
$persetujuan_tgl_proposal = $penawaran->detail_penawaran_tgl_proposal;
$persetujuan_sla_resume = '...';
$persetujuan_sla_final = '...';
if(null !==$penawaran->persetujuan)
{
$sla_resume_text = ceil($data->sla/2);
$sla_final_text = $data->sla;
$sla_resume_text_terbilang = ucfirst(terbilang($sla_resume_text));
$sla_final_text_terbilang = ucfirst(terbilang($sla_final_text));
$persetujuan_no_proposal = $penawaran->persetujuan->nomor_proposal_penawaran;
$persetujuan_tgl_proposal = Carbon::parse($penawaran->persetujuan->tanggal_proposal_penawaran)->format('d F Y');
$persetujuan_sla_resume = $sla_resume_text.' ('.$sla_resume_text_terbilang.')';
$persetujuan_sla_final = $sla_final_text.' ('.$sla_final_text_terbilang.')';
if($penawaran->penilaian_waktu_penilain)
{
$jangka_waktu_date_start=Carbon::parse($penawaran->penilaian_waktu_penilain)->addDays(1)->format('d F Y');
$jangka_waktu_date_end=Carbon::parse($penawaran->persetujuan->sla_final)->format('d F Y');
// Jangka Waktu
// date_start (penilaian.waktu_penilain + 1 day) - date_end (persetujuan_penawaran.sla_final)
$jangka_waktu=$jangka_waktu_date_start.' - '.$jangka_waktu_date_end;
// Jangka Waktu
}
}
return view('lpj::spk.edit', compact('data', 'penawaran', 'persetujuan_no_proposal', 'persetujuan_tgl_proposal', 'persetujuan_sla_resume', 'persetujuan_sla_final', 'jangka_waktu'));
}
public function update(Request $request, $id): JsonResponse
{
// init
$data1 = array();
$dataPermohonan = array();
$data1 = [];
// $dataPermohonan = array();
$dataPenawaran = [];
// data
$penawaran = PenawaranTender::leftJoin('detail_penawaran', 'detail_penawaran.penawaran_id','=','penawaran.id')
->leftJoin('jenis_laporan', 'jenis_laporan.id','=','penawaran.jenis_laporan_id')
->leftJoin('kjpp', 'kjpp.id','=','detail_penawaran.kjpp_rekanan_id')
->where('detail_penawaran.status','=',1)
->where('penawaran.id','=', $id)
->select('penawaran.*', 'detail_penawaran.attachment as attachmentku',
'kjpp.name as kjpp_name',
'kjpp.address as kjpp_address',
'jenis_laporan.name as jenis_laporan_name'
)->first();
$penawaran = PenawaranTender::with(['jenisLaporan','tujuanPenilaianKjpp','detail.kjpp','penilaian','persetujuan_penawaran'])->where('id',$id)->first();
$penawaran->attachmentku = $penawaran->detail->attachment;
$penawaran->detail_penawaran_no_proposal = $penawaran->detail->no_proposal;
$penawaran->detail_penawaran_tgl_proposal = $penawaran->detail->tgl_proposal;
$penawaran->detail_penawaran_biaya_penawaran = $penawaran->detail->biaya_penawaran;
$penawaran->kjpp_name = $penawaran->detail->kjpp->name;
$penawaran->kjpp_address = $penawaran->detail->kjpp->address;
$penawaran->jenis_laporan_name = $penawaran->jenisLaporan->name;
$penawaran->jenis_laporan_code = $penawaran->jenisLaporan->code;
$penawaran->tujuan_penilaian_kjpp_name = $penawaran->tujuanPenilaianKjpp->name;
$penawaran->penilaian_waktu_penilain = $penawaran->penilaian->waktu_penilaian ?? "";
$permohonan = Permohonan::where('nomor_registrasi','=',$penawaran->nomor_registrasi)
->leftJoin('dokumen_jaminan', 'dokumen_jaminan.permohonan_id','=','permohonan.id')
->leftJoin('jenis_jaminan', 'jenis_jaminan.id','=','dokumen_jaminan.jenis_jaminan_id')
->select('permohonan.*', 'jenis_jaminan.name as jenis_jaminan_name');
$data = $permohonan->with(['user', 'debiture', 'branch', 'tujuanPenilaian'])->first();
$data = $permohonan->with(['user', 'debiture', 'branch', 'tujuanPenilaian','dokumenjaminan'])->first();
// Jangka Waktu
// date_start (penilaian.waktu_penilain + 1 day) - date_end (persetujuan_penawaran.sla_final)
$jangka_waktu='';
// Jangka Waktu
if($penawaran->detail_penawaran_tgl_proposal)
$penawaran->detail_penawaran_tgl_proposal = Carbon::parse($penawaran->detail_penawaran_tgl_proposal)->format('d F Y');
$folderPath = 'uploads/spk/';
$extension = '.pdf';
@@ -195,18 +267,97 @@ use Illuminate\Support\Facades\Auth;
$newFileNameWithPath = $folderPath . $newFileName;
// update table permohonan
$dataPermohonan=['dokumen' => $newFileNameWithPath];
$data->update($dataPermohonan);
// $dataPermohonan=['dokumen' => $newFileNameWithPath];
// $data->update($dataPermohonan);
// update table permohonan
// update table penawaran
$dataPenawaran['spk_dokumen_path'] = $newFileNameWithPath;
// $spk_no_last=$penawaran->spk_no;
if(!$penawaran->spk_no)
{
$spk_no_last = onLastnumberCodePenawaranSPK($penawaran->jenis_laporan_code);
// $penawaran->no_spk = $no_spk_last;
$date_now = Carbon::now()->format('Ymd');// 20240124
$spk_number = substr ($spk_no_last, 0, 3);
$dataPenawaran['spk_no'] = $spk_no_last;
$dataPenawaran['spk_no_core'] = $date_now.'_'.$spk_number;
$penawaran->spk_no = $spk_no_last;
}
// pengecekan perubahan jenis report
$spk_no_old=$penawaran->spk_no;
$array_no_last = explode("/",$spk_no_old);
$jenis_report_old=trim($array_no_last[4]);
if($jenis_report_old!=$penawaran->jenis_laporan_code)
{
$penawaran_spk_no_new=str_replace($jenis_report_old,$penawaran->jenis_laporan_code,$spk_no_old);
$penawaran->spk_no=$penawaran_spk_no_new;
$dataPenawaran['spk_no'] = $penawaran_spk_no_new;
}
// pengecekan perubahan jenis report
$penawaranM = PenawaranTender::find($penawaran->id);
$penawaranM->update($dataPenawaran);
// update table penawaran
// pdf path
$spkpenawaran_path = Storage::url($newFileNameWithPath);
$pdf =Pdf::loadView('lpj::spk.documentSPK', compact('data', 'penawaran'));
$persetujuan_no_proposal = $penawaran->detail_penawaran_no_proposal;
$persetujuan_tgl_proposal = $penawaran->detail_penawaran_tgl_proposal;
$persetujuan_sla_resume = '...';
$persetujuan_sla_final = '...';
if(null !==$penawaran->persetujuan)
{
//$sla_resume_text = $penawaran->persetujuan->sla_resume;
//$sla_final_text = $penawaran->persetujuan->sla_final;
$sla_resume_text = ceil($data->sla/2);
$sla_final_text = $data->sla;
$sla_resume_text_terbilang = ucfirst(terbilang($sla_resume_text));
$sla_final_text_terbilang = ucfirst(terbilang($sla_final_text));
$persetujuan_no_proposal = $penawaran->persetujuan->nomor_proposal_penawaran;
$persetujuan_tgl_proposal = Carbon::parse($penawaran->persetujuan->tanggal_proposal_penawaran)->format('d F Y');
$persetujuan_sla_resume = $sla_resume_text.' ('.$sla_resume_text_terbilang.')';
$persetujuan_sla_final = $sla_final_text.' ('.$sla_final_text_terbilang.')';
if($penawaran->penilaian_waktu_penilain)
{
$jangka_waktu_date_start=Carbon::parse($penawaran->penilaian_waktu_penilain)->addDays(1)->format('d F Y');
$jangka_waktu_date_end=Carbon::parse($penawaran->persetujuan->sla_final)->format('d F Y');
// Jangka Waktu
// date_start (penilaian.waktu_penilain + 1 day) - date_end (persetujuan_penawaran.sla_final)
$jangka_waktu=$jangka_waktu_date_start.' - '.$jangka_waktu_date_end;
// Jangka Waktu
}
}
$pdf =Pdf::loadView('lpj::spk.documentSPK', compact('data', 'penawaran', 'persetujuan_no_proposal', 'persetujuan_tgl_proposal', 'persetujuan_sla_resume', 'persetujuan_sla_final', 'jangka_waktu'));
$pdf->setPaper('A4', 'portrait');
$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');
@@ -242,8 +393,26 @@ use Illuminate\Support\Facades\Auth;
}
public function download($id) {
$document = Permohonan::find($id);
// dokumen pdf diambil dari penawaran.spk_dokumen_path
$document = PenawaranTender::find($id);
return response()->download(storage_path('app/public/' .$document->dokumen));
return response()->download(storage_path('app/public/' .$document->spk_dokumen_path));
}
public function updateSla(Request $request, $id): JsonResponse
{
$request->validate([
'sla' => 'required|integer|min:1',
]);
$penawaran = PenawaranTender::find($id);
$permohonan = Permohonan::where('nomor_registrasi','=',$penawaran->nomor_registrasi)->first();
$permohonan->sla = $request->sla;
$permohonan->save();
return response()->json(['message' => 'SLA updated successfully']);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -196,6 +196,9 @@ class TeamsController extends Controller
->leftJoin('teams_users', 'teams.id', '=', 'teams_users.teams_id')
->leftJoin('users', 'teams_users.user_id', '=', 'users.id')
->addSelect('users.id as user_id', 'users.name as user_name');
// Filter pencarian
if ($request->has('search') && !empty($request->get('search'))) {

View File

@@ -5,17 +5,25 @@ namespace Modules\Lpj\Http\Controllers;
use Exception;
use Illuminate\Http\Request;
use Modules\Lpj\Models\KJPP;
use Modules\Location\Models\City;
use Illuminate\Support\Facades\DB;
use Modules\Lpj\Models\Permohonan;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Location\Models\Village;
use Modules\Lpj\Models\JenisLaporan;
use Modules\Location\Models\District;
use Modules\Location\Models\Province;
use Modules\Lpj\Models\PenawaranTender;
use Modules\Lpj\Models\StatusPermohonan;
use Modules\Lpj\Models\TujuanPenilaianKJPP;
use Modules\Lpj\Models\PenawaranDetailTender;
use Modules\Lpj\Exports\PenawaranTenderExport;
use Modules\Lpj\Http\Requests\TenderPenawaranRequest;
use Modules\Lpj\Jobs\SendPenawaranKJPPTenderJob;
use Modules\Lpj\Jobs\SendPenawaranTenderJob;
use Modules\Lpj\Models\PenawaranEmailTenderLog;
class TenderController extends Controller
{
@@ -66,12 +74,14 @@ class TenderController extends Controller
$permohonan = Permohonan::where('nomor_registrasi', '=', $noreg)->first();
// Add created_by/updated_by from the authenticated user
$userId = auth()->user()->id;
$userId = Auth::user()->id;
$validated['nomor_registrasi'] = $permohonan->nomor_registrasi;
$validated['status'] = $request->input('status') ?? 'tender';
$validated['updated_by'] = $userId; // Updating the record
$validated['end_date'] = $request->input('end_date') . ' 17:00:00';
// dd($validated['end_date']);
$permohonan->update($validated);
// Adding created_by for the new PenawaranTender record
@@ -117,6 +127,15 @@ class TenderController extends Controller
$penawaranExists = PenawaranTender::where('nomor_registrasi', $noreg)->exists();
$penawaran1 = PenawaranTender::where('nomor_registrasi', '=', $noreg)->first();
if (!$penawaran1) {
return redirect()->route('tender.penawaran.createPenawaran', ['noreg' => $noreg])->with('error', 'Penawaran dengan nomor registrasi ini belum dibuat. Silahkan isi terlebih dahulu!');
}
if ($penawaran1->status != 'tender') {
return redirect()->route('otorisasitender.penawaran.index')->with('error', 'Penawaran dengan nomor registrasi ini sudah masuk Otorisasi Tender tidak bisa masuk penawaran lagi!');
}
// dd($penawaran1->id);
if ($penawaran1) {
$penawaran = $penawaran1;
@@ -141,8 +160,18 @@ class TenderController extends Controller
{
// Find the specific penawaran by its ID
$penawaran = PenawaranTender::where('nomor_registrasi', '=', $noreg)->first();
if (!$penawaran) {
return redirect()->route('tender.penawaran.createPenawaran', ['noreg' => $noreg])->with('error', 'Penawaran dengan nomor registrasi ini belum dibuat. Silahkan isi terlebih dahulu!');
}
$permohonan = Permohonan::where('nomor_registrasi', '=', $noreg)->first();
if ($penawaran->status != 'tender') {
return redirect()->route('otorisasitender.penawaran.index')->with('error', 'Penawaran dengan nomor registrasi ini sudah masuk Otorisasi Tender tidak bisa masuk penawaran lagi!');
}
$status = StatusPermohonan::all();
$tujuan_penilaian_kjpp = TujuanPenilaianKJPP::all();
$jenis_laporan = JenisLaporan::all();
@@ -152,6 +181,8 @@ class TenderController extends Controller
$kjpp = KJPP::all();
// dd($penawaran);
return view('lpj::penawaran.edit', compact('status', 'tujuan_penilaian_kjpp', 'jenis_laporan', 'kjpp', 'penawaran', 'noreg', 'kjpps', 'permohonan'));
}
@@ -171,13 +202,15 @@ class TenderController extends Controller
$permohonan = Permohonan::where('nomor_registrasi', '=', $noreg)->first();
// Ambil ID user yang sedang login
$userId = auth()->user()->id;
$userId = Auth::user()->id;
// Jangan ubah created_by untuk data yang sudah ada
$validated['nomor_registrasi'] = $penawaran->nomor_registrasi;
$validated['status'] = $request->input('status') ?? 'tender';
$validated['created_by'] = $userId;
$validated['updated_by'] = $userId; // Hanya update 'updated_by'
$validated['end_date'] = $request->input('end_date') . ' 17:00:00';
// dd($validated['end_date']);
// Update data penawaran dan permohonan
$penawaran->update($validated);
@@ -228,7 +261,7 @@ class TenderController extends Controller
DB::commit();
return redirect()
->route('tender.penawaran.index')
->route('tender.penawaran.ulang.index')
->with('success', 'Data Penawaran updated successfully');
} catch (Exception $e) {
// Rollback jika ada kesalahan
@@ -247,19 +280,97 @@ class TenderController extends Controller
public function showSuratTender($noreg)
{
$penawaran = PenawaranTender::where('nomor_registrasi', '=', $noreg)->first();
$permohonan = Permohonan::where('nomor_registrasi', '=', $noreg)->first();
// Kalau tidak ketemu nomor registrasi dengan tabel penawaran
if (!$penawaran) {
return redirect()->route('tender.penawaran.createPenawaran', ['noreg' => $noreg])
->with('error', 'Anda Belum Membuat Penawaran. Silahkan isi terlebih dahulu!');
}
if ($penawaran->status != 'tender') {
return redirect()->route('otorisasitender.penawaran.index')->with('error', 'Penawaran dengan nomor registrasi ini sudah masuk Otorisasi Tender tidak bisa masuk penawaran lagi!');
}
// Kalau tidak ada dokumen jaminan maka di arahkan ke halaman dokumen jaminan
if ($permohonan->documents->isEmpty()) {
return redirect()->route('debitur.jaminan.create', ['id' => $permohonan->debiture->id])
->with('error', 'Anda Belum Membuat Dokumen Jaminan. Silahkan isi terlebih dahulu!');
}
foreach ($permohonan->documents as $document) {
$village_permohonan = $document->village_code;
$district_permohonan = $document->district_code;
$city_permohonan = $document->city_code;
$province_permohonan = $document->province_code;
}
$villages = Village::where('code', $village_permohonan)->get();
$districts = District::where('code', $district_permohonan)->get();
$cities = City::where('code', $city_permohonan)->get();
$provinces = Province::where('code', $province_permohonan)->get();
date_default_timezone_set('Asia/Jakarta');
$now = date('Y-m-d H:i:s');
// Jika batas tanggal penawaran sudah lewat
if ($penawaran->end_date < date('Y-m-d')) {
if ($penawaran->end_date < $now) {
return redirect()->route('tender.penawaran.editPenawaran', ['noreg' => $noreg])
->with('error', 'Sudah Kadaluarsa. Silahkan perpanjang tanggal penawaran terlebih dahulu!');
}
return view('lpj::penawaran.surat_tender', compact('penawaran', 'noreg'));
return view('lpj::penawaran.surat_tender', compact('penawaran', 'noreg', 'permohonan', 'villages', 'districts', 'cities', 'provinces'));
}
public function suratTenderKJPP($noreg, $id)
{
$kjpp = KJPP::find($id);
$permohonan = Permohonan::where('nomor_registrasi', '=', $noreg)->first();
$penawaran = PenawaranTender::where('nomor_registrasi', '=', $noreg)->first();
if (!$penawaran) {
return redirect()->route('tender.penawaran.createPenawaran', ['noreg' => $penawaran->nomor_registrasi])
->with('error', 'Anda Belum Membuat Penawaran. Silahkan isi terlebih dahulu!');
}
if ($penawaran->status != 'tender') {
return redirect()->route('otorisasitender.penawaran.index')->with('error', 'Penawaran dengan nomor registrasi ini sudah masuk Otorisasi Tender tidak bisa masuk penawaran lagi!');
}
// Kalau tidak ada dokumen jaminan maka di arahkan ke halaman dokumen jaminan
if ($permohonan->documents->isEmpty()) {
return redirect()->route('debitur.jaminan.create', ['id' => $permohonan->debiture->id])
->with('error', 'Anda Belum Membuat Dokumen Jaminan. Silahkan isi terlebih dahulu!');
}
foreach ($permohonan->documents as $document) {
$village_permohonan = $document->village_code;
$district_permohonan = $document->district_code;
$city_permohonan = $document->city_code;
$province_permohonan = $document->province_code;
}
$villages = Village::where('code', $village_permohonan)->get();
$districts = District::where('code', $district_permohonan)->get();
$cities = City::where('code', $city_permohonan)->get();
$provinces = Province::where('code', $province_permohonan)->get();
date_default_timezone_set('Asia/Jakarta');
$now = date('Y-m-d H:i:s');
// Jika batas tanggal penawaran sudah lewat
if ($penawaran->end_date < $now) {
return redirect()->route('tender.penawaran.editPenawaran', ['noreg' => $noreg])
->with('error', 'Sudah Kadaluarsa. Silahkan perpanjang tanggal penawaran terlebih dahulu!');
}
$detail_penawaran = PenawaranDetailTender::with('kjpp')->where('kjpp_rekanan_id', '=', $kjpp->id)->get();
foreach ($detail_penawaran as $detail) {
$detail_penawaran_1 = $detail->kjpp;
}
return view('lpj::penawaran.surat_tender_kjpp', compact('penawaran', 'noreg', 'permohonan', 'villages', 'districts', 'cities', 'provinces', 'detail_penawaran_1', 'id'));
}
public function datatablesPenawaran(Request $request)
@@ -414,4 +525,549 @@ class TenderController extends Controller
// Kembalikan hasil pengecekan sebagai JSON
return response()->json(['exists' => $exists]);
}
public function downloadSuratTender($noreg)
{
$penawaran = PenawaranTender::where('nomor_registrasi', '=', $noreg)->first();
$permohonan = Permohonan::where('nomor_registrasi', '=', $noreg)->first();
if ($penawaran->status != 'tender') {
return redirect()->route('otorisasitender.penawaran.index')->with('error', 'Penawaran dengan nomor registrasi ini sudah masuk Otorisasi Tender tidak bisa masuk penawaran lagi!');
}
foreach ($permohonan->documents as $document) {
$village_permohonan = $document->village_code;
$district_permohonan = $document->district_code;
$city_permohonan = $document->city_code;
$province_permohonan = $document->province_code;
}
$villages = Village::where('code', $village_permohonan)->get();
$districts = District::where('code', $district_permohonan)->get();
$cities = City::where('code', $city_permohonan)->get();
$provinces = Province::where('code', $province_permohonan)->get();
$pdf = app('dompdf.wrapper'); // create an instance of the PDF class
$pdf->loadView('lpj::penawaran.surat_tender_download', compact('penawaran', 'permohonan', 'villages', 'districts', 'cities', 'provinces'));
return $pdf->download('surat_tender' . time() . '.pdf');
}
public function downloadSuratTenderKJPP($noreg, $id)
{
$kjpp = KJPP::find($id);
$penawaran = PenawaranTender::where('nomor_registrasi', '=', $noreg)->first();
$permohonan = Permohonan::where('nomor_registrasi', '=', $noreg)->first();
if ($penawaran->status != 'tender') {
return redirect()->route('otorisasitender.penawaran.index')->with('error', 'Penawaran dengan nomor registrasi ini sudah masuk Otorisasi Tender tidak bisa masuk penawaran lagi!');
}
foreach ($permohonan->documents as $document) {
$village_permohonan = $document->village_code;
$district_permohonan = $document->district_code;
$city_permohonan = $document->city_code;
$province_permohonan = $document->province_code;
}
$villages = Village::where('code', $village_permohonan)->get();
$districts = District::where('code', $district_permohonan)->get();
$cities = City::where('code', $city_permohonan)->get();
$provinces = Province::where('code', $province_permohonan)->get();
$detail_penawaran = PenawaranDetailTender::with('kjpp')->where('kjpp_rekanan_id', '=', $kjpp->id)->get();
foreach ($detail_penawaran as $detail) {
$detail_penawaran_1 = $detail->kjpp;
}
$pdf = app('dompdf.wrapper'); // create an instance of the PDF class
$pdf->loadView('lpj::penawaran.surat_tender_kjpp_download', compact('penawaran', 'permohonan', 'villages', 'districts', 'cities', 'provinces', 'detail_penawaran_1'));
return $pdf->download('surat_tender_kjpp' . time() . '.pdf');
}
// Kirim Email
public function showKirimEmail($noreg)
{
$penawaran = PenawaranTender::where('nomor_registrasi', '=', $noreg)->first();
$permohonan = Permohonan::where('nomor_registrasi', '=', $noreg)->first();
if (!$penawaran) {
return redirect()->route('tender.penawaran.createPenawaran', ['noreg' => $noreg])
->with('error', 'Anda Belum Membuat Penawaran. Silahkan isi terlebih dahulu!');
}
if ($penawaran->status != 'tender') {
return redirect()->route('otorisasitender.penawaran.index')->with('error', 'Penawaran dengan nomor registrasi ini sudah masuk Otorisasi Tender tidak bisa masuk penawaran lagi!');
}
if ($permohonan->documents->isEmpty()) {
return redirect()->route('debitur.jaminan.create', ['id' => $permohonan->debiture->id])
->with('error', 'Anda Belum Membuat Dokumen Jaminan. Silahkan isi terlebih dahulu!');
}
return view('lpj::penawaran.showKirimEmail', compact('penawaran', 'permohonan', 'noreg'));
}
public function dataTablesShowKirimSurat(Request $request, $noreg)
{
if (is_null($this->user) || !$this->user->can('penawaran.view')) {
// abort(403, 'Sorry! You are not allowed to view users.');
}
$penawaran = PenawaranTender::where('nomor_registrasi', '=', $noreg)->first();
// Retrieve data from the database
$query = PenawaranDetailTender::query()->where('penawaran_id', '=', $penawaran->id)->with(['kjpp', 'penawaran', 'penawaran.emailTenderLog']);
// dd($query);
// Apply sorting if provided
if ($request->has('sortOrder') && !empty($request->get('sortOrder'))) {
$order = $request->get('sortOrder');
$column = $request->get('sortField');
// Handle sorting for related table columns
if ($column === 'nama_kjpp') {
// Join with the KJPP table and sort by the name column
$query->join('kjpp', 'detail_penawaran.kjpp_rekanan_id', '=', 'kjpp.id')
->orderBy('kjpp.name', $order)
->select('detail_penawaran.*'); // Select only the main table columns to avoid conflicts
} else if ($column === 'nomor_kjpp') {
$query->join('kjpp', 'detail_penawaran.kjpp_rekanan_id', '=', 'kjpp.id')
->orderBy('kjpp.code', $order)
->select('detail_penawaran.*');
} else {
// Sort by columns in the main table
$query->orderBy($column, $order);
}
}
// Get the data for the current page
$data = $query->get();
// add column "No"
$i = 0;
$j = 1;
foreach ($data as $obj) {
// tanggal_permohonan
$data[$i]->numbernya = $j;
$i++;
$j++;
}
// Return the response data as a JSON object
return response()->json([
'draw' => $request->get('draw'),
'data' => $data,
]);
}
public function kirimEmailAll($noreg)
{
$penawaran = PenawaranTender::where('nomor_registrasi', '=', $noreg)->first();
$permohonan = Permohonan::where('nomor_registrasi', '=', $noreg)->first();
if (!$penawaran) {
return redirect()->route('tender.penawaran.createPenawaran', ['noreg' => $noreg])
->with('error', 'Anda Belum Membuat Penawaran. Silahkan isi terlebih dahulu!');
}
if ($penawaran->status != 'tender') {
return redirect()->route('otorisasitender.penawaran.index')->with('error', 'Penawaran dengan nomor registrasi ini sudah masuk Otorisasi Tender tidak bisa masuk penawaran lagi!');
}
if ($permohonan->documents->isEmpty()) {
return redirect()->route('debitur.jaminan.create', ['id' => $permohonan->debiture->id])
->with('error', 'Anda Belum Membuat Dokumen Jaminan. Silahkan isi terlebih dahulu!');
}
$detail_penawaran = PenawaranDetailTender::where('penawaran_id', '=', $penawaran->id)->get();
foreach ($detail_penawaran as $detail) {
$this->kirimEmailKJPP($noreg, $detail->kjpp_rekanan_id);
}
$detail_penawaran = PenawaranDetailTender::where('penawaran_id', '=', $penawaran->id)
->where('status', '=', 1)
->pluck('kjpp_rekanan_id')
->toArray();
$kjpps = KJPP::whereIn('id', $detail_penawaran)
->get()
->map(function ($item) {
$emails = collect(explode(',', $item->email_kantor))->filter()->unique();
// Parse JSON string jika ada dan tidak kosong
if (!empty($item->detail_email_kantor) && $item->detail_email_kantor !== '[]') {
$detail_emails = json_decode($item->detail_email_kantor, true);
if (is_array($detail_emails)) {
foreach ($detail_emails as $detail) {
if (is_array($detail) && isset($detail['email_kantor'])) {
$emails->push($detail['email_kantor']);
} elseif (is_string($detail)) {
$emails->push($detail);
}
}
}
}
return [
'kjpp' => $item,
'emails' => array_filter($emails->unique()->values()->all())
];
});
foreach ($permohonan->documents as $document) {
$village_permohonan = $document->village_code;
$district_permohonan = $document->district_code;
$city_permohonan = $document->city_code;
$province_permohonan = $document->province_code;
}
$villages = Village::where('code', $village_permohonan)->get();
$districts = District::where('code', $district_permohonan)->get();
$cities = City::where('code', $city_permohonan)->get();
$provinces = Province::where('code', $province_permohonan)->get();
$user = auth::user();
$subject = 'Send Penawaran Email';
$body_pdf = view('lpj::penawaran.kirimEmail', [
'penawaran' => $penawaran,
'permohonan' => $permohonan,
'kjpps' => $kjpps->pluck('emails')->flatten()->toArray(),
'villages' => $villages,
'districts' => $districts,
'cities' => $cities,
'provinces' => $provinces,
'user' => $user,
])->render();
// Dispatch job untuk mengirim email
// SendPenawaranTenderJob::dispatch(
// $kjpps->pluck('emails')->flatten()->toArray(),
// $penawaran,
// $permohonan,
// $villages,
// $districts,
// $cities,
// $provinces,
// $user
// );
try {
// Proses log email untuk setiap KJPP
foreach ($kjpps as $kjppData) {
foreach ($kjppData['emails'] as $email) {
// Cek log yang sudah ada
$log = PenawaranEmailTenderLog::where('penawaran_id', $penawaran->id)
->where('to_email', $email)
->where('status', 'failed')
->first();
$log1 = PenawaranEmailTenderLog::where('penawaran_id', $penawaran->id)
->where('to_email', $email)
->where('status', 'success')
->first();
if ($log) {
// Update log failed menjadi success
$log->update([
'penawaran_id' => $penawaran->id,
'kjpp' => $kjppData['kjpp']->code . ' | ' . $kjppData['kjpp']->name,
'to_email' => $email,
'subject' => $subject,
'body_pdf' => $body_pdf,
'status' => 'success',
'error_message' => null,
'updated_at' => now(),
]);
} else if ($log1) {
// Update timestamp jika sudah success
$log1->update([
'penawaran_id' => $penawaran->id,
'kjpp' => $kjppData['kjpp']->code . ' | ' . $kjppData['kjpp']->name,
'to_email' => $email,
'subject' => $subject,
'body_pdf' => $body_pdf,
'updated_at' => now(),
]);
} else {
// Buat log baru
PenawaranEmailTenderLog::create([
'penawaran_id' => $penawaran->id,
'kjpp' => $kjppData['kjpp']->code . ' | ' . $kjppData['kjpp']->name,
'to_email' => $email,
'subject' => $subject,
'body_pdf' => $body_pdf,
'status' => 'success',
'error_message' => null,
'created_at' => now(),
'updated_at' => now(),
]);
}
}
}
return redirect()->back()
->with('success', 'Email Penawaran Berhasil Terkirim!');
} catch (\Exception $e) {
// Log email gagal untuk setiap KJPP
foreach ($kjpps as $kjppData) {
foreach ($kjppData['emails'] as $email) {
$log = PenawaranEmailTenderLog::where('penawaran_id', $penawaran->id)
->where('to_email', $email)
->where('status', 'success')
->first();
$log1 = PenawaranEmailTenderLog::where('penawaran_id', $penawaran->id)
->where('to_email', $email)
->where('status', 'failed')
->first();
if ($log) {
// Update log success menjadi failed
$log->update([
'penawaran_id' => $penawaran->id,
'kjpp' => $kjppData['kjpp']->code . ' | ' . $kjppData['kjpp']->name,
'to_email' => $email,
'subject' => $subject,
'body_pdf' => $body_pdf,
'status' => 'failed',
'error_message' => $e->getMessage(),
'updated_at' => now(),
]);
} else if ($log1) {
// Update error message jika sudah failed
$log1->update([
'penawaran_id' => $penawaran->id,
'kjpp' => $kjppData['kjpp']->code . ' | ' . $kjppData['kjpp']->name,
'to_email' => $email,
'subject' => $subject,
'body_pdf' => $body_pdf,
'error_message' => $e->getMessage(),
'updated_at' => now(),
]);
} else {
// Buat log baru dengan status failed
PenawaranEmailTenderLog::create([
'penawaran_id' => $penawaran->id,
'kjpp' => $kjppData['kjpp']->code . ' | ' . $kjppData['kjpp']->name,
'to_email' => $email,
'subject' => $subject,
'body_pdf' => $body_pdf,
'status' => 'failed',
'error_message' => $e->getMessage(),
'created_at' => now(),
'updated_at' => now(),
]);
}
}
}
return redirect()->back()
->with('error', 'Email Penawaran Gagal Terkirim!');
}
}
public function kirimEmailKJPP($noreg, $id)
{
$penawaran = PenawaranTender::where('nomor_registrasi', '=', $noreg)->first();
$permohonan = Permohonan::where('nomor_registrasi', '=', $noreg)->first();
if (!$penawaran) {
return redirect()->route('tender.penawaran.createPenawaran', ['noreg' => $noreg])
->with('error', 'Anda Belum Membuat Penawaran. Silahkan isi terlebih dahulu!');
}
if ($penawaran->status != 'tender') {
return redirect()->route('otorisasitender.penawaran.index')->with('error', 'Penawaran dengan nomor registrasi ini sudah masuk Otorisasi Tender tidak bisa masuk penawaran lagi!');
}
if ($permohonan->documents->isEmpty()) {
return redirect()->route('debitur.jaminan.create', ['id' => $permohonan->debiture->id])
->with('error', 'Anda Belum Membuat Dokumen Jaminan. Silahkan isi terlebih dahulu!');
}
$detail_penawaran = PenawaranDetailTender::with('kjpp')->where('kjpp_rekanan_id', '=', $id)->pluck('kjpp_rekanan_id')->toArray();
$kjpps = KJPP::whereIn('id', $detail_penawaran)
->get()
->map(function ($item) {
$emails = collect(explode(',', $item->email_kantor))->filter()->unique();
// Parse JSON string jika ada dan tidak kosong
if (!empty($item->detail_email_kantor) && $item->detail_email_kantor !== '[]') {
$detail_emails = json_decode($item->detail_email_kantor, true);
if (is_array($detail_emails)) {
foreach ($detail_emails as $detail) {
if (is_array($detail) && isset($detail['email_kantor'])) {
$emails->add($detail['email_kantor']);
} elseif (is_string($detail)) {
$emails->add($detail);
}
}
}
}
return array_filter(array_values(iterator_to_array($emails)));
})
->flatten()
->unique()
->values()
->toArray();
$dp1 = PenawaranDetailTender::with('kjpp')->where('kjpp_rekanan_id', '=', $id)->first();
foreach ($permohonan->documents as $document) {
$village_permohonan = $document->village_code;
$district_permohonan = $document->district_code;
$city_permohonan = $document->city_code;
$province_permohonan = $document->province_code;
}
$villages = Village::where('code', $village_permohonan)->get();
$districts = District::where('code', $district_permohonan)->get();
$cities = City::where('code', $city_permohonan)->get();
$provinces = Province::where('code', $province_permohonan)->get();
$user = auth()->user();
$subject = 'Send Penawaran Email';
$body_pdf = view('lpj::penawaran.kirimEmailKJPP', [
'dp1' => $dp1,
'penawaran' => $penawaran,
'permohonan' => $permohonan,
'kjpps' => $kjpps,
'villages' => $villages,
'districts' => $districts,
'cities' => $cities,
'provinces' => $provinces,
'user' => $user,
])->render();
SendPenawaranKJPPTenderJob::dispatch(
$kjpps,
$dp1,
$penawaran,
$permohonan,
$villages,
$districts,
$cities,
$provinces,
$user
);
try {
// Proses log email
foreach ($kjpps as $email) {
// Cek apakah sudah ada log dengan status 'failed' untuk email ini
$log = PenawaranEmailTenderLog::where('penawaran_id', $penawaran->id)
->where('to_email', $email)
->where('status', 'failed')
->first();
$log1 = PenawaranEmailTenderLog::where('penawaran_id', $penawaran->id)
->where('to_email', $email)
->where('status', 'success')
->first();
if ($log) {
// Jika log ditemukan dan statusnya 'failed', update status menjadi 'success'
$log->update([
'penawaran_id' => $penawaran->id,
'kjpp' => $dp1->kjpp->code . ' | ' . $dp1->kjpp->name,
'to_email' => $email,
'subject' => $subject,
'body_pdf' => $body_pdf,
'status' => 'success',
'error_message' => null, // Reset error_message saat status diubah menjadi success
'updated_at' => now(),
]);
} else if ($log1) {
// Jika log ditemukan dan statusnya 'success' biarkan saja
$log1->update([
'penawaran_id' => $penawaran->id,
'kjpp' => $dp1->kjpp->code . ' | ' . $dp1->kjpp->name,
'to_email' => $email,
'subject' => $subject,
'body_pdf' => $body_pdf,
'updated_at' => now(),
]);
} else {
// Jika tidak ada log gagal, buat log baru dengan status 'success'
PenawaranEmailTenderLog::create([
'penawaran_id' => $penawaran->id,
'kjpp' => $dp1->kjpp->code . ' | ' . $dp1->kjpp->name,
'to_email' => $email,
'subject' => $subject,
'body_pdf' => $body_pdf,
'status' => 'success',
'error_message' => null, // Tidak ada error message
'created_at' => now(),
'updated_at' => now(),
]);
}
}
return redirect()->back()->with('success', 'Email Penawaran Berhasil Terkirim!');
} catch (\Exception $e) {
// Log email gagal
foreach ($kjpps as $email) {
$log = PenawaranEmailTenderLog::where('penawaran_id', $penawaran->id)
->where('to_email', $email)
->where('status', 'success')
->first();
$log1 = PenawaranEmailTenderLog::where('penawaran_id', $penawaran->id)
->where('to_email', $email)
->where('status', 'failed')
->first();
if ($log) {
// Jika log ditemukan dan statusnya 'success', update status menjadi 'failed'
$log->update([
'penawaran_id' => $penawaran->id,
'kjpp' => $dp1->kjpp->code . ' | ' . $dp1->kjpp->name,
'to_email' => $email,
'subject' => $subject,
'body_pdf' => $body_pdf,
'status' => 'failed',
'error_message' => $e->getMessage(),
'updated_at' => now(),
]);
} else if ($log1) {
// Jika log ditemukan dan statusnya 'failed' biarkan saja
$log1->update([
'penawaran_id' => $penawaran->id,
'kjpp' => $dp1->kjpp->code . ' | ' . $dp1->kjpp->name,
'to_email' => $email,
'subject' => $subject,
'body_pdf' => $body_pdf,
'error_message' => $e->getMessage(),
'updated_at' => now(),
]);
} else {
PenawaranEmailTenderLog::create([
'penawaran_id' => $penawaran->id,
'kjpp' => $dp1->kjpp->code . ' | ' . $dp1->kjpp->name,
'to_email' => $email,
'subject' => $subject,
'body_pdf' => $body_pdf,
'status' => 'failed',
'error_message' => $e->getMessage(),
'created_at' => now(),
'updated_at' => now(),
]);
}
}
return redirect()->back()->with('error', 'Email Penawaran Gagal Terkirim!');
}
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace Modules\Lpj\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class BankDataRequest extends FormRequest
{
public function authorize()
{
return true; // Adjust this based on your authorization logic
}
public function rules()
{
return [
'address' => 'nullable|string|max:255',
'village_code' => 'nullable|string|max:20',
'district_code' => 'nullable|string|max:20',
'city_code' => 'nullable|string|max:20',
'province_code' => 'nullable|string|max:20',
'tahun' => 'nullable|integer',
'luas_tanah' => 'nullable|numeric',
'luas_bangunan' => 'nullable|numeric',
'tahun_bangunan' => 'nullable|integer',
'status_nara_sumber' => 'nullable|string|max:50',
'harga' => 'nullable|numeric',
'harga_diskon' => 'nullable|numeric',
'diskon' => 'nullable|numeric',
'total' => 'nullable|numeric',
'nama_nara_sumber' => 'nullable|string|max:100',
'peruntukan' => 'nullable|string|max:100',
'penawaran' => 'nullable|string|max:50',
'telepon' => 'nullable|string|max:20',
'hak_properti' => 'nullable|string|max:50',
'kordinat_lat' => 'nullable|numeric',
'kordinat_lng' => 'nullable|numeric',
'jenis_aset' => 'nullable|string|max:50',
'foto_objek' => 'nullable|image|max:2048',
'tanggal' => 'nullable|date',
'harga_penawaran' => 'nullable|numeric',
'nomor_laporan' => 'nullable|string|max:50',
'tgl_final_laporan' => 'nullable|date',
'nilai_pasar' => 'nullable|numeric',
'indikasi_nilai_likuidasi' => 'nullable|numeric',
'indikasi_nilai_pasar_tanah' => 'nullable|numeric',
'estimasi_harga_tanah' => 'nullable|numeric',
'estimasi_harga_bangunan' => 'nullable|numeric',
'indikasi_nilai_pasar_bangunan' => 'nullable|numeric',
'indikasi_nilai_pasar_sarana_pelengkap' => 'nullable|numeric',
'indikasi_nilai_pasar_mesin' => 'nullable|numeric',
'indikasi_nilai_pasar_kendaraan_alat_berat' => 'nullable|numeric',
'photos' => 'nullable|array',
'photos.*' => 'nullable|image|max:2048',
];
}
}

View File

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

View File

@@ -0,0 +1,58 @@
<?php
namespace Modules\Lpj\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Modules\Lpj\Models\CustomField;
use Illuminate\Validation\Rule;
class CustomFieldRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*/
public function rules(): array
{
return [
'name' => 'required|max:255',
'type' => 'required|in:text,select,radio,checkbox,date,number',
'label' => 'nullable|max:255',
'urutan_prioritas' => [
'nullable',
'integer',
Rule::unique('custom_fields')->ignore($this->route('custom_field')),
],
];
}
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
public function prepareValidationData($data){
if(!$this->type){
$this->merge(['type' => 'text']);
}
if (!$this->urutan_prioritas) {
$maxPrioritas = CustomField::max('urutan_prioritas') ?? 0;
$this->merge(['urutan_prioritas' => $maxPrioritas + 1]);
}
}
/**
* Get custom messages for validator errors.
*
* @return array
*/
public function messages()
{
return [
'urutan_prioritas.unique' => 'Urutan prioritas sudah digunakan. Silakan pilih nomor lain.',
];
}
}

View File

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

View File

@@ -13,16 +13,17 @@
: array
{
$rules = [
'debiture_id' => 'required|exists:debitures,id',
'pemilik_jaminan_id' => 'required',
'jenis_jaminan_id' => 'required',
'province_code' => 'nullable|exists:provinces,code',
'city_code' => 'nullable|exists:cities,code',
'district_code' => 'nullable|exists:districts,code',
'village_code' => 'nullable|exists:villages,code',
'address' => 'nullable|string',
'postal_code' => 'nullable|string|max:10',
'status' => 'nullable|boolean',
'debiture_id' => 'required|exists:debitures,id',
'permohonan_id' => 'required|exists:permohonan,id',
'pemilik_jaminan_id' => 'required',
'jenis_jaminan_id' => 'required',
'province_code' => 'nullable|exists:provinces,code',
'city_code' => 'nullable|exists:cities,code',
'district_code' => 'nullable|exists:districts,code',
'village_code' => 'nullable|exists:villages,code',
'address' => 'nullable|string',
'postal_code' => 'nullable|string|max:10',
'status' => 'nullable|boolean',
];
return $rules;

View File

@@ -19,57 +19,9 @@ class FormSurveyorRequest extends FormRequest
*/
public function rules(): array
{
$commonRules = $this->getCommonRules();
$actionSpecificRules = $this->getActionSpecificRules();
return array_merge($commonRules, $actionSpecificRules);
}
/**
* Get common rules that apply to all actions.
*/
private function getCommonRules(): array
{
return [
'jenis_jaminan_id' => 'required',
'type' => 'required',
'permohonan_id' => 'required',
'luas' => 'required',
'jarak_jalan_utama' => 'required',
'alamat' => 'required',
'jarak_cbd_point' => 'required',
'lebar_perkerasan_jalan' => 'required',
'perkerasan_jalan' => 'required',
'lalu_lintas' => 'required',
'gol_mas_sekitar' => 'required',
'tingkat_keramaian' => 'required',
'terletak_diarea' => 'required',
'disekitar_lokasi' => 'required',
'dekat_makam' => 'required',
'dekat_tps' => 'required',
'merupakan_daerah' => 'required',
'fasilitas_dekat_object' => 'required',
'fakta_positif' => 'required',
'fakta_negatif' => 'required',
'rute_menuju' => 'required',
'batas_batas' => 'required',
'kondisi_linkungan' => 'required',
'kondisi_lain_bangunan' => 'required',
'informasi_dokument' => 'required',
'peruntukan' => 'required',
'kdb' => 'required',
'kdh' => 'required',
'gsb' => 'required',
'max_lantai' => 'required',
'klb' => 'required',
'gss' => 'required',
'pelebaran_jalan' => 'required',
'nama_petugas' => 'required',
'lat' => 'required|numeric',
'lng' => 'required|numeric',
'foto_tempat' => 'required',
'keterangan' => 'required',
];
return $actionSpecificRules;
}
/**
@@ -78,56 +30,670 @@ class FormSurveyorRequest extends FormRequest
private function getActionSpecificRules(): array
{
$action = $this->input('action');
$pisah = explode(',', $action);
switch ($action) {
case 'tanah_bangunan':
return $this->getTanahBangunanRules();
case 'unit':
return $this->getUnitRules();
default:
return [];
$allRules = [
'tanah' => $this->getTanahRules(),
'bangunan' => $this->getBangunanRules(),
'kapal' => $this->getKapalRules(),
'kendaraan' => $this->getKendaraanRules(),
'mesin' => $this->getMesinRules(),
'pesawat' => $this->getPesawatRules(),
'alat-berat' => $this->getAlatBeratRules(),
'apartemen-kantor' => $this->getUnitRules(),
'lingkungan' => $this->getLinkunganRules(),
'fakta' => $this->getCommonRules(),
'rap' => $this->getRapRules()
];
$rules = [];
$hasAssetDescriptionRules = false;
foreach ($pisah as $act) {
if (isset($allRules[$act])) {
$rules = array_merge($rules, $allRules[$act]);
if ($act == 'tanah' || $act == 'bangunan' || $act == 'apartemen-kantor' || $act == 'rap') {
$hasAssetDescriptionRules = true;
}
}
}
}
if ($hasAssetDescriptionRules) {
$rules = array_merge($rules, $this->getAssetDescriptionRules());
}
return $rules;
}
/**
* Get rules specific to tanah_bangunan action.
* Get rules specific to tanah action.
*/
private function getTanahBangunanRules(): array
public function getTanahRules(): array
{
return [
'action' => 'required',
'bentuk_tanah' => 'required',
'kontur_tanah' => 'required',
'posisi_kavling' => 'required',
'ketinggian_jalan' => 'required',
'kondisi_fisik_tanah' => 'required',
return [
'luas_tanah' => 'required',
'luas_tanah_sesuai' => 'nullable',
'luas_tanah_tidak_sesuai' => 'nullable',
'hadap_mata_angin' => 'required',
'hadap_mata_angin_sesuai' => 'nullable',
'hadap_mata_angin_tidak_sesuai' => 'nullable',
'bentuk_tanah' => 'required|array',
'bentuk_tanah_lainnya' => 'nullable',
'kontur_tanah' => 'required|array',
'ketinggian_jalan' => 'required|array',
'kontur_jalan' => 'required',
'kondisi_bangunan' => 'required',
'sifat_bangunan' => 'required',
'sarana_pelengkap' => 'required',
'luas_tanah_bagunan' => 'required',
'posisi_kavling' => 'required|array',
'posisi_kavling_lainnya' => 'nullable',
'tusuk_sate' => 'required',
'name.*' => 'required|string',
'kategori.*' => 'required|string',
'lockland' => 'required',
'jenis_bangunan' => 'required',
'kondisi_bangunan' => 'required',
'kondisi_fisik_tanah' => 'required|array',
'ketinggian_lebih_tinggi' => 'nullable',
'ketinggian_lebih_rendah' => 'nullable',
];
}
/**
* Get rules specific to unit action.
* Get rules specific to Bangunan action.
*/
private function getBangunanRules(): array
{
return [
'action' => 'required',
'luas_tanah_bangunan_sesuai' => 'nullable',
'luas_tanah_bagunan' => 'required',
'luas_tanah_bangunan_tidak_sesuai' => 'nullable',
'jenis_bangunan' => 'required|array',
'kondisi_bangunan' => 'required|array',
'sifat_bangunan' => 'required|array',
'sifat_bangunan_input' => 'nullable|array',
'nama_bangunan.*' => 'required|string|max:255',
'spek_kategori_bangunan.*' => 'nullable|string',
'spek_bangunan.*.*.lainnya' => 'nullable|string',
'sarana_pelengkap' => 'required',
'sarana_pelengkap_input' => 'nullable|array',
];
}
/**
* Get rules specific to unit action.
*/
private function getUnitRules(): array
{
return [
return [
'action' => 'required',
'jenis_unit' => 'required',
'kondisi_unit' => 'required',
'posisi_unit' => 'required',
'lantai' => 'required',
'view' => 'required',
'bentuk_unit' => 'required',
'luas_unit' => 'required',
'luas_unit_sesuai' => 'nullable',
'luas_unit_tidak_sesuai' => 'nullable',
'kondisi_unit' => 'required|array',
'posisi_unit' => 'required|array',
'lantai' => 'required|array',
'view' => 'required|array',
'bentuk_unit' => 'required|array',
];
}
/**
* Get rules specific to Linkungan action.
*/
private function getLinkunganRules(): array
{
return [
'action' => 'required',
'jarak_jalan_utama' => 'nullable',
'jalan_linkungan' => 'nullable',
'jarak_cbd_point' => 'nullable',
'nama_cbd_point' => 'nullable',
'lebar_perkerasan_jalan' => 'nullable',
'perkerasan_jalan' => 'nullable|array',
'perkerasan_jalan_lainnya' => 'nullable',
'lalu_lintas' => 'nullable',
'gol_mas_sekitar' => 'nullable',
'tingkat_keramaian' => 'nullable',
'terletak_diarea' => 'nullable',
'terletak_diarea_lainnya' => 'nullable',
'disekitar_lokasi' => 'required',
'kondisi_bagunan_disekitar_lokasi' => 'nullable',
'sifat_bagunan_disekitar_lokasi' => 'nullable',
'dekat_makam' => 'nullable',
'jarak_makam' => 'nullable',
'nama_makam' => 'nullable',
'dekat_tps' => 'nullable',
'jarak_tps' => 'nullable',
'nama_tpu' => 'nullable',
'dekat_lainnya' => 'nullable',
'merupakan_daerah' => 'nullable',
'fasilitas_dekat_object' => 'nullable|array',
'fasilitas_dekat_object_input' => 'nullable|array',
];
}
private function getKapalRules(): array
{
return [
'action' => 'required',
'nama_wakil_debitur' => 'nullable',
'hub_calon_debitur' => 'required',
'dermaga' => 'nullable',
'nama_jalan' => 'required',
'perumahan_gang' => 'required',
'blok_nomor' => 'required',
'village_code' => 'nullable|string',
'district_code' => 'nullable|string',
'city_code' => 'nullable|string',
'province_code' => 'nullable|string',
'jenis_kapal' => 'required',
'jenis_kapal_lainnya' => 'nullable',
'size' => 'required',
'kondisi' => 'required',
'klasifikasi' => 'required',
'nama_kapal' => 'required',
'pemilik_kapal' => 'required',
'bendera' => 'required',
'nomor_selar' => 'required',
'kapal' => 'required',
'galangan_kapal' => 'required',
'kapal_shipyard' => 'required',
'tahun_pembuatan' => 'required',
'tahun_launcing' => 'required',
'dwt' => 'required',
'lwt' => 'required',
'gross_tonnage' => 'required',
'net_tonnage' => 'required',
'tenaga_mesin' => 'required',
'loa' => 'required',
'lbp' => 'required',
'beam' => 'required',
'depth' => 'required',
'draft' => 'required',
'lambung_kapal' => 'required',
'dek' => 'required',
'struktur_rangka' => 'required',
'palka' => 'required',
'pondasi_mesin' => 'required',
'area_mesin' => 'required',
'cat_dan_korosi' => 'required',
'sistem_pengelasan' => 'required',
'deskripsi_struktur' => 'required',
'sekoci' => 'required',
'jaket_pelampung' => 'required',
'alat_pemadaman' => 'required',
'rambu_darurat' => 'required',
'sistem_alarm' => 'required',
'sistem_pencegah' => 'required',
'kebakaran' => 'required',
'lampu_darurat' => 'required',
'deskripsi_peralatan' => 'required',
'gps' => 'required',
'radar' => 'required',
'radio_komunikasi' => 'required',
'lampu_navigasi' => 'required',
'sistem_kendali_otomatis' => 'required',
'kompas' => 'required',
'deskripsi_navigasi' => 'required',
'mesin_utama' => 'required',
'mesin_bantu' => 'required',
'pompa_pendingin' => 'required',
'sistem_pelumasan' => 'required',
'propeller' => 'required',
'sistem_kelistrikan' => 'required',
'deskripsi_mesin_penggerak' => 'required',
'lampu_navigasi' => 'required',
'sistem_penerangan' => 'required',
'sistem_panel_distribusi' => 'required',
'kabel_perangkat' => 'required',
'deskripsi_kelistrikan' => 'required',
'kebersihan_dek_luar' => 'nullable',
'tangki_limbah' => 'nullable',
'sistem_pengelolaan_limbah' => 'nullable',
'pengelolaan_air_ballast' => 'nullable',
'deskripsi_kebersihan' => 'required',
'fakta_positif.*' => 'nullable',
'fakta_negatif.*' => 'nullable',
'analisa_makro.*' => 'nullable',
'kesimpulan.*' => 'nullable',
'catatan.*' => 'nullable',
];
}
public function getKendaraanRules(): array
{
return [
'action' => 'required',
'tanggal_survey' => 'required',
'nama_wakil' => 'required',
'hub_calon_debitur' => 'required',
'nama_jalan' => 'required',
'perumahan_gang' => 'required',
'blok_nomor' => 'required',
'village_code' => 'nullable|string',
'district_code' => 'nullable|string',
'city_code' => 'nullable|string',
'province_code' => 'nullable|string',
'masa_stnk' => 'required',
'masa_pajak' => 'required',
'kendaraan.*' => 'required',
'kendaraan_input.*' => 'nullable',
'kondisi' => 'required',
'nomor_polisi' => 'required',
'nomor_polis_tidak_sesuai' => 'nullable',
'merek' => 'required',
'merek_tidak_sesuai' => 'nullable',
'warna' => 'required',
'warna_tidak_sesuai' => 'nullable',
'nomor_rangka' => 'required',
'nomor_rangka_tidak_sesuai' => 'nullable',
'nomor_mesin' => 'required',
'nomor_mesin_tidak_sesuai' => 'nullable',
'posisi_kilometer' => 'required',
'transmisi' => 'required',
'transmisi_input' => 'nullable',
'mesin_panel_instrument.*' => 'required',
'mesin_panel_instrument_input.*' => 'nullable',
'fungsi_mesin_panel_instrument.*' => 'required',
'fungsi_mesin_panel_instrument_input.*' => 'nullable',
'interior.*' => 'required',
'interior_input.*' => 'nullable',
'jumlah_pintu.*' => 'required',
'jumlah_pintu_input.*' => 'nullable',
'rangka_karoseri.*' => 'required',
'rangka_karoseri_input.*' => 'nullable',
'ban.*' => 'required',
'ban_input.*' => 'nullable',
'velg.*' => 'required',
'velg_input.*' => 'nullable',
'bamper_depan.*' => 'required',
'bamper_depan_input.*' => 'nullable',
'bamper_belakang.*' => 'required',
'bamper_belakang_input.*' => 'nullable',
'lampu_depan.*' => 'required',
'lampu_depan_input.*' => 'nullable',
'lampu_belakang.*' => 'required',
'lampu_belakang_input.*' => 'nullable',
'kaca_kendaraan.*' => 'required',
'kaca_kendaraan_input.*' => 'nullable',
'air_conditioner.*' => 'required',
'air_conditioner_input.*' => 'nullable',
'tape_radio_cd.*' => 'required',
'tape_radio_cd_input.*' => 'nullable',
'sensor_parkir.*' => 'required',
'sensor_parkir_input.*' => 'nullable',
'sensor_camera_recorder.*' => 'required',
'sensor_camera_recorder_input.*' => 'nullable',
'lcd.*' => 'required',
'lcd_input.*' => 'nullable',
'sabuk_keselamatan.*' => 'required',
'sabuk_keselamatan_input.*' => 'nullable',
'airbag.*' => 'required',
'airbag_input.*' => 'nullable',
'asuransi.*' => 'required',
'asuransi_input.*' => 'nullable',
'perusahaan_asuransi' => 'required',
'tahun_berakhir' => 'required',
'fakta_positif.*' => 'nullable',
'fakta_negatif.*' => 'nullable',
'analisa_makro.*' => 'nullable',
'kesimpulan.*' => 'nullable',
'catatan.*' => 'nullable',
];
}
public function getMesinRules(): array
{
return [
'action' => 'required',
'nama_wakil' => 'required',
'nama_jalan' => 'required',
'perumahan_gang' => 'required',
'blok' => 'required',
'desa_kelurahan' => 'required',
'kecamatan' => 'required',
'kota_madya' => 'required',
'provinsi' => 'required',
'hub_calon_debitur' => 'required',
'tipe_model' => 'required',
'merek' => 'required',
'tahun_pembuatan' => 'required',
'negara_pembuat' => 'required',
'kondisi_mesin' => 'required',
'faktor_positif' => 'nullable',
'faktor_negatif' => 'nullable',
'kesimpulan' => 'nullable',
'catatan' => 'nullable',
];
}
public function getAlatBeratRules(): array
{
return [
'action' => 'required',
'nama_wakil' => 'required|string',
'hub_calon_debitur' => 'required|string',
'nama_jalan' => 'required',
'perumahan_gang' => 'required',
'blok_nomor' => 'required',
'village_code' => 'nullable|string',
'district_code' => 'nullable|string',
'city_code' => 'nullable|string',
'province_code' => 'nullable|string',
'jenis_model' => 'required',
'nomor_lambung' => 'required',
'model_unit' => 'required',
'tahun_pembuatan' => 'required',
'merk' => 'required',
'negara_pembuat' => 'required',
'tahun_pembelian' => 'required',
'nomor_faktur' => 'nullable',
'nomor_kontrak' => 'nullable',
'nama_pemilik' => 'nullable',
'alamat_pemilik' => 'nullable',
'nomor_asuransi' => 'nullable',
'nomor_rangka' => 'nullable',
'nomor_mesin' => 'nullable',
'hour_mesters' => 'nullable',
'overhaul_mesin' => 'nullable',
'mesin_panel.*' => 'nullable',
'mesin_panel_input.*' => 'nullable',
'fungsi_panel.*' => 'nullable',
'fungsi_panel_input.*' => 'nullable',
'interior.*' => 'nullable',
'interior_input.*' => 'nullable',
'rangka_Karoseri.*' => 'nullable',
'rangka_Karoseri_input.*' => 'nullable',
'ban.*' => 'nullable',
'ban_innput.*' => 'nullable',
'velg.*' => 'nullable',
'velg_input.*' => 'nullable',
'air_conditioner.*' => 'nullable',
'air_conditioner_input.*' => 'nullable',
'aksesoris.*' => 'nullable',
'aksesoris_input.*' => 'nullable',
'lcd.*' => 'nullable',
'lcd_innput.*' => 'nullable',
'perlengkapan.*' => 'nullable',
'perlengkapan_input.*' => 'nullable',
'asuransi.*' => 'nullable',
'asuransi_input.*' => 'nullable',
'perusahaan_asuransi' => 'nullable',
'tahun_berakhir.*' => 'nullable',
'sensor_kamera.*' => 'nullable',
'lcd.*' => 'nullable',
'sabuk_keselamatan.*' => 'nullable',
'air_bag.*' => 'nullable',
'asuransi.*' => 'nullable',
'perusahan_asuransi' => 'nullable',
'tahun_berakhir' => 'nullable',
'fakta_positif' => 'nullable|array',
'fakta_negatif' => 'nullable|array',
'kesimpulan' => 'nullable',
'catatan' => 'nullable|array',
];
}
private function getPesawatRules(): array
{
return [
'action' => 'required',
'nama_wakil' => 'required|string',
'hub_calon_debitur' => 'required|string',
'nama_jalan' => 'required',
'perumahan_gang' => 'required',
'blok_nomor' => 'required',
'village_code' => 'nullable|string',
'district_code' => 'nullable|string',
'city_code' => 'nullable|string',
'province_code' => 'nullable|string',
'jenis_pesawat' => 'required',
'jenis_pesawat_lainnya' => 'nullable',
'size' => 'required',
'kondisi' => 'required',
'nama_pesawat' => 'required',
'model' => 'required',
'nomor_registrasi' => 'required',
'tahun_pembuatan' => 'required',
'certificate_of_airworthines' => 'required',
'certificate_of_registration' => 'required',
'total_service_hours' => 'required',
'total_service_cycles' => 'required',
'last_a_check' => 'required',
'next_a_check' => 'required',
'last_b_check' => 'required',
'next_b_check' => 'required',
'last_c_check' => 'required',
'next_c_check' => 'required',
'next_d_check' => 'required',
'last_d_check' => 'required',
'deskripsi_maintenence' => 'nullable',
'instrument_landing_system' => 'required',
'traffic_collision_avoidance_system' => 'required',
'windshear' => 'required',
'electronic_flight' => 'required',
'winglets' => 'required',
'deskripsi_konfigurasi' => 'required',
'maksimal_penumpang' => 'required',
'jumlah_kursi' => 'required',
'kursi_pramugari_pramugara' => 'required',
'kartu_fitur_keselamatan' => 'required',
'sabuk_pengaman' => 'required',
'lampu_kabin' => 'required',
'lampu_pintu_keluar' => 'required',
'intercom_kabin' => 'required',
'deskripsi_kabin' => 'required',
'badan_pesawat' => 'nullable',
'sayap_pesawat' => 'required',
'ekor_pesawat' => 'required',
'landing_gear' => 'required',
'sabuk_pengaman' => 'required',
'sistem_pengelasan' => 'required',
'deskripsi_struktur' => 'required',
'gps' => 'required',
'radar' => 'required',
'radio_komunikasi' => 'required',
'lampu_navigasi' => 'required',
'sistem_autopilot' => 'required',
'deskripsi_navigasi' => 'required',
'tangki_bahan_bakar' => 'required',
'saluran_pipa_bahan_bakar' => 'required',
'pompa_bahan_bakar' => 'required',
'sistem_hidrolik_utama' => 'required',
'sistem_pendigin_hidrolik' => 'required',
'deskripsi_hidrolik' => 'required',
'mesin_utama' => 'required',
'sistem_pendorong' => 'required',
'sistem_pendigin_mesin' => 'required',
'sistem_pelumasan' => 'required',
'filter_dan_perangkat_pendukung' => 'required',
'deskripsi_kondisi_mesin' => 'required',
'jaket_pelampung' => 'required',
'pintu_darurat' => 'required',
'alat_pemadaman_kebakaran' => 'required',
'sistem_alaram_darurat' => 'required',
'sekoci' => 'required',
'masker_oxigen' => 'required',
'sabuk_pengaman' => 'required',
'deskripsi_fungsi_keselamatan' => 'required',
'sistem_ventilasi_ac' => 'required',
'sistem_penerangan_kabin' => 'required',
'panel_informasi_penumpang' => 'required',
'sistem_hiburan_kabin' => 'required',
'deskripsi_Interior' => 'required',
'fakta_positif' => 'nullable|array',
'fakta_negatif' => 'nullable|array',
'kesimpulan' => 'nullable',
'catatan' => 'nullable|array',
];
}
private function getAssetDescriptionRules(): array
{
return [
'permohonan_id' => 'required',
'dokument_id' => 'required',
'type' => 'required',
'nomor_registrasi' => 'required',
'debitur_perwakilan' => 'required|array',
'jenis_asset_name' => 'nullable|',
'jenis_asset' => 'required',
'jenis_asset_tidak_sesuai' => 'nullable|string',
'alamat_sesuai' => 'required',
'alamat_tidak_sesuai' => 'nullable|string',
'pihak_bank' => 'nullable|string',
'nomor_nib' => 'nullable|string',
'hub_cadeb' => 'nullable|string',
'hub_cadeb_sesuai' => 'nullable|string',
'hub_cadeb_tidak_sesuai' => 'nullable|string',
'hub_cadeb_penghuni' => 'nullable',
'hub_cadeb_penghuni_sesuai' => 'nullable|string',
'hub_penghuni_tidak_sesuai' => 'nullable|string',
'address' => 'nullable|string',
'village_code' => 'nullable|string',
'district_code' => 'nullable|string',
'city_code' => 'nullable|string',
'province_code' => 'nullable|string',
'kordinat_lng' => 'nullable|string',
'kordinat_lat' => 'nullable|string',
];
}
/**
* Get common rules that apply to all actions.
*/
private function getCommonRules(): array
{
return [
'fakta_positif' => 'nullable|array',
'fakta_negatif' => 'nullable|array',
'rute_menuju' => 'nullable',
'batas_batas' => 'required|array',
'batas_batas_input' => 'nullable|array',
'kondisi_lingkungan' => 'nullable|array',
'kondisi_lain_bangunan' => 'nullable|array',
'informasi_dokument' => 'nullable|array',
'peruntukan' => 'nullable',
'kdb' => 'nullable',
'kdh' => 'nullable',
'gsb' => 'nullable',
'max_lantai' => 'nullable',
'klb' => 'nullable',
'gss' => 'nullable',
'pelebaran_jalan' => 'nullable',
'nama_petugas' => 'nullable',
'lat' => 'nullable|numeric',
'lng' => 'nullable|numeric',
'foto_gistaru' => 'nullable',
'foto_bhumi' => 'nullable',
'foto_argis_region' => 'nullable',
'foto_tempat' => 'nullable',
'upload_gs' => 'nullable',
'foto_sentuh_tanahku' => 'nullable',
'keterangan' => 'nullable|array',
];
}
private function getRapRules()
{
return [
'perizinan' => 'nullable|array',
'perizinan.*' => 'nullable|string',
'perizinan_file' => 'nullable|array',
'perizinan_file.*' => 'nullable|file|mimes:pdf,docx',
'brosur_price_list' => 'nullable|array',
'brosur_price_list.*' => 'nullable|string',
'brosur_price_list_file' => 'nullable|array',
'brosur_price_list_file.*' => 'nullable|file|mimes:pdf,docx',
'pengalaman_developer' => 'nullable',
'developer_anggota' => 'nullable',
'lainnya_developer.*' => 'nullable',
'kapan_mulai_dibangun' => 'nullable',
'kondisi_perumahan' => 'nullable',
'progres_pembangunan' => 'nullable',
'kontraktor' => 'nullable',
'lingkungan_sekitar' => 'nullable',
'komplek_disekitar' => 'nullable',
'pusat_keramaian' => 'nullable',
'transportasi_umum' => 'nullable',
'lainnya_kondisi.*' => 'nullable',
// Validasi untuk partisi yang diperbarui
'partisi' => 'nullable|array',
'partisi.*' => 'nullable|array',
'partisi.*.nama' => 'nullable|string',
'partisi.*.value' => 'nullable|string|max:255',
'jumlah_unit.*' => 'nullable',
'batas_batas_perumahan' => 'nullable',
'fasus_fasum.*' => 'nullable',
'progres_penjualan.*' => 'nullable',
'harga_unit.*' => 'nullable',
'target_market.*' => 'nullable',
'kerjasama_dengan_bank' => 'nullable',
'rute_menuju_lokasi' => 'nullable',
'peruntukan' => 'nullable',
'kdb' => 'nullable',
'kdh' => 'nullable',
'gsb' => 'nullable',
'max_lantai' => 'nullable',
'klb' => 'nullable',
'gss' => 'nullable',
'pelebaran_jalan' => 'nullable',
'nama_petugas' => 'nullable',
'lat' => 'nullable|numeric',
'lng' => 'nullable|numeric',
'foto_gistaru' => 'nullable',
'foto_bhumi' => 'nullable',
'foto_argis_region' => 'nullable',
'foto_tempat' => 'nullable',
'upload_gs' => 'nullable',
'foto_sentuh_tanahku' => 'nullable',
'keterangan' => 'nullable|array',
];
}
}

View File

@@ -19,6 +19,7 @@
'name' => 'required|max:255',
'slug' => 'required|max:255',
'jenis_legalitas_jaminan_id' => 'nullable',
'form_kategori' => 'required',
];
}
@@ -38,13 +39,14 @@
$this->merge([
'code' => IdGenerator::generate(
['table' => 'jenis_jaminan', 'length' => 5, 'prefix' => 'JJ', 'field' => 'code'],
)
),
]);
}
$this->merge([
'jenis_legalitas_jaminan_id' => json_encode($this->jenis_legalitas_jaminan_id),
'slug' => Str::slug($this->name),
'form_kategori' => json_encode($this->form_kategori),
'slug' => Str::slug($this->name),
]);
}
}

View File

@@ -0,0 +1,54 @@
<?php
namespace Modules\Lpj\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class JenisLampiranRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
$rules = [
'nama' => [
'required',
'string',
'max:255',
Rule::unique('jenis_lampiran')->where(function ($query) {
return $query->whereNull('deleted_at');
})->ignore($this->route('jenis_lampiran')),
],
'deskripsi' => 'nullable|string',
];
return $rules;
}
/**
* Get custom messages for validator errors.
*
* @return array
*/
public function messages()
{
return [
'nama.required' => 'Nama jenis lampiran harus diisi.',
'nama.max' => 'Nama jenis lampiran tidak boleh lebih dari 255 karakter.',
];
}
}

View File

@@ -20,6 +20,8 @@
'slug' => 'required|max:255',
'custom_field' => 'nullable|max:255',
'custom_field_type' => 'nullable|max:255',
'custom_fields' => 'nullable|array',
'custom_fields.*' => 'required|string|max:255',
];
}
@@ -46,5 +48,10 @@
'slug' => Str::slug($this->name),
]);
}
// Ensure custom_fields is always an array
if (!is_array($this->custom_fields)) {
$this->merge(['custom_fields' => []]);
}
}
}

View File

@@ -24,23 +24,34 @@ class KJPPRequest extends FormRequest
'nomor_telepon_kantor' => 'nullable|numeric|digits_between:8,15',
'email_kantor' => 'required|email',
'detail_email_kantor' => 'nullable',
'detail_email_kantor.email_kantor.*' => 'email',
'nama_pimpinan' => 'required|string|not_regex:/^\d+$/|max:255',
'detail_nama_pimpinan' => 'nullable',
'detail_nama_pimpinan.nama_pimpinan.*' => 'string|not_regex:/^\d+$/|max:255',
'nomor_hp_pimpinan' => 'required|numeric|digits_between:10,15',
'detail_nomor_hp_pimpinan' => 'nullable',
'detail_nomor_hp_pimpinan.nomor_hp_pimpinan.*' => 'numeric|digits_between:10,15',
'nama_pic_reviewer' => 'nullable|string|not_regex:/^\d+$/|max:255',
'detail_nama_pic_reviewer' => 'nullable',
'detail_nama_pic_reviewer.nama_pic_reviewer.*' => 'string|not_regex:/^\d+$/|max:255',
'nomor_hp_pic_reviewer' => 'nullable|numeric|digits_between:10,15',
'detail_nomor_hp_pic_reviewer' => 'nullable',
'detail_nomor_hp_pic_reviewer.nomor_hp_pic_reviewer.*' => 'numeric|digits_between:10,15',
'nama_pic_admin' => 'nullable|string|not_regex:/^\d+$/|max:255',
'detail_nama_pic_admin' => 'nullable',
'detail_nama_pic_admin.nama_pic_admin.*' => 'string|not_regex:/^\d+$/|max:255',
'nomor_hp_pic_admin' => 'nullable|numeric|digits_between:10,15',
'detail_nomor_hp_pic_admin' => 'nullable',
'detail_nomor_hp_pic_admin.nomor_hp_pic_admin.*' => 'numeric|digits_between:10,15',
'nama_pic_marketing' => 'nullable|string|not_regex:/^\d+$/|max:255',
'detail_nama_pic_marketing' => 'nullable',
'detail_nama_pic_marketing.nama_pic_marketing.*' => 'string|not_regex:/^\d+$/|max:255',
'nomor_hp_pic_marketing' => 'nullable|numeric|digits_between:10,15',
'detail_nomor_hp_pic_marketing' => 'nullable',
'detail_nomor_hp_pic_marketing.nomor_hp_pic_marketing.*' => 'numeric|digits_between:10,15',
'ijin_usaha_id' => 'required|array',
'ijin_usaha_id.*' => 'exists:ijin_usaha,code',
'jenis_aset_id' => 'required|array',
'jenis_aset_id' => 'nullable|array',
'jenis_aset_id.*' => 'exists:jenis_jaminan,code',
'attachment' => 'nullable|mimes:pdf|max:1024'
];
@@ -81,22 +92,34 @@ class KJPPRequest extends FormRequest
'nomor_telepon_kantor.digits_between' => 'Nomor Telepon Kantor minimum 8 digit dan maksimum 15 digit!',
'email_kantor.required' => 'Email Kantor Wajib diisi!',
'email_kantor.email' => 'Email Kantor tidak valid!',
'detail_email_kantor.email_kantor.*.email' => 'Email Kantor tidak valid!',
'nama_pimpinan.required' => 'Nama Pimpinan Wajib diisi!',
'nama_pimpinan.not_regex' => 'Nama Pimpinan harus berupa huruf!',
'detail_nama_pimpinan.nama_pimpinan.*.not_regex' => 'Nama Pimpinan harus berupa huruf!',
'nomor_hp_pimpinan.required' => 'Nomor HP Pimpinan Wajib diisi!',
'nomor_hp_pimpinan.numeric' => 'Nomor HP Pimpinan harus berupa angka!',
'nomor_hp_pimpinan.digits_between' => 'Nomor HP Pimpinan minimum 10 digit dan maksimum 15 digit!',
'detail_nomor_hp_pimpinan.nomor_hp_pimpinan.*.numeric' => 'Nomor HP Pimpinan harus berupa angka!',
'detail_nomor_hp_pimpinan.nomor_hp_pimpinan.*.digits_between' => 'Nomor HP Pimpinan minimum 10 digit dan maksimum 15 digit!',
'nama_pic_reviewer.not_regex' => 'Nama PIC Reviewer harus berupa huruf!',
'detail_nama_pic_reviewer.nama_pic_reviewer.*.not_regex' => 'Nama PIC Reviewer harus berupa huruf!',
'nomor_hp_pic_reviewer.numeric' => 'Nomor HP PIC Reviewer harus berupa angka!',
'nomor_hp_pic_reviewer.digits_between' => 'Nomor HP PIC Reviewer minimum 10 digit dan maksimum 15 digit!',
'detail_nomor_hp_pic_reviewer.nomor_hp_pic_reviewer.*.numeric' => 'Nomor HP PIC Reviewer harus berupa angka!',
'detail_nomor_hp_pic_reviewer.nomor_hp_pic_reviewer.*.digits_between' => 'Nomor HP PIC Reviewer minimum 10 digit dan maksimum 15 digit!',
'nama_pic_admin.not_regex' => 'Nama PIC Admin harus berupa huruf!',
'detail_nama_pic_admin.nama_pic_admin.*.not_regex' => 'Nama PIC Admin harus berupa huruf!',
'nomor_hp_pic_admin.numeric' => 'Nomor HP PIC Admin harus berupa angka!',
'nomor_hp_pic_admin.digits_between' => 'Nomor HP PIC Admin minimum 10 digit dan maksimum 15 digit!',
'detail_nomor_hp_pic_admin.nomor_hp_pic_admin.*.numeric' => 'Nomor HP PIC Admin harus berupa angka!',
'detail_nomor_hp_pic_admin.nomor_hp_pic_admin.*.digits_between' => 'Nomor HP PIC Admin minimum 10 digit dan maksimum 15 digit!',
'nama_pic_marketing.not_regex' => 'Nama PIC Marketing harus berupa huruf!',
'detail_nama_pic_marketing.nama_pic_marketing.*.not_regex' => 'Nama PIC Marketing harus berupa huruf!',
'nomor_hp_pic_marketing.numeric' => 'Nomor HP PIC Marketing harus berupa angka!',
'nomor_hp_pic_marketing.digits_between' => 'Nomor HP PIC Marketing minimum 10 digit dan maksimum 15 digit!',
'detail_nomor_hp_pic_marketing.nomor_hp_pic_marketing.*.numeric' => 'Nomor HP PIC Marketing harus berupa angka!',
'detail_nomor_hp_pic_marketing.nomor_hp_pic_marketing.*.digits_between' => 'Nomor HP PIC Marketing minimum 10 digit dan maksimum 15 digit!',
'ijin_usaha_id.required' => 'Ijin Usaha Wajib diisi!',
'jenis_aset_id.required' => 'Jenis Aset Wajib diisi!',
'attachment.mimes' => 'Attachment harus berformat pdf!',
'attachment.max' => 'Attachment berukuran maksimum 1 MB!',
];

View File

@@ -0,0 +1,41 @@
<?php
namespace Modules\Lpj\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class LaporanExternalRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*/
public function rules()
: array
{
return [
'permohonan_id' => 'required|exists:permohonan,id',
'nomor_laporan' => 'nullable|string|max:255',
'tgl_final_laporan' => 'nullable|date',
'nilai_pasar' => 'nullable|numeric',
'indikasi_nilai_likuidasi' => 'nullable|numeric',
'indikasi_nilai_pasar_tanah' => 'nullable|numeric',
'estimasi_harga_tanah' => 'nullable|numeric',
'estimasi_harga_bangunan' => 'nullable|numeric',
'indikasi_nilai_pasar_bangunan' => 'nullable|numeric',
'indikasi_nilai_pasar_sarana_pelengkap' => 'nullable|numeric',
'indikasi_nilai_pasar_mesin' => 'nullable|numeric',
'indikasi_nilai_pasar_kendaraan_alat_berat' => 'nullable|numeric',
'file_resume' => 'nullable|file|mimes:pdf|max:10240', // 10MB max
'file_laporan' => 'nullable|file|mimes:pdf|max:10240',
];
}
/**
* Determine if the user is authorized to make this request.
*/
public function authorize()
: bool
{
return true;
}
}

View File

@@ -14,6 +14,7 @@
{
$rules = [
'name' => 'required|max:255',
'biaya' => 'nullable|numeric|min:0',
];
if ($this->method() == 'PUT') {

View File

@@ -0,0 +1,167 @@
<?php
namespace Modules\Lpj\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
/**
* Form Request untuk validasi data NOC (Notice of Completion)
*/
class NocRequest extends FormRequest
{
/**
* Konstanta untuk jenis file yang diizinkan
*/
private const ALLOWED_FILE_TYPES = 'pdf,jpg,jpeg,png';
/**
* Konstanta untuk ukuran file maksimum (dalam KB)
*/
private const MAX_FILE_SIZE = 10240;
/**
* Menentukan apakah pengguna berwenang untuk melakukan request ini
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Mengumpulkan semua aturan validasi
*
* @return array
*/
public function rules()
{
return array_merge(
$this->getBasicInfoRules(),
$this->getPaymentRules(),
$this->getSettlementRules(),
$this->getAuthorizationRules(),
);
}
/**
* Aturan validasi untuk informasi dasar
*
* @return array
*/
private function getBasicInfoRules()
{
return [
'permohonan_id' => 'nullable|exists:permohonan,id',
'persetujuan_penawaran_id' => 'required|exists:persetujuan_penawaran,id',
'status' => 'nullable|boolean',
'created_by' => 'nullable|exists:users,id',
'updated_by' => 'nullable|exists:users,id',
];
}
/**
* Aturan validasi untuk data pembayaran
*
* @return array
*/
private function getPaymentRules()
{
$fileRule = 'nullable|file|mimes:' . self::ALLOWED_FILE_TYPES . '|max:' . self::MAX_FILE_SIZE;
return [
'total_harus_bayar' => 'nullable|numeric|min:0',
'nominal_bayar' => 'nullable|numeric|min:0',
'total_pembukuan' => 'nullable|numeric|min:0',
'bukti_ksl' => $fileRule,
'bukti_bayar' => $fileRule,
'status_bayar' => 'nullable|boolean',
'tanggal_pembayaran' => 'nullable|date',
'status_kurang_bayar' => 'nullable|boolean',
'status_lebih_bayar' => 'nullable|boolean',
'nominal_kurang_bayar' => 'nullable|numeric|min:0',
'nominal_lebih_bayar' => 'nullable|numeric|min:0',
'bukti_pengembalian' => 'nullable|file|mimes:pdf,jpg,jpeg,png|max:2048',
];
}
/**
* Aturan validasi untuk data penyelesaian
*
* @return array
*/
private function getSettlementRules()
{
$fileRule = 'nullable|file|mimes:' . self::ALLOWED_FILE_TYPES . '|max:' . self::MAX_FILE_SIZE;
return [
'nominal_penyelesaian' => 'nullable|numeric|min:0',
'status_penyelesaian' => 'nullable|boolean',
'tanggal_penyelesaian' => 'nullable|date',
'bukti_penyelesaian' => $fileRule,
'memo_penyelesaian' => $fileRule,
'catatan_noc' => 'nullable|string',
'nomor_tiket' => 'nullable|string',
'nomor_rekening_lebih_bayar' => 'nullable|string',
'bukti_ksl_lebih_bayar' => 'nullable|string',
'bukti_ksl_kurang_bayar' => 'nullable|string'
];
}
/**
* Aturan validasi untuk otorisasi
*
* @return array
*/
private function getAuthorizationRules()
{
return [
'authorized_status' => 'nullable|boolean',
'authorized_at' => 'nullable|date',
'authorized_by' => 'nullable|exists:users,id',
];
}
/**
* Pesan khusus untuk validasi
*
* @return array
*/
public function messages()
{
return [
'permohonan_id.exists' => 'ID Permohonan tidak valid',
'persetujuan_penawaran_id.required' => 'ID Persetujuan Penawaran harus diisi',
'persetujuan_penawaran_id.exists' => 'ID Persetujuan Penawaran tidak valid',
'nominal_bayar.numeric' => 'Nominal Bayar harus berupa angka',
'nominal_bayar.min' => 'Nominal Bayar minimal 0',
'bukti_ksl.file' => 'Bukti KSL harus berupa file',
'bukti_ksl.mimes' => 'Bukti KSL harus berformat pdf, jpg, jpeg, atau png',
'bukti_ksl.max' => 'Ukuran Bukti KSL maksimal 10MB',
'bukti_bayar.file' => 'Bukti Bayar harus berupa file',
'bukti_bayar.mimes' => 'Bukti Bayar harus berformat pdf, jpg, jpeg, atau png',
'bukti_bayar.max' => 'Ukuran Bukti Bayar maksimal 10MB',
'status.boolean' => 'Status harus berupa boolean',
'status_bayar.boolean' => 'Status Bayar harus berupa boolean',
'tanggal_pembayaran.date' => 'Format Tanggal Pembayaran tidak valid',
'nominal_penyelesaian.numeric' => 'Nominal Penyelesaian harus berupa angka',
'nominal_penyelesaian.min' => 'Nominal Penyelesaian minimal 0',
'status_penyelesaian.boolean' => 'Status Penyelesaian harus berupa boolean',
'tanggal_penyelesaian.date' => 'Format Tanggal Penyelesaian tidak valid',
'bukti_penyelesaian.file' => 'Bukti Penyelesaian harus berupa file',
'bukti_penyelesaian.mimes' => 'Bukti Penyelesaian harus berformat pdf, jpg, jpeg, atau png',
'bukti_penyelesaian.max' => 'Ukuran Bukti Penyelesaian maksimal 10MB',
'memo_penyelesaian.file' => 'Memo Penyelesaian harus berupa file',
'memo_penyelesaian.mimes' => 'Memo Penyelesaian harus berformat pdf, jpg, jpeg, atau png',
'memo_penyelesaian.max' => 'Ukuran Memo Penyelesaian maksimal 10MB',
'authorized_status.boolean' => 'Status Otorisasi harus berupa boolean',
'authorized_at.date' => 'Format Tanggal Otorisasi tidak valid',
'authorized_by.exists' => 'User Otorisasi tidak valid',
'status_kurang_bayar.boolean' => 'Status Kurang Bayar harus berupa boolean',
'status_lebih_bayar.boolean' => 'Status Lebih Bayar harus berupa boolean',
'nominal_kurang_bayar.numeric' => 'Nominal Kurang Bayar harus berupa angka',
'nominal_kurang_bayar.min' => 'Nominal Kurang Bayar minimal 0',
'nominal_lebih_bayar.numeric' => 'Nominal Lebih Bayar harus berupa angka',
];
}
}

View File

@@ -25,21 +25,18 @@ class PenilaianRequest extends FormRequest
];
}
return [
'jenis_penilaian_id' => 'required|max:255',
'teams_id' => 'required|max:255',
'tanggal_kunjungan' => 'required|max:255',
'status' => 'required|string',
'nomor_registrasi' => 'required|string',
'surveyor_id' => 'nullable|required_without_all:penilai_surveyor_id,surveyor_region_id,penilai_region_id,penilai_id',
'penilai_id' => 'nullable|required_without_all:penilai_surveyor_id,surveyor_region_id,penilai_region_id,surveyor_id',
'penilai_surveyor_id' => 'nullable',
'surveyor_region_id' => 'nullable|required_without_all:penilai_surveyor_id,penilai_region_id,penilai_id,surveyor_id',
'penilai_region_id' => 'nullable|required_without_all:penilai_surveyor_id,surveyor_region_id,penilai_id,surveyor_id',
'surveyor_penilai_region_id' => 'nullable',
'keterangan' => 'nullable',
];

View File

@@ -23,7 +23,7 @@
'status' => 'nullable|string',
'jenis_fasilitas_kredit_id' => 'required|exists:jenis_fasilitas_kredit,id',
'nilai_plafond_id' => 'required|exists:nilai_plafond,id',
'status_bayar' => 'required|string',
'status_bayar' => 'nullable|string',
'nilai_njop' => 'nullable|numeric'
];
@@ -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

@@ -0,0 +1,67 @@
<?php
namespace Modules\Lpj\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class PersetujuanPenawaranRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'permohonan_id' => 'nullable|exists:permohonan,id',
'penawaran_id' => 'nullable|exists:penawaran,id',
'nomor_proposal_penawaran' => 'nullable|string|max:255',
'nomor_tiket' => 'nullable|string|max:100',
'nominal_kurang_bayar' => 'nullable|string|max:100',
'bukti_ksl_kurang_bayar' => 'nullable|file|mimes:pdf,doc,docx|max:10240',
'tanggal_proposal_penawaran' => 'nullable|date',
'biaya_final' => 'nullable|numeric|min:0',
'sla_resume' => 'nullable|numeric|min:0',
'sla_final' => 'nullable|numeric|min:0',
'file_persetujuan_penawaran' => 'nullable|file|mimes:pdf,doc,docx|max:10240',
'surat_representasi' => 'nullable|file|mimes:pdf,doc,docx|max:10240',
'status' => 'nullable|boolean',
'authorized_status' => 'boolean',
'authorized_at' => 'nullable|date',
'authorized_by' => 'nullable|exists:users,id',
'catatan' => 'nullable|string',
];
}
public function messages()
{
return [
'penawaran_id.required' => 'Penawaran ID wajib diisi.',
'penawaran_id.exists' => 'Penawaran ID tidak valid.',
'nomor_proposal_penawaran.required' => 'Nomor proposal penawaran wajib diisi.',
'nomor_tiket.string' => 'Nomor tiket harus berupa teks.',
'nomor_tiket.max' => 'Nomor tiket tidak boleh lebih dari 100 karakter.',
'tanggal_proposal_penawaran.required' => 'Tanggal proposal penawaran wajib diisi.',
'tanggal_proposal_penawaran.date' => 'Tanggal proposal penawaran harus berupa tanggal yang valid.',
'biaya_final.required' => 'Biaya final wajib diisi.',
'biaya_final.numeric' => 'Biaya final harus berupa angka.',
'biaya_final.min' => 'Biaya final tidak boleh kurang dari 0.',
'sla_resume.required' => 'SLA Resume wajib diisi.',
'sla_final.required' => 'SLA Final wajib diisi.',
'file_persetujuan_penawaran.file' => 'File Persetujuan Penawaran harus berupa file.',
'file_persetujuan_penawaran.mimes' => 'File Persetujuan Penawaran harus berupa file PDF, DOC, atau DOCX.',
'file_persetujuan_penawaran.max' => 'Ukuran File Persetujuan Penawaran tidak boleh lebih dari 10MB.',
'surat_representasi.file' => 'Surat Representasi harus berupa file.',
'surat_representasi.mimes' => 'Surat Representasi harus berupa file PDF, DOC, atau DOCX.',
'surat_representasi.max' => 'Ukuran Surat Representasi tidak boleh lebih dari 10MB.',
'region_id.required' => 'Region ID wajib diisi.',
'region_id.exists' => 'Region ID tidak valid.',
'status.required' => 'Status wajib diisi.',
'status.boolean' => 'Status harus berupa nilai boolean.',
'authorized_status.boolean' => 'Status otorisasi harus berupa nilai boolean.',
'authorized_at.date' => 'Tanggal otorisasi harus berupa tanggal yang valid.',
'authorized_by.exists' => 'ID pengguna yang mengotorisasi tidak valid.',
];
}
}

View File

@@ -0,0 +1,85 @@
<?php
namespace Modules\Lpj\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ProsesPenawaranRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*/
public function rules(): array
{
$rules = [
'kjpp.*' => 'exists:kjpp,id',
'tujuan_penilaian_kjpp_id' => 'required',
'jenis_laporan_id' => 'required',
'start_date' => 'required',
'end_date' => 'required',
'catatan' => 'nullable'
];
// if ($this->method() == 'PUT') {
// $rules['code'] = 'required|max:50';
// } else {
// $rules['code'] = 'required|max:50|unique:penawaran,code';
// }
return $rules;
}
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
public function messages(): array
{
return [
'code.required' => 'Kode Penawaran Wajib diisi!',
'code.max' => 'Kode Penawaran maksimal 255 huruf!',
'code.unique' => 'Kode Penawaran tidak boleh sama!',
'tujuan_penilaian_kjpp_id.required' => 'Tujuan Penilaian KJPP Wajib diisi!',
'jenis_laporan_id.required' => 'Jenis Laporan Wajib diisi!',
'start_date.required' => 'Tanggal Awal Wajib diisi!',
'end_date.required' => 'Tanggal Akhir Wajib diisi!',
];
}
public function withValidator($validator)
{
$validator->after(function ($validator) {
$startDate = strtotime($this->input('start_date'));
$endDate = strtotime($this->input('end_date'));
$today = strtotime(date('Y-m-d'));
// Jika dalam keadaan tambah penawaran maka munculkan pesan ini
// if ($this->method() !== 'PUT') {
// if ($startDate < $today) {
// $validator->errors()->add('start_date', 'Tanggal Awal tidak boleh sebelum hari ini.');
// }
// }
if ($endDate < $startDate) {
$validator->errors()->add('end_date', 'Tanggal Akhir tidak boleh lebih awal dari Tanggal Awal.');
}
// Validasi minimal 3 pilihan pada nama_kjpp
$namaKjpp = $this->input('kjpp', []);
// jika nama KJPP itu kosong
if (empty($namaKjpp)) {
$validator->errors()->add('kjpp', 'Nama KJPP wajib diisi.');
}
// jika terisi kurang dari 3 item
elseif (is_array($namaKjpp) && count($namaKjpp) < 3) {
$validator->errors()->add('kjpp', 'Nama KJPP minimal 3 pilihan.');
}
});
}
}

View File

@@ -14,6 +14,8 @@ class RegionRequest extends FormRequest
$rules = [
'name' => 'required|string|max:255',
'status' => 'nullable|boolean',
'url' => 'nullable|string|max:255',
'name_url' => 'nullable|string|max:255',
'authorized_at' => 'nullable|datetime',
'authorized_status' => 'nullable|string|max:1',
'authorized_by' => 'nullable|exists:users,id',

View File

@@ -3,7 +3,6 @@
namespace Modules\Lpj\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class SurveyorRequest extends FormRequest
@@ -28,6 +27,19 @@ class SurveyorRequest extends FormRequest
'spek-bangunan' => 'spek_bangunan',
'lantai-unit' => 'lantai',
'view-unit' => 'view_unit',
'jenis-pesawat' => 'jenis_pesawat',
'model-alat-berat' => 'model_alat_berat',
'jenis-kapal' => 'jenis_kapal',
'jenis-kendaraan' => 'jenis_kendaraan',
'jenis-unit' => 'jenis_unit',
'terletak-area' => 'terletak_area',
'merupakan-daerah' => 'merupakan_daerah',
'posisi-unit' => 'posisi_unit',
'bentuk-unit' => 'bentuk_unit',
'fasilitas-objek' => 'fasilitas_objek',
'perkerasan-jalan' => 'perkerasan_jalan',
'foto-objek-jaminan' => 'foto_objek_jaminan',
'perizinan' => 'perizinan'
];
/**
@@ -74,6 +86,9 @@ class SurveyorRequest extends FormRequest
],
],
'foto-objek-jaminan' => [
'kategori' => 'required',
],
// Add more action specific rules here
default => [],
};

View File

@@ -13,7 +13,7 @@ class TenderPenawaranRequest extends FormRequest
{
$rules = [
'nama_kjpp_sebelumnya' => 'nullable',
'biaya_kjpp_sebelumnya' => 'nullable|numeric',
'biaya_kjpp_sebelumnya' => 'nullable',
'tanggal_penilaian_sebelumnya' => 'nullable',
'nomor_registrasi' => 'required',
'kjpp.*' => 'exists:kjpp,id',

341
app/Imports/BucokImport.php Normal file
View File

@@ -0,0 +1,341 @@
<?php
namespace Modules\Lpj\Imports;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\WithStartRow;
use Maatwebsite\Excel\Concerns\WithValidation;
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithChunkReading;
use Modules\Lpj\Models\Bucok;
use Carbon\Carbon;
use Exception;
/**
* Kelas untuk mengimpor data Excel ke tabel bucoks
* Menggunakan Laravel Excel dengan validasi dan batch processing
* Data dimulai dari baris ke-5 tanpa header
*/
class BucokImport implements ToCollection, WithStartRow, WithValidation, WithBatchInserts, WithChunkReading
{
private $importedCount = 0;
private $skippedCount = 0;
private $createdCount = 0;
private $updatedCount = 0;
private $errors = [];
/**
* Menentukan baris mulai membaca data (baris ke-5)
*
* @return int
*/
public function startRow(): int
{
return 5;
}
/**
* Memproses koleksi data dari Excel
*
* @param Collection $collection
* @return void
*/
public function collection(Collection $collection)
{
DB::beginTransaction();
try {
foreach ($collection as $rowIndex => $row) {
// Log setiap baris yang diproses
Log::info('Processing Bucok import row', [
'row_number' => $rowIndex + 5, // +5 karena mulai dari baris 5
'row_data' => $row->toArray()
]);
// Konversi row ke array dengan indeks numerik
$rowArray = $row->toArray();
// Skip baris kosong
if (empty(array_filter($rowArray))) {
continue;
}
// Validasi data baris
$mappedData = $this->mapRowToBucok($rowArray, $rowIndex + 5);
// Update atau create berdasarkan nomor_tiket
if (!empty($mappedData['nomor_tiket'])) {
// Update atau create berdasarkan nomor_tiket
$bucok = Bucok::updateOrCreate(
['nomor_tiket' => $mappedData['nomor_tiket']], // Kondisi pencarian
array_merge($mappedData, ['updated_by' => auth()->id()]) // Data yang akan diupdate/create
);
// Log dan tracking apakah data di-update atau di-create
if ($bucok->wasRecentlyCreated) {
$this->createdCount++;
Log::info('Bucok created successfully', [
'row_number' => $rowIndex + 5,
'nomor_tiket' => $mappedData['nomor_tiket'],
'action' => 'created'
]);
} else {
$this->updatedCount++;
Log::info('Bucok updated successfully', [
'row_number' => $rowIndex + 5,
'nomor_tiket' => $mappedData['nomor_tiket'],
'action' => 'updated'
]);
}
}
$this->importedCount++;
}
DB::commit();
// Log summary
Log::info('Bucok import completed', [
'imported' => $this->importedCount,
'skipped' => $this->skippedCount,
'total_errors' => count($this->errors)
]);
} catch (Exception $e) {
DB::rollback();
Log::error('Bucok import failed', ['error' => $e->getMessage()]);
throw $e;
}
}
/**
* Mapping data Excel berdasarkan indeks kolom ke struktur model Bucok
* Kolom dimulai dari indeks 0 (A=0, B=1, C=2, dst.)
*
* @param array $row
* @param int $rowNumber
* @return array
*/
private function mapRowToBucok(array $row, int $rowNumber): array
{
return [
'no' => $row[0] ?? null, // Kolom A
'tanggal' => !empty($row[1]) ? $this->parseDate($row[1]) : null, // Kolom B
'bulan' => $row[2] ?? null, // Kolom C
'tahun' => $row[3] ?? null, // Kolom D
'tanggal_penuh' => !empty($row[4]) ? $this->parseDate($row[4]) : null, // Kolom E
'nomor_categ' => $row[5] ?? null, // Kolom F
'coa_summary' => $row[6] ?? null, // Kolom G
'nomor_coa' => $row[7] ?? null, // Kolom H
'nama_coa' => $row[8] ?? null, // Kolom I
'nomor_tiket' => $row[9] ?? null, // Kolom J - Auto-generate jika kosong
'deskripsi' => $row[10] ?? null, // Kolom K
'nominal' => $this->parseNumeric($row[11] ?? 0), // Kolom L
'penyelesaian' => $row[12] ?? 'Belum Selesai', // Kolom M
'umur_aging' => $this->parseNumeric($row[13] ?? 0), // Kolom N
'cost_center' => $row[14] ?? null, // Kolom O
'nama_sub_direktorat' => $row[15] ?? null, // Kolom P
'nama_direktorat_cabang' => $row[16] ?? null, // Kolom Q
'tanggal_penyelesaian' => !empty($row[17]) ? $this->parseDate($row[17]) : null, // Kolom R
'nominal_penyelesaian' => $this->parseNumeric($row[18] ?? 0), // Kolom S
'nominal_berjalan' => $this->parseNumeric($row[19] ?? 0), // Kolom T
'amortisasi_berjalan' => $this->parseNumeric($row[20] ?? 0), // Kolom U
'sistem_berjalan' => $this->parseNumeric($row[21] ?? 0), // Kolom V
'lainnya_berjalan' => $this->parseNumeric($row[22] ?? 0), // Kolom W
'nominal_gantung' => $this->parseNumeric($row[23] ?? 0), // Kolom X
'aset_gantung' => $this->parseNumeric($row[24] ?? 0), // Kolom Y
'keterangan_gantung' => $row[25] ?? null, // Kolom Z
'lainnya_satu' => $row[26] ?? null, // Kolom AA
'lainnya_dua' => $row[27] ?? null, // Kolom AB
'created_by' => auth()->id(),
'updated_by' => auth()->id()
];
}
/**
* Parse tanggal dari berbagai format
*
* @param mixed $dateValue
* @return Carbon|null
*/
private function parseDate($dateValue)
{
if (empty($dateValue)) {
return null;
}
try {
// Jika berupa angka Excel date serial
if (is_numeric($dateValue)) {
return Carbon::createFromFormat('Y-m-d', \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($dateValue)->format('Y-m-d'));
}
// Jika berupa string tanggal
return Carbon::parse($dateValue);
} catch (Exception $e) {
Log::warning('Failed to parse date', ['value' => $dateValue, 'error' => $e->getMessage()]);
return null;
}
}
/**
* Parse nilai numerik dari berbagai format
*
* @param mixed $numericValue
* @return float
*/
private function parseNumeric($numericValue): float
{
if (empty($numericValue)) {
return 0;
}
// Hapus karakter non-numerik kecuali titik dan koma
$cleaned = preg_replace('/[^0-9.,\-]/', '', $numericValue);
// Ganti koma dengan titik untuk decimal
$cleaned = str_replace(',', '.', $cleaned);
return (float) $cleaned;
}
/**
* Validasi data yang sudah dimapping
*
* @param array $data
* @return \Illuminate\Validation\Validator
*/
private function validateMappedData(array $data)
{
return Validator::make($data, [
'no' => 'nullable|integer',
'tanggal' => 'nullable|date',
'bulan' => 'nullable|integer|between:1,12',
'tahun' => 'nullable|integer|min:2000|max:2099',
'tanggal_penuh' => 'nullable|date',
'nomor_categ' => 'nullable|string|max:50',
'coa_summary' => 'nullable|string|max:255',
'nomor_coa' => 'nullable|string|max:50',
'nama_coa' => 'nullable|string|max:255',
'nomor_tiket' => 'nullable|string|max:50',
'deskripsi' => 'nullable|string',
'nominal' => 'nullable|numeric|min:0',
'penyelesaian' => 'nullable|in:Selesai,Belum Selesai,Dalam Proses',
'umur_aging' => 'nullable|integer|min:0',
'cost_center' => 'nullable|string|max:100',
'nama_sub_direktorat' => 'nullable|string|max:255',
'nama_direktorat_cabang' => 'nullable|string|max:255',
'tanggal_penyelesaian' => 'nullable|date',
'nominal_penyelesaian' => 'nullable|numeric|min:0',
'nominal_berjalan' => 'nullable|numeric|min:0',
'amortisasi_berjalan' => 'nullable|numeric|min:0',
'sistem_berjalan' => 'nullable|numeric|min:0',
'lainnya_berjalan' => 'nullable|numeric|min:0',
'nominal_gantung' => 'nullable|numeric|min:0',
'aset_gantung' => 'nullable|numeric|min:0',
'keterangan_gantung' => 'nullable|string',
'lainnya_satu' => 'nullable|string',
'lainnya_dua' => 'nullable|string'
]);
}
/**
* Aturan validasi untuk seluruh file Excel (tidak digunakan karena tanpa header)
*
* @return array
*/
public function rules(): array
{
return [];
}
/**
* Ukuran batch untuk insert
*
* @return int
*/
public function batchSize(): int
{
return 100;
}
/**
* Ukuran chunk untuk membaca file
*
* @return int
*/
public function chunkSize(): int
{
return 100;
}
/**
* Mendapatkan jumlah data yang berhasil diimpor
*
* @return int
*/
public function getImportedCount(): int
{
return $this->importedCount;
}
/**
* Mendapatkan jumlah data yang berhasil dibuat
*
* @return int
*/
public function getCreatedCount(): int
{
return $this->createdCount;
}
/**
* Mendapatkan jumlah data yang berhasil diupdate
*
* @return int
*/
public function getUpdatedCount(): int
{
return $this->updatedCount;
}
/**
* Mendapatkan statistik lengkap import
*
* @return array
*/
public function getImportStatistics(): array
{
return [
'total_processed' => $this->importedCount,
'created' => $this->createdCount,
'updated' => $this->updatedCount,
'skipped' => $this->skippedCount,
'errors' => count($this->errors)
];
}
/**
* Mendapatkan jumlah data yang dilewati
*
* @return int
*/
public function getSkippedCount(): int
{
return $this->skippedCount;
}
/**
* Mendapatkan daftar error yang terjadi
*
* @return array
*/
public function getErrors(): array
{
return $this->errors;
}
}

415
app/Imports/SlikImport.php Normal file
View File

@@ -0,0 +1,415 @@
<?php
namespace Modules\Lpj\Imports;
use Modules\Lpj\Models\Slik;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\WithStartRow;
use Maatwebsite\Excel\Concerns\WithChunkReading;
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithCustomCsvSettings;
/**
* Class SlikImport
*
* Handle import data Excel untuk modul Slik
* Menggunakan Laravel Excel package untuk membaca file Excel
* dengan optimasi memory dan chunk processing
*
* @package Modules\Lpj\app\Imports
*/
class SlikImport implements ToCollection, WithStartRow, WithBatchInserts, WithChunkReading, WithCustomCsvSettings
{
/**
* Mulai membaca dari baris ke-5 (skip header)
*
* @return int
*/
public function startRow(): int
{
return 5;
}
/**
* Batch size untuk insert data dari konfigurasi
*
* @return int
*/
public function batchSize(): int
{
return config('import.slik.batch_size', 50);
}
/**
* Chunk size untuk membaca file dari konfigurasi
*
* @return int
*/
public function chunkSize(): int
{
return config('import.slik.chunk_size', 50);
}
/**
* Custom CSV settings untuk optimasi pembacaan file
*
* @return array
*/
public function getCsvSettings(): array
{
return [
'input_encoding' => 'UTF-8',
'delimiter' => ',',
'enclosure' => '"',
'escape_character' => '\\',
];
}
/**
* Process collection data dari Excel dengan optimasi memory
*
* @param Collection $collection
* @return void
*/
public function collection(Collection $collection)
{
// Set memory limit dari konfigurasi
$memoryLimit = config('import.slik.memory_limit', 1024);
$currentMemoryLimit = ini_get('memory_limit');
if ($currentMemoryLimit !== '-1' && $this->convertToBytes($currentMemoryLimit) < $memoryLimit * 1024 * 1024) {
ini_set('memory_limit', $memoryLimit . 'M');
}
// Set timeout handler
$timeout = config('import.slik.timeout', 1800);
set_time_limit($timeout);
// Force garbage collection sebelum memulai
if (config('import.slik.enable_gc', true)) {
gc_collect_cycles();
}
Log::info('SlikImport: Memulai import data', [
'total_rows' => $collection->count(),
'memory_usage' => memory_get_usage(true),
'memory_peak' => memory_get_peak_usage(true),
'memory_limit' => ini_get('memory_limit'),
'php_version' => PHP_VERSION,
'memory_limit_before' => $currentMemoryLimit,
'config' => [
'memory_limit' => $memoryLimit,
'chunk_size' => $this->chunkSize(),
'batch_size' => $this->batchSize()
]
]);
DB::beginTransaction();
try {
$processedRows = 0;
$skippedRows = 0;
$errorRows = 0;
$totalRows = $collection->count();
foreach ($collection as $index => $row) {
// Log progress setiap 25 baris untuk chunk lebih kecil
if ($index % 25 === 0) {
Log::info('SlikImport: Processing chunk', [
'current_row' => $index + 5,
'progress' => round(($index / max($totalRows, 1)) * 100, 2) . '%',
'processed' => $processedRows,
'skipped' => $skippedRows,
'errors' => $errorRows,
'memory_usage' => memory_get_usage(true),
'memory_peak' => memory_get_peak_usage(true),
'memory_diff' => memory_get_peak_usage(true) - memory_get_usage(true)
]);
}
// Skip baris kosong
if ($this->isEmptyRow($row)) {
$skippedRows++;
Log::debug('SlikImport: Skipping empty row', ['row_number' => $index + 5]);
continue;
}
// Validasi data
if (!$this->validateRow($row)) {
$errorRows++;
Log::warning('SlikImport: Invalid row data', [
'row_number' => $index + 5,
'data' => $row->toArray()
]);
continue;
}
try {
// Map data dari Excel ke model
$slikData = $this->mapRowToSlik($row);
// Update atau create berdasarkan no_rekening dan cif
$slik = Slik::updateOrCreate(
[
'no_rekening' => $slikData['no_rekening'],
'cif' => $slikData['cif']
],
$slikData
);
$processedRows++;
// Log detail untuk baris pertama sebagai sample
if ($index === 0) {
Log::info('SlikImport: Sample data processed', [
'slik_id' => $slik->id,
'no_rekening' => $slik->no_rekening,
'cif' => $slik->cif,
'was_recently_created' => $slik->wasRecentlyCreated
]);
}
// Force garbage collection setiap 25 baris untuk mengurangi memory
if (config('import.slik.enable_gc', true) && $index > 0 && $index % 25 === 0) {
gc_collect_cycles();
}
// Unset data yang sudah tidak digunakan untuk mengurangi memory
if ($index > 0 && $index % 25 === 0) {
unset($slikData, $slik);
}
// Reset collection internal untuk mengurangi memory
if ($index > 0 && $index % 100 === 0) {
$collection = collect($collection->slice($index + 1)->values());
}
} catch (\Exception $e) {
$errorRows++;
Log::error('SlikImport: Error processing row', [
'row_number' => $index + 5,
'error' => $e->getMessage(),
'data' => $row->toArray(),
'memory_usage' => memory_get_usage(true)
]);
}
}
DB::commit();
// Force garbage collection setelah selesai
if (config('import.slik.enable_gc', true)) {
gc_collect_cycles();
}
// Cleanup variables
unset($collection);
Log::info('SlikImport: Import berhasil diselesaikan', [
'total_rows' => $totalRows,
'processed_rows' => $processedRows,
'skipped_rows' => $skippedRows,
'error_rows' => $errorRows,
'final_memory_usage' => memory_get_usage(true),
'peak_memory_usage' => memory_get_peak_usage(true),
'memory_saved' => memory_get_peak_usage(true) - memory_get_usage(true),
'memory_efficiency' => ($processedRows > 0) ? round(memory_get_peak_usage(true) / $processedRows, 2) : 0
]);
} catch (\Exception $e) {
DB::rollBack();
// Force garbage collection jika error
if (config('import.slik.enable_gc', true)) {
gc_collect_cycles();
}
$errorType = 'general';
if (str_contains(strtolower($e->getMessage()), 'memory')) {
$errorType = 'memory';
} elseif (str_contains(strtolower($e->getMessage()), 'timeout') || str_contains(strtolower($e->getMessage()), 'maximum execution time')) {
$errorType = 'timeout';
}
Log::error('SlikImport: Error during import', [
'error' => $e->getMessage(),
'error_type' => $errorType,
'exception_type' => get_class($e),
'trace' => $e->getTraceAsString(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'memory_usage' => memory_get_usage(true),
'memory_peak' => memory_get_peak_usage(true),
'memory_limit' => ini_get('memory_limit'),
'timeout_limit' => ini_get('max_execution_time'),
'is_memory_error' => str_contains(strtolower($e->getMessage()), 'memory'),
'is_timeout_error' => str_contains(strtolower($e->getMessage()), 'timeout') || str_contains(strtolower($e->getMessage()), 'maximum execution time')
]);
throw $e;
}
}
/**
* Convert memory limit string ke bytes
*
* @param string $memoryLimit
* @return int
*/
private function convertToBytes(string $memoryLimit): int
{
$memoryLimit = trim($memoryLimit);
$lastChar = strtolower(substr($memoryLimit, -1));
$number = (int) substr($memoryLimit, 0, -1);
switch ($lastChar) {
case 'g':
return $number * 1024 * 1024 * 1024;
case 'm':
return $number * 1024 * 1024;
case 'k':
return $number * 1024;
default:
return (int) $memoryLimit;
}
}
/**
* Cek apakah baris kosong
*
* @param Collection $row
* @return bool
*/
private function isEmptyRow(Collection $row): bool
{
return $row->filter(function ($value) {
return !empty(trim($value));
})->isEmpty();
}
/**
* Validasi data baris
*
* @param Collection $row
* @return bool
*/
private function validateRow(Collection $row): bool
{
// Validasi minimal: sandi_bank, no_rekening, dan cif harus ada
return !empty(trim($row[0])) && // sandi_bank
!empty(trim($row[5])) && // no_rekening
!empty(trim($row[6])); // cif
}
/**
* Map data dari baris Excel ke array untuk model Slik
*
* @param Collection $row
* @return array
*/
private function mapRowToSlik(Collection $row): array
{
return [
'sandi_bank' => trim($row[0]) ?: null,
'tahun' => $this->parseInteger($row[1]),
'bulan' => $this->parseInteger($row[2]),
'flag_detail' => trim($row[3]) ?: null,
'kode_register_agunan' => trim($row[4]) ?: null,
'no_rekening' => trim($row[5]) ?: null,
'cif' => trim($row[6]) ?: null,
'kolektibilitas' => trim($row[7]) ?: null,
'fasilitas' => trim($row[8]) ?: null,
'jenis_segmen_fasilitas' => trim($row[9]) ?: null,
'status_agunan' => trim($row[10]) ?: null,
'jenis_agunan' => trim($row[11]) ?: null,
'peringkat_agunan' => trim($row[12]) ?: null,
'lembaga_pemeringkat' => trim($row[13]) ?: null,
'jenis_pengikatan' => trim($row[14]) ?: null,
'tanggal_pengikatan' => $this->parseDate($row[15]),
'nama_pemilik_agunan' => trim($row[16]) ?: null,
'bukti_kepemilikan' => trim($row[17]) ?: null,
'alamat_agunan' => trim($row[18]) ?: null,
'lokasi_agunan' => trim($row[19]) ?: null,
'nilai_agunan' => $this->parseDecimal($row[20]),
'nilai_agunan_menurut_ljk' => $this->parseDecimal($row[21]),
'tanggal_penilaian_ljk' => $this->parseDate($row[22]),
'nilai_agunan_penilai_independen' => $this->parseDecimal($row[23]),
'nama_penilai_independen' => trim($row[24]) ?: null,
'tanggal_penilaian_penilai_independen' => $this->parseDate($row[25]),
'jumlah_hari_tunggakan' => $this->parseInteger($row[26]),
'status_paripasu' => trim($row[27]) ?: null,
'prosentase_paripasu' => $this->parseDecimal($row[28]),
'status_kredit_join' => trim($row[29]) ?: null,
'diasuransikan' => trim($row[30]) ?: null,
'keterangan' => trim($row[31]) ?: null,
'kantor_cabang' => trim($row[32]) ?: null,
'operasi_data' => trim($row[33]) ?: null,
'kode_cabang' => trim($row[34]) ?: null,
'nama_debitur' => trim($row[35]) ?: null,
'nama_cabang' => trim($row[36]) ?: null,
'flag' => trim($row[37]) ?: null,
];
}
/**
* Parse integer value
*
* @param mixed $value
* @return int|null
*/
private function parseInteger($value): ?int
{
if (empty(trim($value))) {
return null;
}
return (int) $value;
}
/**
* Parse decimal value
*
* @param mixed $value
* @return float|null
*/
private function parseDecimal($value): ?float
{
if (empty(trim($value))) {
return null;
}
// Remove currency formatting
$cleaned = str_replace([',', '.'], ['', '.'], $value);
$cleaned = preg_replace('/[^0-9.]/', '', $cleaned);
return (float) $cleaned;
}
/**
* Parse date value
*
* @param mixed $value
* @return string|null
*/
private function parseDate($value): ?string
{
if (empty(trim($value))) {
return null;
}
try {
// Try to parse various date formats
$date = \Carbon\Carbon::parse($value);
return $date->format('Y-m-d');
} catch (\Exception $e) {
Log::warning('SlikImport: Invalid date format', [
'value' => $value,
'error' => $e->getMessage()
]);
return null;
}
}
}

View File

@@ -0,0 +1,156 @@
<?php
namespace Modules\Lpj\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Modules\Lpj\Models\Inspeksi;
/**
* Job untuk membersihkan data inspeksi yang tidak memiliki dokument_id
*
* Case: Jika ada data inspeksi yang masuk dengan permohonan_id yang sama
* tetapi memiliki dokument_id dan user created_by yang sama, maka
* data lama (tanpa dokument_id) akan di-soft delete
*/
class CleanupInspeksiDataJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $timeout = 300; // 5 menit
public $tries = 3;
public $maxExceptions = 3;
public $backoff = [60, 120, 300]; // Exponential backoff dalam detik
protected int $permohonanId;
protected int $createdBy;
protected ?int $dokumentId;
/**
* Create a new job instance.
*
* @param int $permohonanId
* @param int $createdBy
* @param int|null $dokumentId
*/
public function __construct(int $permohonanId, int $createdBy, ?int $dokumentId = null)
{
$this->permohonanId = $permohonanId;
$this->createdBy = $createdBy;
$this->dokumentId = $dokumentId;
}
/**
* Execute the job.
*
* @return void
* @throws \Exception
*/
public function handle(): void
{
Log::info('CleanupInspeksiDataJob: Memulai proses cleanup data inspeksi', [
'permohonan_id' => $this->permohonanId,
'created_by' => $this->createdBy,
'dokument_id' => $this->dokumentId
]);
DB::beginTransaction();
try {
// Cari data inspeksi yang memiliki dokument_id (data baru)
$newInspeksi = Inspeksi::where('permohonan_id', $this->permohonanId)
->where('created_by', $this->createdBy)
->whereNotNull('dokument_id')
->whereNull('deleted_at')
->first();
if (!$newInspeksi) {
Log::warning('CleanupInspeksiDataJob: Tidak ditemukan data inspeksi baru dengan dokument_id', [
'permohonan_id' => $this->permohonanId,
'created_by' => $this->createdBy
]);
DB::rollBack();
return;
}
Log::info('CleanupInspeksiDataJob: Data inspeksi baru ditemukan', [
'inspeksi_id' => $newInspeksi->id,
'dokument_id' => $newInspeksi->dokument_id
]);
// Cari data inspeksi lama yang tidak memiliki dokument_id
$oldInspeksiList = Inspeksi::where('permohonan_id', $this->permohonanId)
->where('created_by', $this->createdBy)
->whereNull('dokument_id')
->whereNull('deleted_at')
->where('id', '!=', $newInspeksi->id) // Jangan hapus data yang baru saja ditemukan
->get();
if ($oldInspeksiList->isEmpty()) {
Log::info('CleanupInspeksiDataJob: Tidak ditemukan data inspeksi lama tanpa dokument_id', [
'permohonan_id' => $this->permohonanId,
'created_by' => $this->createdBy
]);
DB::commit();
return;
}
$deletedCount = 0;
foreach ($oldInspeksiList as $oldInspeksi) {
// Soft delete data lama
$oldInspeksi->delete(); // Menggunakan soft delete karena model menggunakan SoftDeletes trait
Log::info('CleanupInspeksiDataJob: Data inspeksi lama berhasil di-soft delete', [
'old_inspeksi_id' => $oldInspeksi->id,
'permohonan_id' => $oldInspeksi->permohonan_id,
'created_by' => $oldInspeksi->created_by,
'deleted_at' => now()->toDateTimeString()
]);
$deletedCount++;
}
DB::commit();
Log::info('CleanupInspeksiDataJob: Proses cleanup selesai', [
'permohonan_id' => $this->permohonanId,
'created_by' => $this->createdBy,
'deleted_count' => $deletedCount,
'new_inspeksi_id' => $newInspeksi->id
]);
} catch (\Exception $e) {
DB::rollBack();
Log::error('CleanupInspeksiDataJob: Terjadi error saat proses cleanup', [
'permohonan_id' => $this->permohonanId,
'created_by' => $this->createdBy,
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
throw $e;
}
}
/**
* Handle a job failure.
*
* @param \Throwable $exception
* @return void
*/
public function failed(\Throwable $exception): void
{
Log::error('CleanupInspeksiDataJob: Job gagal dieksekusi', [
'permohonan_id' => $this->permohonanId,
'created_by' => $this->createdBy,
'error' => $exception->getMessage(),
'trace' => $exception->getTraceAsString()
]);
}
}

View File

@@ -0,0 +1,179 @@
<?php
namespace Modules\Lpj\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Modules\Lpj\Imports\SlikImport;
use Maatwebsite\Excel\Facades\Excel;
class ProcessSlikImport implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $timeout = 1800; // 30 menit untuk file besar
public $tries = 5; // Tambah retry untuk file sangat besar
public $maxExceptions = 5;
public $backoff = [60, 300, 900, 1800, 3600]; // Exponential backoff dalam detik
protected string $filePath;
protected int $userId;
protected string $importId;
/**
* Create a new job instance.
*
* @param string $filePath
* @param int $userId
* @param string $importId
*/
public function __construct(string $filePath, int $userId, string $importId)
{
$this->filePath = $filePath;
$this->userId = $userId;
$this->importId = $importId;
}
/**
* Execute the job.
*
* @return void
*/
public function handle(): void
{
Log::info('ProcessSlikImport: Memulai proses import via queue', [
'file_path' => $this->filePath,
'user_id' => $this->userId,
'import_id' => $this->importId,
'memory_limit' => ini_get('memory_limit'),
'max_execution_time' => ini_get('max_execution_time')
]);
try {
// Cek file size terlebih dahulu
$fileSize = filesize($this->filePath);
$maxFileSize = config('import.slik.max_file_size', 50) * 1024 * 1024; // Convert MB to bytes
if ($fileSize > $maxFileSize) {
throw new \Exception('File terlalu besar: ' . number_format($fileSize / 1024 / 1024, 2) . ' MB. Maksimum: ' . config('import.slik.max_file_size', 50) . ' MB');
}
// Set optimasi memory untuk queue processing
$memoryLimit = config('import.slik.memory_limit', 1024);
ini_set('memory_limit', $memoryLimit . 'M');
ini_set('max_execution_time', config('import.slik.timeout', 1800));
// Set timeout untuk XML Scanner
$xmlScannerTimeout = config('import.slik.xml_scanner.timeout', 1800);
$xmlScannerMemory = config('import.slik.xml_scanner.memory_limit', 1024);
// Enable garbage collection jika diizinkan
if (config('import.slik.enable_gc', true)) {
gc_enable();
}
// Update progress status
$this->updateProgress('processing', 0, 'Memproses file Excel...');
Log::info('SlikImport: Processing file', [
'file' => basename($this->filePath),
'file_size' => number_format(filesize($this->filePath) / 1024 / 1024, 2) . ' MB',
'memory_limit' => $memoryLimit . 'M',
'timeout' => config('import.slik.timeout', 1800),
'enable_gc' => config('import.slik.enable_gc', true),
'xml_scanner_timeout' => config('import.slik.xml_scanner.timeout', 1800),
'chunk_size' => config('import.slik.chunk_size', 50),
'batch_size' => config('import.slik.batch_size', 50),
]);
// Import file menggunakan SlikImport
$import = new SlikImport();
Excel::import($import, $this->filePath);
// Update progress selesai
$this->updateProgress('completed', 100, 'Import berhasil diselesaikan');
Log::info('ProcessSlikImport: Import berhasil diselesaikan', [
'import_id' => $this->importId,
'file_path' => $this->filePath,
'memory_usage' => memory_get_usage(true),
'memory_peak' => memory_get_peak_usage(true)
]);
// Hapus file temporary setelah selesai
if (config('import.general.cleanup_temp_files', true)) {
Storage::delete($this->filePath);
Log::info('ProcessSlikImport: File temporary dihapus', ['file_path' => $this->filePath]);
}
} catch (\Exception $e) {
// Update progress error
$this->updateProgress('failed', 0, 'Error: ' . $e->getMessage());
Log::error('ProcessSlikImport: Error saat proses import', [
'import_id' => $this->importId,
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'memory_usage' => memory_get_usage(true)
]);
throw $e;
}
}
/**
* Update progress import
*
* @param string $status
* @param int $percentage
* @param string $message
* @return void
*/
private function updateProgress(string $status, int $percentage, string $message): void
{
if (config('import.slik.progress.enabled', true)) {
$cacheKey = config('import.slik.progress.cache_key', 'slik_import_progress') . '_' . $this->importId;
$cacheTtl = config('import.slik.progress.cache_ttl', 3600);
$progressData = [
'status' => $status,
'percentage' => $percentage,
'message' => $message,
'timestamp' => now(),
'user_id' => $this->userId
];
cache()->put($cacheKey, $progressData, $cacheTtl);
}
}
/**
* Handle job failure
*
* @param \Throwable $exception
* @return void
*/
public function failed(\Throwable $exception): void
{
Log::error('ProcessSlikImport: Job failed', [
'import_id' => $this->importId,
'error' => $exception->getMessage(),
'trace' => $exception->getTraceAsString()
]);
// Update progress ke failed
$this->updateProgress('failed', 0, 'Import gagal: ' . $exception->getMessage());
// Cleanup file temporary
if (Storage::exists($this->filePath)) {
Storage::delete($this->filePath);
}
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace Modules\Lpj\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Modules\Lpj\Emails\SendJadwalKunjunganEmail;
use Illuminate\Support\Facades\Mail;
class SendJadwalKunjunganEmailJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $emailData;
/**
* Create a new job instance.
*/
public function __construct(array $emailData)
{
$this->emailData = $emailData;
}
/**
* Execute the job.
*/
public function handle(): void
{
Mail::to($this->emailData['email'])->send(new SendJadwalKunjunganEmail($this->emailData));
}
}

View File

@@ -0,0 +1,72 @@
<?php
namespace Modules\Lpj\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Facades\Mail;
use Modules\Lpj\Emails\SendPenawaranKJPPEmail;
class SendPenawaranKJPPTenderJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $kjpps;
protected $dp1; // Tidak perlu array [0] lagi
protected $penawaran;
protected $permohonan;
protected $villages;
protected $districts;
protected $cities;
protected $provinces;
protected $user;
/**
* Create a new job instance.
*/
public function __construct($kjpps, $dp1, $penawaran, $permohonan, $villages, $districts, $cities, $provinces, $user)
{
$this->kjpps = $kjpps;
$this->dp1 = $dp1; // Simpan keseluruhan array dp1, bukan dp1[0]
$this->penawaran = $penawaran;
$this->permohonan = $permohonan;
$this->villages = $villages;
$this->districts = $districts;
$this->cities = $cities;
$this->provinces = $provinces;
$this->user = $user;
}
/**
* Execute the job.
*/
public function handle(): void
{
$email = new SendPenawaranKJPPEmail(
$this->dp1,
$this->penawaran,
$this->permohonan,
$this->villages,
$this->districts,
$this->cities,
$this->provinces,
$this->user // Kirim user ke email sebagai cc dan bcc
);
$email->with([
'dp1' => $this->dp1, // Kirim seluruh array dp1 ke email
'penawaran' => $this->penawaran,
'permohonan' => $this->permohonan,
'villages' => $this->villages,
'districts' => $this->districts,
'cities' => $this->cities,
'provinces' => $this->provinces,
'user' => $this->user // Kirim user ke email sebagai cc dan bcc
]);
$send = Mail::to($this->kjpps)->send($email);
}
}

View File

@@ -0,0 +1,59 @@
<?php
namespace Modules\Lpj\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Facades\Mail;
use Modules\Lpj\Emails\SendPenawaranTenderEmail;
class SendPenawaranTenderJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $kjpps;
protected $penawaran;
protected $permohonan;
protected $villages;
protected $districts;
protected $cities;
protected $provinces;
protected $user; // Tidak perlu array [0] lagi
/**
* Create a new job instance.
*/
public function __construct($kjpps, $penawaran, $permohonan, $villages, $districts, $cities, $provinces,$user)
{
$this->kjpps = $kjpps;
$this->penawaran = $penawaran;
$this->permohonan = $permohonan;
$this->villages = $villages;
$this->districts = $districts;
$this->cities = $cities;
$this->provinces = $provinces;
$this->user = $user; // Simpan user yang dikirim email ke properti
}
/**
* Execute the job.
*/
public function handle(): void
{
$email = new SendPenawaranTenderEmail();
$email->with([
'penawaran' => $this->penawaran,
'permohonan' => $this->permohonan,
'villages' => $this->villages,
'districts' => $this->districts,
'cities' => $this->cities,
'provinces' => $this->provinces,
'user' => $this->user // Kirim user ke email ke properti sebagai additional data
]);
Mail::to($this->kjpps)->send($email);
}
}

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