diff --git a/Unterlagen/Fahrplan_Kundenverwaltung_GruppeH/Fahrplan_Kundenverwaltung_GruppeH_1.2.md b/Unterlagen/Fahrplan_Kundenverwaltung_GruppeH/Fahrplan_Kundenverwaltung_GruppeH_1.2.md new file mode 100644 index 0000000..89b09ce --- /dev/null +++ b/Unterlagen/Fahrplan_Kundenverwaltung_GruppeH/Fahrplan_Kundenverwaltung_GruppeH_1.2.md @@ -0,0 +1,228 @@ +# Fahrplan – Modul Kundenverwaltung (Gruppe H) Ver. 1.2 + +**Projekt:** Fakturierungssystem · SE1 Team 2 – Hochschule Mannheim +**Modul / Gruppe:** Kundenverwaltung (Gruppe H) · Package `de.hsmannheim.faktura.kunde` +**Verantwortlich (dieses Dokument):** Christopher Lampert [3027248] +**Gruppe H:** Oleg Akimenko [3028868] (Gruppenleiter), Christopher Lampert [3027248], Kenan Pekarovic [3027541] +**Stand:** 26.06.2026 +**Bezug:** Lastenheft v1.1, Pflichtenheft v1.0, Project Charter v1.1, Modultestplan (KV-Teil), Modultestbericht KV v1.0 + +> **Harte Deadline:** Montag, **29.06.2026, 09:00 Uhr** – Abgabe der Artefakte pro Team. +> **Präsentation:** Montag, 29.06.2026 im regulären Vorlesungsblock (20–25 Min/Team, 4 Vortragende, je Gruppe ein Vertreter). +> **Projektphase laut Charter:** M7 „Puffer & Abnahme" (27.–30.06.2026). + +*Änderung gegenüber v1.1: Phase 6 (Modultests MT-KV-01…11) und Phase 7 (Modultestbericht, P7-1/P7-2) abgeschlossen; Statusmarker, „Aktuelle Position" und Umsetzungsstand aktualisiert; offener Punkt OP-4 (K1 ohne „alle Kunden"-Methode) ergänzt; fehlerhafte Export-Marker entfernt.* + +--- + +## 0. So benutzt du diesen Fahrplan + +Jeder Schritt hat einen Status. Aktualisiere ihn, dann kannst du mir jederzeit sagen „ich bin bei P8-1" und ich habe sofort den Kontext. + +**Statuslegende:** +`[ ]` offen · `[~]` in Arbeit · `[x]` fertig · `[!]` blockiert / offener Punkt + +**Aktuelle Position:** *Phasen 0–7 (KV-Kern + Modultestbericht) abgeschlossen – nächster Schritt: Phase 8 (Integration) bzw. Team-Abstimmung P7-3.* + +### 🚀 Aktueller Umsetzungsstand (für den neuen Chat-Kontext) +Die **Phasen 0 bis 7** der Kundenverwaltung sind umgesetzt: Datenmodell, Persistenz, Validierung, Service-Logik und DP-Schnittstelle stehen, die **11 Modultests MT-KV-01…11** sind grün, und der **Modultestbericht** ist erstellt. Alle entwickelten Klassen sind funktionsfähig und durch JUnit-5-Tests abgedeckt; die Logikschicht erreicht **85 % Line Coverage** (NF-TEST-03 ≥ 60 % erfüllt). + +#### 📁 Erstellte Dateien & Paketstruktur (`de.hsmannheim.faktura.kunde`) +* **Wurzelverzeichnis:** `pom.xml` (Maven-Setup für Java 17, JUnit 5 und Jackson) sowie `.gitignore` (ignoriert `target/` und `.idea/`). +* **`model`:** `Kunde.java` (spezifikationskonformes POJO mit allen 12 Feldern, PLZ als `String`). +* **`repository`:** + * `KundeRepository.java` (Interface für Datenhaltung). + * `KundeContainer.java` (Hilfsklasse für JSON-Bündelung inkl. ID-Zähler). + * `KundeRepositoryJson.java` (Jackson-Implementierung mit fortlaufendem ID-Zähler gegen ID-Wiederverwendung). +* **`service`:** + * `KundeService.java` (zentrale CRUD-Logik inkl. `finde(long)` für die Beleg-Schnittstelle K3). + * `KundeValidator.java` (Pflichtfelder, E-Mail-Format, Bedingung `firmenname || nachname`). + * `BelegReferenzPruefer.java` (funktionales Interface zur Entkopplung der GR-05-Löschsperre von Gruppe F). + * `ValidierungsException.java` & `LoeschsperreException.java` (Unchecked Exceptions). +* **`src/test/java`:** + * `KundeModultestTest.java` – konsolidierte Modultestdatei mit **genau 11 Tests** (MT-KV-01…11, 1:1 zum Modultestplan, je `@DisplayName`). Ersetzt die früheren Einzeldateien `KundeServiceTest`, `KundeValidatorTest` und `KundeRepositoryJsonTest` (deren Abdeckung vollständig übernommen wurde; vgl. P10-2 „max. 4 Test-Dateien"). +* **Abgabe-Artefakt:** `Modultestbericht_Kundenverwaltung_v1_0` (Testergebnisse, Coverage-Nachweis, Abdeckungsübersicht). + +--- + +## 1. Ziel & Abgrenzung + +**Im Scope (nur Gruppe H):** Anlegen, Bearbeiten, Suchen und Löschen von Kunden samt Validierung, Persistenz und Modultests – also die fachlichen Anforderungen **F-KV-01 bis F-KV-04** (Herkunft BA-KV-01…04) sowie die mitwirkenden Regeln **GR-05** (Stammdatenschutz) und **NF-ARCH-01** (Persistenz). + +**Nicht im Scope (andere Gruppen):** Produktverwaltung (G), Dokumentenprozess (F), GUI (E). Diese werden hier **nur über die Schnittstellen** berührt (siehe Abschnitt 2). + +**Leitprinzip:** Alles richtet sich nach den vier Projektdokumenten. Abweichungen werden **nicht still aufgelöst**, sondern als offener Punkt in Abschnitt 8 markiert. + +--- + +## 2. Kompatibilitätsvertrag mit den anderen Modulen + +Damit die Kundenverwaltung sauber mit den Teilen der anderen Teilnehmer zusammenspielt, müssen diese vier Berührungspunkte exakt eingehalten werden. **Bevor integriert wird, sollten diese Signaturen mit Gruppe E und F gegengeprüft sein.** + +| # | Wer braucht es | Was die Kundenverwaltung liefern muss | Quelle | +|---|----------------|----------------------------------------|--------| +| K1 | **GUI (Gruppe E)** über IF-01 | `KundeService` mit `anlegen(Kunde): long`, `bearbeiten(Kunde): void`, `suchen(String): List`, `loeschen(long): void` | Pflichtenheft Klassendiagramm (Kap. 7.2), Komponentendiagramm (Kap. 7.1: `KundeAnsicht → KundeService`) | +| K2 | **Datenhaltung** über IF-02 | `KundeRepository`-Interface (speichern/findeById/findeAlle/loeschen), JSON-Persistenz dahinter gekapselt | IF-02, NF-ARCH-01/02 | +| K3 | **Dokumentenprozess (Gruppe F)** | Kunde ist über `kundeId` (long) referenzierbar; F nutzt `FakeCustomerLookup` und `isCustomerReferenced(...)` in seinen Tests (MT-DP-16). KV muss einen Kunden per ID auflösbar machen (`finde(long): Optional`). | Modultestplan DP (MT-DP-01, MT-DP-16); Pflichtenheft Datenobjekte (kundeId als Referenz in allen Belegen) | +| K4 | **Löschsperre GR-05** | Vor dem Löschen prüft `KundeService`, ob der Kunde in einem Beleg referenziert ist → Abfrage gegen `BelegRepository` (Gruppe F). Bei Referenz: Löschen ablehnen. | GR-05; F-KV-04; MT-KV-11 | + +**Daten-Kontrakt „Kunde" (Pflichtenheft Kap. 6.1.2) – verbindlich:** + +| Attribut | Java-Typ | Pflicht | Constraint | +|----------|----------|---------|------------| +| kundeId | `long` | Pflicht | Fortlaufender, eindeutiger Primärschlüssel | +| firmenname | `String` | Pflicht\* | Pflicht, sofern kein Nachname | +| nachname | `String` | Pflicht\* | Pflicht, sofern kein Firmenname | +| vorname | `String` | Optional | – | +| strasse | `String` | Pflicht | Straße + Hausnummer | +| plz | `String` | Pflicht | String (führende Nullen erhalten) | +| ort | `String` | Pflicht | – | +| telefon | `String` | Optional | – | +| email | `String` | Optional | Formatvalidierung, falls angegeben | +| ustIdNr | `String` | Optional | USt-IdNr. | +| lieferadresse | `String` | Optional | abweichende Lieferadresse | +| ansprechpartner | `String` | Optional | – | + +\* **Constraint:** `firmenname != null || nachname != null` (mindestens eines befüllt). + +--- + +## 3. Technische Vorgaben (aus Pflichtenheft Kap. 2.3) + +- **Sprache:** Java LTS ≥ 17 +- **Persistenz:** lokale **JSON-Datei** (z. B. Jackson), hinter `KundeRepository` gekapselt → austauschbar (NF-ARCH-02) +- **Tests:** **JUnit 5 (Jupiter)** – GUI-unabhängige Logiktests (NF-TEST-02) +- **Architektur:** 3-Schichten (ui → service → repository); KV berührt nur `service` + `repository` +- **Versionierung:** Git / Gitty, Code-Review je Merge (NF-VER-02) +- **Relevante NF-Ziele:** NF-USE-01 (Kunde anlegen < 2 min), NF-PERF-01 (Aktion < 1 s bei 1.000 Kunden), NF-PERF-02 (Liste < 2 s), NF-SEC-01 (kein Klartext von außen), NF-SEC-02 (DSGVO-Löschen) + +--- + +## 4. Die Phasen (Schritt für Schritt) + +### Phase 0 – Setup & Abstimmung +- `[x]` **P0-1** Git/Gitty: Branch für Gruppe H angelegt und Paketstruktur erstellt. +- `[x]` **P0-2** Build-Setup: Maven mit Java 17, JUnit 5 und Jackson in `pom.xml` aufgesetzt. +- `[ ]` **P0-3** Schnittstellen K1–K4 mit Gruppe E und F gegenprüfen *(wird bei Integration relevant, Phase 8)*. +- `[ ]` **P0-4** Offenen Punkt OP-1 mit Team klären *(Code ist durch Interface entkoppelt)*. + +### Phase 1 – Datenmodell +- `[x]` **P1-1** Klasse `Kunde` mit allen 12 Attributen erstellt (`plz` als `String`). +- `[x]` **P1-2** Getter/Setter und `equals`/`hashCode` über `kundeId` implementiert. +- `[x]` **P1-3** JSON-Serialisierbarkeit via Jackson durch leeren Konstruktor sichergestellt. + +### Phase 2 – Persistenz (IF-02 / NF-ARCH-01/02) +- `[x]` **P2-1** Interface `KundeRepository` mit CRUD-Signaturen definiert. +- `[x]` **P2-2** `KundeRepositoryJson` lädt/speichert lokale JSON-Datei via Jackson. +- `[x]` **P2-3** Fortlaufende ID-Vergabe über mitgespeicherten Zähler gelöst (kein ID-Reuse nach Löschung). +- `[x]` **P2-4** Persistenz-Roundtrip geprüft (jetzt in MT-KV-06 enthalten). + +### Phase 3 – Validierung +- `[x]` **P3-1** Pflichtfeldprüfung für `strasse`, `plz`, `ort` in `KundeValidator` eingebaut. +- `[x]` **P3-2** Constraint `firmenname != null || nachname != null` umgesetzt. +- `[x]` **P3-3** E-Mail-Formatprüfung per Regex integriert. +- `[x]` **P3-4** `ValidierungsException` erstellt; wird vor dem Speichern geworfen, um ungültige Daten zu blockieren. + +### Phase 4 – Logik: `KundeService` (F-KV-01…04) +- `[x]` **P4-1** `anlegen(Kunde)` validiert, erzwingt ID-Vergabe und persistiert. · **F-KV-01 / BA-KV-01** +- `[x]` **P4-2** `bearbeiten(Kunde)` prüft Existenz, validiert und speichert. · **F-KV-02 / BA-KV-02** +- `[x]` **P4-3** `suchen(String)` filtert über Name (case-insensitive) und Kundennummer. · **F-KV-03 / BA-KV-03** +- `[x]` **P4-4** `loeschen(long)` prüft Existenz und wirft bei aktiver Referenz eine `LoeschsperreException`. · **F-KV-04 / BA-KV-04** +- `[x]` **P4-5** GR-05-Löschsperre über das Interface `BelegReferenzPruefer` vollständig vorbereitet und isoliert getestet. + +### Phase 5 – Schnittstelle zum Dokumentenprozess (K3) +- `[x]` **P5-1** `KundeService.finde(long): Optional` als Schnittstelle für Gruppe F bereitgestellt. +- `[ ]` **P5-2** Mit Gruppe F genaue Aufrufrichtung für `isCustomerReferenced` abstimmen *(offen, Integration)*. + +### Phase 6 – Modultests (JUnit 5, MT-KV-01…11) ✅ abgeschlossen +*Die fachliche Logik wurde in genau die 11 im Modultestplan geforderten Testmethoden überführt – konsolidiert in `KundeModultestTest`, jeweils mit `@DisplayName` (MT-KV-ID sichtbar im Testlauf):* + +- `[x]` **P6-01** MT-KV-01 Kunde mit allen Pflichtattributen anlegen → gespeichert · BA-KV-01 +- `[x]` **P6-02** MT-KV-02 ohne Firmenname/Nachname → abgelehnt · BA-KV-01 +- `[x]` **P6-03** MT-KV-03 ohne Straße → abgelehnt · BA-KV-01 +- `[x]` **P6-04** MT-KV-04 ungültige E-Mail „kunde@" → abgelehnt · BA-KV-01 +- `[x]` **P6-05** MT-KV-05 Telefonnummer ändern → gespeichert · BA-KV-02 +- `[x]` **P6-06** MT-KV-06 Persistenz nach Neuladen → unverändert · BA-KV-02, NF-ARCH-01 +- `[x]` **P6-07** MT-KV-07 Suche über Namen „Muster" → gefunden · BA-KV-03 +- `[x]` **P6-08** MT-KV-08 Suche über Kundennummer → gefunden · BA-KV-03 +- `[x]` **P6-09** MT-KV-09 Suche ohne Treffer → leeres Ergebnis · BA-KV-03 +- `[x]` **P6-10** MT-KV-10 nicht referenzierten Kunden löschen → entfernt · BA-KV-04 +- `[x]` **P6-11** MT-KV-11 referenzierten Kunden löschen → abgewiesen · BA-KV-04, GR-05 +- `[x]` **P6-12** Alle 11 Tests grün; Coverage nachgewiesen: **85 % Line Coverage** im Paket `…kunde.service` (NF-TEST-03 ≥ 60 % erfüllt). + +### Phase 7 – Abgabe-Artefakt: Modultestbericht ✅ weitgehend abgeschlossen +- `[x]` **P7-1** Testlauf dokumentiert: je MT-KV-Fall Ergebnis (bestanden), Datum (26.06.2026), Tester. +- `[x]` **P7-2** Abdeckungsübersicht aus dem Modultestplan (BA-KV-01→MT-KV-01…04 usw.) als Nachweis übernommen. +- `[ ]` **P7-3** Mit Team klären: **max. 4 Dateien** insgesamt → KV-Bericht eigene Datei **oder** in gemeinsame Test-Datei integriert (Koordination mit G/F/E; siehe OP-2). + +### Phase 8 – Integration mit anderen Modulen +- `[ ]` **P8-1** GUI (E): `KundeAnsicht` ruft `KundeService` – Smoke-Test Anlegen/Suchen/Löschen aus der Oberfläche. +- `[ ]` **P8-2** Belege (F): echter Kunde im Angebot referenzierbar; GR-05-Löschsperre greift im integrierten System (MT-DP-16 ↔ MT-KV-11). +- `[ ]` **P8-3** Gesamtsystem startet, KV-CRUD lauffähig (AK-02 Charter). + +### Phase 9 – Präsentation (KV-Anteil) +Pflichtinhalte laut Aufgabenstellung – als KV-Vertreter (1 Person je Gruppe) vorbereiten: +- `[ ]` **P9-1** Demo-Anteil: Kunde anlegen → suchen → bearbeiten → Löschsperre zeigen (referenzierter Kunde). +- `[ ]` **P9-2** **KI-Einsatz:** wo eingesetzt, wie gut hat es funktioniert (konkrete KV-Beispiele). +- `[ ]` **P9-3** **Was nächstes Mal anders:** ehrliche Lessons learned aus der KV-Umsetzung. +- `[ ]` **P9-4** **Modultestplan-Ergebnisse** der KV präsentieren (Abdeckung + Pass-Quote 100 %). +- `[ ]` **P9-5** **Traceability-Stichprobe vorbereiten:** Kette **BA-KV-0x → F-KV-0x → MT-KV-xx → AT-KV-xx** auswendig/griffbereit (Prof prüft stichprobenartig). + +### Phase 10 – Abgabe & Generalprobe +- `[ ]` **P10-1** Code gemergt, Reviews abgeschlossen (NF-VER-02), Tests grün im Hauptbranch. +- `[ ]` **P10-2** Testbericht + Folien im Team konsolidiert (max. 4 Test-Dateien, genau 1 Foliendatei). +- `[ ]` **P10-3** **Abgabe bis Mo 29.06. 09:00 Uhr.** +- `[ ]` **P10-4** Generalprobe Vortrag + Zeitmessung (20–25 Min Team-Budget). + +--- + +## 5. Traceability-Matrix Kundenverwaltung (für die Stichprobenprüfung) + +| Anforderung (LH) | Pflichtenheft | Modultests | Akzeptanztest (LH) | +|------------------|---------------|------------|--------------------| +| BA-KV-01 Kunde anlegen | F-KV-01 | MT-KV-01 … MT-KV-04 | AT-KV-01, AT-KV-02 | +| BA-KV-02 Kunde bearbeiten | F-KV-02 | MT-KV-05, MT-KV-06 | AT-KV-03, AT-KV-04 | +| BA-KV-03 Kunde suchen | F-KV-03 | MT-KV-07 … MT-KV-09 | AT-KV-05, AT-KV-06 | +| BA-KV-04 Kunde löschen | F-KV-04 | MT-KV-10, MT-KV-11 | AT-KV-07, AT-KV-08 | +| GR-05 Stammdatenschutz | F-KV-04 (i.V.m. GR-05) | MT-KV-11 | – | +| NF-ARCH-01 Persistenz | NF-ARCH-01 | MT-KV-06 | AT-NF-… | + +--- + +## 6. Zeitplan bis Montag + +| Tag | Fokus | Status | +|-----|-------|--------| +| **Do 25.06** | Phase 0 + Phase 1 (Setup, Schnittstellen, Datenmodell) | erledigt | +| **Fr 26.06** | Phase 2–7 (Persistenz, Validierung, Service-Logik, DP-Schnittstelle, 11 Modultests grün, Modultestbericht) | erledigt – **KV ist dem Zeitplan voraus** | +| **Sa 27.06** | Puffer + Vorbereitung Integration (Phase 8) und Folien (Phase 9) | offen | +| **So 28.06** | Phase 8 + Phase 9 (Integration, Folien, Traceability-Stichprobe) | offen | +| **Mo 29.06 vor 09:00** | Phase 10 (Konsolidierung, Abgabe, Generalprobe) | offen | + +--- + +## 7. Definition of Done (Kundenverwaltung) + +- `[x]` F-KV-01 bis F-KV-04 implementiert und über `KundeService` aufrufbar (K1). +- `[x]` Persistenz über `KundeRepository`/JSON, Daten überleben Neustart (NF-ARCH-01). +- `[x]` Validierung greift (Pflichtfelder, firmenname||nachname, E-Mail-Format). +- `[~]` GR-05-Löschsperre: isoliert getestet (MT-KV-11); im **integrierten** System noch nachzuweisen (Phase 8). +- `[x]` MT-KV-01…11 alle grün, Coverage ≥ 60 % im `kunde`-Paket (85 % Line in `…service`). +- `[~]` Modultestbericht erstellt; Integration ins Team-Sammelartefakt offen (P7-3). +- `[~]` Traceability BA→F→MT lückenlos und vorführbar; AT-KV-Akzeptanztests teamseitig. +- `[ ]` In Gesamtsystem integriert (GUI + Belege), Code gereviewt und gemergt (Phase 8 / 10). + +--- + +## 8. Offene Punkte (nicht still aufgelöst) + +| ID | Dokument / Stelle | Beschreibung | Vorschlag | +|----|-------------------|--------------|-----------| +| OP-1 | Pflichtenheft Klassendiagramm (Kap. 7.2) vs. GR-05 | Diagramm zeigt `KundeService ..> ProduktRepository`; GR-05-Text fordert Referenzprüfung über `BelegRepository`. Für die Löschsperre F-KV-04/MT-KV-11 ist das **BelegRepository** maßgeblich. | Im Code gegen `BelegRepository` prüfen (über `BelegReferenzPruefer` umgesetzt); Diagramm-Abhängigkeit als Doku-Inkonsistenz an Team/Prüfer melden. | +| OP-2 | Abgabe-Format | „max. 4 Dateien" für Testberichte bei 4 Modulen → Aufteilung 1 Datei/Modul **oder** 1 Sammeldatei? | Team-Entscheidung vor So 28.06; KV-Bericht entsprechend zuschneiden (P7-3). | +| OP-3 | Schnittstelle K3 (Lookup-Richtung) | Genaue Aufrufrichtung zwischen KV und Gruppe F für `isCustomerReferenced` final festzurren. | In P0-3 mit Gruppe F bestätigen. | +| OP-4 | Vertrag K1 vs. GUI-Übersicht (Gruppe E) | K1 enthält keine Methode zum Auflisten **aller** Kunden; `suchen("")` liefert bewusst eine leere Liste. Die `KundeAnsicht` kann die Gesamtliste so nicht über den Service beziehen. Kein Code-Fehler (K1 ist exakt umgesetzt), aber eine Vertragslücke. | Mit Gruppe E klären: entweder `List alle()` im `KundeService` ergänzen oder Konvention „leere Suche = alle Kunden" festlegen. Vor Phase 8 entscheiden. | + +--- + +*Aktualisiere bei jeder Session die Zeile „Aktuelle Position" in Abschnitt 0 und die Status-Marker. Damit kann der Fortschritt jederzeit punktgenau aufgegriffen werden.* diff --git a/Unterlagen/Lastenheft/Lastenheft_v1_1.md b/Unterlagen/Lastenheft/Lastenheft_1.1.md similarity index 100% rename from Unterlagen/Lastenheft/Lastenheft_v1_1.md rename to Unterlagen/Lastenheft/Lastenheft_1.1.md diff --git a/Unterlagen/Lastenheft/Lastenheft_v1_1.pdf b/Unterlagen/Lastenheft/Lastenheft_1.1.pdf similarity index 57% rename from Unterlagen/Lastenheft/Lastenheft_v1_1.pdf rename to Unterlagen/Lastenheft/Lastenheft_1.1.pdf index 3869c75..b15dfce 100644 Binary files a/Unterlagen/Lastenheft/Lastenheft_v1_1.pdf and b/Unterlagen/Lastenheft/Lastenheft_1.1.pdf differ diff --git a/Unterlagen/Modultestbericht/Modultestbericht_Kundenverwaltung_1.0.md b/Unterlagen/Modultestbericht/Modultestbericht_Kundenverwaltung_1.0.md new file mode 100644 index 0000000..3b7c9a4 --- /dev/null +++ b/Unterlagen/Modultestbericht/Modultestbericht_Kundenverwaltung_1.0.md @@ -0,0 +1,117 @@ +--- +title: "Modultestbericht – Kundenverwaltung" +subtitle: "SE1 Team 2 – Hochschule Mannheim · Modul Software Engineering 1" +author: "Christopher Lampert" +date: "26.06.2026" +lang: de-DE +geometry: "left=2.2cm,right=2.2cm,top=2cm,bottom=2cm" +fontsize: 10pt +mainfont: "Latin Modern Roman" +colorlinks: true +linkcolor: "blue" +urlcolor: "blue" +numbersections: false +header-includes: + - \setlength{\tabcolsep}{4pt} + - \renewcommand{\arraystretch}{1.12} + - \usepackage{etoolbox} + - \AtBeginEnvironment{longtable}{\small} + - \usepackage{newunicodechar} + - \newunicodechar{≥}{\ensuremath{\geq}} + - \newunicodechar{≤}{\ensuremath{\leq}} +--- + +# Modultestbericht – Modul Kundenverwaltung (Gruppe H) + +**Modul:** Software Engineering 1 +**Team / Gruppe:** SE1 Team 2 – Gruppe H (Kundenverwaltung), Package `de.hsmannheim.faktura.kunde` +**Version:** 1.0 +**Stand:** 26.06.2026 +**Autor / Tester:** Christopher Lampert +**Bezug:** Modultestplan (KV-Teil), Pflichtenheft v1.1, Lastenheft v1.1, Fahrplan Kundenverwaltung v1.1 + +Dieser Bericht dokumentiert die Durchführung und das Ergebnis der Modultests des Moduls **Kundenverwaltung**. Er weist nach, dass die im Modultestplan definierten Testfälle MT-KV-01 bis MT-KV-11 umgesetzt, ausgeführt und bestanden wurden, und belegt die geforderte Testabdeckung der Logikschicht (NF-TEST-03). + +--- + +## Freigabeübersicht + +| Funktion | Name | Rolle / Gruppe | Datum | +|--------------|----------------------------|------------------------------------|------------| +| Ersteller | Christopher Lampert | Autor / Tester, Gruppe H | 26.06.2026 | +| Prüfer | Oleg Akimenko | Gruppenleiter Gruppe H | _(offen)_ | +| Freigebender | SE1 Team 2 (Gruppenleiter) | Projektleitung / Freigabe | _(offen)_ | + +--- + +## 1. Testgegenstand und Vorgehen + +Geprüft wird die fachliche Logik der Kundenverwaltung – die Anforderungen **F-KV-01 … F-KV-04**, die Geschäftsregel **GR-05** (Stammdatenschutz / Löschsperre) und **NF-ARCH-01** (Persistenz) – über die öffentliche Schnittstelle des `KundeService`. + +Die Tests sind als automatisierte JUnit-5-Tests **ohne GUI-Abhängigkeit** umgesetzt (NF-TEST-02) und in der Datei `KundeModultestTest.java` zusammengefasst. Jeder Testfall bildet **genau einen** Modultestplan-Fall ab (1:1) und trägt dessen Bezeichnung als `@DisplayName`, sodass das Testprotokoll unmittelbar aus dem Testlauf hervorgeht. Die Validierungs- und Persistenzschicht wird dabei real durchlaufen (echtes `KundeValidator`- und JSON-`KundeRepository`-Objekt je Test über `@TempDir`); lediglich die Beleg-Referenzprüfung der Löschsperre (GR-05) wird über das Interface `BelegReferenzPruefer` gesteuert. Die Ausführung erfolgt reproduzierbar über Maven (`mvn test`) bzw. den IntelliJ-Testrunner. + +## 2. Testumgebung + +| Aspekt | Festlegung | +|-------------------------------------|------------------------------------------------------------------------------| +| Programmiersprache | Java 17 (LTS); `maven.compiler.release=17` | +| Test-Framework | JUnit 5 (Jupiter) 5.10.2 | +| Build / Ausführung | Maven, `maven-surefire-plugin` 3.2.5 | +| Persistenz (im Test real genutzt) | Jackson Databind 2.17.1; lokale JSON-Datei je Test (`@TempDir`) | +| Abdeckungsmessung | IntelliJ IDEA Coverage Runner | +| Testdatei | `src/test/java/de/hsmannheim/faktura/kunde/service/KundeModultestTest.java` | + +## 3. Testergebnisse + +Alle elf Modultests wurden am **26.06.2026** ausgeführt und **bestanden**. + +| Testfall | Testziel / Beschreibung | Anforderung | Ergebnis | Datum | Tester | +|----------|---------------------------------------------------|----------------------|-----------|------------|------------| +| MT-KV-01 | Kunde mit vollständigen Pflichtattributen anlegen | BA-KV-01 | bestanden | 26.06.2026 | C. Lampert | +| MT-KV-02 | Kunde ohne Firmenname bzw. Nachname anlegen | BA-KV-01 | bestanden | 26.06.2026 | C. Lampert | +| MT-KV-03 | Kunde ohne Straße anlegen | BA-KV-01 | bestanden | 26.06.2026 | C. Lampert | +| MT-KV-04 | Kunde mit ungültigem E-Mail-Format anlegen | BA-KV-01 | bestanden | 26.06.2026 | C. Lampert | +| MT-KV-05 | Vorhandenen Kunden bearbeiten | BA-KV-02 | bestanden | 26.06.2026 | C. Lampert | +| MT-KV-06 | Persistenz geänderter Kundendaten prüfen | BA-KV-02, NF-ARCH-01 | bestanden | 26.06.2026 | C. Lampert | +| MT-KV-07 | Kunde über Namen suchen | BA-KV-03 | bestanden | 26.06.2026 | C. Lampert | +| MT-KV-08 | Kunde über Kundennummer suchen | BA-KV-03 | bestanden | 26.06.2026 | C. Lampert | +| MT-KV-09 | Nicht vorhandenen Kunden suchen | BA-KV-03 | bestanden | 26.06.2026 | C. Lampert | +| MT-KV-10 | Nicht referenzierten Kunden löschen | BA-KV-04 | bestanden | 26.06.2026 | C. Lampert | +| MT-KV-11 | Referenzierten Kunden löschen | BA-KV-04, GR-05 | bestanden | 26.06.2026 | C. Lampert | + +**Zusammenfassung:** 11 von 11 Testfällen bestanden (Pass-Quote 100 %); 0 fehlgeschlagen; 0 übersprungen. + +## 4. Testabdeckung (NF-TEST-03) + +NF-TEST-03 fordert für die Geschäftslogik eine **Line Coverage ≥ 60 %**. Gemessene Abdeckung der Logikschicht (`de.hsmannheim.faktura.kunde.service`) durch `KundeModultestTest`: + +| Geltungsbereich | Klassen | Methoden | Zeilen (Line) | Branches | +|------------------------------------------|--------------|----------------|-----------------|-----------------| +| Logikschicht (`…kunde.service`) | 100 % (4/4) | 100 % (13/13) | 85 % (41/48) | 73 % (25/34) | + +Mit **85 % Line Coverage** der Geschäftslogik bei **100 % abgedeckten Methoden** ist die geforderte Schwelle von 60 % deutlich übertroffen. **NF-TEST-03 ist erfüllt.** + +## 5. Abdeckungsübersicht (Anforderung → Testfälle) + +Übernommen aus dem Modultestplan (KV-Teil). Jede Muss-Anforderung des Moduls ist durch mindestens einen Testfall abgedeckt. + +| Anforderung | Abgedeckte Testfälle | +|---------------------------|-----------------------| +| BA-KV-01 Kunde anlegen | MT-KV-01 bis MT-KV-04 | +| BA-KV-02 Kunde bearbeiten | MT-KV-05, MT-KV-06 | +| BA-KV-03 Kunde suchen | MT-KV-07 bis MT-KV-09 | +| BA-KV-04 Kunde löschen | MT-KV-10, MT-KV-11 | +| GR-05 Stammdatenschutz | MT-KV-11 | +| NF-ARCH-01 Persistenz | MT-KV-06 | + +## 6. Fazit + +Die fachlichen Anforderungen des Moduls Kundenverwaltung sind durch die Modultests MT-KV-01 bis MT-KV-11 vollständig abgedeckt und nachweislich erfüllt. Alle Tests bestehen (Pass-Quote 100 %), und die geforderte Testabdeckung der Logikschicht ist mit 85 % Line Coverage erreicht (NF-TEST-03). Die Traceability-Kette **BA-KV-0x → F-KV-0x → MT-KV-xx** ist über Modultestplan und diesen Bericht lückenlos belegbar. + +--- + +## Änderungshistorie + +| Version | Datum | Autor | Änderung | +|---------|------------|---------------------|---------------------------------------------------------------------------------------------------------------------------| +| 1.0 | 26.06.2026 | Christopher Lampert | Initiale Erstellung des Modultestberichts: Testergebnisse MT-KV-01…11, Coverage-Nachweis (NF-TEST-03), Abdeckungsübersicht. | diff --git a/Unterlagen/Modultestbericht/Modultestbericht_Kundenverwaltung_1.0.pdf b/Unterlagen/Modultestbericht/Modultestbericht_Kundenverwaltung_1.0.pdf new file mode 100644 index 0000000..d4f9a44 Binary files /dev/null and b/Unterlagen/Modultestbericht/Modultestbericht_Kundenverwaltung_1.0.pdf differ diff --git a/Unterlagen/Pflichtenheft-GruppeH/Pflichtenheft_v1_0.md b/Unterlagen/Pflichtenheft-GruppeH/Pflichtenheft_1.0.md similarity index 100% rename from Unterlagen/Pflichtenheft-GruppeH/Pflichtenheft_v1_0.md rename to Unterlagen/Pflichtenheft-GruppeH/Pflichtenheft_1.0.md diff --git a/Unterlagen/Pflichtenheft-GruppeH/Pflichtenheft_1.1.md b/Unterlagen/Pflichtenheft-GruppeH/Pflichtenheft_1.1.md new file mode 100644 index 0000000..94af53a --- /dev/null +++ b/Unterlagen/Pflichtenheft-GruppeH/Pflichtenheft_1.1.md @@ -0,0 +1,1130 @@ +--- +title: "Pflichtenheft – Fakturierungssystem" +subtitle: "SE1 Team 2 – Hochschule Mannheim" +author: "Christopher Lampert" +date: "11.06.2026" +lang: de-DE +geometry: "left=2.2cm,right=2.2cm,top=2cm,bottom=2cm" +fontsize: 10pt +mainfont: "Latin Modern Roman" +colorlinks: true +linkcolor: "blue" +urlcolor: "blue" +toc: true +toc-depth: 3 +numbersections: false +header-includes: + - \setlength{\tabcolsep}{4pt} + - \renewcommand{\arraystretch}{1.12} + - \usepackage{etoolbox} + - \AtBeginEnvironment{longtable}{\small} + - \usepackage{newunicodechar} + - \newunicodechar{↔}{\ensuremath{\leftrightarrow}} + - \newunicodechar{≥}{\ensuremath{\geq}} + - \newunicodechar{≤}{\ensuremath{\leq}} +--- + +# Pflichtenheft – Fakturierungssystem + +**Modul:** Software Engineering 1 +**Team:** SE1 Team 2 – Hochschule Mannheim +**Version:** 1.0 +**Stand:** 11.06.2026 +**Autor:** Christopher Lampert +**Bezug:** Lastenheft v1.1 (25.06.2026), Project Charter v1.1 (15.05.2026) – Fakturierungssystem + +Dieses Pflichtenheft (System Requirements Specification, SRS) ist das Antwortdokument des Auftragnehmers (SE1 Team 2) auf das Lastenheft v1.1. Es beantwortet die Frage, **wie** die im Lastenheft geforderten Leistungen umgesetzt werden. Im V-Modell steht es auf der Ebene der Systemanforderungen und bildet den direkten Input für den Komponenten- und Integrationstest. + +--- + +## Freigabeübersicht + +| Funktion | Name | Rolle / Gruppe | Datum | +|--------------|----------------------------|------------------------------------|------------| +| Ersteller | Christopher Lampert | Autor, Gruppe H (Kundenverwaltung) | 25.06.2026 | +| Prüfer | Prof. Dr. Gerd Marmitt | Auftraggeber / Gutachter | _(offen)_ | +| Freigebender | SE1 Team 2 (Gruppenleiter) | Projektleitung / Freigabe | _(offen)_ | + +--- + +## Änderungshistorie + +| Version | Datum | Autor | Änderung | +|---------|------------|---------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 1.0 | 11.06.2026 | Christopher Lampert | Initiale Erstellung des Pflichtenhefts auf Basis Lastenheft v1.0 und Project Charter v1.1: funktionale Anforderungen F-PV/F-KV/F-DP/F-GUI mit Satzschablone; nicht-funktionale Anforderungen mit messbaren Kriterien; Datenobjekte mit Java-Datentypen; Schnittstellen IF-01 bis IF-03; Geschäftsregeln GR-01 bis GR-06 mit Java-Umsetzungshinweisen; UML-Diagramme (Use-Case, Kontext, Klassen, Komponenten, Sequenz); testbare Abnahmekriterien (Testfälle TC-*); vollständige Traceability-Matrix LH ↔ PH. | +| 1.1 | 24.06.2026 | Christopher Lampert | Redaktionelle Überarbeitung (Review-Einarbeitung) ohne Versionserhöhung: Freigabeübersicht um Rolle und Datum ergänzt; sechs UML-Diagramme als generierte PNG-Grafiken eingebunden, PlantUML-Quellen nach Anhang 9.5 verschoben; organisatorische Gruppenaufteilung aus Kap. 3.1 entfernt (gehört in den Project-Charter), Modul-Package-Zuordnung beibehalten; Abweichungshinweis zu BA-PV/KV-05…08 in Kap. 4 und Kap. 9.4 bereinigt; Begründung zur BigDecimal-Wahl in Kap. 6.1 ergänzt. | +--- + +## 1. Einleitung + +### 1.1 Zweck des Dokuments + +Das Pflichtenheft beschreibt die technische Umsetzung der im Lastenheft v1.0 spezifizierten fachlichen Anforderungen an das **Fakturierungssystem**. Während das Lastenheft aus Auftraggebersicht festlegt, **was** das System leisten soll, legt dieses Pflichtenheft aus Auftragnehmersicht fest, **wie** die Realisierung erfolgt (Architektur, Technologie, Datentypen, Schnittstellen, Detaildesign). + +| Aspekt | Lastenheft v1.0 | Pflichtenheft (dieses Dokument) | +|----------------|------------------------------|-----------------------------------------------| +| Sichtweise | Auftraggeber (Fachseite) | Auftragnehmer (Entwicklungsteam) | +| Leitfrage | Was soll das System leisten? | Wie wird es umgesetzt? | +| Lösungsneutral | ja | nein | +| V-Modell-Rolle | Eingabe für Abnahmetests | Eingabe für Komponenten- und Integrationstest | + +### 1.2 Geltungsbereich + +Das Pflichtenheft umfasst die technische Spezifikation aller vier Pflichtmodule: + +- **Produktverwaltung** (Gruppe G) +- **Kundenverwaltung** (Gruppe H) +- **Dokumentenprozess** (Gruppe F) +- **Programmoberfläche / GUI** (Gruppe E) + +sowie deren Zusammenspiel über die in Kapitel 6.2 definierten Schnittstellen. + +### 1.3 Referenzen + +- **[1]** `Lastenheft_v1_0.md` – Lastenheft Fakturierungssystem, Version 1.0, 15.05.2026 +- **[2]** `project-charter_v1_1.md` – Project Charter Fakturierungssystem, Version 1.1, 15.05.2026 +- **[3]** § 14 UStG – Umsatzsteuergesetz, Pflichtangaben in Rechnungen +- **[4]** DSGVO – Verordnung (EU) 2016/679 + +### 1.4 Abgrenzung (Nicht-Bestandteil) + +Übernommen aus den Nicht-Zielen des Lastenhefts (Kap. 1.3). Folgende Funktionen sind **nicht** Bestandteil der Realisierung: + +- Mobile Anwendung sowie Cloud- bzw. Multi-Tenant-Betrieb +- Gleichzeitiger Mehrbenutzerbetrieb über Netzwerk +- Vollwertiges Buchhaltungssystem (Bilanz, Kontenrahmen, FiBu-Export) +- Strukturierte E-Rechnung (XRechnung, ZUGFeRD) – die einfache PDF-Ausgabe der Belege ist hingegen Bestandteil (F-DP-07, F-GUI-05) +- Anbindung an externe Buchhaltungs- oder ERP-Systeme +- Mehrsprachigkeit (Realisierung ausschließlich in deutscher Sprache) +- Authentifizierung bzw. Benutzeranmeldung – der Zugriffsschutz erfolgt über das Betriebssystem-Login (vgl. NF-SEC-01) + +--- + +## 2. Systemüberblick + +### 2.1 Kurzbeschreibung + +Das Fakturierungssystem wird als **lokal installierte Java-Desktop-Anwendung** für einen **Einbenutzer-Arbeitsplatz** realisiert. Es bildet den durchgängigen Geschäftsprozess von der Angebotserstellung über Auftragsbestätigung und Lieferschein bis zur Rechnung ab und erlaubt den Export jedes Belegs als PDF. + +### 2.2 Grobe Systemfunktionen + +- CRUD-Operationen für Produkte (anlegen, bearbeiten, suchen, löschen) +- CRUD-Operationen für Kunden (anlegen, bearbeiten, suchen, löschen) +- Dokumentenworkflow Angebot → Auftragsbestätigung → Lieferschein → Rechnung mit automatischen Statusübergängen +- Automatische Summen- und Steuerberechnung gemäß Geschäftsregeln +- Beleg-Export als PDF (inkl. § 14 UStG-Pflichtangaben bei Rechnungen) +- Echtzeit-Suche und tabellarische Übersichten + +### 2.3 Technologiestack + +| Bereich | Festlegung | Begründung | +|--------------------|--------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------| +| Programmiersprache | Java (LTS, ≥ 17) | Modulvorgabe; plattformunabhängige Desktop-Ausführung; objektorientiertes Schichtenmodell | +| GUI-Technologie | JavaFX | Moderne, deklarative Oberflächen (FXML), saubere Trennung von View und Logik; Swing als Alternative | +| Datenpersistenz | Lokale JSON-Datei (z. B. Jackson) | Einbenutzer-Betrieb, keine Server-DB nötig; menschenlesbar und versionierbar; hinter Repository gekapselt (austauschbar gegen SQLite, vgl. NF-ARCH-02) | +| Tests | JUnit 5 (Jupiter) | Standard für Java-Komponententests; GUI-unabhängige Logiktests (NF-TEST-02) | +| PDF-Erzeugung | PDF-Bibliothek (z. B. Apache PDFBox) | Erzeugung druckbarer Belege über die Schnittstelle IF-03 | +| Versionierung | Git / Gitty | Vorgabe Charter v1.1; Code-Reviews je Merge (NF-VER-02) | + +**Hinweis:** Die konkrete Wahl der Persistenz- und PDF-Bibliothek ist eine Realisierungsentscheidung des Auftragnehmers. Sie wird hinter den Schnittstellen IF-02 und IF-03 gekapselt und ist damit austauschbar, ohne die Logikschicht zu verändern. + +### 2.4 Use-Case-Diagramm + +Abbildung 1 zeigt den einzigen Akteur **Anwender** und die Hauptanwendungsfälle des Systems. Die Belegerzeugung folgt der festen Dokumentenkette (GR-01): Eine Auftragsbestätigung setzt ein angenommenes Angebot voraus, ein Lieferschein eine bestätigte Auftragsbestätigung und eine Rechnung einen gelieferten Lieferschein. + +![Abbildung 1: Use-Case-Diagramm des Fakturierungssystems mit Akteur „Anwender".](sources/abb1.png) + +--- + +## 3. Stakeholder und Kontext + +### 3.1 Stakeholder und Modulzuordnung + +Die Stakeholder-Tabelle aus Lastenheft Kap. 3.1 wird um die technische Modul-Package-Zuordnung ergänzt. Die organisatorische Zuordnung der Untergruppen zu den Modulen ist im Project-Charter geregelt. + +| ID | Stakeholder | Beschreibung | Interesse / Implementierungsrolle | +|----|------------------|----------------------------------------|--------------------------------------------------------------------| +| S1 | Auftraggeber | Prof. Dr. Gerd Marmitt | Lehrziele erreicht, Abnahmekriterien erfüllt; Prüfer des Dokuments | +| S2 | Entwicklungsteam | SE1 Team 2 (Gruppen E, F, G, H) | Erfolgreiche Umsetzung; siehe Implementierungsrollen unten | +| S3 | Endnutzer | spätere Anwender (kleines Unternehmen) | Funktionierender Fakturierungsablauf | + +| Modul | Realisierungspaket | Bezug | +|--------------------------|---------------------------------|----------| +| Produktverwaltung | `de.hsmannheim.faktura.produkt` | Kap. 4.1 | +| Kundenverwaltung | `de.hsmannheim.faktura.kunde` | Kap. 4.2 | +| Dokumentenprozess | `de.hsmannheim.faktura.beleg` | Kap. 4.3 | +| Programmoberfläche (GUI) | `de.hsmannheim.faktura.ui` | Kap. 4.4 | + +### 3.2 Benutzerrolle + +Das System kennt – wie im Lastenheft Kap. 3.2 festgelegt – ausschließlich die Rolle **Anwender**. Eine Authentifizierungs- oder Rechtekonzept-Rolle entfällt (vgl. Kap. 1.4). Der Anwender legt Produkt- und Kundenstammdaten an, erstellt Belege entlang der Dokumentenkette und exportiert Belege als PDF. + +### 3.3 Systemkontextdiagramm + +Abbildung 2 grenzt das System gegen seine Umgebung ab. Das System interagiert mit dem Anwender über die GUI, mit dem lokalen Dateisystem zur Persistenz und mit einer PDF-Bibliothek zur Erzeugung druckbarer Belege. Externe System- oder Netzanbindungen bestehen nicht (vgl. Nicht-Ziele). + +![Abbildung 2: Systemkontextdiagramm – Abgrenzung System gegen Umgebung.](sources/abb2.png) + +--- + +## 4. Funktionale Anforderungen + +Jede funktionale Anforderung folgt der Satzschablone des Pflichtenhefts: + +> **F-``-``:** Das System MUSS / SOLLTE / KANN es dem Anwender ermöglichen, ``, indem ``. + +Die Modalverben entsprechen der Priorität (Muss → MUSS, Soll → SOLLTE, Kann → KANN). Jede Anforderung führt ID, Beschreibung, Priorität, Herkunft (Lastenheft-ID) und Akzeptanzkriterium. Die Zuordnung zu Testfällen erfolgt in Kapitel 8 und in der Traceability-Matrix (Kap. 9.4). + +### 4.1 Modul Produktverwaltung (F-PV) + +**F-PV-01 – Produkt anlegen (Muss)** + +Das System MUSS es dem Anwender ermöglichen, ein neues Produkt anzulegen, indem es eine Eingabemaske bereitstellt, die Pflichtattribute `bezeichnung` (String), `einzelpreisNetto` (BigDecimal) und `mehrwertsteuersatz` (BigDecimal) validiert, eine systemintern fortlaufende `produktId` (long) vergibt und das Produkt über den `ProduktService` persistiert sowie in der Produktübersicht anzeigt. + +- **Priorität:** Muss +- **Herkunft:** BA-PV-01 +- **Akzeptanzkriterium:** Ein Produkt mit vollständigen Pflichtattributen wird gespeichert und erscheint in der Übersicht. Fehlt ein Pflichtfeld (insbesondere `mehrwertsteuersatz`), wird eine Fehlermeldung angezeigt und es erfolgt keine Speicherung. + +**F-PV-02 – Produkt bearbeiten (Muss)** + +Das System MUSS es dem Anwender ermöglichen, bestehende Produktdaten zu bearbeiten, indem es das ausgewählte Produkt lädt, geänderte Werte validiert und über den `ProduktService` persistiert; bereits bestehende Belegpositionen behalten ihren zum Erstellungszeitpunkt festgehaltenen `einzelpreisNetto` (GR-04). + +- **Priorität:** Muss +- **Herkunft:** BA-PV-02 (i. V. m. GR-04) +- **Akzeptanzkriterium:** Geänderte Daten sind sofort in den Produktdetails sichtbar und nach erneutem Öffnen weiterhin vorhanden. Eine Preisänderung verändert die Preise bestehender Angebote nicht. + +**F-PV-03 – Produkt suchen (Muss)** + +Das System MUSS es dem Anwender ermöglichen, nach Produkten zu suchen, indem es die Eingabe im Suchfeld gegen die Felder `bezeichnung` und `artikelnummer` auswertet und Treffer tabellarisch anzeigt. + +- **Priorität:** Muss +- **Herkunft:** BA-PV-03 +- **Akzeptanzkriterium:** Produkte werden über Bezeichnung oder Artikelnummer gefunden. Bei ungültiger Eingabe erscheint der Hinweis „Kein Produkt gefunden". + +**F-PV-04 – Produkt löschen (Muss)** + +Das System MUSS es dem Anwender ermöglichen, ein Produkt zu löschen, indem es nach einer Sicherheitsabfrage prüft, ob das Produkt in einem Angebot, einer Auftragsbestätigung, einem Lieferschein oder einer Rechnung referenziert ist (GR-05), und es nur bei fehlender Referenz aus Bestand, Übersicht und Suche entfernt. + +- **Priorität:** Muss +- **Herkunft:** BA-PV-04 (i. V. m. GR-05) +- **Akzeptanzkriterium:** Nach Bestätigung der Sicherheitsabfrage wird ein nicht referenziertes Produkt entfernt und ist nicht mehr auffindbar. Ein referenziertes Produkt wird mit Hinweis abgewiesen. + +### 4.2 Modul Kundenverwaltung (F-KV) + +**F-KV-01 – Kunde anlegen (Muss)** + +Das System MUSS es dem Anwender ermöglichen, einen neuen Kunden anzulegen, indem es die Pflichtattribute (`firmenname` oder `nachname`, `strasse`, `plz`, `ort`) validiert, eine fortlaufende `kundeId` (long) vergibt, eine angegebene `email` auf gültiges Format prüft und den Kunden über den `KundeService` persistiert. + +- **Priorität:** Muss +- **Herkunft:** BA-KV-01 +- **Akzeptanzkriterium:** Ein Kunde mit vollständigen Pflichtattributen wird gespeichert und erscheint in der Kundenliste. Fehlt ein Pflichtfeld oder ist eine angegebene E-Mail-Adresse ungültig formatiert, wird eine Fehlermeldung angezeigt und nicht gespeichert. + +**F-KV-02 – Kunde bearbeiten (Muss)** + +Das System MUSS es dem Anwender ermöglichen, bestehende Kundendaten zu bearbeiten, indem es den ausgewählten Kunden lädt, geänderte Werte validiert und über den `KundeService` persistiert. + +- **Priorität:** Muss +- **Herkunft:** BA-KV-02 +- **Akzeptanzkriterium:** Geänderte Daten werden gespeichert, sofort angezeigt und sind nach erneutem Öffnen des Kunden weiterhin vorhanden. + +**F-KV-03 – Kunde suchen (Muss)** + +Das System MUSS es dem Anwender ermöglichen, nach Kunden zu suchen, indem es die Eingabe im Suchfeld gegen Name (`firmenname`/`nachname`) und Kundennummer (`kundeId`) auswertet und Treffer tabellarisch anzeigt. + +- **Priorität:** Muss +- **Herkunft:** BA-KV-03 +- **Akzeptanzkriterium:** Kunden werden über Namen oder kundeId gefunden. Bei ungültiger Eingabe erscheint der Hinweis „Kein Kunde gefunden". + +**F-KV-04 – Kunde löschen (Muss)** + +Das System MUSS es dem Anwender ermöglichen, einen Kunden zu löschen, indem es nach einer Sicherheitsabfrage prüft, ob der Kunde in einem Beleg referenziert ist (GR-05) bzw. ob gesetzliche Aufbewahrungspflichten bestehen (NF-SEC-02), und ihn nur bei zulässiger Löschung aus Liste und Suche entfernt. + +- **Priorität:** Muss +- **Herkunft:** BA-KV-04 (i. V. m. GR-05, NF-SEC-02) +- **Akzeptanzkriterium:** Ein nicht referenzierter Kunde ohne Aufbewahrungspflicht wird nach Bestätigung entfernt und ist nicht mehr auffindbar. Ein referenzierter Kunde wird mit Hinweis abgewiesen. + +### 4.3 Modul Dokumentenprozess (F-DP) + +**F-DP-01 – Angebot erstellen (Muss)** + +Das System MUSS es dem Anwender ermöglichen, ein Angebot für einen Kunden zu erstellen, indem es Kundenreferenz, `datum` (LocalDate) und mindestens eine `Belegposition` aufnimmt, `gesamtBetragNetto` und `gesamtBetragBrutto` gemäß GR-06 mit BigDecimal berechnet und das Angebot mit `status = AngebotStatus.OFFEN` persistiert. + +- **Priorität:** Muss +- **Herkunft:** BA-DP-01 (i. V. m. GR-06) +- **Akzeptanzkriterium:** Ein Angebot mit Kundenreferenz, Datum, mindestens einer Position und korrekt berechneter Netto- und Bruttosumme ist gespeichert. + +**F-DP-02 – Angebotsstatus setzen (Muss)** + +Das System MUSS es dem Anwender ermöglichen, ein Angebot mit Status `OFFEN` als „angenommen" oder „abgelehnt" zu markieren, indem es `status` auf `AngebotStatus.ANGENOMMEN` bzw. `AngebotStatus.ABGELEHNT` setzt und dauerhaft persistiert (Statusübergänge gemäß Kap. 6.1.7 LH). + +- **Priorität:** Muss +- **Herkunft:** BA-DP-02 +- **Akzeptanzkriterium:** Der gesetzte Status wird dauerhaft gespeichert und ist auch nach Neustart in der Übersicht sichtbar. + +**F-DP-03 – Auftragsbestätigung aus Angebot erzeugen (Muss)** + +Das System MUSS es dem Anwender ermöglichen, ein angenommenes Angebot in eine Auftragsbestätigung umzuwandeln, indem es alle Positionen und die Kundenreferenz übernimmt, die Angebotsreferenz speichert, die Auftragsbestätigung mit `status = AuftragsStatus.BESTAETIGT` anlegt und das Vorgängerangebot automatisch auf `AngebotStatus.UEBERFUEHRT` setzt. + +- **Priorität:** Muss +- **Herkunft:** BA-DP-03 (i. V. m. GR-01) +- **Akzeptanzkriterium:** Alle Angebotsdaten sind übernommen, das Vorgängerangebot ist referenziert und sein Status auf „überführt" gesetzt. + +**F-DP-04 – Lieferschein aus Auftragsbestätigung erzeugen (Muss)** + +Das System MUSS es dem Anwender ermöglichen, aus einer Auftragsbestätigung (`status = BESTAETIGT`) einen Lieferschein zu erzeugen, indem es Referenz, `lieferdatum` (LocalDate) und alle Positionen übernimmt und den Lieferschein mit `status = LieferscheinStatus.OFFEN` persistiert. + +- **Priorität:** Muss +- **Herkunft:** BA-DP-04 (i. V. m. GR-01) +- **Akzeptanzkriterium:** Ein Lieferschein mit Referenz auf die Auftragsbestätigung, Lieferdatum und vollständigen Positionen ist gespeichert. + +**F-DP-05 – Rechnung aus Lieferschein erzeugen (Muss)** + +Das System MUSS es dem Anwender ermöglichen, aus einem Lieferschein (`status = GELIEFERT`) eine Rechnung zu erzeugen, indem es eine eindeutige, fortlaufende `rechnungNr` (GR-02) vergibt, alle § 14 UStG-Pflichtangaben aufnimmt, genau einen Lieferschein referenziert (GR-01) und die Rechnung mit `status = RechnungStatus.OFFEN` persistiert. + +- **Priorität:** Muss +- **Herkunft:** BA-DP-05 (i. V. m. GR-01, GR-02) +- **Akzeptanzkriterium:** Eine Rechnung mit vollständigen § 14 UStG-Pflichtangaben, eindeutiger Rechnungsnummer und Referenz auf den Lieferschein ist erzeugt. + +**F-DP-06 – Rechnungsdatum automatisch setzen (Muss)** + +Das System MUSS es dem Anwender ermöglichen, beim Anlegen einer Rechnung das Rechnungsdatum automatisch zu erhalten, indem es `rechnungsdatum` beim Erzeugen auf `LocalDate.now()` setzt und dauerhaft speichert. + +- **Priorität:** Muss +- **Herkunft:** BA-DP-06 +- **Akzeptanzkriterium:** Das Rechnungsdatum entspricht beim Anlegen dem aktuellen Systemdatum und bleibt persistent. + +**F-DP-07 – Beleg als PDF exportieren (Muss)** + +Das System MUSS es dem Anwender ermöglichen, Angebote, Auftragsbestätigungen, Lieferscheine und Rechnungen als PDF zu exportieren, indem der `PdfExportService` über die Schnittstelle IF-03 eine druckbare PDF-Datei mit allen Beleginhalten erzeugt und unter einem vom Anwender gewählten Pfad speichert; Rechnungs-PDFs enthalten alle § 14 UStG-Pflichtangaben. + +- **Priorität:** Muss +- **Herkunft:** BA-DP-07 +- **Akzeptanzkriterium:** Für jeden Belegtyp wird eine PDF-Datei erzeugt, deren Inhalt dem Beleg entspricht; die Rechnungs-PDF enthält alle § 14 UStG-Pflichtangaben. + +**F-DP-08 – Integrität der Dokumentenkette (Muss)** + +Das System MUSS sicherstellen, dass ein Folgebeleg nur erzeugt werden kann, wenn der Vorgängerbeleg im passenden Status vorliegt, indem es vor jeder Belegerzeugung die Dokumentenkette (Rechnung → Lieferschein → Auftragsbestätigung → Angebot) und den jeweiligen Vorgängerstatus prüft und unzulässige Erzeugungen ablehnt. + +- **Priorität:** Muss +- **Herkunft:** GR-01 +- **Akzeptanzkriterium:** Der Versuch, eine Rechnung ohne zugehörigen Lieferschein (oder einen sonstigen Folgebeleg ohne gültigen Vorgänger) anzulegen, wird abgewiesen. + +**F-DP-09 – Eindeutige fortlaufende Rechnungsnummer (Muss)** + +Das System MUSS sicherstellen, dass jede Rechnung eine eindeutige, fortlaufende und lückenlose Rechnungsnummer erhält, indem es beim Erstellen die nächste freie Nummer vergibt und vergebene Nummern nicht wiederverwendet. + +- **Priorität:** Muss +- **Herkunft:** GR-02 +- **Akzeptanzkriterium:** Drei aufeinanderfolgend erstellte Rechnungen besitzen fortlaufende, eindeutige Nummern. + +**F-DP-10 – Unveränderlichkeit festgeschriebener Rechnungen (Muss)** + +Das System MUSS sicherstellen, dass eine erzeugte und gespeicherte Rechnung inhaltlich nicht mehr geändert werden kann, indem es die Rechnung nach dem Festschreiben als unveränderlich (immutable) behandelt und Bearbeitungsversuche ablehnt. + +- **Priorität:** Muss +- **Herkunft:** GR-03 +- **Akzeptanzkriterium:** Ein Bearbeitungsversuch an einer gespeicherten Rechnung wird abgewiesen. + +**F-DP-11 – Preisübernahme (Preis-Snapshot) (Muss)** + +Das System MUSS sicherstellen, dass der zum Zeitpunkt der Positionsübernahme gültige Einzelpreis in der `Belegposition` festgehalten wird, indem es `einzelpreisNetto` als Kopie in der Position speichert, sodass spätere Produktpreisänderungen bestehende Belege nicht verändern. + +- **Priorität:** Muss +- **Herkunft:** GR-04 +- **Akzeptanzkriterium:** Eine Preisänderung am Produkt verändert den Preis bestehender Angebote nicht. + +**F-DP-12 – Summen- und Steuerberechnung (Muss)** + +Das System MUSS sicherstellen, dass Beträge korrekt berechnet werden, indem es `gesamtpreisNetto` je Position als `menge × einzelpreisNetto`, die Nettosumme als Summe der Positionen, den USt-Betrag je Position als `netto × mehrwertsteuersatz` und die Bruttosumme als `netto + USt` mittels `BigDecimal` (Rundung `HALF_UP`, 2 Nachkommastellen) berechnet. + +- **Priorität:** Muss +- **Herkunft:** GR-06 +- **Akzeptanzkriterium:** Die manuelle Nachrechnung an drei Beispielen stimmt mit der Systemausgabe überein (centgenau). + +### 4.4 Modul Programmoberfläche / GUI (F-GUI) + +**F-GUI-01 – Angebotserfassung über grafische Maske (Muss)** + +Das System MUSS es dem Anwender ermöglichen, Angebote über eine grafische Eingabemaske zu erstellen, indem es Artikel per Dropdown auswählbar macht, die berechnete Gesamtsumme ohne spürbare Verzögerung live aktualisiert und nach dem Speichern eine Erfolgsmeldung anzeigt. + +- **Priorität:** Muss +- **Herkunft:** BA-GUI-01 +- **Akzeptanzkriterium:** Artikel sind per Dropdown wählbar, die Summe aktualisiert sich live und nach dem Speichern erscheint eine Erfolgsmeldung. + +**F-GUI-02 – Auftragsbestätigung über GUI (Muss)** + +Das System MUSS es dem Anwender ermöglichen, ein angenommenes Angebot über die GUI in eine Auftragsbestätigung umzuwandeln, indem es alle Daten ohne erneute Eingabe in die Auftragsbestätigungs-Maske übernimmt, diese mit dem Titel „Auftragsbestätigung" anzeigt und leere Pflichtfelder (Liefertermin) farblich markiert. + +- **Priorität:** Muss +- **Herkunft:** BA-GUI-02 +- **Akzeptanzkriterium:** Alle Daten werden übernommen, der Maskentitel lautet „Auftragsbestätigung" und leere Pflichtfelder sind farblich markiert. + +**F-GUI-03 – Rechnungslegung und Statusanzeige (Muss)** + +Das System MUSS es dem Anwender ermöglichen, über die GUI aus einem Lieferschein eine Rechnung zu erzeugen und deren Status einzusehen, indem es vor dem finalen Speichern eine Druckvorschau anzeigt und den Auftragsstatus in der Übersicht durch ein grünes Icon als „Abgeschlossen" kennzeichnet. + +- **Priorität:** Muss +- **Herkunft:** BA-GUI-03 +- **Akzeptanzkriterium:** Vor dem Speichern erscheint eine Druckvorschau; nach Abschluss ist der Status in der Übersicht durch ein grünes Icon markiert. + +**F-GUI-04 – Belegsuche mit Echtzeit-Filterung (Muss)** + +Das System MUSS es dem Anwender ermöglichen, Belege über eine Suchfunktion zu filtern, indem es die Trefferliste tabellarisch darstellt, sich bei Eingabe von Name oder Nummer sofort aktualisiert und bei einer leeren Trefferliste den Text „Keine Treffer gefunden" anzeigt. + +- **Priorität:** Muss +- **Herkunft:** BA-GUI-04 +- **Akzeptanzkriterium:** Die Trefferliste aktualisiert sich in Echtzeit; bei einer ungültigen Suche erscheint „Keine Treffer gefunden". + +**F-GUI-05 – PDF-Export aus der Belegansicht (Muss)** + +Das System MUSS es dem Anwender ermöglichen, den PDF-Export direkt aus jeder Belegansicht auszulösen, indem es auf der Ansicht eine Schaltfläche „Als PDF exportieren" bereitstellt, beim Klick die Funktion aus F-DP-07 ausführt und eine Erfolgsmeldung mit Speicherpfad anzeigt. + +- **Priorität:** Muss +- **Herkunft:** BA-GUI-05 +- **Akzeptanzkriterium:** Auf jeder Belegansicht ist die Schaltfläche sichtbar und funktionsfähig; nach dem Export erscheint eine Erfolgsmeldung mit Speicherpfad. + +--- + +## 5. Nicht-funktionale Anforderungen + +Die nicht-funktionalen Anforderungen werden 1:1 aus Lastenheft Kap. 5 übernommen und pflichtenheftseitig mit messbarem Kriterium und Realisierungsbezug geführt. Die IDs bleiben unverändert, um die Traceability eindeutig zu halten. Modalverben entsprechen der Priorität. + +### 5.1 Usability (NF-USE) + +| ID | Anforderungstext | Prio | Herkunft (LH) | Akzeptanzkriterium | +|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|------|---------------|---------------------------------------------------------------------------| +| NF-USE-01 | Das Anlegen eines neuen Kunden MUSS ohne vorherige Schulung in weniger als 2 Minuten möglich sein (höchstens 1 Fehlbedienung pro 10 Testnutzenden). | Muss | NF-USE-01 | Usability-Test mit 5 Probanden; Erfolgsquote > 90 %, Median-Zeit < 120 s. | +| NF-USE-02 | Mindestens 80 % der Testnutzenden MÜSSEN die Aufgabe „aus einem Angebot eine Rechnung erzeugen" im ersten Versuch ohne Hilfetext erfolgreich abschließen. | Muss | NF-USE-02 | Usability-Test mit 5 Probanden; mindestens 4 von 5 erfolgreich. | +| NF-USE-03 | Das System MUSS bei jeder validierungspflichtigen Eingabe innerhalb von 1 Sekunde eine sichtbare Rückmeldung (Erfolg oder Fehler) anzeigen. | Muss | NF-USE-03 | Manueller Test mit Stoppuhr; Rückmeldezeit < 1 s. | + +### 5.2 Performance (NF-PERF) + +| ID | Anforderungstext | Prio | Herkunft (LH) | Akzeptanzkriterium | +|------------|-------------------------------------------------------------------------------------------------------------------------------------------------|------|---------------|---------------------------------------------------------------| +| NF-PERF-01 | Das System MUSS jede Benutzeraktion bei bis zu 1.000 Produkten und 1.000 Kunden innerhalb von 1 Sekunde mit sichtbarer Rückmeldung beantworten. | Muss | NF-PERF-01 | Lasttest mit 1.000 Datensätzen je Entität; Antwortzeit < 1 s. | +| NF-PERF-02 | Das System MUSS die Übersichtsliste von Produkten oder Kunden bei bis zu 1.000 Datensätzen innerhalb von 2 Sekunden vollständig anzeigen. | Muss | NF-PERF-02 | Lasttest mit 1.000 Einträgen; Anzeigedauer < 2 s. | +| NF-PERF-03 | Das System SOLLTE den Anwendungsstart bis zur bedienbaren Hauptansicht in höchstens 5 Sekunden abschließen (Referenzhardware). | Soll | NF-PERF-03 | Kaltstart auf Referenzhardware < 5 s. | + +### 5.3 Wartbarkeit (NF-MAINT) + +| ID | Anforderungstext | Prio | Herkunft (LH) | Akzeptanzkriterium | +|-------------|------------------------------------------------------------------------------------------------------------------------------------------|------|---------------|--------------------------------------------------------------------------| +| NF-MAINT-01 | Der Quellcode MUSS modular nach den vier Modulen (Produkt-, Kundenverwaltung, Dokumentenprozess, GUI) in eigenen Paketen getrennt sein. | Muss | NF-MAINT-01 | Statische Prüfung der Repository- und Paketstruktur. | +| NF-MAINT-02 | Mindestens 80 % der öffentlichen Klassen und Methoden SOLLTEN über kurze Dokumentationskommentare (Zweck, Parameter, Rückgabe) verfügen. | Soll | NF-MAINT-02 | Automatisierte Auswertung (JavaDoc-Report) zeigt > 80 %; Stichprobe. | +| NF-MAINT-03 | Das System MUSS einer dokumentierten, dreischichtigen Architektur (Präsentation, Logik, Datenhaltung) folgen. | Muss | NF-MAINT-03 | Review des Architekturkapitels (Kap. 7); nachweisbare Schichtentrennung. | + +### 5.4 Testbarkeit (NF-TEST) + +| ID | Anforderungstext | Prio | Herkunft (LH) | Akzeptanzkriterium | +|------------|----------------------------------------------------------------------------------------------------------------------------------------|------|---------------|-----------------------------------------------------------------------| +| NF-TEST-01 | Jede Anforderung mit Priorität „Muss" MUSS mindestens einem Testfall in der Traceability-Matrix (Kap. 9.4) zugeordnet sein. | Muss | NF-TEST-01 | Vollständigkeitsprüfung der Traceability-Matrix vor Abnahme. | +| NF-TEST-02 | Die Logikschicht MUSS so gestaltet sein, dass sie ohne die GUI durch automatisierte Komponententests (JUnit 5) aufgerufen werden kann. | Muss | NF-TEST-02 | Mindestens ein lauffähiger Unit-Test pro Modul ohne GUI-Abhängigkeit. | +| NF-TEST-03 | Mindestens 60 % der Geschäftslogik-Methoden SOLLTEN durch automatisierte Tests abgedeckt sein (Line Coverage). | Soll | NF-TEST-03 | Coverage-Report > 60 %. | + +### 5.5 Versionierung (NF-VER) + +| ID | Anforderungstext | Prio | Herkunft (LH) | Akzeptanzkriterium | +|-----------|----------------------------------------------------------------------------------------------------------------------|------|---------------|------------------------------------------------------------------| +| NF-VER-01 | Der gesamte Quellcode MUSS in Gitty unter den im Charter v1.1 genannten Repositories versioniert werden. | Muss | NF-VER-01 | Sichtprüfung der Repositories. | +| NF-VER-02 | Jeder Merge in den Hauptbranch MUSS durch mindestens ein Code-Review eines anderen Teammitglieds freigegeben werden. | Muss | NF-VER-02 | Review-Historie zeigt für jeden Merge mindestens einen Reviewer. | + +### 5.6 Architektur und Datenhaltung (NF-ARCH) + +| ID | Anforderungstext | Prio | Herkunft (LH) | Akzeptanzkriterium | +|------------|---------------------------------------------------------------------------------------------------------------------------------------------------------|------|---------------|--------------------------------------------------------------------| +| NF-ARCH-01 | Das System MUSS alle Datensätze (Produkte, Kunden, Dokumente) persistent so speichern, dass sie nach einem Neustart vollständig wiederherstellbar sind. | Muss | NF-ARCH-01 | Datensätze anlegen, Anwendung neu starten; Datensätze unverändert. | +| NF-ARCH-02 | Die Datenhaltung SOLLTE hinter einer abstrakten Schnittstelle (Repository/DAO) gekapselt sein, sodass die Speichertechnologie austauschbar ist. | Soll | NF-ARCH-02 | Code-Review zeigt Repository- bzw. DAO-Abstraktion (IF-02). | + +### 5.7 Sicherheit und Datenschutz (NF-SEC) + +| ID | Anforderungstext | Prio | Herkunft (LH) | Akzeptanzkriterium | +|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------|------|---------------|----------------------------------------------------------------------| +| NF-SEC-01 | Das System SOLLTE personenbezogene Kundendaten so speichern, dass sie ohne Zugriff auf das Anwendungs-Verzeichnis nicht im Klartext einsehbar sind. | Soll | NF-SEC-01 | Inspektion aus fremdem Nutzerkontext zeigt keinen lesbaren Klartext. | +| NF-SEC-02 | Das System SOLLTE das Löschen eines Kunden gemäß DSGVO Art. 17 ermöglichen, sofern keine gesetzlichen Aufbewahrungspflichten entgegenstehen. | Soll | NF-SEC-02 | Löschanforderung ohne aktive Rechnungen entfernt den Kunden. | + +--- + +## 6. Daten und Schnittstellen + +### 6.1 Datenobjekte mit Java-Datentypen + +Für jedes Datenobjekt aus Lastenheft Kap. 6.1 wird die technische Realisierung mit konkreten Java-Datentypen festgelegt. Geldbeträge und Steuersätze werden ausnahmslos als `BigDecimal` modelliert (niemals `double`/`float`), Datumsangaben als `LocalDate`, Statusfelder als eigene `enum`-Klassen. + +BigDecimal wird trotz der in der Vorlesung genannten Nachteile gewählt: höhere Ausführlichkeit (keine arithmetischen Operatoren – Berechnungen über `add()`, `multiply()`, `compareTo()`), höherer Rechen- und Speicheraufwand gegenüber primitiven Typen sowie die bekannte Falle, dass `equals()` die Skala mitvergleicht (Vergleiche daher über `compareTo()`). Diese Nachteile sind hier vertretbar, weil exakte Dezimalarithmetik bei Geldbeträgen Vorrang vor Performance hat (Rundungsfehler von `double`/`float` sind ausgeschlossen), die Datenmengen klein sind (Einzelplatz, wenige Positionen je Beleg) und das Vorgehen den Vorlesungsbeispielen sowie GR-06 entspricht. Die Alternative – Beträge als `long` in Cent – wurde verworfen, da sie Steuersätze und Prozentrechnung (z. B. 0.19) sowie mehrstufige Rundung umständlicher abbildet.Die Entscheidung für BigDecimal wurde daher bewusst getroffen, da die fachliche Korrektheit von Geldbeträgen im Fakturierungsprozess Vorrang vor einer maximalen Rechenleistung besitzt. + +#### 6.1.1 Produkt + +| Attribut | Java-Typ | Pflicht/Optional | Beschreibung / Constraint | +|--------------------|------------|------------------|----------------------------------------------------------------------------------| +| produktId | long | Pflicht | Systeminterner, fortlaufender Primärschlüssel; eindeutig. | +| bezeichnung | String | Pflicht | Anzeigename (synonym: Produktname); nicht leer. | +| einzelpreisNetto | BigDecimal | Pflicht | Nettopreis ≥ 0; Skala 2, Rundung HALF_UP. | +| mehrwertsteuersatz | BigDecimal | Pflicht | Steuersatz als Dezimalwert (z. B. 0.19); ≥ 0. | +| artikelnummer | String | Optional | Anwenderkennung; falls leer, abgeleitet aus produktId nach Schema `P-`. | +| beschreibung | String | Optional | Freitext. | +| kategorie | String | Optional | Gruppierungsmerkmal. | + +#### 6.1.2 Kunde + +| Attribut | Java-Typ | Pflicht/Optional | Beschreibung / Constraint | +|-----------------|----------|------------------|----------------------------------------------------------------------------| +| kundeId | long | Pflicht | Fortlaufender, eindeutiger Primärschlüssel. | +| firmenname | String | Pflicht* | Pflicht, sofern kein Nachname angegeben ist (mindestens eines von beiden). | +| nachname | String | Pflicht* | Pflicht, sofern kein Firmenname angegeben ist. | +| vorname | String | Optional | – | +| strasse | String | Pflicht | Straße und Hausnummer. | +| plz | String | Pflicht | Postleitzahl (String, um führende Nullen zu erhalten). | +| ort | String | Pflicht | – | +| telefon | String | Optional | – | +| email | String | Optional | Wird auf gültiges Format validiert, falls angegeben. | +| ustIdNr | String | Optional | Umsatzsteuer-Identifikationsnummer. | +| lieferadresse | String | Optional | Abweichende Lieferadresse. | +| ansprechpartner | String | Optional | – | + +*Constraint: `firmenname != null || nachname != null` (mindestens eines der beiden Felder ist befüllt). + +#### 6.1.3 Angebot + +| Attribut | Java-Typ | Pflicht/Optional | Beschreibung / Constraint | +|--------------------|-----------------------|------------------|--------------------------------------------| +| angebotNr | String | Pflicht | Format `A--`; eindeutig. | +| kundeId | long | Pflicht | Referenz auf Kunde. | +| datum | LocalDate | Pflicht | Angebotsdatum. | +| positionen | List\ | Pflicht | Mindestens eine Position. | +| gesamtBetragNetto | BigDecimal | Pflicht | Berechnet gemäß GR-06; Skala 2. | +| gesamtBetragBrutto | BigDecimal | Pflicht | Berechnet gemäß GR-06; Skala 2. | +| status | AngebotStatus | Pflicht | OFFEN, ANGENOMMEN, ABGELEHNT, UEBERFUEHRT. | + +#### 6.1.4 Belegposition + +| Attribut | Java-Typ | Pflicht/Optional | Beschreibung / Constraint | +|--------------------|------------|------------------|-------------------------------------------------------------------| +| produktId | long | Pflicht | Referenz auf Produkt. | +| bezeichnung | String | Pflicht | Kopie der Produktbezeichnung zum Erstellungszeitpunkt. | +| menge | int | Pflicht | Stückzahl > 0. | +| einzelpreisNetto | BigDecimal | Pflicht | Preis-Snapshot gemäß GR-04; durch spätere Änderungen unverändert. | +| mehrwertsteuersatz | BigDecimal | Pflicht | Steuersatz-Snapshot der Position. | +| gesamtpreisNetto | BigDecimal | Pflicht | `menge × einzelpreisNetto` (GR-06); Skala 2. | + +#### 6.1.5 Auftragsbestätigung + +| Attribut | Java-Typ | Pflicht/Optional | Beschreibung / Constraint | +|--------------------|-----------------------|------------------|------------------------------------------| +| auftragNr | String | Pflicht | Format `AB--`; eindeutig. | +| angebotNr | String | Pflicht | Referenz auf genau ein Angebot. | +| kundeId | long | Pflicht | Referenz auf Kunde. | +| datum | LocalDate | Pflicht | Bestätigungsdatum. | +| positionen | List\ | Pflicht | Übernommen aus dem Angebot. | +| gesamtBetragNetto | BigDecimal | Pflicht | Skala 2. | +| gesamtBetragBrutto | BigDecimal | Pflicht | Skala 2. | +| status | AuftragsStatus | Pflicht | BESTAETIGT, GELIEFERT. | + +#### 6.1.6 Lieferschein + +| Attribut | Java-Typ | Pflicht/Optional | Beschreibung / Constraint | +|----------------|-----------------------|------------------|----------------------------------------------| +| lieferscheinNr | String | Pflicht | Format `LS--`; eindeutig. | +| auftragNr | String | Pflicht | Referenz auf genau eine Auftragsbestätigung. | +| kundeId | long | Pflicht | Referenz auf Kunde. | +| lieferdatum | LocalDate | Pflicht | Datum der Auslieferung. | +| positionen | List\ | Pflicht | Produkt und Menge je Position. | +| status | LieferscheinStatus | Pflicht | OFFEN, GELIEFERT, FAKTURIERT. | + +#### 6.1.7 Rechnung + +| Attribut | Java-Typ | Pflicht/Optional | Beschreibung / Constraint | +|--------------------|-----------------------|------------------|-------------------------------------------------------------------------| +| rechnungNr | String | Pflicht | Eindeutig, fortlaufend, lückenlos (GR-02); Format `R--`. | +| lieferscheinNr | String | Pflicht | Referenz auf genau einen Lieferschein (GR-01). | +| kundeId | long | Pflicht | Referenz auf Kunde. | +| rechnungsdatum | LocalDate | Pflicht | Automatisch `LocalDate.now()` beim Anlegen (F-DP-06). | +| positionen | List\ | Pflicht | – | +| gesamtBetragNetto | BigDecimal | Pflicht | Skala 2. | +| gesamtBetragUst | BigDecimal | Pflicht | USt-Betrag gemäß GR-06; Skala 2. | +| gesamtBetragBrutto | BigDecimal | Pflicht | Skala 2. | +| status | RechnungStatus | Pflicht | OFFEN, BEZAHLT. | + +#### 6.1.8 Enum-Klassen + +| Enum | Konstanten | +|--------------------|-------------------------------------------| +| AngebotStatus | OFFEN, ANGENOMMEN, ABGELEHNT, UEBERFUEHRT | +| AuftragsStatus | BESTAETIGT, GELIEFERT | +| LieferscheinStatus | OFFEN, GELIEFERT, FAKTURIERT | +| RechnungStatus | OFFEN, BEZAHLT | + +#### 6.1.9 UML-Klassendiagramm der Datenobjekte + +Abbildung 3 zeigt die Datenobjekte mit ihren Java-Typen und Beziehungen. Ein Kunde besitzt beliebig viele Angebote; jeder Beleg besteht aus mindestens einer Belegposition; jede Position verweist auf genau ein Produkt. Die Belege bilden die Dokumentenkette Angebot → Auftragsbestätigung → Lieferschein → Rechnung mit Multiplizität 1:0..1 (jeder Vorgänger hat höchstens einen Nachfolger). + +![Abbildung 3: UML-Klassendiagramm der Datenobjekte mit Java-Typen und Multiplizitäten.](sources/abb3.png) + +### 6.2 Schnittstellen + +Die Schnittstellen folgen der Satzschablone: **IF-``:** Das System MUSS `` bereitstellen, um ``. + +| ID | Schnittstelle | Anforderung (Satzschablone) | Bezug LH | +|-------|--------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------|----------| +| IF-01 | Benutzerschnittstelle | Das System MUSS eine grafische Benutzerschnittstelle (GUI ↔ Logikschicht) bereitstellen, um die Interaktion des Anwenders zu ermöglichen. | IF-01 | +| IF-02 | Persistenzschnittstelle | Das System MUSS eine Persistenzschnittstelle (Logikschicht ↔ Datenhaltung via Repository/DAO) bereitstellen, um Daten dauerhaft zu speichern und zu laden. | IF-02 | +| IF-03 | PDF-Export-Schnittstelle | Das System MUSS eine PDF-Export-Schnittstelle (Logikschicht ↔ PDF-Bibliothek) bereitstellen, um Belege als druckbare PDF auszugeben. | IF-03 | + +### 6.3 Geschäftsregeln + +Die Geschäftsregeln GR-01 bis GR-06 werden aus Lastenheft Kap. 6.3 übernommen und um Java-seitige Umsetzungshinweise ergänzt. + +**GR-01 – Dokumentenkette.** Eine Rechnung verweist auf genau einen Lieferschein, ein Lieferschein auf genau eine Auftragsbestätigung, eine Auftragsbestätigung auf genau ein Angebot. Ein Folgedokument darf nur erzeugt werden, wenn das Vorgängerdokument im passenden Status (Kap. 6.1.7 LH) vorliegt. +*Umsetzung:* Statusprüfung im jeweiligen Service vor der Erzeugung; Referenz als Pflicht-Fremdschlüssel (z. B. `lieferscheinNr` in `Rechnung`); Verstoß löst eine fachliche Ausnahme (`IllegalStateException`/eigene `BelegketteException`) aus. Realisiert in F-DP-08. + +**GR-02 – Eindeutigkeit der Rechnungsnummer.** Das System vergibt beim Erstellen die nächste freie, fortlaufende Rechnungsnummer; Nummern werden nicht wiederverwendet. +*Umsetzung:* Zentraler Nummernkreis im `RechnungService` (z. B. `AtomicLong` bzw. persistierter Zähler); Format `R--`. Realisiert in F-DP-09. + +**GR-03 – Unveränderlichkeit festgeschriebener Rechnungen.** Eine gespeicherte Rechnung ist inhaltlich nicht mehr änderbar. +*Umsetzung:* `Rechnung` als unveränderliches Objekt (finale Felder, keine Setter); das `RechnungRepository` bietet keine Update-Operation für festgeschriebene Rechnungen. Realisiert in F-DP-10. + +**GR-04 – Preisübernahme.** Der zum Zeitpunkt der Positionsübernahme gültige Einzelpreis wird in der Position festgehalten und durch spätere Produktpreisänderungen nicht verändert. +*Umsetzung:* Beim Hinzufügen einer Position wird `einzelpreisNetto` als Kopie aus dem Produkt in die `Belegposition` übernommen (Snapshot), nicht als Referenz. Realisiert in F-DP-11. + +**GR-05 – Stammdatenschutz.** Ein Produkt oder Kunde darf nicht gelöscht werden, solange er in einem Beleg referenziert wird. +*Umsetzung:* Vor dem Löschen prüft der `ProduktService`/`KundeService` über das `BelegRepository`, ob Referenzen bestehen; bei Treffer wird das Löschen abgewiesen. Realisiert in F-PV-04 und F-KV-04. + +**GR-06 – Summenberechnung.** Nettosumme = SUM(Menge × Einzelpreis); USt-Betrag pro Position = Netto × MwSt-Satz; Bruttosumme = Netto + USt. +*Umsetzung:* Berechnung ausschließlich mit `BigDecimal` über `multiply()`/`add()`; Rundung `RoundingMode.HALF_UP` auf 2 Nachkommastellen (`setScale(2, HALF_UP)`). Realisiert in F-DP-12. + +--- + +## 7. Systemarchitektur + +### 7.1 Dreischichtige Architektur + +Das System folgt gemäß NF-MAINT-03 und NF-ARCH-01/02 einer dokumentierten, dreischichtigen Architektur mit klarer Trennung der Verantwortlichkeiten: + +| Schicht | Aufgabe | Realisierung / Package | +|----------------------|--------------------------------------------------------|--------------------------------------------------| +| Präsentationsschicht | Darstellung, Benutzerinteraktion (GUI) | JavaFX/Swing, `de.hsmannheim.faktura.ui` | +| Logikschicht | Geschäftslogik, Validierung, Berechnungen, Statuslogik | Service-Klassen, `de.hsmannheim.faktura.service` | +| Datenhaltungsschicht | Persistenz, gekapselt über Repository/DAO | `de.hsmannheim.faktura.repository` | + +Die Schichten kommunizieren ausschließlich über die in Kap. 6.2 definierten Schnittstellen (IF-01 GUI ↔ Logik, IF-02 Logik ↔ Datenhaltung, IF-03 Logik ↔ PDF-Bibliothek). Abbildung 4 zeigt die vier fachlichen Module als Komponenten innerhalb der drei Schichten. + +![Abbildung 4: Komponentendiagramm – vier Module in der dreischichtigen Architektur.](sources/abb4.png) +Das Komponentendiagramm verdeutlicht die Trennung zwischen Präsentations-, Logik- und Datenhaltungsschicht. Die Kommunikation erfolgt ausschließlich über definierte Schnittstellen. Dadurch wird eine geringe Kopplung der Komponenten sowie eine bessere Wartbarkeit und Testbarkeit des Systems erreicht. + + + +### 7.2 UML-Klassendiagramm der Kernklassen + +Abbildung 5 zeigt die Kernklassen der Logik- und Datenhaltungsschicht mit Methodensignaturen (Parameter- und Rückgabetypen) sowie deren Beziehungen. Die Services bilden die Logikschicht, das `ProduktRepository` steht stellvertretend für die als Interface modellierte Persistenzabstraktion (IF-02, NF-ARCH-02). + +![Abbildung 5: Detailliertes UML-Klassendiagramm der Kernklassen mit Methodensignaturen.](sources/abb5.png) + +### 7.3 UML-Sequenzdiagramm „Angebot → Rechnung" + +Abbildung 6 zeigt den Hauptprozess von der Statusänderung eines angenommenen Angebots bis zur Erzeugung der Rechnung. Der Anwender stößt die Aktionen über die GUI an; die Services kapseln die Geschäftslogik (Statusprüfung GR-01, Nummernvergabe GR-02, Summenberechnung GR-06), die Repositories übernehmen die Persistenz. + +![Abbildung 6: UML-Sequenzdiagramm des Hauptprozesses „Angebot → Rechnung".](sources/abb6.png) +Das Sequenzdiagramm beschreibt den Ablauf der Rechnungserstellung einschließlich Statusprüfung, Nummernvergabe und Persistierung. Die dargestellte Reihenfolge stellt sicher, dass ausschließlich fachlich gültige Geschäftsvorgänge in Rechnungen überführt werden können. + +--- + +## 8. Testbare Abnahmekriterien + +Für jede Muss-Anforderung ist mindestens ein Testfall definiert. Jeder Testfall gibt die Testart an: **Unit** (JUnit-5-Komponententest der Logikschicht ohne GUI), **Integration** (schichtübergreifend, inkl. Persistenz) oder **manuell** (manueller Akzeptanztest über die GUI). Die Testfälle sind so detailliert, dass daraus direkt ein Modultestplan ableitbar ist. + +### 8.1 Produktverwaltung (TC-PV) + +| TC-ID | Bezeichnung | Vorbedingung | Testeingabe | Erwartetes Ergebnis | PH-Anf. | Testart | +|----------|---------------------------------------|------------------------------------|------------------------------------------------|----------------------------------------------------------------------|---------|-------------| +| TC-PV-01 | Produkt mit Pflichtattributen anlegen | Leerer Produktbestand | bezeichnung, einzelpreisNetto=10.00, mwst=0.19 | Produkt gespeichert, erscheint in Übersicht, produktId vergeben. | F-PV-01 | Integration | +| TC-PV-02 | Anlegen ohne MwSt-Satz | Eingabemaske offen | Pflichtfeld mehrwertsteuersatz leer | Fehlermeldung; keine Speicherung. | F-PV-01 | Unit | +| TC-PV-03 | Preis ändern, Angebot unverändert | Produkt in bestehendem Angebot | einzelpreisNetto von 10.00 auf 12.00 ändern | Produktpreis aktualisiert; Position im Bestandsangebot bleibt 10.00. | F-PV-02 | Integration | +| TC-PV-04 | Persistenz nach Neustart | Produkt bearbeitet | Anwendung neu starten, Produkt öffnen | Geänderte Daten weiterhin vorhanden. | F-PV-02 | Integration | +| TC-PV-05 | Produktsuche Treffer | Produkt „Schraube" vorhanden | Suchbegriff „Schraube" | Produkt erscheint in Trefferliste. | F-PV-03 | Unit | +| TC-PV-06 | Produktsuche kein Treffer | Bestand ohne passendes Produkt | Suchbegriff „xyz123" | Hinweis „Kein Produkt gefunden". | F-PV-03 | Unit | +| TC-PV-07 | Löschen referenzierten Produkts | Produkt in Angebot referenziert | Löschen auslösen | Löschen abgewiesen (GR-05); Produkt bleibt erhalten. | F-PV-04 | Integration | +| TC-PV-08 | Löschen nicht referenzierten Produkts | Produkt ohne Referenz, Bestätigung | Löschen + Sicherheitsabfrage bestätigen | Produkt entfernt; nicht mehr in Übersicht/Suche. | F-PV-04 | Integration | + +### 8.2 Kundenverwaltung (TC-KV) + +| TC-ID | Bezeichnung | Vorbedingung | Testeingabe | Erwartetes Ergebnis | PH-Anf. | Testart | +|----------|-------------------------------------|--------------------------------|-------------------------------|----------------------------------------------|---------|-------------| +| TC-KV-01 | Kunde mit Pflichtattributen anlegen | Leerer Kundenbestand | firmenname, strasse, plz, ort | Kunde gespeichert, erscheint in Kundenliste. | F-KV-01 | Integration | +| TC-KV-02 | Ungültige E-Mail abweisen | Eingabemaske offen | email = „abc@" | Fehlermeldung Format; keine Speicherung. | F-KV-01 | Unit | +| TC-KV-03 | Telefonnummer ändern | Kunde vorhanden | telefon ändern, speichern | Änderung sofort sichtbar. | F-KV-02 | Unit | +| TC-KV-04 | Persistenz nach Neustart | Kunde bearbeitet | Neustart, Kunde öffnen | Geänderte Daten weiterhin vorhanden. | F-KV-02 | Integration | +| TC-KV-05 | Kundensuche Treffer | Kunde „Müller GmbH" vorhanden | Suchbegriff „Müller" | Kunde in Trefferliste. | F-KV-03 | Unit | +| TC-KV-06 | Kundensuche kein Treffer | kein passender Kunde | Suchbegriff „zzz" | Hinweis „Kein Kunde gefunden". | F-KV-03 | Unit | +| TC-KV-07 | Kunde löschen | Kunde ohne Referenz | Löschen + Bestätigung | Kunde entfernt; nicht mehr auffindbar. | F-KV-04 | Integration | +| TC-KV-08 | Löschen referenzierten Kunden | Kunde in Rechnung referenziert | Löschen auslösen | Löschen abgewiesen (GR-05). | F-KV-04 | Integration | + +### 8.3 Dokumentenprozess (TC-DP) + +| TC-ID | Bezeichnung | Vorbedingung | Testeingabe | Erwartetes Ergebnis | PH-Anf. | Testart | +|----------|-------------------------------------|-----------------------------------------|--------------------------------------------|-----------------------------------------------------------------------------|---------|-------------| +| TC-DP-01 | Angebot mit einer Position | 1 Kunde, 1 Produkt vorhanden | Position menge=2, einzelpreisNetto=10.00 | Angebot gespeichert; Netto=20.00, Brutto=23.80 (GR-06); status=OFFEN. | F-DP-01 | Integration | +| TC-DP-02 | Angebotsstatus persistent | Angebot status=OFFEN | Status „angenommen" setzen, Neustart | Status ANGENOMMEN nach Neustart sichtbar. | F-DP-02 | Integration | +| TC-DP-03 | Auftragsbestätigung erzeugen | Angebot status=ANGENOMMEN | „Auftragsbestätigung erzeugen" | AB mit allen Daten + Referenz; Angebot status=UEBERFUEHRT. | F-DP-03 | Integration | +| TC-DP-04 | Lieferschein erzeugen | AB status=BESTAETIGT | „Lieferschein erzeugen" | Lieferschein referenziert AB; Positionen vollständig. | F-DP-04 | Integration | +| TC-DP-05 | Rechnung mit Pflichtangaben | Lieferschein status=GELIEFERT | „Rechnung erzeugen" | Rechnung mit § 14 UStG-Angaben, eindeutiger Nr., Lieferschein-Referenz. | F-DP-05 | Integration | +| TC-DP-06 | Automatisches Rechnungsdatum | Rechnungserzeugung möglich | Neue Rechnung anlegen | rechnungsdatum = Systemdatum (LocalDate.now()). | F-DP-06 | Unit | +| TC-DP-07 | PDF-Export je Belegtyp | je ein gespeicherter Beleg | „Als PDF exportieren", Zielpfad wählen | PDF je Typ erzeugt; Inhalt entspricht Beleg; Rechnung enthält § 14-Angaben. | F-DP-07 | Integration | +| TC-DP-08 | Rechnung ohne Lieferschein abweisen | kein Lieferschein vorhanden | Rechnung direkt anlegen | Erzeugung abgewiesen (GR-01). | F-DP-08 | Unit | +| TC-DP-09 | Fortlaufende Rechnungsnummern | 3 abrechnungsreife Lieferscheine | 3 Rechnungen nacheinander erzeugen | Drei eindeutige, fortlaufende Nummern; keine Wiederverwendung. | F-DP-09 | Unit | +| TC-DP-10 | Unveränderlichkeit der Rechnung | gespeicherte Rechnung | Bearbeitungsversuch | Änderung abgewiesen (GR-03). | F-DP-10 | Unit | +| TC-DP-11 | Preis-Snapshot | Angebot mit Position, Preis 10.00 | Produktpreis nachträglich auf 12.00 ändern | Position im Angebot bleibt 10.00 (GR-04). | F-DP-11 | Unit | +| TC-DP-12 | Summenberechnung BigDecimal | Position menge=3, preis=9.99, mwst=0.19 | Summen berechnen | Netto=29.97, USt=5.69, Brutto=35.66 (HALF_UP, GR-06). | F-DP-12 | Unit | + +### 8.4 Programmoberfläche (TC-GUI) + +| TC-ID | Bezeichnung | Vorbedingung | Testeingabe | Erwartetes Ergebnis | PH-Anf. | Testart | +|-----------|------------------------------------|--------------------------------|-----------------------------------|-----------------------------------------------------------------------|----------|---------| +| TC-GUI-01 | Live-Summenaktualisierung | Angebotsmaske offen, Produkte | Artikel per Dropdown hinzufügen | Gesamtsumme aktualisiert sich ohne spürbare Verzögerung. | F-GUI-01 | manuell | +| TC-GUI-02 | Erfolgsmeldung nach Speichern | gültiges Angebot | Speichern | Erfolgsmeldung erscheint. | F-GUI-01 | manuell | +| TC-GUI-03 | Datenübernahme Auftragsbestätigung | Angebot status=ANGENOMMEN | „Auftragsbestätigung" öffnen | Daten übernommen; Titel „Auftragsbestätigung"; Liefertermin markiert. | F-GUI-02 | manuell | +| TC-GUI-04 | Druckvorschau vor Speichern | abrechnungsreifer Lieferschein | Rechnung erzeugen | Druckvorschau wird vor finalem Speichern angezeigt. | F-GUI-03 | manuell | +| TC-GUI-05 | Status-Icon „Abgeschlossen" | Rechnung erzeugt | Übersicht öffnen | Auftragsstatus durch grünes Icon markiert. | F-GUI-03 | manuell | +| TC-GUI-06 | Echtzeit-Filter | mehrere Belege vorhanden | Name/Nummer ins Suchfeld eingeben | Trefferliste aktualisiert sich sofort, tabellarisch. | F-GUI-04 | manuell | +| TC-GUI-07 | Hinweis bei leerer Trefferliste | kein passender Beleg | ungültigen Suchbegriff eingeben | Text „Keine Treffer gefunden" erscheint. | F-GUI-04 | manuell | +| TC-GUI-08 | PDF-Export-Schaltfläche | Beleg angezeigt | „Als PDF exportieren" klicken | Schaltfläche sichtbar; Export ausgeführt; Erfolgsmeldung mit Pfad. | F-GUI-05 | manuell | + +### 8.5 Nicht-funktionale Anforderungen (TC-NF) + +| TC-ID | Bezeichnung | Vorbedingung | Testeingabe / Vorgehen | Erwartetes Ergebnis | PH-Anf. | Testart | +|----------|-----------------------------------|-------------------------------|--------------------------------------|------------------------------------------------------|-------------|-------------| +| TC-NF-01 | Kunde anlegen < 2 min | 5 Probanden, ungeschult | Aufgabe „Kunde anlegen" | Median < 120 s; Erfolgsquote > 90 %. | NF-USE-01 | manuell | +| TC-NF-02 | Angebot → Rechnung erstmalig | 5 Probanden | Aufgabe ohne Hilfetext | ≥ 4 von 5 im ersten Versuch erfolgreich. | NF-USE-02 | manuell | +| TC-NF-03 | Rückmeldezeit Validierung | Eingabemaske | Fehlerhafte Eingabe, Stoppuhr | Sichtbare Rückmeldung < 1 s. | NF-USE-03 | manuell | +| TC-NF-04 | Antwortzeit bei 1.000 Datensätzen | 1.000 Produkte + 1.000 Kunden | Benutzeraktion ausführen | Antwortzeit < 1 s. | NF-PERF-01 | Integration | +| TC-NF-05 | Listenanzeige bei 1.000 Einträgen | 1.000 Datensätze | Übersichtsliste öffnen | Anzeigedauer < 2 s. | NF-PERF-02 | Integration | +| TC-NF-06 | Kaltstart | Referenzhardware | Anwendung kalt starten | Hauptansicht bedienbar < 5 s. | NF-PERF-03 | manuell | +| TC-NF-07 | Modultrennung | Repository vorhanden | Statische Paketprüfung | Vier getrennte Modulpakete vorhanden. | NF-MAINT-01 | Unit | +| TC-NF-08 | Dokumentationsabdeckung | Quellcode | JavaDoc-Report erzeugen | > 80 % öffentliche Klassen/Methoden kommentiert. | NF-MAINT-02 | Unit | +| TC-NF-09 | Schichtentrennung | Architekturkapitel | Review Kap. 7 | Drei Schichten nachweisbar getrennt. | NF-MAINT-03 | manuell | +| TC-NF-10 | Vollständige Traceability | Kap. 9.4 vorhanden | Matrix prüfen | Jede Muss-Anforderung hat ≥ 1 Testfall. | NF-TEST-01 | manuell | +| TC-NF-11 | Logik ohne GUI testbar | Logikschicht | Unit-Test pro Modul ausführen | Mindestens ein GUI-unabhängiger Unit-Test je Modul. | NF-TEST-02 | Unit | +| TC-NF-12 | Testabdeckung | Testsuite | Coverage-Report erzeugen | Line Coverage > 60 %. | NF-TEST-03 | Unit | +| TC-NF-13 | Quellcode versioniert | Gitty-Repositories | Sichtprüfung | Gesamter Code in genannten Repos. | NF-VER-01 | manuell | +| TC-NF-14 | Code-Review je Merge | Merge-Historie | Review-Historie prüfen | Jeder Merge hat ≥ 1 Reviewer. | NF-VER-02 | manuell | +| TC-NF-15 | Persistenz nach Neustart | Datensätze angelegt | Anwendung neu starten | Datensätze vollständig wiederhergestellt. | NF-ARCH-01 | Integration | +| TC-NF-16 | Repository-Abstraktion | Quellcode | Code-Review | Persistenz hinter Repository/DAO gekapselt (IF-02). | NF-ARCH-02 | manuell | +| TC-NF-17 | Klartextschutz | Datendatei geschrieben | Inspektion aus fremdem Nutzerkontext | Keine lesbaren personenbezogenen Daten im Klartext. | NF-SEC-01 | manuell | +| TC-NF-18 | DSGVO-Löschung | Kunde ohne aktive Rechnungen | Löschanforderung Art. 17 | Kunde entfernt; bei Aufbewahrungspflicht abgewiesen. | NF-SEC-02 | Integration | + +--- + +## 9. Anhänge + +### 9.1 Glossar + +Übernommen aus Lastenheft Kap. 8.1, ergänzt um pflichtenheftspezifische Begriffe. + +| Begriff | Bedeutung | +|---------------------|--------------------------------------------------------------------------------------------------------------| +| Angebot | Unverbindliches Preisangebot an einen Kunden. | +| Auftragsbestätigung | Verbindliche Bestätigung der Auftragsannahme nach Angebot (Kurzform AB). | +| Lieferschein | Dokument, das die Auslieferung der Ware bescheinigt. | +| Rechnung | Forderung nach § 14 UStG mit Steuerangaben. | +| Anwender | Einzige Benutzerrolle des Systems (keine Authentifizierungsrolle). | +| Stammdaten | Produkt- und Kundendaten. | +| Bewegungsdaten | Belege (Angebot, Auftragsbestätigung, Lieferschein, Rechnung). | +| Repository | Entwurfsmuster zur Kapselung der Datenhaltung; abstrahiert die konkrete Speichertechnologie (IF-02). | +| DAO | Data Access Object; Objekt, das den Zugriff auf eine Datenquelle kapselt; hier synonym zum Repository. | +| Service-Klasse | Klasse der Logikschicht, die die Geschäftslogik eines Moduls bündelt (z. B. `KundeService`). | +| BigDecimal | Java-Klasse für exakte Dezimalarithmetik; verbindlich für alle Geld- und Steuerbeträge (statt double/float). | +| LocalDate | Java-Klasse für ein Datum ohne Uhrzeit; verbindlich für alle Datumsfelder. | +| Traceability | Rückverfolgbarkeit von Anforderung zu Realisierung und Test. | + +### 9.2 Abkürzungsverzeichnis + +Übernommen aus Lastenheft Kap. 8.2, ergänzt um pflichtenheftspezifische Abkürzungen. + +| Abkürzung | Bedeutung | +|-----------|---------------------------------------------------| +| AB | Auftragsbestätigung | +| BA | Benutzeranforderung (Lastenheft-Schablone) | +| DAO | Data Access Object | +| DSGVO | Datenschutz-Grundverordnung | +| F | Funktionale Anforderung (Pflichtenheft-Schablone) | +| GR | Geschäftsregel | +| GUI | Graphical User Interface | +| IF | Interface / Schnittstelle | +| NF | Nicht-funktionale Anforderung | +| SRS | System Requirements Specification (Pflichtenheft) | +| TC | Testfall (Test Case) | +| UStG | Umsatzsteuergesetz | +| USt-IdNr. | Umsatzsteuer-Identifikationsnummer | + +### 9.3 Referenzen + +- **[1]** Lastenheft v1.0 (`Lastenheft_v1_0.md`), 15.05.2026 +- **[2]** Project Charter v1.1 (`project-charter_v1_1.md`), 15.05.2026 +- **[3]** § 14 UStG – Umsatzsteuergesetz, Pflichtangaben in Rechnungen +- **[4]** DSGVO – Verordnung (EU) 2016/679 + +### 9.4 Traceability-Matrix LH ↔ PH + +Jede Anforderung des Lastenhefts v1.0 ist mindestens einer Pflichtenheft-Anforderung und mindestens einem Testfall zugeordnet. Die Matrix ist lückenlos. + +| LH-Anforderung | Typ | PH-Anforderung(en) | Testfall(e) | +|----------------|------------------|--------------------|----------------------| +| BA-PV-01 | funktional | F-PV-01 | TC-PV-01, TC-PV-02 | +| BA-PV-02 | funktional | F-PV-02 | TC-PV-03, TC-PV-04 | +| BA-PV-03 | funktional | F-PV-03 | TC-PV-05, TC-PV-06 | +| BA-PV-04 | funktional | F-PV-04 | TC-PV-07, TC-PV-08 | +| BA-KV-01 | funktional | F-KV-01 | TC-KV-01, TC-KV-02 | +| BA-KV-02 | funktional | F-KV-02 | TC-KV-03, TC-KV-04 | +| BA-KV-03 | funktional | F-KV-03 | TC-KV-05, TC-KV-06 | +| BA-KV-04 | funktional | F-KV-04 | TC-KV-07, TC-KV-08 | +| BA-DP-01 | funktional | F-DP-01 | TC-DP-01 | +| BA-DP-02 | funktional | F-DP-02 | TC-DP-02 | +| BA-DP-03 | funktional | F-DP-03 | TC-DP-03 | +| BA-DP-04 | funktional | F-DP-04 | TC-DP-04 | +| BA-DP-05 | funktional | F-DP-05 | TC-DP-05 | +| BA-DP-06 | funktional | F-DP-06 | TC-DP-06 | +| BA-DP-07 | funktional | F-DP-07 | TC-DP-07 | +| BA-GUI-01 | funktional | F-GUI-01 | TC-GUI-01, TC-GUI-02 | +| BA-GUI-02 | funktional | F-GUI-02 | TC-GUI-03 | +| BA-GUI-03 | funktional | F-GUI-03 | TC-GUI-04, TC-GUI-05 | +| BA-GUI-04 | funktional | F-GUI-04 | TC-GUI-06, TC-GUI-07 | +| BA-GUI-05 | funktional | F-GUI-05 | TC-GUI-08 | +| GR-01 | Geschäftsregel | F-DP-08 | TC-DP-08 | +| GR-02 | Geschäftsregel | F-DP-09 | TC-DP-09 | +| GR-03 | Geschäftsregel | F-DP-10 | TC-DP-10 | +| GR-04 | Geschäftsregel | F-DP-11 | TC-DP-11 | +| GR-05 | Geschäftsregel | F-PV-04, F-KV-04 | TC-PV-07, TC-KV-08 | +| GR-06 | Geschäftsregel | F-DP-12 | TC-DP-12, TC-DP-01 | +| NF-USE-01 | NF/Usability | NF-USE-01 | TC-NF-01 | +| NF-USE-02 | NF/Usability | NF-USE-02 | TC-NF-02 | +| NF-USE-03 | NF/Usability | NF-USE-03 | TC-NF-03 | +| NF-PERF-01 | NF/Performance | NF-PERF-01 | TC-NF-04 | +| NF-PERF-02 | NF/Performance | NF-PERF-02 | TC-NF-05 | +| NF-PERF-03 | NF/Performance | NF-PERF-03 | TC-NF-06 | +| NF-MAINT-01 | NF/Wartbarkeit | NF-MAINT-01 | TC-NF-07 | +| NF-MAINT-02 | NF/Wartbarkeit | NF-MAINT-02 | TC-NF-08 | +| NF-MAINT-03 | NF/Architektur | NF-MAINT-03 | TC-NF-09 | +| NF-TEST-01 | NF/Testbarkeit | NF-TEST-01 | TC-NF-10 | +| NF-TEST-02 | NF/Testbarkeit | NF-TEST-02 | TC-NF-11 | +| NF-TEST-03 | NF/Testbarkeit | NF-TEST-03 | TC-NF-12 | +| NF-VER-01 | NF/Versionierung | NF-VER-01 | TC-NF-13 | +| NF-VER-02 | NF/Versionierung | NF-VER-02 | TC-NF-14 | +| NF-ARCH-01 | NF/Architektur | NF-ARCH-01 | TC-NF-15 | +| NF-ARCH-02 | NF/Architektur | NF-ARCH-02 | TC-NF-16 | +| NF-SEC-01 | NF/Security | NF-SEC-01 | TC-NF-17 | +| NF-SEC-02 | NF/Security | NF-SEC-02 | TC-NF-18 | + +Die Traceability-Matrix bildet alle Anforderungen des Lastenhefts v1.0 vollständig auf das Pflichtenheft ab. + +### 9.5 PlantUML-Quellen + +Die folgenden Quelltexte erzeugen die Abbildungen 1–6 (gerendert nach `sources/abbX.png`). Sie dienen der Reproduzierbarkeit und sind nicht Teil des Fließtexts. + +**Abbildung 1 – Kap. 2.4 – Use-Case-Diagramm** + +```plantuml +@startuml +left to right direction +skinparam packageStyle rectangle +actor "Anwender" as A + +rectangle "Fakturierungssystem" { + usecase "Produkt verwalten\n(anlegen, bearbeiten,\nsuchen, löschen)" as UC1 + usecase "Kunde verwalten\n(anlegen, bearbeiten,\nsuchen, löschen)" as UC2 + usecase "Angebot erstellen" as UC3 + usecase "Auftragsbestätigung erzeugen" as UC4 + usecase "Lieferschein erzeugen" as UC5 + usecase "Rechnung erzeugen" as UC6 + usecase "Beleg suchen" as UC7 + usecase "Beleg als PDF exportieren" as UC8 +} + +A --> UC1 +A --> UC2 +A --> UC3 +A --> UC4 +A --> UC5 +A --> UC6 +A --> UC7 +A --> UC8 + +UC4 ..> UC3 : <> +UC5 ..> UC4 : <> +UC6 ..> UC5 : <> +@enduml +``` + +**Abbildung 2 – Kap. 3.3 – Systemkontextdiagramm** + +```plantuml +@startuml +left to right direction +skinparam componentStyle rectangle +actor "Anwender" as A +rectangle "Fakturierungssystem" as SYS +database "Lokales Dateisystem\n(JSON-Persistenz)" as FS +file "PDF-Datei\n(Beleg-Export)" as PDF + +A --> SYS : bedient über GUI (IF-01) +SYS --> FS : liest / schreibt Daten (IF-02) +SYS --> PDF : erzeugt Beleg-PDF (IF-03) +@enduml +``` + +**Abbildung 3 – Kap. 6.1.9 – Klassendiagramm der Datenobjekte** + +```plantuml +@startuml +hide empty members +skinparam classAttributeIconSize 0 + +class Produkt { + -produktId: long + -bezeichnung: String + -einzelpreisNetto: BigDecimal + -mehrwertsteuersatz: BigDecimal + -artikelnummer: String + -beschreibung: String + -kategorie: String +} + +class Kunde { + -kundeId: long + -firmenname: String + -nachname: String + -strasse: String + -plz: String + -ort: String + -email: String + -ustIdNr: String +} + +class Belegposition { + -produktId: long + -bezeichnung: String + -menge: int + -einzelpreisNetto: BigDecimal + -mehrwertsteuersatz: BigDecimal + -gesamtpreisNetto: BigDecimal +} + +class Angebot { + -angebotNr: String + -datum: LocalDate + -gesamtBetragNetto: BigDecimal + -gesamtBetragBrutto: BigDecimal + -status: AngebotStatus +} + +class Auftragsbestaetigung { + -auftragNr: String + -datum: LocalDate + -status: AuftragsStatus +} + +class Lieferschein { + -lieferscheinNr: String + -lieferdatum: LocalDate + -status: LieferscheinStatus +} + +class Rechnung { + -rechnungNr: String + -rechnungsdatum: LocalDate + -gesamtBetragNetto: BigDecimal + -gesamtBetragUst: BigDecimal + -gesamtBetragBrutto: BigDecimal + -status: RechnungStatus +} + +enum AngebotStatus { + OFFEN + ANGENOMMEN + ABGELEHNT + UEBERFUEHRT +} +enum AuftragsStatus { + BESTAETIGT + GELIEFERT +} +enum LieferscheinStatus { + OFFEN + GELIEFERT + FAKTURIERT +} +enum RechnungStatus { + OFFEN + BEZAHLT +} + +Kunde "1" --> "0..*" Angebot +Angebot "1" *-- "1..*" Belegposition +Auftragsbestaetigung "1" *-- "1..*" Belegposition +Lieferschein "1" *-- "1..*" Belegposition +Rechnung "1" *-- "1..*" Belegposition +Belegposition "0..*" --> "1" Produkt +Angebot "1" --> "0..1" Auftragsbestaetigung +Auftragsbestaetigung "1" --> "0..1" Lieferschein +Lieferschein "1" --> "0..1" Rechnung + +Angebot ..> AngebotStatus +Auftragsbestaetigung ..> AuftragsStatus +Lieferschein ..> LieferscheinStatus +Rechnung ..> RechnungStatus +@enduml +``` + +**Abbildung 4 – Kap. 7.1 – Komponentendiagramm** + +```plantuml +@startuml +skinparam componentStyle rectangle + +package "Präsentationsschicht (ui)" { + [ProduktAnsicht] + [KundeAnsicht] + [BelegAnsicht] +} + +package "Logikschicht (service)" { + [ProduktService] + [KundeService] + [AngebotService] + [RechnungService] + [PdfExportService] +} + +package "Datenhaltungsschicht (repository)" { + [ProduktRepository] + [KundeRepository] + [BelegRepository] +} + +cloud "PDF-Bibliothek" as PDFLIB +database "JSON-Datei" as JSON + +[ProduktAnsicht] --> [ProduktService] : IF-01 +[KundeAnsicht] --> [KundeService] : IF-01 +[BelegAnsicht] --> [AngebotService] : IF-01 +[BelegAnsicht] --> [RechnungService] : IF-01 +[BelegAnsicht] --> [PdfExportService] : IF-01 + +[ProduktService] --> [ProduktRepository] : IF-02 +[KundeService] --> [KundeRepository] : IF-02 +[AngebotService] --> [BelegRepository] : IF-02 +[RechnungService] --> [BelegRepository] : IF-02 + +[ProduktRepository] --> JSON +[KundeRepository] --> JSON +[BelegRepository] --> JSON +[PdfExportService] --> PDFLIB : IF-03 +@enduml +``` + +**Abbildung 5 – Kap. 7.2 – Klassendiagramm der Kernklassen** + +```plantuml +@startuml +hide empty members +skinparam classAttributeIconSize 0 + +class Produkt { + -produktId: long + -bezeichnung: String + -einzelpreisNetto: BigDecimal + -mehrwertsteuersatz: BigDecimal +} + +class Kunde { + -kundeId: long + -firmenname: String + -nachname: String +} + +class Belegposition { + -menge: int + -einzelpreisNetto: BigDecimal + -mehrwertsteuersatz: BigDecimal + +berechneGesamtpreisNetto(): BigDecimal +} + +class Angebot { + -angebotNr: String + -status: AngebotStatus + +berechneSummen(): void +} + +class Rechnung { + -rechnungNr: String + -rechnungsdatum: LocalDate + -status: RechnungStatus +} + +class AngebotService { + +erstelleAngebot(kundeId: long, positionen: List): Angebot + +setzeStatus(angebotNr: String, status: AngebotStatus): void + +erzeugeAuftragsbestaetigung(angebotNr: String): Auftragsbestaetigung +} + +class KundeService { + +anlegen(kunde: Kunde): long + +bearbeiten(kunde: Kunde): void + +suchen(begriff: String): List + +loeschen(kundeId: long): void +} + +class RechnungService { + +erzeugeRechnung(lieferscheinNr: String): Rechnung + +naechsteRechnungsnummer(): String + +markiereBezahlt(rechnungNr: String): void +} + +class PdfExportService { + +exportiere(beleg: Beleg, zielpfad: Path): Path +} + +interface ProduktRepository { + +speichern(produkt: Produkt): long + +findeById(produktId: long): Optional + +findeAlle(): List + +loeschen(produktId: long): void +} + +AngebotService ..> Angebot +AngebotService ..> Belegposition +RechnungService ..> Rechnung +KundeService ..> Kunde +KundeService ..> ProduktRepository +PdfExportService ..> Rechnung +Angebot "1" *-- "1..*" Belegposition +Belegposition "0..*" --> "1" Produkt +@enduml +``` + +**Abbildung 6 – Kap. 7.3 – Sequenzdiagramm** + +```plantuml +@startuml +actor Anwender +participant "GUI\n(BelegAnsicht)" as GUI +participant AngebotService +participant BelegRepository +participant RechnungService + +Anwender -> GUI : "Rechnung erzeugen" +GUI -> AngebotService : erzeugeAuftragsbestaetigung(angebotNr) +AngebotService -> BelegRepository : pruefeStatus(angebot, ANGENOMMEN) +BelegRepository --> AngebotService : ok +AngebotService -> BelegRepository : speichere(auftragsbestaetigung) +AngebotService -> BelegRepository : setze Angebot=UEBERFUEHRT +note right of AngebotService : weiter über Lieferschein\n(GELIEFERT) zur Rechnung +GUI -> RechnungService : erzeugeRechnung(lieferscheinNr) +RechnungService -> BelegRepository : pruefeStatus(lieferschein, GELIEFERT) +BelegRepository --> RechnungService : ok +RechnungService -> RechnungService : naechsteRechnungsnummer() [GR-02] +RechnungService -> RechnungService : berechneSummen() [GR-06] +RechnungService -> BelegRepository : speichere(rechnung) +BelegRepository --> RechnungService : gespeichert +RechnungService --> GUI : Rechnung +GUI --> Anwender : Druckvorschau + Erfolgsmeldung +@enduml +``` + diff --git a/Unterlagen/Pflichtenheft-GruppeH/Pflichtenheft_1.1.pdf b/Unterlagen/Pflichtenheft-GruppeH/Pflichtenheft_1.1.pdf new file mode 100644 index 0000000..bb1f84b Binary files /dev/null and b/Unterlagen/Pflichtenheft-GruppeH/Pflichtenheft_1.1.pdf differ diff --git a/Unterlagen/Pflichtenheft-GruppeH/Pflichtenheft_v1_0.pdf b/Unterlagen/Pflichtenheft-GruppeH/Pflichtenheft_v1_0.pdf deleted file mode 100644 index 3169d68..0000000 Binary files a/Unterlagen/Pflichtenheft-GruppeH/Pflichtenheft_v1_0.pdf and /dev/null differ diff --git a/Unterlagen/Project-Charter/project-charter_v1.0.md b/Unterlagen/Project-Charter/project-charter_1.0.md similarity index 100% rename from Unterlagen/Project-Charter/project-charter_v1.0.md rename to Unterlagen/Project-Charter/project-charter_1.0.md diff --git a/Unterlagen/Project-Charter/project-charter_v1.0.pdf b/Unterlagen/Project-Charter/project-charter_1.0.pdf similarity index 100% rename from Unterlagen/Project-Charter/project-charter_v1.0.pdf rename to Unterlagen/Project-Charter/project-charter_1.0.pdf diff --git a/Unterlagen/Project-Charter/project-charter_v1_1.md b/Unterlagen/Project-Charter/project-charter_1.1.md similarity index 100% rename from Unterlagen/Project-Charter/project-charter_v1_1.md rename to Unterlagen/Project-Charter/project-charter_1.1.md diff --git a/src/test/java/de/hsmannheim/faktura/kunde/repository/KundeRepositoryJsonTest.java b/src/test/java/de/hsmannheim/faktura/kunde/repository/KundeRepositoryJsonTest.java deleted file mode 100644 index cdf2f76..0000000 --- a/src/test/java/de/hsmannheim/faktura/kunde/repository/KundeRepositoryJsonTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package de.hsmannheim.faktura.kunde.repository; - -import de.hsmannheim.faktura.kunde.model.Kunde; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; - -import java.io.File; -import java.nio.file.Path; -import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -class KundeRepositoryJsonTest { - - @Test - void persistenz_ueberlebt_neustart(@TempDir Path tempDir) { - File datei = tempDir.resolve("kunden.json").toFile(); - - // 1. Repository anlegen und einen Kunden speichern - KundeRepository repo1 = new KundeRepositoryJson(datei); - Kunde kunde = new Kunde(); - kunde.setNachname("Mustermann"); - kunde.setStrasse("Hauptstr. 1"); - kunde.setPlz("01067"); // führende Null! - kunde.setOrt("Dresden"); - long id = repo1.speichern(kunde); - - // 2. Neues Repository auf dieselbe Datei = simulierter Neustart - KundeRepository repo2 = new KundeRepositoryJson(datei); - Optional geladen = repo2.findeById(id); - - // 3. Kunde ist unverändert wiederhergestellt - assertTrue(geladen.isPresent(), "Kunde sollte nach Neustart vorhanden sein"); - assertEquals("Mustermann", geladen.get().getNachname()); - assertEquals("01067", geladen.get().getPlz(), - "Führende Null der PLZ muss erhalten bleiben"); - assertEquals("Dresden", geladen.get().getOrt()); - } -} \ No newline at end of file diff --git a/src/test/java/de/hsmannheim/faktura/kunde/service/KundeModultestTest.java b/src/test/java/de/hsmannheim/faktura/kunde/service/KundeModultestTest.java new file mode 100644 index 0000000..3d7798a --- /dev/null +++ b/src/test/java/de/hsmannheim/faktura/kunde/service/KundeModultestTest.java @@ -0,0 +1,205 @@ +package de.hsmannheim.faktura.kunde.service; + +import de.hsmannheim.faktura.kunde.model.Kunde; +import de.hsmannheim.faktura.kunde.repository.KundeRepositoryJson; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.io.TempDir; + +import java.io.File; +import java.nio.file.Path; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Modultests der Kundenverwaltung (Gruppe H) – Phase 6 des Fahrplans. + * + *

Diese Klasse überführt die fachliche Logik in exakt die elf im Modultestplan + * geforderten Testfälle MT-KV-01 … MT-KV-11 (1:1-Abbildung). Jeder Test trägt den + * Modultestplan-Titel als {@code @DisplayName}, sodass der Testlauf direkt als + * Modultestbericht (Phase 7, P7-1) verwendbar ist.

+ * + *

Die Tests laufen GUI-unabhängig (NF-TEST-02) gegen die echte Service-, + * Validator- und JSON-Repository-Schicht; nur die Beleg-Referenzprüfung der + * GR-05-Löschsperre wird über das Interface {@link BelegReferenzPruefer} + * gesteuert.

+ * + *

Diese Datei ersetzt die zuvor getrennten Testklassen {@code KundeServiceTest}, + * {@code KundeValidatorTest} und {@code KundeRepositoryJsonTest}; deren Abdeckung + * geht hier vollständig auf (vgl. P10-2 „max. 4 Test-Dateien").

+ * + *

Abgedeckte Anforderungen: BA-KV-01 … BA-KV-04, GR-05, NF-ARCH-01.

+ */ +@TestMethodOrder(MethodOrderer.MethodName.class) +@DisplayName("Modultests Kundenverwaltung (MT-KV-01 … MT-KV-11)") +class KundeModultestTest { + + private KundeService service; + private File datei; + private boolean kundeIstReferenziert; // steuert die GR-05-Löschsperre im Test + private BelegReferenzPruefer belegPruefer; + + @BeforeEach + void setUp(@TempDir Path tempDir) { + datei = tempDir.resolve("kunden.json").toFile(); + kundeIstReferenziert = false; + belegPruefer = kundeId -> kundeIstReferenziert; + service = new KundeService(new KundeRepositoryJson(datei), + new KundeValidator(), belegPruefer); + } + + /** Gültiger Kunde mit Firmenname (entspricht „Muster GmbH" aus MT-KV-01 / MT-KV-07). */ + private Kunde musterKunde() { + Kunde k = new Kunde(); + k.setFirmenname("Muster GmbH"); + k.setStrasse("Hauptstr. 1"); + k.setPlz("68159"); + k.setOrt("Mannheim"); + return k; + } + + // ───────────────────────────── BA-KV-01: Kunde anlegen ───────────────────────────── + + @Test + @DisplayName("MT-KV-01: Kunde mit vollständigen Pflichtattributen anlegen") + void mtKv01_kundeMitPflichtattributen_wirdGespeichert() { // BA-KV-01 + long id = service.anlegen(musterKunde()); + + assertTrue(id > 0, "Es muss eine fortlaufende kundeId vergeben werden"); + assertEquals(1, service.suchen("Muster").size(), + "Angelegter Kunde muss in der Kundenliste auffindbar sein"); + } + + @Test + @DisplayName("MT-KV-02: Kunde ohne Firmenname bzw. Nachname anlegen") + void mtKv02_ohneFirmennameUndNachname_wirdAbgelehnt() { // BA-KV-01 + Kunde k = musterKunde(); + k.setFirmenname(null); // nachname ist ohnehin null -> beide leer + + assertThrows(ValidierungsException.class, () -> service.anlegen(k)); + assertTrue(service.suchen("Muster").isEmpty(), "Es darf nichts gespeichert werden"); + } + + @Test + @DisplayName("MT-KV-03: Kunde ohne Straße anlegen") + void mtKv03_ohneStrasse_wirdAbgelehnt() { // BA-KV-01 + Kunde k = musterKunde(); + k.setStrasse(null); + + assertThrows(ValidierungsException.class, () -> service.anlegen(k)); + } + + @Test + @DisplayName("MT-KV-04: Kunde mit ungültigem E-Mail-Format anlegen") + void mtKv04_ungueltigeEmail_wirdAbgelehnt() { // BA-KV-01 + Kunde k = musterKunde(); + k.setEmail("kunde@"); + + assertThrows(ValidierungsException.class, () -> service.anlegen(k)); + } + + // ──────────────────────────── BA-KV-02: Kunde bearbeiten ─────────────────────────── + + @Test + @DisplayName("MT-KV-05: Vorhandenen Kunden bearbeiten") + void mtKv05_telefonnummerAendern_wirdGespeichert() { // BA-KV-02 + long id = service.anlegen(musterKunde()); + Kunde k = service.finde(id).orElseThrow(); + k.setTelefon("0621 12345"); + + service.bearbeiten(k); + + assertEquals("0621 12345", service.finde(id).orElseThrow().getTelefon(), + "Geänderte Telefonnummer muss gespeichert und angezeigt werden"); + } + + @Test + @DisplayName("MT-KV-06: Persistenz geänderter Kundendaten prüfen") + void mtKv06_geaenderteDaten_ueberlebenNeuladen() { // BA-KV-02, NF-ARCH-01 + // Kunde mit führender Null in der PLZ -> prüft zugleich den String-PLZ-Typ (Kap. 6.1.2) + Kunde k = new Kunde(); + k.setNachname("Mustermann"); + k.setStrasse("Hauptstr. 1"); + k.setPlz("01067"); + k.setOrt("Dresden"); + long id = service.anlegen(k); + + Kunde geladen = service.finde(id).orElseThrow(); + geladen.setTelefon("0351 99999"); + service.bearbeiten(geladen); + + // Neues Repository/Service auf dieselbe Datei = simulierter Neustart + KundeService nachNeustart = new KundeService(new KundeRepositoryJson(datei), + new KundeValidator(), belegPruefer); + Kunde wieder = nachNeustart.finde(id).orElseThrow(); + + assertEquals("0351 99999", wieder.getTelefon(), "Geänderte Daten müssen erhalten bleiben"); + assertEquals("01067", wieder.getPlz(), "Führende Null der PLZ muss erhalten bleiben"); + assertEquals("Mustermann", wieder.getNachname()); + } + + // ──────────────────────────── BA-KV-03: Kunde suchen ─────────────────────────────── + + @Test + @DisplayName("MT-KV-07: Kunde über Namen suchen") + void mtKv07_sucheUeberNamen_findetKunden() { // BA-KV-03 + service.anlegen(musterKunde()); // „Muster GmbH" + + List treffer = service.suchen("Muster"); + + assertEquals(1, treffer.size()); + assertEquals("Muster GmbH", treffer.get(0).getFirmenname()); + } + + @Test + @DisplayName("MT-KV-08: Kunde über Kundennummer suchen") + void mtKv08_sucheUeberKundennummer_findetKunden() { // BA-KV-03 + long id = service.anlegen(musterKunde()); + + List treffer = service.suchen(String.valueOf(id)); + + assertEquals(1, treffer.size()); + assertEquals(id, treffer.get(0).getKundeId()); + } + + @Test + @DisplayName("MT-KV-09: Nicht vorhandenen Kunden suchen") + void mtKv09_sucheOhneTreffer_istLeer() { // BA-KV-03 + service.anlegen(musterKunde()); + + assertTrue(service.suchen("Gibtsnicht").isEmpty(), + "Ohne Treffer muss eine leere Liste zurückgegeben werden"); + } + + // ──────────────────────────── BA-KV-04: Kunde löschen ────────────────────────────── + + @Test + @DisplayName("MT-KV-10: Nicht referenzierten Kunden löschen") + void mtKv10_nichtReferenzierterKunde_wirdEntfernt() { // BA-KV-04 + long id = service.anlegen(musterKunde()); + kundeIstReferenziert = false; + + service.loeschen(id); + + assertTrue(service.finde(id).isEmpty(), "Kunde muss entfernt sein"); + assertTrue(service.suchen("Muster").isEmpty(), + "Gelöschter Kunde darf nicht mehr gefunden werden"); + } + + @Test + @DisplayName("MT-KV-11: Referenzierten Kunden löschen") + void mtKv11_referenzierterKunde_wirdAbgewiesen() { // BA-KV-04, GR-05 + long id = service.anlegen(musterKunde()); + kundeIstReferenziert = true; + + assertThrows(LoeschsperreException.class, () -> service.loeschen(id)); + assertTrue(service.finde(id).isPresent(), + "Referenzierter Kunde muss erhalten bleiben"); + } +} \ No newline at end of file diff --git a/src/test/java/de/hsmannheim/faktura/kunde/service/KundeServiceTest.java b/src/test/java/de/hsmannheim/faktura/kunde/service/KundeServiceTest.java deleted file mode 100644 index c58e6f5..0000000 --- a/src/test/java/de/hsmannheim/faktura/kunde/service/KundeServiceTest.java +++ /dev/null @@ -1,99 +0,0 @@ -package de.hsmannheim.faktura.kunde.service; - -import de.hsmannheim.faktura.kunde.model.Kunde; -import de.hsmannheim.faktura.kunde.repository.KundeRepository; -import de.hsmannheim.faktura.kunde.repository.KundeRepositoryJson; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; - -import java.io.File; -import java.nio.file.Path; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - -class KundeServiceTest { - - private KundeService service; - private boolean kundeIstReferenziert; // steuert den BelegReferenzPruefer im Test - - @BeforeEach - void setUp(@TempDir Path tempDir) { - File datei = tempDir.resolve("kunden.json").toFile(); - KundeRepository repository = new KundeRepositoryJson(datei); - KundeValidator validator = new KundeValidator(); - BelegReferenzPruefer belegPruefer = kundeId -> kundeIstReferenziert; - service = new KundeService(repository, validator, belegPruefer); - kundeIstReferenziert = false; - } - - private Kunde gueltigerKunde() { - Kunde k = new Kunde(); - k.setNachname("Mustermann"); - k.setStrasse("Hauptstr. 1"); - k.setPlz("68159"); - k.setOrt("Mannheim"); - return k; - } - - @Test - void anlegen_vergibtIdUndPersistiert() { // BA-KV-01 - long id = service.anlegen(gueltigerKunde()); - assertTrue(id > 0); - assertEquals(1, service.suchen("Mustermann").size()); - } - - @Test - void anlegen_ungueltig_wirdNichtGespeichert() { // P3-4 im Service - Kunde k = gueltigerKunde(); - k.setNachname(null); - assertThrows(ValidierungsException.class, () -> service.anlegen(k)); - assertTrue(service.suchen("Mustermann").isEmpty()); - } - - @Test - void bearbeiten_aendertGespeichertenKunden() { // BA-KV-02 - service.anlegen(gueltigerKunde()); - Kunde k = service.suchen("Mustermann").get(0); - k.setTelefon("0621 12345"); - service.bearbeiten(k); - assertEquals("0621 12345", service.suchen("Mustermann").get(0).getTelefon()); - } - - @Test - void suchen_ueberKundennummer_findet() { // BA-KV-03 / MT-KV-08 - long id = service.anlegen(gueltigerKunde()); - assertEquals(1, service.suchen(String.valueOf(id)).size()); - } - - @Test - void suchen_ohneTreffer_istLeer() { // BA-KV-03 / MT-KV-09 - service.anlegen(gueltigerKunde()); - assertTrue(service.suchen("Gibtsnicht").isEmpty()); - } - - @Test - void loeschen_nichtReferenziert_entfernt() { // BA-KV-04 / MT-KV-10 - long id = service.anlegen(gueltigerKunde()); - kundeIstReferenziert = false; - service.loeschen(id); - assertTrue(service.suchen("Mustermann").isEmpty()); - } - - @Test - void loeschen_referenziert_wirdAbgewiesen() { // BA-KV-04 / GR-05 / MT-KV-11 - long id = service.anlegen(gueltigerKunde()); - kundeIstReferenziert = true; - assertThrows(LoeschsperreException.class, () -> service.loeschen(id)); - assertEquals(1, service.suchen("Mustermann").size()); // noch vorhanden - } - - @Test - void finde_liefertAngelegtenKunden() { // K3 - long id = service.anlegen(gueltigerKunde()); - assertTrue(service.finde(id).isPresent()); - assertEquals(id, service.finde(id).get().getKundeId()); - assertTrue(service.finde(999L).isEmpty()); // unbekannte ID -> leer - } -} \ No newline at end of file diff --git a/src/test/java/de/hsmannheim/faktura/kunde/service/KundeValidatorTest.java b/src/test/java/de/hsmannheim/faktura/kunde/service/KundeValidatorTest.java deleted file mode 100644 index bf2395e..0000000 --- a/src/test/java/de/hsmannheim/faktura/kunde/service/KundeValidatorTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package de.hsmannheim.faktura.kunde.service; - -import de.hsmannheim.faktura.kunde.model.Kunde; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertThrows; - -class KundeValidatorTest { - - private final KundeValidator validator = new KundeValidator(); - - private Kunde gueltigerKunde() { - Kunde k = new Kunde(); - k.setNachname("Mustermann"); - k.setStrasse("Hauptstr. 1"); - k.setPlz("68159"); - k.setOrt("Mannheim"); - return k; - } - - @Test - void gueltigerKunde_wirftNicht() { - assertDoesNotThrow(() -> validator.pruefe(gueltigerKunde())); - } - - @Test - void ohneFirmennameUndNachname_wirdAbgelehnt() { // → MT-KV-02 - Kunde k = gueltigerKunde(); - k.setNachname(null); - assertThrows(ValidierungsException.class, () -> validator.pruefe(k)); - } - - @Test - void ohneStrasse_wirdAbgelehnt() { // → MT-KV-03 - Kunde k = gueltigerKunde(); - k.setStrasse(null); - assertThrows(ValidierungsException.class, () -> validator.pruefe(k)); - } - - @Test - void ungueltigeEmail_wirdAbgelehnt() { // → MT-KV-04 - Kunde k = gueltigerKunde(); - k.setEmail("kunde@"); - assertThrows(ValidierungsException.class, () -> validator.pruefe(k)); - } - - @Test - void gueltigeEmail_wirftNicht() { - Kunde k = gueltigerKunde(); - k.setEmail("kunde@example.com"); - assertDoesNotThrow(() -> validator.pruefe(k)); - } -}