diff --git a/opentech/apply/projects/models.py b/opentech/apply/projects/models.py
index 36388f8742c78a3fd296949dfca5dff5e0be5b44..b99e4a0e41b60add16948c50bbd9308889174b96 100644
--- a/opentech/apply/projects/models.py
+++ b/opentech/apply/projects/models.py
@@ -641,6 +641,9 @@ class Report(models.Model):
     class Meta:
         ordering = ('-end_date',)
 
+    def get_absolute_url(self):
+        return reverse('apply:projects:reports:detail', kwargs={'pk': self.pk})
+
     @property
     def past_due(self):
         return timezone.now().date() > self.end_date
@@ -694,3 +697,6 @@ class ReportPrivateFiles(models.Model):
 
     def __str__(self):
         return self.filename
+
+    def get_absolute_url(self):
+        return reverse('apply:projects:reports:document', kwargs={'pk': self.report.report_id, 'file_pk': self.pk})
diff --git a/opentech/apply/projects/templates/application_projects/includes/reports.html b/opentech/apply/projects/templates/application_projects/includes/reports.html
index 81d83f5c25fcffb327ef0358c95d69e23242d542..ae2af06007938b28b828a24b2273d1b8aaf2def1 100644
--- a/opentech/apply/projects/templates/application_projects/includes/reports.html
+++ b/opentech/apply/projects/templates/application_projects/includes/reports.html
@@ -36,6 +36,7 @@
                     {% if request.user.is_apply_staff %}
                         <a href="{% url "apply:projects:reports:edit" pk=report.pk %}">edit</a>
                     {% endif %}
+                    <a href="{% url "apply:projects:reports:detail" pk=report.pk %}">view</a>
                 </td>
             </tr>
             {% empty %}
diff --git a/opentech/apply/projects/templates/application_projects/report_detail.html b/opentech/apply/projects/templates/application_projects/report_detail.html
new file mode 100644
index 0000000000000000000000000000000000000000..249c07e8cf668de7372e7dda07039cfcb057daf4
--- /dev/null
+++ b/opentech/apply/projects/templates/application_projects/report_detail.html
@@ -0,0 +1,40 @@
+{% extends "base-apply.html" %}
+{% load static bleach_tags %}
+
+{% block title %}Report | {{ object.project.title }}{% endblock %}
+{% block content %}
+<div class="admin-bar">
+    <div class="admin-bar__inner">
+        <a class="admin-bar__back-link" href="{{ object.project.get_absolute_url }}">
+            Project
+        </a>
+        <h2 class="heading heading--no-margin">Report for the period {{ report.start_date }} to {{ report.end_date }}</h2>
+        <h5 class="heading heading--no-margin">{{ object.project.title }}</h5>
+    </div>
+</div>
+
+<div class="wrapper wrapper--light-grey-bg wrapper--form wrapper--sidebar">
+    <div class="wrapper--sidebar--inner">
+        <h3>
+            {% if object.public %}
+                Public
+            {% else %}
+                Private
+            {% endif %}
+        </h3>
+        {{ object.current.content|bleach|safe }}
+        {% for file in object.current.files.all %}
+            {% if forloop.first %}
+                <h4>Files</h4>
+                <ul>
+            {% endif %}
+
+            <li><a href="{{ file.get_absolute_url }}">{{ file.filename }}</a></li>
+
+            {% if forloop.last %}
+                </ul>
+            {% endif %}
+        {% endfor %}
+    </div>
+</div>
+{% endblock %}
diff --git a/opentech/apply/projects/templates/application_projects/report_form.html b/opentech/apply/projects/templates/application_projects/report_form.html
index 72add7fbde5d671ee6d6e25fc96d420d040cb283..3296a547ab57f663cd8b0f1a13c84f10f3fd1f95 100644
--- a/opentech/apply/projects/templates/application_projects/report_form.html
+++ b/opentech/apply/projects/templates/application_projects/report_form.html
@@ -1,14 +1,14 @@
 {% extends "base-apply.html" %}
 {% load static %}
 
-{% block title %}Report | {{ object.project.title }}{% endblock %}
+{% block title %}Edit Report | {{ object.project.title }}{% endblock %}
 {% block content %}
 <div class="admin-bar">
     <div class="admin-bar__inner">
         <a class="admin-bar__back-link" href="{{ object.project.get_absolute_url }}">
             Project
         </a>
-        <h2 class="heading heading--no-margin">Report for the period ending {{ report.end_date }}</h2>
+        <h2 class="heading heading--no-margin">Report for the period {{ report.start_date }} to {{ report.end_date }}</h2>
         <h5 class="heading heading--no-margin">{{ object.project.title }}</h5>
     </div>
 </div>
diff --git a/opentech/apply/projects/tests/test_views.py b/opentech/apply/projects/tests/test_views.py
index ff727e84d8582d3e33ae93d17b665c9845a490fb..c7e09c139ad4882b91b2956a0a316db8c94e76e2 100644
--- a/opentech/apply/projects/tests/test_views.py
+++ b/opentech/apply/projects/tests/test_views.py
@@ -1407,3 +1407,70 @@ class TestApplicantSubmitReport(BaseViewTestCase):
         report = ReportFactory()
         response = self.post_page(report, {'content': 'Some text', 'public': True})
         self.assertEqual(response.status_code, 403)
+
+
+class TestStaffReportDetail(BaseViewTestCase):
+    base_view_name = 'detail'
+    url_name = 'funds:projects:reports:{}'
+    user_factory = StaffFactory
+
+    def get_kwargs(self, instance):
+        return {
+            'pk': instance.pk,
+        }
+
+    def test_can_access_submitted_report(self):
+        report = ReportFactory(is_submitted=True)
+        response = self.get_page(report)
+        self.assertEqual(response.status_code, 200)
+
+    def test_cant_access_draft_report(self):
+        report = ReportFactory(is_draft=True)
+        response = self.get_page(report)
+        self.assertEqual(response.status_code, 404)
+
+    def test_cant_access_future_report(self):
+        report = ReportFactory(end_date=timezone.now() + relativedelta(days=1))
+        response = self.get_page(report)
+        self.assertEqual(response.status_code, 404)
+
+
+class TestApplicantReportDetail(BaseViewTestCase):
+    base_view_name = 'detail'
+    url_name = 'funds:projects:reports:{}'
+    user_factory = StaffFactory
+
+    def get_kwargs(self, instance):
+        return {
+            'pk': instance.pk,
+        }
+
+    def test_can_access_own_submitted_report(self):
+        report = ReportFactory(is_submitted=True, project__user=self.user)
+        response = self.get_page(report)
+        self.assertEqual(response.status_code, 200)
+
+    def test_cant_access_own_draft_report(self):
+        report = ReportFactory(is_draft=True, project__user=self.user)
+        response = self.get_page(report)
+        self.assertEqual(response.status_code, 404)
+
+    def test_cant_access_own_future_report(self):
+        report = ReportFactory(end_date=timezone.now() + relativedelta(days=1), project__user=self.user)
+        response = self.get_page(report)
+        self.assertEqual(response.status_code, 404)
+
+    def test_cant_access_other_submitted_report(self):
+        report = ReportFactory(is_submitted=True)
+        response = self.get_page(report)
+        self.assertEqual(response.status_code, 200)
+
+    def test_cant_access_other_draft_report(self):
+        report = ReportFactory(is_draft=True)
+        response = self.get_page(report)
+        self.assertEqual(response.status_code, 404)
+
+    def test_cant_access_other_future_report(self):
+        report = ReportFactory(end_date=timezone.now() + relativedelta(days=1))
+        response = self.get_page(report)
+        self.assertEqual(response.status_code, 404)
diff --git a/opentech/apply/projects/urls.py b/opentech/apply/projects/urls.py
index eb512ba0e93d0a600ab57efda1300217930b2885..91d07064912a1cf56181221a03e1563292de055a 100644
--- a/opentech/apply/projects/urls.py
+++ b/opentech/apply/projects/urls.py
@@ -14,6 +14,7 @@ from .views import (
     ProjectListView,
     ProjectOverviewView,
     ProjectPrivateMediaView,
+    ReportDetailView,
     ReportPrivateMedia,
     ReportUpdateView,
 )
@@ -43,6 +44,7 @@ urlpatterns = [
     ], 'payments'))),
     path('reports/', include(([
         path('<int:pk>/', include([
+            path('', ReportDetailView.as_view(), name='detail'),
             path('edit/', ReportUpdateView.as_view(), name='edit'),
             path('documents/<int:file_pk>/', ReportPrivateMedia.as_view(), name="document"),
         ])),
diff --git a/opentech/apply/projects/views/report.py b/opentech/apply/projects/views/report.py
index f728f49a24f37c21dfbb9cca892dfe01c676c93e..70c2603ca579608d91f52f8df08b0f7582dee4ef 100644
--- a/opentech/apply/projects/views/report.py
+++ b/opentech/apply/projects/views/report.py
@@ -1,16 +1,18 @@
 from django.contrib.auth.decorators import login_required
 from django.contrib.auth.mixins import UserPassesTestMixin
+from django.core.exceptions import PermissionDenied
 from django.http import Http404
+from django.shortcuts import get_object_or_404, redirect
 from django.utils.decorators import method_decorator
-from django.core.exceptions import PermissionDenied
 from django.views.generic import (
-    UpdateView
+    DetailView,
+    UpdateView,
 )
 
 from opentech.apply.activity.messaging import MESSAGES, messenger
 from opentech.apply.utils.storage import PrivateMediaView
 
-from ..models import Report, ReportConfig
+from ..models import Report, ReportConfig, ReportPrivateFiles
 from ..forms import ReportEditForm
 
 
@@ -34,6 +36,17 @@ class ReportAccessMixin:
         return super().dispatch(request, *args, **kwargs)
 
 
+@method_decorator(login_required, name='dispatch')
+class ReportDetailView(ReportAccessMixin, DetailView):
+    model = Report
+
+    def dispatch(self, *args, **kwargs):
+        report = self.get_object()
+        if not report.current:
+            raise Http404
+        return super().dispatch(*args, **kwargs)
+
+
 @method_decorator(login_required, name='dispatch')
 class ReportUpdateView(ReportAccessMixin, UpdateView):
     form_class = ReportEditForm
@@ -101,13 +114,22 @@ class ReportPrivateMedia(UserPassesTestMixin, PrivateMediaView):
     def dispatch(self, *args, **kwargs):
         report_pk = self.kwargs['pk']
         self.report = get_object_or_404(Report, pk=report_pk)
+        file_pk = kwargs.get('file_pk')
+        self.document = get_object_or_404(
+            ReportPrivateFiles.objects,
+            report__report=self.report,
+            pk=file_pk
+        )
+
+        if not hasattr(self.document.report, 'live_for_report'):
+            # this is not a document in the live report
+            # send the user to the report page to see latest version
+            return redirect(self.report.get_absolute_url())
 
         return super().dispatch(*args, **kwargs)
 
     def get_media(self, *args, **kwargs):
-        file_pk = kwargs.get('file_pk')
-        document = get_object_or_404(self.report.files, pk=file_pk)
-        return document.document
+        return self.document.document
 
     def test_func(self):
         if self.request.user.is_apply_staff: