beginTransaction(); try { // Verificar que el turno existe y está en recepción $stmt = $pdo->prepare( "SELECT id, estado FROM turnero_turnos WHERE id = ? FOR UPDATE" ); $stmt->execute([$turnoId]); $turno = $stmt->fetch(PDO::FETCH_ASSOC); if (!$turno) { $pdo->rollBack(); jsonError('Turno no encontrado.', 404); } if (!in_array($turno['estado'], ['en_recepcion', 'espera'], true)) { $pdo->rollBack(); jsonError("El turno está en estado '{$turno['estado']}' y no se puede editar su solicitud.", 422); } // Verificar que el lugar existe $stmt = $pdo->prepare("SELECT id FROM turnero_lugares WHERE id = ? AND activo = 1"); $stmt->execute([$lugarId]); if (!$stmt->fetch()) { $pdo->rollBack(); jsonError('Lugar destino no encontrado o inactivo.', 404); } // Verificar que todos los exam_tipo_ids existen $in = implode(',', array_fill(0, count($examIds), '?')); $stmt = $pdo->prepare("SELECT COUNT(*) FROM exam_tipos WHERE id IN ({$in}) AND activo = 1"); $stmt->execute($examIds); if ((int)$stmt->fetchColumn() !== count($examIds)) { $pdo->rollBack(); jsonError('Uno o más exámenes no existen o están inactivos.', 422); } // ── Insertar o reemplazar solicitud (DELETE + INSERT para poder re-guardar) ── $stmt = $pdo->prepare("SELECT id FROM turnero_solicitudes WHERE turno_id = ?"); $stmt->execute([$turnoId]); $solAnterior = $stmt->fetch(PDO::FETCH_ASSOC); if ($solAnterior) { // Eliminar ítemes anteriores (CASCADE borrará los turnero_examen_items) $pdo->prepare("DELETE FROM turnero_solicitudes WHERE turno_id = ?")->execute([$turnoId]); } $stmt = $pdo->prepare( "INSERT INTO turnero_solicitudes (turno_id, paciente_id, lugar_id, total_cobrado, metodo_pago, observaciones, creado_por) VALUES (?, ?, ?, ?, ?, ?, ?)" ); $stmt->execute([ $turnoId, $pacienteId, $lugarId, $total, $metodoPago ?: null, $obs ?: null, adminId(), ]); $solicitudId = (int) $pdo->lastInsertId(); // ── Insertar ítemes de examen ────────────────────────────── $stmtItem = $pdo->prepare( "INSERT INTO turnero_examen_items (solicitud_id, exam_tipo_id) VALUES (?, ?)" ); foreach ($examIds as $examId) { $stmtItem->execute([$solicitudId, $examId]); } // ── Consentimientos: todos los formularios activos del laboratorio ── // (no solo los vinculados a exámenes — el recepcionista elige cuáles aplican) $stmt = $pdo->prepare( "SELECT id AS formulario_id, nombre AS formulario_nombre FROM lab_formularios WHERE is_active = 1 ORDER BY nombre ASC" ); $stmt->execute(); $consentimientosRequeridos = $stmt->fetchAll(PDO::FETCH_ASSOC); // Agregar estado actual de cada consentimiento (si ya fue enviado antes) foreach ($consentimientosRequeridos as &$c) { $stC = $pdo->prepare( "SELECT estado FROM turnero_consentimientos WHERE turno_id = ? AND formulario_id = ?" ); $stC->execute([$turnoId, $c['formulario_id']]); $row = $stC->fetch(PDO::FETCH_ASSOC); $c['estado'] = $row['estado'] ?? 'pendiente'; } unset($c); $pdo->commit(); notificarSSE(obtenerOCrearSesionHoy()); // Recuperar solicitud completa $stmt = $pdo->prepare( "SELECT s.id, s.turno_id, s.paciente_id, s.lugar_id, s.total_cobrado, s.metodo_pago, s.observaciones, s.creado_at, p.nombre_completo AS paciente_nombre, p.numero_documento AS paciente_documento, l.nombre AS lugar_nombre FROM turnero_solicitudes s LEFT JOIN lab_pacientes p ON p.id = s.paciente_id LEFT JOIN turnero_lugares l ON l.id = s.lugar_id WHERE s.id = ?" ); $stmt->execute([$solicitudId]); $solicitud = $stmt->fetch(PDO::FETCH_ASSOC); jsonOk([ 'solicitud' => $solicitud, 'consentimientos_requeridos' => $consentimientosRequeridos, ], 'Solicitud guardada correctamente'); } catch (\Throwable $e) { if ($pdo->inTransaction()) $pdo->rollBack(); jsonError('Error al crear solicitud: ' . $e->getMessage(), 500); }