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.fp.document.web.struts; 017 018 import static org.kuali.kfs.fp.document.validation.impl.AuxiliaryVoucherDocumentRuleConstants.AUXILIARY_VOUCHER_ACCOUNTING_PERIOD_GRACE_PERIOD; 019 import static org.kuali.kfs.sys.KFSConstants.AuxiliaryVoucher.ACCRUAL_DOC_TYPE; 020 import static org.kuali.kfs.sys.KFSConstants.AuxiliaryVoucher.ADJUSTMENT_DOC_TYPE; 021 import static org.kuali.kfs.sys.KFSConstants.AuxiliaryVoucher.RECODE_DOC_TYPE; 022 023 import java.sql.Date; 024 import java.util.ArrayList; 025 import java.util.Calendar; 026 import java.util.List; 027 028 import javax.servlet.http.HttpServletRequest; 029 030 import org.apache.commons.collections.CollectionUtils; 031 import org.apache.commons.collections.Predicate; 032 import org.kuali.kfs.coa.businessobject.AccountingPeriod; 033 import org.kuali.kfs.coa.service.AccountingPeriodService; 034 import org.kuali.kfs.fp.document.AuxiliaryVoucherDocument; 035 import org.kuali.kfs.fp.document.validation.impl.AuxiliaryVoucherDocumentRuleConstants; 036 import org.kuali.kfs.sys.KFSConstants; 037 import org.kuali.kfs.sys.context.SpringContext; 038 import org.kuali.kfs.sys.service.UniversityDateService; 039 import org.kuali.rice.kns.document.Document; 040 import org.kuali.rice.kns.service.DateTimeService; 041 import org.kuali.rice.kns.service.ParameterService; 042 043 /** 044 * Struts form so <code>{@link AuxiliaryVoucherDocument}</code> can be accessed and modified through UI. 045 */ 046 public class AuxiliaryVoucherForm extends VoucherForm { 047 protected String originalVoucherType = KFSConstants.AuxiliaryVoucher.ADJUSTMENT_DOC_TYPE; // keep this in sync with the default 048 049 // value set in the document business 050 // object 051 052 public AuxiliaryVoucherForm() { 053 super(); 054 } 055 056 @Override 057 protected String getDefaultDocumentTypeName() { 058 return "AV"; 059 } 060 061 /** 062 * Overrides the parent to call super.populate and then to call the two methods that are specific to loading the two select 063 * lists on the page. In addition, this also makes sure that the credit and debit amounts are filled in for situations where 064 * validation errors occur and the page reposts. 065 * 066 * @see org.kuali.rice.kns.web.struts.pojo.PojoForm#populate(javax.servlet.http.HttpServletRequest) 067 */ 068 public void populate(HttpServletRequest request) { 069 // populate the drop downs 070 super.populate(request); 071 populateReversalDateForRendering(); 072 } 073 074 /** 075 * @return Returns the serviceBillingDocument. 076 */ 077 public AuxiliaryVoucherDocument getAuxiliaryVoucherDocument() { 078 return (AuxiliaryVoucherDocument) getDocument(); 079 } 080 081 /** 082 * @param serviceBillingDocument The serviceBillingDocument to set. 083 */ 084 public void setAuxiliaryVoucherDocument(AuxiliaryVoucherDocument auxiliaryVoucherDocument) { 085 setDocument(auxiliaryVoucherDocument); 086 } 087 088 /** 089 * Gets today's date and then sets the day of the month as 15th, irrespective of the current day of the month 090 * @return the modified reversal date 091 */ 092 protected Date getAvReversalDate() { 093 java.sql.Date avReversalDate = SpringContext.getBean(DateTimeService.class).getCurrentSqlDateMidnight(); 094 095 Calendar cal = Calendar.getInstance(); 096 cal.setTime(avReversalDate); 097 098 int thisMonth; 099 100 if (getAuxiliaryVoucherDocument().getAccountingPeriod().getUniversityFiscalPeriodCode().equals(KFSConstants.MONTH13)) { 101 thisMonth = cal.JULY; 102 } else 103 thisMonth = getAuxiliaryVoucherDocument().getAccountingPeriod().getMonth(); 104 105 cal.set(Calendar.MONTH, (thisMonth)); 106 107 //if today's day > 15 then set the month to next month. 108 // if (cal.get(Calendar.DAY_OF_MONTH) > KFSConstants.AuxiliaryVoucher.ACCRUAL_DOC_DAY_OF_MONTH) { 109 // cal.add(Calendar.MONTH, 1); 110 // } 111 cal.set(Calendar.DAY_OF_MONTH, KFSConstants.AuxiliaryVoucher.ACCRUAL_DOC_DAY_OF_MONTH); 112 long timeInMillis = cal.getTimeInMillis(); 113 avReversalDate.setTime(timeInMillis); 114 115 return avReversalDate; 116 } 117 118 /** 119 * Handles special case display rules for displaying Reversal Date at UI layer 120 */ 121 public void populateReversalDateForRendering() { 122 java.sql.Date today = getAvReversalDate(); 123 124 if (getAuxiliaryVoucherDocument().getTypeCode().equals(ACCRUAL_DOC_TYPE)) { 125 getAuxiliaryVoucherDocument().setReversalDate(today); 126 } 127 else if (getAuxiliaryVoucherDocument().getTypeCode().equals(ADJUSTMENT_DOC_TYPE)) { 128 getAuxiliaryVoucherDocument().setReversalDate(null); 129 } 130 else if (getAuxiliaryVoucherDocument().getTypeCode().equals(RECODE_DOC_TYPE)) { 131 getAuxiliaryVoucherDocument().setReversalDate(new java.sql.Date(getDocument().getDocumentHeader().getWorkflowDocument().getCreateDate().getTime())); 132 } 133 } 134 135 /** 136 * This method returns the reversal date in the format MMM d, yyyy. 137 * 138 * @return String 139 */ 140 public String getFormattedReversalDate() { 141 return formatReversalDate(getAuxiliaryVoucherDocument().getReversalDate()); 142 } 143 144 /** 145 * @return String 146 */ 147 public String getOriginalVoucherType() { 148 return originalVoucherType; 149 } 150 151 /** 152 * @param originalVoucherType 153 */ 154 public void setOriginalVoucherType(String originalVoucherType) { 155 this.originalVoucherType = originalVoucherType; 156 } 157 158 /** 159 * Returns a formatted auxiliary voucher type: <Voucher Type Name> (<Voucher Type Code>) 160 * 161 * @return 162 */ 163 public String getFormattedAuxiliaryVoucherType() { 164 String voucherTypeCode = getAuxiliaryVoucherDocument().getTypeCode(); 165 String formattedVoucherType = new String(); 166 167 if (KFSConstants.AuxiliaryVoucher.ACCRUAL_DOC_TYPE.equals(voucherTypeCode)) { 168 formattedVoucherType = KFSConstants.AuxiliaryVoucher.ACCRUAL_DOC_TYPE_NAME; 169 } 170 else if (KFSConstants.AuxiliaryVoucher.ADJUSTMENT_DOC_TYPE.equals(voucherTypeCode)) { 171 formattedVoucherType = KFSConstants.AuxiliaryVoucher.ADJUSTMENT_DOC_TYPE_NAME; 172 } 173 else if (KFSConstants.AuxiliaryVoucher.RECODE_DOC_TYPE.equals(voucherTypeCode)) { 174 formattedVoucherType = KFSConstants.AuxiliaryVoucher.RECODE_DOC_TYPE_NAME; 175 } 176 else { 177 throw new IllegalStateException("Invalid auxiliary voucher type code: " + voucherTypeCode); 178 } 179 180 return formattedVoucherType + " (" + voucherTypeCode + ")"; 181 } 182 183 /** 184 * This method generates a proper list of valid accounting periods that the user can select from. 185 * 186 * @see org.kuali.kfs.fp.document.web.struts.VoucherForm#populateAccountingPeriodListForRendering() 187 */ 188 @Override 189 public void populateAccountingPeriodListForRendering() { 190 // grab the list of valid accounting periods 191 ArrayList accountingPeriods = new ArrayList(SpringContext.getBean(AccountingPeriodService.class).getOpenAccountingPeriods()); 192 // now, validate further, based on the rules from AuxiliaryVoucherDocumentRule 193 ArrayList filteredAccountingPeriods = new ArrayList(); 194 filteredAccountingPeriods.addAll(CollectionUtils.select(accountingPeriods, new OpenAuxiliaryVoucherPredicate(this.getDocument()))); 195 // if our auxiliary voucher doc contains an accounting period already, make sure the collection has it too! 196 if (this.getDocument() instanceof AuxiliaryVoucherDocument) { 197 AuxiliaryVoucherDocument avDoc = (AuxiliaryVoucherDocument) this.getDocument(); 198 if (avDoc != null && avDoc.getAccountingPeriod() != null && !filteredAccountingPeriods.contains(avDoc.getAccountingPeriod())) { 199 // this is most likely going to happen because the approver is trying 200 // to approve a document after the grace period of an accounting period 201 // or a fiscal year has switched over when the document was first created; 202 // as such, it's probably a good bet that the doc's accounting period 203 // belongs at the top of the list 204 filteredAccountingPeriods.add(0, avDoc.getAccountingPeriod()); 205 } 206 } 207 // set into the form for rendering 208 setAccountingPeriods(filteredAccountingPeriods); 209 // set the chosen accounting period into the form 210 populateSelectedVoucherAccountingPeriod(); 211 } 212 213 protected class OpenAuxiliaryVoucherPredicate implements Predicate { 214 protected ParameterService parameterService; 215 protected UniversityDateService dateService; 216 protected AccountingPeriodService acctPeriodService; 217 protected Document auxiliaryVoucherDocument; 218 protected AccountingPeriod currPeriod; 219 protected java.sql.Date currentDate; 220 protected Integer currentFiscalYear; 221 222 public OpenAuxiliaryVoucherPredicate(Document doc) { 223 this.parameterService = SpringContext.getBean(ParameterService.class); 224 this.dateService = SpringContext.getBean(UniversityDateService.class); 225 this.acctPeriodService = SpringContext.getBean(AccountingPeriodService.class); 226 this.auxiliaryVoucherDocument = doc; 227 this.currPeriod = acctPeriodService.getByDate(new java.sql.Date(new java.util.GregorianCalendar().getTimeInMillis())); 228 this.currentDate = new java.sql.Date(new java.util.Date().getTime()); 229 this.currentFiscalYear = dateService.getCurrentFiscalYear(); 230 } 231 232 public boolean evaluate(Object o) { 233 boolean result = false; 234 if (o instanceof AccountingPeriod) { 235 AccountingPeriod period = (AccountingPeriod) o; 236 result = parameterService.getParameterEvaluator(AuxiliaryVoucherDocument.class, AuxiliaryVoucherDocumentRuleConstants.RESTRICTED_PERIOD_CODES, period.getUniversityFiscalPeriodCode()).evaluationSucceeds(); 237 if (result) { 238 result = (period.getUniversityFiscalYear().equals( currentFiscalYear )); 239 if (result) { 240 // did this accounting period end before now? 241 result = acctPeriodService.compareAccountingPeriodsByDate(period, currPeriod) >= 0; 242 if (!result) { 243 // if yes, are we still in the grace period? 244 result = getAuxiliaryVoucherDocument().calculateIfWithinGracePeriod(currentDate, period); 245 } 246 } 247 else { 248 // are we in current in the grace period of an ending accounting period of the previous fiscal year? 249 result = getAuxiliaryVoucherDocument().calculateIfWithinGracePeriod(currentDate, period) && getAuxiliaryVoucherDocument().isEndOfPreviousFiscalYear(period); 250 } 251 } 252 } 253 return result; 254 } 255 } 256 257 public List<String> getAccountingPeriodCompositeValueList() { 258 List<String> accountingPeriodCompositeValueList = new ArrayList<String>(); 259 for (int i = 0; i < this.getAccountingPeriods().size(); i++) { 260 AccountingPeriod temp = (AccountingPeriod) this.getAccountingPeriods().get(i); 261 accountingPeriodCompositeValueList.add(temp.getUniversityFiscalPeriodCode() + temp.getUniversityFiscalYear()); 262 } 263 264 return accountingPeriodCompositeValueList; 265 } 266 267 public List<String> getAccountingPeriodLabelList() { 268 List<String> accountingPeriodLabelList = new ArrayList<String>(); 269 for (int i = 0; i < this.getAccountingPeriods().size(); i++) { 270 AccountingPeriod temp = (AccountingPeriod) this.getAccountingPeriods().get(i); 271 accountingPeriodLabelList.add(temp.getUniversityFiscalPeriodName()); 272 } 273 274 return accountingPeriodLabelList; 275 } 276 }