diff --git a/src/main/java/de/assecutor/votianlt/pages/view/InvoicesView.java b/src/main/java/de/assecutor/votianlt/pages/view/InvoicesView.java index b0caf95..5fea7be 100644 --- a/src/main/java/de/assecutor/votianlt/pages/view/InvoicesView.java +++ b/src/main/java/de/assecutor/votianlt/pages/view/InvoicesView.java @@ -9,11 +9,16 @@ import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; import com.vaadin.flow.component.UI; 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 java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; +import java.math.BigDecimal; import java.time.LocalDate; +import java.util.ArrayList; import java.util.List; import com.vaadin.flow.server.StreamResource; @@ -24,10 +29,15 @@ import com.vaadin.flow.server.StreamRegistration; @RolesAllowed({ "USER", "ADMIN" }) public class InvoicesView extends VerticalLayout { - private final Grid invoiceGrid; - public InvoicesView() { + private final CustomerInvoiceService customerInvoiceService; + private final SecurityService securityService; + + public InvoicesView(CustomerInvoiceService customerInvoiceService, SecurityService securityService) { + this.customerInvoiceService = customerInvoiceService; + this.securityService = securityService; + setSizeFull(); setPadding(true); setSpacing(true); @@ -67,8 +77,8 @@ public class InvoicesView extends VerticalLayout { private void downloadInvoicePdf(SystemInvoice systemInvoice) { try { - // PDF generieren - byte[] pdfBytes = generatePdf(systemInvoice); + // PDF generieren mit CustomerInvoice (HTML Template) + byte[] pdfBytes = generateCustomerInvoicePdf(systemInvoice); StreamResource resource = new StreamResource(systemInvoice.getId() + ".pdf", () -> new ByteArrayInputStream(pdfBytes)); resource.setContentType("application/pdf"); @@ -84,21 +94,72 @@ public class InvoicesView extends VerticalLayout { } } - 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: " + 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) { - throw new RuntimeException("PDF-Generierung fehlgeschlagen: " + e.getMessage(), e); - } + private byte[] generateCustomerInvoicePdf(SystemInvoice systemInvoice) throws Exception { + // Aktuellen Benutzer als Rechnungssteller ermitteln + de.assecutor.votianlt.model.User user = securityService.getCurrentDatabaseUser(); + + CustomerInvoiceData data = new CustomerInvoiceData(); + // Kopf + data.setInvoiceNumber(systemInvoice.getId()); + data.setInvoiceDate(systemInvoice.getDatum()); + data.setDeliveryDate(systemInvoice.getDatum()); + data.setDescription(systemInvoice.getBeschreibung()); + + // Rechnungssteller = eingeloggter Benutzer + String senderName = (nullToEmpty(user.getFirstname()) + " " + nullToEmpty(user.getName())).trim(); + if (senderName.isBlank() && user.getEmail() != null) + 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 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; } } diff --git a/src/main/java/de/assecutor/votianlt/service/CustomerInvoiceService.java b/src/main/java/de/assecutor/votianlt/service/CustomerInvoiceService.java index ba3a95c..156e15d 100644 --- a/src/main/java/de/assecutor/votianlt/service/CustomerInvoiceService.java +++ b/src/main/java/de/assecutor/votianlt/service/CustomerInvoiceService.java @@ -128,12 +128,20 @@ public class CustomerInvoiceService { } 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 String htmlContent = readCustomerInvoiceHtmlTemplate(); - // Fill HTML with sample data - CustomerInvoiceData sampleData = createCustomerInvoiceData("customerId", "jobId"); - String filledHtml = fillCustomerInvoiceHtmlWithInvoiceData(htmlContent, sampleData); + // Fill HTML with provided data + String filledHtml = fillCustomerInvoiceHtmlWithInvoiceData(htmlContent, data); // Generate PDF from HTML return generatePdfFromHtmlString(filledHtml);