[^/]+)/public$', PlanCategoryPublicView.as_view(), name='overview_category_public'),
+ url(r'^timeslot/new/$', TimeSlotCreateView.as_view(), name='timeslot_create'),
+ url(r'^timeslot/new/success/$', TimeSlotCreateSuccessView.as_view(), name='timeslot_create_success'),
+]
diff --git a/plan/dashboard_views.py b/plan/dashboard_views.py
new file mode 100644
index 00000000..39f8adc2
--- /dev/null
+++ b/plan/dashboard_views.py
@@ -0,0 +1,63 @@
+from django.urls import reverse_lazy
+from django.views.generic import CreateView, ListView, TemplateView, DetailView
+from django.utils.translation import ugettext_lazy as _
+
+from dashboard.components import DashboardAppMixin
+from ophasebase.models import OphaseCategory, Ophase
+from plan.forms import TimeSlotForm
+from plan.models import TimeSlot
+
+
+class PlanAppMixin(DashboardAppMixin):
+ app_name_verbose = "Plan"
+ app_name = 'plan'
+ permissions = ['plan.add_timeslot']
+
+ @property
+ def sidebar_links(self):
+ return [
+ (_('Übersicht'), self.prefix_reverse_lazy('overview')),
+ (_('Neuer Timeslot'), self.prefix_reverse_lazy('timeslot_create')),
+ ]
+
+
+class PlanOverview(PlanAppMixin, ListView):
+ model = TimeSlot
+ context_object_name = "time_slots"
+ template_name = "plan/schedule.html"
+
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context["categories"] = Ophase.current().ophaseactivecategory_set.all()
+ return context
+
+
+class PlanCategoryView(PlanAppMixin, DetailView):
+ model = OphaseCategory
+ context_object_name = "category"
+ template_name = "plan/schedule_category.html"
+
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context["categories"] = Ophase.current().ophaseactivecategory_set.all()
+ context["time_slots"] = context["category"].timeslot_set.all()
+ return context
+
+
+class PlanCategoryPublicView(PlanCategoryView):
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context["time_slots"] = context["time_slots"].filter(public=True)
+ context["public"] = True
+ return context
+
+
+class TimeSlotCreateView(PlanAppMixin, CreateView):
+ success_url = reverse_lazy("dashboard:plan:timeslot_create_success")
+ template_name = "plan/timeslot_create.html"
+ model = TimeSlot
+ form_class = TimeSlotForm
+
+
+class TimeSlotCreateSuccessView(PlanAppMixin, TemplateView):
+ template_name = "plan/timeslot_create_success.html"
diff --git a/plan/dashboard_widgets.py b/plan/dashboard_widgets.py
new file mode 100644
index 00000000..e69de29b
diff --git a/plan/forms.py b/plan/forms.py
new file mode 100644
index 00000000..52094804
--- /dev/null
+++ b/plan/forms.py
@@ -0,0 +1,14 @@
+from django import forms
+
+from .models import TimeSlot
+
+
+class TimeSlotForm(forms.ModelForm):
+ class Meta:
+ model = TimeSlot
+ fields = ['name', 'slottype', 'begin', 'end', 'category', 'relevant_for', 'attendance_required', 'public']
+ widgets = {
+ # use checkboxes for multipleChoice @see http://stackoverflow.com/a/16937145
+ 'category': forms.CheckboxSelectMultiple,
+ # TODO Use DateTimePicker
+ }
diff --git a/plan/migrations/0001_initial.py b/plan/migrations/0001_initial.py
new file mode 100644
index 00000000..d3b6044c
--- /dev/null
+++ b/plan/migrations/0001_initial.py
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.5 on 2017-04-10 14:47
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('staff', '0018_person_tutor_experience'),
+ ('ophasebase', '0007_auto_20170215_1416'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='SlotType',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=50)),
+ ('color', models.CharField(default='#FFFFFF', max_length=7)),
+ ],
+ options={
+ 'verbose_name_plural': 'Veranstaltungsarten',
+ 'verbose_name': 'Veranstaltungsart',
+ 'ordering': ['name'],
+ },
+ ),
+ migrations.CreateModel(
+ name='TimeSlot',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=100, verbose_name='Name')),
+ ('begin', models.DateTimeField(verbose_name='Beginn')),
+ ('end', models.DateTimeField(verbose_name='Ende')),
+ ('attendance_required', models.BooleanField(default=False)),
+ ('public', models.BooleanField(default=False)),
+ ('category', models.ManyToManyField(to='ophasebase.OphaseCategory')),
+ ('ophase', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='ophasebase.Ophase')),
+ ('relevant_for', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='staff.StaffFilterGroup', verbose_name='Filterkriterium: Wer muss anwesend sein?')),
+ ('room', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='ophasebase.Room', verbose_name='Raum')),
+ ('slottype', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='plan.SlotType')),
+ ],
+ options={
+ 'verbose_name_plural': 'Zeitslots',
+ 'verbose_name': 'Zeitslot',
+ 'ordering': ['begin'],
+ },
+ ),
+ ]
diff --git a/plan/migrations/0002_auto_20170410_1702.py b/plan/migrations/0002_auto_20170410_1702.py
new file mode 100644
index 00000000..d57eee05
--- /dev/null
+++ b/plan/migrations/0002_auto_20170410_1702.py
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11 on 2017-04-10 15:02
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('staff', '0018_person_tutor_experience'),
+ ('ophasebase', '0007_auto_20170215_1416'),
+ ('plan', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Event',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('room', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='ophasebase.Room', verbose_name='Raum')),
+ ],
+ options={
+ 'verbose_name': 'Event',
+ 'verbose_name_plural': 'Events',
+ },
+ ),
+ migrations.RemoveField(
+ model_name='timeslot',
+ name='room',
+ ),
+ migrations.AddField(
+ model_name='event',
+ name='timeslot',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='plan.TimeSlot', verbose_name='Zeitslot'),
+ ),
+ migrations.AddField(
+ model_name='event',
+ name='tutorgroup',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='staff.TutorGroup', verbose_name='Kleingruppe'),
+ ),
+ migrations.AlterUniqueTogether(
+ name='event',
+ unique_together=set([('timeslot', 'tutorgroup')]),
+ ),
+ ]
diff --git a/plan/migrations/0003_auto_20170410_1825.py b/plan/migrations/0003_auto_20170410_1825.py
new file mode 100644
index 00000000..0418e0d4
--- /dev/null
+++ b/plan/migrations/0003_auto_20170410_1825.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11 on 2017-04-10 16:25
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('ophasebase', '0007_auto_20170215_1416'),
+ ('plan', '0002_auto_20170410_1702'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Booking',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('begin', models.DateTimeField(verbose_name='Anfang')),
+ ('end', models.DateTimeField(verbose_name='Ende')),
+ ('status', models.PositiveSmallIntegerField(choices=[(1, 'Gebucht'), (2, 'Blockiert'), (3, 'Anfragen?'), (4, 'Angefragt'), (5, 'Überlappung')])),
+ ('comment', models.TextField(blank=True, verbose_name='Kommentar')),
+ ('room', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='ophasebase.Room', verbose_name='Raum')),
+ ],
+ options={
+ 'verbose_name': 'Raumbuchung',
+ 'verbose_name_plural': 'Raumbuchungen',
+ },
+ ),
+ migrations.AlterField(
+ model_name='timeslot',
+ name='relevant_for',
+ field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='staff.StaffFilterGroup', verbose_name='Filterkriterium: Wer könnte anwesend sein?'),
+ ),
+ ]
diff --git a/plan/migrations/0004_auto_20170410_1946.py b/plan/migrations/0004_auto_20170410_1946.py
new file mode 100644
index 00000000..c6737cd2
--- /dev/null
+++ b/plan/migrations/0004_auto_20170410_1946.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11 on 2017-04-10 17:46
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('plan', '0003_auto_20170410_1825'),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name='booking',
+ options={'ordering': ['room', '-begin'], 'verbose_name': 'Raumbuchung', 'verbose_name_plural': 'Raumbuchungen'},
+ ),
+ ]
diff --git a/plan/migrations/0005_auto_20170813_1338.py b/plan/migrations/0005_auto_20170813_1338.py
new file mode 100644
index 00000000..0c384527
--- /dev/null
+++ b/plan/migrations/0005_auto_20170813_1338.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2017-08-13 11:38
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('plan', '0004_auto_20170410_1946'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='slottype',
+ name='split_groups',
+ field=models.BooleanField(default=False, verbose_name='In Kleingruppen aufteilen?'),
+ ),
+ migrations.AlterField(
+ model_name='timeslot',
+ name='relevant_for',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='staff.StaffFilterGroup', verbose_name='Filterkriterium: Wer könnte anwesend sein?'),
+ ),
+ ]
diff --git a/plan/migrations/__init__.py b/plan/migrations/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/plan/models.py b/plan/models.py
new file mode 100644
index 00000000..83efd955
--- /dev/null
+++ b/plan/models.py
@@ -0,0 +1,132 @@
+from django.db import models
+from django.db.models.signals import post_save, m2m_changed
+from django.dispatch import receiver
+from django.utils.translation import ugettext_lazy as _
+
+from ophasebase.models import Ophase, Room, OphaseCategory
+from staff.models import TutorGroup
+
+
+class SlotType(models.Model):
+ class Meta:
+ verbose_name = _("Veranstaltungsart")
+ verbose_name_plural = _("Veranstaltungsarten")
+ ordering = ['name']
+
+ name = models.CharField(max_length=50, blank=False)
+ color = models.CharField(max_length=7, default="#FFFFFF", blank=False)
+ split_groups = models.BooleanField(verbose_name=_("In Kleingruppen aufteilen?"), default=False, blank=True)
+
+ def __str__(self):
+ return self.name
+
+
+class TimeSlot(models.Model):
+ """Time slot for events"""
+ class Meta:
+ verbose_name = _("Zeitslot")
+ verbose_name_plural = _("Zeitslots")
+ ordering = ['begin']
+
+ name = models.CharField(max_length=100, verbose_name=_("Name"))
+ slottype = models.ForeignKey(SlotType, on_delete=models.CASCADE)
+ begin = models.DateTimeField(verbose_name=_("Beginn"))
+ end = models.DateTimeField(verbose_name=_("Ende"))
+ category = models.ManyToManyField(OphaseCategory)
+ relevant_for = models.ForeignKey("staff.StaffFilterGroup", verbose_name=_("Filterkriterium: Wer könnte anwesend sein?"), blank=True, null=True, on_delete=models.SET_NULL)
+ attendance_required = models.BooleanField(blank=True, default=False)
+ ophase = models.ForeignKey(Ophase, models.CASCADE)
+ public = models.BooleanField(blank=True, default=False)
+
+ @classmethod
+ def get_current_events(cls, **kwargs):
+ return cls.objects.filter(ophase=Ophase.current(), **kwargs)
+
+ def __str__(self):
+ return self.name
+
+ def save(self, *args, **kwargs):
+ if self.ophase_id is None:
+ # set Ophase to current active one. We assume that there is only one active Ophase at the same time!
+ self.ophase = Ophase.current()
+ super().save(*args, **kwargs)
+
+
+class Event(models.Model):
+ class Meta:
+ verbose_name = _('Event')
+ verbose_name_plural = _('Events')
+ unique_together = ['timeslot', 'tutorgroup']
+
+ timeslot = models.ForeignKey(TimeSlot, verbose_name=_('Zeitslot'), on_delete=models.CASCADE)
+ room = models.ForeignKey(Room, null=True, verbose_name=_("Raum"), blank=True, on_delete=models.SET_NULL)
+ tutorgroup = models.ForeignKey(TutorGroup, null=True, verbose_name=_('Kleingruppe'), blank=True, on_delete=models.CASCADE)
+
+ def __str__(self):
+ if self.tutorgroup is not None:
+ return "{} ({})".format(str(self.timeslot), str(self.tutorgroup))
+ return str(self.timeslot)
+
+ @staticmethod
+ @receiver(post_save, sender=TimeSlot)
+ def handle_timeslot_created(sender, instance, created, **kwargs):
+ """
+ Create corresponding event for a recently created timeslot
+ Only those kind of timeslot that require only one event are considered by this callback
+
+ :param created: A boolean; True if a new record was created
+ :param instance: The actual instance being saved (timeslot)
+ :param sender: The model class
+ """
+
+ # Create a single event if groups don't have to be split
+ if not instance.slottype.split_groups:
+ Event.objects.create(timeslot=instance)
+
+ @staticmethod
+ # @receiver(m2m_changed, sender=TimeSlot.category.though)
+ def handle_timeslot_created(sender, instance, action, **kwargs):
+ """
+ Create corresponding events for a recently created timeslot
+ Only those kind of timeslot that require only mulitple event are considered by this callback
+
+ :param instance: The actual instance being saved (timeslot)
+ :param sender: The model class
+ """
+
+ # Added categories? Split groups?
+ if action == "post_add" and instance.slottype.split_groups:
+ # Create events for all tutorgroups in all categories
+ for category in instance.category.all():
+ for tg in category.tutorgroup_set.all():
+ if not Event.objects.filter(timeslot=instance, tutorgroup=tg).exists():
+ Event.objects.create(
+ timeslot=instance,
+ tutorgroup=tg
+ )
+
+m2m_changed.connect(Event.handle_timeslot_created, sender=TimeSlot.category.through)
+
+
+class Booking(models.Model):
+ class Meta:
+ verbose_name = _('Raumbuchung')
+ verbose_name_plural = _('Raumbuchungen')
+ ordering = ['room', '-begin']
+
+ STATUS_CHOICES = (
+ (1, _('Gebucht')),
+ (2, _('Blockiert')),
+ (3, _('Anfragen?')),
+ (4, _('Angefragt')),
+ (5, _('Überlappung')),
+ )
+
+ room = models.ForeignKey(Room, verbose_name=_('Raum'), on_delete=models.CASCADE)
+ begin = models.DateTimeField(verbose_name=_('Anfang'))
+ end = models.DateTimeField(verbose_name=_('Ende'))
+ status = models.PositiveSmallIntegerField(choices=STATUS_CHOICES)
+ comment = models.TextField(verbose_name=_('Kommentar'), blank=True)
+
+ def __str__(self):
+ return "{} ({} - {})".format(self.room, self.begin, self.end)
diff --git a/plan/templates/plan/schedule.html b/plan/templates/plan/schedule.html
new file mode 100644
index 00000000..7cb5d342
--- /dev/null
+++ b/plan/templates/plan/schedule.html
@@ -0,0 +1,28 @@
+{% extends "dashboard/action.html" %}{% load bootstrap3 %}
+{% load i18n %}
+
+{% block title %}{% trans "Plan" %}{% endblock %}
+
+{% block content_dashboard_view %}
+
+
+
+ {% trans "Plan" %}
+
+ {% for ts in time_slots %}
+ {{ ts.name }}: {{ ts.begin }} - {{ ts.end }}
+ {% empty %}
+ {% trans "Keine Termine geplant" %}
+ {% endfor %}
+
+{% endblock %}
diff --git a/plan/templates/plan/schedule_category.html b/plan/templates/plan/schedule_category.html
new file mode 100644
index 00000000..855b0ae2
--- /dev/null
+++ b/plan/templates/plan/schedule_category.html
@@ -0,0 +1,28 @@
+{% extends "dashboard/action.html" %}{% load bootstrap3 %}
+{% load i18n %}
+
+{% block title %}{% trans "Plan" %}{% endblock %}
+
+{% block content_dashboard_view %}
+
+
+
+ {% trans "Plan" %}: {{ category.name }} {% if public %}({% trans "Öffentliche Termine" %}){% endif %}
+
+ {% for ts in time_slots %}
+ {{ ts.name }}: {{ ts.begin }} - {{ ts.end }}
+ {% empty %}
+ {% trans "Keine Termine geplant" %}
+ {% endfor %}
+
+{% endblock %}
diff --git a/plan/templates/plan/timeslot_create.html b/plan/templates/plan/timeslot_create.html
new file mode 100644
index 00000000..f67980c4
--- /dev/null
+++ b/plan/templates/plan/timeslot_create.html
@@ -0,0 +1,25 @@
+{% extends "dashboard/action.html" %}{% load bootstrap3 %}
+{% load i18n %}
+
+{% block title %}{% trans "TimeSlot anlegen" %}{% endblock %}
+
+{% block content_dashboard_view %}
+
+ {% trans "TimeSlot anlegen" %}
+
+
+
+
+
+{% endblock %}
diff --git a/plan/templates/plan/timeslot_create_success.html b/plan/templates/plan/timeslot_create_success.html
new file mode 100644
index 00000000..6616fbb3
--- /dev/null
+++ b/plan/templates/plan/timeslot_create_success.html
@@ -0,0 +1,16 @@
+{% extends "dashboard/action.html" %}{% load bootstrap3 %}
+{% load i18n %}
+
+{% block title %}{% trans "TimeSlot anlegen" %}{% endblock %}
+
+{% block content_dashboard_view %}
+ {% trans "TimeSlot anlegen" %}
+
+ {% trans "TimeSlot angelegt" %}
+
+
+
+{% endblock %}
diff --git a/plan/tests.py b/plan/tests.py
new file mode 100644
index 00000000..7ce503c2
--- /dev/null
+++ b/plan/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/plan/views.py b/plan/views.py
new file mode 100644
index 00000000..91ea44a2
--- /dev/null
+++ b/plan/views.py
@@ -0,0 +1,3 @@
+from django.shortcuts import render
+
+# Create your views here.
diff --git a/pyophase/settings.py b/pyophase/settings.py
index ba1b3bb5..63829d03 100644
--- a/pyophase/settings.py
+++ b/pyophase/settings.py
@@ -53,6 +53,7 @@
'exam',
'workshops',
'clothing',
+ 'plan'
)
MIDDLEWARE = (
diff --git a/staff/admin.py b/staff/admin.py
index b6508af5..4632bf62 100644
--- a/staff/admin.py
+++ b/staff/admin.py
@@ -14,7 +14,7 @@
staff_nametag_export,
staff_overview_export,
tutorgroup_export,
- update_attendees, mark_attendance_x, mark_attendance_a, mark_attendance_e, mark_phoned_x, mark_phoned_e,
+ mark_attendance_x, mark_attendance_a, mark_attendance_e, mark_phoned_x, mark_phoned_e,
mark_phoned_n, mark_attendance_v, generate_orga_cert)
from .models import (
HelperJob,
@@ -24,7 +24,6 @@
TutorGroup,
StaffFilterGroup,
Attendance,
- AttendanceEvent,
OrgaSelectedJob, HelperSelectedJob)
@@ -147,19 +146,6 @@ def person_phone(event):
return event.person.phone
-@admin.register(AttendanceEvent)
-class AttendanceAdmin(admin.ModelAdmin):
- list_display = ['name', 'begin', 'end', 'required_for', 'link_attendance_list']
- actions = [update_attendees]
-
- @staticmethod
- def link_attendance_list(event):
- return format_html('{name}',
- url=reverse('admin:staff_attendance_changelist'),
- id=event.pk,
- name=_('Teilnehmerliste'))
-
-
@admin.register(Settings)
class SettingsAdmin(admin.ModelAdmin):
list_display = ['tutor_registration_enabled', 'orga_registration_enabled', 'helper_registration_enabled']
diff --git a/staff/admin_actions.py b/staff/admin_actions.py
index 2f530bdf..d6c38271 100644
--- a/staff/admin_actions.py
+++ b/staff/admin_actions.py
@@ -246,17 +246,6 @@ def generate_orga_cert(modeladmin, request, queryset):
generate_orga_cert.short_description = _('Orga-Bescheinigungen drucken')
-def update_attendees(modeladmin, request, queryset):
- for event in queryset:
- existing_pesons = event.attendance_set.values("person")
- required_for_queryset = event.required_for.get_filtered_staff()
- new_attendees = required_for_queryset.exclude(pk__in=existing_pesons)
-
- Attendance.objects.bulk_create([Attendance(event=event, person=person, status='x') for person in new_attendees])
- modeladmin.message_user(request, _("Teilnehmerliste aktualisiert."))
-update_attendees.short_description = _("Liste der Teilnehmer aktualisieren (anhand des Zielgruppenfilters)")
-
-
def mark_attendance_x(modeladmin, request, queryset):
queryset.update(status='x')
modeladmin.message_user(request, _("Als 'nicht anwesend' markiert."))
diff --git a/staff/dashboard_views.py b/staff/dashboard_views.py
index 6e0db1f2..9fdc85d3 100644
--- a/staff/dashboard_views.py
+++ b/staff/dashboard_views.py
@@ -8,8 +8,9 @@
from dashboard.components import DashboardAppMixin
from ophasebase.models import Ophase, OphaseCategory
+from plan.models import TimeSlot
from .dashboard_forms import GroupMassCreateForm, TutorPairingForm
-from .models import Person, TutorGroup, AttendanceEvent, OrgaJob, OrgaSelectedJob, HelperJob, HelperSelectedJob
+from .models import Person, TutorGroup, OrgaJob, OrgaSelectedJob, HelperJob, HelperSelectedJob
class StaffAppMixin(DashboardAppMixin):
@@ -152,13 +153,13 @@ class TutorPairingSuccess(StaffAppMixin, TemplateView):
class AttendanceEventIndexView(StaffAppMixin, ListView):
permissions = ['staff.edit_attendance']
- model = AttendanceEvent
+ model = TimeSlot
template_name = "staff/dashboard/events_overview.html"
context_object_name = "events"
class AttendanceEventDetailView(StaffAppMixin, DetailView):
permissions = ['staff.edit_attendance']
- model = AttendanceEvent
+ model = TimeSlot
template_name = "staff/dashboard/event.html"
context_object_name = "event"
diff --git a/staff/migrations/0019_auto_20170410_1946.py b/staff/migrations/0019_auto_20170410_1946.py
new file mode 100644
index 00000000..0d3065cf
--- /dev/null
+++ b/staff/migrations/0019_auto_20170410_1946.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11 on 2017-04-10 17:46
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('staff', '0018_person_tutor_experience'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='attendanceevent',
+ name='ophase',
+ ),
+ migrations.RemoveField(
+ model_name='attendanceevent',
+ name='required_for',
+ ),
+ migrations.RemoveField(
+ model_name='attendanceevent',
+ name='room',
+ ),
+ migrations.AlterField(
+ model_name='attendance',
+ name='event',
+ field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='plan.TimeSlot', verbose_name='Anwesenheitstermin'),
+ ),
+ migrations.DeleteModel(
+ name='AttendanceEvent',
+ ),
+ ]
diff --git a/staff/migrations/0023_merge_20170813_1201.py b/staff/migrations/0023_merge_20170813_1201.py
new file mode 100644
index 00000000..a81cc96f
--- /dev/null
+++ b/staff/migrations/0023_merge_20170813_1201.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2017-08-13 10:01
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('staff', '0019_auto_20170410_1946'),
+ ('staff', '0022_auto_20170706_0002'),
+ ]
+
+ operations = [
+ ]
diff --git a/staff/models.py b/staff/models.py
index 094bfaf9..4598c81c 100644
--- a/staff/models.py
+++ b/staff/models.py
@@ -266,7 +266,7 @@ class Meta:
("e", _("angerufen + erreicht"))
)
- event = models.ForeignKey("AttendanceEvent", on_delete=models.CASCADE, verbose_name=_("Anwesenheitstermin"))
+ event = models.ForeignKey("plan.TimeSlot", null=True, on_delete=models.CASCADE, verbose_name=_("Anwesenheitstermin"))
person = models.ForeignKey(Person, on_delete=models.CASCADE, verbose_name=_("Person"))
status = models.CharField(max_length=1, choices=STATUS_CHOICES, default="x", verbose_name=_('Status'))
phone_status = models.CharField(max_length=1, choices=PHONECALL_CHOICES, default="x", verbose_name=_('Telefoniestatus'))
@@ -276,28 +276,6 @@ def __str__(self):
return "{} @ {}: {} ({})".format(self.person, self.event, self.get_status_display(), self.get_phone_status_display())
-class AttendanceEvent(models.Model):
- """An attendance event"""
- class Meta:
- verbose_name = _("Anwesenheitstermin")
- verbose_name_plural = _("Anwesenheitstermine")
- ordering = ['begin']
-
- name = models.CharField(max_length=100, verbose_name=_("Name"))
- begin = models.DateTimeField(verbose_name=_("Beginn"))
- end = models.DateTimeField(verbose_name=_("Ende"))
- required_for = models.ForeignKey(StaffFilterGroup, verbose_name=_("Filterkriterium: Wer muss anwesend sein?"), null=True, on_delete=models.SET_NULL)
- ophase = models.ForeignKey(Ophase, models.CASCADE)
- room = models.ForeignKey(Room, null=True, verbose_name=_("Raum"), blank=True, on_delete=models.SET_NULL)
-
- @staticmethod
- def get_current_events(**kwargs):
- return AttendanceEvent.objects.filter(ophase=Ophase.current(), **kwargs)
-
- def __str__(self):
- return self.name
-
-
class Settings(models.Model):
"""Configuration for Staff App."""
class Meta: