diff --git a/smash/web/admin.py b/smash/web/admin.py
index 5fdcc64ec02827b9b594f08b09513dfa6b27b86d..303aa56d09cf241230750c164e8abb6424dedea9 100644
--- a/smash/web/admin.py
+++ b/smash/web/admin.py
@@ -1,6 +1,6 @@
 from django.contrib import admin
 
-from models import Subject, Item, Room, AppointmentType, Language, Location, Worker, FlyingTeam, Availability, Holiday, \
+from models import StudySubject, Item, Room, AppointmentType, Language, Location, Worker, FlyingTeam, Availability, Holiday, \
     Visit, Appointment
 
 
@@ -9,7 +9,7 @@ class LanguageAdmin(admin.ModelAdmin):
 
 
 # Register your models here.
-admin.site.register(Subject)
+admin.site.register(StudySubject)
 admin.site.register(Visit)
 admin.site.register(Item)
 admin.site.register(Room)
diff --git a/smash/web/api_views/appointment.py b/smash/web/api_views/appointment.py
index a51ddfc058c410f8f65bef590804cf9e793ef35e..14a96d62d4423f0343255cc896301db479169dc1 100644
--- a/smash/web/api_views/appointment.py
+++ b/smash/web/api_views/appointment.py
@@ -87,11 +87,11 @@ def serialize_appointment(appointment):
     nd_number = screening_number = phone_numbers = appointment_types = None
     if appointment.visit is not None:
         title = "Visit " + str(appointment.visit.visit_number)
-        subject = appointment.visit.subject
-        subject_string = subject.last_name + " " + subject.first_name
-        nd_number = subject.nd_number
-        screening_number = subject.screening_number
-        phone_numbers = ", ".join(filter(None, [subject.phone_number, subject.phone_number_2, subject.phone_number_3]))
+        study_subject = appointment.visit.subject
+        subject_string = study_subject.subject.last_name + " " + study_subject.subject.first_name
+        nd_number = study_subject.nd_number
+        screening_number = study_subject.screening_number
+        phone_numbers = ", ".join(filter(None, [study_subject.subject.phone_number, study_subject.subject.phone_number_2, study_subject.subject.phone_number_3]))
         appointment_types = ", ".join([unicode(type) for type in appointment.appointment_types.all()])
     else:
         title = appointment.comment
diff --git a/smash/web/api_views/subject.py b/smash/web/api_views/subject.py
index b84e207c373bdb98fbd3169817c69105df9b3549..6c864c10d9459a06130bc9df93da29d388d14e44 100644
--- a/smash/web/api_views/subject.py
+++ b/smash/web/api_views/subject.py
@@ -5,7 +5,7 @@ from django.db.models import Count, Case, When, Min
 from django.db.models import Q
 from django.http import JsonResponse
 
-from web.models import Subject, Visit, Appointment
+from web.models import Subject, StudySubject, Visit, Appointment
 from web.models.constants import SUBJECT_TYPE_CHOICES
 from web.views import e500_error
 from web.views.notifications import get_subjects_with_no_visit, get_subjects_with_reminder, get_today_midnight_date
@@ -16,15 +16,19 @@ logger = logging.getLogger(__name__)
 
 @login_required
 def cities(request):
-    result_subjects = Subject.objects.filter(city__isnull=False).values_list('city').distinct()
-    return JsonResponse({
-        "cities": [x[0] for x in result_subjects]
-    })
+    try:
+        result_subjects = Subject.objects.filter(city__isnull=False).values_list('city').distinct()
+        return JsonResponse({
+            "cities": [x[0] for x in result_subjects]
+        })
+    except Exception as e:
+        logger.error(e, exc_info=True)
+        return e500_error(request)
 
 
 @login_required
 def referrals(request):
-    result_subjects = Subject.objects.filter(referral__isnull=False).values_list('referral').distinct()
+    result_subjects = StudySubject.objects.filter(referral__isnull=False).values_list('referral').distinct()
     return JsonResponse({
         "referrals": [x[0] for x in result_subjects]
     })
@@ -33,7 +37,7 @@ def referrals(request):
 @login_required
 def get_subjects(request, type):
     if type == SUBJECT_LIST_GENERIC:
-        return Subject.objects.all()
+        return StudySubject.objects.all()
     elif type == SUBJECT_LIST_NO_VISIT:
         return get_subjects_with_no_visit(request.user)
     elif type == SUBJECT_LIST_REQUIRE_CONTACT:
@@ -55,9 +59,9 @@ def get_subjects_order(subjects_to_be_ordered, order_column, order_direction):
     else:
         order_direction = "-"
     if order_column == "first_name":
-        result = subjects_to_be_ordered.order_by(order_direction + 'first_name')
+        result = subjects_to_be_ordered.order_by(order_direction + 'subject__first_name')
     elif order_column == "last_name":
-        result = subjects_to_be_ordered.order_by(order_direction + 'last_name')
+        result = subjects_to_be_ordered.order_by(order_direction + 'subject__last_name')
     elif order_column == "nd_number":
         result = subjects_to_be_ordered.order_by(order_direction + 'nd_number')
     elif order_column == "screening_number":
@@ -65,7 +69,7 @@ def get_subjects_order(subjects_to_be_ordered, order_column, order_direction):
     elif order_column == "default_location":
         result = subjects_to_be_ordered.order_by(order_direction + 'default_location')
     elif order_column == "dead":
-        result = subjects_to_be_ordered.order_by(order_direction + 'dead')
+        result = subjects_to_be_ordered.order_by(order_direction + 'subject__dead')
     elif order_column == "resigned":
         result = subjects_to_be_ordered.order_by(order_direction + 'resigned')
     elif order_column == "information_sent":
@@ -77,7 +81,7 @@ def get_subjects_order(subjects_to_be_ordered, order_column, order_direction):
     elif order_column == "id":
         result = subjects_to_be_ordered.order_by(order_direction + 'id')
     elif order_column == "date_born":
-        result = subjects_to_be_ordered.order_by(order_direction + 'date_born')
+        result = subjects_to_be_ordered.order_by(order_direction + 'subject__date_born')
     elif order_column == "visit_1":
         result = order_by_visit(subjects_to_be_ordered, order_direction, 1)
     elif order_column == "visit_2":
@@ -166,15 +170,15 @@ def get_subjects_filtered(subjects_to_be_filtered, filters):
         column = row[0]
         value = row[1]
         if column == "first_name":
-            result = result.filter(first_name__icontains=value)
+            result = result.filter(subject__first_name__icontains=value)
         elif column == "last_name":
-            result = result.filter(last_name__icontains=value)
+            result = result.filter(subject__last_name__icontains=value)
         elif column == "nd_number":
             result = result.filter(nd_number__icontains=value)
         elif column == "screening_number":
             result = result.filter(screening_number__icontains=value)
         elif column == "dead":
-            result = result.filter(dead=(value == "true"))
+            result = result.filter(subject__dead=(value == "true"))
         elif column == "resigned":
             result = result.filter(resigned=(value == "true"))
         elif column == "postponed":
@@ -256,7 +260,8 @@ def subjects(request, type):
             "recordsFiltered": count_filtered,
             "data": data,
         })
-    except:
+    except Exception as e:
+        logger.error(e, exc_info=True)
         return e500_error(request)
 
 
@@ -282,11 +287,11 @@ def serialize_subject_visit(visit):
     pass
 
 
-def serialize_subject(subject):
+def serialize_subject(study_subject):
     location = ""
-    if subject.default_location is not None:
-        location = subject.default_location.name
-    visits = Visit.objects.filter(subject=subject).order_by('visit_number')
+    if study_subject.default_location is not None:
+        location = study_subject.default_location.name
+    visits = Visit.objects.filter(subject=study_subject).order_by('visit_number')
     serialized_visits = []
     for visit in visits:
         if visit.datetime_begin < get_today_midnight_date():
@@ -315,18 +320,18 @@ def serialize_subject(subject):
         })
 
     result = {
-        "first_name": subject.first_name,
-        "last_name": subject.last_name,
-        "date_born": subject.date_born,
-        "nd_number": subject.nd_number,
-        "screening_number": subject.screening_number,
+        "first_name": study_subject.subject.first_name,
+        "last_name": study_subject.subject.last_name,
+        "date_born": study_subject.subject.date_born,
+        "nd_number": study_subject.nd_number,
+        "screening_number": study_subject.screening_number,
         "default_location": location,
-        "dead": get_yes_no(subject.dead),
-        "resigned": get_yes_no(subject.resigned),
-        "postponed": get_yes_no(subject.postponed),
-        "information_sent": get_yes_no(subject.information_sent),
-        "type": subject.get_type_display(),
-        "id": subject.id,
+        "dead": get_yes_no(study_subject.subject.dead),
+        "resigned": get_yes_no(study_subject.resigned),
+        "postponed": get_yes_no(study_subject.postponed),
+        "information_sent": get_yes_no(study_subject.information_sent),
+        "type": study_subject.get_type_display(),
+        "id": study_subject.id,
         "visits": serialized_visits,
     }
     return result
diff --git a/smash/web/forms.py b/smash/web/forms.py
index 571fd786a5506d785f7aa1107a727ca23cbc88fd..ade762d5d0f7bb3bfdfd76840d90fb337bf1877c 100644
--- a/smash/web/forms.py
+++ b/smash/web/forms.py
@@ -1,11 +1,13 @@
 import datetime
+import logging
 from collections import OrderedDict
 
 from django import forms
 from django.forms import ModelForm, Form
 from django.utils.dates import MONTHS
 
-from web.models import Subject, Worker, Appointment, Visit, AppointmentType, ContactAttempt, AppointmentTypeLink, \
+from web.models import Subject, StudySubject, Worker, Appointment, Visit, AppointmentType, ContactAttempt, \
+    AppointmentTypeLink, \
     Availability, Holiday
 from web.models.constants import SUBJECT_TYPE_CHOICES, SCREENING_NUMBER_PREFIXES_FOR_TYPE, COUNTRY_OTHER_ID
 from web.views.notifications import get_filter_locations
@@ -35,10 +37,12 @@ TIMEPICKER_DATE_ATTRS = {
 START_YEAR_STATISTICS = 2015
 APPOINTMENT_TYPES_FIELD_POSITION = 1
 
+logger = logging.getLogger(__name__)
+
 
 def validate_subject_nd_number(self, cleaned_data):
     if cleaned_data['nd_number'] != "":
-        subjects_from_db = Subject.objects.filter(nd_number=cleaned_data['nd_number'])
+        subjects_from_db = StudySubject.objects.filter(nd_number=cleaned_data['nd_number'])
         if subjects_from_db:
             if subjects_from_db[0].screening_number != cleaned_data.get('screening_number', ''):
                 self.add_error('nd_number', "ND number already in use")
@@ -56,27 +60,22 @@ def validate_subject_resign_reason(self, cleaned_data):
 
 def validate_subject_mpower_number(self, cleaned_data):
     if cleaned_data['mpower_id'] != "":
-        subjects_from_db = Subject.objects.filter(mpower_id=cleaned_data['mpower_id'])
+        subjects_from_db = StudySubject.objects.filter(mpower_id=cleaned_data['mpower_id'])
         if subjects_from_db:
             if subjects_from_db[0].screening_number != cleaned_data.get('screening_number', ''):
                 self.add_error('mpower_id', "mPower number already in use")
 
 
-class SubjectAddForm(ModelForm):
-    date_born = forms.DateField(label="Date of birth",
-                                widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d"),
-                                required=False
-                                )
-
+class StudySubjectAddForm(ModelForm):
     datetime_contact_reminder = forms.DateTimeField(label="Contact on",
                                                     widget=forms.DateTimeInput(DATETIMEPICKER_DATE_ATTRS),
                                                     required=False
                                                     )
 
     class Meta:
-        model = Subject
+        model = StudySubject
         fields = '__all__'
-        exclude = ['dead', 'resigned', 'resign_reason']
+        exclude = ['resigned', 'resign_reason']
 
     def __init__(self, *args, **kwargs):
         user = kwargs.pop('user', None)
@@ -98,15 +97,14 @@ class SubjectAddForm(ModelForm):
         return screening_number
 
     def clean(self):
-        cleaned_data = super(SubjectAddForm, self).clean()
+        cleaned_data = super(StudySubjectAddForm, self).clean()
         screening_number = self.build_screening_number(cleaned_data)
         if screening_number is not None:
             cleaned_data['screening_number'] = screening_number
-            subjects_from_db = Subject.objects.filter(screening_number=screening_number)
+            subjects_from_db = StudySubject.objects.filter(screening_number=screening_number)
 
             if len(subjects_from_db) > 0:
                 self.add_error('screening_number', "Screening number already in use")
-        validate_subject_country(self, cleaned_data)
         validate_subject_nd_number(self, cleaned_data)
         validate_subject_mpower_number(self, cleaned_data)
         return cleaned_data
@@ -128,7 +126,7 @@ class SubjectAddForm(ModelForm):
 
 def get_new_screening_number(screening_number_prefix):
     result_number = 0
-    subjects = Subject.objects.filter(screening_number__contains=screening_number_prefix)
+    subjects = StudySubject.objects.filter(screening_number__contains=screening_number_prefix)
     for subject in subjects:
         screening_numbers = subject.screening_number.split(";")
         for screening_number in screening_numbers:
@@ -143,46 +141,36 @@ def get_new_screening_number(screening_number_prefix):
     return screening_number_prefix + str(result_number + 1).zfill(3)
 
 
-class SubjectDetailForm(ModelForm):
+class StudySubjectDetailForm(ModelForm):
     class Meta:
-        model = Subject
+        model = StudySubject
         fields = '__all__'
 
 
-class SubjectEditForm(ModelForm):
+class StudySubjectEditForm(ModelForm):
     datetime_contact_reminder = forms.DateTimeField(label="Contact on",
                                                     widget=forms.DateTimeInput(DATETIMEPICKER_DATE_ATTRS),
                                                     required=False
                                                     )
-    date_born = forms.DateField(label="Date of birth",
-                                widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d"),
-                                required=False
-                                )
 
     def __init__(self, *args, **kwargs):
-        was_dead = kwargs.get('was_dead', False)
         was_resigned = kwargs.get('was_resigned', False)
         if 'was_resigned' in kwargs:
             kwargs.pop('was_resigned')
-        if 'was_dead' in kwargs:
-            kwargs.pop('was_dead')
-        super(SubjectEditForm, self).__init__(*args, **kwargs)
+        super(StudySubjectEditForm, self).__init__(*args, **kwargs)
         instance = getattr(self, 'instance', None)
         if instance and instance.id:
             self.fields['screening_number'].widget.attrs['readonly'] = True
-        if was_dead:
-            self.fields['dead'].disabled = True
         if was_resigned:
             self.fields['resigned'].disabled = True
 
     def clean(self):
         validate_subject_nd_number(self, self.cleaned_data)
         validate_subject_mpower_number(self, self.cleaned_data)
-        validate_subject_country(self, self.cleaned_data)
         validate_subject_resign_reason(self, self.cleaned_data)
 
     class Meta:
-        model = Subject
+        model = StudySubject
         fields = '__all__'
 
 
@@ -343,7 +331,8 @@ class VisitDetailForm(ModelForm):
 
 
 class VisitAddForm(ModelForm):
-    subject = forms.ModelChoiceField(queryset=Subject.objects.order_by('last_name', 'first_name'))
+    subject = forms.ModelChoiceField(
+        queryset=StudySubject.objects.order_by('subject__last_name', 'subject__first_name'))
     datetime_begin = forms.DateField(label="Visit begins on",
                                      widget=forms.TextInput(attrs=DATEPICKER_DATE_ATTRS)
                                      )
@@ -521,3 +510,48 @@ class HolidayAddForm(ModelForm):
         availabilities = worker.availability_set.all()
         for availability in availabilities:
             validate_availability_conflict(self, self.cleaned_data, availability)
+
+
+class SubjectAddForm(ModelForm):
+    date_born = forms.DateField(label="Date of birth",
+                                widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d"),
+                                required=False
+                                )
+
+    class Meta:
+        model = Subject
+        fields = '__all__'
+        exclude = ['dead']
+
+    def clean(self):
+        cleaned_data = super(SubjectAddForm, self).clean()
+        validate_subject_country(self, cleaned_data)
+        return cleaned_data
+
+
+class SubjectEditForm(ModelForm):
+    date_born = forms.DateField(label="Date of birth",
+                                widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d"),
+                                required=False
+                                )
+
+    def __init__(self, *args, **kwargs):
+        was_dead = kwargs.get('was_dead', False)
+        if 'was_dead' in kwargs:
+            kwargs.pop('was_dead')
+        super(SubjectEditForm, self).__init__(*args, **kwargs)
+        if was_dead:
+            self.fields['dead'].disabled = True
+
+    def clean(self):
+        validate_subject_country(self, self.cleaned_data)
+
+    class Meta:
+        model = Subject
+        fields = '__all__'
+
+
+class SubjectDetailForm(ModelForm):
+    class Meta:
+        model = Subject
+        fields = '__all__'
diff --git a/smash/web/migrations/0063_auto_20171120_1429.py b/smash/web/migrations/0063_auto_20171120_1429.py
new file mode 100644
index 0000000000000000000000000000000000000000..7b9c1de9d8c4e5eba269740c479e658a87de8433
--- /dev/null
+++ b/smash/web/migrations/0063_auto_20171120_1429.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2017-11-20 14:29
+from __future__ import unicode_literals
+
+import django.core.validators
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0062_subject_resign_reason'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='subject',
+            name='nd_number',
+            field=models.CharField(blank=True, max_length=25, validators=[django.core.validators.RegexValidator(b'^(ND[0-9]{4}|)$', message=b'ND number should look as follows: NDxxxx')], verbose_name=b'ND number'),
+        ),
+    ]
diff --git a/smash/web/migrations/0064_auto_20171127_0954.py b/smash/web/migrations/0064_auto_20171127_0954.py
new file mode 100644
index 0000000000000000000000000000000000000000..4fd29798f2f5fa6180904177aa22be5db2c72dcc
--- /dev/null
+++ b/smash/web/migrations/0064_auto_20171127_0954.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2017-11-27 09:54
+from __future__ import unicode_literals
+
+import django.core.validators
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0063_auto_20171120_1429'),
+    ]
+
+    operations = [
+        migrations.RenameModel('Subject', 'StudySubject')
+    ]
diff --git a/smash/web/migrations/0065_auto_20171127_0957.py b/smash/web/migrations/0065_auto_20171127_0957.py
new file mode 100644
index 0000000000000000000000000000000000000000..79e6a2a186804e87b40fb729b72c03247b6561ea
--- /dev/null
+++ b/smash/web/migrations/0065_auto_20171127_0957.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2017-11-27 09:57
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0064_auto_20171127_0954'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='studysubject',
+            name='default_written_communication_language',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='studysubject_written_comunication', to='web.Language', verbose_name=b'Default language for document generation'),
+        ),
+    ]
diff --git a/smash/web/migrations/0066_subject.py b/smash/web/migrations/0066_subject.py
new file mode 100644
index 0000000000000000000000000000000000000000..511f3560a02a48efb4d3a708ed1e538deab50795
--- /dev/null
+++ b/smash/web/migrations/0066_subject.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2017-11-27 10:42
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0065_auto_20171127_0957'),
+    ]
+
+    operations = [
+        migrations.RunSQL('alter sequence web_subject_id_seq rename to web_studysubject_id_seq;'),
+        migrations.RunSQL('alter sequence web_subject_languages_id_seq rename to web_studysubject_languages_id_seq;'),
+        migrations.RunSQL('alter table web_studysubject rename constraint web_subject_flying_team_id_ef78de5d_fk_web_flyingteam_id to web_studysubject_flying_team_id_ef78de5d_fk_web_flyingteam_id;'),
+        migrations.RunSQL('alter table web_studysubject_languages rename constraint web_subject_languages_language_id_80eca4c1_fk_web_language_id to web_studysubject_languages_language_id_80eca4c1_fk_web_language_id;'),
+        migrations.RunSQL('alter table web_studysubject rename constraint web_subject_country_id_5d976875_fk_web_country_id to web_studysubject_country_id_5d976875_fk_web_country_id;'),
+        migrations.RunSQL('alter table web_studysubject rename constraint web_subject_default_location_id_da83b714_fk_web_location_id to web_studyubject_default_location_id_da83b714_fk_web_location_id;'),
+        migrations.RunSQL('alter table web_studysubject rename constraint web_subject_pkey to web_studysubject_pkey;'),
+        migrations.RunSQL('alter table web_studysubject_languages rename constraint web_subject_languages_pkey to web_studysubject_languages_pkey;'),
+        migrations.RunSQL('alter table web_studysubject_languages rename constraint web_subject_languages_subject_id_a5eb4f49_uniq to web_studysubject_languages_subject_id_a5eb4f49_uniq;'),
+        migrations.RunSQL('alter index if exists web_subject_15d1b6cd rename to web_studysubject_15d1b6cd;'),
+        migrations.RunSQL('alter index if exists web_subject_496f9482 rename to web_studysubject_496f9482;'),
+        migrations.RunSQL('alter index if exists web_subject_84b500ff rename to web_studysubject_84b500ff;'),
+        migrations.RunSQL('alter index if exists web_subject_9571fdf9 rename to web_studysubject_9571fdf9;'),
+        migrations.RunSQL('alter index if exists web_subject_languages_468679bd rename to web_studysubject_languages_468679bd;'),
+        migrations.RunSQL('alter index if exists web_subject_languages_ffaba1d1 rename to web_studysubject_languages_ffaba1d1;'),
+        migrations.RunSQL('alter index if exists web_subject_screening_number_75aa70c7_like rename to web_studysubject_screening_number_75aa70c7_like;')
+    ]
diff --git a/smash/web/migrations/0067_subject.py b/smash/web/migrations/0067_subject.py
new file mode 100644
index 0000000000000000000000000000000000000000..6039e17520676f685812939e069109492ba20cf5
--- /dev/null
+++ b/smash/web/migrations/0067_subject.py
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2017-11-27 13:29
+from __future__ import unicode_literals
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('web', '0066_subject'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Subject',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('tmp_study_subject_id', models.IntegerField()),
+                ('sex',
+                 models.CharField(choices=[(b'M', b'Male'), (b'F', b'Female')], max_length=1, verbose_name=b'Sex')),
+                ('first_name', models.CharField(max_length=50, verbose_name=b'First name')),
+                ('last_name', models.CharField(max_length=50, verbose_name=b'Last name')),
+                ('phone_number', models.CharField(blank=True, max_length=20, null=True, verbose_name=b'Phone number')),
+                ('phone_number_2',
+                 models.CharField(blank=True, max_length=20, null=True, verbose_name=b'Phone number 2')),
+                ('phone_number_3',
+                 models.CharField(blank=True, max_length=20, null=True, verbose_name=b'Phone number 3')),
+                ('email', models.EmailField(blank=True, max_length=254, null=True, verbose_name=b'E-mail')),
+                ('date_born', models.DateField(blank=True, null=True, verbose_name=b'Date of birth (YYYY-MM-DD)')),
+                ('address', models.CharField(blank=True, max_length=255, verbose_name=b'Address')),
+                ('postal_code', models.CharField(blank=True, max_length=7, verbose_name=b'Postal code')),
+                ('city', models.CharField(blank=True, max_length=50, verbose_name=b'City')),
+                ('dead', models.BooleanField(default=False, verbose_name=b'Deceased')),
+                ('country', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='web.Country',
+                                              verbose_name=b'Country')),
+                ('default_written_communication_language',
+                 models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE,
+                                   related_name='subjects_written_communication', to='web.Language',
+                                   verbose_name=b'Default language for document generation')),
+                ('languages', models.ManyToManyField(blank=True, to='web.Language', verbose_name=b'Known languages')),
+            ],
+        ),
+        migrations.RunSQL('insert into web_subject (tmp_study_subject_id, sex, first_name, last_name, phone_number, ' +
+                          'phone_number_2, phone_number_3, email, date_born, address, postal_code, city, dead, ' +
+                          'country_id, default_written_communication_language_id) ' +
+                          'select id, sex, first_name, last_name, phone_number, phone_number_2, phone_number_3, ' +
+                          'email, date_born, address, postal_code, city, dead, country_id, '
+                          'default_written_communication_language_id from web_studysubject;'),
+        migrations.AddField(
+            model_name='studysubject',
+            name='subject',
+            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='web.Subject',
+                                    verbose_name=b'Subject'),
+        ),
+        migrations.RunSQL('update web_studysubject set subject_id = ' +
+                          '(select id from web_subject where tmp_study_subject_id =web_studysubject.id);'),
+        migrations.RemoveField(
+            model_name='subject',
+            name='tmp_study_subject_id',
+        ),
+        migrations.AlterField(
+            model_name='studysubject',
+            name='subject',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='web.Subject',
+                                    verbose_name=b'Subject'),
+        ),
+    ]
diff --git a/smash/web/migrations/0068_remove_studysubject_dead.py b/smash/web/migrations/0068_remove_studysubject_dead.py
new file mode 100644
index 0000000000000000000000000000000000000000..75f6b95408308d0413cff30232afe1947145333e
--- /dev/null
+++ b/smash/web/migrations/0068_remove_studysubject_dead.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2017-11-27 15:29
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0067_subject'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='studysubject',
+            name='dead',
+        ),
+    ]
diff --git a/smash/web/migrations/0069_remove_studysubject_sex.py b/smash/web/migrations/0069_remove_studysubject_sex.py
new file mode 100644
index 0000000000000000000000000000000000000000..1f3c708b0a2e3d52db8ff7cf14d7bcad70fe1e5c
--- /dev/null
+++ b/smash/web/migrations/0069_remove_studysubject_sex.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2017-11-28 11:14
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0068_remove_studysubject_dead'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='studysubject',
+            name='sex',
+        ),
+    ]
diff --git a/smash/web/migrations/0070_auto_20171128_1124.py b/smash/web/migrations/0070_auto_20171128_1124.py
new file mode 100644
index 0000000000000000000000000000000000000000..fe02c8a9cedff7df383393b69fcbd63178b9185c
--- /dev/null
+++ b/smash/web/migrations/0070_auto_20171128_1124.py
@@ -0,0 +1,67 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2017-11-28 11:24
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0069_remove_studysubject_sex'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='studysubject',
+            name='address',
+        ),
+        migrations.RemoveField(
+            model_name='studysubject',
+            name='city',
+        ),
+        migrations.RemoveField(
+            model_name='studysubject',
+            name='country',
+        ),
+        migrations.RemoveField(
+            model_name='studysubject',
+            name='date_born',
+        ),
+        migrations.RemoveField(
+            model_name='studysubject',
+            name='default_written_communication_language',
+        ),
+        migrations.RemoveField(
+            model_name='studysubject',
+            name='email',
+        ),
+        migrations.RemoveField(
+            model_name='studysubject',
+            name='first_name',
+        ),
+        migrations.RemoveField(
+            model_name='studysubject',
+            name='languages',
+        ),
+        migrations.RemoveField(
+            model_name='studysubject',
+            name='last_name',
+        ),
+        migrations.RemoveField(
+            model_name='studysubject',
+            name='phone_number',
+        ),
+        migrations.RemoveField(
+            model_name='studysubject',
+            name='phone_number_2',
+        ),
+        migrations.RemoveField(
+            model_name='studysubject',
+            name='phone_number_3',
+        ),
+        migrations.RemoveField(
+            model_name='studysubject',
+            name='postal_code',
+        ),
+    ]
diff --git a/smash/web/models/__init__.py b/smash/web/models/__init__.py
index 28a4bfa0bbae63229028fc45c83657f1031f9370..2b7f7dba19788a6778d0430ed60436cc0c6c4e88 100644
--- a/smash/web/models/__init__.py
+++ b/smash/web/models/__init__.py
@@ -18,12 +18,13 @@ from holiday import Holiday
 from item import Item
 from language import Language
 from subject import Subject
+from study_subject import StudySubject
 from contact_attempt import ContactAttempt
 from mail_template import MailTemplate
 from missing_subject import MissingSubject
 from inconsistent_subject import InconsistentSubject, InconsistentField
 
 
-__all__ = [FlyingTeam, Appointment, AppointmentType, Availability, Holiday, Item, Language, Location, Room, Subject,
+__all__ = [FlyingTeam, Appointment, AppointmentType, Availability, Holiday, Item, Language, Location, Room, Subject, StudySubject,
            Visit, Worker, ContactAttempt, ConfigurationItem, MailTemplate, AppointmentTypeLink, MissingSubject,
            InconsistentSubject, InconsistentField, Country]
diff --git a/smash/web/models/appointment.py b/smash/web/models/appointment.py
index f4a6c043a3dc13da9bed30f999ae19cc42fa6caa..9b5b3944c623d47a8e090bccab83fbfed6eb245b 100644
--- a/smash/web/models/appointment.py
+++ b/smash/web/models/appointment.py
@@ -125,7 +125,7 @@ class Appointment(models.Model):
                 title = "N/A"
             return title
         else:
-            title = self.visit.subject.first_name + " " + self.visit.subject.last_name + " type: "
+            title = self.visit.subject.subject.first_name + " " + self.visit.subject.subject.last_name + " type: "
             for appointment_type in self.appointment_types.all():
                 title += appointment_type.code + ", "
             return title
diff --git a/smash/web/models/contact_attempt.py b/smash/web/models/contact_attempt.py
index b21d8d60de852e1588c785cbecfd885554390d68..e8a2608e2b78655add178a3d09de4570137a5545 100644
--- a/smash/web/models/contact_attempt.py
+++ b/smash/web/models/contact_attempt.py
@@ -7,7 +7,7 @@ __author__ = 'Valentin Grouès'
 
 
 class ContactAttempt(models.Model):
-    subject = models.ForeignKey("web.Subject",
+    subject = models.ForeignKey("web.StudySubject",
                                 verbose_name='Subject'
                                 )
     worker = models.ForeignKey("web.Worker", null=True,
diff --git a/smash/web/models/inconsistent_subject.py b/smash/web/models/inconsistent_subject.py
index b9298c515b5d7dead50cecf5d02c94615be5d8e1..d50564e7e93b5f1aa4d98a152c15bb32bac9c8ed 100644
--- a/smash/web/models/inconsistent_subject.py
+++ b/smash/web/models/inconsistent_subject.py
@@ -44,7 +44,7 @@ class InconsistentSubject(models.Model):
     class Meta:
         app_label = 'web'
 
-    subject = models.ForeignKey("web.Subject",
+    subject = models.ForeignKey("web.StudySubject",
                                 verbose_name='Subject',
                                 null=True,
                                 blank=True
diff --git a/smash/web/models/mail_template.py b/smash/web/models/mail_template.py
index 9803905cdbd38f69cf579cb622b606563b979068..5d6e081bcf38a7f96834546549dc4f961e030407 100644
--- a/smash/web/models/mail_template.py
+++ b/smash/web/models/mail_template.py
@@ -9,7 +9,7 @@ from django.db import models
 from .constants import MAIL_TEMPLATE_CONTEXT_CHOICES, MAIL_TEMPLATE_CONTEXT_APPOINTMENT, \
     MAIL_TEMPLATE_CONTEXT_SUBJECT, MAIL_TEMPLATE_CONTEXT_VISIT
 from ..docx_helper import process_file
-from ..models import Appointment, Visit, Subject, Worker
+from ..models import Appointment, Visit, StudySubject, Worker
 
 DATE_FORMAT_FULL = "%A %d %B %Y"
 
@@ -124,16 +124,16 @@ class MailTemplate(models.Model):
     def apply(self, instance, user, stream):
         appointment = None
         visit = None
-        subject = None
+        study_subject = None
         if isinstance(instance, Appointment):
             appointment = instance
             visit = instance.visit
-            subject = visit.subject
+            study_subject = visit.subject
         elif isinstance(instance, Visit):
             visit = instance
-            subject = visit.subject
-        elif isinstance(instance, Subject):
-            subject = instance
+            study_subject = visit.subject
+        elif isinstance(instance, StudySubject):
+            study_subject = instance
         # set locale to get correct date format
         locale_name = self.language.locale
         if platform.system() == 'Windows':
@@ -143,7 +143,7 @@ class MailTemplate(models.Model):
             self._add_generic_replacements(replacements, Worker.get_by_user(user))
             self._add_appointment_replacements(replacements, appointment)
             self._add_visit_replacements(replacements, visit)
-            self._add_subject_replacements(replacements, subject)
+            self._add_subject_replacements(replacements, study_subject)
             process_file(self.template_file.path, stream, replacements)
         return stream
 
@@ -194,33 +194,33 @@ class MailTemplate(models.Model):
                 "##V_DATE_ENDS_SHORT##": visit.datetime_end.strftime(DATE_FORMAT_SHORT),
             })
 
-    def _add_subject_replacements(self, replacements, subject):
-        if subject is not None:
-            if subject.date_born is not None:
-                date_born = subject.date_born.strftime(DATE_FORMAT_SHORT)
+    def _add_subject_replacements(self, replacements, study_subject):
+        if study_subject is not None:
+            if study_subject.subject.date_born is not None:
+                date_born = study_subject.subject.date_born.strftime(DATE_FORMAT_SHORT)
             else:
                 date_born = None
             replacements.update({
-                "##S_FULL_NAME##": unicode(subject),
-                "##S_FIRST_NAME##": subject.first_name,
-                "##S_LAST_NAME##": subject.last_name,
-                "##S_ADDRESS##": subject.address,
-                "##S_CITY##": subject.city,
-                "##S_COUNTRY##": unicode(subject.country),
-                "##S_DIAGNOSIS_YEAR##": subject.year_of_diagnosis,
-                "##S_DATE_ADDED##": subject.date_added.strftime(DATE_FORMAT_SHORT),
+                "##S_FULL_NAME##": unicode(study_subject),
+                "##S_FIRST_NAME##": study_subject.subject.first_name,
+                "##S_LAST_NAME##": study_subject.subject.last_name,
+                "##S_ADDRESS##": study_subject.subject.address,
+                "##S_CITY##": study_subject.subject.city,
+                "##S_COUNTRY##": unicode(study_subject.subject.country),
+                "##S_DIAGNOSIS_YEAR##": study_subject.year_of_diagnosis,
+                "##S_DATE_ADDED##": study_subject.date_added.strftime(DATE_FORMAT_SHORT),
                 "##S_DATE_BORN##": date_born,
-                "##S_DIAGNOSIS##": subject.diagnosis,
-                "##S_EMAIL##": subject.email,
-                "##S_SEX##": subject.get_sex_display(),
-                "##S_MPOWER_ID##": subject.mpower_id,
-                "##S_ND_NUMBER##": subject.nd_number,
-                "##S_PHONE_NUMBER##": subject.phone_number,
-                "##S_PHONE_NUMBER_2##": subject.phone_number_2,
-                "##S_PHONE_NUMBER_3##": subject.phone_number_3,
-                "##S_POST_CODE##": subject.postal_code,
-                "##S_SCREENING_NUMBER##": subject.screening_number,
-                "##S_TYPE##": subject.get_type_display(),
-                '##S_MAIL_LANGUAGE##': str(subject.default_written_communication_language),
-                '##S_KNOWN_LANGUAGES##': ", ".join([l.name for l in subject.languages.all()])
+                "##S_DIAGNOSIS##": study_subject.diagnosis,
+                "##S_EMAIL##": study_subject.subject.email,
+                "##S_SEX##": study_subject.subject.get_sex_display(),
+                "##S_MPOWER_ID##": study_subject.mpower_id,
+                "##S_ND_NUMBER##": study_subject.nd_number,
+                "##S_PHONE_NUMBER##": study_subject.subject.phone_number,
+                "##S_PHONE_NUMBER_2##": study_subject.subject.phone_number_2,
+                "##S_PHONE_NUMBER_3##": study_subject.subject.phone_number_3,
+                "##S_POST_CODE##": study_subject.subject.postal_code,
+                "##S_SCREENING_NUMBER##": study_subject.screening_number,
+                "##S_TYPE##": study_subject.get_type_display(),
+                '##S_MAIL_LANGUAGE##': str(study_subject.subject.default_written_communication_language),
+                '##S_KNOWN_LANGUAGES##': ", ".join([l.name for l in study_subject.subject.languages.all()])
             })
diff --git a/smash/web/models/missing_subject.py b/smash/web/models/missing_subject.py
index ff7353bbfec9910de716a47575fc90a9d0466782..6050dd7e290ee6e10b6edbf059b2d592cc4e3c9d 100644
--- a/smash/web/models/missing_subject.py
+++ b/smash/web/models/missing_subject.py
@@ -11,7 +11,7 @@ class MissingSubject(models.Model):
         verbose_name='Ignore missing subject'
     )
 
-    subject = models.ForeignKey("web.Subject",
+    subject = models.ForeignKey("web.StudySubject",
                                 verbose_name='Subject',
                                 null=True,
                                 blank=True
diff --git a/smash/web/models/study_subject.py b/smash/web/models/study_subject.py
new file mode 100644
index 0000000000000000000000000000000000000000..7fdc2eaca43b9bfffe90bca16f298dc88056d1ec
--- /dev/null
+++ b/smash/web/models/study_subject.py
@@ -0,0 +1,119 @@
+# coding=utf-8
+from django.core.validators import RegexValidator
+from django.db import models
+
+from constants import BOOL_CHOICES, SUBJECT_TYPE_CHOICES
+from . import Appointment, Location, Visit
+
+
+class StudySubject(models.Model):
+    class Meta:
+        app_label = 'web'
+
+    def finish_all_visits(self):
+        visits = Visit.objects.filter(subject=self, is_finished=False)
+        for visit in visits:
+            visit.is_finished = True
+            visit.save()
+
+    def finish_all_appointments(self):
+        appointments = Appointment.objects.filter(visit__subject=self, status=Appointment.APPOINTMENT_STATUS_SCHEDULED)
+        for appointment in appointments:
+            appointment.status = Appointment.APPOINTMENT_STATUS_CANCELLED
+            appointment.save()
+
+    def mark_as_resigned(self):
+        self.resigned = True
+        self.finish_all_visits()
+        self.finish_all_appointments()
+
+    subject = models.ForeignKey("web.Subject",
+                                verbose_name='Subject',
+                                editable=False,
+                                null=False,
+                                )
+
+    postponed = models.BooleanField(choices=BOOL_CHOICES,
+                                    verbose_name='Postponed',
+                                    default=False
+                                    )
+    datetime_contact_reminder = models.DateTimeField(
+        null=True,
+        blank=True,
+        verbose_name='Please make a contact on',
+    )
+    type = models.CharField(max_length=1,
+                            choices=SUBJECT_TYPE_CHOICES.items(),
+                            verbose_name='Type'
+                            )
+
+    default_location = models.ForeignKey(Location,
+                                         verbose_name='Default appointment location',
+                                         )
+
+    flying_team = models.ForeignKey("web.FlyingTeam",
+                                    verbose_name='Default flying team location (if applicable)',
+                                    null=True, blank=True
+                                    )
+
+    screening_number = models.CharField(max_length=50,
+                                        unique=True,
+                                        verbose_name='Screening number', blank=False, null=False
+                                        )
+    nd_number = models.CharField(max_length=25,
+                                 blank=True,
+                                 verbose_name='ND number',
+                                 validators=[
+                                     RegexValidator('^(ND[0-9]{4}|)$',
+                                                    message="ND number should look as follows: NDxxxx")]
+                                 )
+    mpower_id = models.CharField(max_length=20,
+                                 blank=True,
+                                 verbose_name='MPower ID'
+                                 )
+    comments = models.TextField(max_length=2000,
+                                blank=True,
+                                verbose_name='Comments'
+                                )
+    date_added = models.DateField(verbose_name='Added on',
+                                  auto_now=True
+                                  )
+    referral = models.CharField(max_length=128,
+                                null=True,
+                                blank=True,
+                                verbose_name='Referred by'
+                                )
+    diagnosis = models.CharField(max_length=128,
+                                 null=True,
+                                 blank=True,
+                                 verbose_name='Diagnosis'
+                                 )
+    year_of_diagnosis = models.IntegerField(
+        null=True,
+        blank=True,
+        verbose_name='Year of diagnosis (YYYY)'
+    )
+
+    information_sent = models.BooleanField(
+        verbose_name='Information sent',
+        default=False
+    )
+    pd_in_family = models.NullBooleanField(
+        verbose_name='PD in family',
+        default=None,
+    )
+    resigned = models.BooleanField(
+        verbose_name='Resigned',
+        default=False,
+        editable=True
+    )
+    resign_reason = models.TextField(max_length=2000,
+                                     blank=True,
+                                     verbose_name='Resign reason'
+                                     )
+
+    def __str__(self):
+        return "%s %s" % (self.subject.first_name, self.subject.last_name)
+
+    def __unicode__(self):
+        return "%s %s" % (self.subject.first_name, self.subject.last_name)
diff --git a/smash/web/models/subject.py b/smash/web/models/subject.py
index ab779e001586776b650fea2bb7f8da0e67e9162b..ae09e54185c35374522fb59b8efb790af5428c9b 100644
--- a/smash/web/models/subject.py
+++ b/smash/web/models/subject.py
@@ -1,79 +1,37 @@
 # coding=utf-8
-from django.core.validators import RegexValidator
 from django.db import models
 
-from constants import BOOL_CHOICES, SEX_CHOICES, SUBJECT_TYPE_CHOICES, COUNTRY_OTHER_ID
-from web.models import Country
-from . import Appointment, Language, Location, Visit
+from constants import SEX_CHOICES, COUNTRY_OTHER_ID
+from web.models import Country, Visit, Appointment
+from . import Language
 
 
 class Subject(models.Model):
     class Meta:
         app_label = 'web'
 
-    def finish_all_visits(self):
-        visits = Visit.objects.filter(subject=self, is_finished=False)
-        for visit in visits:
-            visit.is_finished = True
-            visit.save()
-
-    def finish_all_appointments(self):
-        appointments = Appointment.objects.filter(visit__subject=self, status=Appointment.APPOINTMENT_STATUS_SCHEDULED)
-        for appointment in appointments:
-            appointment.status = Appointment.APPOINTMENT_STATUS_CANCELLED
-            appointment.save()
-
-    def mark_as_dead(self):
-        self.dead = True
-        self.finish_all_visits()
-        self.finish_all_appointments()
-
-    def mark_as_resigned(self):
-        self.resigned = True
-        self.finish_all_visits()
-        self.finish_all_appointments()
-
     sex = models.CharField(max_length=1,
                            choices=SEX_CHOICES,
                            verbose_name='Sex'
                            )
-    postponed = models.BooleanField(choices=BOOL_CHOICES,
-                                    verbose_name='Postponed',
-                                    default=False
-                                    )
-    datetime_contact_reminder = models.DateTimeField(
-        null=True,
-        blank=True,
-        verbose_name='Please make a contact on',
-    )
-    type = models.CharField(max_length=1,
-                            choices=SUBJECT_TYPE_CHOICES.items(),
-                            verbose_name='Type'
-                            )
-
-    default_location = models.ForeignKey(Location,
-                                         verbose_name='Default appointment location',
-                                         )
-
-    flying_team = models.ForeignKey("web.FlyingTeam",
-                                    verbose_name='Default flying team location (if applicable)',
-                                    null=True, blank=True
-                                    )
 
     first_name = models.CharField(max_length=50,
                                   verbose_name='First name'
                                   )
+
     last_name = models.CharField(max_length=50,
                                  verbose_name='Last name'
                                  )
+
     languages = models.ManyToManyField(Language,
                                        blank=True,
                                        verbose_name='Known languages'
                                        )
+
     default_written_communication_language = models.ForeignKey(Language,
                                                                null=True,
                                                                blank=True,
-                                                               related_name="%(class)s_written_comunication",
+                                                               related_name="subjects_written_communication",
                                                                verbose_name='Default language for document generation'
                                                                )
     phone_number = models.CharField(max_length=20,
@@ -81,103 +39,76 @@ class Subject(models.Model):
                                     blank=True,
                                     verbose_name='Phone number'
                                     )
+
     phone_number_2 = models.CharField(max_length=20,
                                       null=True,
                                       blank=True,
                                       verbose_name='Phone number 2'
                                       )
+
     phone_number_3 = models.CharField(max_length=20,
                                       null=True,
                                       blank=True,
                                       verbose_name='Phone number 3'
                                       )
+
     email = models.EmailField(
         null=True,
         blank=True,
         verbose_name='E-mail'
     )
+
     date_born = models.DateField(
         null=True,
         blank=True,
         verbose_name='Date of birth (YYYY-MM-DD)'
     )
+
     address = models.CharField(max_length=255,
                                blank=True,
                                verbose_name='Address'
                                )
+
     postal_code = models.CharField(max_length=7,
                                    blank=True,
                                    verbose_name='Postal code'
                                    )
+
     city = models.CharField(max_length=50,
                             blank=True,
                             verbose_name='City'
                             )
+
     country = models.ForeignKey(Country,
                                 null=False,
                                 blank=False,
                                 default=COUNTRY_OTHER_ID,
                                 verbose_name='Country'
                                 )
-    screening_number = models.CharField(max_length=50,
-                                        unique=True,
-                                        verbose_name='Screening number', blank=False, null=False
-                                        )
-    nd_number = models.CharField(max_length=25,
-                                 blank=True,
-                                 verbose_name='ND number',
-                                 validators=[
-                                     RegexValidator('^(ND[0-9]{4}|)$', message="ND number should look as follows: NDxxxx")]
-                                 )
-    mpower_id = models.CharField(max_length=20,
-                                 blank=True,
-                                 verbose_name='MPower ID'
-                                 )
-    comments = models.TextField(max_length=2000,
-                                blank=True,
-                                verbose_name='Comments'
-                                )
-    date_added = models.DateField(verbose_name='Added on',
-                                  auto_now=True
-                                  )
-    referral = models.CharField(max_length=128,
-                                null=True,
-                                blank=True,
-                                verbose_name='Referred by'
-                                )
-    diagnosis = models.CharField(max_length=128,
-                                 null=True,
-                                 blank=True,
-                                 verbose_name='Diagnosis'
-                                 )
-    year_of_diagnosis = models.IntegerField(
-        null=True,
-        blank=True,
-        verbose_name='Year of diagnosis (YYYY)'
-    )
 
-    information_sent = models.BooleanField(
-        verbose_name='Information sent',
-        default=False
-    )
-    pd_in_family = models.NullBooleanField(
-        verbose_name='PD in family',
-        default=None,
-    )
     dead = models.BooleanField(
         verbose_name='Deceased',
         default=False,
         editable=True
     )
-    resigned = models.BooleanField(
-        verbose_name='Resigned',
-        default=False,
-        editable=True
-    )
-    resign_reason = models.TextField(max_length=2000,
-                                     blank=True,
-                                     verbose_name='Resign reason'
-                                     )
+
+    def mark_as_dead(self):
+        self.dead = True
+        self.finish_all_visits()
+        self.finish_all_appointments()
+
+    def finish_all_visits(self):
+        visits = Visit.objects.filter(subject__subject=self, is_finished=False)
+        for visit in visits:
+            visit.is_finished = True
+            visit.save()
+
+    def finish_all_appointments(self):
+        appointments = Appointment.objects.filter(visit__subject__subject=self,
+                                                  status=Appointment.APPOINTMENT_STATUS_SCHEDULED)
+        for appointment in appointments:
+            appointment.status = Appointment.APPOINTMENT_STATUS_CANCELLED
+            appointment.save()
 
     def __str__(self):
         return "%s %s" % (self.first_name, self.last_name)
diff --git a/smash/web/models/visit.py b/smash/web/models/visit.py
index 1f491319e8f87585433ee7c1129f1b48c152ef33..61b29704181cff23b8091e5fb43c0e01232a3e88 100644
--- a/smash/web/models/visit.py
+++ b/smash/web/models/visit.py
@@ -12,7 +12,7 @@ class Visit(models.Model):
     class Meta:
         app_label = 'web'
 
-    subject = models.ForeignKey("web.Subject", on_delete=models.CASCADE,
+    subject = models.ForeignKey("web.StudySubject", on_delete=models.CASCADE,
                                 verbose_name='Subject'
                                 )
     datetime_begin = models.DateTimeField(
@@ -42,16 +42,16 @@ class Visit(models.Model):
     )
 
     def __unicode__(self):
-        return "%s %s" % (self.subject.first_name, self.subject.last_name)
+        return "%s %s" % (self.subject.subject.first_name, self.subject.subject.last_name)
 
     def __str__(self):
-        return "%s %s" % (self.subject.first_name, self.subject.last_name)
+        return "%s %s" % (self.subject.subject.first_name, self.subject.subject.last_name)
 
     def mark_as_finished(self):
         self.is_finished = True
         self.save()
 
-        if (not self.subject.dead) and (not self.subject.resigned):
+        if (not self.subject.subject.dead) and (not self.subject.resigned):
             visit_started = Visit.objects.filter(subject=self.subject).filter(visit_number=1)[0].datetime_begin
             follow_up_number = Visit.objects.filter(subject=self.subject).count() + 1
 
diff --git a/smash/web/redcap_connector.py b/smash/web/redcap_connector.py
index bca70fc0951a5894d2557f83a03f271eb216ce85..8a2828583aee2e92ff795c73ae3182fc505d5e9b 100644
--- a/smash/web/redcap_connector.py
+++ b/smash/web/redcap_connector.py
@@ -7,7 +7,7 @@ import pycurl
 import certifi
 from django_cron import CronJobBase, Schedule
 
-from web.models import ConfigurationItem, Subject, Language
+from web.models import ConfigurationItem, StudySubject, Language
 from web.models.constants import REDCAP_TOKEN_CONFIGURATION_TYPE, \
     REDCAP_BASE_URL_CONFIGURATION_TYPE
 from web.models.inconsistent_subject import InconsistentField, InconsistentSubject
@@ -85,7 +85,7 @@ class RedcapConnector(object):
         for subject in red_cap_subjects:
             red_cap_subject_by_nd[subject.nd_number] = subject
 
-        smash_subjects = Subject.objects.exclude(nd_number='')
+        smash_subjects = StudySubject.objects.exclude(nd_number='')
         smash_subject_by_nd = {}
         for subject in smash_subjects:
             smash_subject_by_nd[subject.nd_number] = subject
@@ -158,7 +158,7 @@ class RedcapConnector(object):
         for subject in red_cap_subjects:
             red_cap_subject_by_nd[subject.nd_number] = subject
 
-        smash_subjects = Subject.objects.exclude(nd_number='')
+        smash_subjects = StudySubject.objects.exclude(nd_number='')
 
         result = []
         for subject in smash_subjects:
@@ -173,14 +173,14 @@ class RedcapConnector(object):
         return result
 
     @staticmethod
-    def create_inconsistency_subject(red_cap_subject, subject, url):
+    def create_inconsistency_subject(red_cap_subject, study_subject, url):
         fields = []
-        if subject.sex != red_cap_subject.sex:
-            field = InconsistentField.create("sex", subject.sex, red_cap_subject.sex)
+        if study_subject.subject.sex != red_cap_subject.sex:
+            field = InconsistentField.create("sex", study_subject.subject.sex, red_cap_subject.sex)
             fields.append(field)
         subject_date_born = ""
-        if subject.date_born is not None:
-            subject_date_born = subject.date_born.strftime('%Y-%m-%d')
+        if study_subject.subject.date_born is not None:
+            subject_date_born = study_subject.subject.date_born.strftime('%Y-%m-%d')
         redcap_subject_date_born = red_cap_subject.date_born
         if redcap_subject_date_born is None:
             redcap_subject_date_born = ""
@@ -189,23 +189,23 @@ class RedcapConnector(object):
         if subject_date_born != redcap_subject_date_born:
             field = InconsistentField.create("date of birth", subject_date_born, redcap_subject_date_born)
             fields.append(field)
-        if subject.dead != red_cap_subject.dead:
-            field = InconsistentField.create("dead", str(subject.dead), str(red_cap_subject.dead))
+        if study_subject.subject.dead != red_cap_subject.dead:
+            field = InconsistentField.create("dead", str(study_subject.subject.dead), str(red_cap_subject.dead))
             fields.append(field)
-        if different_string(subject.mpower_id, red_cap_subject.mpower_id):
-            field = InconsistentField.create("mpower id", subject.mpower_id, red_cap_subject.mpower_id)
+        if different_string(study_subject.mpower_id, red_cap_subject.mpower_id):
+            field = InconsistentField.create("mpower id", study_subject.mpower_id, red_cap_subject.mpower_id)
             fields.append(field)
         missing_language = False
         if len(red_cap_subject.languages) < 4:
-            for language in subject.languages.all():
+            for language in study_subject.subject.languages.all():
                 if language not in red_cap_subject.languages:
                     missing_language = True
         for language in red_cap_subject.languages:
-            if language not in subject.languages.all():
+            if language not in study_subject.subject.languages.all():
                 missing_language = True
         if missing_language:
             subject_languages = ""
-            for language in subject.languages.all():
+            for language in study_subject.subject.languages.all():
                 subject_languages += language.name + ", "
             red_cap_subject_languages = ""
             for language in red_cap_subject.languages:
@@ -214,7 +214,7 @@ class RedcapConnector(object):
             fields.append(field)
         result = None
         if len(fields) > 0:
-            result = InconsistentSubject.create(smash_subject=subject, url=url, fields=fields)
+            result = InconsistentSubject.create(smash_subject=study_subject, url=url, fields=fields)
         return result
 
     def create_redcap_link(self, pid, redcap_version, subject):
diff --git a/smash/web/statistics.py b/smash/web/statistics.py
index 63a710dca60acf2a2269e7a27d41ff9318ca2e92..f94df0a8a5c6a318c0b4f6ee6bb766732201d722 100644
--- a/smash/web/statistics.py
+++ b/smash/web/statistics.py
@@ -16,28 +16,28 @@ SELECT DISTINCT(rank() OVER (PARTITION BY subject_id ORDER BY datetime_begin)) A
 """
 
 QUERY_APPOINTMENTS_COUNT = """
-SELECT count(*) FROM web_appointment LEFT JOIN (SELECT id, subject_id, rank()
+SELECT count(*) FROM web_appointment LEFT JOIN (SELECT id, subject_id as web_visit_subject_id, rank()
 OVER (PARTITION BY subject_id ORDER BY datetime_begin) AS rnk FROM web_visit)
 a ON a.id = web_appointment.visit_id 
-LEFT JOIN web_subject ON web_subject.id = subject_id
+LEFT JOIN web_studysubject ON web_studysubject.id = web_visit_subject_id
 WHERE a.rnk = %s 
 AND EXTRACT(MONTH FROM web_appointment.datetime_when) = %s
 AND EXTRACT(YEAR FROM web_appointment.datetime_when) = %s
 """
 
 QUERY_VISITS_ENDED_COUNT = """
-SELECT count(*) FROM  (SELECT id, subject_id, datetime_begin, datetime_end, rank()
+SELECT count(*) FROM  (SELECT id, subject_id as web_visit_subject_id, datetime_begin, datetime_end, rank()
 OVER (PARTITION BY subject_id ORDER BY datetime_begin) AS rnk FROM web_visit) a
-LEFT JOIN web_subject ON web_subject.id = subject_id
+LEFT JOIN web_studysubject ON web_studysubject.id = web_visit_subject_id
 WHERE a.rnk = %s AND
 EXTRACT(MONTH FROM a.datetime_end) = %s AND
 EXTRACT(YEAR FROM a.datetime_end) = %s
 """
 
 QUERY_VISITS_STARTED_COUNT = """
-SELECT count(*) FROM  (SELECT id, subject_id, datetime_begin, datetime_end, rank()
+SELECT count(*) FROM  (SELECT id, subject_id as web_visit_subject_id, datetime_begin, datetime_end, rank()
 OVER (PARTITION BY subject_id ORDER BY datetime_begin) AS rnk FROM web_visit) a
-LEFT JOIN web_subject ON web_subject.id = subject_id
+LEFT JOIN web_studysubject ON web_studysubject.id = web_visit_subject_id
 WHERE a.rnk = %s AND
 EXTRACT(MONTH FROM a.datetime_begin) = %s AND
 EXTRACT(YEAR FROM a.datetime_begin) = %s
@@ -45,10 +45,10 @@ EXTRACT(YEAR FROM a.datetime_begin) = %s
 
 QUERY_APPOINTMENTS = """
 SELECT types.appointment_type_id, web_appointment.status, count(*) FROM web_appointment
-LEFT JOIN (SELECT id, subject_id, rank() OVER (PARTITION BY subject_id ORDER BY datetime_begin) AS rnk
+LEFT JOIN (SELECT id, subject_id as web_visit_subject_id, rank() OVER (PARTITION BY subject_id ORDER BY datetime_begin) AS rnk
 FROM web_visit) a ON a.id = web_appointment.visit_id LEFT JOIN web_appointmenttypelink types
 ON types.appointment_id = web_appointment.id 
-LEFT JOIN web_subject ON web_subject.id = subject_id
+LEFT JOIN web_studysubject ON web_studysubject.id = web_visit_subject_id
 WHERE a.rnk = %s
 AND EXTRACT(MONTH FROM web_appointment.datetime_when) = %s
 AND EXTRACT(YEAR FROM web_appointment.datetime_when) = %s
@@ -136,7 +136,7 @@ class StatisticsManager(object):
             query = QUERY_APPOINTMENTS
             subject_type_clause = ""
             if subject_type is not None:
-                subject_type_clause = " AND web_subject.type = '{}'".format(subject_type)
+                subject_type_clause = " AND web_studysubject.type = '{}'".format(subject_type)
             query = query.format(subject_type_clause)
             with connection.cursor() as cursor:
                 cursor.execute(query, [visit, month, year])
@@ -159,7 +159,7 @@ class StatisticsManager(object):
     def _get_count_from_filters_or_sql(model, filters, query, visit, month, year, subject_type):
         if visit:
             if subject_type is not None:
-                query += " AND web_subject.type = '{}'".format(subject_type)
+                query += " AND web_studysubject.type = '{}'".format(subject_type)
             with connection.cursor() as cursor:
                 cursor.execute(
                     query,
@@ -208,7 +208,7 @@ class StatisticsManager(object):
     def _get_visits_ranks(subject_type=None):
         query = QUERY_VISITS_RANKS
         if subject_type is not None:
-            query += " LEFT JOIN web_subject ON web_subject.id = web_visit.subject_id WHERE web_subject.type = '{}'".format(
+            query += " LEFT JOIN web_studysubject ON web_studysubject.id = web_visit.subject_id WHERE web_studysubject.type = '{}'".format(
                 subject_type)
         with connection.cursor() as cursor:
             cursor.execute(
diff --git a/smash/web/templates/appointments/add.html b/smash/web/templates/appointments/add.html
index 1cfc3c883b50b027f97ed385d08855e67f279f0b..b29fc125c36b8e753afa41b7067714f4132f7f2f 100644
--- a/smash/web/templates/appointments/add.html
+++ b/smash/web/templates/appointments/add.html
@@ -133,14 +133,15 @@
                     document.getElementById("id_datetime_when").value = dateString;
 
                 },
-                events: get_calendar_events_function("{% url 'web.api.appointments' full_list %}", false),
+                events: get_calendar_events_function("{% url 'web.api.appointments' full_list %}", false)
             });
 
         });
 
-        appointment_type_behaviour($("input[name='appointment_types']"), $("input[name='length']"), "{% url 'web.api.appointment_types' %}");
+        var lengthInput = $("input[name='length']");
+        appointment_type_behaviour($("input[name='appointment_types']"), lengthInput, "{% url 'web.api.appointment_types' %}");
         appointment_flying_team_place_behaviour($("select[name='flying_team']"), $("select[name='location']"));
-        appointment_date_change_behaviour($("input[name='datetime_when']"), $("select[name='worker_assigned']"), $("input[name='length']"));
+        appointment_date_change_behaviour($("input[name='datetime_when']"), $("select[name='worker_assigned']"), lengthInput);
     </script>
 
     {% include "includes/datetimepicker.js.html" %}
diff --git a/smash/web/templates/appointments/edit.html b/smash/web/templates/appointments/edit.html
index d87475c2b2e8403a4e619da027ff9c7b53db6ace..1d7cfa2ab4d86d3105f38041af240c4202339785 100644
--- a/smash/web/templates/appointments/edit.html
+++ b/smash/web/templates/appointments/edit.html
@@ -42,7 +42,7 @@
                         <h3 class="box-title">Appointment's details</h3>
                     </div>
                     <div class="box-body">
-                        {% for field in form %}
+                        {% for field in appointment_form %}
                             <div class="col-md-6 form-group  {% if field.errors %}has-error{% endif %}  {% if field|is_checkbox %}multi-checkboxes{% endif %}">
                                 <label for="{# TODO #}" class="col-sm-4 control-label">
                                     {{ field.label }}
@@ -87,6 +87,30 @@
                         </div><!-- /.box-body -->
 
                     </fieldset>
+                    <fieldset>
+                        <div class="box-header with-border">
+                            <h3 class="box-title">Subject's study details</h3>
+                        </div>
+
+                        <div class="box-body">
+                            {% for field in study_subject_form %}
+                                <div class="col-md-6 form-group  {% if field.errors %}has-error{% endif %}">
+                                    <label for="{# TODO #}" class="col-sm-4 control-label">
+                                        {{ field.label }}
+                                    </label>
+
+                                    <div class="col-sm-8">
+                                        {{ field|add_class:'form-control' }}
+                                    </div>
+
+                                    {% if field.errors %}
+                                        <span class="help-block"> {{ field.errors }} </span>
+                                    {% endif %}
+                                </div>
+                            {% endfor %}
+                        </div><!-- /.box-body -->
+
+                    </fieldset>
                 {% endif %}
                 <div class="box-footer">
                     <div class="col-sm-3">
@@ -138,9 +162,10 @@
                 "autoWidth": false
             });
         });
-        appointment_type_behaviour($("input[name='appointment-appointment_types']"), $("input[name='appointment-length']"), "{% url 'web.api.appointment_types' %}");
+        var appointmentLengthInput = $("input[name='appointment-length']");
+        appointment_type_behaviour($("input[name='appointment-appointment_types']"), appointmentLengthInput, "{% url 'web.api.appointment_types' %}");
         appointment_flying_team_place_behaviour($("select[name='appointment-flying_team']"), $("select[name='appointment-location']"));
-        appointment_date_change_behaviour($("input[name='appointment-datetime_when']"), $("select[name='appointment-worker_assigned']"), $("input[name='appointment-length']"), {{ appointment.id }});
+        appointment_date_change_behaviour($("input[name='appointment-datetime_when']"), $("select[name='appointment-worker_assigned']"), appointmentLengthInput, {{ appointment.id }});
 
     </script>
 
diff --git a/smash/web/templates/export/index.html b/smash/web/templates/export/index.html
index a4e8aef298bbe802d4997a9f54f325ca03b8d0c5..39276ce9354c7af97029bb0aa4665ddbd8be01ff 100644
--- a/smash/web/templates/export/index.html
+++ b/smash/web/templates/export/index.html
@@ -24,12 +24,12 @@
             <li><a href="{% url 'web.views.export_to_excel' 'subjects' %}"><i class="fa fa-file-excel-o"></i> XLS -
                 Excel</a>
             </li>
-            <li><a href="{% url 'web.views.export_to_excel' 'appointments' %}"><i class="fa fa-file-text-o"></i> CSV -
+            <li><a href="{% url 'web.views.export_to_csv' 'subjects' %}"><i class="fa fa-file-text-o"></i> CSV -
                 Text based</a></li>
         </ul>
         <h3>Appointments</h3>
         <ul>
-            <li><a href="{% url 'web.views.export_to_csv' 'subjects' %}"><i class="fa fa-file-excel-o"></i> XLS -
+            <li><a href="{% url 'web.views.export_to_excel' 'appointments' %}"><i class="fa fa-file-excel-o"></i> XLS -
                 Excel</a></li>
             <li><a href="{% url 'web.views.export_to_csv' 'appointments' %}"><i class="fa fa-file-text-o"></i> CSV -
                 Text based</a></li>
diff --git a/smash/web/templates/subjects/add.html b/smash/web/templates/subjects/add.html
index 317c54e6953fe565d2e5e01216834c30228340a8..3bacf8021599c202596190da36dc00db059e1f88 100644
--- a/smash/web/templates/subjects/add.html
+++ b/smash/web/templates/subjects/add.html
@@ -23,37 +23,60 @@
 {% block maincontent %}
 
     {% block content %}
-        <div class="box box-info">
+        <div class="row">
             <div class="box-header with-border">
                 <a href="{% url 'web.views.subjects' %}" class="btn btn-block btn-default">Cancel</a>
             </div>
 
-            {% comment %} <div class="box-header with-border">
-		<h3 class="box-title">Details of subject</h3>
-	</div>{% endcomment %}
+        </div>
+        <div class="row">
 
             <form method="post" action="" class="form-horizontal">
                 {% csrf_token %}
-
-                <div class="box-body">
-                    <div class="col-sm-6">
-                        {% for field in form %}
-                            <div class="form-group {% if field.errors %}has-error{% endif %}">
-                                <label class="col-sm-4 control-label">
-                                    {{ field.label }}
-                                </label>
-
-                                <div class="col-sm-8">
-                                    {{ field|add_class:'form-control' }}
-                                </div>
-
-                                {% if field.errors %}
-                                    <span class="help-block">
-  							{{ field.errors }}
-  						</span>
-                                {% endif %}
+                <div class="col-md-12">
+                    <div class="box box-body">
+                        <div class="box-header with-border">
+                            <h3>Subject data</h3>
+                        </div>
+                        <div class="box-body">
+                            <div class="col-md-12">
+                                {% for field in subject_form %}
+                                    <div class="col-md-6 form-group {% if field.errors %}has-error{% endif %}">
+                                        <label class="col-sm-4 control-label">
+                                            {{ field.label }}
+                                        </label>
+
+                                        <div class="col-sm-8">
+                                            {{ field|add_class:'form-control' }}
+                                        </div>
+
+                                        {% if field.errors %}
+                                            <span class="help-block">{{ field.errors }}</span>
+                                        {% endif %}
+                                    </div>
+                                {% endfor %}
                             </div>
-                        {% endfor %}
+                        </div>
+                        <div class="box-header with-border">
+                            <h3>Study data</h3>
+                        </div>
+                        <div class="box-body">
+                            {% for field in study_subject_form %}
+                                <div class="col-md-6 form-group {% if field.errors %}has-error{% endif %}">
+                                    <label class="col-sm-4 control-label">
+                                        {{ field.label }}
+                                    </label>
+
+                                    <div class="col-sm-8">
+                                        {{ field|add_class:'form-control' }}
+                                    </div>
+
+                                    {% if field.errors %}
+                                        <span class="help-block">{{ field.errors }}</span>
+                                    {% endif %}
+                                </div>
+                            {% endfor %}
+                        </div>
                     </div>
                 </div><!-- /.box-body -->
 
@@ -79,17 +102,28 @@
     <script src="{% static 'AdminLTE/plugins/awesomplete/awesomplete.min.js' %}"></script>
     <script>
         $(document).ready(function () {
+
+            var cityInput = document.querySelector("#id_subject-city");
+            var referralInput = document.querySelector("#id_study_subject-referral");
+            var lastNameInput = $("input[name='subject-last_name']");
+            var firstNameInput = $("input[name='subject-first_name']");
+
+            if (cityInput === null || referralInput === null || lastNameInput.length === 0 || firstNameInput.length === 0) {
+                alert("Internal error. Contact administrators.");
+            }
+
             // If ever to debug and thinking why it doesn't work => look if there is 'null' in data from API
             $.get("{% url 'web.api.cities' %}", function (data) {
-                new Awesomplete(document.querySelector("#id_city")).list = data.cities;
+                new Awesomplete(cityInput).list = data.cities;
             });
             $.get("{% url 'web.api.referrals' %}", function (data) {
-                new Awesomplete(document.querySelector("#id_referral")).list = data.referrals;
+                new Awesomplete(referralInput).list = data.referrals;
             });
 
+
             var checkDuplicates = function (e) {
-                var first_name = $("input[name='first_name']").val();
-                var last_name = $("input[name='last_name']").val();
+                var first_name = firstNameInput.val();
+                var last_name = lastNameInput.val();
                 if (last_name !== "") {
                     var url = "{% url 'web.api.subjects' 'GENERIC' %}";
                     url += "?columns[0][data]=first_name&columns[0][search][value]=" + first_name;
@@ -102,19 +136,21 @@
                             }
                         });
                         if (subjects.length > 0) {
-                            $("#duplicate_warning").css("display", "block");
+                            var duplicateWarningDiv = $("#duplicate_warning");
+                            duplicateWarningDiv.css("display", "block");
                             var content = "There are possible duplicate(s) with the same name:<br/>";
                             $.each(subjects, function (index, subject) {
                                 content += subject.first_name + " " + subject.last_name + ", born: " + subjects.date_born + ", screening number: " + subject.screening_number + "<br/>"
                             });
-                            $("#duplicate_warning").html(content);
+                            duplicateWarningDiv.html(content);
                         }
                     });
                 }
             };
-            $("input[name='last_name']").after("<div id='duplicate_warning' class='btn-warning' style='display:none'>message</div>");
-            $("input[name='last_name']").on('keyup', checkDuplicates);
-            $("input[name='first_name']").on('keyup', checkDuplicates);
+            lastNameInput.after("<div id='duplicate_warning' class='btn-warning' style='display:none'>message</div>");
+
+            lastNameInput.on('keyup', checkDuplicates);
+            firstNameInput.on('keyup', checkDuplicates);
 
         });
 
diff --git a/smash/web/templates/subjects/delete.html b/smash/web/templates/subjects/delete.html
deleted file mode 100644
index 372dce816701f74a8fc01ef7078452ed61004f20..0000000000000000000000000000000000000000
--- a/smash/web/templates/subjects/delete.html
+++ /dev/null
@@ -1,93 +0,0 @@
-{% extends "_base.html" %}
-{% load static %}
-{% load filters %}
-
-{% block styles %}
-    {{ block.super }}
-    <!-- DataTables -->
-    <link rel="stylesheet" href="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.css' %}">
-{% endblock styles %}
-
-{% block ui_active_tab %}'subjects'{% endblock ui_active_tab %}
-{% block page_header %}Are you sure you want to remove information concerning this subject?{% endblock page_header %}
-{% block page_description %}{% endblock page_description %}
-
-{% block title %}{{ block.super }} - Delete subject information{% endblock %}
-
-{% block breadcrumb %}
-    {% include "subjects/breadcrumb.html" %}
-{% endblock breadcrumb %}
-
-{% block maincontent %}
-
-
-    {% block content %}
-        <div class="box box-info">
-            <div class="box-header with-border">
-                <a href="{% url 'web.views.subjects' %}" class="btn btn-block btn-default" onclick="history.back()">Go
-                    back (without changes)</a>
-            </div>
-
-            {% comment %} <div class="box-header with-border">
-		<h3 class="box-title">Details of subject</h3>
-	</div>{% endcomment %}
-
-            <form method="post" action="" class="form-horizontal">
-                {% csrf_token %}
-
-                <div class="box-body">
-                    {% for field in form %}
-                        <div class="col-md-6 form-group">
-                            <label class="col-sm-4 control-label">
-                                {{ field.label }}
-                            </label>
-
-                            <div class="col-sm-8">
-                                {{ field|disable|add_class:'form-control' }}
-                            </div>
-
-                            {% if field.help_text %}
-                                <span class="help-block">
-							{{ field.help_text }}
-						</span>
-                            {% endif %}
-                        </div>
-                    {% endfor %}
-                </div><!-- /.box-body -->
-
-                <div class="box-footer">
-                    <div class="col-sm-6">
-                        <button type="submit" class="btn btn-block btn-danger">Delete</button>
-                    </div>
-                    <div class="col-sm-6">
-                        <a href="{% url 'web.views.subjects' %}" class="btn btn-block btn-default"
-                           onclick="history.back()">Cancel</a>
-                    </div>
-                </div><!-- /.box-footer -->
-            </form>
-        </div>
-    {% endblock %}
-
-
-
-
-{% endblock maincontent %}
-
-{% block scripts %}
-    {{ block.super }}
-
-    <script src="{% static 'AdminLTE/plugins/datatables/jquery.dataTables.min.js' %}"></script>
-    <script src="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.min.js' %}"></script>
-    <script>
-        $(function () {
-            $('#table').DataTable({
-                "paging": true,
-                "lengthChange": false,
-                "searching": true,
-                "ordering": true,
-                "info": true,
-                "autoWidth": false
-            });
-        });
-    </script>
-{% endblock scripts %}
diff --git a/smash/web/templates/subjects/details.html b/smash/web/templates/subjects/details.html
deleted file mode 100644
index d3cd52aae7946204bc849ce185a5f1259cc76658..0000000000000000000000000000000000000000
--- a/smash/web/templates/subjects/details.html
+++ /dev/null
@@ -1,89 +0,0 @@
-{% extends "_base.html" %}
-{% load static %}
-{% load filters %}
-
-{% block styles %}
-    {{ block.super }}
-    <!-- DataTables -->
-    <link rel="stylesheet" href="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.css' %}">
-{% endblock styles %}
-
-{% block ui_active_tab %}'subjects'{% endblock ui_active_tab %}
-{% block page_header %}Details of the subject{% endblock page_header %}
-{% block page_description %}{% endblock page_description %}
-
-{% block title %}{{ block.super }} - Details of subject {% endblock %}
-
-{% block breadcrumb %}
-    {% include "subjects/breadcrumb.html" %}
-{% endblock breadcrumb %}
-
-{% block maincontent %}
-
-    {% block content %}
-        <div class="box box-info">
-            <div class="box-header with-border">
-                <a href="javascript:history.back(1)" class="btn btn-block btn-default">Back</a>
-            </div>
-
-            {% comment %} <div class="box-header with-border">
-		<h3 class="box-title">Details of subject</h3>
-	</div>{% endcomment %}
-
-            <form class="form-horizontal">
-                <div class="box-body">
-                    {% for field in form %}
-                        <div class="col-md-6 form-group {% if field.errors %}has-error{% endif %}">
-                            <label for="{# TODO #}" class="col-sm-4 control-label">
-                                {{ field.label }}
-                            </label>
-
-                            <div class="col-sm-8">
-                                {{ field|disable|add_class:'form-control' }}
-                            </div>
-
-                            {% if field.errors %}
-                                <span class="help-block">
-              {{ field.errors }}
-            </span>
-                            {% endif %}
-                        </div>
-                    {% endfor %}
-                </div><!-- /.box-body -->
-
-                <a href="{% url 'web.views.subject_visit_details' sid %}" type="button"
-                   class="btn btn-block btn-default">Subject's visits</a>
-
-
-                <div class="box-footer">
-                    <a href="javascript:history.back(1)" class="btn btn-block btn-default">Back</a>
-                </div><!-- /.box-footer -->
-            </form>
-        </div>
-
-        </form>
-    {% endblock %}
-
-
-
-
-{% endblock maincontent %}
-
-{% block scripts %}
-    {{ block.super }}
-
-    <script src="{% static 'AdminLTE/plugins/datatables/jquery.dataTables.min.js' %}"></script>
-    <script src="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.min.js' %}"></script>
-    <script>
-        $(function () {
-            $('#table').DataTable({
-                "paging": true,
-                "lengthChange": false,
-                "searching": true,
-                "ordering": true,
-                "info": true,
-                "autoWidth": false
-            });
-        });
-    </script>
-{% endblock scripts %}
diff --git a/smash/web/templates/subjects/edit.html b/smash/web/templates/subjects/edit.html
index 609cfbe22dab89900bfeb0343eeacf2bb54dbe3c..7e956ad711830c9c1e318edb5b474346910ff521 100644
--- a/smash/web/templates/subjects/edit.html
+++ b/smash/web/templates/subjects/edit.html
@@ -26,12 +26,10 @@
     {% block content %}
         <div class="row">
             <p class="col-lg-3 pull-left">
-                <a href="javascript:history.back(1)" class="btn btn-block btn-default"
-                ">Go
-                back (discard changes)</a>
+                <a href="javascript:history.back(1)" class="btn btn-block btn-default">Go back (discard changes)</a>
             </p>
             <p class="col-md-2 pull-right">
-                <a href="{% url 'web.views.subject_visit_details' subject.id %}" type="button"
+                <a href="{% url 'web.views.subject_visit_details' study_subject.id %}" type="button"
                    class="btn btn-block btn-default">Subject's visits</a>
             </p>
         </div>
@@ -44,11 +42,34 @@
                     </div>
 
                     <form method="post" action="" class="form-horizontal">
+                        {% csrf_token %}
                         <div class="box-body">
                             <div class="col-md-12">
-                                {% csrf_token %}
 
-                                {% for field in form %}
+                                {% for field in subject_form %}
+                                    <div class="col-md-6 form-group  {% if field.errors %}has-error{% endif %}">
+                                        <label for="{# TODO #}" class="col-sm-4 control-label">
+                                            {{ field.label }}
+                                        </label>
+
+                                        <div class="col-sm-8">
+                                            {{ field|add_class:'form-control' }}
+                                        </div>
+
+                                        {% if field.errors %}
+                                            <span class="help-block"> {{ field.errors }} </span>
+                                        {% endif %}
+                                    </div>
+                                {% endfor %}
+
+                            </div>
+                        </div><!-- /.box-body -->
+                        <div class="box-header with-border">
+                            <h3>Subject's study details</h3>
+                        </div>
+                        <div class="box-body">
+                            <div class="col-md-12">
+                                {% for field in study_subject_form %}
                                     <div class="col-md-6 form-group  {% if field.errors %}has-error{% endif %}">
                                         <label for="{# TODO #}" class="col-sm-4 control-label">
                                             {{ field.label }}
@@ -88,9 +109,9 @@
             </div><!-- /.col-md-12 -->
         </div><!-- /.row -->
 
-        {% include 'includes/mail_templates_box.html' with instance_id=subject.id %}
+        {% include 'includes/mail_templates_box.html' with instance_id=study_subject.id %}
 
-        {% include 'includes/contact_attempts_box.html' with subject=subject contact_attempts=contact_attempts %}
+        {% include 'includes/contact_attempts_box.html' with subject=study_subject contact_attempts=contact_attempts %}
 
 
         <div class="modal modal-danger fade" id="confirm-dead-resigned-mark-dialog" tabindex="-1" role="dialog">
@@ -152,18 +173,28 @@
                 "info": true,
                 "autoWidth": false
             });
-            var dead_was_checked = $("#id_dead").is(":checked");
-            var resigned_was_checked = $("#id_resigned").is(":checked");
-            $("#id_resign_reason").prop('disabled', !resigned_was_checked);
-            $("#id_resigned").on("click", function(){
-                var checked = $("#id_resigned").is(":checked");
-                $("#id_resign_reason").prop('disabled', !checked);
+            var deadCheckbox = $("#id_subject-dead");
+            var resignedCheckbox = $("#id_study_subject-resigned");
+            var resignReasonInput = $("#id_study_subject-resign_reason");
+            var screeningNumberInput = $("input[name='screening_number']");
+
+            if (deadCheckbox.length === 0 || resignedCheckbox.length === 0 || resignReasonInput.length === 0 || screeningNumberInput === null) {
+                alert("Internal error. Contact administrators");
+            }
+
+            var dead_was_checked = deadCheckbox.is(":checked");
+            var resigned_was_checked = resignedCheckbox.is(":checked");
+
+            resignReasonInput.prop('disabled', !resigned_was_checked);
+            resignedCheckbox.on("click", function () {
+                var checked = resignedCheckbox.is(":checked");
+                resignReasonInput.prop('disabled', !checked);
             });
             $("form").submit(function () {
                 if (confirmed) {
                     return true;
                 }
-                if ((!dead_was_checked && $("#id_dead").is(":checked")) || (!resigned_was_checked && $("#id_resigned").is(":checked"))) {
+                if ((!dead_was_checked && deadCheckbox.is(":checked")) || (!resigned_was_checked && resignedCheckbox.is(":checked"))) {
                     confirmed = false;
                     $("#confirm-dead-resigned-mark-dialog").modal("show");
                     return false;
@@ -177,15 +208,16 @@
             $("#confirm-screening-change").click(function () {
                 $('#enable-screening-number-dialog').modal('hide');
 
-                $("input[name='screening_number']").attr("readonly", false);
-                $("input[name='screening_number']")[0].focus();
+                screeningNumberInput.attr("readonly", false);
+                screeningNumberInput[0].focus();
             });
 
-            $("input[name='screening_number']").attr("readonly", true);
-            $("input[name='screening_number']").after("<div><a class='btn btn-block btn-danger' onclick='show_screening_number_enable_dialog()'>modify<a/></div>");
+            screeningNumberInput.attr("readonly", true);
+            screeningNumberInput.after("<div><a class='btn btn-block btn-danger' onclick='show_screening_number_enable_dialog()'>modify<a/></div>");
 
 
         });
+
         function show_screening_number_enable_dialog() {
             $('#enable-screening-number-dialog').modal('show');
         }
diff --git a/smash/web/templates/visits/details.html b/smash/web/templates/visits/details.html
index f6c632b961d953120b79982937a94a509a5cde74..ed73408d2e1030b164c7a6e38be41df5b83c9fb8 100644
--- a/smash/web/templates/visits/details.html
+++ b/smash/web/templates/visits/details.html
@@ -36,7 +36,7 @@
             <form method="post" action="" class="form-horizontal">
                 {% csrf_token %}
                 <div class="box-body">
-                    {% for field in vform %}
+                    {% for field in visit_form %}
                         {% if not field|is_checkbox %}
                             <div class="col-md-6 form-group  {% if field.errors %}has-error{% endif %}  {% if field|is_checkbox %}multi-checkboxes{% endif %}">
                                 <label for="{# TODO #}" class="col-sm-4 control-label">{{ field.label }}</label>
@@ -155,7 +155,32 @@
 
             <form class="form-horizontal">
                 <div class="box-body">
-                    {% for field in sform %}
+                    {% for field in subject_form %}
+                        <div class="col-md-6 form-group  {% if field.errors %}has-error{% endif %}">
+                            <label for="{# TODO #}" class="col-sm-4 control-label">
+                                {{ field.label }}
+                            </label>
+
+                            <div class="col-sm-8">
+                                {{ field|disable|add_class:'form-control' }}
+                            </div>
+
+                            {% if field.errors %}
+                                <span class="help-block">
+                                    {{ field.errors }}
+                                </span>
+                            {% endif %}
+                        </div>
+                    {% endfor %}
+                </div><!-- /.box-body -->
+
+            </form>
+            <div class="box-header with-border">
+                <h3 class="box-title">Subject's study details</h3>
+            </div>
+            <form class="form-horizontal">
+                <div class="box-body">
+                    {% for field in study_subject_form %}
                         <div class="col-md-6 form-group  {% if field.errors %}has-error{% endif %}">
                             <label for="{# TODO #}" class="col-sm-4 control-label">
                                 {{ field.label }}
@@ -174,11 +199,11 @@
                     {% endfor %}
                 </div><!-- /.box-body -->
 
-                <div class="box-footer">
-                    <td><a href="{% url 'web.views.subject_edit' visit.subject.id %}" type="button"
-                           class="btn btn-block btn-default">Edit subject</a></td>
-                </div><!-- /.box-footer -->
             </form>
+            <div class="box-footer">
+                <td><a href="{% url 'web.views.subject_edit' visit.subject.id %}" type="button"
+                       class="btn btn-block btn-default">Edit subject</a></td>
+            </div><!-- /.box-footer -->
         </div>
 
         {% include 'includes/mail_templates_box.html' with instance_id=visit.id %}
diff --git a/smash/web/tests/api_views/test_appointment.py b/smash/web/tests/api_views/test_appointment.py
index b6e11b47ab024922ac51394591356279f0166517..8e73b87519c8e8653fed2a95d3bb58c5651272e1 100644
--- a/smash/web/tests/api_views/test_appointment.py
+++ b/smash/web/tests/api_views/test_appointment.py
@@ -8,15 +8,15 @@ from django.test import TestCase
 from django.urls import reverse
 
 from web.models import AppointmentTypeLink
-from web.tests.functions import create_subject, create_worker, create_visit, create_appointment, \
+from web.tests.functions import create_study_subject, create_worker, create_visit, create_appointment, \
     create_appointment_type, create_get_suffix
 from web.views.appointment import APPOINTMENT_LIST_GENERIC, APPOINTMENT_LIST_APPROACHING, APPOINTMENT_LIST_UNFINISHED
 from web.views.notifications import get_today_midnight_date
 
 
-class TestApi(TestCase):
+class TestAppointmentApi(TestCase):
     def setUp(self):
-        self.subject = create_subject()
+        self.study_subject = create_study_subject()
         self.client = Client()
         username = 'piotr'
         password = 'top_secret'
@@ -31,9 +31,9 @@ class TestApi(TestCase):
 
     def test_appointments_valid(self):
         name = "Piotrek"
-        self.subject.first_name = name
-        self.subject.save()
-        visit = create_visit(self.subject)
+        self.study_subject.subject.first_name = name
+        self.study_subject.subject.save()
+        visit = create_visit(self.study_subject)
         create_appointment(visit)
         appointment2 = create_appointment(visit, get_today_midnight_date())
         appointment2.visit = None
@@ -50,9 +50,9 @@ class TestApi(TestCase):
 
     def test_appointments_approaching(self):
         name = "Piotrek"
-        self.subject.first_name = name
-        self.subject.save()
-        visit = create_visit(self.subject)
+        self.study_subject.subject.first_name = name
+        self.study_subject.subject.save()
+        visit = create_visit(self.study_subject)
         create_appointment(visit, get_today_midnight_date() + datetime.timedelta(days=2))
 
         url = reverse('web.api.appointments', kwargs={'type': APPOINTMENT_LIST_APPROACHING})
@@ -63,9 +63,9 @@ class TestApi(TestCase):
 
     def test_appointments_unfinished(self):
         name = "Piotrek"
-        self.subject.first_name = name
-        self.subject.save()
-        visit = create_visit(self.subject)
+        self.study_subject.subject.first_name = name
+        self.study_subject.subject.save()
+        visit = create_visit(self.study_subject)
         create_appointment(visit, get_today_midnight_date() + datetime.timedelta(days=-12))
 
         url = reverse('web.api.appointments', kwargs={'type': APPOINTMENT_LIST_UNFINISHED})
@@ -76,9 +76,9 @@ class TestApi(TestCase):
 
     def test_get_calendar_appointments(self):
         name = "Peter"
-        self.subject.first_name = name
-        self.subject.save()
-        visit = create_visit(self.subject)
+        self.study_subject.subject.first_name = name
+        self.study_subject.subject.save()
+        visit = create_visit(self.study_subject)
         appointment = create_appointment(visit, get_today_midnight_date())
         appointment.save()
 
diff --git a/smash/web/tests/api_views/test_daily_planning.py b/smash/web/tests/api_views/test_daily_planning.py
index 257e4d7abdd681e9a03c028189879b05160b4622..abaea166149c9dbf02967115040209f5fcaa9cb8 100644
--- a/smash/web/tests/api_views/test_daily_planning.py
+++ b/smash/web/tests/api_views/test_daily_planning.py
@@ -10,7 +10,7 @@ from django.urls import reverse
 from web.api_views.daily_planning import get_workers_for_daily_planning, get_generic_appointment_events
 from web.models import Worker, Availability, Holiday, AppointmentTypeLink
 from web.models.constants import TUESDAY_AS_DAY_OF_WEEK
-from web.tests.functions import create_worker, create_subject, create_appointment, create_flying_team, create_visit, \
+from web.tests.functions import create_worker, create_study_subject, create_appointment, create_flying_team, create_visit, \
     create_appointment_type, get_test_location
 
 
@@ -38,7 +38,7 @@ class TestApi(TestCase):
         flying_team = create_flying_team()
         flying_team.place = "UTF name: ät"
         flying_team.save()
-        subject = create_subject()
+        subject = create_study_subject()
         visit = create_visit(subject)
 
         appointment = create_appointment(visit)
diff --git a/smash/web/tests/api_views/test_subject.py b/smash/web/tests/api_views/test_subject.py
index 7fafc2f84a3705ade0f09c9701f60412b022f67d..c7ea23613277ecb644b9403f1db1989dd09a960b 100644
--- a/smash/web/tests/api_views/test_subject.py
+++ b/smash/web/tests/api_views/test_subject.py
@@ -1,22 +1,25 @@
 # coding=utf-8
-import json
 import datetime
+import json
+import logging
 
 from django.contrib.auth.models import User
 from django.test import Client
 from django.test import TestCase
 from django.urls import reverse
 
-from web.views.notifications import get_today_midnight_date
 from web.api_views.subject import get_subjects_order, get_subjects_filtered, serialize_subject, SUBJECT_LIST_GENERIC, \
     SUBJECT_LIST_NO_VISIT, SUBJECT_LIST_REQUIRE_CONTACT
-from web.models import Subject, Appointment, Visit
-from web.tests.functions import create_subject, create_worker, create_get_suffix, create_visit, create_appointment
+from web.models import StudySubject, Appointment
+from web.tests.functions import create_study_subject, create_worker, create_get_suffix, create_visit, create_appointment
+from web.views.notifications import get_today_midnight_date
+
+logger = logging.getLogger(__name__)
 
 
 class TestApi(TestCase):
     def setUp(self):
-        self.subject = create_subject()
+        self.study_subject = create_study_subject()
         self.client = Client()
         username = 'piotr'
         password = 'top_secret'
@@ -35,8 +38,8 @@ class TestApi(TestCase):
 
         self.assertFalse(city_name in cities)
 
-        self.subject.city = city_name
-        self.subject.save()
+        self.study_subject.subject.city = city_name
+        self.study_subject.subject.save()
 
         response = self.client.get(reverse('web.api.cities'))
         cities = json.loads(response.content)['cities']
@@ -53,8 +56,8 @@ class TestApi(TestCase):
 
         self.assertFalse(referral_name in referrals)
 
-        self.subject.referral = referral_name
-        self.subject.save()
+        self.study_subject.referral = referral_name
+        self.study_subject.save()
 
         response = self.client.get(reverse('web.api.referrals'))
         referrals = json.loads(response.content)['referrals']
@@ -79,8 +82,8 @@ class TestApi(TestCase):
 
     def test_subjects_general_search(self):
         name = "Piotrek"
-        self.subject.first_name = name
-        self.subject.save()
+        self.study_subject.subject.first_name = name
+        self.study_subject.subject.save()
 
         params = {
             "columns[0][search][value]": "another_name",
@@ -98,163 +101,163 @@ class TestApi(TestCase):
         self.assertTrue(name in response.content)
 
     def check_subject_filtered(self, filters, result):
-        subjects = get_subjects_filtered(Subject.objects.all(), filters)
+        subjects = get_subjects_filtered(StudySubject.objects.all(), filters)
         self.assertEqual(len(result), subjects.count())
         for index in range(len(result)):
             self.assertEqual(result[index], subjects[index])
 
     def check_subject_ordered(self, order, result):
-        subjects = get_subjects_order(Subject.objects.all(), order, "asc")
+        subjects = get_subjects_order(StudySubject.objects.all(), order, "asc")
         self.assertEqual(len(result), subjects.count())
         for index in range(len(result)):
             self.assertEqual(result[index], subjects[index])
 
-        subjects = get_subjects_order(Subject.objects.all(), order, "desc")
+        subjects = get_subjects_order(StudySubject.objects.all(), order, "desc")
         length = len(result)
         self.assertEqual(length, subjects.count())
         for index in range(length):
             self.assertEqual(result[length - index - 1], subjects[index])
 
     def test_subjects_sort_nd_number(self):
-        subject = self.subject
+        subject = self.study_subject
         subject.nd_number = "PPP"
         subject.save()
 
-        subject2 = create_subject(2)
+        subject2 = create_study_subject(2)
         subject2.nd_number = "QQQ"
         subject2.save()
 
         self.check_subject_ordered("nd_number", [subject, subject2])
 
     def test_subjects_sort_id(self):
-        subject = self.subject
+        subject = self.study_subject
 
-        subject2 = create_subject(2)
+        subject2 = create_study_subject(2)
 
         self.check_subject_ordered("id", [subject, subject2])
 
     def test_subjects_sort_date_born(self):
-        subject = self.subject
-        subject.date_born = get_today_midnight_date()
-        subject.save()
+        subject = self.study_subject
+        subject.subject.date_born = get_today_midnight_date()
+        subject.subject.save()
 
-        subject2 = create_subject(2)
-        subject2.date_born = get_today_midnight_date() + datetime.timedelta(days=1)
-        subject2.save()
+        subject2 = create_study_subject(2)
+        subject2.subject.date_born = get_today_midnight_date() + datetime.timedelta(days=1)
+        subject2.subject.save()
 
         self.check_subject_ordered("date_born", [subject, subject2])
 
     def test_subjects_sort_default_location(self):
-        subject = self.subject
+        subject = self.study_subject
 
         self.check_subject_ordered("default_location", [subject])
 
     def test_subjects_sort_screening_number(self):
-        subject = self.subject
+        subject = self.study_subject
         subject.screening_number = "PPP"
         subject.save()
 
-        subject2 = create_subject(2)
+        subject2 = create_study_subject(2)
         subject2.screening_number = "QQQ"
         subject2.save()
 
         self.check_subject_ordered("screening_number", [subject, subject2])
 
     def test_subjects_sort_last_name(self):
-        subject = self.subject
-        subject.last_name = "XXX"
-        subject.save()
+        subject = self.study_subject
+        subject.subject.last_name = "XXX"
+        subject.subject.save()
 
-        subject2 = create_subject(2)
-        subject2.last_name = "YYY"
-        subject2.save()
+        subject2 = create_study_subject(2)
+        subject2.subject.last_name = "YYY"
+        subject2.subject.save()
 
         self.check_subject_ordered("last_name", [subject, subject2])
 
     def test_subjects_sort_dead(self):
-        subject = self.subject
-        subject.dead = True
-        subject.save()
+        study_subject = self.study_subject
+        study_subject.subject.dead = True
+        study_subject.subject.save()
 
-        subject2 = create_subject(2)
-        subject2.dead = False
-        subject2.save()
+        study_subject2 = create_study_subject(2)
+        study_subject2.subject.dead = False
+        study_subject2.subject.save()
 
-        self.check_subject_ordered("dead", [subject2, subject])
+        self.check_subject_ordered("dead", [study_subject2, study_subject])
 
     def test_subjects_sort_resigned(self):
-        subject = self.subject
+        subject = self.study_subject
         subject.resigned = True
         subject.save()
 
-        subject2 = create_subject(2)
+        subject2 = create_study_subject(2)
         subject2.resigned = False
         subject2.save()
 
         self.check_subject_ordered("resigned", [subject2, subject])
 
     def test_subjects_sort_postponed(self):
-        subject = self.subject
+        subject = self.study_subject
         subject.postponed = True
         subject.save()
 
-        subject2 = create_subject(2)
+        subject2 = create_study_subject(2)
         subject2.postponed = False
         subject2.save()
 
         self.check_subject_ordered("postponed", [subject2, subject])
 
     def test_subjects_filter_dead(self):
-        subject = self.subject
+        subject = self.study_subject.subject
         subject.dead = True
         subject.save()
 
-        subject2 = create_subject(2)
-        subject2.dead = False
-        subject2.save()
+        study_subject2 = create_study_subject(2)
+        study_subject2.subject.dead = False
+        study_subject2.subject.save()
 
-        self.check_subject_filtered([["dead", "true"]], [subject])
-        self.check_subject_filtered([["dead", "false"]], [subject2])
+        self.check_subject_filtered([["dead", "true"]], [self.study_subject])
+        self.check_subject_filtered([["dead", "false"]], [study_subject2])
 
     def test_subjects_filter_nd_number(self):
-        subject = self.subject
+        subject = self.study_subject
         subject.nd_number = "PPP"
         subject.save()
 
-        subject2 = create_subject(2)
+        subject2 = create_study_subject(2)
         subject2.nd_number = "QQQ"
         subject2.save()
 
         self.check_subject_filtered([["nd_number", "P"]], [subject])
 
     def test_subjects_filter_screening_number(self):
-        subject = self.subject
+        subject = self.study_subject
         subject.screening_number = "PPP"
         subject.save()
 
-        subject2 = create_subject(2)
+        subject2 = create_study_subject(2)
         subject2.screening_number = "QQQ"
         subject2.save()
 
         self.check_subject_filtered([["screening_number", "Q"]], [subject2])
 
     def test_subjects_filter_last_name(self):
-        subject = self.subject
-        subject.last_name = "XXX"
-        subject.save()
+        subject = self.study_subject
+        subject.subject.last_name = "XXX"
+        subject.subject.save()
 
-        subject2 = create_subject(2)
-        subject2.last_name = "YYY"
-        subject2.save()
+        subject2 = create_study_subject(2)
+        subject2.subject.last_name = "YYY"
+        subject2.subject.save()
 
         self.check_subject_filtered([["last_name", "Q"]], [])
 
     def test_subjects_filter_resigned(self):
-        subject = self.subject
+        subject = self.study_subject
         subject.resigned = True
         subject.save()
 
-        subject2 = create_subject(2)
+        subject2 = create_study_subject(2)
         subject2.resigned = False
         subject2.save()
 
@@ -262,11 +265,11 @@ class TestApi(TestCase):
         self.check_subject_filtered([["resigned", "false"]], [subject2])
 
     def test_subjects_filter_postponed(self):
-        subject = self.subject
+        subject = self.study_subject
         subject.postponed = True
         subject.save()
 
-        subject2 = create_subject(2)
+        subject2 = create_study_subject(2)
         subject2.postponed = False
         subject2.save()
 
@@ -274,28 +277,26 @@ class TestApi(TestCase):
         self.check_subject_filtered([["postponed", "false"]], [subject2])
 
     def test_subjects_filter_default_location(self):
-        subject = self.subject
+        subject = self.study_subject
 
         self.check_subject_filtered([["default_location", str(subject.default_location.id)]], [subject])
         self.check_subject_filtered([["default_location", "-1"]], [])
 
     def test_subjects_filter_unknown(self):
-        subject = self.subject
+        subject = self.study_subject
 
         self.check_subject_filtered([["some_unknown", "unknown data"]], [subject])
         self.check_subject_filtered([["", ""]], [subject])
 
     def test_serialize_subject(self):
-        subject = self.subject
-        subject.dead = True
+        study_subject = self.study_subject
+        study_subject.subject.dead = True
 
-        subject_json = serialize_subject(subject)
+        subject_json = serialize_subject(study_subject)
         self.assertEqual("YES", subject_json["dead"])
 
     def test_subjects_filter_visit_1_DONE(self):
-        subject = self.subject
-        subject.dead = True
-        subject.save()
+        subject = self.study_subject
 
         visit = create_visit(subject)
         appointment = create_appointment(visit)
@@ -313,9 +314,7 @@ class TestApi(TestCase):
         self.check_subject_filtered([["visit_1", "UPCOMING"]], [])
 
     def test_subjects_filter_visit_1_MISSED(self):
-        subject = self.subject
-        subject.dead = True
-        subject.save()
+        subject = self.study_subject
 
         visit = create_visit(subject)
         appointment = create_appointment(visit)
@@ -333,9 +332,7 @@ class TestApi(TestCase):
         self.check_subject_filtered([["visit_1", "UPCOMING"]], [])
 
     def test_subjects_filter_visit_1_EXCEED(self):
-        subject = self.subject
-        subject.dead = True
-        subject.save()
+        subject = self.study_subject
 
         visit = create_visit(subject)
         visit.datetime_begin = get_today_midnight_date() + datetime.timedelta(days=-365 * 2)
@@ -352,9 +349,7 @@ class TestApi(TestCase):
         self.check_subject_filtered([["visit_1", "UPCOMING"]], [])
 
     def test_subjects_filter_visit_1_IN_PROGRESS(self):
-        subject = self.subject
-        subject.dead = True
-        subject.save()
+        subject = self.study_subject
 
         visit = create_visit(subject)
         appointment = create_appointment(visit)
@@ -371,9 +366,7 @@ class TestApi(TestCase):
         self.check_subject_filtered([["visit_1", "UPCOMING"]], [])
 
     def test_subjects_filter_visit_1_SHOULD_BE_IN_PROGRESS(self):
-        subject = self.subject
-        subject.dead = True
-        subject.save()
+        subject = self.study_subject
 
         visit = create_visit(subject)
 
@@ -387,9 +380,7 @@ class TestApi(TestCase):
         self.check_subject_filtered([["visit_1", "UPCOMING"]], [])
 
     def test_subjects_filter_visit_1_UPCOMING(self):
-        subject = self.subject
-        subject.dead = True
-        subject.save()
+        subject = self.study_subject
 
         visit = create_visit(subject)
         visit.datetime_begin = get_today_midnight_date() + datetime.timedelta(days=2)
@@ -406,8 +397,7 @@ class TestApi(TestCase):
         self.check_subject_filtered([["visit_1", "SHOULD_BE_IN_PROGRESS"]], [])
 
     def test_subjects_filter_visit_1_visit_2_combined(self):
-        subject = self.subject
-        subject.save()
+        subject = self.study_subject
 
         visit = create_visit(subject)
         appointment = create_appointment(visit)
diff --git a/smash/web/tests/api_views/test_worker.py b/smash/web/tests/api_views/test_worker.py
index 33e4b71dcea12e2aec30eb85cc4b24ff6f382467..0b32a0b321347ea85467de611b981e1d551508b7 100644
--- a/smash/web/tests/api_views/test_worker.py
+++ b/smash/web/tests/api_views/test_worker.py
@@ -73,7 +73,7 @@ class TestApi(LoggedInWithWorkerTestCase):
 
         result = availabilities(request)
         entries = json.loads(result.content)['availabilities']
-        count = 0;
+        count = 0
         for entry in entries:
             count += len(entry["workers"])
         self.assertTrue(count > 0)
diff --git a/smash/web/tests/forms/test_SubjectAddForm.py b/smash/web/tests/forms/test_StudySubjectAddForm.py
similarity index 66%
rename from smash/web/tests/forms/test_SubjectAddForm.py
rename to smash/web/tests/forms/test_StudySubjectAddForm.py
index 907cfe39d93200d6bfedff92d7f18a4463d085fa..a417a5bb3f11f562dbf2121b02c4074d3f5f45ff 100644
--- a/smash/web/tests/forms/test_SubjectAddForm.py
+++ b/smash/web/tests/forms/test_StudySubjectAddForm.py
@@ -1,25 +1,28 @@
-from web.forms import SubjectAddForm, get_new_screening_number
-from web.models.constants import SEX_CHOICES_MALE, SUBJECT_TYPE_CHOICES_CONTROL, COUNTRY_AFGHANISTAN_ID
+import logging
+
+from web.forms import StudySubjectAddForm, get_new_screening_number
+from web.models.constants import SUBJECT_TYPE_CHOICES_CONTROL
 from web.tests import LoggedInWithWorkerTestCase
-from web.tests.functions import create_subject
+from web.tests.functions import create_study_subject, create_subject
+
+logger = logging.getLogger(__name__)
 
 
-class SubjectAddFormTests(LoggedInWithWorkerTestCase):
+class StudySubjectAddFormTests(LoggedInWithWorkerTestCase):
     def setUp(self):
-        super(SubjectAddFormTests, self).setUp()
+        super(StudySubjectAddFormTests, self).setUp()
 
         location = self.worker.locations.all()[0]
-        self.sample_data = {'first_name': 'name',
-                            'last_name': 'name',
-                            'sex': SEX_CHOICES_MALE,
-                            'type': SUBJECT_TYPE_CHOICES_CONTROL,
-                            'default_location': location.id,
-                            'screening_number': "123",
-                            'country': COUNTRY_AFGHANISTAN_ID,
-                            }
+        self.subject = create_subject()
+        self.sample_data = {
+            'type': SUBJECT_TYPE_CHOICES_CONTROL,
+            'default_location': location.id,
+            'screening_number': "123",
+            'subject': self.subject.id
+        }
 
     def test_validation(self):
-        form = SubjectAddForm(data=self.sample_data, user=self.user)
+        form = StudySubjectAddForm(data=self.sample_data, user=self.user)
         form.is_valid()
         self.assertTrue(form.is_valid())
 
@@ -27,13 +30,14 @@ class SubjectAddFormTests(LoggedInWithWorkerTestCase):
         form_data = self.sample_data
         form_data['screening_number'] = "123"
 
-        form = SubjectAddForm(data=form_data, user=self.user)
+        form = StudySubjectAddForm(data=form_data, user=self.user)
         form.is_valid()
+        form.instance.subject_id = self.subject.id
         self.assertTrue(form.is_valid())
         self.assertIsNone(form.fields['year_of_diagnosis'].initial)
         form.save()
 
-        form2 = SubjectAddForm(data=form_data, user=self.user)
+        form2 = StudySubjectAddForm(data=form_data, user=self.user)
         validation_status = form2.is_valid()
         self.assertFalse(validation_status)
         self.assertTrue("screening_number" in form2.errors)
@@ -42,13 +46,14 @@ class SubjectAddFormTests(LoggedInWithWorkerTestCase):
         form_data = self.sample_data
         form_data['nd_number'] = "ND0123"
 
-        form = SubjectAddForm(data=form_data, user=self.user)
+        form = StudySubjectAddForm(data=form_data, user=self.user)
         form.is_valid()
         self.assertTrue(form.is_valid())
+        form.instance.subject_id = self.subject.id
         form.save()
 
         form_data['screening_number'] = "2"
-        form2 = SubjectAddForm(data=form_data, user=self.user)
+        form2 = StudySubjectAddForm(data=form_data, user=self.user)
         validation_status = form2.is_valid()
         self.assertFalse(validation_status)
         self.assertTrue("nd_number" in form2.errors)
@@ -57,20 +62,21 @@ class SubjectAddFormTests(LoggedInWithWorkerTestCase):
         form_data = self.sample_data
         form_data['mpower_id'] = "123"
 
-        form = SubjectAddForm(data=form_data, user=self.user)
+        form = StudySubjectAddForm(data=form_data, user=self.user)
         form.is_valid()
         self.assertTrue(form.is_valid())
+        form.instance.subject_id = self.subject.id
         form.save()
 
         form_data['screening_number'] = "2"
-        form2 = SubjectAddForm(data=form_data, user=self.user)
+        form2 = StudySubjectAddForm(data=form_data, user=self.user)
         validation_status = form2.is_valid()
         self.assertFalse(validation_status)
         self.assertTrue("mpower_id" in form2.errors)
 
     def test_get_new_screening_number(self):
         prefix = "X-"
-        subject = create_subject()
+        subject = create_study_subject()
         subject.screening_number = prefix + "300"
         subject.save()
 
@@ -79,7 +85,7 @@ class SubjectAddFormTests(LoggedInWithWorkerTestCase):
 
     def test_get_new_screening_number_2(self):
         prefix = "X-"
-        subject = create_subject()
+        subject = create_study_subject()
         subject.screening_number = "L-1111; " + prefix + "300"
         subject.save()
 
@@ -88,7 +94,7 @@ class SubjectAddFormTests(LoggedInWithWorkerTestCase):
 
     def test_get_new_screening_number_3(self):
         prefix = "X-"
-        subject = create_subject()
+        subject = create_study_subject()
         subject.screening_number = "P-1112; " + prefix + "300" + "; L-1111"
         subject.save()
 
@@ -97,7 +103,7 @@ class SubjectAddFormTests(LoggedInWithWorkerTestCase):
 
     def test_get_new_screening_number_4(self):
         prefix = "X-"
-        subject = create_subject()
+        subject = create_study_subject()
         subject.screening_number = "P-1112; "
         subject.save()
 
@@ -106,19 +112,19 @@ class SubjectAddFormTests(LoggedInWithWorkerTestCase):
 
     def test_get_new_screening_number_5(self):
         prefix = "X-"
-        subject = create_subject()
+        subject = create_study_subject()
         subject.screening_number = prefix + "100"
         subject.save()
 
-        subject = create_subject()
+        subject = create_study_subject()
         subject.screening_number = prefix + "200"
         subject.save()
 
-        subject = create_subject()
+        subject = create_study_subject()
         subject.screening_number = "Y-300"
         subject.save()
 
-        subject = create_subject()
+        subject = create_study_subject()
         subject.screening_number = prefix + "20"
         subject.save()
 
@@ -127,7 +133,7 @@ class SubjectAddFormTests(LoggedInWithWorkerTestCase):
 
     def test_get_new_screening_number_6(self):
         prefix = "X-"
-        subject = create_subject()
+        subject = create_study_subject()
         subject.screening_number = "X-"
         subject.save()
 
diff --git a/smash/web/tests/forms/test_StudySubjectEditForm.py b/smash/web/tests/forms/test_StudySubjectEditForm.py
new file mode 100644
index 0000000000000000000000000000000000000000..5f838cff2724de1c31ae353a5e828d426d3bb002
--- /dev/null
+++ b/smash/web/tests/forms/test_StudySubjectEditForm.py
@@ -0,0 +1,60 @@
+import logging
+
+from web.forms import StudySubjectEditForm
+from web.models import StudySubject
+from web.tests import LoggedInWithWorkerTestCase
+from web.tests.functions import create_study_subject
+
+logger = logging.getLogger(__name__)
+
+
+class StudySubjectEditFormTests(LoggedInWithWorkerTestCase):
+    def setUp(self):
+        super(StudySubjectEditFormTests, self).setUp()
+        self.study_subject = create_study_subject()
+
+        location = self.worker.locations.all()[0]
+        self.sample_data = {
+            'type': self.study_subject.type,
+            'default_location': location.id,
+            'screening_number': self.study_subject.screening_number,
+            'nd_number': self.study_subject.nd_number,
+            'subject': self.study_subject.subject.id,
+            'id': self.study_subject.id
+        }
+
+    def tearDown(self):
+        StudySubject.objects.all().delete()
+
+    def test_validation(self):
+        edit_form = StudySubjectEditForm(self.sample_data)
+        save_status = edit_form.is_valid()
+        self.assertTrue(save_status)
+
+    def test_invalid_nd_number_edit(self):
+        study_subject2 = create_study_subject(124)
+        study_subject2.nd_number = "ND0124"
+        study_subject2.screening_number = "124"
+        study_subject2.save()
+
+        self.sample_data['nd_number'] = "ND0124"
+        edit_form = StudySubjectEditForm(self.sample_data)
+
+        save_status = edit_form.is_valid()
+        self.assertTrue("nd_number" in edit_form.errors)
+        self.assertFalse(save_status)
+
+    def test_invalid_mpower_id_edit(self):
+        self.study_subject.mpower_id = "mpower_002"
+        self.study_subject.nd_number = "ND0002"
+        self.study_subject.screening_number = "002"
+        self.study_subject.save()
+
+        self.sample_data['mpower_id'] = "mpower_002"
+        self.sample_data['nd_number'] = "ND0001"
+        self.sample_data['screening_number'] = "001"
+        edit_form = StudySubjectEditForm(self.sample_data)
+
+        save_status = edit_form.is_valid()
+        self.assertTrue("mpower_id" in edit_form.errors)
+        self.assertFalse(save_status)
diff --git a/smash/web/tests/forms/test_SubjectEditForm.py b/smash/web/tests/forms/test_SubjectEditForm.py
deleted file mode 100644
index 3de9b95dd970d2aeeb0b029ec32af74c5413b420..0000000000000000000000000000000000000000
--- a/smash/web/tests/forms/test_SubjectEditForm.py
+++ /dev/null
@@ -1,69 +0,0 @@
-from web.forms import SubjectAddForm
-from web.forms import SubjectEditForm
-from web.models import Subject
-from web.models.constants import SEX_CHOICES_MALE, SUBJECT_TYPE_CHOICES_CONTROL, COUNTRY_AFGHANISTAN_ID
-from web.tests import LoggedInWithWorkerTestCase
-
-
-class SubjectEditFormTests(LoggedInWithWorkerTestCase):
-    def setUp(self):
-        super(SubjectEditFormTests, self).setUp()
-
-        location = self.worker.locations.all()[0]
-        self.sample_data = {'first_name': 'name',
-                            'last_name': 'name',
-                            'sex': SEX_CHOICES_MALE,
-                            'type': SUBJECT_TYPE_CHOICES_CONTROL,
-                            'default_location': location.id,
-                            'country': COUNTRY_AFGHANISTAN_ID,
-                            'screening_number': '123',
-                            'nd_number': 'ND0123'
-                            }
-
-    def tearDown(self):
-        Subject.objects.all().delete()
-
-    def test_validation(self):
-        add_form = SubjectAddForm(data=self.sample_data, user=self.user)
-        subject = add_form.save()
-        self.sample_data['id'] = subject.id
-
-        edit_form = SubjectEditForm(self.sample_data)
-        save_status = edit_form.is_valid()
-        self.assertTrue(save_status)
-
-    def test_invalid_nd_number_edit(self):
-        add_form = SubjectAddForm(data=self.sample_data, user=self.user)
-        add_form.save()
-
-        self.sample_data['nd_number'] = "ND0124"
-        self.sample_data['screening_number'] = "124"
-        add_form = SubjectAddForm(data=self.sample_data, user=self.user)
-        subject = add_form.save()
-
-        self.sample_data['id'] = subject.id
-        self.sample_data['nd_number'] = "ND0123"
-        edit_form = SubjectEditForm(self.sample_data)
-
-        save_status = edit_form.is_valid()
-        self.assertFalse(save_status)
-
-    def test_invalid_mpower_id_edit(self):
-        self.sample_data['screening_number'] = "001"
-        add_form = SubjectAddForm(data=self.sample_data, user=self.user)
-        subject = add_form.save()
-
-        self.sample_data['mpower_id'] = "mpower_002"
-        self.sample_data['nd_number'] = "ND0002"
-        self.sample_data['screening_number'] = "002"
-        add_form = SubjectAddForm(data=self.sample_data, user=self.user)
-        add_form.save()
-
-        self.sample_data['id'] = subject.id
-        self.sample_data['mpower_id'] = "mpower_002"
-        self.sample_data['nd_number'] = "ND0001"
-        self.sample_data['screening_number'] = "001"
-        edit_form = SubjectEditForm(self.sample_data)
-
-        save_status = edit_form.is_valid()
-        self.assertFalse(save_status)
diff --git a/smash/web/tests/forms/test_VisitAddForm.py b/smash/web/tests/forms/test_VisitAddForm.py
index b6a0d817ad2b577e83bcbf9a03fbfd71b3baf6f7..14fbed837708331b331bdaf415d859ce9a13ca7b 100644
--- a/smash/web/tests/forms/test_VisitAddForm.py
+++ b/smash/web/tests/forms/test_VisitAddForm.py
@@ -3,14 +3,14 @@ from __future__ import print_function
 from django.test import TestCase
 
 from web.forms import VisitAddForm
-from web.tests.functions import create_subject
+from web.tests.functions import create_study_subject
 from web.tests.functions import get_test_location
 
 
 class VisitAddFormTests(TestCase):
     def setUp(self):
         get_test_location()
-        self.subject = create_subject()
+        self.subject = create_study_subject()
 
         self.sample_data = {'datetime_begin': "2017-01-01",
                             'datetime_end': "2017-02-02",
diff --git a/smash/web/tests/functions.py b/smash/web/tests/functions.py
index aa6ee1114a859f7df40d03b71f71c5821f22a10f..adb1eaf8511656ec1b92688405d4979d893ccb53 100644
--- a/smash/web/tests/functions.py
+++ b/smash/web/tests/functions.py
@@ -3,8 +3,8 @@ import os
 
 from django.contrib.auth.models import User
 
-from web.models import Location, AppointmentType, Subject, Worker, Visit, Appointment, ConfigurationItem, Language, \
-    ContactAttempt, FlyingTeam, Availability
+from web.models import Location, AppointmentType, StudySubject, Worker, Visit, Appointment, ConfigurationItem, Language, \
+    ContactAttempt, FlyingTeam, Availability, Subject
 from web.models.constants import REDCAP_TOKEN_CONFIGURATION_TYPE, REDCAP_BASE_URL_CONFIGURATION_TYPE, \
     SEX_CHOICES_MALE, SUBJECT_TYPE_CHOICES_CONTROL, CONTACT_TYPES_PHONE, \
     MONDAY_AS_DAY_OF_WEEK, COUNTRY_AFGHANISTAN_ID
@@ -41,7 +41,7 @@ def create_appointment_type():
 
 def create_contact_attempt(subject=None, worker=None):
     if subject is None:
-        subject = create_subject()
+        subject = create_study_subject()
     if worker is None:
         worker = create_worker()
 
@@ -54,15 +54,23 @@ def create_contact_attempt(subject=None, worker=None):
                                          )
 
 
-def create_subject(subject_id=1):
+def create_subject():
     return Subject.objects.create(
         first_name="Piotr",
         last_name="Gawron",
-        default_location=get_test_location(),
         sex=SEX_CHOICES_MALE,
+        country_id=COUNTRY_AFGHANISTAN_ID
+    )
+
+
+def create_study_subject(subject_id=1, subject=None):
+    if subject is None:
+        subject = create_subject()
+    return StudySubject.objects.create(
+        default_location=get_test_location(),
         type=SUBJECT_TYPE_CHOICES_CONTROL,
         screening_number="piotr's number" + str(subject_id),
-        country_id=COUNTRY_AFGHANISTAN_ID
+        subject=subject
     )
 
 
@@ -112,7 +120,7 @@ def create_availability(worker=None):
 
 def create_visit(subject=None):
     if subject is None:
-        subject = create_subject()
+        subject = create_study_subject()
     return Visit.objects.create(datetime_begin=get_today_midnight_date() + datetime.timedelta(days=-31),
                                 datetime_end=get_today_midnight_date() + datetime.timedelta(days=31),
                                 subject=subject,
diff --git a/smash/web/tests/models/test_appointment.py b/smash/web/tests/models/test_appointment.py
index a781e69c9ec36a99bd92e3cbf5616d16ee8d2b4d..3568ad558b96ab0c2b9e38a54d4d0a1d9ee69d53 100644
--- a/smash/web/tests/models/test_appointment.py
+++ b/smash/web/tests/models/test_appointment.py
@@ -1,7 +1,11 @@
+import logging
+
 from django.test import TestCase
 
 from web.tests.functions import create_appointment
 
+logger = logging.getLogger(__name__)
+
 
 class AppointmentModelTests(TestCase):
     def test_title_for_appointment_without_visit(self):
@@ -12,3 +16,7 @@ class AppointmentModelTests(TestCase):
         appointment.save()
 
         self.assertEqual(comment, appointment.title())
+
+    def test_title_for_appointment_with_visit(self):
+        appointment = create_appointment()
+        self.assertIsNotNone(appointment.title())
diff --git a/smash/web/tests/models/test_inconsistent_subject.py b/smash/web/tests/models/test_inconsistent_subject.py
index 926314158302ac7bb18ed4900a7c2ba1fa0d5216..1ee33c4e38a2e1ef0706fd3f5b2864758413251d 100644
--- a/smash/web/tests/models/test_inconsistent_subject.py
+++ b/smash/web/tests/models/test_inconsistent_subject.py
@@ -1,12 +1,12 @@
 from django.test import TestCase
 
 from web.models.inconsistent_subject import InconsistentSubject, InconsistentField
-from web.tests.functions import create_subject
+from web.tests.functions import create_study_subject
 
 
 class InconsistentSubjectTests(TestCase):
     def test_create_with_empty_data(self):
-        subject = create_subject()
+        subject = create_study_subject()
         inconsistent_subject = InconsistentSubject.create(subject)
         self.assertIsNotNone(str(inconsistent_subject))
         self.assertIsNotNone(unicode(inconsistent_subject))
diff --git a/smash/web/tests/models/test_mail_template.py b/smash/web/tests/models/test_mail_template.py
index d718ba2e5ddf4a02f283ae4008d6297b831ec5b5..49c84a13962049a563cd007c6a2b819575e33361 100644
--- a/smash/web/tests/models/test_mail_template.py
+++ b/smash/web/tests/models/test_mail_template.py
@@ -7,7 +7,8 @@ from web.models import MailTemplate
 from web.models.constants import MAIL_TEMPLATE_CONTEXT_APPOINTMENT, MAIL_TEMPLATE_CONTEXT_VISIT, \
     MAIL_TEMPLATE_CONTEXT_SUBJECT
 from web.models.mail_template import DATE_FORMAT_SHORT
-from web.tests.functions import create_language, get_resource_path, create_appointment, create_user, create_subject, \
+from web.tests.functions import create_language, get_resource_path, create_appointment, create_user, \
+    create_study_subject, \
     create_visit
 
 
@@ -80,7 +81,7 @@ class MailTemplateModelTests(TestCase):
 
     def test_apply_subject(self):
         template_name_french = "test_fr"
-        subject = create_subject()
+        subject = create_study_subject()
         subject_template_french = MailTemplate(name=template_name_french, language=self.french_language,
                                                context=MAIL_TEMPLATE_CONTEXT_SUBJECT,
                                                template_file=self.template_file)
@@ -89,7 +90,7 @@ class MailTemplateModelTests(TestCase):
         doc = Document(stream)
         worker_name = str(self.user.worker)
 
-        self.check_doc_contains(doc, [worker_name, str(subject), str(subject.country), subject.nd_number,
+        self.check_doc_contains(doc, [worker_name, str(subject), str(subject.subject.country), subject.nd_number,
                                       subject.get_type_display()])
 
     def test_apply_visit(self):
@@ -103,7 +104,8 @@ class MailTemplateModelTests(TestCase):
         doc = Document(stream)
         worker_name = str(self.user.worker)
 
-        self.check_doc_contains(doc, [worker_name, str(visit.subject), str(visit.subject.country), visit.subject.nd_number,
+        self.check_doc_contains(doc, [worker_name, str(visit.subject), str(visit.subject.subject.country),
+                                      visit.subject.nd_number,
                                       visit.subject.get_type_display(),
                                       visit.datetime_begin.strftime(DATE_FORMAT_SHORT),
                                       visit.datetime_end.strftime(DATE_FORMAT_SHORT)])
diff --git a/smash/web/tests/models/test_missing_subject.py b/smash/web/tests/models/test_missing_subject.py
index 37a7f92459ec0ad09ae3ec06203f370712eb95d7..712969a9b125ca8b4e7a6c80ed735aac3f601fa0 100644
--- a/smash/web/tests/models/test_missing_subject.py
+++ b/smash/web/tests/models/test_missing_subject.py
@@ -1,12 +1,12 @@
 from django.test import TestCase
 
 from web.models.missing_subject import MissingSubject
-from web.tests.functions import create_subject, create_red_cap_subject
+from web.tests.functions import create_study_subject, create_red_cap_subject
 
 
 class MissingSubjectTests(TestCase):
     def test_create_with_empty_redcap_subject(self):
-        subject = create_subject()
+        subject = create_study_subject()
         missing_subject = MissingSubject.create(red_cap_subject=None, smash_subject=subject)
         self.assertIsNotNone(str(missing_subject))
         self.assertIsNotNone(unicode(missing_subject))
diff --git a/smash/web/tests/models/test_study_subject.py b/smash/web/tests/models/test_study_subject.py
new file mode 100644
index 0000000000000000000000000000000000000000..cebd56b769b72493aac87487444c0594b856bbcd
--- /dev/null
+++ b/smash/web/tests/models/test_study_subject.py
@@ -0,0 +1,21 @@
+from django.test import TestCase
+
+from web.models import Appointment
+from web.models import Visit
+from web.tests.functions import create_study_subject, create_appointment
+from web.tests.functions import create_visit
+
+
+class SubjectModelTests(TestCase):
+    def test_mark_as_resigned(self):
+        subject = create_study_subject()
+        visit = create_visit(subject)
+        appointment = create_appointment(visit)
+
+        subject.mark_as_resigned()
+        appointment_status = Appointment.objects.filter(id=appointment.id)[0].status
+        visit_finished = Visit.objects.filter(id=visit.id)[0].is_finished
+
+        self.assertTrue(subject.resigned)
+        self.assertTrue(visit_finished)
+        self.assertEquals(Appointment.APPOINTMENT_STATUS_CANCELLED, appointment_status)
diff --git a/smash/web/tests/models/test_subject.py b/smash/web/tests/models/test_subject.py
index 6266ec03e6eb3eeab698a0732d37f42425527ce5..8bfdafdd9443d24be50449052c2337cb33f79997 100644
--- a/smash/web/tests/models/test_subject.py
+++ b/smash/web/tests/models/test_subject.py
@@ -1,17 +1,16 @@
-from django.contrib.auth.models import User
-from django.test import Client
 from django.test import TestCase
 
-from web.tests.functions import create_subject, create_appointment, create_worker
-from web.tests.functions import create_visit
 from web.models import Appointment
 from web.models import Visit
+from web.tests.functions import create_study_subject, create_appointment
+from web.tests.functions import create_visit
 
 
 class SubjectModelTests(TestCase):
     def test_mark_as_dead(self):
-        subject = create_subject()
-        visit = create_visit(subject)
+        study_subject = create_study_subject()
+        subject = study_subject.subject
+        visit = create_visit(study_subject)
         appointment = create_appointment(visit)
 
         subject.mark_as_dead()
@@ -21,16 +20,3 @@ class SubjectModelTests(TestCase):
         self.assertTrue(subject.dead)
         self.assertTrue(visit_finished)
         self.assertEquals(Appointment.APPOINTMENT_STATUS_CANCELLED, appointment_status)
-
-    def test_mark_as_resigned(self):
-        subject = create_subject()
-        visit = create_visit(subject)
-        appointment = create_appointment(visit)
-
-        subject.mark_as_resigned()
-        appointment_status = Appointment.objects.filter(id=appointment.id)[0].status
-        visit_finished = Visit.objects.filter(id=visit.id)[0].is_finished
-
-        self.assertTrue(subject.resigned)
-        self.assertTrue(visit_finished)
-        self.assertEquals(Appointment.APPOINTMENT_STATUS_CANCELLED, appointment_status)
\ No newline at end of file
diff --git a/smash/web/tests/models/test_visit.py b/smash/web/tests/models/test_visit.py
index f4a231344474b3eb0b946ea9cb0e8b5dbc6f65a2..a247d83886c073d3d40d4318949b98817dc7924a 100644
--- a/smash/web/tests/models/test_visit.py
+++ b/smash/web/tests/models/test_visit.py
@@ -2,15 +2,14 @@ import datetime
 
 from django.test import TestCase
 
-from web.models.constants import SUBJECT_TYPE_CHOICES_PATIENT
 from web.models import Visit
-from web.tests.functions import create_subject, create_visit
-from web.views.notifications import get_today_midnight_date
+from web.models.constants import SUBJECT_TYPE_CHOICES_PATIENT
+from web.tests.functions import create_study_subject, create_visit
 
 
 class VisitModelTests(TestCase):
     def test_mark_as_finished(self):
-        subject = create_subject()
+        subject = create_study_subject()
         visit = create_visit(subject)
 
         visit.mark_as_finished()
@@ -19,18 +18,18 @@ class VisitModelTests(TestCase):
         self.assertEquals(2, visit_count)
 
     def test_mark_as_finished_2(self):
-        subject = create_subject()
-        visit = create_visit(subject)
-        subject.dead = True
-        subject.save()
+        study_subject = create_study_subject()
+        visit = create_visit(study_subject)
+        study_subject.subject.dead = True
+        study_subject.subject.save()
 
         visit.mark_as_finished()
 
-        visit_count = Visit.objects.filter(subject=subject).count()
+        visit_count = Visit.objects.filter(subject=study_subject).count()
         self.assertEquals(1, visit_count)
 
     def test_mark_as_finished_3(self):
-        subject = create_subject()
+        subject = create_study_subject()
         visit = create_visit(subject)
         subject.resigned = True
         subject.save()
@@ -41,7 +40,7 @@ class VisitModelTests(TestCase):
         self.assertEquals(1, visit_count)
 
     def test_mark_as_finished_for_follow_up_visit(self):
-        subject = create_subject()
+        subject = create_study_subject()
         subject.type = SUBJECT_TYPE_CHOICES_PATIENT
         subject.save()
         visit = create_visit(subject)
@@ -64,9 +63,9 @@ class VisitModelTests(TestCase):
         self.assertTrue(visit.datetime_begin + datetime.timedelta(days=365 * 2 - 1) < new_follow_up.datetime_begin)
 
     def test_visit_to_string(self):
-        visit = create_visit(create_subject())
+        visit = create_visit(create_study_subject())
         self.assertIsNotNone(str(visit))
 
     def test_visit_to_unicode(self):
-        visit = create_visit(create_subject())
+        visit = create_visit(create_study_subject())
         self.assertIsNotNone(unicode(visit))
diff --git a/smash/web/tests/test_RedcapConnector.py b/smash/web/tests/test_RedcapConnector.py
index de3a1378a67218bfd393cfc4cd8efffd5f03ed02..bde702f4d61a714bbc250727f356c5d20a36c3ed 100644
--- a/smash/web/tests/test_RedcapConnector.py
+++ b/smash/web/tests/test_RedcapConnector.py
@@ -4,7 +4,7 @@ import logging
 
 from django.test import TestCase
 
-from functions import create_subject, prepare_test_redcap_connection
+from functions import create_study_subject, prepare_test_redcap_connection
 from web.models import Language
 from web.models.inconsistent_subject import InconsistentSubject
 from web.models.missing_subject import MissingSubject
@@ -39,7 +39,7 @@ class TestRedcapConnector(TestCase):
 
     def test_get_invalid_connections_for_new_local(self):
         prepare_test_redcap_connection()
-        subject = create_subject()
+        subject = create_study_subject()
         subject.nd_number = "123"
         subject.save()
 
@@ -49,7 +49,7 @@ class TestRedcapConnector(TestCase):
 
     def test_get_inconsistent_data(self):
         prepare_test_redcap_connection()
-        subject = create_subject()
+        subject = create_study_subject()
         # noinspection SpellCheckingInspection
         subject.nd_number = 'NDtest_external'
         subject.save()
@@ -72,43 +72,43 @@ class TestRedcapConnector(TestCase):
 
     def test_create_inconsistent_data_for_date_born(self):
         prepare_test_redcap_connection()
-        subject = create_subject()
+        study_subject = create_study_subject()
 
-        redcap_subject = self.create_redcap_subject_from_smash_subject(subject)
-        subject.date_born = get_today_midnight_date()
+        redcap_subject = self.create_redcap_subject_from_smash_subject(study_subject)
+        study_subject.subject.date_born = get_today_midnight_date()
 
-        self.check_single_inconsistency(redcap_subject, subject)
+        self.check_single_inconsistency(redcap_subject, study_subject)
 
-    def check_single_inconsistency(self, redcap_subject, subject):
+    def check_single_inconsistency(self, redcap_subject, study_subject):
         redcap_connection = RedcapConnector()
-        result = redcap_connection.create_inconsistency_subject(redcap_subject, subject, "")
+        result = redcap_connection.create_inconsistency_subject(redcap_subject, study_subject, "")
         self.assertIsNotNone(result)
         self.assertEqual(1, len(result.fields), "Invalid number of fields. Found: " + str(result.fields))
 
     def test_create_inconsistent_data_for_dead(self):
         prepare_test_redcap_connection()
-        subject = create_subject()
+        study_subject = create_study_subject()
 
-        redcap_subject = self.create_redcap_subject_from_smash_subject(subject)
-        subject.dead = not subject.dead
+        redcap_subject = self.create_redcap_subject_from_smash_subject(study_subject)
+        study_subject.subject.dead = not study_subject.subject.dead
 
-        self.check_single_inconsistency(redcap_subject, subject)
+        self.check_single_inconsistency(redcap_subject, study_subject)
 
     def test_create_inconsistent_data_for_language(self):
         language = Language.objects.create(name="xx")
         language.save()
         prepare_test_redcap_connection()
-        subject = create_subject()
+        study_subject = create_study_subject()
 
-        redcap_subject = self.create_redcap_subject_from_smash_subject(subject)
-        subject.languages.add(language)
+        redcap_subject = self.create_redcap_subject_from_smash_subject(study_subject)
+        study_subject.subject.languages.add(language)
 
-        self.check_single_inconsistency(redcap_subject, subject)
+        self.check_single_inconsistency(redcap_subject, study_subject)
 
     def test_create_inconsistent_data_for_language2(self):
         language = Language.objects.create(name="xx")
         prepare_test_redcap_connection()
-        subject = create_subject()
+        subject = create_study_subject()
 
         redcap_subject = self.create_redcap_subject_from_smash_subject(subject)
         redcap_subject.add_language(language)
@@ -117,7 +117,7 @@ class TestRedcapConnector(TestCase):
 
     def test_create_inconsistent_data_for_mpower_id(self):
         prepare_test_redcap_connection()
-        subject = create_subject()
+        subject = create_study_subject()
 
         redcap_subject = self.create_redcap_subject_from_smash_subject(subject)
         subject.mpower_id = "105"
@@ -126,7 +126,7 @@ class TestRedcapConnector(TestCase):
 
     def test_create_inconsistent_data_for_mpower_id_with_whitespace(self):
         prepare_test_redcap_connection()
-        subject = create_subject()
+        subject = create_study_subject()
         subject.mpower_id = "105"
 
         redcap_subject = self.create_redcap_subject_from_smash_subject(subject)
@@ -137,15 +137,15 @@ class TestRedcapConnector(TestCase):
         self.assertIsNone(result)
 
     @staticmethod
-    def create_redcap_subject_from_smash_subject(subject):
+    def create_redcap_subject_from_smash_subject(study_subject):
         redcap_subject = RedcapSubject()
-        for language in subject.languages.all():
+        for language in study_subject.subject.languages.all():
             redcap_subject.add_language(language)
-        redcap_subject.mpower_id = subject.mpower_id
-        redcap_subject.dead = subject.dead
-        redcap_subject.date_born = subject.date_born
-        redcap_subject.nd_number = subject.nd_number
-        redcap_subject.sex = subject.sex
+        redcap_subject.mpower_id = study_subject.mpower_id
+        redcap_subject.dead = study_subject.subject.dead
+        redcap_subject.date_born = study_subject.subject.date_born
+        redcap_subject.nd_number = study_subject.nd_number
+        redcap_subject.sex = study_subject.subject.sex
         return redcap_subject
 
     def test_get_language(self):
@@ -203,7 +203,7 @@ class TestRedcapConnector(TestCase):
 
     def test_refresh_inconsistent_data(self):
         prepare_test_redcap_connection()
-        subject = create_subject()
+        subject = create_study_subject()
         # noinspection SpellCheckingInspection
         subject.nd_number = 'NDtest_external'
         subject.save()
diff --git a/smash/web/tests/view/test_appointments.py b/smash/web/tests/view/test_appointments.py
index 239fb666b8b039fe5a5c0bc3783fe65105ec23db..97f26eb5c7abae165eb7f89d2766c299f9245e35 100644
--- a/smash/web/tests/view/test_appointments.py
+++ b/smash/web/tests/view/test_appointments.py
@@ -3,12 +3,13 @@ import logging
 
 from django.urls import reverse
 
-from web.tests.functions import create_subject, create_visit, create_appointment, create_worker, create_flying_team, \
+from web.forms import AppointmentEditForm, StudySubjectEditForm, SubjectEditForm
+from web.models import Appointment, StudySubject
+from web.tests import LoggedInTestCase
+from web.tests.functions import create_study_subject, create_visit, create_appointment, create_worker, \
+    create_flying_team, \
     format_form_field
-from web.forms import AppointmentEditForm, SubjectEditForm
-from web.models import Appointment, Subject
 from web.views.notifications import get_today_midnight_date
-from web.tests import LoggedInTestCase
 
 logger = logging.getLogger(__name__)
 
@@ -23,21 +24,13 @@ class AppointmentsViewTests(LoggedInTestCase):
         self.assertEqual(response.status_code, 200)
 
     def test_appointments_edit(self):
-        subject = create_subject()
+        subject = create_study_subject()
         visit = create_visit(subject)
         appointment = create_appointment(visit, when=datetime.datetime.now())
         new_comment = 'new comment'
         new_status = appointment.APPOINTMENT_STATUS_NO_SHOW
         new_last_name = "new last name"
-        form_appointment = AppointmentEditForm(user=self.user, instance=appointment, prefix="appointment")
-        form_subject = SubjectEditForm(instance=subject, prefix="subject")
-        form_data = {}
-        for key, value in form_appointment.initial.items():
-            if value is not None:
-                form_data['appointment-{}'.format(key)] = value
-        for key, value in form_subject.initial.items():
-            if value is not None:
-                form_data['subject-{}'.format(key)] = value
+        form_data = self.prepare_form(appointment, subject)
         form_data["appointment-comment"] = new_comment
         form_data["appointment-status"] = new_status
         form_data["subject-last_name"] = new_last_name
@@ -45,10 +38,10 @@ class AppointmentsViewTests(LoggedInTestCase):
             reverse('web.views.appointment_edit', kwargs={'id': appointment.id}), data=form_data)
         self.assertEqual(response.status_code, 302)
         updated_appointment = Appointment.objects.filter(id=appointment.id)[0]
-        updated_subject = Subject.objects.filter(id=subject.id)[0]
+        updated_subject = StudySubject.objects.filter(id=subject.id)[0]
         self.assertEqual(new_comment, updated_appointment.comment)
         self.assertEqual(new_status, updated_appointment.status)
-        self.assertEqual(new_last_name, updated_subject.last_name)
+        self.assertEqual(new_last_name, updated_subject.subject.last_name)
 
     def test_appointments_edit_without_visit(self):
         appointment = create_appointment()
@@ -59,6 +52,24 @@ class AppointmentsViewTests(LoggedInTestCase):
             reverse('web.views.appointment_edit', kwargs={'id': appointment.id}))
         self.assertEqual(response.status_code, 200)
 
+    def test_render_appointments_edit(self):
+        appointment = create_appointment()
+        appointment.comment = "APPOINTMENT_COMMENT_DATA"
+        appointment.save()
+        appointment.visit.subject.comments = "STUDY_SUBJECT_COMMENT_DATA"
+        appointment.visit.subject.save()
+        appointment.visit.subject.subject.first_name = "SUBJECT_FIRST_NAME_DATA"
+        appointment.visit.subject.subject.save()
+
+        response = self.client.get(
+            reverse('web.views.appointment_edit', kwargs={'id': appointment.id}))
+        self.assertEqual(response.status_code, 200)
+        self.assertTrue(appointment.comment in response.content, msg="Appointment data not visible in rendered page")
+        self.assertTrue(appointment.visit.subject.comments in response.content,
+                        msg="Subject study data not visible in rendered page")
+        self.assertTrue(appointment.visit.subject.subject.first_name in response.content,
+                        msg="Subject data not visible in rendered page")
+
     def test_save_appointments_edit_without_visit(self):
         appointment = create_appointment()
         appointment.visit = None
@@ -91,7 +102,7 @@ class AppointmentsViewTests(LoggedInTestCase):
         self.assertEqual(Appointment.APPOINTMENT_STATUS_FINISHED, appointment_result.status)
 
     def test_save_appointments_edit_with_invalid_nd_number(self):
-        subject = create_subject()
+        subject = create_study_subject()
         visit = create_visit(subject)
         appointment = create_appointment(visit, get_today_midnight_date())
 
@@ -103,40 +114,44 @@ class AppointmentsViewTests(LoggedInTestCase):
 
         self.assertEqual(response.status_code, 200)
 
-        updated_subject = Subject.objects.get(id=subject.id)
+        updated_subject = StudySubject.objects.get(id=subject.id)
         self.assertFalse(updated_subject.information_sent)
 
     def test_save_appointments_edit_with_valid_nd_number(self):
-        subject = create_subject()
+        subject = create_study_subject()
         visit = create_visit(subject)
         appointment = create_appointment(visit, get_today_midnight_date())
 
         form_data = self.prepare_form(appointment, subject)
         form_data["appointment-status"] = Appointment.APPOINTMENT_STATUS_FINISHED
-        form_data["subject-nd_number"] = "ND9999"
+        form_data["study-subject-nd_number"] = "ND9999"
 
         response = self.client.post(
             reverse('web.views.appointment_edit', kwargs={'id': appointment.id}), data=form_data)
 
         self.assertEqual(response.status_code, 302)
 
-        updated_subject = Subject.objects.get(id=subject.id)
+        updated_subject = StudySubject.objects.get(id=subject.id)
         self.assertTrue(updated_subject.information_sent)
 
     def prepare_form(self, appointment, subject):
         form_appointment = AppointmentEditForm(user=self.user, instance=appointment, prefix="appointment")
-        form_subject = SubjectEditForm(instance=subject, prefix="subject")
+        form_study_subject = StudySubjectEditForm(instance=subject, prefix="study-subject")
+        form_subject = SubjectEditForm(instance=subject.subject, prefix="study-subject")
         form_data = {}
         for key, value in form_appointment.initial.items():
             if value is not None:
                 form_data['appointment-{}'.format(key)] = format_form_field(value)
+        for key, value in form_study_subject.initial.items():
+            if value is not None:
+                form_data['study-subject-{}'.format(key)] = format_form_field(value)
         for key, value in form_subject.initial.items():
             if value is not None:
                 form_data['subject-{}'.format(key)] = format_form_field(value)
         return form_data
 
     def test_subject_flying_team_location(self):
-        subject = create_subject()
+        subject = create_study_subject()
         visit = create_visit(subject)
         appointment = create_appointment(visit, get_today_midnight_date())
 
@@ -144,11 +159,11 @@ class AppointmentsViewTests(LoggedInTestCase):
         form_data["appointment-status"] = Appointment.APPOINTMENT_STATUS_FINISHED
         form_data["appointment-flying_team"] = create_flying_team().id
         form_data['appointment-status'] = Appointment.APPOINTMENT_STATUS_FINISHED
-        form_data["subject-nd_number"] = "ND9999"
+        form_data["study-subject-nd_number"] = "ND9999"
 
         self.client.post(reverse('web.views.appointment_edit', kwargs={'id': appointment.id}), data=form_data)
 
-        updated_subject = Subject.objects.get(id=subject.id)
+        updated_subject = StudySubject.objects.get(id=subject.id)
         self.assertIsNotNone(updated_subject.flying_team)
 
     def test_delete_appointment(self):
diff --git a/smash/web/tests/view/test_configuration.py b/smash/web/tests/view/test_configuration.py
index 23a147796de28f012dcf257e1dac12313160bcb3..024f5e24d59c91245253108f4cab248f32929f45 100644
--- a/smash/web/tests/view/test_configuration.py
+++ b/smash/web/tests/view/test_configuration.py
@@ -1,5 +1,3 @@
-import datetime
-
 from django.urls import reverse
 
 from web.tests import LoggedInTestCase
@@ -9,4 +7,3 @@ class ConfigurationViewTests(LoggedInTestCase):
     def test_visit_details_request(self):
         response = self.client.get(reverse('web.views.configuration'))
         self.assertEqual(response.status_code, 200)
-
diff --git a/smash/web/tests/view/test_contact_attempt.py b/smash/web/tests/view/test_contact_attempt.py
index 9bb40d7191ef127995ec1a01f2a9618c91547971..a240ce9721866421cfde0c5bfd463b159e119594 100644
--- a/smash/web/tests/view/test_contact_attempt.py
+++ b/smash/web/tests/view/test_contact_attempt.py
@@ -7,18 +7,18 @@ from web.forms import ContactAttemptEditForm
 from web.models import ContactAttempt
 from web.models.constants import CONTACT_TYPES_EMAIL
 from web.tests import LoggedInWithWorkerTestCase
-from web.tests.functions import create_subject, create_contact_attempt, format_form_field
+from web.tests.functions import create_study_subject, create_contact_attempt, format_form_field
 
 
 class ContactAttemptViewTests(LoggedInWithWorkerTestCase):
     def test_contact_attempt_add_get(self):
-        subject = create_subject()
+        subject = create_study_subject()
         response = self.client.get(reverse('web.views.contact_add', kwargs={'subject_id': subject.id}))
         self.assertContains(response, 'selected">{}'.format(self.worker), 1)
         self.assertContains(response, 'selected">{}'.format(subject), 1)
 
     def test_contact_attempt_add_post_valid(self):
-        subject = create_subject()
+        subject = create_study_subject()
         self.assertEqual(0, ContactAttempt.objects.filter(subject=subject).count())
         now = datetime.datetime.now()
         now_aware = timezone.make_aware(now, timezone.get_default_timezone())
@@ -43,7 +43,7 @@ class ContactAttemptViewTests(LoggedInWithWorkerTestCase):
         self.assertContains(response, comment, 1)
 
     def test_contact_attempt_add_post_invalid(self):
-        subject = create_subject()
+        subject = create_study_subject()
         self.assertEqual(0, ContactAttempt.objects.filter(subject=subject).count())
         contact_type = CONTACT_TYPES_EMAIL
         comment = "this is a comment"
diff --git a/smash/web/tests/view/test_export.py b/smash/web/tests/view/test_export.py
index 91e1462730506a790a59ad8885ce431c60210cdb..d1394128104a6ece78d90d9b2a75ce46213687b0 100644
--- a/smash/web/tests/view/test_export.py
+++ b/smash/web/tests/view/test_export.py
@@ -3,13 +3,13 @@ from django.urls import reverse
 
 from web.models import Appointment
 from web.tests import LoggedInTestCase
-from web.tests.functions import create_subject, create_appointment, create_visit
+from web.tests.functions import create_study_subject, create_appointment, create_visit
 from web.views.export import subject_to_row_for_fields, DROP_OUT_FIELD
 
 
 class TestExportView(LoggedInTestCase):
     def test_export_subjects_to_csv(self):
-        create_subject()
+        create_study_subject()
         response = self.client.get(reverse('web.views.export_to_csv', kwargs={'data_type': "subjects"}))
         self.assertEqual(response.status_code, 200)
 
@@ -19,7 +19,7 @@ class TestExportView(LoggedInTestCase):
         self.assertEqual(response.status_code, 200)
 
     def test_export_subjects_to_excel(self):
-        create_subject()
+        create_study_subject()
         response = self.client.get(reverse('web.views.export_to_excel', kwargs={'data_type': "subjects"}))
         self.assertEqual(response.status_code, 200)
 
@@ -29,7 +29,7 @@ class TestExportView(LoggedInTestCase):
         self.assertEqual(response.status_code, 200)
 
     def test_subject_to_row_for_fields_when_not_resigned(self):
-        subject = create_subject()
+        subject = create_study_subject()
         subject.resigned = False
         subject.save()
 
@@ -37,7 +37,7 @@ class TestExportView(LoggedInTestCase):
         self.assertFalse(result[0])
 
     def test_subject_to_row_for_fields_when_resigned(self):
-        subject = create_subject()
+        subject = create_study_subject()
         subject.resigned = True
         subject.save()
 
@@ -45,7 +45,7 @@ class TestExportView(LoggedInTestCase):
         self.assertFalse(result[0])
 
     def test_subject_to_row_for_fields_when_dropped_out(self):
-        subject = create_subject()
+        subject = create_study_subject()
         subject.resigned = True
         subject.save()
 
diff --git a/smash/web/tests/view/test_notifications.py b/smash/web/tests/view/test_notifications.py
index c2586124a76f713af2746ad99f1cf5063123c773..031a225c754c4a41bb50bc81a3f8fe93f1c2b3fd 100644
--- a/smash/web/tests/view/test_notifications.py
+++ b/smash/web/tests/view/test_notifications.py
@@ -5,7 +5,7 @@ from django.contrib.auth.models import AnonymousUser
 from web.models import Appointment, Location, AppointmentTypeLink
 from web.tests import LoggedInTestCase
 from web.tests.functions import create_appointment, create_location, create_worker, create_appointment_type
-from web.tests.functions import create_subject
+from web.tests.functions import create_study_subject
 from web.tests.functions import create_visit
 from web.views.notifications import \
     get_approaching_visits_for_mail_contact, \
@@ -29,7 +29,7 @@ class NotificationViewTests(LoggedInTestCase):
     def test_get_exceeded_visit_notifications_count(self):
         original_notification = get_visits_without_appointments_count(self.user)
 
-        subject = create_subject()
+        subject = create_study_subject()
         visit = create_visit(subject)
         visit.datetime_end = "2011-01-01"
         visit.save()
@@ -41,7 +41,7 @@ class NotificationViewTests(LoggedInTestCase):
     def test_get_exceeded_visit_notifications_count_2(self):
         original_notification = get_visits_without_appointments_count(self.user)
 
-        subject = create_subject()
+        subject = create_study_subject()
         visit = create_visit(subject)
         visit.datetime_end = "2011-01-01"
         visit.is_finished = True
@@ -53,7 +53,7 @@ class NotificationViewTests(LoggedInTestCase):
 
     def test_get_visits_without_appointments_count(self):
         original_notification = get_visits_without_appointments_count(self.user)
-        subject = create_subject()
+        subject = create_study_subject()
         create_visit(subject)
 
         notification = get_visits_without_appointments_count(self.user)
@@ -97,7 +97,7 @@ class NotificationViewTests(LoggedInTestCase):
     def test_get_visits_without_appointments_count_2(self):
         appointment_type = create_appointment_type()
         original_notification = get_visits_without_appointments_count(self.user)
-        subject = create_subject()
+        subject = create_study_subject()
         visit = create_visit(subject)
         visit.appointment_types.add(appointment_type)
         visit.save()
@@ -107,7 +107,7 @@ class NotificationViewTests(LoggedInTestCase):
 
     def test_get_visits_without_appointments_count_3(self):
         original_notification = get_visits_without_appointments_count(self.user)
-        subject = create_subject()
+        subject = create_study_subject()
         visit = create_visit(subject)
         appointment = create_appointment(visit)
 
@@ -118,7 +118,7 @@ class NotificationViewTests(LoggedInTestCase):
         self.assertEquals(original_notification.count + 1, notification.count)
 
     def test_get_unfinished_visits_order(self):
-        subject = create_subject()
+        subject = create_study_subject()
 
         visit = create_visit(subject)
         visit.datetime_begin = get_today_midnight_date() + datetime.timedelta(days=-10)
@@ -141,7 +141,7 @@ class NotificationViewTests(LoggedInTestCase):
 
     def test_get_approaching_visits_without_appointments_count(self):
         original_notification = get_approaching_visits_without_appointments_count(self.user)
-        subject = create_subject()
+        subject = create_study_subject()
         visit = create_visit(subject)
         visit.datetime_begin = get_today_midnight_date() + datetime.timedelta(days=2)
         visit.save()
@@ -151,7 +151,7 @@ class NotificationViewTests(LoggedInTestCase):
 
     def test_get_approaching_visits_without_appointments_count_2(self):
         original_notification = get_approaching_visits_without_appointments_count(self.user)
-        subject = create_subject()
+        subject = create_study_subject()
         visit = create_visit(subject)
         visit.datetime_begin = get_today_midnight_date() + datetime.timedelta(days=2)
         visit.save()
@@ -162,7 +162,7 @@ class NotificationViewTests(LoggedInTestCase):
 
     def test_get_approaching_visits_without_appointments_count_3(self):
         original_notification = get_approaching_visits_without_appointments_count(self.user)
-        subject = create_subject()
+        subject = create_study_subject()
         visit = create_visit(subject)
         visit.datetime_begin = get_today_midnight_date() + datetime.timedelta(days=2)
         visit.save()
@@ -175,7 +175,7 @@ class NotificationViewTests(LoggedInTestCase):
         self.assertEquals(original_notification.count + 1, notification.count)
 
     def test_get_approaching_visits_without_appointments_order(self):
-        subject = create_subject()
+        subject = create_study_subject()
 
         visit = create_visit(subject)
         visit.datetime_begin = get_today_midnight_date() + datetime.timedelta(days=10)
@@ -198,14 +198,14 @@ class NotificationViewTests(LoggedInTestCase):
 
     def test_get_subject_with_no_visit_notifications_count(self):
         original_notification = get_subject_with_no_visit_notifications_count(self.user)
-        create_subject()
+        create_study_subject()
 
         notification = get_subject_with_no_visit_notifications_count(self.user)
         self.assertEquals(original_notification.count + 1, notification.count)
 
     def test_get_subject_with_no_visit_notifications_count_2(self):
         original_notification = get_subject_with_no_visit_notifications_count(self.user)
-        subject = create_subject()
+        subject = create_study_subject()
 
         visit = create_visit(subject)
         visit.is_finished = True
@@ -216,7 +216,7 @@ class NotificationViewTests(LoggedInTestCase):
 
     def test_get_subject_with_no_visit_notifications_count_3(self):
         original_notification = get_subject_with_no_visit_notifications_count(self.user)
-        subject = create_subject()
+        subject = create_study_subject()
 
         create_visit(subject)
 
@@ -225,16 +225,16 @@ class NotificationViewTests(LoggedInTestCase):
 
     def test_get_subject_with_no_visit_notifications_count_4(self):
         original_notification = get_subject_with_no_visit_notifications_count(self.user)
-        subject = create_subject()
-        subject.dead = True
-        subject.save()
+        study_subject = create_study_subject()
+        study_subject.subject.dead = True
+        study_subject.subject.save()
 
         notification = get_subject_with_no_visit_notifications_count(self.user)
         self.assertEquals(original_notification.count, notification.count)
 
     def test_get_subject_with_no_visit_notifications_count_5(self):
         original_notification = get_subject_with_no_visit_notifications_count(self.user)
-        subject = create_subject()
+        subject = create_study_subject()
         subject.resigned = True
         subject.save()
 
@@ -243,7 +243,7 @@ class NotificationViewTests(LoggedInTestCase):
 
     def test_get_unfinished_appointments_count(self):
         original_notification = get_unfinished_appointments_count(self.user)
-        subject = create_subject()
+        subject = create_study_subject()
         visit = create_visit(subject)
         appointment = create_appointment(visit)
         appointment.datetime_when = "2011-01-01"
@@ -255,7 +255,7 @@ class NotificationViewTests(LoggedInTestCase):
 
     def test_get_unfinished_appointments_count_2(self):
         original_notification = get_unfinished_appointments_count(self.user)
-        subject = create_subject()
+        subject = create_study_subject()
         visit = create_visit(subject)
         appointment = create_appointment(visit)
         appointment.datetime_when = "2011-01-01"
@@ -266,7 +266,7 @@ class NotificationViewTests(LoggedInTestCase):
         self.assertEquals(original_notification.count, notification.count)
 
     def test_get_unfinished_appointments_order(self):
-        subject = create_subject()
+        subject = create_study_subject()
         visit = create_visit(subject)
 
         appointment = create_appointment(visit, get_today_midnight_date() + datetime.timedelta(days=-10))
@@ -290,7 +290,7 @@ class NotificationViewTests(LoggedInTestCase):
         create_location("l1")
         create_location("l2")
         original_notification = get_subject_with_no_visit_notifications_count(self.user)
-        create_subject()
+        create_study_subject()
 
         notification = get_subject_with_no_visit_notifications_count(self.user)
         self.assertEquals(original_notification.count + 1, notification.count)
@@ -302,7 +302,7 @@ class NotificationViewTests(LoggedInTestCase):
 
         original_notification = get_subject_with_no_visit_notifications_count(worker)
 
-        subject = create_subject()
+        subject = create_study_subject()
         subject.default_location = create_location("l1")
         subject.save()
 
@@ -317,7 +317,7 @@ class NotificationViewTests(LoggedInTestCase):
 
     def test_get_approaching_visits_for_mail_contact_count(self):
         original_notification = get_approaching_visits_for_mail_contact_count(self.user)
-        subject = create_subject()
+        subject = create_study_subject()
         visit = create_visit(subject)
         visit.datetime_begin = get_today_midnight_date() + datetime.timedelta(days=100)
         visit.save()
@@ -327,7 +327,7 @@ class NotificationViewTests(LoggedInTestCase):
 
     def test_get_approaching_visits_for_mail_contact_count_2(self):
         original_notification = get_approaching_visits_for_mail_contact_count(self.user)
-        subject = create_subject()
+        subject = create_study_subject()
         visit = create_visit(subject)
         visit.datetime_begin = get_today_midnight_date() + datetime.timedelta(days=100)
         visit.save()
@@ -338,7 +338,7 @@ class NotificationViewTests(LoggedInTestCase):
 
     def test_get_approaching_visits_for_mail_contact_count_3(self):
         original_notification = get_approaching_visits_for_mail_contact_count(self.user)
-        subject = create_subject()
+        subject = create_study_subject()
         visit = create_visit(subject)
         visit.datetime_begin = get_today_midnight_date() + datetime.timedelta(days=100)
         visit.save()
@@ -352,7 +352,7 @@ class NotificationViewTests(LoggedInTestCase):
 
     def test_get_approaching_visits_for_mail_contact_count_4(self):
         original_notification = get_approaching_visits_for_mail_contact_count(self.user)
-        subject = create_subject()
+        subject = create_study_subject()
         visit = create_visit(subject)
         visit.datetime_begin = get_today_midnight_date() + datetime.timedelta(days=100)
         visit.post_mail_sent = True
@@ -362,7 +362,7 @@ class NotificationViewTests(LoggedInTestCase):
         self.assertEquals(original_notification.count, notification.count)
 
     def test_get_approaching_visits_for_mail_contact_order(self):
-        subject = create_subject()
+        subject = create_study_subject()
 
         visit = create_visit(subject)
         visit.datetime_begin = get_today_midnight_date() + datetime.timedelta(days=110)
@@ -386,7 +386,7 @@ class NotificationViewTests(LoggedInTestCase):
     def test_get_subjects_with_reminder_count(self):
         original_without_visit_notification = get_subject_with_no_visit_notifications_count(self.user)
         original_notification = get_subjects_with_reminder_count(self.user)
-        subject = create_subject()
+        subject = create_study_subject()
         subject.datetime_contact_reminder = get_today_midnight_date() + datetime.timedelta(days=-1)
         subject.save()
 
@@ -399,7 +399,7 @@ class NotificationViewTests(LoggedInTestCase):
     def test_get_subjects_with_reminder_count_2(self):
         original_without_visit_notification = get_subject_with_no_visit_notifications_count(self.user)
         original_notification = get_subjects_with_reminder_count(self.user)
-        subject = create_subject()
+        subject = create_study_subject()
         subject.datetime_contact_reminder = get_today_midnight_date() + datetime.timedelta(hours=1)
         subject.save()
 
@@ -412,7 +412,7 @@ class NotificationViewTests(LoggedInTestCase):
     def test_get_subjects_with_reminder_count_3(self):
         original_without_visit_notification = get_subject_with_no_visit_notifications_count(self.user)
         original_notification = get_subjects_with_reminder_count(self.user)
-        subject = create_subject()
+        subject = create_study_subject()
         subject.datetime_contact_reminder = get_today_midnight_date() + datetime.timedelta(days=2)
         subject.save()
 
diff --git a/smash/web/tests/view/test_subjects.py b/smash/web/tests/view/test_subjects.py
index 834ba8d09d950625bd64d32465753c74ce3b2e9f..4617ccab3367d799f1aaefad73d5bf39f60d8072 100644
--- a/smash/web/tests/view/test_subjects.py
+++ b/smash/web/tests/view/test_subjects.py
@@ -1,183 +1,177 @@
 import datetime
+import logging
 
 from django.urls import reverse
 
-from web.forms import SubjectAddForm, SubjectEditForm
-from web.models import Subject
+from web.forms import StudySubjectAddForm, StudySubjectEditForm, SubjectEditForm, SubjectAddForm
+from web.models import StudySubject
 from web.models.constants import SEX_CHOICES_MALE, SUBJECT_TYPE_CHOICES_CONTROL, SUBJECT_TYPE_CHOICES_PATIENT, \
     COUNTRY_AFGHANISTAN_ID, COUNTRY_OTHER_ID
 from web.tests import LoggedInWithWorkerTestCase
-from web.tests.functions import create_subject, create_visit, create_appointment, get_test_location
+from web.tests.functions import create_study_subject, create_visit, create_appointment, get_test_location
 from web.views.notifications import get_today_midnight_date
 
+logger = logging.getLogger(__name__)
+
 
 class SubjectsViewTests(LoggedInWithWorkerTestCase):
     def setUp(self):
         super(SubjectsViewTests, self).setUp()
+        self.study_subject = create_study_subject()
 
-    def test_subjects_add(self):
+    def test_render_subjects_add(self):
         self.worker.save()
 
         response = self.client.get(reverse('web.views.subject_add'))
         self.assertEqual(response.status_code, 200)
 
     def test_render_subject_edit(self):
-        subject = create_subject()
-
-        response = self.client.get(reverse('web.views.subject_edit', kwargs={'id': subject.id}))
+        response = self.client.get(reverse('web.views.subject_edit', kwargs={'id': self.study_subject.id}))
         self.assertEqual(response.status_code, 200)
 
     def test_render_subject_visit_details(self):
-        subject = create_subject()
-        visit = create_visit(subject)
+        visit = create_visit(self.study_subject)
         create_appointment(visit)
 
-        response = self.client.get(reverse('web.views.subject_visit_details', kwargs={'id': subject.id}))
+        response = self.client.get(reverse('web.views.subject_visit_details', kwargs={'id': self.study_subject.id}))
         self.assertEqual(response.status_code, 200)
         self.assertFalse("Add visit" in response.content)
 
     def test_render_subject_visit_details_without_visit(self):
-        subject = create_subject()
-
-        response = self.client.get(reverse('web.views.subject_visit_details', kwargs={'id': subject.id}))
+        response = self.client.get(reverse('web.views.subject_visit_details', kwargs={'id': self.study_subject.id}))
         self.assertEqual(response.status_code, 200)
         self.assertTrue("Add visit" in response.content)
 
     def test_save_subject_edit_when_resigned_without_reason(self):
-        subject = create_subject()
-        form_subject = SubjectEditForm(instance=subject)
-        form_data = {}
-        for key, value in form_subject.initial.items():
-            if value is not None:
-                form_data[key] = value
+        form_data = self.create_edit_form_data_for_study_subject()
 
-        form_data['dead'] = "True"
-        form_data['resigned'] = "True"
+        form_data['subject-dead'] = "True"
+        form_data['study_subject-resigned'] = "True"
         response = self.client.post(
-            reverse('web.views.subject_edit', kwargs={'id': subject.id}), data=form_data)
+            reverse('web.views.subject_edit', kwargs={'id': self.study_subject.id}), data=form_data)
 
         self.assertEqual(response.status_code, 200)
         self.assertTrue("Resign reason cannot be empty" in response.content)
 
     def test_save_subject_edit(self):
-        subject = create_subject()
-        form_subject = SubjectEditForm(instance=subject)
-        form_data = {}
-        for key, value in form_subject.initial.items():
-            if value is not None:
-                form_data[key] = value
+        form_data = self.create_edit_form_data_for_study_subject()
 
-        form_data['dead'] = "True"
-        form_data['resigned'] = "True"
-        form_data['resign_reason'] = "doesn't want to participate"
+        form_data['subject-dead'] = "True"
+        form_data['study_subject-resigned'] = "True"
+        form_data['study_subject-resign_reason'] = "doesn't want to participate"
         response = self.client.post(
-            reverse('web.views.subject_edit', kwargs={'id': subject.id}), data=form_data)
+            reverse('web.views.subject_edit', kwargs={'id': self.study_subject.id}), data=form_data)
 
         self.assertEqual(response.status_code, 302)
-        updated_subject = Subject.objects.filter(id=subject.id)[0]
-        self.assertTrue(updated_subject.dead)
-        self.assertTrue(updated_subject.resigned)
+        updated_study_subject = StudySubject.objects.filter(id=self.study_subject.id)[0]
+        self.assertTrue(updated_study_subject.subject.dead)
+        self.assertTrue(updated_study_subject.resigned)
 
-    def test_subjects_add_2(self):
-
-        form = SubjectAddForm(user=self.user)
+    def create_edit_form_data_for_study_subject(self):
+        form_study_subject = StudySubjectEditForm(instance=self.study_subject, prefix="study_subject")
+        form_subject = SubjectEditForm(instance=self.study_subject.subject, prefix="subject")
         form_data = {}
-        for key, value in form.initial.items():
+        for key, value in form_study_subject.initial.items():
+            if value is not None:
+                form_data['study_subject-{}'.format(key)] = value
+        for key, value in form_subject.initial.items():
             if value is not None:
-                form_data[key] = value
+                form_data['subject-{}'.format(key)] = value
+        return form_data
 
+    def create_add_form_data_for_study_subject(self):
+        form_study_subject = StudySubjectAddForm(prefix="study_subject", user=self.user)
+        form_subject = SubjectAddForm(prefix="subject")
+        form_data = {}
+        for key, value in form_study_subject.initial.items():
+            if value is not None:
+                form_data['study_subject-{}'.format(key)] = value
+        for key, value in form_subject.initial.items():
+            if value is not None:
+                form_data['subject-{}'.format(key)] = value
         self.add_valid_form_data_for_subject_add(form_data)
-        form_data["type"] = SUBJECT_TYPE_CHOICES_CONTROL
-        form_data["default_location"] = get_test_location().id
+        return form_data
+
+    def test_subjects_add_2(self):
+        form_data = self.create_add_form_data_for_study_subject()
+
+        form_data["study_subject-type"] = SUBJECT_TYPE_CHOICES_CONTROL
+        form_data["study_subject-default_location"] = get_test_location().id
         response = self.client.post(reverse('web.views.subject_add'), data=form_data)
         self.assertEqual(response.status_code, 302)
         response = self.client.get(response.url)
         self.assertContains(response, "Subject created")
 
-        subject = Subject.objects.all()[0]
+        subject = StudySubject.objects.all().order_by("-id")[0]
         self.assertEqual("L-001", subject.screening_number,
                          "prefix should start by L" +
                          " as default location prefix is not defined and subject type is control")
 
-    @staticmethod
-    def add_valid_form_data_for_subject_add(form_data):
-        form_data["country"] = COUNTRY_AFGHANISTAN_ID
-        form_data["first_name"] = "John"
-        form_data["last_name"] = "Doe"
-        form_data["sex"] = SEX_CHOICES_MALE
-        form_data["type"] = SUBJECT_TYPE_CHOICES_PATIENT
+    def add_valid_form_data_for_subject_add(self, form_data):
+        form_data["subject-country"] = COUNTRY_AFGHANISTAN_ID
+        form_data["subject-first_name"] = "John"
+        form_data["subject-last_name"] = "Doe"
+        form_data["subject-sex"] = SEX_CHOICES_MALE
+        form_data["study_subject-type"] = SUBJECT_TYPE_CHOICES_PATIENT
+        form_data["study_subject-subject"] = self.study_subject.id
 
-    def test_subjects_add_patient(self):
+        # TODO remove after refactoring
+        form_data["study_subject-country"] = COUNTRY_AFGHANISTAN_ID
+        form_data["study_subject-first_name"] = "John"
+        form_data["study_subject-last_name"] = "Doe"
 
-        form = SubjectAddForm(user=self.user)
-        form_data = {}
-        for key, value in form.initial.items():
-            if value is not None:
-                form_data[key] = value
+    def test_subjects_add_patient(self):
+        form_data = self.create_add_form_data_for_study_subject()
 
-        self.add_valid_form_data_for_subject_add(form_data)
-        form_data["default_location"] = get_test_location().id
+        form_data["study_subject-default_location"] = get_test_location().id
         response = self.client.post(reverse('web.views.subject_add'), data=form_data)
         self.assertEqual(response.status_code, 302)
         response = self.client.get(response.url)
         self.assertContains(response, "Subject created")
 
-        subject = Subject.objects.all()[0]
+        subject = StudySubject.objects.all().order_by("-id")[0]
         self.assertEqual("P-001", subject.screening_number,
                          "prefix should start by P" +
                          " as default location prefix is not defined and subject type is patient")
 
     def test_subjects_add_invalid(self):
+        form_data = self.create_add_form_data_for_study_subject()
+        form_data["study_subject-type"] = SUBJECT_TYPE_CHOICES_CONTROL
+        form_data["study_subject-default_location"] = get_test_location().id
 
-        form = SubjectAddForm(user=self.user)
-        form_data = {}
-        for key, value in form.initial.items():
-            if value is not None:
-                form_data[key] = value
-
-        self.add_valid_form_data_for_subject_add(form_data)
-        form_data["country"] = COUNTRY_OTHER_ID
+        form_data["subject-country"] = COUNTRY_OTHER_ID
         response = self.client.post(reverse('web.views.subject_add'), data=form_data)
 
         self.assertTrue("Invalid data" in response.content)
 
     def test_subjects_add_with_prefixed_location(self):
-
-        form = SubjectAddForm(user=self.user)
-        form_data = {}
-        for key, value in form.initial.items():
-            if value is not None:
-                form_data[key] = value
+        form_data = self.create_add_form_data_for_study_subject()
+        form_data["study_subject-type"] = SUBJECT_TYPE_CHOICES_CONTROL
 
         self.add_valid_form_data_for_subject_add(form_data)
         location = get_test_location()
         location.prefix = 'X'
         location.save()
-        form_data["default_location"] = location.id
+        form_data["study_subject-default_location"] = get_test_location().id
         response = self.client.post(reverse('web.views.subject_add'), data=form_data)
         self.assertEqual(response.status_code, 302)
         response = self.client.get(response.url)
         self.assertContains(response, "Subject created")
 
-        subject = Subject.objects.all()[0]
+        subject = StudySubject.objects.all().order_by("-id")[0]
         self.assertEqual("X-001", subject.screening_number,
                          "prefix should start by X as default location prefix is equal to 'X'")
 
     def test_render_subjects(self):
-        create_subject()
-
         response = self.client.get(reverse('web.views.subjects'))
         self.assertEqual(response.status_code, 200)
 
     def test_render_subjects_with_no_visit(self):
-        create_subject()
-
         response = self.client.get(reverse('web.views.subject_no_visits'))
         self.assertEqual(response.status_code, 200)
 
     def test_render_subjects_require_contact(self):
-        subject = create_subject()
-        subject.datetime_contact_reminder = get_today_midnight_date() + datetime.timedelta(days=-1)
+        self.study_subject.datetime_contact_reminder = get_today_midnight_date() + datetime.timedelta(days=-1)
 
         response = self.client.get(reverse('web.views.subject_require_contact'))
         self.assertEqual(response.status_code, 200)
diff --git a/smash/web/tests/view/test_visit.py b/smash/web/tests/view/test_visit.py
index 217475e6822e106079f7fc52550b706bcddd3a55..8925d6d8fa8b0be13fba8098c288027c02b071b9 100644
--- a/smash/web/tests/view/test_visit.py
+++ b/smash/web/tests/view/test_visit.py
@@ -1,21 +1,30 @@
 import datetime
+import logging
 
 from django.urls import reverse
 
 from web.forms import VisitDetailForm, VisitAddForm
 from web.models import Visit
 from web.tests import LoggedInTestCase
-from web.tests.functions import create_subject, create_visit, create_appointment, create_appointment_type
+from web.tests.functions import create_study_subject, create_visit, create_appointment, create_appointment_type
 from web.views.notifications import get_today_midnight_date
 
+logger = logging.getLogger(__name__)
+
 
 class VisitViewTests(LoggedInTestCase):
     def test_visit_details_request(self):
         visit = create_visit()
         create_appointment(visit)
+        visit.subject.subject.address = "SUBJECT_ADDRESS_DATA"
+        visit.subject.subject.save()
+        visit.subject.comments = "STUDY_SUBJECT_COMMENTS_DATA"
+        visit.subject.save()
 
-        response = self.client.get(reverse('web.views.visit_details', args=[visit.id]))
+        response = self.client.get(reverse('web.views.visit_details', kwargs={'id': visit.id}))
         self.assertEqual(response.status_code, 200)
+        self.assertTrue(visit.subject.comments in response.content, msg="No study subject data in rendered response")
+        self.assertTrue(visit.subject.subject.address in response.content, msg="No subject data in rendered response")
 
     def test_save_visit_details(self):
         visit = create_visit()
@@ -36,14 +45,14 @@ class VisitViewTests(LoggedInTestCase):
         self.assertNotContains(response, "error")
 
     def test_render_add_visit(self):
-        subject = create_subject()
+        study_subject = create_study_subject()
 
-        response = self.client.get(reverse('web.views.visit_add', kwargs={'subject_id': subject.id}))
+        response = self.client.get(reverse('web.views.visit_add', kwargs={'subject_id': study_subject.id}))
         self.assertEqual(response.status_code, 200)
 
     def test_save_add_visit(self):
         visit_count = Visit.objects.all().count()
-        subject = create_subject()
+        subject = create_study_subject()
 
         form = VisitAddForm()
         form_data = {}
diff --git a/smash/web/views/appointment.py b/smash/web/views/appointment.py
index 2ec6de2acb48e7232dfe72f5afe13d2d3bf59745..e7f08ea311fe1581c2c1363606c0842f11f572a2 100644
--- a/smash/web/views/appointment.py
+++ b/smash/web/views/appointment.py
@@ -7,8 +7,9 @@ from django.core.exceptions import ValidationError
 from django.shortcuts import get_object_or_404, redirect
 
 from . import wrap_response
-from ..forms import AppointmentDetailForm, AppointmentAddForm, AppointmentEditForm, SubjectEditForm
-from ..models import Appointment, Subject, MailTemplate
+from ..forms import AppointmentDetailForm, AppointmentAddForm, AppointmentEditForm, StudySubjectEditForm, \
+    SubjectEditForm
+from ..models import Appointment, StudySubject, MailTemplate
 
 APPOINTMENT_LIST_GENERIC = "GENERIC"
 APPOINTMENT_LIST_UNFINISHED = "UNFINISHED"
@@ -58,6 +59,7 @@ def appointment_add(request, visit_id=None):
 
 def appointment_edit(request, id):
     the_appointment = get_object_or_404(Appointment, id=id)
+    study_subject_form = None
     subject_form = None
     contact_attempts = None
 
@@ -69,7 +71,12 @@ def appointment_edit(request, id):
                                                prefix="appointment")
         is_valid_form = True
         if the_appointment.visit is not None:
-            subject_form = SubjectEditForm(request.POST, instance=the_appointment.visit.subject, prefix="subject")
+            study_subject_form = StudySubjectEditForm(request.POST, instance=the_appointment.visit.subject,
+                                                      prefix="study-subject")
+            if not study_subject_form.is_valid():
+                is_valid_form = False
+            subject_form = SubjectEditForm(request.POST, instance=the_appointment.visit.subject.subject,
+                                           prefix="subject")
             if not subject_form.is_valid():
                 is_valid_form = False
 
@@ -78,18 +85,19 @@ def appointment_edit(request, id):
 
         if the_appointment.visit is not None:
             if appointment_form.cleaned_data["status"] == Appointment.APPOINTMENT_STATUS_FINISHED:
-                if re.match('ND[0-9][0-9][0-9][0-9]', subject_form.cleaned_data["nd_number"]) is None:
-                    subject_form.add_error('nd_number', ValidationError("invalid ND number"))
+                if re.match('ND[0-9][0-9][0-9][0-9]', study_subject_form.cleaned_data["nd_number"]) is None:
+                    study_subject_form.add_error('nd_number', ValidationError("invalid ND number"))
                     is_valid_form = False
 
         if is_valid_form:
             appointment_form.save()
-            if subject_form is not None:
+            if study_subject_form is not None:
+                study_subject_form.save()
                 subject_form.save()
             the_appointment = get_object_or_404(Appointment, id=id)
 
             if the_appointment.status == Appointment.APPOINTMENT_STATUS_FINISHED and the_appointment.visit is not None:
-                subject = Subject.objects.get(id=the_appointment.visit.subject.id)
+                subject = StudySubject.objects.get(id=the_appointment.visit.subject.id)
                 subject.information_sent = True
                 if the_appointment.flying_team is not None and subject.flying_team is None:
                     subject.flying_team = the_appointment.flying_team
@@ -109,17 +117,20 @@ def appointment_edit(request, id):
         appointment_form = AppointmentEditForm(instance=the_appointment, user=request.user, prefix="appointment")
 
         if the_appointment.visit is not None:
-            subject_form = SubjectEditForm(instance=the_appointment.visit.subject, prefix="subject")
+            study_subject_form = StudySubjectEditForm(instance=the_appointment.visit.subject, prefix="study-subject")
+            subject_form = SubjectEditForm(instance=the_appointment.visit.subject.subject,
+                                           prefix="subject")
             contact_attempts = the_appointment.visit.subject.contactattempt_set.order_by('-datetime_when').all()
 
     languages = []
     if the_appointment.visit is not None:
-        subject = the_appointment.visit.subject
+        subject = the_appointment.visit.subject.subject
         if subject.default_written_communication_language:
             languages.append(subject.default_written_communication_language)
         languages.extend(subject.languages.all())
     return wrap_response(request, 'appointments/edit.html', {
-        'form': appointment_form,
+        'appointment_form': appointment_form,
+        'study_subject_form': study_subject_form,
         'subject_form': subject_form,
         'id': id,
         'appointment': the_appointment,
diff --git a/smash/web/views/contact_attempt.py b/smash/web/views/contact_attempt.py
index 6246cd03afc6fdea92f4e5f0bd9daea80cd8ed81..6694bc41836623bef0041fe6c7861ee2e4a4c7bc 100644
--- a/smash/web/views/contact_attempt.py
+++ b/smash/web/views/contact_attempt.py
@@ -2,11 +2,11 @@ from django.shortcuts import redirect, get_object_or_404
 
 from . import wrap_response
 from ..forms import ContactAttemptForm, ContactAttemptEditForm
-from ..models import Subject, ContactAttempt
+from ..models import StudySubject, ContactAttempt
 
 
 def contact_add(request, subject_id):
-    subject = get_object_or_404(Subject, id=subject_id)
+    subject = get_object_or_404(StudySubject, id=subject_id)
     if request.method == 'POST':
         form = ContactAttemptForm(request.POST, user=request.user, subject=subject)
         form.instance.subject_id = subject_id
diff --git a/smash/web/views/export.py b/smash/web/views/export.py
index 5279b6b8f302574f0ffaf4f78cdb774256458f21..b5b755e61ebd600e8043c9a50259fb8802815912 100644
--- a/smash/web/views/export.py
+++ b/smash/web/views/export.py
@@ -7,7 +7,7 @@ from django.http import HttpResponse
 
 from notifications import get_today_midnight_date
 from . import e500_error, wrap_response
-from ..models import Subject, Appointment
+from ..models import Subject, StudySubject, Appointment
 
 
 @login_required
@@ -65,28 +65,31 @@ def get_subjects_as_array():
 
     result.append(field_names)
 
-    subjects = Subject.objects.order_by('-last_name')
+    subjects = StudySubject.objects.order_by('-subject__last_name')
     for subject in subjects:
         row = subject_to_row_for_fields(subject, subject_fields)
         result.append([unicode(s).replace("\n", ";").replace("\r", ";") for s in row])
     return result
 
 
-def subject_to_row_for_fields(subject, subject_fields):
+def subject_to_row_for_fields(study_subject, subject_fields):
     row = []
     for field in subject_fields:
         if field == DROP_OUT_FIELD:
-            if not subject.resigned:
+            if not study_subject.resigned:
                 cell = False
             else:
-                finished_appointments = Appointment.objects.filter(visit__subject=subject).filter(
+                finished_appointments = Appointment.objects.filter(visit__subject=study_subject).filter(
                     status=Appointment.APPOINTMENT_STATUS_FINISHED).count()
                 if finished_appointments > 0:
                     cell = True
                 else:
                     cell = False
         else:
-            cell = getattr(subject, field.name)
+            if hasattr(study_subject, field.name):
+                cell = getattr(study_subject, field.name)
+            elif hasattr(study_subject.subject, field.name):
+                cell = getattr(study_subject.subject, field.name)
             if cell is None:
                 cell = ""
         row.append(cell)
@@ -98,6 +101,9 @@ def get_default_subject_fields():
     for field in Subject._meta.fields:
         if field.name != "ID":
             subject_fields.append(field)
+    for field in StudySubject._meta.fields:
+        if field.name != "ID" and field.name != "subject":
+            subject_fields.append(field)
     subject_fields.append(DROP_OUT_FIELD)
     return subject_fields
 
@@ -121,8 +127,8 @@ def get_appointments_as_array():
 
     for appointment in appointments:
         if appointment.visit is not None:
-            row = [appointment.visit.subject.nd_number, appointment.visit.subject.last_name,
-                   appointment.visit.subject.first_name, appointment.visit.visit_number]
+            row = [appointment.visit.subject.nd_number, appointment.visit.subject.subject.last_name,
+                   appointment.visit.subject.subject.first_name, appointment.visit.visit_number]
         else:
             row = ["---", "---", "---", "---"]
         for field in appointments_fields:
diff --git a/smash/web/views/mails.py b/smash/web/views/mails.py
index abe5d7f79cf1d12b087d2da1c5b66a9314f4ee1b..8ca773008e269e26c2c9a03010ff25ad5f8df05a 100644
--- a/smash/web/views/mails.py
+++ b/smash/web/views/mails.py
@@ -13,14 +13,14 @@ from django.views.generic import ListView
 from django.views.generic import UpdateView
 
 from . import wrap_response, WrappedView
-from ..models import Subject, Visit, Appointment, MailTemplate
+from ..models import StudySubject, Visit, Appointment, MailTemplate
 from ..models.constants import MAIL_TEMPLATE_CONTEXT_SUBJECT, MAIL_TEMPLATE_CONTEXT_VISIT, \
     MAIL_TEMPLATE_CONTEXT_APPOINTMENT
 
 MIMETYPE_DOCX = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
 
 CONTEXT_TYPES_MAPPING = {
-    MAIL_TEMPLATE_CONTEXT_SUBJECT: Subject,
+    MAIL_TEMPLATE_CONTEXT_SUBJECT: StudySubject,
     MAIL_TEMPLATE_CONTEXT_VISIT: Visit,
     MAIL_TEMPLATE_CONTEXT_APPOINTMENT: Appointment
 }
diff --git a/smash/web/views/notifications.py b/smash/web/views/notifications.py
index 42cbc3e41952d551f53f4d08b99c84a4ba52ecaf..3829d3ebebc09360004a2730fad67c52dd0df520 100644
--- a/smash/web/views/notifications.py
+++ b/smash/web/views/notifications.py
@@ -5,7 +5,7 @@ from django.utils import timezone
 from django.contrib.auth.models import User, AnonymousUser
 from django.db.models import Count, Case, When
 
-from ..models import Worker, Subject, Visit, Appointment, Location, MissingSubject, InconsistentSubject
+from ..models import Worker, StudySubject, Visit, Appointment, Location, MissingSubject, InconsistentSubject
 
 
 class NotificationCount(object):
@@ -132,8 +132,8 @@ def get_notifications(the_user):
 
 
 def get_subjects_with_no_visit(user):
-    result = Subject.objects.annotate(my_count=Count(Case(When(visit__is_finished=False, then=1)))).filter(
-        dead=False,
+    result = StudySubject.objects.annotate(my_count=Count(Case(When(visit__is_finished=False, then=1)))).filter(
+        subject__dead=False,
         resigned=False,
         my_count=0,
         default_location__in=get_filter_locations(user),
@@ -146,8 +146,8 @@ def get_subjects_with_no_visit(user):
 def get_subjects_with_reminder(user):
     tomorrow = datetime.datetime.now() + datetime.timedelta(hours=1)
 
-    result = Subject.objects.filter(
-        dead=False,
+    result = StudySubject.objects.filter(
+        subject__dead=False,
         resigned=False,
         default_location__in=get_filter_locations(user),
         datetime_contact_reminder__lt=tomorrow,
diff --git a/smash/web/views/subject.py b/smash/web/views/subject.py
index dfc0c2bc0cb57991c3f49210e49a38787e3c2136..53ceafe61a78afb0d1e260df5cfb4e8248e547b5 100644
--- a/smash/web/views/subject.py
+++ b/smash/web/views/subject.py
@@ -1,15 +1,19 @@
 # coding=utf-8
+import logging
+
 from django.contrib import messages
 from django.shortcuts import redirect, get_object_or_404
 
 from . import wrap_response
-from ..forms import SubjectAddForm, SubjectEditForm, VisitDetailForm
-from ..models import Subject, MailTemplate, Worker
+from ..forms import StudySubjectAddForm, StudySubjectEditForm, VisitDetailForm, SubjectEditForm, SubjectAddForm
+from ..models import StudySubject, MailTemplate, Worker
 
 SUBJECT_LIST_GENERIC = "GENERIC"
 SUBJECT_LIST_NO_VISIT = "NO_VISIT"
 SUBJECT_LIST_REQUIRE_CONTACT = "REQUIRE_CONTACT"
 
+logger = logging.getLogger(__name__)
+
 
 def subjects(request):
     context = {
@@ -21,18 +25,24 @@ def subjects(request):
 
 def subject_add(request):
     if request.method == 'POST':
-        form = SubjectAddForm(request.POST, request.FILES, user=request.user)
-        if form.is_valid():
-            form.save()
+        study_subject_form = StudySubjectAddForm(request.POST, request.FILES, prefix="study_subject", user=request.user)
+
+        subject_form = SubjectAddForm(request.POST, request.FILES, prefix="subject")
+        if study_subject_form.is_valid() and subject_form.is_valid():
+            subject = subject_form.save()
+            study_subject_form.instance.subject_id = subject.id
+            study_subject_form.save()
             messages.add_message(request, messages.SUCCESS, 'Subject created')
-            return redirect('web.views.subject_edit', id=form.instance.id)
+            return redirect('web.views.subject_edit', id=study_subject_form.instance.id)
         else:
             messages.add_message(request, messages.ERROR, 'Invalid data. Please fix data and try again.')
 
     else:
-        form = SubjectAddForm(user=request.user)
+        study_subject_form = StudySubjectAddForm(user=request.user, prefix="study_subject")
+        subject_form = SubjectAddForm(prefix="subject")
 
-    return wrap_response(request, 'subjects/add.html', {'form': form})
+    return wrap_response(request, 'subjects/add.html',
+                         {'study_subject_form': study_subject_form, 'subject_form': subject_form})
 
 
 def subject_no_visits(request):
@@ -50,45 +60,53 @@ def subject_require_contact(request):
 
 
 def subject_edit(request, id):
-    the_subject = get_object_or_404(Subject, id=id)
-    contact_attempts = the_subject.contactattempt_set.order_by('-datetime_when').all()
-    was_dead = the_subject.dead
-    was_resigned = the_subject.resigned
+    study_subject = get_object_or_404(StudySubject, id=id)
+    contact_attempts = study_subject.contactattempt_set.order_by('-datetime_when').all()
+    was_dead = study_subject.subject.dead
+    was_resigned = study_subject.resigned
     if request.method == 'POST':
-        form = SubjectEditForm(request.POST, request.FILES, instance=the_subject, was_dead=was_dead,
-                               was_resigned=was_resigned)
-        if form.is_valid():
-            form.save()
+        study_subject_form = StudySubjectEditForm(request.POST, request.FILES, instance=study_subject,
+                                                  was_resigned=was_resigned, prefix="study_subject"
+                                                  )
+        subject_form = SubjectEditForm(request.POST, request.FILES, instance=study_subject.subject,
+                                       was_dead=was_dead, prefix="subject"
+                                       )
+        if study_subject_form.is_valid() and subject_form.is_valid():
+            study_subject_form.save()
+            subject_form.save()
             # check if subject was marked as dead or resigned
-            if form.cleaned_data['dead'] and not was_dead:
-                the_subject.mark_as_dead()
-            if form.cleaned_data['resigned'] and not was_resigned:
-                the_subject.mark_as_resigned()
+            if subject_form.cleaned_data['dead'] and not was_dead:
+                study_subject.subject.mark_as_dead()
+            if study_subject_form.cleaned_data['resigned'] and not was_resigned:
+                study_subject.mark_as_resigned()
             messages.success(request, "Modifications saved")
             if '_continue' in request.POST:
-                return redirect('web.views.subject_edit', id=the_subject.id)
+                return redirect('web.views.subject_edit', id=study_subject.id)
             return redirect('web.views.subjects')
         else:
             messages.add_message(request, messages.ERROR, 'Invalid data. Please fix data and try again.')
     else:
-        form = SubjectEditForm(instance=the_subject, was_dead=was_dead, was_resigned=was_resigned)
+        study_subject_form = StudySubjectEditForm(instance=study_subject, was_resigned=was_resigned,
+                                                  prefix="study_subject")
+        subject_form = SubjectEditForm(instance=study_subject.subject, was_dead=was_dead, prefix="subject")
 
     languages = []
-    if the_subject.default_written_communication_language:
-        languages.append(the_subject.default_written_communication_language)
-    languages.extend(the_subject.languages.all())
+    if study_subject.subject.default_written_communication_language:
+        languages.append(study_subject.subject.default_written_communication_language)
+    languages.extend(study_subject.subject.languages.all())
 
     return wrap_response(request, 'subjects/edit.html', {
-        'form': form,
-        'subject': the_subject,
+        'study_subject_form': study_subject_form,
+        'subject_form': subject_form,
+        'study_subject': study_subject,
         'contact_attempts': contact_attempts,
         'mail_templates': MailTemplate.get_subject_mail_templates(languages)
     })
 
 
 def subject_visit_details(request, id):
-    subject_to_be_viewed = get_object_or_404(Subject, id=id)
-    visits = subject_to_be_viewed.visit_set.order_by("-visit_number").all()
+    study_subject_to_be_viewed = get_object_or_404(StudySubject, id=id)
+    visits = study_subject_to_be_viewed.visit_set.order_by("-visit_number").all()
     visits_data = []
     allow_add_visit = True
     for visit in visits:
diff --git a/smash/web/views/visit.py b/smash/web/views/visit.py
index b4f11304a30f1d2417424c1779f98ff5682bac45..2dd081106633856fa109d72fdb9db7f7ee57a2d6 100644
--- a/smash/web/views/visit.py
+++ b/smash/web/views/visit.py
@@ -5,8 +5,8 @@ from notifications import get_active_visits_with_missing_appointments, get_unfin
     get_approaching_visits_without_appointments, get_approaching_visits_for_mail_contact, get_exceeded_visits, \
     waiting_for_appointment
 from . import wrap_response
-from ..forms import VisitDetailForm, SubjectDetailForm, VisitAddForm
-from ..models import Visit, Appointment, Subject, MailTemplate
+from ..forms import VisitDetailForm, StudySubjectDetailForm, VisitAddForm, SubjectDetailForm
+from ..models import Visit, Appointment, StudySubject, MailTemplate
 
 
 def visits(request):
@@ -51,7 +51,7 @@ def visit_details(request, id):
 
     visit_finished = displayed_visit.is_finished
     visit_id = displayed_visit.id
-    displayed_subject = displayed_visit.subject
+    study_subject = displayed_visit.subject
     list_of_appointments = displayed_visit.appointment_set.all()
 
     can_finish = not waiting_for_appointment(displayed_visit)
@@ -60,15 +60,17 @@ def visit_details(request, id):
         if appointment.status == Appointment.APPOINTMENT_STATUS_SCHEDULED:
             can_finish = False
 
-    subject_form = SubjectDetailForm(instance=displayed_subject)
+    study_subject_form = StudySubjectDetailForm(instance=study_subject)
+    subject_form = SubjectDetailForm(instance=study_subject.subject)
     languages = []
-    if displayed_subject.default_written_communication_language:
-        languages.append(displayed_subject.default_written_communication_language)
-    languages.extend(displayed_subject.languages.all())
+    if study_subject.subject.default_written_communication_language:
+        languages.append(study_subject.subject.default_written_communication_language)
+    languages.extend(study_subject.subject.languages.all())
 
     return wrap_response(request, 'visits/details.html', {
-        'vform': visit_form,
-        'sform': subject_form,
+        'visit_form': visit_form,
+        'study_subject_form': study_subject_form,
+        'subject_form': subject_form,
         'loApp': list_of_appointments,
         'visFinished': visit_finished,
         'canFinish': can_finish,
@@ -92,7 +94,7 @@ def visit_add(request, subject_id=-1):
             visit = form.save()
             return redirect('web.views.visit_details', visit.id)
     else:
-        subjects = Subject.objects.filter(id=subject_id)
+        subjects = StudySubject.objects.filter(id=subject_id)
         subject = None
         if len(subjects) > 0:
             subject = subjects[0]