From 0bd6e0d2ab8f81721402aad84dba3c6f7c895f6f Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Fri, 1 Jun 2018 10:48:30 +0200
Subject: [PATCH] voucher partner is obligatory in voucher, voucher number is
 generated using schema

---
 smash/web/forms/voucher_forms.py              | 19 ++++-----
 smash/web/forms/worker_form.py                |  5 ++-
 .../web/migrations/0110_auto_20180601_0754.py | 41 +++++++++++++++++++
 smash/web/models/voucher.py                   |  5 +--
 smash/web/models/worker.py                    |  5 +++
 smash/web/tests/forms/test_voucher_forms.py   | 14 -------
 smash/web/tests/functions.py                  | 20 ++++++++-
 smash/web/tests/view/test_voucher.py          | 18 ++++++--
 8 files changed, 94 insertions(+), 33 deletions(-)
 create mode 100644 smash/web/migrations/0110_auto_20180601_0754.py

diff --git a/smash/web/forms/voucher_forms.py b/smash/web/forms/voucher_forms.py
index 7067d0d9..681f7bad 100644
--- a/smash/web/forms/voucher_forms.py
+++ b/smash/web/forms/voucher_forms.py
@@ -57,28 +57,27 @@ class VoucherForm(ModelForm):
         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)
+                voucher_types=instance.voucher_type)
 
             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)
+            max_id = str(1).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)
+                max_id = str(Voucher.objects.latest('id').id + 1).zfill(5)
+            # number in format  {ND_NUMBER}-{DATE}-{VOUCHER_TYPE_CODE}-{VOUCHER_TYPE}-{SEQ_NUMBER}{CHECKSUM}
+            instance.number = instance.study_subject.nd_number + "-" + \
+                              datetime.datetime.now().strftime("%Y%m%d") + "-" + \
+                              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()
 
diff --git a/smash/web/forms/worker_form.py b/smash/web/forms/worker_form.py
index 8d5fdc67..1237b46b 100644
--- a/smash/web/forms/worker_form.py
+++ b/smash/web/forms/worker_form.py
@@ -9,7 +9,7 @@ from django_common.auth_backends import User
 from web.models import Worker, WorkerStudyRole
 from web.models.constants import GLOBAL_STUDY_ID
 from web.models.worker import role_choices_by_worker_type, worker_type_by_worker
-from web.models.worker_study_role import WORKER_STAFF
+from web.models.worker_study_role import WORKER_STAFF, WORKER_VOUCHER_PARTNER
 
 logger = logging.getLogger(__name__)
 
@@ -43,6 +43,9 @@ class WorkerForm(ModelForm):
         else:
             del self.fields['locations']
 
+        if worker_type != WORKER_VOUCHER_PARTNER:
+            del self.fields['voucher_partner_code']
+
         fields = OrderedDict()
 
         if worker_type == WORKER_STAFF:
diff --git a/smash/web/migrations/0110_auto_20180601_0754.py b/smash/web/migrations/0110_auto_20180601_0754.py
new file mode 100644
index 00000000..2c878270
--- /dev/null
+++ b/smash/web/migrations/0110_auto_20180601_0754.py
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2018-06-01 07:54
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0109_missing_appointment_list_update'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='worker',
+            name='voucher_partner_code',
+            field=models.CharField(blank=True, max_length=10, verbose_name=b'Code'),
+        ),
+        migrations.AlterField(
+            model_name='studysubjectlist',
+            name='type',
+            field=models.CharField(blank=True, choices=[(b'GENERIC', b'Generic subject list'), (b'NO_VISIT', b'Subjects without visit'), (b'REQUIRE_CONTACT', b'Subjects required contact'), (b'VOUCHER_EXPIRY', b'Subject with vouchers to be expired soon')], max_length=50, null=True, verbose_name=b'Type of list'),
+        ),
+        migrations.AlterField(
+            model_name='studyvisitlist',
+            name='type',
+            field=models.CharField(choices=[(b'UNFINISHED', b'unfinished visits'), (b'APPROACHING_WITHOUT_APPOINTMENTS', b'approaching visits'), (b'APPROACHING_FOR_MAIL_CONTACT', b'post mail for approaching visits'), (b'GENERIC', b'Generic visit list'), (b'MISSING_APPOINTMENTS', b'visits with missing appointments'), (b'EXCEEDED_TIME', b'exceeded visit time')], max_length=50, verbose_name=b'Type of list'),
+        ),
+        migrations.AlterField(
+            model_name='voucher',
+            name='number',
+            field=models.CharField(max_length=50, unique=True, verbose_name=b'Number'),
+        ),
+        migrations.AlterField(
+            model_name='voucher',
+            name='usage_partner',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='web.Worker'),
+        ),
+    ]
diff --git a/smash/web/models/voucher.py b/smash/web/models/voucher.py
index 340b7876..7cf9a64e 100644
--- a/smash/web/models/voucher.py
+++ b/smash/web/models/voucher.py
@@ -11,7 +11,7 @@ class Voucher(models.Model):
         app_label = 'web'
 
     number = models.CharField(
-        max_length=10,
+        max_length=50,
         verbose_name='Number',
         blank=False,
         null=False,
@@ -48,8 +48,7 @@ class Voucher(models.Model):
     usage_partner = models.ForeignKey(
         Worker,
         on_delete=models.CASCADE,
-        null=True,
-        blank=True
+        null=False
     )
 
     def __str__(self):
diff --git a/smash/web/models/worker.py b/smash/web/models/worker.py
index ab5ec2c1..b3dde9b8 100644
--- a/smash/web/models/worker.py
+++ b/smash/web/models/worker.py
@@ -126,6 +126,11 @@ class Worker(models.Model):
                                       blank=True
                                       )
 
+    voucher_partner_code = models.CharField(max_length=10,
+                                            verbose_name='Code',
+                                            blank=True
+                                            )
+
     def is_on_leave(self):
         if len(self.holiday_set.filter(datetime_end__gt=datetime.datetime.now(),
                                        datetime_start__lt=datetime.datetime.now())):
diff --git a/smash/web/tests/forms/test_voucher_forms.py b/smash/web/tests/forms/test_voucher_forms.py
index c95063e2..003cf6c3 100644
--- a/smash/web/tests/forms/test_voucher_forms.py
+++ b/smash/web/tests/forms/test_voucher_forms.py
@@ -62,17 +62,3 @@ class VoucherFormTests(LoggedInWithWorkerTestCase):
         for key, value in voucher_form.initial.items():
             form_data[key] = format_form_field(value)
         return form_data
-
-    def test_valid_status(self):
-        study_subject = create_study_subject()
-        voucher = create_voucher(study_subject)
-        self.voucher_partner.voucher_types.add(voucher.voucher_type)
-        voucher.usage_partner = self.voucher_partner
-        voucher.save()
-
-        form_data = self.get_voucher_form_data(voucher)
-
-        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 0bebd3af..f7da4add 100644
--- a/smash/web/tests/functions.py
+++ b/smash/web/tests/functions.py
@@ -10,7 +10,7 @@ from web.models import Location, AppointmentType, StudySubject, Worker, Visit, A
 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, VOUCHER_STATUS_NEW, GLOBAL_STUDY_ID
-from web.models.worker_study_role import ROLE_CHOICES_DOCTOR
+from web.models.worker_study_role import ROLE_CHOICES_DOCTOR, WORKER_VOUCHER_PARTNER
 from web.redcap_connector import RedcapSubject
 from web.views.notifications import get_today_midnight_date
 
@@ -78,15 +78,18 @@ def get_test_id():
     return result
 
 
-def create_voucher(study_subject=None):
+def create_voucher(study_subject=None, partner=None):
     if study_subject is None:
         study_subject = create_study_subject()
+    if partner is None:
+        partner = create_voucher_partner()
     number = str(get_test_id())
     return Voucher.objects.create(number=number,
                                   study_subject=study_subject,
                                   issue_date=get_today_midnight_date(),
                                   expiry_date=get_today_midnight_date(),
                                   voucher_type=create_voucher_type(),
+                                  usage_partner=partner,
                                   status=VOUCHER_STATUS_NEW)
 
 
@@ -229,6 +232,19 @@ def create_worker(user=None, with_test_location=False):
     return worker
 
 
+def create_voucher_partner():
+    worker = Worker.objects.create(
+        first_name='piotr',
+        last_name="gawron",
+        email='jacob@bla.com',
+        specialization="spec",
+        unit="LCSB",
+        phone_number="0123456789"
+    )
+    WorkerStudyRole.objects.create(worker=worker, study_id=GLOBAL_STUDY_ID, role=WORKER_VOUCHER_PARTNER)
+    return worker
+
+
 def create_availability(worker=None):
     if worker is None:
         worker = create_worker()
diff --git a/smash/web/tests/view/test_voucher.py b/smash/web/tests/view/test_voucher.py
index f8c71ab9..891c4232 100644
--- a/smash/web/tests/view/test_voucher.py
+++ b/smash/web/tests/view/test_voucher.py
@@ -3,12 +3,15 @@ import logging
 import datetime
 from django.urls import reverse
 
+from web.models import Worker
+from web.models.worker_study_role import WORKER_VOUCHER_PARTNER
 from web.views.notifications import get_today_midnight_date
 from web.views.voucher import ExpireVouchersJob
 from web.forms import VoucherForm
 from web.models import Voucher
 from web.models.constants import VOUCHER_STATUS_NEW, VOUCHER_STATUS_USED, VOUCHER_STATUS_EXPIRED
-from web.tests.functions import create_voucher, create_study_subject, format_form_field, create_voucher_type
+from web.tests.functions import create_voucher, create_study_subject, format_form_field, create_voucher_type, \
+    create_voucher_partner
 from .. import LoggedInTestCase
 
 logger = logging.getLogger(__name__)
@@ -30,8 +33,14 @@ class VoucherTypeViewTests(LoggedInTestCase):
         voucher_type = create_voucher_type()
         study_subject = create_study_subject()
         study_subject.voucher_types.add(voucher_type)
+
+        usage_partner = create_voucher_partner()
+        usage_partner.voucher_types.add(voucher_type)
+        usage_partner.save()
+
         visit_detail_form = VoucherForm()
         form_data = {
+            "usage_partner": usage_partner.id,
             "status": VOUCHER_STATUS_NEW,
             "voucher_type": voucher_type.id
         }
@@ -46,13 +55,16 @@ class VoucherTypeViewTests(LoggedInTestCase):
 
     def test_edit_voucher(self):
         voucher = create_voucher()
+        usage_partner = create_voucher_partner()
+        usage_partner.voucher_types.add(voucher.voucher_type)
+        usage_partner.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"] = ""
-        form_data["use_date"] = ""
+        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)
-- 
GitLab