GR-04: Loeschsperre fuer referenzierte Kunden und Produkte vollstaendig implementiert

main
Christian Khazanovych 2026-06-25 00:21:29 +02:00
parent 9815a352bf
commit 03155e9dd5
5 changed files with 139 additions and 49 deletions

View File

@ -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<Angebot> angebote;
private List<Rechnung> 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<Angebot> alleAngebote() { return new ArrayList<>(angebote); }
public List<Rechnung> 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<String> 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<String> 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());
}

View File

@ -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<Produkt> alleProdukte() {
return repository.alleProdukte();
}
// Sucht Artikel nach Bezeichnung oder ID (F-07)
public List<Produkt> sucheNachBezeichnung(String suchbegriff) {
return repository.sucheNachBezeichnung(suchbegriff);
}
// Gibt einen Artikel anhand der ID zurück
public Produkt findeProdukt(String produktId) {
return repository.findeNachId(produktId);
}

View File

@ -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<Kunde> alleKunden() {
return repository.alleKunden();
}
// Sucht Kunden nach Name (F-09)
public List<Kunde> 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 {
}
}
}
}
}

View File

@ -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);
}
}
});

View File

@ -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);
}
}
});