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)
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())
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)
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
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
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
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)
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
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())
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)
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, )
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)
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
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
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())
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
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
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())
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
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)
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)
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})