from startpage.views import render from django.utils.translation import gettext_lazy as _ from django.http import HttpResponseRedirect, Http404 from django import forms from django.forms import ModelForm, TextInput, DateInput, BaseInlineFormSet,\ inlineformset_factory, HiddenInput, FileInput from members.models import Member, RegistrationPassword, MemberUnconfirmedProxy, MemberWaitingList, Group,\ confirm_mail_by_key, EmergencyContact, InvitationToGroup from django.urls import reverse from django.utils import timezone from django.conf import settings from .pdf import render_tex, media_path class MemberForm(ModelForm): class Meta: model = Member fields = ['prename', 'lastname', 'gender', 'street', 'plz', 'town', 'address_extra', 'phone_number', 'dav_badge_no'] class MemberRegistrationForm(ModelForm): def __init__(self, *args, **kwargs): super(MemberRegistrationForm, self).__init__(*args, **kwargs) for field in self.Meta.required: self.fields[field].required = True class Meta: model = Member fields = ['prename', 'lastname', 'street', 'plz', 'town', 'address_extra', 'phone_number', 'birth_date', 'gender', 'email', 'alternative_email'] widgets = { 'birth_date': DateInput(format='%Y-%m-%d', attrs={'type': 'date'}), } help_texts = { 'prename': _('Prename of the member.'), 'lastname': _('Lastname of the member.'), 'phone_number': _('phone number of child or parent'), 'email': _('email of child if available, otherwise parental email address'), 'alternative_email': _('optional additional email address'), } required = ['street', 'plz', 'town'] class UploadRegistrationForm(ModelForm): def __init__(self, *args, **kwargs): super(UploadRegistrationForm, self).__init__(*args, **kwargs) for field in self.Meta.required: self.fields[field].required = True class Meta: model = Member fields = ['registration_form'] widgets = { 'registration_form': FileInput(attrs={'accept': 'application/pdf,image/jpeg,image/png'}), } required = ['registration_form'] class MemberRegistrationWaitingListForm(ModelForm): def __init__(self, *args, **kwargs): super(MemberRegistrationWaitingListForm, self).__init__(*args, **kwargs) for field in self.Meta.required: self.fields[field].required = True class Meta: model = MemberWaitingList fields = ['prename', 'lastname', 'birth_date', 'gender', 'email', 'application_text'] widgets = { 'birth_date': DateInput(format='%Y-%m-%d', attrs={'type': 'date'}) } help_texts = { 'prename': _('Prename of the member.'), 'lastname': _('Lastname of the member.'), } required = [] class EmergencyContactForm(ModelForm): def __init__(self, *args, **kwargs): super(EmergencyContactForm, self).__init__(*args, **kwargs) for field in self.Meta.required: self.fields[field].widget.attrs['required'] = 'required' class Meta: model = EmergencyContact fields = ['prename', 'lastname', 'email', 'phone_number'] required = ['prename', 'lastname', 'phone_number'] class BaseEmergencyContactsFormSet(BaseInlineFormSet): deletion_widget = HiddenInput EmergencyContactsFormSet = inlineformset_factory(Member, EmergencyContact, form=EmergencyContactForm, fields=['prename', 'lastname', 'email', 'phone_number'], extra=0, min_num=1, can_delete=True, can_delete_extra=True, validate_min=True, formset=BaseEmergencyContactsFormSet) def render_echo_password(request, key): return render(request, 'members/echo_password.html', context={'key': key}) def render_echo_wrong_password(request, key): return render(request, 'members/echo_password.html', {'error_message': _("The entered password is wrong."), 'key': key}) def render_echo_failed(request, reason=""): context = {} if reason: context['reason'] = reason return render(request, 'members/echo_failed.html', context) def render_echo(request, key, password, form, emergency_contacts_formset): return render(request, 'members/echo.html', {'form': form.as_table(), 'emergency_contacts_formset': emergency_contacts_formset, 'key' : key, 'registration': False, 'password': password}) def render_echo_success(request, name): return render(request, 'members/echo_success.html', {'name': name}) def echo(request): if request.method == 'GET' and 'key' not in request.GET: # invalid return HttpResponseRedirect(reverse('startpage:index')) if request.method == 'GET': key = request.GET['key'] # try to get a member from the supplied echo key try: member = Member.objects.get(echo_key=key) except Member.DoesNotExist: return render_echo_failed(request, _("invalid")) # show password return render_echo_password(request, request.GET['key']) if 'password' not in request.POST or 'key' not in request.POST: return render_echo_failed(request, _("invalid")) key = request.POST['key'] password = request.POST['password'] # try to get a member from the supplied echo key try: member = Member.objects.get(echo_key=key) except Member.DoesNotExist: return render_echo_failed(request, _("invalid")) # check if echo key is not expired if not member.may_echo(key): return render_echo_failed(request, _("expired")) # check password if password != member.echo_password: return render_echo_wrong_password(request, key) if "save" in request.POST: form = MemberForm(request.POST, instance=member) emergency_contacts_formset = EmergencyContactsFormSet(request.POST, instance=member) try: if not emergency_contacts_formset.is_valid(): raise ValueError(_("Invalid emergency contacts")) form.save() emergency_contacts_formset.save() # We don't invalidate the echo key, so the user # can echo again if wanted. # member.echo_key, member.echo_expire = "", timezone.now() member.echoed = True member.save() return render_echo_success(request, member.prename) except ValueError: # when input is invalid form = MemberForm(request.POST) emergency_contacts_formset = EmergencyContactsFormSet(request.POST) return render_echo(request, key, password, form, emergency_contacts_formset) else: form = MemberForm(instance=member) emergency_contacts_formset = EmergencyContactsFormSet(instance=member) return render_echo(request, key, password, form, emergency_contacts_formset) def render_register_password(request): return render(request, 'members/register_password.html', context={'sektion': settings.SEKTION}) def render_register_wrong_password(request): return render(request, 'members/register_password.html', {'error_message': _("The entered password is wrong.")}) def render_register_success(request, groupname, membername, needs_mail_confirmation): return render(request, 'members/register_success.html', {'groupname': groupname, 'membername': membername, 'needs_mail_confirmation': needs_mail_confirmation}) def render_register(request, group, form=None, emergency_contacts_formset=None, pwd='', waiter_key=''): if form is None: form = MemberRegistrationForm() if emergency_contacts_formset is None: emergency_contacts_formset = EmergencyContactsFormSet() return render(request, 'members/register.html', {'form': form, 'emergency_contacts_formset': emergency_contacts_formset, 'group': group, 'waiter_key': waiter_key, 'password': pwd, 'sektion': settings.SEKTION, 'registration': True }) def render_register_failed(request, reason=""): context = {} if reason: context['reason'] = reason return render(request, 'members/register_failed.html', context) def register(request): if request.method == 'GET' or ("password" not in request.POST and "waiter_key" not in request.POST): # show password return render_register_password(request) # find group and potential waiter group = None waiter = None pwd = None waiter_key = request.POST['waiter_key'] if 'waiter_key' in request.POST else '' if "password" in request.POST and request.POST['password']: # confirm password try: pwd = RegistrationPassword.objects.get(password=request.POST['password']) group = pwd.group except RegistrationPassword.DoesNotExist: return render_register_wrong_password(request) elif waiter_key: try: invitation = InvitationToGroup.objects.get(key=waiter_key) waiter = invitation.waiter group = invitation.group except InvitationToGroup.DoesNotExist: return render_register_failed(request) # group must not be None if group is None: return render_register_failed(request) if "save" in request.POST: # process registration form = MemberRegistrationForm(request.POST, request.FILES) emergency_contacts_formset = EmergencyContactsFormSet(request.POST) try: # first try to save member new_member = form.save(commit=False) # then instantiate emergency contacts with this member emergency_contacts_formset.instance = new_member if emergency_contacts_formset.is_valid(): # if emergency contacts are valid, save new_member and save emergency contacts new_member.save() emergency_contacts_formset.save() else: raise ValueError needs_mail_confirmation = new_member.create_from_registration(waiter, group) new_member.send_upload_registration_form_link() return HttpResponseRedirect(reverse('members:upload_registration_form') + "?key=" + new_member.upload_registration_form_key) except ValueError as e: print("value error", e) # when input is invalid if pwd: return render_register(request, group, form, emergency_contacts_formset, pwd=pwd.password, waiter_key=waiter_key) else: return render_register(request, group, form, emergency_contacts_formset, waiter_key=waiter_key) # we are not saving yet return render_register(request, group, form=None, pwd=pwd.password, waiter_key=waiter_key) def render_download_registration_form(request, member): context = dict(member=member, settings=settings) return render_tex('Anmeldeformular_' + member.name, 'members/registration_form.tex', context) def download_registration_form(request): if request.method != 'GET' or 'key' not in request.GET: return render_upload_registration_form_invalid(request) key = request.GET['key'] try: member = MemberUnconfirmedProxy.objects.get(upload_registration_form_key=key) return render_download_registration_form(request, member) except Member.DoesNotExist: return render_upload_registration_form_invalid(request) return render_upload_registration_form_invalid(request) def render_upload_registration_form_invalid(request): return render(request, 'members/upload_registration_form_invalid.html') def render_upload_registration_form_success(request, member): return render(request, 'members/upload_registration_form_success.html', context={'member': member}) def render_upload_registration_form(request, member, form, key): return render(request, 'members/upload_registration_form.html', context={'form': form, 'member': member, 'key': key}) def upload_registration_form(request): if request.method == 'GET': if not 'key' in request.GET: return render_upload_registration_form_invalid(request) key = request.GET['key'] try: member = MemberUnconfirmedProxy.objects.get(upload_registration_form_key=key) except Member.DoesNotExist: return render_upload_registration_form_invalid(request) form = UploadRegistrationForm(instance=member) return render_upload_registration_form(request, member, form, key) if not 'key' in request.POST: return render_upload_registration_form_invalid(request) key = request.POST['key'] try: member = MemberUnconfirmedProxy.objects.get(upload_registration_form_key=key) except Member.DoesNotExist: return render_upload_registration_form_invalid(request) form = UploadRegistrationForm(request.POST, request.FILES, instance=member) if not form.is_valid(): return render_upload_registration_form(request, member, form, key) try: form.save() member.validate_registration_form() return render_upload_registration_form_success(request, member) except ValueError as e: return render_upload_registration_form(request, member, form, key) return render_upload_registration_form_invalid(request) def confirm_mail(request): if request.method == 'GET' and 'key' in request.GET: res = confirm_mail_by_key(request.GET['key']) if res: return render_mail_confirmation_success(request, res[1], res[0].prename, False) else: return render_mail_confirmation_invalid(request) return HttpResponseRedirect(reverse('startpage:index')) def render_mail_confirmation_invalid(request): return render(request, 'members/mail_confirmation_invalid.html') def render_mail_confirmation_success(request, email, name, parents=False): return render(request, 'members/mail_confirmation_success.html', {'email': email, 'name': name, 'parents': parents}) def render_register_waiting_list(request, form=None): if form is None: form = MemberRegistrationWaitingListForm() return render(request, 'members/register_waiting_list.html', {'form': form, 'sektion': settings.SEKTION }) def render_register_waiting_list_success(request, membername): return render(request, 'members/register_waiting_list_success.html', {'membername': membername}) def register_waiting_list(request): if request.method == 'GET': # ask to fill in form return render_register_waiting_list(request) if "save" in request.POST: # process registration for waiting list form = MemberRegistrationWaitingListForm(request.POST, request.FILES) try: new_waiter = form.save() new_waiter.save() new_waiter.request_mail_confirmation() return render_register_waiting_list_success(request, new_waiter.prename) except ValueError: # when input is invalid return render_register_waiting_list(request, form) # we are not saving yet return render_register_waiting_list(request, form=None) def invited_registration(request): if request.method == 'GET' and 'key' in request.GET: try: key = request.GET['key'] invitation = InvitationToGroup.objects.get(key=key) waiter = invitation.waiter if invitation.is_expired() or invitation.rejected: raise KeyError form = MemberRegistrationForm(instance=waiter) return render_register(request, group=invitation.group, form=form, waiter_key=key) except InvitationToGroup.DoesNotExist: return render_invited_registration_failed(request, _("invalid")) except KeyError: return render_invited_registration_failed(request, _("expired")) # if its a POST request return register(request) def render_invited_registration_failed(request, reason=""): context = {} if reason: context['reason'] = reason return render(request, 'members/invited_registration_failed.html', context) def render_reject_invitation(request, invitation): return render(request, 'members/reject_invitation.html', {'invitation': invitation, 'groupname': invitation.group.name}) def render_reject_invalid(request): return render(request, 'members/reject_invalid.html') def render_reject_success(request, invitation, leave_waitinglist=False): return render(request, 'members/reject_success.html', {'invitation': invitation, 'leave_waitinglist': leave_waitinglist, 'groupname': invitation.group.name}) def reject_invitation(request): if request.method == 'GET' and 'key' in request.GET: key = request.GET['key'] try: invitation = InvitationToGroup.objects.get(key=key) if invitation.rejected or invitation.is_expired(): raise ValueError return render_reject_invitation(request, invitation) except (ValueError, InvitationToGroup.DoesNotExist): return render_reject_invalid(request) if request.method != 'POST' or 'key' not in request.POST: return render_reject_invalid(request) key = request.POST['key'] try: invitation = InvitationToGroup.objects.get(key=key) except InvitationToGroup.DoesNotExist: return render_reject_invalid(request) if 'reject_invitation' in request.POST: invitation.rejected = True invitation.save() return render_reject_success(request, invitation) elif 'leave_waitinglist' in request.POST: invitation.waiter.unregister() return render_reject_success(request, invitation, leave_waitinglist=True) return render_reject_invalid(request) def confirm_waiting(request): if request.method == 'GET' and 'key' in request.GET: key = request.GET['key'] try: waiter = MemberWaitingList.objects.get(wait_confirmation_key=key) except MemberWaitingList.DoesNotExist: return render_waiting_confirmation_invalid(request) status = waiter.confirm_waiting(key) if status == MemberWaitingList.WAITING_CONFIRMATION_SUCCESS: return render_waiting_confirmation_success(request, waiter.prename, already_confirmed=False) elif status == MemberWaitingList.WAITING_CONFIRMED: return render_waiting_confirmation_success(request, waiter.prename, already_confirmed=True) elif status == MemberWaitingList.WAITING_CONFIRMATION_EXPIRED: return render_waiting_confirmation_invalid(request, prename=waiter.prename, expired=True) else: # invalid return render_waiting_confirmation_invalid(request) return HttpResponseRedirect(reverse('startpage:index')) def render_waiting_confirmation_invalid(request, prename=None, expired=False): return render(request, 'members/waiting_confirmation_invalid.html', {'expired': expired, 'prename': prename}) def render_waiting_confirmation_success(request, prename, already_confirmed): return render(request, 'members/waiting_confirmation_success.html', {'prename': prename, 'already_confirmed': already_confirmed}) def render_leave_waitinglist(request, waiter): return render(request, 'members/leave_waitinglist.html', dict(waiter=waiter)) def render_leave_waitinglist_success(request, waiter): return render(request, 'members/leave_waitinglist_success.html', dict(waiter=waiter)) def leave_waitinglist(request): if request.method == 'GET' and 'key' in request.GET: key = request.GET['key'] try: waiter = MemberWaitingList.objects.get(leave_key=key) return render_leave_waitinglist(request, waiter) except (MemberWaitingList.DoesNotExist, MemberWaitingList.MultipleObjectsReturned): raise Http404("Waiter with given leave key does not exist.") if request.method != 'POST' or 'key' not in request.POST: raise Http404("Waiter with given leave key does not exist.") key = request.POST['key'] try: waiter = MemberWaitingList.objects.get(leave_key=key) except (MemberWaitingList.DoesNotExist, MemberWaitingList.MultipleObjectsReturned): raise Http404("Waiter with given leave key does not exist.") if not 'leave_waitinglist' in request.POST: raise Http404("leave_waitinglist not found in POST data.") waiter.unregister() return render_leave_waitinglist_success(request, waiter)