From 715564e838c308d4b6430f05859a5c6c307690bd Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Fri, 1 Jun 2018 15:25:56 +0200
Subject: [PATCH] single voucher can be used in few sessions at voucher partner

---
 smash/web/forms/voucher_forms.py              | 13 +--
 .../forms/voucher_partner_session_forms.py    | 19 +++++
 .../web/migrations/0111_auto_20180601_1318.py | 43 ++++++++++
 smash/web/models/constants.py                 |  2 +
 smash/web/models/voucher.py                   |  8 +-
 smash/web/models/voucher_partner_session.py   | 25 ++++++
 .../includes/subject_vouchers_box.html        |  2 -
 .../voucher_partner_sessions/add.html         |  9 +++
 .../voucher_partner_sessions/add_edit.html    | 81 +++++++++++++++++++
 smash/web/templates/vouchers/add_edit.html    | 34 +++++++-
 smash/web/templates/vouchers/list.html        |  2 -
 smash/web/tests/forms/test_voucher_forms.py   |  6 +-
 smash/web/tests/view/test_voucher.py          |  3 +-
 .../view/test_voucher_partner_session.py      | 62 ++++++++++++++
 smash/web/urls.py                             | 29 +++++--
 smash/web/views/__init__.py                   |  1 +
 smash/web/views/voucher.py                    |  2 +-
 smash/web/views/voucher_partner_session.py    | 40 +++++++++
 18 files changed, 354 insertions(+), 27 deletions(-)
 create mode 100644 smash/web/forms/voucher_partner_session_forms.py
 create mode 100644 smash/web/migrations/0111_auto_20180601_1318.py
 create mode 100644 smash/web/models/voucher_partner_session.py
 create mode 100644 smash/web/templates/voucher_partner_sessions/add.html
 create mode 100644 smash/web/templates/voucher_partner_sessions/add_edit.html
 create mode 100644 smash/web/tests/view/test_voucher_partner_session.py
 create mode 100644 smash/web/views/voucher_partner_session.py

diff --git a/smash/web/forms/voucher_forms.py b/smash/web/forms/voucher_forms.py
index 681f7bad..defa1698 100644
--- a/smash/web/forms/voucher_forms.py
+++ b/smash/web/forms/voucher_forms.py
@@ -8,7 +8,7 @@ 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, Worker
-from web.models.constants import VOUCHER_STATUS_NEW, VOUCHER_STATUS_USED
+from web.models.constants import VOUCHER_STATUS_NEW, VOUCHER_STATUS_USED, VOUCHER_STATUS_EXPIRED
 from web.models.worker_study_role import WORKER_VOUCHER_PARTNER
 
 logger = logging.getLogger(__name__)
@@ -52,17 +52,15 @@ class VoucherForm(ModelForm):
         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
-            self.fields['usage_partner'].queryset = Worker.get_workers_by_worker_type(WORKER_VOUCHER_PARTNER).filter(
-                voucher_types=instance.voucher_type)
+            self.fields['hours'].widget.attrs['readonly'] = True
+            self.fields['usage_partner'].widget.attrs['readonly'] = True
 
-            if instance.status != VOUCHER_STATUS_NEW:
+            if instance.status == VOUCHER_STATUS_USED or instance.status == VOUCHER_STATUS_EXPIRED:
                 self.fields['status'].widget.attrs['readonly'] = True
                 self.fields['feedback'].widget.attrs['readonly'] = True
-                self.fields['usage_partner'].widget.attrs['readonly'] = True
 
     def save(self, commit=True):
         instance = super(VoucherForm, self).save(commit=False)
@@ -78,8 +76,5 @@ class VoucherForm(ModelForm):
                               instance.voucher_type.code + "-" + \
                               instance.usage_partner.voucher_partner_code + "-" + \
                               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/forms/voucher_partner_session_forms.py b/smash/web/forms/voucher_partner_session_forms.py
new file mode 100644
index 00000000..706ab5d5
--- /dev/null
+++ b/smash/web/forms/voucher_partner_session_forms.py
@@ -0,0 +1,19 @@
+import datetime
+import logging
+
+from django import forms
+from django.forms import ModelForm
+
+from web.forms.forms import DATETIMEPICKER_DATE_ATTRS
+from web.models.voucher_partner_session import VoucherPartnerSession
+
+logger = logging.getLogger(__name__)
+
+
+class VoucherPartnerSessionForm(ModelForm):
+    date = forms.DateTimeField(widget=forms.DateTimeInput(DATETIMEPICKER_DATE_ATTRS),
+                               initial=datetime.datetime.now().replace(hour=8, minute=0, second=0))
+
+    class Meta:
+        model = VoucherPartnerSession
+        exclude = ['voucher']
diff --git a/smash/web/migrations/0111_auto_20180601_1318.py b/smash/web/migrations/0111_auto_20180601_1318.py
new file mode 100644
index 00000000..d666a0b0
--- /dev/null
+++ b/smash/web/migrations/0111_auto_20180601_1318.py
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2018-06-01 13:18
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0110_auto_20180601_0754'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='VoucherPartnerSession',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('length', models.IntegerField(verbose_name=b'Length (minutes)')),
+                ('date', models.DateTimeField(verbose_name=b'Issue date')),
+            ],
+        ),
+        migrations.RemoveField(
+            model_name='voucher',
+            name='use_date',
+        ),
+        migrations.AddField(
+            model_name='voucher',
+            name='hours',
+            field=models.IntegerField(default=0, verbose_name=b'Hours'),
+        ),
+        migrations.AlterField(
+            model_name='voucher',
+            name='status',
+            field=models.CharField(choices=[(b'NEW', b'New'), (b'IN_USE', b'In use'), (b'USED', b'Used'), (b'EXPIRED', b'Expired')], default=b'NEW', max_length=20, verbose_name=b'Status'),
+        ),
+        migrations.AddField(
+            model_name='voucherpartnersession',
+            name='voucher',
+            field=models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='voucher_partner_sessions', to='web.Voucher'),
+        ),
+    ]
diff --git a/smash/web/models/constants.py b/smash/web/models/constants.py
index 5db58bb9..0ef157f4 100644
--- a/smash/web/models/constants.py
+++ b/smash/web/models/constants.py
@@ -85,10 +85,12 @@ COUNTRY_AFGHANISTAN_ID = 2
 GLOBAL_STUDY_ID = 1
 
 VOUCHER_STATUS_NEW = "NEW"
+VOUCHER_STATUS_IN_USE = "IN_USE"
 VOUCHER_STATUS_USED = "USED"
 VOUCHER_STATUS_EXPIRED = "EXPIRED"
 VOUCHER_STATUS_CHOICES = (
     (VOUCHER_STATUS_NEW, 'New'),
+    (VOUCHER_STATUS_IN_USE, 'In use'),
     (VOUCHER_STATUS_USED, 'Used'),
     (VOUCHER_STATUS_EXPIRED, 'Expired'),
 )
diff --git a/smash/web/models/voucher.py b/smash/web/models/voucher.py
index 7cf9a64e..7de7d714 100644
--- a/smash/web/models/voucher.py
+++ b/smash/web/models/voucher.py
@@ -20,7 +20,13 @@ class Voucher(models.Model):
 
     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)
+
+    hours = models.IntegerField(
+        verbose_name='Hours',
+        default=0,
+        null=False
+    )
+
     voucher_type = models.ForeignKey(
         VoucherType,
         on_delete=models.CASCADE,
diff --git a/smash/web/models/voucher_partner_session.py b/smash/web/models/voucher_partner_session.py
new file mode 100644
index 00000000..84a25b5f
--- /dev/null
+++ b/smash/web/models/voucher_partner_session.py
@@ -0,0 +1,25 @@
+# coding=utf-8
+
+from django.db import models
+
+from web.models import Voucher
+
+
+class VoucherPartnerSession(models.Model):
+    class Meta:
+        app_label = 'web'
+
+    length = models.IntegerField(
+        verbose_name='Length (minutes)',
+        null=False
+    )
+
+    date = models.DateTimeField(verbose_name='Issue date', null=False)
+
+    voucher = models.ForeignKey(
+        Voucher,
+        on_delete=models.CASCADE,
+        null=False,
+        related_name="voucher_partner_sessions",
+        editable=False
+    )
diff --git a/smash/web/templates/includes/subject_vouchers_box.html b/smash/web/templates/includes/subject_vouchers_box.html
index 36638b10..a17610a2 100644
--- a/smash/web/templates/includes/subject_vouchers_box.html
+++ b/smash/web/templates/includes/subject_vouchers_box.html
@@ -18,7 +18,6 @@
                         <th class="text-center">Issue date</th>
                         <th class="text-center">Expiry date</th>
                         <th class="text-center">Status</th>
-                        <th class="text-center">Use date</th>
                         <th class="text-center">Partner</th>
                         <th class="text-center">Feedback</th>
                         <th class="text-center">Edit</th>
@@ -32,7 +31,6 @@
                             <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>
diff --git a/smash/web/templates/voucher_partner_sessions/add.html b/smash/web/templates/voucher_partner_sessions/add.html
new file mode 100644
index 00000000..80de643c
--- /dev/null
+++ b/smash/web/templates/voucher_partner_sessions/add.html
@@ -0,0 +1,9 @@
+{% extends "voucher_partner_sessions/add_edit.html" %}
+
+{% block page_header %}New voucher partner session{% endblock page_header %}
+
+{% block title %}{{ block.super }} - Add voucher partner session{% endblock %}
+
+{% block form-title %}Enter session details{% endblock %}
+
+{% block save-button %}Add{% endblock %}
diff --git a/smash/web/templates/voucher_partner_sessions/add_edit.html b/smash/web/templates/voucher_partner_sessions/add_edit.html
new file mode 100644
index 00000000..73b82a9e
--- /dev/null
+++ b/smash/web/templates/voucher_partner_sessions/add_edit.html
@@ -0,0 +1,81 @@
+{% extends "_base.html" %}
+{% load static %}
+{% load filters %}
+
+{% block styles %}
+    {{ block.super }}
+    <link rel="stylesheet" href="{% static 'AdminLTE/plugins/awesomplete/awesomplete.css' %}"/>
+    {% include "includes/datepicker.css.html" %}
+    {% include "includes/datetimepicker.css.html" %}
+
+{% 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 session 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>
+    {% include "includes/datepicker.js.html" %}
+    {% include "includes/datetimepicker.js.html" %}
+
+{% endblock scripts %}
\ No newline at end of file
diff --git a/smash/web/templates/vouchers/add_edit.html b/smash/web/templates/vouchers/add_edit.html
index 8e5e5dfb..0ce71496 100644
--- a/smash/web/templates/vouchers/add_edit.html
+++ b/smash/web/templates/vouchers/add_edit.html
@@ -59,11 +59,43 @@
                             </div>
                         </div><!-- /.box-footer -->
                     </form>
-                </div>
+                    {% if voucher.id %}
+                        <h3 class="box-title">List of voucher partner sessions
+                            {% if voucher.status == 'NEW' or voucher.status == 'IN_USE' %}
+
+                                <a title="add a new voucher partner session"
+                                   id="add-voucher-partner-session"
+                                   href="{% url 'web.views.voucher_partner_sessions_add' pk=voucher.id %}"
+                                   class="text-primary"
+                                ><i class="fa fa-plus-circle text-success"></i></a>
+                            {% endif %}
+                        </h3>
 
+                        <div class="box-body">
+                            <table class="table table-bordered table-striped">
+                                <thead>
+                                <tr>
+                                    <th>Date</th>
+                                    <th>Length (minutes)</th>
+                                </tr>
+                                </thead>
+                                <tbody>
+                                {% for voucher_partner_session in voucher.voucher_partner_sessions.all %}
+                                    <tr>
+                                        <td>{{ voucher_partner_session.date |date:'Y-m-d H:i' }}</td>
+                                        <td>{{ voucher_partner_session.length }}</td>
+                                    </tr>
+                                {% endfor %}
+                                </tbody>
+                            </table>
+                        </div>
+
+                    {% endif %}
+                </div>
             </div>
         </div>
 
+
     {% endblock %}
 
 
diff --git a/smash/web/templates/vouchers/list.html b/smash/web/templates/vouchers/list.html
index d0f242e7..1b29b296 100644
--- a/smash/web/templates/vouchers/list.html
+++ b/smash/web/templates/vouchers/list.html
@@ -28,7 +28,6 @@
                 <th>Issue date</th>
                 <th>Expiry date</th>
                 <th>Status</th>
-                <th>Use date</th>
                 <th>Partner</th>
                 <th>Feedback</th>
                 <th>Edit</th>
@@ -44,7 +43,6 @@
                     <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>
diff --git a/smash/web/tests/forms/test_voucher_forms.py b/smash/web/tests/forms/test_voucher_forms.py
index 003cf6c3..71031d21 100644
--- a/smash/web/tests/forms/test_voucher_forms.py
+++ b/smash/web/tests/forms/test_voucher_forms.py
@@ -19,7 +19,7 @@ class VoucherFormTests(LoggedInWithWorkerTestCase):
         self.voucher_partner = create_worker()
         WorkerStudyRole.objects.filter(worker=self.voucher_partner).update(role=ROLE_CHOICES_VOUCHER_PARTNER)
 
-    def test_auto_generated_use_date(self):
+    def test_create_voucher(self):
         voucher_type = create_voucher_type()
         study_subject = create_study_subject()
         study_subject.voucher_types.add(voucher_type)
@@ -29,6 +29,7 @@ class VoucherFormTests(LoggedInWithWorkerTestCase):
         form_data = {
             "status": VOUCHER_STATUS_USED,
             "usage_partner": str(self.voucher_partner.id),
+            "hours": 10,
             "voucher_type": voucher_type.id
         }
         for key, value in voucher_form.initial.items():
@@ -39,9 +40,8 @@ class VoucherFormTests(LoggedInWithWorkerTestCase):
         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):
+    def test_invalid_usage_partner(self):
         study_subject = create_study_subject()
         voucher = create_voucher(study_subject)
         voucher.status = VOUCHER_STATUS_USED
diff --git a/smash/web/tests/view/test_voucher.py b/smash/web/tests/view/test_voucher.py
index 891c4232..18609fb8 100644
--- a/smash/web/tests/view/test_voucher.py
+++ b/smash/web/tests/view/test_voucher.py
@@ -42,6 +42,7 @@ class VoucherTypeViewTests(LoggedInTestCase):
         form_data = {
             "usage_partner": usage_partner.id,
             "status": VOUCHER_STATUS_NEW,
+            "hours": 10,
             "voucher_type": voucher_type.id
         }
         for key, value in visit_detail_form.initial.items():
@@ -49,6 +50,7 @@ class VoucherTypeViewTests(LoggedInTestCase):
 
         url = reverse('web.views.voucher_add') + '?study_subject_id=' + str(study_subject.id)
         response = self.client.post(url, data=form_data)
+        print response.content
         self.assertEqual(response.status_code, 302)
 
         self.assertEqual(1, Voucher.objects.all().count())
@@ -64,7 +66,6 @@ class VoucherTypeViewTests(LoggedInTestCase):
             form_data[key] = format_form_field(value)
 
         form_data["usage_partner"] = usage_partner.id
-        form_data["use_date"] = "2011-01-01"
 
         url = reverse('web.views.voucher_edit', kwargs={'pk': voucher.id})
         response = self.client.post(url, data=form_data)
diff --git a/smash/web/tests/view/test_voucher_partner_session.py b/smash/web/tests/view/test_voucher_partner_session.py
new file mode 100644
index 00000000..4b803329
--- /dev/null
+++ b/smash/web/tests/view/test_voucher_partner_session.py
@@ -0,0 +1,62 @@
+import datetime
+import logging
+
+from django.urls import reverse
+
+from web.forms.voucher_partner_session_forms import VoucherPartnerSessionForm
+from web.models import Voucher
+from web.models.constants import VOUCHER_STATUS_USED, VOUCHER_STATUS_IN_USE
+from web.tests.functions import create_voucher, format_form_field
+from .. import LoggedInTestCase
+
+logger = logging.getLogger(__name__)
+
+
+class VoucherTypeViewTests(LoggedInTestCase):
+    def test_render_add_voucher_partner_session_request(self):
+        voucher = create_voucher()
+        url = reverse('web.views.voucher_partner_sessions_add', kwargs={'pk': voucher.id})
+        response = self.client.get(url)
+        self.assertEqual(response.status_code, 200)
+
+    def test_add_voucher_partner_session_without_using_time(self):
+        voucher = create_voucher()
+        voucher.hours = 10
+        voucher.save()
+
+        form = VoucherPartnerSessionForm()
+        form_data = {
+            "length": 50,
+            "date": datetime.datetime.now(),
+        }
+        for key, value in form.initial.items():
+            form_data[key] = format_form_field(value)
+
+        url = reverse('web.views.voucher_partner_sessions_add', kwargs={'pk': voucher.id})
+        response = self.client.post(url, data=form_data)
+        print response.content
+        self.assertEqual(response.status_code, 302)
+
+        voucher = Voucher.objects.get(id=voucher.id)
+        self.assertEqual(VOUCHER_STATUS_IN_USE, voucher.status)
+
+    def test_add_voucher_partner_session_with_using_time(self):
+        voucher = create_voucher()
+        voucher.hours = 1
+        voucher.save()
+
+        form = VoucherPartnerSessionForm()
+        form_data = {
+            "length": 60,
+            "date": datetime.datetime.now(),
+        }
+        for key, value in form.initial.items():
+            form_data[key] = format_form_field(value)
+
+        url = reverse('web.views.voucher_partner_sessions_add', kwargs={'pk': voucher.id})
+        response = self.client.post(url, data=form_data)
+        print response.content
+        self.assertEqual(response.status_code, 302)
+
+        voucher = Voucher.objects.get(id=voucher.id)
+        self.assertEqual(VOUCHER_STATUS_USED, voucher.status)
diff --git a/smash/web/urls.py b/smash/web/urls.py
index 3816e9c4..63496dee 100644
--- a/smash/web/urls.py
+++ b/smash/web/urls.py
@@ -127,8 +127,10 @@ urlpatterns = [
 
     url(r'^equipment_and_rooms/equipment$', views.equipment.equipment, name='web.views.equipment'),
     url(r'^equipment_and_rooms/equipment/add$', views.equipment.equipment_add, name='web.views.equipment_add'),
-    url(r'^equipment_and_rooms/equipment/edit/(?P<equipment_id>\d+)$', views.equipment.equipment_edit, name='web.views.equipment_edit'),
-    url(r'^equipment_and_rooms/equipment/delete/(?P<equipment_id>\d+)$', views.equipment.equipment_delete, name='web.views.equipment_delete'),
+    url(r'^equipment_and_rooms/equipment/edit/(?P<equipment_id>\d+)$', views.equipment.equipment_edit,
+        name='web.views.equipment_edit'),
+    url(r'^equipment_and_rooms/equipment/delete/(?P<equipment_id>\d+)$', views.equipment.equipment_delete,
+        name='web.views.equipment_delete'),
 
     url(r'^equipment_and_rooms/kit_requests$', views.kit.kit_requests, name='web.views.kit_requests'),
     url(r'^equipment_and_rooms/kit_requests/(?P<start_date>[\w-]+)/$', views.kit.kit_requests_send_mail,
@@ -136,14 +138,19 @@ urlpatterns = [
     url(r'^equipment_and_rooms/kit_requests/(?P<start_date>[\w-]+)/(?P<end_date>[\w-]+)/$',
         views.kit.kit_requests_send_mail, name='web.views.kit_requests_send_mail'),
 
-    url(r'^equipment_and_rooms/flying_teams$', views.flying_teams.flying_teams, name='web.views.equipment_and_rooms.flying_teams'),
-    url(r'^equipment_and_rooms/flying_teams/add$', views.flying_teams.flying_teams_add, name='web.views.equipment_and_rooms.flying_teams_add'),
-    url(r'^equipment_and_rooms/flying_teams/edit/(?P<flying_team_id>\d+)$', views.flying_teams.flying_teams_edit, name='web.views.equipment_and_rooms.flying_teams_edit'),
+    url(r'^equipment_and_rooms/flying_teams$', views.flying_teams.flying_teams,
+        name='web.views.equipment_and_rooms.flying_teams'),
+    url(r'^equipment_and_rooms/flying_teams/add$', views.flying_teams.flying_teams_add,
+        name='web.views.equipment_and_rooms.flying_teams_add'),
+    url(r'^equipment_and_rooms/flying_teams/edit/(?P<flying_team_id>\d+)$', views.flying_teams.flying_teams_edit,
+        name='web.views.equipment_and_rooms.flying_teams_edit'),
 
     url(r'^equipment_and_rooms/rooms$', views.rooms.rooms, name='web.views.equipment_and_rooms.rooms'),
     url(r'^equipment_and_rooms/rooms/add$', views.rooms.rooms_add, name='web.views.equipment_and_rooms.rooms_add'),
-    url(r'^equipment_and_rooms/rooms/edit/(?P<room_id>\d+)$', views.rooms.rooms_edit, name='web.views.equipment_and_rooms.rooms_edit'),
-    url(r'^equipment_and_rooms/rooms/delete/(?P<room_id>\d+)$', views.rooms.rooms_delete, name='web.views.equipment_and_rooms.rooms_delete'),
+    url(r'^equipment_and_rooms/rooms/edit/(?P<room_id>\d+)$', views.rooms.rooms_edit,
+        name='web.views.equipment_and_rooms.rooms_edit'),
+    url(r'^equipment_and_rooms/rooms/delete/(?P<room_id>\d+)$', views.rooms.rooms_delete,
+        name='web.views.equipment_and_rooms.rooms_delete'),
 
     ####################
     #       MAIL       #
@@ -202,6 +209,14 @@ urlpatterns = [
     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'),
 
+    ####################################
+    #     VOUCHER PARTNER SESSIONS     #
+    ####################################
+
+    url(r'^vouchers/(?P<pk>\d+)/voucher_partner_session/add$',
+        views.voucher_partner_session.VoucherPartnerSessionCreateView.as_view(),
+        name='web.views.voucher_partner_sessions_add'),
+
     ####################
     #    STATISTICS    #
     ####################
diff --git a/smash/web/views/__init__.py b/smash/web/views/__init__.py
index a0c8a353..e3e10f31 100644
--- a/smash/web/views/__init__.py
+++ b/smash/web/views/__init__.py
@@ -77,6 +77,7 @@ import contact_attempt
 import configuration_item
 import language
 import voucher
+import voucher_partner_session
 import voucher_type
 import voucher_type_price
 import redcap
diff --git a/smash/web/views/voucher.py b/smash/web/views/voucher.py
index 6d7dd7d8..45b5a8f4 100644
--- a/smash/web/views/voucher.py
+++ b/smash/web/views/voucher.py
@@ -58,7 +58,7 @@ class VoucherEditView(SuccessMessageMixin, UpdateView, WrappedView):
     success_url = reverse_lazy('web.views.vouchers')
     success_message = "Voucher saved successfully"
     template_name = "vouchers/edit.html"
-    context_object_name = "voucher_type"
+    context_object_name = "voucher"
 
     def get_success_url(self, **kwargs):
         # noinspection PyUnresolvedReferences
diff --git a/smash/web/views/voucher_partner_session.py b/smash/web/views/voucher_partner_session.py
new file mode 100644
index 00000000..58697f91
--- /dev/null
+++ b/smash/web/views/voucher_partner_session.py
@@ -0,0 +1,40 @@
+# coding=utf-8
+import logging
+
+from django.urls import reverse_lazy
+from django.views.generic import CreateView
+
+from web.forms.voucher_partner_session_forms import VoucherPartnerSessionForm
+from web.models import Voucher
+from web.models.constants import VOUCHER_STATUS_IN_USE, VOUCHER_STATUS_NEW, VOUCHER_STATUS_USED
+from web.models.voucher_partner_session import VoucherPartnerSession
+from . import WrappedView
+
+logger = logging.getLogger(__name__)
+
+
+class VoucherPartnerSessionCreateView(CreateView, WrappedView):
+    form_class = VoucherPartnerSessionForm
+    model = VoucherPartnerSession
+
+    template_name = "voucher_partner_sessions/add.html"
+    success_url = reverse_lazy('web.views.voucher_edit')
+    success_message = "Voucher partner session added"
+
+    def form_valid(self, form):
+        form.instance.voucher_id = pk = self.kwargs['pk']
+        response = super(VoucherPartnerSessionCreateView, self).form_valid(form)
+        voucher = Voucher.objects.get(pk=self.kwargs['pk'])
+        if voucher.status == VOUCHER_STATUS_NEW:
+            voucher.status = VOUCHER_STATUS_IN_USE
+            voucher.save()
+        session_time_used_in_minutes = 0
+        for session in voucher.voucher_partner_sessions.all():
+            session_time_used_in_minutes += session.length
+        if session_time_used_in_minutes >= voucher.hours * 60:
+            voucher.status = VOUCHER_STATUS_USED
+            voucher.save()
+        return response
+
+    def get_success_url(self, **kwargs):
+        return reverse_lazy('web.views.voucher_edit', kwargs={'pk': self.kwargs['pk']})
-- 
GitLab