MIF_E31230680/app/Http/Controllers/WargaController.php

390 lines
12 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Exports\TemplateWargaExport;
use App\Exports\WargaExport;
use App\Imports\WargaImport; // <-- PASTIKAN INI ADA
use App\Models\Kriteria;
use App\Models\SubKriteria;
use App\Models\Warga;
use App\Models\WargaDetail;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Maatwebsite\Excel\Facades\Excel;
class WargaController extends Controller
{
/**
* Menampilkan daftar warga dengan pagination.
*/
public function index(Request $request)
{
$perPage = $request->get('per_page', 10);
$kriterias = Kriteria::orderBy('kode', 'asc')->get();
// Eager loading 'details' untuk menghindari N+1 Query saat looping di tabel
$query = Warga::with(['details.kriteria', 'details.subKriteria']);
if ($request->filled('search')) {
$search = $request->search;
$query->where(function ($q) use ($search) {
$q->where('nama', 'LIKE', "%$search%")
->orWhere('nik', 'LIKE', "%$search%");
});
}
if ($request->filled('rt')) {
$query->where('rt', str_pad($request->rt, 3, '0', STR_PAD_LEFT));
}
if ($request->filled('rw')) {
$query->where('rw', str_pad($request->rw, 3, '0', STR_PAD_LEFT));
}
if ($request->filled('status')) {
$query->where('status_verifikasi', $request->status);
}
foreach ($kriterias as $k) {
$filterKey = 'f_kriteria_'.$k->id;
if ($request->filled($filterKey)) {
$nilaiFilter = $request->get($filterKey);
$query->whereHas('details', function ($q) use ($k, $nilaiFilter) {
$q->where('kriteria_id', $k->id)
->where('nilai_asli', $nilaiFilter);
});
}
}
$wargas = $query->latest()->paginate($perPage)->appends($request->all());
return view('warga.index', compact('wargas', 'kriterias'));
}
/**
* Form tambah warga.
*/
public function create()
{
$kriterias = Kriteria::with('subKriterias')->orderBy('kode', 'asc')->get();
return view('warga.create', compact('kriterias'));
}
/**
* Menyimpan data warga manual (Identitas + Kriteria Dinamis + Files).
*/
public function store(Request $request)
{
// 1. Validasi Identitas Dasar & Dokumen
$rules = [
'nik' => 'required|digits:16|unique:wargas,nik',
'nama' => 'required|string|max:255',
'alamat' => 'required',
'rt' => 'required|max:3',
'rw' => 'required|max:3',
'files' => 'nullable|array',
'files.*' => 'nullable|mimes:jpg,jpeg,png,pdf|max:2048',
];
// 2. Validasi Dinamis untuk Input Kriteria
$kriterias = Kriteria::all();
foreach ($kriterias as $k) {
$rules['kriteria_'.$k->id] = 'required';
}
$request->validate($rules);
try {
DB::beginTransaction();
// 3. Handling Multiple File Upload
$paths = [];
if ($request->hasFile('files')) {
foreach ($request->file('files') as $file) {
$paths[] = $file->store('dokumen_warga', 'public');
}
}
// 4. Simpan Data Utama Warga
$warga = Warga::create([
'nik' => $request->nik,
'nama' => $request->nama,
'alamat' => $request->alamat,
'rt' => $request->rt,
'rw' => $request->rw,
'dokumen_pendukung' => $paths,
'status_verifikasi' => 'pending',
'status_bansos_riil' => 'aktif',
]);
// 5. Simpan Detail Kriteria
$this->saveWargaDetails($warga, $request, $kriterias);
DB::commit();
return redirect()->route('warga.index')->with('success', 'Data Warga Berhasil Ditambahkan!');
} catch (\Exception $e) {
DB::rollback();
Log::error('Error Store Warga: '.$e->getMessage());
return redirect()->back()->withInput()->with('error', 'Gagal menyimpan data: '.$e->getMessage());
}
}
/**
* Import Data dari Excel/CSV.
*/
public function importExcel(Request $request)
{
$request->validate([
'file_excel' => 'required|mimes:xlsx,xls,csv|max:10240',
]);
try {
Excel::import(new WargaImport, $request->file('file_excel'));
return redirect()->route('warga.index')->with('success', 'Import Data Berhasil!');
} catch (\Exception $e) {
Log::error('Error Import Warga: '.$e->getMessage());
return redirect()->back()->with('error', 'Gagal Import: '.$e->getMessage());
}
}
/**
* Form Edit Warga.
*/
public function edit($id)
{
$warga = Warga::with('details')->findOrFail($id);
$kriterias = Kriteria::with('subKriterias')->orderBy('kode', 'asc')->get();
return view('warga.edit', compact('warga', 'kriterias'));
}
/**
* Update data warga.
*/
public function update(Request $request, $id)
{
$warga = Warga::findOrFail($id);
$rules = [
'nik' => 'required|digits:16|unique:wargas,nik,'.$id,
'nama' => 'required|string|max:255',
'alamat' => 'required',
'rt' => 'required|max:3',
'rw' => 'required|max:3',
'files.*' => 'nullable|mimes:jpg,jpeg,png,pdf|max:2048',
'status_bansos_riil' => 'required|in:aktif,meninggal,pindah,mampu',
];
$kriterias = Kriteria::all();
foreach ($kriterias as $k) {
$rules['kriteria_'.$k->id] = 'required';
}
$request->validate($rules);
try {
DB::beginTransaction();
$paths = is_array($warga->dokumen_pendukung) ? $warga->dokumen_pendukung : [];
if ($request->has('hapus_dokumen')) {
foreach ($request->hapus_dokumen as $fileToDelete) {
Storage::disk('public')->delete($fileToDelete);
}
$paths = array_diff($paths, [$fileToDelete]);
}
if ($request->hasFile('files')) {
foreach ($request->file('files') as $file) {
$path = $file->store('dokumen_warga', 'public');
$paths[] = $path;
}
}
// --- LOGIKA CERDAS: ALUR PENOLAKAN ---
$statusBaru = $warga->status_verifikasi;
$catatanBaru = $warga->catatan;
$verifikatorBaru = $warga->verified_by;
// Jika sebelumnya ditolak, lalu datanya diperbaiki, kembalikan ke antrean verifikasi
if ($warga->status_verifikasi === 'tolak') {
$statusBaru = 'pending';
$catatanBaru = null;
$verifikatorBaru = null;
}
// -------------------------------------
$warga->update([
'nik' => $request->nik,
'nama' => $request->nama,
'alamat' => $request->alamat,
'rt' => str_pad($request->rt, 3, '0', STR_PAD_LEFT),
'rw' => str_pad($request->rw, 3, '0', STR_PAD_LEFT),
'dokumen_pendukung' => array_values($paths),
'status_verifikasi' => $statusBaru,
'catatan' => $catatanBaru,
'verified_by' => $verifikatorBaru,
'status_bansos_riil' => $request->status_bansos_riil,
]);
$this->saveWargaDetails($warga, $request, $kriterias, true);
DB::commit();
return redirect()->route('warga.index')->with('success', 'Data Berhasil Diperbarui!');
} catch (\Exception $e) {
DB::rollback();
Log::error('Error Update Warga: '.$e->getMessage());
return redirect()->back()->with('error', 'Gagal update: '.$e->getMessage());
}
}
public function bulkUpdate(Request $request)
{
// 1. Validasi input
$request->validate([
'ids' => 'required|string', // Kita kirim string ID yang dipisah koma dari JS
'kriteria_id' => 'required|exists:kriterias,id',
'sub_kriteria_id' => 'required|exists:sub_kriterias,id'
]);
try {
DB::beginTransaction();
// Ubah string "1,2,3" menjadi array [1,2,3]
$idsArray = explode(',', $request->ids);
$sub = SubKriteria::findOrFail($request->sub_kriteria_id);
// 2. Eksekusi Update Massal
WargaDetail::whereIn('warga_id', $idsArray)
->where('kriteria_id', $request->kriteria_id)
->update([
'sub_kriteria_id' => $sub->id,
'nilai_asli' => $sub->nama_sub
]);
DB::commit();
return redirect()->back()->with('success', count($idsArray) . ' Data warga berhasil di-update secara massal!');
} catch (\Exception $e) {
DB::rollBack();
return redirect()->back()->with('error', 'Gagal update massal: ' . $e->getMessage());
}
}
/**
* Method Privat: Logika simpan detail kriteria.
*/
private function saveWargaDetails($warga, $request, $kriterias, $isUpdate = false)
{
foreach ($kriterias as $k) {
$nilaiInput = $request->input('kriteria_'.$k->id);
$sub = SubKriteria::where('kriteria_id', $k->id)
->where('nama_sub', $nilaiInput)
->first();
$dataDetail = [
'sub_kriteria_id' => $sub ? $sub->id : null,
'nilai_asli' => $nilaiInput,
];
if ($isUpdate) {
WargaDetail::updateOrCreate(
['warga_id' => $warga->id, 'kriteria_id' => $k->id],
$dataDetail
);
} else {
WargaDetail::create(array_merge([
'warga_id' => $warga->id,
'kriteria_id' => $k->id,
], $dataDetail));
}
}
}
/**
* Download Template XLSX Dinamis.
*/
public function downloadTemplate()
{
// Pastikan facade Excel diimport (use Maatwebsite\Excel\Facades\Excel;)
return Excel::download(new TemplateWargaExport, 'template_import_warga.xlsx');
}
public function exportExcel(Request $request)
{
$nama_file = 'Data_Warga_'.date('d-m-Y_H-i').'.xlsx';
return Excel::download(new WargaExport($request), $nama_file);
}
/**
* Hapus Data Warga beserta filenya.
*/
public function destroy($id)
{
try {
$warga = Warga::findOrFail($id);
if ($warga->dokumen_pendukung) {
foreach ($warga->dokumen_pendukung as $file) {
Storage::disk('public')->delete($file);
}
}
$warga->delete();
return redirect()->route('warga.index')->with('success', 'Data Warga Berhasil Dihapus!');
} catch (\Exception $e) {
return redirect()->back()->with('error', 'Gagal menghapus data.');
}
}
public function bulkDelete(Request $request)
{
// 1. Validasi input
$request->validate([
'ids' => 'required|string', // String ID yang dipisah koma
]);
try {
DB::beginTransaction();
// Ubah string "1,2,3" menjadi array [1,2,3]
$idsArray = explode(',', $request->ids);
// Ambil data warga
$wargas = Warga::whereIn('id', $idsArray)->get();
// Lakukan looping hapus agar file fisik dan detailnya ikut terhapus
foreach ($wargas as $warga) {
if ($warga->dokumen_pendukung) {
foreach ($warga->dokumen_pendukung as $file) {
Storage::disk('public')->delete($file);
}
}
// Hapus warga (akan otomatis menghapus detail & hasil seleksi berkat fungsi boot di Model)
$warga->delete();
}
DB::commit();
return redirect()->back()->with('success', count($idsArray) . ' Data warga berhasil dihapus massal!');
} catch (\Exception $e) {
DB::rollBack();
return redirect()->back()->with('error', 'Gagal menghapus massal: ' . $e->getMessage());
}
}
}