org.openlmis.web.view.pdf.requisition.RequisitionPdfModel.java Source code

Java tutorial

Introduction

Here is the source code for org.openlmis.web.view.pdf.requisition.RequisitionPdfModel.java

Source

/*
 * This program is part of the OpenLMIS logistics management information system platform software.
 * Copyright  2013 VillageReach
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU Affero General Public License along with this program. If not, see http://www.gnu.org/licenses. For additional information contact info@OpenLMIS.org.
 */

package org.openlmis.web.view.pdf.requisition;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.collections.Predicate;
import org.apache.commons.lang.ArrayUtils;
import org.openlmis.core.domain.Facility;
import org.openlmis.core.domain.GeographicZone;
import org.openlmis.core.domain.Money;
import org.openlmis.core.service.ConfigurationSettingService;
import org.openlmis.core.service.MessageService;
import org.openlmis.rnr.domain.*;
import org.openlmis.web.model.PrintRnrLineItem;

import java.io.IOException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import static org.apache.commons.collections.CollectionUtils.find;
import static org.openlmis.rnr.domain.RnrStatus.AUTHORIZED;
import static org.openlmis.rnr.domain.RnrStatus.SUBMITTED;
import static org.openlmis.web.controller.RequisitionController.*;
import static org.openlmis.web.view.pdf.requisition.RequisitionCellFactory.*;

/**
 * This entity is used to encapsulate rnr attributes, report formatting attributes to be used in requisition report.
 */

@Data
@NoArgsConstructor
public class RequisitionPdfModel {
    public static final String LABEL_CURRENCY_SYMBOL = "label.currency.symbol";
    public static final float PARAGRAPH_SPACING = 30.0f;
    public static final BaseColor ROW_GREY_BACKGROUND = new BaseColor(235, 235, 235);
    public static final Font H1_FONT = FontFactory.getFont(FontFactory.TIMES, 30, Font.BOLD, BaseColor.BLACK);
    public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd/MM/yyyy");
    public static final int TABLE_SPACING = 25;
    private List<RequisitionStatusChange> statusChanges;
    private List<? extends Column> rnrColumnList;
    private List<? extends Column> regimenColumnList;
    private Integer numberOfMonths;
    private Rnr requisition;
    private List<LossesAndAdjustmentsType> lossesAndAdjustmentsTypes;
    private MessageService messageService;

    private ConfigurationSettingService configService;

    public RequisitionPdfModel(Map<String, Object> model, MessageService messageService,
            ConfigurationSettingService configService) {
        this.statusChanges = (List<RequisitionStatusChange>) model.get(STATUS_CHANGES);
        this.rnrColumnList = (List<RnrColumn>) model.get(RNR_TEMPLATE);
        this.regimenColumnList = (List<RegimenColumn>) model.get(REGIMEN_TEMPLATE);
        this.requisition = (Rnr) model.get(RNR);
        this.lossesAndAdjustmentsTypes = (List<LossesAndAdjustmentsType>) model.get(LOSSES_AND_ADJUSTMENT_TYPES);
        this.numberOfMonths = (Integer) model.get(NUMBER_OF_MONTHS);
        this.messageService = messageService;
        this.configService = configService;
    }

    public Paragraph getFullSupplyHeader() {
        return new Paragraph(messageService.message("label.full.supply.products"), H2_FONT);
    }

    public Paragraph getNonFullSupplyHeader() {
        return new Paragraph(messageService.message("label.non.full.supply.products"), H2_FONT);
    }

    public PdfPTable getFullSupplyTable()
            throws DocumentException, NoSuchFieldException, IllegalAccessException, IOException {
        return getTableFor(requisition.getFullSupplyLineItems(), true, rnrColumnList);
    }

    public PdfPTable getRegimenTable()
            throws DocumentException, NoSuchFieldException, IllegalAccessException, IOException {
        List<RegimenLineItem> regimenLineItems = requisition.getRegimenLineItems();
        if (regimenLineItems.size() == 0)
            return null;

        return getTableFor(regimenLineItems, null, regimenColumnList);
    }

    private PdfPTable getTableFor(List<? extends LineItem> lineItems, Boolean fullSupply,
            List<? extends Column> columnList)
            throws DocumentException, NoSuchFieldException, IllegalAccessException, IOException {
        Template template = Template.getInstance(columnList);
        List<? extends Column> visibleColumns = template.getPrintableColumns(fullSupply);

        PdfPTable table = prepareTable(visibleColumns);

        boolean odd = true;

        LineItem previousLineItem = null;
        for (LineItem lineItem : lineItems) {
            if (previousLineItem == null || !lineItem.compareCategory(previousLineItem)) {
                table.addCell(categoryRow(visibleColumns.size(), lineItem));
                previousLineItem = lineItem;
            }

            if (lineItem.isRnrLineItem()) {
                PrintRnrLineItem printRnrLineItem = new PrintRnrLineItem((RnrLineItem) lineItem);
                printRnrLineItem.calculate(rnrColumnList, lossesAndAdjustmentsTypes, numberOfMonths,
                        requisition.getStatus());
            }

            String currencySymbol = messageService.message(LABEL_CURRENCY_SYMBOL);

            if (!configService.getBoolValue("RNR_PRINT_REPEAT_CURRENCY_SYMBOL")) {
                currencySymbol = "";
            }

            List<PdfPCell> cells = getCells(visibleColumns, lineItem, currencySymbol);
            odd = !odd;

            for (PdfPCell cell : cells) {
                cell.setBackgroundColor(odd ? BaseColor.WHITE : ROW_GREY_BACKGROUND);
                table.addCell(cell);
            }
        }
        return table;
    }

    private void setTableHeader(PdfPTable table, List<? extends Column> visibleColumns) {
        for (Column column : visibleColumns) {
            table.addCell(column.getLabel());
        }
    }

    private PdfPTable prepareTable(List<? extends Column> visibleColumns) throws DocumentException {
        java.util.List<Integer> widths = new ArrayList<>();
        for (Column column : visibleColumns) {
            widths.add(column.getColumnWidth());
        }
        PdfPTable table = new PdfPTable(widths.size());

        table.setWidths(ArrayUtils.toPrimitive(widths.toArray(new Integer[widths.size()])));
        table.getDefaultCell().setBackgroundColor(HEADER_BACKGROUND);
        table.getDefaultCell().setPadding(CELL_PADDING);
        table.setWidthPercentage(WIDTH_PERCENTAGE);
        table.setSpacingBefore(TABLE_SPACING);
        table.setHeaderRows(2);
        table.setFooterRows(1);
        setTableHeader(table, visibleColumns);
        setBlankFooter(table, visibleColumns.size());
        return table;
    }

    private void setBlankFooter(PdfPTable table, Integer visibleColumnsSize) {
        PdfPCell cell = new PdfPCell(new Phrase(" "));
        cell.setBorder(0);
        cell.setColspan(visibleColumnsSize);
        cell.setBackgroundColor(BaseColor.WHITE);
        table.addCell(cell);
    }

    public PdfPTable getNonFullSupplyTable()
            throws DocumentException, NoSuchFieldException, IllegalAccessException, IOException {
        List<RnrLineItem> nonFullSupplyLineItems = requisition.getNonFullSupplyLineItems();
        Collections.sort(nonFullSupplyLineItems, new LineItemComparator());
        if (nonFullSupplyLineItems.size() == 0)
            return null;

        return getTableFor(nonFullSupplyLineItems, false, rnrColumnList);
    }

    public PdfPTable getRequisitionHeader() throws DocumentException {
        PdfPTable table = prepareRequisitionHeaderTable();
        addHeading(table);

        Facility facility = requisition.getFacility();
        addFirstLine(facility, table);
        addSecondLine(facility, table, requisition.isEmergency());
        table.setSpacingAfter(PARAGRAPH_SPACING);
        return table;
    }

    private void addHeading(PdfPTable table) throws DocumentException {
        Chunk chunk = new Chunk(String.format(messageService.message("label.requisition") + ": %s (%s)",
                this.requisition.getProgram().getName(),
                this.requisition.getFacility().getFacilityType().getName()), H1_FONT);

        PdfPCell cell = new PdfPCell(new Phrase(chunk));
        cell.setColspan(5);
        cell.setPadding(10);
        cell.setBorder(0);
        table.addCell(cell);
    }

    private void addFirstLine(Facility facility, PdfPTable table) {
        String text = String.format(messageService.message("label.facility") + ": %s", facility.getName());
        insertCell(table, text, 1);
        text = String.format(messageService.message("create.facility.operatedBy") + ": %s",
                facility.getOperatedBy().getText());
        insertCell(table, text, 1);
        text = String.format(messageService.message("label.facility.maximumStock") + ": %s",
                facility.getFacilityType().getNominalMaxMonth());
        insertCell(table, text, 1);
        text = String.format(messageService.message("label.emergency.order.point") + ": %s",
                facility.getFacilityType().getNominalEop());
        insertCell(table, text, 1);
        insertCell(table, "", 1);
    }

    private void insertCell(PdfPTable table, String text, int colSpan) {
        Chunk chunk;
        chunk = new Chunk(text);
        PdfPCell cell = table.getDefaultCell();
        cell.setPhrase(new Phrase(chunk));
        cell.setColspan(colSpan);
        table.addCell(cell);
    }

    private void addSecondLine(Facility facility, PdfPTable table, Boolean emergency) {
        GeographicZone geographicZone = facility.getGeographicZone();
        GeographicZone parent = geographicZone.getParent();
        String text = String.format(messageService.message("header.facility.code") + ": %s", facility.getCode());
        insertCell(table, text, 1);

        StringBuilder builder = new StringBuilder();
        builder.append(geographicZone.getLevel().getName()).append(": ").append(geographicZone.getName());
        insertCell(table, builder.toString(), 1);
        builder = new StringBuilder();
        builder.append(parent.getLevel().getName()).append(": ").append(parent.getName());
        insertCell(table, builder.toString(), 1);
        builder = new StringBuilder();
        builder.append(messageService.message("label.facility.reportingPeriod")).append(": ")
                .append(DATE_FORMAT.format(requisition.getPeriod().getStartDate())).append(" - ")
                .append(DATE_FORMAT.format(requisition.getPeriod().getEndDate()));

        insertCell(table, builder.toString(), 1);

        String label = emergency ? "requisition.type.emergency" : "requisition.type.regular";
        builder = new StringBuilder();
        builder.append(messageService.message("label.requisition.type")).append(": ")
                .append(messageService.message(label));
        insertCell(table, builder.toString(), 1);
    }

    private PdfPTable prepareRequisitionHeaderTable() throws DocumentException {
        int[] columnWidths = { 160, 160, 160, 160, 160 };
        PdfPTable table = new PdfPTable(columnWidths.length);
        table.setWidths(columnWidths);
        table.getDefaultCell().setBackgroundColor(HEADER_BACKGROUND);
        table.getDefaultCell().setPadding(10);
        table.getDefaultCell().setBorder(0);
        table.setWidthPercentage(WIDTH_PERCENTAGE);
        table.setSpacingBefore(TABLE_SPACING);
        table.setHeaderRows(1);
        return table;
    }

    public PdfPTable getSummary() throws DocumentException {
        this.requisition.fillFullSupplyCost();
        this.requisition.fillNonFullSupplyCost();

        DecimalFormat formatter = new DecimalFormat("#,##0.00");

        PdfPTable summaryTable = new PdfPTable(2);
        summaryTable.setWidths(new int[] { 30, 20 });
        summaryTable.setSpacingBefore(TABLE_SPACING);
        summaryTable.setWidthPercentage(40);
        summaryTable.setHorizontalAlignment(0);

        PdfPCell summaryHeaderCell = headingCell(messageService.message("label.summary"));
        summaryHeaderCell.setColspan(2);
        summaryHeaderCell.setPadding(10);
        summaryHeaderCell.setBorder(0);
        summaryTable.addCell(summaryHeaderCell);

        boolean showBudget = !requisition.isEmergency() && requisition.getProgram().getBudgetingApplies();
        if (showBudget) {
            summaryTable.addCell(summaryCell(textCell(messageService.message("label.allocated.budget"))));
            PdfPCell allocatedBudgetCell = requisition.getAllocatedBudget() != null
                    ? numberCell(messageService.message(LABEL_CURRENCY_SYMBOL)
                            + formatter.format(new Money(requisition.getAllocatedBudget()).toDecimal()))
                    : numberCell(messageService.message("msg.budget.not.allocated"));
            summaryTable.addCell(summaryCell(allocatedBudgetCell));
        }
        summaryTable.addCell(summaryCell(textCell(messageService.message("label.total.cost.full.supply.items"))));
        summaryTable.addCell(summaryCell(numberCell(messageService.message(LABEL_CURRENCY_SYMBOL)
                + formatter.format(requisition.getFullSupplyItemsSubmittedCost().toDecimal()))));
        summaryTable
                .addCell(summaryCell(textCell(messageService.message("label.total.cost.non.full.supply.items"))));
        summaryTable.addCell(summaryCell(numberCell(messageService.message(LABEL_CURRENCY_SYMBOL)
                + formatter.format(requisition.getNonFullSupplyItemsSubmittedCost().toDecimal()))));
        summaryTable.addCell(summaryCell(textCell(messageService.message("label.total.cost"))));
        summaryTable.addCell(summaryCell(numberCell(messageService.message(LABEL_CURRENCY_SYMBOL)
                + formatter.format(this.getTotalCost(requisition).toDecimal()).toString())));
        if (showBudget && requisition.getAllocatedBudget() != null
                && (requisition.getAllocatedBudget().compareTo(this.getTotalCost(requisition).getValue()) == -1)) {
            summaryTable.addCell(summaryCell(textCell(messageService.message("msg.cost.exceeds.budget"))));
            summaryTable.addCell(summaryCell(textCell(" ")));
        }

        summaryTable.addCell(summaryCell(textCell(" ")));
        summaryTable.addCell(summaryCell(textCell(" ")));
        summaryTable.addCell(summaryCell(textCell(" ")));
        summaryTable.addCell(summaryCell(textCell(" ")));

        fillAuditFields(summaryTable);
        return summaryTable;
    }

    private void fillAuditFields(PdfPTable summaryTable) {
        RequisitionStatusChange submittedStatusChange = getStatusChangeFor(SUBMITTED);
        RequisitionStatusChange authorizedStatusChange = getStatusChangeFor(AUTHORIZED);

        String submittedDate = submittedStatusChange != null
                ? DATE_FORMAT.format(submittedStatusChange.getCreatedDate())
                : "";
        String submittedBy = submittedStatusChange != null
                ? submittedStatusChange.getCreatedBy().getFirstName() + " "
                        + submittedStatusChange.getCreatedBy().getLastName()
                : "";

        String authorizedDate = authorizedStatusChange != null
                ? DATE_FORMAT.format(authorizedStatusChange.getCreatedDate())
                : "";
        String authorizedBy = authorizedStatusChange != null
                ? authorizedStatusChange.getCreatedBy().getFirstName() + " "
                        + authorizedStatusChange.getCreatedBy().getLastName()
                : "";

        summaryTable
                .addCell(summaryCell(textCell(messageService.message("label.submitted.by") + ": " + submittedBy)));
        summaryTable.addCell(summaryCell(textCell(messageService.message("label.date") + ": " + submittedDate)));
        summaryTable.addCell(summaryCell(textCell(" ")));
        summaryTable.addCell(summaryCell(textCell(" ")));
        summaryTable.addCell(
                summaryCell(textCell(messageService.message("label.authorized.by") + ": " + authorizedBy)));
        summaryTable.addCell(summaryCell(textCell(messageService.message("label.date") + ": " + authorizedDate)));
    }

    private RequisitionStatusChange getStatusChangeFor(final RnrStatus status) {
        return (RequisitionStatusChange) find(statusChanges, new Predicate() {
            @Override
            public boolean evaluate(Object o) {
                return ((RequisitionStatusChange) o).getStatus().equals(status);
            }
        });
    }

    private PdfPCell summaryCell(PdfPCell cell) {
        cell.setPadding(15);
        cell.setBorder(0);
        return cell;
    }

    public Money getTotalCost(Rnr requisition) {
        return new Money(requisition.getFullSupplyItemsSubmittedCost().getValue()
                .add(requisition.getNonFullSupplyItemsSubmittedCost().getValue()));
    }

    public Paragraph getRegimenHeader() {
        return new Paragraph(messageService.message("label.regimens"), H2_FONT);
    }
}