Erweiterungen
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
package de.assecutor.votianlt.model;
|
||||
package de.assecutor.votianlt.model.invoices;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
@@ -9,7 +9,7 @@ import java.time.LocalDate;
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Invoice {
|
||||
public class SystemInvoice {
|
||||
private String id;
|
||||
private String kunde;
|
||||
private LocalDate datum;
|
||||
@@ -1,8 +1,8 @@
|
||||
package de.assecutor.votianlt.model;
|
||||
package de.assecutor.votianlt.model.invoices;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class InvoiceData {
|
||||
public class SystemInvoiceData {
|
||||
private String companyName = "Assecutor";
|
||||
private String companySubtitle = "Data Service GmbH";
|
||||
private String companyStreet = "Gerhart-Hauptmann-Weg 14";
|
||||
@@ -22,7 +22,7 @@ public class InvoiceData {
|
||||
private String recipientStreet;
|
||||
private String recipientCity;
|
||||
|
||||
private List<InvoiceItem> invoiceItems;
|
||||
private List<SystemInvoiceItem> systemInvoiceItems;
|
||||
private String netAmount;
|
||||
private String vatRate = "19";
|
||||
private String vatAmount;
|
||||
@@ -34,7 +34,7 @@ public class InvoiceData {
|
||||
"Steuernummer: 22 294 53099 · USt-IdNr.: DE261094748 · Sitz: Geesthacht · Handelsregister: Lübeck HRB 8595<br>" +
|
||||
"Bankverbindung: Hamburger Sparkasse · IBAN DE67200505501217139888 · BIC HASPDEHHXXX";
|
||||
|
||||
public InvoiceData() {
|
||||
public SystemInvoiceData() {
|
||||
}
|
||||
|
||||
public String getCompanyName() { return companyName; }
|
||||
@@ -85,8 +85,8 @@ public class InvoiceData {
|
||||
public String getRecipientCity() { return recipientCity; }
|
||||
public void setRecipientCity(String recipientCity) { this.recipientCity = recipientCity; }
|
||||
|
||||
public List<InvoiceItem> getInvoiceItems() { return invoiceItems; }
|
||||
public void setInvoiceItems(List<InvoiceItem> invoiceItems) { this.invoiceItems = invoiceItems; }
|
||||
public List<SystemInvoiceItem> getInvoiceItems() { return systemInvoiceItems; }
|
||||
public void setInvoiceItems(List<SystemInvoiceItem> systemInvoiceItems) { this.systemInvoiceItems = systemInvoiceItems; }
|
||||
|
||||
public String getNetAmount() { return netAmount; }
|
||||
public void setNetAmount(String netAmount) { this.netAmount = netAmount; }
|
||||
@@ -1,15 +1,15 @@
|
||||
package de.assecutor.votianlt.model;
|
||||
package de.assecutor.votianlt.model.invoices;
|
||||
|
||||
public class InvoiceItem {
|
||||
public class SystemInvoiceItem {
|
||||
private String quantity;
|
||||
private String description;
|
||||
private String unitPrice;
|
||||
private String totalPrice;
|
||||
|
||||
public InvoiceItem() {
|
||||
public SystemInvoiceItem() {
|
||||
}
|
||||
|
||||
public InvoiceItem(String quantity, String description, String unitPrice, String totalPrice) {
|
||||
public SystemInvoiceItem(String quantity, String description, String unitPrice, String totalPrice) {
|
||||
this.quantity = quantity;
|
||||
this.description = description;
|
||||
this.unitPrice = unitPrice;
|
||||
@@ -8,8 +8,7 @@ import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.component.UI;
|
||||
import de.assecutor.votianlt.model.Invoice;
|
||||
import de.assecutor.votianlt.service.PdfBoxService;
|
||||
import de.assecutor.votianlt.model.invoices.SystemInvoice;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -19,7 +18,6 @@ import java.util.List;
|
||||
|
||||
import com.vaadin.flow.server.StreamResource;
|
||||
import com.vaadin.flow.server.StreamRegistration;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@PageTitle("Rechnungen")
|
||||
@Route(value = "invoices", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class)
|
||||
@@ -27,7 +25,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
public class InvoicesView extends VerticalLayout {
|
||||
|
||||
|
||||
private final Grid<Invoice> invoiceGrid;
|
||||
private final Grid<SystemInvoice> invoiceGrid;
|
||||
|
||||
public InvoicesView() {
|
||||
setSizeFull();
|
||||
@@ -39,39 +37,39 @@ public class InvoicesView extends VerticalLayout {
|
||||
H2 title = new H2("Rechnungen");
|
||||
add(title);
|
||||
|
||||
invoiceGrid = new Grid<>(Invoice.class, false);
|
||||
invoiceGrid.addColumn(Invoice::getId).setHeader("Rechnungsnummer").setAutoWidth(true);
|
||||
invoiceGrid.addColumn(Invoice::getKunde).setHeader("Kunde").setAutoWidth(true);
|
||||
invoiceGrid.addColumn(Invoice::getDatum).setHeader("Datum").setAutoWidth(true);
|
||||
invoiceGrid.addColumn(Invoice::getBetrag).setHeader("Betrag").setAutoWidth(true);
|
||||
invoiceGrid.addColumn(Invoice::getBeschreibung).setHeader("Beschreibung").setAutoWidth(true);
|
||||
invoiceGrid = new Grid<>(SystemInvoice.class, false);
|
||||
invoiceGrid.addColumn(SystemInvoice::getId).setHeader("Rechnungsnummer").setAutoWidth(true);
|
||||
invoiceGrid.addColumn(SystemInvoice::getKunde).setHeader("Kunde").setAutoWidth(true);
|
||||
invoiceGrid.addColumn(SystemInvoice::getDatum).setHeader("Datum").setAutoWidth(true);
|
||||
invoiceGrid.addColumn(SystemInvoice::getBetrag).setHeader("Betrag").setAutoWidth(true);
|
||||
invoiceGrid.addColumn(SystemInvoice::getBeschreibung).setHeader("Beschreibung").setAutoWidth(true);
|
||||
invoiceGrid.setSelectionMode(Grid.SelectionMode.SINGLE);
|
||||
invoiceGrid.getStyle().set("cursor", "pointer");
|
||||
|
||||
// Testdaten
|
||||
List<Invoice> testInvoices = List.of(
|
||||
new Invoice("R-2024-001", "Max Mustermann", LocalDate.now().minusDays(2), 199.99,
|
||||
List<SystemInvoice> testSystemInvoices = List.of(
|
||||
new SystemInvoice("R-2024-001", "Max Mustermann", LocalDate.now().minusDays(2), 199.99,
|
||||
"Transport Hamburg-Berlin"),
|
||||
new Invoice("R-2024-002", "Erika Musterfrau", LocalDate.now().minusDays(1), 299.49,
|
||||
new SystemInvoice("R-2024-002", "Erika Musterfrau", LocalDate.now().minusDays(1), 299.49,
|
||||
"Express München-Köln"),
|
||||
new Invoice("R-2024-003", "Hans Beispiel", LocalDate.now(), 149.00, "Standard Leipzig-Dresden"));
|
||||
invoiceGrid.setItems(testInvoices);
|
||||
new SystemInvoice("R-2024-003", "Hans Beispiel", LocalDate.now(), 149.00, "Standard Leipzig-Dresden"));
|
||||
invoiceGrid.setItems(testSystemInvoices);
|
||||
|
||||
invoiceGrid.addItemClickListener(event -> {
|
||||
Invoice invoice = event.getItem();
|
||||
if (invoice != null) {
|
||||
downloadInvoicePdf(invoice);
|
||||
SystemInvoice systemInvoice = event.getItem();
|
||||
if (systemInvoice != null) {
|
||||
downloadInvoicePdf(systemInvoice);
|
||||
}
|
||||
});
|
||||
|
||||
add(invoiceGrid);
|
||||
}
|
||||
|
||||
private void downloadInvoicePdf(Invoice invoice) {
|
||||
private void downloadInvoicePdf(SystemInvoice systemInvoice) {
|
||||
try {
|
||||
// PDF generieren
|
||||
byte[] pdfBytes = generatePdf(invoice);
|
||||
StreamResource resource = new StreamResource(invoice.getId() + ".pdf",
|
||||
byte[] pdfBytes = generatePdf(systemInvoice);
|
||||
StreamResource resource = new StreamResource(systemInvoice.getId() + ".pdf",
|
||||
() -> new ByteArrayInputStream(pdfBytes));
|
||||
resource.setContentType("application/pdf");
|
||||
resource.setCacheTime(0);
|
||||
@@ -86,17 +84,17 @@ public class InvoicesView extends VerticalLayout {
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] generatePdf(Invoice invoice) {
|
||||
private byte[] generatePdf(SystemInvoice systemInvoice) {
|
||||
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
|
||||
// Einfache PDF mit iText (oder OpenPDF, falls iText nicht verfügbar)
|
||||
com.lowagie.text.Document document = new com.lowagie.text.Document();
|
||||
com.lowagie.text.pdf.PdfWriter.getInstance(document, out);
|
||||
document.open();
|
||||
document.add(new com.lowagie.text.Paragraph("Rechnung: " + invoice.getId()));
|
||||
document.add(new com.lowagie.text.Paragraph("Kunde: " + invoice.getKunde()));
|
||||
document.add(new com.lowagie.text.Paragraph("Datum: " + invoice.getDatum()));
|
||||
document.add(new com.lowagie.text.Paragraph("Betrag: " + invoice.getBetrag() + " EUR"));
|
||||
document.add(new com.lowagie.text.Paragraph("Beschreibung: " + invoice.getBeschreibung()));
|
||||
document.add(new com.lowagie.text.Paragraph("Rechnung: " + systemInvoice.getId()));
|
||||
document.add(new com.lowagie.text.Paragraph("Kunde: " + systemInvoice.getKunde()));
|
||||
document.add(new com.lowagie.text.Paragraph("Datum: " + systemInvoice.getDatum()));
|
||||
document.add(new com.lowagie.text.Paragraph("Betrag: " + systemInvoice.getBetrag() + " EUR"));
|
||||
document.add(new com.lowagie.text.Paragraph("Beschreibung: " + systemInvoice.getBeschreibung()));
|
||||
document.close();
|
||||
return out.toByteArray();
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -7,9 +7,9 @@ import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.server.StreamResource;
|
||||
import de.assecutor.votianlt.model.InvoiceData;
|
||||
import de.assecutor.votianlt.model.invoices.SystemInvoiceData;
|
||||
import de.assecutor.votianlt.pages.base.ui.view.AdminLayout;
|
||||
import de.assecutor.votianlt.service.PdfBoxService;
|
||||
import de.assecutor.votianlt.service.SystemInvoiceService;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -18,10 +18,10 @@ import java.io.ByteArrayInputStream;
|
||||
@PageTitle("PDF Test")
|
||||
@RolesAllowed("ADMIN")
|
||||
public class PdfTestView extends VerticalLayout {
|
||||
private final PdfBoxService pdfBoxService;
|
||||
private final SystemInvoiceService systemInvoiceService;
|
||||
|
||||
public PdfTestView(PdfBoxService pdfBoxService) {
|
||||
this.pdfBoxService = pdfBoxService;
|
||||
public PdfTestView(SystemInvoiceService systemInvoiceService) {
|
||||
this.systemInvoiceService = systemInvoiceService;
|
||||
|
||||
setSpacing(false);
|
||||
setPadding(false);
|
||||
@@ -39,8 +39,8 @@ public class PdfTestView extends VerticalLayout {
|
||||
|
||||
private void generateTestPdf() {
|
||||
try {
|
||||
InvoiceData sampleData = pdfBoxService.createSampleInvoiceData();
|
||||
byte[] pdfBytes = pdfBoxService.generateInvoicePdf(sampleData);
|
||||
SystemInvoiceData sampleData = systemInvoiceService.createSampleInvoiceData();
|
||||
byte[] pdfBytes = systemInvoiceService.generateInvoicePdf(sampleData);
|
||||
|
||||
StreamResource resource = new StreamResource("test-rechnung.pdf",
|
||||
() -> new ByteArrayInputStream(pdfBytes));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package de.assecutor.votianlt.service;
|
||||
|
||||
import de.assecutor.votianlt.model.InvoiceData;
|
||||
import de.assecutor.votianlt.model.InvoiceItem;
|
||||
import de.assecutor.votianlt.model.invoices.SystemInvoiceData;
|
||||
import de.assecutor.votianlt.model.invoices.SystemInvoiceItem;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||
@@ -16,7 +16,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class PdfBoxService {
|
||||
public class SystemInvoiceService {
|
||||
|
||||
private static final float MARGIN = 50;
|
||||
private static final float FONT_SIZE = 12;
|
||||
@@ -24,7 +24,7 @@ public class PdfBoxService {
|
||||
private static final float SUBTITLE_FONT_SIZE = 16;
|
||||
private static final float LINE_HEIGHT = 15;
|
||||
|
||||
public byte[] generateInvoicePdf(InvoiceData invoiceData) throws IOException {
|
||||
public byte[] generateInvoicePdf(SystemInvoiceData systemInvoiceData) throws IOException {
|
||||
try (PDDocument document = new PDDocument();
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
|
||||
|
||||
@@ -35,30 +35,30 @@ public class PdfBoxService {
|
||||
float yPosition = page.getMediaBox().getHeight() - MARGIN;
|
||||
|
||||
// Draw header
|
||||
yPosition = drawHeader(contentStream, yPosition, invoiceData);
|
||||
yPosition = drawHeader(contentStream, yPosition, systemInvoiceData);
|
||||
yPosition -= 30;
|
||||
|
||||
// Draw company and recipient info
|
||||
yPosition = drawAddresses(contentStream, yPosition, invoiceData);
|
||||
yPosition = drawAddresses(contentStream, yPosition, systemInvoiceData);
|
||||
yPosition -= 30;
|
||||
|
||||
// Draw invoice details
|
||||
yPosition = drawInvoiceDetails(contentStream, yPosition, invoiceData);
|
||||
yPosition = drawInvoiceDetails(contentStream, yPosition, systemInvoiceData);
|
||||
yPosition -= 30;
|
||||
|
||||
// Draw items table
|
||||
yPosition = drawItemsTable(contentStream, yPosition, invoiceData);
|
||||
yPosition = drawItemsTable(contentStream, yPosition, systemInvoiceData);
|
||||
yPosition -= 30;
|
||||
|
||||
// Draw totals
|
||||
yPosition = drawTotals(contentStream, yPosition, invoiceData);
|
||||
yPosition = drawTotals(contentStream, yPosition, systemInvoiceData);
|
||||
yPosition -= 30;
|
||||
|
||||
// Draw payment terms
|
||||
yPosition = drawPaymentTerms(contentStream, yPosition, invoiceData);
|
||||
yPosition = drawPaymentTerms(contentStream, yPosition, systemInvoiceData);
|
||||
|
||||
// Draw footer at bottom of page
|
||||
drawFooter(contentStream, page, invoiceData);
|
||||
drawFooter(contentStream, page, systemInvoiceData);
|
||||
}
|
||||
|
||||
document.save(outputStream);
|
||||
@@ -66,7 +66,7 @@ public class PdfBoxService {
|
||||
}
|
||||
}
|
||||
|
||||
private float drawHeader(PDPageContentStream contentStream, float yPosition, InvoiceData data) throws IOException {
|
||||
private float drawHeader(PDPageContentStream contentStream, float yPosition, SystemInvoiceData data) throws IOException {
|
||||
// Company name
|
||||
contentStream.beginText();
|
||||
contentStream.setFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA_BOLD), TITLE_FONT_SIZE);
|
||||
@@ -97,7 +97,7 @@ public class PdfBoxService {
|
||||
return yPosition - 10;
|
||||
}
|
||||
|
||||
private float drawAddresses(PDPageContentStream contentStream, float yPosition, InvoiceData data) throws IOException {
|
||||
private float drawAddresses(PDPageContentStream contentStream, float yPosition, SystemInvoiceData data) throws IOException {
|
||||
contentStream.setNonStrokingColor(0f, 0f, 0f); // Black
|
||||
contentStream.setFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA), FONT_SIZE);
|
||||
|
||||
@@ -152,7 +152,7 @@ public class PdfBoxService {
|
||||
return Math.min(yPosition, rightYPosition) - 10;
|
||||
}
|
||||
|
||||
private float drawInvoiceDetails(PDPageContentStream contentStream, float yPosition, InvoiceData data) throws IOException {
|
||||
private float drawInvoiceDetails(PDPageContentStream contentStream, float yPosition, SystemInvoiceData data) throws IOException {
|
||||
|
||||
// Invoice title
|
||||
contentStream.beginText();
|
||||
@@ -194,7 +194,7 @@ public class PdfBoxService {
|
||||
return yPosition - 40;
|
||||
}
|
||||
|
||||
private float drawItemsTable(PDPageContentStream contentStream, float yPosition, InvoiceData data) throws IOException {
|
||||
private float drawItemsTable(PDPageContentStream contentStream, float yPosition, SystemInvoiceData data) throws IOException {
|
||||
float[] columnWidths = {60, 300, 100, 100}; // Menge, Bezeichnung, Einzelpreis, Gesamt
|
||||
float rowHeight = 20;
|
||||
|
||||
@@ -248,7 +248,7 @@ public class PdfBoxService {
|
||||
contentStream.setFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA), 10);
|
||||
|
||||
if (data.getInvoiceItems() != null) {
|
||||
for (InvoiceItem item : data.getInvoiceItems()) {
|
||||
for (SystemInvoiceItem item : data.getInvoiceItems()) {
|
||||
xOffset = MARGIN + 5;
|
||||
|
||||
contentStream.beginText();
|
||||
@@ -286,7 +286,7 @@ public class PdfBoxService {
|
||||
return yPosition;
|
||||
}
|
||||
|
||||
private float drawTotals(PDPageContentStream contentStream, float yPosition, InvoiceData data) throws IOException {
|
||||
private float drawTotals(PDPageContentStream contentStream, float yPosition, SystemInvoiceData data) throws IOException {
|
||||
float rightColumn = 400;
|
||||
|
||||
contentStream.setFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA), FONT_SIZE);
|
||||
@@ -332,7 +332,7 @@ public class PdfBoxService {
|
||||
return yPosition - 30;
|
||||
}
|
||||
|
||||
private float drawPaymentTerms(PDPageContentStream contentStream, float yPosition, InvoiceData data) throws IOException {
|
||||
private float drawPaymentTerms(PDPageContentStream contentStream, float yPosition, SystemInvoiceData data) throws IOException {
|
||||
contentStream.setFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA), FONT_SIZE);
|
||||
|
||||
// Payment terms with text wrapping
|
||||
@@ -385,7 +385,7 @@ public class PdfBoxService {
|
||||
return text.length() * fontSize * 0.6f;
|
||||
}
|
||||
|
||||
private void drawFooter(PDPageContentStream contentStream, PDPage page, InvoiceData data) throws IOException {
|
||||
private void drawFooter(PDPageContentStream contentStream, PDPage page, SystemInvoiceData data) throws IOException {
|
||||
contentStream.setFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA), 8);
|
||||
|
||||
// Footer text (company details) - positioned at absolute bottom
|
||||
@@ -410,8 +410,8 @@ public class PdfBoxService {
|
||||
}
|
||||
}
|
||||
|
||||
public InvoiceData createSampleInvoiceData() {
|
||||
InvoiceData data = new InvoiceData();
|
||||
public SystemInvoiceData createSampleInvoiceData() {
|
||||
SystemInvoiceData data = new SystemInvoiceData();
|
||||
data.setInvoiceNumber("HHA-2021-007");
|
||||
data.setInvoiceDate("19.07.2021");
|
||||
data.setInvoiceText("Gemäß unserem Nutzungsvertrag zu der Bestellnummer 45519389 berechnen wir Ihnen für den Monat Juli 2021 wie folgt:");
|
||||
@@ -421,8 +421,8 @@ public class PdfBoxService {
|
||||
data.setRecipientStreet("Steinstraße 20");
|
||||
data.setRecipientCity("20095 Hamburg");
|
||||
|
||||
List<InvoiceItem> items = new ArrayList<>();
|
||||
items.add(new InvoiceItem("1", "Mtl. Lizenzgebühr »ILLT«", "5.639,00 €", "5.639,00 €"));
|
||||
List<SystemInvoiceItem> items = new ArrayList<>();
|
||||
items.add(new SystemInvoiceItem("1", "Mtl. Lizenzgebühr »ILLT«", "5.639,00 €", "5.639,00 €"));
|
||||
data.setInvoiceItems(items);
|
||||
|
||||
data.setNetAmount("5.639,00 €");
|
||||
Reference in New Issue
Block a user