123 lines
4.3 KiB
Python
123 lines
4.3 KiB
Python
from datetime import timedelta
|
|
import os
|
|
|
|
from django.utils import timezone
|
|
from rest_framework import status, viewsets
|
|
from rest_framework.exceptions import Throttled
|
|
from rest_framework.permissions import AllowAny, IsAdminUser
|
|
from rest_framework.response import Response
|
|
from rest_framework.views import APIView
|
|
|
|
from .models import AvailabilityRequest, ScheduleEntry
|
|
from .notifications import send_ntfy_notification
|
|
from .serializers import (
|
|
AvailabilityRequestAdminSerializer,
|
|
AvailabilityRequestCreateSerializer,
|
|
AvailabilityRequestPublicSerializer,
|
|
AvailabilityResponseSerializer,
|
|
ScheduleEntrySerializer,
|
|
)
|
|
|
|
|
|
def client_ip(request):
|
|
forwarded = request.META.get('HTTP_X_FORWARDED_FOR')
|
|
return forwarded.split(',')[0].strip() if forwarded else request.META.get('REMOTE_ADDR')
|
|
|
|
|
|
def filter_schedule(queryset, request):
|
|
start = request.query_params.get('start')
|
|
end = request.query_params.get('end')
|
|
if start and end:
|
|
queryset = queryset.filter(start_date__lte=end, end_date__gte=start)
|
|
return queryset
|
|
|
|
|
|
class PublicScheduleView(APIView):
|
|
permission_classes = [AllowAny]
|
|
|
|
def get(self, request):
|
|
queryset = filter_schedule(ScheduleEntry.objects.all(), request)
|
|
return Response(ScheduleEntrySerializer(queryset, many=True).data)
|
|
|
|
|
|
class PublicAvailabilityRequestCreateView(APIView):
|
|
permission_classes = [AllowAny]
|
|
|
|
def post(self, request):
|
|
ip = client_ip(request)
|
|
if ip and AvailabilityRequest.objects.filter(
|
|
requester_ip=ip,
|
|
requested_at__gte=timezone.now() - timedelta(seconds=45),
|
|
).exists():
|
|
raise Throttled(detail="Une demande vient déjà d'être envoyée. Réessaie dans quelques secondes.")
|
|
|
|
serializer = AvailabilityRequestCreateSerializer(data=request.data)
|
|
serializer.is_valid(raise_exception=True)
|
|
item = serializer.save(requester_ip=ip)
|
|
|
|
public_site_url = os.getenv('PUBLIC_SITE_URL', '').rstrip('/')
|
|
message = f'{item.guest_name} demande si tu es disponible maintenant.'
|
|
if item.message:
|
|
message += f'\n{item.message}'
|
|
send_ntfy_notification(
|
|
'Nouvelle demande de disponibilité',
|
|
message,
|
|
f'{public_site_url}/requests' if public_site_url else None,
|
|
)
|
|
|
|
return Response(
|
|
AvailabilityRequestPublicSerializer(item).data,
|
|
status=status.HTTP_201_CREATED,
|
|
)
|
|
|
|
|
|
class PublicAvailabilityRequestDetailView(APIView):
|
|
permission_classes = [AllowAny]
|
|
|
|
def get(self, request, token):
|
|
try:
|
|
item = AvailabilityRequest.objects.get(public_token=token)
|
|
except AvailabilityRequest.DoesNotExist:
|
|
return Response({'detail': 'Demande introuvable.'}, status=status.HTTP_404_NOT_FOUND)
|
|
return Response(AvailabilityRequestPublicSerializer(item).data)
|
|
|
|
|
|
class AdminScheduleViewSet(viewsets.ModelViewSet):
|
|
serializer_class = ScheduleEntrySerializer
|
|
permission_classes = [IsAdminUser]
|
|
|
|
def get_queryset(self):
|
|
return filter_schedule(ScheduleEntry.objects.all(), self.request)
|
|
|
|
|
|
class AdminAvailabilityRequestViewSet(viewsets.ReadOnlyModelViewSet):
|
|
serializer_class = AvailabilityRequestAdminSerializer
|
|
permission_classes = [IsAdminUser]
|
|
|
|
def get_queryset(self):
|
|
queryset = AvailabilityRequest.objects.all()
|
|
status_filter = self.request.query_params.get('status')
|
|
if status_filter:
|
|
queryset = queryset.filter(status=status_filter)
|
|
return queryset
|
|
|
|
def respond(self, request, pk=None):
|
|
item = self.get_object()
|
|
serializer = AvailabilityResponseSerializer(data=request.data)
|
|
serializer.is_valid(raise_exception=True)
|
|
|
|
new_status = serializer.validated_data['status']
|
|
duration = serializer.validated_data.get('duration_minutes')
|
|
item.status = new_status
|
|
item.duration_minutes = duration if new_status == 'accepted' else None
|
|
item.available_until = (
|
|
timezone.now() + timedelta(minutes=duration)
|
|
if new_status == 'accepted' and duration
|
|
else None
|
|
)
|
|
item.response_message = serializer.validated_data.get('response_message', '')
|
|
item.responded_at = timezone.now()
|
|
item.save()
|
|
|
|
return Response(AvailabilityRequestAdminSerializer(item).data)
|