# Admin Business Logic — Leitfaden für Operatoren Dieses Dokument beschreibt die **Geschäftslogik der Bestellverwaltung** im Admin-Bereich. Es richtet sich an Operatoren, die Bestellungen im Alltag bearbeiten: Welche Status es gibt, was sie bedeuten, wo Bestellungen und Positionen angezeigt werden, und welche Aktionen wo möglich sind. Technische Details zum Kundenprozess (Checkout, E-Mail-Bestätigung) stehen in [ORDER_PROCESS.md](ORDER_PROCESS.md). Login und Admin-Konten: [ADMIN_SYSTEM.md](ADMIN_SYSTEM.md). --- ## Admin-Seiten im Überblick Vier Seiten sind für die Bestellbearbeitung relevant: | Seite | Datei | Rolle für Operatoren | | --- | --- | --- | | Dashboard | `admin/index.php` | Tagesübersicht, offene Arbeit, Statistik | | Bestellliste | `admin/orders.php` | Suchen, filtern, alle Bestellungen finden | | Bestelldetail | `admin/order.php` | Positionen bearbeiten, stornieren | | Nachbestellungen | `admin/backorders.php` | Externe Bestellung und Lieferung verwalten | Weitere Admin-Seiten (Produkte, Kategorien, Organisationen, FAQ, Einstellungen, Admins) haben **keinen Bezug** zu Bestellstatus oder -anzeige. --- ## Drei unabhängige Status-Dimensionen Eine Bestellung hat **keinen einzelnen Status**, sondern mehrere Felder, die unabhängig voneinander wirken: ```mermaid flowchart TB subgraph orderLevel [Bestellung] confStatus["confirmation_status"] opStatus["status"] end subgraph lineLevel [Position] backorder["backorder_status"] processed["is_processed"] end confStatus --> opStatus backorder --> processed ``` - **Bestellung — Bestätigung** (`confirmation_status`): Hat der Kunde die E-Mail bestätigt? Blockiert Bearbeitung, solange unbestätigt oder abgelaufen. - **Bestellung — Bearbeitung** (`status`): Wie weit ist die Abarbeitung insgesamt? Wird automatisch aus den Positionen berechnet (`open`, `partial`, `processed`) oder manuell gesetzt (`cancelled`). - **Position — Nachbestellung** (`backorder_status`): Liegt der Artikel auf Lager oder muss extern nachbestellt werden? - **Position — Bearbeitet** (`is_processed`): Wurde diese Position ausgegeben/abarbeitet? In Tabellen und Listen erscheint **ein kombiniertes Anzeige-Label** (z. B. „Unbestätigt" oder „Offen"). Die Nachbestellung wird auf Positionsebene geführt und erscheint zusätzlich als Badge „Nachbestellung" auf der Detailseite, wenn mindestens eine Position einen Nachbestell-Status hat. --- ## Bestellstatus — was Operatoren sehen ### Anzeige-Label in Listen und Dashboard Das sichtbare Label folgt einer **festen Priorität**. Höhere Priorität überschreibt niedrigere: | Anzeige-Label | Bedingung | Bedeutung für Operatoren | | --- | --- | --- | | **Storniert** | Bestellung storniert | Bestellung ist ungültig; nur „Stornierung aufheben" möglich | | **Unbestätigt** | E-Mail-Bestätigung ausstehend | Kunde hat noch nicht bestätigt; **keine Bearbeitung** möglich | | **Bestätigung abgelaufen** | Bestätigungsfrist abgelaufen | Kunde hat nicht rechtzeitig bestätigt; **keine Bearbeitung** möglich | | **Bearbeitet** | Alle Positionen bearbeitet | Bestellung abgeschlossen | | **Teilweise bearbeitet** | Mindestens eine, nicht alle Positionen bearbeitet | Bestellung in Arbeit | | **Offen** | Sonst | Noch keine Position bearbeitet | **Wichtig:** Die internen Werte `not_required` (Bestätigung nicht nötig) und `confirmed` (Kunde hat bestätigt) erscheinen **nie als eigenes Label**. Sobald keine Blockade durch Unbestätigt/Abgelaufen besteht, sehen Operatoren den operativen Status: Offen, Teilweise bearbeitet oder Bearbeitet. ### Interne Bestätigungsstatus (Referenz) | Wert | Wann gesetzt | Operator-Relevanz | | --- | --- | --- | | `not_required` | Bestätigung in Einstellungen deaktiviert | Bestellung sofort bearbeitbar | | `pending` | Bestätigung aktiviert, Kunde hat noch nicht bestätigt | Label „Unbestätigt"; Bearbeitung gesperrt | | `confirmed` | Kunde hat per Link bestätigt | Bearbeitung freigegeben | | `expired` | Frist (`confirmation_expires_at`) überschritten | Label „Bestätigung abgelaufen"; Bearbeitung gesperrt | Auf der Detailseite sind ggf. sichtbar: Bestätigungsfrist (bei Unbestätigt), Bestätigungszeitpunkt, Zeitpunkt der internen Weiterleitung. ### Interner Bearbeitungsstatus der Bestellung | Wert | Bedeutung | Wie gesetzt | | --- | --- | --- | | `open` | Keine Position bearbeitet | Automatisch | | `partial` | Einige Positionen bearbeitet | Automatisch | | `processed` | Alle Positionen bearbeitet | Automatisch | | `cancelled` | Bestellung storniert | Manuell durch Operator | Stornierte Bestellungen werden **nicht** automatisch aus Positionen neu berechnet. Nach „Stornierung aufheben" wird der Status wieder aus den Positionen abgeleitet. --- ## Positionsstatus — Bearbeitung und Nachbestellung ### Bearbeitet (`is_processed`) - Pro Position auf der **Bestelldetail**-Seite umschaltbar: „Als bearbeitet markieren" / „Als offen markieren". - Steuert den Bestellstatus automatisch: keine Position bearbeitet → Offen; alle → Bearbeitet; dazwischen → Teilweise bearbeitet. ### Nachbestellung (`backorder_status`) | Wert | Anzeige-Label | Bedeutung | | --- | --- | --- | | *(leer)* | — | Normale offene Position (Lager/Abgabe) | | `to_be_backordered` | Nachzubestellen | Position muss extern nachbestellt werden | | `ordered` | Wartet auf Lieferung | Extern bestellt, Lieferung steht aus | **Manuelle Nachbestellungen** (`data/manual_backorders.json`): Gleicher Ablauf wie bei Bestellpositionen, aber **ohne Kundenbestellung** — nur auf der Seite Nachbestellungen sichtbar und verwaltbar. --- ## Wo erscheint was? ### Dashboard (`admin/index.php`) #### Statistik-Karten | Karte | Was gezählt wird | | --- | --- | | **Offen** | Bestellungen mit operativem Status `open`, **ohne** Unbestätigt; **inkl.** abgelaufener Bestätigungen (siehe Bekannte Unstimmigkeiten) | | **Teilweise bearbeitet** | `status = partial`, ohne Unbestätigt | | **Bearbeitet** | `status = processed`, ohne Unbestätigt | | **Storniert** | `status = cancelled` | | **Nachbestellung** | Summe aller Positionen in `to_be_backordered` oder `ordered` (inkl. manueller Nachbestellungen) | **Unbestätigte Bestellungen** (`pending`) werden in **keiner** Statistik-Karte gezählt. #### „Letzte offene Bestellungen" (max. 5) Eine Bestellung erscheint hier nur, wenn: 1. Das Anzeige-Label **Offen** oder **Teilweise bearbeitet** ist (nicht Unbestätigt, nicht Abgelaufen, nicht Bearbeitet, nicht Storniert), **und** 2. Mindestens **eine Position** existiert, die **nicht** bearbeitet ist **und** **keinen** Nachbestell-Status hat. Sortierung: neueste zuerst. #### „Offene Positionen" Eine Position erscheint hier nur, wenn: 1. Die zugehörige Bestellung das Label **Offen** oder **Teilweise bearbeitet** hat, **und** 2. Die Position **nicht** bearbeitet ist **und** **keinen** Nachbestell-Status hat. Sortierung: **älteste zuerst** (FIFO-Arbeitsliste). **Operator-Hinweis:** Positionen mit Nachbestell-Status (**Nachzubestellen** oder **Wartet auf Lieferung**) erscheinen **nirgends** auf dem Dashboard. Diese werden ausschließlich unter **Nachbestellungen** verwaltet. --- ### Bestellliste (`admin/orders.php`) Filter und Suchfeld (Bestellnummer): | Filter | Was angezeigt wird | | --- | --- | | **Alle** | Alle Bestellungen (inkl. Unbestätigt) | | **Unbestätigt** | `confirmation_status = pending` | | **Bestätigung abgelaufen** | `confirmation_status = expired` | | **Offen** | Nicht Unbestätigt **und** `status = open` | | **Teilweise bearbeitet** | `status = partial` | | **Bearbeitet** | `status = processed` | | **Storniert** | `status = cancelled` | Die Status-Spalte zeigt das **kombinierte Anzeige-Label** (Bestätigung hat Vorrang vor operativem Status). **Hinweis zum Filter „Offen":** Enthält auch Bestellungen mit abgelaufener Bestätigung, solange der operative Status `open` ist (siehe Bekannte Unstimmigkeiten). --- ### Bestelldetail (`admin/order.php`) Jede Bestellung ist immer über die Bestellliste oder Dashboard-Links erreichbar — unabhängig vom Status. | Aktion | Wann sichtbar / erlaubt | | --- | --- | | **Als bearbeitet / offen markieren** | Bestellung nicht storniert; nicht Unbestätigt; nicht Abgelaufen | | **Als Nachbestellung markieren / aufheben** | Wie oben; nur Wechsel zwischen *(leer)* und **Nachzubestellen** — **nicht** von **Wartet auf Lieferung** | | **Bestellung stornieren** | Nicht storniert; nicht vollständig Bearbeitet | | **Stornierung aufheben** | Bestellung storniert | Zusätzliches Badge **„Nachbestellung"**, wenn mindestens eine Position einen Nachbestell-Status hat. Positionen im Status **Wartet auf Lieferung** (`ordered`): Kein Nachbestell-Toggle auf der Detailseite — Weiterbearbeitung nur über **Nachbestellungen** („Lieferung eingetroffen"). --- ### Nachbestellungen (`admin/backorders.php`) #### Was erscheint in der Liste? - Alle **manuellen** Nachbestell-Einträge mit Status Nachzubestellen oder Wartet auf Lieferung. - Bestellpositionen mit Nachbestell-Status, **ausgenommen** Bestellungen die: - storniert sind, oder - Unbestätigt sind, oder - abgelaufene Bestätigung haben. Positionen werden nach **Produkt und Größe** gruppiert. Spalten **Nachzubestellen** und **Wartet auf Lieferung** werden getrennt gezählt. #### Bulk-Aktionen (FIFO — älteste zuerst) | Aktion | Wirkung | | --- | --- | | **Als bestellt markieren** | Verschiebt N Positionen von **Nachzubestellen** → **Wartet auf Lieferung** | | **Lieferung eingetroffen** | Setzt N Positionen von **Wartet auf Lieferung** → *(leer)*; Position bleibt offen zur normalen Abarbeitung auf der Detailseite | Manuelle Nachbestellungen können über ein Formular auf derselben Seite hinzugefügt werden. --- ## Sichtbarkeits-Matrix Übersicht: Wo erscheint ein Zustand? | Zustand / Bedingung | Dashboard-Statistik | Letzte offene Bestellungen | Offene Positionen | Bestellliste-Filter | Bestelldetail | Nachbestellungen | | --- | --- | --- | --- | --- | --- | --- | | **Unbestätigt** (`pending`) | — (nicht gezählt) | — | — | Unbestätigt, Alle | Ja (nur Ansehen) | — | | **Bestätigung abgelaufen** (`expired`) | Zählt als **Offen** | — | — | Abgelaufen, **auch Offen** | Ja (nur Ansehen) | — | | **Offen** (bestätigt/nicht nötig) | Offen | Ja*, wenn offene Positionen ohne NB | Ja*, pro Position | Offen, Alle | Ja, bearbeitbar | Ja, wenn NB markiert | | **Teilweise bearbeitet** | Teilweise | Ja*, wenn offene Positionen ohne NB | Ja*, pro Position | Teilweise, Alle | Ja, bearbeitbar | Ja, wenn NB markiert | | **Bearbeitet** | Bearbeitet | — | — | Bearbeitet, Alle | Ja (nur Ansehen) | Ja, wenn NB markiert | | **Storniert** | Storniert | — | — | Storniert, Alle | Ja (Stornierung aufheben) | — | | Position **Nachzubestellen** | In NB-Statistik | Position ausgeblendet | Position ausgeblendet | Bestellung in Liste | Toggle auf Detail | Ja | | Position **Wartet auf Lieferung** | In NB-Statistik | Position ausgeblendet | Position ausgeblendet | Bestellung in Liste | Kein Toggle auf Detail | Ja | | Nur NB-Positionen, Bestellung operativ **Offen** | Offen | — (keine qualif. Position) | — | Alle, Offen | Ja | Ja | | Manuelle Nachbestellung | In NB-Statistik | — | — | — | — | Ja | *NB = Nachbestell-Status. „Ja*" = nur wenn mindestens eine unverarbeitete Position **ohne** Nachbestell-Status existiert. --- ## Typische Operator-Workflows ### 1. Neue bestätigte Bestellung abarbeiten 1. **Dashboard** → „Offene Positionen" oder „Letzte offene Bestellungen" prüfen. 2. **Details** öffnen. 3. Pro Position **„Als bearbeitet markieren"**, sobald ausgegeben. 4. Wenn alle Positionen bearbeitet: Status wechselt automatisch zu **Bearbeitet**. ### 2. Artikel nicht auf Lager (Nachbestellung) 1. **Bestelldetail** → Position **„Als Nachbestellung markieren"** (Status: Nachzubestellen). 2. Position verschwindet aus Dashboard-Listen. 3. **Nachbestellungen** → gruppiert nach Produkt/Größe → **„Als bestellt markieren"** (extern bestellt). 4. Nach Lieferung: **„Lieferung eingetroffen"** → Position wieder normal offen. 5. Zurück auf **Bestelldetail** → **„Als bearbeitet markieren"**. ```mermaid stateDiagram-v2 direction LR state backorder { none --> toBeBackordered: Detail markieren toBeBackordered --> ordered: Nachbestellungen bestellt ordered --> none: Lieferung eingetroffen toBeBackordered --> none: Detail aufheben } ``` ### 3. Unbestätigte Bestellung 1. **Bestellliste** → Filter **Unbestätigt**. 2. Abwarten, bis Kunde bestätigt, oder Frist abläuft. 3. Nach Bestätigung: normal auf Dashboard sichtbar. 4. Nach Ablauf: Label **Bestätigung abgelaufen** — keine Bearbeitung möglich. ### 4. Manuelle Nachbestellung (ohne Kundenbestellung) 1. **Nachbestellungen** → Formular „Manuelle Nachbestellung". 2. Produkt, Größe, Anzahl wählen. 3. Weiter wie Workflow 2 (bestellt → geliefert). ### 5. Bestellung stornieren 1. **Bestelldetail** → **„Bestellung stornieren"** (nicht möglich bei Status Bearbeitet). 2. Optional Stornogrund angeben. 3. Stornierte Bestellungen: Filter **Storniert** in der Bestellliste; **Stornierung aufheben** auf der Detailseite. --- ## Einstellungen mit Einfluss auf neue Bestellungen Unter **Einstellungen** (`admin/settings.php`): - **E-Mail-Bestätigung erforderlich**: Neue Bestellungen starten als **Unbestätigt** statt sofort bearbeitbar. - **Bestätigungsfrist (Tage)**: Nach Ablauf → **Bestätigung abgelaufen**. Diese Einstellungen betreffen nur **neu eingehende** Bestellungen, nicht bereits gespeicherte. --- ## Bekannte Unstimmigkeiten Die folgenden Punkte sind **keine Bedienanleitung**, sondern dokumentierte Abweichungen in der Anzeige-Logik. Sie können später im Code behoben werden. 1. **`expirePendingOrders()` speichert Ablauf ggf. nicht dauerhaft** In `includes/functions.php`: Der Vergleich `$updated !== $order` ist bei Arrays per Referenz immer falsch. Abgelaufene Bestätigungen werden beim Lesen berechnet, `orders.json` kann aber weiterhin `pending` enthalten, bis eine andere Speicherung erfolgt. 2. **Dashboard-Zähler „Offen" inkl. abgelaufener Bestätigungen** Abgelaufene Bestellungen erhöhen die Karte **Offen**, zeigen in Listen aber **Bestätigung abgelaufen** — die Zahl kann irreführend sein. 3. **Filter „Offen" in der Bestellliste inkl. abgelaufener Bestätigungen** Der Filter schließt nur `pending` aus, nicht `expired`. Abgelaufene Bestellungen mit operativem Status `open` erscheinen unter **Offen** und **Bestätigung abgelaufen**. 4. **Kein Dashboard-Zähler für Unbestätigt** Unbestätigte Bestellungen fehlen in allen Statistik-Karten; sie sind nur über Bestellliste → Filter **Unbestätigt** oder **Alle** auffindbar. 5. **Bestellung nur mit Nachbestellpositionen** Operativer Status kann **Offen** bleiben (0 Positionen bearbeitet), aber alle Positionen haben Nachbestell-Status → Bestellung erscheint **nicht** in Dashboard-Tabellen, nur in **Alle** und **Nachbestellungen**. 6. **Status „Wartet auf Lieferung" nicht auf Detailseite änderbar** Bewusste Trennung: Weiterführung nur über **Nachbestellungen**. Operatoren, die nur die Detailseite nutzen, finden keinen Button dafür. 7. **Stornierte Bestellungen können Nachbestell-Flags in den Daten behalten** In der Nachbestellungen-Ansicht ausgeblendet, in den Rohdaten ggf. noch vorhanden. 8. **Position bearbeitbar trotz Nachbestell-Flag** „Als bearbeitet markieren" löscht den Nachbestell-Status nicht automatisch. Umgekehrt blockiert ein gesetzter Nachbestell-Status auf bereits bearbeiteten Positionen keine erneute Markierung als offen/bearbeitet. 9. **FIFO-Sortierung bei Bulk-Aktionen inkonsistent** Anzeige in Nachbestellungen sortiert u. a. nach `sort_at` (Bestell-/Bestellzeitpunkt). Bulk-Updates sortieren Kandidaten nur nach `created_at` — Reihenfolge kann bei „Wartet auf Lieferung" abweichen. 10. **`MANUAL_BACKORDERS_FILE` fehlt in `config.sample.php`** Manuelle Nachbestellungen setzen die Konstante voraus; fehlt sie in der produktiven `config.php`, kann die Nachbestellungen-Seite fehlschlagen. --- ## Querverweise - [ORDER_PROCESS.md](ORDER_PROCESS.md) — Gesamtprozess von Bestellung bis Abarbeitung, E-Mail-Bestätigung, technische Abläufe - [ADMIN_SYSTEM.md](ADMIN_SYSTEM.md) — Admin-Login und Kontenverwaltung - [CONFIG_REFERENCE.md](CONFIG_REFERENCE.md) — Konfigurationsoptionen (sofern relevant für Betrieb)