306 lines
13 KiB
PHP
306 lines
13 KiB
PHP
<?php
|
|
// api/laporan.php — Pelaporan Warga oleh Kontributor & Koordinator
|
|
header('Content-Type: application/json');
|
|
header('Access-Control-Allow-Origin: *');
|
|
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
|
|
header('Access-Control-Allow-Headers: Content-Type');
|
|
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(204); exit; }
|
|
|
|
require_once '../config/db.php';
|
|
require_once 'middleware.php';
|
|
|
|
$method = $_SERVER['REQUEST_METHOD'];
|
|
if ($method === 'POST' && isset($_POST['_method'])) {
|
|
$method = strtoupper($_POST['_method']);
|
|
}
|
|
$action = $_GET['action'] ?? '';
|
|
|
|
try {
|
|
switch ($method) {
|
|
|
|
// ── GET: List laporan ──────────────────────────────────────────────────
|
|
case 'GET':
|
|
$currentUser = requireAuth(['admin', 'petugas', 'koordinator', 'kontributor']);
|
|
$role = $currentUser['role'];
|
|
$userId = (int)$currentUser['id'];
|
|
|
|
// Jika ada action=stats untuk admin dashboard
|
|
if ($action === 'stats') {
|
|
if (!in_array($role, ['admin', 'petugas'])) {
|
|
http_response_code(403);
|
|
echo json_encode(['success' => false, 'message' => 'Forbidden']);
|
|
exit;
|
|
}
|
|
$stmtStats = $pdo->query("
|
|
SELECT status, COUNT(*) as jumlah
|
|
FROM laporan_warga
|
|
GROUP BY status
|
|
");
|
|
$stats = [];
|
|
while ($r = $stmtStats->fetch(PDO::FETCH_ASSOC)) {
|
|
$stats[$r['status']] = (int)$r['jumlah'];
|
|
}
|
|
$stmtTotal = $pdo->query("SELECT COUNT(*) FROM laporan_warga");
|
|
echo json_encode(['success' => true, 'stats' => $stats, 'total' => (int)$stmtTotal->fetchColumn()]);
|
|
exit;
|
|
}
|
|
|
|
// Filter berdasarkan role
|
|
$where = [];
|
|
$params = [];
|
|
|
|
// Jika ada action=get_petugas
|
|
if ($action === 'get_petugas') {
|
|
if (!in_array($role, ['admin', 'petugas'])) {
|
|
http_response_code(403); echo json_encode(['success' => false, 'message' => 'Forbidden']); exit;
|
|
}
|
|
$stmt = $pdo->query("SELECT username FROM users WHERE role = 'petugas' ORDER BY username ASC");
|
|
$petugas = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
|
echo json_encode(['success' => true, 'petugas' => $petugas]);
|
|
exit;
|
|
}
|
|
|
|
if ($role === 'kontributor') {
|
|
// Kontributor hanya lihat laporan milik sendiri
|
|
$where[] = 'lw.pelapor_id = ?';
|
|
$params[] = $userId;
|
|
} elseif ($role === 'koordinator') {
|
|
// Koordinator lihat laporan dari wilayahnya + laporan milik sendiri
|
|
$where[] = '(lw.pelapor_id = ? OR lw.koordinator_ibadah_id = ?)';
|
|
$params[] = $userId;
|
|
$params[] = !empty($currentUser['rumah_ibadah_id']) ? (int)$currentUser['rumah_ibadah_id'] : 0;
|
|
} elseif ($role === 'petugas') {
|
|
// Petugas hanya lihat laporan yang ditugaskan ke mereka
|
|
$where[] = 'lw.ditugaskan_ke = ?';
|
|
$params[] = $currentUser['username'];
|
|
}
|
|
// Admin: lihat semua
|
|
|
|
// Filter status
|
|
if (!empty($_GET['status'])) {
|
|
$where[] = 'lw.status = ?';
|
|
$params[] = $_GET['status'];
|
|
}
|
|
|
|
// Filter prioritas
|
|
if (!empty($_GET['prioritas'])) {
|
|
$where[] = 'lw.prioritas = ?';
|
|
$params[] = $_GET['prioritas'];
|
|
}
|
|
|
|
$whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
|
|
|
|
$sql = "
|
|
SELECT
|
|
lw.*,
|
|
rw.nama_kepala_keluarga,
|
|
rw.kelurahan,
|
|
rw.kecamatan,
|
|
rw.kategori_kemiskinan,
|
|
rw.status_bantuan,
|
|
u.username AS pelapor_nama,
|
|
u.role AS pelapor_role
|
|
FROM laporan_warga lw
|
|
JOIN rumah_warga rw ON rw.id = lw.rumah_warga_id
|
|
JOIN users u ON u.id = lw.pelapor_id
|
|
$whereSql
|
|
ORDER BY lw.created_at DESC
|
|
LIMIT 100
|
|
";
|
|
|
|
$stmt = $pdo->prepare($sql);
|
|
$stmt->execute($params);
|
|
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
// Summary counts for filter badges
|
|
$stmtSummary = $pdo->query("SELECT status, COUNT(*) as n FROM laporan_warga GROUP BY status");
|
|
$summary = [];
|
|
while ($r = $stmtSummary->fetch(PDO::FETCH_ASSOC)) {
|
|
$summary[$r['status']] = (int)$r['n'];
|
|
}
|
|
|
|
$response = ['success' => true, 'data' => $data, 'summary' => $summary, 'total' => count($data)];
|
|
|
|
// Sertakan list petugas jika user admin
|
|
if ($role === 'admin' || $role === 'petugas') {
|
|
$stmtP = $pdo->query("SELECT username FROM users WHERE role = 'petugas' ORDER BY username ASC");
|
|
$response['petugas'] = $stmtP->fetchAll(PDO::FETCH_COLUMN);
|
|
}
|
|
|
|
echo json_encode($response);
|
|
break;
|
|
|
|
// ── POST: Buat laporan baru ──────────────────────────────────────────
|
|
case 'POST':
|
|
$currentUser = requireAuth(['koordinator', 'kontributor']);
|
|
|
|
$input = json_decode(file_get_contents('php://input'), true) ?: $_POST;
|
|
|
|
$rumahWargaId = (int)($input['rumah_warga_id'] ?? 0);
|
|
$jenisLaporan = trim($input['jenis_laporan'] ?? '');
|
|
$deskripsi = trim($input['deskripsi'] ?? '');
|
|
|
|
// Penentuan prioritas otomatis berdasarkan jenis laporan
|
|
$prioritasMap = [
|
|
'warga_meninggal' => 'tinggi',
|
|
'warga_pindah' => 'tinggi',
|
|
'warga_mampu' => 'tinggi',
|
|
'data_ganda' => 'sedang',
|
|
'data_tidak_sesuai'=> 'sedang',
|
|
'lainnya' => 'rendah'
|
|
];
|
|
$prioritas = $prioritasMap[$jenisLaporan] ?? 'sedang';
|
|
|
|
if (!$rumahWargaId || !$jenisLaporan || !$deskripsi) {
|
|
http_response_code(400);
|
|
echo json_encode(['success' => false, 'message' => 'Data tidak lengkap: rumah_warga_id, jenis_laporan, dan deskripsi wajib diisi.']);
|
|
exit;
|
|
}
|
|
|
|
// Cek warga ada
|
|
$stmtCek = $pdo->prepare("SELECT id, nama_kepala_keluarga FROM rumah_warga WHERE id = ?");
|
|
$stmtCek->execute([$rumahWargaId]);
|
|
$warga = $stmtCek->fetch();
|
|
if (!$warga) {
|
|
http_response_code(404);
|
|
echo json_encode(['success' => false, 'message' => 'Data warga tidak ditemukan.']);
|
|
exit;
|
|
}
|
|
|
|
// Cek apakah laporan duplikat dalam 7 hari terakhir
|
|
$stmtDupCheck = $pdo->prepare("
|
|
SELECT id FROM laporan_warga
|
|
WHERE rumah_warga_id = ? AND pelapor_id = ?
|
|
AND status NOT IN ('selesai', 'ditolak')
|
|
AND created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)
|
|
");
|
|
$stmtDupCheck->execute([$rumahWargaId, $currentUser['id']]);
|
|
if ($stmtDupCheck->fetch()) {
|
|
http_response_code(409);
|
|
echo json_encode(['success' => false, 'message' => 'Anda sudah membuat laporan untuk warga ini dalam 7 hari terakhir. Harap tunggu laporan sebelumnya diproses.']);
|
|
exit;
|
|
}
|
|
|
|
$koordinatorIbadahId = !empty($currentUser['rumah_ibadah_id']) ? (int)$currentUser['rumah_ibadah_id'] : null;
|
|
|
|
$stmtInsert = $pdo->prepare("
|
|
INSERT INTO laporan_warga
|
|
(rumah_warga_id, pelapor_id, koordinator_ibadah_id, jenis_laporan, deskripsi, prioritas, status)
|
|
VALUES (?, ?, ?, ?, ?, ?, 'pending')
|
|
");
|
|
$stmtInsert->execute([
|
|
$rumahWargaId,
|
|
$currentUser['id'],
|
|
$koordinatorIbadahId,
|
|
$jenisLaporan,
|
|
$deskripsi,
|
|
$prioritas,
|
|
]);
|
|
|
|
echo json_encode([
|
|
'success' => true,
|
|
'message' => 'Laporan berhasil dikirim. Admin akan meninjau laporan Anda segera.',
|
|
'id' => $pdo->lastInsertId()
|
|
]);
|
|
break;
|
|
|
|
case 'PUT':
|
|
$currentUser = requireAuth(['admin', 'petugas']);
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
if (!$input) $input = $_POST;
|
|
|
|
$id = (int)($input['id'] ?? 0);
|
|
$status = $input['status'] ?? '';
|
|
$catatanAdmin = trim($input['catatan_admin'] ?? '');
|
|
$ditugaskanKe = trim($input['ditugaskan_ke'] ?? '');
|
|
|
|
// Ambil dari old state
|
|
$stmtDok = $pdo->prepare("SELECT dokumentasi FROM laporan_warga WHERE id = ?");
|
|
$stmtDok->execute([$id]);
|
|
$oldDok = $stmtDok->fetchColumn();
|
|
|
|
$dokumentasi = trim($input['dokumentasi'] ?? $oldDok ?? '');
|
|
|
|
// Handle file upload
|
|
if (isset($_FILES['dokumentasi_file']) && $_FILES['dokumentasi_file']['error'] === UPLOAD_ERR_OK) {
|
|
$uploadDir = '../uploads/dokumentasi/';
|
|
if (!is_dir($uploadDir)) {
|
|
mkdir($uploadDir, 0755, true);
|
|
}
|
|
$ext = strtolower(pathinfo($_FILES['dokumentasi_file']['name'], PATHINFO_EXTENSION));
|
|
$allowedExts = ['jpg', 'jpeg', 'png', 'pdf'];
|
|
if (in_array($ext, $allowedExts)) {
|
|
$filename = 'dok_' . $id . '_' . time() . '.' . $ext;
|
|
$dest = $uploadDir . $filename;
|
|
if (move_uploaded_file($_FILES['dokumentasi_file']['tmp_name'], $dest)) {
|
|
$dokumentasi = 'uploads/dokumentasi/' . $filename;
|
|
}
|
|
}
|
|
}
|
|
|
|
$allowedStatus = ['pending', 'ditinjau', 'diproses', 'selesai', 'ditolak'];
|
|
if (!$id || !in_array($status, $allowedStatus)) {
|
|
http_response_code(400);
|
|
echo json_encode(['success' => false, 'message' => 'ID dan status valid wajib diisi.']);
|
|
exit;
|
|
}
|
|
|
|
// Jika petugas, pastikan hanya bisa update dokumentasi, status, catatan. (ditugaskan_ke biarkan tetap)
|
|
if ($currentUser['role'] === 'petugas') {
|
|
$stmt = $pdo->prepare("
|
|
UPDATE laporan_warga
|
|
SET status = ?, catatan_admin = ?, dokumentasi = ?, updated_at = NOW()
|
|
WHERE id = ? AND ditugaskan_ke = ?
|
|
");
|
|
$stmt->execute([$status, $catatanAdmin, $dokumentasi, $id, $currentUser['username']]);
|
|
} else {
|
|
// Admin bisa update semua
|
|
$stmt = $pdo->prepare("
|
|
UPDATE laporan_warga
|
|
SET status = ?, catatan_admin = ?, ditugaskan_ke = ?, dokumentasi = ?, updated_at = NOW()
|
|
WHERE id = ?
|
|
");
|
|
$stmt->execute([$status, $catatanAdmin, $ditugaskanKe ?: null, $dokumentasi, $id]);
|
|
}
|
|
|
|
$statusLabel = [
|
|
'pending' => 'Menunggu',
|
|
'ditinjau' => 'Sedang Ditinjau',
|
|
'diproses' => 'Sedang Diproses',
|
|
'selesai' => 'Selesai',
|
|
'ditolak' => 'Ditolak',
|
|
];
|
|
|
|
echo json_encode([
|
|
'success' => true,
|
|
'message' => 'Laporan berhasil diperbarui ke status: ' . ($statusLabel[$status] ?? $status)
|
|
]);
|
|
break;
|
|
|
|
// ── DELETE: Hapus laporan (admin only) ──────────────────────────────
|
|
case 'DELETE':
|
|
$currentUser = requireAuth(['admin']);
|
|
$id = (int)($_GET['id'] ?? 0);
|
|
if (!$id) {
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
$id = (int)($input['id'] ?? 0);
|
|
}
|
|
if (!$id) {
|
|
http_response_code(400);
|
|
echo json_encode(['success' => false, 'message' => 'ID laporan wajib diisi.']);
|
|
exit;
|
|
}
|
|
$stmt = $pdo->prepare("DELETE FROM laporan_warga WHERE id = ?");
|
|
$stmt->execute([$id]);
|
|
echo json_encode(['success' => true, 'message' => 'Laporan berhasil dihapus.']);
|
|
break;
|
|
|
|
default:
|
|
http_response_code(405);
|
|
echo json_encode(['error' => 'Method not allowed']);
|
|
}
|
|
} catch (Exception $e) {
|
|
http_response_code(500);
|
|
echo json_encode(['success' => false, 'message' => 'Kesalahan sistem: ' . $e->getMessage()]);
|
|
}
|