Skip to content

Report

hypha.apply.projects.views.report

ReportingMixin

dispatch

dispatch(*args, **kwargs)
Source code in hypha/apply/projects/views/report.py
def dispatch(self, *args, **kwargs):
    project = self.get_object()
    if project.is_in_progress:
        if not hasattr(project, "report_config"):
            ReportConfig.objects.create(project=project)

    return super().dispatch(*args, **kwargs)

ReportAccessMixin

Bases: UserPassesTestMixin

model class-attribute instance-attribute

model = Report

test_func

test_func()
Source code in hypha/apply/projects/views/report.py
def test_func(self):
    if self.request.user.is_apply_staff:
        return True

    if self.request.user.is_finance:
        return True

    if self.request.user == self.get_object().project.user:
        return True

    return False

ReportDetailView

Bases: DetailView

model class-attribute instance-attribute

model = Report

dispatch

dispatch(*args, **kwargs)
Source code in hypha/apply/projects/views/report.py
def dispatch(self, *args, **kwargs):
    report = self.get_object()
    permission, _ = has_permission(
        "report_view", self.request.user, object=report, raise_exception=True
    )
    return super().dispatch(*args, **kwargs)

ReportUpdateView

Bases: BaseStreamForm, UpdateView

submission_form_class class-attribute instance-attribute

submission_form_class = PageStreamBaseForm

wagtail_reference_index_ignore class-attribute instance-attribute

wagtail_reference_index_ignore = True

model class-attribute instance-attribute

model = Report

object class-attribute instance-attribute

object = None

form_class class-attribute instance-attribute

form_class = None

form_fields class-attribute instance-attribute

form_fields = None

from_db classmethod

from_db(db, field_names, values)
Source code in hypha/apply/stream_forms/models.py
@classmethod
def from_db(cls, db, field_names, values):
    instance = super().from_db(db, field_names, values)
    if "form_data" in field_names:
        instance.form_data = cls.deserialize_form_data(
            instance, instance.form_data, instance.form_fields
        )
    return instance

deserialize_form_data classmethod

deserialize_form_data(instance, form_data, form_fields)
Source code in hypha/apply/stream_forms/models.py
@classmethod
def deserialize_form_data(cls, instance, form_data, form_fields):
    data = form_data.copy()
    # PERFORMANCE NOTE:
    # Do not attempt to iterate over form_fields - that will fully instantiate the form_fields
    # including any sub queries that they do
    for _i, field_data in enumerate(form_fields.raw_data):
        block = form_fields.stream_block.child_blocks[field_data["type"]]
        field_id = field_data.get("id")
        try:
            value = data[field_id]
        except KeyError:
            pass
        else:
            data[field_id] = block.decode(value)
    return data

get_defined_fields

get_defined_fields()
Source code in hypha/apply/stream_forms/models.py
def get_defined_fields(self):
    return self.form_fields

get_form_fields

get_form_fields(draft=False, form_data=None, user=None)
Source code in hypha/apply/stream_forms/models.py
def get_form_fields(self, draft=False, form_data=None, user=None):
    if form_data is None:
        form_data = {}

    form_fields = OrderedDict()
    field_blocks = self.get_defined_fields()
    group_counter = 1
    is_in_group = False

    # If true option 1 is selected
    grouped_fields_visible = False
    for struct_child in field_blocks:
        block = struct_child.block
        struct_value = struct_child.value
        if isinstance(block, FormFieldBlock):
            field_from_block = block.get_field(struct_value)
            disabled_help_text = _(
                "You are logged in so this information is fetched from your user account."
            )
            if isinstance(block, FullNameBlock) and user and user.is_authenticated:
                if user.full_name:
                    field_from_block.disabled = True
                    field_from_block.initial = user.full_name
                    field_from_block.help_text = disabled_help_text
                else:
                    field_from_block.help_text = _(
                        "You are logged in but your user account does not have a "
                        "full name. We'll update your user account with the name you provide here."
                    )
            if isinstance(block, EmailBlock) and user and user.is_authenticated:
                field_from_block.disabled = True
                field_from_block.initial = user.email
                field_from_block.help_text = disabled_help_text
            if draft and not issubclass(
                block.__class__, ApplicationMustIncludeFieldBlock
            ):
                field_from_block.required = False
            field_from_block.help_link = struct_value.get("help_link")
            field_from_block.group_number = group_counter if is_in_group else 1
            if isinstance(block, GroupToggleBlock) and not is_in_group:
                field_from_block.group_number = 1
                field_from_block.grouper_for = group_counter + 1
                group_counter += 1
                is_in_group = True
                grouped_fields_visible = (
                    form_data.get(struct_child.id) == field_from_block.choices[0][0]
                )
            if isinstance(block, TextFieldBlock):
                field_from_block.word_limit = struct_value.get("word_limit")
            if isinstance(block, MultiInputCharFieldBlock):
                number_of_inputs = struct_value.get("number_of_inputs")
                for index in range(number_of_inputs):
                    form_fields[struct_child.id + "_" + str(index)] = (
                        field_from_block
                    )
                    field_from_block.multi_input_id = struct_child.id
                    field_from_block.add_button_text = struct_value.get(
                        "add_button_text"
                    )
                    if (
                        index == number_of_inputs - 1
                    ):  # Add button after last input field
                        field_from_block.multi_input_add_button = True
                        # Index for field until which fields will be visible to applicant.
                        # Initially only the first field with id UUID_0 will be visible.
                        field_from_block.visibility_index = 0
                        field_from_block.max_index = index
                    if index != 0:
                        field_from_block.multi_input_field = True
                        field_from_block.required = False
                        field_from_block.initial = None
                    field_from_block = copy.copy(field_from_block)
            else:
                if is_in_group and not isinstance(block, GroupToggleBlock):
                    field_from_block.required_when_visible = (
                        field_from_block.required
                    )
                    field_from_block.required = (
                        field_from_block.required & grouped_fields_visible
                    )
                    field_from_block.visible = grouped_fields_visible
                form_fields[struct_child.id] = field_from_block
        elif isinstance(block, GroupToggleEndBlock):
            # Group toggle end block is used only to group fields and not used in actual form.
            # Todo: Use streamblock to create nested form field blocks, a more elegant method to group form fields.
            is_in_group = False
        else:
            field_wrapper = BlockFieldWrapper(struct_child)
            field_wrapper.group_number = group_counter if is_in_group else 1
            form_fields[struct_child.id] = field_wrapper

    return form_fields

get_form_class

get_form_class(draft=False, form_data=None, user=None)

Expects self.form_fields to have already been set.

Source code in hypha/apply/projects/views/report.py
def get_form_class(self, draft=False, form_data=None, user=None):
    """
    Expects self.form_fields to have already been set.
    """
    # This is where the magic happens.
    fields = self.get_form_fields(draft, form_data, user)
    the_class = type(
        "WagtailStreamForm",
        (ReportEditForm,),
        fields,
    )
    return the_class

dispatch

dispatch(request, *args, **kwargs)
Source code in hypha/apply/projects/views/report.py
def dispatch(self, request, *args, **kwargs):
    report = self.get_object()
    permission, _ = has_permission(
        "report_update", self.request.user, object=report, raise_exception=True
    )
    self.object = report
    # super().dispatch calls get_context_data() which calls the rest to get the form fully ready for use.
    return super().dispatch(request, *args, **kwargs)

get_context_data

get_context_data(*args, **kwargs)

Django note: super().dispatch calls get_context_data.

Source code in hypha/apply/projects/views/report.py
def get_context_data(self, *args, **kwargs):
    """
    Django note: super().dispatch calls get_context_data.
    """
    # Is this where we need to get the associated form fields? Not in the form itself but up here? Yes. But in a
    # roundabout way: get_form (here) gets fields and calls get_form_class (here) which calls get_form_fields
    # (super) which sets up the fields in the returned form.
    form = self.get_form()
    context_data = {
        "form": form,
        "object": self.object,
        "report_form": True
        if self.object.project.submission.page.specific.report_forms.first()
        else False,
        **kwargs,
    }
    return context_data

get_form

get_form(form_class=None)
Source code in hypha/apply/projects/views/report.py
def get_form(self, form_class=None):
    if self.object.current is None or self.object.form_fields is None:
        # Here is where we get the form_fields, the ProjectReportForm associated with the Fund:
        report_form = (
            self.object.project.submission.page.specific.report_forms.first()
        )
        if report_form:
            self.form_fields = report_form.form.form_fields
        else:
            self.form_fields = {}
    else:
        self.form_fields = self.object.form_fields

    if form_class is None:
        form_class = self.get_form_class()
    report_instance = form_class(**self.get_form_kwargs())
    return report_instance

get_initial

get_initial()
Source code in hypha/apply/projects/views/report.py
def get_initial(self):
    initial = {}
    if self.object.draft:
        current = self.object.draft
    else:
        current = self.object.current

    # current here is a ReportVersion which should already have the data associated.
    if current:
        # The following allows existing data to populate the form. This code was inspired by (aka copied from)
        # ProjectFormEditView.get_paf_form_kwargs().
        initial = current.raw_data
        # Is the following needed to see the file in a friendly URL? Does not appear so. But needed to not blow up.
        for field_id in current.file_field_ids:
            initial.pop(field_id + "-uploads", False)
            initial[field_id] = get_placeholder_file(current.raw_data.get(field_id))

    return initial

get_form_kwargs

get_form_kwargs()
Source code in hypha/apply/projects/views/report.py
def get_form_kwargs(self):
    form_kwargs = {
        "user": self.request.user,
        **super().get_form_kwargs(),
    }
    return form_kwargs

post

post(request, *args, **kwargs)
Source code in hypha/apply/projects/views/report.py
def post(self, request, *args, **kwargs):
    form = self.get_form()
    if form.is_valid():
        form.save(form_fields=self.form_fields)
        form.delete_temporary_files()

        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,
            )
        response = HttpResponseRedirect(self.get_success_url())
    else:
        response = self.form_invalid(form)
    return response

get_success_url

get_success_url()
Source code in hypha/apply/projects/views/report.py
def get_success_url(self):
    success_url = self.object.project.get_absolute_url()
    return success_url

ReportPrivateMedia

Bases: ReportAccessMixin, PrivateMediaView

storage class-attribute instance-attribute

storage = PrivateStorage()

model class-attribute instance-attribute

model = Report

get

get(*args, **kwargs)
Source code in hypha/apply/utils/storage.py
def get(self, *args, **kwargs):
    file_to_serve = self.get_media(*args, **kwargs)
    return FileResponse(file_to_serve)

test_func

test_func()
Source code in hypha/apply/projects/views/report.py
def test_func(self):
    if self.request.user.is_apply_staff:
        return True

    if self.request.user.is_finance:
        return True

    if self.request.user == self.get_object().project.user:
        return True

    return False

dispatch

dispatch(*args, **kwargs)
Source code in hypha/apply/projects/views/report.py
def dispatch(self, *args, **kwargs):
    report_pk = self.kwargs["pk"]
    self.report = get_object_or_404(Report, pk=report_pk)
    file_pk = kwargs.get("file_pk")
    self.document = get_object_or_404(
        ReportPrivateFiles.objects, report__report=self.report, pk=file_pk
    )

    if not hasattr(self.document.report, "live_for_report"):
        # this is not a document in the live report
        # send the user to the report page to see latest version
        return redirect(self.report.get_absolute_url())

    return super().dispatch(*args, **kwargs)

get_media

get_media(*args, **kwargs)
Source code in hypha/apply/projects/views/report.py
def get_media(self, *args, **kwargs):
    return self.document.document

ReportSkipView

Bases: SingleObjectMixin, View

model class-attribute instance-attribute

model = Report

post

post(*args, **kwargs)
Source code in hypha/apply/projects/views/report.py
def post(self, *args, **kwargs):
    report = self.get_object()
    unsubmitted = not report.current
    not_current = report.project.report_config.current_due_report() != report
    if unsubmitted and not_current:
        report.skipped = not report.skipped
        report.save()
        messenger(
            MESSAGES.SKIPPED_REPORT,
            request=self.request,
            user=self.request.user,
            source=report.project,
            related=report,
        )
    return HttpResponseClientRefresh()

ReportFrequencyUpdate

Bases: View

form_class class-attribute instance-attribute

form_class = ReportFrequencyForm

model class-attribute instance-attribute

model = ReportConfig

template_name class-attribute instance-attribute

template_name = 'application_projects/modals/report_frequency_config.html'

dispatch

dispatch(request, *args, **kwargs)
Source code in hypha/apply/projects/views/report.py
def dispatch(self, request, *args, **kwargs):
    self.project = get_object_or_404(Project, id=kwargs.get("pk"))
    self.object = self.project.report_config
    return super().dispatch(request, *args, **kwargs)

get_due_report_data

get_due_report_data()
Source code in hypha/apply/projects/views/report.py
def get_due_report_data(self):
    report_data = {}
    if not self.object.disable_reporting:
        project_end_date = self.project.end_date
        if self.object.current_due_report():
            start_date = self.object.current_due_report().start_date
        else:
            start_date = self.object.last_report().start_date
        report_data = {"startDate": start_date, "projectEndDate": project_end_date}
    return report_data

get

get(*args, **kwargs)
Source code in hypha/apply/projects/views/report.py
def get(self, *args, **kwargs):
    form = self.get_form()
    report_data = self.get_due_report_data()

    return render(
        self.request,
        self.template_name,
        context={
            "form": form,
            "object": self.object,
            "report_data": report_data,
        },
    )

get_form_kwargs

get_form_kwargs(**kwargs)
Source code in hypha/apply/projects/views/report.py
def get_form_kwargs(self, **kwargs):
    kwargs = kwargs or {}
    kwargs["instance"] = self.object
    if not self.object.disable_reporting:
        # Current due report can be none for ONE_TIME(does not repeat),
        # In case of ONE_TIME, either reporting is already completed(last_report exists)
        # or there should be a current_due_report.
        if self.object.current_due_report():
            kwargs["initial"] = {
                "start": self.object.current_due_report().end_date,
            }
        else:
            kwargs["initial"] = {
                "start": self.object.last_report().end_date,
            }
    else:
        kwargs["initial"] = {
            "start": self.project.start_date,
        }
    return kwargs

get_form

get_form(*args, **kwargs)
Source code in hypha/apply/projects/views/report.py
def get_form(self, *args, **kwargs):
    if self.project.is_in_progress:
        return self.form_class(*args, **(self.get_form_kwargs(**kwargs)))
    return None

post

post(*args, **kwargs)
Source code in hypha/apply/projects/views/report.py
def post(self, *args, **kwargs):
    form = self.get_form(self.request.POST)
    if form.is_valid():
        if "disable-reporting" in self.request.POST:
            form.instance.disable_reporting = True
            form.instance.schedule_start = None
            form.save()
            messenger(
                MESSAGES.DISABLED_REPORTING,
                request=self.request,
                user=self.request.user,
                source=self.project,
            )
        else:
            form.instance.disable_reporting = False
            form.instance.schedule_start = form.cleaned_data["start"]
            form.save()
            messenger(
                MESSAGES.REPORT_FREQUENCY_CHANGED,
                request=self.request,
                user=self.request.user,
                source=self.project,
                related=self.object,
            )
        return HttpResponseClientRefresh()

    report_data = self.get_due_report_data()
    return render(
        self.request,
        self.template_name,
        context={
            "form": form,
            "object": self.object,
            "report_data": report_data,
        },
    )

ReportListView

Bases: SingleTableMixin, FilterView

queryset class-attribute instance-attribute

queryset = for_table()

filterset_class class-attribute instance-attribute

filterset_class = ReportListFilter

table_class class-attribute instance-attribute

table_class = ReportListTable

template_name class-attribute instance-attribute

template_name = 'application_projects/report_list.html'

ReportingView

Bases: SingleTableMixin, FilterView

queryset class-attribute instance-attribute

queryset = for_reporting_table()

filterset_class class-attribute instance-attribute

filterset_class = ReportingFilter

table_class class-attribute instance-attribute

table_class = ReportingTable

template_name class-attribute instance-attribute

template_name = 'application_projects/reporting.html'