diff --git a/smash/web/forms/voucher_forms.py b/smash/web/forms/voucher_forms.py index 7067d0d9d83ce82ae24d88a0d072ab66faa6944a..b446eaf8b7b5ffd7f00f6c4fc91c67dc9888a876 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_USED, VOUCHER_STATUS_EXPIRED from web.models.worker_study_role import WORKER_VOUCHER_PARTNER logger = logging.getLogger(__name__) @@ -52,35 +52,29 @@ 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 in [VOUCHER_STATUS_USED, 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 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) - if instance.status == VOUCHER_STATUS_USED and not instance.use_date: - instance.use_date = timezone.now() - + 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 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 0000000000000000000000000000000000000000..706ab5d53cc719ee48ea8749d307d3cf2dd64300 --- /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/forms/worker_form.py b/smash/web/forms/worker_form.py index 8d5fdc67251217d3cfa75f7bf6bd1e2bb1c34f84..1237b46b5634196b51450b4eada03e0b235d7586 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 0000000000000000000000000000000000000000..2c8782702f04b11d11b85c7e6dde091187f8c5b4 --- /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/migrations/0111_auto_20180601_1318.py b/smash/web/migrations/0111_auto_20180601_1318.py new file mode 100644 index 0000000000000000000000000000000000000000..d666a0b0b011d8e2b3d16b2aba6fcaf373a171a7 --- /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 5db58bb977dc42c08b437e45c91ca1e542e8be0b..0ef157f4b99f0f009eec4f5de0cca8f20a651305 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 340b78764e16e537b72809a29f767811b105650d..7de7d71443b2038e7af377f1a27868fda80dd33c 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, @@ -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, @@ -48,8 +54,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/voucher_partner_session.py b/smash/web/models/voucher_partner_session.py new file mode 100644 index 0000000000000000000000000000000000000000..84a25b5fb396fc30aa184e21242bcd0495271d4d --- /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/models/worker.py b/smash/web/models/worker.py index ab5ec2c19b57f35c17c63bb670de78c2be419f56..b3dde9b892d7e7fb9e16ccf5817a231be03b9b2b 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/templates/includes/subject_vouchers_box.html b/smash/web/templates/includes/subject_vouchers_box.html index 36638b10787183d64546baaa7fc5d2ec3810f496..a17610a2a9e70bf1ff3d106b2a57eeeca09c3211 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 0000000000000000000000000000000000000000..80de643c37241a99c5fd273208150e0fda4c5247 --- /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 0000000000000000000000000000000000000000..73b82a9ed963c0a6b4b1f6272b29a8c5251167e4 --- /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 8e5e5dfbaf497bf4a88f70ded534fd2e8ef92a8f..488467ec25e1bd6a4184b4e60e82ea118bf6a92f 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 in 'NEW,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 d0f242e76cf2e0159b03cc12b22a8ece5c974f01..1b29b2965c072b85dd28d1342adb9417809791fa 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 c95063e2dadb08234ea3485346b5fc9263f9052f..71031d21400246576f383ac3b71ba7b22a2ed995 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 @@ -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 0bebd3af31ceefe79b5dcf8ee4aba7f230175144..f7da4add1364911a0e51a2015cfe53842f754b06 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 f8c71ab90e31c7b544a39d4091ff4f871e8dd9e4..18609fb8775bef36a332864257817c34dbc7461b 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,9 +33,16 @@ 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, + "hours": 10, "voucher_type": voucher_type.id } for key, value in visit_detail_form.initial.items(): @@ -40,19 +50,22 @@ 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()) 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 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 0000000000000000000000000000000000000000..4b8033291eb0600defc0274a5c9ca848e3565d42 --- /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 3816e9c4a5129cccdc84351fd2818e115c285c92..63496dee167e3951c5c7957bdc0e8c9888609c0d 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 a0c8a353160dbc8b61c6ab861cfe113ab539fba9..e3e10f3171d3085795180a820c611940bac8250b 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 6d7dd7d8e4fdd337cdd4fe58a5c58359ec905492..45b5a8f4f850aba0e19084b8ebefe3a2a44471dc 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 0000000000000000000000000000000000000000..58697f912635a0d0b462870666a686f456b10b22 --- /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']})