Example #1
0
 def render_landing_page(self,
                         request,
                         form_submission=None,
                         *args,
                         **kwargs):
     # We only reach this page after creation of a new submission
     # Hook in to notify about new applications
     messenger(
         MESSAGES.NEW_SUBMISSION,
         request=request,
         user=form_submission.user,
         source=form_submission,
     )
     return super().render_landing_page(request,
                                        form_submission=None,
                                        *args,
                                        **kwargs)
Example #2
0
    def form_valid(self, form):
        self.object.new_data(form.cleaned_data)

        if 'save' in self.request.POST:
            self.object.create_revision(draft=True, by=self.request.user)
            messages.success(self.request, _('Submission saved successfully'))
            return self.form_invalid(form)

        revision = self.object.create_revision(by=self.request.user)
        submitting_proposal = self.object.phase.name in STAGE_CHANGE_ACTIONS

        if submitting_proposal:
            messenger(
                MESSAGES.PROPOSAL_SUBMITTED,
                request=self.request,
                user=self.request.user,
                source=self.object,
            )
        elif revision and not self.object.status == DRAFT_STATE:
            messenger(
                MESSAGES.APPLICANT_EDIT,
                request=self.request,
                user=self.request.user,
                source=self.object,
                related=revision,
            )

        action = set(self.request.POST.keys()) & set(self.transitions.keys())
        try:
            transition = self.transitions[action.pop()]
        except KeyError:
            pass
        else:
            self.object.perform_transition(
                transition.target,
                self.request.user,
                request=self.request,
                notify=not (revision or submitting_proposal)
                or self.object.status
                == DRAFT_STATE,  # Use the other notification
            )

        # Required for django-file-form: delete temporary files for the new files
        # uploaded while edit.
        form.delete_temporary_files()
        return HttpResponseRedirect(self.get_success_url())
Example #3
0
    def update(self, request, *args, **kwargs):
        """
        Update a determination submitted on a submission.
        """
        determination = self.get_object()
        ser = self.get_serializer(data=request.data)
        ser.is_valid(raise_exception=True)
        ser.update(determination, ser.validated_data)

        messenger(
            MESSAGES.DETERMINATION_OUTCOME,
            request=self.request,
            user=determination.author,
            source=determination.submission,
            related=determination,
        )
        ser = self.get_serializer(self.get_determination_data(determination))
        return Response(ser.data)
Example #4
0
    def form_valid(self, form):
        form.instance.project = self.project
        form.instance.by = self.request.user

        response = super().form_valid(form)

        messenger(
            MESSAGES.REQUEST_PAYMENT,
            request=self.request,
            user=self.request.user,
            source=self.project,
            related=self.object,
        )

        # Required for django-file-form: delete temporary files for the new files
        # that are uploaded.
        form.delete_temporary_files()
        return response
Example #5
0
    def form_valid(self, form):
        submissions = self.get_submissions()
        response = super().form_valid(form)
        determinations = {
            determination.submission.id: determination
            for determination in form.instances
        }

        messenger(
            MESSAGES.BATCH_DETERMINATION_OUTCOME,
            request=self.request,
            user=self.request.user,
            sources=submissions.filter(id__in=list(determinations)),
            related=determinations,
        )

        for submission in submissions:
            try:
                determination = determinations[submission.id]
            except KeyError:
                messages.warning(
                    self.request,
                    'Unable to determine submission "{title}" as already determined'
                    .format(title=submission.title),
                )
            else:
                transition = transition_from_outcome(
                    form.cleaned_data.get('outcome'), submission)

                if determination.outcome == NEEDS_MORE_INFO:
                    # We keep a record of the message sent to the user in the comment
                    Activity.comments.create(
                        message=determination.stripped_message,
                        timestamp=timezone.now(),
                        user=self.request.user,
                        source=submission,
                        related_object=determination,
                    )

                submission.perform_transition(transition,
                                              self.request.user,
                                              request=self.request,
                                              notify=False)
        return response
Example #6
0
    def form_valid(self, form):
        project = self.kwargs['object']

        form.instance.project = project

        if self.request.user == project.user:
            form.instance.is_signed = True

        response = super().form_valid(form)

        messenger(
            MESSAGES.UPLOAD_CONTRACT,
            request=self.request,
            user=self.request.user,
            source=project,
            related=form.instance,
        )

        return response
Example #7
0
    def form_valid(self, form):
        submissions = form.cleaned_data['submissions']
        form.save()
        reviewers = [[role, form.cleaned_data[field_name]]
                     for field_name, role in form.role_fields.items()]

        messenger(
            MESSAGES.BATCH_REVIEWERS_UPDATED,
            request=self.request,
            user=self.request.user,
            sources=submissions,
            added=reviewers,
        )

        for submission in submissions:
            # Update submission status if needed.
            self.set_status_after_reviewers_assigned(submission)

        return super().form_valid(form)
Example #8
0
    def form_valid(self, form):
        old_reviewers = set(
            copy(reviewer) for reviewer in form.instance.assigned.all())
        response = super().form_valid(form)

        new_reviewers = set(form.instance.assigned.all())
        added = new_reviewers - old_reviewers
        removed = old_reviewers - new_reviewers

        messenger(
            MESSAGES.REVIEWERS_UPDATED,
            request=self.request,
            user=self.request.user,
            source=self.kwargs['object'],
            added=added,
            removed=removed,
        )

        # Check if two internal reviewers have been selected.
        internal_reviewers_count = form.instance.assigned.with_roles().count()
        if internal_reviewers_count > 1:
            # Automatic workflow actions.
            action = None
            if self.object.status == INITIAL_STATE:
                # Automatically transition the application to "Internal review".
                action = self.object.workflow.stepped_phases[1][0].name
            elif self.object.status == 'proposal_discussion':
                # Automatically transition the proposal to "Internal review".
                action = 'proposal_internal_review'

            # If action is set run perform_transition().
            if action:
                try:
                    self.object.perform_transition(
                        action,
                        self.request.user,
                        request=self.request,
                        notify=False,
                    )
                except (PermissionDenied, KeyError):
                    pass

        return response
Example #9
0
    def form_valid(self, form):
        self.object.new_data(form.cleaned_data)

        if 'save' in self.request.POST:
            self.object.create_revision(draft=True, by=self.request.user)
            return self.form_invalid(form)

        if 'submit' in self.request.POST:
            revision = self.object.create_revision(by=self.request.user)
            if revision:
                messenger(
                    MESSAGES.EDIT,
                    request=self.request,
                    user=self.request.user,
                    source=self.object,
                    related=revision,
                )

        return HttpResponseRedirect(self.get_success_url())
Example #10
0
    def update(self, request, *args, **kwargs):
        """
        Update a review submitted on a submission.
        """
        review = self.get_object()
        ser = self.get_serializer(data=request.data)
        ser.is_valid(raise_exception=True)
        ser.update(review, ser.validated_data)

        messenger(
            MESSAGES.EDIT_REVIEW,
            user=self.request.user,
            request=self.request,
            source=review.submission,
            related=review,
        )
        # Automatic workflow actions.
        review_workflow_actions(self.request, review.submission)
        ser = self.get_serializer(self.get_review_data(review))
        return Response(ser.data)
Example #11
0
def log_status_update(sender, **kwargs):
    instance = kwargs['instance']
    old_phase = instance.workflow[kwargs['source']]

    by = kwargs['method_kwargs']['by']
    request = kwargs['method_kwargs']['request']
    notify = kwargs['method_kwargs'].get('notify', True)

    if request and notify:
        messenger(
            MESSAGES.TRANSITION,
            user=by,
            request=request,
            source=instance,
            related=old_phase,
        )

        if instance.status in review_statuses:
            messenger(
                MESSAGES.READY_FOR_REVIEW,
                user=by,
                request=request,
                source=instance,
            )

    if instance.status in STAGE_CHANGE_ACTIONS:
        messenger(
            MESSAGES.INVITED_TO_PROPOSAL,
            request=request,
            user=by,
            source=instance,
        )
Example #12
0
    def create(self, request, *args, **kwargs):
        """
        Create a review on a submission.

        Accept a post data in form of `{field_id: value}`.
        `field_id` is same id which you get from the `/fields` api.
        `value` should be submitted with html tags, so that response can
        be displayed with correct formatting, e.g. in case of rich text field,
        we need to show the data with same formatting user has submitted.

        Accepts optional parameter `is_draft` when a review is to be saved as draft.

        Raise ValidationError if a review is already submitted by the user.
        """
        submission = self.get_submission_object()
        ser = self.get_serializer(data=request.data)
        ser.is_valid(raise_exception=True)
        instance, create = ser.Meta.model.objects.get_or_create(
            submission=submission, author=self.get_reviewer())
        if not create and not instance.is_draft:
            raise ValidationError({
                'detail':
                'You have already posted a review for this submission'
            })
        instance.form_fields = self.get_defined_fields()
        instance.save()
        ser.update(instance, ser.validated_data)
        if not instance.is_draft:
            messenger(
                MESSAGES.NEW_REVIEW,
                request=self.request,
                user=self.request.user,
                source=submission,
                related=instance,
            )
            # Automatic workflow actions.
            review_workflow_actions(self.request, submission)
        ser = self.get_serializer(self.get_review_data(instance))
        return Response(ser.data, status=status.HTTP_201_CREATED)
Example #13
0
    def form_valid(self, form):
        response = super().form_valid(form)

        should_notify = True
        if self.object.draft:
            # It was a draft submission
            should_notify = False
        else:
            if self.object.submitted != self.object.current.submitted:
                # It was a staff edit - post submission
                should_notify = False

        if should_notify:
            messenger(
                MESSAGES.SUBMIT_REPORT,
                request=self.request,
                user=self.request.user,
                source=self.object.project,
                related=self.object,
            )

        return response
Example #14
0
    def form_valid(self, form):
        old_reviewers = set(
            copy(reviewer) for reviewer in form.instance.assigned.all())
        response = super().form_valid(form)

        new_reviewers = set(form.instance.assigned.all())
        added = new_reviewers - old_reviewers
        removed = old_reviewers - new_reviewers

        messenger(
            MESSAGES.REVIEWERS_UPDATED,
            request=self.request,
            user=self.request.user,
            source=self.kwargs['object'],
            added=added,
            removed=removed,
        )

        # Update submission status if needed.
        self.set_status_after_reviewers_assigned(form.instance)

        return response
Example #15
0
    def form_valid(self, form):
        self.object.new_data(form.cleaned_data)

        if 'save' in self.request.POST:
            self.object.create_revision(draft=True, by=self.request.user)
            return self.form_invalid(form)

        if 'submit' in self.request.POST:
            revision = self.object.create_revision(by=self.request.user)
            if revision:
                messenger(
                    MESSAGES.EDIT,
                    request=self.request,
                    user=self.request.user,
                    source=self.object,
                    related=revision,
                )

        # Required for django-file-form: delete temporary files for the new files
        # uploaded while edit.
        form.delete_temporary_files()
        return HttpResponseRedirect(self.get_success_url())
Example #16
0
    def form_valid(self, form):
        form.instance.form_fields = self.get_defined_fields()
        form.instance.author, _ = AssignedReviewers.objects.get_or_create_for_user(
            submission=self.submission,
            reviewer=self.request.user,
        )

        response = super().form_valid(form)

        if not self.object.is_draft:
            messenger(
                MESSAGES.NEW_REVIEW,
                request=self.request,
                user=self.request.user,
                source=self.submission,
                related=self.object,
            )

            # Automatic workflow actions.
            review_workflow_actions(self.request, self.submission)

        return response
Example #17
0
    def form_valid(self, form):
        self.review = self.get_object()
        author, _ = AssignedReviewers.objects.get_or_create_for_user(
            submission=self.review.submission,
            reviewer=self.request.user,
        )
        form.instance.author = author
        form.instance.review = self.review
        response = super().form_valid(form)
        opinion = form.instance

        messenger(
            MESSAGES.REVIEW_OPINION,
            request=self.request,
            user=self.request.user,
            source=self.review.submission,
            related=opinion,
        )

        if opinion.opinion == DISAGREE:
            return HttpResponseRedirect(reverse_lazy('apply:submissions:reviews:form', args=(self.review.submission.pk,)))
        else:
            return response
Example #18
0
    def form_valid(self, form):
        if self.submission.is_determination_form_attached:
            form.instance.form_fields = self.get_defined_fields()

        super().form_valid(form)
        if self.object.is_draft:
            return HttpResponseRedirect(self.submission.get_absolute_url())

        with transaction.atomic():
            messenger(
                MESSAGES.DETERMINATION_OUTCOME,
                request=self.request,
                user=self.object.author,
                submission=self.object.submission,
                related=self.object,
            )
            proposal_form = form.cleaned_data.get('proposal_form')
            transition = transition_from_outcome(int(self.object.outcome),
                                                 self.submission)

            if self.object.outcome == NEEDS_MORE_INFO:
                # We keep a record of the message sent to the user in the comment
                Activity.comments.create(
                    message=self.object.stripped_message,
                    timestamp=timezone.now(),
                    user=self.request.user,
                    source=self.submission,
                    related_object=self.object,
                )
            self.submission.perform_transition(
                transition,
                self.request.user,
                request=self.request,
                notify=False,
                proposal_form=proposal_form,
            )

            if self.submission.accepted_for_funding and settings.PROJECTS_AUTO_CREATE:
                project = Project.create_from_submission(self.submission)
                if project:
                    messenger(
                        MESSAGES.CREATED_PROJECT,
                        request=self.request,
                        user=self.request.user,
                        source=project,
                        related=project.submission,
                    )

        messenger(
            MESSAGES.DETERMINATION_OUTCOME,
            request=self.request,
            user=self.object.author,
            source=self.object.submission,
            related=self.object,
        )

        return HttpResponseRedirect(self.submission.get_absolute_url())
Example #19
0
    def form_valid(self, form):
        response = super().form_valid(form)
        if form.cleaned_data:
            if self.object.status in [CHANGES_REQUESTED, RESUBMITTED]:
                self.object.status = RESUBMITTED
                self.object.save()

            if form.cleaned_data['message_for_pm']:
                invoice_status_change = _(
                    '<p>Invoice status updated to: {status}.</p>').format(
                        status=self.object.status_display)
                message_for_pm = f'<p>{form.cleaned_data["message_for_pm"]}</p>'
                message = invoice_status_change + message_for_pm

                Activity.objects.create(
                    user=self.request.user,
                    type=COMMENT,
                    source=self.object.project,
                    timestamp=timezone.now(),
                    message=message,
                    visibility=ALL,
                    related_object=self.object,
                )

        messenger(
            MESSAGES.UPDATE_INVOICE_STATUS,
            request=self.request,
            user=self.request.user,
            source=self.object.project,
            related=self.object,
        )

        # Required for django-file-form: delete temporary files for the new files
        # that are uploaded.
        form.delete_temporary_files()
        return response
Example #20
0
    def form_valid(self, form):
        submissions = form.cleaned_data['submissions']
        transitions = form.cleaned_data.get('action')

        try:
            redirect = BatchDeterminationCreateView.should_redirect(
                self.request, submissions, transitions)
        except ValueError as e:
            messages.warning(self.request, 'Could not determine: ' + str(e))
            return self.form_invalid(form)
        else:
            if redirect:
                return redirect

        failed = []
        phase_changes = {}
        for submission in submissions:
            valid_actions = {
                action
                for action, _ in submission.get_actions_for_user(
                    self.request.user)
            }
            old_phase = submission.phase
            try:
                transition = (valid_actions & set(transitions)).pop()
                submission.perform_transition(
                    transition,
                    self.request.user,
                    request=self.request,
                    notify=False,
                )
            except (PermissionDenied, KeyError):
                failed.append(submission)
            else:
                phase_changes[submission.id] = old_phase

        if failed:
            messages.warning(
                self.request,
                _('Failed to update: ') +
                ', '.join(str(submission) for submission in failed))

        succeeded_submissions = submissions.exclude(
            id__in=[submission.id for submission in failed])
        messenger(
            MESSAGES.BATCH_TRANSITION,
            user=self.request.user,
            request=self.request,
            sources=succeeded_submissions,
            related=phase_changes,
        )

        ready_for_review = [
            phase for phase in transitions if phase in review_statuses
        ]
        if ready_for_review:
            messenger(
                MESSAGES.BATCH_READY_FOR_REVIEW,
                user=self.request.user,
                request=self.request,
                sources=succeeded_submissions.filter(
                    status__in=ready_for_review),
            )

        return super().form_valid(form)
Example #21
0
    def create(self, request, *args, **kwargs):
        """
        Create a determination on a submission.

        Accept a post data in form of `{field_id: value}`.
        `field_id` is same id which you get from the `/fields` api.
        `value` should be submitted with html tags, so that response can
        be displayed with correct formatting, e.g. in case of rich text field,
        we need to show the data with same formatting user has submitted.

        Accepts optional parameter `is_draft` when a determination is to be saved as draft.

        Raise ValidationError if a determination is already submitted by the user.
        """
        submission = self.get_submission_object()
        ser = self.get_serializer(data=request.data)
        ser.is_valid(raise_exception=True)
        if has_final_determination(submission):
            return ValidationError({
                'detail':
                'A final determination has already been submitted.'
            })
        determination = self.get_draft_determination()
        if determination is None:
            determination = Determination.objects.create(submission=submission,
                                                         author=request.user)
        determination.form_fields = self.get_defined_fields()
        determination.save()
        ser.update(determination, ser.validated_data)
        if determination.is_draft:
            ser = self.get_serializer(
                self.get_determination_data(determination))
            return Response(ser.data, status=status.HTTP_201_CREATED)
        with transaction.atomic():
            messenger(
                MESSAGES.DETERMINATION_OUTCOME,
                request=self.request,
                user=determination.author,
                submission=submission,
                related=determination,
            )
            proposal_form = ser.validated_data.get('proposal_form')
            transition = transition_from_outcome(int(determination.outcome),
                                                 submission)

            if determination.outcome == NEEDS_MORE_INFO:
                # We keep a record of the message sent to the user in the comment
                Activity.comments.create(
                    message=determination.stripped_message,
                    timestamp=timezone.now(),
                    user=self.request.user,
                    source=submission,
                    related_object=determination,
                )
            submission.perform_transition(
                transition,
                self.request.user,
                request=self.request,
                notify=False,
                proposal_form=proposal_form,
            )

            if submission.accepted_for_funding and settings.PROJECTS_AUTO_CREATE:
                Project.create_from_submission(submission)

        messenger(
            MESSAGES.DETERMINATION_OUTCOME,
            request=self.request,
            user=determination.author,
            source=submission,
            related=determination,
        )
        ser = self.get_serializer(self.get_determination_data(determination))
        return Response(ser.data, status=status.HTTP_201_CREATED)
Example #22
0
    def done(self, form_list, **kwargs):
        vendor_project = self.get_project()
        cleaned_data = self.get_all_cleaned_data()
        vendor = vendor_project.vendor
        need_extra_info = cleaned_data['need_extra_info']
        bank_info = vendor.bank_info
        account_holder_name = cleaned_data['account_holder_name']
        account_routing_number = cleaned_data['account_routing_number']
        account_number = cleaned_data['account_number']
        account_currency = cleaned_data['account_currency']
        if not bank_info:
            bank_info = BankInformation.objects.create(
                account_holder_name=account_holder_name,
                account_number=account_number,
                account_routing_number=account_routing_number,
                account_currency=account_currency,
                need_extra_info=need_extra_info,
            )
        else:
            bank_info.account_holder_name = account_holder_name
            bank_info.account_number = account_number
            bank_info.account_currency = account_currency
            bank_info.need_extra_info = need_extra_info
        if need_extra_info:
            ib_account_routing_number = cleaned_data[
                'ib_account_routing_number']
            ib_account_number = cleaned_data['ib_account_number']
            ib_account_currency = cleaned_data['ib_account_currency']
            ib_branch_address = cleaned_data['ib_branch_address']
            iba_info = bank_info.iba_info
            if not iba_info:
                iba_info = BankInformation.objects.create(
                    account_routing_number=ib_account_routing_number,
                    account_number=ib_account_number,
                    account_currency=ib_account_currency,
                    branch_address=ib_branch_address)
            else:
                iba_info.branch_address = ib_branch_address
                iba_info.account_routing_number = ib_account_routing_number
                iba_info.account_number = ib_account_number
                iba_info.account_currency = ib_account_currency
            iba_info.save()
            bank_info.branch_address = cleaned_data['branch_address']
            bank_info.nid_type = cleaned_data['nid_type']
            bank_info.nid_number = cleaned_data['nid_number']
            bank_info.iba_info = iba_info
            vendor.other_info = cleaned_data['other_info']

        bank_info.save()

        vendor.bank_info = bank_info
        vendor.name = cleaned_data['name']
        vendor.contractor_name = cleaned_data['contractor_name']
        vendor.type = cleaned_data['type']
        vendor.required_to_pay_taxes = cleaned_data['required_to_pay_taxes']
        vendor.updated_at = timezone.now()
        vendor.user_has_updated_details = True
        vendor.save()

        not_deleted_original_filenames = [
            file['name'] for file in json.loads(
                cleaned_data['due_diligence_documents-uploads'])
        ]
        for f in vendor.due_diligence_documents.all():
            if f.document.name not in not_deleted_original_filenames:
                f.document.delete()
                f.delete()

        for f in cleaned_data["due_diligence_documents"]:
            if not isinstance(f, FieldFile):
                try:
                    DueDiligenceDocument.objects.create(vendor=vendor,
                                                        document=f)
                finally:
                    f.close()
        form = self.get_form('documents')
        form.delete_temporary_files()

        messenger(MESSAGES.UPDATED_VENDOR,
                  request=self.request,
                  user=vendor_project.lead,
                  source=vendor_project)

        return render(self.request, 'application_projects/vendor_success.html',
                      {'project': vendor_project})