Files
2026-06-09 19:36:57 +07:00

286 lines
11 KiB
PHP

<?php
// ============================================================
// API: Keluarga Miskin (CRUD + Filter + Auto-assign)
// GET: publik | POST: admin+pengurus | PUT: admin+pengurus | DELETE: admin
// ============================================================
require_once __DIR__ . '/config.php';
$method = $_SERVER['REQUEST_METHOD'];
// Blokir aksi tulis walikota
blockWalikotaWrite();
// ── GET: Ambil semua (dengan filter) atau satu KK ────────────
if ($method === 'GET') {
$id = isset($_GET['id']) ? (int)$_GET['id'] : null;
if ($id) {
// Ambil satu KK beserta info rumah ibadah terkait
$stmt = $pdo->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);