Erweiterungen
This commit is contained in:
7
pom.xml
7
pom.xml
@@ -116,12 +116,7 @@
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Apache PDFBox for PDF generation -->
|
||||
<dependency>
|
||||
<groupId>org.apache.pdfbox</groupId>
|
||||
<artifactId>pdfbox</artifactId>
|
||||
<version>3.0.3</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- iText8 for PDF generation -->
|
||||
<dependency>
|
||||
|
||||
@@ -2,418 +2,38 @@ package de.assecutor.votianlt.service;
|
||||
|
||||
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;
|
||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||
import org.apache.pdfbox.pdmodel.font.PDType1Font;
|
||||
import org.apache.pdfbox.pdmodel.font.Standard14Fonts;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.itextpdf.html2pdf.HtmlConverter;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class SystemInvoiceService {
|
||||
|
||||
private static final float MARGIN = 50;
|
||||
private static final float FONT_SIZE = 12;
|
||||
private static final float TITLE_FONT_SIZE = 24;
|
||||
private static final float SUBTITLE_FONT_SIZE = 16;
|
||||
private static final float LINE_HEIGHT = 15;
|
||||
|
||||
public byte[] generateInvoicePdf(SystemInvoiceData systemInvoiceData) throws IOException {
|
||||
try (PDDocument document = new PDDocument();
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
|
||||
|
||||
PDPage page = new PDPage(PDRectangle.A4);
|
||||
document.addPage(page);
|
||||
|
||||
try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
|
||||
float yPosition = page.getMediaBox().getHeight() - MARGIN;
|
||||
|
||||
// Draw header
|
||||
yPosition = drawHeader(contentStream, yPosition, systemInvoiceData);
|
||||
yPosition -= 30;
|
||||
|
||||
// Draw company and recipient info
|
||||
yPosition = drawAddresses(contentStream, yPosition, systemInvoiceData);
|
||||
yPosition -= 30;
|
||||
|
||||
// Draw invoice details
|
||||
yPosition = drawInvoiceDetails(contentStream, yPosition, systemInvoiceData);
|
||||
yPosition -= 30;
|
||||
|
||||
// Draw items table
|
||||
yPosition = drawItemsTable(contentStream, yPosition, systemInvoiceData);
|
||||
yPosition -= 30;
|
||||
|
||||
// Draw totals
|
||||
yPosition = drawTotals(contentStream, yPosition, systemInvoiceData);
|
||||
yPosition -= 30;
|
||||
|
||||
// Draw payment terms
|
||||
yPosition = drawPaymentTerms(contentStream, yPosition, systemInvoiceData);
|
||||
|
||||
// Draw footer at bottom of page
|
||||
drawFooter(contentStream, page, systemInvoiceData);
|
||||
}
|
||||
|
||||
document.save(outputStream);
|
||||
return outputStream.toByteArray();
|
||||
}
|
||||
public byte[] generateInvoicePdf(SystemInvoiceData systemInvoiceData) throws Exception {
|
||||
// Generate PDF using HTML to PDF conversion
|
||||
return generateInvoicePdfFromHtml();
|
||||
}
|
||||
|
||||
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);
|
||||
contentStream.setNonStrokingColor(27/255f, 18/255f, 185/255f); // Blue color (RGB values normalized to 0-1)
|
||||
contentStream.newLineAtOffset(MARGIN, yPosition);
|
||||
contentStream.showText(data.getCompanyName() != null ? data.getCompanyName() : "");
|
||||
contentStream.endText();
|
||||
public byte[] generateInvoicePdfFromHtml() throws Exception {
|
||||
// Read the HTML template
|
||||
String htmlContent = readHtmlTemplate();
|
||||
|
||||
yPosition -= 30;
|
||||
// Fill HTML with sample data
|
||||
SystemInvoiceData sampleData = createSampleInvoiceData();
|
||||
String filledHtml = fillHtmlWithInvoiceData(htmlContent, sampleData);
|
||||
|
||||
// Company subtitle
|
||||
contentStream.beginText();
|
||||
contentStream.setFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA_BOLD), FONT_SIZE);
|
||||
contentStream.setNonStrokingColor(27/255f, 18/255f, 185/255f);
|
||||
contentStream.newLineAtOffset(MARGIN, yPosition);
|
||||
contentStream.showText(data.getCompanySubtitle() != null ? data.getCompanySubtitle() : "");
|
||||
contentStream.endText();
|
||||
|
||||
yPosition -= 20;
|
||||
|
||||
// Draw line
|
||||
contentStream.setStrokingColor(27/255f, 18/255f, 185/255f);
|
||||
contentStream.setLineWidth(2);
|
||||
contentStream.moveTo(MARGIN, yPosition);
|
||||
contentStream.lineTo(PDRectangle.A4.getWidth() - MARGIN, yPosition);
|
||||
contentStream.stroke();
|
||||
|
||||
return yPosition - 10;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
float leftColumn = MARGIN;
|
||||
float rightColumn = 350;
|
||||
|
||||
// Sender line
|
||||
contentStream.beginText();
|
||||
contentStream.setFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA), 8);
|
||||
contentStream.newLineAtOffset(leftColumn, yPosition);
|
||||
contentStream.showText(data.getSenderLine() != null ? data.getSenderLine() : "");
|
||||
contentStream.endText();
|
||||
|
||||
yPosition -= 20;
|
||||
float recipientStartY = yPosition; // Store starting position for date alignment
|
||||
|
||||
// Recipient address
|
||||
String[] recipientLines = {
|
||||
data.getRecipientName(),
|
||||
data.getRecipientDepartment(),
|
||||
data.getRecipientStreet(),
|
||||
data.getRecipientCity()
|
||||
};
|
||||
|
||||
contentStream.setFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA), FONT_SIZE);
|
||||
for (String line : recipientLines) {
|
||||
if (line != null && !line.trim().isEmpty()) {
|
||||
contentStream.beginText();
|
||||
contentStream.newLineAtOffset(leftColumn, yPosition);
|
||||
contentStream.showText(line);
|
||||
contentStream.endText();
|
||||
yPosition -= LINE_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
// Date (right aligned, same vertical level as recipient)
|
||||
float dateColumn = 450; // Move further to the right
|
||||
contentStream.beginText();
|
||||
contentStream.setFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA), FONT_SIZE);
|
||||
contentStream.newLineAtOffset(dateColumn, recipientStartY);
|
||||
contentStream.showText("Datum");
|
||||
contentStream.endText();
|
||||
|
||||
contentStream.beginText();
|
||||
contentStream.newLineAtOffset(dateColumn, recipientStartY - LINE_HEIGHT);
|
||||
contentStream.showText(data.getInvoiceDate() != null ? data.getInvoiceDate() : "");
|
||||
contentStream.endText();
|
||||
|
||||
// Company address (right side)
|
||||
float rightYPosition = yPosition + (recipientLines.length * LINE_HEIGHT);
|
||||
|
||||
return Math.min(yPosition, rightYPosition) - 10;
|
||||
}
|
||||
|
||||
private float drawInvoiceDetails(PDPageContentStream contentStream, float yPosition, SystemInvoiceData data) throws IOException {
|
||||
|
||||
// Invoice title
|
||||
contentStream.beginText();
|
||||
contentStream.setFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA_BOLD), SUBTITLE_FONT_SIZE);
|
||||
contentStream.newLineAtOffset(MARGIN, yPosition);
|
||||
contentStream.showText("Rechnung " + (data.getInvoiceNumber() != null ? data.getInvoiceNumber() : ""));
|
||||
contentStream.endText();
|
||||
|
||||
yPosition -= 30;
|
||||
|
||||
// Invoice text
|
||||
contentStream.beginText();
|
||||
contentStream.setFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA), FONT_SIZE);
|
||||
contentStream.newLineAtOffset(MARGIN, yPosition);
|
||||
|
||||
// Split long text into multiple lines
|
||||
String invoiceText = data.getInvoiceText();
|
||||
if (invoiceText != null && invoiceText.length() > 80) {
|
||||
String[] words = invoiceText.split(" ");
|
||||
StringBuilder currentLine = new StringBuilder();
|
||||
for (String word : words) {
|
||||
if (currentLine.length() + word.length() + 1 > 80) {
|
||||
contentStream.showText(currentLine.toString());
|
||||
contentStream.newLineAtOffset(0, -LINE_HEIGHT);
|
||||
currentLine = new StringBuilder(word);
|
||||
} else {
|
||||
if (currentLine.length() > 0) currentLine.append(" ");
|
||||
currentLine.append(word);
|
||||
}
|
||||
}
|
||||
if (currentLine.length() > 0) {
|
||||
contentStream.showText(currentLine.toString());
|
||||
}
|
||||
} else {
|
||||
contentStream.showText(invoiceText != null ? invoiceText : "");
|
||||
}
|
||||
contentStream.endText();
|
||||
|
||||
return yPosition - 40;
|
||||
}
|
||||
|
||||
private float drawItemsTable(PDPageContentStream contentStream, float yPosition, SystemInvoiceData data) throws IOException {
|
||||
float[] columnWidths = {60, 300, 100, 100}; // Menge, Bezeichnung, Einzelpreis, Gesamt
|
||||
float rowHeight = 20;
|
||||
|
||||
// Calculate actual table width based on column widths
|
||||
float actualTableWidth = 0;
|
||||
for (float width : columnWidths) {
|
||||
actualTableWidth += width;
|
||||
}
|
||||
|
||||
// Add 2cm margin to the right of the gray header
|
||||
float rightMargin = 2 * 28.35f; // 2cm in points (1cm = 28.35pt)
|
||||
float headerWidth = actualTableWidth + rightMargin;
|
||||
|
||||
// Table header
|
||||
contentStream.setNonStrokingColor(230/255f, 230/255f, 230/255f); // Light gray background
|
||||
contentStream.addRect(MARGIN, yPosition - rowHeight, headerWidth, rowHeight);
|
||||
contentStream.fill();
|
||||
|
||||
contentStream.setNonStrokingColor(0f, 0f, 0f); // Black
|
||||
contentStream.setFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA_BOLD), 10);
|
||||
|
||||
String[] headers = {"Menge", "Bezeichnung", "Einzelpreis", "Gesamt"};
|
||||
float xOffset = MARGIN + 5;
|
||||
|
||||
contentStream.beginText();
|
||||
contentStream.newLineAtOffset(xOffset, yPosition - 15);
|
||||
contentStream.showText(headers[0]);
|
||||
contentStream.endText();
|
||||
|
||||
xOffset += columnWidths[0];
|
||||
contentStream.beginText();
|
||||
contentStream.newLineAtOffset(xOffset, yPosition - 15);
|
||||
contentStream.showText(headers[1]);
|
||||
contentStream.endText();
|
||||
|
||||
xOffset += columnWidths[1];
|
||||
contentStream.beginText();
|
||||
contentStream.newLineAtOffset(xOffset, yPosition - 15);
|
||||
contentStream.showText(headers[2]);
|
||||
contentStream.endText();
|
||||
|
||||
xOffset += columnWidths[2];
|
||||
contentStream.beginText();
|
||||
contentStream.newLineAtOffset(xOffset, yPosition - 15);
|
||||
contentStream.showText(headers[3]);
|
||||
contentStream.endText();
|
||||
|
||||
yPosition -= rowHeight;
|
||||
|
||||
// Table rows
|
||||
contentStream.setFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA), 10);
|
||||
|
||||
if (data.getInvoiceItems() != null) {
|
||||
for (SystemInvoiceItem item : data.getInvoiceItems()) {
|
||||
xOffset = MARGIN + 5;
|
||||
|
||||
contentStream.beginText();
|
||||
contentStream.newLineAtOffset(xOffset, yPosition - 15);
|
||||
contentStream.showText(item.getQuantity() != null ? item.getQuantity() : "");
|
||||
contentStream.endText();
|
||||
|
||||
xOffset += columnWidths[0];
|
||||
contentStream.beginText();
|
||||
contentStream.newLineAtOffset(xOffset, yPosition - 15);
|
||||
contentStream.showText(item.getDescription() != null ? item.getDescription() : "");
|
||||
contentStream.endText();
|
||||
|
||||
xOffset += columnWidths[1];
|
||||
contentStream.beginText();
|
||||
contentStream.newLineAtOffset(xOffset, yPosition - 15);
|
||||
contentStream.showText(item.getUnitPrice() != null ? item.getUnitPrice() : "");
|
||||
contentStream.endText();
|
||||
|
||||
xOffset += columnWidths[2];
|
||||
contentStream.beginText();
|
||||
contentStream.newLineAtOffset(xOffset, yPosition - 15);
|
||||
contentStream.showText(item.getTotalPrice() != null ? item.getTotalPrice() : "");
|
||||
contentStream.endText();
|
||||
|
||||
yPosition -= rowHeight;
|
||||
}
|
||||
}
|
||||
|
||||
// Add some empty rows for spacing
|
||||
for (int i = 0; i < 3; i++) {
|
||||
yPosition -= rowHeight;
|
||||
}
|
||||
|
||||
return yPosition;
|
||||
}
|
||||
|
||||
private float drawTotals(PDPageContentStream contentStream, float yPosition, SystemInvoiceData data) throws IOException {
|
||||
float rightColumn = 400;
|
||||
|
||||
contentStream.setFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA), FONT_SIZE);
|
||||
|
||||
// Net amount
|
||||
contentStream.beginText();
|
||||
contentStream.newLineAtOffset(rightColumn, yPosition);
|
||||
contentStream.showText("Nettobetrag:");
|
||||
contentStream.endText();
|
||||
|
||||
contentStream.beginText();
|
||||
contentStream.newLineAtOffset(rightColumn + 100, yPosition);
|
||||
contentStream.showText(data.getNetAmount() != null ? data.getNetAmount() : "");
|
||||
contentStream.endText();
|
||||
|
||||
yPosition -= LINE_HEIGHT;
|
||||
|
||||
// VAT
|
||||
contentStream.beginText();
|
||||
contentStream.newLineAtOffset(rightColumn, yPosition);
|
||||
contentStream.showText("+ " + (data.getVatRate() != null ? data.getVatRate() : "") + "% MwSt.:");
|
||||
contentStream.endText();
|
||||
|
||||
contentStream.beginText();
|
||||
contentStream.newLineAtOffset(rightColumn + 100, yPosition);
|
||||
contentStream.showText(data.getVatAmount() != null ? data.getVatAmount() : "");
|
||||
contentStream.endText();
|
||||
|
||||
yPosition -= LINE_HEIGHT;
|
||||
|
||||
// Total amount
|
||||
contentStream.setFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA_BOLD), FONT_SIZE);
|
||||
contentStream.beginText();
|
||||
contentStream.newLineAtOffset(rightColumn, yPosition);
|
||||
contentStream.showText("Endbetrag:");
|
||||
contentStream.endText();
|
||||
|
||||
contentStream.beginText();
|
||||
contentStream.newLineAtOffset(rightColumn + 100, yPosition);
|
||||
contentStream.showText(data.getTotalAmount() != null ? data.getTotalAmount() : "");
|
||||
contentStream.endText();
|
||||
|
||||
return yPosition - 30;
|
||||
}
|
||||
|
||||
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
|
||||
String paymentTerms = data.getPaymentTerms();
|
||||
if (paymentTerms != null && !paymentTerms.trim().isEmpty()) {
|
||||
float maxWidth = PDRectangle.A4.getWidth() - 2 * MARGIN;
|
||||
yPosition = drawWrappedText(contentStream, paymentTerms, MARGIN, yPosition, maxWidth, FONT_SIZE);
|
||||
}
|
||||
|
||||
return yPosition - 20;
|
||||
}
|
||||
|
||||
private float drawWrappedText(PDPageContentStream contentStream, String text, float x, float y, float maxWidth, float fontSize) throws IOException {
|
||||
String[] words = text.split(" ");
|
||||
StringBuilder currentLine = new StringBuilder();
|
||||
float currentY = y;
|
||||
|
||||
contentStream.beginText();
|
||||
contentStream.newLineAtOffset(x, currentY);
|
||||
|
||||
for (String word : words) {
|
||||
String testLine = currentLine.length() > 0 ? currentLine + " " + word : word;
|
||||
|
||||
// Estimate text width (rough calculation)
|
||||
float textWidth = estimateTextWidth(testLine, fontSize);
|
||||
|
||||
if (textWidth > maxWidth && currentLine.length() > 0) {
|
||||
// Print current line and start new line
|
||||
contentStream.showText(currentLine.toString());
|
||||
currentLine = new StringBuilder(word);
|
||||
currentY -= LINE_HEIGHT;
|
||||
contentStream.newLineAtOffset(0, -LINE_HEIGHT);
|
||||
} else {
|
||||
currentLine = new StringBuilder(testLine);
|
||||
}
|
||||
}
|
||||
|
||||
// Print remaining text
|
||||
if (currentLine.length() > 0) {
|
||||
contentStream.showText(currentLine.toString());
|
||||
currentY -= LINE_HEIGHT;
|
||||
}
|
||||
|
||||
contentStream.endText();
|
||||
return currentY;
|
||||
}
|
||||
|
||||
private float estimateTextWidth(String text, float fontSize) {
|
||||
// Rough estimation: average character width is about 0.6 * font size
|
||||
return text.length() * fontSize * 0.6f;
|
||||
}
|
||||
|
||||
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
|
||||
String footerText = data.getFooterText();
|
||||
if (footerText != null) {
|
||||
String[] footerLines = footerText.split("<br>");
|
||||
|
||||
// Calculate footer position from bottom of page
|
||||
float lineSpacing = 10; // 10 points between lines
|
||||
float footerBottomMargin = 30; // 30 points from absolute bottom
|
||||
|
||||
// Start from the bottom and work upwards
|
||||
float currentY = footerBottomMargin + (footerLines.length - 1) * lineSpacing;
|
||||
|
||||
for (String line : footerLines) {
|
||||
contentStream.beginText();
|
||||
contentStream.newLineAtOffset(MARGIN, currentY);
|
||||
contentStream.showText(line.trim());
|
||||
contentStream.endText();
|
||||
currentY -= lineSpacing;
|
||||
}
|
||||
}
|
||||
// Generate PDF from HTML
|
||||
return generatePdfFromHtmlString(filledHtml);
|
||||
}
|
||||
|
||||
public SystemInvoiceData createSampleInvoiceData() {
|
||||
SystemInvoiceData data = new SystemInvoiceData();
|
||||
|
||||
// Set sample data
|
||||
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:");
|
||||
@@ -434,20 +54,6 @@ public class SystemInvoiceService {
|
||||
return data;
|
||||
}
|
||||
|
||||
public byte[] generateInvoicePdfFromHtml() throws Exception {
|
||||
// Read the HTML template
|
||||
String htmlContent = readHtmlTemplate();
|
||||
|
||||
// For simplicity, we'll use the existing sample data to fill the PDF
|
||||
SystemInvoiceData sampleData = createSampleInvoiceData();
|
||||
|
||||
// Replace placeholders in HTML with actual data
|
||||
String filledHtml = fillHtmlWithInvoiceData(htmlContent, sampleData);
|
||||
|
||||
// Create PDF from HTML using iText
|
||||
return generatePdfFromHtmlString(filledHtml);
|
||||
}
|
||||
|
||||
private String readHtmlTemplate() throws Exception {
|
||||
// Read the HTML template file
|
||||
java.nio.file.Path path = java.nio.file.Paths.get("src/main/resources/templates/vltInvoice.html");
|
||||
@@ -458,25 +64,22 @@ public class SystemInvoiceService {
|
||||
// Replace placeholders in HTML with actual invoice data
|
||||
String filledHtml = html;
|
||||
|
||||
filledHtml = filledHtml.replace("HHA-2021-07", data.getInvoiceNumber() != null ? data.getInvoiceNumber() : "");
|
||||
// Replace invoice data placeholders
|
||||
filledHtml = filledHtml.replace("HHA-2021-007", data.getInvoiceNumber() != null ? data.getInvoiceNumber() : "");
|
||||
filledHtml = filledHtml.replace("19.07.2021", data.getInvoiceDate() != null ? data.getInvoiceDate() : "");
|
||||
filledHtml = filledHtml.replace("Gemäß unserem Nutzungsvertrag zu der Bestellnummer 45519389 berechnen wir Ihnen für den Monat Juli 2021 wie folgt:",
|
||||
data.getInvoiceText() != null ? data.getInvoiceText() : "");
|
||||
|
||||
// Replace recipient address
|
||||
filledHtml = filledHtml.replace("Hamburger Hochbahn AG<br>\n Kreditorenbuchhaltung<br>\n Steinstraße 20<br>\n 20095 Hamburg",
|
||||
data.getRecipientName() != null ? data.getRecipientName() : "" + "<br>\n " +
|
||||
(data.getRecipientDepartment() != null ? data.getRecipientDepartment() : "") + "<br>\n " +
|
||||
(data.getRecipientStreet() != null ? data.getRecipientStreet() : "") + "<br>\n " +
|
||||
(data.getRecipientCity() != null ? data.getRecipientCity() : ""));
|
||||
filledHtml = filledHtml.replace("Hamburger Hochbahn AG", data.getRecipientName() != null ? data.getRecipientName() : "");
|
||||
filledHtml = filledHtml.replace("Kreditorenbuchhaltung", data.getRecipientDepartment() != null ? data.getRecipientDepartment() : "");
|
||||
filledHtml = filledHtml.replace("Steinstraße 20", data.getRecipientStreet() != null ? data.getRecipientStreet() : "");
|
||||
filledHtml = filledHtml.replace("20095 Hamburg", data.getRecipientCity() != null ? data.getRecipientCity() : "");
|
||||
|
||||
// Replace invoice items
|
||||
if (data.getInvoiceItems() != null && !data.getInvoiceItems().isEmpty()) {
|
||||
SystemInvoiceItem item = data.getInvoiceItems().get(0);
|
||||
filledHtml = filledHtml.replace("1", item.getQuantity() != null ? item.getQuantity() : "");
|
||||
SystemInvoiceItem item = data.getInvoiceItems().getFirst();
|
||||
filledHtml = filledHtml.replace("Mtl. Lizenzgebühr »ILLT«", item.getDescription() != null ? item.getDescription() : "");
|
||||
filledHtml = filledHtml.replace("5.639,00 €", item.getUnitPrice() != null ? item.getUnitPrice() : "");
|
||||
filledHtml = filledHtml.replace("5.639,00 €", item.getTotalPrice() != null ? item.getTotalPrice() : "");
|
||||
}
|
||||
|
||||
// Replace amounts
|
||||
|
||||
Reference in New Issue
Block a user