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 }