from django.shortcuts import render, get_object_or_404, redirect from django.contrib.auth.decorators import login_required, user_passes_test from django.contrib import messages from django.core.mail import EmailMultiAlternatives from django.conf import settings from django.template.loader import render_to_string from django.utils import timezone import logging from django.core.mail import send_mass_mail from django.core.mail import BadHeaderError from smtplib import SMTPException from django.http import HttpResponse from rest_framework.response import Response from rest_framework.decorators import api_view from .serializers import EventoSerializer, ReservaSerializer, ListaEsperaSerializer, NoticiaSerializer from .models import Evento, Reserva, ListaEspera, Noticia from .forms import ListaEsperaForm, EventoForm, MensajeCorreoForm logger = logging.getLogger(__name__) @login_required def reservar_evento(request, evento_id): evento = get_object_or_404(Evento, id=evento_id) # Verificar si el usuario ya tiene una reserva para este evento if Reserva.objects.filter(evento=evento, usuario=request.user).exists(): messages.error(request, 'Ya tienes una reserva para este evento.') return redirect('eventos:lista_eventos') # Verificar si quedan plazas disponibles if evento.plazas_restantes() > 0: Reserva.objects.create(evento=evento, usuario=request.user) # Enviar un correo con la información del evento asunto = f'Confirmación de Reserva para {evento.nombre}' from_email = settings.DEFAULT_FROM_EMAIL to_email = request.user.email cc_email = [settings.ADMIN_EMAIL] texto = f'Hola {request.user.nombre},\n\n' \ f'Te has inscrito correctamente en el evento "{evento.nombre}".\n' \ f'Detalles del evento:\n' \ f'Nombre: {evento.nombre}\n' \ f'Descripción: {evento.descripcion}\n' \ f'Fecha: {evento.fecha.strftime("%d/%b/%y")} a las {evento.hora}\n' \ f'\n¡Gracias por inscribirte!\n\n' html_content = render_to_string('emails/confirmacion_reserva.html', {'evento': evento, 'usuario': request.user}) # Enviar el correo con el administrador en copia msg = EmailMultiAlternatives(asunto, texto, from_email, [to_email], cc=cc_email) msg.attach_alternative(html_content, "text/html") msg.send() # Aquí hay que mirar si quedan más de n plazas. # n es un numero aleatorio entre 2 y el total de plazas # si es así, y ya hay añadir a dos participantes. messages.success(request, f'Reserva realizada para el evento {evento.nombre}.') else: messages.error(request, 'Lo sentimos, no quedan plazas disponibles.') return redirect('eventos:lista_eventos') @user_passes_test(lambda u: u.is_staff) def publicar_evento(request, evento_id): evento = get_object_or_404(Evento, id=evento_id) if not evento.publicado: evento.publicado = True evento.save() messages.success(request, 'El evento %s ha sido publicado' % evento.nombre) else: messages.info(request, 'El evento %s ya está publicado' % evento.nombre) return redirect('eventos:detalle_evento', evento_id=evento_id) @login_required def lista_eventos(request): # anno_actual = timezone.now().year # Solo mostrar los eventos publicados a los usuarios normales if request.user.is_staff: eventos = Evento.objects.all().order_by('-fecha', '-hora') else: eventos = Evento.objects.filter(publicado=True).order_by('-fecha', '-hora') # eventos = Evento.objects.filter(publicado=True, fecha__year=anno_actual) # Los usuarios ven solo eventos publicados y del año en curso # Crear un diccionario que mapea cada evento con un booleano indicando si el usuario ya ha reservado eventos_con_reserva = [] for evento in eventos: inscrito = Reserva.objects.filter(evento=evento, usuario=request.user).exists() if request.user.is_authenticated else False if ListaEspera.objects.filter(evento=evento, usuario=request.user).exists(): en_espera = True else: en_espera = False eventos_con_reserva.append({ 'evento': evento, 'inscrito': inscrito, 'id': evento.id, 'nombre': evento.nombre, 'fecha': evento.fecha, 'hora': evento.hora, 'plazas_disponibles': evento.plazas_disponibles, 'plazas_restantes': evento.plazas_restantes, 'en_espera': en_espera, 'usuario': request.user, 'publicado': evento.publicado, 'url_imagen': evento.url_imagen }) return render(request, 'eventos/lista_eventos.html', {'eventos_con_reserva': eventos_con_reserva}) def detalle_noticia(request, noticia_id): noticia = get_object_or_404(Noticia, id=noticia_id, publicado=True) return render(request, 'detalle_noticia.html', {'noticia': noticia}) def ayuda(request): return render(request, 'eventos/help.html') @login_required def detalle_evento(request, evento_id): el_evento = [] evento = get_object_or_404(Evento, pk=evento_id) reservas = Reserva.objects.filter(evento=evento_id) inscrito = Reserva.objects.filter(evento=evento, usuario=request.user).exists() if request.user.is_authenticated else False if ListaEspera.objects.filter(evento=evento, usuario=request.user).exists(): en_espera = True else: en_espera = False lista_espera = ListaEspera.objects.filter(evento=evento_id) el_evento.append( { 'evento': evento, 'inscrito': inscrito, 'id': evento.id, 'nombre': evento.nombre, 'descripcion': evento.descripcion, 'fecha': evento.fecha, 'plazas_disponibles': evento.plazas_disponibles, 'plazas_restantes': evento.plazas_restantes, 'en_espera': en_espera, 'usuario': request.user, 'publicado': evento.publicado, 'url_imagen': evento.url_imagen } ) return render(request, 'eventos/detalle_evento.html', {'eventos': el_evento, 'reservas': reservas, 'lista': lista_espera}) # Verificar si el usuario es administrador def es_admin(user): return user.is_staff @user_passes_test(es_admin) def crear_evento(request): if request.method == 'POST': form = EventoForm(request.POST) if form.is_valid(): form.save() messages.success(request, 'Evento creado exitosamente.') return redirect('eventos:lista_eventos') # Redirige a la lista de eventos else: form = EventoForm() return render(request, 'eventos/crear_evento.html', {'form': form}) @user_passes_test(lambda u: u.is_staff) def editar_evento(request, evento_id): evento = get_object_or_404(Evento, id=evento_id) if request.method == 'POST': form = EventoForm(request.POST, instance=evento) if form.is_valid(): form.save() return redirect('lista_eventos') else: form = EventoForm(instance=evento) return render(request, 'crear_evento.html', {'form': form, 'evento': evento}) @login_required def apuntar_lista_espera(request, evento_id): evento = get_object_or_404(Evento, id=evento_id) # Verificar si el usuario ya está en la lista de espera if ListaEspera.objects.filter(evento=evento, usuario=request.user).exists(): messages.error(request, 'Ya estás en la lista de espera para este evento.') return redirect('eventos:lista_eventos') # Crear una entrada en la lista de espera if request.method == 'POST': form = ListaEsperaForm(request.POST) if form.is_valid(): ListaEspera.objects.create(evento=evento, usuario=request.user) messages.success(request, 'Te has apuntado a la lista de espera para este evento.') return redirect('eventos:lista_eventos') form = ListaEsperaForm() return render(request, 'eventos/apuntar_lista_espera.html', {'form': form, 'evento': evento}) # # API # @api_view(['GET']) def api_lista_eventos(request): """Devuelve la lista de todos los eventos.""" eventos = Evento.objects.all() serializer = EventoSerializer(eventos, many=True) return Response(serializer.data) @api_view(['GET']) def api_detalle_evento(request, evento_id): """Devuelve los detalles de un evento específico.""" try: evento = Evento.objects.get(id=evento_id) serializer = EventoSerializer(evento) return Response(serializer.data) except Evento.DoesNotExist: return Response({'error': 'Evento no encontrado'}, status=404) @api_view(['GET']) def api_lista_reservas(request): """Devuelve la lista de todos los reservas.""" reservas = Reserva.objects.all() serializer = ReservaSerializer(reservas, many=True) return Response(serializer.data) @api_view(['GET']) def api_detalle_reserva(request, reserva_id): """Devuelve los detalles de un reserva específico.""" try: reserva = Reserva.objects.get(id=reserva_id) serializer = ReservaSerializer(reserva) return Response(serializer.data) except Reserva.DoesNotExist: return Response({'error': 'Reserva no encontrado'}, status=404) @api_view(['GET']) def api_lista_listaespera(request): """Devuelve la lista de todos los listaespera.""" listaesperas = ListaEspera.objects.all() serializer = ListaEsperaSerializer(listaesperas, many=True) return Response(serializer.data) @api_view(['GET']) def api_detalle_listaespera(request, listaespera_id): """Devuelve los detalles de un listaespera específico.""" try: listaespera = ListaEspera.objects.get(id=listaespera_id) serializer = ListaEsperaSerializer(listaespera) return Response(serializer.data) except ListaEspera.DoesNotExist: return Response({'error': 'ListaEspera no encontrado'}, status=404) @api_view(['GET']) def api_lista_noticias(request): """Devuelve la lista de todos los noticias.""" noticias = Noticia.objects.all() serializer = NoticiaSerializer(noticias, many=True) return Response(serializer.data) @api_view(['GET']) def api_detalle_noticia(request, noticia_id): """Devuelve los detalles de un noticia específico.""" try: noticia = Noticia.objects.get(id=noticia_id) serializer = NoticiaSerializer(noticia) return Response(serializer.data) except Noticia.DoesNotExist: return Response({'error': 'Noticia no encontrado'}, status=404) # Verifica si el usuario es administrador def es_admin(user): return user.is_staff @user_passes_test(es_admin) # Solo administradores pueden acceder def enviar_correo_inscritos(request, evento_id): evento = get_object_or_404(Evento, id=evento_id) inscritos = Reserva.objects.filter(evento=evento).select_related('usuario') if not inscritos: messages.warning(request, "No hay usuarios inscritos en este evento.") return redirect('eventos:detalle_evento', evento_id=evento.id) destinatarios = [reserva.usuario.email for reserva in inscritos if reserva.usuario.email] if not destinatarios: messages.warning(request, "No hay correos disponibles para los inscritos.") return redirect('eventos:detalle_evento', evento_id=evento.id) if request.method == "POST": form = MensajeCorreoForm(request.POST) if form.is_valid(): asunto_usuario = form.cleaned_data['asunto'] mensaje_usuario = form.cleaned_data['mensaje'] asunto = f"{asunto_usuario} - {evento.nombre}" firma = "\n\n\nSaludos, \n\nPádel entre amigos" mensaje = f"{mensaje_usuario}{firma}" mensajes = [ (asunto, mensaje, settings.DEFAULT_FROM_EMAIL, [email]) for email in destinatarios ] try: send_mass_mail(mensajes, fail_silently=False) except BadHeaderError: return HttpResponse('Encabezado inválido encontrado.') except SMTPException as e: return HttpResponse(f'Error de SMTP: {e}') except Exception as e: return HttpResponse(f'Ocurrió un error: {e}') logger.debug('Correo enviado') messages.success(request, f"Correo enviado a {len(destinatarios)} inscritos.") return redirect('eventos:detalle_evento', evento_id=evento.id) else: form = MensajeCorreoForm() return render(request, 'eventos/enviar_correo_inscritos.html', {'form': form, 'evento': evento})