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.current.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.current.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()
        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

form_valid

form_valid(form)
Source code in hypha/apply/projects/views/report.py
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,
        )

    # Required for django-file-form: delete temporary files for the new files
    # that are uploaded.
    form.delete_temporary_files()
    return response

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 redirect(report.project.get_absolute_url())

ReportFrequencyUpdate

Bases: DelegatedViewMixin, UpdateView

form_class class-attribute instance-attribute

form_class = ReportFrequencyForm

context_name class-attribute instance-attribute

context_name = 'update_frequency_form'

model class-attribute instance-attribute

model = ReportConfig

setup

setup(request, *args, **kwargs)

Initialize attributes shared by all view methods.

Source code in hypha/apply/utils/views.py
def setup(self, request, *args, **kwargs):
    """Initialize attributes shared by all view methods."""
    self.request = request
    self.args = args
    self.kwargs = kwargs

get_template_names

get_template_names()
Source code in hypha/apply/utils/views.py
def get_template_names(self):
    return self.kwargs["template_names"]

get_form_name

get_form_name()
Source code in hypha/apply/utils/views.py
def get_form_name(self):
    return self.context_name

get_parent_kwargs

get_parent_kwargs()
Source code in hypha/apply/utils/views.py
def get_parent_kwargs(self):
    try:
        return self.parent.get_form_kwargs()
    except AttributeError:
        return self.kwargs["parent"].get_form_kwargs()

get_parent_object

get_parent_object()
Source code in hypha/apply/utils/views.py
def get_parent_object(self):
    return self.get_parent_kwargs()["instance"]

get_context_data

get_context_data(**kwargs)
Source code in hypha/apply/utils/views.py
def get_context_data(self, **kwargs):
    # Use the previous context but override the validated form
    form = kwargs.pop("form")
    kwargs.update(self.kwargs["context"])
    kwargs.update(**{self.context_name: form})
    return super().get_context_data(**kwargs)

is_model_form classmethod

is_model_form()
Source code in hypha/apply/utils/views.py
@classmethod
def is_model_form(cls):
    return issubclass(cls.form_class, ModelForm)

contribute_form

contribute_form(parent)
Source code in hypha/apply/utils/views.py
def contribute_form(self, parent):
    self.parent = parent

    # We do not want to bind any forms generated this way
    # pretend we are doing a get request to avoid passing data to forms
    old_method = None
    if self.request.method in ("POST", "PUT"):
        old_method = self.request.method
        self.request.method = "GET"

    form = self.get_form()

    if old_method:
        self.request.method = old_method
    return self.context_name, form

get_success_url

get_success_url()
Source code in hypha/apply/utils/views.py
def get_success_url(self):
    query = self.request.GET.urlencode()
    if query:
        query = "?" + query
    return self.request.path + query

get_form_kwargs

get_form_kwargs()
Source code in hypha/apply/projects/views/report.py
def get_form_kwargs(self):
    kwargs = super().get_form_kwargs()
    kwargs.pop("user")
    project = kwargs["instance"]
    instance = project.report_config
    kwargs["instance"] = instance
    if not instance.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 instance.current_due_report():
            kwargs["initial"] = {
                "start": instance.current_due_report().end_date,
            }
        else:
            kwargs["initial"] = {
                "start": instance.last_report().end_date,
            }
    else:
        kwargs["initial"] = {
            "start": project.start_date,
        }
    return kwargs

get_object

get_object()
Source code in hypha/apply/projects/views/report.py
def get_object(self):
    project = self.get_parent_object()
    return project.report_config

get_form

get_form()
Source code in hypha/apply/projects/views/report.py
def get_form(self):
    if self.get_parent_object().is_in_progress:
        return super().get_form()
    return None

form_valid

form_valid(form)
Source code in hypha/apply/projects/views/report.py
def form_valid(self, form):
    config = form.instance
    # 'form-submitted-' is set as form_prefix in DelegateBase view
    if "disable-reporting" in self.request.POST.get(
        f"form-submitted-{self.context_name}"
    ):
        form.instance.disable_reporting = True
        form.instance.schedule_start = None
        response = super().form_valid(form)
        messenger(
            MESSAGES.DISABLED_REPORTING,
            request=self.request,
            user=self.request.user,
            source=config.project,
        )
    else:
        form.instance.disable_reporting = False
        form.instance.schedule_start = form.cleaned_data["start"]
        response = super().form_valid(form)
        messenger(
            MESSAGES.REPORT_FREQUENCY_CHANGED,
            request=self.request,
            user=self.request.user,
            source=config.project,
            related=config,
        )

    return response

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'