001/*
002 * Copyright 2007 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.apache.commons.lang.StringUtils;
019import org.kuali.ole.module.purap.PurapConstants;
020import org.kuali.ole.module.purap.PurapKeyConstants;
021import org.kuali.ole.module.purap.document.PurchaseOrderDocument;
022import org.kuali.ole.module.purap.document.PurchasingAccountsPayableDocument;
023import org.kuali.ole.module.purap.document.PurchasingDocument;
024import org.kuali.ole.module.purap.document.service.PurapService;
025import org.kuali.ole.sys.OLEConstants;
026import org.kuali.ole.sys.context.SpringContext;
027import org.kuali.ole.sys.document.AmountTotaling;
028import org.kuali.rice.core.api.config.property.ConfigurationService;
029import org.kuali.rice.core.api.util.type.KualiDecimal;
030import org.kuali.rice.kns.util.KNSGlobalVariables;
031import org.kuali.rice.krad.document.Document;
032import org.kuali.rice.krad.util.ObjectUtils;
033
034/**
035 * Business Prerules applicable to purchase order document.
036 */
037public class PurchaseOrderDocumentPreRules extends PurchasingDocumentPreRulesBase {
038
039    /**
040     * Overrides the method in PromptBeforeValidationBase to also invoke the confirmNotToExceedOverride if the PromptBeforeValidationEvent is
041     * blank and the question matches with the OverrideNotToExceed
042     *
043     * @param document The purchase order document upon which we're performing the prerules logic.
044     * @return boolean true if it passes the pre rules conditions.
045     * @see org.kuali.rice.kns.rules.PromptBeforeValidationBase#doRules(org.kuali.rice.krad.document.Document)
046     */
047    @Override
048    public boolean doPrompts(Document document) {
049
050        boolean preRulesOK = true;
051
052        PurchaseOrderDocument purchaseOrderDocument = (PurchaseOrderDocument) document;
053
054        if (StringUtils.isBlank(event.getQuestionContext()) || StringUtils.equals(question, PurapConstants.PO_OVERRIDE_NOT_TO_EXCEED_QUESTION)) {
055            preRulesOK &= confirmNotToExceedOverride(purchaseOrderDocument);
056        }
057
058        if (isDocumentInStateToReceiveNextFyWarning(purchaseOrderDocument) &&
059                (StringUtils.isBlank(event.getQuestionContext()) || StringUtils.equals(question, PurapConstants.PO_NEXT_FY_WARNING))) {
060            preRulesOK &= confirmNextFYPriorToApoAllowedDate(purchaseOrderDocument);
061        }
062
063        if (!purchaseOrderDocument.isUseTaxIndicator()) {
064            preRulesOK &= checkForTaxRecalculation(purchaseOrderDocument);
065        }
066
067        return preRulesOK;
068    }
069
070    /**
071     * Give next FY warning if the PO status is "In Process" or "Awaiting Purchasing Review"
072     *
073     * @param poDocument
074     * @return boolean
075     */
076    protected boolean isDocumentInStateToReceiveNextFyWarning(PurchaseOrderDocument poDocument) {
077        return (PurapConstants.PurchaseOrderStatuses.APPDOC_IN_PROCESS.equals(poDocument.getApplicationDocumentStatus()) ||
078                PurapConstants.PurchaseOrderStatuses.APPDOC_AWAIT_PURCHASING_REVIEW.equals(poDocument.getApplicationDocumentStatus()));
079    }
080
081    /**
082     * Checks whether the 'Not-to-exceed' amount has been exceeded by the purchase order total dollar limit. If so, it
083     * prompts the user for confirmation.
084     *
085     * @param purchaseOrderDocument The current PurchaseOrderDocument
086     * @return True if the 'Not-to-exceed' amount is to be overridden or if the total dollar amount is less than the purchase order
087     *         total dollar limit.
088     */
089    protected boolean confirmNotToExceedOverride(PurchaseOrderDocument purchaseOrderDocument) {
090
091        // If the total exceeds the limit, ask for confirmation.
092        if (!validateTotalDollarAmountIsLessThanPurchaseOrderTotalLimit(purchaseOrderDocument)) {
093            String questionText = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(PurapKeyConstants.PURCHASE_ORDER_QUESTION_OVERRIDE_NOT_TO_EXCEED);
094
095            boolean confirmOverride = super.askOrAnalyzeYesNoQuestion(PurapConstants.PO_OVERRIDE_NOT_TO_EXCEED_QUESTION, questionText);
096
097            // Set a marker to record that this method has been used.
098            if (confirmOverride && StringUtils.isBlank(event.getQuestionContext())) {
099                event.setQuestionContext(PurapConstants.PO_OVERRIDE_NOT_TO_EXCEED_QUESTION);
100            }
101
102            if (!confirmOverride) {
103                event.setActionForwardName(OLEConstants.MAPPING_BASIC);
104
105                return false;
106            }
107        }
108
109        return true;
110    }
111
112    /**
113     * Validate that if the PurchaseOrderTotalLimit is not null then the TotalDollarAmount cannot be greater than the
114     * PurchaseOrderTotalLimit.
115     *
116     * @param purDocument The purchase order document to be validated.
117     * @return True if the TotalDollarAmount is less than the PurchaseOrderTotalLimit. False otherwise.
118     */
119    public boolean validateTotalDollarAmountIsLessThanPurchaseOrderTotalLimit(PurchasingDocument purDocument) {
120        boolean valid = true;
121        if (ObjectUtils.isNotNull(purDocument.getPurchaseOrderTotalLimit()) && ObjectUtils.isNotNull(((AmountTotaling) purDocument).getTotalDollarAmount())) {
122            KualiDecimal totalAmount = ((AmountTotaling) purDocument).getTotalDollarAmount();
123            if (((AmountTotaling) purDocument).getTotalDollarAmount().isGreaterThan(purDocument.getPurchaseOrderTotalLimit())) {
124                valid &= false;
125                KNSGlobalVariables.getMessageList().add(PurapKeyConstants.PO_TOTAL_GREATER_THAN_PO_TOTAL_LIMIT);
126            }
127        }
128
129        return valid;
130    }
131
132    /**
133     * If the PO is set to encumber in the next fiscal year and the PO is created before the APO allowed date, then give the user a
134     * warning that this might be a mistake. Prompt the user for confirmation that the year is set correctly both at submit and upon
135     * approval at the Purchasing Internal Review route level.
136     *
137     * @param purchaseOrderDocument The current PurchaseOrderDocument
138     * @return True if the user wants to continue with PO routing; False to send the user back to the PO for editing.
139     */
140    protected boolean confirmNextFYPriorToApoAllowedDate(PurchaseOrderDocument poDocument) {
141
142        // If the FY is set to NEXT and today is not within APO allowed range, ask for confirmation to continue
143        if (poDocument.isPostingYearNext() && !SpringContext.getBean(PurapService.class).isTodayWithinApoAllowedRange()) {
144            String questionText = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(PurapKeyConstants.WARNING_PURCHASE_ORDER_ENCUMBER_NEXT_FY);
145            boolean confirmOverride = super.askOrAnalyzeYesNoQuestion(PurapConstants.PO_NEXT_FY_WARNING, questionText);
146
147            // Set a marker to record that this method has been used.
148            if (confirmOverride && StringUtils.isBlank(event.getQuestionContext())) {
149                event.setQuestionContext(PurapConstants.PO_NEXT_FY_WARNING);
150            }
151            if (!confirmOverride) {
152                event.setActionForwardName(OLEConstants.MAPPING_BASIC);
153                return false;
154            }
155        }
156
157        return true;
158    }
159
160    @Override
161    protected boolean checkCAMSWarningStatus(PurchasingAccountsPayableDocument purapDocument) {
162        return PurapConstants.CAMSWarningStatuses.PURCHASEORDER_STATUS_WARNING_NO_CAMS_DATA.contains(purapDocument.getApplicationDocumentStatus());
163    }
164
165}