001/*
002 * Copyright 2008 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.ole.module.purap.document.validation.impl;
017
018import org.kuali.ole.module.purap.PurapConstants;
019import org.kuali.ole.module.purap.PurapKeyConstants;
020import org.kuali.ole.module.purap.businessobject.InvoiceItem;
021import org.kuali.ole.module.purap.businessobject.PurApItem;
022import org.kuali.ole.module.purap.document.InvoiceDocument;
023import org.kuali.ole.sys.OLEPropertyConstants;
024import org.kuali.ole.sys.document.validation.GenericValidation;
025import org.kuali.ole.sys.document.validation.event.AttributedDocumentEvent;
026import org.kuali.rice.core.api.util.type.KualiDecimal;
027import org.kuali.rice.kns.util.KNSGlobalVariables;
028import org.kuali.rice.krad.util.GlobalVariables;
029import org.kuali.rice.krad.util.ObjectUtils;
030
031import java.util.List;
032
033public class InvoiceTotalsValidation extends GenericValidation {
034
035    @Override
036    public boolean validate(AttributedDocumentEvent event) {
037        InvoiceDocument document = (InvoiceDocument) event.getDocument();
038        GlobalVariables.getMessageMap().clearErrorPath();
039        GlobalVariables.getMessageMap().addToErrorPath(OLEPropertyConstants.DOCUMENT);
040
041        String[] excludeArray = {PurapConstants.ItemTypeCodes.ITEM_TYPE_PMT_TERMS_DISCOUNT_CODE};
042
043        // if NO invoice amount
044        if (ObjectUtils.isNull(document.getVendorInvoiceAmount())) {
045            if (!KNSGlobalVariables.getMessageList().contains(PurapKeyConstants.WARNING_PAYMENT_REQUEST_VENDOR_INVOICE_AMOUNT_INVALID)) {
046                KNSGlobalVariables.getMessageList().add(PurapKeyConstants.WARNING_PAYMENT_REQUEST_VENDOR_INVOICE_AMOUNT_INVALID);
047            }
048        }
049        // if UseTax is included, then the invoiceInitialAmount should be compared against the
050        // total amount NOT INCLUDING tax
051        else if (document.isUseTaxIndicator()) {
052            if (document.getTotalPreTaxDollarAmountAllItems(excludeArray).compareTo(document.getVendorInvoiceAmount()) != 0
053                    && !document.isUnmatchedOverride()) {
054                if (!KNSGlobalVariables.getMessageList().contains(
055                        PurapKeyConstants.WARNING_PAYMENT_REQUEST_VENDOR_INVOICE_AMOUNT_INVALID)) {
056                    KNSGlobalVariables.getMessageList().add(
057                            PurapKeyConstants.WARNING_PAYMENT_REQUEST_VENDOR_INVOICE_AMOUNT_INVALID);
058                }
059            }
060        }
061        // if NO UseTax, then the invoiceInitialAmount should be compared against the
062        // total amount INCLUDING sales tax (since if the vendor invoices with sales tax, then we pay it)
063        else {
064            if (document.getTotalDollarAmountAllItems(excludeArray).compareTo(document.getVendorInvoiceAmount()) != 0
065                    && !document.isUnmatchedOverride()) {
066                if (!KNSGlobalVariables.getMessageList().contains(
067                        PurapKeyConstants.WARNING_PAYMENT_REQUEST_VENDOR_INVOICE_AMOUNT_INVALID)) {
068                    KNSGlobalVariables.getMessageList().add(
069                            PurapKeyConstants.WARNING_PAYMENT_REQUEST_VENDOR_INVOICE_AMOUNT_INVALID);
070                }
071            }
072        }
073
074        flagLineItemTotals(document.getItems());
075
076        GlobalVariables.getMessageMap().clearErrorPath();
077
078        //always returns true, as this is a warning, not an error
079        return true;
080    }
081
082    /**
083     * Calculates a total but excludes passed in item types from the totalling.
084     *
085     * @param itemList          - list of purap items
086     * @param excludedItemTypes - list of item types to exclude from totalling
087     * @return
088     */
089    protected KualiDecimal getTotalExcludingItemTypes(List<PurApItem> itemList, List<String> excludedItemTypes) {
090        KualiDecimal total = KualiDecimal.ZERO;
091        for (PurApItem item : itemList) {
092            if (item.getTotalAmount() != null && item.getTotalAmount().isNonZero()) {
093                boolean skipThisItem = false;
094                if (excludedItemTypes.contains(item.getItemTypeCode())) {
095                    // this item type is excluded
096                    skipThisItem = true;
097                    break;
098                }
099                if (skipThisItem) {
100                    continue;
101                }
102                total = total.add(item.getTotalAmount());
103            }
104        }
105        return total;
106    }
107
108    /**
109     * Flags with an erorr the item totals whos calculated extended price does not equal its extended price.
110     *
111     * @param itemList - list of purap items
112     */
113    protected void flagLineItemTotals(List<PurApItem> itemList) {
114        for (PurApItem purApItem : itemList) {
115            InvoiceItem item = (InvoiceItem) purApItem;
116            if (item.getItemQuantity() != null && item.getExtendedPrice() != null) {
117                if (item.calculateExtendedPrice().compareTo(item.getExtendedPrice()) != 0) {
118                    GlobalVariables.getMessageMap().putError(PurapConstants.ITEM_TAB_ERROR_PROPERTY, PurapKeyConstants.ERROR_PAYMENT_REQUEST_ITEM_TOTAL_NOT_EQUAL, item.getItemIdentifierString());
119                }
120            }
121        }
122    }
123
124}