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_mail from django.core.mail import send_mass_mail from django.core.mail import BadHeaderError, SMTPException from rest_framework.response import Response from rest_framework.decorators import api_view from .serializers import EventoSerializer, ReservaSerializer, ListaEsperaSerializer, NoticiaSerializer from django.core.mail import BadHeaderError, SMTPException from django.http import HttpResponse 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) destinatarios_str = ', '.join(destinatarios) logger.info("destinatarios: " + destinatarios_str) 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}" mensaje_comun = (asunto, mensaje,settings.DEFAULT_FROM_EMAIL, destinatarios) mensaje_final =[mensaje_comun] try: send_mass_mail(mensaje_final, 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})