diff --git a/smash/web/algorithm/__init__.py b/smash/web/algorithm/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..defa4efb79e533df509ea627c72f61a3e4e001b1
--- /dev/null
+++ b/smash/web/algorithm/__init__.py
@@ -0,0 +1,4 @@
+from luhn_algorithm import LuhnAlgorithm
+from verhoeff_alogirthm import VerhoeffAlgorithm
+
+__all__ = [VerhoeffAlgorithm, LuhnAlgorithm]
diff --git a/smash/web/algorithm/luhn_algorithm.py b/smash/web/algorithm/luhn_algorithm.py
new file mode 100644
index 0000000000000000000000000000000000000000..c752bc333716c2b7e4081bae0875cdd2911ee02d
--- /dev/null
+++ b/smash/web/algorithm/luhn_algorithm.py
@@ -0,0 +1,21 @@
+class LuhnAlgorithm(object):
+    def __init__(self):
+        pass
+
+    @staticmethod
+    def luhn_checksum(card_number):
+        def digits_of(n):
+            return [int(d) for d in str(n)]
+
+        digits = digits_of(card_number)
+        odd_digits = digits[-1::-2]
+        even_digits = digits[-2::-2]
+        checksum = 0
+        checksum += sum(odd_digits)
+        for d in even_digits:
+            checksum += sum(digits_of(d * 2))
+        return checksum % 10
+
+    @staticmethod
+    def is_luhn_valid(card_number):
+        return LuhnAlgorithm.luhn_checksum(card_number) == 0
diff --git a/smash/web/algorithm/verhoeff_alogirthm.py b/smash/web/algorithm/verhoeff_alogirthm.py
new file mode 100644
index 0000000000000000000000000000000000000000..0b9dc9ffcf0b5026bfa95845efc71b34fd8b03d4
--- /dev/null
+++ b/smash/web/algorithm/verhoeff_alogirthm.py
@@ -0,0 +1,45 @@
+verhoeff_multiplication_table = (
+    (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
+    (1, 2, 3, 4, 0, 6, 7, 8, 9, 5),
+    (2, 3, 4, 0, 1, 7, 8, 9, 5, 6),
+    (3, 4, 0, 1, 2, 8, 9, 5, 6, 7),
+    (4, 0, 1, 2, 3, 9, 5, 6, 7, 8),
+    (5, 9, 8, 7, 6, 0, 4, 3, 2, 1),
+    (6, 5, 9, 8, 7, 1, 0, 4, 3, 2),
+    (7, 6, 5, 9, 8, 2, 1, 0, 4, 3),
+    (8, 7, 6, 5, 9, 3, 2, 1, 0, 4),
+    (9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
+verhoeff_permutation_table = (
+    (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
+    (1, 5, 7, 6, 2, 8, 3, 0, 9, 4),
+    (5, 8, 0, 3, 7, 9, 6, 1, 4, 2),
+    (8, 9, 1, 6, 0, 4, 3, 5, 2, 7),
+    (9, 4, 5, 3, 1, 2, 6, 8, 7, 0),
+    (4, 2, 8, 6, 5, 7, 3, 9, 0, 1),
+    (2, 7, 9, 3, 8, 0, 6, 4, 1, 5),
+    (7, 0, 4, 6, 9, 1, 3, 2, 5, 8))
+
+
+class VerhoeffAlgorithm(object):
+    def __init__(self):
+        pass
+
+    @staticmethod
+    def verhoeff_checksum(number):
+        """Calculate the Verhoeff checksum over the provided number. The checksum
+        is returned as an int. Valid numbers should have a checksum of 0."""
+        # transform number list
+        number = tuple(int(n) for n in reversed(str(number)))
+        # calculate checksum
+        check = 0
+        for i, n in enumerate(number):
+            check = verhoeff_multiplication_table[check][verhoeff_permutation_table[i % 8][n]]
+        return check
+
+    @staticmethod
+    def is_valid_verhoeff(number):
+        return VerhoeffAlgorithm.verhoeff_checksum(number) == 0
+
+    @staticmethod
+    def calculate_verhoeff_check_sum(number):
+        return str(verhoeff_multiplication_table[VerhoeffAlgorithm.verhoeff_checksum(str(number) + '0')].index(0))
diff --git a/smash/web/forms/__init__.py b/smash/web/forms/__init__.py
index 41432b74e56c6ac250f4f182d9654a39f6f7f772..23d44c9490bb74edddc5ec5ad5d436dffd829ae2 100644
--- a/smash/web/forms/__init__.py
+++ b/smash/web/forms/__init__.py
@@ -4,8 +4,10 @@ from forms import WorkerAddForm, \
     AvailabilityEditForm, HolidayAddForm
 from study_subject_forms import StudySubjectAddForm, StudySubjectDetailForm, StudySubjectEditForm
 from subject_forms import SubjectAddForm, SubjectEditForm, SubjectDetailForm
+from voucher_forms import VoucherTypeForm, VoucherTypePriceForm, VoucherForm
 
 __all__ = [StudySubjectAddForm, StudySubjectDetailForm, StudySubjectEditForm, WorkerAddForm, WorkerEditForm,
            AppointmentDetailForm, AppointmentEditForm, AppointmentAddForm, VisitDetailForm, VisitAddForm,
            ContactAttemptForm, ContactAttemptEditForm, KitRequestForm, StatisticsForm, AvailabilityAddForm,
-           AvailabilityEditForm, HolidayAddForm, SubjectAddForm, SubjectEditForm, SubjectDetailForm]
+           AvailabilityEditForm, HolidayAddForm, SubjectAddForm, SubjectEditForm, SubjectDetailForm, VoucherTypeForm,
+           VoucherTypePriceForm, VoucherForm]
diff --git a/smash/web/forms/forms.py b/smash/web/forms/forms.py
index 570db43352dd9935a0ec0f9dc7871d6aaae6c427..e59536a3c6d8e6b7866d6a593f80ffcbc3bed321 100644
--- a/smash/web/forms/forms.py
+++ b/smash/web/forms/forms.py
@@ -7,7 +7,7 @@ from django.forms import ModelForm, Form
 from django.utils.dates import MONTHS
 
 from web.models import StudySubject, Worker, Appointment, Visit, AppointmentType, ContactAttempt, AppointmentTypeLink, \
-    Availability, Holiday, VoucherType, VoucherTypePrice
+    Availability, Holiday
 from web.models.constants import SUBJECT_TYPE_CHOICES
 from web.views.notifications import get_filter_locations
 
@@ -387,20 +387,3 @@ class HolidayAddForm(ModelForm):
             validate_availability_conflict(self, self.cleaned_data, availability)
 
 
-class VoucherTypeForm(ModelForm):
-    class Meta:
-        model = VoucherType
-        exclude = ['study']
-
-
-class VoucherTypePriceForm(ModelForm):
-    start_date = forms.DateField(label="Start date",
-                                 widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d")
-                                 )
-    end_date = forms.DateField(label="End date",
-                               widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d")
-                               )
-
-    class Meta:
-        model = VoucherTypePrice
-        exclude = ['voucher_type']
diff --git a/smash/web/forms/subject_forms.py b/smash/web/forms/subject_forms.py
index cc717842d2065b99fb9e622ebc63ae0ec17fe785..05fe533ea79251c871e1a6c9b66454384758e437 100644
--- a/smash/web/forms/subject_forms.py
+++ b/smash/web/forms/subject_forms.py
@@ -3,6 +3,7 @@ import logging
 from django import forms
 from django.forms import ModelForm
 
+from web.algorithm import VerhoeffAlgorithm, LuhnAlgorithm
 from web.forms.forms import DATEPICKER_DATE_ATTRS
 from web.models import Subject
 from web.models.constants import COUNTRY_OTHER_ID
@@ -26,75 +27,14 @@ def is_valid_social_security_number(number):
             return False
         if not number.isdigit():
             return False
-        if not is_luhn_valid(number[:12]):
+        if not LuhnAlgorithm.is_luhn_valid(number[:12]):
             return False
-        if not is_valid_verhoeff(number[:11] + number[12]):
+        if not VerhoeffAlgorithm.is_valid_verhoeff(number[:11] + number[12]):
             return False
 
     return True
 
 
-def luhn_checksum(card_number):
-    def digits_of(n):
-        return [int(d) for d in str(n)]
-
-    digits = digits_of(card_number)
-    odd_digits = digits[-1::-2]
-    even_digits = digits[-2::-2]
-    checksum = 0
-    checksum += sum(odd_digits)
-    for d in even_digits:
-        checksum += sum(digits_of(d * 2))
-    return checksum % 10
-
-
-def is_luhn_valid(card_number):
-    return luhn_checksum(card_number) == 0
-
-
-verhoeff_multiplication_table = (
-    (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
-    (1, 2, 3, 4, 0, 6, 7, 8, 9, 5),
-    (2, 3, 4, 0, 1, 7, 8, 9, 5, 6),
-    (3, 4, 0, 1, 2, 8, 9, 5, 6, 7),
-    (4, 0, 1, 2, 3, 9, 5, 6, 7, 8),
-    (5, 9, 8, 7, 6, 0, 4, 3, 2, 1),
-    (6, 5, 9, 8, 7, 1, 0, 4, 3, 2),
-    (7, 6, 5, 9, 8, 2, 1, 0, 4, 3),
-    (8, 7, 6, 5, 9, 3, 2, 1, 0, 4),
-    (9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
-
-verhoeff_permutation_table = (
-    (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
-    (1, 5, 7, 6, 2, 8, 3, 0, 9, 4),
-    (5, 8, 0, 3, 7, 9, 6, 1, 4, 2),
-    (8, 9, 1, 6, 0, 4, 3, 5, 2, 7),
-    (9, 4, 5, 3, 1, 2, 6, 8, 7, 0),
-    (4, 2, 8, 6, 5, 7, 3, 9, 0, 1),
-    (2, 7, 9, 3, 8, 0, 6, 4, 1, 5),
-    (7, 0, 4, 6, 9, 1, 3, 2, 5, 8))
-
-
-def verhoeff_checksum(number):
-    """Calculate the Verhoeff checksum over the provided number. The checksum
-    is returned as an int. Valid numbers should have a checksum of 0."""
-    # transform number list
-    number = tuple(int(n) for n in reversed(str(number)))
-    # calculate checksum
-    check = 0
-    for i, n in enumerate(number):
-        check = verhoeff_multiplication_table[check][verhoeff_permutation_table[i % 8][n]]
-    return check
-
-
-def is_valid_verhoeff(number):
-    return verhoeff_checksum(number) == 0
-
-
-def calculate_verhoeff_check_sum(number):
-    return str(verhoeff_multiplication_table[verhoeff_checksum(str(number) + '0')].index(0))
-
-
 FIELD_ORDER = ["first_name", "last_name", "sex", "date_born", "social_security_number",
                "default_written_communication_language", "languages", "phone_number", "phone_number_2",
                "phone_number_3", "address", "city", "postal_code", "country"]
diff --git a/smash/web/forms/voucher_forms.py b/smash/web/forms/voucher_forms.py
new file mode 100644
index 0000000000000000000000000000000000000000..68de4581885be709aca5cc71916a63c7d073ec63
--- /dev/null
+++ b/smash/web/forms/voucher_forms.py
@@ -0,0 +1,77 @@
+import datetime
+import logging
+
+from django import forms
+from django.forms import ModelForm
+from django.utils import timezone
+
+from web.algorithm import VerhoeffAlgorithm
+from web.forms.forms import DATEPICKER_DATE_ATTRS
+from web.models import VoucherType, VoucherTypePrice, Voucher
+from web.models.constants import VOUCHER_STATUS_NEW, VOUCHER_STATUS_USED
+
+logger = logging.getLogger(__name__)
+
+
+class VoucherTypeForm(ModelForm):
+    class Meta:
+        model = VoucherType
+        exclude = ['study']
+
+
+class VoucherTypePriceForm(ModelForm):
+    start_date = forms.DateField(label="Start date",
+                                 widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d")
+                                 )
+    end_date = forms.DateField(label="End date",
+                               widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d")
+                               )
+
+    class Meta:
+        model = VoucherTypePrice
+        exclude = ['voucher_type']
+
+
+class VoucherForm(ModelForm):
+    class Meta:
+        model = Voucher
+        fields = '__all__'
+
+    def __init__(self, *args, **kwargs):
+        super(VoucherForm, self).__init__(*args, **kwargs)
+        self.fields['number'].widget.attrs['readonly'] = True
+        self.fields['number'].required = False
+
+        self.fields['issue_date'].widget.attrs['readonly'] = True
+        self.fields['issue_date'].required = False
+        self.fields['expiry_date'].widget.attrs['readonly'] = True
+        self.fields['expiry_date'].required = False
+        self.fields['use_date'].widget.attrs['readonly'] = True
+        instance = getattr(self, 'instance', None)
+        if instance and instance.pk:
+            self.fields['voucher_type'].widget.attrs['readonly'] = True
+            if instance.status != VOUCHER_STATUS_NEW:
+                self.fields['status'].widget.attrs['readonly'] = True
+                self.fields['feedback'].widget.attrs['readonly'] = True
+                self.fields['usage_partner'].widget.attrs['readonly'] = True
+
+    def clean(self):
+        if self.cleaned_data["status"] == VOUCHER_STATUS_USED and not self.cleaned_data["usage_partner"]:
+            self.add_error('usage_partner', "Partner must be defined for used voucher")
+        if self.cleaned_data["status"] != VOUCHER_STATUS_USED and self.cleaned_data["usage_partner"]:
+            self.add_error('status', "Status must be used for voucher with defined partner")
+
+    def save(self, commit=True):
+        instance = super(VoucherForm, self).save(commit=False)
+        if not instance.id:
+            instance.issue_date = timezone.now()
+            instance.expiry_date = instance.issue_date + datetime.timedelta(days=92)
+            max_id = str(0).zfill(5)
+            if Voucher.objects.all().count() > 0:
+                max_id = str(Voucher.objects.latest('id').id).zfill(5)
+            instance.number = max_id + VerhoeffAlgorithm.calculate_verhoeff_check_sum(max_id)
+        if instance.status == VOUCHER_STATUS_USED and not instance.use_date:
+            instance.use_date = timezone.now()
+
+        if commit:
+            instance.save()
diff --git a/smash/web/migrations/0091_auto_20171208_1312.py b/smash/web/migrations/0091_auto_20171208_1312.py
new file mode 100644
index 0000000000000000000000000000000000000000..3c823e288d5e639c074ca55b08041f45aa18d1c7
--- /dev/null
+++ b/smash/web/migrations/0091_auto_20171208_1312.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2017-12-08 13:12
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0090_vouchertype_vouchertypeprice'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='vouchertypeprice',
+            name='voucher_type',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='prices', to='web.VoucherType'),
+        ),
+    ]
diff --git a/smash/web/migrations/0092_voucher.py b/smash/web/migrations/0092_voucher.py
new file mode 100644
index 0000000000000000000000000000000000000000..963120ee80b966459eebaf0c9490d56b9ca37a85
--- /dev/null
+++ b/smash/web/migrations/0092_voucher.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2017-12-08 15:00
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0091_auto_20171208_1312'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Voucher',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('number', models.CharField(max_length=10, unique=True, verbose_name=b'Number')),
+                ('issue_date', models.DateField(verbose_name=b'Issue date')),
+                ('expiry_date', models.DateField(verbose_name=b'Expiry date')),
+                ('use_date', models.DateField(verbose_name=b'Use date')),
+                ('status', models.CharField(choices=[(b'NEW', b'New'), (b'USED', b'Used'), (b'EXPIRED', b'Expired')], default=b'NEW', max_length=20, verbose_name=b'Status')),
+                ('feedback', models.TextField(blank=True, max_length=2000, verbose_name=b'Feedback')),
+                ('study_subject', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to='web.StudySubject')),
+                ('usage_partner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='web.Worker')),
+                ('voucher_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='web.VoucherType')),
+            ],
+        ),
+    ]
diff --git a/smash/web/migrations/0093_auto_20171208_1508.py b/smash/web/migrations/0093_auto_20171208_1508.py
new file mode 100644
index 0000000000000000000000000000000000000000..839c2936a2f41311e6f79358abe979c4abe41b83
--- /dev/null
+++ b/smash/web/migrations/0093_auto_20171208_1508.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2017-12-08 15:08
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0092_voucher'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='voucher',
+            name='usage_partner',
+            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='web.Worker'),
+        ),
+    ]
diff --git a/smash/web/migrations/0094_auto_20171208_1508.py b/smash/web/migrations/0094_auto_20171208_1508.py
new file mode 100644
index 0000000000000000000000000000000000000000..5ca263649479e21e768968f07d8db7ba7d3d65ee
--- /dev/null
+++ b/smash/web/migrations/0094_auto_20171208_1508.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2017-12-08 15:08
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0093_auto_20171208_1508'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='voucher',
+            name='usage_partner',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='web.Worker'),
+        ),
+    ]
diff --git a/smash/web/migrations/0095_auto_20171208_1509.py b/smash/web/migrations/0095_auto_20171208_1509.py
new file mode 100644
index 0000000000000000000000000000000000000000..37b50905594f0b4d2e34c07991813bb36b5fe7a9
--- /dev/null
+++ b/smash/web/migrations/0095_auto_20171208_1509.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2017-12-08 15:09
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0094_auto_20171208_1508'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='voucher',
+            name='use_date',
+            field=models.DateField(null=True, verbose_name=b'Use date'),
+        ),
+    ]
diff --git a/smash/web/migrations/0096_auto_20171208_1509.py b/smash/web/migrations/0096_auto_20171208_1509.py
new file mode 100644
index 0000000000000000000000000000000000000000..b076d5c3f0bcb912bab2db36a94f67bc15746c85
--- /dev/null
+++ b/smash/web/migrations/0096_auto_20171208_1509.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2017-12-08 15:09
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0095_auto_20171208_1509'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='voucher',
+            name='use_date',
+            field=models.DateField(blank=True, null=True, verbose_name=b'Use date'),
+        ),
+    ]
diff --git a/smash/web/models/__init__.py b/smash/web/models/__init__.py
index 6b9eac7eed601cc8b85949cb752d87ecce2f2764..77a30db094dfd4b977b2ca164a0070b39ea1e8cc 100644
--- a/smash/web/models/__init__.py
+++ b/smash/web/models/__init__.py
@@ -27,6 +27,7 @@ from item import Item
 from language import Language
 from subject import Subject
 from study_subject import StudySubject
+from voucher import Voucher
 from study_subject_list import StudySubjectList
 from study_visit_list import StudyVisitList
 from appointment_list import AppointmentList
@@ -38,5 +39,5 @@ from inconsistent_subject import InconsistentSubject, InconsistentField
 __all__ = [Study, FlyingTeam, Appointment, AppointmentType, Availability, Holiday, Item, Language, Location, Room,
            Subject, StudySubject, StudySubjectList, SubjectColumns, StudyNotificationParameters,
            AppointmentList, AppointmentColumns, Visit, Worker, ContactAttempt, ConfigurationItem, MailTemplate,
-           AppointmentTypeLink, VoucherType, VoucherTypePrice,
+           AppointmentTypeLink, VoucherType, VoucherTypePrice, Voucher,
            MissingSubject, InconsistentSubject, InconsistentField, Country, StudyColumns, VisitColumns, StudyVisitList]
diff --git a/smash/web/models/constants.py b/smash/web/models/constants.py
index fe6ade3b9b0c61fb9df46206f7c427d0735157f9..57794ce9ed36fd7287d221e1b64add2bdfeab395 100644
--- a/smash/web/models/constants.py
+++ b/smash/web/models/constants.py
@@ -81,3 +81,12 @@ COUNTRY_AFGHANISTAN_ID = 2
 # id of the singleton Study,
 # TODO remove after allowing many studies per Smasch instance
 GLOBAL_STUDY_ID = 1
+
+VOUCHER_STATUS_NEW = "NEW"
+VOUCHER_STATUS_USED = "USED"
+VOUCHER_STATUS_EXPIRED = "EXPIRED"
+VOUCHER_STATUS_CHOICES = (
+    (VOUCHER_STATUS_NEW, 'New'),
+    (VOUCHER_STATUS_USED, 'Used'),
+    (VOUCHER_STATUS_EXPIRED, 'Expired'),
+)
diff --git a/smash/web/models/voucher.py b/smash/web/models/voucher.py
new file mode 100644
index 0000000000000000000000000000000000000000..f7cc8f15c50c5c84cec75c33483678f4abab4ba0
--- /dev/null
+++ b/smash/web/models/voucher.py
@@ -0,0 +1,58 @@
+# coding=utf-8
+
+from django.db import models
+
+from web.models import VoucherType, StudySubject, Worker
+from web.models.constants import VOUCHER_STATUS_CHOICES, VOUCHER_STATUS_NEW
+
+
+class Voucher(models.Model):
+    class Meta:
+        app_label = 'web'
+
+    number = models.CharField(
+        max_length=10,
+        verbose_name='Number',
+        blank=False,
+        null=False,
+        unique=True
+    )
+
+    issue_date = models.DateField(verbose_name='Issue date', null=False)
+    expiry_date = models.DateField(verbose_name='Expiry date', null=False)
+    use_date = models.DateField(verbose_name='Use date', null=True, blank=True)
+    voucher_type = models.ForeignKey(
+        VoucherType,
+        on_delete=models.CASCADE,
+        null=False,
+    )
+
+    study_subject = models.ForeignKey(
+        StudySubject,
+        on_delete=models.CASCADE,
+        null=False,
+        editable=False
+    )
+
+    status = models.CharField(max_length=20, choices=VOUCHER_STATUS_CHOICES,
+                              verbose_name='Status',
+                              default=VOUCHER_STATUS_NEW
+                              )
+
+    feedback = models.TextField(max_length=2000,
+                                blank=True,
+                                verbose_name='Feedback'
+                                )
+
+    usage_partner = models.ForeignKey(
+        Worker,
+        on_delete=models.CASCADE,
+        null=True,
+        blank=True
+    )
+
+    def __str__(self):
+        return "%s - %s %s" % (self.number, self.study_subject.subject.first_name, self.study_subject.subject.last_name)
+
+    def __unicode__(self):
+        return "%s - %s %s" % (self.number, self.study_subject.subject.first_name, self.study_subject.subject.last_name)
diff --git a/smash/web/templates/sidebar.html b/smash/web/templates/sidebar.html
index a8dd1d750c13fb5c824c11c40f9d9681bf535126..71c325a1cc768df50f5898b59b8e3e1b1aeefa6a 100644
--- a/smash/web/templates/sidebar.html
+++ b/smash/web/templates/sidebar.html
@@ -57,6 +57,14 @@
             <span>Export</span>
         </a>
     </li>
+
+    <li data-desc="vouchers">
+        <a href="{% url 'web.views.vouchers' %}">
+            <i class="fa fa-user-md"></i>
+            <span>Vouchers</span>
+        </a>
+    </li>
+
     <li data-desc="configuration" class="treeview">
         <a href="#">
             <i class="fa fa-wrench"></i> <span>Configuration</span>
diff --git a/smash/web/templates/vouchers/add.html b/smash/web/templates/vouchers/add.html
new file mode 100644
index 0000000000000000000000000000000000000000..994ab3cb9337086474d330f2b288d6a4aaa2bba5
--- /dev/null
+++ b/smash/web/templates/vouchers/add.html
@@ -0,0 +1,9 @@
+{% extends "vouchers/add_edit.html" %}
+
+{% block page_header %}New voucher{% endblock page_header %}
+
+{% block title %}{{ block.super }} - Add voucher{% endblock %}
+
+{% block form-title %}Enter voucher details{% endblock %}
+
+{% block save-button %}Add{% endblock %}
diff --git a/smash/web/templates/vouchers/add_edit.html b/smash/web/templates/vouchers/add_edit.html
new file mode 100644
index 0000000000000000000000000000000000000000..8e5e5dfbaf497bf4a88f70ded534fd2e8ef92a8f
--- /dev/null
+++ b/smash/web/templates/vouchers/add_edit.html
@@ -0,0 +1,77 @@
+{% extends "_base.html" %}
+{% load static %}
+{% load filters %}
+
+{% block styles %}
+    {{ block.super }}
+    <link rel="stylesheet" href="{% static 'AdminLTE/plugins/awesomplete/awesomplete.css' %}"/>
+
+{% endblock styles %}
+
+{% block ui_active_tab %}'configuration'{% endblock ui_active_tab %}
+{% block page_description %}{% endblock page_description %}
+
+{% block breadcrumb %}
+    {% include "vouchers/breadcrumb.html" %}
+{% endblock breadcrumb %}
+
+{% block maincontent %}
+
+    {% block content %}
+        <div class="row">
+            <div class="col-md-12">
+                <div class="box box-success">
+                    <div class="box-header with-border">
+                        <h3 class="box-title">{% block form-title %}Enter voucher details{% endblock %}</h3>
+                    </div>
+
+
+                    <form method="post" action="" class="form-horizontal" enctype="multipart/form-data">
+                        {% csrf_token %}
+
+                        <div class="box-body">
+                            {% for field in form %}
+                                <div class="form-group {% if field.errors %}has-error{% endif %}">
+                                    <label class="col-sm-4  col-lg-offset-1 col-lg-2 control-label">
+                                        {{ field.label }}
+                                    </label>
+
+                                    <div class="col-sm-8 col-lg-4">
+                                        {{ field|add_class:'form-control' }}
+                                        {% if field.errors %}
+                                            <span class="help-block">{{ field.errors }}</span>
+                                        {% endif %}
+                                    </div>
+
+
+                                </div>
+                            {% endfor %}
+                        </div><!-- /.box-body -->
+                        <div class="box-footer">
+                            <div class="col-sm-6">
+                                <button type="submit" class="btn btn-block btn-success">{% block save-button %}
+                                    Add{% endblock %}
+                                </button>
+                            </div>
+                            <div class="col-sm-6">
+                                <a href="{% url 'web.views.vouchers' %}"
+                                   class="btn btn-block btn-default">Cancel</a>
+                            </div>
+                        </div><!-- /.box-footer -->
+                    </form>
+                </div>
+
+            </div>
+        </div>
+
+    {% endblock %}
+
+
+{% endblock maincontent %}
+
+{% block scripts %}
+    {{ block.super }}
+
+    <script src="{% static 'AdminLTE/plugins/awesomplete/awesomplete.min.js' %}"></script>
+
+{% endblock scripts %}
\ No newline at end of file
diff --git a/smash/web/templates/vouchers/breadcrumb.html b/smash/web/templates/vouchers/breadcrumb.html
new file mode 100644
index 0000000000000000000000000000000000000000..f71acc808f35010d4240224a41f00db70a830f0d
--- /dev/null
+++ b/smash/web/templates/vouchers/breadcrumb.html
@@ -0,0 +1,2 @@
+<li><a href="{% url 'web.views.appointments' %}"><i class="fa fa-dashboard"></i> Dashboard</a></li>
+<li class="active"><a href="{% url 'web.views.vouchers' %}">Vouchers</a></li>
\ No newline at end of file
diff --git a/smash/web/templates/vouchers/edit.html b/smash/web/templates/vouchers/edit.html
new file mode 100644
index 0000000000000000000000000000000000000000..20e1bea665a6be2c70b8f260a23d8fee1e2b1ba5
--- /dev/null
+++ b/smash/web/templates/vouchers/edit.html
@@ -0,0 +1,10 @@
+{% extends "vouchers/add_edit.html" %}
+
+{% block page_header %}Edit voucher "{{ voucher.number }}"{% endblock page_header %}
+
+{% block title %}{{ block.super }} - Edit voucher "{{ voucher.number }}"{% endblock %}
+
+{% block form-title %}Enter voucher details{% endblock %}
+
+{% block save-button %}Save{% endblock %}
+
diff --git a/smash/web/templates/vouchers/list.html b/smash/web/templates/vouchers/list.html
new file mode 100644
index 0000000000000000000000000000000000000000..7a29b16f449daa5efa1baf27c23dc3d98d17c69e
--- /dev/null
+++ b/smash/web/templates/vouchers/list.html
@@ -0,0 +1,74 @@
+{% extends "_base.html" %}
+{% load static %}
+
+{% block styles %}
+    {{ block.super }}
+    <!-- DataTables -->
+    <link rel="stylesheet" href="{% static 'AdminLTE/plugins/datatables/dataTables.bootstrap.css' %}">
+{% endblock styles %}
+
+{% block ui_active_tab %}'configuration'{% endblock ui_active_tab %}
+{% block page_header %}Vouchers{% endblock page_header %}
+{% block page_description %}{% endblock page_description %}
+
+{% block breadcrumb %}
+    {% include "vouchers/breadcrumb.html" %}
+{% endblock breadcrumb %}
+
+{% block maincontent %}
+
+    <div class="box-body">
+        <table id="table" class="table table-bordered table-striped">
+            <thead>
+            <tr>
+                <th>Number</th>
+                <th>First name</th>
+                <th>Last name</th>
+                <th>Issue date</th>
+                <th>Expiry date</th>
+                <th>Status</th>
+                <th>Use date</th>
+                <th>Partner</th>
+                <th>Feedback</th>
+                <th>Edit</th>
+            </tr>
+            </thead>
+            <tbody>
+            {% for voucher in vouchers %}
+                <tr>
+                    <td>{{ voucher.number }}</td>
+                    <td>{{ voucher.study_subject.subject.first_name }}</td>
+                    <td>{{ voucher.study_subject.subject.last_name }}</td>
+                    <td>{{ voucher.issue_date }}</td>
+                    <td>{{ voucher.expiry_date }}</td>
+                    <td>{{ voucher.status }}</td>
+                    <td>{{ voucher.use_date }}</td>
+                    <td>{{ voucher.usage_partner.first_name }} {{ voucher.usage_partner.last_name }}</td>
+                    <td>{{ voucher.feedback }}</td>
+                    <td><a href="{% url 'web.views.voucher_edit' voucher.id %}"><i class="fa fa-edit"></i></a></td>
+                </tr>
+            {% endfor %}
+            </tbody>
+        </table>
+    </div>
+{% 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/tests/__init__.py b/smash/web/tests/__init__.py
index 4d84e29961f15842b84f3f3c8878073c755a0cbe..692232677b9701a19afaa9b63a85628248f09e5f 100644
--- a/smash/web/tests/__init__.py
+++ b/smash/web/tests/__init__.py
@@ -1,3 +1,4 @@
+import logging
 import os
 from django.conf import settings
 from django.contrib.auth.models import User
@@ -8,6 +9,8 @@ from functions import create_worker
 
 settings.MEDIA_ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data')
 
+logger = logging.getLogger(__name__)
+
 
 class LoggedInTestCase(TestCase):
     def setUp(self):
diff --git a/smash/web/tests/forms/test_subject_forms.py b/smash/web/tests/forms/test_subject_forms.py
index beb2bcbd1acff6c20ff7dae0ca213588d600b6bb..fe109455c9595a3b3ee475a27ff23509e41a2e1b 100644
--- a/smash/web/tests/forms/test_subject_forms.py
+++ b/smash/web/tests/forms/test_subject_forms.py
@@ -9,7 +9,7 @@ logger = logging.getLogger(__name__)
 
 class StudySubjectAddFormTests(LoggedInWithWorkerTestCase):
     def setUp(self):
-        super(LoggedInWithWorkerTestCase, self).setUp()
+        super(StudySubjectAddFormTests, self).setUp()
         self.subject = create_subject()
 
     def test_is_valid_social_security_number_too_short(self):
diff --git a/smash/web/tests/forms/test_voucher_forms.py b/smash/web/tests/forms/test_voucher_forms.py
new file mode 100644
index 0000000000000000000000000000000000000000..e7310f34cc85ce677cec636da9be9de5fdead66b
--- /dev/null
+++ b/smash/web/tests/forms/test_voucher_forms.py
@@ -0,0 +1,71 @@
+import logging
+
+from django.urls import reverse
+
+from web.forms import VoucherForm
+from web.models import Voucher
+from web.models.constants import VOUCHER_STATUS_USED
+from web.tests import LoggedInWithWorkerTestCase
+from web.tests.functions import create_study_subject, create_voucher_type, format_form_field, create_voucher
+
+logger = logging.getLogger(__name__)
+
+
+class VoucherFormTests(LoggedInWithWorkerTestCase):
+    def setUp(self):
+        super(VoucherFormTests, self).setUp()
+
+    def test_auto_generated_use_date(self):
+        study_subject = create_study_subject()
+        create_voucher(study_subject)
+
+        voucher_form = VoucherForm()
+        form_data = {
+            "status": VOUCHER_STATUS_USED,
+            "usage_partner": str(self.worker.id),
+            "voucher_type": create_voucher_type().id
+        }
+        for key, value in voucher_form.initial.items():
+            form_data[key] = format_form_field(value)
+
+        url = reverse('web.views.voucher_add') + '?study_subject_id=' + str(study_subject.id)
+        response = self.client.post(url, data=form_data)
+        self.assertEqual(response.status_code, 302)
+
+        self.assertEqual(2, Voucher.objects.all().count())
+        self.assertEqual(1, Voucher.objects.filter(use_date__isnull=False).count())
+
+    def test_valid_usage_partner(self):
+        study_subject = create_study_subject()
+        voucher = create_voucher(study_subject)
+        voucher.status = VOUCHER_STATUS_USED
+        voucher.save()
+
+        voucher_form = VoucherForm(instance=voucher)
+
+        form_data = {}
+        for key, value in voucher_form.initial.items():
+            form_data[key] = format_form_field(value)
+        form_data["usage_partner"] = ""
+
+        voucher_form = VoucherForm(instance=voucher, data=form_data)
+
+        self.assertFalse(voucher_form.is_valid())
+        self.assertTrue("usage_partner" in voucher_form.errors)
+
+    def test_valid_status(self):
+        study_subject = create_study_subject()
+        voucher = create_voucher(study_subject)
+        voucher.usage_partner = self.worker
+        voucher.save()
+
+        voucher_form = VoucherForm(instance=voucher)
+
+        form_data = {}
+        for key, value in voucher_form.initial.items():
+            form_data[key] = format_form_field(value)
+
+        voucher_form = VoucherForm(instance=voucher, data=form_data)
+
+        self.assertFalse(voucher_form.is_valid())
+        self.assertTrue("status" in voucher_form.errors)
diff --git a/smash/web/tests/functions.py b/smash/web/tests/functions.py
index 52ba55dfdfa75cfec5161885500b5294244371a4..ad3da907a16f158491a12f5f85a905274d1d3064 100644
--- a/smash/web/tests/functions.py
+++ b/smash/web/tests/functions.py
@@ -6,10 +6,10 @@ from django.contrib.auth.models import User
 
 from web.models import Location, AppointmentType, StudySubject, Worker, Visit, Appointment, ConfigurationItem, \
     Language, ContactAttempt, FlyingTeam, Availability, Subject, Study, StudyColumns, StudyNotificationParameters, \
-    VoucherType, VoucherTypePrice
+    VoucherType, VoucherTypePrice, Voucher
 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
+    MONDAY_AS_DAY_OF_WEEK, COUNTRY_AFGHANISTAN_ID, VOUCHER_STATUS_NEW
 from web.redcap_connector import RedcapSubject
 from web.views.notifications import get_today_midnight_date
 
@@ -67,7 +67,18 @@ def create_study(name="test"):
     return Study.objects.create(name=name, columns=study_columns, notification_parameters=notification_parameters)
 
 
-def create_empty_notification_parametres():
+def create_voucher(study_subject=None):
+    if study_subject is None:
+        study_subject = create_study_subject()
+    return Voucher.objects.create(number="123456",
+                                  study_subject=study_subject,
+                                  issue_date=get_today_midnight_date(),
+                                  expiry_date=get_today_midnight_date(),
+                                  voucher_type=create_voucher_type(),
+                                  status = VOUCHER_STATUS_NEW)
+
+
+def create_empty_notification_parameters():
     return StudyNotificationParameters.objects.create(
         exceeded_visits_visible=False,
         unfinished_visits_visible=False,
@@ -84,7 +95,7 @@ def create_empty_notification_parametres():
 
 def create_empty_study(name="test"):
     study_columns = create_empty_study_columns()
-    notification_parameters = create_empty_notification_parametres()
+    notification_parameters = create_empty_notification_parameters()
     result = create_study(name)
     result.columns = study_columns
     result.notification_parameters = notification_parameters
diff --git a/smash/web/tests/models/test_voucher.py b/smash/web/tests/models/test_voucher.py
new file mode 100644
index 0000000000000000000000000000000000000000..ec5e94316c2bda04dd70bb337498063ff4decca8
--- /dev/null
+++ b/smash/web/tests/models/test_voucher.py
@@ -0,0 +1,15 @@
+import logging
+
+from django.test import TestCase
+
+from web.tests.functions import create_voucher
+
+logger = logging.getLogger(__name__)
+
+
+class VoucherTests(TestCase):
+    def test_to_string(self):
+        voucher = create_voucher()
+
+        self.assertTrue(voucher.number in str(voucher))
+        self.assertTrue(voucher.number in unicode(voucher))
diff --git a/smash/web/tests/models/test_voucher_type.py b/smash/web/tests/models/test_voucher_type.py
new file mode 100644
index 0000000000000000000000000000000000000000..3c47e30bc18f79f2f41ae75cdb6fac9861b6a5f1
--- /dev/null
+++ b/smash/web/tests/models/test_voucher_type.py
@@ -0,0 +1,15 @@
+import logging
+
+from django.test import TestCase
+
+from web.tests.functions import create_voucher_type
+
+logger = logging.getLogger(__name__)
+
+
+class VoucherTypeTests(TestCase):
+    def test_to_string(self):
+        voucher_type = create_voucher_type()
+
+        self.assertTrue(voucher_type.code in str(voucher_type))
+        self.assertTrue(voucher_type.code in unicode(voucher_type))
diff --git a/smash/web/tests/view/test_notifications.py b/smash/web/tests/view/test_notifications.py
index e02b515089640176d13e3b57c13c0b7a902a64b8..e84952c33c2207af6c1c65c0e505da4768e0d876 100644
--- a/smash/web/tests/view/test_notifications.py
+++ b/smash/web/tests/view/test_notifications.py
@@ -7,7 +7,7 @@ from web.models import Appointment, Location, AppointmentTypeLink, Study, Visit
 from web.models.constants import GLOBAL_STUDY_ID
 from web.tests import LoggedInTestCase
 from web.tests.functions import create_appointment, create_location, create_worker, create_appointment_type, \
-    create_empty_notification_parametres, create_study_subject, create_visit
+    create_empty_notification_parameters, create_study_subject, create_visit
 from web.views.notifications import \
     get_approaching_visits_for_mail_contact, \
     get_approaching_visits_for_mail_contact_count, \
@@ -118,7 +118,7 @@ class NotificationViewTests(LoggedInTestCase):
 
     def test_get_notifications_with_empty_study_notification(self):
         study = Study.objects.filter(id=GLOBAL_STUDY_ID)[0]
-        study.notification_parameters = create_empty_notification_parametres()
+        study.notification_parameters = create_empty_notification_parameters()
         study.save()
 
         create_worker(self.user)
diff --git a/smash/web/tests/view/test_voucher.py b/smash/web/tests/view/test_voucher.py
new file mode 100644
index 0000000000000000000000000000000000000000..871bf563689ad15dfc4d97c2d1cb1ebd28b6b4a4
--- /dev/null
+++ b/smash/web/tests/view/test_voucher.py
@@ -0,0 +1,54 @@
+import logging
+
+from django.urls import reverse
+
+from web.forms import VoucherForm
+from web.models import Voucher
+from web.models.constants import VOUCHER_STATUS_NEW
+from web.tests.functions import create_voucher, create_study_subject, format_form_field, create_voucher_type
+from .. import LoggedInTestCase
+
+logger = logging.getLogger(__name__)
+
+
+class VoucherTypeViewTests(LoggedInTestCase):
+    def test_render_add_voucher_request(self):
+        response = self.client.get(reverse('web.views.voucher_add'))
+        self.assertEqual(response.status_code, 200)
+
+    def test_render_edit_voucher_request(self):
+        voucher = create_voucher()
+        response = self.client.get(reverse('web.views.voucher_edit', kwargs={'pk': voucher.id}))
+        self.assertEqual(response.status_code, 200)
+
+    def test_add_voucher(self):
+        study_subject = create_study_subject()
+        visit_detail_form = VoucherForm()
+        form_data = {
+            "status": VOUCHER_STATUS_NEW,
+            "voucher_type": create_voucher_type().id
+        }
+        for key, value in visit_detail_form.initial.items():
+            form_data[key] = format_form_field(value)
+
+        url = reverse('web.views.voucher_add') + '?study_subject_id=' + str(study_subject.id)
+        response = self.client.post(url, data=form_data)
+        self.assertEqual(response.status_code, 302)
+
+        self.assertEqual(1, Voucher.objects.all().count())
+
+    def test_edit_voucher(self):
+        voucher = create_voucher()
+        voucher_form = VoucherForm(instance=voucher)
+        form_data = {}
+        for key, value in voucher_form.initial.items():
+            form_data[key] = format_form_field(value)
+
+        form_data["usage_partner"] = ""
+        form_data["use_date"] = ""
+
+        url = reverse('web.views.voucher_edit', kwargs={'pk': voucher.id})
+        response = self.client.post(url, data=form_data)
+        self.assertEqual(response.status_code, 302)
+
+        self.assertEqual(1, Voucher.objects.all().count())
diff --git a/smash/web/tests/view/test_voucher_type_price.py b/smash/web/tests/view/test_voucher_type_price.py
index be90a2fd10abf9ffe14a774be02eee329d1e4fab..5032c40b46ed966049086ef792ba09061bbf78ba 100644
--- a/smash/web/tests/view/test_voucher_type_price.py
+++ b/smash/web/tests/view/test_voucher_type_price.py
@@ -2,7 +2,7 @@ import logging
 
 from django.urls import reverse
 
-from web.forms.forms import VoucherTypePriceForm
+from web.forms import VoucherTypePriceForm
 from web.models import VoucherType, VoucherTypePrice
 from web.tests.functions import create_voucher_type, create_voucher_type_price, format_form_field
 from .. import LoggedInTestCase
@@ -53,6 +53,6 @@ class VoucherTypePriceViewTests(LoggedInTestCase):
 
         url = reverse('web.views.voucher_type_price_edit',
                       kwargs={'pk': voucher_type_price.id, 'voucher_type_id': voucher_type_price.voucher_type.id})
-        response = self.client.post(url, data=form_data)
+        self.client.post(url, data=form_data)
 
         self.assertEqual(90.50, VoucherTypePrice.objects.get(id=voucher_type_price.id).price)
diff --git a/smash/web/urls.py b/smash/web/urls.py
index c2bc3d3bd480fecf6f3977d6c3ed209af04cdb34..1ee0abb3b5510f17ced9243d6cec7f7c15543f5a 100644
--- a/smash/web/urls.py
+++ b/smash/web/urls.py
@@ -178,6 +178,14 @@ urlpatterns = [
     url(r'^voucher_types/(?P<voucher_type_id>\d+)/prices/(?P<pk>\d+)/edit$',
         views.voucher_type_price.VoucherTypePriceEditView.as_view(), name='web.views.voucher_type_price_edit'),
 
+    ####################
+    #     VOUCHERS     #
+    ####################
+
+    url(r'^vouchers$', views.voucher.VoucherListView.as_view(), name='web.views.vouchers'),
+    url(r'^vouchers/add$', views.voucher.VoucherCreateView.as_view(), name='web.views.voucher_add'),
+    url(r'^vouchers/(?P<pk>\d+)/edit$', views.voucher.VoucherEditView.as_view(), name='web.views.voucher_edit'),
+
     ####################
     #    STATISTICS    #
     ####################
diff --git a/smash/web/views/__init__.py b/smash/web/views/__init__.py
index 01bdb13fac46bb895c6e33ebc0b9a78f9089461d..9a8ed660a3ba8424b17d85a53d890c66c76cfd66 100644
--- a/smash/web/views/__init__.py
+++ b/smash/web/views/__init__.py
@@ -72,6 +72,7 @@ import export
 import contact_attempt
 import configuration_item
 import language
+import voucher
 import voucher_type
 import voucher_type_price
 import redcap
diff --git a/smash/web/views/voucher.py b/smash/web/views/voucher.py
new file mode 100644
index 0000000000000000000000000000000000000000..840e5d34f67df75f44e8e01d9e97838977e6a51c
--- /dev/null
+++ b/smash/web/views/voucher.py
@@ -0,0 +1,55 @@
+# coding=utf-8
+import logging
+
+from django.contrib.messages.views import SuccessMessageMixin
+from django.urls import reverse_lazy
+from django.views.generic import CreateView
+from django.views.generic import ListView
+from django.views.generic import UpdateView
+
+from web.forms import VoucherForm
+from web.models import Voucher
+from web.models.constants import GLOBAL_STUDY_ID
+from . import WrappedView
+
+logger = logging.getLogger(__name__)
+
+
+class VoucherListView(ListView, WrappedView):
+    model = Voucher
+    context_object_name = "vouchers"
+    template_name = 'vouchers/list.html'
+
+
+class VoucherCreateView(CreateView, WrappedView):
+    form_class = VoucherForm
+    model = Voucher
+
+    template_name = "vouchers/add.html"
+    success_url = reverse_lazy('web.views.vouchers')
+    success_message = "Voucher type created"
+
+    def form_valid(self, form):
+        form.instance.study_id = GLOBAL_STUDY_ID
+        # noinspection PyUnresolvedReferences
+        form.instance.study_subject_id = self.request.GET.get("study_subject_id", -1)
+        return super(VoucherCreateView, self).form_valid(form)
+
+    def get_success_url(self, **kwargs):
+        # noinspection PyUnresolvedReferences
+        return reverse_lazy('web.views.subject_edit', kwargs={'id': self.request.GET.get("study_subject_id", -1)})
+
+
+class VoucherEditView(SuccessMessageMixin, UpdateView, WrappedView):
+    form_class = VoucherForm
+    model = Voucher
+
+    success_url = reverse_lazy('web.views.vouchers')
+    success_message = "Voucher saved successfully"
+    template_name = "vouchers/edit.html"
+    context_object_name = "voucher_type"
+
+    def get_success_url(self, **kwargs):
+        # noinspection PyUnresolvedReferences
+        study_subject_id = Voucher.objects.get(id=self.kwargs['pk']).study_subject.id
+        return reverse_lazy('web.views.subject_edit', kwargs={'id': study_subject_id})
diff --git a/smash/web/views/voucher_type.py b/smash/web/views/voucher_type.py
index 87b13059fb6b2812c22f8aab0e6a0d9e3bb06c29..5cb45eb57245bbf5df0e1163eb274266f30e871e 100644
--- a/smash/web/views/voucher_type.py
+++ b/smash/web/views/voucher_type.py
@@ -4,7 +4,7 @@ from django.views.generic import CreateView
 from django.views.generic import ListView
 from django.views.generic import UpdateView
 
-from web.forms.forms import VoucherTypeForm
+from web.forms import VoucherTypeForm
 from web.models import VoucherType
 from web.models.constants import GLOBAL_STUDY_ID
 from . import WrappedView
diff --git a/smash/web/views/voucher_type_price.py b/smash/web/views/voucher_type_price.py
index f93a045f3d188adc78d2994d5e5e6d135a77f8fc..11f6f4dd43981c64e1bb032accd8b543f763939a 100644
--- a/smash/web/views/voucher_type_price.py
+++ b/smash/web/views/voucher_type_price.py
@@ -5,7 +5,7 @@ from django.urls import reverse_lazy
 from django.views.generic import CreateView
 from django.views.generic import UpdateView
 
-from web.forms.forms import VoucherTypePriceForm
+from web.forms import VoucherTypePriceForm
 from web.models import VoucherTypePrice
 from . import WrappedView