(sin sesión de usuario). * * Body JSON (todos opcionales excepto nombre_completo en creación): * { numero_documento, tipo_documento, nombre_completo, telefono, email, * fecha_nacimiento, genero, direccion, ciudad, eps, origen } * * Respuesta: * { ok, action: "created"|"updated"|"skipped", id, message } */ ob_start(); require_once __DIR__ . '/../../config/config.php'; require_once __DIR__ . '/../../classes/lab/Paciente.php'; error_reporting(E_ERROR | E_PARSE); ini_set('display_errors', '0'); ini_set('html_errors', '0'); register_shutdown_function(function () { $err = error_get_last(); if ($err && in_array($err['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) { ob_clean(); http_response_code(500); header('Content-Type: application/json; charset=utf-8'); echo json_encode(['ok' => false, 'error' => 'Error interno: ' . $err['message']]); } }); header('Content-Type: application/json; charset=utf-8'); header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: POST, OPTIONS'); header('Access-Control-Allow-Headers: Content-Type, X-Lab-Key, X-Lab-Sync-Key'); header('Access-Control-Max-Age: 86400'); if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(204); exit; } if ($_SERVER['REQUEST_METHOD'] !== 'POST') { http_response_code(405); echo json_encode(['ok' => false, 'error' => 'Método no permitido']); exit; } // ── Autenticación por API key ──────────────────────────────────────────────── $keyHeader = $_SERVER['HTTP_X_LAB_KEY'] ?? $_SERVER['HTTP_X_LAB_SYNC_KEY'] ?? ''; if (!$keyHeader || !hash_equals(LAB_SYNC_KEY, $keyHeader)) { http_response_code(401); ob_clean(); echo json_encode(['ok' => false, 'error' => 'API key inválida']); exit; } // ── Leer body ──────────────────────────────────────────────────────────────── $raw = file_get_contents('php://input'); $data = json_decode($raw, true); if (!is_array($data)) { http_response_code(400); ob_clean(); echo json_encode(['ok' => false, 'error' => 'Body JSON inválido']); exit; } // ── Normalizar campos ──────────────────────────────────────────────────────── $campos = []; if (!empty($data['nombre_completo'])) { $campos['nombre_completo'] = mb_strtoupper(trim($data['nombre_completo'])); } if (!empty($data['numero_documento'])) { $campos['numero_documento'] = trim($data['numero_documento']); } if (!empty($data['tipo_documento'])) { $tiposValidos = ['CC', 'CE', 'TI', 'PA', 'NIT', 'RC', 'MS']; $t = strtoupper(trim($data['tipo_documento'])); $campos['tipo_documento'] = in_array($t, $tiposValidos) ? $t : 'CC'; } if (!empty($data['telefono'])) { $tel = preg_replace('/[^0-9+]/', '', $data['telefono']); if (strlen($tel) >= 6) { $campos['telefono'] = $tel; } } if (!empty($data['email']) && filter_var($data['email'], FILTER_VALIDATE_EMAIL)) { $e = strtolower(trim($data['email'])); // Ignorar emails de relleno generados por RIPS if (!str_contains($e, '@sinregistro.co') && !str_contains($e, 'sinregistro')) { $campos['email'] = $e; } } if (!empty($data['fecha_nacimiento'])) { $fn = trim($data['fecha_nacimiento']); // Acepta dd/mm/yyyy o yyyy-mm-dd if (preg_match('/^(\d{2})\/(\d{2})\/(\d{4})$/', $fn, $m)) { $campos['fecha_nacimiento'] = "{$m[3]}-{$m[2]}-{$m[1]}"; } elseif (preg_match('/^\d{4}-\d{2}-\d{2}$/', $fn)) { $campos['fecha_nacimiento'] = $fn; } } if (!empty($data['genero'])) { $g = strtoupper(trim($data['genero'])); if (in_array($g, ['M', 'F', 'O'])) { $campos['genero'] = $g; } } if (!empty($data['direccion'])) { $campos['direccion'] = trim($data['direccion']); } if (!empty($data['ciudad'])) { $campos['ciudad'] = trim($data['ciudad']); } if (!empty($data['eps'])) { $campos['eps'] = trim($data['eps']); } // origen solo se aplica en creación, nunca en update $origenValidos = ['manual', 'lab', 'whatsapp']; $campos['origen'] = in_array($data['origen'] ?? '', $origenValidos, true) ? $data['origen'] : 'lab'; // ── Modo: "insertar" (solo nuevos) | "upsert" (crea o actualiza) ───────────── $modo = trim($data['modo'] ?? 'upsert'); if (!in_array($modo, ['insertar', 'upsert'], true)) { $modo = 'upsert'; } // ── UPSERT / INSERT-ONLY ───────────────────────────────────────────────────── try { $pac = new Paciente(); $existente = null; if (!empty($campos['numero_documento'])) { $existente = $pac->porDocumento($campos['numero_documento']); } ob_clean(); if ($existente) { if ($modo === 'insertar') { echo json_encode([ 'ok' => true, 'action' => 'skipped', 'id' => $existente['id'], 'message' => 'Paciente ya existe', ]); } else { // Nunca pisar origen en update — conservar el que ya tiene en BD unset($campos['origen']); $pac->actualizar($existente['id'], $campos, null); echo json_encode([ 'ok' => true, 'action' => 'updated', 'id' => $existente['id'], 'message' => 'Paciente actualizado', ]); } } elseif (!empty($campos['nombre_completo'])) { $id = $pac->crear($campos, null); echo json_encode([ 'ok' => true, 'action' => 'created', 'id' => $id, 'message' => 'Paciente creado', ]); } else { http_response_code(422); echo json_encode([ 'ok' => false, 'action' => 'skipped', 'error' => 'Sin número de documento ni nombre: registro omitido', ]); } } catch (Exception $e) { ob_clean(); http_response_code(500); echo json_encode(['ok' => false, 'error' => $e->getMessage()]); }