84 lines
3.4 KiB
PHP
84 lines
3.4 KiB
PHP
<?php
|
|
/**
|
|
* api/warga_import.php — Import data warga dari CSV (KF-15).
|
|
* Template kolom (Lampiran A):
|
|
* nik_kk, nama_kk, kode_kelurahan, latitude, longitude,
|
|
* jumlah_jiwa, sumber_air, status_listrik, material_dinding, pekerjaan_kk
|
|
*/
|
|
require_once __DIR__ . '/../config/db.php';
|
|
require_once __DIR__ . '/helpers.php';
|
|
require_once __DIR__ . '/../config/activity.php';
|
|
|
|
$pdo = Database::getConnection();
|
|
requireApiAnyRole(['operator']);
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') sendError('Method not allowed', 405);
|
|
if (empty($_FILES['file']['tmp_name'])) sendError('File CSV wajib diunggah');
|
|
|
|
$fh = fopen($_FILES['file']['tmp_name'], 'r');
|
|
if (!$fh) sendError('Gagal membaca file');
|
|
|
|
// Peta kode kelurahan -> id
|
|
$wmap = [];
|
|
foreach ($pdo->query("SELECT id, kode_wilayah FROM wilayah") as $w) {
|
|
if ($w['kode_wilayah']) $wmap[trim($w['kode_wilayah'])] = $w['id'];
|
|
}
|
|
|
|
$header = fgetcsv($fh);
|
|
if (!$header) sendError('CSV kosong');
|
|
$header = array_map(fn($h) => strtolower(trim($h)), $header);
|
|
$idx = array_flip($header);
|
|
|
|
$need = ['nama_kk', 'latitude', 'longitude'];
|
|
foreach ($need as $col) {
|
|
if (!isset($idx[$col])) sendError("Kolom wajib '$col' tidak ditemukan di CSV");
|
|
}
|
|
|
|
$enumAir = ['SUMUR_BOR','PDAM','SUNGAI','HUJAN','TIDAK_ADA'];
|
|
$enumListrik = ['PLN','NON_PLN','TIDAK_ADA'];
|
|
$enumDinding = ['PERMANEN','SEMI_PERMANEN','TIDAK_PERMANEN'];
|
|
$val = fn($row, $key) => isset($idx[$key]) && isset($row[$idx[$key]]) ? trim($row[$idx[$key]]) : null;
|
|
$enumOrNull = fn($v, $allowed) => ($v && in_array(strtoupper($v), $allowed, true)) ? strtoupper($v) : null;
|
|
|
|
$ins = $pdo->prepare("
|
|
INSERT INTO warga_miskin
|
|
(nama_kk, nik_kk, wilayah_id, jumlah_jiwa, pekerjaan_kk, penghasilan, jumlah_tanggungan,
|
|
sumber_air, status_listrik, material_dinding, status_verifikasi, created_by, geom)
|
|
VALUES (?,?,?,?,?,?,?,?,?,?, 'belum', ?, ST_GeomFromText(?))
|
|
");
|
|
|
|
$ok = 0; $fail = 0; $errors = []; $line = 1;
|
|
while (($row = fgetcsv($fh)) !== false) {
|
|
$line++;
|
|
if (count(array_filter($row, fn($x) => $x !== '' && $x !== null)) === 0) continue; // baris kosong
|
|
$nama = $val($row, 'nama_kk');
|
|
$lat = $val($row, 'latitude');
|
|
$lng = $val($row, 'longitude');
|
|
if (!$nama) { $fail++; $errors[] = "Baris $line: nama_kk kosong"; continue; }
|
|
if (!is_numeric($lat) || !is_numeric($lng)) { $fail++; $errors[] = "Baris $line: koordinat tidak valid"; continue; }
|
|
|
|
$kode = $val($row, 'kode_kelurahan');
|
|
$wid = ($kode && isset($wmap[$kode])) ? $wmap[$kode] : null;
|
|
try {
|
|
$ins->execute([
|
|
$nama, $val($row, 'nik_kk'), $wid,
|
|
($val($row, 'jumlah_jiwa') !== null && $val($row, 'jumlah_jiwa') !== '') ? (int)$val($row, 'jumlah_jiwa') : null,
|
|
$val($row, 'pekerjaan_kk'),
|
|
(float)($val($row, 'penghasilan') ?? 0),
|
|
(int)($val($row, 'jumlah_tanggungan') ?? 0),
|
|
$enumOrNull($val($row, 'sumber_air'), $enumAir),
|
|
$enumOrNull($val($row, 'status_listrik'), $enumListrik),
|
|
$enumOrNull($val($row, 'material_dinding'), $enumDinding),
|
|
$_SESSION['user_id'] ?? null,
|
|
sprintf('POINT(%F %F)', (float)$lng, (float)$lat),
|
|
]);
|
|
$ok++;
|
|
} catch (Exception $e) {
|
|
$fail++; $errors[] = "Baris $line: " . $e->getMessage();
|
|
}
|
|
}
|
|
fclose($fh);
|
|
|
|
logActivity($pdo, 'create', 'warga_miskin', null, "Import CSV: $ok berhasil, $fail gagal");
|
|
sendSuccess(['berhasil' => $ok, 'gagal' => $fail, 'errors' => array_slice($errors, 0, 15)], 'Import selesai');
|