SearchResultHelper.java

package com.tradecloud.dto.invoice;

import com.tradecloud.domain.base.utils.MathUtils;
import com.tradecloud.domain.base.utils.ObjectUtil;
import com.tradecloud.domain.comment.Comment;
import com.tradecloud.domain.costing.clean.CostingStructureMatcher;
import com.tradecloud.domain.document.Document;
import com.tradecloud.domain.document.DocumentState;
import com.tradecloud.domain.document.DocumentType;
import com.tradecloud.domain.document.invoice.ActualOrder;
import com.tradecloud.domain.document.invoice.BaseCommercialInvoice;
import com.tradecloud.domain.event.EnumTypedEvent;
import com.tradecloud.domain.event.Event;
import com.tradecloud.domain.model.ordermanagement.Consignment;
import com.tradecloud.domain.model.ordermanagement.Order;
import com.tradecloud.domain.settlement.Payment;
import com.tradecloud.domain.settlement.PlannedSettlement;
import com.tradecloud.domain.settlement.PlannedSettlementOrder;
import com.tradecloud.domain.shipment.AirShipment;
import com.tradecloud.domain.shipment.SeaShipment;
import com.tradecloud.domain.shipment.Shipment;
import com.tradecloud.domain.state.Stateful;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created with IntelliJ IDEA. User: ds Date: 2014/04/08 Time: 2:22 PM To change
 * this template use File | Settings | File Templates.
 */
public class SearchResultHelper {

    private static final int ROUND_SCALE = 4;
    private static final transient Logger log = Logger.getLogger(SearchResultHelper.class);
    private static final String SEPARATOR = "|";

    private static String flattenComments(List<Comment> commentList, String delimiter) {
        boolean commentFirstRun = false;
        StringBuilder comments = new StringBuilder();
        Comment comment = new Comment();
        for (Comment comment1 : commentList) {
            if (commentFirstRun) {
                comments.append(comment1.getCommentText());
            } else {
                comments.append("; " + comment1.getCommentText());
            }
            comment = comment1;
        }
        return comments.toString();
    }

    public static <S extends Enum<?>, X extends Event> Date getLastEventDate(Stateful<S,X> stateful, Enum e) {
        Date date = null;
        for ( Event event : stateful.getEvents() ) {
            // Should always be true
            if ( event instanceof EnumTypedEvent ) {
                if ( ((EnumTypedEvent)event).getEventType() == e ) {
                    date = event.getCreateDateTime();
                }
            }
        }
        return date;
    }

    public static void populateSupplierPaymentReportSearchResult(SupplyPaymentReportSearchResult result,
            Document document, PlannedSettlement plannedSettlement, DateFormat dateFormat) {
        BaseCommercialInvoice baseCommercialInvoice = (BaseCommercialInvoice) document;
        result.setDocumentType(document.getDocumentType() == null ? "" : document.getDocumentType().name());
        List<SupplyPaymentPlannedSettlementDTO> settlementDTOList = new ArrayList<>();
        SupplyPaymentPlannedSettlementDTO settlementDTO = new SupplyPaymentPlannedSettlementDTO();

        Order order = null;
        Shipment shipment = baseCommercialInvoice.getShipment();
        String shipmentRef = null;
        String shipmentNo = null;

        List<String> orderReferences = new ArrayList<>();
        List<String> shippingReferences = new ArrayList<>();
        List<String> forwardROEs = new ArrayList<>();

        PlannedSettlementOrder plannedSettlementOrder = ObjectUtil.first(plannedSettlement.getPlannedSettlementOrders());

        if (shipment != null && plannedSettlementOrder != null) {
            shipmentRef = shipment.getReference();
            shipmentNo = shipment.getNumber();
            result.setShipmentId(shipment.getId());

            for (Consignment consignment : shipment.getConsignments()) {
                for (Order order1 : consignment.getOrders()) {
                    orderReferences.add(order1.getOrderReference());
                    shippingReferences.add(order1.getShippingInformation().getShippingReference());
                    forwardROEs.add("" + plannedSettlementOrder.getForwardRate());
                    order = (order == null) ? order1 : order;

                }
                checkInvoiceQuantity(baseCommercialInvoice, orderReferences, shippingReferences, forwardROEs);
            }
        } else if (plannedSettlementOrder != null) {
            shipmentRef = "N/A";
            shipmentNo = "N/A";

            Consignment consignment = baseCommercialInvoice.getConsignment();
            for (Order order1 : consignment.getOrders()) {
                orderReferences.add(order1.getOrderReference());
                shippingReferences.add(order1.getShippingInformation().getShippingReference());
                forwardROEs.add("" + plannedSettlementOrder.getForwardRate());
                order = (order == null) ? order1 : order;
            }
        }

        if (shipment != null) {
            result.setOriginalDocumentsReceivedDate(shipment.getOriginalDocumentsReceivedDate());
        }

        Date billOfLandingDate = new Date();
        String transportDocumentNumber = "";

        if (baseCommercialInvoice.getShipment() instanceof SeaShipment) {
            SeaShipment seaShipment = (SeaShipment) baseCommercialInvoice.getShipment();
            if (seaShipment != null && seaShipment.getBillOfLadingDate() != null) {
                billOfLandingDate = seaShipment.getBillOfLadingDate();
                transportDocumentNumber = seaShipment.getBillOfLadingReference();
            }
        } else if (baseCommercialInvoice.getShipment() instanceof AirShipment) {
            AirShipment airShipment = (AirShipment) baseCommercialInvoice.getShipment();
            if (airShipment != null && airShipment.getHouseAirwayBillIssueDate() != null) {
                billOfLandingDate = airShipment.getHouseAirwayBillIssueDate();
                transportDocumentNumber = airShipment.getHouseAirwayBillNumber();
            }
        }

        result.setShipmentReference(shipmentRef);
        result.setShipmentNumber(shipmentNo);

        if (document.getReference() != null) {
            result.setDocumentReference(document.getReference());
        }
        if (document.getDateCreated() != null) {
            result.setDocumentDate(document.getDateCreated());
        }
        if (order != null) {
            if (order.getOrderReference() != null) {
                result.setOrderReferences(StringUtils.join(orderReferences, SEPARATOR));
            }
            if (order.getShippingInformation().getShippingReference() != null) {
                result.setShippingReference(StringUtils.join(shippingReferences, SEPARATOR));
            }
            ActualOrder actualOrder = ((BaseCommercialInvoice) document).getActualOrders().get(0);
            Order firstCIOrder = CostingStructureMatcher.getOrder(shipment, actualOrder);
            if (firstCIOrder.getOrderLetterOfCredit() != null) {
                //result.setLcBankReference(order.getOrderLetterOfCredit().getBankReference());
                result.setLcBankReference(firstCIOrder.getOrderLetterOfCredit().getNumber());
            }

            if (firstCIOrder.getPaymentMethod() != null) {
                result.setPaymentMethod(firstCIOrder.getPaymentMethod().getName());
                //  result.setPaymentMethod(order.getPaymentMethod().getName());
            }
            if (firstCIOrder.getPaymentTerm() != null) {
                //The first order on the CI should be used as the lookup for the payment terms
                result.setPaymentTerm(firstCIOrder.getPaymentTerm().getName());
                //result.setPaymentTerm(baseCommercialInvoice.getSupplier().getPaymentTerm().getCode());
            }
        }
        if (baseCommercialInvoice.getOrganisationalUnit() != null) {
            result.setBusinessUnit(baseCommercialInvoice.getOrganisationalUnit().getName());
        }
        if (baseCommercialInvoice.getSupplier() != null) {
            result.setSupplierName(baseCommercialInvoice.getSupplier().getName());
        }
        if (baseCommercialInvoice.getWeightedAverageForwardRateOfExchange() != null) {
            DocumentState documentState = baseCommercialInvoice.getState();
            if (documentState.equals(DocumentState.SIGNED_OFF) || documentState.equals(DocumentState.SETTLED)) {
                result.setALCForwardRate(StringUtils.join(forwardROEs, SEPARATOR));
            }
        }
        if (baseCommercialInvoice.getCurrency() != null) {
            result.setDocumentCurrency(baseCommercialInvoice.getCurrency().getCode());
        }
        if (billOfLandingDate != null) {
            result.setBillOfLandingDate(billOfLandingDate);
        }
        if (baseCommercialInvoice.getState() != null) {
         //   result.setDocumentState(baseCommercialInvoice.getState());
        }
        if (document.getId() != null) {
            result.setDocumentId(document.getId());
        }
        result.setDocumentComments(flattenComments(baseCommercialInvoice.getDocumentsComments(), ";"));
        //if (baseCommercialInvoice.getTotalSettleableValue() != null) {
        //    result.setDocumentValue(MathUtils.setScale(baseCommercialInvoice.getTotalSettleableValue(), ROUND_SCALE).toString());
        //}
//        result.setDocumentValue(MathUtils.setScale(
//                getAmountPerSettlement(baseCommercialInvoice,plannedSettlement), ROUND_SCALE).toString());

        if (baseCommercialInvoice.getPlannedSettlements() != null) {
            settlementDTOList.add(settlementDTO);
            result.setPlannedSettlementList(settlementDTOList);
        }
        if (transportDocumentNumber != null) {
            result.setTransportDocumentNumber(transportDocumentNumber);
        }

        BigDecimal paidAmount = BigDecimal.ZERO;
        List<String> paymentReferences = new ArrayList<>();
        List<String> paymentDates = new ArrayList<>();
        for (Payment payment : plannedSettlement.getPayments()) {
            paidAmount = paidAmount.add(payment.getAmount());
            paymentReferences.add(payment.getReference());
            paymentDates.add(dateFormat.format(payment.getPaymentDate()));
        }
      //  result.setPaidAmount(MathUtils.setScale(paidAmount, ROUND_SCALE).toString());
        //if (baseCommercialInvoice.getTotalSettleableValue() != null) {
        //    result.setBalance((MathUtils.setScale(baseCommercialInvoice.getTotalSettleableValue().subtract(paidAmount), ROUND_SCALE).toString()));
        //}
        result.setBalance((MathUtils.setScale(getAmountPerSettlement(
                baseCommercialInvoice,plannedSettlement).subtract(paidAmount), ROUND_SCALE).toString()));
        result.setPaymentReferences(StringUtils.join(paymentReferences, SEPARATOR));
        result.setPaymentDates(StringUtils.join(paymentDates, SEPARATOR));
    }

    private static BigDecimal getAmountPerSettlement(BaseCommercialInvoice document, PlannedSettlement settlement) {
        if(document.getDocumentType()!= DocumentType.COMMERCIAL_CREDIT_NOTE) {
            return settlement.getAmount();
        } else {
            return document.getGrossValue();
        }
    }

    /**
     * Check Invoice quauntity and if its zero remove the order. reference from
     * the invoice results.
     *
     * @return
     */
    private static void checkInvoiceQuantity(BaseCommercialInvoice commercialInvoice, List<String> orderReferences, List<String> shippingReferences,
            List<String> forwardROEs) {
        List<PlannedSettlement> plannedSettlementList = commercialInvoice.getPlannedSettlementList();
        for (PlannedSettlementOrder plannedSettlementOrder : plannedSettlementList.iterator().next().getPlannedSettlementOrders()) {

            List<Integer> indicesToRemove = new ArrayList<>();
            for (String reference : orderReferences) {
                if (plannedSettlementOrder.getReference().equals(reference)) {
                    if (plannedSettlementOrder.getAmount().doubleValue() <= 0.0000) {
                        indicesToRemove.add(orderReferences.indexOf(reference));
                    }
                }
            }
            for (int i : indicesToRemove) {
                orderReferences.remove(i);
                shippingReferences.remove(i);
                forwardROEs.remove(i);
            }
        }
    }
}