1
0
Fork 0
mirror of https://github.com/s-frick/effigenix.git synced 2026-03-28 08:29:36 +01:00
effigenix/backend/docs/MASTERDATA_MANUAL_TESTS.md
Sebastian Frick 8c042925eb docs: manuelle Testfälle für Inventory und Production BC ergänzen
Testfälle aus allen GitHub-Issues mit Status 'Done' abgeleitet:
- TC-SL (1-15): Lagerorte
- TC-STK (1-5): Bestandspositionen
- TC-BATCH (1-10): Chargen
- TC-REC (1-22): Rezepte
- TC-CYCLE (1-3): Zyklus-Erkennung
- TC-BAT (1-4): Chargenplanung
- TC-INV-CROSS/TC-PROD-CROSS: Übergreifende Tests
2026-02-20 16:40:39 +01:00

27 KiB
Raw Permalink Blame History

Manuelle Testfälle Masterdata BC

Kontext

Der Masterdata Bounded Context ist vollständig implementiert und umfasst vier Aggregate:

  • ProductCategory einfaches Kategorie-Aggregate
  • Supplier Lieferanten mit Zertifikaten, Bewertungen, Adressen
  • Article Artikel mit Verkaufseinheiten (SalesUnits), Lieferantenzuordnung
  • Customer Kunden (B2B/B2C) mit Lieferadressen, Präferenzen, Rahmenvertrag (nur B2B)

Die TUI ist das Testwerkzeug für das Backend. Alle Schreiboperationen erfordern MASTERDATA_WRITE-Permission.


Voraussetzungen

  • Backend läuft (./mvnw spring-boot:run oder Docker)
  • TUI läuft (pnpm dev im CLI-Verzeichnis)
  • Eingeloggt als User mit MASTERDATA_WRITE-Permission (z.B. admin)
  • Eingeloggt als User ohne MASTERDATA_WRITE-Permission (z.B. viewer) für Authz-Tests

TC-CAT: Produktkategorien

TC-CAT-01: Kategorie erstellen (Happy Path)

  1. Masterdata → Produktkategorien → [n] Neu
  2. Name: Obst & Gemüse, Beschreibung: Frische Produkte → Enter
  • Erwartung: Kategorie erscheint in der Liste; Name und Beschreibung korrekt

TC-CAT-02: Kategorie erstellen ohne Beschreibung

  1. Name: Milchprodukte, Beschreibung: leer → Enter
  • Erwartung: Kategorie wird angelegt; Beschreibung fehlt ohne Fehler

TC-CAT-03: Kategorie bearbeiten

  1. Kategorie Obst & Gemüse auswählen → [e]
  2. Name ändern auf Obst und Gemüse, Beschreibung auf Saisonale Frische
  • Erwartung: Änderungen werden gespeichert und korrekt angezeigt

TC-CAT-04: Doppelter Name wird abgelehnt

  1. Neue Kategorie mit Name Milchprodukte (existiert bereits) anlegen
  • Erwartung: Fehlermeldung Name bereits vergeben; kein Datensatz angelegt

TC-CAT-05: Kategorie löschen

  1. Kategorie Milchprodukte in der Liste auswählen → [d]
  2. Bestätigungsdialog mit Ja bestätigen
  • [c] Erwartung: Kategorie verschwindet aus der Liste

TC-CAT-06: Leerer Name wird abgelehnt

  1. Neue Kategorie, Name leer → Enter
  • Erwartung: Fehler / Eingabe nicht möglich; kein API-Aufruf

TC-SUP: Lieferanten

TC-SUP-01: Lieferant erstellen Pflichtfelder

  1. Lieferanten → [n] Neu
  2. Name: Frisch AG, Telefon: +49 30 12345 → restliche Felder leer → Enter
  • Erwartung: Lieferant erscheint in der Liste, Status AKTIV

TC-SUP-02: Lieferant erstellen alle Felder

  1. Name: Bio GmbH, Telefon: +49 89 999, E-Mail: bio@example.com
  2. Ansprechpartner: Max Muster
  3. Adresse: Gartenstraße 5, 12, 80333, München, Deutschland
  4. Zahlungsziel: 30 Tage
  • [/] Erwartung: Alle Daten in der Detailansicht korrekt angezeigt

TC-SUP-03: Lieferant erstellen ohne Pflichtfelder

  1. Name leer → versuchen zu speichern
  • Erwartung: Fehler; kein Lieferant angelegt
  1. Name gefüllt, Telefon leer → versuchen zu speichern
  • Erwartung: Fehler; kein Lieferant angelegt

TC-SUP-04: Doppelter Name wird abgelehnt

  1. Neuen Lieferanten Frisch AG anlegen (Name existiert bereits)
  • Erwartung: Fehlermeldung Name bereits vergeben

TC-SUP-05: Lieferant deaktivieren und aktivieren

  1. Frisch AG → Detailansicht → [Deaktivieren] → Bestätigen
  • Erwartung: Status wechselt auf INAKTIV (roter Punkt in Liste)
  1. Erneut öffnen → [Aktivieren] → Bestätigen
  • Erwartung: Status wechselt auf AKTIV

TC-SUP-06: Lieferant filtern

  1. Lieferantenliste: [A] nur Aktive
  • Erwartung: Nur AKTIV-Lieferanten sichtbar
  1. [I] nur Inaktive
  • Erwartung: Nur INAKTIV-Lieferanten sichtbar
  1. [a] alle
  • Erwartung: Alle Lieferanten sichtbar

TC-SUP-07: Lieferant bewerten

  1. Frisch AG[Bewerten]
  2. Qualität: 4, Lieferung: 3, Preis: 5 → Enter
  • Erwartung: Bewertung in Detailansicht sichtbar; Durchschnitt = 4.0
  1. In der Liste: Stern-Anzeige ★ 4.0

TC-SUP-08: Bewertung Grenzen (1 und 5)

  1. Alle Scores auf 1 setzen → Speichern
  • Erwartung: Gespeichert; Durchschnitt = 1.0
  1. Alle Scores auf 5 → Speichern
  • Erwartung: Gespeichert; Durchschnitt = 5.0

TC-SUP-09: Zertifikat hinzufügen (gültig)

  1. Frisch AG[Zertifikat hinzufügen]
  2. Typ: ISO9001, Aussteller: TÜV, ab: 2024-01-01, bis: 2027-01-01
  • Erwartung: Zertifikat erscheint in Detailansicht; Anzahl in Liste = 1

TC-SUP-10: Zertifikat hinzufügen (abgelaufen)

  1. Zertifikat, bis: 2023-12-31 (Datum in der Vergangenheit)
  • Erwartung: Zertifikat wird angelegt (keine Ablauf-Prüfung beim Hinzufügen); in Detail sichtbar (Edge Case: System soll abgelaufene Zertifikate anzeigen, nicht blocken)

TC-SUP-11: Doppeltes Zertifikat wird abgelehnt

  1. Erneut ISO9001, TÜV, 2024-01-01 hinzufügen
  • Erwartung: Fehlermeldung Duplikat abgelehnt

TC-SUP-12: Zertifikat entfernen

  1. Frisch AG[Zertifikat entfernen] → Zertifikat auswählen → Enter
  • Erwartung: Zertifikat aus Detailansicht verschwunden

TC-ART: Artikel

TC-ART-01: Artikel erstellen PIECE_FIXED

  1. Artikel → [n] Neu
  2. Name: Äpfel Gala, Nummer: OG-001
  3. Kategorie: Obst & Gemüse (mit ← →)
  4. Einheit: PIECE_FIXED, Preis: 1.99
  • Erwartung: Artikel in Liste; Preismodell automatisch FIXED

TC-ART-02: Artikel erstellen KG (gewichtsbasiert)

  1. Name: Bananen, Nummer: OG-002
  2. Einheit: KG, Preis: 2.49
  • Erwartung: Preismodell automatisch WEIGHT_BASED

TC-ART-03: Artikel erstellen HUNDRED_GRAM und PIECE_VARIABLE

  1. Einheit HUNDRED_GRAM → Preismodell WEIGHT_BASED
  2. Einheit PIECE_VARIABLE → Preismodell WEIGHT_BASED
  • Erwartung: Konsistenz in beiden Fällen korrekt

TC-ART-04: Doppelte Artikelnummer wird abgelehnt

  1. Neuen Artikel mit Nummer OG-001 anlegen
  • Erwartung: Fehlermeldung Artikelnummer bereits vergeben

TC-ART-05: Artikel deaktivieren und aktivieren

  1. Äpfel Gala[Deaktivieren] → Bestätigen
  • Erwartung: Status INAKTIV
  • Erwartung: Status AKTIV

TC-ART-06: Artikel filtern

  1. [A] nur Aktive, [I] nur Inaktive, [a] alle
  • Erwartung: Filter wirkt korrekt

TC-ART-07: Verkaufseinheit hinzufügen

  1. Äpfel Gala[Verkaufseinheit hinzufügen]
  2. Einheit: KG, Preis: 3.50
  • Erwartung: Zweite VE in Detailansicht; Anzahl VE in Liste = 2

TC-ART-08: Doppelte Einheit wird abgelehnt

  1. Erneut PIECE_FIXED für Äpfel Gala hinzufügen
  • Erwartung: Fehlermeldung Einheit bereits vorhanden

TC-ART-09: Letzte Verkaufseinheit kann nicht entfernt werden

  1. Artikel mit genau einer VE → [Verkaufseinheit entfernen]
  • Erwartung: Aktion nicht verfügbar / Fehler mindestens eine VE erforderlich

TC-ART-10: Verkaufseinheit entfernen (wenn 2+ vorhanden)

  1. Äpfel Gala hat 2 VE → [Verkaufseinheit entfernen] → KG-Einheit wählen
  • Erwartung: VE entfernt; nur noch PIECE_FIXED vorhanden

TC-ART-11: Lieferant dem Artikel zuweisen (falls TUI-Unterstützung vorhanden)

  1. Äpfel Gala → Lieferant Frisch AG zuweisen
  • Erwartung: Lieferant in Detailansicht sichtbar

TC-CUS: Kunden

TC-CUS-01: B2C-Kunde erstellen

  1. Kunden → [n] Neu
  2. Typ: B2C, Name: Max Mustermann, Telefon: +49 176 12345
  3. Rechnungsadresse: Musterstr. 1, 2, 10115, Berlin, Deutschland
  • Erwartung: Kunde in Liste, Typ-Badge B2C, Status AKTIV

TC-CUS-02: B2B-Kunde erstellen

  1. Typ: B2B, Name: Gastro GmbH, Telefon: +49 30 9876
  2. Rechnungsadresse vollständig ausfüllen
  • Erwartung: Kunde in Liste, Typ-Badge B2B

TC-CUS-03: Pflichtfelder Validierung

  1. Name leer → Fehler
  2. Telefon leer → Fehler
  3. Rechnungsadresse unvollständig → Fehler
  • Erwartung: Jeweils spezifische Fehlermeldung

TC-CUS-04: Doppelter Kundenname wird abgelehnt

  1. Erneut Gastro GmbH anlegen
  • Erwartung: Fehlermeldung Name bereits vergeben

TC-CUS-05: Kunde deaktivieren und aktivieren

  1. Max Mustermann[Deaktivieren] → Bestätigen → [Aktivieren]
  • Erwartung: Status wechselt korrekt

TC-CUS-06: Kunden filtern (Status + Typ)

  1. [A] → nur Aktive; [I] → nur Inaktive; [a] → alle
  2. [B] → nur B2B; [C] → nur B2C; [b] → alle
  3. Kombination: Aktive B2B-Kunden
  • Erwartung: Alle Filter wirken korrekt und kombinierbar

TC-CUS-07: Lieferadresse hinzufügen

  1. Gastro GmbH[Lieferadresse hinzufügen]
  2. Label: Hauptküche, Straße: Kochstr., Nr: 12, PLZ: 10963, Stadt: Berlin, Land: Deutschland
  3. Ansprechpartner: Koch Müller, Lieferhinweis: Bitte kühlen
  • Erwartung: Lieferadresse in Detailansicht; Anzahl in Liste = 1

TC-CUS-08: Lieferadresse entfernen

  1. [Lieferadresse entfernen]Hauptküche auswählen
  • Erwartung: Lieferadresse entfernt

TC-CUS-09: Mehrere Lieferadressen

  1. Zwei Lieferadressen Filiale Nord und Filiale Süd hinzufügen
  • Erwartung: Beide in Detailansicht; Anzahl in Liste = 2

TC-CUS-10: Präferenzen setzen

  1. Max Mustermann[Präferenzen setzen]
  2. BIO und REGIONAL aktivieren → Enter
  • Erwartung: Präferenzen in Detailansicht sichtbar
  1. Erneut öffnen → nur HALAL aktivieren → Enter
  • Erwartung: Nur HALAL gesetzt (Set wird ersetzt, nicht ergänzt)

TC-CUS-11: Alle Präferenzen abwählen

  1. [Präferenzen setzen] → alle deaktivieren → Enter
  • Erwartung: Keine Präferenzen mehr sichtbar

TC-B2B: Rahmenverträge (B2B-spezifisch)

Vorbedingung: Gastro GmbH (B2B) existiert; Artikel Äpfel Gala existiert

TC-B2B-01: Rahmenvertrag für B2B-Kunden erstellen (falls TUI-Unterstützung vorhanden)

  1. Gastro GmbH → Rahmenvertrag-Bereich
  2. Gültig ab: 2025-01-01, bis: 2025-12-31, Rhythmus: WEEKLY
  3. Position: Artikel Äpfel Gala, vereinbarter Preis: 1.50, Menge: 100
  • Erwartung: Rahmenvertrag in Detailansicht sichtbar

TC-B2B-02: Rahmenvertrag für B2C-Kunden nicht möglich (Backend-Test via API)

POST /api/customers/{b2c-id}/frame-contract
  • Erwartung: HTTP 400/422, Fehler FrameContractNotAllowed

TC-AUTH: Autorisierung

TC-AUTH-01: Lesezugriff ohne MASTERDATA_WRITE

  1. Als viewer (ohne MASTERDATA_WRITE) einloggen
  2. Alle Listen aufrufen (Kategorien, Lieferanten, Artikel, Kunden)
  • Erwartung: Daten sichtbar, kein Fehler

TC-AUTH-02: Schreibzugriff ohne MASTERDATA_WRITE wird abgelehnt

  1. Als viewer versuchen: neue Kategorie erstellen
  • Erwartung: HTTP 403 / Fehlermeldung in TUI; kein Datensatz angelegt
  1. Dasselbe für Lieferant, Artikel, Kunde anlegen
  • Erwartung: Jeweils Ablehnung

TC-AUTH-03: Schreibzugriff mit MASTERDATA_WRITE funktioniert

  1. Als admin (mit MASTERDATA_WRITE) → alle CRUD-Operationen möglich
  • Erwartung: Alle Operationen erfolgreich

TC-CROSS: Übergreifende / Integrations-Tests

TC-CROSS-01: Artikel-Lieferant-Verknüpfung konsistent

  1. Lieferant Frisch AG einem Artikel zuweisen
  2. Frisch AG deaktivieren
  3. Artikel aufrufen → Lieferant weiterhin referenziert (keine Zwangstrennung)
  • Erwartung: Artikel zeigt Frisch AG trotz INAKTIV-Status

TC-CROSS-02: Kategorie in Artikelauswahl verfügbar

  1. Neue Kategorie Getränke anlegen
  2. Artikel erstellen → Kategorie-Auswahl enthält Getränke
  • Erwartung: Neue Kategorien sofort im Artikel-Formular verfügbar

TC-CROSS-03: Sequenz Kompletter Lieferant-Workflow

  1. Lieferant erstellen → bewerten → Zertifikat hinzufügen → deaktivieren → wieder aktivieren → Zertifikat entfernen
  • Erwartung: Alle Schritte funktionieren in Folge ohne Datenverlust

TC-CROSS-04: Sequenz Kompletter Artikel-Workflow

  1. Kategorie erstellen → Artikel erstellen (mit Kategorie) → 2. VE hinzufügen → 1. VE entfernen → Artikel deaktivieren → aktivieren
  • Erwartung: Konsistenz über alle Schritte

TC-CROSS-05: Sequenz B2B-Kunde vollständig

  1. B2B-Kunde erstellen → 2 Lieferadressen → Präferenzen setzen → 1 Adresse entfernen → Präferenzen ändern → deaktivieren → aktivieren
  • Erwartung: Konsistenz über alle Schritte

Manuelle Testfälle Inventory BC

Kontext

Der Inventory Bounded Context umfasst zwei Aggregate:

  • StorageLocation Lagerorte mit Typ und optionalem Temperaturbereich
  • Stock Bestandspositionen mit chargengenauer Führung (Batches)

Alle Schreiboperationen erfordern INVENTORY_WRITE-Permission. API-Basis: /api/inventory/


TC-SL: Lagerorte (GitHub #1, #2, #3)

TC-SL-01: Lagerort erstellen Pflichtfelder (Happy Path)

  1. POST /api/inventory/storage-locations
  2. Body: name: "Kühlraum 1", storageType: "COLD_ROOM" → ohne Temperaturbereich
  • Erwartung: 201 Created; Lagerort hat ID, Status aktiv

TC-SL-02: Lagerort erstellen mit Temperaturbereich

  1. POST /api/inventory/storage-locations
  2. Body: name: "Tiefkühllager", storageType: "FREEZER", minTemperature: -25, maxTemperature: -18
  • Erwartung: 201 Created; Temperaturbereich korrekt gespeichert

TC-SL-03: Lagerort erstellen ungültiger Temperaturbereich (min >= max)

  1. Body: name: "Fehler-Lager", storageType: "COLD_ROOM", minTemperature: 10, maxTemperature: 5
  • Erwartung: 400 Bad Request; Validierungsfehler

TC-SL-04: Lagerort erstellen Temperatur außerhalb Grenzen

  1. Body: minTemperature: -60, maxTemperature: 90 (Grenzen: -50 bis +80)
  • Erwartung: 400 Bad Request

TC-SL-05: Doppelter Name wird abgelehnt

  1. Lagerort Kühlraum 1 erneut anlegen (Name existiert bereits)
  • Erwartung: 409 Conflict; spezifische Fehlermeldung

TC-SL-06: Leerer Name wird abgelehnt

  1. Body: name: "", storageType: "COLD_ROOM"
  • Erwartung: 400 Bad Request

TC-SL-07: Lagerort bearbeiten Name und Temperatur ändern

  1. PUT /api/inventory/storage-locations/{id}
  2. Name auf Kühlraum A ändern, Temperaturbereich anpassen
  • Erwartung: 200 OK; Änderungen gespeichert
  • Erwartung: StorageType ist unverändert (immutable)

TC-SL-08: Lagerort bearbeiten Unique-Check bei Namensänderung

  1. Lagerort umbenennen auf einen bereits existierenden Namen
  • Erwartung: 409 Conflict

TC-SL-09: Lagerort deaktivieren (ohne Bestand)

  1. PATCH /api/inventory/storage-locations/{id}/deactivate (Lagerort ohne Stock)
  • Erwartung: 200 OK; Status inaktiv

TC-SL-10: Lagerort deaktivieren (mit Bestand) schlägt fehl

  1. Lagerort hat zugeordneten Stock → Deaktivieren versuchen
  • Erwartung: 400/409; Fehlermeldung Bestand existiert

TC-SL-11: Lagerort aktivieren

  1. Deaktivierten Lagerort reaktivieren
  • Erwartung: 200 OK; Status aktiv

TC-SL-12: Doppelte Deaktivierung/Aktivierung

  1. Bereits inaktiven Lagerort erneut deaktivieren
  • Erwartung: Spezifischer Fehler (bereits inaktiv)
  1. Bereits aktiven Lagerort erneut aktivieren
  • Erwartung: Spezifischer Fehler (bereits aktiv)

TC-SL-13: Lagerorte auflisten

  1. GET /api/inventory/storage-locations
  • Erwartung: Liste aller Lagerorte mit id, name, storageType, temperatureRange, active

TC-SL-14: Lagerorte filtern nach Typ

  1. GET /api/inventory/storage-locations?storageType=COLD_ROOM
  • Erwartung: Nur Kühlraum-Lagerorte

TC-SL-15: Lagerorte filtern nach Status

  1. GET /api/inventory/storage-locations?active=true
  • Erwartung: Nur aktive Lagerorte

TC-STK: Bestandspositionen (GitHub #4)

TC-STK-01: Bestandsposition erstellen (Happy Path)

  1. POST /api/inventory/stocks
  2. Body: articleId: "{existierendeId}", storageLocationId: "{existierendeId}"
  • Erwartung: 201 Created; Stock angelegt

TC-STK-02: Bestandsposition erstellen mit MinimumLevel und MinimumShelfLife

  1. Body: articleId, storageLocationId, minimumLevel: 10, minimumShelfLife: 5
  • Erwartung: 201 Created; Werte korrekt gespeichert

TC-STK-03: Doppelte Bestandsposition (gleicher Artikel + Lagerort)

  1. Gleiche Kombination articleId + storageLocationId erneut anlegen
  • Erwartung: 409 Conflict

TC-STK-04: Bestandsposition MinimumLevel negativ

  1. Body: minimumLevel: -1
  • Erwartung: 400 Bad Request

TC-STK-05: Bestandsposition MinimumShelfLife 0 oder negativ

  1. Body: minimumShelfLife: 0
  • Erwartung: 400 Bad Request

TC-BATCH: Chargen einbuchen/entnehmen/sperren (GitHub #5, #6, #7)

TC-BATCH-01: Charge einbuchen (Happy Path)

  1. POST /api/inventory/stocks/{stockId}/batches
  2. Body: batchId: "CH-001", batchType: "PURCHASED", quantity: 50, expiryDate: "2026-06-01"
  • Erwartung: 201 Created; Status AVAILABLE; receivedAt automatisch gesetzt

TC-BATCH-02: Charge einbuchen Menge 0 oder negativ

  1. Body: quantity: 0
  • Erwartung: 400 Bad Request
  1. Body: quantity: -5
  • Erwartung: 400 Bad Request

TC-BATCH-03: Doppelte BatchReference im selben Stock

  1. Erneut batchId: "CH-001", batchType: "PURCHASED" einbuchen
  • Erwartung: 400/409; Duplikat abgelehnt

TC-BATCH-04: Charge teilweise entnehmen

  1. POST /api/inventory/stocks/{stockId}/batches/{batchId}/remove
  2. Body: quantity: 20 (von 50 verfügbar)
  • Erwartung: 200 OK; Restmenge = 30

TC-BATCH-05: Charge vollständig entnehmen

  1. Restmenge (30) komplett entnehmen
  • Erwartung: 200 OK; Charge wird entfernt

TC-BATCH-06: Entnahme übersteigt Bestand

  1. Mehr entnehmen als verfügbar (z.B. 100 von 50)
  • Erwartung: 400; NegativeStockNotAllowed

TC-BATCH-07: Charge sperren

  1. POST /api/inventory/stocks/{stockId}/batches/{batchId}/block
  2. Body: reason: "Qualitätsprüfung ausstehend"
  • Erwartung: 200 OK; Status wechselt auf BLOCKED; Grund dokumentiert

TC-BATCH-08: Gesperrte Charge kann nicht entnommen werden

  1. Entnahme aus BLOCKED-Charge versuchen
  • Erwartung: 400; Entnahme verweigert

TC-BATCH-09: Charge entsperren

  1. POST /api/inventory/stocks/{stockId}/batches/{batchId}/unblock
  • Erwartung: 200 OK; Status zurück auf AVAILABLE (oder EXPIRING_SOON)

TC-BATCH-10: Doppeltes Sperren/Entsperren

  1. Bereits gesperrte Charge erneut sperren
  • Erwartung: Spezifischer Fehler
  1. Bereits freigegebene Charge erneut entsperren
  • Erwartung: Spezifischer Fehler

Manuelle Testfälle Production BC

Kontext

Der Production Bounded Context umfasst:

  • Recipe Rezeptverwaltung mit Zutaten, Produktionsschritten, Status-Lifecycle
  • Batch Chargenplanung und -produktion
  • Quantity Value Object mit Catch-Weight-Unterstützung

API-Basis: /api/recipes und /api/batches


TC-REC: Rezepte (GitHub #26, #27, #28, #29, #30, #31)

TC-REC-01: Rezept erstellen (Happy Path)

  1. POST /api/recipes
  2. Body: name: "Bratwurst Classic", version: 1, recipeType: "FINISHED_PRODUCT", yieldPercentage: 85, shelfLifeDays: 14, outputQuantity: {amount: 10, uom: "KILOGRAM"}
  • Erwartung: 201 Created; Status = DRAFT

TC-REC-02: Rezept erstellen YieldPercentage Grenzen

  1. Body: yieldPercentage: 0
  • Erwartung: 400; InvalidYieldPercentage
  1. Body: yieldPercentage: 201
  • Erwartung: 400; InvalidYieldPercentage

TC-REC-03: Rezept erstellen ShelfLifeDays 0 bei FINISHED_PRODUCT

  1. Body: recipeType: "FINISHED_PRODUCT", shelfLifeDays: 0
  • Erwartung: 400; InvalidShelfLife

TC-REC-04: Doppelter Name + Version wird abgelehnt

  1. Erneut name: "Bratwurst Classic", version: 1 anlegen
  • Erwartung: 409 Conflict

TC-REC-05: Zutat zu DRAFT-Rezept hinzufügen (Happy Path)

  1. POST /api/recipes/{id}/ingredients
  2. Body: position: 1, articleId: "{id}", quantity: {amount: 5, uom: "KILOGRAM"}, substitutable: false
  • Erwartung: 200 OK; Zutat im Rezept

TC-REC-06: Zweite Zutat hinzufügen

  1. Body: position: 2, andere ArticleId, Menge
  • Erwartung: 200 OK; 2 Zutaten im Rezept

TC-REC-07: Zutat mit doppelter Position

  1. Body: position: 1 (bereits vergeben)
  • Erwartung: 400; DuplicatePosition

TC-REC-08: Zutat zu ACTIVE-Rezept hinzufügen

  1. Rezept aktivieren, dann Zutat hinzufügen versuchen
  • Erwartung: 400; NotInDraftStatus

TC-REC-09: Zutat mit SubRecipeId (Zwischen-Rezept)

  1. INTERMEDIATE-Rezept als SubRecipe anlegen
  2. Zutat mit subRecipeId zum Hauptrezept hinzufügen
  • Erwartung: 200 OK; Zutat referenziert Sub-Rezept

TC-REC-10: Zutat entfernen

  1. DELETE /api/recipes/{id}/ingredients/{ingredientId}
  • Erwartung: 200 OK; Zutat entfernt, Position-Lücke erlaubt

TC-REC-11: Produktionsschritt hinzufügen (Happy Path)

  1. POST /api/recipes/{id}/steps
  2. Body: stepNumber: 1, description: "Fleisch wolfen", durationMinutes: 15, temperatureCelsius: 4
  • Erwartung: 200 OK; Schritt im Rezept

TC-REC-12: Produktionsschritt leere Beschreibung

  1. Body: stepNumber: 2, description: ""
  • Erwartung: 400; Validierungsfehler

TC-REC-13: Produktionsschritt zu ACTIVE-Rezept

  1. Schritt zu aktiviertem Rezept hinzufügen versuchen
  • Erwartung: 400; NotInDraftStatus

TC-REC-14: Produktionsschritt entfernen

  1. DELETE /api/recipes/{id}/steps/{stepNumber}
  • Erwartung: 200 OK; Schritt entfernt, keine automatische Umnummerierung

TC-REC-15: Rezept aktivieren (Happy Path)

  1. Rezept mit mindestens einer Zutat → POST /api/recipes/{id}/activate
  • Erwartung: 200 OK; Status = ACTIVE

TC-REC-16: Rezept aktivieren ohne Zutaten

  1. Leeres DRAFT-Rezept aktivieren
  • Erwartung: 400; NoIngredients

TC-REC-17: Rezept aktivieren bereits ACTIVE

  1. Aktives Rezept erneut aktivieren
  • Erwartung: 400; InvalidStatusTransition

TC-REC-18: Rezept archivieren (Happy Path)

  1. POST /api/recipes/{id}/archive (Rezept ist ACTIVE)
  • Erwartung: 200 OK; Status = ARCHIVED

TC-REC-19: Rezept archivieren aus DRAFT

  1. DRAFT-Rezept archivieren versuchen
  • Erwartung: 400; InvalidStatusTransition

TC-REC-20: Rezept per ID abfragen

  1. GET /api/recipes/{id}
  • Erwartung: 200 OK; vollständiges Rezept mit Zutaten und Schritten

TC-REC-21: Rezept nicht gefunden

  1. GET /api/recipes/{nicht-existierende-id}
  • Erwartung: 404 Not Found

TC-REC-22: Rezepte nach Status filtern

  1. GET /api/recipes?status=ACTIVE
  • Erwartung: Nur aktive Rezepte; Liste enthält Zutaten-Count aber nicht volle Zutaten

TC-CYCLE: Zyklus-Erkennung (GitHub #32)

TC-CYCLE-01: Lineare Verschachtelung erlaubt (A → B → C)

  1. Rezept C (ACTIVE, mit Zutat)
  2. Rezept B (DRAFT) → Zutat mit subRecipeId: C
  3. Rezept A (DRAFT) → Zutat mit subRecipeId: B
  • Erwartung: Alle Zuweisungen erfolgreich; keine Fehler

TC-CYCLE-02: Direkte Zirkularität (A → B → A)

  1. Rezept A enthält Zutat mit subRecipeId: B
  2. Rezept B: Zutat mit subRecipeId: A hinzufügen
  • Erwartung: 400; CyclicDependencyDetected mit Pfad-Angabe

TC-CYCLE-03: Indirekte Zirkularität (A → B → C → A)

  1. A → B → C existiert
  2. Zutat mit subRecipeId: A zu Rezept C hinzufügen
  • Erwartung: 400; CyclicDependencyDetected mit Pfad-Angabe

TC-BAT: Chargenplanung (GitHub #33)

TC-BAT-01: Charge planen (Happy Path)

  1. POST /api/batches
  2. Body: recipeId: "{id}", plannedQuantity: {amount: 50, uom: "KILOGRAM"}, productionDate: "2026-03-01", bestBeforeDate: "2026-03-15"
  • Erwartung: 201 Created; Status = PLANNED; BatchNumber automatisch generiert (Format P-YYYY-MM-DD-XXX)

TC-BAT-02: Charge planen PlannedQuantity 0

  1. Body: plannedQuantity: {amount: 0, uom: "KILOGRAM"}
  • Erwartung: 400; Menge muss positiv sein

TC-BAT-03: Charge planen BestBeforeDate vor ProductionDate

  1. Body: productionDate: "2026-03-15", bestBeforeDate: "2026-03-01"
  • Erwartung: 400; BestBeforeDate muss nach ProductionDate liegen

TC-BAT-04: BatchNumber-Format prüfen

  1. Mehrere Chargen am selben Tag planen
  • Erwartung: BatchNumbers haben Format P-YYYY-MM-DD-XXX mit aufsteigender Sequenz

TC-INV-CROSS: Übergreifende Tests Inventory

TC-INV-CROSS-01: Sequenz Kompletter Lagerort-Workflow

  1. Lagerort erstellen → Name ändern → Temperatur anpassen → deaktivieren (ohne Stock) → reaktivieren
  • Erwartung: Alle Schritte funktionieren ohne Datenverlust

TC-INV-CROSS-02: Sequenz Kompletter Chargen-Workflow

  1. Lagerort erstellen → Stock anlegen → Charge einbuchen → Teilentnahme → Charge sperren → Charge entsperren → Rest entnehmen
  • Erwartung: Konsistenz über alle Schritte; Mengen korrekt

TC-INV-CROSS-03: Lagerort mit Bestand kann nicht deaktiviert werden

  1. Lagerort mit Stock + Charge → Deaktivierung versuchen
  • Erwartung: Fehler; Bestand muss erst entfernt werden

TC-PROD-CROSS: Übergreifende Tests Production

TC-PROD-CROSS-01: Sequenz Rezept-Lifecycle komplett

  1. Rezept erstellen (DRAFT) → 2 Zutaten hinzufügen → 2 Schritte hinzufügen → 1 Zutat entfernen → aktivieren → archivieren
  • Erwartung: Konsistenz über alle Schritte

TC-PROD-CROSS-02: Sequenz Rezept + Chargenplanung

  1. Rezept erstellen → Zutaten → aktivieren → Charge planen mit diesem Rezept
  • Erwartung: Charge referenziert Rezept korrekt

TC-PROD-CROSS-03: Verschachteltes Rezept vollständig

  1. INTERMEDIATE-Rezept erstellen + aktivieren → FINISHED_PRODUCT-Rezept mit SubRecipe-Zutat → aktivieren → Charge planen
  • Erwartung: Alle Abhängigkeiten korrekt aufgelöst

Verifikation / Testdurchführung

# Backend starten
./mvnw spring-boot:run

# TUI starten
cd frontend/apps/cli && pnpm dev

# Backend-Logs beobachten (Fehler sichtbar machen)
# Direkte API-Tests (für TC-B2B-02, TC-AUTH, Inventory, Production)
curl -X POST http://localhost:8080/api/... -H "Authorization: Bearer <token>"

Checkliste nach Test-Durchlauf:

  • Alle TC-CAT (1-6) durchgeführt
  • Alle TC-SUP (1-12) durchgeführt
  • Alle TC-ART (1-11) durchgeführt
  • Alle TC-CUS (1-11) durchgeführt
  • TC-B2B (1-2) durchgeführt
  • TC-AUTH (1-3) durchgeführt
  • TC-CROSS (1-5) durchgeführt
  • Alle TC-SL (1-15) durchgeführt
  • Alle TC-STK (1-5) durchgeführt
  • Alle TC-BATCH (1-10) durchgeführt
  • Alle TC-REC (1-22) durchgeführt
  • TC-CYCLE (1-3) durchgeführt
  • TC-BAT (1-4) durchgeführt
  • TC-INV-CROSS (1-3) durchgeführt
  • TC-PROD-CROSS (1-3) durchgeführt