Compare commits
2 Commits
16ef33a1c9
...
ea61d6c301
| Author | SHA1 | Date |
|---|---|---|
|
|
ea61d6c301 | |
|
|
b04757f9db |
|
|
@ -0,0 +1,498 @@
|
|||
package de.hsmannheim.faktura.dokumente.service;
|
||||
|
||||
import de.hsmannheim.faktura.dokumente.domain.*;
|
||||
import de.hsmannheim.faktura.dokumente.exception.*;
|
||||
import de.hsmannheim.faktura.dokumente.export.PdfExportService;
|
||||
import de.hsmannheim.faktura.dokumente.export.SimplePdfExportService;
|
||||
import de.hsmannheim.faktura.dokumente.lookup.*;
|
||||
import de.hsmannheim.faktura.dokumente.repository.InMemoryDokumentRepository;
|
||||
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.LocalDate;
|
||||
import java.util.*;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Modultestplan für den Dokumentenprozess (Gruppe F).
|
||||
* Alle 16 Testfälle MT-DP-01 bis MT-DP-16 aus dem Pflichtenheft.
|
||||
*
|
||||
* Keine JavaFX-Abhängigkeit – alle Tests laufen ohne GUI-Start (PH-DP-16, PH-NF-DP-05).
|
||||
*/
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
class DokumentServiceTest {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Test-Infrastruktur: Fake-Implementierungen
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/** Fake-Produktverwaltung mit festen Testprodukten (MT-DP-01). */
|
||||
static class FakeProductLookup implements ProductLookup {
|
||||
private final Map<Long, ProductDto> produkte = new HashMap<>();
|
||||
|
||||
FakeProductLookup() {
|
||||
produkte.put(20001L, new ProductDto(20001L, "Produkt Alpha",
|
||||
new BigDecimal("100.00"), new BigDecimal("0.19")));
|
||||
produkte.put(20002L, new ProductDto(20002L, "Produkt Beta",
|
||||
new BigDecimal("50.00"), new BigDecimal("0.07")));
|
||||
produkte.put(20003L, new ProductDto(20003L, "Produkt Gamma",
|
||||
new BigDecimal("200.00"), new BigDecimal("0.19")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ProductDto> findProduct(long produktId) {
|
||||
return Optional.ofNullable(produkte.get(produktId));
|
||||
}
|
||||
|
||||
/** Ändert den Preis eines Produkts – für MT-DP-13 (Snapshot-Test). */
|
||||
void setztePreis(long produktId, BigDecimal neuerPreis) {
|
||||
ProductDto alt = produkte.get(produktId);
|
||||
if (alt != null) {
|
||||
produkte.put(produktId, new ProductDto(
|
||||
alt.getProduktId(), alt.getBezeichnung(), neuerPreis, alt.getMwstSatz()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Fake-Kundenverwaltung mit festen Testkunden. */
|
||||
static class FakeCustomerLookup implements CustomerLookup {
|
||||
private final Map<Long, CustomerDto> kunden = new HashMap<>();
|
||||
|
||||
FakeCustomerLookup() {
|
||||
kunden.put(10001L, new CustomerDto(10001L, "Max Mustermann",
|
||||
"Musterweg 5, 68159 Mannheim", "DE123456789"));
|
||||
kunden.put(10002L, new CustomerDto(10002L, "Erika Muster",
|
||||
"Beispielgasse 3, 68161 Mannheim", null));
|
||||
// Kunde 10002 hat keine Steuernummer → für MT-DP-10 (fehlende Pflichtangaben)
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<CustomerDto> findCustomer(long kundenId) {
|
||||
return Optional.ofNullable(kunden.get(kundenId));
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Setup
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private InMemoryDokumentRepository repository;
|
||||
private FakeProductLookup productLookup;
|
||||
private FakeCustomerLookup customerLookup;
|
||||
private DokumentService service;
|
||||
|
||||
@TempDir
|
||||
Path tempDir;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
repository = new InMemoryDokumentRepository();
|
||||
productLookup = new FakeProductLookup();
|
||||
customerLookup = new FakeCustomerLookup();
|
||||
PdfExportService pdfExport = new SimplePdfExportService(tempDir);
|
||||
service = new DokumentServiceImpl(repository, productLookup, customerLookup, pdfExport);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// MT-DP-01: Angebot anlegen – Happy Path (PH-DP-01)
|
||||
// =========================================================================
|
||||
@Test
|
||||
@Order(1)
|
||||
@DisplayName("MT-DP-01: Angebot anlegen – Happy Path")
|
||||
void testAngebotAnlegen_HappyPath() {
|
||||
List<PositionCommand> positionen = List.of(
|
||||
new PositionCommand(20001L, 2),
|
||||
new PositionCommand(20002L, 1)
|
||||
);
|
||||
|
||||
Angebot angebot = service.erstelleAngebot(10001L, positionen);
|
||||
|
||||
assertNotNull(angebot, "Angebot darf nicht null sein");
|
||||
assertTrue(angebot.getDokumentNummer().startsWith("A-2026-"),
|
||||
"Nummer muss mit A-2026- beginnen, war: " + angebot.getDokumentNummer());
|
||||
assertEquals(DokumentStatus.OFFEN, angebot.getStatus(), "Status muss OFFEN sein");
|
||||
assertEquals(2, angebot.getPositionen().size(), "Muss genau 2 Positionen haben");
|
||||
assertEquals(10001L, angebot.getKundenId(), "Kunden-ID muss stimmen");
|
||||
assertNotNull(angebot.getDatum(), "Datum darf nicht null sein");
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// MT-DP-02: Summenberechnung Angebot (PH-DP-01, PH-DP-08)
|
||||
// =========================================================================
|
||||
@Test
|
||||
@Order(2)
|
||||
@DisplayName("MT-DP-02: Summenberechnung – Netto 250,00, USt 41,50, Brutto 291,50")
|
||||
void testSummenberechnung_Angebot() {
|
||||
// 2 x 100,00 EUR mit 19%, 1 x 50,00 EUR mit 7%
|
||||
List<PositionCommand> positionen = List.of(
|
||||
new PositionCommand(20001L, 2), // 2 x 100 @ 19%
|
||||
new PositionCommand(20002L, 1) // 1 x 50 @ 7%
|
||||
);
|
||||
|
||||
Angebot angebot = service.erstelleAngebot(10001L, positionen);
|
||||
|
||||
assertEquals(0, new BigDecimal("250.00").compareTo(angebot.getNettoSumme()),
|
||||
"Nettosumme muss 250,00 EUR sein, war: " + angebot.getNettoSumme());
|
||||
assertEquals(0, new BigDecimal("41.50").compareTo(angebot.getUstSumme()),
|
||||
"USt-Summe muss 41,50 EUR sein, war: " + angebot.getUstSumme());
|
||||
assertEquals(0, new BigDecimal("291.50").compareTo(angebot.getBruttoSumme()),
|
||||
"Bruttosumme muss 291,50 EUR sein, war: " + angebot.getBruttoSumme());
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// MT-DP-03: Fortlaufende Angebotsnummern (PH-DP-02)
|
||||
// =========================================================================
|
||||
@Test
|
||||
@Order(3)
|
||||
@DisplayName("MT-DP-03: Angebotsnummern sind fortlaufend und eindeutig")
|
||||
void testFortlaufendeAngebotsnummern() {
|
||||
List<PositionCommand> pos = List.of(new PositionCommand(20001L, 1));
|
||||
|
||||
Angebot a1 = service.erstelleAngebot(10001L, pos);
|
||||
Angebot a2 = service.erstelleAngebot(10001L, pos);
|
||||
|
||||
assertNotEquals(a1.getDokumentNummer(), a2.getDokumentNummer(),
|
||||
"Nummern müssen unterschiedlich sein");
|
||||
assertTrue(a1.getDokumentNummer().endsWith("0001"),
|
||||
"Erste Nummer muss auf 0001 enden, war: " + a1.getDokumentNummer());
|
||||
assertTrue(a2.getDokumentNummer().endsWith("0002"),
|
||||
"Zweite Nummer muss auf 0002 enden, war: " + a2.getDokumentNummer());
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// MT-DP-04: Angebot nach Überführung sperren (PH-DP-03)
|
||||
// =========================================================================
|
||||
@Test
|
||||
@Order(4)
|
||||
@DisplayName("MT-DP-04: Überführtes Angebot kann nicht mehr bearbeitet werden")
|
||||
void testAngebotNachUeberfuehrungGesperrt() {
|
||||
List<PositionCommand> pos = List.of(new PositionCommand(20001L, 1));
|
||||
Angebot angebot = service.erstelleAngebot(10001L, pos);
|
||||
service.erstelleAuftragsbestaetigung(angebot.getDokumentNummer());
|
||||
|
||||
// Versuch Angebot nach Überführung zu bearbeiten → IllegalStateException
|
||||
assertThrows(IllegalStateException.class,
|
||||
() -> service.aktualisiereAngebot(angebot.getDokumentNummer(), pos),
|
||||
"Bearbeitung eines überführten Angebots muss IllegalStateException werfen");
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// MT-DP-05: Auftragsbestätigung erzeugen (PH-DP-04)
|
||||
// =========================================================================
|
||||
@Test
|
||||
@Order(5)
|
||||
@DisplayName("MT-DP-05: Auftragsbestätigung aus offenem Angebot erzeugen")
|
||||
void testAuftragsbestaetigung_Erzeugen() {
|
||||
List<PositionCommand> pos = List.of(
|
||||
new PositionCommand(20001L, 2),
|
||||
new PositionCommand(20002L, 1)
|
||||
);
|
||||
Angebot angebot = service.erstelleAngebot(10001L, pos);
|
||||
|
||||
Auftragsbestaetigung ab = service.erstelleAuftragsbestaetigung(angebot.getDokumentNummer());
|
||||
|
||||
assertNotNull(ab, "AB darf nicht null sein");
|
||||
assertTrue(ab.getDokumentNummer().startsWith("AB-"),
|
||||
"AB-Nummer muss mit AB- beginnen");
|
||||
assertEquals(angebot.getDokumentNummer(), ab.getAngebotsNummer(),
|
||||
"AB muss Angebotsnummer referenzieren");
|
||||
assertEquals(2, ab.getPositionen().size(),
|
||||
"AB muss dieselbe Anzahl Positionen wie Angebot haben");
|
||||
assertEquals(DokumentStatus.UEBERFUEHRT,
|
||||
((Angebot) repository.findByNummer(angebot.getDokumentNummer()).get()).getStatus(),
|
||||
"Angebot muss nach AB-Erstellung auf UEBERFUEHRT stehen");
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// MT-DP-06: Doppelte AB verhindern (PH-DP-05)
|
||||
// =========================================================================
|
||||
@Test
|
||||
@Order(6)
|
||||
@DisplayName("MT-DP-06: Zweite AB für dasselbe Angebot wird abgelehnt")
|
||||
void testDoppelteAuftragsbestaetigung_Verhindern() {
|
||||
List<PositionCommand> pos = List.of(new PositionCommand(20001L, 1));
|
||||
Angebot angebot = service.erstelleAngebot(10001L, pos);
|
||||
service.erstelleAuftragsbestaetigung(angebot.getDokumentNummer());
|
||||
|
||||
// Zweiter Versuch → DuplicateDocumentException
|
||||
assertThrows(DuplicateDocumentException.class,
|
||||
() -> service.erstelleAuftragsbestaetigung(angebot.getDokumentNummer()),
|
||||
"Zweite AB für dasselbe Angebot muss DuplicateDocumentException werfen");
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// MT-DP-07: Lieferschein erzeugen (PH-DP-06)
|
||||
// =========================================================================
|
||||
@Test
|
||||
@Order(7)
|
||||
@DisplayName("MT-DP-07: Lieferschein aus bestätigter AB erzeugen")
|
||||
void testLieferschein_Erzeugen() {
|
||||
List<PositionCommand> pos = List.of(new PositionCommand(20001L, 3));
|
||||
Angebot angebot = service.erstelleAngebot(10001L, pos);
|
||||
Auftragsbestaetigung ab = service.erstelleAuftragsbestaetigung(angebot.getDokumentNummer());
|
||||
LocalDate lieferdatum = LocalDate.now().plusDays(3);
|
||||
|
||||
Lieferschein ls = service.erstelleLieferschein(ab.getDokumentNummer(), lieferdatum);
|
||||
|
||||
assertNotNull(ls, "Lieferschein darf nicht null sein");
|
||||
assertTrue(ls.getDokumentNummer().startsWith("LS-"),
|
||||
"LS-Nummer muss mit LS- beginnen");
|
||||
assertEquals(ab.getDokumentNummer(), ls.getAuftragsNummer(),
|
||||
"Lieferschein muss AB-Nummer referenzieren");
|
||||
assertEquals(lieferdatum, ls.getLieferdatum(), "Lieferdatum muss übereinstimmen");
|
||||
assertEquals(DokumentStatus.GELIEFERT, ls.getStatus(), "Status muss GELIEFERT sein");
|
||||
assertEquals(1, ls.getPositionen().size(), "Muss 1 Position enthalten");
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// MT-DP-08: Lieferschein enthält keine Preise (PH-DP-07)
|
||||
// =========================================================================
|
||||
@Test
|
||||
@Order(8)
|
||||
@DisplayName("MT-DP-08: Lieferschein-Export enthält keine Preisfelder")
|
||||
void testLieferschein_EnthältKeinePreise() throws Exception {
|
||||
List<PositionCommand> pos = List.of(new PositionCommand(20001L, 2));
|
||||
Angebot angebot = service.erstelleAngebot(10001L, pos);
|
||||
Auftragsbestaetigung ab = service.erstelleAuftragsbestaetigung(angebot.getDokumentNummer());
|
||||
Lieferschein ls = service.erstelleLieferschein(ab.getDokumentNummer(), LocalDate.now());
|
||||
|
||||
// PDF exportieren und Inhalt prüfen
|
||||
Path pdfPfad = service.exportiereAlsPdf(ls.getDokumentNummer());
|
||||
String inhalt = Files.readString(pdfPfad);
|
||||
|
||||
assertTrue(inhalt.contains("Produkt Alpha"), "Bezeichnung muss enthalten sein");
|
||||
assertFalse(inhalt.contains("Nettosumme:"), "Nettosumme darf nicht enthalten sein");
|
||||
assertFalse(inhalt.contains("Bruttosumme:"), "Bruttosumme darf nicht enthalten sein");
|
||||
assertFalse(inhalt.contains("USt:"), "USt-Betrag darf nicht enthalten sein");
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// MT-DP-09: Rechnung erzeugen – Happy Path (PH-DP-08, PH-DP-09)
|
||||
// =========================================================================
|
||||
@Test
|
||||
@Order(9)
|
||||
@DisplayName("MT-DP-09: Rechnung aus Lieferschein erzeugen (Happy Path)")
|
||||
void testRechnung_Erzeugen_HappyPath() {
|
||||
Lieferschein ls = erstelleKompletteDokumentenkette(10001L);
|
||||
|
||||
Rechnung rechnung = service.erstelleRechnung(ls.getDokumentNummer());
|
||||
|
||||
assertAll("Rechnung muss vollständig sein",
|
||||
() -> assertNotNull(rechnung, "Rechnung darf nicht null sein"),
|
||||
() -> assertTrue(rechnung.getDokumentNummer().startsWith("R-"),
|
||||
"Rechnungsnummer muss mit R- beginnen"),
|
||||
() -> assertEquals(DokumentStatus.FESTGESCHRIEBEN, rechnung.getStatus(),
|
||||
"Status muss FESTGESCHRIEBEN sein"),
|
||||
() -> assertTrue(rechnung.isFestgeschrieben(), "Rechnung muss festgeschrieben sein"),
|
||||
() -> assertNotNull(rechnung.getPflichtangaben(), "Pflichtangaben dürfen nicht null sein"),
|
||||
() -> assertEquals(0, new BigDecimal("250.00").compareTo(rechnung.getNettoSumme()),
|
||||
"Nettosumme muss 250,00 EUR sein"),
|
||||
() -> assertEquals(0, new BigDecimal("291.50").compareTo(rechnung.getBruttoSumme()),
|
||||
"Bruttosumme muss 291,50 EUR sein")
|
||||
);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// MT-DP-10: Pflichtangaben fehlen (PH-DP-09)
|
||||
// =========================================================================
|
||||
@Test
|
||||
@Order(10)
|
||||
@DisplayName("MT-DP-10: Fehlende Pflichtangaben verhindern Rechnungserstellung")
|
||||
void testRechnung_PflichtangabenFehlen() {
|
||||
// Wir manipulieren den CustomerLookup so, dass er einen Kunden
|
||||
// mit leerer Anschrift zurückgibt → Validierung schlägt fehl
|
||||
CustomerLookup schlechterLookup = id ->
|
||||
Optional.of(new CustomerDto(id, "", "", null));
|
||||
|
||||
DokumentService serviceOhneKunde = new DokumentServiceImpl(
|
||||
repository, productLookup, schlechterLookup, new SimplePdfExportService(tempDir));
|
||||
|
||||
List<PositionCommand> pos = List.of(new PositionCommand(20001L, 2),
|
||||
new PositionCommand(20002L, 1));
|
||||
|
||||
// Erst Angebot → AB → LS aufbauen
|
||||
Angebot angebot = serviceOhneKunde.erstelleAngebot(10001L, pos);
|
||||
Auftragsbestaetigung ab = serviceOhneKunde.erstelleAuftragsbestaetigung(
|
||||
angebot.getDokumentNummer());
|
||||
Lieferschein ls = serviceOhneKunde.erstelleLieferschein(
|
||||
ab.getDokumentNummer(), LocalDate.now());
|
||||
|
||||
// Rechnung erstellen → soll ValidationException werfen
|
||||
assertThrows(ValidationException.class,
|
||||
() -> serviceOhneKunde.erstelleRechnung(ls.getDokumentNummer()),
|
||||
"Rechnung mit fehlenden Pflichtangaben muss ValidationException werfen");
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// MT-DP-11: Rechnungsnummern lückenlos (PH-DP-10)
|
||||
// =========================================================================
|
||||
@Test
|
||||
@Order(11)
|
||||
@DisplayName("MT-DP-11: Drei Rechnungen erhalten Nummern 0001, 0002, 0003")
|
||||
void testRechnungsnummern_Lueckenlos() {
|
||||
List<PositionCommand> pos = List.of(
|
||||
new PositionCommand(20001L, 2),
|
||||
new PositionCommand(20002L, 1)
|
||||
);
|
||||
|
||||
// Drei vollständige Dokumentenketten erzeugen
|
||||
List<String> rechnungsNummern = new ArrayList<>();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
Lieferschein ls = erstelleKompletteDokumentenkette(10001L);
|
||||
Rechnung rechnung = service.erstelleRechnung(ls.getDokumentNummer());
|
||||
rechnungsNummern.add(rechnung.getDokumentNummer());
|
||||
}
|
||||
|
||||
assertTrue(rechnungsNummern.get(0).endsWith("0001"),
|
||||
"Erste Rechnung muss auf 0001 enden, war: " + rechnungsNummern.get(0));
|
||||
assertTrue(rechnungsNummern.get(1).endsWith("0002"),
|
||||
"Zweite Rechnung muss auf 0002 enden, war: " + rechnungsNummern.get(1));
|
||||
assertTrue(rechnungsNummern.get(2).endsWith("0003"),
|
||||
"Dritte Rechnung muss auf 0003 enden, war: " + rechnungsNummern.get(2));
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// MT-DP-12: Rechnung unveränderlich (PH-DP-11)
|
||||
// =========================================================================
|
||||
@Test
|
||||
@Order(12)
|
||||
@DisplayName("MT-DP-12: Festgeschriebene Rechnung kann nicht mehr geändert werden")
|
||||
void testRechnung_Unveraenderlich() {
|
||||
Lieferschein ls = erstelleKompletteDokumentenkette(10001L);
|
||||
Rechnung rechnung = service.erstelleRechnung(ls.getDokumentNummer());
|
||||
|
||||
assertTrue(rechnung.isFestgeschrieben(), "Rechnung muss festgeschrieben sein");
|
||||
|
||||
// Versuch Positionen zu ändern → IllegalStateException
|
||||
assertThrows(IllegalStateException.class,
|
||||
() -> rechnung.pruefeAenderbar(),
|
||||
"Änderung einer festgeschriebenen Rechnung muss IllegalStateException werfen");
|
||||
|
||||
// Rechnung erneut aus Repository laden → unverändert
|
||||
Rechnung geladen = (Rechnung) repository.findByNummer(rechnung.getDokumentNummer()).get();
|
||||
assertTrue(geladen.isFestgeschrieben(), "Geladene Rechnung muss noch festgeschrieben sein");
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// MT-DP-13: Preis-Snapshot bleibt stabil (PH-DP-14)
|
||||
// =========================================================================
|
||||
@Test
|
||||
@Order(13)
|
||||
@DisplayName("MT-DP-13: Spätere Produktpreisänderung beeinflusst bestehende Angebote nicht")
|
||||
void testPreisSnapshot_BleibtStabil() {
|
||||
// Angebot mit Preis 100,00 EUR erzeugen
|
||||
List<PositionCommand> pos = List.of(new PositionCommand(20001L, 1));
|
||||
Angebot angebot = service.erstelleAngebot(10001L, pos);
|
||||
|
||||
BigDecimal preisImAngebot = angebot.getPositionen().get(0).getEinzelpreisNettoSnapshot();
|
||||
assertEquals(0, new BigDecimal("100.00").compareTo(preisImAngebot),
|
||||
"Preis im Angebot muss 100,00 EUR sein");
|
||||
|
||||
// Produktpreis ändern (Snapshot darf nicht beeinflusst werden)
|
||||
productLookup.setztePreis(20001L, new BigDecimal("120.00"));
|
||||
|
||||
// Angebot erneut aus Repository laden
|
||||
Angebot geladen = (Angebot) repository.findByNummer(angebot.getDokumentNummer()).get();
|
||||
BigDecimal preisNachAenderung = geladen.getPositionen().get(0).getEinzelpreisNettoSnapshot();
|
||||
|
||||
assertEquals(0, new BigDecimal("100.00").compareTo(preisNachAenderung),
|
||||
"Snapshot-Preis muss weiterhin 100,00 EUR sein (nicht 120,00)");
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// MT-DP-14: PDF-Export erzeugt Datei (PH-DP-12)
|
||||
// =========================================================================
|
||||
@Test
|
||||
@Order(14)
|
||||
@DisplayName("MT-DP-14: PDF-Export erzeugt vorhandene, nicht-leere Datei")
|
||||
void testPdfExport_DateiErzeugt() throws Exception {
|
||||
List<PositionCommand> pos = List.of(new PositionCommand(20001L, 1));
|
||||
Angebot angebot = service.erstelleAngebot(10001L, pos);
|
||||
|
||||
Path pdfPfad = service.exportiereAlsPdf(angebot.getDokumentNummer());
|
||||
|
||||
assertNotNull(pdfPfad, "Rückgabepfad darf nicht null sein");
|
||||
assertTrue(Files.exists(pdfPfad), "PDF-Datei muss existieren: " + pdfPfad);
|
||||
assertTrue(Files.size(pdfPfad) > 0, "PDF-Datei darf nicht leer sein");
|
||||
|
||||
String inhalt = Files.readString(pdfPfad);
|
||||
assertTrue(inhalt.contains(angebot.getDokumentNummer()),
|
||||
"PDF muss Dokumentnummer enthalten");
|
||||
assertTrue(inhalt.contains("ANGEBOT"),
|
||||
"PDF muss Dokumenttyp enthalten");
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// MT-DP-15: Dokumentübersicht pro Kunde (PH-DP-13)
|
||||
// =========================================================================
|
||||
@Test
|
||||
@Order(15)
|
||||
@DisplayName("MT-DP-15: findByKunde liefert nur Dokumente des richtigen Kunden")
|
||||
void testDokumentenuebersicht_ProKunde() {
|
||||
List<PositionCommand> pos = List.of(new PositionCommand(20001L, 1));
|
||||
|
||||
// Dokumente für Kunde 10001
|
||||
service.erstelleAngebot(10001L, pos);
|
||||
service.erstelleAngebot(10001L, pos);
|
||||
|
||||
// Dokument für Kunde 10002 (anderen Kunden)
|
||||
service.erstelleAngebot(10002L, pos);
|
||||
|
||||
List<Dokument> dokKunde1 = service.findByKunde(10001L);
|
||||
List<Dokument> dokKunde2 = service.findByKunde(10002L);
|
||||
|
||||
assertEquals(2, dokKunde1.size(),
|
||||
"Kunde 10001 muss genau 2 Dokumente haben");
|
||||
assertEquals(1, dokKunde2.size(),
|
||||
"Kunde 10002 muss genau 1 Dokument haben");
|
||||
|
||||
assertTrue(dokKunde1.stream().allMatch(d -> d.getKundenId() == 10001L),
|
||||
"Alle Dokumente in der Liste müssen Kunden-ID 10001 haben");
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// MT-DP-16: Stammdatenreferenz prüfen (PH-DP-15)
|
||||
// =========================================================================
|
||||
@Test
|
||||
@Order(16)
|
||||
@DisplayName("MT-DP-16: isProductReferenced gibt true/false korrekt zurück")
|
||||
void testStammdatenreferenz_Pruefen() {
|
||||
// Angebot mit Produkt 20001 anlegen
|
||||
List<PositionCommand> pos = List.of(new PositionCommand(20001L, 1));
|
||||
service.erstelleAngebot(10001L, pos);
|
||||
|
||||
// Produkt 20001 wird referenziert → true
|
||||
assertTrue(repository.existsReferencedProdukt(20001L),
|
||||
"Produkt 20001 muss als referenziert erkannt werden");
|
||||
|
||||
// Produkt 99999 existiert nicht in Dokumenten → false
|
||||
assertFalse(repository.existsReferencedProdukt(99999L),
|
||||
"Produkt 99999 darf nicht als referenziert gelten");
|
||||
|
||||
// Kunde 10001 wird referenziert → true
|
||||
assertTrue(repository.existsReferencedKunde(10001L),
|
||||
"Kunde 10001 muss als referenziert erkannt werden");
|
||||
|
||||
// Kunde 99998 nicht → false
|
||||
assertFalse(repository.existsReferencedKunde(99998L),
|
||||
"Kunde 99998 darf nicht als referenziert gelten");
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Hilfsmethode: Erstellt eine vollständige Dokumentenkette bis zum Lieferschein
|
||||
// =========================================================================
|
||||
private Lieferschein erstelleKompletteDokumentenkette(long kundenId) {
|
||||
List<PositionCommand> pos = List.of(
|
||||
new PositionCommand(20001L, 2),
|
||||
new PositionCommand(20002L, 1)
|
||||
);
|
||||
Angebot angebot = service.erstelleAngebot(kundenId, pos);
|
||||
Auftragsbestaetigung ab = service.erstelleAuftragsbestaetigung(angebot.getDokumentNummer());
|
||||
return service.erstelleLieferschein(ab.getDokumentNummer(), LocalDate.now());
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue