Erweiterungen

This commit is contained in:
2025-09-22 09:41:15 +02:00
parent 431c99143b
commit 57066e22c3
2 changed files with 93 additions and 24 deletions

View File

@@ -9,11 +9,16 @@ import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route; import com.vaadin.flow.router.Route;
import com.vaadin.flow.component.UI; import com.vaadin.flow.component.UI;
import de.assecutor.votianlt.model.invoices.SystemInvoice; import de.assecutor.votianlt.model.invoices.SystemInvoice;
import de.assecutor.votianlt.model.invoices.CustomerInvoiceData;
import de.assecutor.votianlt.model.invoices.CustomerInvoiceItem;
import de.assecutor.votianlt.security.SecurityService;
import de.assecutor.votianlt.service.CustomerInvoiceService;
import jakarta.annotation.security.RolesAllowed; import jakarta.annotation.security.RolesAllowed;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.math.BigDecimal;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.vaadin.flow.server.StreamResource; import com.vaadin.flow.server.StreamResource;
@@ -24,10 +29,15 @@ import com.vaadin.flow.server.StreamRegistration;
@RolesAllowed({ "USER", "ADMIN" }) @RolesAllowed({ "USER", "ADMIN" })
public class InvoicesView extends VerticalLayout { public class InvoicesView extends VerticalLayout {
private final Grid<SystemInvoice> invoiceGrid; private final Grid<SystemInvoice> invoiceGrid;
public InvoicesView() { private final CustomerInvoiceService customerInvoiceService;
private final SecurityService securityService;
public InvoicesView(CustomerInvoiceService customerInvoiceService, SecurityService securityService) {
this.customerInvoiceService = customerInvoiceService;
this.securityService = securityService;
setSizeFull(); setSizeFull();
setPadding(true); setPadding(true);
setSpacing(true); setSpacing(true);
@@ -67,8 +77,8 @@ public class InvoicesView extends VerticalLayout {
private void downloadInvoicePdf(SystemInvoice systemInvoice) { private void downloadInvoicePdf(SystemInvoice systemInvoice) {
try { try {
// PDF generieren // PDF generieren mit CustomerInvoice (HTML Template)
byte[] pdfBytes = generatePdf(systemInvoice); byte[] pdfBytes = generateCustomerInvoicePdf(systemInvoice);
StreamResource resource = new StreamResource(systemInvoice.getId() + ".pdf", StreamResource resource = new StreamResource(systemInvoice.getId() + ".pdf",
() -> new ByteArrayInputStream(pdfBytes)); () -> new ByteArrayInputStream(pdfBytes));
resource.setContentType("application/pdf"); resource.setContentType("application/pdf");
@@ -84,21 +94,72 @@ public class InvoicesView extends VerticalLayout {
} }
} }
private byte[] generatePdf(SystemInvoice systemInvoice) { private byte[] generateCustomerInvoicePdf(SystemInvoice systemInvoice) throws Exception {
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { // Aktuellen Benutzer als Rechnungssteller ermitteln
// Einfache PDF mit iText (oder OpenPDF, falls iText nicht verfügbar) de.assecutor.votianlt.model.User user = securityService.getCurrentDatabaseUser();
com.lowagie.text.Document document = new com.lowagie.text.Document();
com.lowagie.text.pdf.PdfWriter.getInstance(document, out); CustomerInvoiceData data = new CustomerInvoiceData();
document.open(); // Kopf
document.add(new com.lowagie.text.Paragraph("Rechnung: " + systemInvoice.getId())); data.setInvoiceNumber(systemInvoice.getId());
document.add(new com.lowagie.text.Paragraph("Kunde: " + systemInvoice.getKunde())); data.setInvoiceDate(systemInvoice.getDatum());
document.add(new com.lowagie.text.Paragraph("Datum: " + systemInvoice.getDatum())); data.setDeliveryDate(systemInvoice.getDatum());
document.add(new com.lowagie.text.Paragraph("Betrag: " + systemInvoice.getBetrag() + " EUR")); data.setDescription(systemInvoice.getBeschreibung());
document.add(new com.lowagie.text.Paragraph("Beschreibung: " + systemInvoice.getBeschreibung()));
document.close(); // Rechnungssteller = eingeloggter Benutzer
return out.toByteArray(); String senderName = (nullToEmpty(user.getFirstname()) + " " + nullToEmpty(user.getName())).trim();
} catch (Exception e) { if (senderName.isBlank() && user.getEmail() != null)
throw new RuntimeException("PDF-Generierung fehlgeschlagen: " + e.getMessage(), e); senderName = user.getEmail();
data.setSenderName(user.getCompany() != null && !user.getCompany().isBlank() ? user.getCompany() : senderName);
data.setSenderAddress((nullToEmpty(user.getStreet()) + " " + nullToEmpty(user.getHouseNumber())).trim());
data.setSenderPostcode(nullToEmpty(user.getZip()));
data.setSenderCity(nullToEmpty(user.getCity()));
data.setSenderCountry("Deutschland");
data.setSenderTaxNumber("");
data.setSenderVatId("");
data.setSenderPhone(nullToEmpty(user.getPhone()));
data.setSenderEmail(nullToEmpty(user.getEmail()));
data.setSenderWebsite("");
// Empfänger = Kunde aus der Zeile (nur Name vorhanden in Testdaten)
data.setRecipientCompany("");
data.setRecipientName(systemInvoice.getKunde());
data.setRecipientAddress("");
data.setRecipientPostcode("");
data.setRecipientCity("");
data.setRecipientCountry("Deutschland");
data.setRecipientVatId("");
// Positionen (eine einfache Position aus Betrag/Beschreibung)
List<CustomerInvoiceItem> items = new ArrayList<>();
BigDecimal vatRate = new BigDecimal("0.19");
BigDecimal unitPrice = BigDecimal.valueOf(systemInvoice.getBetrag());
items.add(new CustomerInvoiceItem(BigDecimal.ONE, "Stk.", systemInvoice.getBeschreibung(), unitPrice, vatRate));
data.setItems(items);
// Summen berechnen
BigDecimal netAmount = items.stream().map(CustomerInvoiceItem::getNetTotal).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal vatAmount = netAmount.multiply(vatRate);
BigDecimal totalAmount = netAmount.add(vatAmount);
data.setNetAmount(netAmount);
data.setVatRate(vatRate);
data.setVatAmount(vatAmount);
data.setTotalAmount(totalAmount);
// Zahlung
data.setPaymentTerms("Zahlbar innerhalb von 14 Tagen netto ohne Abzug.");
data.setPaymentDueDate(systemInvoice.getDatum().plusDays(14));
data.setBankAccount(data.getSenderName());
data.setIban("");
data.setBic("");
// Rechtliches
data.setLegalNotes("");
data.setReverseChargeNote("");
return customerInvoiceService.generateCustomerInvoicePdf(data);
} }
private String nullToEmpty(String s) {
return s == null ? "" : s;
} }
} }

View File

@@ -128,12 +128,20 @@ public class CustomerInvoiceService {
} }
public byte[] generateCustomerInvoicePdf() throws Exception { public byte[] generateCustomerInvoicePdf() throws Exception {
// Backward-compatible sample generation
CustomerInvoiceData sampleData = createCustomerInvoiceData("customerId", "jobId");
return generateCustomerInvoicePdf(sampleData);
}
/**
* Generate a Customer Invoice PDF from provided data using the HTML template.
*/
public byte[] generateCustomerInvoicePdf(CustomerInvoiceData data) throws Exception {
// Read the HTML template // Read the HTML template
String htmlContent = readCustomerInvoiceHtmlTemplate(); String htmlContent = readCustomerInvoiceHtmlTemplate();
// Fill HTML with sample data // Fill HTML with provided data
CustomerInvoiceData sampleData = createCustomerInvoiceData("customerId", "jobId"); String filledHtml = fillCustomerInvoiceHtmlWithInvoiceData(htmlContent, data);
String filledHtml = fillCustomerInvoiceHtmlWithInvoiceData(htmlContent, sampleData);
// Generate PDF from HTML // Generate PDF from HTML
return generatePdfFromHtmlString(filledHtml); return generatePdfFromHtmlString(filledHtml);