diff --git a/invitations/forms.py b/invitations/forms.py index afd2f63135dd0e54e067566ec39199c77812d1a5..45e5fa3b5b9360981891ac511315f544f6115708 100644 --- a/invitations/forms.py +++ b/invitations/forms.py @@ -7,7 +7,6 @@ from submissions.models import Submission from . import constants from .models import RegistrationInvitation, CitationNotification -from .utils import Utils from ajax_select.fields import AutoCompleteSelectField, AutoCompleteSelectMultipleField @@ -26,7 +25,7 @@ class RegistrationInvitationFilterForm(forms.Form): return qs.filter(last_name__icontains=last_name) -class ContributorSearchForm(forms.Form): +class SuggestionSearchForm(forms.Form): last_name = forms.CharField() def search(self): @@ -35,7 +34,9 @@ class ContributorSearchForm(forms.Form): if last_name: contributors = Contributor.objects.filter(user__last_name__icontains=last_name) invitations = RegistrationInvitation.objects.filter(last_name__icontains=last_name) - return contributors, invitations + declines = RegistrationInvitation.objects.declined().filter( + last_name__icontains=last_name) + return contributors, invitations, declines return Contributor.objects.none(), RegistrationInvitation.objects.none() @@ -142,6 +143,16 @@ class RegistrationInvitationForm(AcceptRequestMixin, forms.ModelForm): del self.fields['message_style'] del self.fields['personal_message'] + + def clean_email(self): + email = self.cleaned_data['email'] + if Contributor.objects.filter(user__email=email).exists(): + self.add_error('email', 'This email address is already associated to a Contributor') + elif RegistrationInvitation.objects.declined().filter(email=email).exists(): + self.add_error('email', 'This person has already declined an earlier invitation') + + return email + def save(self, *args, **kwargs): if not hasattr(self.instance, 'created_by'): self.instance.created_by = self.request.user diff --git a/invitations/models.py b/invitations/models.py index 66d245832520a9badf11a8538e5efee79a48e131..ddfce32025f16e39cf6b35db16b7ab4bd4da6f3f 100644 --- a/invitations/models.py +++ b/invitations/models.py @@ -35,10 +35,6 @@ class RegistrationInvitation(models.Model): # Related to objects invitation_type = models.CharField(max_length=2, choices=constants.INVITATION_TYPE, default=constants.INVITATION_CONTRIBUTOR) - # cited_in_submissions = models.ManyToManyField('submissions.Submission', - # blank=True, related_name='+') - # cited_in_publications = models.ManyToManyField('journals.Publication', - # blank=True, related_name='+') # Response keys invitation_key = models.CharField(max_length=40, unique=True) diff --git a/invitations/templates/invitations/registrationinvitation_form_add_new.html b/invitations/templates/invitations/registrationinvitation_form_add_new.html index 3f3fae14564d2df091b14b05e2bdeb9764fbf8b7..922c6f743be867698e6c4cb2513ae40ef85300f8 100644 --- a/invitations/templates/invitations/registrationinvitation_form_add_new.html +++ b/invitations/templates/invitations/registrationinvitation_form_add_new.html @@ -20,18 +20,18 @@ If you want to invite a new Contributor to SciPost, first try to use the following search form to see if this person already is available in the SciPost database. </p> - {% if contributor_search_form %} + {% if suggestion_search_form %} <h3 class="mb-1">Search for existing Contributor</h3> <form method="get"> - {{ contributor_search_form|bootstrap }} + {{ suggestion_search_form|bootstrap }} <input type="submit" class="btn btn-primary" value="Search"> - {% if contributor_search_form.is_bound %} + {% if suggestion_search_form.is_bound %} <a href="{% url 'invitations:new' %}" class="ml-2 btn btn-link">Cancel search</a> {% endif %} </form> <hr class="divider"> - {% if contributor_search_form.is_bound %} + {% if suggestion_search_form.is_bound %} {% if suggested_invitations %} <h3>Registration Invitations found</h3> <p> @@ -43,10 +43,21 @@ {% endfor %} </ul> {% endif %} + {% if declined_invitations %} + <h3>Declined Registration Invitations</h3> + <p> + If the person you are trying to invite is within this list of Registration Invitations, do not invite them again. They have already declined an earlier invitation. + </p> + <ul class="mb-2"> + {% for inv in declined_invitations %} + <li>{{ inv.first_name }} {{ inv.last_name }}: {{ inv.email }}</a></li> + {% endfor %} + </ul> + {% endif %} <h3>Citation Notification</h3> <p> - If the person you are trying to invite is already a registered Contributor, it'll be listed in the following form. If not, you can <a href="{% url 'invitations:new' %}?prefill-last_name={{ contributor_search_form.last_name.value|urlencode }}">write a new Registration Invitation</a>. + If the person you are trying to invite is already a registered Contributor, it'll be listed in the following form. If not, you can <a href="{% url 'invitations:new' %}?prefill-last_name={{ suggestion_search_form.last_name.value|urlencode }}">write a new Registration Invitation</a>. </p> {% else %} <h3 class="mb-1">...or write a new Registration Invitation</h3> @@ -54,7 +65,7 @@ {% endif %} - {% if contributor_search_form.is_bound %} + {% if suggestion_search_form.is_bound %} <form method="post"> {% csrf_token %} {{ citation_form|bootstrap }} diff --git a/invitations/views.py b/invitations/views.py index 406ef0459c6669efaa750978eb9dbb17156b2133..60e8351a36c128701dbb63b0f83886d9373f8692 100644 --- a/invitations/views.py +++ b/invitations/views.py @@ -8,7 +8,7 @@ from django.views.generic.edit import UpdateView, DeleteView from .forms import RegistrationInvitationForm, RegistrationInvitationReminderForm,\ RegistrationInvitationMarkForm, RegistrationInvitationMapToContributorForm,\ - CitationNotificationForm, ContributorSearchForm, RegistrationInvitationFilterForm,\ + CitationNotificationForm, SuggestionSearchForm, RegistrationInvitationFilterForm,\ CitationNotificationProcessForm, RegistrationInvitationAddCitationForm from .mixins import RequestArgumentMixin, PermissionsMixin, SaveAndSendFormMixin from .models import RegistrationInvitation, CitationNotification @@ -75,6 +75,7 @@ def create_registration_invitation_or_citation(request): """ contributors = [] suggested_invitations = [] + declined_invitations = [] # Only take specific GET data to prevent for unexpected bound forms. search_data = {} @@ -83,10 +84,10 @@ def create_registration_invitation_or_citation(request): search_data['last_name'] = request.GET['last_name'] if request.GET.get('prefill-last_name'): initial_search_data['last_name'] = request.GET['prefill-last_name'] - contributor_search_form = ContributorSearchForm(search_data or None, - initial=initial_search_data) - if contributor_search_form.is_valid(): - contributors, suggested_invitations = contributor_search_form.search() + suggestion_search_form = SuggestionSearchForm(search_data or None, + initial=initial_search_data) + if suggestion_search_form.is_valid(): + contributors, suggested_invitations, declined_invitations = suggestion_search_form.search() citation_form = CitationNotificationForm(request.POST or None, contributors=contributors, prefix='notification', request=request) @@ -110,9 +111,10 @@ def create_registration_invitation_or_citation(request): return redirect('invitations:list') context = { - 'contributor_search_form': contributor_search_form, + 'suggestion_search_form': suggestion_search_form, 'citation_form': citation_form, 'suggested_invitations': suggested_invitations, + 'declined_invitations': declined_invitations, 'invitation_form': invitation_form, } return render(request, 'invitations/registrationinvitation_form_add_new.html', context)