From 1b631ac450b46770e560c91caeda77556cecdc86 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Benjamin=20H=C3=A4ttasch?=
 <benjamin.haettasch@fachschaft.informatik.tu-darmstadt.de>
Date: Sat, 22 Oct 2022 15:34:39 +0200
Subject: [PATCH] Introduce default slots

Create model
Create migration
Create admin interface
---
 AKModel/admin.py                         | 22 +++++++++++++++++-
 AKModel/migrations/0054_default_slots.py | 29 ++++++++++++++++++++++++
 AKModel/models.py                        | 27 ++++++++++++++++++++++
 3 files changed, 77 insertions(+), 1 deletion(-)
 create mode 100644 AKModel/migrations/0054_default_slots.py

diff --git a/AKModel/admin.py b/AKModel/admin.py
index ff73729d..65f4b6a6 100644
--- a/AKModel/admin.py
+++ b/AKModel/admin.py
@@ -16,7 +16,7 @@ from simple_history.admin import SimpleHistoryAdmin
 from AKModel.availability.forms import AvailabilitiesFormMixin
 from AKModel.availability.models import Availability
 from AKModel.models import Event, AKOwner, AKCategory, AKTrack, AKTag, AKRequirement, AK, AKSlot, Room, AKOrgaMessage, \
-    ConstraintViolation
+    ConstraintViolation, DefaultSlot
 from AKModel.urls import get_admin_urls_event_wizard, get_admin_urls_event
 from AKModel.views import CVMarkResolvedView, CVSetLevelViolationView, CVSetLevelWarningView, AKResetInterestView, \
     AKResetInterestCounterView, PlanPublishView, PlanUnpublishView
@@ -393,3 +393,23 @@ class ConstraintViolationAdmin(admin.ModelAdmin):
     def set_warning(self, request, queryset):
         selected = queryset.values_list('pk', flat=True)
         return HttpResponseRedirect(f"{reverse_lazy('admin:cv-set-warning')}?pks={','.join(str(pk) for pk in selected)}")
+
+
+class DefaultSlotAdminForm(forms.ModelForm):
+    class Meta:
+        widgets = {
+            'primary_categories': forms.CheckboxSelectMultiple
+        }
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        # Filter possible values for foreign keys & m2m when event is specified
+        if hasattr(self.instance, "event") and self.instance.event is not None:
+            self.fields["primary_categories"].queryset = AKCategory.objects.filter(event=self.instance.event)
+
+
+@admin.register(DefaultSlot)
+class DefaultSlotAdmin(admin.ModelAdmin):
+    list_display = ['start', 'end', 'event']
+    list_filter = ['event']
+    form = DefaultSlotAdminForm
diff --git a/AKModel/migrations/0054_default_slots.py b/AKModel/migrations/0054_default_slots.py
new file mode 100644
index 00000000..d8876223
--- /dev/null
+++ b/AKModel/migrations/0054_default_slots.py
@@ -0,0 +1,29 @@
+# Generated by Django 3.2.16 on 2022-10-22 12:18
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('AKModel', '0053_plan_published_at'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='DefaultSlot',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('start', models.DateTimeField(help_text='Time and date the slot begins', verbose_name='Slot Begin')),
+                ('end', models.DateTimeField(help_text='Time and date the slot ends', verbose_name='Slot End')),
+                ('event', models.ForeignKey(help_text='Associated event', on_delete=django.db.models.deletion.CASCADE, to='AKModel.event', verbose_name='Event')),
+                ('primary_categories', models.ManyToManyField(blank=True, help_text='Categories that should be assigned to this slot primarily', to='AKModel.AKCategory', verbose_name='Primary categories')),
+            ],
+            options={
+                'verbose_name': 'Default Slot',
+                'verbose_name_plural': 'Default Slots',
+                'ordering': ['-start'],
+            },
+        ),
+    ]
diff --git a/AKModel/models.py b/AKModel/models.py
index a1896eac..fe8b9a7f 100644
--- a/AKModel/models.py
+++ b/AKModel/models.py
@@ -650,3 +650,30 @@ class ConstraintViolation(models.Model):
             if getattr(self, field) != getattr(other, field):
                 return False
         return True
+
+
+class DefaultSlot(models.Model):
+    class Meta:
+        verbose_name = _('Default Slot')
+        verbose_name_plural = _('Default Slots')
+        ordering = ['-start']
+
+    start = models.DateTimeField(verbose_name=_('Slot Begin'), help_text=_('Time and date the slot begins'))
+    end = models.DateTimeField(verbose_name=_('Slot End'), help_text=_('Time and date the slot ends'))
+
+    event = models.ForeignKey(to=Event, on_delete=models.CASCADE, verbose_name=_('Event'),
+                              help_text=_('Associated event'))
+
+    primary_categories = models.ManyToManyField(to=AKCategory, verbose_name=_('Primary categories'), blank=True,
+                                            help_text=_('Categories that should be assigned to this slot primarily'))
+
+    @property
+    def start_simplified(self):
+        return self.start.astimezone(self.event.timezone).strftime('%a %H:%M')
+
+    @property
+    def end_simplified(self):
+        return self.end.astimezone(self.event.timezone).strftime('%a %H:%M')
+
+    def __str__(self):
+        return f"{self.event}: {self.start_simplified} - {self.end_simplified}"
-- 
GitLab