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