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.PurapParameterConstants; 022 import org.kuali.kfs.module.purap.PurapConstants.PREQDocumentsStrings; 023 import org.kuali.kfs.module.purap.document.AccountsPayableDocument; 024 import org.kuali.kfs.module.purap.document.PaymentRequestDocument; 025 import org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument; 026 import org.kuali.kfs.module.purap.document.service.PaymentRequestService; 027 import org.kuali.kfs.module.purap.document.service.PurapService; 028 import org.kuali.kfs.module.purap.document.validation.event.AttributedExpiredAccountWarningEvent; 029 import org.kuali.kfs.module.purap.document.validation.event.AttributedTradeInWarningEvent; 030 import org.kuali.kfs.sys.KFSConstants; 031 import org.kuali.kfs.sys.KFSKeyConstants; 032 import org.kuali.kfs.sys.context.SpringContext; 033 import org.kuali.kfs.sys.service.UniversityDateService; 034 import org.kuali.kfs.sys.service.impl.KfsParameterConstants; 035 import org.kuali.rice.kns.document.Document; 036 import org.kuali.rice.kns.service.KualiConfigurationService; 037 import org.kuali.rice.kns.service.KualiRuleService; 038 import org.kuali.rice.kns.service.ParameterService; 039 import org.kuali.rice.kns.web.format.CurrencyFormatter; 040 041 /** 042 * Business pre rule(s) applicable to Payment Request documents. 043 */ 044 public class PaymentRequestDocumentPreRules extends AccountsPayableDocumentPreRulesBase { 045 046 /** 047 * Default Constructor 048 */ 049 public PaymentRequestDocumentPreRules() { 050 super(); 051 } 052 053 /** 054 * Main hook point to perform rules check. 055 * 056 * @see org.kuali.rice.kns.rules.PromptBeforeValidationBase#doRules(org.kuali.rice.kns.document.Document) 057 */ 058 @Override 059 public boolean doPrompts(Document document) { 060 boolean preRulesOK = true; 061 062 PaymentRequestDocument preq = (PaymentRequestDocument) document; 063 if ((!SpringContext.getBean(PurapService.class).isFullDocumentEntryCompleted(preq)) || (StringUtils.equals(preq.getStatusCode(), PurapConstants.PaymentRequestStatuses.AWAITING_ACCOUNTS_PAYABLE_REVIEW))) { 064 if (!confirmPayDayNotOverThresholdDaysAway(preq)) { 065 return false; 066 } 067 if (!confirmUnusedTradeIn(preq)) { 068 return false; 069 } 070 if (!confirmEncumberNextFiscalYear(preq)) { 071 return false; 072 } 073 074 if (!confirmEncumberPriorFiscalYear(preq)) { 075 return false; 076 } 077 } 078 if (SpringContext.getBean(PurapService.class).isFullDocumentEntryCompleted(preq)) { 079 if (!confirmExpiredAccount(preq)) { 080 return false; 081 } 082 } 083 084 085 086 preRulesOK &= super.doPrompts(document); 087 return preRulesOK; 088 } 089 090 /** 091 * Prompts user to confirm with a Yes or No to a question being asked. 092 * 093 * @param questionType - type of question 094 * @param messageConstant - key to retrieve message 095 * @return - true if overriding, false otherwise 096 */ 097 protected boolean askForConfirmation(String questionType, String messageConstant) { 098 099 String questionText = SpringContext.getBean(KualiConfigurationService.class).getPropertyString(messageConstant); 100 if (questionText.contains("{")) { 101 questionText = prepareQuestionText(questionType, questionText); 102 } 103 else if (StringUtils.equals(messageConstant, KFSKeyConstants.ERROR_ACCOUNT_EXPIRED) || StringUtils.equals(messageConstant,PurapKeyConstants.WARNING_ITEM_TRADE_IN_AMOUNT_UNUSED)) { 104 questionText = questionType; 105 } 106 107 108 boolean confirmOverride = super.askOrAnalyzeYesNoQuestion(questionType, questionText); 109 110 if (!confirmOverride) { 111 event.setActionForwardName(KFSConstants.MAPPING_BASIC); 112 return false; 113 } 114 return true; 115 } 116 117 /** 118 * Creates the actual text of the question, replacing place holders like pay date threshold with an actual constant value. 119 * 120 * @param questionType - type of question 121 * @param questionText - actual text of question pulled from resource file 122 * @return - question text with place holders replaced 123 */ 124 protected String prepareQuestionText(String questionType, String questionText) { 125 if (StringUtils.equals(questionType, PREQDocumentsStrings.THRESHOLD_DAYS_OVERRIDE_QUESTION)) { 126 questionText = StringUtils.replace(questionText, "{0}", new Integer(PurapConstants.PREQ_PAY_DATE_DAYS_BEFORE_WARNING).toString()); 127 } 128 return questionText; 129 } 130 131 /** 132 * Validates if the pay date threshold has not been passed, if so confirmation is required by the user to 133 * exceed the threshold. 134 * 135 * @param preq - payment request document 136 * @return - true if threshold has not been surpassed or if user confirmed ok to override, false otherwise 137 */ 138 public boolean confirmPayDayNotOverThresholdDaysAway(PaymentRequestDocument preq) { 139 140 // If the pay date is more than the threshold number of days in the future, ask for confirmation. 141 //boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new AttributedPayDateNotOverThresholdDaysAwayEvent("", preq)); 142 143 //if (!rulePassed) { 144 // The problem is that rulePassed always return true 145 int thresholdDays = PurapConstants.PREQ_PAY_DATE_DAYS_BEFORE_WARNING; 146 if ((preq.getPaymentRequestPayDate() != null) && SpringContext.getBean(PurapService.class).isDateMoreThanANumberOfDaysAway(preq.getPaymentRequestPayDate(), thresholdDays)) { 147 return askForConfirmation(PREQDocumentsStrings.THRESHOLD_DAYS_OVERRIDE_QUESTION, PurapKeyConstants.MESSAGE_PAYMENT_REQUEST_PAYDATE_OVER_THRESHOLD_DAYS); 148 } 149 return true; 150 } 151 152 public boolean confirmUnusedTradeIn(PaymentRequestDocument preq) { 153 boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new AttributedTradeInWarningEvent("", preq)); 154 155 if (!rulePassed) { 156 return askForConfirmation(PREQDocumentsStrings.UNUSED_TRADE_IN_QUESTION, PurapKeyConstants.WARNING_ITEM_TRADE_IN_AMOUNT_UNUSED); 157 } 158 return true; 159 } 160 161 public boolean confirmExpiredAccount(PaymentRequestDocument preq) { 162 boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new AttributedExpiredAccountWarningEvent("", preq)); 163 164 if (!rulePassed) { 165 return askForConfirmation(PREQDocumentsStrings.EXPIRED_ACCOUNT_QUESTION, KFSKeyConstants.ERROR_ACCOUNT_EXPIRED); 166 } 167 return true; 168 } 169 170 public boolean confirmEncumberNextFiscalYear(PaymentRequestDocument preq) { 171 Integer fiscalYear = SpringContext.getBean(UniversityDateService.class).getCurrentFiscalYear(); 172 if (preq.getPurchaseOrderDocument().getPostingYear().intValue() > fiscalYear) { 173 return askForConfirmation(PREQDocumentsStrings.ENCUMBER_NEXT_FISCAL_YEAR_QUESTION, PurapKeyConstants.WARNING_ENCUMBER_NEXT_FY); 174 } 175 176 return true; 177 } 178 179 public boolean confirmEncumberPriorFiscalYear(PaymentRequestDocument preq) { 180 181 Integer fiscalYear = SpringContext.getBean(UniversityDateService.class).getCurrentFiscalYear(); 182 if (preq.getPurchaseOrderDocument().getPostingYear().intValue() == fiscalYear && SpringContext.getBean(PaymentRequestService.class).allowBackpost(preq)) { 183 return askForConfirmation(PREQDocumentsStrings.ENCUMBER_PRIOR_FISCAL_YEAR_QUESTION, PurapKeyConstants.WARNING_ENCUMBER_PRIOR_FY); 184 } 185 return true; 186 } 187 188 /** 189 * @see org.kuali.kfs.module.purap.document.validation.impl.AccountsPayableDocumentPreRulesBase#getDocumentName() 190 */ 191 @Override 192 public String getDocumentName() { 193 return "Payment Request"; 194 } 195 196 /** 197 * @see org.kuali.kfs.module.purap.document.validation.impl.AccountsPayableDocumentPreRulesBase#createInvoiceNoMatchQuestionText(org.kuali.kfs.module.purap.document.AccountsPayableDocument) 198 */ 199 @Override 200 public String createInvoiceNoMatchQuestionText(AccountsPayableDocument accountsPayableDocument){ 201 202 String questionText = super.createInvoiceNoMatchQuestionText(accountsPayableDocument); 203 204 CurrencyFormatter cf = new CurrencyFormatter(); 205 PaymentRequestDocument preq = (PaymentRequestDocument) accountsPayableDocument; 206 207 StringBuffer questionTextBuffer = new StringBuffer(""); 208 questionTextBuffer.append(questionText); 209 210 questionTextBuffer.append("[br][br][b]Summary Detail Below:[b][br][br][table questionTable]"); 211 questionTextBuffer.append("[tr][td leftTd]Vendor Invoice Amount entered on start screen:[/td][td rightTd]" + (String)cf.format(preq.getInitialAmount()) + "[/td][/tr]"); 212 questionTextBuffer.append("[tr][td leftTd]Invoice Total Prior to Additional Charges:[/td][td rightTd]" + (String)cf.format(preq.getTotalPreTaxDollarAmountAboveLineItems()) + "[/td][/tr]"); 213 214 215 //only add this line if payment request has a discount 216 if( preq.isDiscount() ){ 217 questionTextBuffer.append("[tr][td leftTd]Total Before Discount:[/td][td rightTd]" + (String)cf.format(preq.getGrandPreTaxTotalExcludingDiscount()) + "[/td][/tr]"); 218 } 219 220 //if sales tax is enabled, show additional summary lines 221 boolean salesTaxInd = SpringContext.getBean(ParameterService.class).getIndicatorParameter(KfsParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.ENABLE_SALES_TAX_IND); 222 if(salesTaxInd){ 223 questionTextBuffer.append("[tr][td leftTd]Grand Total Prior to Tax:[/td][td rightTd]" + (String)cf.format(preq.getGrandPreTaxTotal()) + "[/td][/tr]"); 224 questionTextBuffer.append("[tr][td leftTd]Grand Total Tax:[/td][td rightTd]" + (String)cf.format(preq.getGrandTaxAmount()) + "[/td][/tr]"); 225 } 226 227 questionTextBuffer.append("[tr][td leftTd]Grand Total:[/td][td rightTd]" + (String)cf.format(preq.getGrandTotal()) + "[/td][/tr][/table]"); 228 229 return questionTextBuffer.toString(); 230 231 } 232 @Override 233 protected boolean checkCAMSWarningStatus(PurchasingAccountsPayableDocument purapDocument) { 234 return PurapConstants.CAMSWarningStatuses.PAYMENT_REQUEST_STATUS_WARNING_NO_CAMS_DATA.contains(purapDocument.getStatusCode()); 235 } 236 237 }