prepare("SELECT rp.*, p.nama_pelatihan, p.penyelenggara, p.tanggal as tgl_pelatihan FROM riwayat_pelatihan rp JOIN pelatihan p ON p.id=rp.pelatihan_id WHERE rp.penduduk_id=? ORDER BY rp.tanggal_ikut DESC"); $st->execute([$pid]); jsonOk($st->fetchAll()); } // ── DAFTARKAN PESERTA ── if ($action === 'daftar' && $method === 'POST') { requireRole(['superadmin', 'pengurus', 'relawan']); $b = json_decode(file_get_contents('php://input'), true); $pid = (int)($b['penduduk_id'] ?? 0); $tid = (int)($b['pelatihan_id'] ?? 0); if (!$pid || !$tid) jsonErr('penduduk_id dan pelatihan_id wajib.'); // validasi: cek umur >= 18 untuk pelatihan kerja $p = $db->prepare("SELECT umur FROM penduduk WHERE id=?"); $p->execute([$pid]); $row = $p->fetch(); if ($row && (int)$row['umur'] < 15) jsonErr('Peserta minimal berusia 15 tahun untuk mengikuti pelatihan.'); $db->prepare("INSERT INTO riwayat_pelatihan (penduduk_id, pelatihan_id, tanggal_ikut) VALUES (?,?,?)") ->execute([$pid, $tid, $b['tanggal_ikut'] ?? date('Y-m-d')]); log_aksi($user['id'], 'CREATE', 'riwayat_pelatihan', (int)$db->lastInsertId(), "Daftar pelatihan pid:$pid tid:$tid"); jsonOk(null, 'Peserta berhasil didaftarkan ke pelatihan.'); } // ── CRUD MASTER PELATIHAN ── switch ($method) { case 'GET': if ($id) { $st = $db->prepare("SELECT p.*, COUNT(rp.id) as jumlah_peserta FROM pelatihan p LEFT JOIN riwayat_pelatihan rp ON rp.pelatihan_id=p.id WHERE p.id=? GROUP BY p.id"); $st->execute([$id]); $row = $st->fetch(); if (!$row) jsonErr('Tidak ditemukan.', 404); // peserta $ps = $db->prepare("SELECT rp.id, rp.tanggal_ikut, pd.nama, pd.nik, pd.umur FROM riwayat_pelatihan rp JOIN v_penduduk pd ON pd.id=rp.penduduk_id WHERE rp.pelatihan_id=? ORDER BY rp.tanggal_ikut DESC"); $ps->execute([$id]); $row['peserta'] = $ps->fetchAll(); jsonOk($row); break; } $rows = $db->query("SELECT p.*, COUNT(rp.id) as jumlah_peserta FROM pelatihan p LEFT JOIN riwayat_pelatihan rp ON rp.pelatihan_id=p.id GROUP BY p.id ORDER BY p.tanggal DESC")->fetchAll(); jsonOk($rows); break; case 'POST': requireRole(['superadmin', 'pengurus']); $b = json_decode(file_get_contents('php://input'), true); $nama = sanitize($b['nama_pelatihan'] ?? ''); if (!$nama) jsonErr('Nama pelatihan wajib diisi.'); $db->prepare("INSERT INTO pelatihan (nama_pelatihan, penyelenggara, tanggal, durasi_hari, deskripsi) VALUES (?,?,?,?,?)") ->execute([$nama, sanitize($b['penyelenggara'] ?? ''), $b['tanggal'] ?? null, (int)($b['durasi_hari'] ?? 1), sanitize($b['deskripsi'] ?? '')]); jsonOk(['id' => (int)$db->lastInsertId()], 'Pelatihan ditambahkan.'); break; case 'PUT': requireRole(['superadmin', 'pengurus']); if (!$id) jsonErr('ID tidak valid.'); $b = json_decode(file_get_contents('php://input'), true); $db->prepare("UPDATE pelatihan SET nama_pelatihan=?, penyelenggara=?, tanggal=?, durasi_hari=?, deskripsi=? WHERE id=?") ->execute([sanitize($b['nama_pelatihan'] ?? ''), sanitize($b['penyelenggara'] ?? ''), $b['tanggal'] ?? null, (int)($b['durasi_hari'] ?? 1), sanitize($b['deskripsi'] ?? ''), $id]); jsonOk(null, 'Pelatihan diperbarui.'); break; case 'DELETE': requireRole(['superadmin']); if (!$id) jsonErr('ID tidak valid.'); $db->prepare("DELETE FROM pelatihan WHERE id=?")->execute([$id]); jsonOk(null, 'Pelatihan dihapus.'); break; default: jsonErr('Method tidak didukung.', 405); }