main
3027248 2026-06-29 10:46:44 +02:00
parent d73359ffc2
commit 576220c381
7 changed files with 63 additions and 41 deletions

View File

@ -98,7 +98,6 @@ public abstract class Dokument {
return String.format("%s{nummer='%s', kundenId=%d, datum=%s, status=%s}", return String.format("%s{nummer='%s', kundenId=%d, datum=%s, status=%s}",
getClass().getSimpleName(), dokumentNummer, kundenId, datum, status); getClass().getSimpleName(), dokumentNummer, kundenId, datum, status);
} }
}
// === Alias-Methoden für GUI-Kompatibilität === // === Alias-Methoden für GUI-Kompatibilität ===
@ -129,3 +128,4 @@ public abstract class Dokument {
case RECHNUNG -> "Rechnung"; case RECHNUNG -> "Rechnung";
}; };
} }
}

View File

@ -68,10 +68,9 @@ public class DokumentPosition {
@Override @Override
public String toString() { public String toString() {
return String.format("DokumentPosition{produktId=%d, bezeichnung='%s', menge=%d, " + return String.format("DokumentPosition{produktId=%d, bezeichnung='%s', menge=%d, " +
"einzelpreisNetto=%s, mwstSatz=%s}", "einzelpreisNetto=%s, mwstSatz=%s}",
produktId, bezeichnungSnapshot, menge, einzelpreisNettoSnapshot, mwstSatzSnapshot); produktId, bezeichnungSnapshot, menge, einzelpreisNettoSnapshot, mwstSatzSnapshot);
} }
}
// === Alias-Methoden für GUI-Kompatibilität === // === Alias-Methoden für GUI-Kompatibilität ===
@ -91,3 +90,4 @@ public class DokumentPosition {
/** Alias für getNettoGesamt() GUI-Kompatibilität. */ /** Alias für getNettoGesamt() GUI-Kompatibilität. */
public BigDecimal getSumme() { return getNettoGesamt(); } public BigDecimal getSumme() { return getNettoGesamt(); }
}

View File

@ -74,7 +74,6 @@ public interface DokumentRepository {
* @return die höchste laufende Nummer oder 0 wenn noch keine existiert * @return die höchste laufende Nummer oder 0 wenn noch keine existiert
*/ */
int findMaxLaufendeNummer(String praefix, int jahr); int findMaxLaufendeNummer(String praefix, int jahr);
}
/** /**
* Gibt alle gespeicherten Dokumente zurück (für die Listenansicht in der GUI). * Gibt alle gespeicherten Dokumente zurück (für die Listenansicht in der GUI).
@ -91,3 +90,4 @@ public interface DokumentRepository {
* @return true wenn gelöscht, false wenn nicht gefunden * @return true wenn gelöscht, false wenn nicht gefunden
*/ */
boolean delete(String nummer); boolean delete(String nummer);
}

View File

@ -94,7 +94,6 @@ public class InMemoryDokumentRepository implements DokumentRepository {
public void clear() { public void clear() {
store.clear(); store.clear();
} }
}
@Override @Override
public List<Dokument> findAll() { public List<Dokument> findAll() {
@ -105,3 +104,4 @@ public class InMemoryDokumentRepository implements DokumentRepository {
public boolean delete(String nummer) { public boolean delete(String nummer) {
return store.remove(nummer) != null; return store.remove(nummer) != null;
} }
}

View File

@ -49,8 +49,8 @@ public class ProduktPanel extends JPanel {
public ProduktPanel(MainFrame mainFrame) { public ProduktPanel(MainFrame mainFrame) {
this.mainFrame = mainFrame; this.mainFrame = mainFrame;
this.productService = new ProductService( this.productService = new ProductService(
new ProductRepository(), new ProductRepository(),
createDummyDokumentRepository() createDummyDokumentRepository()
); );
setLayout(new BorderLayout(8, 8)); setLayout(new BorderLayout(8, 8));
setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
@ -192,9 +192,9 @@ public class ProduktPanel extends JPanel {
tableModel.setRowCount(0); tableModel.setRowCount(0);
for (Product p : liste) { for (Product p : liste) {
tableModel.addRow(new Object[]{ tableModel.addRow(new Object[]{
p.getProductId(), p.getProductId(),
p.getBezeichnung(), p.getBezeichnung(),
p.getEinzelpreisNetto() + " €" p.getEinzelpreisNetto() + " €"
}); });
} }
} }
@ -267,12 +267,12 @@ public class ProduktPanel extends JPanel {
if (!valid) return; if (!valid) return;
Product p = new Product( Product p = new Product(
txtProduktId.getText().trim(), txtProduktId.getText().trim(),
bezeichnung, bezeichnung,
preis, preis,
(MwstSatz) cmbMwst.getSelectedItem(), (MwstSatz) cmbMwst.getSelectedItem(),
txtBeschreibung.getText().trim(), txtBeschreibung.getText().trim(),
txtKategorie.getText().trim() txtKategorie.getText().trim()
); );
try { try {
@ -295,10 +295,10 @@ public class ProduktPanel extends JPanel {
// PHGUI07: Bestätigungsdialog // PHGUI07: Bestätigungsdialog
int confirm = JOptionPane.showConfirmDialog( int confirm = JOptionPane.showConfirmDialog(
this, this,
"Produkt wirklich löschen?", "Produkt wirklich löschen?",
"Löschen bestätigen", "Löschen bestätigen",
JOptionPane.YES_NO_OPTION JOptionPane.YES_NO_OPTION
); );
if (confirm != JOptionPane.YES_OPTION) return; if (confirm != JOptionPane.YES_OPTION) return;
@ -337,6 +337,8 @@ public class ProduktPanel extends JPanel {
public java.util.Optional<de.hsmannheim.faktura.dokumente.domain.Dokument> findByNummer(String n) { return java.util.Optional.empty(); } public java.util.Optional<de.hsmannheim.faktura.dokumente.domain.Dokument> findByNummer(String n) { return java.util.Optional.empty(); }
public List<de.hsmannheim.faktura.dokumente.domain.Dokument> findByKunde(long id) { return List.of(); } public List<de.hsmannheim.faktura.dokumente.domain.Dokument> findByKunde(long id) { return List.of(); }
public boolean existsFolgedokument(String q) { return false; } public boolean existsFolgedokument(String q) { return false; }
public List<de.hsmannheim.faktura.dokumente.domain.Dokument> findAll() { return List.of(); }
public boolean delete(String n) { return false; }
}; };
} }
} }

View File

@ -34,24 +34,26 @@ public class ProductPerformanceTest {
@Override public java.util.Optional<de.hsmannheim.faktura.dokumente.domain.Dokument> findByNummer(String n) { return java.util.Optional.empty(); } @Override public java.util.Optional<de.hsmannheim.faktura.dokumente.domain.Dokument> findByNummer(String n) { return java.util.Optional.empty(); }
@Override public List<de.hsmannheim.faktura.dokumente.domain.Dokument> findByKunde(long id) { return java.util.List.of(); } @Override public List<de.hsmannheim.faktura.dokumente.domain.Dokument> findByKunde(long id) { return java.util.List.of(); }
@Override public boolean existsFolgedokument(String q) { return false; } @Override public boolean existsFolgedokument(String q) { return false; }
@Override public List<de.hsmannheim.faktura.dokumente.domain.Dokument> findAll() { return java.util.List.of(); }
@Override public boolean delete(String n) { return false; }
}; };
ProductService service = new ProductService(repo, dummyDocRepo); ProductService service = new ProductService(repo, dummyDocRepo);
// Bereinigen und künstliches Befüllen mit exakt 1.000 Produkten // Bereinigen und künstliches Befüllen mit exakt 1.000 Produkten
for (Product p : repo.findAll()) { for (Product p : repo.findAll()) {
repo.deleteById(p.getProductId()); repo.deleteById(p.getProductId());
} }
for (int i = 1; i <= 1000; i++) { for (int i = 1; i <= 1000; i++) {
repo.save(new Product("P-" + i, "Produkt Nummer " + i, new BigDecimal("10.00"), MwstSatz.NORMAL, "", "Kategorie")); repo.save(new Product("P-" + i, "Produkt Nummer " + i, new BigDecimal("10.00"), MwstSatz.NORMAL, "", "Kategorie"));
} }
// Zeitmessung starten // Zeitmessung starten
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
List<Product> results = service.searchProducts("Nummer 999"); List<Product> results = service.searchProducts("Nummer 999");
long endTime = System.currentTimeMillis(); long endTime = System.currentTimeMillis();
long duration = endTime - startTime; long duration = endTime - startTime;

View File

@ -32,11 +32,11 @@ public class ProductServiceTest {
@BeforeEach @BeforeEach
public void setUp() { public void setUp() {
productRepository = new ProductRepository(); productRepository = new ProductRepository();
dokumentRepository = new de.hsmannheim.faktura.dokumente.repository.DokumentRepository() { dokumentRepository = new de.hsmannheim.faktura.dokumente.repository.DokumentRepository() {
@Override @Override
public boolean existsReferencedProdukt(long produktId) { public boolean existsReferencedProdukt(long produktId) {
return false; return false;
} }
@Override @Override
@ -68,10 +68,20 @@ public class ProductServiceTest {
public boolean existsFolgedokument(String quellDokumentNummer) { public boolean existsFolgedokument(String quellDokumentNummer) {
throw new UnsupportedOperationException("Unimplemented method 'existsFolgedokument'"); throw new UnsupportedOperationException("Unimplemented method 'existsFolgedokument'");
} }
@Override
public List<Dokument> findAll() {
throw new UnsupportedOperationException("Unimplemented method 'findAll'");
}
@Override
public boolean delete(String nummer) {
throw new UnsupportedOperationException("Unimplemented method 'delete'");
}
}; };
productService = new ProductService(productRepository, dokumentRepository); productService = new ProductService(productRepository, dokumentRepository);
for (Product p : productRepository.findAll()) { for (Product p : productRepository.findAll()) {
productRepository.deleteById(p.getProductId()); productRepository.deleteById(p.getProductId());
} }
@ -84,7 +94,7 @@ public class ProductServiceTest {
@Test @Test
public void testSaveValidProduct() { public void testSaveValidProduct() {
Product valid = new Product("P-0001", "M6 Schraube", new BigDecimal("10.50"), MwstSatz.NORMAL, "Beschreibung", "Werkzeug"); Product valid = new Product("P-0001", "M6 Schraube", new BigDecimal("10.50"), MwstSatz.NORMAL, "Beschreibung", "Werkzeug");
assertDoesNotThrow(() -> productService.saveProduct(valid)); assertDoesNotThrow(() -> productService.saveProduct(valid));
assertTrue(productService.getProductById("P-0001").isPresent()); assertTrue(productService.getProductById("P-0001").isPresent());
} }
@ -115,7 +125,7 @@ public class ProductServiceTest {
@Test @Test
public void testNegativePriceRejection() { public void testNegativePriceRejection() {
Product invalidProduct = new Product("P-9999", "Testprodukt", new BigDecimal("-1.00"), MwstSatz.NORMAL, "Test", "Test"); Product invalidProduct = new Product("P-9999", "Testprodukt", new BigDecimal("-1.00"), MwstSatz.NORMAL, "Test", "Test");
assertThrows(IllegalArgumentException.class, () -> { assertThrows(IllegalArgumentException.class, () -> {
productService.saveProduct(invalidProduct); productService.saveProduct(invalidProduct);
}); });
@ -162,10 +172,10 @@ public class ProductServiceTest {
public void testSearchCaseInsensitive() { public void testSearchCaseInsensitive() {
Product p1 = new Product("P-0001", "M6 Schraube", new BigDecimal("1.00"), MwstSatz.NORMAL, "", ""); Product p1 = new Product("P-0001", "M6 Schraube", new BigDecimal("1.00"), MwstSatz.NORMAL, "", "");
Product p2 = new Product("P-0002", "M8 SCHRAUBE", new BigDecimal("2.00"), MwstSatz.NORMAL, "", ""); Product p2 = new Product("P-0002", "M8 SCHRAUBE", new BigDecimal("2.00"), MwstSatz.NORMAL, "", "");
productService.saveProduct(p1); productService.saveProduct(p1);
productService.saveProduct(p2); productService.saveProduct(p2);
List<Product> results = productService.searchProducts("schraube"); List<Product> results = productService.searchProducts("schraube");
assertEquals(2, results.size()); assertEquals(2, results.size());
} }
@ -178,16 +188,16 @@ public class ProductServiceTest {
public void testDeleteReferencedProduct() { public void testDeleteReferencedProduct() {
de.hsmannheim.faktura.dokumente.repository.DokumentRepository mockRepo = new de.hsmannheim.faktura.dokumente.repository.DokumentRepository() { de.hsmannheim.faktura.dokumente.repository.DokumentRepository mockRepo = new de.hsmannheim.faktura.dokumente.repository.DokumentRepository() {
@Override @Override
public boolean existsReferencedProdukt(long produktId) { public boolean existsReferencedProdukt(long produktId) {
return true; return true;
}
@Override
public boolean existsReferencedKunde(long kundenId) {
return false;
} }
@Override @Override
public int findMaxLaufendeNummer(String praefix, int jahr) { public boolean existsReferencedKunde(long kundenId) {
return 0; return false;
}
@Override
public int findMaxLaufendeNummer(String praefix, int jahr) {
return 0;
} }
@Override @Override
public void save(Dokument dokument) { public void save(Dokument dokument) {
@ -205,8 +215,16 @@ public class ProductServiceTest {
public boolean existsFolgedokument(String quellDokumentNummer) { public boolean existsFolgedokument(String quellDokumentNummer) {
throw new UnsupportedOperationException("Unimplemented method 'existsFolgedokument'"); throw new UnsupportedOperationException("Unimplemented method 'existsFolgedokument'");
} }
@Override
public List<Dokument> findAll() {
throw new UnsupportedOperationException("Unimplemented method 'findAll'");
}
@Override
public boolean delete(String nummer) {
throw new UnsupportedOperationException("Unimplemented method 'delete'");
}
}; };
ProductService serviceWithSperre = new ProductService(productRepository, mockRepo); ProductService serviceWithSperre = new ProductService(productRepository, mockRepo);
Product product = new Product("P-0001", "Gesperrtes Produkt", new BigDecimal("10.00"), MwstSatz.NORMAL, "", ""); Product product = new Product("P-0001", "Gesperrtes Produkt", new BigDecimal("10.00"), MwstSatz.NORMAL, "", "");
productRepository.save(product); productRepository.save(product);