196 lines
6.7 KiB
Python
196 lines
6.7 KiB
Python
from django.db import models
|
|
from django.contrib.auth.models import User
|
|
from django.utils import timezone
|
|
import datetime
|
|
|
|
class Person(models.Model):
|
|
"""Repräsentiert Schüler oder Lehrer."""
|
|
user = models.OneToOneField(User, on_delete=models.CASCADE)
|
|
rolle = models.CharField(max_length=20, choices=[('schueler', 'Schüler'), ('lehrer', 'Lehrer'), ('mitarbeiter','Mensa-Mitarbeiter'), ('chef','Mensa-Leitung')])
|
|
klasse = models.CharField(max_length=4, blank=True, null=True) # Nur für Schüler relevant
|
|
|
|
class Meta:
|
|
verbose_name_plural = "Personen"
|
|
|
|
def __str__(self):
|
|
return f"{self.user.username} ({self.rolle})"
|
|
|
|
|
|
class Schulwoche(models.Model):
|
|
"""Repräsentiert eine Schulwoche mit einem eindeutigen Datum."""
|
|
|
|
id = models.CharField(max_length=20, unique=True, primary_key=True, default="test_1") # eine eindeutige ID wie "Woche_2024_10"
|
|
datum = models.DateField(unique=True) # Datum der Schulwoche (z. B. Montag der ersten Woche)
|
|
|
|
ist_aktiv = models.BooleanField(default=False)
|
|
ist_ferienwoche = models.BooleanField(default=False)
|
|
|
|
class Meta:
|
|
verbose_name = "Schulwoche"
|
|
verbose_name_plural = "Schulwochen"
|
|
|
|
|
|
class SpeiseplanTag(models.Model):
|
|
"""Ein bestimmter Tag im Speiseplan."""
|
|
datum = models.DateField(unique=True)
|
|
|
|
schulwoche = models.ForeignKey(
|
|
Schulwoche,
|
|
on_delete=models.CASCADE,
|
|
#related_name='tag_get_schulwoche' # Für Abfragen wie: Schulwoche.tag_get_schulwoche.all()
|
|
default = "test_1"
|
|
)
|
|
|
|
class Meta:
|
|
verbose_name = "Tag mit Speiseplan"
|
|
verbose_name_plural = "Tage mit Speiseplan"
|
|
|
|
def __str__(self):
|
|
return self.datum.strftime('%d.%m.%Y')
|
|
|
|
class Kategorie(models.Model):
|
|
"""
|
|
Definiert die Art der Speise (Süßspeise, Hauptgericht, etc.).
|
|
"""
|
|
name = models.CharField(max_length=50, unique=True, default="")
|
|
|
|
class Meta:
|
|
verbose_name = "Kategorie"
|
|
verbose_name_plural = "Kategorien"
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
class Gericht(models.Model):
|
|
"""Ein einzelnes Gericht (z.B. 'Nudeln mit Tomatensauce')."""
|
|
name = models.CharField(max_length=100)
|
|
# PROTECT verhindert, dass eine Kategorie gelöscht wird,
|
|
# solange noch Gerichte ihr zugeordnet sind.
|
|
kategorie = models.ForeignKey(
|
|
Kategorie,
|
|
on_delete=models.PROTECT,
|
|
related_name='gerichte'
|
|
)
|
|
ist_vegetarisch = models.BooleanField(default=False)
|
|
ist_allergene_frei = models.BooleanField(default=False)
|
|
allergene = models.TextField(blank=True, default="")
|
|
preis = models.DecimalField(max_digits=5, decimal_places=2, default=0.00)
|
|
|
|
now = datetime.datetime.now()
|
|
|
|
time_last_change = models.TimeField(default=now)
|
|
time_creation = models.TimeField(default=now)
|
|
|
|
# Das Attribut für das "Dauerangebot"
|
|
ist_dauerangebot = models.BooleanField(
|
|
default=False,
|
|
help_text="Wenn aktiviert, ist dieses Gericht immer verfügbar und nicht an einen spezifischen Tag gebunden."
|
|
)
|
|
|
|
def __str__(self):
|
|
return f"{self.name} ({self.kategorie.name})"
|
|
|
|
class Meta:
|
|
verbose_name = "Gericht"
|
|
verbose_name_plural = "Gerichte"
|
|
permissions = [("can_create_Gericht", "Kann neues Gericht anlegen")]
|
|
ordering = ["kategorie", "name", "preis"]
|
|
get_latest_by = "time_last_change"
|
|
|
|
class Menue(models.Model):
|
|
"""Eine Kombination von Speisen für einen Tag (z.B. Hauptgang + Dessert)."""
|
|
tag = models.ForeignKey(SpeiseplanTag, on_delete=models.CASCADE, related_name='menues')
|
|
gericht = models.ForeignKey(Gericht, on_delete=models.CASCADE)
|
|
preis = models.DecimalField(max_digits=5, decimal_places=2)
|
|
|
|
def __str__(self):
|
|
return f"{self.tag.datum}: {self.gericht.name} ({self.preis}€)"
|
|
|
|
class Meta:
|
|
verbose_name = "Menü"
|
|
verbose_name_plural = "Menüs"
|
|
|
|
class Bestellung(models.Model):
|
|
"""Eine abgeschlossene Bestellung eines Nutzers."""
|
|
STATUS_CHOICES = [
|
|
('offen', 'Offen'),
|
|
('abgeholt', 'Abgeholt'),
|
|
('verwaist', 'Nicht abgeholt'),
|
|
('bezahlt', 'Bezahlt'),
|
|
('storniert', 'Storniert'),
|
|
]
|
|
|
|
person = models.ForeignKey(Person, on_delete=models.CASCADE)
|
|
menue = models.ForeignKey(Menue, on_delete=models.CASCADE)
|
|
datum_bestellung = models.DateTimeField(default=timezone.now)
|
|
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='offen')
|
|
bezahlt = models.BooleanField(default=False)
|
|
|
|
def __str__(self):
|
|
return f"Bestellung {self.id} von {self.person.user.username}"
|
|
|
|
class Meta:
|
|
verbose_name = "Bestellung"
|
|
verbose_name_plural = "Bestellungen"
|
|
|
|
|
|
from django.core.exceptions import ValidationError
|
|
|
|
|
|
class Bewertung(models.Model):
|
|
"""
|
|
Repräsentiert die Bewertung eines Gerichts durch einen Nutzer.
|
|
"""
|
|
|
|
class Sterne(models.IntegerChoices):
|
|
EINER = 1, '★☆☆☆☆'
|
|
ZWEI = 2, '★★☆☆☆'
|
|
DREI = 3, '★★★☆☆'
|
|
VIER = 4, '★★★★☆'
|
|
FUENF = 5, '★★★★★'
|
|
|
|
user = models.ForeignKey('Person', on_delete=models.CASCADE, related_name='bewertungen')
|
|
gericht = models.ForeignKey('Gericht', on_delete=models.CASCADE, related_name='bewertungen')
|
|
sterne = models.IntegerField(choices=Sterne.choices, default=3)
|
|
kommentar = models.TextField(blank=True, null=True)
|
|
datum = models.DateTimeField(auto_now_add=True)
|
|
|
|
# Das Feld für die Verifizierung
|
|
ist_verifiziert = models.BooleanField(
|
|
default=False,
|
|
help_text="Wird automatisch auf True gesetzt, wenn eine bezahlte Bestellung vorliegt."
|
|
)
|
|
|
|
class Meta:
|
|
# Verhindert, dass ein Nutzer dasselbe Gericht mehrfach bewertet
|
|
unique_together = ('user', 'gericht')
|
|
verbose_name = "Bewertung"
|
|
verbose_name_plural = "Bewertungen"
|
|
|
|
def __str__(self):
|
|
return f"{self.user.user.username} bewertet {self.gericht.name} mit {self.sterne} Sternen"
|
|
|
|
def clean(self):
|
|
"""
|
|
Hier können wir zusätzliche Validierungen einbauen.
|
|
"""
|
|
if self.sterne < 1 or self.sterne > 5:
|
|
raise ValidationError("Die Bewertung muss zwischen 1 und 5 Sternen liegen.")
|
|
|
|
def check_verifizierung(self):
|
|
"""
|
|
Ein hilfreicher Service-Method, um den Status der Verifizierung
|
|
automatisch zu prüfen.
|
|
"""
|
|
# Wir prüfen, ob es eine Bestellung für diesen User und dieses Gericht gibt,
|
|
# die bereits als 'bezahlt' markiert ist.
|
|
exists = Bestellung.objects.filter(
|
|
person=self.user,
|
|
menue__gericht=self.gericht,
|
|
bezahlt=True
|
|
).exists()
|
|
|
|
if exists:
|
|
self.ist_verifiziert = True
|
|
return self.ist_verifiziert
|