Matthias Nagel d45fc54280 Feat: Wiederkehrende Trainingsevents
Fügt die Funktionalität hinzu, wiederkehrende Trainingsevents zu erstellen,
zu verwalten und zu löschen. Ein Coach kann nun ein Training erstellen,
das sich alle X Tage bis zu einem bestimmten Enddatum wiederholt.

Wesentliche Änderungen:
- **Datenmodell ():** Das -Modell wurde um Felder
  für die Wiederholung (, ,
  ) und zur Gruppierung von Serien ()
  erweitert.
- **Formulare ():** Das Formular zur Erstellung von Trainings
  wurde um die neuen Wiederholungsoptionen erweitert.
- **Views:**
    - : Die Logik wurde erweitert, um beim Speichern
      eines wiederkehrenden Events automatisch alle zukünftigen Instanzen
      der Serie zu erstellen.
    - : Bietet nun die Möglichkeit, entweder nur ein
      einzelnes Event einer Serie oder die gesamte Serie zu löschen.
- **Templates:**
    - : Enthält jetzt die neuen Formularfelder mit
      JavaScript, um die Wiederholungsoptionen dynamisch ein- und
      auszublenden.
    - : Zeigt eine Auswahlmöglichkeit für den
      Löschumfang an, wenn das Event Teil einer Serie ist.
- **Migration:** Eine neue Datenbankmigration wurde erstellt, um die
  Änderungen am -Modell anzuwenden.
2025-11-22 21:34:04 +01:00

53 lines
2.3 KiB
Python

from django.db import models
from django.conf import settings
import urllib.parse
class Event(models.Model):
title = models.CharField(max_length=255)
description = models.TextField(blank=True)
start_time = models.DateTimeField()
end_time = models.DateTimeField(null=True, blank=True)
location_address = models.CharField(max_length=255)
maps_shortlink = models.URLField(blank=True, editable=False)
team = models.ForeignKey('clubs.Team', on_delete=models.CASCADE, related_name='events')
# Fields for recurring events
is_recurring = models.BooleanField(default=False)
recurrence_interval = models.PositiveIntegerField(null=True, blank=True, help_text="In days")
recurrence_end_date = models.DateField(null=True, blank=True)
parent_event = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True, related_name='child_events')
def save(self, *args, **kwargs):
if self.location_address and not self.maps_shortlink:
self.maps_shortlink = f"https://www.google.com/maps/search/?api=1&query={urllib.parse.quote(self.location_address)}"
super().save(*args, **kwargs)
def __str__(self):
return self.title
class Training(Event):
pass
class Game(Event):
opponent = models.CharField(max_length=255)
meeting_minutes_before_game = models.PositiveIntegerField(default=60)
season = models.CharField(max_length=255, blank=True)
min_players = models.PositiveIntegerField(default=9)
is_home_game = models.BooleanField(default=True)
number_of_innings = models.PositiveIntegerField(default=9)
opened_for_teams = models.ManyToManyField('clubs.Team', related_name='opened_games', blank=True)
class GameResult(models.Model):
game = models.OneToOneField(Game, on_delete=models.CASCADE, related_name='result')
inning_results = models.JSONField(default=dict)
def __str__(self):
return f"Result for {self.game}"
class EventParticipation(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
event = models.ForeignKey(Event, on_delete=models.CASCADE)
status = models.CharField(max_length=20, choices=[('attending', 'Attending'), ('rejected', 'Rejected'), ('maybe', 'Maybe')], default='maybe')
class Meta:
unique_together = ('user', 'event')