prepare(" SELECT km.*, ri.nama AS nama_ri, ri.jenis AS jenis_ri, ri.kode_pengurus, COALESCE((SELECT SUM(hb.nominal) FROM histori_bantuan hb WHERE hb.kk_id = km.id), 0) AS total_bantuan FROM keluarga_miskin km LEFT JOIN rumah_ibadah ri ON km.rumah_ibadah_id = ri.id WHERE km.id = ? "); $stmt->execute([$id]); $row = $stmt->fetch(); if (!$row) { jsonResponse(null, 'Data keluarga miskin tidak ditemukan.', false, 404); } // Cek akses pengurus — hanya boleh lihat KK binaan miliknya $sess = $_SESSION['user'] ?? null; if ($sess && $sess['role'] === 'pengurus') { if ((int)($row['rumah_ibadah_id'] ?? 0) !== (int)$sess['rumah_ibadah_id']) { jsonResponse(null, 'Akses ditolak. KK ini bukan binaan Anda.', false, 403); } } // Decode riwayat_penyakit JSON $row['riwayat_penyakit'] = json_decode($row['riwayat_penyakit'] ?? '[]', true); // Flag eligible_bansos_tunai: hanya untuk KK dengan status_dtks = 'Belum DTKS' $row['eligible_bansos_tunai'] = ($row['status_dtks'] === 'Belum DTKS'); // Format total_bantuan $row['total_bantuan_formatted'] = 'Rp ' . number_format((int)$row['total_bantuan'], 0, ',', '.'); jsonResponse($row, 'Data keluarga miskin ditemukan.'); } // ── Ambil semua dengan filter ── $where = []; $params = []; // Filter berdasarkan role pengurus $sess = $_SESSION['user'] ?? null; if ($sess && $sess['role'] === 'pengurus' && !empty($sess['rumah_ibadah_id'])) { $where[] = 'km.rumah_ibadah_id = ?'; $params[] = (int)$sess['rumah_ibadah_id']; } // Filter kecamatan if (!empty($_GET['kecamatan'])) { $where[] = 'km.kecamatan = ?'; $params[] = clean($_GET['kecamatan']); } // Filter tingkat_kemiskinan if (!empty($_GET['tingkat_kemiskinan'])) { $where[] = 'km.tingkat_kemiskinan = ?'; $params[] = clean($_GET['tingkat_kemiskinan']); } // Filter status_dtks if (!empty($_GET['status_dtks'])) { $where[] = 'km.status_dtks = ?'; $params[] = clean($_GET['status_dtks']); } // Filter rumah_ibadah_id if (isset($_GET['rumah_ibadah_id']) && $_GET['rumah_ibadah_id'] !== '') { $where[] = 'km.rumah_ibadah_id = ?'; $params[] = (int)$_GET['rumah_ibadah_id']; } $sql = " SELECT km.*, ri.nama AS nama_ri, ri.jenis AS jenis_ri, COALESCE((SELECT SUM(hb.nominal) FROM histori_bantuan hb WHERE hb.kk_id = km.id), 0) AS total_bantuan FROM keluarga_miskin km LEFT JOIN rumah_ibadah ri ON km.rumah_ibadah_id = ri.id "; if (!empty($where)) { $sql .= ' WHERE ' . implode(' AND ', $where); } $sql .= ' ORDER BY km.nama_kepala_keluarga ASC'; $stmt = $pdo->prepare($sql); $stmt->execute($params); $rows = $stmt->fetchAll(); // Proses setiap baris: decode JSON + flag eligible + format total foreach ($rows as &$r) { $r['riwayat_penyakit'] = json_decode($r['riwayat_penyakit'] ?? '[]', true); $r['eligible_bansos_tunai'] = ($r['status_dtks'] === 'Belum DTKS'); $r['total_bantuan_formatted'] = 'Rp ' . number_format((int)$r['total_bantuan'], 0, ',', '.'); } jsonResponse($rows, 'Daftar keluarga miskin.', true, 200); } // ── POST: Tambah KK (admin + pengurus) ─────────────────────── if ($method === 'POST') { $user = requireRole(['admin', 'pengurus']); $body = json_decode(file_get_contents('php://input'), true) ?? []; // Validasi input $nik = clean($body['nik'] ?? ''); $nama_kepala_keluarga = clean($body['nama_kepala_keluarga'] ?? ''); $tanggal_lahir = clean($body['tanggal_lahir'] ?? ''); $pendidikan = clean($body['pendidikan'] ?? 'Tidak Sekolah'); $jumlah_anggota = (int)($body['jumlah_anggota'] ?? 1); $alamat = clean($body['alamat'] ?? ''); $kecamatan = clean($body['kecamatan'] ?? ''); $lat = (float)($body['lat'] ?? 0); $lng = (float)($body['lng'] ?? 0); $tingkat_kemiskinan = clean($body['tingkat_kemiskinan'] ?? 'Miskin'); $status_dtks = clean($body['status_dtks'] ?? 'Belum DTKS'); $riwayat_penyakit = $body['riwayat_penyakit'] ?? []; if (!$nik || !$nama_kepala_keluarga || !$alamat || !$kecamatan || !$lat || !$lng) { jsonResponse(null, 'NIK, nama KK, alamat, kecamatan, dan koordinat wajib diisi.', false, 400); } // Cek NIK unik $stmt = $pdo->prepare("SELECT id FROM keluarga_miskin WHERE nik = ? LIMIT 1"); $stmt->execute([$nik]); if ($stmt->fetch()) { jsonResponse(null, 'NIK sudah terdaftar dalam sistem.', false, 400); } // Auto-assign ke rumah ibadah terdekat dalam radius $assign = autoAssign($pdo, $lat, $lng); $riId = $assign['rumah_ibadah_id']; $jarakKm = $assign['jarak_km']; $riwayatJson = json_encode(is_array($riwayat_penyakit) ? $riwayat_penyakit : []); // Pengurus: paksa assign ke RI miliknya (jika dalam radius) if ($user['role'] === 'pengurus') { $riId = (int)$user['rumah_ibadah_id']; // Hitung jarak ke RI miliknya $stRi = $pdo->prepare("SELECT lat, lng FROM rumah_ibadah WHERE id = ?"); $stRi->execute([$riId]); $riData = $stRi->fetch(); $jarakKm = $riData ? haversine($lat, $lng, (float)$riData['lat'], (float)$riData['lng']) : null; } $stmt = $pdo->prepare(" INSERT INTO keluarga_miskin (nik, nama_kepala_keluarga, tanggal_lahir, pendidikan, jumlah_anggota, alamat, kecamatan, lat, lng, tingkat_kemiskinan, status_dtks, riwayat_penyakit, rumah_ibadah_id, jarak_ke_ibadah) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "); $stmt->execute([ $nik, $nama_kepala_keluarga, $tanggal_lahir ?: null, $pendidikan, $jumlah_anggota, $alamat, $kecamatan, $lat, $lng, $tingkat_kemiskinan, $status_dtks, $riwayatJson, $riId, $jarakKm ]); $newId = (int)$pdo->lastInsertId(); $assignMsg = $riId ? "Auto-assign ke rumah ibadah (jarak: {$jarakKm} km)." : "Tidak ada rumah ibadah dalam radius cakupan."; jsonResponse([ 'id' => $newId, 'rumah_ibadah_id' => $riId, 'jarak_km' => $jarakKm, ], 'Data keluarga miskin berhasil ditambahkan. ' . $assignMsg); } // ── PUT: Update KK ─────────────────────────────────────────── if ($method === 'PUT') { $user = requireRole(['admin', 'pengurus']); $body = json_decode(file_get_contents('php://input'), true) ?? []; $id = (int)($body['id'] ?? 0); if (!$id) { jsonResponse(null, 'ID keluarga miskin wajib diisi.', false, 400); } // Cek data ada $stmt = $pdo->prepare("SELECT rumah_ibadah_id FROM keluarga_miskin WHERE id = ? LIMIT 1"); $stmt->execute([$id]); $existing = $stmt->fetch(); if (!$existing) { jsonResponse(null, 'Data keluarga miskin tidak ditemukan.', false, 404); } // Pengurus hanya bisa edit KK dalam RI-nya if ($user['role'] === 'pengurus') { if ((int)($existing['rumah_ibadah_id'] ?? 0) !== (int)$user['rumah_ibadah_id']) { jsonResponse(null, 'Anda hanya dapat mengedit KK binaan rumah ibadah Anda.', false, 403); } } $nik = clean($body['nik'] ?? ''); $nama_kepala_keluarga = clean($body['nama_kepala_keluarga'] ?? ''); $tanggal_lahir = clean($body['tanggal_lahir'] ?? ''); $pendidikan = clean($body['pendidikan'] ?? 'Tidak Sekolah'); $jumlah_anggota = (int)($body['jumlah_anggota'] ?? 1); $alamat = clean($body['alamat'] ?? ''); $kecamatan = clean($body['kecamatan'] ?? ''); $lat = (float)($body['lat'] ?? 0); $lng = (float)($body['lng'] ?? 0); $tingkat_kemiskinan = clean($body['tingkat_kemiskinan'] ?? 'Miskin'); $status_dtks = clean($body['status_dtks'] ?? 'Belum DTKS'); $riwayat_penyakit = $body['riwayat_penyakit'] ?? []; if (!$nik || !$nama_kepala_keluarga || !$alamat || !$kecamatan || !$lat || !$lng) { jsonResponse(null, 'Semua field wajib diisi.', false, 400); } // Cek NIK unik (kecuali milik sendiri) $stmt = $pdo->prepare("SELECT id FROM keluarga_miskin WHERE nik = ? AND id != ? LIMIT 1"); $stmt->execute([$nik, $id]); if ($stmt->fetch()) { jsonResponse(null, 'NIK sudah digunakan oleh KK lain.', false, 400); } // Re-calculate auto-assign $assign = autoAssign($pdo, $lat, $lng); $riId = $assign['rumah_ibadah_id']; $jarakKm = $assign['jarak_km']; $riwayatJson = json_encode(is_array($riwayat_penyakit) ? $riwayat_penyakit : []); $stmt = $pdo->prepare(" UPDATE keluarga_miskin SET nik = ?, nama_kepala_keluarga = ?, tanggal_lahir = ?, pendidikan = ?, jumlah_anggota = ?, alamat = ?, kecamatan = ?, lat = ?, lng = ?, tingkat_kemiskinan = ?, status_dtks = ?, riwayat_penyakit = ?, rumah_ibadah_id = ?, jarak_ke_ibadah = ? WHERE id = ? "); $stmt->execute([ $nik, $nama_kepala_keluarga, $tanggal_lahir ?: null, $pendidikan, $jumlah_anggota, $alamat, $kecamatan, $lat, $lng, $tingkat_kemiskinan, $status_dtks, $riwayatJson, $riId, $jarakKm, $id ]); jsonResponse([ 'rumah_ibadah_id' => $riId, 'jarak_km' => $jarakKm, ], 'Data keluarga miskin berhasil diperbarui.'); } // ── DELETE: Hapus KK (admin only) ──────────────────────────── if ($method === 'DELETE') { $user = requireRole(['admin']); $id = (int)($_GET['id'] ?? 0); if (!$id) { jsonResponse(null, 'ID keluarga miskin wajib diisi.', false, 400); } $stmt = $pdo->prepare("DELETE FROM keluarga_miskin WHERE id = ?"); $stmt->execute([$id]); if ($stmt->rowCount() === 0) { jsonResponse(null, 'Data tidak ditemukan.', false, 404); } jsonResponse(null, 'Data keluarga miskin berhasil dihapus.'); } // ── Method tidak didukung ──────────────────────────────────── jsonResponse(null, 'Method tidak didukung.', false, 405);