diff --git a/tjdests/apps/profile/forms.py b/tjdests/apps/profile/forms.py index d279379..db94828 100644 --- a/tjdests/apps/profile/forms.py +++ b/tjdests/apps/profile/forms.py @@ -4,6 +4,7 @@ from crispy_forms.helper import FormHelper from crispy_forms.layout import Submit from django import forms +from django.core.exceptions import ValidationError from tjdests.apps.authentication.models import User from tjdests.apps.destinations.models import Decision, TestScore @@ -36,6 +37,44 @@ class DecisionForm(forms.ModelForm): model = Decision fields = ["college", "decision_type", "admission_status"] + def __init__(self, *args, **kwargs): + self.request = kwargs.pop("request", None) + self.is_edit = kwargs.pop("edit", False) + super().__init__(*args, **kwargs) + + def clean(self) -> Dict[str, Any]: + cleaned_data = super().clean() + + # Ensure that the college is not a duplicate for this user + # Yes, this is weird. Basically: if we are not editing + # (i.e. creating a new one), we make sure that + # the user does not have a Decision object with that college already. + # If we are editing, then we ensure that the college + # has not changed. If it has changed, then we + # make sure that the user does not have a Decision object with that college already. + if ( + not self.is_edit + and Decision.objects.filter( + user=self.request.user, college=cleaned_data.get("college") + ).count() + > 0 + ) or ( + self.is_edit + and Decision.objects.filter( + user=self.request.user, + id=self.instance.id, + college=cleaned_data.get("college"), + ).count() + != 1 + and Decision.objects.filter( + user=self.request.user, college=cleaned_data.get("college") + ).count() + > 0 + ): + raise ValidationError("You cannot add a second entry for this college") + + return cleaned_data + class TestScoreForm(forms.ModelForm): class Meta: diff --git a/tjdests/apps/profile/views.py b/tjdests/apps/profile/views.py index 73d381e..7b8de37 100644 --- a/tjdests/apps/profile/views.py +++ b/tjdests/apps/profile/views.py @@ -1,3 +1,5 @@ +from typing import Any, Dict + from django.contrib import messages from django.contrib.auth.decorators import login_required from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin @@ -10,7 +12,7 @@ from django.views.generic import CreateView, DeleteView, UpdateView from tjdests.apps.authentication.decorators import require_accept_tos from tjdests.apps.destinations.models import Decision, TestScore -from .forms import ProfilePublishForm, TestScoreForm +from .forms import DecisionForm, ProfilePublishForm, TestScoreForm @login_required @@ -103,7 +105,7 @@ class DecisionCreateView( LoginRequiredMixin, SuccessMessageMixin, UserPassesTestMixin, CreateView ): model = Decision - fields = ["college", "decision_type", "admission_status"] + form_class = DecisionForm template_name = "profile/decision_form.html" success_message = "Decision created successfully." @@ -111,6 +113,11 @@ class DecisionCreateView( form.instance.user = self.request.user return super().form_valid(form) + def get_form_kwargs(self) -> Dict[str, Any]: + form_kwargs = super().get_form_kwargs() + form_kwargs["request"] = self.request + return form_kwargs + def test_func(self): return self.request.user.is_senior and self.request.user.accepted_terms @@ -122,7 +129,7 @@ class DecisionUpdateView( LoginRequiredMixin, SuccessMessageMixin, UserPassesTestMixin, UpdateView ): model = Decision - fields = ["college", "decision_type", "admission_status"] + form_class = DecisionForm template_name = "profile/decision_form.html" success_message = "Decision created successfully." @@ -130,6 +137,12 @@ class DecisionUpdateView( form.instance.user = self.request.user return super().form_valid(form) + def get_form_kwargs(self) -> Dict[str, Any]: + form_kwargs = super().get_form_kwargs() + form_kwargs["request"] = self.request + form_kwargs["edit"] = True + return form_kwargs + def get_queryset(self): owner = self.request.user return self.model.objects.filter(user=owner)