mensa_app/views.py aktualisiert #7

Closed
m.zillmann wants to merge 1 commits from m.zillmann/SGTMensa:m.zillmann-patch-2 into main
+86 -90
View File
@@ -1,101 +1,97 @@
from django.shortcuts import render
from django.shortcuts import render, redirect
from django.views import View
from .forms import OrderConfirmationForm # Ein Formular für die finalen Details
# Importieren Sie notwendige Django-Module (z.B. Django Payments)
import stripe # Beispiel: Stripe Payment Library
# Create your views here.
from django.views.generic import ListView
from .models import Gericht
class CheckoutView(View):
def get(self, request):
# 1. Warenkorb aus der Session laden (vereinfacht dargestellt)
cart_items = self.get_cart_from_session(request)
context = {
'cart': cart_items,
}
return render(request, 'orders/checkout.html', context)
class GerichtListView(ListView):
model = Gericht
template_name = 'mensa_app/gericht_liste.html' # Der Pfad zum Template
context_object_name = 'alle_gerichte' # Der Name, den wir im Template nutzen
def post(self, request):
# 2. Bestätigungsdaten validieren (z.B. Lieferadresse falls nötig)
form = OrderConfirmationForm()
if form.is_valid():
user = request.user
cart_items = self.get_cart_from_session(request)
from django.views.generic import TemplateView
from django.utils import timezone
from datetime import datetime
from .models import Menue, Gericht, SpeiseplanTag
# --- 3. Transaktionsdaten erstellen und speichern ---
total = sum(item['price'] * item['quantity'] for item in cart_items)
class SpeiseplanView(TemplateView):
template_name = 'mensa_app/speiseplan.html'
# Erstelle die Hauptbestellung (STATUS: PENDING)
order = Order.objects.create(user=user, total_price=total, status='PENDING')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# 1. Datum aus der URL holen (z.B. ?datum=2023-10-27)
# Wenn kein Datum angegeben ist, nehmen wir heute.
date_str = self.request.GET.get('datum')
if date_str:
try:
target_date = datetime.strptime(date_str, '%Y-%m-%d').date()
except ValueError:
target_date = timezone.glob.now().date()
else:
target_date = timezone.now().date()
# 2. Menüs für diesen spezifischen Tag laden
# Wir suchen alle Menüs, deren Tag das target_date hat
context['target_date'] = target_date
context['menues_day'] = Menue.objects.filter(tag__datum=target_date)
# 3. Dauerangebote laden (unabhängig vom Tag)
context['dauerangebote'] = Gericht.objects.filter(ist_dauerangebot=True)
# 4. Pager-Logik: Vorherigen und nächsten Tag finden
# Wir suchen in der Tabelle SpeiseplanTag nach dem Tag davor/danach
prev_tag = SpeiseplanTag.objects.filter(datum__lt=target_date).order_by('-datum').first()
next_tag = SpeiseplanTag.objects.filter(datum__gt=target_date).order_by('datum').first()
context['prev_date'] = prev_tag.datum.strftime('%Y-%m-%d') if prev_tag else None
context['next_date'] = next_tag.datum.strftime('%Y-%m-%d') if next_tag else None
return context
from django.views.generic import TemplateView
from django.utils import timezone
from django.db.models import Count, Sum
from datetime import datetime
from .models import Bestellung, SpeiseplanTag, Gericht, Menue
class BestellSummaryView(TemplateView):
template_name = 'mensa_app/bestell_summary.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# 1. Datum aus der URL holen (wie beim Speiseplan)
date_str = self.request.GET. get('datum')
if date_str:
try:
target_date = datetime.strptime(date_str, '%Y-%m-%d').date()
except ValueError:
target_date = timezone.now().date()
else:
target_date = timezone.now().date()
context['target_date'] = target_date
# 2. Aggregation: Bestellungen nach Gericht gruppieren
# Wir suchen alle Bestellungen, deren Menü am target_date stattfindet
summary_stats = (
Bestellung.objects.filter(menue__tag__datum=target_date)
.values('menue__gericht__name', 'menue__gericht__kategorie__name') # Gruppierung nach Name & Kategorie
.annotate(
anzahl=Count('id'), # Wie viele wurden bestellt?
umsatz=Sum('menue__preis') # Was macht das für einen Umsatz?
# Speichere jeden Artikel als OrderItem
for item in cart_items:
OrderItem.objects.create(
order=order,
menu_item=item['item'], # Angenommen, der Item-Objekt ist verfügbar
quantity=item['quantity'],
price_at_purchase=item['price']
)
.order_by('menue__gericht__name')
# --- 4. Zahlung verarbeiten (CRITICAL STEP) ---
try:
payment_token = request.POST.get('stripePaymentToken') # Token aus dem Frontend erhalten
# ACHTUNG: Hier wird das tatsächliche Stripe/PayPal API-Call ausgeführt
charge = stripe.Charge.create(
amount=int(total * 100), # Stripe erwartet Cent
currency='eur',
source=payment_token,
description=f"Mensa Bestellung für {user.username}"
)
context['summary_stats'] = summary_stats
# 3. Pager-Logik (identisch mit dem Speiseplan-View)
prev_tag = SpeiseplanTag.objects.filter(datum__lt=target_date).order_by('-datum').first()
next_tag = SpeiseplanTag.objects.filter(datum__gt=target_date).order_by('datum').first()
# Zahlung erfolgreich! Bestätige die Order im Backend
order.status = 'CONFIRMED'
order.save()
context['prev_date'] = prev_tag.datum.strftime('%Y-%m-%d') if prev_tag else None
context['next_date'] = next_tag.datum.strftime('%Y-%m-%d') if next_tag else None
return redirect('bestellung_erfolgreich')
# 4. Gesamtzahlen für die Übersicht
context['total_bestellungen'] = Bestellung.objects.filter(menue__tag__datum=target_date).count()
context['total_umsatz'] = Bestellung.objects.filter(menue__tag__datum=target_date).aggregate(Sum('menue__preis'))['menue__preis__sum'] or 0
except stripe.error.CardError as e:
# Fehlerbehandlung (z.B. falsche Karte, zu viel Geld)
form.add_error('payment', 'Zahlung fehlgeschlagen: ' + str(e))
except Exception as e:
print(f"Allgemeiner Fehler bei der Zahlung: {e}")
return context
return render(request, 'orders/checkout.html', {'form': form})
# Hilfsfunktion (muss in die View oder ein Servicescript ausgelagert werden)
def get_cart_from_session(request):
# Logik zum Laden von Menüpunkten und Mengen aus der Session
pass
from django.shortcuts import render, redirect
from django.views import View
from .forms import ReviewForm # Muss ein Formular für Rating und Kommentar enthalten
class ReviewView(View):
def get(self, request):
# Zeigt alle bestehenden Bewertungen (z.B. für das Hauptmenü)
all_reviews = Review.objects.select_related('menu_item').order_by('-created_at')
context = {'reviews': all_reviews}
return render(request, 'reviews/list.html', context)
def post(self, request):
form = ReviewForm(request.POST)
if form.is_valid():
review_data = form.cleaned_data
# 1. Den Menüpunkt bestimmen (oder lassen Sie ihn optional)
menu_item = request.GET.get('menu_item')
# 2. Review erstellen
Review.objects.create(
user=request.user,
menu_item=menu_item, # Kann None sein
rating=review_data['rating'],
comment=review_data['comment']
)
return redirect('nach_bewertung')
# Bei Fehler: Formular mit Fehlern erneut anzeigen
return render(request, 'reviews/list.html', {'form': form, 'reviews': Review.objects.all()})