diff --git a/submissions/exceptions.py b/submissions/exceptions.py
new file mode 100644
index 0000000000000000000000000000000000000000..19c5684bd004f175ffe4169cc2938d312d66edf0
--- /dev/null
+++ b/submissions/exceptions.py
@@ -0,0 +1,6 @@
+class CycleUpdateDeadlineError(Exception):
+    def __init__(self, name):
+        self.name = name
+
+    def __str__(self):
+        return self.name
diff --git a/submissions/factories.py b/submissions/factories.py
index cdf905fb56b2672019ee707381672388a939eba3..da936a2e7a8fcbe4d2d9225a6d4a83f2b4f812da 100644
--- a/submissions/factories.py
+++ b/submissions/factories.py
@@ -1,16 +1,14 @@
 import factory
-import datetime
 import pytz
 
 from django.utils import timezone
 
-from scipost.factories import ContributorFactory
 from scipost.models import Contributor
 from journals.constants import SCIPOST_JOURNALS_DOMAINS
 from common.helpers import random_arxiv_identifier_without_version_number, random_scipost_journal
 
 from .constants import STATUS_UNASSIGNED, STATUS_EIC_ASSIGNED, STATUS_RESUBMISSION_INCOMING,\
-                       STATUS_PUBLISHED
+                       STATUS_PUBLISHED, SUBMISSION_TYPE
 from .models import Submission
 
 from faker import Faker
@@ -21,7 +19,7 @@ class SubmissionFactory(factory.django.DjangoModelFactory):
         model = Submission
 
     author_list = factory.Faker('name')
-    submitted_by = factory.SubFactory(ContributorFactory)
+    submitted_by = Contributor.objects.first()
     submitted_to_journal = factory.Sequence(lambda n: random_scipost_journal())
     title = factory.lazy_attribute(lambda x: Faker().sentence())
     abstract = factory.lazy_attribute(lambda x: Faker().paragraph())
@@ -32,7 +30,8 @@ class SubmissionFactory(factory.django.DjangoModelFactory):
     abstract = Faker().paragraph()
     author_comments = Faker().paragraph()
     remarks_for_editors = Faker().paragraph()
-    submission_type = 'Letter'
+    submission_type = factory.Iterator(SUBMISSION_TYPE, getter=lambda c: c[0])
+    is_current = True
 
     @factory.post_generation
     def fill_arxiv_fields(self, create, extracted, **kwargs):
@@ -43,11 +42,13 @@ class SubmissionFactory(factory.django.DjangoModelFactory):
 
     @factory.post_generation
     def contributors(self, create, extracted, **kwargs):
-        contributors = list(Contributor.objects.order_by('?')
-                            .exclude(pk=self.submitted_by.pk).all()[:3])
+        contributors = list(Contributor.objects.order_by('?')[:4])
+
+        # Auto-add the submitter as an author
+        self.submitted_by = contributors.pop()
+
         if not create:
             return
-        # Auto-add the submitter as an author
         self.authors.add(self.submitted_by)
 
         # Add three random authors
@@ -60,11 +61,13 @@ class SubmissionFactory(factory.django.DjangoModelFactory):
         timezone.now()
         if kwargs.get('submission', False):
             self.submission_date = kwargs['submission']
-        else:
-            self.submission_date = Faker().date_time_between(start_date="-3y", end_date="now",
-                                                             tzinfo=pytz.UTC)
+            self.cycle.update_deadline()
+            return
+        self.submission_date = Faker().date_time_between(start_date="-3y", end_date="now",
+                                                         tzinfo=pytz.UTC).date()
         self.latest_activity = Faker().date_time_between(start_date=self.submission_date,
                                                          end_date="now", tzinfo=pytz.UTC)
+        self.cycle.update_deadline()
 
 
 class UnassignedSubmissionFactory(SubmissionFactory):
@@ -79,24 +82,53 @@ class EICassignedSubmissionFactory(SubmissionFactory):
     open_for_commenting = True
     open_for_reporting = True
 
-    @factory.post_generation
-    def report_dates(self, create, extracted, **kwargs):
-        self.reporting_deadline = self.latest_activity + datetime.timedelta(weeks=2)
-
     @factory.post_generation
     def eic(self, create, extracted, **kwargs):
+        '''Assign an EIC to submission.'''
         author_ids = list(self.authors.values_list('id', flat=True))
         self.editor_in_charge = (Contributor.objects.order_by('?')
                                             .exclude(pk=self.submitted_by.pk)
                                             .exclude(pk__in=author_ids).first())
 
 
-class ResubmittedScreeningSubmissionFactory(SubmissionFactory):
+class ResubmittedSubmissionFactory(SubmissionFactory):
+    '''
+    This Submission is a newer version of a Submission which is
+    already known by the SciPost database.
+    '''
     status = STATUS_RESUBMISSION_INCOMING
+    open_for_commenting = True
+    open_for_reporting = True
+    is_resubmission = True
+
+    @factory.post_generation
+    def alter_arxiv_fields(self, create, extracted, **kwargs):
+        '''Alter arxiv fields to save as version 2.'''
+        self.arxiv_identifier_w_vn_nr = '%sv2' % self.arxiv_identifier_wo_vn_nr
+        self.arxiv_vn_nr = 2
+
+    @factory.post_generation
+    def eic(self, create, extracted, **kwargs):
+        '''Assign an EIC to submission.'''
+        author_ids = list(self.authors.values_list('id', flat=True))
+        self.editor_in_charge = (Contributor.objects.order_by('?')
+                                            .exclude(pk=self.submitted_by.pk)
+                                            .exclude(pk__in=author_ids).first())
+
+    @factory.post_generation
+    def dates(self, create, extracted, **kwargs):
+        """Overwrite the parent `dates` method to skip the update_deadline call."""
+        timezone.now()
+        if kwargs.get('submission', False):
+            self.submission_date = kwargs['submission']
+            return
+        self.submission_date = Faker().date_time_between(start_date="-3y", end_date="now",
+                                                         tzinfo=pytz.UTC).date()
+        self.latest_activity = Faker().date_time_between(start_date=self.submission_date,
+                                                         end_date="now", tzinfo=pytz.UTC)
 
 
 class PublishedSubmissionFactory(SubmissionFactory):
     status = STATUS_PUBLISHED
     open_for_commenting = False
     open_for_reporting = False
-    is_current = True
diff --git a/submissions/migrations/0042_auto_20170511_2321.py b/submissions/migrations/0042_auto_20170511_2321.py
new file mode 100644
index 0000000000000000000000000000000000000000..20b3a653e5fc906c41d3159a46c85278dba8b182
--- /dev/null
+++ b/submissions/migrations/0042_auto_20170511_2321.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.3 on 2017-05-11 21:21
+from __future__ import unicode_literals
+
+import datetime
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('submissions', '0041_auto_20170418_1022'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='submission',
+            name='submission_date',
+            field=models.DateField(default=datetime.date.today, verbose_name='submission date'),
+        ),
+    ]
diff --git a/submissions/models.py b/submissions/models.py
index 0a2b82f9ae8f5dfb2a42b6a9df8c0a3978d772e3..787754332f0ecdd4c01c8b9685b499e84333b448 100644
--- a/submissions/models.py
+++ b/submissions/models.py
@@ -78,7 +78,7 @@ class Submission(ArxivCallable, models.Model):
 
     # Metadata
     metadata = JSONField(default={}, blank=True, null=True)
-    submission_date = models.DateField(verbose_name='submission date', default=timezone.now)
+    submission_date = models.DateField(verbose_name='submission date', default=datetime.date.today)
     latest_activity = models.DateTimeField(default=timezone.now)
 
     objects = SubmissionManager()
diff --git a/submissions/test_utils.py b/submissions/test_utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..36f9a5ca7a3727542c52ff5345ea96dd197c8a3f
--- /dev/null
+++ b/submissions/test_utils.py
@@ -0,0 +1,137 @@
+import datetime
+
+from django.test import TestCase, tag
+
+from common.helpers.test import add_groups_and_permissions
+from scipost.factories import ContributorFactory
+from scipost.models import Contributor
+
+from .constants import STATUS_UNASSIGNED, STATUS_RESUBMISSION_INCOMING, STATUS_AWAITING_ED_REC,\
+                       STATUS_EIC_ASSIGNED, CYCLE_DEFAULT, CYCLE_DIRECT_REC
+from .exceptions import CycleUpdateDeadlineError
+from .factories import UnassignedSubmissionFactory, ResubmittedSubmissionFactory
+from .utils import GeneralSubmissionCycle
+
+
+class TestDefaultSubmissionCycle(TestCase):
+    '''
+    This TestCase should act as a master test to check all steps in the
+    submission's cycle: default.
+    '''
+
+    def setUp(self):
+        """Basics for all tests"""
+        self.submission_date = datetime.date.today()
+        add_groups_and_permissions()
+        ContributorFactory.create_batch(5)
+        self.new_submission = UnassignedSubmissionFactory(
+            dates__submission=self.submission_date
+        )
+
+    @tag('cycle', 'core')
+    def test_init_submission_factory_is_valid(self):
+        """Ensure valid fields for the factory."""
+        self.assertEqual(self.new_submission.status, STATUS_UNASSIGNED)
+        self.assertIsNone(self.new_submission.editor_in_charge)
+        self.assertTrue(self.new_submission.is_current)
+        self.assertFalse(self.new_submission.is_resubmission)
+        self.assertIsNot(self.new_submission.title, '')
+        self.assertIsInstance(self.new_submission.submitted_by, Contributor)
+        self.assertFalse(self.new_submission.open_for_commenting)
+        self.assertFalse(self.new_submission.open_for_reporting)
+        self.assertEqual(self.new_submission.submission_date, self.submission_date)
+
+    @tag('cycle', 'core')
+    def test_initial_cycle_required_actions_and_deadline(self):
+        """Test valid required actions for default cycle."""
+        self.assertIsInstance(self.new_submission.cycle, GeneralSubmissionCycle)
+
+        # Explicit: No actions required if no EIC is assigned yet
+        self.assertFalse(self.new_submission.cycle.get_required_actions())
+
+        # Two weeks deadline check
+        self.new_submission.cycle.update_deadline()
+        real_report_deadline = self.submission_date + datetime.timedelta(days=28)
+        self.assertEqual(self.new_submission.reporting_deadline.day, real_report_deadline.day)
+        self.assertEqual(self.new_submission.reporting_deadline.month, real_report_deadline.month)
+        self.assertEqual(self.new_submission.reporting_deadline.year, real_report_deadline.year)
+        self.assertIsInstance(self.new_submission.reporting_deadline, datetime.datetime)
+
+
+class TestResubmissionSubmissionCycle(TestCase):
+    '''
+    This TestCase should act as a master test to check all steps in the
+    submission's cycle: resubmission.
+    '''
+
+    def setUp(self):
+        """Basics for all tests"""
+        self.submission_date = datetime.date.today()
+        add_groups_and_permissions()
+        ContributorFactory.create_batch(5)
+        self.submission = ResubmittedSubmissionFactory(
+            dates__submission=self.submission_date
+        )
+
+    @tag('cycle', 'core')
+    def test_init_resubmission_factory_is_valid(self):
+        """Ensure valid fields for the factory."""
+        self.assertEqual(self.submission.status, STATUS_RESUBMISSION_INCOMING)
+        self.assertIsInstance(self.submission.editor_in_charge, Contributor)
+        self.assertTrue(self.submission.is_current)
+        self.assertTrue(self.submission.is_resubmission)
+        self.assertIsNot(self.submission.title, '')
+        self.assertIsInstance(self.submission.submitted_by, Contributor)
+        self.assertTrue(self.submission.open_for_commenting)
+        self.assertTrue(self.submission.open_for_reporting)
+        self.assertEqual(self.submission.submission_date, self.submission_date)
+        self.assertEqual(self.submission.refereeing_cycle, CYCLE_DEFAULT)
+
+    @tag('cycle', 'core')
+    def test_initial_cycle_required_actions_and_deadline(self):
+        """Test valid required actions for default cycle."""
+        self.assertRaises(CycleUpdateDeadlineError, self.submission.cycle.update_deadline)
+
+        # Update status for default cycle to check new status
+        self.submission.cycle.update_status()
+        self.assertEqual(self.submission.status, STATUS_EIC_ASSIGNED)
+
+
+class TestResubmissionDirectSubmissionCycle(TestCase):
+    '''
+    This TestCase should act as a master test to check all steps in the
+    submission's cycle: resubmission (cycle: DIRECT_RECOMMENDATION).
+    '''
+
+    def setUp(self):
+        """Basics for all tests"""
+        self.submission_date = datetime.date.today()
+        add_groups_and_permissions()
+        ContributorFactory.create_batch(5)
+        self.submission = ResubmittedSubmissionFactory(
+            dates__submission=self.submission_date,
+            refereeing_cycle=CYCLE_DIRECT_REC
+        )
+
+    @tag('cycle', 'core')
+    def test_init_resubmission_factory_is_valid(self):
+        """Ensure valid fields for the factory."""
+        self.assertEqual(self.submission.status, STATUS_RESUBMISSION_INCOMING)
+        self.assertIsInstance(self.submission.editor_in_charge, Contributor)
+        self.assertTrue(self.submission.is_current)
+        self.assertTrue(self.submission.is_resubmission)
+        self.assertIsNot(self.submission.title, '')
+        self.assertIsInstance(self.submission.submitted_by, Contributor)
+        self.assertTrue(self.submission.open_for_commenting)
+        self.assertTrue(self.submission.open_for_reporting)
+        self.assertEqual(self.submission.submission_date, self.submission_date)
+        self.assertEqual(self.submission.refereeing_cycle, CYCLE_DIRECT_REC)
+
+    @tag('cycle', 'core')
+    def test_initial_cycle_required_actions_and_deadline(self):
+        """Test valid required actions for default cycle."""
+        self.assertRaises(CycleUpdateDeadlineError, self.submission.cycle.update_deadline)
+
+        # Update status for default cycle to check new status
+        self.submission.cycle.update_status()
+        self.assertEqual(self.submission.status, STATUS_AWAITING_ED_REC)
diff --git a/submissions/utils.py b/submissions/utils.py
index d713236f3f2b66dab3fd04300962da4ece33e9a6..29ed7e85be4febc089c51bd4b476b66f3db4c21a 100644
--- a/submissions/utils.py
+++ b/submissions/utils.py
@@ -7,6 +7,7 @@ from django.utils import timezone
 from .constants import NO_REQUIRED_ACTION_STATUSES,\
                        STATUS_REVISION_REQUESTED, STATUS_EIC_ASSIGNED,\
                        STATUS_RESUBMISSION_INCOMING, STATUS_AWAITING_ED_REC
+from .exceptions import CycleUpdateDeadlineError
 
 from scipost.utils import EMAIL_FOOTER
 from common.utils import BaseMailUtil
@@ -112,11 +113,19 @@ class BaseSubmissionCycle:
                 SubmissionUtils.reinvite_referees_email()
 
     def update_deadline(self, period=None):
+        """
+        Reset the reporting deadline according to current datetime and default cycle length.
+        New reporting deadline may be explicitly given as datetime instance.
+        """
+        if self.submission.status == STATUS_RESUBMISSION_INCOMING:
+            raise CycleUpdateDeadlineError('Submission has invalid status: %s'
+                                           % self.submission.status)
         delta_d = period or self.default_days
         deadline = timezone.now() + datetime.timedelta(days=delta_d)
         self.submission.reporting_deadline = deadline
         self.submission.save()
 
+
     def get_required_actions(self):
         '''Return list of the submission its required actions'''
         if not self.updated_action: