diff --git a/smash/web/api_views/subject.py b/smash/web/api_views/subject.py
index 6bf6bc78d0c6b507e82f70551a361d427186a848..ad8d4fc05db75f8dfcb5e659989891dc81ae49d5 100644
--- a/smash/web/api_views/subject.py
+++ b/smash/web/api_views/subject.py
@@ -1,5 +1,6 @@
 import logging
 
+from django.urls import reverse
 from django.db.models import Count, Case, When, Min, Max
 from django.db.models import Q
 from django.http import JsonResponse
@@ -322,7 +323,6 @@ def types(request):
         "types": data
     })
 
-
 def serialize_subject(study_subject):
     location = location_to_str(study_subject.default_location)
     flying_team = flying_team_to_str(study_subject.flying_team)
@@ -353,10 +353,19 @@ def serialize_subject(study_subject):
                     status = "SHOULD_BE_IN_PROGRESS"
         else:
             status = "UPCOMING"
+        
+        appointment_types = ['{} ({})'.format(at.code, at.description) for at in visit.appointment_types.all()]
+        if len(appointment_types) == 0:
+            appointment_types = ['No appointment types set.']
+
         serialized_visits.append({
             "status": status,
+            "appointment_types": appointment_types,
+            "edit_visit_url": reverse('web.views.visit_details', args=(visit.id,)),
+            "add_appointment_url": reverse('web.views.appointment_add', args=(visit.id,)),
             "datetime_start": serialize_date(visit.datetime_begin),
             "datetime_end": serialize_date(visit.datetime_end),
+            "is_finished": visit.is_finished
         })
     contact_reminder = serialize_datetime(study_subject.datetime_contact_reminder)
     contact_attempts = ContactAttempt.objects.filter(subject=study_subject).order_by("-datetime_when")
diff --git a/smash/web/forms/forms.py b/smash/web/forms/forms.py
index 3106fba657d935031fcf148a5cbe6c253dc6c9d2..acead32df6e5e1401a5346ecbec59be00aac8d8d 100644
--- a/smash/web/forms/forms.py
+++ b/smash/web/forms/forms.py
@@ -60,6 +60,14 @@ class VisitDetailForm(ModelForm):
     appointment_types = forms.ModelMultipleChoiceField(required=False, widget=forms.CheckboxSelectMultiple,
                                                        queryset=AppointmentType.objects.all())
 
+    def __init__(self, *args, **kwargs):
+        super(VisitDetailForm, self).__init__(*args, **kwargs)
+        instance = getattr(self, 'instance', None)
+        if instance.is_finished: #set form as readonly
+            for key in self.fields.keys():
+                self.fields[key].widget.attrs['readonly'] = True
+
+
     class Meta:
         model = Visit
         exclude = ['is_finished', 'visit_number']
diff --git a/smash/web/forms/study_forms.py b/smash/web/forms/study_forms.py
index 6e827cf3282821cd482ae0f933e6cf1754a5d903..df1874fa316d955ecd36530e99fa7f8866866738 100644
--- a/smash/web/forms/study_forms.py
+++ b/smash/web/forms/study_forms.py
@@ -3,6 +3,9 @@ import logging
 from django.forms import ModelForm, ValidationError
 from web.models import Study, StudyNotificationParameters, StudyColumns, StudySubject
 
+import datetime
+from dateutil.relativedelta import relativedelta
+
 logger = logging.getLogger(__name__)
 
 
@@ -11,17 +14,35 @@ class StudyEditForm(ModelForm):
     def __init__(self, *args, **kwargs):
         super(StudyEditForm, self).__init__(*args, **kwargs)
 
-    def clean_nd_number_study_subject_regex(self):
-        nd_number_study_subject_regex = self.cleaned_data.get(
-            'nd_number_study_subject_regex')
+    def clean(self):
+        cleaned_data = super(StudyEditForm, self).clean()
 
+        #check regex
+        nd_number_study_subject_regex = cleaned_data.get('nd_number_study_subject_regex')
+        
         instance = getattr(self, 'instance', None)
 
-        if StudySubject.check_nd_number_regex(nd_number_study_subject_regex, instance) == False:
-            raise ValidationError(
-                'Please enter a valid nd_number_study_subject_regex regex.')
-
-        return nd_number_study_subject_regex
+        if nd_number_study_subject_regex is None or StudySubject.check_nd_number_regex(nd_number_study_subject_regex, instance) == False:
+            self.add_error('nd_number_study_subject_regex', 'Please enter a valid nd_number_study_subject_regex regex.')
+
+        #check default_visit_duration_in_months
+        visit_duration_in_months = cleaned_data.get('default_visit_duration_in_months')
+        control_follow_up = cleaned_data.get('default_delta_time_for_control_follow_up')
+        patient_follow_up = cleaned_data.get('default_delta_time_for_patient_follow_up')
+        units = cleaned_data.get('default_delta_time_for_follow_up_units')
+
+        if None not in [visit_duration_in_months, control_follow_up, patient_follow_up, units]:
+            t = datetime.datetime.today()
+            visit_duration = relativedelta(months=int(visit_duration_in_months))
+            control_delta = relativedelta(**{units: control_follow_up})
+            patient_delta = relativedelta(**{units: patient_follow_up})
+        
+            #relative time delta has no __cmp__ method, so we add them to a datetime
+            min_delta_time = min((t + control_delta), (t + patient_delta))
+            if (t+visit_duration) > min_delta_time:
+                self.add_error('default_visit_duration_in_months', 'Please enter a valid "duration of the visits". It must be shorter than the time difference between patient and control visits.')
+
+        return cleaned_data
 
     class Meta:
         model = Study
diff --git a/smash/web/management/commands/holidays.py b/smash/web/management/commands/holidays.py
index 01a33ecc137bc7c077dfc120c2107f2b399ee1ff..5b729987a2673ae3c3503e50efc1228685654e81 100644
--- a/smash/web/management/commands/holidays.py
+++ b/smash/web/management/commands/holidays.py
@@ -4,6 +4,7 @@ from django.core.management.base import BaseCommand
 
 from ...models import Appointment, Location, AppointmentType, AppointmentTypeLink
 
+
 def get_easter_monday(easter_sunday):
     return next_weekday(easter_sunday, 0)
 
diff --git a/smash/web/migrations/0132_study_default_visit_duration_in_months.py b/smash/web/migrations/0132_study_default_visit_duration_in_months.py
new file mode 100644
index 0000000000000000000000000000000000000000..522e672e1041241ab5c52140cebbbc53b8be7bbc
--- /dev/null
+++ b/smash/web/migrations/0132_study_default_visit_duration_in_months.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.5 on 2018-11-13 10:05
+from __future__ import unicode_literals
+
+import django.core.validators
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0131_study_default_voucher_expiration_in_months'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='study',
+            name='default_visit_duration_in_months',
+            field=models.IntegerField(default=3, validators=[django.core.validators.MinValueValidator(1)], verbose_name=b'Default duration of the visits in months'),
+        ),
+    ]
diff --git a/smash/web/migrations/0133_auto_20181113_1550.py b/smash/web/migrations/0133_auto_20181113_1550.py
new file mode 100644
index 0000000000000000000000000000000000000000..efc19768b94521fcc1c12fcdaf030d640d94a8f7
--- /dev/null
+++ b/smash/web/migrations/0133_auto_20181113_1550.py
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.5 on 2018-11-13 15:50
+from __future__ import unicode_literals
+
+import django.core.validators
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0132_study_default_visit_duration_in_months'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='study',
+            name='default_delta_time_for_control_follow_up',
+            field=models.IntegerField(default=4, help_text=b'Time difference between visits used to automatically create follow up visits', validators=[django.core.validators.MinValueValidator(1)], verbose_name=b'Time difference between control visits'),
+        ),
+        migrations.AddField(
+            model_name='study',
+            name='default_delta_time_for_follow_up_units',
+            field=models.CharField(choices=[(b'days', b'Days'), (b'years', b'Years')], default=b'years', help_text=b'Units for the number of days between visits for both patients and controls', max_length=10, verbose_name=b'Units for the follow up incrementals'),
+        ),
+        migrations.AddField(
+            model_name='study',
+            name='default_delta_time_for_patient_follow_up',
+            field=models.IntegerField(default=1, help_text=b'Time difference between visits used to automatically create follow up visits', validators=[django.core.validators.MinValueValidator(1)], verbose_name=b'Time difference between patient visits'),
+        ),
+        migrations.AlterField(
+            model_name='study',
+            name='default_visit_duration_in_months',
+            field=models.IntegerField(default=6, help_text=b'Duration of the visit, this is, the time interval, in months, when the appointments may take place', validators=[django.core.validators.MinValueValidator(1)], verbose_name=b'Duration of the visits in months'),
+        ),
+        migrations.AlterField(
+            model_name='study',
+            name='default_voucher_expiration_in_months',
+            field=models.IntegerField(default=3, validators=[django.core.validators.MinValueValidator(1)], verbose_name=b'Duration of the vouchers in months'),
+        ),
+    ]
diff --git a/smash/web/migrations/0134_merge_20181211_1542.py b/smash/web/migrations/0134_merge_20181211_1542.py
new file mode 100644
index 0000000000000000000000000000000000000000..9ea20794127870e032566c49af3e2d438e0c7acd
--- /dev/null
+++ b/smash/web/migrations/0134_merge_20181211_1542.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.5 on 2018-12-11 15:42
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0132_workerstudyrole_permissions'),
+        ('web', '0133_auto_20181113_1550'),
+    ]
+
+    operations = [
+    ]
diff --git a/smash/web/models/study.py b/smash/web/models/study.py
index e89ac16fc1f491a335b770d6e953b127227771bd..b4e9dfa5a1410cfd82d4a6b2d42a915cb9f81f57 100644
--- a/smash/web/models/study.py
+++ b/smash/web/models/study.py
@@ -6,6 +6,12 @@ from django.core.validators import MaxValueValidator, MinValueValidator
 
 import re
 
+FOLLOW_UP_INCREMENT_IN_YEARS = 'years'
+FOLLOW_UP_INCREMENT_IN_DAYS = 'days'
+FOLLOW_UP_INCREMENT_UNIT_CHOICE = {
+    FOLLOW_UP_INCREMENT_IN_YEARS: 'Years',
+    FOLLOW_UP_INCREMENT_IN_DAYS: 'Days'
+}
 
 class Study(models.Model):
 
@@ -39,11 +45,40 @@ class Study(models.Model):
     )
 
     default_voucher_expiration_in_months = models.IntegerField(
-        verbose_name='Default duration of the vouchers in months',
+        verbose_name='Duration of the vouchers in months',
         default=3,
         validators=[MinValueValidator(1)]
     )
 
+    default_visit_duration_in_months = models.IntegerField(
+        verbose_name='Duration of the visits in months',
+        help_text='Duration of the visit, this is, the time interval, in months, when the appointments may take place',
+        default=6,
+        validators=[MinValueValidator(1)]
+    )
+
+    default_delta_time_for_patient_follow_up = models.IntegerField(
+        verbose_name='Time difference between patient visits',
+        help_text='Time difference between visits used to automatically create follow up visits',
+        default=1,
+        validators=[MinValueValidator(1)]
+    )
+
+    default_delta_time_for_control_follow_up = models.IntegerField(
+        verbose_name='Time difference between control visits',
+        help_text='Time difference between visits used to automatically create follow up visits',
+        default=4,
+        validators=[MinValueValidator(1)]
+    )
+
+    default_delta_time_for_follow_up_units = models.CharField(max_length=10,
+        choices=FOLLOW_UP_INCREMENT_UNIT_CHOICE.items(),
+        verbose_name='Units for the follow up incrementals',
+        help_text='Units for the number of days between visits for both patients and controls',
+        default=FOLLOW_UP_INCREMENT_IN_YEARS,
+        blank=False
+    )
+
     def check_nd_number(self, nd_number):
         regex = re.compile(self.nd_number_study_subject_regex)
         return regex.match(nd_number) is not None
diff --git a/smash/web/models/visit.py b/smash/web/models/visit.py
index cb6fd2c45f20467dd351ed4849bbd3e93639c978..c2b00ebb5056edda65023becaba5a6d126959ea6 100644
--- a/smash/web/models/visit.py
+++ b/smash/web/models/visit.py
@@ -1,5 +1,6 @@
 # coding=utf-8
 import datetime
+from dateutil.relativedelta import relativedelta
 
 from django.db import models
 from django.db.models.signals import post_save
@@ -7,7 +8,10 @@ from django.dispatch import receiver
 from django.db import transaction
 
 from web.models.constants import BOOL_CHOICES, SUBJECT_TYPE_CHOICES_CONTROL
+from web.models import Study
 
+import logging
+logger = logging.getLogger(__name__)
 
 class Visit(models.Model):
 
@@ -69,18 +73,21 @@ class Visit(models.Model):
             follow_up_number = Visit.objects.filter(
                 subject=self.subject).count() + 1
 
-            delta_days = 365
+            study = self.subject.study
+
             if self.subject.type == SUBJECT_TYPE_CHOICES_CONTROL:
-                delta_days = 365 * 3 + 366
+                args = {study.default_delta_time_for_follow_up_units: study.default_delta_time_for_control_follow_up}
+            else:
+                args = {study.default_delta_time_for_follow_up_units: study.default_delta_time_for_patient_follow_up}
+            
+            time_to_next_visit = relativedelta(**args) * (follow_up_number - 1) #calculated from first visit
 
-            time_to_next_visit = datetime.timedelta(
-                days=delta_days * (follow_up_number - 1))
+            logger.warn('new visit: {} {} {}'.format(args, relativedelta(**args), time_to_next_visit))
 
             Visit.objects.create(
                 subject=self.subject,
                 datetime_begin=visit_started + time_to_next_visit,
-                datetime_end=visit_started + time_to_next_visit +
-                datetime.timedelta(days=93)
+                datetime_end=visit_started + time_to_next_visit + relativedelta(months=study.default_visit_duration_in_months)
             )
 
 @receiver(post_save, sender=Visit)
diff --git a/smash/web/static/js/smash.js b/smash/web/static/js/smash.js
index f92df08f2378d2e88dbe5deae555202b7103d463..dcf03f52dee0cf0914ecc7c85ccb7a38d641d934 100644
--- a/smash/web/static/js/smash.js
+++ b/smash/web/static/js/smash.js
@@ -185,27 +185,56 @@ function create_visit_row(visit) {
     var text = "---";
     if (visit !== undefined && visit !== null) {
         if (visit.status === "DONE") {
-            color = "green";
-            text = "OK";
+            color = "#6bff5a";
+            text = `<span title="Visit is finished, all appointments done.">OK</span>`;
+
         } else if (visit.status === "MISSED") {
             color = "pink";
-            text = "MISSED";
+            text = `<span title="Visit is finished, some appointments were not carried out.">MISSED</span>`;
+
         } else if (visit.status === "UPCOMING") {
             color = "#00ffff";
-            text = "UPCOMING";
+            text = `<span title="Visit has not started yet.">UPCOMING</span>`;
+
         } else if (visit.status === "EXCEEDED") {
             color = "orange";
-            text = "EXCEEDED";
+            text = `<span title="Visit is over and no appointments were set.">EXCEEDED</span>`;
+
         } else if (visit.status === "SHOULD_BE_IN_PROGRESS") {
             color = "orange";
-            text = "IN PROGRESS (NO APPOINTMENTS)";
+            text = `<span title="Visit has started but no appointments have been set yet.">IN PROGRESS (NO APPOINTMENTS)</span>`;
+
         } else if (visit.status === "IN_PROGRESS") {
             color = "lightgreen";
-            text = "IN PROGRESS";
+            text = `<span title="Appointments are taking place.">IN PROGRESS</span>`;
+
         }
-        text += "<br/>" + visit.datetime_start + " - " + visit.datetime_end;
+        
+        var start_date = moment(visit.datetime_start);
+        var end_date   = moment(visit.datetime_end);
+
+        text += `<br/>
+            <span data-html="true" title="From: ${start_date.format('ddd Do MMMM YYYY')} </br> To: ${end_date.format('ddd Do MMMM YYYY')}">
+            From: ${start_date.format('D MMM. YYYY')}
+            </span>
+            <br/>
+            <span data-html="true" title="From: ${start_date.format('ddd Do MMMM YYYY')} </br> To: ${end_date.format('ddd Do MMMM YYYY')}">
+            To: ${end_date.format('D MMM. YYYY')}
+            </span>`
+ 
+        text += `<br/><span data-html="true" title="Visit details<br/>Appointment Types:<br/><div class='appointment_type_list'>${visit.appointment_types.join('<br/>')}</div>">
+                    <a href="${visit.edit_visit_url}"><i class="fa fa-list" aria-hidden="true"></i></a>
+                </span>`;
+
+        if(!visit.is_finished){
+            text += `<span title="Add new appointment to visit"><a href="${visit.add_appointment_url}"><i class="fa fa-plus-square-o" aria-hidden="true"></i></a></span>`;
+        }else{
+            text += `<span title="Visit is marked as finished" ><i class="fa fa-check-circle" aria-hidden="true"></i></span>`;
+        }
+
+        
     }
-    return "<div style='background-color:" + color + "';width:100%;height:100%>" + text + "</div>";
+    return "<div class='visit_row' style='background-color:" + color + "';width:100%;height:100%>" + text + "</div>";
 }
 
 function createVisibilityCheckboxes(checkboxesElement, columns) {
diff --git a/smash/web/static/js/visit.js b/smash/web/static/js/visit.js
index a2636ed219748484b648296a736608d14732589c..1e5aa2208b0177fad7bd72613cf637f7681c6f3e 100644
--- a/smash/web/static/js/visit.js
+++ b/smash/web/static/js/visit.js
@@ -1,10 +1,12 @@
-function visit_dates_behaviour(startDateInput, endDateInput) {
+function visit_dates_behaviour(startDateInput, endDateInput, default_visit_duration) {
     $(startDateInput).change(function () {
         var object = $(this);
         try {
             var date = new Date(object.val());
-            date.setMonth(date.getMonth() + 3);
-            $(endDateInput).val(date.toISOString().substring(0, 10));
+            date.setMonth(date.getMonth() + default_visit_duration);
+            if($(endDateInput).val() == ""){
+                $(endDateInput).val(date.toISOString().substring(0, 10));
+            }
         } catch (err) {
             //there was a problematic date to process
         }
diff --git a/smash/web/templates/includes/visit_appointment_types_field.html b/smash/web/templates/includes/visit_appointment_types_field.html
index 4e167755b38db5821992197a8d3edf9ddb12245c..8cd1998f280aaebad4286e617f260e0191f00dbd 100644
--- a/smash/web/templates/includes/visit_appointment_types_field.html
+++ b/smash/web/templates/includes/visit_appointment_types_field.html
@@ -13,7 +13,7 @@
                                          background: orange;
                                      {% endif %}{% endif %}{% endfor %}{% endfor %}
                                      "></div>
-                        <input {% if readonly %}disabled="disabled"{% endif %}
+                        <input {% if field.field.widget.attrs.readonly %}disabled="disabled"{% endif %}
                                {% for option in field.value %}{% if option == pk|slugify or option == pk %}checked="checked"
                                {% endif %}{% endfor %} type="checkbox"
                                id="id_{{ field.name }}_{{ forloop.counter0 }}"
diff --git a/smash/web/templates/subjects/index.html b/smash/web/templates/subjects/index.html
index 7042377035d26f30ec7a6deb59535e7e4f0ff80f..c3192e6452f79ca6e13194a6b8483ba168932326 100644
--- a/smash/web/templates/subjects/index.html
+++ b/smash/web/templates/subjects/index.html
@@ -3,6 +3,7 @@
 
 {% block styles %}
     {{ block.super }}
+    <script src="{% static 'AdminLTE/plugins/moment.js/moment.min.js' %}"></script>
     <link rel="stylesheet" href="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.css' %}">
     <style type="text/css">
         .box-body {
@@ -12,6 +13,23 @@
             font-weight: bolder;
             border-bottom: black 1px solid;
         }
+        .visit_row{
+            font-size: 10pt;
+            max-width: 22ch;
+            min-width: 18ch;
+            text-align: center;
+        }
+        .visit_row > span{
+            padding-right: 2px;
+            padding-left: 2px;
+        }
+        .visit_row > span > a{
+            color: inherit; 
+        }
+        .appointment_type_list{
+            margin-top: 10px;
+            text-align: left;
+        }
     </style>
 
 {% endblock styles %}
@@ -72,7 +90,12 @@
                 columns: getColumns(data.columns, getSubjectEditUrl),
                 checkboxesElement: document.getElementById("visible-column-checkboxes"),
                 dom_settings: 'lrtip' // show table without search box
-            })
+            });
+        });
+
+        $('body').tooltip({
+            selector: '.visit_row > span[title]',
+            trigger: 'hover'
         });
 
     </script>
diff --git a/smash/web/templates/visits/add.html b/smash/web/templates/visits/add.html
index 749641be57b7d9c1e4160a5d7457fff0cbfa5fed..4c93ee497b56c5d68886deb070115662d1fa3e05 100644
--- a/smash/web/templates/visits/add.html
+++ b/smash/web/templates/visits/add.html
@@ -70,7 +70,8 @@
 
 <script src="{% static 'js/visit.js' %}"></script>
 <script>
-    visit_dates_behaviour($("[name='datetime_begin']"),$("[name='datetime_end']"));
+    var default_visit_duration_in_months = parseInt("{{default_visit_duration}}");
+    visit_dates_behaviour($("[name='datetime_begin']"), $("[name='datetime_end']"), default_visit_duration_in_months);
 </script>
 
 {% include "includes/datepicker.js.html" %}
diff --git a/smash/web/templates/visits/details.html b/smash/web/templates/visits/details.html
index 62069efad065578c2615da6a13a554e261b11629..a85ce75d1f33ac0ce2284b723f1fca38ef46ea1c 100644
--- a/smash/web/templates/visits/details.html
+++ b/smash/web/templates/visits/details.html
@@ -91,10 +91,17 @@
             </div>
 
             <div>
+                {%if visFinished%}
+                <a href="{% url 'web.views.appointment_add' vid %}" class="btn btn-app" disabled>
+                    <i class="fa fa-plus"></i>
+                    Add new appointment
+                </a>
+                {% else %}
                 <a href="{% url 'web.views.appointment_add' vid %}" class="btn btn-app">
                     <i class="fa fa-plus"></i>
                     Add new appointment
                 </a>
+                {% endif %}
             </div>
 
 
@@ -221,7 +228,8 @@
     <script src="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.min.js' %}"></script>
     <script src="{% static 'js/visit.js' %}"></script>
     <script>
-        visit_dates_behaviour($("[name='datetime_begin']"), $("[name='datetime_end']"));
+        var default_visit_duration_in_months = parseInt("{{default_visit_duration}}");
+        visit_dates_behaviour($("[name='datetime_begin']"), $("[name='datetime_end']"), default_visit_duration_in_months);
     </script>
 
     {% include "includes/datepicker.js.html" %}
diff --git a/smash/web/tests/forms/test_study_forms.py b/smash/web/tests/forms/test_study_forms.py
index 6893bce69694866e8da3838acf419365776663a8..0fe2bd2cd5f0b9fce56a6f11feef5e9bb471fd49 100644
--- a/smash/web/tests/forms/test_study_forms.py
+++ b/smash/web/tests/forms/test_study_forms.py
@@ -18,16 +18,15 @@ class StudyFormTests(TestCase):
             'nd_number_study_subject_regex').get_default()
         form.cleaned_data = {
             'nd_number_study_subject_regex': nd_number_study_subject_regex_default}
-        self.assertTrue(form.clean_nd_number_study_subject_regex()
-                        == nd_number_study_subject_regex_default)
+
+        self.assertTrue(form.clean()['nd_number_study_subject_regex'] == nd_number_study_subject_regex_default)
         # test wrong regex
         form = StudyEditForm()
         form.instance = get_test_study()
         nd_number_study_subject_regex_default = r'^nd\d{5}$'
         form.cleaned_data = {
             'nd_number_study_subject_regex': nd_number_study_subject_regex_default}
-        self.assertRaises(
-            ValidationError, form.clean_nd_number_study_subject_regex)
+        self.assertFalse(form.is_valid())
 
     def test_study_other_regex(self):
         StudySubject.objects.all().delete()
@@ -39,5 +38,5 @@ class StudyFormTests(TestCase):
         nd_number_study_subject_regex_default = r'^nd\d{5}$'
         form.cleaned_data = {
             'nd_number_study_subject_regex': nd_number_study_subject_regex_default}
-        self.assertTrue(form.clean_nd_number_study_subject_regex()
+        self.assertTrue(form.clean()['nd_number_study_subject_regex']
                         == nd_number_study_subject_regex_default)
diff --git a/smash/web/tests/models/test_visit.py b/smash/web/tests/models/test_visit.py
index 38cb4b6c50585a8cd1b983b7aca609a3c67712ae..d9c7efb9c1c416f98e83d4fecac819d4433512e2 100644
--- a/smash/web/tests/models/test_visit.py
+++ b/smash/web/tests/models/test_visit.py
@@ -1,5 +1,5 @@
 import datetime
-
+from dateutil.relativedelta import relativedelta
 from django.test import TestCase
 
 from web.models import Visit
@@ -137,7 +137,8 @@ class VisitModelTests(TestCase):
 
         visit.mark_as_finished()
 
-        follow_up_visit = Visit.objects.filter(subject=subject).filter(visit_number=2)[0]
+        visit_number=2
+        follow_up_visit = Visit.objects.filter(subject=subject).filter(visit_number=visit_number)[0]
         follow_up_visit.datetime_begin = visit.datetime_begin + datetime.timedelta(days=133)
         follow_up_visit.datetime_end = visit.datetime_begin + datetime.timedelta(days=170)
         follow_up_visit.save()
@@ -147,10 +148,16 @@ class VisitModelTests(TestCase):
         visit_count = Visit.objects.filter(subject=subject).count()
         self.assertEquals(3, visit_count)
 
-        new_follow_up = Visit.objects.filter(subject=subject).filter(visit_number=3)[0]
+        visit_number=3
+        new_follow_up = Visit.objects.filter(subject=subject).filter(visit_number=visit_number)[0]
 
         # check if follow up date is based on the first visit date
-        self.assertTrue(visit.datetime_begin + datetime.timedelta(days=365 * 2 - 1) < new_follow_up.datetime_begin)
+        study = visit.subject.study
+        args = {study.default_delta_time_for_follow_up_units: study.default_delta_time_for_patient_follow_up} #patient
+        
+        time_to_next_visit = relativedelta(**args) * (visit_number - 1) #calculated from first visit
+
+        self.assertTrue(visit.datetime_begin + time_to_next_visit - datetime.timedelta(days=1) < new_follow_up.datetime_begin)
 
     def test_visit_to_string(self):
         visit = create_visit(create_study_subject())
diff --git a/smash/web/views/visit.py b/smash/web/views/visit.py
index 96dde765288b7b54fd87468952d6a742e2fd133a..77625043f21147bc3c9b0e3cc314a9925120c2de 100644
--- a/smash/web/views/visit.py
+++ b/smash/web/views/visit.py
@@ -74,6 +74,7 @@ def visit_details(request, id):
     languages.extend(study_subject.subject.languages.all())
 
     return wrap_response(request, 'visits/details.html', {
+        'default_visit_duration' : study_subject.study.default_visit_duration_in_months,
         'visit_form': visit_form,
         'study_subject_form': study_subject_form,
         'subject_form': subject_form,
@@ -96,6 +97,7 @@ def visit_mark(request, id, as_what):
 def visit_add(request, subject_id=-1):
     if request.method == 'POST':
         form = VisitAddForm(request.POST, request.FILES)
+        args = {'form': form}
         if form.is_valid():
             visit = form.save()
             return redirect('web.views.visit_details', visit.id)
@@ -105,5 +107,6 @@ def visit_add(request, subject_id=-1):
         if len(subjects) > 0:
             subject = subjects[0]
         form = VisitAddForm(initial={'subject': subject})
+        args = {'form': form, 'default_visit_duration': subject.study.default_visit_duration_in_months}
 
-    return wrap_response(request, 'visits/add.html', {'form': form})
+    return wrap_response(request, 'visits/add.html', args)