diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py
index 77e1634f99787db2d0b4fb44bfbd40fbbeb39708..7f984f22accc5d6c6607120f37cb7276f1566076 100644
--- a/core/migrations/0001_initial.py
+++ b/core/migrations/0001_initial.py
@@ -1,4 +1,4 @@
-# Generated by Django 2.0.1 on 2018-02-01 15:08
+# Generated by Django 2.0.2 on 2018-02-08 15:11
 
 import uuid
 
@@ -24,37 +24,22 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='UserAccount',
             fields=[
-                ('id', models.AutoField(auto_created=True,
-                                        primary_key=True, serialize=False, verbose_name='ID')),
-                ('password', models.CharField(
-                    max_length=128, verbose_name='password')),
-                ('last_login', models.DateTimeField(
-                    blank=True, null=True, verbose_name='last login')),
-                ('is_superuser', models.BooleanField(default=False,
-                                                     help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
-                ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.',
-                                              max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
-                ('first_name', models.CharField(blank=True,
-                                                max_length=30, verbose_name='first name')),
-                ('last_name', models.CharField(blank=True,
-                                               max_length=150, verbose_name='last name')),
-                ('email', models.EmailField(blank=True,
-                                            max_length=254, verbose_name='email address')),
-                ('is_staff', models.BooleanField(default=False,
-                                                 help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
-                ('is_active', models.BooleanField(
-                    default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
-                ('date_joined', models.DateTimeField(
-                    default=django.utils.timezone.now, verbose_name='date joined')),
-                ('fullname', models.CharField(blank=True,
-                                              max_length=70, verbose_name='full name')),
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('password', models.CharField(max_length=128, verbose_name='password')),
+                ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
+                ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
+                ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
+                ('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')),
+                ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
+                ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
+                ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
+                ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
+                ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
+                ('fullname', models.CharField(blank=True, max_length=70, verbose_name='full name')),
                 ('is_admin', models.BooleanField(default=False)),
-                ('role', models.CharField(choices=[
-                 ('Student', 'student'), ('Tutor', 'tutor'), ('Reviewer', 'reviewer')], max_length=50)),
-                ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.',
-                                                  related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
-                ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.',
-                                                            related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
+                ('role', models.CharField(choices=[('Student', 'student'), ('Tutor', 'tutor'), ('Reviewer', 'reviewer')], max_length=50)),
+                ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
+                ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
             ],
             options={
                 'verbose_name': 'user',
@@ -68,8 +53,7 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='ExamType',
             fields=[
-                ('id', models.AutoField(auto_created=True,
-                                        primary_key=True, serialize=False, verbose_name='ID')),
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                 ('module_reference', models.CharField(max_length=50, unique=True)),
                 ('total_score', models.PositiveIntegerField()),
                 ('pass_score', models.PositiveIntegerField()),
@@ -83,13 +67,11 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='Feedback',
             fields=[
-                ('id', models.AutoField(auto_created=True,
-                                        primary_key=True, serialize=False, verbose_name='ID')),
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                 ('score', models.PositiveIntegerField(default=0)),
                 ('created', models.DateTimeField(auto_now_add=True)),
                 ('is_final', models.BooleanField(default=False)),
-                ('origin', models.IntegerField(choices=[(0, 'was empty'), (1, 'passed unittests'), (
-                    2, 'did not compile'), (3, 'could not link'), (4, 'created by a human. yak!')], default=4)),
+                ('origin', models.IntegerField(choices=[(0, 'was empty'), (1, 'passed unittests'), (2, 'did not compile'), (3, 'could not link'), (4, 'created by a human. yak!')], default=4)),
             ],
             options={
                 'verbose_name': 'Feedback',
@@ -99,17 +81,14 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='FeedbackComment',
             fields=[
-                ('id', models.AutoField(auto_created=True,
-                                        primary_key=True, serialize=False, verbose_name='ID')),
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                 ('text', models.TextField()),
                 ('created', models.DateTimeField(auto_now_add=True)),
                 ('modified', models.DateTimeField(auto_now=True)),
-                ('is_final', models.BooleanField(default=True)),
+                ('visible_to_student', models.BooleanField(default=True)),
                 ('of_line', models.PositiveIntegerField(default=0)),
-                ('of_feedback', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE,
-                                                  related_name='feedback_lines', to='core.Feedback')),
-                ('of_tutor', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT,
-                                               related_name='comment_list', to=settings.AUTH_USER_MODEL)),
+                ('of_feedback', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='feedback_lines', to='core.Feedback')),
+                ('of_tutor', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='comment_list', to=settings.AUTH_USER_MODEL)),
             ],
             options={
                 'verbose_name': 'Feedback Comment',
@@ -117,32 +96,14 @@ class Migration(migrations.Migration):
                 'ordering': ('created',),
             },
         ),
-        migrations.CreateModel(
-            name='GeneralTaskSubscription',
-            fields=[
-                ('subscription_id', models.UUIDField(default=uuid.uuid4,
-                                                     editable=False, primary_key=True, serialize=False)),
-                ('query_key', models.CharField(blank=True, max_length=75)),
-                ('query_type', models.CharField(choices=[('random', 'Query for any submission'), ('student', 'Query for submissions of student'), (
-                    'exam', 'Query for submissions of exam type'), ('submission_type', 'Query for submissions of submissions_type')], default='random', max_length=75)),
-                ('feedback_stage', models.CharField(choices=[('feedback-creation', 'No feedback was ever assigned'), ('feedback-validation',
-                                                                                                                      'Feedback exists but is not validated'), ('feedback-conflict-resolution', 'Previous correctors disagree')], default='feedback-creation', max_length=40)),
-                ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
-                                            related_name='subscriptions', to=settings.AUTH_USER_MODEL)),
-            ],
-        ),
         migrations.CreateModel(
             name='StudentInfo',
             fields=[
-                ('student_id', models.UUIDField(default=uuid.uuid4,
-                                                editable=False, primary_key=True, serialize=False)),
+                ('student_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
                 ('has_logged_in', models.BooleanField(default=False)),
-                ('matrikel_no', models.CharField(
-                    default=core.models.random_matrikel_no, max_length=8, unique=True)),
-                ('exam', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL,
-                                           related_name='students', to='core.ExamType')),
-                ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE,
-                                              related_name='student', to=settings.AUTH_USER_MODEL)),
+                ('matrikel_no', models.CharField(default=core.models.random_matrikel_no, max_length=8, unique=True)),
+                ('exam', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='students', to='core.ExamType')),
+                ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='student', to=settings.AUTH_USER_MODEL)),
             ],
             options={
                 'verbose_name': 'Student',
@@ -152,12 +113,10 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='Submission',
             fields=[
-                ('submission_id', models.UUIDField(default=uuid.uuid4,
-                                                   editable=False, primary_key=True, serialize=False)),
+                ('submission_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
                 ('seen_by_student', models.BooleanField(default=False)),
                 ('text', models.TextField(blank=True)),
-                ('student', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
-                                              related_name='submissions', to='core.StudentInfo')),
+                ('student', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='submissions', to='core.StudentInfo')),
             ],
             options={
                 'verbose_name': 'Submission',
@@ -165,11 +124,20 @@ class Migration(migrations.Migration):
                 'ordering': ('type__name',),
             },
         ),
+        migrations.CreateModel(
+            name='SubmissionSubscription',
+            fields=[
+                ('subscription_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+                ('query_key', models.CharField(blank=True, max_length=75)),
+                ('query_type', models.CharField(choices=[('random', 'Query for any submission'), ('student', 'Query for submissions of student'), ('exam', 'Query for submissions of exam type'), ('submission_type', 'Query for submissions of submissions_type')], default='random', max_length=75)),
+                ('feedback_stage', models.CharField(choices=[('feedback-creation', 'No feedback was ever assigned'), ('feedback-validation', 'Feedback exists but is not validated'), ('feedback-conflict-resolution', 'Previous correctors disagree')], default='feedback-creation', max_length=40)),
+                ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='subscriptions', to=settings.AUTH_USER_MODEL)),
+            ],
+        ),
         migrations.CreateModel(
             name='SubmissionType',
             fields=[
-                ('id', models.AutoField(auto_created=True,
-                                        primary_key=True, serialize=False, verbose_name='ID')),
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                 ('name', models.CharField(max_length=50, unique=True)),
                 ('full_score', models.PositiveIntegerField(default=0)),
                 ('description', models.TextField()),
@@ -183,13 +151,11 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='Test',
             fields=[
-                ('id', models.AutoField(auto_created=True,
-                                        primary_key=True, serialize=False, verbose_name='ID')),
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                 ('name', models.CharField(max_length=30)),
                 ('label', models.CharField(max_length=50)),
                 ('annotation', models.TextField()),
-                ('submission', models.ForeignKey(
-                    on_delete=django.db.models.deletion.CASCADE, related_name='tests', to='core.Submission')),
+                ('submission', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tests', to='core.Submission')),
             ],
             options={
                 'verbose_name': 'Test',
@@ -199,39 +165,34 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='TutorSubmissionAssignment',
             fields=[
-                ('assignment_id', models.UUIDField(default=uuid.uuid4,
-                                                   editable=False, primary_key=True, serialize=False)),
+                ('assignment_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
                 ('is_done', models.BooleanField(default=False)),
                 ('created', models.DateTimeField(auto_now_add=True)),
-                ('submission', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
-                                                 related_name='assignments', to='core.Submission')),
-                ('subscription', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
-                                                   related_name='assignments', to='core.GeneralTaskSubscription')),
+                ('submission', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='assignments', to='core.Submission')),
+                ('subscription', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='assignments', to='core.SubmissionSubscription')),
             ],
         ),
         migrations.AddField(
             model_name='submission',
             name='type',
-            field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT,
-                                    related_name='submissions', to='core.SubmissionType'),
+            field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='submissions', to='core.SubmissionType'),
         ),
         migrations.AddField(
             model_name='feedback',
             name='of_submission',
-            field=models.OneToOneField(
-                on_delete=django.db.models.deletion.CASCADE, related_name='feedback', to='core.Submission'),
+            field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='feedback', to='core.Submission'),
         ),
         migrations.AlterUniqueTogether(
             name='test',
             unique_together={('submission', 'name')},
         ),
         migrations.AlterUniqueTogether(
-            name='submission',
-            unique_together={('type', 'student')},
+            name='submissionsubscription',
+            unique_together={('owner', 'query_key', 'query_type', 'feedback_stage')},
         ),
         migrations.AlterUniqueTogether(
-            name='generaltasksubscription',
-            unique_together={('owner', 'query_key', 'query_type')},
+            name='submission',
+            unique_together={('type', 'student')},
         ),
         migrations.AlterUniqueTogether(
             name='feedbackcomment',
diff --git a/core/migrations/0002_auto_20180202_1421.py b/core/migrations/0002_auto_20180202_1421.py
deleted file mode 100644
index f06014c19a731cb17a4e96b67fdeba4f84a0301f..0000000000000000000000000000000000000000
--- a/core/migrations/0002_auto_20180202_1421.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Generated by Django 2.0.2 on 2018-02-02 14:21
-
-from django.db import migrations
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('core', '0001_initial'),
-    ]
-
-    operations = [
-        migrations.AlterUniqueTogether(
-            name='generaltasksubscription',
-            unique_together={('owner', 'query_key', 'query_type', 'feedback_stage')},
-        ),
-    ]
diff --git a/core/migrations/0002_submissionsubscription_deactivated.py b/core/migrations/0002_submissionsubscription_deactivated.py
new file mode 100644
index 0000000000000000000000000000000000000000..d10cbe69303a4867e6d3cca71b2d999e2dde362f
--- /dev/null
+++ b/core/migrations/0002_submissionsubscription_deactivated.py
@@ -0,0 +1,18 @@
+# Generated by Django 2.0.2 on 2018-02-08 15:50
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='submissionsubscription',
+            name='deactivated',
+            field=models.BooleanField(default=False),
+        ),
+    ]
diff --git a/core/migrations/0003_auto_20180207_1922.py b/core/migrations/0003_auto_20180207_1922.py
deleted file mode 100644
index b76df083879f12521f5edbb0d9b8135f3e8944e7..0000000000000000000000000000000000000000
--- a/core/migrations/0003_auto_20180207_1922.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Generated by Django 2.0.2 on 2018-02-07 19:22
-
-from django.db import migrations
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('core', '0002_auto_20180202_1421'),
-    ]
-
-    operations = [
-        migrations.RenameField(
-            model_name='feedbackcomment',
-            old_name='is_final',
-            new_name='visible_to_student',
-        ),
-    ]
diff --git a/core/models.py b/core/models.py
index 08e852ee757dd1f5e4a674786f917e5df24d8e25..77f8fcc0c10bbe8f5461067345404b545b70f2be 100644
--- a/core/models.py
+++ b/core/models.py
@@ -420,11 +420,15 @@ class SubscriptionEnded(Exception):
     pass
 
 
-class AssignmentError(Exception):
+class SubscriptionTemporarilyEnded(Exception):
     pass
 
 
-class GeneralTaskSubscription(models.Model):
+class NotMoreThanTwoOpenAssignmentsAllowed(Exception):
+    pass
+
+
+class SubmissionSubscription(models.Model):
 
     RANDOM = 'random'
     STUDENT_QUERY = 'student'
@@ -449,7 +453,7 @@ class GeneralTaskSubscription(models.Model):
     FEEDBACK_VALIDATION = 'feedback-validation'
     FEEDBACK_CONFLICT_RESOLUTION = 'feedback-conflict-resolution'
 
-    stage_to_assignment_count_map = {
+    assignment_count_on_stage = {
         FEEDBACK_CREATION: 0,
         FEEDBACK_VALIDATION: 1,
         FEEDBACK_CONFLICT_RESOLUTION: 2,
@@ -461,6 +465,7 @@ class GeneralTaskSubscription(models.Model):
         (FEEDBACK_CONFLICT_RESOLUTION, 'Previous correctors disagree'),
     )
 
+    deactivated = models.BooleanField(default=False)
     subscription_id = models.UUIDField(primary_key=True,
                                        default=uuid.uuid4,
                                        editable=False)
@@ -488,92 +493,77 @@ class GeneralTaskSubscription(models.Model):
         return Submission.objects.filter(
             **{self.type_query_mapper[self.query_type]: self.query_key})
 
-    def _find_submissions_based_on_completed_assignments(
-            self, done_assignments_count):
-        return self._get_submission_base_query().filter(
+    def _get_submissions_that_do_not_have_final_feedback(self):
+        return self._get_submission_base_query().exclude(
             Q(feedback__isnull=False),
-            Q(feedback__is_final=False),
-            ~Q(assignments__subscription__owner=self.owner)
-        ).annotate(  # to display only manual
+            Q(feedback__is_final=True)
+        ).exclude(
+            Q(assignments__subscription__owner=self.owner)
+        ).annotate(
             done_assignments_count=Count(
                 Case(When(assignments__is_done=True, then=Value(1)),
                      output_field=IntegerField(),)
             )
-        ).filter(done_assignments_count=self.stage_to_assignment_count_map[
-            done_assignments_count])
-
-    def _find_unassigned_non_final_submissions(self):
-        unassigned_non_final_submissions = \
-            self._get_submission_base_query().filter(
-                Q(assignments__isnull=True),
-                Q(feedback__isnull=True)
-            )
-
-        log.debug('unassigned non final submissions %s',
-                  unassigned_non_final_submissions)
-
-        return unassigned_non_final_submissions
-
-    def _find_unassigned_unapproved_non_final_submissions(self):
-        return self._find_submissions_based_on_completed_assignments(
-            done_assignments_count=self.FEEDBACK_VALIDATION)
-
-    def _find_submissions_with_conflicting_feedback(self):
-        return self._find_submissions_based_on_completed_assignments(
-            done_assignments_count=self.FEEDBACK_CONFLICT_RESOLUTION)
+        )
 
-    def _get_next_assignment_in_subscription(self):
-        candidates = (
-            self._find_unassigned_non_final_submissions,
-            self._find_unassigned_unapproved_non_final_submissions,
-            self._find_submissions_with_conflicting_feedback
-        )[self.stage_to_assignment_count_map[self.feedback_stage]]()
+    def _get_available_submissions_in_subscription_stage(self):
+        candidates = self._get_submissions_that_do_not_have_final_feedback()
 
         if candidates.count() == 0:
             raise SubscriptionEnded(
                 f'The task which user {self.owner} subscribed to is done')
 
-        return candidates.first()
+        done_assignments_count = self.assignment_count_on_stage[self.feedback_stage]  # noqa
+        stage_candiates = candidates.filter(
+            done_assignments_count=done_assignments_count
+        )
+
+        if stage_candiates.count() == 0:
+            raise SubscriptionTemporarilyEnded(
+                'Currently unavailabe. Please check for more soon. '
+                'Submissions remaining: %s' % stage_candiates.count())
+
+        return stage_candiates
 
     @transaction.atomic
     def get_or_create_work_assignment(self):
-        task = self._get_next_assignment_in_subscription()
+        task = self._get_available_submissions_in_subscription_stage().first()
+        if self.assignments.filter(is_done=False).count() >= 2:
+            raise NotMoreThanTwoOpenAssignmentsAllowed(
+                'Not more than 2 active assignments allowed.')
 
         return TutorSubmissionAssignment.objects.get_or_create(
             subscription=self,
             submission=task)[0]
 
+    @transaction.atomic
     def reserve_all_assignments_for_a_student(self):
         assert self.query_type == self.STUDENT_QUERY
 
-        try:
-            while True:
-                self.get_or_create_work_assignment()
-        except SubscriptionEnded as err:
-            log.info(f'Loaded all subscriptions of student {self.query_key}')
+        submissions = self._get_submissions_that_do_not_have_final_feedback()
 
-    def _create_new_assignment_if_subscription_empty(self):
-        if self.assignments.filter(is_done=False).count() < 1:
-            self.get_or_create_work_assignment()
+        for submission in submissions:
+            if hasattr(submission, 'assignments'):
+                submission.assignments.filter(is_done=False).delete()
+            TutorSubmissionAssignment.objects.create(
+                subscription=self,
+                submission=submission
+            )
 
-    def _eagerly_reserve_the_next_assignment(self):
-        if self.assignments.filter(is_done=False).count() < 2:
-            self.get_or_create_work_assignment()
+        log.info(f'Loaded all subscriptions of student {self.query_key}')
+
+    @transaction.atomic
+    def delete(self):
+        self.assignments.filter(is_done=False).delete()
+        if self.assignments.count() == 0:
+            super().delete()
+        else:
+            self.deactivated = True
+            self.save()
 
-    def get_oldest_unfinished_assignment(self):
-        self._create_new_assignment_if_subscription_empty()
-        return self.assignments \
-            .filter(is_done=False) \
-            .order_by('created') \
-            .first()
 
-    def get_youngest_unfinished_assignment(self):
-        self._create_new_assignment_if_subscription_empty()
-        self._eagerly_reserve_the_next_assignment()
-        return self.assignments \
-            .filter(is_done=False) \
-            .order_by('-created') \
-            .first()
+class DeletionOfDoneAssignmentsNotPermitted(Exception):
+    pass
 
 
 class TutorSubmissionAssignment(models.Model):
@@ -584,7 +574,7 @@ class TutorSubmissionAssignment(models.Model):
     submission = models.ForeignKey(Submission,
                                    on_delete=models.CASCADE,
                                    related_name='assignments')
-    subscription = models.ForeignKey(GeneralTaskSubscription,
+    subscription = models.ForeignKey(SubmissionSubscription,
                                      on_delete=models.CASCADE,
                                      related_name='assignments')
     is_done = models.BooleanField(default=False)
@@ -599,6 +589,11 @@ class TutorSubmissionAssignment(models.Model):
         return (f'{self.subscription.owner} assigned to {self.submission}'
                 f' (done={self.is_done})')
 
+    def delete(self, *args, **kwargs):
+        if self.is_done:
+            raise DeletionOfDoneAssignmentsNotPermitted()
+        super().delete(*args, **kwargs)
+
 
 class FeedbackComment(models.Model):
 
diff --git a/core/serializers/feedback.py b/core/serializers/feedback.py
index 95e0e0d92baf9f37d9b5a1de83638d06984a2489..b57b21a69c12a64f6ac44ef4a0e3e38d646023a6 100644
--- a/core/serializers/feedback.py
+++ b/core/serializers/feedback.py
@@ -1,14 +1,13 @@
 import logging
 from collections import defaultdict
 
-from django.core.exceptions import ObjectDoesNotExist
 from django.db import transaction
 from django.db.models.manager import Manager
 from rest_framework import serializers
 from rest_framework.utils import html
 
 from core import models
-from core.models import Feedback, TutorSubmissionAssignment
+from core.models import Feedback
 from util.factories import GradyUserFactory
 
 from .generic import DynamicFieldsModelSerializer
@@ -82,16 +81,16 @@ class FeedbackCommentSerializer(serializers.ModelSerializer):
 
 
 class FeedbackSerializer(DynamicFieldsModelSerializer):
-    pk = serializers.ReadOnlyField(source='of_submission.pk')
-    assignment_pk = serializers.UUIDField(write_only=True)
     feedback_lines = FeedbackCommentSerializer(many=True, required=False)
 
     @transaction.atomic
     def create(self, validated_data) -> Feedback:
-        assignment = validated_data.pop('assignment_pk')
+        submission = validated_data.pop('of_submission')
+        assignment = submission.assignments.get(
+            subscription__owner=self.context['request'].user)
         feedback_lines = validated_data.pop('feedback_lines', [])
 
-        feedback = Feedback.objects.create(of_submission=assignment.submission,
+        feedback = Feedback.objects.create(of_submission=submission,
                                            **validated_data)
 
         for comment in feedback_lines:
@@ -102,7 +101,7 @@ class FeedbackSerializer(DynamicFieldsModelSerializer):
             )
 
         assignment.set_done()
-        return Feedback.objects.get(of_submission=assignment.submission)
+        return Feedback.objects.get(of_submission=submission)
 
     @transaction.atomic
     def update(self, instance, validated_data):
@@ -115,21 +114,26 @@ class FeedbackSerializer(DynamicFieldsModelSerializer):
 
         return super().update(instance, validated_data)
 
-    def validate_assignment_pk(self, assignment_pk):
-        try:
-            assignment = TutorSubmissionAssignment.objects.get(
-                pk=assignment_pk)
-        except ObjectDoesNotExist as err:
-            raise serializers.ValidationError('No assignment for given id.')
+    def validate_of_submission(self, submission):
+        feedback = self.instance
+        if feedback is not None and feedback.submission is not submission:
+            raise serializers.ValidationError(
+                'It is not allowed to update this field.')
 
-        return assignment
+        return submission
 
     def validate(self, data):
-        log.debug("Validate feedback data: %s", data)
-        score = data.get('score')
-        assignment = data.get('assignment_pk')
+        if self.instance:
+            score = data.get('score', self.instance.score)
+            submission = data.get('of_submission', self.instance.of_submission)
+        else:
+            try:
+                score = data.get('score')
+                submission = data.get('of_submission')
+            except KeyError as err:
+                raise serializers.ValidationError(
+                    'You need a score and a submission.')
 
-        submission = assignment.submission
         if not 0 <= score <= submission.type.full_score:
             raise serializers.ValidationError(
                 f'Score has to be in range [0..{submission.type.full_score}].')
@@ -157,4 +161,4 @@ class FeedbackSerializer(DynamicFieldsModelSerializer):
 
     class Meta:
         model = Feedback
-        fields = ('pk', 'assignment_pk', 'is_final', 'score', 'feedback_lines')
+        fields = ('pk', 'of_submission', 'is_final', 'score', 'feedback_lines')
diff --git a/core/serializers/subscription.py b/core/serializers/subscription.py
index 9bbeaab5b978848562f33204a657add21a55d8e5..ef9a63c808ebb7d13d25a76a64d394893c7f9e66 100644
--- a/core/serializers/subscription.py
+++ b/core/serializers/subscription.py
@@ -1,18 +1,24 @@
-from django.core.exceptions import ObjectDoesNotExist
 from rest_framework import serializers
 
-from core.models import (GeneralTaskSubscription, Submission,
+from core.models import (Submission, SubmissionSubscription,
                          TutorSubmissionAssignment)
 from core.serializers import DynamicFieldsModelSerializer, FeedbackSerializer
 
 
 class AssignmentSerializer(DynamicFieldsModelSerializer):
-    submission_pk = serializers.ReadOnlyField(
-        source='submission.pk')
+    submission_pk = serializers.ReadOnlyField(source='submission.pk')
 
     class Meta:
         model = TutorSubmissionAssignment
-        fields = ('pk', 'submission_pk', 'is_done',)
+        fields = ('pk', 'submission_pk', 'is_done', 'subscription',)
+        read_only_fields = ('is_done',)
+        extra_kwargs = {
+            'subscription': {'write_only': True},
+        }
+
+    def create(self, validated_data):
+        subscription = validated_data.get('subscription')
+        return subscription.get_or_create_work_assignment()
 
 
 class SubmissionAssignmentSerializer(DynamicFieldsModelSerializer):
@@ -43,33 +49,28 @@ class SubscriptionSerializer(DynamicFieldsModelSerializer):
         data['owner'] = self.context['request'].user
 
         if 'query_key' in data != \
-                data['query_type'] == GeneralTaskSubscription.RANDOM:
+                data['query_type'] == SubmissionSubscription.RANDOM:
             raise serializers.ValidationError(
                 f'The {data["query_type"]} query_type does not work with the'
                 f'provided key')
 
-        try:
-            GeneralTaskSubscription.objects.get(
-                owner=data['owner'],
-                query_type=data['query_type'],
-                query_key=data.get('query_key', None))
-        except ObjectDoesNotExist:
-            pass
-        else:
-            raise serializers.ValidationError(
-                'The user already has the subscription')
-
         return data
 
-    def create(self, validated_data) -> GeneralTaskSubscription:
-        return GeneralTaskSubscription.objects.create(**validated_data)
+    def create(self, validated_data) -> SubmissionSubscription:
+        return SubmissionSubscription.objects.create(**validated_data)
+
+    def update(self, instance, validated_data):
+        instance.deactivated = False
+        instance.save()
+        return instance
 
     class Meta:
-        model = GeneralTaskSubscription
-        fields = (
-            'pk',
-            'owner',
-            'query_type',
-            'query_key',
-            'assignments',
-            'feedback_stage')
+        model = SubmissionSubscription
+        fields = ('pk',
+                  'owner',
+                  'query_type',
+                  'query_key',
+                  'feedback_stage',
+                  'deactivated',
+                  'assignments')
+        read_only_fields = ('deactivated',)
diff --git a/core/tests/test_feedback.py b/core/tests/test_feedback.py
index 17b3cbfdc323f8ca76941873384067bda7b2c6bd..8397faf857442bedefecefef8d29b71355c06adf 100644
--- a/core/tests/test_feedback.py
+++ b/core/tests/test_feedback.py
@@ -109,7 +109,7 @@ class FeedbackCreateTestCase(APITestCase):
 
     def setUp(self):
         self.client.force_authenticate(user=self.tutor)
-        self.subscription = models.GeneralTaskSubscription.objects.create(
+        self.subscription = models.SubmissionSubscription.objects.create(
             owner=self.tutor,
             query_type='random',
             query_key=''
@@ -123,7 +123,7 @@ class FeedbackCreateTestCase(APITestCase):
         data = {
             'score': 10,
             'is_final': False,
-            'assignment_pk': self.assignment.pk
+            'of_submission': self.assignment.submission.pk
 
         }
         self.assertEqual(Feedback.objects.count(), 0)
@@ -135,7 +135,7 @@ class FeedbackCreateTestCase(APITestCase):
         data = {
             'score': 101,
             'is_final': False,
-            'assignment_pk': self.assignment.pk
+            'of_submission': self.assignment.submission.pk
         }
         self.assertEqual(Feedback.objects.count(), 0)
         response = self.client.post(self.url, data, format='json')
@@ -146,7 +146,7 @@ class FeedbackCreateTestCase(APITestCase):
         data = {
             'score': 100,
             'is_final': True,
-            'assignment_pk': self.assignment.assignment_id
+            'of_submission': self.assignment.submission.pk
         }
         response = self.client.post(self.url, data, format='json')
         self.assertEqual(status.HTTP_403_FORBIDDEN, response.status_code)
@@ -156,7 +156,7 @@ class FeedbackCreateTestCase(APITestCase):
         data = {
             'score': 50,
             'is_final': False,
-            'assignment_pk': self.assignment.assignment_id
+            'of_submission': self.assignment.submission.pk
         }
         response = self.client.post(self.url, data, format='json')
         self.assertEqual(status.HTTP_400_BAD_REQUEST, response.status_code)
@@ -166,7 +166,7 @@ class FeedbackCreateTestCase(APITestCase):
         data = {
             'score': -1,
             'is_final': False,
-            'assignment_pk': self.assignment.pk
+            'of_submission': self.assignment.submission.pk
         }
         self.assertEqual(Feedback.objects.count(), 0)
         response = self.client.post(self.url, data, format='json')
@@ -177,7 +177,7 @@ class FeedbackCreateTestCase(APITestCase):
         data = {
             'score': 5,
             'is_final': False,
-            'assignment_pk': self.assignment.pk,
+            'of_submission': self.assignment.submission.pk,
             'feedback_lines': {
                 '4': {
                     'text': 'Why you no learn how to code, man?'
@@ -192,7 +192,7 @@ class FeedbackCreateTestCase(APITestCase):
         data = {
             'score': 0,
             'is_final': False,
-            'assignment_pk': self.assignment.pk,
+            'of_submission': self.assignment.submission.pk,
             'feedback_lines': {
                 '4': {
                     'text': 'Nice meth!'
@@ -208,7 +208,7 @@ class FeedbackCreateTestCase(APITestCase):
         data = {
             'score': 0,
             'is_final': False,
-            'assignment_pk': self.assignment.pk,
+            'of_submission': self.assignment.submission.pk,
             'feedback_lines': {
                 '3': {
                     'text': 'Nice meth!'
@@ -226,7 +226,7 @@ class FeedbackCreateTestCase(APITestCase):
     def test_cannot_create_without_assignment(self):
         data = {
             'score': 0,
-            'assignment_pk': self.assignment.assignment_id,
+            'of_submission': self.assignment.submission.pk,
             'feedback_lines': {
                 '2': {
                     'text': 'Well, at least you tried.'
@@ -235,12 +235,12 @@ class FeedbackCreateTestCase(APITestCase):
         }
         self.assignment.delete()
         response = self.client.post(self.url, data, format='json')
-        self.assertEqual(status.HTTP_400_BAD_REQUEST, response.status_code)
+        self.assertEqual(status.HTTP_403_FORBIDDEN, response.status_code)
 
     def test_cannot_create_with_someoneelses_assignment(self):
         data = {
             'score': 0,
-            'assignment_pk': self.assignment.assignment_id,
+            'of_submission': self.assignment.submission.pk,
             'feedback_lines': {
                 '1': {
                     'text': 'Well, at least you tried.'
@@ -256,7 +256,7 @@ class FeedbackCreateTestCase(APITestCase):
         data = {
             'score': 0,
             'is_final': False,
-            'assignment_pk': self.assignment.pk,
+            'of_submission': self.assignment.submission.pk,
             'feedback_lines': {
                 '1': {
                     'text': 'Nice meth!'
@@ -316,7 +316,7 @@ class FeedbackPatchTestCase(APITestCase):
         self.tutor01 = self.data['tutors'][0]
         self.tutor02 = self.data['tutors'][1]
         self.client.force_authenticate(user=self.tutor01)
-        self.subscription = models.GeneralTaskSubscription.objects.create(
+        self.subscription = models.SubmissionSubscription.objects.create(
             owner=self.tutor01,
             query_type='random',
             query_key=''
@@ -325,13 +325,14 @@ class FeedbackPatchTestCase(APITestCase):
         data = {
             'score': 35,
             'is_final': False,
-            'assignment_pk': self.assignment.assignment_id,
+            'of_submission': self.assignment.submission.pk,
             'feedback_lines': {
                 '2': {'text': 'Very good.'},
             }
         }
         response = self.client.post(self.burl, data, format='json')
-        self.feedback = Feedback.objects.get(of_submission=response.data['pk'])
+        self.feedback = Feedback.objects.get(
+            of_submission=response.data['of_submission'])
         self.url = f'{self.burl}{self.feedback.of_submission.submission_id}/'
 
     def test_can_patch_onto_the_own_feedback(self):
@@ -363,7 +364,7 @@ class FeedbackPatchTestCase(APITestCase):
 
     def test_tutor_can_not_update_when_there_is_a_new_assignment(self):
         # Step 1 - Create a new assignment
-        second_subs = models.GeneralTaskSubscription.objects.create(
+        second_subs = models.SubmissionSubscription.objects.create(
             owner=self.tutor02,
             query_type='random',
             feedback_stage='feedback-validation'
diff --git a/core/tests/test_subscription_assignment_service.py b/core/tests/test_subscription_assignment_service.py
index 01d418e0b075fa7a14e2e100acc473d7b9a027af..247217068f1dc97c57d04cf7f9afeaebb65585d8 100644
--- a/core/tests/test_subscription_assignment_service.py
+++ b/core/tests/test_subscription_assignment_service.py
@@ -2,12 +2,12 @@ from rest_framework import status
 from rest_framework.test import APIClient, APITestCase
 
 from core import models
-from core.models import (GeneralTaskSubscription, Submission, SubmissionType,
-                         SubscriptionEnded)
+from core.models import (Submission, SubmissionSubscription, SubmissionType,
+                         SubscriptionEnded, SubscriptionTemporarilyEnded)
 from util.factories import GradyUserFactory, make_test_data
 
 
-class GeneralTaskSubscriptionRandomTest(APITestCase):
+class SubmissionSubscriptionRandomTest(APITestCase):
 
     @classmethod
     def setUpTestData(cls):
@@ -27,36 +27,69 @@ class GeneralTaskSubscriptionRandomTest(APITestCase):
             type=self.submission_type, student=self.s2.student,
             text='I like apples')
 
-        self.subscription = GeneralTaskSubscription.objects.create(
-            owner=self.t, query_type=GeneralTaskSubscription.RANDOM)
+        self.subscription = SubmissionSubscription.objects.create(
+            owner=self.t, query_type=SubmissionSubscription.RANDOM)
 
     def test_subscription_gets_an_assignment(self):
-        self.subscription._create_new_assignment_if_subscription_empty()
+        self.subscription.get_or_create_work_assignment()
         self.assertEqual(1, self.subscription.assignments.count())
 
     def test_first_work_assignment_was_created_unfinished(self):
-        self.subscription._create_new_assignment_if_subscription_empty()
+        self.subscription.get_or_create_work_assignment()
         self.assertFalse(self.subscription.assignments.first().is_done)
 
     def test_subscription_raises_error_when_depleted(self):
         self.submission_01.delete()
         self.submission_02.delete()
         try:
-            self.subscription._create_new_assignment_if_subscription_empty()
+            self.subscription.get_or_create_work_assignment()
         except SubscriptionEnded as err:
             self.assertFalse(False)
         else:
             self.assertTrue(False)
 
     def test_can_prefetch(self):
-        self.subscription._create_new_assignment_if_subscription_empty()
-        self.subscription._eagerly_reserve_the_next_assignment()
+        self.subscription.get_or_create_work_assignment()
+        self.subscription.get_or_create_work_assignment()
         self.assertEqual(2, self.subscription.assignments.count())
 
-    def test_oldest_assignment_is_current(self):
-        assignment = self.subscription.get_oldest_unfinished_assignment()
-        self.assertEqual(assignment,
-                         self.subscription.get_oldest_unfinished_assignment())
+    def test_new_subscription_is_temporarily_unavailabe(self):
+        validation = SubmissionSubscription.objects.create(
+            owner=self.t, query_type=SubmissionSubscription.RANDOM,
+            feedback_stage=SubmissionSubscription.FEEDBACK_VALIDATION)
+        try:
+            validation.get_or_create_work_assignment()
+        except SubscriptionTemporarilyEnded as err:
+            self.assertTrue(True)
+        else:
+            self.assertTrue(False)
+
+    def test_delete_with_done_assignments_subscription_remains(self):
+        first = self.subscription.get_or_create_work_assignment()
+        self.subscription.get_or_create_work_assignment()
+        self.assertEqual(2, self.subscription.assignments.count())
+
+        first.is_done = True
+        first.save()
+        self.subscription.delete()
+        self.assertEqual(1, self.subscription.assignments.count())
+
+    def test_delete_without_done_assignments_subscription_is_deleted(self):
+        self.subscription.delete()
+        self.assertEqual(0, models.SubmissionSubscription.objects.count())
+
+    def test_assignment_delete_of_done_not_permitted(self):
+        first = self.subscription.get_or_create_work_assignment()
+        first.is_done = True
+        first.save()
+
+        self.assertRaises(models.DeletionOfDoneAssignmentsNotPermitted,
+                          first.delete)
+
+    def test_assignment_delete_undone_permitted(self):
+        first = self.subscription.get_or_create_work_assignment()
+        first.delete()
+        self.assertEqual(0, self.subscription.assignments.count())
 
 
 class TestApiEndpoints(APITestCase):
@@ -158,22 +191,31 @@ class TestApiEndpoints(APITestCase):
         client = APIClient()
         client.force_authenticate(user=self.data['tutors'][0])
 
-        response_subs = client.post(
+        response_subscription_create = client.post(
             '/api/subscription/', {'query_type': 'random'})
-        subscription_id = response_subs.data['pk']
-        assignment_pk = response_subs.data['assignments'][0]['pk']
+        subscription_pk = response_subscription_create.data['pk']
 
-        response = client.get(
-            f'/api/subscription/{subscription_id}/assignments/current/')
+        subscription_pk = response_subscription_create.data['pk']
+        response_assignment = client.post(
+            f'/api/assignment/', {
+                'subscription': subscription_pk
+            })
+
+        assignment_pk = response_assignment.data['pk']
+        response_subscription = client.get(
+            f'/api/subscription/{subscription_pk}/')
 
-        self.assertEqual(1, len(response_subs.data['assignments']))
-        self.assertEqual(assignment_pk,
-                         response.data['pk'])
+        self.assertEqual(1, len(response_subscription.data['assignments']))
+        self.assertEqual(response_assignment.data['pk'],
+                         response_subscription.data['assignments'][0]['pk'])
 
-        response_next = client.get(
-            f'/api/subscription/{subscription_id}/assignments/next/')
+        subscription_pk = response_subscription.data['pk']
+        response_next = client.post(
+            f'/api/assignment/', {
+                'subscription': subscription_pk
+            })
         response_detail_subs = \
-            client.get(f'/api/subscription/{subscription_id}/')
+            client.get(f'/api/subscription/{subscription_pk}/')
 
         self.assertEqual(2, len(response_detail_subs.data['assignments']))
         self.assertNotEqual(assignment_pk, response_next.data['pk'])
@@ -205,13 +247,17 @@ class TestApiEndpoints(APITestCase):
                 'feedback_stage': 'feedback-creation'
             })
 
-        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
+        self.assertEqual(status.HTTP_201_CREATED, response.status_code)
 
-        assignment_pk = response.data['assignments'][0]['pk']
+        subscription_pk = response.data['pk']
+        response = client.post(
+            f'/api/assignment/', {
+                'subscription': subscription_pk
+            })
         response = client.post(
             f'/api/feedback/', {
                 "score": 23,
-                "assignment_pk": assignment_pk,
+                "of_submission": response.data['submission']['pk'],
                 "feedback_lines": {
                     2: {"text": "< some string >"},
                     3: {"text": "< some string >"}
@@ -219,7 +265,7 @@ class TestApiEndpoints(APITestCase):
             }
         )
         print(response, response.data)
-        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
+        self.assertEqual(status.HTTP_201_CREATED, response.status_code)
 
         # some other tutor reviews it
         client.force_authenticate(user=self.data['tutors'][1])
@@ -230,13 +276,15 @@ class TestApiEndpoints(APITestCase):
                 'feedback_stage': 'feedback-validation'
             })
 
-        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
+        self.assertEqual(status.HTTP_201_CREATED, response.status_code)
 
-        subscription_id = response.data['pk']
-        response = client.get(
-            f'/api/subscription/{subscription_id}/assignments/current/')
+        subscription_pk = response.data['pk']
+        response = client.post(
+            f'/api/assignment/', {
+                'subscription': subscription_pk
+            })
 
-        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual(status.HTTP_201_CREATED, response.status_code)
         submission_id_in_database = models.Feedback.objects.filter(
             is_final=False).first().of_submission.submission_id
         submission_id_in_response = \
diff --git a/core/urls.py b/core/urls.py
index e11beea8bfb4f019b0c240fd94676188582b127f..3eaaa62d63a7b35e7c17b9c039bb55115ee92394 100644
--- a/core/urls.py
+++ b/core/urls.py
@@ -12,7 +12,8 @@ router.register('examtype', views.ExamApiViewSet)
 router.register('feedback', views.FeedbackApiView)
 router.register('submissiontype', views.SubmissionTypeApiView)
 router.register('tutor', views.TutorApiViewSet, base_name='tutor')
-router.register('subscription', views.SubscriptionApiViewSet)
+router.register('subscription', views.SubscriptionApiViewSet,
+                base_name='subscription')
 router.register('assignment', views.AssignmentApiViewSet)
 
 # regular views that are not viewsets
diff --git a/core/views/feedback.py b/core/views/feedback.py
index 4bdf36f69e78debc9ad521f20c4542cadd0bd58b..f0af99b1fa828822e3c77f8ff3ba87e49b9221b1 100644
--- a/core/views/feedback.py
+++ b/core/views/feedback.py
@@ -24,9 +24,19 @@ class FeedbackApiView(
         user_is_tutor = self.request.user.role == models.UserAccount.TUTOR
         return feedback_is_final and user_is_tutor
 
+    def _get_implicit_assignment_for_user(self, submission):
+        return models.TutorSubmissionAssignment.objects.get(
+            subscription__owner=self.request.user,
+            submission=submission
+        )
+
     def _request_user_does_not_own_assignment(self, serializer):
-        assignment = serializer.validated_data['assignment_pk']
-        return assignment.subscription.owner != self.request.user
+        try:
+            submission = serializer.validated_data['of_submission']
+            assignment = self._get_implicit_assignment_for_user(submission)
+            return assignment.subscription.owner != self.request.user
+        except models.TutorSubmissionAssignment.DoesNotExist as err:
+            return True
 
     def _tutor_attempts_to_set_first_feedback_final(self, serializer):
         is_final_set = serializer.validated_data.get('is_final', False)
@@ -34,18 +44,20 @@ class FeedbackApiView(
         return is_final_set and user_is_tutor
 
     def _tutor_is_allowed_to_change_own_feedback(self, serializer):
-        assignment = serializer.validated_data['assignment_pk']
-        youngest = models.TutorSubmissionAssignment.objects\
-            .filter(submission=assignment.submission)\
-            .order_by('-created')\
+        submission = self.get_object().of_submission
+        assignment = self._get_implicit_assignment_for_user(submission)
+        youngest = models.TutorSubmissionAssignment.objects \
+            .filter(submission=submission) \
+            .order_by('-created') \
             .first()
 
         return assignment == youngest
 
     def _tutor_attempts_to_patch_first_feedback_final(self, serializer):
         is_final_set = serializer.validated_data.get('is_final', False)
-        assignment = serializer.validated_data.get('assignment_pk')
-        in_creation = assignment.subscription.feedback_stage == models.GeneralTaskSubscription.FEEDBACK_CREATION  # noqa
+        submission = self.get_object().of_submission
+        assignment = self._get_implicit_assignment_for_user(submission)
+        in_creation = assignment.subscription.feedback_stage == models.SubmissionSubscription.FEEDBACK_CREATION  # noqa
         return is_final_set and in_creation
 
     def create(self, request, *args, **kwargs):
@@ -54,12 +66,12 @@ class FeedbackApiView(
 
         if self._tutor_attempts_to_set_first_feedback_final(serializer):
             return Response(
-                {'It is not allowed to create feedback final for tutors'},
+                {'For tutors it is not allowed to create feedback final.'},
                 status=status.HTTP_403_FORBIDDEN)
 
         if self._request_user_does_not_own_assignment(serializer):
             return Response(
-                {'This user has not permission to create this feedback'},
+                {'This user has no permission to create this feedback'},
                 status=status.HTTP_403_FORBIDDEN)
 
         self.perform_create(serializer)
@@ -68,22 +80,13 @@ class FeedbackApiView(
 
     def partial_update(self, request, **kwargs):
         feedback = self.get_object()
-        assignment = models.TutorSubmissionAssignment.objects.get(
-            subscription__owner=request.user,
-            submission=feedback.of_submission
-        )
-        serializer = self.get_serializer(
-            feedback,
-            data={'assignment_pk': assignment.pk,
-                  'score': feedback.score,
-                  **request.data},
-            partial=True)
+        serializer = self.get_serializer(feedback, data=request.data,
+                                         partial=True)
 
         serializer.is_valid(raise_exception=True)
-
         if self._tutor_attempts_to_change_final_feedback(serializer):
             return Response(
-                {'Cannot set the first feedback final unless user reviewer'},
+                {"Changing final feedback is not allowed"},
                 status=status.HTTP_403_FORBIDDEN)
 
         if self._tutor_attempts_to_patch_first_feedback_final(serializer):
diff --git a/core/views/subscription.py b/core/views/subscription.py
index e1920b3b200181284064e316c3b38e46c0869746..66908d69c963636f17f4adec9342888e274db88f 100644
--- a/core/views/subscription.py
+++ b/core/views/subscription.py
@@ -1,13 +1,13 @@
 import logging
 
+from django.core.exceptions import ObjectDoesNotExist
 from rest_framework import mixins, status, viewsets
-from rest_framework.decorators import detail_route
 from rest_framework.response import Response
 
 from core import models, permissions, serializers
 from core.models import TutorSubmissionAssignment
 from core.permissions import IsTutorOrReviewer
-from core.serializers import AssignmentSerializer
+from core.serializers import AssignmentDetailSerializer, AssignmentSerializer
 
 log = logging.getLogger(__name__)
 
@@ -15,64 +15,45 @@ log = logging.getLogger(__name__)
 class SubscriptionApiViewSet(
         mixins.RetrieveModelMixin,
         mixins.CreateModelMixin,
+        mixins.DestroyModelMixin,
         mixins.ListModelMixin,
         viewsets.GenericViewSet):
     permission_classes = (permissions.IsTutorOrReviewer,)
-    queryset = models.GeneralTaskSubscription.objects.all()
     serializer_class = serializers.SubscriptionSerializer
 
-    def fetch_assignment(self,
-                         request,
-                         assignment_fetcher,
-                         error_message):
-        try:
-            assignment = assignment_fetcher()
-        except models.SubscriptionEnded as err:
-            return Response(
-                {'Error': error_message},
-                status=status.HTTP_410_GONE)
-        serializer = serializers.AssignmentDetailSerializer(assignment)
-        return Response(serializer.data)
-
-    @detail_route(methods=['get'], url_path='assignments/current')
-    def current_assignment(self, request, pk=None):
-        subscription = self.get_object()
-
-        return self.fetch_assignment(
-            request,
-            subscription.get_oldest_unfinished_assignment,
-            'Seems this subscription has ended')
-
-    @detail_route(methods=['get'], url_path='assignments/next')
-    def next_assignment(self, request, pk=None):
-        subscription = self.get_object()
-
-        return self.fetch_assignment(
-            request,
-            subscription.get_youngest_unfinished_assignment,
-            'Seems there is nothing left to prefetch')
-
     def get_queryset(self):
-        return models.GeneralTaskSubscription.objects.filter(
+        return models.SubmissionSubscription.objects.filter(
             owner=self.request.user)
 
-    def destroy(self, request, pk=None):
-        instance = self.get_object()
-
-        raise NotImplemented  # todo: just impl. deactivate and reactivate
-
-        instance.delete()
-        return Response(status=status.HTTP_204_NO_CONTENT)
+    def _get_subscription_if_type_exists(self, data):
+        try:
+            return models.SubmissionSubscription.objects.get(
+                owner=self.request.user,
+                query_type=data.get('query_type', ''),
+                query_key=data.get('query_key', ''),
+                feedback_stage=data.get(
+                    'feedback_stage',
+                    models.SubmissionSubscription.FEEDBACK_CREATION)
+            )
+        except ObjectDoesNotExist:
+            return None
 
     def create(self, request, *args, **kwargs):
-        serializer = self.get_serializer(data=request.data)
+        subscription = self._get_subscription_if_type_exists(request.data)
+        if subscription and not subscription.deactivated:
+            return Response({'Error': 'Subscriptions have to be unique.'},
+                            status.HTTP_409_CONFLICT)
+        elif subscription and subscription.deactivated:
+            serializer = self.get_serializer(subscription,
+                                             data=request.data)
+        else:
+            serializer = self.get_serializer(data=request.data)
+
         serializer.is_valid(raise_exception=True)
         subscription = serializer.save()
 
-        if subscription.query_type == models.GeneralTaskSubscription.STUDENT_QUERY:  # noqa TODO refactor name of generaltasksubscription to SubmissionSubscription
+        if subscription.query_type == models.SubmissionSubscription.STUDENT_QUERY:  # noqa TODO refactor name of generaltasksubscription to SubmissionSubscription
             subscription.reserve_all_assignments_for_a_student()
-        else:
-            subscription.get_oldest_unfinished_assignment()
 
         headers = self.get_success_headers(serializer.data)
         return Response(serializer.data,
@@ -88,6 +69,21 @@ class AssignmentApiViewSet(
     queryset = TutorSubmissionAssignment.objects.all()
     serializer_class = AssignmentSerializer
 
+    def _fetch_assignment(self, serializer):
+        try:
+            serializer.save()
+        except models.SubscriptionEnded as err:
+            return Response({'Error': str(err)},
+                            status=status.HTTP_410_GONE)
+        except models.SubscriptionTemporarilyEnded as err:
+            return Response({'Error': str(err)},
+                            status=status.HTTP_404_NOT_FOUND)
+        except models.NotMoreThanTwoOpenAssignmentsAllowed as err:
+            return Response({'Error': str(err)},
+                            status=status.HTTP_403_FORBIDDEN)
+        serializer = AssignmentDetailSerializer(serializer.instance)
+        return Response(serializer.data, status=status.HTTP_201_CREATED)
+
     def get_queryset(self):
         """ Get only assignments of that user """
         return TutorSubmissionAssignment.objects.filter(
@@ -98,7 +94,12 @@ class AssignmentApiViewSet(
         instance = self.get_object()
 
         if instance.is_done:
-            return Response(status=status.HTTP_403_FORBIDDEN)  # test
+            return Response(status=status.HTTP_403_FORBIDDEN)
 
         instance.delete()
-        return Response(status=status.HTTP_204_NO_CONTENT)  # test
+        return Response(status=status.HTTP_204_NO_CONTENT)
+
+    def create(self, request, *args, **kwargs):
+        serializer = self.get_serializer(data=request.data)
+        serializer.is_valid(raise_exception=True)
+        return self._fetch_assignment(serializer)