diff --git a/core/migrations/0003_submissiondoneassignmentscount.py b/core/migrations/0003_submissiondoneassignmentscount.py
index 0d1f0b23cb879e9cf3c114a3169d74b43b574f6e..61375c886a3e202723072949ebcd13ced0cc3e27 100644
--- a/core/migrations/0003_submissiondoneassignmentscount.py
+++ b/core/migrations/0003_submissiondoneassignmentscount.py
@@ -1,7 +1,7 @@
 # Generated by Django 2.0.2 on 2018-02-17 12:01
 
-from django.db import migrations, models
 import django.db.models.deletion
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
diff --git a/core/migrations/0004_auto_20180217_1723.py b/core/migrations/0004_auto_20180217_1723.py
new file mode 100644
index 0000000000000000000000000000000000000000..b87bf36814f5d52e5261c10c90d826624f6d7aa9
--- /dev/null
+++ b/core/migrations/0004_auto_20180217_1723.py
@@ -0,0 +1,38 @@
+# Generated by Django 2.0.2 on 2018-02-17 17:23
+
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0003_submissiondoneassignmentscount'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='MetaSubmission',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('done_assignments', models.PositiveIntegerField(default=0)),
+                ('has_active_assignment', models.BooleanField(default=False)),
+                ('has_feedback', models.BooleanField(default=False)),
+                ('has_final_feedback', models.BooleanField(default=False)),
+                ('feedback_authors', models.ManyToManyField(to=settings.AUTH_USER_MODEL)),
+                ('submission', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='meta', to='core.Submission')),
+            ],
+        ),
+        migrations.RemoveField(
+            model_name='submissiondoneassignmentscount',
+            name='submission',
+        ),
+        migrations.AlterUniqueTogether(
+            name='tutorsubmissionassignment',
+            unique_together={('submission', 'subscription')},
+        ),
+        migrations.DeleteModel(
+            name='SubmissionDoneAssignmentsCount',
+        ),
+    ]
diff --git a/core/migrations/0005_auto_20180217_1728.py b/core/migrations/0005_auto_20180217_1728.py
new file mode 100644
index 0000000000000000000000000000000000000000..8506733712e2def2dd5aa26355b5d91e36818782
--- /dev/null
+++ b/core/migrations/0005_auto_20180217_1728.py
@@ -0,0 +1,19 @@
+# Generated by Django 2.0.2 on 2018-02-17 17:28
+
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0004_auto_20180217_1723'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='metasubmission',
+            name='feedback_authors',
+            field=models.ManyToManyField(related_name='authors', to=settings.AUTH_USER_MODEL),
+        ),
+    ]
diff --git a/core/migrations/0006_auto_20180217_1729.py b/core/migrations/0006_auto_20180217_1729.py
new file mode 100644
index 0000000000000000000000000000000000000000..3783adfbe216195018c3664103e64ec5aecd0e04
--- /dev/null
+++ b/core/migrations/0006_auto_20180217_1729.py
@@ -0,0 +1,19 @@
+# Generated by Django 2.0.2 on 2018-02-17 17:29
+
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0005_auto_20180217_1728'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='metasubmission',
+            name='feedback_authors',
+            field=models.ManyToManyField(to=settings.AUTH_USER_MODEL),
+        ),
+    ]
diff --git a/core/models.py b/core/models.py
index 6b823bdca30692218a082dde48425ecc7e406b03..22d63829442190ff0a18998286d993fde180585e 100644
--- a/core/models.py
+++ b/core/models.py
@@ -500,11 +500,11 @@ class SubmissionSubscription(models.Model):
         e.g. all submissions of one student or submission type.
         """
         if self.query_type == self.RANDOM:
-            return Submission.objects.all()
+            return MetaSubmission.objects.all()
 
-        TutorSubmissionAssignment.objects.select_for_update()
-        return Submission.objects.filter(
-            **{self.type_query_mapper[self.query_type]: self.query_key})
+        return MetaSubmission.objects.filter(
+            **{'submission__' + self.type_query_mapper[self.query_type]:
+               self.query_key})
 
     def _get_submissions_that_do_not_have_final_feedback(self) -> QuerySet:
         """ There are a number of conditions to check for each submission
@@ -516,12 +516,10 @@ class SubmissionSubscription(models.Model):
         Returns:
             QuerySet -- a list of all submissions ready for consumption
         """
-        return self._get_submission_base_query().exclude(
-            Q(feedback__isnull=False) & Q(feedback__is_final=True)
-        ).exclude(
-            Q(assignments__subscription__owner=self.owner)
-        ).exclude(
-            assignments__is_done=False
+        return self._get_submission_base_query().select_for_update().exclude(
+            Q(has_final_feedback=True) |
+            Q(has_active_assignment=True) |
+            Q(feedback_authors=self.owner)
         )
 
     def _get_available_submissions_in_subscription_stage(self) -> QuerySet:
@@ -542,7 +540,7 @@ class SubmissionSubscription(models.Model):
 
         done_assignments_count = self.assignment_count_on_stage[self.feedback_stage]  # noqa
         stage_candiates = candidates.filter(
-            counter__done_assignments=done_assignments_count,
+            done_assignments=done_assignments_count,
         )
 
         if stage_candiates.count() == 0:
@@ -552,9 +550,11 @@ class SubmissionSubscription(models.Model):
 
         return stage_candiates
 
+    @transaction.atomic
     def get_remaining_not_final(self) -> int:
         return self._get_submissions_that_do_not_have_final_feedback().count()
 
+    @transaction.atomic
     def get_available_in_stage(self) -> int:
         try:
             return self._get_available_submissions_in_subscription_stage().count()  # noqa
@@ -568,18 +568,19 @@ class SubmissionSubscription(models.Model):
             raise NotMoreThanTwoOpenAssignmentsAllowed(
                 'Not more than 2 active assignments allowed.')
 
-        log.info(f'{self.owner} is assignment to {task}.')
-        return TutorSubmissionAssignment.objects.get_or_create(
+        log.info(f'{self.owner} is assigned to {task} ({self.feedback_stage})')
+        return TutorSubmissionAssignment.objects.create(
             subscription=self,
-            submission=task)[0]
+            submission=task.submission)
 
     @transaction.atomic
     def reserve_all_assignments_for_a_student(self):
         assert self.query_type == self.STUDENT_QUERY
 
-        submissions = self._get_submissions_that_do_not_have_final_feedback()
+        meta_submissions = self._get_submissions_that_do_not_have_final_feedback()  # noqa
 
-        for submission in submissions:
+        for meta in meta_submissions:
+            submission = meta.submission
             if hasattr(submission, 'assignments'):
                 submission.assignments.filter(is_done=False).delete()
             TutorSubmissionAssignment.objects.create(
@@ -603,12 +604,28 @@ class DeletionOfDoneAssignmentsNotPermitted(Exception):
     pass
 
 
-class SubmissionDoneAssignmentsCount(models.Model):
+class MetaSubmission(models.Model):
 
     submission = models.OneToOneField('submission',
-                                      related_name='counter',
+                                      related_name='meta',
                                       on_delete=models.CASCADE)
     done_assignments = models.PositiveIntegerField(default=0)
+    has_active_assignment = models.BooleanField(default=False)
+
+    has_feedback = models.BooleanField(default=False)
+    has_final_feedback = models.BooleanField(default=False)
+
+    feedback_authors = models.ManyToManyField(get_user_model())
+
+    def __str__(self):
+        return f''' Submission Meta of {self.submission}
+
+        done_assignments      = {self.done_assignments}
+        has_active_assignment = {self.has_active_assignment}
+        has_feedback          = {self.has_feedback}
+        has_final_feedback    = {self.has_final_feedback}
+        feedback_authors      = {self.feedback_authors}
+        '''
 
 
 class TutorSubmissionAssignment(models.Model):
@@ -625,14 +642,6 @@ class TutorSubmissionAssignment(models.Model):
     is_done = models.BooleanField(default=False)
     created = models.DateTimeField(auto_now_add=True)
 
-    @transaction.atomic
-    def set_done(self):
-        if not self.is_done:
-            self.submission.counter.done_assignments += 1
-            self.submission.counter.save()
-        self.is_done = True
-        self.save()
-
     def __str__(self):
         return (f'{self.subscription.owner} assigned to {self.submission}'
                 f' (done={self.is_done})')
@@ -642,6 +651,9 @@ class TutorSubmissionAssignment(models.Model):
             raise DeletionOfDoneAssignmentsNotPermitted()
         super().delete(*args, **kwargs)
 
+    class Meta:
+        unique_together = ('submission', 'subscription')
+
 
 class FeedbackComment(models.Model):
     """ This Class contains the Feedback for a specific line of a Submission"""
@@ -664,14 +676,6 @@ class FeedbackComment(models.Model):
         null=True
     )
 
-    def save(self, *args, **kwargs):
-        comments_on_the_same_line = FeedbackComment.objects.filter(
-            of_line=self.of_line,
-            of_feedback=self.of_feedback,
-        )
-        comments_on_the_same_line.update(visible_to_student=False)
-        super().save(*args, **kwargs)
-
     class Meta:
         verbose_name = "Feedback Comment"
         verbose_name_plural = "Feedback Comments"
diff --git a/core/serializers/feedback.py b/core/serializers/feedback.py
index 1b5c181c08e29946a84695aa0b63d1e5d34e01ed..b3a5181928dcdfd1eea4e4bef2bf01487daebdca 100644
--- a/core/serializers/feedback.py
+++ b/core/serializers/feedback.py
@@ -83,11 +83,6 @@ class FeedbackCommentSerializer(serializers.ModelSerializer):
 class FeedbackSerializer(DynamicFieldsModelSerializer):
     feedback_lines = FeedbackCommentSerializer(many=True, required=False)
 
-    def _set_assignment_done(self, submission):
-        assignment = submission.assignments.get(
-            subscription__owner=self.context['request'].user)
-        assignment.set_done()
-
     @transaction.atomic
     def create(self, validated_data) -> Feedback:
         submission = validated_data.pop('of_submission')
@@ -103,7 +98,6 @@ class FeedbackSerializer(DynamicFieldsModelSerializer):
                 **comment
             )
 
-        self._set_assignment_done(submission)
         return Feedback.objects.get(of_submission=submission)
 
     @transaction.atomic
@@ -115,7 +109,6 @@ class FeedbackSerializer(DynamicFieldsModelSerializer):
                 of_line=comment.get('of_line'),
                 defaults={'text': comment.get('text')})
 
-        self._set_assignment_done(feedback.of_submission)
         return super().update(feedback, validated_data)
 
     def validate_of_submission(self, submission):
diff --git a/core/signals.py b/core/signals.py
index 57173f12227d54cecb920b91d80cf58d03d3778f..f74b8f2dc1e892c97383a15df2d4c52ede94442a 100644
--- a/core/signals.py
+++ b/core/signals.py
@@ -1,13 +1,73 @@
-from core.models import Submission, SubmissionDoneAssignmentsCount
+import logging
 
-from django.db.models.signals import post_save
+from django.db.models.signals import post_save, pre_delete, pre_save
 from django.dispatch import receiver
 
+from core import models
+from core.models import (Feedback, FeedbackComment, MetaSubmission, Submission,
+                         TutorSubmissionAssignment)
+
+log = logging.getLogger(__name__)
+
 
 @receiver(post_save, sender=Submission)
-def create_counter_after_submission_create(sender,
-                                           instance,
-                                           created,
-                                           **kwargs):
+def create_meta_after_submission_create(sender, instance, created, **kwargs):
+    log.debug('SIGNAL -- create_meta_after_submission_create')
     if created:
-        SubmissionDoneAssignmentsCount.objects.create(submission=instance)
+        MetaSubmission.objects.create(submission=instance)
+
+
+@receiver(post_save, sender=TutorSubmissionAssignment)
+def update_active_after_assignment_save(sender, instance, created, **kwargs):
+    """ Assignments are created undone therefore save that no other
+    should use it. If it is already set to done it is not active.
+    """
+    log.debug('SIGNAL -- update_active_after_assignment_save')
+    meta = instance.submission.meta
+    meta.has_active_assignment = created and not instance.is_done
+    meta.save()
+
+
+@receiver(pre_delete, sender=TutorSubmissionAssignment)
+def remove_active_assignment_on_delete(sender, instance, **kwargs):
+    log.debug('SIGNAL -- remove_active_assignment_on_delete')
+    if instance.is_done:
+        raise models.DeletionOfDoneAssignmentsNotPermitted()
+    meta = instance.submission.meta
+    meta.has_active_assignment = False
+    meta.save()
+
+
+@receiver(post_save, sender=Feedback)
+def update_after_feedback_save(sender, instance, created, **kwargs):
+    """ Do the following steps when feedback is saved:
+
+    - set that feedback exists
+    - copy the final status of the feedback
+    - set all assignments of the submission done and remove active status
+    """
+    log.debug('SIGNAL -- update_after_feedback_save')
+    meta = instance.of_submission.meta
+    meta.has_feedback = True
+    meta.has_final_feedback = instance.is_final
+
+    undone_assignment = meta.submission.assignments.filter(is_done=False)
+    assert undone_assignment.count() <= 1
+    if undone_assignment.count() > 0:
+        log.debug('SIGNAL -- Completed: %s' % undone_assignment.first())
+        meta.feedback_authors.add(undone_assignment.first().subscription.owner)
+        meta.done_assignments += 1
+        meta.has_active_assignment = False
+        undone_assignment.update(is_done=True)
+
+    meta.save()
+
+
+@receiver(pre_save, sender=FeedbackComment)
+def set_comment_visibility_after_conflict(sender, instance, **kwargs):
+    log.debug('SIGNAL -- set_comment_visibility_after_conflict')
+    comments_on_the_same_line = FeedbackComment.objects.filter(
+        of_line=instance.of_line,
+        of_feedback=instance.of_feedback,
+    )
+    comments_on_the_same_line.update(visible_to_student=False)
diff --git a/core/tests/test_export.py b/core/tests/test_export.py
index 182db20688ec5fa72adead7d9b8cc03927acae10..9165bb4768a86cd5f117561d8253b4ed45adcb93 100644
--- a/core/tests/test_export.py
+++ b/core/tests/test_export.py
@@ -1,5 +1,5 @@
+from django.test import Client, TestCase
 from rest_framework import status
-from django.test import TestCase, Client
 
 from util.factories import make_test_data
 
diff --git a/core/tests/test_feedback.py b/core/tests/test_feedback.py
index 8b377de2c8bc3913d291b1f6df46d292b90f1c5b..f904a785fbeb9d9fa80e41a18d31609371129f85 100644
--- a/core/tests/test_feedback.py
+++ b/core/tests/test_feedback.py
@@ -361,7 +361,7 @@ class FeedbackPatchTestCase(APITestCase):
         self.assertEqual(status.HTTP_200_OK, response.status_code)
 
     def test_tutor_can_not_update_when_there_is_a_new_assignment(self):
-        # Step 1 - Create a new assignment
+        # Step 1 - Create a new assignment for Tutor 2
         second_subs = models.SubmissionSubscription.objects.create(
             owner=self.tutor02,
             query_type='random',
@@ -369,7 +369,7 @@ class FeedbackPatchTestCase(APITestCase):
         )
         second_subs.get_or_create_work_assignment()
 
-        # Step 2 - Tutor 2 tries to patch
+        # Step 2 - Tutor 1 tries to patch
         data = {
             'feedback_lines': {
                 '2': {'text': 'Turns out this is rather bad.'},
diff --git a/core/tests/test_tutor_api_endpoints.py b/core/tests/test_tutor_api_endpoints.py
index 0e9a5773a8785dbcf67de3fad2dcb4625ef6ec18..63a1cda65ecc55dae68bff6ba8fca1e3ef0388b1 100644
--- a/core/tests/test_tutor_api_endpoints.py
+++ b/core/tests/test_tutor_api_endpoints.py
@@ -10,7 +10,7 @@ from rest_framework.reverse import reverse
 from rest_framework.test import (APIClient, APIRequestFactory, APITestCase,
                                  force_authenticate)
 
-from core.models import TutorSubmissionAssignment, SubmissionSubscription
+from core.models import SubmissionSubscription, TutorSubmissionAssignment
 from core.views import TutorApiViewSet
 from util.factories import GradyUserFactory
 
diff --git a/core/views/common_views.py b/core/views/common_views.py
index b79dec5c6eaeefc8cde76beb1a7613d4471fc385..27e838921a133669ce8d22a47d2c175dd27eecce 100644
--- a/core/views/common_views.py
+++ b/core/views/common_views.py
@@ -13,8 +13,8 @@ from core.models import ExamType, StudentInfo, SubmissionType
 from core.permissions import IsReviewer, IsStudent
 from core.serializers import (ExamSerializer, StudentInfoSerializer,
                               StudentInfoSerializerForListView,
-                              SubmissionSerializer, SubmissionTypeSerializer,
-                              TutorSerializer, SubmissionNoTypeSerializer)
+                              SubmissionNoTypeSerializer, SubmissionSerializer,
+                              SubmissionTypeSerializer, TutorSerializer)
 
 log = logging.getLogger(__name__)
 
diff --git a/frontend/src/pages/SubscriptionWorkPage.vue b/frontend/src/pages/SubscriptionWorkPage.vue
index 62b0f4d332370ebd1f0fc696c9666198d4169c9d..e3532b823220a038438523094a6cab910bf3e2f6 100644
--- a/frontend/src/pages/SubscriptionWorkPage.vue
+++ b/frontend/src/pages/SubscriptionWorkPage.vue
@@ -35,8 +35,8 @@
       if (subscription['assignments'].length === 0) {
         store.dispatch('getAssignmentForSubscription', {subscription}).then(() => {
           next()
-          store.dispatch('getAssignmentForSubscription', {subscription})
         })
+        store.dispatch('getAssignmentForSubscription', {subscription})
       } else {
         next()
       }