diff --git a/opentech/apply/projects/forms.py b/opentech/apply/projects/forms.py
index e5e84899d6e4a6df4c7fa6f28f39d28df143d49a..dbbf3125d0489889c21298d70705c3974c74398a 100644
--- a/opentech/apply/projects/forms.py
+++ b/opentech/apply/projects/forms.py
@@ -399,6 +399,10 @@ class ReportEditForm(forms.ModelForm):
         self.fields['file_list'].queryset = self.report_files
         self.user = user
 
+        # Cant change the privacy of a submitted report
+        if self.instance.current:
+            del self.fields['public']
+
     @transaction.atomic
     def save(self, commit=True):
         is_draft = 'save' in self.data
@@ -414,6 +418,10 @@ class ReportEditForm(forms.ModelForm):
         if is_draft:
             self.instance.draft = version
         else:
+            # If this is the first submission of the report we track that as the
+            # submitted date of the report
+            if not self.instance.submitted:
+                self.instance.submitted = version.submitted
             self.instance.current = version
             self.instance.draft = None
 
diff --git a/opentech/apply/projects/migrations/0029_report_submitted.py b/opentech/apply/projects/migrations/0029_report_submitted.py
new file mode 100644
index 0000000000000000000000000000000000000000..635f0b796fed614a7adc5a0b34583c445df72221
--- /dev/null
+++ b/opentech/apply/projects/migrations/0029_report_submitted.py
@@ -0,0 +1,18 @@
+# Generated by Django 2.1.11 on 2019-10-31 09:10
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('application_projects', '0028_report_draft'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='report',
+            name='submitted',
+            field=models.DateTimeField(null=True),
+        ),
+    ]
diff --git a/opentech/apply/projects/models.py b/opentech/apply/projects/models.py
index b792ddcf96c2e083bcf7e92198c0dfd26e4a5a01..36388f8742c78a3fd296949dfca5dff5e0be5b44 100644
--- a/opentech/apply/projects/models.py
+++ b/opentech/apply/projects/models.py
@@ -601,6 +601,7 @@ class ReportConfig(models.Model):
         report, _ = self.project.reports.update_or_create(
             project=self.project,
             end_date__gte=today,
+            current__isnull=True,
             defaults={'end_date': next_due_date}
         )
         return report
@@ -621,6 +622,7 @@ class Report(models.Model):
     public = models.BooleanField(default=True)
     end_date = models.DateField()
     project = models.ForeignKey("Project", on_delete=models.CASCADE, related_name="reports")
+    submitted = models.DateTimeField(null=True)
     current = models.OneToOneField(
         "ReportVersion",
         on_delete=models.CASCADE,
@@ -645,7 +647,9 @@ class Report(models.Model):
 
     @property
     def is_very_late(self):
-        more_than_one_report_late = self.project.reports.filter(end_date__gt=self.end_date).count() >= 2
+        more_than_one_report_late = self.project.reports.filter(
+            Q(end_date__gt=self.end_date) & Q(end_date__lt=timezone.now().date())
+        ).count() >= 1
         not_submitted = not self.current
         return not_submitted and more_than_one_report_late
 
@@ -655,12 +659,12 @@ class Report(models.Model):
 
     @property
     def submitted_date(self):
-        if self.current:
-            return self.current.submitted.date()
+        if self.submitted:
+            return self.submitted.date()
 
     @cached_property
     def start_date(self):
-        last_report = self.project.reports.order_by('current__submitted').filter(end_date__lt=self.end_date).first()
+        last_report = self.project.reports.filter(end_date__lt=self.end_date).first()
         if last_report:
             return last_report.end_date + relativedelta(days=1)
 
diff --git a/opentech/apply/projects/templates/application_projects/includes/reports.html b/opentech/apply/projects/templates/application_projects/includes/reports.html
index be0b115cb57d7301818f82dc8dfcc7d2e4d5e0e0..81d83f5c25fcffb327ef0358c95d69e23242d542 100644
--- a/opentech/apply/projects/templates/application_projects/includes/reports.html
+++ b/opentech/apply/projects/templates/application_projects/includes/reports.html
@@ -33,6 +33,9 @@
                     <span class="payment-block__mobile-label">Privacy: </span>{% if report.public %}Public{% else %}Private{% endif %}
                 </td>
                 <td>
+                    {% if request.user.is_apply_staff %}
+                        <a href="{% url "apply:projects:reports:edit" pk=report.pk %}">edit</a>
+                    {% endif %}
                 </td>
             </tr>
             {% empty %}
diff --git a/opentech/apply/projects/tests/factories.py b/opentech/apply/projects/tests/factories.py
index 994bfc33153dbe7f49527b8d25132b63479bba55..bdca5a9a5f48247178b4df1fb4eb8d0d96bf22a0 100644
--- a/opentech/apply/projects/tests/factories.py
+++ b/opentech/apply/projects/tests/factories.py
@@ -175,6 +175,7 @@ class ReportVersionFactory(factory.DjangoModelFactory):
                 obj.report.draft = obj
             else:
                 obj.report.current = obj
+                obj.report.submitted = obj.submitted
             obj.report.save()
 
 
@@ -189,7 +190,7 @@ class ReportFactory(factory.DjangoModelFactory):
         past_due = factory.Trait(
             end_date=factory.LazyFunction(lambda: timezone.now() - relativedelta(days=1))
         )
-        submitted = factory.Trait(
+        is_submitted = factory.Trait(
             version=factory.RelatedFactory(ReportVersionFactory, 'report', draft=False, relate=True)
         )
         is_draft = factory.Trait(
diff --git a/opentech/apply/projects/tests/test_models.py b/opentech/apply/projects/tests/test_models.py
index 91e2540fb654860f107101e55054634a8f88f888..15abe89865880e4d7c6ed08300a08e9132772d68 100644
--- a/opentech/apply/projects/tests/test_models.py
+++ b/opentech/apply/projects/tests/test_models.py
@@ -177,7 +177,6 @@ class TestPaymentRequestsQueryset(TestCase):
 
 
 class TestReportConfigCalculations(TestCase):
-
     @property
     def today(self):
         return timezone.now().date()
@@ -254,3 +253,47 @@ class TestReportConfigCalculations(TestCase):
         report = config.current_due_report()
         self.assertEqual(Report.objects.count(), 2)
         self.assertEqual(report.end_date, self.today + relativedelta(days=3))
+
+    def test_submitted_report_unaffected(self):
+        config = ReportConfigFactory()
+        report = ReportFactory(is_submitted=True, project=config.project, end_date=self.today + relativedelta(days=1))
+        next_report = config.current_due_report()
+        self.assertNotEqual(report, next_report)
+
+
+class TestReport(TestCase):
+    @property
+    def today(self):
+        return timezone.now().date()
+
+    def from_today(self, days):
+        return self.today + relativedelta(days=days)
+
+    def test_not_late_if_one_ahead(self):
+        report = ReportFactory(end_date=self.from_today(-3))
+        ReportFactory(project=report.project)
+        self.assertFalse(report.is_very_late)
+
+    def test_late_if_two_ahead(self):
+        report = ReportFactory(end_date=self.from_today(-3))
+        ReportFactory(end_date=self.from_today(-2), project=report.project)
+        ReportFactory(project=report.project)
+        self.assertTrue(report.is_very_late)
+
+    def test_not_late_if_two_ahead_but_one_in_future(self):
+        report = ReportFactory(end_date=self.from_today(-3))
+        ReportFactory(project=report.project)
+        ReportFactory(end_date=self.from_today(2), project=report.project)
+        self.assertFalse(report.is_very_late)
+
+    def test_start_date(self):
+        yesterday = self.from_today(-1)
+        ReportFactory(end_date=yesterday)
+        report = ReportFactory(end_date=self.from_today(1))
+        self.assertEqual(report.start_date, self.today)
+
+    def test_start_date_with_submitted(self):
+        yesterday = self.from_today(-1)
+        ReportFactory(end_date=yesterday)
+        report = ReportFactory(end_date=self.from_today(1), is_submitted=True)
+        self.assertEqual(report.start_date, self.today)
diff --git a/opentech/apply/projects/tests/test_views.py b/opentech/apply/projects/tests/test_views.py
index 3cebdb7cf264e55508ce8f401a9cfa76d962d2e7..ff727e84d8582d3e33ae93d17b665c9845a490fb 100644
--- a/opentech/apply/projects/tests/test_views.py
+++ b/opentech/apply/projects/tests/test_views.py
@@ -37,6 +37,7 @@ from .factories import (
     PaymentRequestFactory,
     ProjectFactory,
     ReportFactory,
+    ReportVersionFactory,
 )
 
 
@@ -1284,7 +1285,7 @@ class TestStaffSubmitReport(BaseViewTestCase):
         self.assertIsNone(report.draft)
 
     def test_edit_submitted_report(self):
-        report = ReportFactory(submitted=True)
+        report = ReportFactory(is_submitted=True)
         self.assertEqual(report.versions.first(), report.current)
         response = self.post_page(report, {'content': 'Some text', 'public': True, 'save': ' Save'})
         report.refresh_from_db()
@@ -1293,10 +1294,28 @@ class TestStaffSubmitReport(BaseViewTestCase):
         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(submitted=yesterday)
+        report = version.report
+        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, {'content': 'Some text', 'public': True})
+        report.refresh_from_db()
+        self.assertRedirects(response, self.absolute_url(report.project.get_absolute_url()))
+        self.assertEqual(report.versions.last().content, 'Some text')
+        self.assertEqual(report.versions.last(), report.current)
+        self.assertIsNone(report.draft)
+        self.assertEqual(report.submitted.date(), yesterday.date())
+        self.assertEqual(report.current.submitted.date(), timezone.now().date())
+
     def test_can_submit_future_report(self):
         submitted_report = ReportFactory(
             end_date=timezone.now() + relativedelta(days=1),
-            submitted=True,
+            is_submitted=True,
         )
         future_report = ReportFactory(
             end_date=timezone.now() + relativedelta(days=3),
@@ -1306,12 +1325,22 @@ class TestStaffSubmitReport(BaseViewTestCase):
         self.assertEqual(response.status_code, 404)
 
     def test_change_privacy(self):
-        report = ReportFactory()
+        report = ReportFactory(public=True)
         response = self.post_page(report, {'content': 'Some text', 'public': False})
         report.refresh_from_db()
         self.assertRedirects(response, self.absolute_url(report.project.get_absolute_url()))
         self.assertFalse(report.public)
 
+    def test_cant_change_privacy_submitted(self):
+        report = ReportFactory(
+            is_submitted=True,
+            public=True,
+        )
+        response = self.post_page(report, {'content': 'Some text', 'public': False})
+        report.refresh_from_db()
+        self.assertRedirects(response, self.absolute_url(report.project.get_absolute_url()))
+        self.assertTrue(report.public)
+
 
 class TestApplicantSubmitReport(BaseViewTestCase):
     base_view_name = 'edit'
@@ -1369,7 +1398,7 @@ class TestApplicantSubmitReport(BaseViewTestCase):
         self.assertIsNone(report.draft)
 
     def test_cant_edit_submitted_report(self):
-        report = ReportFactory(submitted=True, project__user=self.user)
+        report = ReportFactory(is_submitted=True, project__user=self.user)
         self.assertEqual(report.versions.first(), report.current)
         response = self.post_page(report, {'content': 'Some text', 'public': True, 'save': ' Save'})
         self.assertEqual(response.status_code, 404)
diff --git a/opentech/apply/projects/views/report.py b/opentech/apply/projects/views/report.py
index af02271ac0280ffb71de1bb27ab2f979150c4439..f728f49a24f37c21dfbb9cca892dfe01c676c93e 100644
--- a/opentech/apply/projects/views/report.py
+++ b/opentech/apply/projects/views/report.py
@@ -73,7 +73,16 @@ class ReportUpdateView(ReportAccessMixin, UpdateView):
     def form_valid(self, form):
         response = super().form_valid(form)
 
-        if not form.instance.draft:
+        should_notify = True
+        if self.object.draft:
+            # It was a draft submission
+            should_notify = False
+        else:
+            if self.object.submitted != self.object.current.submitted:
+                # It was a staff edit - post submission
+                should_notify = False
+
+        if should_notify:
             messenger(
                 MESSAGES.SUBMIT_REPORT,
                 request=self.request,