We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Cannot renew membership as benefactor, expects length field
### Describe the bug
Right now, when trying to renew a membership as benefactor from http://localhost:8000/user/membership/ I can't send the form. I get a javascript error: `An invalid form control with name='length' is not focusable.` 
So the problem is that the length field is expected to have a value while this isn't the case for benefactors.

### How to reproduce
Steps to reproduce the behaviour:
1. Go to http://localhost:8000/user/membership/
2. Add a benefactor membership renewal 
3. The form will not respond when trying to send
4. You will get a javascript error, indicating that the form can't focus on the length field (as it is hidden for benefactors), 

### Expected behaviour
It should ignore the length field for benefactorship renewals, as for benefactors it is always 1 year


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `website/registrations/views.py`
Content:
```
1 """Views provided by the registrations package."""
2 from django.conf import settings
3 from django.contrib import messages
4 from django.contrib.admin.utils import model_ngettext
5 from django.contrib.admin.views.decorators import staff_member_required
6 from django.contrib.auth.decorators import login_required, permission_required
7 from django.contrib.contenttypes.models import ContentType
8 from django.core.exceptions import ValidationError
9 from django.db.models import Q
10 from django.http import Http404
11 from django.shortcuts import redirect, get_object_or_404
12 from django.template.defaultfilters import floatformat
13 from django.urls import reverse
14 from django.utils import timezone
15 from django.utils.decorators import method_decorator
16 from django.utils.translation import gettext_lazy as _
17 from django.views import View
18 from django.views.generic import FormView, CreateView
19 from django.views.generic.base import TemplateResponseMixin, TemplateView
20 
21 from members.decorators import membership_required
22 from members.models import Membership
23 from . import emails, forms, services
24 from .models import Entry, Registration, Renewal, Reference
25 
26 
27 class BecomeAMemberView(TemplateView):
28     """View that render a HTML template with context data."""
29 
30     template_name = "registrations/become_a_member.html"
31 
32     def get_context_data(self, **kwargs):
33         context = super().get_context_data(**kwargs)
34         context["year_fees"] = floatformat(
35             settings.MEMBERSHIP_PRICES[Entry.MEMBERSHIP_YEAR], 2
36         )
37         context["study_fees"] = floatformat(
38             settings.MEMBERSHIP_PRICES[Entry.MEMBERSHIP_STUDY], 2
39         )
40         return context
41 
42 
43 @method_decorator(staff_member_required, name="dispatch")
44 @method_decorator(
45     permission_required("registrations.review_entries"), name="dispatch",
46 )
47 class EntryAdminView(View):
48     """View that handles the processing of entries."""
49 
50     def post(self, request, *args, **kwargs):
51         action = request.POST.get("action")
52         entry_qs = Entry.objects.filter(pk=kwargs["pk"])
53         try:
54             entry = entry_qs.get()
55         except Entry.DoesNotExist:
56             return redirect("admin:index")
57 
58         if action == "accept":
59             if not services.check_unique_user(entry):
60                 messages.error(
61                     request,
62                     _("Could not accept %s. Username is not unique.")
63                     % model_ngettext(entry, 1),
64                 )
65             elif services.accept_entries(request.user.pk, entry_qs) > 0:
66                 messages.success(
67                     request, _("Successfully accepted %s.") % model_ngettext(entry, 1)
68                 )
69             else:
70                 messages.error(
71                     request, _("Could not accept %s.") % model_ngettext(entry, 1)
72                 )
73         elif action == "reject":
74             if services.reject_entries(request.user.pk, entry_qs) > 0:
75                 messages.success(
76                     request, _("Successfully rejected %s.") % model_ngettext(entry, 1)
77                 )
78             else:
79                 messages.error(
80                     request, _("Could not reject %s.") % model_ngettext(entry, 1)
81                 )
82         elif action == "resend":
83             try:
84                 emails.send_registration_email_confirmation(entry.registration)
85             except Registration.DoesNotExist:
86                 pass
87         elif action == "revert":
88             services.revert_entry(request.user.pk, entry)
89 
90         if entry_qs.filter(renewal=None).exists():
91             content_type = ContentType.objects.get_for_model(Registration)
92         else:
93             content_type = ContentType.objects.get_for_model(Renewal)
94 
95         return redirect(
96             f"admin:{content_type.app_label}_{content_type.model}_change", kwargs["pk"],
97         )
98 
99 
100 class ConfirmEmailView(View, TemplateResponseMixin):
101     """View that renders an HTML template and confirms the email address of the provided registration."""
102 
103     template_name = "registrations/confirm_email.html"
104 
105     def get(self, request, *args, **kwargs):
106         queryset = Registration.objects.filter(pk=kwargs["pk"])
107 
108         processed = 0
109         try:
110             processed = services.confirm_entry(queryset)
111         except ValidationError:
112             pass
113 
114         if processed == 0:
115             return redirect("registrations:register-member")
116 
117         registration = queryset.get()
118 
119         if (
120             registration.membership_type == Membership.BENEFACTOR
121             and not registration.no_references
122         ):
123             emails.send_references_information_message(registration)
124 
125         emails.send_new_registration_board_message(registration)
126 
127         return self.render_to_response({})
128 
129 
130 class BaseRegistrationFormView(FormView):
131     """View that renders a membership registration form."""
132 
133     form_class = forms.MemberRegistrationForm
134     template_name = "registrations/register_member.html"
135 
136     def get_context_data(self, **kwargs):
137         context = super().get_context_data(**kwargs)
138         context["google_api_key"] = settings.GOOGLE_PLACES_API_KEY
139         context["year_fees"] = floatformat(
140             settings.MEMBERSHIP_PRICES[Entry.MEMBERSHIP_YEAR], 2
141         )
142         context["study_fees"] = floatformat(
143             settings.MEMBERSHIP_PRICES[Entry.MEMBERSHIP_STUDY], 2
144         )
145         return context
146 
147     def get(self, request, *args, **kwargs):
148         if request.user.is_authenticated:
149             return redirect("registrations:renew")
150         return super().get(request, args, kwargs)
151 
152     def form_valid(self, form):
153         form.save()
154         emails.send_registration_email_confirmation(form.instance)
155         return redirect("registrations:register-success")
156 
157 
158 class MemberRegistrationFormView(BaseRegistrationFormView):
159     """View that renders the `member` membership registration form."""
160 
161     form_class = forms.MemberRegistrationForm
162     template_name = "registrations/register_member.html"
163 
164     def get_context_data(self, **kwargs):
165         context = super().get_context_data(**kwargs)
166         context["tpay_enabled"] = (
167             settings.THALIA_PAY_ENABLED_PAYMENT_METHOD
168             and settings.THALIA_PAY_FOR_NEW_MEMBERS
169         )
170         return context
171 
172     def post(self, request, *args, **kwargs):
173         request.POST = request.POST.dict()
174         request.POST["language"] = request.LANGUAGE_CODE
175         request.POST["membership_type"] = Membership.MEMBER
176         return super().post(request, *args, **kwargs)
177 
178 
179 class BenefactorRegistrationFormView(BaseRegistrationFormView):
180     """View that renders the `benefactor` membership registration form."""
181 
182     form_class = forms.BenefactorRegistrationForm
183     template_name = "registrations/register_benefactor.html"
184 
185     def get_context_data(self, **kwargs):
186         context = super().get_context_data(**kwargs)
187         context["tpay_enabled"] = (
188             settings.THALIA_PAY_ENABLED_PAYMENT_METHOD
189             and settings.THALIA_PAY_FOR_NEW_MEMBERS
190         )
191         return context
192 
193     def post(self, request, *args, **kwargs):
194         request.POST = request.POST.dict()
195         request.POST["language"] = request.LANGUAGE_CODE
196         request.POST["membership_type"] = Membership.BENEFACTOR
197         request.POST["length"] = Entry.MEMBERSHIP_YEAR
198         request.POST["remarks"] = (
199             "Registered as iCIS employee" if "icis_employee" in request.POST else ""
200         )
201         request.POST["no_references"] = "icis_employee" in request.POST
202         return super().post(request, *args, **kwargs)
203 
204 
205 @method_decorator(login_required, name="dispatch")
206 class RenewalFormView(FormView):
207     """View that renders the membership renewal form."""
208 
209     form_class = forms.RenewalForm
210     template_name = "registrations/renewal.html"
211 
212     def get_context_data(self, **kwargs):
213         context = super().get_context_data(**kwargs)
214         context["year_fees"] = floatformat(
215             settings.MEMBERSHIP_PRICES[Entry.MEMBERSHIP_YEAR], 2
216         )
217         context["study_fees"] = floatformat(
218             settings.MEMBERSHIP_PRICES[Entry.MEMBERSHIP_STUDY], 2
219         )
220         context["latest_membership"] = self.request.member.latest_membership
221         context["latest_renewal"] = Renewal.objects.filter(
222             Q(member=self.request.member)
223             & (
224                 Q(status=Registration.STATUS_ACCEPTED)
225                 | Q(status=Registration.STATUS_REVIEW)
226             )
227         ).last()
228         context["was_member"] = Membership.objects.filter(
229             user=self.request.member, type=Membership.MEMBER
230         ).exists()
231         context["benefactor_type"] = Membership.BENEFACTOR
232         return context
233 
234     def get_form(self, form_class=None):
235         form = super().get_form(form_class)
236         member = self.request.member
237         if member is not None and member.latest_membership is not None:
238             latest_membership = member.latest_membership
239             # If latest membership has not ended or does not ends
240             # within 1 month: do not show 'year' length
241             hide_year_choice = not (
242                 latest_membership is not None
243                 and latest_membership.until is not None
244                 and (latest_membership.until - timezone.now().date()).days <= 31
245             )
246 
247             if hide_year_choice:
248                 form.fields["length"].choices = [
249                     c
250                     for c in form.fields["length"].choices
251                     if c[0] != Entry.MEMBERSHIP_YEAR
252                 ]
253 
254         return form
255 
256     def post(self, request, *args, **kwargs):
257         request.POST = request.POST.dict()
258         if request.member.latest_membership.type == Membership.BENEFACTOR:
259             request.POST["membership_type"] = Membership.BENEFACTOR
260             request.POST["length"] = Entry.MEMBERSHIP_YEAR
261         request.POST["member"] = request.member.pk
262         request.POST["remarks"] = ""
263         request.POST["no_references"] = True
264 
265         if request.POST["membership_type"] == Membership.BENEFACTOR:
266             request.POST["no_references"] = False
267             if Membership.objects.filter(
268                 user=request.member, type=Membership.MEMBER
269             ).exists():
270                 request.POST["remarks"] = "Was a Thalia member in the past."
271                 request.POST["no_references"] = True
272             if "icis_employee" in request.POST:
273                 request.POST["remarks"] = "Registered as iCIS employee."
274                 request.POST["no_references"] = True
275 
276         return super().post(request, *args, **kwargs)
277 
278     def form_valid(self, form):
279         renewal = form.save()
280         if not renewal.no_references:
281             emails.send_references_information_message(renewal)
282         emails.send_new_renewal_board_message(renewal)
283         return redirect("registrations:renew-success")
284 
285 
286 @method_decorator(login_required, name="dispatch")
287 @method_decorator(membership_required, name="dispatch")
288 class ReferenceCreateView(CreateView):
289     """View that renders a reference creation form."""
290 
291     model = Reference
292     form_class = forms.ReferenceForm
293     template_name = "registrations/reference.html"
294     entry = None
295     success = False
296 
297     def get_success_url(self):
298         return reverse("registrations:reference-success", args=(self.entry.pk,))
299 
300     def get_context_data(self, **kwargs):
301         context = super().get_context_data(**kwargs)
302 
303         context["success"] = self.success
304         try:
305             context["name"] = self.entry.registration.get_full_name()
306         except Registration.DoesNotExist:
307             context["name"] = self.entry.renewal.member.get_full_name()
308 
309         return context
310 
311     def dispatch(self, request, *args, **kwargs):
312         self.entry = get_object_or_404(Entry, pk=kwargs.get("pk"))
313 
314         if (
315             self.entry.no_references
316             or self.entry.membership_type != Membership.BENEFACTOR
317         ):
318             raise Http404
319 
320         return super().dispatch(request, *args, **kwargs)
321 
322     def post(self, request, *args, **kwargs):
323         request.POST = request.POST.dict()
324         request.POST["member"] = request.member.pk
325         request.POST["entry"] = kwargs["pk"]
326         return super().post(request, *args, **kwargs)
327
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/website/registrations/views.py b/website/registrations/views.py
--- a/website/registrations/views.py
+++ b/website/registrations/views.py
@@ -237,7 +237,7 @@
         if member is not None and member.latest_membership is not None:
             latest_membership = member.latest_membership
             # If latest membership has not ended or does not ends
-            # within 1 month: do not show 'year' length
+            # within 1 month: do not show 'year' length and disable benefactor option
             hide_year_choice = not (
                 latest_membership is not None
                 and latest_membership.until is not None
@@ -250,6 +250,11 @@
                     for c in form.fields["length"].choices
                     if c[0] != Entry.MEMBERSHIP_YEAR
                 ]
+                form.fields["membership_type"].choices = [
+                    c
+                    for c in form.fields["membership_type"].choices
+                    if c[0] != Membership.BENEFACTOR
+                ]
 
         return form

{"golden_diff": "diff --git a/website/registrations/views.py b/website/registrations/views.py\n--- a/website/registrations/views.py\n+++ b/website/registrations/views.py\n@@ -237,7 +237,7 @@\n         if member is not None and member.latest_membership is not None:\n             latest_membership = member.latest_membership\n             # If latest membership has not ended or does not ends\n-            # within 1 month: do not show 'year' length\n+            # within 1 month: do not show 'year' length and disable benefactor option\n             hide_year_choice = not (\n                 latest_membership is not None\n                 and latest_membership.until is not None\n@@ -250,6 +250,11 @@\n                     for c in form.fields[\"length\"].choices\n                     if c[0] != Entry.MEMBERSHIP_YEAR\n                 ]\n+                form.fields[\"membership_type\"].choices = [\n+                    c\n+                    for c in form.fields[\"membership_type\"].choices\n+                    if c[0] != Membership.BENEFACTOR\n+                ]\n \n         return form\n", "issue": "Cannot renew membership as benefactor, expects length field\n### Describe the bug\r\nRight now, when trying to renew a membership as benefactor from http://localhost:8000/user/membership/ I can't send the form. I get a javascript error: `An invalid form control with name='length' is not focusable.` \r\nSo the problem is that the length field is expected to have a value while this isn't the case for benefactors.\r\n\r\n### How to reproduce\r\nSteps to reproduce the behaviour:\r\n1. Go to http://localhost:8000/user/membership/\r\n2. Add a benefactor membership renewal \r\n3. The form will not respond when trying to send\r\n4. You will get a javascript error, indicating that the form can't focus on the length field (as it is hidden for benefactors), \r\n\r\n### Expected behaviour\r\nIt should ignore the length field for benefactorship renewals, as for benefactors it is always 1 year\r\n\n", "before_files": [{"content": "\"\"\"Views provided by the registrations package.\"\"\"\nfrom django.conf import settings\nfrom django.contrib import messages\nfrom django.contrib.admin.utils import model_ngettext\nfrom django.contrib.admin.views.decorators import staff_member_required\nfrom django.contrib.auth.decorators import login_required, permission_required\nfrom django.contrib.contenttypes.models import ContentType\nfrom django.core.exceptions import ValidationError\nfrom django.db.models import Q\nfrom django.http import Http404\nfrom django.shortcuts import redirect, get_object_or_404\nfrom django.template.defaultfilters import floatformat\nfrom django.urls import reverse\nfrom django.utils import timezone\nfrom django.utils.decorators import method_decorator\nfrom django.utils.translation import gettext_lazy as _\nfrom django.views import View\nfrom django.views.generic import FormView, CreateView\nfrom django.views.generic.base import TemplateResponseMixin, TemplateView\n\nfrom members.decorators import membership_required\nfrom members.models import Membership\nfrom . import emails, forms, services\nfrom .models import Entry, Registration, Renewal, Reference\n\n\nclass BecomeAMemberView(TemplateView):\n    \"\"\"View that render a HTML template with context data.\"\"\"\n\n    template_name = \"registrations/become_a_member.html\"\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context[\"year_fees\"] = floatformat(\n            settings.MEMBERSHIP_PRICES[Entry.MEMBERSHIP_YEAR], 2\n        )\n        context[\"study_fees\"] = floatformat(\n            settings.MEMBERSHIP_PRICES[Entry.MEMBERSHIP_STUDY], 2\n        )\n        return context\n\n\n@method_decorator(staff_member_required, name=\"dispatch\")\n@method_decorator(\n    permission_required(\"registrations.review_entries\"), name=\"dispatch\",\n)\nclass EntryAdminView(View):\n    \"\"\"View that handles the processing of entries.\"\"\"\n\n    def post(self, request, *args, **kwargs):\n        action = request.POST.get(\"action\")\n        entry_qs = Entry.objects.filter(pk=kwargs[\"pk\"])\n        try:\n            entry = entry_qs.get()\n        except Entry.DoesNotExist:\n            return redirect(\"admin:index\")\n\n        if action == \"accept\":\n            if not services.check_unique_user(entry):\n                messages.error(\n                    request,\n                    _(\"Could not accept %s. Username is not unique.\")\n                    % model_ngettext(entry, 1),\n                )\n            elif services.accept_entries(request.user.pk, entry_qs) > 0:\n                messages.success(\n                    request, _(\"Successfully accepted %s.\") % model_ngettext(entry, 1)\n                )\n            else:\n                messages.error(\n                    request, _(\"Could not accept %s.\") % model_ngettext(entry, 1)\n                )\n        elif action == \"reject\":\n            if services.reject_entries(request.user.pk, entry_qs) > 0:\n                messages.success(\n                    request, _(\"Successfully rejected %s.\") % model_ngettext(entry, 1)\n                )\n            else:\n                messages.error(\n                    request, _(\"Could not reject %s.\") % model_ngettext(entry, 1)\n                )\n        elif action == \"resend\":\n            try:\n                emails.send_registration_email_confirmation(entry.registration)\n            except Registration.DoesNotExist:\n                pass\n        elif action == \"revert\":\n            services.revert_entry(request.user.pk, entry)\n\n        if entry_qs.filter(renewal=None).exists():\n            content_type = ContentType.objects.get_for_model(Registration)\n        else:\n            content_type = ContentType.objects.get_for_model(Renewal)\n\n        return redirect(\n            f\"admin:{content_type.app_label}_{content_type.model}_change\", kwargs[\"pk\"],\n        )\n\n\nclass ConfirmEmailView(View, TemplateResponseMixin):\n    \"\"\"View that renders an HTML template and confirms the email address of the provided registration.\"\"\"\n\n    template_name = \"registrations/confirm_email.html\"\n\n    def get(self, request, *args, **kwargs):\n        queryset = Registration.objects.filter(pk=kwargs[\"pk\"])\n\n        processed = 0\n        try:\n            processed = services.confirm_entry(queryset)\n        except ValidationError:\n            pass\n\n        if processed == 0:\n            return redirect(\"registrations:register-member\")\n\n        registration = queryset.get()\n\n        if (\n            registration.membership_type == Membership.BENEFACTOR\n            and not registration.no_references\n        ):\n            emails.send_references_information_message(registration)\n\n        emails.send_new_registration_board_message(registration)\n\n        return self.render_to_response({})\n\n\nclass BaseRegistrationFormView(FormView):\n    \"\"\"View that renders a membership registration form.\"\"\"\n\n    form_class = forms.MemberRegistrationForm\n    template_name = \"registrations/register_member.html\"\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context[\"google_api_key\"] = settings.GOOGLE_PLACES_API_KEY\n        context[\"year_fees\"] = floatformat(\n            settings.MEMBERSHIP_PRICES[Entry.MEMBERSHIP_YEAR], 2\n        )\n        context[\"study_fees\"] = floatformat(\n            settings.MEMBERSHIP_PRICES[Entry.MEMBERSHIP_STUDY], 2\n        )\n        return context\n\n    def get(self, request, *args, **kwargs):\n        if request.user.is_authenticated:\n            return redirect(\"registrations:renew\")\n        return super().get(request, args, kwargs)\n\n    def form_valid(self, form):\n        form.save()\n        emails.send_registration_email_confirmation(form.instance)\n        return redirect(\"registrations:register-success\")\n\n\nclass MemberRegistrationFormView(BaseRegistrationFormView):\n    \"\"\"View that renders the `member` membership registration form.\"\"\"\n\n    form_class = forms.MemberRegistrationForm\n    template_name = \"registrations/register_member.html\"\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context[\"tpay_enabled\"] = (\n            settings.THALIA_PAY_ENABLED_PAYMENT_METHOD\n            and settings.THALIA_PAY_FOR_NEW_MEMBERS\n        )\n        return context\n\n    def post(self, request, *args, **kwargs):\n        request.POST = request.POST.dict()\n        request.POST[\"language\"] = request.LANGUAGE_CODE\n        request.POST[\"membership_type\"] = Membership.MEMBER\n        return super().post(request, *args, **kwargs)\n\n\nclass BenefactorRegistrationFormView(BaseRegistrationFormView):\n    \"\"\"View that renders the `benefactor` membership registration form.\"\"\"\n\n    form_class = forms.BenefactorRegistrationForm\n    template_name = \"registrations/register_benefactor.html\"\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context[\"tpay_enabled\"] = (\n            settings.THALIA_PAY_ENABLED_PAYMENT_METHOD\n            and settings.THALIA_PAY_FOR_NEW_MEMBERS\n        )\n        return context\n\n    def post(self, request, *args, **kwargs):\n        request.POST = request.POST.dict()\n        request.POST[\"language\"] = request.LANGUAGE_CODE\n        request.POST[\"membership_type\"] = Membership.BENEFACTOR\n        request.POST[\"length\"] = Entry.MEMBERSHIP_YEAR\n        request.POST[\"remarks\"] = (\n            \"Registered as iCIS employee\" if \"icis_employee\" in request.POST else \"\"\n        )\n        request.POST[\"no_references\"] = \"icis_employee\" in request.POST\n        return super().post(request, *args, **kwargs)\n\n\n@method_decorator(login_required, name=\"dispatch\")\nclass RenewalFormView(FormView):\n    \"\"\"View that renders the membership renewal form.\"\"\"\n\n    form_class = forms.RenewalForm\n    template_name = \"registrations/renewal.html\"\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context[\"year_fees\"] = floatformat(\n            settings.MEMBERSHIP_PRICES[Entry.MEMBERSHIP_YEAR], 2\n        )\n        context[\"study_fees\"] = floatformat(\n            settings.MEMBERSHIP_PRICES[Entry.MEMBERSHIP_STUDY], 2\n        )\n        context[\"latest_membership\"] = self.request.member.latest_membership\n        context[\"latest_renewal\"] = Renewal.objects.filter(\n            Q(member=self.request.member)\n            & (\n                Q(status=Registration.STATUS_ACCEPTED)\n                | Q(status=Registration.STATUS_REVIEW)\n            )\n        ).last()\n        context[\"was_member\"] = Membership.objects.filter(\n            user=self.request.member, type=Membership.MEMBER\n        ).exists()\n        context[\"benefactor_type\"] = Membership.BENEFACTOR\n        return context\n\n    def get_form(self, form_class=None):\n        form = super().get_form(form_class)\n        member = self.request.member\n        if member is not None and member.latest_membership is not None:\n            latest_membership = member.latest_membership\n            # If latest membership has not ended or does not ends\n            # within 1 month: do not show 'year' length\n            hide_year_choice = not (\n                latest_membership is not None\n                and latest_membership.until is not None\n                and (latest_membership.until - timezone.now().date()).days <= 31\n            )\n\n            if hide_year_choice:\n                form.fields[\"length\"].choices = [\n                    c\n                    for c in form.fields[\"length\"].choices\n                    if c[0] != Entry.MEMBERSHIP_YEAR\n                ]\n\n        return form\n\n    def post(self, request, *args, **kwargs):\n        request.POST = request.POST.dict()\n        if request.member.latest_membership.type == Membership.BENEFACTOR:\n            request.POST[\"membership_type\"] = Membership.BENEFACTOR\n            request.POST[\"length\"] = Entry.MEMBERSHIP_YEAR\n        request.POST[\"member\"] = request.member.pk\n        request.POST[\"remarks\"] = \"\"\n        request.POST[\"no_references\"] = True\n\n        if request.POST[\"membership_type\"] == Membership.BENEFACTOR:\n            request.POST[\"no_references\"] = False\n            if Membership.objects.filter(\n                user=request.member, type=Membership.MEMBER\n            ).exists():\n                request.POST[\"remarks\"] = \"Was a Thalia member in the past.\"\n                request.POST[\"no_references\"] = True\n            if \"icis_employee\" in request.POST:\n                request.POST[\"remarks\"] = \"Registered as iCIS employee.\"\n                request.POST[\"no_references\"] = True\n\n        return super().post(request, *args, **kwargs)\n\n    def form_valid(self, form):\n        renewal = form.save()\n        if not renewal.no_references:\n            emails.send_references_information_message(renewal)\n        emails.send_new_renewal_board_message(renewal)\n        return redirect(\"registrations:renew-success\")\n\n\n@method_decorator(login_required, name=\"dispatch\")\n@method_decorator(membership_required, name=\"dispatch\")\nclass ReferenceCreateView(CreateView):\n    \"\"\"View that renders a reference creation form.\"\"\"\n\n    model = Reference\n    form_class = forms.ReferenceForm\n    template_name = \"registrations/reference.html\"\n    entry = None\n    success = False\n\n    def get_success_url(self):\n        return reverse(\"registrations:reference-success\", args=(self.entry.pk,))\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n\n        context[\"success\"] = self.success\n        try:\n            context[\"name\"] = self.entry.registration.get_full_name()\n        except Registration.DoesNotExist:\n            context[\"name\"] = self.entry.renewal.member.get_full_name()\n\n        return context\n\n    def dispatch(self, request, *args, **kwargs):\n        self.entry = get_object_or_404(Entry, pk=kwargs.get(\"pk\"))\n\n        if (\n            self.entry.no_references\n            or self.entry.membership_type != Membership.BENEFACTOR\n        ):\n            raise Http404\n\n        return super().dispatch(request, *args, **kwargs)\n\n    def post(self, request, *args, **kwargs):\n        request.POST = request.POST.dict()\n        request.POST[\"member\"] = request.member.pk\n        request.POST[\"entry\"] = kwargs[\"pk\"]\n        return super().post(request, *args, **kwargs)\n", "path": "website/registrations/views.py"}], "after_files": [{"content": "\"\"\"Views provided by the registrations package.\"\"\"\nfrom django.conf import settings\nfrom django.contrib import messages\nfrom django.contrib.admin.utils import model_ngettext\nfrom django.contrib.admin.views.decorators import staff_member_required\nfrom django.contrib.auth.decorators import login_required, permission_required\nfrom django.contrib.contenttypes.models import ContentType\nfrom django.core.exceptions import ValidationError\nfrom django.db.models import Q\nfrom django.http import Http404\nfrom django.shortcuts import redirect, get_object_or_404\nfrom django.template.defaultfilters import floatformat\nfrom django.urls import reverse\nfrom django.utils import timezone\nfrom django.utils.decorators import method_decorator\nfrom django.utils.translation import gettext_lazy as _\nfrom django.views import View\nfrom django.views.generic import FormView, CreateView\nfrom django.views.generic.base import TemplateResponseMixin, TemplateView\n\nfrom members.decorators import membership_required\nfrom members.models import Membership\nfrom . import emails, forms, services\nfrom .models import Entry, Registration, Renewal, Reference\n\n\nclass BecomeAMemberView(TemplateView):\n    \"\"\"View that render a HTML template with context data.\"\"\"\n\n    template_name = \"registrations/become_a_member.html\"\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context[\"year_fees\"] = floatformat(\n            settings.MEMBERSHIP_PRICES[Entry.MEMBERSHIP_YEAR], 2\n        )\n        context[\"study_fees\"] = floatformat(\n            settings.MEMBERSHIP_PRICES[Entry.MEMBERSHIP_STUDY], 2\n        )\n        return context\n\n\n@method_decorator(staff_member_required, name=\"dispatch\")\n@method_decorator(\n    permission_required(\"registrations.review_entries\"), name=\"dispatch\",\n)\nclass EntryAdminView(View):\n    \"\"\"View that handles the processing of entries.\"\"\"\n\n    def post(self, request, *args, **kwargs):\n        action = request.POST.get(\"action\")\n        entry_qs = Entry.objects.filter(pk=kwargs[\"pk\"])\n        try:\n            entry = entry_qs.get()\n        except Entry.DoesNotExist:\n            return redirect(\"admin:index\")\n\n        if action == \"accept\":\n            if not services.check_unique_user(entry):\n                messages.error(\n                    request,\n                    _(\"Could not accept %s. Username is not unique.\")\n                    % model_ngettext(entry, 1),\n                )\n            elif services.accept_entries(request.user.pk, entry_qs) > 0:\n                messages.success(\n                    request, _(\"Successfully accepted %s.\") % model_ngettext(entry, 1)\n                )\n            else:\n                messages.error(\n                    request, _(\"Could not accept %s.\") % model_ngettext(entry, 1)\n                )\n        elif action == \"reject\":\n            if services.reject_entries(request.user.pk, entry_qs) > 0:\n                messages.success(\n                    request, _(\"Successfully rejected %s.\") % model_ngettext(entry, 1)\n                )\n            else:\n                messages.error(\n                    request, _(\"Could not reject %s.\") % model_ngettext(entry, 1)\n                )\n        elif action == \"resend\":\n            try:\n                emails.send_registration_email_confirmation(entry.registration)\n            except Registration.DoesNotExist:\n                pass\n        elif action == \"revert\":\n            services.revert_entry(request.user.pk, entry)\n\n        if entry_qs.filter(renewal=None).exists():\n            content_type = ContentType.objects.get_for_model(Registration)\n        else:\n            content_type = ContentType.objects.get_for_model(Renewal)\n\n        return redirect(\n            f\"admin:{content_type.app_label}_{content_type.model}_change\", kwargs[\"pk\"],\n        )\n\n\nclass ConfirmEmailView(View, TemplateResponseMixin):\n    \"\"\"View that renders an HTML template and confirms the email address of the provided registration.\"\"\"\n\n    template_name = \"registrations/confirm_email.html\"\n\n    def get(self, request, *args, **kwargs):\n        queryset = Registration.objects.filter(pk=kwargs[\"pk\"])\n\n        processed = 0\n        try:\n            processed = services.confirm_entry(queryset)\n        except ValidationError:\n            pass\n\n        if processed == 0:\n            return redirect(\"registrations:register-member\")\n\n        registration = queryset.get()\n\n        if (\n            registration.membership_type == Membership.BENEFACTOR\n            and not registration.no_references\n        ):\n            emails.send_references_information_message(registration)\n\n        emails.send_new_registration_board_message(registration)\n\n        return self.render_to_response({})\n\n\nclass BaseRegistrationFormView(FormView):\n    \"\"\"View that renders a membership registration form.\"\"\"\n\n    form_class = forms.MemberRegistrationForm\n    template_name = \"registrations/register_member.html\"\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context[\"google_api_key\"] = settings.GOOGLE_PLACES_API_KEY\n        context[\"year_fees\"] = floatformat(\n            settings.MEMBERSHIP_PRICES[Entry.MEMBERSHIP_YEAR], 2\n        )\n        context[\"study_fees\"] = floatformat(\n            settings.MEMBERSHIP_PRICES[Entry.MEMBERSHIP_STUDY], 2\n        )\n        return context\n\n    def get(self, request, *args, **kwargs):\n        if request.user.is_authenticated:\n            return redirect(\"registrations:renew\")\n        return super().get(request, args, kwargs)\n\n    def form_valid(self, form):\n        form.save()\n        emails.send_registration_email_confirmation(form.instance)\n        return redirect(\"registrations:register-success\")\n\n\nclass MemberRegistrationFormView(BaseRegistrationFormView):\n    \"\"\"View that renders the `member` membership registration form.\"\"\"\n\n    form_class = forms.MemberRegistrationForm\n    template_name = \"registrations/register_member.html\"\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context[\"tpay_enabled\"] = (\n            settings.THALIA_PAY_ENABLED_PAYMENT_METHOD\n            and settings.THALIA_PAY_FOR_NEW_MEMBERS\n        )\n        return context\n\n    def post(self, request, *args, **kwargs):\n        request.POST = request.POST.dict()\n        request.POST[\"language\"] = request.LANGUAGE_CODE\n        request.POST[\"membership_type\"] = Membership.MEMBER\n        return super().post(request, *args, **kwargs)\n\n\nclass BenefactorRegistrationFormView(BaseRegistrationFormView):\n    \"\"\"View that renders the `benefactor` membership registration form.\"\"\"\n\n    form_class = forms.BenefactorRegistrationForm\n    template_name = \"registrations/register_benefactor.html\"\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context[\"tpay_enabled\"] = (\n            settings.THALIA_PAY_ENABLED_PAYMENT_METHOD\n            and settings.THALIA_PAY_FOR_NEW_MEMBERS\n        )\n        return context\n\n    def post(self, request, *args, **kwargs):\n        request.POST = request.POST.dict()\n        request.POST[\"language\"] = request.LANGUAGE_CODE\n        request.POST[\"membership_type\"] = Membership.BENEFACTOR\n        request.POST[\"length\"] = Entry.MEMBERSHIP_YEAR\n        request.POST[\"remarks\"] = (\n            \"Registered as iCIS employee\" if \"icis_employee\" in request.POST else \"\"\n        )\n        request.POST[\"no_references\"] = \"icis_employee\" in request.POST\n        return super().post(request, *args, **kwargs)\n\n\n@method_decorator(login_required, name=\"dispatch\")\nclass RenewalFormView(FormView):\n    \"\"\"View that renders the membership renewal form.\"\"\"\n\n    form_class = forms.RenewalForm\n    template_name = \"registrations/renewal.html\"\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context[\"year_fees\"] = floatformat(\n            settings.MEMBERSHIP_PRICES[Entry.MEMBERSHIP_YEAR], 2\n        )\n        context[\"study_fees\"] = floatformat(\n            settings.MEMBERSHIP_PRICES[Entry.MEMBERSHIP_STUDY], 2\n        )\n        context[\"latest_membership\"] = self.request.member.latest_membership\n        context[\"latest_renewal\"] = Renewal.objects.filter(\n            Q(member=self.request.member)\n            & (\n                Q(status=Registration.STATUS_ACCEPTED)\n                | Q(status=Registration.STATUS_REVIEW)\n            )\n        ).last()\n        context[\"was_member\"] = Membership.objects.filter(\n            user=self.request.member, type=Membership.MEMBER\n        ).exists()\n        context[\"benefactor_type\"] = Membership.BENEFACTOR\n        return context\n\n    def get_form(self, form_class=None):\n        form = super().get_form(form_class)\n        member = self.request.member\n        if member is not None and member.latest_membership is not None:\n            latest_membership = member.latest_membership\n            # If latest membership has not ended or does not ends\n            # within 1 month: do not show 'year' length and disable benefactor option\n            hide_year_choice = not (\n                latest_membership is not None\n                and latest_membership.until is not None\n                and (latest_membership.until - timezone.now().date()).days <= 31\n            )\n\n            if hide_year_choice:\n                form.fields[\"length\"].choices = [\n                    c\n                    for c in form.fields[\"length\"].choices\n                    if c[0] != Entry.MEMBERSHIP_YEAR\n                ]\n                form.fields[\"membership_type\"].choices = [\n                    c\n                    for c in form.fields[\"membership_type\"].choices\n                    if c[0] != Membership.BENEFACTOR\n                ]\n\n        return form\n\n    def post(self, request, *args, **kwargs):\n        request.POST = request.POST.dict()\n        if request.member.latest_membership.type == Membership.BENEFACTOR:\n            request.POST[\"membership_type\"] = Membership.BENEFACTOR\n            request.POST[\"length\"] = Entry.MEMBERSHIP_YEAR\n        request.POST[\"member\"] = request.member.pk\n        request.POST[\"remarks\"] = \"\"\n        request.POST[\"no_references\"] = True\n\n        if request.POST[\"membership_type\"] == Membership.BENEFACTOR:\n            request.POST[\"no_references\"] = False\n            if Membership.objects.filter(\n                user=request.member, type=Membership.MEMBER\n            ).exists():\n                request.POST[\"remarks\"] = \"Was a Thalia member in the past.\"\n                request.POST[\"no_references\"] = True\n            if \"icis_employee\" in request.POST:\n                request.POST[\"remarks\"] = \"Registered as iCIS employee.\"\n                request.POST[\"no_references\"] = True\n\n        return super().post(request, *args, **kwargs)\n\n    def form_valid(self, form):\n        renewal = form.save()\n        if not renewal.no_references:\n            emails.send_references_information_message(renewal)\n        emails.send_new_renewal_board_message(renewal)\n        return redirect(\"registrations:renew-success\")\n\n\n@method_decorator(login_required, name=\"dispatch\")\n@method_decorator(membership_required, name=\"dispatch\")\nclass ReferenceCreateView(CreateView):\n    \"\"\"View that renders a reference creation form.\"\"\"\n\n    model = Reference\n    form_class = forms.ReferenceForm\n    template_name = \"registrations/reference.html\"\n    entry = None\n    success = False\n\n    def get_success_url(self):\n        return reverse(\"registrations:reference-success\", args=(self.entry.pk,))\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n\n        context[\"success\"] = self.success\n        try:\n            context[\"name\"] = self.entry.registration.get_full_name()\n        except Registration.DoesNotExist:\n            context[\"name\"] = self.entry.renewal.member.get_full_name()\n\n        return context\n\n    def dispatch(self, request, *args, **kwargs):\n        self.entry = get_object_or_404(Entry, pk=kwargs.get(\"pk\"))\n\n        if (\n            self.entry.no_references\n            or self.entry.membership_type != Membership.BENEFACTOR\n        ):\n            raise Http404\n\n        return super().dispatch(request, *args, **kwargs)\n\n    def post(self, request, *args, **kwargs):\n        request.POST = request.POST.dict()\n        request.POST[\"member\"] = request.member.pk\n        request.POST[\"entry\"] = kwargs[\"pk\"]\n        return super().post(request, *args, **kwargs)\n", "path": "website/registrations/views.py"}]}