From 1ed1d7a591c089c59cf1a8ce8fecfb798d98c74a Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Mon, 11 Dec 2017 12:41:10 +0100
Subject: [PATCH] unit tests for voucher forms

---
 smash/web/forms/__init__.py                   |  4 +-
 smash/web/forms/forms.py                      | 68 +---------------
 smash/web/forms/voucher_forms.py              | 77 +++++++++++++++++++
 smash/web/tests/__init__.py                   |  3 +
 smash/web/tests/forms/test_subject_forms.py   |  2 +-
 smash/web/tests/forms/test_voucher_forms.py   | 71 +++++++++++++++++
 smash/web/tests/view/test_voucher.py          |  2 +-
 .../web/tests/view/test_voucher_type_price.py |  2 +-
 smash/web/views/voucher.py                    |  2 +-
 smash/web/views/voucher_type.py               |  2 +-
 smash/web/views/voucher_type_price.py         |  2 +-
 11 files changed, 162 insertions(+), 73 deletions(-)
 create mode 100644 smash/web/forms/voucher_forms.py
 create mode 100644 smash/web/tests/forms/test_voucher_forms.py

diff --git a/smash/web/forms/__init__.py b/smash/web/forms/__init__.py
index 41432b74..23d44c94 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 836874bf..e59536a3 100644
--- a/smash/web/forms/forms.py
+++ b/smash/web/forms/forms.py
@@ -4,13 +4,11 @@ from collections import OrderedDict
 
 from django import forms
 from django.forms import ModelForm, Form
-from django.utils import timezone
 from django.utils.dates import MONTHS
 
-from web.algorithm import VerhoeffAlgorithm
 from web.models import StudySubject, Worker, Appointment, Visit, AppointmentType, ContactAttempt, AppointmentTypeLink, \
-    Availability, Holiday, VoucherType, VoucherTypePrice, Voucher
-from web.models.constants import SUBJECT_TYPE_CHOICES, VOUCHER_STATUS_NEW, VOUCHER_STATUS_USED
+    Availability, Holiday
+from web.models.constants import SUBJECT_TYPE_CHOICES
 from web.views.notifications import get_filter_locations
 
 """
@@ -389,65 +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']
-
-
-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/forms/voucher_forms.py b/smash/web/forms/voucher_forms.py
new file mode 100644
index 00000000..68de4581
--- /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/tests/__init__.py b/smash/web/tests/__init__.py
index 4d84e299..69223267 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 beb2bcbd..fe109455 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 00000000..e7310f34
--- /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/view/test_voucher.py b/smash/web/tests/view/test_voucher.py
index 3d2b0233..871bf563 100644
--- a/smash/web/tests/view/test_voucher.py
+++ b/smash/web/tests/view/test_voucher.py
@@ -2,7 +2,7 @@ import logging
 
 from django.urls import reverse
 
-from web.forms.forms import VoucherForm
+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
diff --git a/smash/web/tests/view/test_voucher_type_price.py b/smash/web/tests/view/test_voucher_type_price.py
index 60c20dd2..5032c40b 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
diff --git a/smash/web/views/voucher.py b/smash/web/views/voucher.py
index a054d9d0..840e5d34 100644
--- a/smash/web/views/voucher.py
+++ b/smash/web/views/voucher.py
@@ -7,7 +7,7 @@ from django.views.generic import CreateView
 from django.views.generic import ListView
 from django.views.generic import UpdateView
 
-from web.forms.forms import VoucherForm
+from web.forms import VoucherForm
 from web.models import Voucher
 from web.models.constants import GLOBAL_STUDY_ID
 from . import WrappedView
diff --git a/smash/web/views/voucher_type.py b/smash/web/views/voucher_type.py
index 87b13059..5cb45eb5 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 f93a045f..11f6f4dd 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
 
-- 
GitLab