from django.shortcuts import render, redirect, get_object_or_404 from .models import Shift, LoginToken, Helper, ShiftRegistration from django.db import transaction from django.db.models import F, Count, Q, ExpressionWrapper from .forms import RegisterForm, EmptyForm, AstaForm from django.db.models.fields import DateTimeField from datetime import timedelta from django.utils import timezone from django.conf import settings from django.contrib import messages import datetime from .decorators import event_state from dynamic_preferences.registries import global_preferences_registry import math global_preferences = global_preferences_registry.manager() @event_state def index(request): if request.session.get("last_seen_shift"): del request.session["last_seen_shift"] context = { "days": Shift.objects.datetimes("start_at", "day"), } if request.helper: context["my_future_shifts"] = list( reg.shift for reg in request.helper.shiftregistration_set.filter( shift__start_at__gt=timezone.now(), state__in=[ ShiftRegistration.RegState.REGISTERED, ShiftRegistration.RegState.CHECKED_IN, ], ).order_by("shift__start_at") ) imp_shift = request.helper.important_shift() if imp_shift and imp_shift.is_running(): context["current_shift"] = imp_shift help_wanted = Q(required_helpers__gt=F("reg_count")) | Q(required_helpers=0) & Q( room__required_helpers__gt=F("reg_count") ) # dont show shifts starting in <60 minutes? # currently only sorts by date free_shifts = ( Shift.with_reg_count() .filter( help_wanted, start_at__gte=day + timedelta(hours=6), start_at__lte=day + timedelta(hours=30), start_at__gt=timezone.now(), deleted=False, ) .order_by("start_at") for day in Shift.objects.datetimes("start_at", "day") ) if request.helper: free_shifts = ( day.filter(~Q(shiftregistration__helper=request.helper)) for day in free_shifts ) context["free_shifts"] = list( map(lambda qs: list(qs), filter(lambda qs: qs.exists(), free_shifts)) ) return render(request, "shiftlist.html", context) def login(request, token): tk = get_object_or_404(LoginToken, pk=token) if not tk.helper.number_validated: tk.helper.number_validated = True tk.helper.save() messages.add_message( request, messages.SUCCESS, "Nummer bestätigt, du kannst dich jetzt für Schichten anmelden.", ) request.session["token"] = token # if the user was viewing a single shift before registering, they probably want to register for that # shift so we redirect them there. if request.session.get("last_seen_shift"): return redirect("shift", shiftid=request.session["last_seen_shift"]) return redirect("index") def logout(request): if request.session.get("token"): del request.session["token"] return redirect("index") def register(request): if global_preferences["helper__event_state"] == "AFTER": return render(request, "event_after.html", {}) if request.helper: if request.session.get("last_seen_shift"): return redirect("shift", shiftid=request.session["last_seen_shift"]) return redirect("index") context = {} if request.method == "POST": form = RegisterForm(request.POST) if not form.is_valid(): context["form"] = form return render(request, "register.html", context) helper = Helper.objects.filter(phone=form.cleaned_data["phone"]).first() if helper: token = helper.logintoken_set.first() messages.add_message( request, messages.INFO, f"Du hast einen Login-Link an deine Telefonnummer erhalten. Falls du die SMS nicht erhalten hast, probiere es in 15 Minuten noch ein mal.", ) if settings.DEBUG: messages.add_message( request, messages.INFO, f"DEBUG:{token.get_absolute_url()}", ) if token.sent_at < ( timezone.now() - datetime.timedelta(minutes=math.pow(10, token.send_count)) ): token.send() return render(request, "wait_confirmation.html", context) helper = Helper( name=form.cleaned_data["name"], phone=form.cleaned_data["phone"] ) with transaction.atomic(): helper.save() token = helper.send_confirmation() request.session["token"] = token.pk if settings.DEBUG: messages.add_message( request, messages.INFO, f"DEBUG: login token: {token.get_absolute_url()}", ) return render(request, "wait_confirmation.html", {"helper": helper}) context["form"] = RegisterForm() return render(request, "register.html", context) @event_state def shift(request, shiftid): shift = get_object_or_404(Shift, pk=shiftid) helper = request.helper context = { "can_register": False, "is_registered": False, "can_cancel": False, "shift": shift, "shift_form": EmptyForm, } # this currently ignores date/time request.session["last_seen_shift"] = shiftid if ( shift.required_helpers > shift.registration_count() or shift.required_helpers == 0 and shift.room.required_helpers > shift.registration_count() ): context["can_register"] = True if helper: context["helper"] = helper reg = ShiftRegistration.objects.filter(shift=shift, helper=helper) if reg: context["is_registered"] = True context["can_register"] = False if reg[0].can_cancel(): context["can_cancel"] = True if request.method == "POST": if EmptyForm(request.POST).is_valid(): if not helper: messages.add_message( request, messages.WARNING, "Bitte registriere dich, bevor du dich zu Schichten anmeldest", ) return redirect("register") if not helper.number_validated: messages.add_message( request, messages.WARNING, "Bitte bestätige zuerst deine Telefonnummer", ) return redirect("shift", shiftid=shift.pk) if shift.deleted: messages.add_message( request, messages.ERROR, "Diese Schicht wurde gelöscht.", ) return redirect("index") if context["can_register"]: s = ShiftRegistration(helper=helper, shift=shift) s.save() messages.add_message( request, messages.SUCCESS, "Erfolgreich angemeldet, bitte komme eine halbe Stunde vor deiner Schicht an den Infopoint", ) # redirect so page can be reloaded without resending post data return redirect("shift", shiftid=shift.pk) return render(request, "shift.html", context) def cancel(request, shiftid): if request.method != "POST": return redirect("shift", shiftid=shiftid) if not EmptyForm(request.POST).is_valid(): return redirect("shift", shiftid=shiftid) if not request.session.get("token"): return redirect("shift", shiftid=shiftid) shift = get_object_or_404(Shift, pk=shiftid) reg = get_object_or_404(ShiftRegistration, helper=request.helper, shift=shift) if reg.can_cancel(): reg.delete() messages.add_message( request, messages.SUCCESS, "Erfolgreich abgemeldet", ) else: messages.add_message( request, messages.WARNING, "Abmeldung nicht (mehr) möglich, bitte wende dich an den Infopoint", ) return redirect("shift", shiftid=shiftid) def asta(request): if not request.helper: return redirect("index") form = AstaForm() if request.method == "POST": form = AstaForm(request.POST) if AstaForm(request.POST).is_valid(): request.helper.asta_confirmed = True request.helper.save() messages.add_message( request, messages.SUCCESS, "Deine AStA-Mitgliedschaft wurde gespeichert", ) return redirect("index") return render(request, "asta.html", {"form": form})