|
|
|
|
@ -3,69 +3,33 @@ package de.hsmannheim.faktura.gui;
|
|
|
|
|
import javax.swing.*;
|
|
|
|
|
import javax.swing.table.*;
|
|
|
|
|
import java.awt.*;
|
|
|
|
|
import java.io.File;
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
|
import java.nio.file.Path;
|
|
|
|
|
import java.time.LocalDate;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Collections;
|
|
|
|
|
import java.util.Comparator;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Optional;
|
|
|
|
|
|
|
|
|
|
import de.hsmannheim.faktura.dokumente.domain.Dokument;
|
|
|
|
|
import de.hsmannheim.faktura.dokumente.domain.DokumentPosition;
|
|
|
|
|
import de.hsmannheim.faktura.dokumente.domain.DokumentStatus;
|
|
|
|
|
import de.hsmannheim.faktura.dokumente.domain.DokumentType;
|
|
|
|
|
import de.hsmannheim.faktura.dokumente.export.PdfExportService;
|
|
|
|
|
import de.hsmannheim.faktura.dokumente.export.SimplePdfExportService;
|
|
|
|
|
import de.hsmannheim.faktura.dokumente.lookup.CustomerDto;
|
|
|
|
|
import de.hsmannheim.faktura.dokumente.lookup.CustomerLookup;
|
|
|
|
|
import de.hsmannheim.faktura.dokumente.lookup.ProductDto;
|
|
|
|
|
import de.hsmannheim.faktura.dokumente.lookup.ProductLookup;
|
|
|
|
|
import de.hsmannheim.faktura.dokumente.repository.DokumentRepository;
|
|
|
|
|
import de.hsmannheim.faktura.dokumente.service.DokumentenService;
|
|
|
|
|
import de.hsmannheim.faktura.dokumente.repository.InMemoryDokumentRepository;
|
|
|
|
|
import de.hsmannheim.faktura.dokumente.service.DokumentService;
|
|
|
|
|
import de.hsmannheim.faktura.dokumente.service.DokumentServiceImpl;
|
|
|
|
|
import de.hsmannheim.faktura.kunde.repository.KundeRepositoryJson;
|
|
|
|
|
import de.hsmannheim.faktura.kunde.service.BelegReferenzPruefer;
|
|
|
|
|
import de.hsmannheim.faktura.kunde.service.KundeService;
|
|
|
|
|
import de.hsmannheim.faktura.kunde.service.KundeValidator;
|
|
|
|
|
import de.hsmannheim.faktura.kunde.model.Kunde;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Panel für den Dokumentenprozess (PHGUI10, PHGUI11, PHGUI12).
|
|
|
|
|
*
|
|
|
|
|
* Verdrahtung gegen die spec-konforme Schnittstelle aus dem
|
|
|
|
|
* Pflichtenheft Gruppe F v1.0 (Kap. 6.2):
|
|
|
|
|
* - Service: {@link DokumentService} / {@link DokumentServiceImpl}
|
|
|
|
|
* - Repository: {@link DokumentRepository} / {@link InMemoryDokumentRepository}
|
|
|
|
|
* - Methoden: erstelleAuftragsbestaetigung / erstelleLieferschein /
|
|
|
|
|
* erstelleRechnung / exportiereAlsPdf
|
|
|
|
|
* - Status: OFFEN, UEBERFUEHRT, BESTAETIGT, GELIEFERT, FAKTURIERT,
|
|
|
|
|
* FESTGESCHRIEBEN
|
|
|
|
|
*
|
|
|
|
|
* Die ursprüngliche GUI-Verdrahtung (DokumentenService, getDokumentnummer,
|
|
|
|
|
* RECHNUNG_ERSTELLT, deleteDokument, ...) findet sich in keinem Pflichtenheft
|
|
|
|
|
* wieder und wurde hier auf die gemeinsame Spec gemappt. OP-6 (GUI vs.
|
|
|
|
|
* PH v1.1 / Gruppe F PH v1.0).
|
|
|
|
|
* Zeigt Status und zulässige Folgeaktionen an. Deaktiviert unzulässige Aktionen (PHGUI10).
|
|
|
|
|
* Festgeschriebene Rechnungen sind schreibgeschützt (PHGUI11).
|
|
|
|
|
*/
|
|
|
|
|
public class DokumentPanel extends JPanel {
|
|
|
|
|
|
|
|
|
|
private final MainFrame mainFrame;
|
|
|
|
|
private final DokumentService dokumentService;
|
|
|
|
|
private final TrackingDokumentRepository tracking;
|
|
|
|
|
private final DokumentenService dokumentenService;
|
|
|
|
|
|
|
|
|
|
// Tabelle
|
|
|
|
|
private DefaultTableModel tableModel;
|
|
|
|
|
private JTable dokumentTable;
|
|
|
|
|
|
|
|
|
|
// Detailfelder (schreibgeschützt)
|
|
|
|
|
private JTextField txtDokumentNummer;
|
|
|
|
|
private JTextField txtDokumentnummer;
|
|
|
|
|
private JTextField txtKundenId;
|
|
|
|
|
private JTextField txtDatum;
|
|
|
|
|
private JTextField txtStatus;
|
|
|
|
|
private JCheckBox chkFestgeschrieben;
|
|
|
|
|
private JCheckBox chkFestgeschrieben;
|
|
|
|
|
|
|
|
|
|
// Positionstabelle
|
|
|
|
|
private DefaultTableModel posTableModel;
|
|
|
|
|
@ -78,6 +42,8 @@ public class DokumentPanel extends JPanel {
|
|
|
|
|
|
|
|
|
|
// Aktions-Buttons (PHGUI10)
|
|
|
|
|
private JButton btnNeu;
|
|
|
|
|
private JButton btnSpeichern;
|
|
|
|
|
private JButton btnLoeschen;
|
|
|
|
|
private JButton btnAbbrechen;
|
|
|
|
|
private JButton btnPdfExport;
|
|
|
|
|
|
|
|
|
|
@ -90,53 +56,18 @@ public class DokumentPanel extends JPanel {
|
|
|
|
|
|
|
|
|
|
public DokumentPanel(MainFrame mainFrame) {
|
|
|
|
|
this.mainFrame = mainFrame;
|
|
|
|
|
|
|
|
|
|
// DokumentServiceImpl braucht 4 Abhängigkeiten (DI laut Gruppe F):
|
|
|
|
|
// Repository, ProductLookup, CustomerLookup, PdfExportService.
|
|
|
|
|
this.tracking = new TrackingDokumentRepository(new InMemoryDokumentRepository());
|
|
|
|
|
PdfExportService pdfExport = new SimplePdfExportService(Path.of("exports"));
|
|
|
|
|
CustomerLookup customerLookup = new KundeCustomerLookup(buildKundeService());
|
|
|
|
|
ProductLookup productLookup = stubProductLookup();
|
|
|
|
|
|
|
|
|
|
this.dokumentService = new DokumentServiceImpl(
|
|
|
|
|
tracking, productLookup, customerLookup, pdfExport);
|
|
|
|
|
|
|
|
|
|
// FIX: InMemoryDokumentRepository statt DokumentRepository (Interface)
|
|
|
|
|
this.dokumentenService = new DokumentenService(new InMemoryDokumentRepository());
|
|
|
|
|
setLayout(new BorderLayout(8, 8));
|
|
|
|
|
setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
|
|
|
|
|
initComponents();
|
|
|
|
|
ladeDokumente();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* KundeService nur als Datenquelle für den CustomerLookup-Adapter
|
|
|
|
|
* (K3 aus PH v1.1). Eigener Aufbau, da das Panel self-contained ist –
|
|
|
|
|
* geteiltes Wiring zwischen Panels ist Bestandteil von OP-6.
|
|
|
|
|
*/
|
|
|
|
|
private KundeService buildKundeService() {
|
|
|
|
|
return new KundeService(
|
|
|
|
|
new KundeRepositoryJson(new File("data/kunden.json")),
|
|
|
|
|
new KundeValidator(),
|
|
|
|
|
(BelegReferenzPruefer) (kundeId -> false));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* DokumentPanel kann derzeit keine neuen Angebote anlegen
|
|
|
|
|
* (Eingabemaske fehlt im UI), deshalb wird der ProductLookup nicht
|
|
|
|
|
* aktiv genutzt. Stub ist ausreichend, damit DokumentServiceImpl
|
|
|
|
|
* verdrahtet werden kann.
|
|
|
|
|
*/
|
|
|
|
|
private ProductLookup stubProductLookup() {
|
|
|
|
|
return produktId -> Optional.<ProductDto>empty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
|
// UI-Aufbau
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
private void initComponents() {
|
|
|
|
|
// --- Linke Seite: Dokumentenliste ---
|
|
|
|
|
JPanel leftPanel = new JPanel(new BorderLayout(4, 4));
|
|
|
|
|
leftPanel.setPreferredSize(new Dimension(320, 0));
|
|
|
|
|
leftPanel.setPreferredSize(new Dimension(300, 0));
|
|
|
|
|
|
|
|
|
|
String[] cols = {"Nr.", "Typ", "Status"};
|
|
|
|
|
tableModel = new DefaultTableModel(cols, 0) {
|
|
|
|
|
@ -146,9 +77,14 @@ public class DokumentPanel extends JPanel {
|
|
|
|
|
// Status-Spalte farbig (PHGUI10)
|
|
|
|
|
public Component prepareRenderer(TableCellRenderer r, int row, int col) {
|
|
|
|
|
Component c = super.prepareRenderer(r, row, col);
|
|
|
|
|
if (col == 2 && !isRowSelected(row)) {
|
|
|
|
|
String status = String.valueOf(getValueAt(row, col));
|
|
|
|
|
c.setForeground(farbeFuerStatus(status));
|
|
|
|
|
if (col == 2) {
|
|
|
|
|
String status = (String) getValueAt(row, col);
|
|
|
|
|
if (status != null) {
|
|
|
|
|
if (status.contains("Offen")) c.setForeground(new Color(41, 128, 185));
|
|
|
|
|
else if (status.contains("Bestätigt")) c.setForeground(new Color(39, 174, 96));
|
|
|
|
|
else if (status.contains("Festgeschr")) c.setForeground(new Color(192, 57, 43));
|
|
|
|
|
else c.setForeground(Color.BLACK);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
c.setForeground(Color.BLACK);
|
|
|
|
|
}
|
|
|
|
|
@ -157,266 +93,264 @@ public class DokumentPanel extends JPanel {
|
|
|
|
|
};
|
|
|
|
|
dokumentTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
|
|
|
|
dokumentTable.setAutoCreateRowSorter(true);
|
|
|
|
|
dokumentTable.getTableHeader().setReorderingAllowed(false);
|
|
|
|
|
dokumentTable.getSelectionModel().addListSelectionListener(e -> {
|
|
|
|
|
if (!e.getValueIsAdjusting()) zeigeAusgewaehltes();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
leftPanel.add(new JLabel("Dokumente"), BorderLayout.NORTH);
|
|
|
|
|
leftPanel.add(new JScrollPane(dokumentTable), BorderLayout.CENTER);
|
|
|
|
|
|
|
|
|
|
// --- Rechte Seite: Detailbereich ---
|
|
|
|
|
JPanel rightPanel = new JPanel(new BorderLayout(0, 8));
|
|
|
|
|
rightPanel.add(kopfPanel(), BorderLayout.NORTH);
|
|
|
|
|
rightPanel.add(positionsBereich(), BorderLayout.CENTER);
|
|
|
|
|
rightPanel.add(buttonPanel(), BorderLayout.SOUTH);
|
|
|
|
|
// --- Rechte Seite: Detailansicht ---
|
|
|
|
|
JPanel rightPanel = new JPanel(new BorderLayout(4, 8));
|
|
|
|
|
|
|
|
|
|
JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, rightPanel);
|
|
|
|
|
split.setDividerLocation(320);
|
|
|
|
|
add(split, BorderLayout.CENTER);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private JPanel kopfPanel() {
|
|
|
|
|
JPanel p = new JPanel(new GridBagLayout());
|
|
|
|
|
p.setBorder(BorderFactory.createTitledBorder("Dokumentkopf"));
|
|
|
|
|
JPanel headerPanel = new JPanel(new GridBagLayout());
|
|
|
|
|
headerPanel.setBorder(BorderFactory.createTitledBorder("Dokumentdetail"));
|
|
|
|
|
GridBagConstraints g = new GridBagConstraints();
|
|
|
|
|
g.insets = new Insets(4, 6, 2, 6);
|
|
|
|
|
g.anchor = GridBagConstraints.WEST;
|
|
|
|
|
g.fill = GridBagConstraints.HORIZONTAL;
|
|
|
|
|
g.weightx = 1.0;
|
|
|
|
|
g.insets = new Insets(3, 4, 3, 4);
|
|
|
|
|
g.fill = GridBagConstraints.HORIZONTAL;
|
|
|
|
|
g.weightx = 0.5;
|
|
|
|
|
|
|
|
|
|
txtDokumentNummer = createReadOnlyField();
|
|
|
|
|
txtKundenId = createReadOnlyField();
|
|
|
|
|
txtDatum = createReadOnlyField();
|
|
|
|
|
txtStatus = createReadOnlyField();
|
|
|
|
|
chkFestgeschrieben = new JCheckBox("Festgeschrieben (PHGUI11)");
|
|
|
|
|
// Festgeschrieben-Checkbox (PHGUI11)
|
|
|
|
|
chkFestgeschrieben = new JCheckBox("Festgeschrieben");
|
|
|
|
|
chkFestgeschrieben.setEnabled(false);
|
|
|
|
|
g.gridx = 1; g.gridy = 0; g.anchor = GridBagConstraints.EAST;
|
|
|
|
|
headerPanel.add(chkFestgeschrieben, g);
|
|
|
|
|
|
|
|
|
|
int row = 0;
|
|
|
|
|
row = addLabelField(p, g, "Dokumentnummer:", txtDokumentNummer, row);
|
|
|
|
|
row = addLabelField(p, g, "Kunden-ID:", txtKundenId, row);
|
|
|
|
|
row = addLabelField(p, g, "Datum:", txtDatum, row);
|
|
|
|
|
row = addLabelField(p, g, "Status:", txtStatus, row);
|
|
|
|
|
g.anchor = GridBagConstraints.WEST;
|
|
|
|
|
g.gridx = 0; g.gridy = 1; headerPanel.add(new JLabel("Dokumentnummer"), g);
|
|
|
|
|
g.gridx = 1; headerPanel.add(new JLabel("Kundennummer"), g);
|
|
|
|
|
txtDokumentnummer = createReadOnlyField();
|
|
|
|
|
txtKundenId = createReadOnlyField();
|
|
|
|
|
g.gridx = 0; g.gridy = 2; headerPanel.add(txtDokumentnummer, g);
|
|
|
|
|
g.gridx = 1; headerPanel.add(txtKundenId, g);
|
|
|
|
|
|
|
|
|
|
g.gridx = 0; g.gridy = row; g.gridwidth = 2; p.add(chkFestgeschrieben, g);
|
|
|
|
|
g.gridwidth = 1;
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
g.gridx = 0; g.gridy = 3; headerPanel.add(new JLabel("Datum"), g);
|
|
|
|
|
g.gridx = 1; headerPanel.add(new JLabel("Status"), g);
|
|
|
|
|
txtDatum = createReadOnlyField();
|
|
|
|
|
txtStatus = createReadOnlyField();
|
|
|
|
|
g.gridx = 0; g.gridy = 4; headerPanel.add(txtDatum, g);
|
|
|
|
|
g.gridx = 1; headerPanel.add(txtStatus, g);
|
|
|
|
|
|
|
|
|
|
private JPanel positionsBereich() {
|
|
|
|
|
JPanel p = new JPanel(new BorderLayout(0, 4));
|
|
|
|
|
p.setBorder(BorderFactory.createTitledBorder("Positionen / Summen"));
|
|
|
|
|
rightPanel.add(headerPanel, BorderLayout.NORTH);
|
|
|
|
|
|
|
|
|
|
String[] posCols = {"Pos.", "Bezeichnung", "Menge", "Einzelpreis", "MwSt.", "Gesamt"};
|
|
|
|
|
// Positionstabelle
|
|
|
|
|
String[] posCols = {"Pos", "Bezeichnung", "Menge", "Einzelpreis", "MwSt.", "Summe"};
|
|
|
|
|
posTableModel = new DefaultTableModel(posCols, 0) {
|
|
|
|
|
public boolean isCellEditable(int r, int c) { return false; }
|
|
|
|
|
};
|
|
|
|
|
posTable = new JTable(posTableModel);
|
|
|
|
|
posTable.getTableHeader().setReorderingAllowed(false);
|
|
|
|
|
p.add(new JScrollPane(posTable), BorderLayout.CENTER);
|
|
|
|
|
posTable.setEnabled(false);
|
|
|
|
|
|
|
|
|
|
JPanel summenPanel = new JPanel(new GridLayout(1, 6, 8, 0));
|
|
|
|
|
summenPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
|
|
|
|
|
summenPanel.add(new JLabel("Netto:"));
|
|
|
|
|
lblNetto = new JLabel("0.00 €");
|
|
|
|
|
summenPanel.add(lblNetto);
|
|
|
|
|
summenPanel.add(new JLabel("USt.:"));
|
|
|
|
|
lblUst = new JLabel("0.00 €");
|
|
|
|
|
summenPanel.add(lblUst);
|
|
|
|
|
summenPanel.add(new JLabel("Brutto:"));
|
|
|
|
|
lblBrutto = new JLabel("0.00 €");
|
|
|
|
|
summenPanel.add(lblBrutto);
|
|
|
|
|
p.add(summenPanel, BorderLayout.SOUTH);
|
|
|
|
|
return p;
|
|
|
|
|
}
|
|
|
|
|
JPanel posPanel = new JPanel(new BorderLayout());
|
|
|
|
|
posPanel.setBorder(BorderFactory.createTitledBorder("Positionen:"));
|
|
|
|
|
posPanel.add(new JScrollPane(posTable), BorderLayout.CENTER);
|
|
|
|
|
|
|
|
|
|
private JPanel buttonPanel() {
|
|
|
|
|
JPanel p = new JPanel(new FlowLayout(FlowLayout.RIGHT, 8, 4));
|
|
|
|
|
// Summen
|
|
|
|
|
JPanel summenPanel = new JPanel(new GridLayout(3, 2, 4, 2));
|
|
|
|
|
summenPanel.setBorder(BorderFactory.createEmptyBorder(4, 8, 4, 8));
|
|
|
|
|
lblNetto = new JLabel("0,00 €"); lblNetto.setHorizontalAlignment(SwingConstants.RIGHT);
|
|
|
|
|
lblUst = new JLabel("0,00 €"); lblUst.setHorizontalAlignment(SwingConstants.RIGHT);
|
|
|
|
|
lblBrutto = new JLabel("0,00 €", SwingConstants.RIGHT);
|
|
|
|
|
lblBrutto.setFont(new Font("SansSerif", Font.BOLD, 13));
|
|
|
|
|
summenPanel.add(new JLabel("Netto:")); summenPanel.add(lblNetto);
|
|
|
|
|
summenPanel.add(new JLabel("USt.:")); summenPanel.add(lblUst);
|
|
|
|
|
summenPanel.add(new JLabel("Brutto:")); summenPanel.add(lblBrutto);
|
|
|
|
|
|
|
|
|
|
btnNeu = new JButton("Auswahl zurücksetzen");
|
|
|
|
|
btnAbbrechen = new JButton("Abbrechen");
|
|
|
|
|
btnPdfExport = new JButton("PDF-Export");
|
|
|
|
|
btnAngebotZuAuftrag = new JButton("→ Auftragsbestätigung");
|
|
|
|
|
btnAuftragZuLieferschein = new JButton("→ Lieferschein");
|
|
|
|
|
btnLieferscheinZuRechnung = new JButton("→ Rechnung");
|
|
|
|
|
JPanel mittelPanel = new JPanel(new BorderLayout());
|
|
|
|
|
mittelPanel.add(posPanel, BorderLayout.CENTER);
|
|
|
|
|
mittelPanel.add(summenPanel, BorderLayout.SOUTH);
|
|
|
|
|
rightPanel.add(mittelPanel, BorderLayout.CENTER);
|
|
|
|
|
|
|
|
|
|
// --- Aktionen (PHGUI10: nur zulässige aktiv) ---
|
|
|
|
|
JPanel aktionenPanel = new JPanel(new BorderLayout());
|
|
|
|
|
aktionenPanel.setBorder(BorderFactory.createTitledBorder("Aktionen:"));
|
|
|
|
|
|
|
|
|
|
JPanel stdButtons = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
|
|
|
|
btnNeu = new JButton("Neu");
|
|
|
|
|
btnSpeichern = new JButton("Speichern");
|
|
|
|
|
btnLoeschen = new JButton("Löschen");
|
|
|
|
|
btnAbbrechen = new JButton("Abbrechen");
|
|
|
|
|
btnPdfExport = new JButton("PDF-Export");
|
|
|
|
|
btnPdfExport.setBackground(new Color(41, 128, 185));
|
|
|
|
|
btnPdfExport.setForeground(Color.WHITE);
|
|
|
|
|
stdButtons.add(btnNeu);
|
|
|
|
|
stdButtons.add(btnSpeichern);
|
|
|
|
|
stdButtons.add(btnLoeschen);
|
|
|
|
|
stdButtons.add(btnAbbrechen);
|
|
|
|
|
stdButtons.add(btnPdfExport);
|
|
|
|
|
|
|
|
|
|
JPanel folgeButtons = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
|
|
|
|
btnAngebotZuAuftrag = new JButton("→ Auftragsbestätigung erstellen");
|
|
|
|
|
btnAuftragZuLieferschein = new JButton("→ Lieferschein erstellen");
|
|
|
|
|
btnLieferscheinZuRechnung = new JButton("→ Rechnung erstellen");
|
|
|
|
|
folgeButtons.add(btnAngebotZuAuftrag);
|
|
|
|
|
folgeButtons.add(btnAuftragZuLieferschein);
|
|
|
|
|
folgeButtons.add(btnLieferscheinZuRechnung);
|
|
|
|
|
|
|
|
|
|
aktionenPanel.add(stdButtons, BorderLayout.NORTH);
|
|
|
|
|
aktionenPanel.add(folgeButtons, BorderLayout.SOUTH);
|
|
|
|
|
rightPanel.add(aktionenPanel, BorderLayout.SOUTH);
|
|
|
|
|
|
|
|
|
|
// Button-Actions
|
|
|
|
|
btnNeu.addActionListener(e -> neuesFormular());
|
|
|
|
|
btnAbbrechen.addActionListener(e -> neuesFormular());
|
|
|
|
|
btnAbbrechen.addActionListener(e -> { neuesFormular(); ladeDokumente(); });
|
|
|
|
|
btnPdfExport.addActionListener(e -> pdfExport());
|
|
|
|
|
btnAngebotZuAuftrag.addActionListener(e ->
|
|
|
|
|
folgeaktion(DokumentType.ANGEBOT));
|
|
|
|
|
btnAuftragZuLieferschein.addActionListener(e ->
|
|
|
|
|
folgeaktion(DokumentType.AUFTRAGSBESTAETIGUNG));
|
|
|
|
|
btnLieferscheinZuRechnung.addActionListener(e ->
|
|
|
|
|
folgeaktion(DokumentType.LIEFERSCHEIN));
|
|
|
|
|
btnLoeschen.addActionListener(e -> loeschen());
|
|
|
|
|
|
|
|
|
|
p.add(btnAngebotZuAuftrag);
|
|
|
|
|
p.add(btnAuftragZuLieferschein);
|
|
|
|
|
p.add(btnLieferscheinZuRechnung);
|
|
|
|
|
p.add(btnPdfExport);
|
|
|
|
|
p.add(btnNeu);
|
|
|
|
|
p.add(btnAbbrechen);
|
|
|
|
|
btnAngebotZuAuftrag.addActionListener(e -> folgeaktion("ANGEBOT_ZU_AUFTRAG"));
|
|
|
|
|
btnAuftragZuLieferschein.addActionListener(e -> folgeaktion("AUFTRAG_ZU_LIEFERSCHEIN"));
|
|
|
|
|
btnLieferscheinZuRechnung.addActionListener(e -> folgeaktion("LIEFERSCHEIN_ZU_RECHNUNG"));
|
|
|
|
|
|
|
|
|
|
// Initial alles deaktiviert (es ist nichts ausgewählt)
|
|
|
|
|
setAktionenDeaktiviert();
|
|
|
|
|
return p;
|
|
|
|
|
|
|
|
|
|
JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, rightPanel);
|
|
|
|
|
split.setDividerLocation(300);
|
|
|
|
|
add(split, BorderLayout.CENTER);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private int addLabelField(JPanel p, GridBagConstraints g,
|
|
|
|
|
String label, JComponent field, int row) {
|
|
|
|
|
g.weighty = 0;
|
|
|
|
|
g.gridx = 0; g.gridy = row; g.weightx = 0; p.add(new JLabel(label), g);
|
|
|
|
|
g.gridx = 1; g.gridy = row; g.weightx = 1.0; p.add(field, g);
|
|
|
|
|
return row + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
|
// Daten laden / anzeigen
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
|
// --- Daten ---
|
|
|
|
|
|
|
|
|
|
private void ladeDokumente() {
|
|
|
|
|
tableModel.setRowCount(0);
|
|
|
|
|
for (Dokument d : tracking.findAll()) {
|
|
|
|
|
List<Dokument> alle = dokumentenService.getAllDokumente();
|
|
|
|
|
for (Dokument d : alle) {
|
|
|
|
|
tableModel.addRow(new Object[]{
|
|
|
|
|
d.getDokumentNummer(),
|
|
|
|
|
typBezeichnung(d.getTyp()),
|
|
|
|
|
d.getStatus().name()
|
|
|
|
|
d.getDokumentNummer(), // FIX: getDokumentNummer() statt getDokumentnummer()
|
|
|
|
|
d.getTypBezeichnung(),
|
|
|
|
|
d.getStatus().getAnzeigename()
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void zeigeAusgewaehltes() {
|
|
|
|
|
int row = dokumentTable.getSelectedRow();
|
|
|
|
|
if (row < 0) { aktuellesDokument = null; return; }
|
|
|
|
|
if (row < 0) return;
|
|
|
|
|
int modelRow = dokumentTable.convertRowIndexToModel(row);
|
|
|
|
|
String nr = (String) tableModel.getValueAt(modelRow, 0);
|
|
|
|
|
|
|
|
|
|
tracking.findByNummer(nr).ifPresent(this::zeigeDokument);
|
|
|
|
|
}
|
|
|
|
|
dokumentenService.getDokumentByNummer(nr).ifPresent(d -> {
|
|
|
|
|
aktuellesDokument = d;
|
|
|
|
|
txtDokumentnummer.setText(d.getDokumentNummer()); // FIX
|
|
|
|
|
txtKundenId.setText(String.valueOf(d.getKundenId())); // FIX
|
|
|
|
|
txtDatum.setText(d.getDatum().toString());
|
|
|
|
|
txtStatus.setText(d.getStatus().getAnzeigename());
|
|
|
|
|
|
|
|
|
|
private void zeigeDokument(Dokument d) {
|
|
|
|
|
aktuellesDokument = d;
|
|
|
|
|
txtDokumentNummer.setText(d.getDokumentNummer());
|
|
|
|
|
txtKundenId.setText(Long.toString(d.getKundenId()));
|
|
|
|
|
txtDatum.setText(d.getDatum() == null ? "" : d.getDatum().toString());
|
|
|
|
|
txtStatus.setText(d.getStatus().name());
|
|
|
|
|
chkFestgeschrieben.setSelected(d.isFestgeschrieben());
|
|
|
|
|
|
|
|
|
|
boolean festgeschrieben = d.getStatus() == DokumentStatus.FESTGESCHRIEBEN;
|
|
|
|
|
chkFestgeschrieben.setSelected(festgeschrieben);
|
|
|
|
|
|
|
|
|
|
// Positionen
|
|
|
|
|
posTableModel.setRowCount(0);
|
|
|
|
|
int pos = 1;
|
|
|
|
|
boolean lieferschein = d.getTyp() == DokumentType.LIEFERSCHEIN; // PH-DP-07
|
|
|
|
|
for (DokumentPosition p : d.getPositionen()) {
|
|
|
|
|
posTableModel.addRow(new Object[]{
|
|
|
|
|
// Positionen laden
|
|
|
|
|
posTableModel.setRowCount(0);
|
|
|
|
|
int pos = 1;
|
|
|
|
|
for (var position : d.getPositionen()) {
|
|
|
|
|
posTableModel.addRow(new Object[]{
|
|
|
|
|
pos++,
|
|
|
|
|
p.getBezeichnungSnapshot(),
|
|
|
|
|
p.getMenge(),
|
|
|
|
|
lieferschein ? "—" : (p.getEinzelpreisNettoSnapshot() + " €"),
|
|
|
|
|
lieferschein ? "—" : (formatProzent(p.getMwstSatzSnapshot())),
|
|
|
|
|
lieferschein ? "—" : (p.getNettoGesamt() + " €")
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
position.getBezeichnungSnapshot(), // FIX
|
|
|
|
|
position.getMenge(),
|
|
|
|
|
position.getEinzelpreisNettoSnapshot() + " €", // FIX
|
|
|
|
|
position.getMwstSatzSnapshot().multiply(java.math.BigDecimal.valueOf(100))
|
|
|
|
|
.setScale(0, java.math.RoundingMode.HALF_UP) + "%",// FIX
|
|
|
|
|
position.getNettoGesamt() + " €" // FIX
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Summen (Lieferschein zeigt keine Preise – PH-DP-07)
|
|
|
|
|
if (lieferschein) {
|
|
|
|
|
lblNetto.setText("—");
|
|
|
|
|
lblUst.setText("—");
|
|
|
|
|
lblBrutto.setText("—");
|
|
|
|
|
} else {
|
|
|
|
|
lblNetto.setText(nullSichBd(d.getNettoSumme()) + " €");
|
|
|
|
|
lblUst.setText( nullSichBd(d.getUstSumme()) + " €");
|
|
|
|
|
lblBrutto.setText(nullSichBd(d.getBruttoSumme())+ " €");
|
|
|
|
|
}
|
|
|
|
|
// Summen (nicht für Lieferschein)
|
|
|
|
|
if (d.getNettoSumme() != null) { // FIX
|
|
|
|
|
lblNetto.setText(d.getNettoSumme().toPlainString() + " €"); // FIX
|
|
|
|
|
lblUst.setText(d.getUstSumme().toPlainString() + " €");
|
|
|
|
|
lblBrutto.setText(d.getBruttoSumme().toPlainString() + " €"); // FIX
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
aktualisiereAktionen(d);
|
|
|
|
|
aktualisiereAktionen(d);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String nullSichBd(BigDecimal v) { return v == null ? "0.00" : v.toPlainString(); }
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Aktiviert nur die zulässigen Folgeaktionen basierend auf
|
|
|
|
|
* Dokumenttyp und -status (PHGUI10).
|
|
|
|
|
* Festgeschriebene Rechnungen: alle Aktionen außer PDF-Export
|
|
|
|
|
* deaktiviert (PHGUI11).
|
|
|
|
|
* Aktiviert nur zulässige Folgeaktionen basierend auf Dokumentstatus (PHGUI10).
|
|
|
|
|
* Festgeschriebene Rechnungen: nur PDF-Export aktiv (PHGUI11).
|
|
|
|
|
*/
|
|
|
|
|
private void aktualisiereAktionen(Dokument d) {
|
|
|
|
|
DokumentType typ = d.getTyp();
|
|
|
|
|
DokumentStatus status = d.getStatus();
|
|
|
|
|
boolean festgeschrieben = d.isFestgeschrieben();
|
|
|
|
|
|
|
|
|
|
if (status == DokumentStatus.FESTGESCHRIEBEN) {
|
|
|
|
|
// PHGUI11: Festgeschriebene Rechnung → nur PDF-Export
|
|
|
|
|
if (festgeschrieben) {
|
|
|
|
|
btnNeu.setEnabled(true);
|
|
|
|
|
btnSpeichern.setEnabled(false);
|
|
|
|
|
btnLoeschen.setEnabled(false);
|
|
|
|
|
btnAbbrechen.setEnabled(true);
|
|
|
|
|
btnPdfExport.setEnabled(true); // PHGUI12
|
|
|
|
|
btnAngebotZuAuftrag.setEnabled(false);
|
|
|
|
|
btnAuftragZuLieferschein.setEnabled(false);
|
|
|
|
|
btnLieferscheinZuRechnung.setEnabled(false);
|
|
|
|
|
btnPdfExport.setEnabled(true); // PHGUI12
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
btnPdfExport.setEnabled(true);
|
|
|
|
|
btnAngebotZuAuftrag.setEnabled(
|
|
|
|
|
typ == DokumentType.ANGEBOT && status == DokumentStatus.OFFEN);
|
|
|
|
|
btnAuftragZuLieferschein.setEnabled(
|
|
|
|
|
typ == DokumentType.AUFTRAGSBESTAETIGUNG && status == DokumentStatus.BESTAETIGT);
|
|
|
|
|
btnLieferscheinZuRechnung.setEnabled(
|
|
|
|
|
typ == DokumentType.LIEFERSCHEIN && status == DokumentStatus.GELIEFERT);
|
|
|
|
|
// PHGUI10: Folgeaktionen je nach Status (FIX: korrekte Status-Konstanten)
|
|
|
|
|
btnNeu.setEnabled(true);
|
|
|
|
|
btnSpeichern.setEnabled(true);
|
|
|
|
|
btnLoeschen.setEnabled(true);
|
|
|
|
|
btnAbbrechen.setEnabled(true);
|
|
|
|
|
btnPdfExport.setEnabled(status == DokumentStatus.FESTGESCHRIEBEN); // FIX
|
|
|
|
|
|
|
|
|
|
btnAngebotZuAuftrag.setEnabled(status == DokumentStatus.OFFEN); // FIX
|
|
|
|
|
btnAuftragZuLieferschein.setEnabled(status == DokumentStatus.BESTAETIGT); // FIX
|
|
|
|
|
btnLieferscheinZuRechnung.setEnabled(status == DokumentStatus.GELIEFERT); // FIX
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void setAktionenDeaktiviert() {
|
|
|
|
|
btnSpeichern.setEnabled(false);
|
|
|
|
|
btnLoeschen.setEnabled(false);
|
|
|
|
|
btnPdfExport.setEnabled(false);
|
|
|
|
|
btnAngebotZuAuftrag.setEnabled(false);
|
|
|
|
|
btnAuftragZuLieferschein.setEnabled(false);
|
|
|
|
|
btnLieferscheinZuRechnung.setEnabled(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
|
// Aktionen
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
private void neuesFormular() {
|
|
|
|
|
aktuellesDokument = null;
|
|
|
|
|
dokumentTable.clearSelection();
|
|
|
|
|
txtDokumentNummer.setText("");
|
|
|
|
|
txtKundenId.setText("");
|
|
|
|
|
txtDatum.setText("");
|
|
|
|
|
txtStatus.setText("");
|
|
|
|
|
txtDokumentnummer.setText(""); txtKundenId.setText("");
|
|
|
|
|
txtDatum.setText(""); txtStatus.setText("");
|
|
|
|
|
chkFestgeschrieben.setSelected(false);
|
|
|
|
|
posTableModel.setRowCount(0);
|
|
|
|
|
lblNetto.setText("0.00 €");
|
|
|
|
|
lblUst.setText("0.00 €");
|
|
|
|
|
lblBrutto.setText("0.00 €");
|
|
|
|
|
lblNetto.setText("0,00 €"); lblUst.setText("0,00 €"); lblBrutto.setText("0,00 €");
|
|
|
|
|
setAktionenDeaktiviert();
|
|
|
|
|
btnNeu.setEnabled(true); btnAbbrechen.setEnabled(true);
|
|
|
|
|
dokumentTable.clearSelection();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Erzeugt das spec-konforme Folgedokument zum aktuell ausgewählten
|
|
|
|
|
* Dokument. PH-DP-04 / PH-DP-06 / PH-DP-08.
|
|
|
|
|
*/
|
|
|
|
|
private void folgeaktion(DokumentType erwartet) {
|
|
|
|
|
private void loeschen() {
|
|
|
|
|
if (aktuellesDokument == null) {
|
|
|
|
|
mainFrame.showStatus("Kein Dokument ausgewählt.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (aktuellesDokument.getTyp() != erwartet) {
|
|
|
|
|
mainFrame.showStatus("Aktion passt nicht zum Dokumenttyp.");
|
|
|
|
|
return;
|
|
|
|
|
int confirm = JOptionPane.showConfirmDialog(
|
|
|
|
|
this, "Dokument wirklich löschen?", "Löschen bestätigen",
|
|
|
|
|
JOptionPane.YES_NO_OPTION
|
|
|
|
|
);
|
|
|
|
|
if (confirm != JOptionPane.YES_OPTION) return;
|
|
|
|
|
|
|
|
|
|
boolean deleted = dokumentenService.deleteDokument(aktuellesDokument.getDokumentNummer()); // FIX
|
|
|
|
|
if (deleted) {
|
|
|
|
|
ladeDokumente(); neuesFormular();
|
|
|
|
|
mainFrame.showStatus("Dokument gelöscht.");
|
|
|
|
|
} else {
|
|
|
|
|
mainFrame.showStatus("Dokument kann nicht gelöscht werden (z. B. festgeschriebene Rechnung).");
|
|
|
|
|
}
|
|
|
|
|
String quellNr = aktuellesDokument.getDokumentNummer();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void folgeaktion(String typ) {
|
|
|
|
|
if (aktuellesDokument == null) return;
|
|
|
|
|
try {
|
|
|
|
|
Dokument folge;
|
|
|
|
|
switch (erwartet) {
|
|
|
|
|
case ANGEBOT ->
|
|
|
|
|
folge = dokumentService.erstelleAuftragsbestaetigung(quellNr); // PH-DP-04
|
|
|
|
|
case AUFTRAGSBESTAETIGUNG ->
|
|
|
|
|
folge = dokumentService.erstelleLieferschein(quellNr, LocalDate.now()); // PH-DP-06
|
|
|
|
|
case LIEFERSCHEIN ->
|
|
|
|
|
folge = dokumentService.erstelleRechnung(quellNr); // PH-DP-08
|
|
|
|
|
default -> { mainFrame.showStatus("Kein Folgedokument vorgesehen."); return; }
|
|
|
|
|
switch (typ) {
|
|
|
|
|
case "ANGEBOT_ZU_AUFTRAG" ->
|
|
|
|
|
dokumentenService.createAuftragsbestaetigung(aktuellesDokument.getDokumentNummer()); // FIX
|
|
|
|
|
case "AUFTRAG_ZU_LIEFERSCHEIN" ->
|
|
|
|
|
dokumentenService.createLieferschein(aktuellesDokument.getDokumentNummer()); // FIX
|
|
|
|
|
case "LIEFERSCHEIN_ZU_RECHNUNG" ->
|
|
|
|
|
dokumentenService.createRechnung(aktuellesDokument.getDokumentNummer()); // FIX
|
|
|
|
|
}
|
|
|
|
|
ladeDokumente();
|
|
|
|
|
mainFrame.showStatus("Folgedokument erstellt: " + folge.getDokumentNummer());
|
|
|
|
|
} catch (RuntimeException ex) {
|
|
|
|
|
// Fängt IllegalStateException, DuplicateDocumentException,
|
|
|
|
|
// ValidationException, DokumentNotFoundException
|
|
|
|
|
mainFrame.showStatus("Folgedokument erfolgreich erstellt.");
|
|
|
|
|
} catch (Exception ex) {
|
|
|
|
|
mainFrame.showStatus("Fehler: " + ex.getMessage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -427,128 +361,18 @@ public class DokumentPanel extends JPanel {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
Path pfad = dokumentService.exportiereAlsPdf(
|
|
|
|
|
aktuellesDokument.getDokumentNummer()); // PHGUI12 / PH-DP-12
|
|
|
|
|
mainFrame.showStatus("PDF erzeugt: " + pfad);
|
|
|
|
|
} catch (RuntimeException ex) {
|
|
|
|
|
dokumentenService.exportPdf(
|
|
|
|
|
aktuellesDokument.getDokumentNummer(), aktuellesDokument.getTyp()); // FIX
|
|
|
|
|
mainFrame.showStatus("PDF-Export erfolgreich.");
|
|
|
|
|
} catch (Exception ex) {
|
|
|
|
|
mainFrame.showStatus("PDF-Export fehlgeschlagen: " + ex.getMessage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
|
// Helfer
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
private static String typBezeichnung(DokumentType t) {
|
|
|
|
|
if (t == null) return "";
|
|
|
|
|
return switch (t) {
|
|
|
|
|
case ANGEBOT -> "Angebot";
|
|
|
|
|
case AUFTRAGSBESTAETIGUNG -> "Auftragsbestätigung";
|
|
|
|
|
case LIEFERSCHEIN -> "Lieferschein";
|
|
|
|
|
case RECHNUNG -> "Rechnung";
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static Color farbeFuerStatus(String status) {
|
|
|
|
|
return switch (status) {
|
|
|
|
|
case "OFFEN", "BESTAETIGT" -> new Color(41, 128, 185);
|
|
|
|
|
case "GELIEFERT" -> new Color(39, 174, 96);
|
|
|
|
|
case "FESTGESCHRIEBEN" -> new Color(155, 89, 182);
|
|
|
|
|
case "UEBERFUEHRT", "FAKTURIERT" -> new Color(127, 140, 141);
|
|
|
|
|
default -> Color.BLACK;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static String formatProzent(BigDecimal mwstSatz) {
|
|
|
|
|
if (mwstSatz == null) return "";
|
|
|
|
|
return mwstSatz.multiply(BigDecimal.valueOf(100)) + " %";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private JTextField createReadOnlyField() {
|
|
|
|
|
JTextField f = new JTextField();
|
|
|
|
|
f.setEditable(false);
|
|
|
|
|
f.setBackground(new Color(230, 230, 230));
|
|
|
|
|
return f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// =========================================================================
|
|
|
|
|
// Adapter / Wrapper – GUI-intern, keine Eingriffe in fremde Module
|
|
|
|
|
// =========================================================================
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Adapter K3 (PH v1.1 Kap. 6.2): Bedient die von Gruppe F geforderte
|
|
|
|
|
* {@link CustomerLookup}-Schnittstelle über das spec-konforme
|
|
|
|
|
* {@link KundeService} der Kundenverwaltung.
|
|
|
|
|
*/
|
|
|
|
|
private static final class KundeCustomerLookup implements CustomerLookup {
|
|
|
|
|
private final KundeService kundeService;
|
|
|
|
|
KundeCustomerLookup(KundeService kundeService) {
|
|
|
|
|
this.kundeService = kundeService;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Optional<CustomerDto> findCustomer(long kundenId) {
|
|
|
|
|
return kundeService.finde(kundenId).map(this::toDto);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private CustomerDto toDto(Kunde k) {
|
|
|
|
|
String name;
|
|
|
|
|
if (k.getFirmenname() != null && !k.getFirmenname().isBlank()) {
|
|
|
|
|
name = k.getFirmenname();
|
|
|
|
|
} else {
|
|
|
|
|
String n = k.getNachname() == null ? "" : k.getNachname();
|
|
|
|
|
name = (k.getVorname() == null || k.getVorname().isBlank())
|
|
|
|
|
? n : (k.getVorname() + " " + n);
|
|
|
|
|
}
|
|
|
|
|
String anschrift = String.format("%s, %s %s",
|
|
|
|
|
nullAls(k.getStrasse()),
|
|
|
|
|
nullAls(k.getPlz()),
|
|
|
|
|
nullAls(k.getOrt()));
|
|
|
|
|
return new CustomerDto(k.getKundeId(), name, anschrift, nullAls(k.getUstIdNr()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static String nullAls(String s) { return s == null ? "" : s; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Decorator über {@link DokumentRepository}: trackt zusätzlich alle
|
|
|
|
|
* gespeicherten Dokumente, damit das Panel eine vollständige Liste
|
|
|
|
|
* anzeigen kann. {@code findByNummer/findByKunde/...} werden an das
|
|
|
|
|
* gekapselte Repository delegiert.
|
|
|
|
|
*
|
|
|
|
|
* Notwendig, weil das Schnittstellen-Interface kein {@code findAll()}
|
|
|
|
|
* vorsieht (Gruppe F PH v1.0 Kap. 6.2) – ein Tracking in der GUI ist
|
|
|
|
|
* spec-neutral und greift nicht in Gruppe F's Modul ein.
|
|
|
|
|
*/
|
|
|
|
|
private static final class TrackingDokumentRepository implements DokumentRepository {
|
|
|
|
|
private final DokumentRepository delegate;
|
|
|
|
|
private final List<Dokument> alle = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
TrackingDokumentRepository(DokumentRepository delegate) {
|
|
|
|
|
this.delegate = delegate;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<Dokument> findAll() {
|
|
|
|
|
List<Dokument> kopie = new ArrayList<>(alle);
|
|
|
|
|
kopie.sort(Comparator
|
|
|
|
|
.comparing(Dokument::getDatum, Comparator.nullsLast(Comparator.naturalOrder()))
|
|
|
|
|
.thenComparing(Dokument::getDokumentNummer));
|
|
|
|
|
return Collections.unmodifiableList(kopie);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void save(Dokument dokument) {
|
|
|
|
|
delegate.save(dokument);
|
|
|
|
|
if (!alle.contains(dokument)) {
|
|
|
|
|
alle.add(dokument);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override public Optional<Dokument> findByNummer(String nummer) { return delegate.findByNummer(nummer); }
|
|
|
|
|
@Override public List<Dokument> findByKunde(long kundenId) { return delegate.findByKunde(kundenId); }
|
|
|
|
|
@Override public boolean existsFolgedokument(String quellDokumentNr) { return delegate.existsFolgedokument(quellDokumentNr); }
|
|
|
|
|
@Override public boolean existsReferencedProdukt(long produktId) { return delegate.existsReferencedProdukt(produktId); }
|
|
|
|
|
@Override public boolean existsReferencedKunde(long kundenId) { return delegate.existsReferencedKunde(kundenId); }
|
|
|
|
|
@Override public int findMaxLaufendeNummer(String praefix, int j) { return delegate.findMaxLaufendeNummer(praefix, j); }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|