diff --git a/requirements.txt b/requirements.txt
index a4015bf9..777295e8 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,7 @@
coverage==4.3.4
-Django==1.10.5
-django-debug-toolbar==1.6
+Django==1.10.6
+django-debug-toolbar==1.7
docutils==0.13.1
-sqlparse==0.2.2
+sqlparse==0.2.3
freezegun==0.3.8
django-formtools==2.0
diff --git a/src/feedback/forms.py b/src/feedback/forms.py
index ee9cb8f0..bbe9db49 100644
--- a/src/feedback/forms.py
+++ b/src/feedback/forms.py
@@ -165,6 +165,16 @@ class Meta:
fields = ('anschrift', 'fachgebiet')
+CLOSE_ORDER_CHOICES = (
+ ('ja', 'Ja'),
+ ('nein', 'Nein')
+)
+
+
+class CloseOrderForm(forms.Form):
+ auswahl = forms.ChoiceField(choices=CLOSE_ORDER_CHOICES)
+
+
class CreateBarcodeScannEventForm(forms.ModelForm):
"""Handelt die erste haelfte von Barcode scanns"""
scanner_token = forms.CharField()
diff --git a/src/feedback/migrations/0035_auto_20170313_1743.py b/src/feedback/migrations/0035_auto_20170313_1743.py
new file mode 100644
index 00000000..8ef254d6
--- /dev/null
+++ b/src/feedback/migrations/0035_auto_20170313_1743.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.6 on 2017-03-13 17:43
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('feedback', '0034_auto_20170207_1854'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='barcodeallowedstate',
+ name='allow_state',
+ field=models.IntegerField(choices=[(100, 'Angelegt'), (200, 'Bestellung ge\xf6ffnet'), (300, 'Keine Evaluation'), (310, 'Keine Evaluation final'), (500, 'Bestellung liegt vor'), (510, 'Bestellung wird verarbeitet'), (600, 'Gedruckt'), (700, 'Versandt'), (800, 'B\xf6gen eingegangen'), (900, 'B\xf6gen gescannt'), (1000, 'Ergebnisse versandt')], null=True, unique=True),
+ ),
+ migrations.AlterField(
+ model_name='log',
+ name='status',
+ field=models.IntegerField(choices=[(100, 'Angelegt'), (200, 'Bestellung ge\xf6ffnet'), (300, 'Keine Evaluation'), (310, 'Keine Evaluation final'), (500, 'Bestellung liegt vor'), (510, 'Bestellung wird verarbeitet'), (600, 'Gedruckt'), (700, 'Versandt'), (800, 'B\xf6gen eingegangen'), (900, 'B\xf6gen gescannt'), (1000, 'Ergebnisse versandt')], default=100),
+ ),
+ migrations.AlterField(
+ model_name='veranstaltung',
+ name='status',
+ field=models.IntegerField(choices=[(100, 'Angelegt'), (200, 'Bestellung ge\xf6ffnet'), (300, 'Keine Evaluation'), (310, 'Keine Evaluation final'), (500, 'Bestellung liegt vor'), (510, 'Bestellung wird verarbeitet'), (600, 'Gedruckt'), (700, 'Versandt'), (800, 'B\xf6gen eingegangen'), (900, 'B\xf6gen gescannt'), (1000, 'Ergebnisse versandt')], default=100),
+ ),
+ ]
diff --git a/src/feedback/models/base.py b/src/feedback/models/base.py
index f8f62d39..3ed2ef5b 100644
--- a/src/feedback/models/base.py
+++ b/src/feedback/models/base.py
@@ -318,7 +318,9 @@ class Veranstaltung(models.Model):
STATUS_ANGELEGT = 100
STATUS_BESTELLUNG_GEOEFFNET = 200
STATUS_KEINE_EVALUATION = 300
+ STATUS_KEINE_EVALUATION_FINAL = 310
STATUS_BESTELLUNG_LIEGT_VOR = 500
+ STATUS_BESTELLUNG_WIRD_VERARBEITET = 510
STATUS_GEDRUCKT = 600
STATUS_VERSANDT = 700
STATUS_BOEGEN_EINGEGANGEN = 800
@@ -329,7 +331,9 @@ class Veranstaltung(models.Model):
(STATUS_ANGELEGT, 'Angelegt'),
(STATUS_BESTELLUNG_GEOEFFNET, 'Bestellung geöffnet'),
(STATUS_KEINE_EVALUATION, 'Keine Evaluation'),
+ (STATUS_KEINE_EVALUATION_FINAL, 'Keine Evaluation final'),
(STATUS_BESTELLUNG_LIEGT_VOR, 'Bestellung liegt vor'),
+ (STATUS_BESTELLUNG_WIRD_VERARBEITET, 'Bestellung wird verarbeitet'),
(STATUS_GEDRUCKT, 'Gedruckt'),
(STATUS_VERSANDT, 'Versandt'),
(STATUS_BOEGEN_EINGEGANGEN, 'Bögen eingegangen'),
diff --git a/src/feedback/tests/test_views_intern.py b/src/feedback/tests/test_views_intern.py
index bf79f0d5..f6e78858 100644
--- a/src/feedback/tests/test_views_intern.py
+++ b/src/feedback/tests/test_views_intern.py
@@ -1,434 +1,494 @@
-# coding=utf-8
-
-import os
-
-from StringIO import StringIO
-
-from django.conf import settings
-from django.core import mail
-from django.test import TestCase
-from django.core.urlresolvers import reverse
-
-from feedback.forms import UploadFileForm
-from feedback.models import Semester, Person, Veranstaltung, Fragebogen2009, Mailvorlage, Einstellung, \
- Fachgebiet, FachgebietEmail
-from feedback.tests.tools import NonSuTestMixin, get_veranstaltung
-
-from feedback import tests
-
-
-class InternMiscTest(NonSuTestMixin, TestCase):
- def test_index(self):
- path = tests.INDEX_END
- self.do_non_su_test(path)
- self.client.login(username='supers', password='pw')
-
- s = Semester.objects.create(semester=20110, fragebogen='2009', sichtbarkeit='ADM')
-
- response = self.client.get(path, **{'REMOTE_USER': 'super'})
- self.assertEqual(response.templates[0].name, 'intern/index.html')
- self.assertEqual(response.context['cur_semester'], s)
-
- def test_fragebogensprache(self):
- path = '/intern/fragebogensprache/'
- self.do_non_su_test(path)
- self.client.login(username='supers', password='pw')
-
- Semester.objects.create(semester=20110, fragebogen='2009', sichtbarkeit='ADM')
-
- response = self.client.get(path, **{'REMOTE_USER': 'super'})
- self.assertEqual(response.templates[0].name, 'intern/fragebogensprache.html')
-
- def test_export_veranstaltungen_get(self):
- path = '/intern/export_veranstaltungen/'
- self.do_non_su_test(path)
- self.client.login(username='supers', password='pw')
-
- response = self.client.get(path, **{'REMOTE_USER': 'super'})
- self.assertEqual(response.templates[0].name, 'intern/export_veranstaltungen.html')
- self.assertSequenceEqual(response.context['semester'], list(Semester.objects.all()))
-
-
-class ExportVeranstaltungenTest(NonSuTestMixin, TestCase):
- def test_export_veranstaltungen_post(self):
- path = '/intern/export_veranstaltungen/'
- self.client.login(username='supers', password='pw')
- self.client.login(username='supers', password='pw')
-
- _, v1 = get_veranstaltung('v')
- s, v2 = get_veranstaltung('vu')
- empty_semester = Semester.objects.create(semester=20120, fragebogen='2009', sichtbarkeit='ADM')
-
- p = Person.objects.create(vorname='Je', nachname='Mand', email='je@ma.nd', geschlecht='w')
- v1.veranstalter.add(p)
- v2.veranstalter.add(p)
-
- v1.grundstudium = True
- v1.sprache = 'en'
- v1.verantwortlich = p
- v1.save()
-
- # kein Semester angegeben
- response = self.client.post(path, **{'REMOTE_USER': 'super'})
- self.assertEqual(response.status_code, 302)
- self.assertTrue(response['Location'].endswith('/intern/export_veranstaltungen/'))
-
- # keine Bestellung vorhanden
- response = self.client.post(path, {'semester': s.semester}, **{'REMOTE_USER': 'super'})
- self.assertEqual(response.status_code, 302)
- self.assertTrue(response['Location'].endswith('/intern/export_veranstaltungen/'))
-
- # niemand als Verantwortlicher eingetragen
- v1.anzahl = 42
- v1.save()
- v2.anzahl = 23
- v2.save()
- response = self.client.post(path, {'semester': s.semester}, **{'REMOTE_USER': 'super'})
- self.assertEqual(response.status_code, 302)
- self.assertTrue(response['Location'].endswith('/intern/export_veranstaltungen/'))
-
- response = self.client.post(path, {'semester': empty_semester.semester, 'xml_ubung': True}, **{'REMOTE_USER': 'super'})
- self.assertEqual(response.status_code, 302)
- self.assertTrue(response['Location'].endswith('/intern/export_veranstaltungen/'))
-
- # keine Sprache angegeben
- v2.verantwortlich = p
- v2.save()
- response = self.client.post(path, {'semester': s.semester}, **{'REMOTE_USER': 'super'})
- self.assertEqual(response.status_code, 302)
- self.assertTrue(response['Location'].endswith('/intern/export_veranstaltungen/'))
-
- # alles OK
- v2.sprache = 'de'
- v2.save()
- response = self.client.post(path, {'semester': s.semester}, **{'REMOTE_USER': 'super'})
- self.assertRegexpMatches(response['Content-Disposition'],
- r'^attachment; filename="[a-zA-Z0-9_-]+\.xml"$')
-
- self.assertXMLEqual(response.content,
- '''
-
-
-
-
-
-Stoning I
-FB 20
-123v-SS11
-SS11
-Vorlesung
-42
-Informatik
-
-
-
-lv-1
-
-
-FB20Vv1e
-SS11
-coversheet
-0
-
-
-
-
-
-Stoning I
-FB 20
-123vu-SS11
-SS11
-Vorlesung + Übung
-23
-Informatik
-
-
-
-lv-2
-
-
-FB20Vv1
-SS11
-coversheet
-0
-
-
-''')
- response = self.client.post(path, {'semester': s.semester, 'xml_ubung': True}, **{'REMOTE_USER': 'super'})
- self.assertRegexpMatches(response['Content-Disposition'],
- r'^attachment; filename="[a-zA-Z0-9_-]+\.xml"$')
-
- self.assertXMLEqual(response.content, '''
-
-
-
-
-
-Stoning I
-FB 20
-123vu-SS11
-SS11
-Vorlesung + Übung
-23
-Informatik
-
-
-
-lv-2
-
-
-FB20\xc3\x9cv1
-SS11
-coversheet
-0
-
-
-''')
-
- def test_export_veranstaltungen_post_primaerdozent(self):
- path = '/intern/export_veranstaltungen/'
- self.client.login(username='supers', password='pw')
-
- s, v = get_veranstaltung('v')
- p1 = Person.objects.create(vorname='Je', nachname='Mand', email='je@ma.nd', geschlecht='w')
- p2 = Person.objects.create(vorname='Prim', nachname='Ardozent', email='prim@ardoz.ent', geschlecht='m')
- p3 = Person.objects.create(vorname='Je1', nachname='Mand1', email='je1@ma.nd', geschlecht='m')
-
- v.veranstalter.add(p1)
- v.veranstalter.add(p2)
- v.veranstalter.add(p3)
- v.ergebnis_empfaenger.add(p1)
- v.ergebnis_empfaenger.add(p2)
- v.ergebnis_empfaenger.add(p3)
-
- v.grundstudium = True
- v.sprache = 'en'
- v.verantwortlich = p1
- v.primaerdozent = p2
- v.anzahl = 42
- v.save()
-
- response = self.client.post(path, {'semester': s.semester}, **{'REMOTE_USER': 'super'})
- self.assertRegexpMatches(response['Content-Disposition'],
- r'^attachment; filename="[a-zA-Z0-9_-]+\.xml"$')
-
- self.assertXMLEqual(response.content,
- '''
-
-
-
-
-
-
-
-
-
-
-
-
-
-Stoning I
-FB 20
-123v-SS11
-SS11
-Vorlesung
-42
-Informatik
-
-
-
-lv-1
-
-
-FB20Vv1e
-SS11
-coversheet
-0
-
-
-Je
-Mand
-je@ma.nd
-f
-pe-1
-
-Prim
-Ardozent
-prim@ardoz.ent
-m
-pe-2
-
-Je1
-Mand1
-je1@ma.nd
-m
-pe-3
-
-
-''')
-
-
-#
-class ImportErgebnisseTest(NonSuTestMixin, TestCase):
- def setUp(self):
- super(ImportErgebnisseTest, self).setUp()
- self.path = '/intern/import_ergebnisse/'
- self.s = Semester.objects.create(semester=20110, fragebogen='2009', sichtbarkeit='ADM')
-
- def test_get(self):
- self.do_non_su_test(self.path)
- self.client.login(username='supers', password='pw')
-
- response = self.client.get(self.path, **{'REMOTE_USER': 'super'})
- self.assertEqual(response.templates[0].name, 'intern/import_ergebnisse.html')
- self.assertSequenceEqual(response.context['semester'], [self.s])
- self.assertTrue(isinstance(response.context['form'], UploadFileForm))
-
- def test_post(self):
- self.client.login(username='supers', password='pw')
- default_params = {'semester': self.s, 'grundstudium': False, 'evaluieren': True}
- Veranstaltung.objects.create(name='Test I', lv_nr='1', **default_params)
-
- # kein Semester angegeben
- response = self.client.post(self.path, **{'REMOTE_USER': 'super'})
- self.assertEqual(response.status_code, 302)
- self.assertTrue(response['Location'].endswith('/intern/import_ergebnisse/'))
-
- # unvollständiges Formular
- response = self.client.post(self.path, {'semester': self.s.semester, 'file': ''}, **{'REMOTE_USER': 'super'})
- self.assertEqual(response.templates[0].name, 'intern/import_ergebnisse.html')
-
- # fehlerhafte Datei angegeben
- f = StringIO('b;l;a;b;l;a;b;l;a')
- f.name = 'test.csv'
- response = self.client.post(self.path, {'semester': self.s.semester, 'file': f}, **{'REMOTE_USER': 'super'})
- f.close()
- self.assertEqual(response.status_code, 302)
- self.assertTrue(response['Location'].endswith('/intern/sync_ergebnisse/'))
-
- # alles OK
- with open(settings.TESTDATA_PATH + 'ergebnis_test_20115.csv', 'r') as f:
- response = self.client.post(self.path, {'semester': self.s.semester, 'file': f}, **{'REMOTE_USER': 'super'})
- self.assertEqual(response.status_code, 302)
- self.assertTrue(response['Location'].endswith('/intern/sync_ergebnisse/'))
-
-
-class SyncErgebnisseTest(NonSuTestMixin, TestCase):
- def setUp(self):
- super(SyncErgebnisseTest, self).setUp()
- self.path = '/intern/sync_ergebnisse/'
- self.s, self.v = get_veranstaltung('v')
-
- def test_get(self):
- self.do_non_su_test(self.path)
- self.client.login(username='supers', password='pw')
-
- response = self.client.get(self.path, **{'REMOTE_USER': 'super'})
- self.assertEqual(response.templates[0].name, 'intern/sync_ergebnisse.html')
- self.assertSequenceEqual(response.context['semester'], [self.s])
-
- def test_post(self):
- self.client.login(username='supers', password='pw')
-
- # kein Semester angegeben
- response = self.client.post(self.path, **{'REMOTE_USER': 'super'})
- self.assertEqual(response.status_code, 302)
- self.assertTrue(response['Location'].endswith('/intern/sync_ergebnisse/'))
-
- # keine Ergebnisse gefunden
- response = self.client.post(self.path, {'semester': self.s.semester}, **{'REMOTE_USER': 'super'})
- self.assertEqual(response.status_code, 302)
- self.assertTrue(response['Location'].endswith('/intern/sync_ergebnisse/'))
-
- # alles OK
- Fragebogen2009.objects.create(veranstaltung=self.v, ue_gesamt=1,
- ue_e=2, ue_f=3,
- ue_a=4, ue_b=5, ue_c=1, ue_d=2,
- ue_g=3, ue_i=4, ue_j=5, ue_k=1)
- response = self.client.post(self.path, {'semester': self.s.semester}, **{'REMOTE_USER': 'super'})
- self.assertEqual(response.status_code, 302)
- self.assertTrue(response['Location'].endswith('/intern/sync_ergebnisse/'))
-
-
-class SendmailTest(NonSuTestMixin, TestCase):
- path = '/intern/sendmail/'
-
- def test_get(self):
- self.do_non_su_test(self.path)
- self.client.login(username='supers', password='pw')
-
- response = self.client.get(self.path, **{'REMOTE_USER': 'super'})
- self.assertEqual(response.templates[0].name, 'intern/sendmail.html')
-
- def test_post(self):
- self.client.login(username='supers', password='pw')
- get_veranstaltung('v')
- s, v1 = get_veranstaltung('vu')
- v1.anzahl = 42
- v1.sprache = 'de'
- v1.save()
- fb = Fachgebiet.objects.create(name="Fachgebiet1", kuerzel="FB1")
- FachgebietEmail.objects.create(fachgebiet=fb, email_suffix="ul.bla", email_sekretaerin="sek@ul.bla")
- p1 = Person.objects.create(vorname='Pe', nachname='Ter', email='pe@ter.bla')
- p2 = Person.objects.create(vorname='Pa', nachname='Ul', email='pa@ul.bla', fachgebiet=fb)
-
- v1.veranstalter.add(p1)
- v1.veranstalter.add(p2)
- mv = Mailvorlage.objects.create(subject='Testmail', body='Dies ist eine Testmail.')
- Einstellung.objects.create(name='bestellung_erlaubt', wert='0')
-
- params = {'uebernehmen': 'x', 'recipient': 'cur_sem_missing_order', 'subject': 'abc', 'body': 'xyz'}
-
- # kein Semester angegeben
- response = self.client.post(self.path, params, **{'REMOTE_USER': 'super'})
- self.assertEqual(response.status_code, 302)
- self.assertTrue(response['Location'].endswith('/intern/sendmail/'))
-
- # Vorlage übernehmen; Vorlage nicht angegeben
- params['semester'] = s.semester
- response = self.client.post(self.path, params, **{'REMOTE_USER': 'super'})
- self.assertEqual(response.status_code, 302)
- self.assertTrue(response['Location'].endswith('/intern/sendmail/'))
-
- # Vorlage übernehmen; Vorlage ist angegeben
- params['vorlage'] = mv.id
- response = self.client.post(self.path, params, **{'REMOTE_USER': 'super'})
- self.assertEqual(response.templates[0].name, 'intern/sendmail.html')
- self.assertEqual(response.context['subject'], mv.subject)
- self.assertEqual(response.context['body'], mv.body)
-
- # Vorschau; Empfänger ist auf Veranstalter mit fehlenden Bestellungen eingestellt
- del params['uebernehmen']
- params['vorschau'] = 'x'
- response = self.client.post(self.path, params, **{'REMOTE_USER': 'super'})
- self.assertIn('intern/sendmail_preview.html', (t.name for t in response.templates))
- self.assertTrue(response.context['vorschau'])
-
- # Vorschau; Empfänger ist auf Veranstaltungen mit Ergebnissen eingestellt
- params['recipient'] = 'cur_sem_results'
- response = self.client.post(self.path, params, **{'REMOTE_USER': 'super'})
- self.assertIn('intern/sendmail_preview.html', (t.name for t in response.templates))
- self.assertTrue(response.context['vorschau'])
-
- # Vorschau: Check if the replacements are highlighted
- color_span = '{}'
- self.assertEqual(color_span.format('Grundlagen der Agrarphilosophie I') , response.context['veranstaltung'])
- link_veranstalter = 'https://www.fachschaft.informatik.tu-darmstadt.de%s' % reverse('veranstalter-login')
- link_suffix_format = '?vid=%d&token=%s'
- self.assertEqual(color_span.format(link_veranstalter + (link_suffix_format % (1337, '0123456789abcdef'))) , response.context['link_veranstalter'])
-
- # Senden
- del params['vorschau']
- params['senden'] = 'x'
- params['recipient'] = 'cur_sem_all'
- del params['vorlage']
- response = self.client.post(self.path, params, **{'REMOTE_USER': 'super'})
- self.assertEqual(response.status_code, 302)
- self.assertTrue(response['Location'], tests.LOGIN_URL)
- # Hier wird in Eclipse ein Fehler angezeigt; mail.outbox gibt es während der Testläufe
- # aber wirklich (siehe https://docs.djangoproject.com/en/1.4/topics/testing/#email-services)
- self.assertEqual(len(mail.outbox), 2)
- self.assertEqual(len(mail.outbox[0].to), 3) # an zwei veranstalter und sekretaerin
+# coding=utf-8
+
+from StringIO import StringIO
+
+from django.conf import settings
+from django.core import mail
+from django.test import TestCase
+from django.core.urlresolvers import reverse
+
+from feedback.forms import UploadFileForm
+from feedback.models import Semester, Person, Veranstaltung, Fragebogen2009, Mailvorlage, Einstellung, \
+ Fachgebiet, FachgebietEmail
+from feedback.tests.tools import NonSuTestMixin, get_veranstaltung
+
+from feedback import tests
+
+
+class CloseOrderTest(NonSuTestMixin, TestCase):
+ def setUp(self):
+ self.client.login(username='supers', password='pw')
+ self.s, self.v = get_veranstaltung('vu')
+
+ def test_close_order_bestellung_liegt_vor_post(self):
+ path = '/intern/status_final/'
+ self.v.status = Veranstaltung.STATUS_BESTELLUNG_LIEGT_VOR
+ self.v.save()
+
+ response = self.client.post(path, {'auswahl': 'ja', 'submit': 'Bestätigen'}, **{'REMOTE_USER': 'super'})
+
+ self.v.refresh_from_db()
+ self.assertEqual(response.status_code, 302)
+ self.assertEqual(self.v.status, Veranstaltung.STATUS_BESTELLUNG_WIRD_VERARBEITET)
+
+ def test_close_order_keine_evaluation_post(self):
+ path = '/intern/status_final/'
+ self.v.status = Veranstaltung.STATUS_KEINE_EVALUATION
+ self.v.save()
+
+ response = self.client.post(path, {'auswahl': 'ja', 'submit': 'Bestätigen'}, **{'REMOTE_USER': 'super'})
+
+ self.v.refresh_from_db()
+ self.assertEqual(response.status_code, 302)
+ self.assertEqual(self.v.status, Veranstaltung.STATUS_KEINE_EVALUATION_FINAL)
+
+ def test_close_order_status_angelegt_post(self):
+ path = '/intern/status_final/'
+ self.v.status = Veranstaltung.STATUS_ANGELEGT
+ self.v.save()
+
+ response = self.client.post(path, {'auswahl': 'ja', 'submit': 'Bestätigen'}, **{'REMOTE_USER': 'super'})
+
+ self.v.refresh_from_db()
+ self.assertEqual(response.status_code, 302)
+ self.assertEqual(self.v.status, Veranstaltung.STATUS_KEINE_EVALUATION_FINAL)
+
+ def test_close_order_bestellung_geoeffnet_post(self):
+ path = '/intern/status_final/'
+ self.v.status = Veranstaltung.STATUS_BESTELLUNG_GEOEFFNET
+ self.v.save()
+
+ response = self.client.post(path, {'auswahl': 'ja', 'submit': 'Bestätigen'}, **{'REMOTE_USER': 'super'})
+
+ self.v.refresh_from_db()
+ self.assertEqual(response.status_code, 302)
+ self.assertEqual(self.v.status, Veranstaltung.STATUS_KEINE_EVALUATION_FINAL)
+
+ def test_close_order_refuse(self):
+ path = '/intern/status_final/'
+ self.v.status = Veranstaltung.STATUS_BESTELLUNG_LIEGT_VOR
+ self.v.save()
+
+ response = self.client.post(path, {'auswahl': 'nein', 'submit': 'Bestätigen'}, **{'REMOTE_USER': 'super'})
+
+ self.v.refresh_from_db()
+ self.assertEqual(response.status_code, 302)
+ self.assertEqual(self.v.status, Veranstaltung.STATUS_BESTELLUNG_LIEGT_VOR)
+
+
+class InternMiscTest(NonSuTestMixin, TestCase):
+ def test_index(self):
+ path = tests.INDEX_END
+ self.do_non_su_test(path)
+ self.client.login(username='supers', password='pw')
+
+ s = Semester.objects.create(semester=20110, fragebogen='2009', sichtbarkeit='ADM')
+
+ response = self.client.get(path, **{'REMOTE_USER': 'super'})
+ self.assertEqual(response.templates[0].name, 'intern/index.html')
+ self.assertEqual(response.context['cur_semester'], s)
+
+ def test_fragebogensprache(self):
+ path = '/intern/fragebogensprache/'
+ self.do_non_su_test(path)
+ self.client.login(username='supers', password='pw')
+
+ Semester.objects.create(semester=20110, fragebogen='2009', sichtbarkeit='ADM')
+
+ response = self.client.get(path, **{'REMOTE_USER': 'super'})
+ self.assertEqual(response.templates[0].name, 'intern/fragebogensprache.html')
+
+ def test_export_veranstaltungen_get(self):
+ path = '/intern/export_veranstaltungen/'
+ self.do_non_su_test(path)
+ self.client.login(username='supers', password='pw')
+
+ response = self.client.get(path, **{'REMOTE_USER': 'super'})
+ self.assertEqual(response.templates[0].name, 'intern/export_veranstaltungen.html')
+ self.assertSequenceEqual(response.context['semester'], list(Semester.objects.all()))
+
+
+class ExportVeranstaltungenTest(NonSuTestMixin, TestCase):
+ def test_export_veranstaltungen_post(self):
+ path = '/intern/export_veranstaltungen/'
+ self.client.login(username='supers', password='pw')
+ self.client.login(username='supers', password='pw')
+
+ _, v1 = get_veranstaltung('v')
+ s, v2 = get_veranstaltung('vu')
+ empty_semester = Semester.objects.create(semester=20120, fragebogen='2009', sichtbarkeit='ADM')
+
+ p = Person.objects.create(vorname='Je', nachname='Mand', email='je@ma.nd', geschlecht='w')
+ v1.veranstalter.add(p)
+ v2.veranstalter.add(p)
+
+ v1.grundstudium = True
+ v1.sprache = 'en'
+ v1.verantwortlich = p
+ v1.save()
+
+ # kein Semester angegeben
+ response = self.client.post(path, **{'REMOTE_USER': 'super'})
+ self.assertEqual(response.status_code, 302)
+ self.assertTrue(response['Location'].endswith('/intern/export_veranstaltungen/'))
+
+ # keine Bestellung vorhanden
+ response = self.client.post(path, {'semester': s.semester}, **{'REMOTE_USER': 'super'})
+ self.assertEqual(response.status_code, 302)
+ self.assertTrue(response['Location'].endswith('/intern/export_veranstaltungen/'))
+
+ # niemand als Verantwortlicher eingetragen
+ v1.anzahl = 42
+ v1.save()
+ v2.anzahl = 23
+ v2.save()
+ response = self.client.post(path, {'semester': s.semester}, **{'REMOTE_USER': 'super'})
+ self.assertEqual(response.status_code, 302)
+ self.assertTrue(response['Location'].endswith('/intern/export_veranstaltungen/'))
+
+ response = self.client.post(path, {'semester': empty_semester.semester, 'xml_ubung': True}, **{'REMOTE_USER': 'super'})
+ self.assertEqual(response.status_code, 302)
+ self.assertTrue(response['Location'].endswith('/intern/export_veranstaltungen/'))
+
+ # keine Sprache angegeben
+ v2.verantwortlich = p
+ v2.save()
+ response = self.client.post(path, {'semester': s.semester}, **{'REMOTE_USER': 'super'})
+ self.assertEqual(response.status_code, 302)
+ self.assertTrue(response['Location'].endswith('/intern/export_veranstaltungen/'))
+
+ # alles OK
+ v2.sprache = 'de'
+ v2.save()
+ response = self.client.post(path, {'semester': s.semester}, **{'REMOTE_USER': 'super'})
+ self.assertRegexpMatches(response['Content-Disposition'],
+ r'^attachment; filename="[a-zA-Z0-9_-]+\.xml"$')
+
+ self.assertXMLEqual(response.content,
+ '''
+
+
+
+
+
+Stoning I
+FB 20
+123v-SS11
+SS11
+Vorlesung
+42
+Informatik
+
+
+
+lv-1
+
+
+FB20Vv1e
+SS11
+coversheet
+0
+
+
+
+
+
+Stoning I
+FB 20
+123vu-SS11
+SS11
+Vorlesung + Übung
+23
+Informatik
+
+
+
+lv-2
+
+
+FB20Vv1
+SS11
+coversheet
+0
+
+
+''')
+ response = self.client.post(path, {'semester': s.semester, 'xml_ubung': True}, **{'REMOTE_USER': 'super'})
+ self.assertRegexpMatches(response['Content-Disposition'],
+ r'^attachment; filename="[a-zA-Z0-9_-]+\.xml"$')
+
+ self.assertXMLEqual(response.content, '''
+
+
+
+
+
+Stoning I
+FB 20
+123vu-SS11
+SS11
+Vorlesung + Übung
+23
+Informatik
+
+
+
+lv-2
+
+
+FB20\xc3\x9cv1
+SS11
+coversheet
+0
+
+
+''')
+
+ def test_export_veranstaltungen_post_primaerdozent(self):
+ path = '/intern/export_veranstaltungen/'
+ self.client.login(username='supers', password='pw')
+
+ s, v = get_veranstaltung('v')
+ p1 = Person.objects.create(vorname='Je', nachname='Mand', email='je@ma.nd', geschlecht='w')
+ p2 = Person.objects.create(vorname='Prim', nachname='Ardozent', email='prim@ardoz.ent', geschlecht='m')
+ p3 = Person.objects.create(vorname='Je1', nachname='Mand1', email='je1@ma.nd', geschlecht='m')
+
+ v.veranstalter.add(p1)
+ v.veranstalter.add(p2)
+ v.veranstalter.add(p3)
+ v.ergebnis_empfaenger.add(p1)
+ v.ergebnis_empfaenger.add(p2)
+ v.ergebnis_empfaenger.add(p3)
+
+ v.grundstudium = True
+ v.sprache = 'en'
+ v.verantwortlich = p1
+ v.primaerdozent = p2
+ v.anzahl = 42
+ v.save()
+
+ response = self.client.post(path, {'semester': s.semester}, **{'REMOTE_USER': 'super'})
+ self.assertRegexpMatches(response['Content-Disposition'],
+ r'^attachment; filename="[a-zA-Z0-9_-]+\.xml"$')
+
+ self.assertXMLEqual(response.content,
+ '''
+
+
+
+
+
+
+
+
+
+
+
+
+
+Stoning I
+FB 20
+123v-SS11
+SS11
+Vorlesung
+42
+Informatik
+
+
+
+lv-1
+
+
+FB20Vv1e
+SS11
+coversheet
+0
+
+
+Je
+Mand
+je@ma.nd
+f
+pe-1
+
+Prim
+Ardozent
+prim@ardoz.ent
+m
+pe-2
+
+Je1
+Mand1
+je1@ma.nd
+m
+pe-3
+
+
+''')
+
+
+#
+class ImportErgebnisseTest(NonSuTestMixin, TestCase):
+ def setUp(self):
+ super(ImportErgebnisseTest, self).setUp()
+ self.path = '/intern/import_ergebnisse/'
+ self.s = Semester.objects.create(semester=20110, fragebogen='2009', sichtbarkeit='ADM')
+
+ def test_get(self):
+ self.do_non_su_test(self.path)
+ self.client.login(username='supers', password='pw')
+
+ response = self.client.get(self.path, **{'REMOTE_USER': 'super'})
+ self.assertEqual(response.templates[0].name, 'intern/import_ergebnisse.html')
+ self.assertSequenceEqual(response.context['semester'], [self.s])
+ self.assertTrue(isinstance(response.context['form'], UploadFileForm))
+
+ def test_post(self):
+ self.client.login(username='supers', password='pw')
+ default_params = {'semester': self.s, 'grundstudium': False, 'evaluieren': True}
+ Veranstaltung.objects.create(name='Test I', lv_nr='1', **default_params)
+
+ # kein Semester angegeben
+ response = self.client.post(self.path, **{'REMOTE_USER': 'super'})
+ self.assertEqual(response.status_code, 302)
+ self.assertTrue(response['Location'].endswith('/intern/import_ergebnisse/'))
+
+ # unvollständiges Formular
+ response = self.client.post(self.path, {'semester': self.s.semester, 'file': ''}, **{'REMOTE_USER': 'super'})
+ self.assertEqual(response.templates[0].name, 'intern/import_ergebnisse.html')
+
+ # fehlerhafte Datei angegeben
+ f = StringIO('b;l;a;b;l;a;b;l;a')
+ f.name = 'test.csv'
+ response = self.client.post(self.path, {'semester': self.s.semester, 'file': f}, **{'REMOTE_USER': 'super'})
+ f.close()
+ self.assertEqual(response.status_code, 302)
+ self.assertTrue(response['Location'].endswith('/intern/sync_ergebnisse/'))
+
+ # alles OK
+ with open(settings.TESTDATA_PATH + 'ergebnis_test_20115.csv', 'r') as f:
+ response = self.client.post(self.path, {'semester': self.s.semester, 'file': f}, **{'REMOTE_USER': 'super'})
+ self.assertEqual(response.status_code, 302)
+ self.assertTrue(response['Location'].endswith('/intern/sync_ergebnisse/'))
+
+
+class SyncErgebnisseTest(NonSuTestMixin, TestCase):
+ def setUp(self):
+ super(SyncErgebnisseTest, self).setUp()
+ self.path = '/intern/sync_ergebnisse/'
+ self.s, self.v = get_veranstaltung('v')
+
+ def test_get(self):
+ self.do_non_su_test(self.path)
+ self.client.login(username='supers', password='pw')
+
+ response = self.client.get(self.path, **{'REMOTE_USER': 'super'})
+ self.assertEqual(response.templates[0].name, 'intern/sync_ergebnisse.html')
+ self.assertSequenceEqual(response.context['semester'], [self.s])
+
+ def test_post(self):
+ self.client.login(username='supers', password='pw')
+
+ # kein Semester angegeben
+ response = self.client.post(self.path, **{'REMOTE_USER': 'super'})
+ self.assertEqual(response.status_code, 302)
+ self.assertTrue(response['Location'].endswith('/intern/sync_ergebnisse/'))
+
+ # keine Ergebnisse gefunden
+ response = self.client.post(self.path, {'semester': self.s.semester}, **{'REMOTE_USER': 'super'})
+ self.assertEqual(response.status_code, 302)
+ self.assertTrue(response['Location'].endswith('/intern/sync_ergebnisse/'))
+
+ # alles OK
+ Fragebogen2009.objects.create(veranstaltung=self.v, ue_gesamt=1,
+ ue_e=2, ue_f=3,
+ ue_a=4, ue_b=5, ue_c=1, ue_d=2,
+ ue_g=3, ue_i=4, ue_j=5, ue_k=1)
+ response = self.client.post(self.path, {'semester': self.s.semester}, **{'REMOTE_USER': 'super'})
+ self.assertEqual(response.status_code, 302)
+ self.assertTrue(response['Location'].endswith('/intern/sync_ergebnisse/'))
+
+
+class SendmailTest(NonSuTestMixin, TestCase):
+ path = '/intern/sendmail/'
+
+ def test_get(self):
+ self.do_non_su_test(self.path)
+ self.client.login(username='supers', password='pw')
+
+ response = self.client.get(self.path, **{'REMOTE_USER': 'super'})
+ self.assertEqual(response.templates[0].name, 'intern/sendmail.html')
+
+ def test_post(self):
+ self.client.login(username='supers', password='pw')
+ get_veranstaltung('v')
+ s, v1 = get_veranstaltung('vu')
+ v1.anzahl = 42
+ v1.sprache = 'de'
+ v1.save()
+
+ fb = Fachgebiet.objects.create(name="Fachgebiet1", kuerzel="FB1")
+ FachgebietEmail.objects.create(fachgebiet=fb, email_suffix="ul.bla", email_sekretaerin="sek@ul.bla")
+ p1 = Person.objects.create(vorname='Pe', nachname='Ter', email='pe@ter.bla')
+ p2 = Person.objects.create(vorname='Pa', nachname='Ul', email='pa@ul.bla', fachgebiet=fb)
+
+ v1.veranstalter.add(p1)
+ v1.veranstalter.add(p2)
+ mv = Mailvorlage.objects.create(subject='Testmail', body='Dies ist eine Testmail.')
+ Einstellung.objects.create(name='bestellung_erlaubt', wert='0')
+
+ params = {'uebernehmen': 'x', 'recipient': 'cur_sem_missing_order', 'subject': 'abc', 'body': 'xyz'}
+
+ # kein Semester angegeben
+ response = self.client.post(self.path, params, **{'REMOTE_USER': 'super'})
+ self.assertEqual(response.status_code, 302)
+ self.assertTrue(response['Location'].endswith('/intern/sendmail/'))
+
+ # Vorlage übernehmen; Vorlage nicht angegeben
+ params['semester'] = s.semester
+ response = self.client.post(self.path, params, **{'REMOTE_USER': 'super'})
+ self.assertEqual(response.status_code, 302)
+ self.assertTrue(response['Location'].endswith('/intern/sendmail/'))
+
+ # Vorlage übernehmen; Vorlage ist angegeben
+ params['vorlage'] = mv.id
+ response = self.client.post(self.path, params, **{'REMOTE_USER': 'super'})
+ self.assertEqual(response.templates[0].name, 'intern/sendmail.html')
+ self.assertEqual(response.context['subject'], mv.subject)
+ self.assertEqual(response.context['body'], mv.body)
+
+ # Vorschau; Empfänger ist auf Veranstalter mit fehlenden Bestellungen eingestellt
+ del params['uebernehmen']
+ params['vorschau'] = 'x'
+ response = self.client.post(self.path, params, **{'REMOTE_USER': 'super'})
+ self.assertIn('intern/sendmail_preview.html', (t.name for t in response.templates))
+ self.assertTrue(response.context['vorschau'])
+
+ # Vorschau; Empfänger ist auf Veranstaltungen mit Ergebnissen eingestellt
+ params['recipient'] = 'cur_sem_results'
+ response = self.client.post(self.path, params, **{'REMOTE_USER': 'super'})
+ self.assertIn('intern/sendmail_preview.html', (t.name for t in response.templates))
+ self.assertTrue(response.context['vorschau'])
+
+ # Vorschau: Check if the replacements are highlighted
+ color_span = '{}'
+ self.assertEqual(color_span.format('Grundlagen der Agrarphilosophie I') , response.context['veranstaltung'])
+ link_veranstalter = 'https://www.fachschaft.informatik.tu-darmstadt.de%s' % reverse('veranstalter-login')
+ link_suffix_format = '?vid=%d&token=%s'
+ self.assertEqual(color_span.format(link_veranstalter + (link_suffix_format % (1337, '0123456789abcdef'))) , response.context['link_veranstalter'])
+
+ # Senden
+ del params['vorschau']
+ params['senden'] = 'x'
+ params['recipient'] = 'cur_sem_all'
+ del params['vorlage']
+ response = self.client.post(self.path, params, **{'REMOTE_USER': 'super'})
+ self.assertEqual(response.status_code, 302)
+ self.assertTrue(response['Location'], tests.LOGIN_URL)
+ # Hier wird in Eclipse ein Fehler angezeigt; mail.outbox gibt es während der Testläufe
+ # aber wirklich (siehe https://docs.djangoproject.com/en/1.4/topics/testing/#email-services)
+ self.assertEqual(len(mail.outbox), 2)
+ self.assertEqual(len(mail.outbox[0].to), 3) # an zwei veranstalter und sekretaerin
diff --git a/src/feedback/views/intern/__init__.py b/src/feedback/views/intern/__init__.py
index 74d3bc3c..ddb686df 100644
--- a/src/feedback/views/intern/__init__.py
+++ b/src/feedback/views/intern/__init__.py
@@ -1,6 +1,5 @@
# coding=utf-8
-import csv
import os
import subprocess
@@ -14,21 +13,25 @@
from django.template import RequestContext
from django.utils.encoding import smart_str
from django.views.decorators.http import require_safe, require_http_methods
+from django.contrib.auth.mixins import UserPassesTestMixin
+from django.views.generic import FormView
from feedback import tools
+from feedback.forms import CloseOrderForm
from feedback.parser.ergebnisse import parse_ergebnisse
from feedback.models import Veranstaltung, Semester, Einstellung, Mailvorlage, get_model, long_not_ordert, FachgebietEmail
from feedback.forms import UploadFileForm
from feedback.views import public
from django.db.models import Q
+
@user_passes_test(lambda u: u.is_superuser)
@require_safe
def index(request):
cur_semester = Semester.current()
all_veranst = Veranstaltung.objects.filter(semester=cur_semester)
- #Veranstaltung für die es Rückmeldungen gibt
+ # Veranstaltung für die es Rückmeldungen gibt
ruck_veranst = all_veranst.filter(Q(anzahl__gt=0)|Q(evaluieren=False))
num_all_veranst = all_veranst.count()
@@ -36,7 +39,7 @@ def index(request):
relativ_result = 0
- if (num_all_veranst >= 1):
+ if num_all_veranst >= 1:
relativ_result = (100/float(num_all_veranst)) * num_ruck_veranst
width_progressbar = 500
@@ -49,11 +52,13 @@ def index(request):
'width_progressbar': width_progressbar,
'width_progressbar_success': width_progressbar_success,})
+
@user_passes_test(lambda u: u.is_superuser)
@require_safe
def lange_ohne_evaluation(request):
return render(request, 'intern/lange_ohne_evaluation.html', {'veranstaltungen': long_not_ordert()})
+
@user_passes_test(lambda u: u.is_superuser)
@require_safe
def fragebogensprache(request):
@@ -64,6 +69,7 @@ def fragebogensprache(request):
data = {'veranstaltungen': veranstaltungen}
return render(request, 'intern/fragebogensprache.html', data)
+
@user_passes_test(lambda u: u.is_superuser)
@require_http_methods(('HEAD', 'GET', 'POST'))
def export_veranstaltungen(request):
@@ -111,10 +117,11 @@ def export_veranstaltungen(request):
person_set = set()
- data = {}
+ data = {
+ 'veranst': veranst,
+ 'ubung_export': ubung_export
+ }
- data['veranst'] = veranst
- data['ubung_export'] = ubung_export
for ver in veranst:
for cur_empf in ver.ergebnis_empfaenger.all():
person_set.add(cur_empf)
@@ -135,24 +142,28 @@ def export_veranstaltungen(request):
def translate_to_latex(text):
- dic = {'&':'\&',
- '%':'\%',
- '$':'\$',
- '#':'\#',
- '_':'\_',
- '"':'"{}',
- '~':'\~{}',
- '^':'\\textasciicircum',
+ dic = {
+ '&': '\&',
+ '%': '\%',
+ '$': '\$',
+ '#': '\#',
+ '_': '\_',
+ '"': '"{}',
+ '~': '\~{}',
+ '^': '\\textasciicircum',
}
+
for i, j in dic.iteritems():
text = text.replace(i, j)
return text
+
@user_passes_test(lambda u: u.is_superuser)
@require_http_methods(('HEAD', 'GET', 'POST'))
def generate_letters(request):
- data = {}
- data['semester'] = Semester.objects.all()
+ data = {
+ 'semester': Semester.objects.all()
+ }
datefilename = settings.LATEX_PATH + 'erhebungswoche.inc'
@@ -184,7 +195,7 @@ def generate_letters(request):
templatename = 'aufkleber'
# aus Sicherheitsgründen TeX-Befehle in Abgabedatum-String deaktivieren
- #TODO: Kalender-Widget einführen, nur noch dessen Format akzeptieren
+ # TODO: Kalender-Widget einführen, nur noch dessen Format akzeptieren
try:
abgabedatum = request.POST['erhebungswoche'].replace('\\', '')
except KeyError:
@@ -194,6 +205,7 @@ def generate_letters(request):
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename=%s.pdf' % (templatename)
+
if vorlage != 'Aufkleber':
veranst = Veranstaltung.objects.filter(semester=semester, evaluieren=True, anzahl__gt=0).order_by('sprache','anzahl')
elif 'anzahlaufkleber' in request.POST and request.POST['anzahlaufkleber'].isdigit():
@@ -202,19 +214,20 @@ def generate_letters(request):
veranst = Veranstaltung.objects.filter(semester=semester, evaluieren=True, anzahl__gt=anzahl).order_by('sprache','anzahl')
else:
veranst = Veranstaltung.objects.filter(semester=semester, evaluieren=True, anzahl__gt=0).order_by('sprache','anzahl')
+
if not veranst.count():
messages.error(request, 'Für das ausgewählte Semester (%s) liegen keine Bestellungen vor oder die Mindesteilnehmeranzahl ist zu hoch!' % semester)
return HttpResponseRedirect(reverse('generate_letters'))
lines = []
for v in veranst:
- eva_id=v.get_barcode_number()
+ eva_id = v.get_barcode_number()
empfaenger = unicode(v.verantwortlich.full_name())
line = u'\\adrentry{%s}{%s}{%s}{%s}{%s}{%s}{%s}{%s}{%s}\n' % (
translate_to_latex(v.verantwortlich.full_name()), translate_to_latex(v.verantwortlich.anschrift), translate_to_latex(v.name), v.anzahl, v.sprache, v.get_typ_display(), eva_id, v.freiefrage1.strip(), v.freiefrage2.strip())
lines.append(smart_str(line))
- #TODO: prüfen, ob nötige Dateien schreibbar sind (abgabedatum.inc, anschreiben.{log,aux,pdf}, veranstalter.adr)
+ # TODO: prüfen, ob nötige Dateien schreibbar sind (abgabedatum.inc, anschreiben.{log,aux,pdf}, veranstalter.adr)
with open(latexpath + 'veranstalter.adr', 'w') as f:
f.writelines(lines)
@@ -234,12 +247,14 @@ def generate_letters(request):
response.write(f.read())
return response
+
@user_passes_test(lambda u: u.is_superuser)
@require_http_methods(('HEAD', 'GET', 'POST'))
def sendmail(request):
- data = {}
- data['semester'] = Semester.objects.order_by('-semester')
- data['vorlagen'] = Mailvorlage.objects.all()
+ data = {
+ 'semester': Semester.objects.order_by('-semester'),
+ 'vorlagen': Mailvorlage.objects.all()
+ }
if request.method == 'POST':
try:
@@ -357,9 +372,10 @@ def import_ergebnisse(request):
if form.is_valid():
warnings, errors, vcount, fbcount = parse_ergebnisse(semester, request.FILES['file'])
if fbcount:
- messages.success(request,
- u'%u Veranstaltungen mit insgesamt %u Fragebögen wurden erfolgreich importiert.' %
- (vcount, fbcount))
+ messages.success(
+ request,
+ u'%u Veranstaltungen mit insgesamt %u Fragebögen wurden erfolgreich importiert.' % (vcount, fbcount)
+ )
else:
warnings.append(u'Es konnten keine Fragebögen importiert werden.')
@@ -376,6 +392,7 @@ def import_ergebnisse(request):
return render(request, 'intern/import_ergebnisse.html', data)
+
@user_passes_test(lambda u: u.is_superuser)
@require_http_methods(('HEAD', 'GET', 'POST'))
def sync_ergebnisse(request):
@@ -388,21 +405,21 @@ def sync_ergebnisse(request):
except (Semester.DoesNotExist, KeyError):
return HttpResponseRedirect(reverse('sync_ergebnisse'))
- Fragebogen = get_model('Fragebogen', semester)
- Ergebnis = get_model('Ergebnis', semester)
- Ergebnis.objects.filter(veranstaltung__semester=semester).delete()
+ fragebogen = get_model('Fragebogen', semester)
+ ergebnis = get_model('Ergebnis', semester)
+ ergebnis.objects.filter(veranstaltung__semester=semester).delete()
found_something = False
for v in Veranstaltung.objects.filter(semester=semester):
- fbs = Fragebogen.objects.filter(veranstaltung=v)
+ fbs = fragebogen.objects.filter(veranstaltung=v)
if len(fbs):
found_something = True
data = {'veranstaltung': v, 'anzahl': len(fbs)}
- for part in Ergebnis.parts + Ergebnis.hidden_parts:
- result, count = tools.get_average(Ergebnis, fbs, part[0])
+ for part in ergebnis.parts + ergebnis.hidden_parts:
+ result, count = tools.get_average(ergebnis, fbs, part[0])
data[part[0]] = result
data[part[0]+'_count'] = count
- Ergebnis.objects.create(**data)
+ ergebnis.objects.create(**data)
if not found_something:
messages.warning(request, u'Für das %s liegen keine Ergebnisse vor.' % semester)
@@ -410,6 +427,59 @@ def sync_ergebnisse(request):
messages.success(request, u'Das Ranking für das %s wurde erfolgreich berechnet.' % semester)
return HttpResponseRedirect(reverse('sync_ergebnisse'))
+
@user_passes_test(lambda u: u.is_superuser)
def ergebnisse(request):
return public.index(request)
+
+
+def is_no_evaluation_final(status):
+ return status == Veranstaltung.STATUS_KEINE_EVALUATION or status == Veranstaltung.STATUS_ANGELEGT or \
+ status == Veranstaltung.STATUS_BESTELLUNG_GEOEFFNET
+
+
+def update_veranstaltungen_status(veranstaltungen):
+ for v in veranstaltungen:
+ if is_no_evaluation_final(v.status):
+ v.status = Veranstaltung.STATUS_KEINE_EVALUATION_FINAL
+ v.save()
+ elif v.status == Veranstaltung.STATUS_BESTELLUNG_LIEGT_VOR:
+ v.status = Veranstaltung.STATUS_BESTELLUNG_WIRD_VERARBEITET
+ v.save()
+
+
+class CloseOrderFormView(UserPassesTestMixin, FormView):
+ template_name = 'intern/status_final.html'
+ form_class = CloseOrderForm
+
+ def post(self, request, *args, **kwargs):
+ form_class = self.get_form_class()
+ form = self.get_form(form_class)
+ if form.is_valid:
+ choice = self.get_form_kwargs().get('data').get('auswahl')
+ if choice == 'ja':
+ return self.form_valid(form)
+ else:
+ return self.form_invalid(form)
+
+ def form_valid(self, form):
+ update_veranstaltungen_status(self.get_queryset())
+ messages.success(self.request, u'Alle Status wurden erfolgreich aktualisiert.')
+ return super(CloseOrderFormView, self).form_valid(form)
+
+ def form_invalid(self, form):
+ return HttpResponseRedirect(reverse('intern-index'))
+
+ def get_queryset(self):
+ try:
+ veranstaltungen = Veranstaltung.objects.filter(semester=Semester.current())
+ return veranstaltungen
+ except (Veranstaltung.DoesNotExist, KeyError):
+ messages.warning(self.request, u'Keine passenden Veranstaltungen für das aktuelle Semester gefunden.')
+ return HttpResponseRedirect(reverse('intern-index'))
+
+ def get_success_url(self):
+ return reverse('intern-index')
+
+ def test_func(self):
+ return self.request.user.is_superuser
diff --git a/src/feedback/views/veranstalter.py b/src/feedback/views/veranstalter.py
index dc31ba75..a59d10ef 100644
--- a/src/feedback/views/veranstalter.py
+++ b/src/feedback/views/veranstalter.py
@@ -46,9 +46,8 @@ def veranstalter_dashboard(request):
data["logs"] = Log.objects.filter(veranstaltung=veranst).order_by('timestamp')
data["allow_order"] = veranst.allow_order()
- if veranst.status >= Veranstaltung.STATUS_BESTELLUNG_GEOEFFNET:
- bestellung = []
- bestellung.append(("Evaluieren", veranst.get_evaluieren_display))
+ if veranst.status >= Veranstaltung.STATUS_BESTELLUNG_LIEGT_VOR:
+ bestellung = [("Evaluieren", veranst.get_evaluieren_display)]
if veranst.evaluieren:
bestellung.append(("Typ", veranst.get_typ_display))
bestellung.append(("Anazhl", veranst.anzahl))
diff --git a/src/templates/intern/index.html b/src/templates/intern/index.html
index 2dc7d4b3..1757eed2 100644
--- a/src/templates/intern/index.html
+++ b/src/templates/intern/index.html
@@ -1,35 +1,43 @@
-{% extends "bestellung_base.html" %} {% block title %}Interner Bereich{% endblock %} {% block content %}
-
Interner Bereich
-
-Status der Rückmeldungen durch die Veranstalter
-Aktuell haben wir {{ruck_veranst}} Rückmeldungen von {{all_veranst}} Veranstaltungen.
-
-
-
{{relativ_result|floatformat:-2}}%
+{% extends "bestellung_base.html" %}
+{% load static %}
+{% block title %}
+ Interner Bereich
+{% endblock %}
+
+{% block content %}
+
Interner Bereich
+
+
Status der Rückmeldungen durch die Veranstalter
+
Aktuell haben wir {{ruck_veranst}} Rückmeldungen von {{all_veranst}} Veranstaltungen.
+
+
+
{{relativ_result|floatformat:-2}}%
+
-
-
Ablauf
-
Dies sind nicht alle nötigen Schritte; siehe Ablauf im Trac.
-
- - neues Semester anlegen (aktuell:
- {% if cur_semester %}{{cur_semester.short}}{% else %}nicht Vorhanden{% endif %})
- - Veranstaltungen aus VV importieren (vor Bestellphase)
- - Fehlende Personendaten nachtragen (vor Bestellphase)
- - Anschreiben für Veranstalter erzeugen (nach Bestellphase)
- - Veranstaltungen für EvaSys exportieren (vor dem Scannen)
- - Ergebnisse aus EvaSys importieren (nach dem Scannen)
- - Rankings berechnen (nach dem Ergebnis-Import)
- {% if cur_semester %}
- - Ergebnisse veröffentlichen (aktuell: sichtbar für {{cur_semester.get_sichtbarkeit_display}})
- {% endif %}
-
+
Ablauf
+
Dies sind nicht alle nötigen Schritte; siehe Ablauf im Trac.
+
+
+ - neues Semester anlegen (aktuell:
+ {% if cur_semester %}{{cur_semester.short}}{% else %}nicht Vorhanden{% endif %})
+ - Veranstaltungen aus VV importieren (vor Bestellphase)
+ - Fehlende Personendaten nachtragen (vor Bestellphase)
+ - Bestellphase abschließen (nach Bestellphase)
+ - Anschreiben für Veranstalter erzeugen (nach Bestellphase)
+ - Veranstaltungen für EvaSys exportieren (vor dem Scannen)
+ - Ergebnisse aus EvaSys importieren (nach dem Scannen)
+ - Rankings berechnen (nach dem Ergebnis-Import)
+ {% if cur_semester %}
+ - Ergebnisse veröffentlichen (aktuell: sichtbar für {{cur_semester.get_sichtbarkeit_display}})
+ {% endif %}
+
{% endblock %}
{% block backlink %}{% endblock %}
diff --git a/src/templates/intern/status_final.html b/src/templates/intern/status_final.html
new file mode 100644
index 00000000..026d7390
--- /dev/null
+++ b/src/templates/intern/status_final.html
@@ -0,0 +1,15 @@
+{% extends "bestellung_base.html" %}
+{% load static %}
+{% block title %}
+ Interner Bereich
+{% endblock %}
+
+{% block content %}
+
Bestellphase abschließen?
+
Sie sind dabei die Bestellphase zu beenden. Möchten Sie das wirklich tun?
+
+{% endblock %}
\ No newline at end of file
diff --git a/src/urls.py b/src/urls.py
index 966a4b02..2d3f4b96 100644
--- a/src/urls.py
+++ b/src/urls.py
@@ -63,6 +63,7 @@
url(r'^intern/export_veranstaltungen/$', feedback.views.intern.export_veranstaltungen, name='export_veranstaltungen'),
url(r'^intern/generate_letters/$', feedback.views.intern.generate_letters, name='generate_letters'),
url(r'^intern/import_ergebnisse/$', feedback.views.intern.import_ergebnisse, name='import_ergebnisse'),
+ url(r'^intern/status_final/$', feedback.views.intern.CloseOrderFormView.as_view(), name='status_final'),
url(r'^intern/sync_ergebnisse/$', feedback.views.intern.sync_ergebnisse, name='sync_ergebnisse'),
url(r'^intern/fragebogensprache/$', feedback.views.intern.fragebogensprache, name='fragebogensprache'),
url(r'^intern/lange_ohne_evaluation/$', feedback.views.intern.lange_ohne_evaluation, name='lange_ohne_evaluation'),