From 03155e9dd56f8de5cc77e8c26dab0dab000ffac3 Mon Sep 17 00:00:00 2001 From: Christian Khazanovych Date: Thu, 25 Jun 2026 00:21:29 +0200 Subject: [PATCH] GR-04: Loeschsperre fuer referenzierte Kunden und Produkte vollstaendig implementiert --- .../belegworkflow/BelegworkflowService.java | 89 ++++++++++++++++--- .../ProduktServiceImpl.java | 43 +++++---- .../kundenverwaltung/KundenServiceImpl.java | 48 +++++----- src/main/java/ui/KundenPanel.java | 4 + src/main/java/ui/ProduktPanel.java | 4 + 5 files changed, 139 insertions(+), 49 deletions(-) diff --git a/src/main/java/belegworkflow/BelegworkflowService.java b/src/main/java/belegworkflow/BelegworkflowService.java index 6852208..da71aa4 100644 --- a/src/main/java/belegworkflow/BelegworkflowService.java +++ b/src/main/java/belegworkflow/BelegworkflowService.java @@ -1,23 +1,34 @@ package belegworkflow; import java.io.*; +import java.math.BigDecimal; import java.nio.file.*; import java.time.LocalDate; import java.util.*; +import kundenverwaltung.Kunde; +import kundenverwaltung.KundenServiceImpl; +import bestandsmanagement.Produkt; +import bestandsmanagement.ProduktServiceImpl; public class BelegworkflowService { - private static final String ANGEBOTE_FILE = "data/angebote.csv"; - private static final String RECHNUNGEN_FILE = "data/rechnungen.csv"; + private static final String ANGEBOTE_FILE = "data/angebote.csv"; + private static final String ANGEBOTE_POSITIONEN_FILE = "data/angebote_positionen.csv"; + private static final String RECHNUNGEN_FILE = "data/rechnungen.csv"; + private static final String RECHNUNGEN_POSITIONEN_FILE = "data/rechnungen_positionen.csv"; private List angebote; private List rechnungen; private BelegnummernGenerator generator; + private KundenServiceImpl kundenService; + private ProduktServiceImpl produktService; public BelegworkflowService() throws IOException { - this.angebote = new ArrayList<>(); - this.rechnungen = new ArrayList<>(); - this.generator = new BelegnummernGenerator(); + this.angebote = new ArrayList<>(); + this.rechnungen = new ArrayList<>(); + this.generator = new BelegnummernGenerator(); + this.kundenService = new KundenServiceImpl(); + this.produktService = new ProduktServiceImpl(); Files.createDirectories(Path.of("data")); ladeAngebote(); ladeRechnungen(); @@ -38,6 +49,21 @@ public class BelegworkflowService { String nr = generator.naechsteAngebotsnummer(LocalDate.now().getYear()); Angebot angebot = new Angebot(nr, LocalDate.now(), kundenId, positionen, gueltigBis); angebote.add(angebot); + + // Belegreferenz beim Kunden setzen (GR-04) + Kunde kunde = kundenService.findeKunde(kundenId); + if (kunde != null) { + kunde.belegHinzufuegen(nr); + } + + // Belegreferenz bei allen Produkten setzen (GR-04) + for (Dokumentposition pos : positionen) { + Produkt produkt = produktService.findeProdukt(pos.getProduktReferenz()); + if (produkt != null) { + produkt.belegHinzufuegen(nr); + } + } + speichereAngebote(); System.out.println("Angebot erfolgreich erstellt: " + nr); return angebot; @@ -98,7 +124,7 @@ public class BelegworkflowService { public List alleAngebote() { return new ArrayList<>(angebote); } public List alleRechnungen() { return new ArrayList<>(rechnungen); } - public Angebot findeAngebot(String nr) { + public Angebot findeAngebot(String nr) { return angebote.stream().filter(a -> a.getBelegnummer().equals(nr)).findFirst().orElse(null); } public Rechnung findeRechnung(String nr) { @@ -109,6 +135,7 @@ public class BelegworkflowService { private void speichereAngebote() { try { StringBuilder sb = new StringBuilder(); + StringBuilder posSb = new StringBuilder(); for (Angebot a : angebote) { sb.append(a.getBelegnummer()).append(";") .append(a.getDatum()).append(";") @@ -118,8 +145,17 @@ public class BelegworkflowService { .append(a.getSummeNetto()).append(";") .append(a.getSummeSteuer()).append(";") .append(a.getSummeBrutto()).append("\n"); + for (Dokumentposition pos : a.getPositionen()) { + posSb.append(a.getBelegnummer()).append(";") + .append(pos.getProduktReferenz()).append(";") + .append(pos.getBezeichnung()).append(";") + .append(pos.getMenge()).append(";") + .append(pos.getEinzelpreisNetto()).append(";") + .append(pos.getSteuersatz()).append("\n"); + } } Files.writeString(Path.of(ANGEBOTE_FILE), sb.toString()); + Files.writeString(Path.of(ANGEBOTE_POSITIONEN_FILE), posSb.toString()); } catch (IOException e) { System.err.println("Fehler beim Speichern der Angebote: " + e.getMessage()); } @@ -129,9 +165,7 @@ public class BelegworkflowService { try { Path path = Path.of(ANGEBOTE_FILE); if (!Files.exists(path)) return; - // Vereinfachtes Laden - nur Metadaten ohne Positionen - List zeilen = Files.readAllLines(path); - for (String zeile : zeilen) { + for (String zeile : Files.readAllLines(path)) { if (zeile.isBlank()) continue; String[] t = zeile.split(";", -1); if (t.length < 8) continue; @@ -140,6 +174,18 @@ public class BelegworkflowService { a.setStatus(AngebotStatus.valueOf(t[4])); angebote.add(a); } + Path posPath = Path.of(ANGEBOTE_POSITIONEN_FILE); + if (Files.exists(posPath)) { + for (String zeile : Files.readAllLines(posPath)) { + if (zeile.isBlank()) continue; + String[] t = zeile.split(";", -1); + if (t.length < 6) continue; + Dokumentposition pos = new Dokumentposition(t[1], t[2], + Integer.parseInt(t[3]), new BigDecimal(t[4]), new BigDecimal(t[5])); + angebote.stream().filter(a -> a.getBelegnummer().equals(t[0])) + .findFirst().ifPresent(a -> a.getPositionen().add(pos)); + } + } } catch (IOException e) { System.err.println("Fehler beim Laden der Angebote: " + e.getMessage()); } @@ -148,6 +194,7 @@ public class BelegworkflowService { private void speichereRechnungen() { try { StringBuilder sb = new StringBuilder(); + StringBuilder posSb = new StringBuilder(); for (Rechnung r : rechnungen) { sb.append(r.getBelegnummer()).append(";") .append(r.getDatum()).append(";") @@ -161,8 +208,17 @@ public class BelegworkflowService { .append(r.getSummeNetto()).append(";") .append(r.getSummeSteuer()).append(";") .append(r.getSummeBrutto()).append("\n"); + for (Dokumentposition pos : r.getPositionen()) { + posSb.append(r.getBelegnummer()).append(";") + .append(pos.getProduktReferenz()).append(";") + .append(pos.getBezeichnung()).append(";") + .append(pos.getMenge()).append(";") + .append(pos.getEinzelpreisNetto()).append(";") + .append(pos.getSteuersatz()).append("\n"); + } } Files.writeString(Path.of(RECHNUNGEN_FILE), sb.toString()); + Files.writeString(Path.of(RECHNUNGEN_POSITIONEN_FILE), posSb.toString()); } catch (IOException e) { System.err.println("Fehler beim Speichern der Rechnungen: " + e.getMessage()); } @@ -172,8 +228,7 @@ public class BelegworkflowService { try { Path path = Path.of(RECHNUNGEN_FILE); if (!Files.exists(path)) return; - List zeilen = Files.readAllLines(path); - for (String zeile : zeilen) { + for (String zeile : Files.readAllLines(path)) { if (zeile.isBlank()) continue; String[] t = zeile.split(";", -1); if (t.length < 12) continue; @@ -184,6 +239,18 @@ public class BelegworkflowService { if (Boolean.parseBoolean(t[8])) r.festschreiben(); rechnungen.add(r); } + Path posPath = Path.of(RECHNUNGEN_POSITIONEN_FILE); + if (Files.exists(posPath)) { + for (String zeile : Files.readAllLines(posPath)) { + if (zeile.isBlank()) continue; + String[] t = zeile.split(";", -1); + if (t.length < 6) continue; + Dokumentposition pos = new Dokumentposition(t[1], t[2], + Integer.parseInt(t[3]), new BigDecimal(t[4]), new BigDecimal(t[5])); + rechnungen.stream().filter(r -> r.getBelegnummer().equals(t[0])) + .findFirst().ifPresent(r -> r.getPositionen().add(pos)); + } + } } catch (IOException e) { System.err.println("Fehler beim Laden der Rechnungen: " + e.getMessage()); } diff --git a/src/main/java/bestandsmanagement/ProduktServiceImpl.java b/src/main/java/bestandsmanagement/ProduktServiceImpl.java index b41b492..6677961 100644 --- a/src/main/java/bestandsmanagement/ProduktServiceImpl.java +++ b/src/main/java/bestandsmanagement/ProduktServiceImpl.java @@ -2,6 +2,7 @@ package bestandsmanagement; import java.io.IOException; import java.math.BigDecimal; +import java.nio.file.*; import java.util.List; public class ProduktServiceImpl { @@ -14,23 +15,18 @@ public class ProduktServiceImpl { this.idGenerator = new ProduktIdGenerator(); } - // Legt einen neuen Artikel an (F-01, F-02, F-05) public Produkt produktAnlegen(String bezeichnung, BigDecimal nettoEinzelpreis, BigDecimal mehrwertsteuersatz, int bestand, String beschreibung) { - // Negativer Bestand wird abgelehnt (F-09) if (bestand < 0) { System.out.println("Fehler: Negativer Lagerbestand ist nicht erlaubt."); return null; } - Produkt produkt = new Produkt("TEMP", bezeichnung, nettoEinzelpreis, mehrwertsteuersatz, bestand, beschreibung); - if (!produkt.validiereFelder()) { System.out.println("Fehler: Alle Pflichtfelder muessen ausgefuellt sein."); return null; } - String id = idGenerator.naechsteProduktId(); Produkt neuesProdukt = new Produkt(id, bezeichnung, nettoEinzelpreis, mehrwertsteuersatz, bestand, beschreibung); @@ -39,7 +35,6 @@ public class ProduktServiceImpl { return neuesProdukt; } - // Bearbeitet einen bestehenden Artikel (F-03, F-04) public boolean produktBearbeiten(String produktId, String bezeichnung, BigDecimal nettoEinzelpreis, BigDecimal mehrwertsteuersatz, int bestand, String beschreibung) { @@ -48,30 +43,24 @@ public class ProduktServiceImpl { System.out.println("Fehler: Artikel mit ID " + produktId + " nicht gefunden."); return false; } - - // Negativer Bestand wird abgelehnt (F-09) if (bestand < 0) { System.out.println("Fehler: Negativer Lagerbestand ist nicht erlaubt."); return false; } - produkt.setBezeichnung(bezeichnung); produkt.setNettoEinzelpreis(nettoEinzelpreis); produkt.setMehrwertsteuersatz(mehrwertsteuersatz); produkt.setBestand(bestand); produkt.setBeschreibung(beschreibung); - if (!produkt.validiereFelder()) { System.out.println("Fehler: Alle Pflichtfelder muessen ausgefuellt sein."); return false; } - repository.aktualisieren(produkt); System.out.println("Artikel erfolgreich aktualisiert: " + produkt); return true; } - // Löscht einen Artikel mit Integritätsprüfung (F-10, F-11) public boolean produktLoeschen(String produktId) { Produkt produkt = repository.findeNachId(produktId); if (produkt == null) { @@ -79,9 +68,9 @@ public class ProduktServiceImpl { return false; } - if (!produkt.getBelegReferenzen().isEmpty()) { - System.out.println("Fehler: Artikel kann nicht geloescht werden, da er in " + - produkt.getBelegReferenzen().size() + " Beleg(en) referenziert wird."); + // Direkt in CSV-Dateien prüfen (GR-04) + if (istProduktInBelegReferenziert(produktId)) { + System.out.println("Fehler: Artikel ist in einem Beleg referenziert und kann nicht geloescht werden."); return false; } @@ -90,17 +79,35 @@ public class ProduktServiceImpl { return true; } - // Gibt alle Artikel zurück (F-06) + private boolean istProduktInBelegReferenziert(String produktId) { + try { + String[] positionenDateien = { + "data/angebote_positionen.csv", + "data/rechnungen_positionen.csv" + }; + for (String datei : positionenDateien) { + Path path = Path.of(datei); + if (Files.exists(path)) { + for (String zeile : Files.readAllLines(path)) { + String[] t = zeile.split(";", -1); + if (t.length >= 2 && t[1].equals(produktId)) return true; + } + } + } + } catch (IOException e) { + System.err.println("Warnung: Belegpruefung konnte nicht durchgefuehrt werden."); + } + return false; + } + public List alleProdukte() { return repository.alleProdukte(); } - // Sucht Artikel nach Bezeichnung oder ID (F-07) public List sucheNachBezeichnung(String suchbegriff) { return repository.sucheNachBezeichnung(suchbegriff); } - // Gibt einen Artikel anhand der ID zurück public Produkt findeProdukt(String produktId) { return repository.findeNachId(produktId); } diff --git a/src/main/java/kundenverwaltung/KundenServiceImpl.java b/src/main/java/kundenverwaltung/KundenServiceImpl.java index accefde..16f60be 100644 --- a/src/main/java/kundenverwaltung/KundenServiceImpl.java +++ b/src/main/java/kundenverwaltung/KundenServiceImpl.java @@ -1,6 +1,7 @@ package kundenverwaltung; import java.io.IOException; +import java.nio.file.*; import java.util.List; public class KundenServiceImpl { @@ -13,18 +14,13 @@ public class KundenServiceImpl { this.idGenerator = new KundenIdGenerator(); } - // Legt einen neuen Kunden an (F-01, F-02, F-03, F-04) public Kunde kundeAnlegen(String name, String strasse, String plz, String ort, String steuerNummer, String email, String telefon) { Kunde kunde = new Kunde("TEMP", name, strasse, plz, ort, steuerNummer, email, telefon); - - // Pflichtfeldprüfung (F-03) if (!kunde.validiereFelder()) { System.out.println("Fehler: Alle Pflichtfelder müssen ausgefüllt sein."); return null; } - - // ID vergeben (F-02) String id = idGenerator.naechsteKundenId(); Kunde neuerKunde = new Kunde(id, name, strasse, plz, ort, steuerNummer, email, telefon); repository.speichern(neuerKunde); @@ -32,7 +28,6 @@ public class KundenServiceImpl { return neuerKunde; } - // Bearbeitet einen bestehenden Kunden (F-05, F-06, F-07) public boolean kundeBearbeiten(String kundenId, String name, String strasse, String plz, String ort, String steuerNummer, String email, String telefon) { Kunde kunde = repository.findeNachId(kundenId); @@ -40,7 +35,6 @@ public class KundenServiceImpl { System.out.println("Fehler: Kunde mit ID " + kundenId + " nicht gefunden."); return false; } - kunde.setName(name); kunde.setStrasse(strasse); kunde.setPlz(plz); @@ -48,19 +42,15 @@ public class KundenServiceImpl { kunde.setSteuerNummer(steuerNummer); kunde.setEmail(email); kunde.setTelefon(telefon); - - // Pflichtfeldprüfung nach Änderung (F-06) if (!kunde.validiereFelder()) { System.out.println("Fehler: Alle Pflichtfelder müssen ausgefüllt sein."); return false; } - repository.aktualisieren(kunde); System.out.println("Kunde erfolgreich aktualisiert: " + kunde); return true; } - // Löscht einen Kunden mit Integritätsprüfung (F-11, F-12, GR-04) public boolean kundeLoschen(String kundenId) { Kunde kunde = repository.findeNachId(kundenId); if (kunde == null) { @@ -68,10 +58,9 @@ public class KundenServiceImpl { return false; } - // Referenzielle Integrität prüfen (GR-04) - if (!kunde.getBelegReferenzen().isEmpty()) { - System.out.println("Fehler: Kunde kann nicht gelöscht werden, da er in " + - kunde.getBelegReferenzen().size() + " Beleg(en) referenziert wird."); + // Direkt in CSV-Dateien prüfen (GR-04) + if (istKundeInBelegReferenziert(kundenId)) { + System.out.println("Fehler: Kunde ist in einem Beleg referenziert und kann nicht geloescht werden."); return false; } @@ -80,22 +69,41 @@ public class KundenServiceImpl { return true; } - // Gibt alle Kunden zurück (F-08) + private boolean istKundeInBelegReferenziert(String kundenId) { + try { + Path angebotePath = Path.of("data/angebote.csv"); + Path rechnungenPath = Path.of("data/rechnungen.csv"); + + if (Files.exists(angebotePath)) { + for (String zeile : Files.readAllLines(angebotePath)) { + String[] teile = zeile.split(";", -1); + if (teile.length >= 3 && teile[2].equals(kundenId)) return true; + } + } + if (Files.exists(rechnungenPath)) { + for (String zeile : Files.readAllLines(rechnungenPath)) { + String[] teile = zeile.split(";", -1); + if (teile.length >= 3 && teile[2].equals(kundenId)) return true; + } + } + } catch (IOException e) { + System.err.println("Warnung: Belegpruefung konnte nicht durchgefuehrt werden."); + } + return false; + } + public List alleKunden() { return repository.alleKunden(); } - // Sucht Kunden nach Name (F-09) public List sucheNachName(String suchbegriff) { return repository.sucheNachName(suchbegriff); } - // Gibt einen Kunden anhand der ID zurück (F-10) public Kunde findeKunde(String kundenId) { return repository.findeNachId(kundenId); } - // Zeigt die Transaktionshistorie eines Kunden (F-13) public void zeigeTransaktionshistorie(String kundenId) { Kunde kunde = repository.findeNachId(kundenId); if (kunde == null) { @@ -111,4 +119,4 @@ public class KundenServiceImpl { } } } -} +} \ No newline at end of file diff --git a/src/main/java/ui/KundenPanel.java b/src/main/java/ui/KundenPanel.java index 91a7acb..bef7805 100644 --- a/src/main/java/ui/KundenPanel.java +++ b/src/main/java/ui/KundenPanel.java @@ -153,6 +153,10 @@ public class KundenPanel extends JPanel { JOptionPane.showMessageDialog(this, "Kunde wurde erfolgreich geloescht.", "Erfolg", JOptionPane.INFORMATION_MESSAGE); + } else { + JOptionPane.showMessageDialog(this, + "Kunde kann nicht geloescht werden, da er in einem Beleg referenziert wird.", + "Loeschen nicht moeglich", JOptionPane.ERROR_MESSAGE); } } }); diff --git a/src/main/java/ui/ProduktPanel.java b/src/main/java/ui/ProduktPanel.java index 304312e..4462b66 100644 --- a/src/main/java/ui/ProduktPanel.java +++ b/src/main/java/ui/ProduktPanel.java @@ -158,6 +158,10 @@ public class ProduktPanel extends JPanel { JOptionPane.showMessageDialog(this, "Artikel wurde erfolgreich geloescht.", "Erfolg", JOptionPane.INFORMATION_MESSAGE); + } else { + JOptionPane.showMessageDialog(this, + "Artikel kann nicht geloescht werden, da er in einem Beleg referenziert wird.", + "Loeschen nicht moeglich", JOptionPane.ERROR_MESSAGE); } } });