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    }