'Invalid JSON body']); exit; } if (!isset($data['head_name']) || trim((string)$data['head_name']) === '') { http_response_code(400); echo json_encode(['error' => 'Missing required field: head_name']); exit; } if (!isset($data['latitude']) || !isset($data['longitude'])) { http_response_code(400); echo json_encode(['error' => 'Missing required fields: latitude and longitude']); exit; } $error = null; if (!validateCoordinates($data['latitude'], $data['longitude'], $error)) { http_response_code(400); echo json_encode(['error' => $error]); exit; } $db = getDB(); $headName = trim((string)$data['head_name']); $latitude = (float)$data['latitude']; $longitude = (float)$data['longitude']; $monthlyIncome = normalizeMonthlyIncome($data['monthly_income'] ?? null, $error); if ($monthlyIncome === null) { http_response_code(400); echo json_encode(['error' => $error]); exit; } $dependentsCount = normalizeDependentsCount($data['dependents_count'] ?? null, $error); if ($dependentsCount === null) { http_response_code(400); echo json_encode(['error' => $error]); exit; } $housingConditionScore = normalizeHousingConditionScore($data['housing_condition_score'] ?? null, $error); if ($housingConditionScore === null) { http_response_code(400); echo json_encode(['error' => $error]); exit; } $employmentStatus = normalizeEmploymentStatus($data['employment_status'] ?? null, $error); if ($employmentStatus === null) { http_response_code(400); echo json_encode(['error' => $error]); exit; } $economicStatus = isset($data['economic_status']) ? strtolower(trim((string)$data['economic_status'])) : 'unknown'; $allowedEconomicStatuses = ['sangat_miskin', 'miskin', 'rentan', 'cukup', 'baik', 'unknown']; if (!in_array($economicStatus, $allowedEconomicStatuses, true)) { http_response_code(400); echo json_encode(['error' => 'economic_status is invalid']); exit; } $verificationStatus = normalizeVerificationStatus($data['verification_status'] ?? null, $error, true); if ($verificationStatus === null) { http_response_code(400); echo json_encode(['error' => $error]); exit; } $needPointId = null; if (array_key_exists('need_point_id', $data) && $data['need_point_id'] !== null && $data['need_point_id'] !== '') { if (!is_numeric($data['need_point_id'])) { http_response_code(400); echo json_encode(['error' => 'need_point_id must be numeric']); exit; } $needPointId = (int)$data['need_point_id']; $needPointStmt = $db->prepare('SELECT id, masjid_id FROM need_points WHERE id = ?'); $needPointStmt->execute([$needPointId]); $needPoint = $needPointStmt->fetch(PDO::FETCH_ASSOC); if (!$needPoint) { http_response_code(400); echo json_encode(['error' => 'need_point_id is not found']); exit; } } $masjidId = null; if (array_key_exists('masjid_id', $data) && $data['masjid_id'] !== null && $data['masjid_id'] !== '') { if (!is_numeric($data['masjid_id'])) { http_response_code(400); echo json_encode(['error' => 'masjid_id must be numeric']); exit; } $masjidId = (int)$data['masjid_id']; $masjidStmt = $db->prepare('SELECT id FROM masjids WHERE id = ?'); $masjidStmt->execute([$masjidId]); if (!$masjidStmt->fetch(PDO::FETCH_ASSOC)) { http_response_code(400); echo json_encode(['error' => 'masjid_id is not found']); exit; } } if ($masjidId === null) { if ($needPointId !== null) { $npMasjidStmt = $db->prepare('SELECT masjid_id FROM need_points WHERE id = ?'); $npMasjidStmt->execute([$needPointId]); $npMasjid = $npMasjidStmt->fetch(PDO::FETCH_ASSOC); if ($npMasjid && isset($npMasjid['masjid_id'])) { $masjidId = (int)$npMasjid['masjid_id']; } } if ($masjidId === null) { $nearestMasjid = findNearestMasjidCoveringPoint($db, $latitude, $longitude); if ($nearestMasjid) { $masjidId = (int)$nearestMasjid['id']; } } } $pontianakAreaId = null; if (array_key_exists('pontianak_area_id', $data) && $data['pontianak_area_id'] !== null && $data['pontianak_area_id'] !== '') { if (!is_numeric($data['pontianak_area_id'])) { http_response_code(400); echo json_encode(['error' => 'pontianak_area_id must be numeric']); exit; } $pontianakAreaId = (int)$data['pontianak_area_id']; $areaStmt = $db->prepare('SELECT id FROM pontianak_areas WHERE id = ?'); $areaStmt->execute([$pontianakAreaId]); if (!$areaStmt->fetch(PDO::FETCH_ASSOC)) { http_response_code(400); echo json_encode(['error' => 'pontianak_area_id is not found']); exit; } } $householdCode = normalizeHouseholdCode($db, $data['household_code'] ?? null); $nikHash = null; if (array_key_exists('nik', $data)) { $nikHash = normalizeNikHashFromInput($data['nik']); } else if (array_key_exists('nik_hash', $data)) { $nikHash = trim((string)$data['nik_hash']); if ($nikHash === '') { $nikHash = null; } } $vulnerabilityNotes = isset($data['vulnerability_notes']) ? trim((string)$data['vulnerability_notes']) : null; if ($vulnerabilityNotes === '') { $vulnerabilityNotes = null; } $insertStmt = $db->prepare(' INSERT INTO households ( household_code, head_name, nik_hash, latitude, longitude, need_point_id, masjid_id, pontianak_area_id, monthly_income, dependents_count, housing_condition_score, employment_status, economic_status, verification_status, vulnerability_notes ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) '); $insertStmt->execute([ $householdCode, $headName, $nikHash, $latitude, $longitude, $needPointId, $masjidId, $pontianakAreaId, $monthlyIncome, $dependentsCount, $housingConditionScore, $employmentStatus, $economicStatus, $verificationStatus, $vulnerabilityNotes ]); $id = (int)$db->lastInsertId(); $household = getHouseholdById($db, $id); echo json_encode([ 'success' => true, 'household' => $household ]); } catch (PDOException $e) { if ($e->getCode() === '23000') { http_response_code(409); echo json_encode(['error' => 'Duplicate household_code or need_point_id mapping']); exit; } http_response_code(500); echo json_encode(['error' => $e->getMessage()]); } catch (Exception $e) { http_response_code(500); echo json_encode(['error' => $e->getMessage()]); } } else { http_response_code(405); echo json_encode(['error' => 'Method not allowed']); } ?>