You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

465 lines
16 KiB
PHP

<?php
namespace App\Http\Controllers\Administracion;
use App\Http\Controllers\Controller;
use App\Models\Academia;
use App\Models\User;
use App\Models\Examen;
use App\Models\Pregunta;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Carbon\Carbon;
class ExamenesController extends Controller
{
public function getExamenes(Request $request)
{
try {
$user = auth()->user();
if (!$user->hasRole('administrador')) {
return response()->json([
'success' => false,
'message' => 'No autorizado'
], 403);
}
$academia = Academia::where('admin_academia_id', $user->id)->first();
if (!$academia) {
return response()->json([
'success' => false,
'message' => 'Academia no encontrada'
], 404);
}
$query = $academia->examenes()
->withCount(['preguntas', 'intentos' => function($query) {
$query->where('estado', 'finalizado');
}])
->latest();
if ($request->has('search')) {
$search = $request->search;
$query->where('titulo', 'like', "%{$search}%");
}
if ($request->has('publicado')) {
$query->where('publicado', $request->publicado);
}
if ($request->has('tipo')) {
$query->where('tipo', $request->tipo);
}
$examenes = $query->paginate(15);
return response()->json([
'success' => true,
'data' => $examenes
]);
} catch (\Exception $e) {
Log::error('Error obteniendo exámenes', [
'error' => $e->getMessage()
]);
return response()->json([
'success' => false,
'message' => 'Error al cargar los exámenes'
], 500);
}
}
public function crearExamen(Request $request)
{
try {
$user = auth()->user();
if (!$user->hasRole('administrador')) {
return response()->json([
'success' => false,
'message' => 'No autorizado'
], 403);
}
$academia = Academia::where('admin_academia_id', $user->id)->first();
if (!$academia) {
return response()->json([
'success' => false,
'message' => 'Academia no encontrada'
], 404);
}
$validator = Validator::make($request->all(), [
'titulo' => 'required|string|max:255',
'descripcion' => 'nullable|string',
'tipo' => 'required|in:practica,simulacro,evaluacion',
'dificultad' => 'required|in:facil,medio,dificil,avanzado',
'duracion_minutos' => 'required|integer|min:1|max:480',
'intentos_permitidos' => 'required|integer|min:1|max:10',
'puntaje_minimo' => 'required|numeric|min:0|max:100',
'preguntas_aleatorias' => 'boolean',
'mostrar_resultados' => 'boolean',
'mostrar_respuestas' => 'boolean',
'publicado' => 'boolean',
'fecha_inicio' => 'nullable|date',
'fecha_fin' => 'nullable|date|after_or_equal:fecha_inicio',
'configuracion' => 'nullable|array'
]);
if ($validator->fails()) {
return response()->json([
'success' => false,
'errors' => $validator->errors()
], 422);
}
DB::beginTransaction();
$examen = Examen::create([
'academia_id' => $academia->id,
'titulo' => $request->titulo,
'descripcion' => $request->descripcion,
'tipo' => $request->tipo,
'dificultad' => $request->dificultad,
'duracion_minutos' => $request->duracion_minutos,
'intentos_permitidos' => $request->intentos_permitidos,
'puntaje_minimo' => $request->puntaje_minimo,
'preguntas_aleatorias' => $request->preguntas_aleatorias ?? 0,
'mezclar_opciones' => $request->mezclar_opciones ?? true,
'mostrar_resultados' => $request->mostrar_resultados ?? true,
'mostrar_respuestas' => $request->mostrar_respuestas ?? false,
'mostrar_explicaciones' => $request->mostrar_explicaciones ?? false,
'activar_timer' => $request->activar_timer ?? true,
'permitir_navegacion' => $request->permitir_navegacion ?? true,
'permitir_revisar' => $request->permitir_revisar ?? true,
'publicado' => $request->publicado ?? false,
'fecha_inicio' => $request->fecha_inicio,
'fecha_fin' => $request->fecha_fin,
'orden' => $request->orden ?? 1,
'configuracion' => $request->configuracion ?? []
]);
DB::commit();
Log::info('Examen creado por admin', [
'academia_id' => $academia->id,
'examen_id' => $examen->id,
'admin_id' => $user->id
]);
return response()->json([
'success' => true,
'message' => 'Examen creado exitosamente',
'data' => $examen
], 201);
} catch (\Exception $e) {
DB::rollBack();
Log::error('Error creando examen', [
'error' => $e->getMessage()
]);
return response()->json([
'success' => false,
'message' => 'Error al crear el examen'
], 500);
}
}
public function getExamen($examenId)
{
try {
$user = auth()->user();
if (!$user->hasRole('administrador')) {
return response()->json([
'success' => false,
'message' => 'No autorizado'
], 403);
}
$academia = Academia::where('admin_academia_id', $user->id)->first();
if (!$academia) {
return response()->json([
'success' => false,
'message' => 'Academia no encontrada'
], 404);
}
$examen = Examen::where('academia_id', $academia->id)
->with(['preguntas'])
->find($examenId);
if (!$examen) {
return response()->json([
'success' => false,
'message' => 'Examen no encontrado'
], 404);
}
$estadisticas = DB::table('intentos_examen')
->where('examen_id', $examenId)
->where('estado', 'finalizado')
->selectRaw('COUNT(*) as total_intentos')
->selectRaw('AVG(porcentaje) as promedio')
->selectRaw('SUM(CASE WHEN aprobado = 1 THEN 1 ELSE 0 END) as aprobados')
->first();
return response()->json([
'success' => true,
'data' => [
'examen' => $examen,
'estadisticas' => $estadisticas
]
]);
} catch (\Exception $e) {
Log::error('Error obteniendo examen', [
'error' => $e->getMessage()
]);
return response()->json([
'success' => false,
'message' => 'Error al cargar el examen'
], 500);
}
}
public function actualizarExamen(Request $request, $examenId)
{
try {
$user = auth()->user();
if (!$user->hasRole('administrador')) {
return response()->json([
'success' => false,
'message' => 'No autorizado'
], 403);
}
$academia = Academia::where('admin_academia_id', $user->id)->first();
if (!$academia) {
return response()->json([
'success' => false,
'message' => 'Academia no encontrada'
], 404);
}
$examen = Examen::where('academia_id', $academia->id)->find($examenId);
if (!$examen) {
return response()->json([
'success' => false,
'message' => 'Examen no encontrado'
], 404);
}
$validator = Validator::make($request->all(), [
'titulo' => 'sometimes|string|max:255',
'descripcion' => 'nullable|string',
'tipo' => 'sometimes|in:practica,simulacro,evaluacion',
'duracion_minutos' => 'sometimes|integer|min:1|max:480',
'intentos_permitidos' => 'sometimes|integer|min:1|max:10',
'puntaje_minimo' => 'sometimes|numeric|min:0|max:100',
'preguntas_aleatorias' => 'boolean',
'mostrar_resultados' => 'boolean',
'mostrar_respuestas' => 'boolean',
'publicado' => 'boolean',
'fecha_inicio' => 'nullable|date',
'fecha_fin' => 'nullable|date|after_or_equal:fecha_inicio',
'configuracion' => 'nullable|array'
]);
if ($validator->fails()) {
return response()->json([
'success' => false,
'errors' => $validator->errors()
], 422);
}
$examen->update($request->only([
'titulo', 'descripcion', 'tipo', 'duracion_minutos', 'intentos_permitidos',
'puntaje_minimo', 'preguntas_aleatorias', 'mostrar_resultados',
'mostrar_respuestas', 'publicado', 'fecha_inicio', 'fecha_fin', 'configuracion'
]));
Log::info('Examen actualizado por admin', [
'academia_id' => $academia->id,
'examen_id' => $examen->id,
'admin_id' => $user->id
]);
return response()->json([
'success' => true,
'message' => 'Examen actualizado exitosamente',
'data' => $examen
]);
} catch (\Exception $e) {
Log::error('Error actualizando examen', [
'error' => $e->getMessage()
]);
return response()->json([
'success' => false,
'message' => 'Error al actualizar el examen'
], 500);
}
}
public function eliminarExamen($examenId)
{
try {
$user = auth()->user();
if (!$user->hasRole('administrador')) {
return response()->json([
'success' => false,
'message' => 'No autorizado'
], 403);
}
$academia = Academia::where('admin_academia_id', $user->id)->first();
if (!$academia) {
return response()->json([
'success' => false,
'message' => 'Academia no encontrada'
], 404);
}
$examen = Examen::where('academia_id', $academia->id)->find($examenId);
if (!$examen) {
return response()->json([
'success' => false,
'message' => 'Examen no encontrado'
], 404);
}
$tieneIntentos = $examen->intentos()->exists();
if ($tieneIntentos) {
return response()->json([
'success' => false,
'message' => 'No se puede eliminar un examen con intentos realizados'
], 400);
}
$examen->delete();
Log::info('Examen eliminado por admin', [
'academia_id' => $academia->id,
'examen_id' => $examenId,
'admin_id' => $user->id
]);
return response()->json([
'success' => true,
'message' => 'Examen eliminado exitosamente'
]);
} catch (\Exception $e) {
Log::error('Error eliminando examen', [
'error' => $e->getMessage()
]);
return response()->json([
'success' => false,
'message' => 'Error al eliminar el examen'
], 500);
}
}
public function getResultadosExamen($examenId)
{
try {
$user = auth()->user();
if (!$user->hasRole('administrador')) {
return response()->json([
'success' => false,
'message' => 'No autorizado'
], 403);
}
$academia = Academia::where('admin_academia_id', $user->id)->first();
if (!$academia) {
return response()->json([
'success' => false,
'message' => 'Academia no encontrada'
], 404);
}
$examen = Examen::where('academia_id', $academia->id)->find($examenId);
if (!$examen) {
return response()->json([
'success' => false,
'message' => 'Examen no encontrado'
], 404);
}
$resultados = DB::table('intentos_examen')
->join('users', 'intentos_examen.user_id', '=', 'users.id')
->where('intentos_examen.examen_id', $examenId)
->where('intentos_examen.estado', 'finalizado')
->select(
'users.id as estudiante_id',
'users.name as estudiante_nombre',
'users.email as estudiante_email',
'intentos_examen.numero_intento',
'intentos_examen.porcentaje',
'intentos_examen.aprobado',
'intentos_examen.tiempo_utilizado',
'intentos_examen.finalizado_en'
)
->orderBy('intentos_examen.porcentaje', 'desc')
->get();
$estadisticas = [
'total_estudiantes' => $resultados->groupBy('estudiante_id')->count(),
'promedio' => $resultados->avg('porcentaje'),
'aprobados' => $resultados->where('aprobado', true)->count(),
'reprobados' => $resultados->where('aprobado', false)->count(),
'tiempo_promedio' => $resultados->avg('tiempo_utilizado')
];
return response()->json([
'success' => true,
'data' => [
'resultados' => $resultados,
'estadisticas' => $estadisticas
]
]);
} catch (\Exception $e) {
Log::error('Error obteniendo resultados', [
'error' => $e->getMessage()
]);
return response()->json([
'success' => false,
'message' => 'Error al cargar los resultados'
], 500);
}
}
}