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 }