package co.smartreceipts.android.workers.reports.pdf.pdfbox; import android.support.annotation.NonNull; import android.text.TextUtils; import com.google.common.base.Preconditions; import com.tom_roush.pdfbox.pdmodel.PDDocument; import com.tom_roush.pdfbox.pdmodel.common.PDRectangle; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import co.smartreceipts.android.R; import co.smartreceipts.android.filters.LegacyReceiptFilter; import co.smartreceipts.android.model.Column; import co.smartreceipts.android.model.Distance; import co.smartreceipts.android.model.Receipt; import co.smartreceipts.android.model.Trip; import co.smartreceipts.android.model.comparators.ReceiptDateComparator; import co.smartreceipts.android.model.converters.DistanceToReceiptsConverter; import co.smartreceipts.android.settings.UserPreferenceManager; import co.smartreceipts.android.settings.catalog.UserPreference; import co.smartreceipts.android.workers.reports.pdf.colors.PdfColorStyle; import co.smartreceipts.android.workers.reports.pdf.fonts.PdfFontStyle; import co.smartreceipts.android.workers.reports.pdf.renderer.empty.EmptyRenderer; import co.smartreceipts.android.workers.reports.pdf.renderer.formatting.Alignment; import co.smartreceipts.android.workers.reports.pdf.renderer.grid.GridRenderer; import co.smartreceipts.android.workers.reports.pdf.renderer.grid.GridRowRenderer; import co.smartreceipts.android.workers.reports.pdf.renderer.text.TextRenderer; import co.smartreceipts.android.workers.reports.pdf.renderer.impl.PdfTableGenerator; public class PdfBoxReceiptsTablePdfSection extends PdfBoxSection { private static final float EPSILON = 0.0001f; private final List<Receipt> mReceipts; private final List<Column<Receipt>> mReceiptColumns; private final List<Distance> mDistances; private final List<Column<Distance>> mDistanceColumns; private final UserPreferenceManager mPreferences; private PdfBoxWriter mWriter; protected PdfBoxReceiptsTablePdfSection(@NonNull PdfBoxContext context, @NonNull Trip trip, @NonNull List<Receipt> receipts, @NonNull List<Column<Receipt>> receiptColumns, @NonNull List<Distance> distances, @NonNull List<Column<Distance>> distanceColumns) { super(context, trip); mReceipts = Preconditions.checkNotNull(receipts); mDistances = Preconditions.checkNotNull(distances); mReceiptColumns = Preconditions.checkNotNull(receiptColumns); mPreferences = Preconditions.checkNotNull(context.getPreferences()); mDistanceColumns = Preconditions.checkNotNull(distanceColumns); } @Override public void writeSection(@NonNull PDDocument doc, @NonNull PdfBoxWriter writer) throws IOException { final DefaultPdfBoxPageDecorations pageDecorations = new DefaultPdfBoxPageDecorations(pdfBoxContext, trip); final ReceiptsTotals totals = new ReceiptsTotals(trip, mReceipts, mDistances, mPreferences); // switch to landscape mode if (mPreferences.get(UserPreference.ReportOutput.PrintReceiptsTableInLandscape)) { pdfBoxContext.setPageSize(new PDRectangle(pdfBoxContext.getPageSize().getHeight(), pdfBoxContext.getPageSize().getWidth())); } mWriter = writer; mWriter.newPage(); final float availableWidth = pdfBoxContext.getPageSize().getWidth() - 2 * pdfBoxContext.getPageMarginHorizontal(); final float availableHeight = pdfBoxContext.getPageSize().getHeight() - 2 * pdfBoxContext.getPageMarginVertical() - pageDecorations.getHeaderHeight() - pageDecorations.getFooterHeight(); final GridRenderer gridRenderer = new GridRenderer(availableWidth, availableHeight); gridRenderer.addRows(writeHeader(trip, doc, totals)); gridRenderer.addRow(new GridRowRenderer(new EmptyRenderer(0, 40))); gridRenderer.addRows(writeReceiptsTable(mReceipts, doc)); if (mPreferences.get(UserPreference.Distance.PrintDistanceTableInReports) && !mDistances.isEmpty()) { gridRenderer.addRow(new GridRowRenderer(new EmptyRenderer(0, 40))); gridRenderer.addRows(writeDistancesTable(mDistances, doc)); } gridRenderer.measure(); gridRenderer.render(mWriter); // reset the page size if necessary if (mPreferences.get(UserPreference.ReportOutput.PrintReceiptsTableInLandscape)) { pdfBoxContext.setPageSize(new PDRectangle(pdfBoxContext.getPageSize().getHeight(), pdfBoxContext.getPageSize().getWidth())); } } private List<GridRowRenderer> writeHeader(@NonNull Trip trip, @NonNull PDDocument pdDocument, @NonNull ReceiptsTotals data) throws IOException { final List<GridRowRenderer> headerRows = new ArrayList<>(); headerRows.add(new GridRowRenderer(new TextRenderer( pdfBoxContext.getAndroidContext(), pdDocument, trip.getName(), pdfBoxContext.getColorManager().getColor(PdfColorStyle.Default), pdfBoxContext.getFontManager().getFont(PdfFontStyle.Title)))); if (!data.receiptsPrice.equals(data.netPrice)) { headerRows.add(new GridRowRenderer(new TextRenderer( pdfBoxContext.getAndroidContext(), pdDocument, pdfBoxContext.getAndroidContext().getString(R.string.report_header_receipts_total, data.receiptsPrice.getCurrencyFormattedPrice()), pdfBoxContext.getColorManager().getColor(PdfColorStyle.Default), pdfBoxContext.getFontManager().getFont(PdfFontStyle.Default)))); } if (mPreferences.get(UserPreference.Receipts.IncludeTaxField)) { if (mPreferences.get(UserPreference.Receipts.UsePreTaxPrice) && data.taxPrice.getPriceAsFloat() > EPSILON) { headerRows.add(new GridRowRenderer(new TextRenderer( pdfBoxContext.getAndroidContext(), pdDocument, pdfBoxContext.getAndroidContext().getString(R.string.report_header_receipts_total_tax, data.taxPrice.getCurrencyFormattedPrice()), pdfBoxContext.getColorManager().getColor(PdfColorStyle.Default), pdfBoxContext.getFontManager().getFont(PdfFontStyle.Default)))); } else if (!data.noTaxPrice.equals(data.receiptsPrice) && data.noTaxPrice.getPriceAsFloat() > EPSILON) { headerRows.add(new GridRowRenderer(new TextRenderer( pdfBoxContext.getAndroidContext(), pdDocument, pdfBoxContext.getAndroidContext().getString(R.string.report_header_receipts_total_no_tax, data.noTaxPrice.getCurrencyFormattedPrice()), pdfBoxContext.getColorManager().getColor(PdfColorStyle.Default), pdfBoxContext.getFontManager().getFont(PdfFontStyle.Default)))); } } if (!mPreferences.get(UserPreference.Receipts.OnlyIncludeReimbursable) && !data.reimbursablePrice.equals(data.receiptsPrice)) { headerRows.add(new GridRowRenderer(new TextRenderer( pdfBoxContext.getAndroidContext(), pdDocument, pdfBoxContext.getAndroidContext().getString(R.string.report_header_receipts_total_reimbursable, data.reimbursablePrice.getCurrencyFormattedPrice()), pdfBoxContext.getColorManager().getColor(PdfColorStyle.Default), pdfBoxContext.getFontManager().getFont(PdfFontStyle.Default)))); } if (!mDistances.isEmpty()) { headerRows.add(new GridRowRenderer(new TextRenderer( pdfBoxContext.getAndroidContext(), pdDocument, pdfBoxContext.getAndroidContext().getString(R.string.report_header_distance_total, data.distancePrice.getCurrencyFormattedPrice()), pdfBoxContext.getColorManager().getColor(PdfColorStyle.Default), pdfBoxContext.getFontManager().getFont(PdfFontStyle.Default)))); } headerRows.add(new GridRowRenderer(new TextRenderer( pdfBoxContext.getAndroidContext(), pdDocument, pdfBoxContext.getAndroidContext().getString(R.string.report_header_gross_total, data.netPrice.getCurrencyFormattedPrice()), pdfBoxContext.getColorManager().getColor(PdfColorStyle.Default), pdfBoxContext.getFontManager().getFont(PdfFontStyle.Default)))); String fromToPeriod = pdfBoxContext.getString(R.string.report_header_from, trip.getFormattedStartDate(pdfBoxContext.getAndroidContext(), mPreferences.get(UserPreference.General.DateSeparator))) + " " + pdfBoxContext.getString(R.string.report_header_to, trip.getFormattedEndDate(pdfBoxContext.getAndroidContext(), mPreferences.get(UserPreference.General.DateSeparator))); headerRows.add(new GridRowRenderer(new TextRenderer( pdfBoxContext.getAndroidContext(), pdDocument, fromToPeriod, pdfBoxContext.getColorManager().getColor(PdfColorStyle.Default), pdfBoxContext.getFontManager().getFont(PdfFontStyle.Default)))); if (mPreferences.get(UserPreference.General.IncludeCostCenter) && !TextUtils.isEmpty(trip.getCostCenter())) { headerRows.add(new GridRowRenderer(new TextRenderer( pdfBoxContext.getAndroidContext(), pdDocument, pdfBoxContext.getAndroidContext().getString(R.string.report_header_cost_center, trip.getCostCenter()), pdfBoxContext.getColorManager().getColor(PdfColorStyle.Default), pdfBoxContext.getFontManager().getFont(PdfFontStyle.Default)))); } if (!TextUtils.isEmpty(trip.getComment())) { headerRows.add(new GridRowRenderer(new TextRenderer( pdfBoxContext.getAndroidContext(), pdDocument, pdfBoxContext.getAndroidContext().getString(R.string.report_header_comment, trip.getComment()), pdfBoxContext.getColorManager().getColor(PdfColorStyle.Default), pdfBoxContext.getFontManager().getFont(PdfFontStyle.Default)))); } for (final GridRowRenderer headerRow : headerRows) { headerRow.getRenderingFormatting().addFormatting(new Alignment(Alignment.Type.Left)); } return headerRows; } private List<GridRowRenderer> writeReceiptsTable(@NonNull List<Receipt> receipts, @NonNull PDDocument pdDocument) throws IOException { final List<Receipt> receiptsTableList = new ArrayList<>(receipts); if (mPreferences.get(UserPreference.Distance.PrintDistanceAsDailyReceiptInReports)) { receiptsTableList.addAll(new DistanceToReceiptsConverter(pdfBoxContext.getAndroidContext(), mPreferences).convert(mDistances)); Collections.sort(receiptsTableList, new ReceiptDateComparator()); } final PdfTableGenerator<Receipt> pdfTableGenerator = new PdfTableGenerator<>(pdfBoxContext, mReceiptColumns, pdDocument, new LegacyReceiptFilter(mPreferences), true, false); return pdfTableGenerator.generate(receiptsTableList); } private List<GridRowRenderer> writeDistancesTable(@NonNull List<Distance> distances, @NonNull PDDocument pdDocument) throws IOException { final PdfTableGenerator<Distance> pdfTableGenerator = new PdfTableGenerator<>(pdfBoxContext, mDistanceColumns, pdDocument, null, true, true); return pdfTableGenerator.generate(distances); } }