diff --git a/smash/web/api_views/subject.py b/smash/web/api_views/subject.py
index 589d19d633efa14f693aff4fbe624ec80c55c1b2..6c9bdcbf30453e4c385bf59da815289ae78c0b08 100644
--- a/smash/web/api_views/subject.py
+++ b/smash/web/api_views/subject.py
@@ -10,9 +10,10 @@ from web.api_views.serialization_utils import bool_to_yes_no, flying_team_to_str
 from web.models import StudySubject, Visit, Appointment, Subject, SubjectColumns, StudyColumns, Study, ContactAttempt
 from web.models.constants import SUBJECT_TYPE_CHOICES, GLOBAL_STUDY_ID
 from web.models.study_subject_list import SUBJECT_LIST_GENERIC, SUBJECT_LIST_NO_VISIT, SUBJECT_LIST_REQUIRE_CONTACT, \
-    StudySubjectList
+    StudySubjectList, SUBJECT_LIST_VOUCHER_EXPIRY
 from web.views import e500_error
-from web.views.notifications import get_subjects_with_no_visit, get_subjects_with_reminder, get_today_midnight_date
+from web.views.notifications import get_subjects_with_no_visit, get_subjects_with_reminder, get_today_midnight_date, \
+    get_subjects_with_almost_expired_vouchers
 
 logger = logging.getLogger(__name__)
 
@@ -89,6 +90,8 @@ def get_subjects(request, type):
         return get_subjects_with_no_visit(request.user)
     elif type == SUBJECT_LIST_REQUIRE_CONTACT:
         return get_subjects_with_reminder(request.user)
+    elif type == SUBJECT_LIST_VOUCHER_EXPIRY:
+        return get_subjects_with_almost_expired_vouchers(request.user)
     else:
         raise TypeError("Unknown query type: " + type)
 
diff --git a/smash/web/migrations/0102_studynotificationparameters_subject_voucher_expiry_visible.py b/smash/web/migrations/0102_studynotificationparameters_subject_voucher_expiry_visible.py
new file mode 100644
index 0000000000000000000000000000000000000000..df7f4833a1e947d2240708c52e8229396ffc09d3
--- /dev/null
+++ b/smash/web/migrations/0102_studynotificationparameters_subject_voucher_expiry_visible.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2017-12-14 12:55
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0101_auto_20171214_1047'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='studynotificationparameters',
+            name='subject_voucher_expiry_visible',
+            field=models.BooleanField(default=False, verbose_name=b'subject vouchers almost expired'),
+        ),
+    ]
diff --git a/smash/web/models/notification_columns.py b/smash/web/models/notification_columns.py
index aa1141734ad6b861dd3780bc39f923533c19c520..4bfeb00a4301fefe4b6a916cd5aedde8d765d74a 100644
--- a/smash/web/models/notification_columns.py
+++ b/smash/web/models/notification_columns.py
@@ -31,6 +31,11 @@ class StudyNotificationParameters(models.Model):
         verbose_name='subject without visit',
     )
 
+    subject_voucher_expiry_visible = models.BooleanField(
+        default=False,
+        verbose_name='subject vouchers almost expired',
+    )
+
     unfinished_visits_visible = models.BooleanField(
         default=True,
         verbose_name='unfinished visits',
diff --git a/smash/web/models/study_subject_list.py b/smash/web/models/study_subject_list.py
index cd2f5bbbbfff4142032e0cd68b9624b53e0f7668..de31e3cf04711d7909c80f56019597ef59605cb3 100644
--- a/smash/web/models/study_subject_list.py
+++ b/smash/web/models/study_subject_list.py
@@ -6,11 +6,13 @@ from web.models import Study, SubjectColumns, StudyColumns
 SUBJECT_LIST_GENERIC = "GENERIC"
 SUBJECT_LIST_NO_VISIT = "NO_VISIT"
 SUBJECT_LIST_REQUIRE_CONTACT = "REQUIRE_CONTACT"
+SUBJECT_LIST_VOUCHER_EXPIRY = "VOUCHER_EXPIRY"
 
 SUBJECT_LIST_CHOICES = {
     SUBJECT_LIST_GENERIC: 'Generic',
     SUBJECT_LIST_NO_VISIT: 'Subjects without visit',
     SUBJECT_LIST_REQUIRE_CONTACT: 'Subjects required contact',
+    SUBJECT_LIST_VOUCHER_EXPIRY: 'Subject with vouchers to be expired soon'
 }
 
 
diff --git a/smash/web/tests/api_views/test_subject.py b/smash/web/tests/api_views/test_subject.py
index 3b4ad50d6f1af4e47c121b1ce4e78f9e7c1a487b..4276b7346901ff26e972498352260bfb8d169f43 100644
--- a/smash/web/tests/api_views/test_subject.py
+++ b/smash/web/tests/api_views/test_subject.py
@@ -9,7 +9,7 @@ from web.api_views.subject import get_subjects_order, get_subjects_filtered, ser
 from web.models import StudySubject, Appointment, Study, Worker
 from web.models.constants import GLOBAL_STUDY_ID, SUBJECT_TYPE_CHOICES_PATIENT, SUBJECT_TYPE_CHOICES_CONTROL
 from web.models.study_subject_list import SUBJECT_LIST_GENERIC, SUBJECT_LIST_NO_VISIT, SUBJECT_LIST_REQUIRE_CONTACT, \
-    StudySubjectList
+    StudySubjectList, SUBJECT_LIST_VOUCHER_EXPIRY
 from web.tests import LoggedInWithWorkerTestCase
 from web.tests.functions import create_study_subject, create_get_suffix, create_visit, \
     create_appointment, create_empty_study_columns, create_contact_attempt, create_flying_team, create_worker
@@ -104,6 +104,10 @@ class TestSubjectApi(LoggedInWithWorkerTestCase):
         response = self.client.get(reverse('web.api.subjects', kwargs={'type': SUBJECT_LIST_GENERIC}))
         self.assertEqual(response.status_code, 200)
 
+    def test_subjects_voucher_almost_expired(self):
+        response = self.client.get(reverse('web.api.subjects', kwargs={'type': SUBJECT_LIST_VOUCHER_EXPIRY}))
+        self.assertEqual(response.status_code, 200)
+
     def test_subjects_no_visit(self):
         response = self.client.get(reverse('web.api.subjects', kwargs={'type': SUBJECT_LIST_NO_VISIT}))
         self.assertEqual(response.status_code, 200)
diff --git a/smash/web/tests/functions.py b/smash/web/tests/functions.py
index 49888524124b9842bdf68786f110b3037775215b..eb9e87dd7ddca95144ef58a1337b67f141417dda 100644
--- a/smash/web/tests/functions.py
+++ b/smash/web/tests/functions.py
@@ -102,6 +102,23 @@ def create_empty_notification_parameters():
         subject_require_contact_visible=False,
         missing_redcap_subject_visible=False,
         inconsistent_redcap_subject_visible=False,
+        subject_voucher_expiry_visible=False,
+    )
+
+
+def create_full_notification_parameters():
+    return StudyNotificationParameters.objects.create(
+        exceeded_visits_visible=True,
+        unfinished_visits_visible=True,
+        approaching_visits_without_appointments_visible=True,
+        unfinished_appointments_visible=True,
+        visits_with_missing_appointments_visible=True,
+        subject_no_visits_visible=True,
+        approaching_visits_for_mail_contact_visible=True,
+        subject_require_contact_visible=True,
+        missing_redcap_subject_visible=True,
+        inconsistent_redcap_subject_visible=True,
+        subject_voucher_expiry_visible=True,
     )
 
 
diff --git a/smash/web/tests/view/test_notifications.py b/smash/web/tests/view/test_notifications.py
index 1be70d94ce1c722e4c45f68a55de6aecb2eb8605..de8c59457b9d5a26106e4dafccf4c99fc899725f 100644
--- a/smash/web/tests/view/test_notifications.py
+++ b/smash/web/tests/view/test_notifications.py
@@ -7,7 +7,8 @@ from web.models import Appointment, Location, AppointmentTypeLink, Study, Visit
 from web.models.constants import GLOBAL_STUDY_ID, VOUCHER_STATUS_USED
 from web.tests import LoggedInTestCase
 from web.tests.functions import create_appointment, create_location, create_worker, create_appointment_type, \
-    create_empty_notification_parameters, create_study_subject, create_visit, create_voucher
+    create_empty_notification_parameters, create_study_subject, create_visit, create_voucher, create_contact_attempt, \
+    create_full_notification_parameters
 from web.views.notifications import \
     get_approaching_visits_for_mail_contact, \
     get_approaching_visits_for_mail_contact_count, \
@@ -23,7 +24,7 @@ from web.views.notifications import \
     get_today_midnight_date, \
     get_unfinished_appointments, \
     get_unfinished_appointments_count, \
-    get_unfinished_visits, get_exceeded_visits
+    get_unfinished_visits, get_exceeded_visits, get_subject_voucher_expiry_notifications_count
 
 logger = logging.getLogger(__name__)
 
@@ -57,7 +58,6 @@ class NotificationViewTests(LoggedInTestCase):
         appointment.status = Appointment.APPOINTMENT_STATUS_FINISHED
         appointment.save()
         notification = get_exceeded_visit_notifications_count(self.user)
-        logger.debug(get_exceeded_visits(self.user).query)
         self.assertEquals(1, notification.count)
 
     def test_get_exceeded_visit_notifications_count_2(self):
@@ -127,6 +127,17 @@ class NotificationViewTests(LoggedInTestCase):
         self.assertEquals(0, result[0])
         self.assertEquals(0, len(result[1]))
 
+    def test_get_notifications_with_full_study_notification(self):
+        study = Study.objects.filter(id=GLOBAL_STUDY_ID)[0]
+        study.notification_parameters = create_full_notification_parameters()
+        study.save()
+
+        create_worker(self.user)
+        result = get_notifications(self.user)
+
+        self.assertEquals(0, result[0])
+        self.assertTrue(len(result[1]) > 0)
+
     def test_get_visits_without_appointments_count_2(self):
         appointment_type = create_appointment_type()
         original_notification = get_visits_without_appointments_count(self.user)
@@ -493,3 +504,34 @@ class NotificationViewTests(LoggedInTestCase):
             self.fail("Exception expected")
         except TypeError:
             pass
+
+    def test_get_subjects_with_expiry_vouchers(self):
+        original_notification = get_subject_voucher_expiry_notifications_count(self.user)
+        voucher = create_voucher()
+        voucher.expiry_date = get_today_midnight_date()
+        voucher.save()
+
+        notification = get_subject_voucher_expiry_notifications_count(self.user)
+        self.assertEquals(original_notification.count + 1, notification.count)
+
+        voucher.expiry_date = get_today_midnight_date() + datetime.timedelta(days=365)
+        voucher.save()
+
+        notification = get_subject_voucher_expiry_notifications_count(self.user)
+        self.assertEquals(original_notification.count, notification.count)
+
+    def test_get_subjects_with_expiry_vouchers_and_contact_attempt(self):
+        original_notification = get_subject_voucher_expiry_notifications_count(self.user)
+        voucher = create_voucher()
+        voucher.expiry_date = get_today_midnight_date()
+        voucher.save()
+        contact_attempt = create_contact_attempt(voucher.study_subject)
+
+        notification = get_subject_voucher_expiry_notifications_count(self.user)
+        self.assertEquals(original_notification.count, notification.count)
+
+        contact_attempt.datetime_when = "2011-11-11"
+        contact_attempt.save()
+
+        notification = get_subject_voucher_expiry_notifications_count(self.user)
+        self.assertEquals(original_notification.count + 1, notification.count)
diff --git a/smash/web/tests/view/test_subjects.py b/smash/web/tests/view/test_subjects.py
index c84a8d6e126f08d90009851e721a4486d3e5cd4c..ac0d9beae241b0af56d2ff2dfadb5e894727c01b 100644
--- a/smash/web/tests/view/test_subjects.py
+++ b/smash/web/tests/view/test_subjects.py
@@ -219,6 +219,10 @@ class SubjectsViewTests(LoggedInWithWorkerTestCase):
         response = self.client.get(reverse('web.views.subject_no_visits'))
         self.assertEqual(response.status_code, 200)
 
+    def test_render_subjects_voucher_expiry(self):
+        response = self.client.get(reverse('web.views.subject_voucher_expiry'))
+        self.assertEqual(response.status_code, 200)
+
     def test_render_subjects_require_contact(self):
         self.study_subject.datetime_contact_reminder = get_today_midnight_date() + datetime.timedelta(days=-1)
 
diff --git a/smash/web/urls.py b/smash/web/urls.py
index f5da2cb56dd161f3a3f82f2e37d366d25ca9fef4..baa812987f233ae90767d6f5c139e7b33c2a49ff 100644
--- a/smash/web/urls.py
+++ b/smash/web/urls.py
@@ -73,6 +73,8 @@ urlpatterns = [
     url(r'^subjects$', views.subject.subjects, name='web.views.subjects'),
     url(r'^subjects/no_visit$', views.subject.subject_no_visits, name='web.views.subject_no_visits'),
     url(r'^subjects/require_contact$', views.subject.subject_require_contact, name='web.views.subject_require_contact'),
+    url(r'^subjects/voucher_expiry', views.subject.subject_voucher_expiry, name='web.views.subject_voucher_expiry'),
+
     url(r'^subjects/add$', views.subject.subject_add, name='web.views.subject_add'),
     url(r'^subjects/subject_visit_details/(?P<id>\d+)$', views.subject.subject_visit_details,
         name='web.views.subject_visit_details'),
diff --git a/smash/web/views/notifications.py b/smash/web/views/notifications.py
index 5a42783a6a7233b6b0fcf22b66ec0f8e083301a2..58e305a63de108a643a78647bfa5fd122dfb4de3 100644
--- a/smash/web/views/notifications.py
+++ b/smash/web/views/notifications.py
@@ -1,13 +1,15 @@
 # coding=utf-8
 import datetime
+import logging
 
 from django.contrib.auth.models import User, AnonymousUser
-from django.db.models import Count, Case, When, Q, F
+from django.db.models import Count, Case, When, Q, F, Max
 from django.utils import timezone
 
-from web.models import Study
+from web.models import Study, Worker, StudySubject, Visit, Appointment, Location, MissingSubject, InconsistentSubject
 from web.models.constants import GLOBAL_STUDY_ID, VOUCHER_STATUS_NEW
-from ..models import Worker, StudySubject, Visit, Appointment, Location, MissingSubject, InconsistentSubject
+
+logger = logging.getLogger(__name__)
 
 
 class NotificationCount(object):
@@ -68,6 +70,15 @@ def get_subject_with_no_visit_notifications_count(user):
     return notification
 
 
+def get_subject_voucher_expiry_notifications_count(user):
+    notification = NotificationCount(
+        title="subject vouchers almost expired",
+        count=get_subjects_with_almost_expired_vouchers(user).count(),
+        style="fa fa-users text-aqua",
+        type='web.views.subject_voucher_expiry')
+    return notification
+
+
 def get_visits_without_appointments_count(user):
     notification = NotificationCount(
         title="unfinished visits",
@@ -130,6 +141,8 @@ def get_notifications(the_user):
             notifications.append(get_visits_with_missing_appointments_count(worker))
         if study.notification_parameters.subject_no_visits_visible:
             notifications.append(get_subject_with_no_visit_notifications_count(worker))
+        if study.notification_parameters.subject_voucher_expiry_visible:
+            notifications.append(get_subject_voucher_expiry_notifications_count(worker))
         if study.notification_parameters.approaching_visits_for_mail_contact_visible:
             notifications.append(get_approaching_visits_for_mail_contact_count(worker))
         if study.notification_parameters.subject_require_contact_visible:
@@ -157,6 +170,19 @@ def get_subjects_with_no_visit(user):
     return result
 
 
+def get_subjects_with_almost_expired_vouchers(user):
+    notification_min_date = get_today_midnight_date() + datetime.timedelta(days=14)
+    contact_attempt_min_date = get_today_midnight_date() - datetime.timedelta(days=14)
+    result = StudySubject.objects.filter(
+        subject__dead=False,
+        resigned=False,
+        default_location__in=get_filter_locations(user),
+    ).annotate(last_contact=Max(Case(When(contactattempt__success=True, then="contactattempt__datetime_when")))).filter(
+        Q(vouchers__status=VOUCHER_STATUS_NEW) & Q(vouchers__expiry_date__lte=notification_min_date)).filter(
+        Q(last_contact__lt=contact_attempt_min_date) | Q(last_contact__isnull=True))
+    return result
+
+
 def get_subjects_with_reminder(user):
     tomorrow = datetime.datetime.now() + datetime.timedelta(hours=1)
 
diff --git a/smash/web/views/subject.py b/smash/web/views/subject.py
index f1c9566a8be16acd252dc146bfcf3c06be5165b9..d891d0d65be6a3c07243f40d4704ee0c071d2103 100644
--- a/smash/web/views/subject.py
+++ b/smash/web/views/subject.py
@@ -5,11 +5,12 @@ from django.contrib import messages
 from django.contrib.auth.decorators import login_required
 from django.shortcuts import redirect, get_object_or_404
 
-from ..models.study_subject_list import SUBJECT_LIST_GENERIC, SUBJECT_LIST_NO_VISIT, SUBJECT_LIST_REQUIRE_CONTACT
 from . import wrap_response
 from ..forms import VisitDetailForm, SubjectAddForm, SubjectEditForm, StudySubjectAddForm, StudySubjectEditForm
 from ..models import StudySubject, MailTemplate, Worker, Study
 from ..models.constants import GLOBAL_STUDY_ID
+from ..models.study_subject_list import SUBJECT_LIST_GENERIC, SUBJECT_LIST_NO_VISIT, SUBJECT_LIST_REQUIRE_CONTACT, \
+    SUBJECT_LIST_VOUCHER_EXPIRY
 
 logger = logging.getLogger(__name__)
 
@@ -54,6 +55,13 @@ def subject_no_visits(request):
     return wrap_response(request, 'subjects/index.html', context)
 
 
+def subject_voucher_expiry(request):
+    context = {
+        'list_type': SUBJECT_LIST_VOUCHER_EXPIRY,
+    }
+    return wrap_response(request, 'subjects/index.html', context)
+
+
 def subject_require_contact(request):
     context = {
         'list_type': SUBJECT_LIST_REQUIRE_CONTACT,