Source code for invitations.views

__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
__license__ = "AGPL v3"


from django.contrib import messages
from django.contrib.auth.decorators import login_required, permission_required
from django.db import transaction
from django.shortcuts import render, redirect
from django.urls import reverse_lazy, reverse
from django.views.generic.list import ListView
from django.views.generic.edit import UpdateView, DeleteView

from .constants import INVITATION_EDITORIAL_FELLOW
from .forms import RegistrationInvitationForm, RegistrationInvitationReminderForm,\
    RegistrationInvitationMarkForm, RegistrationInvitationMapToContributorForm,\
    CitationNotificationForm, SuggestionSearchForm, RegistrationInvitationFilterForm,\
    CitationNotificationProcessForm, RegistrationInvitationAddCitationForm,\
    RegistrationInvitationMergeForm
from .mixins import RequestArgumentMixin
from .models import RegistrationInvitation, CitationNotification

from scipost.models import Contributor
from scipost.mixins import PaginationMixin, PermissionsMixin
from mails.views import MailFormView


[docs]class RegistrationInvitationsView(PaginationMixin, PermissionsMixin, ListView): permission_required = 'scipost.can_create_registration_invitations' queryset = RegistrationInvitation.objects.drafts().not_for_fellows() paginate_by = 10 ordering = ['date_sent_last', 'last_name'] search_form = None
[docs] def get_queryset(self): self.search_form = RegistrationInvitationFilterForm(self.request.GET or None) if self.search_form.is_valid(): self.queryset = self.search_form.search(self.queryset) return super().get_queryset()
[docs] def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['count_in_draft'] = RegistrationInvitation.objects.drafts().count() context['count_pending'] = RegistrationInvitation.objects.sent().count() context['count_unprocessed'] = CitationNotification.objects.unprocessed().count() context['search_form'] = self.search_form return context
[docs]class RegistrationInvitationsSentView(RegistrationInvitationsView): permission_required = 'scipost.can_manage_registration_invitations' queryset = RegistrationInvitation.objects.sent().not_for_fellows() template_name = 'invitations/registrationinvitation_list_sent.html'
[docs]class RegistrationInvitationsDraftContributorView(RegistrationInvitationsView): permission_required = 'scipost.can_manage_registration_invitations' queryset = RegistrationInvitation.objects.drafts().for_contributors() template_name = 'invitations/registrationinvitation_list_contributors.html'
[docs] def get_queryset(self): qs = super().get_queryset() return qs.order_by('created')
[docs]class RegistrationInvitationsFellowView(RegistrationInvitationsView): permission_required = 'scipost.can_invite_fellows' queryset = RegistrationInvitation.objects.no_response().for_fellows() template_name = 'invitations/registrationinvitation_list_fellows.html'
[docs]class CitationNotificationsView(PermissionsMixin, PaginationMixin, ListView): permission_required = 'scipost.can_manage_registration_invitations' queryset = CitationNotification.objects.unprocessed().prefetch_related( 'invitation', 'contributor', 'contributor__user') paginate_by = 25
[docs]class CitationNotificationsProcessView(PermissionsMixin, RequestArgumentMixin, MailFormView): permission_required = 'scipost.can_manage_registration_invitations' form_class = CitationNotificationProcessForm queryset = CitationNotification.objects.unprocessed() success_url = reverse_lazy('invitations:citation_notification_list') mail_code = 'citation_notification'
[docs] def can_send_mail(self): """ Only send mail if Contributor has not opted-out. """ citation = self.get_form().get_all_notifications().filter(contributor__isnull=False).first() if not citation.contributor: return True return citation.contributor.accepts_SciPost_emails
[docs] @transaction.atomic def form_valid(self, form): """ Form is valid; the MailFormView will send the mail if (possible) Contributor didn't opt-out from mails. """ form.get_all_notifications().update(processed=True) return super().form_valid(form)
[docs]@login_required @permission_required('scipost.can_create_registration_invitations', raise_exception=True) @transaction.atomic def create_registration_invitation_or_citation(request): """ Create a new Registration Invitation or Citation Notification, depending whether it is meant for an already existing Contributor or not. """ contributors = [] suggested_invitations = [] declined_invitations = [] # Only take specific GET data to prevent for unexpected bound forms. search_data = {} initial_search_data = {} if request.GET.get('last_name'): 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'] 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) # New citation is related to a Contributor: RegistationInvitation invitation_form = RegistrationInvitationForm(request.POST or None, request=request, prefix='invitation', initial=initial_search_data) if invitation_form.is_valid(): invitation_form.save() messages.success(request, 'New Registration Invitation created') if request.POST.get('save') == 'save_and_create': return redirect('invitations:new') return redirect('invitations:list') # New citation is related to a Contributor: CitationNotification if citation_form.is_valid(): citation_form.save() messages.success(request, 'New Citation Notification created') if request.POST.get('save') == 'save_and_create': return redirect('invitations:new') return redirect('invitations:list') context = { '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)
[docs]class RegistrationInvitationsUpdateView(RequestArgumentMixin, PermissionsMixin, MailFormView): permission_required = 'scipost.can_create_registration_invitations' form_class = RegistrationInvitationForm mail_code = 'registration_invitation'
[docs] def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['invitation_form'] = context['form'] return context
[docs] def get_success_url(self): if self.request.POST.get('save') == 'save_and_create': return reverse('invitations:new') return reverse('invitations:list')
[docs] def get_queryset(self): qs = RegistrationInvitation.objects.drafts() if not self.request.user.has_perm('scipost.can_invite_fellows'): qs = qs.not_for_fellows() if not self.request.user.has_perm('scipost.can_manage_registration_invitations'): qs = qs.created_by(self.request.user) return qs
[docs] def can_send_mail(self): return self.request.user.has_perm('scipost.can_manage_registration_invitations')
[docs] def get_mail_config(self): config = super().get_mail_config() print('Config', config) print(self.object) if self.object.invitation_type == INVITATION_EDITORIAL_FELLOW: config['from_email'] = 'jscaux@scipost.org' config['from_name'] = 'J-S Caux' return config
[docs]class RegistrationInvitationsMergeView(RequestArgumentMixin, PermissionsMixin, UpdateView): permission_required = 'scipost.can_manage_registration_invitations' queryset = RegistrationInvitation.objects.no_response() form_class = RegistrationInvitationMergeForm template_name = 'invitations/registrationinvitation_form_merge.html' success_url = reverse_lazy('invitations:list')
[docs]class RegistrationInvitationsAddCitationView(RequestArgumentMixin, PermissionsMixin, UpdateView): permission_required = 'scipost.can_create_registration_invitations' form_class = RegistrationInvitationAddCitationForm template_name = 'invitations/registrationinvitation_form_add_citation.html' success_url = reverse_lazy('invitations:list') queryset = RegistrationInvitation.objects.no_response()
[docs]class RegistrationInvitationsMarkView(RequestArgumentMixin, PermissionsMixin, UpdateView): permission_required = 'scipost.can_manage_registration_invitations' queryset = RegistrationInvitation.objects.drafts() form_class = RegistrationInvitationMarkForm template_name = 'invitations/registrationinvitation_form_mark_as.html' success_url = reverse_lazy('invitations:list')
[docs]class RegistrationInvitationsMapToContributorView(RequestArgumentMixin, PermissionsMixin, UpdateView): permission_required = 'scipost.can_manage_registration_invitations' model = RegistrationInvitation form_class = RegistrationInvitationMapToContributorForm template_name = 'invitations/registrationinvitation_form_map_to_contributor.html' success_url = reverse_lazy('invitations:list')
[docs]class RegistrationInvitationsReminderView(RequestArgumentMixin, PermissionsMixin, MailFormView): permission_required = 'scipost.can_manage_registration_invitations' queryset = RegistrationInvitation.objects.sent() success_url = reverse_lazy('invitations:list') form_class = RegistrationInvitationReminderForm template_name = 'invitations/registrationinvitation_reminder_form.html' mail_code = 'registration_invitation_reminder'
[docs] def get_mail_config(self): config = super().get_mail_config() if self.object.invitation_type == INVITATION_EDITORIAL_FELLOW: config['from_email'] = 'jscaux@scipost.org' config['from_name'] = 'J-S Caux' return config
[docs]class RegistrationInvitationsDeleteView(PermissionsMixin, DeleteView): permission_required = 'scipost.can_manage_registration_invitations' model = RegistrationInvitation success_url = reverse_lazy('invitations:list')
[docs]@login_required @permission_required('scipost.can_manage_registration_invitations', raise_exception=True) def cleanup(request): """ Compares the email addresses of invitations with those in the database of registered Contributors. Flags overlaps. """ contributor_email_list = Contributor.objects.values_list('user__email', flat=True) invitations = RegistrationInvitation.objects.sent().filter(email__in=contributor_email_list) context = { 'invitations': invitations } return render(request, 'invitations/registrationinvitation_cleanup.html', context)