Files
WebGIS-Poverty-MAP/api/import.php
T

185 lines
6.7 KiB
PHP

<?php
// ================================================================
// API: Import Data Massal dari CSV
// ================================================================
require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../config/config.php';
require_once __DIR__ . '/../includes/auth.php';
require_once __DIR__ . '/../includes/functions.php';
header('Content-Type: application/json; charset=utf-8');
// Hanya POST
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['success' => false, 'message' => 'Method tidak didukung']);
exit;
}
$db = getDB();
$type = $_POST['type'] ?? ''; // 'penduduk' | 'ibadah'
if (!in_array($type, ['penduduk', 'ibadah'])) {
echo json_encode(['success' => false, 'message' => 'Tipe import tidak valid']); exit;
}
if (empty($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
echo json_encode(['success' => false, 'message' => 'File tidak valid atau tidak ada']); exit;
}
// Baca isi file
$content = file_get_contents($_FILES['file']['tmp_name']);
if ($content === false) {
echo json_encode(['success' => false, 'message' => 'Gagal membaca file']); exit;
}
// Normalize line endings & parse CSV
$content = str_replace("\r\n", "\n", $content);
$content = str_replace("\r", "\n", $content);
$lines = array_filter(explode("\n", $content), 'strlen');
$lines = array_values($lines);
if (empty($lines)) {
echo json_encode(['success' => false, 'message' => 'File kosong']); exit;
}
// Parse CSV baris per baris
function parseCSVLine(string $line): array {
$cols = [];
$cur = '';
$inQ = false;
for ($i = 0; $i < strlen($line); $i++) {
$ch = $line[$i];
if ($ch === '"') { $inQ = !$inQ; }
elseif ($ch === ',' && !$inQ) { $cols[] = trim($cur, " \t\""); $cur = ''; }
else { $cur .= $ch; }
}
$cols[] = trim($cur, " \t\"");
return $cols;
}
// Deteksi header row
$firstLine = strtolower($lines[0]);
$hasHeader = str_contains($firstLine, 'nama') || str_contains($firstLine, 'lat') || str_contains($firstLine, 'kk_nama');
$dataLines = $hasHeader ? array_slice($lines, 1) : $lines;
$imported = 0;
$failed = 0;
$skipped = 0;
$errors = [];
// ── Import Penduduk Miskin ─────────────────────────────────────
if ($type === 'penduduk') {
$stmt = $db->prepare("
INSERT INTO penduduk_miskin
(kk_nama, nik, jumlah_anggota, alamat, kelurahan, kecamatan, lat, lng,
rumah_ibadah_id, jarak_ke_ibadah, status_bantuan, jenis_bantuan, tanggal_bantuan, nominal_bantuan)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)
");
foreach ($dataLines as $lineNum => $line) {
if (!trim($line)) continue;
$row = parseCSVLine($line);
// kk_nama (0), nik (1), jumlah_anggota (2), alamat (3), kelurahan (4),
// kecamatan (5), lat (6), lng (7), status_bantuan (8), jenis_bantuan (9),
// tanggal_bantuan (10), nominal_bantuan (11)
if (count($row) < 8 || empty($row[0]) || empty($row[6]) || empty($row[7])) {
$failed++;
$errors[] = "Baris " . ($lineNum + ($hasHeader ? 2 : 1)) . ": kolom tidak lengkap atau koordinat kosong";
if (count($errors) > 10) { $errors[] = '... dan lebih banyak error'; break; }
continue;
}
$lat = (float)$row[6];
$lng = (float)$row[7];
if ($lat === 0.0 && $lng === 0.0) { $skipped++; continue; }
$status = in_array($row[8] ?? '', ['sudah','belum','menunggu']) ? $row[8] : 'belum';
$tanggal_bantuan = !empty($row[10]) ? sanitize($row[10]) : null;
$nominal_bantuan = isset($row[11]) && $row[11] !== '' ? (float)str_replace(['.', ','], ['', '.'], $row[11]) : null;
$nearest = findNearestIbadah($lat, $lng);
$ibadahId = $nearest ? (int)$nearest['id'] : null;
$jarakIbadah = $nearest ? (float)$nearest['jarak'] : null;
try {
$stmt->execute([
sanitize($row[0]),
sanitize($row[1] ?? ''),
max(1, (int)($row[2] ?? 1)),
sanitize($row[3] ?? ''),
sanitize($row[4] ?? ''),
sanitize($row[5] ?? ''),
$lat, $lng,
$ibadahId,
$jarakIbadah,
$status,
sanitize($row[9] ?? ''),
$tanggal_bantuan,
$nominal_bantuan,
]);
$imported++;
} catch (PDOException $e) {
$failed++;
$errors[] = "Baris " . ($lineNum + ($hasHeader ? 2 : 1)) . ": " . $e->getMessage();
}
}
}
// ── Import Rumah Ibadah ───────────────────────────────────────
if ($type === 'ibadah') {
$validJenis = ['Masjid','Musholla','Gereja','Katolik','Pura','Vihara','Klenteng','Lainnya'];
$stmt = $db->prepare("
INSERT INTO rumah_ibadah (nama, jenis, kontak, alamat, kelurahan, kecamatan, lat, lng, radius)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
");
foreach ($dataLines as $lineNum => $line) {
if (!trim($line)) continue;
$row = parseCSVLine($line);
// nama (0), jenis (1), kontak (2), alamat (3), kelurahan (4),
// kecamatan (5), lat (6), lng (7), radius (8)
if (count($row) < 8 || empty($row[0]) || empty($row[6]) || empty($row[7])) {
$failed++;
$errors[] = "Baris " . ($lineNum + ($hasHeader ? 2 : 1)) . ": kolom tidak lengkap";
if (count($errors) > 10) { $errors[] = '... dan lebih banyak error'; break; }
continue;
}
$lat = (float)$row[6];
$lng = (float)$row[7];
if ($lat === 0.0 && $lng === 0.0) { $skipped++; continue; }
$jenis = in_array($row[1] ?? '', $validJenis) ? $row[1] : 'Lainnya';
$radius = max(100, min(5000, (int)($row[8] ?? RADIUS_DEFAULT)));
try {
$stmt->execute([
sanitize($row[0]),
$jenis,
sanitize($row[2] ?? ''),
sanitize($row[3] ?? ''),
sanitize($row[4] ?? ''),
sanitize($row[5] ?? ''),
$lat, $lng, $radius,
]);
$imported++;
} catch (PDOException $e) {
$failed++;
$errors[] = "Baris " . ($lineNum + ($hasHeader ? 2 : 1)) . ": " . $e->getMessage();
}
}
}
echo json_encode([
'success' => true,
'imported' => $imported,
'failed' => $failed,
'skipped' => $skipped,
'errors' => array_slice($errors, 0, 15),
'message' => "Import selesai: $imported berhasil, $failed gagal, $skipped dilewati",
], JSON_UNESCAPED_UNICODE);