examenService = $examenService; } public function procesoexamen(Request $request) { $postulante = $request->user(); $procesos = Proceso::where('activo', 1) ->whereNotExists(function ($q) use ($postulante) { $q->select(\DB::raw(1)) ->from('examenes') ->join('area_proceso', 'area_proceso.id', '=', 'examenes.area_proceso_id') ->whereColumn('area_proceso.proceso_id', 'procesos.id') ->where('examenes.postulante_id', $postulante->id); }) ->select('id', 'nombre', 'requiere_pago') ->get(); return response()->json($procesos); } public function areas(Request $request) { $procesoId = $request->query('proceso_id'); $areas = Area::select('areas.id', 'areas.nombre') ->whereHas('procesos', function ($query) use ($procesoId) { $query->where('procesos.id', $procesoId) ->where('procesos.activo', 1); }) ->with(['procesos' => function ($q) use ($procesoId) { $q->where('procesos.id', $procesoId) ->select('procesos.id') ->withPivot('id', 'proceso_id', 'area_id'); }]) ->get() ->map(function ($area) { $pivot = $area->procesos->first()->pivot; return [ 'area_id' => $area->id, 'nombre' => $area->nombre, 'area_proceso_id' => $pivot->id, ]; }); return response()->json($areas); } public function crearExamen(Request $request) { $postulante = $request->user(); $request->validate([ 'area_proceso_id' => 'required|exists:area_proceso,id', ]); // 🔥 Obtener TODO desde el pivot $areaProceso = \DB::table('area_proceso') ->join('procesos', 'procesos.id', '=', 'area_proceso.proceso_id') ->join('areas', 'areas.id', '=', 'area_proceso.area_id') ->where('area_proceso.id', $request->area_proceso_id) ->select( 'area_proceso.id', 'area_proceso.area_id', 'area_proceso.proceso_id', 'procesos.requiere_pago' ) ->first(); if (!$areaProceso) { return response()->json(['message' => 'Relación área-proceso inválida'], 400); } $yaDioProceso = Examen::join('area_proceso', 'area_proceso.id', '=', 'examenes.area_proceso_id') ->where('examenes.postulante_id', $postulante->id) ->where('area_proceso.proceso_id', $areaProceso->proceso_id) ->exists(); if ($yaDioProceso) { return response()->json([ 'message' => 'Ya rendiste un examen para este proceso' ], 400); } $pagado = 0; $pagoId = null; // 💰 Validación de pago if ($areaProceso->requiere_pago) { $request->validate([ 'tipo_pago' => 'required|in:pyto_peru,banco_nacion,caja', 'codigo_pago' => 'required', ]); $response = $this->validarPago( $request->tipo_pago, $request->codigo_pago, $postulante->dni ); if (!$response['estado']) { return response()->json(['message' => 'Pago inválido'], 400); } $pago = Pago::firstOrCreate( [ 'codigo_pago' => $request->codigo_pago, 'tipo_pago' => $request->tipo_pago, ], [ 'postulante_id' => $postulante->id, 'monto' => $response['monto'], 'fecha_pago' => $response['fecha_pago'], ] ); if ($pago->utilizado) { return response()->json(['message' => 'Pago ya utilizado'], 400); } $pago->update(['utilizado' => true]); $pagado = 1; $pagoId = $pago->id; } // 🧠 Crear / actualizar examen $examen = Examen::updateOrCreate( ['postulante_id' => $postulante->id, 'area_proceso_id' => $areaProceso->id, // 🔥 pivot 'pagado' => $pagado, 'tipo_pago' => $request->tipo_pago ?? null, 'pago_id' => $pagoId, ] ); return response()->json([ 'success' => true, 'examen_id' => $examen->id, 'mensaje' => 'Examen creado correctamente', ]); } public function validarPago($tipoPago, $codigoPago, $dni) { return match ($tipoPago) { 'pyto_peru' => $this->validarPagoPytoPeru($codigoPago, $dni), 'banco_nacion' => $this->validarPagoBancoNacion($codigoPago, $dni), 'caja' => $this->validarPagoCaja($codigoPago, $dni), default => ['estado' => false], }; } private function validarPagoBancoNacion($secuencia, $dni) { $url = 'https://inscripciones.admision.unap.edu.pe/api/get-pagos-banco-secuencia'; $response = Http::post($url, [ 'secuencia' => $secuencia, ]); if (!$response->successful()) { \Log::error('Error en la solicitud a la API', ['status' => $response->status(), 'body' => $response->body()]); return ['estado' => false, 'message' => 'Error en la solicitud a la API']; } $data = $response->json(); if (isset($data['estado']) && $data['estado'] === true) { foreach ($data['datos'] as $pago) { if (isset($pago['dni']) && trim($pago['dni']) == trim($dni)) { return [ 'estado' => true, 'monto' => $pago['imp_pag'], 'fecha_pago' => $pago['fch_pag'], ]; } } } return ['estado' => false, 'message' => 'Datos no válidos o no encontrados']; } private function validarPagoPytoPeru($authorizationCode, $dni) { $url = "https://service2.unap.edu.pe/PAYMENTS_MNG/v1/{$dni}/8/"; $response = Http::get($url); if ($response->successful()) { $data = $response->json(); if (isset($data['data'][0]['autorizationCode']) && $data['data'][0]['autorizationCode'] === $authorizationCode) { return [ 'estado' => true, 'monto' => $data['data'][0]['total'], 'fecha_pago' => $data['data'][0]['confirmedDate'], ]; } } return ['estado' => false, 'message' => 'El código de autorización no coincide.']; } private function validarPagoCaja($codigoPago, $dni) { $url = "https://inscripciones.admision.unap.edu.pe/api/get-pago-caja/{$dni}/{$codigoPago}"; $response = Http::get($url); if (!$response->successful()) { \Log::error('Error API Caja', [ 'status' => $response->status(), 'body' => $response->body() ]); return ['estado' => false, 'message' => 'Error en la API de Caja']; } $data = $response->json(); if ( isset($data['paymentTitle'], $data['paymentAmount'], $data['paymentDatetime']) && trim($data['paymentTitle']) === trim($codigoPago) ) { return [ 'estado' => true, 'monto' => (float) $data['paymentAmount'], 'fecha_pago' => $data['paymentDatetime'], ]; } return ['estado' => false, 'message' => 'Pago no válido o no encontrado']; } public function miExamenActual(Request $request) { $postulante = $request->user(); $examen = Examen::join('area_proceso', 'area_proceso.id', '=', 'examenes.area_proceso_id') ->join('areas', 'areas.id', '=', 'area_proceso.area_id') ->join('procesos', 'procesos.id', '=', 'area_proceso.proceso_id') ->where('examenes.postulante_id', $postulante->id) ->select( 'examenes.id', 'examenes.pagado', 'examenes.tipo_pago', 'examenes.intentos', 'areas.id as area_id', 'areas.nombre as area_nombre', 'procesos.id as proceso_id', 'procesos.nombre as proceso_nombre', 'procesos.intentos_maximos as proceso_intentos_maximos' ) ->latest('examenes.created_at') ->first(); if (!$examen) { return response()->json([ 'success' => true, 'mensaje' => 'No tienes exámenes asignados actualmente', 'examen' => null ]); } return response()->json([ 'success' => true, 'examen' => [ 'id' => $examen->id, 'intentos' => $examen->intentos, 'intentos_maximos' => $examen->proceso_intentos_maximos, 'proceso' => [ 'id' => $examen->proceso_id, 'nombre' => $examen->proceso_nombre, ], 'area' => [ 'id' => $examen->area_id, 'nombre' => $examen->area_nombre, ], 'pagado' => $examen->pagado, 'tipo_pago' => $examen->tipo_pago ?? null, ] ]); } public function generarPreguntas($examenId) { $examen = Examen::findOrFail($examenId); $postulante = request()->user(); if ($examen->postulante_id !== $postulante->id) { return response()->json([ 'success' => false, 'message' => 'No autorizado' ], 403); } if ($examen->preguntasAsignadas()->exists()) { return response()->json([ 'success' => true, 'message' => 'El examen ya tiene preguntas generadas', 'ya_tiene_preguntas' => true, 'total_preguntas' => $examen->preguntasAsignadas()->count() ]); } $resultado = $this->examenService->generarPreguntasExamen($examen); if (!$resultado['success']) { return response()->json($resultado, 400); } return response()->json([ 'success' => true, 'message' => 'Preguntas generadas exitosamente', 'ya_tiene_preguntas' => false, 'total_preguntas' => $examen->preguntasAsignadas()->count() ]); } public function iniciarExamen(Request $request) { $request->validate([ 'examen_id' => 'required|exists:examenes,id' ]); $examen = Examen::findOrFail($request->examen_id); $postulante = $request->user(); if ($examen->postulante_id !== $postulante->id) { return response()->json([ 'success' => false, 'message' => 'No autorizado' ], 403); } $areaProceso = \DB::table('area_proceso') ->join('procesos', 'area_proceso.proceso_id', '=', 'procesos.id') ->join('areas', 'area_proceso.area_id', '=', 'areas.id') ->where('area_proceso.id', $examen->area_proceso_id) ->select( 'procesos.id as proceso_id', 'procesos.nombre as proceso_nombre', 'procesos.duracion as proceso_duracion', 'procesos.intentos_maximos as proceso_intentos_maximos', 'areas.nombre as area_nombre' ) ->first(); if (!$examen->preguntasAsignadas()->exists()) { return response()->json([ 'success' => false, 'message' => 'El examen no tiene preguntas generadas' ], 400); } if ($areaProceso && $examen->intentos >= $areaProceso->proceso_intentos_maximos) { return response()->json([ 'success' => false, 'message' => 'Has alcanzado el número máximo de intentos para este proceso' ], 403); } $examen->increment('intentos'); $examen->update([ 'hora_inicio' => now(), 'estado' => 'en_progreso' ]); $preguntas = $this->examenService->obtenerPreguntasExamen($examen); return response()->json([ 'success' => true, 'examen' => [ 'id' => $examen->id, 'estado' => $examen->estado, 'hora_inicio' => $examen->hora_inicio, 'intentos' => $examen->intentos, 'intentos_maximos' => $areaProceso->proceso_intentos_maximos ?? null, 'proceso' => $areaProceso->proceso_nombre ?? null, 'duracion' => $areaProceso->proceso_duracion ?? null, 'area' => $areaProceso->area_nombre ?? null ], 'preguntas' => $preguntas ]); } public function responderPregunta($preguntaAsignadaId, Request $request) { $request->validate([ 'respuesta' => 'nullable|string' ]); $preguntaAsignada = PreguntaAsignada::with(['examen', 'pregunta']) ->findOrFail($preguntaAsignadaId); $postulante = $request->user(); if ($preguntaAsignada->examen->postulante_id !== $postulante->id) { return response()->json([ 'success' => false, 'message' => 'No autorizado' ], 403); } $resultado = $this->examenService->guardarRespuesta( $preguntaAsignada, $request->respuesta ); return response()->json($resultado); } public function finalizarExamen($examenId) { $examen = Examen::findOrFail($examenId); $postulante = request()->user(); if ($examen->postulante_id !== $postulante->id) { return response()->json([ 'success' => false, 'message' => 'No autorizado' ], 403); } $this->examenService->finalizarExamen($examen); return response()->json([ 'success' => true, 'message' => 'Examen finalizado exitosamente' ]); } }