El arreglo anterior dejó un defecto: obtenerOCrearDesdeWhatsapp() copiaba users.phone_number al teléfono de la ficha, y para quien oculta su número ahí va el BSUID. normalizarTelefono() le quitaba el punto y las letras, así que "CO.1761088155094242" quedaba guardado como "1761088155094242": un número de 16 dígitos, falso, con apariencia de real, dentro de una historia clínica y sin que nadie lo notara. Ahora esa ficha se crea sin teléfono, que es la verdad: no lo tenemos. - esBsuid() queda definido una sola vez, en config.php, que es donde lo ven tanto el servicio de WhatsApp como las clases del laboratorio. - La lista y el detalle de pacientes dicen "Solo por WhatsApp" en vez de mostrar el identificador crudo: recepción necesita entender por qué no puede llamar, no ver un código. - Al crear la ficha desde una conversación se le pide el número con el botón de Meta, una sola vez (users.contacto_pedido_at). El texto es editable desde configuración. Solo se marca como pedido si Meta aceptó el envío, para poder reintentar si falló. - tests/test_bsuid.php: 30 verificaciones sobre identidad, envío, vinculación y creación de fichas. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
167 lines
6.5 KiB
PHP
167 lines
6.5 KiB
PHP
<?php
|
|
/**
|
|
* API: Crear orden médica desde conversación de WhatsApp
|
|
*
|
|
* GET ?solo_paciente=1&conversation_id=X → obtiene/crea paciente del contacto
|
|
* POST { paciente_id, conversation_id, local_file, media_message_id, ... }
|
|
* → crea lab_ordenes_medicas
|
|
*/
|
|
require_once __DIR__ . '/../../config/config.php';
|
|
require_once __DIR__ . '/../../classes/Database.php';
|
|
require_once __DIR__ . '/../../classes/lab/ActividadAdmin.php';
|
|
require_once __DIR__ . '/../../classes/lab/Paciente.php';
|
|
require_once __DIR__ . '/../../classes/lab/OrdenMedica.php';
|
|
|
|
// Helpers inline (similar a _helpers.php pero sin incluir todas las clases de nuevo)
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
header('X-Content-Type-Options: nosniff');
|
|
|
|
requireAuthentication();
|
|
|
|
$adminId = (int)($_SESSION['admin_user']['id'] ?? 0);
|
|
$db = Database::getInstance();
|
|
|
|
/**
|
|
* Le pide el teléfono a quien lo tiene oculto en WhatsApp, una sola vez.
|
|
*
|
|
* Solo aplica a quien se identifica con un BSUID: de esa persona no tenemos
|
|
* número, y sin él el laboratorio no puede llamarla. Se le manda el botón que
|
|
* Meta dispone para esto y ella decide si lo comparte; si acepta, el webhook
|
|
* recibe el teléfono y lo vincula solo.
|
|
*
|
|
* No se insiste: pedir los datos una vez es razonable, repetirlo en cada
|
|
* trámite es acoso. Tampoco se interrumpe la creación de la ficha si el envío
|
|
* falla, porque la ficha es lo importante.
|
|
*
|
|
* @return string qué pasó, para que la interfaz lo pueda mostrar
|
|
*/
|
|
function pedirContactoSiHaceFalta(Database $db, int $userId): string {
|
|
$u = $db->fetch(
|
|
'SELECT phone_number, contacto_pedido_at FROM users WHERE id = ?',
|
|
[$userId]
|
|
);
|
|
if (!$u) return 'usuario_no_encontrado';
|
|
if (!esBsuid($u['phone_number'])) return 'no_hace_falta'; // ya tenemos su número
|
|
if (!empty($u['contacto_pedido_at'])) return 'ya_se_pidio';
|
|
|
|
try {
|
|
require_once __DIR__ . '/../../services/WhatsAppService.php';
|
|
$wa = new WhatsAppService();
|
|
$texto = getConfigFromDB(
|
|
'whatsapp_texto_pedir_contacto',
|
|
'Para poder registrar su atención necesitamos un número de contacto. ¿Nos comparte el suyo?'
|
|
);
|
|
|
|
$r = $wa->pedirContacto($u['phone_number'], $texto);
|
|
if (!$r) {
|
|
error_log('[crear_desde_whatsapp] WhatsApp rechazó la solicitud de contacto del usuario ' . $userId);
|
|
return 'fallo_envio';
|
|
}
|
|
|
|
// Se marca solo si Meta aceptó: si falló, hay que poder reintentarlo
|
|
$db->update('users', ['contacto_pedido_at' => date('Y-m-d H:i:s')], 'id = ?', [$userId]);
|
|
return 'pedido';
|
|
|
|
} catch (Exception $e) {
|
|
error_log('[crear_desde_whatsapp] Error pidiendo el contacto: ' . $e->getMessage());
|
|
return 'fallo_envio';
|
|
}
|
|
}
|
|
|
|
// ── GET: solo_paciente ─────────────────────────────────────────────────────
|
|
if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['solo_paciente'])) {
|
|
$convId = (int)($_GET['conversation_id'] ?? 0);
|
|
$userId = (int)($_GET['user_id'] ?? 0);
|
|
|
|
if (!$convId && !$userId) {
|
|
echo json_encode(['success' => false, 'error' => 'conversation_id o user_id requerido']);
|
|
exit;
|
|
}
|
|
|
|
// Obtener user_id y phone_number: por conversation_id o directamente por user_id
|
|
if ($convId) {
|
|
$conv = $db->fetch(
|
|
'SELECT c.id, c.user_id, u.phone_number, u.name AS whatsapp_name
|
|
FROM conversations c
|
|
JOIN users u ON u.id = c.user_id
|
|
WHERE c.id = ?',
|
|
[$convId]
|
|
);
|
|
} else {
|
|
$conv = $db->fetch(
|
|
'SELECT u.id AS user_id, u.phone_number, u.name AS whatsapp_name
|
|
FROM users u
|
|
WHERE u.id = ?',
|
|
[$userId]
|
|
);
|
|
}
|
|
|
|
if (!$conv) {
|
|
echo json_encode(['success' => false, 'error' => 'Conversación / usuario no encontrado']);
|
|
exit;
|
|
}
|
|
|
|
$pacienteRepo = new Paciente();
|
|
$pacienteId = $pacienteRepo->obtenerOCrearDesdeWhatsapp($conv['user_id']);
|
|
$paciente = $pacienteRepo->obtener($pacienteId);
|
|
|
|
// Si la persona oculta su teléfono, la ficha queda sin número. Es el momento
|
|
// de pedírselo: se le manda el botón de WhatsApp una sola vez.
|
|
$contactoPedido = pedirContactoSiHaceFalta($db, (int) $conv['user_id']);
|
|
|
|
echo json_encode([
|
|
'success' => true,
|
|
'paciente' => $paciente,
|
|
'contacto_pedido' => $contactoPedido,
|
|
]);
|
|
exit;
|
|
}
|
|
|
|
// ── POST: crear orden ──────────────────────────────────────────────────────
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
|
http_response_code(405);
|
|
echo json_encode(['success' => false, 'error' => 'Método no permitido']);
|
|
exit;
|
|
}
|
|
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
if (!$input) {
|
|
echo json_encode(['success' => false, 'error' => 'Datos inválidos']);
|
|
exit;
|
|
}
|
|
|
|
$pacienteId = (int)($input['paciente_id'] ?? 0);
|
|
if (!$pacienteId) {
|
|
echo json_encode(['success' => false, 'error' => 'paciente_id requerido']);
|
|
exit;
|
|
}
|
|
|
|
// Construir datos de la orden
|
|
$datos = [
|
|
'paciente_id' => $pacienteId,
|
|
'conversation_id' => !empty($input['conversation_id']) ? (int)$input['conversation_id'] : null,
|
|
'local_file' => $input['local_file'] ?? null,
|
|
'media_message_id' => $input['media_message_id'] ?? null,
|
|
'medico_nombre' => $input['medico_nombre'] ?? null,
|
|
'fecha_orden' => !empty($input['fecha_orden']) ? $input['fecha_orden'] : null,
|
|
'examenes_solicitados'=> $input['examenes_solicitados']?? null,
|
|
'requiere_ayuno' => isset($input['requiere_ayuno']) ? (int)$input['requiere_ayuno'] : 0,
|
|
'horas_ayuno' => !empty($input['horas_ayuno']) ? (int)$input['horas_ayuno'] : null,
|
|
'notas_admin' => $input['notas_admin'] ?? null,
|
|
'estado' => 'pendiente',
|
|
];
|
|
|
|
try {
|
|
$orden = new OrdenMedica();
|
|
$ordenId = $orden->crear($datos, $adminId);
|
|
|
|
echo json_encode([
|
|
'success' => true,
|
|
'orden_id' => $ordenId,
|
|
'message' => "Orden médica #$ordenId creada correctamente",
|
|
]);
|
|
} catch (Exception $e) {
|
|
error_log('[lab/crear_desde_whatsapp] ' . $e->getMessage());
|
|
echo json_encode(['success' => false, 'error' => 'Error interno: ' . $e->getMessage()]);
|
|
}
|