plantelUsuarios->pluck('id'); // Prospectos del plantel que tienen historial de WhatsApp $prospectos = Alumno::whereHas('alumnos.plantelUsuarios', function ($q) use ($plantelesIds) { $q->whereIn('plantels.id', $plantelesIds); }) ->whereHas('whatsappLogs') ->with(['alumnos' => fn($q) => $q->select('users.id', 'users.name', 'users.apellidoPaterno', 'users.telefono', 'users.profile_photo_path')]) ->get() ->map(function (Alumno $alumno) { $ultimoMensaje = $alumno->whatsappLogs()->latest('created_at')->first(); $noLeidos = $alumno->whatsappLogs()->where('leido', false)->where('tipo', 'recibido')->count(); return [ 'alumno' => $alumno, 'user' => $alumno->alumnos->first(), 'ultimo' => $ultimoMensaje, 'no_leidos' => $noLeidos, ]; }) ->sortByDesc(fn($item) => optional($item['ultimo'])->created_at); $totalNoLeidos = WhatsappLog::whereIn('alumno_id', $prospectos->pluck('alumno.id')) ->where('leido', false) ->where('tipo', 'recibido') ->count(); return view('promocion.chat', compact('prospectos', 'totalNoLeidos')); } public function show(Alumno $alumno) { $this->autorizarAlumno($alumno); $logs = WhatsappLog::where('alumno_id', $alumno->id) ->orderBy('created_at') ->get(); // Marcar como leídos WhatsappLog::where('alumno_id', $alumno->id) ->where('leido', false) ->update(['leido' => true]); $user = $alumno->alumnos()->first(); return response()->json([ 'alumno' => [ 'id' => $alumno->id, 'nombre' => $user ? "{$user->name} {$user->apellidoPaterno}" : "Alumno #{$alumno->id}", 'avatar' => $user?->profile_photo_url ?? null, 'tel' => $alumno->telefonoWhatsapp(), ], 'logs' => $logs->map(fn($log) => [ 'id' => $log->id, 'tipo' => $log->tipo, 'mensaje' => $log->mensaje, 'media_type' => $log->media_type, 'created_at' => $log->created_at?->format('d/m/Y H:i'), ]), ]); } public function send(Request $request, WhatsAppService $whatsapp) { $request->validate([ 'alumno_id' => 'required|exists:alumnos,id', 'mensaje' => 'required|string|max:4096', ]); $alumno = Alumno::findOrFail($request->alumno_id); $this->autorizarAlumno($alumno); if ($alumno->opt_out) { return response()->json(['error' => 'El prospecto solicitó no recibir mensajes (opt-out).'], 422); } $telefono = $alumno->telefonoWhatsapp(); if (!$telefono) { return response()->json(['error' => 'El prospecto no tiene teléfono registrado.'], 422); } $mensajeId = $whatsapp->enviarTexto($telefono, $request->mensaje); $log = WhatsappLog::create([ 'alumno_id' => $alumno->id, 'telefono' => $telefono, 'tipo' => 'enviado', 'mensaje' => $request->mensaje, 'payload' => ['enviado_por' => Auth::id(), 'whatsapp_id' => $mensajeId], ]); return response()->json([ 'id' => $log->id, 'tipo' => $log->tipo, 'mensaje' => $log->mensaje, 'created_at' => $log->created_at->format('d/m/Y H:i'), ]); } private function autorizarAlumno(Alumno $alumno): void { $plantelesIds = Auth::user()->plantelUsuarios->pluck('id'); $tiene = $alumno->alumnos() ->whereHas('plantelUsuarios', fn($q) => $q->whereIn('plantels.id', $plantelesIds)) ->exists(); if (!$tiene) { abort(403); } } }