diff --git a/app/Exports/KertasKerjaExport.php b/app/Exports/KertasKerjaExport.php index c931d47..57c61c6 100644 --- a/app/Exports/KertasKerjaExport.php +++ b/app/Exports/KertasKerjaExport.php @@ -3,72 +3,270 @@ namespace Modules\Lpj\Exports; use Maatwebsite\Excel\Concerns\FromCollection; -use Maatwebsite\Excel\Concerns\WithColumnFormatting; +// use Maatwebsite\Excel\Concerns\WithColumnFormatting; +use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; use Maatwebsite\Excel\Concerns\WithHeadings; -use Maatwebsite\Excel\Concerns\WithMapping; -use PhpOffice\PhpSpreadsheet\Style\NumberFormat; +use Maatwebsite\Excel\Concerns\WithStyles; +use Maatwebsite\Excel\Concerns\WithColumnWidths; +use Maatwebsite\Excel\Concerns\WithEvents; +use Maatwebsite\Excel\Events\AfterSheet; -class KertasKerjaExport implements WithColumnFormatting, WithHeadings, FromCollection, WithMapping +class KertasKerjaExport implements FromCollection, WithHeadings, WithStyles, WithColumnWidths, WithEvents { protected $data; - public function __construct($data) + protected $headerInfo; + + public function __construct($data, $headerInfo) { $this->data = $data; + $this->headerInfo = $headerInfo; } public function collection() { - return collect([ - [ - 'Pendekatan pasar', - 'Nama Pemilik Aset', - '', - ], - [ - 'Metode Perbandingan Data Pasar', - 'Nama Pemberi Tugas: ', - '', - '', - ], - [ - 'Tanggal Penilaian: ', - 'Lokasi: ', - '', - '', - ], - [ - 'No.', - 'Objek Penilaian', - 'Data Pembanding 1', - 'Data Pembanding 2', - 'Data Pembanding 3' - ], - ]); - } + $rows = []; - // Tambahkan method map() - public function map($row): array - { - return $row; + $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' + + ]; + + foreach ($fields as $key => $label) { + $rows[] = [ + $nomor++, + $label, + $this->data['objek'][$key] ?? '', + $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 []; - } - - public function columnFormats(): array { return [ - 'A' => NumberFormat::FORMAT_NUMBER, - 'C' => NumberFormat::FORMAT_NUMBER, - 'D' => NumberFormat::FORMAT_NUMBER, - 'F' => NumberFormat::FORMAT_NUMBER, - 'G' => NumberFormat::FORMAT_NUMBER, - 'P' => NumberFormat::FORMAT_DATE_DATETIME, - 'Q' => NumberFormat::FORMAT_DATE_DATETIME + ['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'] ?? '')], + ['Nama Debitur: ' . ($this->headerInfo['nama_debitur'] ?? '')], + [''], + ['A. INFORMASI UMUM'], + ['No.','Uraian', 'Objek Penilaian', 'Data Pembanding 1', 'Data Pembanding 2', 'Data Pembanding 3'] + + ]; } + 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); + } + ]; + } + 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 + ]; + } + } diff --git a/app/Http/Controllers/PenilaiController.php b/app/Http/Controllers/PenilaiController.php index 48b2635..11f5b8c 100644 --- a/app/Http/Controllers/PenilaiController.php +++ b/app/Http/Controllers/PenilaiController.php @@ -192,131 +192,19 @@ class PenilaiController extends Controller ]); } - public function kertas_kerja() + public function kertas_kerja($id, $jeniJaminan) { - $data = [ - [ - 'Pendekatan pasar', - 'Nama Pemilik Aset', - '', - ], - [ - 'Metode Perbandingan Data Pasar', - 'Nama Pemberi Tugas: ', - '', - '', - ], - [ - 'Tanggal Penilaian: ', - 'Lokasi: ', - '', - '', - ], - [ - 'No.', - 'Objek Penilaian', - 'Data Pembanding 1', - 'Data Pembanding 2', - 'Data Pembanding 3' - ],[ - '1', - 'Jenis Aset', - 'Pembanding 1', - 'Pembanding 1', - 'Pembanding 1' - ], - [ - '2', - 'Luas Tanah', - 'Pembanding 2', - 'Pembanding 2', - 'Pembanding 2' - ], - [ - '3', - 'Penawaran/Transaksi', - '', - 'Pembanding 3', - 'Pembanding 3' - ], - [ - '4', - 'Harga penawaran/Transaksi', - '', - 'Pembanding 3', - 'Pembanding 3' - ],[ - '5', - 'Nomor Telepon', - '', - 'Pembanding 3', - 'Pembanding 3' - ], - [ - '6', - 'Estimasi Harga Transaksi', - '', - 'Pembanding 3', - 'Pembanding 3' - ], - [ - '7', - 'Nama Nara sumber', - '', - 'Pembanding 3', - 'Pembanding 3' - ], - [ - '8', - 'Status Nara sumber', - '', - 'Pembanding 3', - 'Pembanding 3' - ], - [ - '9', - 'Waktu Penawaran/Transaksi', - '', - 'Pembanding 3', - 'Pembanding 3' - ], - [ - '10', - 'Titik GPS', - '', - 'Pembanding 3', - ], - [ - '11', - 'Alamat', - '', - 'Pembanding 3', - 'Pembanding 3' - ], - [ - '12', - 'Jarak Pembanding dengan Objek (m)', - '', - 'Pembanding 3', - 'Pembanding 3' - ], - [ - '13', - 'Estimasi Rangking Tanah', - '', - 'Pembanding 3', - 'Pembanding 3' - ], - [ - '14', - 'Estimasi Rangking Bangunan', - '', - 'Pembanding 3', - 'Pembanding 3' - ] + $data = Inspeksi::where('permohonan_id', $id)->where('jenis_jaminan_id', $jaminanId)->first(); + $headerInfo = [ + 'tanggal_penilaian' => '', + 'nama_pemilik' => '', + 'nama_pemberi_tugas' => '', + 'lokasi_lengkap' => '', + 'nama_debitur' => '' ]; - return Excel::download(new KertasKerjaExport($data), 'kertas-kerja.xlsx'); + + return Excel::download(new KertasKerjaExport($data, $headerInfo), 'kertas-kerja.xlsx'); } diff --git a/database/seeders/KJPPSeeder.php b/database/seeders/KJPPSeeder.php index c2d9207..a32e1a7 100644 --- a/database/seeders/KJPPSeeder.php +++ b/database/seeders/KJPPSeeder.php @@ -21,7 +21,7 @@ class KJPPSeeder extends Seeder public function run(): void { - $filePath = __DIR__ . '/LISTsatsa.xlsx'; + $filePath = __DIR__ . '/list-update-kjpp.xlsx'; // DB::unprepared(file_get_contents(__DIR__ . '/kjpp.sql')); if (!file_exists($filePath)) { @@ -33,31 +33,26 @@ class KJPPSeeder extends Seeder try { // Baca excel dan tampilkan raw data - $collection = Excel::toCollection(null, $filePath, null, function($reader) { - $reader->setActiveSheetIndex(1); - })->first(); - + $collection = Excel::toCollection(null, $filePath)->first(); // Debug: Tampilkan jumlah baris $this->command->info('Total baris: ' . $collection->count()); // Debug: Tampilkan 3 baris pertama (header) - $this->command->info('Header data:'); - foreach($collection->take(3) as $index => $row) { - $this->command->info("Baris $index: " . print_r($row->toArray(), true)); - } + // $this->command->info('Header data:'); + // foreach($collection->take(3) as $index => $row) { + // $this->command->info("Baris $index: " . print_r($row->toArray(), true)); + // } // Skip 3 baris header $data = $collection->skip(3); - // Debug: Tampilkan jumlah data setelah skip header - $this->command->info('Total data setelah skip header: ' . $data->count()); // Proses setiap baris foreach ($data as $index => $row) { $this->command->info("Memproses baris ke-$index:"); // Debug: Tampilkan data mentah - $this->command->info('Raw data: ' . print_r($row->toArray(), true)); + // $this->command->info('Raw data: ' . print_r($row->toArray(), true)); // Skip jika baris kosong if (empty($row[2])) { @@ -68,8 +63,20 @@ class KJPPSeeder extends Seeder $locationData = $this->checkKota($row[5]); - $jenisUsaha = $this->checkJenisUsaha($row[17]); - $jenisAsset = $this->checkJenisAsset($row[18]); + $jenisUsaha = $this->checkJenisUsaha($row[18]); + $jenisAsset = $this->checkJenisAsset($row[19]); + + $detail_email_kantor = $this->checkDanJadikanJson($row[8]); + $nama_pic_reviewer = $this->checkDanJadikanJson($row[11]); + $nomor_hp_pic_reviewer = $this->checkDanJadikanJson($row[12]); + $detail_nama_pic_admin = $this->checkDanJadikanJson($row[13]); + + $nomor_hp_pic_admin = $this->checkDanJadikanJson($row[14]); + $nama_pic_marketing = $this->checkDanJadikanJson($row[15]); + + + $nomor_hp_pic_marketing = $this->checkDanJadikanJson($row[16]); + try { $dataToInsert = [ @@ -81,33 +88,33 @@ class KJPPSeeder extends Seeder 'city_code' => $locationData['city'], 'district_code' => $locationData['district'], 'village_code' => $locationData['village'], - 'address' => $row[6], + 'address' => $row[7], 'postal_code' => $locationData['postal_code'], - 'nomor_telepon_kantor' => $row[7], - 'email_kantor' => $row[8], - 'detail_email_kantor' => json_encode($row[8]), + 'nomor_telepon_kantor' => $row[8], + 'email_kantor' => $detail_email_kantor, + 'detail_email_kantor' => $detail_email_kantor, 'nama_pimpinan' => $row[9], 'nomor_hp_pimpinan' => $row[10], - 'nama_pic_reviewer' => json_encode($row[11]), - 'detail_nama_pic_reviewer' => json_encode($row[11]), - 'nomor_hp_pic_reviewer' => json_encode($row[12]), - 'detail_nomor_hp_pic_reviewer' => json_encode($row[12]), - 'nama_pic_admin' => $row[13], - 'detail_nama_pic_admin' => json_encode($row[13]), - 'nomor_hp_pic_admin' => json_encode($row[14]), - 'detail_nomor_hp_pic_admin' => json_encode($row[14]), - 'nama_pic_marketing' => json_encode($row[15]), - 'detail_nama_pic_marketing' => json_encode($row[15]), - 'nomor_hp_pic_marketing' => json_encode($row[16]), - 'detail_nomor_hp_pic_marketing' => json_encode($row[16]), + 'nama_pic_reviewer' => $nama_pic_reviewer, + 'detail_nama_pic_reviewer' => $nama_pic_reviewer, + 'nomor_hp_pic_reviewer' => $nomor_hp_pic_reviewer, + 'detail_nomor_hp_pic_reviewer' => $nomor_hp_pic_reviewer, + + 'nama_pic_admin' => $detail_nama_pic_admin, + 'detail_nama_pic_admin' => $detail_nama_pic_admin, + 'nomor_hp_pic_admin' => $nomor_hp_pic_admin, + 'detail_nomor_hp_pic_admin' => $nomor_hp_pic_admin, + 'nama_pic_marketing' => $nama_pic_marketing, + 'detail_nama_pic_marketing' => $nama_pic_marketing, + 'nomor_hp_pic_marketing' => $nomor_hp_pic_marketing[0], + 'detail_nomor_hp_pic_marketing' => $nomor_hp_pic_marketing, 'ijin_usaha_id' => json_encode($jenisUsaha), 'jenis_aset_id' => json_encode($jenisAsset), 'attachment' => null, ]; - // Debug: Tampilkan data yang akan diinsert - $this->command->info('Data yang akan disimpan: ' . print_r($dataToInsert, true)); + // Simpan ke database KJPP::create($dataToInsert); @@ -196,22 +203,37 @@ public function checkJenisAsset($data) // Bersihkan dan ubah ke lowercase $cleanData = trim(strtolower($data)); - // Pisahkan berdasarkan koma - $assets = array_map('trim', explode(',', $cleanData)); + // Pisahkan berdasarkan koma, titik koma, dan spasi + $assets = preg_split('/[;,]+|\\s+/', $cleanData); // Daftar asset yang valid di database $validAssets = JenisJaminan::pluck('code')->toArray(); $assetIds = []; foreach ($assets as $asset) { - // Cari di database dengan lowercase - $jenisAsset = JenisJaminan::whereRaw('LOWER(name) = ?', [$asset])->first(); + // Hapus spasi di awal dan akhir + $asset = trim($asset); + // Cek jika ada tanda kurung + if (preg_match('/\((.*?)\)/', $asset, $matches)) { + // Ambil isi dalam tanda kurung dan pisahkan + $insideParentheses = explode(',', $matches[1]); + foreach ($insideParentheses as $insideAsset) { + $insideAsset = trim($insideAsset); + // Cari di database + $jenisAsset = JenisJaminan::whereRaw('LOWER(name) = ?', [$insideAsset])->first(); + if ($jenisAsset && in_array($jenisAsset->code, $validAssets)) { + $assetIds[] = $jenisAsset->code; + } + } + } + + // Cek jenis aset utama (tanpa tanda kurung) + $jenisAsset = JenisJaminan::whereRaw('LOWER(name) = ?', [$asset])->first(); if ($jenisAsset && in_array($jenisAsset->code, $validAssets)) { $assetIds[] = $jenisAsset->code; - $this->command->info(" ✅ Jenis Asset ditemukan: " . $jenisAsset->name); + } - // Hilangkan warning untuk yang tidak ditemukan } // Menghilangkan duplikat jika ada @@ -237,22 +259,23 @@ public function checkJenisUsaha($data) // Bersihkan dan ubah ke lowercase $cleanData = trim(strtolower($data)); - // Pisahkan berdasarkan koma jika ada - $usahas = array_map('trim', explode(',', $cleanData)); + // Pisahkan berdasarkan koma, titik koma, atau garis miring + $usahas = preg_split('/[\s,;\/]+/', $cleanData); - // Daftar usaha yang valid di database + // Ambil daftar valid usaha dari database $validUsaha = IjinUsaha::pluck('code')->toArray(); $usahaIds = []; foreach ($usahas as $usaha) { - // Cari di database dengan lowercase + // Hapus spasi di awal dan akhir + $usaha = trim($usaha); + + // Cari jenis usaha di database $jenisUsaha = IjinUsaha::whereRaw('LOWER(name) = ?', [$usaha])->first(); if ($jenisUsaha && in_array($jenisUsaha->code, $validUsaha)) { $usahaIds[] = $jenisUsaha->code; - $this->command->info(" ✅ Jenis Usaha ditemukan: " . $jenisUsaha->name); } - // Hilangkan warning untuk yang tidak ditemukan } // Menghilangkan duplikat jika ada @@ -264,11 +287,32 @@ public function checkJenisUsaha($data) return $usahaIds; } catch (\Exception $e) { + $this->command->error(" ❌ Error pada checkJenisUsaha: " . $e->getMessage()); return []; } } +// Fungsi untuk memisahkan dan mengonversi data menjadi array JSON +function checkDanJadikanJson($input) { + + $input = trim($input); + + // memisahkan berdasarkan "/", ";", "dan", atau baris baru ("\n") + $separatedData = preg_split('/\s*\/\s*|\s*;\s*|\s*dan\s*|\s*\n\s*/i', $input); + + + $cleanedData = array_map(function($item) { + return trim($item); + }, $separatedData); + + $cleanedData = array_filter($cleanedData, function($item) { + return !empty($item); + }); + + return json_encode(array_values($cleanedData)); +} + } diff --git a/database/seeders/list-update-kjpp.xlsx b/database/seeders/list-update-kjpp.xlsx new file mode 100644 index 0000000..89329e9 Binary files /dev/null and b/database/seeders/list-update-kjpp.xlsx differ