185 lines
6.7 KiB
PHP
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','darurat']) ? $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);
|