390 lines
12 KiB
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());
|
|
}
|
|
}
|
|
|
|
}
|