package org.dicadeveloper.weplantaforest.receipt;
import java.io.IOException;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;
import org.dicadeveloper.weplantaforest.cart.Cart;
import org.dicadeveloper.weplantaforest.support.PdfHelper;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.Image;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
public class PdfReceiptView {
private String _imagePath;
private final static Font textFontForReceiptHeader = new Font(FontFamily.TIMES_ROMAN, 22, Font.ITALIC, BaseColor.BLACK);
private final static Font textFont = new Font(FontFamily.HELVETICA, 10, Font.NORMAL, BaseColor.BLACK);
private final static Font textFontLawText = new Font(FontFamily.HELVETICA, 9, Font.NORMAL, BaseColor.BLACK);
private final static Font textFontUserData = new Font(FontFamily.HELVETICA, 12, Font.NORMAL, BaseColor.BLACK);
private final static Font textFontHint = new Font(FontFamily.HELVETICA, 6.8f, Font.NORMAL, BaseColor.BLACK);
private final static Font textFontHintBold = new Font(FontFamily.HELVETICA, 7, Font.BOLD, BaseColor.BLACK);
private final static DecimalFormat priceFormat = new DecimalFormat("#0.00");
private PdfHelper pdfHelper = new PdfHelper();
public void writePdfDataToOutputStream(OutputStream toWrite, String imagePath, Receipt receipt) throws Exception {
// create pdf
final Document doc = new Document();
final PdfWriter pdfWriter = PdfWriter.getInstance(doc, toWrite);
pdfWriter.setEncryption(null, null, PdfWriter.ALLOW_DEGRADED_PRINTING | PdfWriter.ALLOW_PRINTING, PdfWriter.STANDARD_ENCRYPTION_128);
final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+2"), Locale.GERMAN);
cal.setTimeInMillis(System.currentTimeMillis());
final String date = cal.get(Calendar.DAY_OF_MONTH) + "." + (cal.get(Calendar.MONTH) + 1) + "." + cal.get(Calendar.YEAR);
_imagePath = imagePath;
doc.open();
int amountOfCarts = receipt.getCarts()
.size();
PdfContentByte cb = pdfWriter.getDirectContent();
pdfHelper.addLogo(cb, _imagePath, 262f, 720f);
createGeometricObjects(cb, amountOfCarts, doc);
PdfHelper.createAdress(cb, 75f, 710f);
createReceiptHeaderAndTextBelow(cb);
createUserFields(cb, receipt, doc);
PdfPTable priceTable = createPriceTable(cb, receipt);
PdfPTable dateTable = createDateTable(cb, receipt);
PdfPTable hintTable = createHintTable(cb);
PdfPTable lawTable = createLawTable(cb);
PdfPTable signatureTable = createSignatureTable(cb, date);
// hint block
if (amountOfCarts < 3) {
PdfHelper.createHeaderBlock(cb, 1, 1);
priceTable.writeSelectedRows(0, 3 + amountOfCarts, 85f, 390f, cb);
dateTable.writeSelectedRows(0, 3 + amountOfCarts, 395f, 390f, cb);
lawTable.writeSelectedRows(0, 6, 75f, 310f - (amountOfCarts + 1) * 16f, cb);
signatureTable.writeSelectedRows(0, 2, 75f, 225f - (amountOfCarts + 1) * 16f, cb);
cb.saveState();
cb.setRGBColorFill(0xE0, 0xDE, 0xDF);
cb.rectangle(0.0f, 0.0f, 595.0f, 100.0f);
cb.fill();
cb.stroke();
cb.restoreState();
hintTable.writeSelectedRows(0, 7, 75f, 90f, cb);
} else if (amountOfCarts >= 3 && amountOfCarts < 9) {
PdfHelper.createHeaderBlock(cb, 1, 2);
priceTable.writeSelectedRows(0, 3 + amountOfCarts, 85f, 390f, cb);
dateTable.writeSelectedRows(0, 3 + amountOfCarts, 395f, 390f, cb);
lawTable.writeSelectedRows(0, 6, 75f, 310f - (amountOfCarts + 1) * 16f, cb);
signatureTable.writeSelectedRows(0, 2, 75f, 225f - (amountOfCarts + 1) * 16f, cb);
doc.newPage();
PdfHelper.createHeaderBlock(cb, 2, 2);
cb.saveState();
cb.setRGBColorFill(0xE0, 0xDE, 0xDF);
cb.rectangle(0.0f, 722.0f, 595.0f, 100.0f);
cb.fill();
cb.stroke();
cb.restoreState();
hintTable.writeSelectedRows(0, 7, 75f, 812f, cb);
} else if (amountOfCarts >= 9 && amountOfCarts < 14) {
PdfHelper.createHeaderBlock(cb, 1, 2);
priceTable.writeSelectedRows(0, 3 + amountOfCarts, 85f, 390f, cb);
dateTable.writeSelectedRows(0, 3 + amountOfCarts, 395f, 390f, cb);
lawTable.writeSelectedRows(0, 6, 75f, 310f - (amountOfCarts + 1) * 16f, cb);
doc.newPage();
PdfHelper.createHeaderBlock(cb, 2, 2);
signatureTable.writeSelectedRows(0, 2, 75f, 812f, cb);
cb.saveState();
cb.setRGBColorFill(0xE0, 0xDE, 0xDF);
cb.rectangle(0.0f, 625.0f, 595.0f, 100.0f);
cb.fill();
cb.stroke();
cb.restoreState();
hintTable.writeSelectedRows(0, 7, 75f, 725f, cb);
} else if (amountOfCarts >= 14 && amountOfCarts < 20) {
PdfHelper.createHeaderBlock(cb, 1, 2);
priceTable.writeSelectedRows(0, 3 + amountOfCarts, 85f, 390f, cb);
dateTable.writeSelectedRows(0, 3 + amountOfCarts, 395f, 390f, cb);
doc.newPage();
PdfHelper.createHeaderBlock(cb, 2, 2);
lawTable.writeSelectedRows(0, 6, 75f, 812, cb);
signatureTable.writeSelectedRows(0, 2, 75f, 717, cb);
cb.saveState();
cb.setRGBColorFill(0xE0, 0xDE, 0xDF);
cb.rectangle(0.0f, 525.0f, 595.0f, 100.0f);
cb.fill();
cb.stroke();
cb.restoreState();
hintTable.writeSelectedRows(0, 7, 75f, 625f, cb);
} else if (amountOfCarts >= 20) {
PdfHelper.createHeaderBlock(cb, 1, 2);
priceTable.writeSelectedRows(0, 21, 85f, 390f, cb);
dateTable.writeSelectedRows(0, 21, 395f, 390f, cb);
doc.newPage();
PdfHelper.createHeaderBlock(cb, 2, 2);
// grey block
cb.saveState();
cb.setRGBColorFill(0xE0, 0xDE, 0xDF);
cb.rectangle(0.0f, 822f - (amountOfCarts - 18 + 1) * 16f - 8f, 595.0f, (amountOfCarts - 18 + 1) * 16f + 8f);
cb.fill();
cb.stroke();
cb.restoreState();
// price block
cb.saveState();
cb.setRGBColorFill(0xFC, 0xFC, 0xFC);
cb.rectangle(75.0f, 812f - (amountOfCarts - 18 + 1) * 16f + 12f, 295f, (amountOfCarts - 18 + 1) * 16f - 12f);
cb.fill();
cb.stroke();
cb.restoreState();
// date block
cb.saveState();
cb.setRGBColorFill(0xFC, 0xFC, 0xFC);
cb.rectangle(385.0f, 812f - (amountOfCarts - 18 + 1) * 16f + 12f, 135f, (amountOfCarts - 18 + 1) * 16f - 12f);
cb.fill();
cb.stroke();
cb.restoreState();
priceTable.writeSelectedRows(21, 22 + (amountOfCarts - 19), 85f, 812f, cb);
dateTable.writeSelectedRows(21, 22 + (amountOfCarts - 19), 395f, 812f, cb);
lawTable.writeSelectedRows(0, 6, 75f, 812 - (amountOfCarts - 18 + 1) * 16f, cb);
signatureTable.writeSelectedRows(0, 2, 75f, 727 - (amountOfCarts - 18 + 1) * 16f, cb);
cb.saveState();
cb.setRGBColorFill(0xE0, 0xDE, 0xDF);
cb.rectangle(0.0f, 550.0f - (amountOfCarts - 18 + 1) * 16f, 595.0f, 100.0f);
cb.fill();
cb.stroke();
cb.restoreState();
hintTable.writeSelectedRows(0, 7, 75f, 630f - (amountOfCarts - 18 + 1) * 16f, cb);
}
doc.close();
}
private void createGeometricObjects(PdfContentByte cb, long amountOfCarts, Document doc) {
// first big grey block
// float y 310 h 325
cb.saveState();
cb.setRGBColorFill(0xE0, 0xDE, 0xDF);
cb.rectangle(0.0f, 325f - (amountOfCarts + 1) * 16f, 595.0f, 310 + (amountOfCarts + 1) * 16f);
cb.fill();
cb.stroke();
cb.restoreState();
// name and address block
cb.saveState();
cb.setRGBColorFill(0xFC, 0xFC, 0xFC);
cb.rectangle(75.0f, 410.0f, 445.0f, 120.0f);
cb.fill();
cb.stroke();
cb.restoreState();
// price block
cb.saveState();
cb.setRGBColorFill(0xFC, 0xFC, 0xFC);
cb.rectangle(75.0f, 350f - (amountOfCarts + 1) * 16f, 295f, 45f + (amountOfCarts + 1) * 16f);
cb.fill();
cb.stroke();
cb.restoreState();
// date block
cb.saveState();
cb.setRGBColorFill(0xFC, 0xFC, 0xFC);
cb.rectangle(385.0f, 350f - (amountOfCarts + 1) * 16f, 135f, 45f + (amountOfCarts + 1) * 16f);
cb.fill();
cb.stroke();
cb.restoreState();
// small triangle in address block
cb.saveState();
cb.setRGBColorFill(0xE0, 0xDE, 0xDF);
cb.moveTo(74f, 455f);
cb.lineTo(74f, 485f);
cb.lineTo(82f, 470f);
cb.lineTo(74f, 455f);
cb.fill();
cb.closePathStroke();
cb.restoreState();
// small triangle in price block
cb.saveState();
cb.setRGBColorFill(0xE0, 0xDE, 0xDF);
cb.moveTo(74f, 350f);
cb.lineTo(74f, 380f);
cb.lineTo(82f, 365f);
cb.lineTo(74f, 350f);
cb.fill();
cb.closePathStroke();
cb.restoreState();
}
private void createReceiptHeaderAndTextBelow(PdfContentByte cb) throws DocumentException {
PdfPTable headerTable = new PdfPTable(1);
float[] rows = { 450f };
headerTable.setTotalWidth(rows);
headerTable.getDefaultCell()
.setBorder(Rectangle.NO_BORDER);
headerTable.addCell(new Phrase(new Chunk("Bestätigung über Geldzuwendungen", textFontForReceiptHeader)));
headerTable.writeSelectedRows(0, 1, 75f, 625, cb);
PdfPTable table = new PdfPTable(1);
table.setTotalWidth(rows);
table.getDefaultCell()
.setBorder(Rectangle.NO_BORDER);
table.getDefaultCell()
.setLeading(8f, 0);
table.addCell(new Phrase(new Chunk("im Sinne des §10b des Einkommensteuergesetzes", textFont)));
table.addCell(new Phrase(new Chunk("an eine der in §5 Abs. 1 Nr. 9 des Körperschaftsteuergesetzes bezeichneten", textFont)));
table.addCell(new Phrase(new Chunk("Körperschaften, Personenvereinigungen oder Vermögensmassen", textFont)));
table.writeSelectedRows(0, 3, 75f, 590, cb);
}
private void createUserFields(PdfContentByte cb, Receipt receipt, Document doc) throws DocumentException {
// get latest cart and sum of total prices
Cart latest = receipt.getCarts()
.get(0);
// create Strings
String name = (latest.getCallBackNachname() == null ? "" : latest.getCallBackNachname() + ", ") + (latest.getCallBackVorname() == null ? "" : latest.getCallBackVorname());
String company = latest.getCallBackFirma() == null ? "" : latest.getCallBackFirma();
String street = latest.getCallBackStrasse() == null ? "" : latest.getCallBackStrasse();
String city = (latest.getCallBackPlz() == null ? "" : latest.getCallBackPlz() + " ") + (latest.getCallBackOrt() == null ? "" : latest.getCallBackOrt());
PdfPTable tableForNameAndAdress = new PdfPTable(1);
float[] rows = { 450f };
tableForNameAndAdress.setTotalWidth(rows);
tableForNameAndAdress.getDefaultCell()
.setBorder(Rectangle.NO_BORDER);
tableForNameAndAdress.addCell(new Phrase(new Chunk("Name und Anschrift des Zuwendenden:", textFont)));
tableForNameAndAdress.addCell(new Phrase(new Chunk(" ", textFont)));
tableForNameAndAdress.addCell(new Phrase(new Chunk(company, textFontUserData)));
tableForNameAndAdress.addCell(new Phrase(new Chunk(name, textFontUserData)));
tableForNameAndAdress.addCell(new Phrase(new Chunk(street, textFontUserData)));
tableForNameAndAdress.addCell(new Phrase(new Chunk(city, textFontUserData)));
tableForNameAndAdress.writeSelectedRows(0, 6, 85f, 525f, cb);
}
private PdfPTable createPriceTable(PdfContentByte cb, Receipt receipt) throws DocumentException {
PdfPTable tableForPrices = new PdfPTable(1);
float[] rowForTotalPrice = { 250f };
tableForPrices.setTotalWidth(rowForTotalPrice);
tableForPrices.getDefaultCell()
.setBorder(Rectangle.NO_BORDER);
tableForPrices.addCell(new Phrase(new Chunk("Betrag der Zuwendung in Ziffern:", textFont)));
tableForPrices.addCell(new Phrase(new Chunk(" ", textFont)));
Double totalPrice = 0.0;
for (final Cart cart : receipt.getCarts()) {
tableForPrices.addCell(new Phrase(new Chunk(cart.getTotalPrice()
.toString()
+ " €", textFontUserData)));
totalPrice += cart.getTotalPrice()
.doubleValue();
}
String formattedPrice = priceFormat.format(totalPrice)
.toString();
tableForPrices.addCell(new Phrase(new Chunk("Gesamt: " + formattedPrice + " €", textFontUserData)));
return tableForPrices;
}
private PdfPTable createDateTable(PdfContentByte cb, Receipt receipt) throws DocumentException {
PdfPTable tableForDate = new PdfPTable(1);
float[] rowForDate = { 110f };
tableForDate.setTotalWidth(rowForDate);
tableForDate.getDefaultCell()
.setBorder(Rectangle.NO_BORDER);
tableForDate.addCell(new Phrase(new Chunk("Datum der Zuwendung:", textFont)));
tableForDate.addCell(new Phrase(new Chunk(" ", textFont)));
final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+2"), Locale.GERMAN);
for (final Cart cart : receipt.getCarts()) {
cal.setTimeInMillis(cart.getTimeStamp());
final String date = cal.get(Calendar.DAY_OF_MONTH) + "." + (cal.get(Calendar.MONTH) + 1) + "." + cal.get(Calendar.YEAR);
PdfPCell cell = new PdfPCell(new Phrase(new Chunk(date, textFontUserData)));
cell.setHorizontalAlignment(PdfPCell.ALIGN_RIGHT);
cell.setBorder(PdfPCell.NO_BORDER);
tableForDate.addCell(cell);
}
return tableForDate;
}
private PdfPTable createLawTable(PdfContentByte cb) throws DocumentException {
PdfPTable table = new PdfPTable(1);
float[] rows = { 445f };
table.setTotalWidth(rows);
table.getDefaultCell()
.setBorder(Rectangle.NO_BORDER);
table.getDefaultCell()
.setLeading(8f, 0);
table.addCell(new Phrase(new Chunk("Es handelt sich nicht um den Verzicht auf Erstattung von Aufwendungen.", textFontLawText)));
table.addCell(new Phrase(new Chunk("Die Gesellschaft ist wegen Förderung (begünstigter Zweck: Umweltschutz (§52 (2) S. 1 Nr.(n) 8 AO)) durch", textFontLawText)));
table.addCell(new Phrase(new Chunk("Bescheinigung des Finanzamt Halle (Saale)-Nord, StNr. 110/108/91169, vom 19.11.2008 ab 01.01.2009", textFontLawText)));
table.addCell(new Phrase(new Chunk("als gemeinnützig anerkannt. Letzter Freistellungsbescheid datiert auf den 20.06.2013.", textFontLawText)));
table.addCell(new Phrase(new Chunk("Es wird bestätigt, dass die Zuwendung nur zur Förderung des Umweltschutzes verwendet wird.", textFontLawText)));
PdfPCell emptyCell = new PdfPCell();
emptyCell.setBorder(Rectangle.BOTTOM);
emptyCell.setFixedHeight(15f);
table.addCell(emptyCell);
return table;
}
private PdfPTable createSignatureTable(PdfContentByte cb, String date) throws DocumentException, MalformedURLException, IOException {
PdfPTable table = new PdfPTable(5);
float[] rows = { 95f, 10f, 35f, 10f, 110f };
table.setTotalWidth(rows);
table.getDefaultCell()
.setBorder(Rectangle.NO_BORDER);
final Image signatureImage = Image.getInstance(getClass().getResource(_imagePath + "/Unterschrift150.jpg"));
final Image stampImage = Image.getInstance(getClass().getResource(_imagePath + "/stamp.jpg"));
PdfPCell placeDateCell = new PdfPCell();
placeDateCell.setVerticalAlignment(Element.ALIGN_BOTTOM);
placeDateCell.setBorder(Rectangle.NO_BORDER);
placeDateCell.addElement(new Phrase(new Chunk("Halle, " + date, textFontUserData)));
PdfPCell signatureCell = new PdfPCell();
signatureCell.setBorder(Rectangle.NO_BORDER);
signatureCell.setVerticalAlignment(Element.ALIGN_BOTTOM);
signatureCell.setImage(signatureImage);
PdfPCell stampCell = new PdfPCell();
stampCell.setBorder(Rectangle.NO_BORDER);
stampCell.setVerticalAlignment(Element.ALIGN_BOTTOM);
stampCell.setImage(stampImage);
table.addCell(placeDateCell);
table.addCell(new Phrase(new Chunk(" ", textFontUserData)));
table.addCell(signatureCell);
table.addCell(new Phrase(new Chunk(" ", textFontUserData)));
table.addCell(stampCell);
PdfPCell underSignatureCell = new PdfPCell();
underSignatureCell.setColspan(5);
underSignatureCell.setBorder(Rectangle.TOP);
underSignatureCell.addElement(new Phrase(new Chunk("Ort, Datum, Unterschrift des Zuwendungsempfängers", textFont)));
table.addCell(underSignatureCell);
return table;
}
private PdfPTable createHintTable(PdfContentByte cb) throws DocumentException {
PdfPTable table = new PdfPTable(3);
float[] rows = { 215f, 15f, 215f };
table.setTotalWidth(rows);
table.getDefaultCell()
.setBorder(Rectangle.NO_BORDER);
table.getDefaultCell()
.setHorizontalAlignment(Element.ALIGN_JUSTIFIED_ALL);
table.getDefaultCell()
.setLeading(5f, 0f);
PdfPCell hintCell = new PdfPCell();
hintCell.setHorizontalAlignment(Element.ALIGN_LEFT);
hintCell.setBorder(Rectangle.NO_BORDER);
hintCell.addElement(new Phrase(new Chunk("Hinweis:", textFontHintBold)));
table.addCell(hintCell);
table.addCell(new Phrase(new Chunk(" ", textFontHintBold)));
table.addCell(new Phrase(new Chunk(" ", textFontHintBold)));
table.addCell(new Paragraph(new Chunk("Wer vorsätzlich oder grob fahrlässig eine unrichtige Zuwendungsbe-", textFontHint)));
table.addCell(new Phrase(new Chunk(" ", textFontHintBold)));
table.addCell(new Paragraph(new Chunk("Diese Bestätigung wird nicht als Nachweis für die steuerliche Berück-", textFontHint)));
table.addCell(new Phrase(new Chunk("stätigung erstellt oder wer veranlasst, dass Zuwendungen nicht zu", textFontHint)));
table.addCell(new Phrase(new Chunk(" ", textFontHintBold)));
table.addCell(new Phrase(new Chunk("sichtigung der Zuwendung anerkannt, wenn das Datum des Freistel-", textFontHint)));
table.addCell(new Phrase(new Chunk("den in der Zuwendungsbestätigung angegebenen steuerbegünstig-", textFontHint)));
table.addCell(new Phrase(new Chunk(" ", textFontHintBold)));
table.addCell(new Phrase(new Chunk("lungsbesscheides länger als 5 Jahre bzw. das Datum der vorläufigen", textFontHint)));
table.addCell(new Phrase(new Chunk("ten Zwecken verwendet werden, haftet für die Steuer, die dem Fiskus", textFontHint)));
table.addCell(new Phrase(new Chunk(" ", textFontHintBold)));
table.addCell(new Phrase(new Chunk("Bescheinigung länger als 3 Jahre seit Ausstellung der Bestätigung zu-", textFontHint)));
PdfPCell lastCellRight = new PdfPCell();
lastCellRight.setHorizontalAlignment(Element.ALIGN_LEFT);
lastCellRight.setBorder(Rectangle.NO_BORDER);
lastCellRight.addElement(new Phrase(5f, new Chunk("rückliegt (BMF vom 15.12.1994 - BStBl I S. 884).", textFontHint)));
table.addCell(new Phrase(new Chunk("durch einen etwaigen Abzug der Zuwendungen beim Zuwendenden", textFontHint)));
table.addCell(new Phrase(new Chunk(" ", textFontHintBold)));
table.addCell(lastCellRight);
PdfPCell lastCellLeft = new PdfPCell();
lastCellLeft.setHorizontalAlignment(Element.ALIGN_LEFT);
lastCellLeft.setBorder(Rectangle.NO_BORDER);
lastCellLeft.addElement(new Phrase(5f, new Chunk("entgeht(§10b Abs. 4 EStG, §9 Abs. 3 KStG, §9 Nr.5 GewStG).", textFontHint)));
table.addCell(lastCellLeft);
table.addCell(new Phrase(new Chunk(" ", textFontHintBold)));
table.addCell(new Phrase(new Chunk(" ", textFontHint)));
return table;
}
}