Checkout-Flow¶
Der Bestellablauf erstreckt sich über mehrere Django-Apps und folgt einem definierten Prozess mit Pfand-Berechnung, Versandzuschlägen und Kommunikations-Dispatch.
Übersicht¶
Basket Checkout Order
┌────────────┐ ┌────────────────┐ ┌──────────┐
│ Warenkorb │ ────────→ │ 1. Lieferadresse│ │Bestellung│
│ + Pfand │ │ 2. Versandwahl │ ──────→ │erstellt │
│ + Angebote │ │ 3. Zahlung │ │ │
│ + Zuschläge│ │ 4. Bestätigung │ │ │
└────────────┘ └────────────────┘ └──────────┘
│
▼
┌────────────────┐
│ Communication │
│ + OU-Routing │
│ + E-Mail │
│ + API-Dispatch │
└────────────────┘
Phasen im Detail¶
1. Warenkorb (Basket)¶
Datei: apps/basket/models.py
Der Basket enthält Line-Objekte mit folgenden Erweiterungen:
| Konzept | Property/Methode | Beschreibung |
|---|---|---|
| Pfand-Ausschluss | after_deposit |
Warenkorbwert ohne Pfand (Basis für Schwellwerte) |
| Kisten-Anzahl | num_boxes |
Summe der Kisten im Warenkorb |
| Verfügbarkeit | is_available_to_buy() |
Produkt-Prüfung pro Line |
| Angebote | offer_applicator.apply() |
Oscar-Standard + Custom Benefits |
2. Checkout-Schritte¶
Views: apps/checkout/views.py – PaymentDetailsView
Schritt 1: Lieferadresse¶
- Auswahl aus gespeicherten Adressen oder Neueingabe
- Validierung: Postleitzahl muss zum Liefergebiet passen
- Session-basierte Zwischenspeicherung
Schritt 2: Versandmethode¶
Forms: apps/checkout/forms.py – SingleShippingMethodForm
- Listet verfügbare Versandmethoden (
ShippingMethod.objects.available()) - Berücksichtigt:
- Mindestbestellwert (
minimum_order_value) - Postleitzahl-Zonen (
Zone+Postcode) - Lieferzeitfenster-Verfügbarkeit
- Mindestbestellwert (
- Zeigt Zuschläge als separate Positionen
Stockwerk-Auswahl¶
Das Formular zeigt ein Dropdown für die Stockwerksanzahl:
# get_number_choices(): Nur wenn floor_only=True
# Zeigt Anzahl der Stockwerke mit zugehörigem Preis
choices = [
(0, "Erdgeschoss – 0,00 €"),
(1, "1. Stock – 2,00 €"),
(2, "2. Stock – 4,00 €"),
]
Schritt 3: Zahlungsmethode¶
Provider: apps/payment/providers.py
Unterstützte Methoden: - Vorkasse - PayPal - Rechnung - Barzahlung (bei Abholung/Lieferung)
Schritt 4: Bestätigung & Submit¶
- Zusammenfassung aller Positionen, Zuschläge und Rabatte
- Checkbox für AGB / Widerrufsbelehrung
- Abschicken triggert
handle_order_submission()
3. SurchargeApplicator¶
Datei: apps/checkout/applicator.py
Der SurchargeApplicator erbt von oscar.apps.checkout.applicator.Applicator
und erweitert die get_surcharges()-Methode:
def get_surcharges(self, basket, shipping_method, **kwargs):
surcharges = []
if shipping_method:
surcharges = shipping_method.get_extra_charges(basket)
return surcharges
Jeder Zuschlag wird als Surcharge-Objekt mit name, code und price
angelegt – separat von der Versandmethode.
4. Bestellabschluss¶
Datei: apps/checkout/mixins.py – handle_successful_order()
1. Basket.freeze() → Order erstellen
↓
2. Order in DB speichern
↓
3. send_custom_emails(order, …)
↓
4. CommunicationEvent ORDER_PLACED auslösen
↓
5. Basket leeren + Session bereinigen
Pfand-Splitting in der Bestellung¶
apps/order/models.py enthält Logik zur Trennung von Warenwert und Pfand in
der Bestellungsaufstellung. Der Pfand wird als separate Position mit eigener
MwSt.-Behandlung geführt.
5. Kommunikation nach Bestellabschluss¶
Datei: apps/communication/utils.py – CustomDispatcher
ORDER_PLACED Event
↓
CustomDispatcher.send_event_type()
↓
OrganizationUnit.get_responsible_ous(event, user, order)
↓
OrganizationUnit.send_all(event, user, messages)
↓
├──→ E-Mail an Kunde
├──→ E-Mail an Zusatzempfänger
├──→ E-Mail an OU-Mitglieder
└──→ API-Request (optional)
Siehe E-Mail-Versand für den vollständigen Ablauf.
Wichtige Dateien¶
| Datei | Funktion |
|---|---|
apps/basket/models.py |
Basket, Line, Pfand-Logik (after_deposit) |
apps/checkout/views.py |
PaymentDetailsView |
apps/checkout/forms.py |
SingleShippingMethodForm (Versandwahl) |
apps/checkout/applicator.py |
SurchargeApplicator |
apps/checkout/mixins.py |
handle_successful_order(), send_custom_emails() |
apps/checkout/session.py |
Checkout-Session-Daten |
apps/shipping/models.py |
OrderAndItemCharges (alle Zuschläge) |
apps/shipping/repository.py |
Shipping method repository |
apps/payment/providers.py |
Zahlungsprovider |
apps/communication/utils.py |
CustomDispatcher |
user/models.py |
OrganizationUnit.send_all() |
apps/order/models.py |
Order mit Pfand-Splitting |
Edge Cases¶
Mindestbestellwert nicht erreicht¶
Die Versandmethode steht nicht zur Auswahl. Der Kunde sieht eine Meldung: „Ihr Warenkorb liegt unter dem Mindestbestellwert von 30,00 €“.
Kein Liefertermin verfügbar¶
Wenn alle Zeitfenster belegt oder gesperrt sind, erscheint ein Hinweis statt des Dropdowns. Der Checkout kann nicht fortgesetzt werden.
Zahlungsfehler¶
Bei fehlgeschlagener Zahlung (z.B. PayPal-Ablehnung) wird die Bestellung im Status „Zahlung ausstehend“ angelegt. Dashboard-User können den Zahlungsstatus manuell korrigieren.