diff --git a/hypha/apply/funds/files.py b/hypha/apply/funds/files.py
index 27b8fcba75be89f1a6302345c5736347eb69e052..0c4a263c32f94ac4b86a23f5b03ecd111efb7561 100644
--- a/hypha/apply/funds/files.py
+++ b/hypha/apply/funds/files.py
@@ -5,36 +5,57 @@ from django.urls import reverse
 from hypha.apply.stream_forms.files import StreamFieldFile
 
 
-def generate_submission_file_path(submission_id, field_id, file_name):
-    path = os.path.join("submission", str(submission_id), str(field_id))
+def generate_private_file_path(entity_id, field_id, file_name, path_start="submission"):
+    path = os.path.join(path_start, str(entity_id), str(field_id))
     if file_name.startswith(path):
         return file_name
 
     return os.path.join(path, file_name)
 
 
-class SubmissionStreamFieldFile(StreamFieldFile):
-    def get_submission_id(self):
+class PrivateStreamFieldFile(StreamFieldFile):
+    """
+    Represents a file from a Wagtail/Hypha Stream Form block.
+    Aside: with imports in their usual place, there could be circular imports. Deferring or delaying import to methods
+    resolves the issue.
+    """
+
+    def get_entity_id(self):
         from hypha.apply.funds.models import ApplicationRevision
+        from hypha.apply.projects.models import ReportVersion
 
-        submission_id = self.instance.pk
+        entity_id = self.instance.pk
 
         if isinstance(self.instance, ApplicationRevision):
-            submission_id = self.instance.submission.pk
-        return submission_id
+            entity_id = self.instance.submission.pk
+        elif isinstance(self.instance, ReportVersion):
+            # Reports are project documents.
+            entity_id = self.instance.report.project.pk
+        return entity_id
 
     def generate_filename(self):
-        return generate_submission_file_path(
-            self.get_submission_id(), self.field.id, self.name
+        from hypha.apply.projects.models import ReportVersion
+
+        path_start = "submission"
+        if isinstance(self.instance, ReportVersion):
+            path_start = "project"
+        return generate_private_file_path(
+            self.get_entity_id(),
+            self.field.id,
+            self.name,
+            path_start=path_start,
         )
 
     @property
     def url(self):
-        return reverse(
-            "apply:submissions:serve_private_media",
-            kwargs={
-                "pk": self.get_submission_id(),
-                "field_id": self.field.id,
-                "file_name": self.basename,
-            },
-        )
+        from hypha.apply.projects.models import ReportVersion
+
+        view_name = "apply:submissions:serve_private_media"
+        kwargs = {
+            "pk": self.get_entity_id(),
+            "field_id": self.field.id,
+            "file_name": self.basename,
+        }
+        if isinstance(self.instance, ReportVersion):
+            view_name = "apply:projects:document"
+        return reverse(viewname=view_name, kwargs=kwargs)
diff --git a/hypha/apply/funds/migrations/0118_labbaseprojectreportform_and_more.py b/hypha/apply/funds/migrations/0118_labbaseprojectreportform_and_more.py
new file mode 100644
index 0000000000000000000000000000000000000000..802db4a8876865487e3bdd46077e98474402f4b0
--- /dev/null
+++ b/hypha/apply/funds/migrations/0118_labbaseprojectreportform_and_more.py
@@ -0,0 +1,89 @@
+# Generated by Django 4.2.11 on 2024-04-17 20:38
+
+from django.db import migrations, models
+import django.db.models.deletion
+import modelcluster.fields
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("application_projects", "0082_projectreportform_and_more"),
+        ("funds", "0117_applicationrevision_is_draft"),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name="LabBaseProjectReportForm",
+            fields=[
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "sort_order",
+                    models.IntegerField(blank=True, editable=False, null=True),
+                ),
+                (
+                    "form",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.PROTECT,
+                        to="application_projects.projectreportform",
+                    ),
+                ),
+                (
+                    "lab",
+                    modelcluster.fields.ParentalKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="report_forms",
+                        to="funds.labbase",
+                    ),
+                ),
+            ],
+            options={
+                "ordering": ["sort_order"],
+                "abstract": False,
+            },
+        ),
+        migrations.CreateModel(
+            name="ApplicationBaseProjectReportForm",
+            fields=[
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                (
+                    "sort_order",
+                    models.IntegerField(blank=True, editable=False, null=True),
+                ),
+                (
+                    "application",
+                    modelcluster.fields.ParentalKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name="report_forms",
+                        to="funds.applicationbase",
+                    ),
+                ),
+                (
+                    "form",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.PROTECT,
+                        to="application_projects.projectreportform",
+                    ),
+                ),
+            ],
+            options={
+                "ordering": ["sort_order"],
+                "abstract": False,
+            },
+        ),
+    ]
diff --git a/hypha/apply/funds/models/forms.py b/hypha/apply/funds/models/forms.py
index 39ad01c0d69bd4dcb30c1649900eac426326e676..92a5f9e7f35f8fd6f3b19373033fd94afa390423 100644
--- a/hypha/apply/funds/models/forms.py
+++ b/hypha/apply/funds/models/forms.py
@@ -4,6 +4,7 @@ from wagtail.admin.panels import FieldPanel
 from wagtail.fields import StreamField
 from wagtail.models import Orderable
 
+from ...projects.models.project import ProjectReportForm
 from ..blocks import ApplicationCustomFormFieldsBlock
 from ..edit_handlers import FilteredFieldPanel
 
@@ -268,3 +269,40 @@ class LabBaseProjectApprovalForm(AbstractRelatedProjectApprovalForm):
 
 class LabBaseProjectSOWForm(AbstractRelatedProjectSOWForm):
     lab = ParentalKey("LabBase", related_name="sow_forms")
+
+
+class AbstractRelatedProjectReportForm(Orderable):
+    class Meta(Orderable.Meta):
+        abstract = True
+
+    form = models.ForeignKey(to=ProjectReportForm, on_delete=models.PROTECT)
+
+    @property
+    def fields(self):
+        return self.form.form_fields
+
+    def __eq__(self, other):
+        try:
+            if self.fields == other.fields and self.sort_order == other.sort_order:
+                # If the objects are saved to db. pk should also be compared
+                if hasattr(other, "pk") and hasattr(self, "pk"):
+                    return self.pk == other.pk
+                return True
+            return False
+        except AttributeError:
+            return False
+
+    def __hash__(self):
+        fields = [field.id for field in self.fields]
+        return hash((tuple(fields), self.sort_order, self.pk))
+
+    def __str__(self):
+        return self.form.name
+
+
+class ApplicationBaseProjectReportForm(AbstractRelatedProjectReportForm):
+    application = ParentalKey("ApplicationBase", related_name="report_forms")
+
+
+class LabBaseProjectReportForm(AbstractRelatedProjectReportForm):
+    lab = ParentalKey("LabBase", related_name="report_forms")
diff --git a/hypha/apply/funds/models/mixins.py b/hypha/apply/funds/models/mixins.py
index 1d7aae6feeaba73b79252a18a71d8df39ae4a900..b6479d3fdc0ae35b60ffee03f9e83b265f664beb 100644
--- a/hypha/apply/funds/models/mixins.py
+++ b/hypha/apply/funds/models/mixins.py
@@ -14,7 +14,7 @@ from hypha.apply.stream_forms.blocks import (
 from hypha.apply.utils.blocks import SingleIncludeMixin
 from hypha.apply.utils.storage import PrivateStorage
 
-from ..files import SubmissionStreamFieldFile
+from ..files import PrivateStreamFieldFile
 
 __all__ = ["AccessFormData"]
 
@@ -31,7 +31,7 @@ class AccessFormData:
          - form_fields > streamfield containing the original form fields
     """
 
-    stream_file_class = SubmissionStreamFieldFile
+    stream_file_class = PrivateStreamFieldFile
     storage_class = PrivateStorage
 
     @property
diff --git a/hypha/apply/funds/models/utils.py b/hypha/apply/funds/models/utils.py
index dd52fbe334097e54ea86cd1a07eedee8f6693994..b8ead66526f2d296615dfae1d9a8d01a863ceeb9 100644
--- a/hypha/apply/funds/models/utils.py
+++ b/hypha/apply/funds/models/utils.py
@@ -146,6 +146,8 @@ class WorkflowStreamForm(WorkflowHelpers, AbstractStreamForm):  # type: ignore
         InlinePanel("determination_forms", label=_("Determination Forms")),
         InlinePanel("approval_forms", label=_("Project Approval Form"), max_num=1),
         InlinePanel("sow_forms", label=_("Project SOW Form"), max_num=1),
+        # The models technically allow for multiple Report forms but to start we permit only one in the UIs.
+        InlinePanel("report_forms", label=_("Project Report Form"), max_num=1),
     ]
 
 
diff --git a/hypha/apply/funds/tests/test_admin_form.py b/hypha/apply/funds/tests/test_admin_form.py
index f2f147a9d1371afe82ea2f3ffae43526489fdba9..f484492c777dd9ea9052ab8cd00af550d8913fce 100644
--- a/hypha/apply/funds/tests/test_admin_form.py
+++ b/hypha/apply/funds/tests/test_admin_form.py
@@ -5,6 +5,7 @@ from hypha.apply.determinations.tests.factories import DeterminationFormFactory
 from hypha.apply.funds.models import FundType
 from hypha.apply.projects.tests.factories import (
     ProjectApprovalFormFactory,
+    ProjectReportFormFactory,
     ProjectSOWFormFactory,
 )
 from hypha.apply.review.tests.factories import ReviewFormFactory
@@ -55,6 +56,7 @@ def form_data(
     stages=1,
     same_forms=False,
     form_stage_info=None,
+    num_project_report_forms=0,
 ):
     if form_stage_info is None:
         form_stage_info = [1]
@@ -101,12 +103,19 @@ def form_data(
         same=same_forms,
         factory=ProjectSOWFormFactory,
     )
-
+    project_report_form_data = formset_base(
+        "report_forms",
+        num_project_report_forms,
+        False,
+        same=same_forms,
+        factory=ProjectReportFormFactory,
+    )
     form_data.update(review_form_data)
     form_data.update(external_review_form_data)
     form_data.update(determination_form_data)
     form_data.update(project_approval_form_data)
     form_data.update(project_sow_form_data)
+    form_data.update(project_report_form_data)
 
     fund_data = factory.build(dict, FACTORY_CLASS=FundTypeFactory)
     fund_data["workflow_name"] = workflow_for_stages(stages)
@@ -232,3 +241,7 @@ class TestWorkflowFormAdminForm(TestCase):
             form_data(1, 1, 1, 0, num_project_approval_form=2, stages=2)
         )
         self.assertFalse(form.is_valid(), form.errors.as_text())
+
+    def test_validates_with_project_report_form(self):
+        form = self.submit_data(form_data(1, 1, 1, 0, 1, 0, 0, 1, False, None, 1))
+        self.assertTrue(form.is_valid(), form.errors.as_text())
diff --git a/hypha/apply/funds/views.py b/hypha/apply/funds/views.py
index 0b60e99d2215cff882e1b5de057d6e0c91b32f74..51eff45830c8e1b0cae7c317b1d13f5141d31e0f 100644
--- a/hypha/apply/funds/views.py
+++ b/hypha/apply/funds/views.py
@@ -76,7 +76,7 @@ from hypha.apply.utils.views import (
 
 from . import services
 from .differ import compare
-from .files import generate_submission_file_path
+from .files import generate_private_file_path
 from .forms import (
     ArchiveSubmissionForm,
     BatchArchiveSubmissionForm,
@@ -1701,7 +1701,7 @@ class SubmissionPrivateMediaView(UserPassesTestMixin, PrivateMediaView):
     def get_media(self, *args, **kwargs):
         field_id = kwargs["field_id"]
         file_name = kwargs["file_name"]
-        path_to_file = generate_submission_file_path(
+        path_to_file = generate_private_file_path(
             self.submission.pk, field_id, file_name
         )
         return self.storage.open(path_to_file)
diff --git a/hypha/apply/projects/admin.py b/hypha/apply/projects/admin.py
index 6a3b58fed405eaeefdfaf45374f9b6e9cfdcb4c1..0a46204ae3ba456ff28ca12d1ab5847eb5ee3935 100644
--- a/hypha/apply/projects/admin.py
+++ b/hypha/apply/projects/admin.py
@@ -5,14 +5,17 @@ from hypha.core.wagtail.admin import SettingModelAdmin
 
 from .admin_views import (
     CreateProjectApprovalFormView,
+    CreateProjectReportFormView,
     CreateProjectSOWFormView,
     EditProjectApprovalFormView,
+    EditProjectReportFormView,
     EditProjectSOWFormView,
 )
 from .models import (
     ContractDocumentCategory,
     DocumentCategory,
     ProjectApprovalForm,
+    ProjectReportForm,
     ProjectSettings,
     ProjectSOWForm,
     VendorFormSettings,
@@ -71,6 +74,23 @@ class ProjectSOWFormAdmin(ListRelatedMixin, ModelAdmin):
     ]
 
 
+class ProjectReportFormAdmin(ListRelatedMixin, ModelAdmin):
+    model = ProjectReportForm
+    menu_label = "Report Forms"
+    menu_icon = "form"
+    list_display = (
+        "name",
+        "used_by",
+    )
+    create_view_class = CreateProjectReportFormView
+    edit_view_class = EditProjectReportFormView
+
+    related_models = [
+        ("applicationbaseprojectreportform", "application"),
+        ("labbaseprojectreportform", "lab"),
+    ]
+
+
 class ProjectSettingsAdmin(SettingModelAdmin):
     model = ProjectSettings
 
@@ -86,6 +106,7 @@ class ProjectAdminGroup(ModelAdminGroup):
         ContractDocumentCategoryAdmin,
         DocumentCategoryAdmin,
         ProjectApprovalFormAdmin,
+        ProjectReportFormAdmin,
         ProjectSOWFormAdmin,
         VendorFormSettingsAdmin,
         ProjectSettingsAdmin,
diff --git a/hypha/apply/projects/admin_views.py b/hypha/apply/projects/admin_views.py
index 5dcc4c04d8cb7766a3c45004810f18e4019bf948..4bdaa7a802f664c4778440cd2181ae886eb4f80a 100644
--- a/hypha/apply/projects/admin_views.py
+++ b/hypha/apply/projects/admin_views.py
@@ -21,3 +21,11 @@ class CreateProjectSOWFormView(CreateProjectApprovalFormView):
 
 class EditProjectSOWFormView(EditProjectApprovalFormView):
     pass
+
+
+class CreateProjectReportFormView(CreateProjectApprovalFormView):
+    pass
+
+
+class EditProjectReportFormView(EditProjectApprovalFormView):
+    pass
diff --git a/hypha/apply/projects/blocks.py b/hypha/apply/projects/blocks.py
index c5378ff36e91f7836f93d04337aae2ab3b862508..a8207a333aa93bccf8114618dd870969cf8bbe9c 100644
--- a/hypha/apply/projects/blocks.py
+++ b/hypha/apply/projects/blocks.py
@@ -2,5 +2,7 @@ from hypha.apply.stream_forms.blocks import FormFieldsBlock
 from hypha.apply.utils.blocks import CustomFormFieldsBlock
 
 
-class ProjectApprovalFormCustomFormFieldsBlock(CustomFormFieldsBlock, FormFieldsBlock):
+class ProjectFormCustomFormFieldsBlock(CustomFormFieldsBlock, FormFieldsBlock):
+    """A block that can be used for customizable Project-related forms: PAF, SOW, and Report."""
+
     pass
diff --git a/hypha/apply/projects/forms/report.py b/hypha/apply/projects/forms/report.py
index 917ae5824cc29174cdf5f3eb3854626d598bdf39..f63ad8b910a9376b9ca89f26a0ad82b2243b1ea6 100644
--- a/hypha/apply/projects/forms/report.py
+++ b/hypha/apply/projects/forms/report.py
@@ -1,76 +1,73 @@
 from django import forms
 from django.db import transaction
 from django.utils import timezone
-from django.utils.translation import gettext_lazy as _
-from django_file_form.forms import FileFormMixin
 
-from hypha.apply.stream_forms.fields import MultiFileField
-from hypha.apply.utils.fields import RichTextField
+from ...review.forms import MixedMetaClass
+from ...stream_forms.forms import StreamBaseForm
+from ..models.report import Report, ReportConfig, ReportVersion
 
-from ..models.report import Report, ReportConfig, ReportPrivateFiles, ReportVersion
-
-
-class ReportEditForm(FileFormMixin, forms.ModelForm):
-    public_content = RichTextField(
-        help_text=_(
-            "This section of the report will be shared with the broader community."
-        )
-    )
-    private_content = RichTextField(
-        help_text=_("This section of the report will be shared with staff only.")
-    )
-    file_list = forms.ModelMultipleChoiceField(
-        widget=forms.CheckboxSelectMultiple(attrs={"class": "delete"}),
-        queryset=ReportPrivateFiles.objects.all(),
-        required=False,
-        label=_("Files"),
-    )
-    files = MultiFileField(required=False, label="")
 
+class ReportEditForm(StreamBaseForm, forms.ModelForm, metaclass=MixedMetaClass):
     class Meta:
         model = Report
-        fields = (
-            "public_content",
-            "private_content",
-            "file_list",
-            "files",
-        )
+        fields: list = []
 
     def __init__(self, *args, user=None, initial=None, **kwargs):
         if initial is None:
             initial = {}
-        self.report_files = initial.pop(
-            "file_list",
-            ReportPrivateFiles.objects.none(),
-        )
+        # Need to populate form_fields, right?
+        # No: The form_fields got populated from the view which instantiated this Form.
+        # Yes: they don't seem to be here.
+        # No: this is not where the magic happens.
+        # self.form_fields = kwargs.pop("form_fields", {})
+        # Need to populate form_data, right? Yes. No. IDK. Appears no.
+        # self.form_data = kwargs.pop("form_data", {})
+        # OK, both yes and no. If there is an existing value it will come via "initial", so if present there, use them.
+        # if initial["form_fields"] is not None:
+        #     self.form_fields = initial["form_fields"]
+        # if initial["form_data"] is not None:
+        #     self.form_data = initial["form_data"]
+        # But this should not be needed because super().__init__ will already take these initial values and use them.
         super().__init__(*args, initial=initial, **kwargs)
-        self.fields["file_list"].queryset = self.report_files
         self.user = user
 
     def clean(self):
         cleaned_data = super().clean()
-        public = cleaned_data["public_content"]
-        private = cleaned_data["private_content"]
-        if not private and not public:
-            missing_content = _(
-                "Must include either public or private content when submitting a report."
-            )
-            self.add_error("public_content", missing_content)
-            self.add_error("private_content", missing_content)
+        cleaned_data["form_data"] = {
+            key: value
+            for key, value in cleaned_data.items()
+            if key not in self._meta.fields
+        }
         return cleaned_data
 
     @transaction.atomic
-    def save(self, commit=True):
+    def save(self, commit=True, form_fields=dict):
         is_draft = "save" in self.data
-
         version = ReportVersion.objects.create(
             report=self.instance,
-            public_content=self.cleaned_data["public_content"],
-            private_content=self.cleaned_data["private_content"],
+            form_fields=form_fields,
+            # Save a ReportVersion first then edit/update the form_data below.
+            form_data={},
             submitted=timezone.now(),
             draft=is_draft,
             author=self.user,
         )
+        # We need to save the fields first, not attempt to save form_data on first save, then update the form_data next.
+        # Otherwise, we don't get access to the generator method "question_field_ids" which we use to prevent temp file
+        # fields from getting into the saved form_data.
+        # Inspired by ProjectApprovalForm.save and ProjectSOWForm.save but enhanced to support multi-answer fields.
+        version.form_data = {
+            field: self.cleaned_data["form_data"][field]
+            for field in self.cleaned_data["form_data"]
+            # Where do we get question_field_ids? On the version, but only when it exists, thus the create-then-update.
+            # The split-on-underscore supports the use of multi-answer fields such as MultiInputCharFieldBlock.
+            if field.split("_")[0] in version.question_field_ids
+        }
+
+        # In case there are stream form file fields, process those here.
+        version.process_file_data(self.cleaned_data["form_data"])
+        # Because ReportVersion is a separate entity from Project, super().save will not save ReportVersion: save here.
+        version.save()
 
         if is_draft:
             self.instance.draft = version
@@ -83,21 +80,6 @@ class ReportEditForm(FileFormMixin, forms.ModelForm):
             self.instance.draft = None
 
         instance = super().save(commit)
-
-        removed_files = self.cleaned_data["file_list"]
-        ReportPrivateFiles.objects.bulk_create(
-            ReportPrivateFiles(report=version, document=file.document)
-            for file in self.report_files
-            if file not in removed_files
-        )
-
-        added_files = self.cleaned_data["files"]
-        if added_files:
-            ReportPrivateFiles.objects.bulk_create(
-                ReportPrivateFiles(report=version, document=file)
-                for file in added_files
-            )
-
         return instance
 
 
diff --git a/hypha/apply/projects/migrations/0082_projectreportform_and_more.py b/hypha/apply/projects/migrations/0082_projectreportform_and_more.py
new file mode 100644
index 0000000000000000000000000000000000000000..37535ccaf7d46061017b39177f244fcf5a2537bb
--- /dev/null
+++ b/hypha/apply/projects/migrations/0082_projectreportform_and_more.py
@@ -0,0 +1,1423 @@
+# Generated by Django 4.2.11 on 2024-04-05 16:30
+
+from django.db import migrations, models
+import hypha.apply.stream_forms.blocks
+import hypha.apply.stream_forms.files
+import hypha.apply.stream_forms.models
+import wagtail.blocks
+import wagtail.fields
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("application_projects", "0081_alter_project_value"),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name="ProjectReportForm",
+            fields=[
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("name", models.CharField(max_length=255)),
+                (
+                    "form_fields",
+                    wagtail.fields.StreamField(
+                        [
+                            (
+                                "text_markup",
+                                wagtail.blocks.RichTextBlock(
+                                    group="Custom", label="Paragraph"
+                                ),
+                            ),
+                            (
+                                "header_markup",
+                                wagtail.blocks.StructBlock(
+                                    [
+                                        (
+                                            "heading_text",
+                                            wagtail.blocks.CharBlock(
+                                                form_classname="title", required=True
+                                            ),
+                                        ),
+                                        (
+                                            "size",
+                                            wagtail.blocks.ChoiceBlock(
+                                                choices=[
+                                                    ("h2", "H2"),
+                                                    ("h3", "H3"),
+                                                    ("h4", "H4"),
+                                                ]
+                                            ),
+                                        ),
+                                    ],
+                                    group="Custom",
+                                    label="Section header",
+                                ),
+                            ),
+                            (
+                                "char",
+                                wagtail.blocks.StructBlock(
+                                    [
+                                        (
+                                            "field_label",
+                                            wagtail.blocks.CharBlock(label="Label"),
+                                        ),
+                                        (
+                                            "help_text",
+                                            wagtail.blocks.TextBlock(
+                                                label="Help text", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "help_link",
+                                            wagtail.blocks.URLBlock(
+                                                label="Help link", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "required",
+                                            wagtail.blocks.BooleanBlock(
+                                                label="Required", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "format",
+                                            wagtail.blocks.ChoiceBlock(
+                                                choices=[
+                                                    ("email", "Email"),
+                                                    ("url", "URL"),
+                                                ],
+                                                label="Format",
+                                                required=False,
+                                            ),
+                                        ),
+                                        (
+                                            "default_value",
+                                            wagtail.blocks.CharBlock(
+                                                label="Default value", required=False
+                                            ),
+                                        ),
+                                    ],
+                                    group="Fields",
+                                ),
+                            ),
+                            (
+                                "multi_inputs_char",
+                                wagtail.blocks.StructBlock(
+                                    [
+                                        (
+                                            "field_label",
+                                            wagtail.blocks.CharBlock(label="Label"),
+                                        ),
+                                        (
+                                            "help_text",
+                                            wagtail.blocks.TextBlock(
+                                                label="Help text", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "help_link",
+                                            wagtail.blocks.URLBlock(
+                                                label="Help link", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "required",
+                                            wagtail.blocks.BooleanBlock(
+                                                label="Required", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "format",
+                                            wagtail.blocks.ChoiceBlock(
+                                                choices=[
+                                                    ("email", "Email"),
+                                                    ("url", "URL"),
+                                                ],
+                                                label="Format",
+                                                required=False,
+                                            ),
+                                        ),
+                                        (
+                                            "default_value",
+                                            wagtail.blocks.CharBlock(
+                                                label="Default value", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "number_of_inputs",
+                                            wagtail.blocks.IntegerBlock(
+                                                default=2, label="Max number of inputs"
+                                            ),
+                                        ),
+                                        (
+                                            "add_button_text",
+                                            wagtail.blocks.CharBlock(
+                                                default="Add new item", required=False
+                                            ),
+                                        ),
+                                    ],
+                                    group="Fields",
+                                ),
+                            ),
+                            (
+                                "text",
+                                wagtail.blocks.StructBlock(
+                                    [
+                                        (
+                                            "field_label",
+                                            wagtail.blocks.CharBlock(label="Label"),
+                                        ),
+                                        (
+                                            "help_text",
+                                            wagtail.blocks.TextBlock(
+                                                label="Help text", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "help_link",
+                                            wagtail.blocks.URLBlock(
+                                                label="Help link", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "required",
+                                            wagtail.blocks.BooleanBlock(
+                                                label="Required", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "default_value",
+                                            wagtail.blocks.TextBlock(
+                                                label="Default value", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "word_limit",
+                                            wagtail.blocks.IntegerBlock(
+                                                default=1000, label="Word limit"
+                                            ),
+                                        ),
+                                    ],
+                                    group="Fields",
+                                ),
+                            ),
+                            (
+                                "number",
+                                wagtail.blocks.StructBlock(
+                                    [
+                                        (
+                                            "field_label",
+                                            wagtail.blocks.CharBlock(label="Label"),
+                                        ),
+                                        (
+                                            "help_text",
+                                            wagtail.blocks.TextBlock(
+                                                label="Help text", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "help_link",
+                                            wagtail.blocks.URLBlock(
+                                                label="Help link", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "required",
+                                            wagtail.blocks.BooleanBlock(
+                                                label="Required", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "default_value",
+                                            wagtail.blocks.CharBlock(
+                                                label="Default value", required=False
+                                            ),
+                                        ),
+                                    ],
+                                    group="Fields",
+                                ),
+                            ),
+                            (
+                                "checkbox",
+                                wagtail.blocks.StructBlock(
+                                    [
+                                        (
+                                            "field_label",
+                                            wagtail.blocks.CharBlock(label="Label"),
+                                        ),
+                                        (
+                                            "help_text",
+                                            wagtail.blocks.TextBlock(
+                                                label="Help text", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "help_link",
+                                            wagtail.blocks.URLBlock(
+                                                label="Help link", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "required",
+                                            wagtail.blocks.BooleanBlock(
+                                                label="Required", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "default_value",
+                                            wagtail.blocks.BooleanBlock(required=False),
+                                        ),
+                                    ],
+                                    group="Fields",
+                                ),
+                            ),
+                            (
+                                "radios",
+                                wagtail.blocks.StructBlock(
+                                    [
+                                        (
+                                            "field_label",
+                                            wagtail.blocks.CharBlock(label="Label"),
+                                        ),
+                                        (
+                                            "help_text",
+                                            wagtail.blocks.TextBlock(
+                                                label="Help text", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "help_link",
+                                            wagtail.blocks.URLBlock(
+                                                label="Help link", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "required",
+                                            wagtail.blocks.BooleanBlock(
+                                                label="Required", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "choices",
+                                            wagtail.blocks.ListBlock(
+                                                wagtail.blocks.CharBlock(label="Choice")
+                                            ),
+                                        ),
+                                    ],
+                                    group="Fields",
+                                ),
+                            ),
+                            (
+                                "dropdown",
+                                wagtail.blocks.StructBlock(
+                                    [
+                                        (
+                                            "field_label",
+                                            wagtail.blocks.CharBlock(label="Label"),
+                                        ),
+                                        (
+                                            "help_text",
+                                            wagtail.blocks.TextBlock(
+                                                label="Help text", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "help_link",
+                                            wagtail.blocks.URLBlock(
+                                                label="Help link", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "required",
+                                            wagtail.blocks.BooleanBlock(
+                                                label="Required", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "choices",
+                                            wagtail.blocks.ListBlock(
+                                                wagtail.blocks.CharBlock(label="Choice")
+                                            ),
+                                        ),
+                                    ],
+                                    group="Fields",
+                                ),
+                            ),
+                            (
+                                "checkboxes",
+                                wagtail.blocks.StructBlock(
+                                    [
+                                        (
+                                            "field_label",
+                                            wagtail.blocks.CharBlock(label="Label"),
+                                        ),
+                                        (
+                                            "help_text",
+                                            wagtail.blocks.TextBlock(
+                                                label="Help text", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "help_link",
+                                            wagtail.blocks.URLBlock(
+                                                label="Help link", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "required",
+                                            wagtail.blocks.BooleanBlock(
+                                                label="Required", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "checkboxes",
+                                            wagtail.blocks.ListBlock(
+                                                wagtail.blocks.CharBlock(
+                                                    label="Checkbox"
+                                                )
+                                            ),
+                                        ),
+                                    ],
+                                    group="Fields",
+                                ),
+                            ),
+                            (
+                                "date",
+                                wagtail.blocks.StructBlock(
+                                    [
+                                        (
+                                            "field_label",
+                                            wagtail.blocks.CharBlock(label="Label"),
+                                        ),
+                                        (
+                                            "help_text",
+                                            wagtail.blocks.TextBlock(
+                                                label="Help text", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "help_link",
+                                            wagtail.blocks.URLBlock(
+                                                label="Help link", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "required",
+                                            wagtail.blocks.BooleanBlock(
+                                                label="Required", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "default_value",
+                                            wagtail.blocks.DateBlock(required=False),
+                                        ),
+                                    ],
+                                    group="Fields",
+                                ),
+                            ),
+                            (
+                                "time",
+                                wagtail.blocks.StructBlock(
+                                    [
+                                        (
+                                            "field_label",
+                                            wagtail.blocks.CharBlock(label="Label"),
+                                        ),
+                                        (
+                                            "help_text",
+                                            wagtail.blocks.TextBlock(
+                                                label="Help text", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "help_link",
+                                            wagtail.blocks.URLBlock(
+                                                label="Help link", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "required",
+                                            wagtail.blocks.BooleanBlock(
+                                                label="Required", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "default_value",
+                                            wagtail.blocks.TimeBlock(required=False),
+                                        ),
+                                    ],
+                                    group="Fields",
+                                ),
+                            ),
+                            (
+                                "datetime",
+                                wagtail.blocks.StructBlock(
+                                    [
+                                        (
+                                            "field_label",
+                                            wagtail.blocks.CharBlock(label="Label"),
+                                        ),
+                                        (
+                                            "help_text",
+                                            wagtail.blocks.TextBlock(
+                                                label="Help text", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "help_link",
+                                            wagtail.blocks.URLBlock(
+                                                label="Help link", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "required",
+                                            wagtail.blocks.BooleanBlock(
+                                                label="Required", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "default_value",
+                                            wagtail.blocks.DateTimeBlock(
+                                                required=False
+                                            ),
+                                        ),
+                                    ],
+                                    group="Fields",
+                                ),
+                            ),
+                            (
+                                "image",
+                                wagtail.blocks.StructBlock(
+                                    [
+                                        (
+                                            "field_label",
+                                            wagtail.blocks.CharBlock(label="Label"),
+                                        ),
+                                        (
+                                            "help_text",
+                                            wagtail.blocks.TextBlock(
+                                                label="Help text", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "help_link",
+                                            wagtail.blocks.URLBlock(
+                                                label="Help link", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "required",
+                                            wagtail.blocks.BooleanBlock(
+                                                label="Required", required=False
+                                            ),
+                                        ),
+                                    ],
+                                    group="Fields",
+                                ),
+                            ),
+                            (
+                                "file",
+                                wagtail.blocks.StructBlock(
+                                    [
+                                        (
+                                            "field_label",
+                                            wagtail.blocks.CharBlock(label="Label"),
+                                        ),
+                                        (
+                                            "help_text",
+                                            wagtail.blocks.TextBlock(
+                                                label="Help text", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "help_link",
+                                            wagtail.blocks.URLBlock(
+                                                label="Help link", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "required",
+                                            wagtail.blocks.BooleanBlock(
+                                                label="Required", required=False
+                                            ),
+                                        ),
+                                    ],
+                                    group="Fields",
+                                ),
+                            ),
+                            (
+                                "multi_file",
+                                wagtail.blocks.StructBlock(
+                                    [
+                                        (
+                                            "field_label",
+                                            wagtail.blocks.CharBlock(label="Label"),
+                                        ),
+                                        (
+                                            "help_text",
+                                            wagtail.blocks.TextBlock(
+                                                label="Help text", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "help_link",
+                                            wagtail.blocks.URLBlock(
+                                                label="Help link", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "required",
+                                            wagtail.blocks.BooleanBlock(
+                                                label="Required", required=False
+                                            ),
+                                        ),
+                                    ],
+                                    group="Fields",
+                                ),
+                            ),
+                            (
+                                "group_toggle",
+                                wagtail.blocks.StructBlock(
+                                    [
+                                        (
+                                            "field_label",
+                                            wagtail.blocks.CharBlock(label="Label"),
+                                        ),
+                                        (
+                                            "help_text",
+                                            wagtail.blocks.TextBlock(
+                                                label="Help text", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "help_link",
+                                            wagtail.blocks.URLBlock(
+                                                label="Help link", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "required",
+                                            wagtail.blocks.BooleanBlock(
+                                                default=True,
+                                                label="Required",
+                                                required=False,
+                                            ),
+                                        ),
+                                        (
+                                            "choices",
+                                            wagtail.blocks.ListBlock(
+                                                wagtail.blocks.CharBlock(
+                                                    label="Choice"
+                                                ),
+                                                help_text="Please create only two choices for toggle. First choice will revel the group and the second hide it. Additional choices will be ignored.",
+                                            ),
+                                        ),
+                                    ],
+                                    group="Custom",
+                                ),
+                            ),
+                            (
+                                "group_toggle_end",
+                                hypha.apply.stream_forms.blocks.GroupToggleEndBlock(
+                                    group="Custom"
+                                ),
+                            ),
+                            (
+                                "rich_text",
+                                wagtail.blocks.StructBlock(
+                                    [
+                                        (
+                                            "field_label",
+                                            wagtail.blocks.CharBlock(label="Label"),
+                                        ),
+                                        (
+                                            "help_text",
+                                            wagtail.blocks.TextBlock(
+                                                label="Help text", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "help_link",
+                                            wagtail.blocks.URLBlock(
+                                                label="Help link", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "required",
+                                            wagtail.blocks.BooleanBlock(
+                                                label="Required", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "default_value",
+                                            wagtail.blocks.TextBlock(
+                                                label="Default value", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "word_limit",
+                                            wagtail.blocks.IntegerBlock(
+                                                default=1000, label="Word limit"
+                                            ),
+                                        ),
+                                    ],
+                                    group="Fields",
+                                ),
+                            ),
+                            (
+                                "markdown_text",
+                                wagtail.blocks.StructBlock(
+                                    [
+                                        (
+                                            "field_label",
+                                            wagtail.blocks.CharBlock(label="Label"),
+                                        ),
+                                        (
+                                            "help_text",
+                                            wagtail.blocks.TextBlock(
+                                                label="Help text", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "help_link",
+                                            wagtail.blocks.URLBlock(
+                                                label="Help link", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "required",
+                                            wagtail.blocks.BooleanBlock(
+                                                label="Required", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "default_value",
+                                            wagtail.blocks.TextBlock(
+                                                label="Default value", required=False
+                                            ),
+                                        ),
+                                        (
+                                            "word_limit",
+                                            wagtail.blocks.IntegerBlock(
+                                                default=1000, label="Word limit"
+                                            ),
+                                        ),
+                                    ],
+                                    group="Fields",
+                                ),
+                            ),
+                        ],
+                        use_json_field=True,
+                    ),
+                ),
+            ],
+            options={
+                "abstract": False,
+            },
+            bases=(hypha.apply.stream_forms.models.BaseStreamForm, models.Model),
+        ),
+        migrations.RemoveField(
+            model_name="reportversion",
+            name="private_content",
+        ),
+        migrations.RemoveField(
+            model_name="reportversion",
+            name="public_content",
+        ),
+        migrations.AddField(
+            model_name="reportversion",
+            name="form_data",
+            field=models.JSONField(
+                default=dict,
+                encoder=hypha.apply.stream_forms.files.StreamFieldDataEncoder,
+            ),
+        ),
+        migrations.AddField(
+            model_name="reportversion",
+            name="form_fields",
+            field=wagtail.fields.StreamField(
+                [
+                    (
+                        "text_markup",
+                        wagtail.blocks.RichTextBlock(group="Custom", label="Paragraph"),
+                    ),
+                    (
+                        "header_markup",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "heading_text",
+                                    wagtail.blocks.CharBlock(
+                                        form_classname="title", required=True
+                                    ),
+                                ),
+                                (
+                                    "size",
+                                    wagtail.blocks.ChoiceBlock(
+                                        choices=[
+                                            ("h2", "H2"),
+                                            ("h3", "H3"),
+                                            ("h4", "H4"),
+                                        ]
+                                    ),
+                                ),
+                            ],
+                            group="Custom",
+                            label="Section header",
+                        ),
+                    ),
+                    (
+                        "char",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "field_label",
+                                    wagtail.blocks.CharBlock(label="Label"),
+                                ),
+                                (
+                                    "help_text",
+                                    wagtail.blocks.TextBlock(
+                                        label="Help text", required=False
+                                    ),
+                                ),
+                                (
+                                    "help_link",
+                                    wagtail.blocks.URLBlock(
+                                        label="Help link", required=False
+                                    ),
+                                ),
+                                (
+                                    "required",
+                                    wagtail.blocks.BooleanBlock(
+                                        label="Required", required=False
+                                    ),
+                                ),
+                                (
+                                    "format",
+                                    wagtail.blocks.ChoiceBlock(
+                                        choices=[("email", "Email"), ("url", "URL")],
+                                        label="Format",
+                                        required=False,
+                                    ),
+                                ),
+                                (
+                                    "default_value",
+                                    wagtail.blocks.CharBlock(
+                                        label="Default value", required=False
+                                    ),
+                                ),
+                            ],
+                            group="Fields",
+                        ),
+                    ),
+                    (
+                        "multi_inputs_char",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "field_label",
+                                    wagtail.blocks.CharBlock(label="Label"),
+                                ),
+                                (
+                                    "help_text",
+                                    wagtail.blocks.TextBlock(
+                                        label="Help text", required=False
+                                    ),
+                                ),
+                                (
+                                    "help_link",
+                                    wagtail.blocks.URLBlock(
+                                        label="Help link", required=False
+                                    ),
+                                ),
+                                (
+                                    "required",
+                                    wagtail.blocks.BooleanBlock(
+                                        label="Required", required=False
+                                    ),
+                                ),
+                                (
+                                    "format",
+                                    wagtail.blocks.ChoiceBlock(
+                                        choices=[("email", "Email"), ("url", "URL")],
+                                        label="Format",
+                                        required=False,
+                                    ),
+                                ),
+                                (
+                                    "default_value",
+                                    wagtail.blocks.CharBlock(
+                                        label="Default value", required=False
+                                    ),
+                                ),
+                                (
+                                    "number_of_inputs",
+                                    wagtail.blocks.IntegerBlock(
+                                        default=2, label="Max number of inputs"
+                                    ),
+                                ),
+                                (
+                                    "add_button_text",
+                                    wagtail.blocks.CharBlock(
+                                        default="Add new item", required=False
+                                    ),
+                                ),
+                            ],
+                            group="Fields",
+                        ),
+                    ),
+                    (
+                        "text",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "field_label",
+                                    wagtail.blocks.CharBlock(label="Label"),
+                                ),
+                                (
+                                    "help_text",
+                                    wagtail.blocks.TextBlock(
+                                        label="Help text", required=False
+                                    ),
+                                ),
+                                (
+                                    "help_link",
+                                    wagtail.blocks.URLBlock(
+                                        label="Help link", required=False
+                                    ),
+                                ),
+                                (
+                                    "required",
+                                    wagtail.blocks.BooleanBlock(
+                                        label="Required", required=False
+                                    ),
+                                ),
+                                (
+                                    "default_value",
+                                    wagtail.blocks.TextBlock(
+                                        label="Default value", required=False
+                                    ),
+                                ),
+                                (
+                                    "word_limit",
+                                    wagtail.blocks.IntegerBlock(
+                                        default=1000, label="Word limit"
+                                    ),
+                                ),
+                            ],
+                            group="Fields",
+                        ),
+                    ),
+                    (
+                        "number",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "field_label",
+                                    wagtail.blocks.CharBlock(label="Label"),
+                                ),
+                                (
+                                    "help_text",
+                                    wagtail.blocks.TextBlock(
+                                        label="Help text", required=False
+                                    ),
+                                ),
+                                (
+                                    "help_link",
+                                    wagtail.blocks.URLBlock(
+                                        label="Help link", required=False
+                                    ),
+                                ),
+                                (
+                                    "required",
+                                    wagtail.blocks.BooleanBlock(
+                                        label="Required", required=False
+                                    ),
+                                ),
+                                (
+                                    "default_value",
+                                    wagtail.blocks.CharBlock(
+                                        label="Default value", required=False
+                                    ),
+                                ),
+                            ],
+                            group="Fields",
+                        ),
+                    ),
+                    (
+                        "checkbox",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "field_label",
+                                    wagtail.blocks.CharBlock(label="Label"),
+                                ),
+                                (
+                                    "help_text",
+                                    wagtail.blocks.TextBlock(
+                                        label="Help text", required=False
+                                    ),
+                                ),
+                                (
+                                    "help_link",
+                                    wagtail.blocks.URLBlock(
+                                        label="Help link", required=False
+                                    ),
+                                ),
+                                (
+                                    "required",
+                                    wagtail.blocks.BooleanBlock(
+                                        label="Required", required=False
+                                    ),
+                                ),
+                                (
+                                    "default_value",
+                                    wagtail.blocks.BooleanBlock(required=False),
+                                ),
+                            ],
+                            group="Fields",
+                        ),
+                    ),
+                    (
+                        "radios",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "field_label",
+                                    wagtail.blocks.CharBlock(label="Label"),
+                                ),
+                                (
+                                    "help_text",
+                                    wagtail.blocks.TextBlock(
+                                        label="Help text", required=False
+                                    ),
+                                ),
+                                (
+                                    "help_link",
+                                    wagtail.blocks.URLBlock(
+                                        label="Help link", required=False
+                                    ),
+                                ),
+                                (
+                                    "required",
+                                    wagtail.blocks.BooleanBlock(
+                                        label="Required", required=False
+                                    ),
+                                ),
+                                (
+                                    "choices",
+                                    wagtail.blocks.ListBlock(
+                                        wagtail.blocks.CharBlock(label="Choice")
+                                    ),
+                                ),
+                            ],
+                            group="Fields",
+                        ),
+                    ),
+                    (
+                        "dropdown",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "field_label",
+                                    wagtail.blocks.CharBlock(label="Label"),
+                                ),
+                                (
+                                    "help_text",
+                                    wagtail.blocks.TextBlock(
+                                        label="Help text", required=False
+                                    ),
+                                ),
+                                (
+                                    "help_link",
+                                    wagtail.blocks.URLBlock(
+                                        label="Help link", required=False
+                                    ),
+                                ),
+                                (
+                                    "required",
+                                    wagtail.blocks.BooleanBlock(
+                                        label="Required", required=False
+                                    ),
+                                ),
+                                (
+                                    "choices",
+                                    wagtail.blocks.ListBlock(
+                                        wagtail.blocks.CharBlock(label="Choice")
+                                    ),
+                                ),
+                            ],
+                            group="Fields",
+                        ),
+                    ),
+                    (
+                        "checkboxes",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "field_label",
+                                    wagtail.blocks.CharBlock(label="Label"),
+                                ),
+                                (
+                                    "help_text",
+                                    wagtail.blocks.TextBlock(
+                                        label="Help text", required=False
+                                    ),
+                                ),
+                                (
+                                    "help_link",
+                                    wagtail.blocks.URLBlock(
+                                        label="Help link", required=False
+                                    ),
+                                ),
+                                (
+                                    "required",
+                                    wagtail.blocks.BooleanBlock(
+                                        label="Required", required=False
+                                    ),
+                                ),
+                                (
+                                    "checkboxes",
+                                    wagtail.blocks.ListBlock(
+                                        wagtail.blocks.CharBlock(label="Checkbox")
+                                    ),
+                                ),
+                            ],
+                            group="Fields",
+                        ),
+                    ),
+                    (
+                        "date",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "field_label",
+                                    wagtail.blocks.CharBlock(label="Label"),
+                                ),
+                                (
+                                    "help_text",
+                                    wagtail.blocks.TextBlock(
+                                        label="Help text", required=False
+                                    ),
+                                ),
+                                (
+                                    "help_link",
+                                    wagtail.blocks.URLBlock(
+                                        label="Help link", required=False
+                                    ),
+                                ),
+                                (
+                                    "required",
+                                    wagtail.blocks.BooleanBlock(
+                                        label="Required", required=False
+                                    ),
+                                ),
+                                (
+                                    "default_value",
+                                    wagtail.blocks.DateBlock(required=False),
+                                ),
+                            ],
+                            group="Fields",
+                        ),
+                    ),
+                    (
+                        "time",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "field_label",
+                                    wagtail.blocks.CharBlock(label="Label"),
+                                ),
+                                (
+                                    "help_text",
+                                    wagtail.blocks.TextBlock(
+                                        label="Help text", required=False
+                                    ),
+                                ),
+                                (
+                                    "help_link",
+                                    wagtail.blocks.URLBlock(
+                                        label="Help link", required=False
+                                    ),
+                                ),
+                                (
+                                    "required",
+                                    wagtail.blocks.BooleanBlock(
+                                        label="Required", required=False
+                                    ),
+                                ),
+                                (
+                                    "default_value",
+                                    wagtail.blocks.TimeBlock(required=False),
+                                ),
+                            ],
+                            group="Fields",
+                        ),
+                    ),
+                    (
+                        "datetime",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "field_label",
+                                    wagtail.blocks.CharBlock(label="Label"),
+                                ),
+                                (
+                                    "help_text",
+                                    wagtail.blocks.TextBlock(
+                                        label="Help text", required=False
+                                    ),
+                                ),
+                                (
+                                    "help_link",
+                                    wagtail.blocks.URLBlock(
+                                        label="Help link", required=False
+                                    ),
+                                ),
+                                (
+                                    "required",
+                                    wagtail.blocks.BooleanBlock(
+                                        label="Required", required=False
+                                    ),
+                                ),
+                                (
+                                    "default_value",
+                                    wagtail.blocks.DateTimeBlock(required=False),
+                                ),
+                            ],
+                            group="Fields",
+                        ),
+                    ),
+                    (
+                        "image",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "field_label",
+                                    wagtail.blocks.CharBlock(label="Label"),
+                                ),
+                                (
+                                    "help_text",
+                                    wagtail.blocks.TextBlock(
+                                        label="Help text", required=False
+                                    ),
+                                ),
+                                (
+                                    "help_link",
+                                    wagtail.blocks.URLBlock(
+                                        label="Help link", required=False
+                                    ),
+                                ),
+                                (
+                                    "required",
+                                    wagtail.blocks.BooleanBlock(
+                                        label="Required", required=False
+                                    ),
+                                ),
+                            ],
+                            group="Fields",
+                        ),
+                    ),
+                    (
+                        "file",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "field_label",
+                                    wagtail.blocks.CharBlock(label="Label"),
+                                ),
+                                (
+                                    "help_text",
+                                    wagtail.blocks.TextBlock(
+                                        label="Help text", required=False
+                                    ),
+                                ),
+                                (
+                                    "help_link",
+                                    wagtail.blocks.URLBlock(
+                                        label="Help link", required=False
+                                    ),
+                                ),
+                                (
+                                    "required",
+                                    wagtail.blocks.BooleanBlock(
+                                        label="Required", required=False
+                                    ),
+                                ),
+                            ],
+                            group="Fields",
+                        ),
+                    ),
+                    (
+                        "multi_file",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "field_label",
+                                    wagtail.blocks.CharBlock(label="Label"),
+                                ),
+                                (
+                                    "help_text",
+                                    wagtail.blocks.TextBlock(
+                                        label="Help text", required=False
+                                    ),
+                                ),
+                                (
+                                    "help_link",
+                                    wagtail.blocks.URLBlock(
+                                        label="Help link", required=False
+                                    ),
+                                ),
+                                (
+                                    "required",
+                                    wagtail.blocks.BooleanBlock(
+                                        label="Required", required=False
+                                    ),
+                                ),
+                            ],
+                            group="Fields",
+                        ),
+                    ),
+                    (
+                        "group_toggle",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "field_label",
+                                    wagtail.blocks.CharBlock(label="Label"),
+                                ),
+                                (
+                                    "help_text",
+                                    wagtail.blocks.TextBlock(
+                                        label="Help text", required=False
+                                    ),
+                                ),
+                                (
+                                    "help_link",
+                                    wagtail.blocks.URLBlock(
+                                        label="Help link", required=False
+                                    ),
+                                ),
+                                (
+                                    "required",
+                                    wagtail.blocks.BooleanBlock(
+                                        default=True, label="Required", required=False
+                                    ),
+                                ),
+                                (
+                                    "choices",
+                                    wagtail.blocks.ListBlock(
+                                        wagtail.blocks.CharBlock(label="Choice"),
+                                        help_text="Please create only two choices for toggle. First choice will revel the group and the second hide it. Additional choices will be ignored.",
+                                    ),
+                                ),
+                            ],
+                            group="Custom",
+                        ),
+                    ),
+                    (
+                        "group_toggle_end",
+                        hypha.apply.stream_forms.blocks.GroupToggleEndBlock(
+                            group="Custom"
+                        ),
+                    ),
+                    (
+                        "rich_text",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "field_label",
+                                    wagtail.blocks.CharBlock(label="Label"),
+                                ),
+                                (
+                                    "help_text",
+                                    wagtail.blocks.TextBlock(
+                                        label="Help text", required=False
+                                    ),
+                                ),
+                                (
+                                    "help_link",
+                                    wagtail.blocks.URLBlock(
+                                        label="Help link", required=False
+                                    ),
+                                ),
+                                (
+                                    "required",
+                                    wagtail.blocks.BooleanBlock(
+                                        label="Required", required=False
+                                    ),
+                                ),
+                                (
+                                    "default_value",
+                                    wagtail.blocks.TextBlock(
+                                        label="Default value", required=False
+                                    ),
+                                ),
+                                (
+                                    "word_limit",
+                                    wagtail.blocks.IntegerBlock(
+                                        default=1000, label="Word limit"
+                                    ),
+                                ),
+                            ],
+                            group="Fields",
+                        ),
+                    ),
+                    (
+                        "markdown_text",
+                        wagtail.blocks.StructBlock(
+                            [
+                                (
+                                    "field_label",
+                                    wagtail.blocks.CharBlock(label="Label"),
+                                ),
+                                (
+                                    "help_text",
+                                    wagtail.blocks.TextBlock(
+                                        label="Help text", required=False
+                                    ),
+                                ),
+                                (
+                                    "help_link",
+                                    wagtail.blocks.URLBlock(
+                                        label="Help link", required=False
+                                    ),
+                                ),
+                                (
+                                    "required",
+                                    wagtail.blocks.BooleanBlock(
+                                        label="Required", required=False
+                                    ),
+                                ),
+                                (
+                                    "default_value",
+                                    wagtail.blocks.TextBlock(
+                                        label="Default value", required=False
+                                    ),
+                                ),
+                                (
+                                    "word_limit",
+                                    wagtail.blocks.IntegerBlock(
+                                        default=1000, label="Word limit"
+                                    ),
+                                ),
+                            ],
+                            group="Fields",
+                        ),
+                    ),
+                ],
+                default={},
+                use_json_field=True,
+            ),
+            preserve_default=False,
+        ),
+    ]
diff --git a/hypha/apply/projects/models/__init__.py b/hypha/apply/projects/models/__init__.py
index 5e289c2031b104c9a347b36be36a1e3520d10d88..871444e464ef76c88903fc22334302ced6cba99f 100644
--- a/hypha/apply/projects/models/__init__.py
+++ b/hypha/apply/projects/models/__init__.py
@@ -9,6 +9,7 @@ from .project import (
     PAFApprovals,
     Project,
     ProjectApprovalForm,
+    ProjectReportForm,
     ProjectSettings,
     ProjectSOWForm,
 )
@@ -18,6 +19,7 @@ from .vendor import BankInformation, DueDiligenceDocument, Vendor, VendorFormSet
 __all__ = [
     "Project",
     "ProjectApprovalForm",
+    "ProjectReportForm",
     "ProjectSOWForm",
     "ProjectSettings",
     "PAFApprovals",
diff --git a/hypha/apply/projects/models/project.py b/hypha/apply/projects/models/project.py
index 14aae7c1773049e6901f760983942c3085deba90..e7a162b297cebce7b1074b6725eba82136b8443c 100644
--- a/hypha/apply/projects/models/project.py
+++ b/hypha/apply/projects/models/project.py
@@ -30,7 +30,7 @@ from hypha.apply.stream_forms.files import StreamFieldDataEncoder
 from hypha.apply.stream_forms.models import BaseStreamForm
 from hypha.apply.utils.storage import PrivateStorage
 
-from ..blocks import ProjectApprovalFormCustomFormFieldsBlock
+from ..blocks import ProjectFormCustomFormFieldsBlock
 from .vendor import Vendor
 
 logger = logging.getLogger(__name__)
@@ -219,7 +219,7 @@ class Project(BaseStreamForm, AccessFormData, models.Model):
 
     form_data = models.JSONField(encoder=StreamFieldDataEncoder, default=dict)
     form_fields = StreamField(
-        ProjectApprovalFormCustomFormFieldsBlock(), null=True, use_json_field=True
+        ProjectFormCustomFormFieldsBlock(), null=True, use_json_field=True
     )
 
     # tracks read/write state of the Project
@@ -321,7 +321,6 @@ class Project(BaseStreamForm, AccessFormData, models.Model):
         )
         if not first_approved_contract:
             return None
-
         return first_approved_contract.approved_at.date()
 
     @property
@@ -455,15 +454,13 @@ class ProjectSOW(BaseStreamForm, AccessFormData, models.Model):
     )
     form_data = models.JSONField(encoder=StreamFieldDataEncoder, default=dict)
     form_fields = StreamField(
-        ProjectApprovalFormCustomFormFieldsBlock(), null=True, use_json_field=True
+        ProjectFormCustomFormFieldsBlock(), null=True, use_json_field=True
     )
 
 
 class ProjectBaseStreamForm(BaseStreamForm, models.Model):
     name = models.CharField(max_length=255)
-    form_fields = StreamField(
-        ProjectApprovalFormCustomFormFieldsBlock(), use_json_field=True
-    )
+    form_fields = StreamField(ProjectFormCustomFormFieldsBlock(), use_json_field=True)
 
     panels = [
         FieldPanel("name"),
@@ -485,6 +482,17 @@ class ProjectSOWForm(ProjectBaseStreamForm):
     pass
 
 
+class ProjectReportForm(ProjectBaseStreamForm):
+    """
+    An Applicant Report Form can be attached to a Fund to collect reports from Applicants aka Grantees during the
+    Project. It is only relevant for accepted or granted Submissions which is why it is attached to Project. It is
+    similar to the other Forms (PAF, SOW) in that it uses StreamForm to allow maximum flexibility in form creation.
+    See Also ReportVersion where the fields from the form get copied and the response data gets filled in.
+    """
+
+    pass
+
+
 class PAFReviewersRole(Orderable, ClusterableModel):
     label = models.CharField(max_length=200)
     user_roles = ParentalManyToManyField(
diff --git a/hypha/apply/projects/models/report.py b/hypha/apply/projects/models/report.py
index 9467b2f03340857c98add2afc71eaa7253eed4c4..ee6a2d12c26efda2b5b301806a6f55d5059ccab4 100644
--- a/hypha/apply/projects/models/report.py
+++ b/hypha/apply/projects/models/report.py
@@ -12,7 +12,12 @@ from django.urls import reverse
 from django.utils import timezone
 from django.utils.functional import cached_property
 from django.utils.translation import gettext_lazy as _
+from wagtail.fields import StreamField
 
+from hypha.apply.funds.models.mixins import AccessFormData
+from hypha.apply.projects.blocks import ProjectFormCustomFormFieldsBlock
+from hypha.apply.stream_forms.files import StreamFieldDataEncoder
+from hypha.apply.stream_forms.models import BaseStreamForm
 from hypha.apply.utils.storage import PrivateStorage
 
 
@@ -166,13 +171,17 @@ class Report(models.Model):
         return self.project.start_date
 
 
-class ReportVersion(models.Model):
+class ReportVersion(BaseStreamForm, AccessFormData, models.Model):
     report = models.ForeignKey(
         "Report", on_delete=models.CASCADE, related_name="versions"
     )
     submitted = models.DateTimeField()
-    public_content = models.TextField()
-    private_content = models.TextField()
+    form_fields = StreamField(
+        # Re-use the Project Custom Form class. The original fields (used at the time of response) should be required.
+        ProjectFormCustomFormFieldsBlock(),
+        use_json_field=True,
+    )
+    form_data = models.JSONField(encoder=StreamFieldDataEncoder, default=dict)
     draft = models.BooleanField()
     author = models.ForeignKey(
         settings.AUTH_USER_MODEL,
diff --git a/hypha/apply/projects/templates/application_projects/report_detail.html b/hypha/apply/projects/templates/application_projects/report_detail.html
index b0209e7be5fb6dc6b8cd5d92b1e631037eb025a0..10ecebe2cfe87e23e153d407c36566d126d67818 100644
--- a/hypha/apply/projects/templates/application_projects/report_detail.html
+++ b/hypha/apply/projects/templates/application_projects/report_detail.html
@@ -27,14 +27,14 @@
                     <h2>{% trans "Report Skipped" %}</h2>
                 {% else %}
                     <h4>{% trans "Public Report" %}</h4>
-                    <div class="rich-text">
-                        {{ object.current.public_content|nh3|safe }}
+                    <div class="card card--solid">
+                        {% if object.current %}
+                            <div class="simplified__paf_answers">
+                                {{ object.current.output_answers }}
+                            </div>
+                        {% endif %}
                     </div>
 
-                    <h4>{% trans "Private Report" %}</h4>
-                    <div class="rich-text">
-                        {{ object.current.private_content|nh3|safe }}
-                    </div>
                     {% for file in object.current.files.all %}
                         {% if forloop.first %}
                             <h4>{% trans "Attachements" %}</h4>
diff --git a/hypha/apply/projects/templates/application_projects/report_form.html b/hypha/apply/projects/templates/application_projects/report_form.html
index da0de3f82f1d3ad6ce99a888d6edb7211c67b308..d7669e1024a0edce7c17ab2e650e60f691548f55 100644
--- a/hypha/apply/projects/templates/application_projects/report_form.html
+++ b/hypha/apply/projects/templates/application_projects/report_form.html
@@ -35,16 +35,23 @@
 
                 {% for field in form %}
                     {% if field.field %}
-                        {% include "forms/includes/field.html" %}
+                        {% if field.field.multi_input_field %}
+                            {% include "forms/includes/multi_input_field.html" %}
+                        {% else %}
+                            {% include "forms/includes/field.html" %}
+                        {% endif %}
                     {% else %}
-                        {{ field }}
+                        {{ field.block }}
                     {% endif %}
                 {% endfor %}
 
+                {% for hidden_field in form.hidden_fields %}
+                    {{ hidden_field }}
+                {% endfor %}
                 <input type="submit" id="submit-report-form-submit" name="submit" class="is-hidden" />
                 <input type="submit" id="submit-report-form-save" name="save" class="is-hidden" />
-                <button data-fancybox data-src="#save-report" class="button button--submit button--top-space button--white" type="button">{% trans "Save" %}</button>
-                <button data-fancybox data-src="#submit-report" class="button button--primary" type="button">{% trans "Submit" %}</button>
+                <button data-fancybox data-src="#save-report" class="button button--submit button--top-space button--white" type="button">{% trans "Save draft" %}</button>
+                <button data-fancybox data-src="#submit-report" class="button  button--submit button--top-space button--primary" type="button">{% trans "Submit" %}</button>
 
             <!-- Save report modal -->
                 <div class="modal" id="save-report">
@@ -75,4 +82,5 @@
 {% block extra_js %}
     <script src="{% static 'js/jquery.fancybox.min.js' %}"></script>
     <script src="{% static 'js/fancybox-global.js' %}"></script>
+    <script src="{% static 'js/multi-input-fields.js' %}"></script>
 {% endblock %}
diff --git a/hypha/apply/projects/tests/factories.py b/hypha/apply/projects/tests/factories.py
index f65f243f94aba9e193627f6c9c5bb4da42a1f969..8c40c41bfbeccc953cbcf8ca3c76d45472973c49 100644
--- a/hypha/apply/projects/tests/factories.py
+++ b/hypha/apply/projects/tests/factories.py
@@ -8,6 +8,7 @@ from hypha.apply.funds.tests.factories import ApplicationSubmissionFactory
 from hypha.apply.stream_forms.testing.factories import (
     FormDataFactory,
     FormFieldsBlockFactory,
+    NonFileFormFieldsBlockFactory,
 )
 from hypha.apply.users.groups import APPROVER_GROUP_NAME, STAFF_GROUP_NAME
 from hypha.apply.users.tests.factories import GroupFactory, StaffFactory, UserFactory
@@ -24,6 +25,7 @@ from ..models.project import (
     PAFReviewersRole,
     Project,
     ProjectApprovalForm,
+    ProjectReportForm,
     ProjectSOWForm,
 )
 from ..models.report import Report, ReportConfig, ReportVersion
@@ -84,6 +86,14 @@ class ProjectApprovalFormDataFactory(FormDataFactory):
     field_factory = FormFieldsBlockFactory
 
 
+class ProjectReportFormFactory(factory.django.DjangoModelFactory):
+    class Meta:
+        model = ProjectReportForm
+
+    name = factory.Faker("word")
+    form_fields = FormFieldsBlockFactory
+
+
 class ProjectFactory(factory.django.DjangoModelFactory):
     submission = factory.SubFactory(ApplicationSubmissionFactory)
     user = factory.SubFactory(UserFactory)
@@ -200,11 +210,19 @@ class ReportConfigFactory(factory.django.DjangoModelFactory):
         )
 
 
+class ReportVersionDataFactory(FormDataFactory):
+    field_factory = NonFileFormFieldsBlockFactory
+
+
 class ReportVersionFactory(factory.django.DjangoModelFactory):
     report = factory.SubFactory("hypha.apply.projects.tests.factories.ReportFactory")
     submitted = factory.LazyFunction(timezone.now)
-    public_content = factory.Faker("paragraph")
-    private_content = factory.Faker("paragraph")
+    form_fields = NonFileFormFieldsBlockFactory
+    # TODO: is it better to keep the following link between form_data and form_fields or to remove it?
+    form_data = factory.SubFactory(
+        ReportVersionDataFactory,
+        form_fields=factory.SelfAttribute("..form_fields"),
+    )
     draft = True
 
     class Meta:
diff --git a/hypha/apply/projects/tests/test_views.py b/hypha/apply/projects/tests/test_views.py
index 7e2b462c7fe54c51d6ae50687a215d82edcaf2f0..429e71e19ef1e6a09fce14ca9cf836bb14e420ea 100644
--- a/hypha/apply/projects/tests/test_views.py
+++ b/hypha/apply/projects/tests/test_views.py
@@ -1,6 +1,7 @@
 import json
 from io import BytesIO
 
+import factory
 from dateutil.relativedelta import relativedelta
 from django.conf import settings
 from django.contrib.auth.models import AnonymousUser
@@ -23,6 +24,7 @@ from hypha.apply.users.tests.factories import (
 from hypha.apply.utils.testing.tests import BaseViewTestCase
 from hypha.home.factories import ApplySiteFactory
 
+from ...funds.models.forms import ApplicationBaseProjectReportForm
 from ..files import get_files
 from ..forms import SetPendingForm
 from ..models.payment import CHANGES_REQUESTED_BY_STAFF, SUBMITTED
@@ -35,6 +37,7 @@ from ..models.project import (
     INTERNAL_APPROVAL,
     INVOICING_AND_REPORTING,
     REQUEST_CHANGE,
+    ProjectReportForm,
     ProjectSettings,
 )
 from ..views.project import ContractsMixin, ProjectDetailApprovalView
@@ -51,6 +54,20 @@ from .factories import (
     SupportingDocumentFactory,
 )
 
+# A boilerplate stream form for Project Report tests below.
+FORM_FIELDS = [
+    {
+        "id": "012a4f29-0882-4b1c-b567-aede1b601d4a",
+        "type": "number",
+        "value": {
+            "required": True,
+            "help_text": "",
+            "field_label": "How many folks did you reach?",
+            "default_value": "",
+        },
+    }
+]
+
 
 class TestUpdateLeadView(BaseViewTestCase):
     base_view_name = "detail"
@@ -1189,6 +1206,15 @@ class TestStaffSubmitReport(BaseViewTestCase):
     base_view_name = "edit"
     url_name = "funds:projects:reports:{}"
     user_factory = StaffFactory
+    report_form_id = None
+
+    def setUp(self):
+        super().setUp()
+        report_form, _ = ProjectReportForm.objects.get_or_create(
+            name=factory.Faker("word"),
+            form_fields=FORM_FIELDS,
+        )
+        self.report_form_id = report_form.id
 
     def get_kwargs(self, instance):
         return {
@@ -1197,11 +1223,19 @@ class TestStaffSubmitReport(BaseViewTestCase):
 
     def test_get_page_for_inprogress_project(self):
         report = ReportFactory(project__status=INVOICING_AND_REPORTING)
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
         response = self.get_page(report)
         self.assertContains(response, report.project.title)
 
     def test_cant_get_page_for_closing_and_complete_project(self):
         report = ReportFactory(project__status=CLOSING)
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
         response = self.get_page(report)
         self.assertEqual(response.status_code, 403)
 
@@ -1211,39 +1245,72 @@ class TestStaffSubmitReport(BaseViewTestCase):
 
     def test_submit_report(self):
         report = ReportFactory(project__status=INVOICING_AND_REPORTING)
-        response = self.post_page(report, {"public_content": "Some text"})
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
+        response = self.post_page(
+            report, {"012a4f29-0882-4b1c-b567-aede1b601d4a": "11"}
+        )
         report.refresh_from_db()
         self.assertRedirects(
             response, self.absolute_url(report.project.get_absolute_url())
         )
-        self.assertEqual(report.versions.first().public_content, "Some text")
+        self.assertEqual(
+            report.versions.first().form_data,
+            {"012a4f29-0882-4b1c-b567-aede1b601d4a": "11"},
+        )
         self.assertEqual(report.versions.first(), report.current)
         self.assertEqual(report.current.author, self.user)
         self.assertIsNone(report.draft)
 
     def test_cant_submit_report_for_closing_and_complete_project(self):
         report = ReportFactory(project__status=CLOSING)
-        response = self.post_page(report, {"public_content": "Some text"})
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
+        response = self.post_page(
+            report, {"012a4f29-0882-4b1c-b567-aede1b601d4a": "13"}
+        )
         self.assertEqual(response.status_code, 403)
 
         report = ReportFactory(project__status=COMPLETE)
-        response = self.post_page(report, {"public_content": "Some text"})
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
+        response = self.post_page(
+            report, {"012a4f29-0882-4b1c-b567-aede1b601d4a": "13"}
+        )
         self.assertEqual(response.status_code, 403)
 
     def test_submit_private_report(self):
         report = ReportFactory(project__status=INVOICING_AND_REPORTING)
-        response = self.post_page(report, {"private_content": "Some text"})
+        # Link the single-field report_form to the Fund associated with this Submission.
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
+        response = self.post_page(
+            report, {"012a4f29-0882-4b1c-b567-aede1b601d4a": "17"}
+        )
         report.refresh_from_db()
-        self.assertRedirects(
-            response, self.absolute_url(report.project.get_absolute_url())
+        self.assertEquals(response.status_code, 200)
+        self.assertEqual(
+            report.versions.first().form_data,
+            {"012a4f29-0882-4b1c-b567-aede1b601d4a": "17"},
         )
-        self.assertEqual(report.versions.first().private_content, "Some text")
         self.assertEqual(report.versions.first(), report.current)
         self.assertEqual(report.current.author, self.user)
         self.assertIsNone(report.draft)
 
     def test_cant_submit_blank_report(self):
         report = ReportFactory(project__status=INVOICING_AND_REPORTING)
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
         response = self.post_page(report, {})
         report.refresh_from_db()
         self.assertEqual(response.status_code, 200)
@@ -1251,62 +1318,94 @@ class TestStaffSubmitReport(BaseViewTestCase):
 
     def test_save_report_draft(self):
         report = ReportFactory(project__status=INVOICING_AND_REPORTING)
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
         response = self.post_page(
-            report, {"public_content": "Some text", "save": "Save"}
+            report, {"012a4f29-0882-4b1c-b567-aede1b601d4a": "19", "save": "Save"}
         )
         report.refresh_from_db()
-        self.assertRedirects(
-            response, self.absolute_url(report.project.get_absolute_url())
+        self.assertEquals(response.status_code, 200)
+        self.assertEqual(
+            report.versions.first().form_data,
+            {"012a4f29-0882-4b1c-b567-aede1b601d4a": "19"},
         )
-        self.assertEqual(report.versions.first().public_content, "Some text")
         self.assertEqual(report.versions.first(), report.draft)
         self.assertIsNone(report.current)
 
     def test_save_report_with_draft(self):
         report = ReportFactory(is_draft=True, project__status=INVOICING_AND_REPORTING)
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
         self.assertEqual(report.versions.first(), report.draft)
-        response = self.post_page(report, {"public_content": "Some text"})
+        response = self.post_page(
+            report, {"012a4f29-0882-4b1c-b567-aede1b601d4a": "23"}
+        )
         report.refresh_from_db()
-        self.assertRedirects(
-            response, self.absolute_url(report.project.get_absolute_url())
+        self.assertEquals(response.status_code, 200)
+        self.assertEqual(
+            report.versions.last().form_data,
+            {"012a4f29-0882-4b1c-b567-aede1b601d4a": "23"},
         )
-        self.assertEqual(report.versions.last().public_content, "Some text")
         self.assertEqual(report.versions.last(), report.current)
         self.assertIsNone(report.draft)
 
     def test_edit_submitted_report(self):
         report = ReportFactory(
-            is_submitted=True, project__status=INVOICING_AND_REPORTING
+            is_submitted=True,
+            project__status=INVOICING_AND_REPORTING,
+            version__form_fields=json.dumps(FORM_FIELDS),
+        )
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
         )
         self.assertEqual(report.versions.first(), report.current)
         response = self.post_page(
-            report, {"public_content": "Some text", "save": " Save"}
+            report, {"012a4f29-0882-4b1c-b567-aede1b601d4a": "29", "save": " Save"}
         )
         report.refresh_from_db()
         self.assertRedirects(
             response, self.absolute_url(report.project.get_absolute_url())
         )
-        self.assertEqual(report.versions.last().public_content, "Some text")
+        self.assertEqual(
+            report.versions.last().form_data["012a4f29-0882-4b1c-b567-aede1b601d4a"],
+            "29",
+        )
         self.assertEqual(report.versions.last(), report.draft)
         self.assertEqual(report.versions.first(), report.current)
 
     def test_resubmit_submitted_report(self):
         yesterday = timezone.now() - relativedelta(days=1)
         version = ReportVersionFactory(
-            report__project__status=INVOICING_AND_REPORTING, submitted=yesterday
+            report__project__status=INVOICING_AND_REPORTING,
+            submitted=yesterday,
+            form_fields=json.dumps(FORM_FIELDS),
         )
         report = version.report
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
         report.current = version
         report.submitted = version.submitted
         report.save()
         self.assertEqual(report.submitted, yesterday)
         self.assertEqual(report.versions.first(), report.current)
-        response = self.post_page(report, {"public_content": "Some text"})
+        response = self.post_page(
+            report, {"012a4f29-0882-4b1c-b567-aede1b601d4a": "31"}
+        )
         report.refresh_from_db()
         self.assertRedirects(
             response, self.absolute_url(report.project.get_absolute_url())
         )
-        self.assertEqual(report.versions.last().public_content, "Some text")
+        self.assertEqual(
+            report.versions.last().form_data,
+            {"012a4f29-0882-4b1c-b567-aede1b601d4a": "31"},
+        )
         self.assertEqual(report.versions.last(), report.current)
         self.assertIsNone(report.draft)
         self.assertEqual(report.submitted.date(), yesterday.date())
@@ -1318,11 +1417,17 @@ class TestStaffSubmitReport(BaseViewTestCase):
             is_submitted=True,
             project__status=INVOICING_AND_REPORTING,
         )
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=submitted_report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
         future_report = ReportFactory(
             end_date=timezone.now() + relativedelta(days=3),
             project=submitted_report.project,
         )
-        response = self.post_page(future_report, {"public_content": "Some text"})
+        response = self.post_page(
+            future_report, {"012a4f29-0882-4b1c-b567-aede1b601d4a": "37"}
+        )
         self.assertEqual(response.status_code, 403)
 
 
@@ -1330,6 +1435,15 @@ class TestApplicantSubmitReport(BaseViewTestCase):
     base_view_name = "edit"
     url_name = "funds:projects:reports:{}"
     user_factory = ApplicantFactory
+    report_form_id = None
+
+    def setUp(self):
+        super().setUp()
+        report_form, _ = ProjectReportForm.objects.get_or_create(
+            name=factory.Faker("word"),
+            form_fields=FORM_FIELDS,
+        )
+        self.report_form_id = report_form.id
 
     def get_kwargs(self, instance):
         return {
@@ -1340,20 +1454,36 @@ class TestApplicantSubmitReport(BaseViewTestCase):
         report = ReportFactory(
             project__status=INVOICING_AND_REPORTING, project__user=self.user
         )
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
         response = self.get_page(report)
         self.assertContains(response, report.project.title)
 
     def test_cant_get_own_report_for_closing_and_complete_project(self):
         report = ReportFactory(project__status=CLOSING, project__user=self.user)
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
         response = self.get_page(report)
         self.assertEqual(response.status_code, 403)
 
         report = ReportFactory(project__status=COMPLETE, project__user=self.user)
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
         response = self.get_page(report)
         self.assertEqual(response.status_code, 403)
 
     def test_cant_get_other_report(self):
         report = ReportFactory(project__status=INVOICING_AND_REPORTING)
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
         response = self.get_page(report)
         self.assertEqual(response.status_code, 403)
 
@@ -1361,12 +1491,21 @@ class TestApplicantSubmitReport(BaseViewTestCase):
         report = ReportFactory(
             project__status=INVOICING_AND_REPORTING, project__user=self.user
         )
-        response = self.post_page(report, {"public_content": "Some text"})
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
+        response = self.post_page(
+            report, {"012a4f29-0882-4b1c-b567-aede1b601d4a": "37"}
+        )
         report.refresh_from_db()
         self.assertRedirects(
             response, self.absolute_url(report.project.get_absolute_url())
         )
-        self.assertEqual(report.versions.first().public_content, "Some text")
+        self.assertEqual(
+            report.versions.first().form_data,
+            {"012a4f29-0882-4b1c-b567-aede1b601d4a": "37"},
+        )
         self.assertEqual(report.versions.first(), report.current)
         self.assertEqual(report.current.author, self.user)
 
@@ -1374,12 +1513,19 @@ class TestApplicantSubmitReport(BaseViewTestCase):
         report = ReportFactory(
             project__status=INVOICING_AND_REPORTING, project__user=self.user
         )
-        response = self.post_page(report, {"private_content": "Some text"})
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
+        response = self.post_page(
+            report, {"012a4f29-0882-4b1c-b567-aede1b601d4a": "41"}
+        )
         report.refresh_from_db()
-        self.assertRedirects(
-            response, self.absolute_url(report.project.get_absolute_url())
+        self.assertEquals(response.status_code, 200)
+        self.assertEqual(
+            report.versions.first().form_data,
+            {"012a4f29-0882-4b1c-b567-aede1b601d4a": "41"},
         )
-        self.assertEqual(report.versions.first().private_content, "Some text")
         self.assertEqual(report.versions.first(), report.current)
         self.assertEqual(report.current.author, self.user)
         self.assertIsNone(report.draft)
@@ -1388,6 +1534,10 @@ class TestApplicantSubmitReport(BaseViewTestCase):
         report = ReportFactory(
             project__status=INVOICING_AND_REPORTING, project__user=self.user
         )
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
         response = self.post_page(report, {})
         report.refresh_from_db()
         self.assertEqual(response.status_code, 200)
@@ -1397,14 +1547,21 @@ class TestApplicantSubmitReport(BaseViewTestCase):
         report = ReportFactory(
             project__status=INVOICING_AND_REPORTING, project__user=self.user
         )
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
         response = self.post_page(
-            report, {"public_content": "Some text", "save": "Save"}
+            report, {"012a4f29-0882-4b1c-b567-aede1b601d4a": "43", "save": "Save"}
         )
         report.refresh_from_db()
         self.assertRedirects(
             response, self.absolute_url(report.project.get_absolute_url())
         )
-        self.assertEqual(report.versions.first().public_content, "Some text")
+        self.assertEqual(
+            report.versions.first().form_data,
+            {"012a4f29-0882-4b1c-b567-aede1b601d4a": "43"},
+        )
         self.assertEqual(report.versions.first(), report.draft)
         self.assertIsNone(report.current)
 
@@ -1414,13 +1571,22 @@ class TestApplicantSubmitReport(BaseViewTestCase):
             is_draft=True,
             project__user=self.user,
         )
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
         self.assertEqual(report.versions.first(), report.draft)
-        response = self.post_page(report, {"public_content": "Some text"})
+        response = self.post_page(
+            report, {"012a4f29-0882-4b1c-b567-aede1b601d4a": "47"}
+        )
         report.refresh_from_db()
         self.assertRedirects(
             response, self.absolute_url(report.project.get_absolute_url())
         )
-        self.assertEqual(report.versions.last().public_content, "Some text")
+        self.assertEqual(
+            report.versions.last().form_data,
+            {"012a4f29-0882-4b1c-b567-aede1b601d4a": "47"},
+        )
         self.assertEqual(report.versions.last(), report.current)
         self.assertIsNone(report.draft)
 
@@ -1431,6 +1597,10 @@ class TestApplicantSubmitReport(BaseViewTestCase):
             is_submitted=True,
             project__user=self.user,
         )
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
         self.assertEqual(report.versions.first(), report.current)
         response = self.post_page(
             report, {"public_content": "Some text", "save": " Save"}
@@ -1439,7 +1609,13 @@ class TestApplicantSubmitReport(BaseViewTestCase):
 
     def test_cant_submit_other_report(self):
         report = ReportFactory(project__status=INVOICING_AND_REPORTING)
-        response = self.post_page(report, {"public_content": "Some text"})
+        ApplicationBaseProjectReportForm.objects.get_or_create(
+            application_id=report.project.submission.page.specific.id,
+            form_id=self.report_form_id,
+        )
+        response = self.post_page(
+            report, {"012a4f29-0882-4b1c-b567-aede1b601d4a": "53"}
+        )
         self.assertEqual(response.status_code, 403)
 
 
diff --git a/hypha/apply/projects/urls.py b/hypha/apply/projects/urls.py
index a3d80e397e6137ab6028bd1732598673ba497851..88601a80cd21138aa2849c0cc01ab060e393d6e3 100644
--- a/hypha/apply/projects/urls.py
+++ b/hypha/apply/projects/urls.py
@@ -54,7 +54,12 @@ urlpatterns = [
                 ),
                 path("edit/", ProjectApprovalFormEditView.as_view(), name="edit"),
                 path(
-                    "documents/<int:file_pk>/",
+                    "documents/<int:file_pk>",
+                    ProjectPrivateMediaView.as_view(),
+                    name="document",
+                ),
+                path(
+                    "documents/<uuid:field_id>/<str:file_name>",
                     ProjectPrivateMediaView.as_view(),
                     name="document",
                 ),
diff --git a/hypha/apply/projects/utils.py b/hypha/apply/projects/utils.py
index 5a07ecb82e516215b13f8b156d9bea8f6ab9f11d..ea06cc42766f55fca2c49548428b43295b960aac 100644
--- a/hypha/apply/projects/utils.py
+++ b/hypha/apply/projects/utils.py
@@ -1,5 +1,6 @@
 from django.conf import settings
 from django.utils.translation import gettext_lazy as _
+from django_file_form.uploaded_file import PlaceholderUploadedFile
 
 from .constants import (
     INT_DECLINED,
@@ -190,3 +191,14 @@ def get_invoice_table_status(invoice_status, is_applicant=False):
         return INT_DECLINED
     if invoice_status == PAYMENT_FAILED:
         return INT_PAYMENT_FAILED
+
+
+def get_placeholder_file(initial_file):
+    if not isinstance(initial_file, list):
+        return PlaceholderUploadedFile(
+            initial_file.filename, size=initial_file.size, file_id=initial_file.name
+        )
+    return [
+        PlaceholderUploadedFile(f.filename, size=f.size, file_id=f.name)
+        for f in initial_file
+    ]
diff --git a/hypha/apply/projects/views/project.py b/hypha/apply/projects/views/project.py
index 2ab814bae1afe34cd2d56781eb3a3960848947a4..f65848aa10690d5587c49a7e5bd6c1cb7b3e6c37 100644
--- a/hypha/apply/projects/views/project.py
+++ b/hypha/apply/projects/views/project.py
@@ -1,6 +1,6 @@
+import copy
 import datetime
 import io
-from copy import copy
 
 from django.conf import settings
 from django.contrib import messages
@@ -29,7 +29,6 @@ from django.views.generic import (
     UpdateView,
 )
 from django.views.generic.detail import SingleObjectMixin
-from django_file_form.models import PlaceholderUploadedFile
 from django_filters.views import FilterView
 from django_tables2 import SingleTableMixin
 from docx import Document
@@ -67,6 +66,7 @@ from hypha.apply.utils.models import PDFPageSettings
 from hypha.apply.utils.storage import PrivateMediaView
 from hypha.apply.utils.views import DelegateableView, DelegatedViewMixin, ViewDispatcher
 
+from ...funds.files import generate_private_file_path
 from ..files import get_files
 from ..filters import InvoiceListFilter, ProjectListFilter, ReportListFilter
 from ..forms import (
@@ -110,7 +110,7 @@ from ..models.project import (
 from ..models.report import Report
 from ..permissions import has_permission
 from ..tables import InvoiceListTable, ProjectsListTable, ReportListTable
-from ..utils import get_paf_status_display
+from ..utils import get_paf_status_display, get_placeholder_file
 from ..views.payment import ChangeInvoiceStatusView
 from .report import ReportFrequencyUpdate, ReportingMixin
 
@@ -371,7 +371,7 @@ class UpdateLeadView(DelegatedViewMixin, UpdateView):
 
     def form_valid(self, form):
         # Fetch the old lead from the database
-        old_lead = copy(self.get_object().lead)
+        old_lead = copy.copy(self.get_object().lead)
 
         response = super().form_valid(form)
         project = form.instance
@@ -1315,6 +1315,10 @@ class ProjectDetailView(ViewDispatcher):
 
 @method_decorator(login_required, name="dispatch")
 class ProjectPrivateMediaView(UserPassesTestMixin, PrivateMediaView):
+    """
+    See also hypha/apply/funds/files.py
+    """
+
     raise_exception = True
 
     def dispatch(self, *args, **kwargs):
@@ -1323,10 +1327,18 @@ class ProjectPrivateMediaView(UserPassesTestMixin, PrivateMediaView):
         return super().dispatch(*args, **kwargs)
 
     def get_media(self, *args, **kwargs):
-        document = PacketFile.objects.get(pk=kwargs["file_pk"])
-        if document.project != self.project:
-            raise Http404
-        return document.document
+        if "file_pk" in kwargs:
+            document = PacketFile.objects.get(pk=kwargs["file_pk"])
+            if document.project != self.project:
+                raise Http404
+            return document.document
+        else:
+            field_id = kwargs["field_id"]
+            file_name = kwargs["file_name"]
+            path_to_file = generate_private_file_path(
+                self.project.pk, field_id, file_name, path_start="project"
+            )
+            return self.storage.open(path_to_file)
 
     def test_func(self):
         if self.request.user.is_apply_staff:
@@ -1765,22 +1777,10 @@ class ProjectApprovalFormEditView(BaseStreamForm, UpdateView):
         initial = self.object.raw_data
         for field_id in self.object.file_field_ids:
             initial.pop(field_id + "-uploads", False)
-            initial[field_id] = self.get_placeholder_file(
-                self.object.raw_data.get(field_id)
-            )
+            initial[field_id] = get_placeholder_file(self.object.raw_data.get(field_id))
         kwargs["initial"].update(initial)
         return kwargs
 
-    def get_placeholder_file(self, initial_file):
-        if not isinstance(initial_file, list):
-            return PlaceholderUploadedFile(
-                initial_file.filename, size=initial_file.size, file_id=initial_file.name
-            )
-        return [
-            PlaceholderUploadedFile(f.filename, size=f.size, file_id=f.name)
-            for f in initial_file
-        ]
-
     def get_sow_form_kwargs(self):
         kwargs = super().get_form_kwargs()
         if self.approval_sow_form:
@@ -1792,7 +1792,7 @@ class ProjectApprovalFormEditView(BaseStreamForm, UpdateView):
                 initial = sow_instance.raw_data
                 for field_id in sow_instance.file_field_ids:
                     initial.pop(field_id + "-uploads", False)
-                    initial[field_id] = self.get_placeholder_file(
+                    initial[field_id] = get_placeholder_file(
                         sow_instance.raw_data.get(field_id)
                     )
                 initial["project"] = self.object
diff --git a/hypha/apply/projects/views/report.py b/hypha/apply/projects/views/report.py
index f34341b1eedb577bdfba3b4d2f71727f2f341f3b..71d0f475763cac5436c0c9d5db529ccd86728e26 100644
--- a/hypha/apply/projects/views/report.py
+++ b/hypha/apply/projects/views/report.py
@@ -1,5 +1,6 @@
 from django.contrib.auth.decorators import login_required
 from django.contrib.auth.mixins import UserPassesTestMixin
+from django.http import HttpResponseRedirect
 from django.shortcuts import get_object_or_404, redirect
 from django.utils.decorators import method_decorator
 from django.views import View
@@ -13,11 +14,13 @@ from hypha.apply.users.decorators import staff_or_finance_required, staff_requir
 from hypha.apply.utils.storage import PrivateMediaView
 from hypha.apply.utils.views import DelegatedViewMixin
 
+from ...stream_forms.models import BaseStreamForm
 from ..filters import ReportListFilter
 from ..forms import ReportEditForm, ReportFrequencyForm
 from ..models import Report, ReportConfig, ReportPrivateFiles
 from ..permissions import has_permission
 from ..tables import ReportListTable
+from ..utils import get_placeholder_file
 
 
 class ReportingMixin:
@@ -60,40 +63,109 @@ class ReportDetailView(DetailView):
 
 
 @method_decorator(login_required, name="dispatch")
-class ReportUpdateView(UpdateView):
-    form_class = ReportEditForm
+class ReportUpdateView(BaseStreamForm, UpdateView):
     model = Report
+    # Values for `object`, `form_class`, and `form_fields` are set during `dispatch` and functions it calls.
+    object = None
+    form_class = None
+    form_fields = None
+
+    def get_form_class(self, draft=False, form_data=None, user=None):
+        """
+        Expects self.form_fields to have already been set.
+        """
+        if not self.form_fields:
+            raise RuntimeError("Expected self.form_fields to be 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
 
-    def dispatch(self, *args, **kwargs):
+    def dispatch(self, request, *args, **kwargs):
         report = self.get_object()
         permission, _ = has_permission(
             "report_update", self.request.user, object=report, raise_exception=True
         )
-        return super().dispatch(*args, **kwargs)
+        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)
+
+    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,
+            **kwargs,
+        }
+        return context_data
+
+    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
 
     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:
-            return {
-                "public_content": current.public_content,
-                "private_content": current.private_content,
-                "file_list": current.files.all(),
-            }
+            # The following allows existing data to populate the form. This code was inspired by (aka copied from)
+            # ProjectApprovalFormEditView.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 {}
+        return initial
 
     def get_form_kwargs(self):
-        return {
+        form_kwargs = {
             "user": self.request.user,
             **super().get_form_kwargs(),
         }
+        return form_kwargs
+
+    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
 
     def get_success_url(self):
-        return self.object.project.get_absolute_url()
+        success_url = self.object.project.get_absolute_url()
+        return success_url
 
     def form_valid(self, form):
         response = super().form_valid(form)
diff --git a/hypha/apply/stream_forms/testing/factories.py b/hypha/apply/stream_forms/testing/factories.py
index 3c23d0bcc671db664ceae8c80ad9a2e608047e3b..9b30e4f1fa145be6ccab6629d2a4c9ddbf343f73 100644
--- a/hypha/apply/stream_forms/testing/factories.py
+++ b/hypha/apply/stream_forms/testing/factories.py
@@ -318,7 +318,7 @@ class StreamFieldUUIDFactory(wagtail_factories.StreamFieldFactory):
         return flatten_for_form(data)
 
 
-BLOCK_FACTORY_DEFINITION = {
+NON_FILE_BLOCK_FACTORY_DEFINITION = {
     "text_markup": ParagraphBlockFactory,
     "char": CharFieldBlockFactory,
     "text": TextFieldBlockFactory,
@@ -330,11 +330,20 @@ BLOCK_FACTORY_DEFINITION = {
     "date": DateFieldBlockFactory,
     "time": TimeFieldBlockFactory,
     "datetime": DateTimeFieldBlockFactory,
+}
+
+BLOCK_FACTORY_DEFINITION = {
+    **NON_FILE_BLOCK_FACTORY_DEFINITION,
     "image": ImageFieldBlockFactory,
     "file": FileFieldBlockFactory,
     "multi_file": MultiFileFieldBlockFactory,
 }
 
+# There are two here, because some tests will fail due to JSON serialization errors
+# if SimpleUploadedFile is included in the factory (most notably Project ReportVersion tests)
+NonFileFormFieldsBlockFactory = StreamFieldUUIDFactory(
+    NON_FILE_BLOCK_FACTORY_DEFINITION
+)
 FormFieldsBlockFactory = StreamFieldUUIDFactory(BLOCK_FACTORY_DEFINITION)