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
|
|
|
|
from django.contrib.auth import get_user_model
|
|
from django.db.models import Count
|
|
|
|
User = get_user_model()
|
|
|
|
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):
|
|
# 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
|
|
|
|
# comprobar si el evento es pasado ya
|
|
|
|
evento_es_pasado = evento.fecha < timezone.now().date()
|
|
|
|
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,
|
|
'evento_es_pasado': evento_es_pasado
|
|
})
|
|
|
|
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)
|
|
|
|
evento_es_pasado = evento.fecha < timezone.now().date()
|
|
|
|
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,
|
|
'evento_es_pasado': evento_es_pasado
|
|
}
|
|
)
|
|
|
|
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})
|
|
|
|
|
|
@user_passes_test(es_admin)
|
|
def estadisticas_por_usuario(request):
|
|
usuarios = User.objects.annotate(num_eventos=Count("reserva__evento")).order_by("-num_eventos")
|
|
return render(request, "eventos/estadisticas_usuarios.html", {"usuarios": usuarios})
|
|
|