Skip to content
Snippets Groups Projects
views.py 7.74 KiB
Newer Older
  • Learn to ignore specific revisions
  • from django import forms
    
    from django.contrib.auth.decorators import login_required
    
    from django.core.exceptions import PermissionDenied
    
    from django.http import HttpResponseRedirect
    
    from django.template.response import TemplateResponse
    
    from django.utils.decorators import method_decorator
    
    from django.views.generic import UpdateView
    
    from django_filters.views import FilterView
    from django_tables2.views import SingleTableMixin
    
    
    from opentech.apply.activity.views import (
        AllActivityContextMixin,
        ActivityContextMixin,
        CommentFormView,
        DelegatedViewMixin,
    )
    
    from opentech.apply.activity.models import Activity
    
    from opentech.apply.users.decorators import staff_required
    
    from opentech.apply.utils.views import DelegateableView, ViewDispatcher
    
    from .blocks import MustIncludeFieldBlock
    
    from .forms import ProgressSubmissionForm, UpdateSubmissionLeadForm
    
    Todd Dembrey's avatar
    Todd Dembrey committed
    from .models import ApplicationSubmission
    
    from .tables import AdminSubmissionsTable, SubmissionFilter, SubmissionFilterAndSearch
    
    Todd Dembrey's avatar
    Todd Dembrey committed
    from .workflow import SingleStage, DoubleStage
    
    @method_decorator(staff_required, name='dispatch')
    
    class SubmissionListView(AllActivityContextMixin, SingleTableMixin, FilterView):
    
        template_name = 'funds/submissions.html'
    
        table_class = AdminSubmissionsTable
    
    
        filterset_class = SubmissionFilter
    
    
        def get_queryset(self):
            return self.filterset_class._meta.model.objects.current()
    
    
        def get_context_data(self, **kwargs):
            active_filters = self.filterset.data
            return super().get_context_data(active_filters=active_filters, **kwargs)
    
    
    
    @method_decorator(staff_required, name='dispatch')
    
    class SubmissionSearchView(SingleTableMixin, FilterView):
        template_name = 'funds/submissions_search.html'
    
        table_class = AdminSubmissionsTable
    
    
        filterset_class = SubmissionFilterAndSearch
    
    
        def get_queryset(self):
            return self.filterset_class._meta.model.objects.current()
    
    
        def get_context_data(self, **kwargs):
            search_term = self.request.GET.get('query')
    
            # We have more data than just 'query'
            active_filters = len(self.filterset.data) > 1
    
            return super().get_context_data(
                search_term=search_term,
                active_filters=active_filters,
                **kwargs,
            )
    
    
    @method_decorator(staff_required, name='dispatch')
    
    Todd Dembrey's avatar
    Todd Dembrey committed
    class ProgressSubmissionView(DelegatedViewMixin, UpdateView):
    
        model = ApplicationSubmission
        form_class = ProgressSubmissionForm
        context_name = 'progress_form'
    
        def form_valid(self, form):
    
            old_phase = form.instance.phase.name
            response = super().form_valid(form)
            new_phase = form.instance.phase.name
    
            Activity.actions.create(
    
                user=self.request.user,
                submission=self.kwargs['submission'],
                message=f'Progressed from {old_phase} to {new_phase}'
            )
            return response
    
    @method_decorator(staff_required, name='dispatch')
    
    class UpdateLeadView(DelegatedViewMixin, UpdateView):
        model = ApplicationSubmission
        form_class = UpdateSubmissionLeadForm
        context_name = 'lead_form'
    
        def form_valid(self, form):
    
            # Fetch the old lead from the database
            old_lead = self.get_object().lead
    
            response = super().form_valid(form)
            new_lead = form.instance.lead
            Activity.actions.create(
                user=self.request.user,
                submission=self.kwargs['submission'],
                message=f'Lead changed from {old_lead} to {new_lead}'
            )
            return response
    
    
    
    class AdminSubmissionDetailView(ActivityContextMixin, DelegateableView):
    
        template_name_suffix = '_admin_detail'
    
        model = ApplicationSubmission
    
        form_views = {
            'progress': ProgressSubmissionView,
            'comment': CommentFormView,
    
            'update': UpdateLeadView,
    
        def get_context_data(self, **kwargs):
    
            other_submissions = self.model.objects.filter(user=self.object.user).current().exclude(id=self.object.id)
            if self.object.next:
                other_submissions = other_submissions.exclude(id=self.object.next.id)
    
    
            return super().get_context_data(
    
                other_submissions=other_submissions,
    
                **kwargs,
    
    class ApplicantSubmissionDetailView(ActivityContextMixin, DelegateableView):
    
        model = ApplicationSubmission
    
        form_views = {
            'comment': CommentFormView,
        }
    
    
        def dispatch(self, request, *args, **kwargs):
            if self.get_object().user != request.user:
                raise PermissionDenied
            return super().dispatch(request, *args, **kwargs)
    
    
    class SubmissionDetailView(ViewDispatcher):
        admin_view = AdminSubmissionDetailView
        applicant_view = ApplicantSubmissionDetailView
    
    
    
    @method_decorator(login_required, name='dispatch')
    
    class SubmissionEditView(UpdateView):
    
        """
        Converts the data held on the submission into an editable format and knows how to save
        that back to the object. Shortcuts the normal update view save approach
        """
    
        model = ApplicationSubmission
    
    
        def dispatch(self, request, *args, **kwargs):
            if request.user != self.get_object().user:
                raise PermissionDenied
    
            if not self.get_object().phase.has_perm(request.user, 'edit'):
                raise PermissionDenied
    
            return super().dispatch(request, *args, **kwargs)
    
    
        def get_form_kwargs(self):
            kwargs = super().get_form_kwargs()
            instance = kwargs.pop('instance')
            form_data = instance.form_data
    
            for field in self.object.form_fields:
                if isinstance(field.block, MustIncludeFieldBlock):
    
                    # convert certain data to the correct field id
    
                    try:
                        response = form_data[field.block.name]
                    except KeyError:
                        pass
                    else:
                        form_data[field.id] = response
    
            kwargs['initial'] = form_data
            return kwargs
    
        def get_form_class(self):
            return self.object.get_form_class()
    
        def form_valid(self, form):
            self.object.form_data = form.cleaned_data
            self.object.save()
            return HttpResponseRedirect(self.get_success_url())
    
    
    
    workflows = [SingleStage, DoubleStage]
    
    # Workflow Demo Views
    
    
    class BasicSubmissionForm(forms.Form):
        who_are_you = forms.CharField()
    
    
    
    def demo_workflow(request, wf_id):
    
        logs = request.session.get('logs', list())
        submission = request.session.get('submission', dict())
    
    
    Todd Dembrey's avatar
    Todd Dembrey committed
        workflow_class = workflows[wf - 1]
    
        workflow = workflow_class()
        forms = [BasicSubmissionForm] * wf
    
        current_phase = request.POST.get('current')
    
        current = workflow.current(current_phase)
    
    
        if request.POST:
    
            if current.stage.name not in submission:
    
                form = forms[workflow.stages.index(current.stage)]
                submitted_form = form(request.POST)
    
                if submitted_form.is_valid():
    
                    submission[current.stage.name] = submitted_form.cleaned_data
    
                    phase = current
                    logs.append(
                        f'{phase.stage}: Form was submitted'
                    )
                    form = None
                else:
                    form = submitted_form
            else:
                phase = workflow.process(current_phase, request.POST['action'])
                logs.append(
                    f'{current.stage}: {current.name} was updated to {phase.stage}: {phase.name}'
                )
    
            phase = current
    
            logs.clear()
    
            submission.clear()
    
        if phase.stage.name not in submission:
    
            form = forms[workflow.stages.index(phase.stage)]
    
        else:
            form = None
    
        request.session['logs'] = logs
        request.session['submission'] = submission
    
    
        context = {
            'workflow': workflow,
            'phase': phase,
    
            'logs': logs,
    
            'data': submission,
            'form': form,
    
    Todd Dembrey's avatar
    Todd Dembrey committed
        return TemplateResponse(request, 'funds/demo_workflow.html', context)