001: /*
002: * Copyright 2005-2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.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/ecl1.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.module.financial.document;
017:
018: import static org.kuali.kfs.KFSConstants.EMPTY_STRING;
019: import static org.kuali.kfs.KFSConstants.GL_CREDIT_CODE;
020: import static org.kuali.kfs.KFSConstants.GL_DEBIT_CODE;
021: import static org.kuali.kfs.KFSConstants.AuxiliaryVoucher.ACCRUAL_DOC_TYPE;
022: import static org.kuali.kfs.KFSConstants.AuxiliaryVoucher.ADJUSTMENT_DOC_TYPE;
023: import static org.kuali.kfs.KFSConstants.AuxiliaryVoucher.RECODE_DOC_TYPE;
024:
025: import java.util.Iterator;
026: import java.util.List;
027:
028: import org.apache.commons.lang.StringUtils;
029: import org.kuali.core.document.AmountTotaling;
030: import org.kuali.core.document.Copyable;
031: import org.kuali.core.document.Correctable;
032: import org.kuali.core.service.DateTimeService;
033: import org.kuali.core.util.KualiDecimal;
034: import org.kuali.kfs.KFSConstants;
035: import org.kuali.kfs.bo.AccountingLineBase;
036: import org.kuali.kfs.bo.AccountingLineParser;
037: import org.kuali.kfs.bo.GeneralLedgerPendingEntry;
038: import org.kuali.kfs.bo.SourceAccountingLine;
039: import org.kuali.kfs.context.SpringContext;
040: import org.kuali.kfs.document.AccountingDocumentBase;
041: import org.kuali.module.financial.bo.AuxiliaryVoucherAccountingLineParser;
042:
043: import edu.iu.uis.eden.exception.WorkflowException;
044:
045: /**
046: * This is the business object that represents the AuxiliaryVoucherDocument in Kuali. This is a transactional document that will
047: * eventually post transactions to the G/L. It integrates with workflow and also contains two groupings of accounting lines: Expense
048: * and target. Expense is the expense and target is the income lines.
049: */
050: public class AuxiliaryVoucherDocument extends AccountingDocumentBase
051: implements VoucherDocument, Copyable, Correctable,
052: AmountTotaling {
053: private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger
054: .getLogger(AuxiliaryVoucherDocument.class);
055:
056: private String typeCode = ADJUSTMENT_DOC_TYPE;
057: private java.sql.Date reversalDate;
058:
059: /**
060: * @see org.kuali.kfs.document.AccountingDocumentBase#documentPerformsSufficientFundsCheck()
061: */
062: @Override
063: public boolean documentPerformsSufficientFundsCheck() {
064: if (isRecodeType()) {
065: return super .documentPerformsSufficientFundsCheck();
066: } else {
067: return false;
068: }
069: }
070:
071: /**
072: * Initializes the array lists and some basic info.
073: */
074: public AuxiliaryVoucherDocument() {
075: super ();
076: }
077:
078: /**
079: * Read Accessor for Reversal Date
080: *
081: * @return java.sql.Date
082: */
083: public java.sql.Date getReversalDate() {
084: return reversalDate;
085: }
086:
087: /**
088: * Write Accessor for Reversal Date
089: *
090: * @param reversalDate
091: */
092: public void setReversalDate(java.sql.Date reversalDate) {
093: this .reversalDate = reversalDate;
094: }
095:
096: /**
097: * Read Accessor for Auxiliary Voucher Type
098: *
099: * @return String
100: */
101: public String getTypeCode() {
102: return typeCode;
103: }
104:
105: /**
106: * Write Accessor for Auxiliary Voucher Type
107: *
108: * @param typeCode
109: */
110: public void setTypeCode(String typeCode) {
111: this .typeCode = typeCode;
112: }
113:
114: /**
115: * A helper to test whether this document is an adjustment type AV.
116: *
117: * @return boolean
118: */
119: public boolean isAdjustmentType() {
120: return ADJUSTMENT_DOC_TYPE.equals(typeCode);
121: }
122:
123: /**
124: * A helper to test whether this document is an recode type AV.
125: *
126: * @return boolean
127: */
128: public boolean isRecodeType() {
129: return RECODE_DOC_TYPE.equals(typeCode);
130: }
131:
132: /**
133: * A helper to test whether this document is an accrual type AV.
134: *
135: * @return boolean
136: */
137: public boolean isAccrualType() {
138: return ACCRUAL_DOC_TYPE.equals(typeCode);
139: }
140:
141: /**
142: * This method calculates the debit total for a JV document keying off of the debit/debit code, only summing the accounting
143: * lines with a debitDebitCode that matched the debit constant, and returns the results.
144: *
145: * @return KualiDecimal
146: */
147: public KualiDecimal getDebitTotal() {
148: KualiDecimal debitTotal = new KualiDecimal(0);
149: AccountingLineBase al = null;
150: Iterator iter = sourceAccountingLines.iterator();
151: while (iter.hasNext()) {
152: al = (AccountingLineBase) iter.next();
153: if (StringUtils.isNotBlank(al.getDebitCreditCode())
154: && al.getDebitCreditCode().equals(
155: KFSConstants.GL_DEBIT_CODE)) {
156: debitTotal = debitTotal.add(al.getAmount());
157: }
158: }
159: return debitTotal;
160: }
161:
162: /**
163: * This method calculates the credit total for a JV document keying off of the debit/credit code, only summing the accounting
164: * lines with a debitCreditCode that matched the debit constant, and returns the results.
165: *
166: * @return KualiDecimal
167: */
168: public KualiDecimal getCreditTotal() {
169: KualiDecimal creditTotal = new KualiDecimal(0);
170: AccountingLineBase al = null;
171: Iterator iter = sourceAccountingLines.iterator();
172: while (iter.hasNext()) {
173: al = (AccountingLineBase) iter.next();
174: if (StringUtils.isNotBlank(al.getDebitCreditCode())
175: && al.getDebitCreditCode().equals(
176: KFSConstants.GL_CREDIT_CODE)) {
177: creditTotal = creditTotal.add(al.getAmount());
178: }
179: }
180: return creditTotal;
181: }
182:
183: /**
184: * Same as default implementation but uses debit / credit totals instead. Meaning it returns either credit or if 0, debit.
185: *
186: * @see org.kuali.kfs.document.AccountingDocumentBase#getTotalDollarAmount()
187: * @return KualiDecimal
188: */
189: @Override
190: public KualiDecimal getTotalDollarAmount() {
191: return getCreditTotal().equals(KualiDecimal.ZERO) ? getDebitTotal()
192: : getCreditTotal();
193: }
194:
195: /**
196: * Overrides to call super and then change the reversal date if the type is accrual and the date is greater than the set
197: * reversal date.
198: */
199: @Override
200: public void handleRouteStatusChange() {
201: LOG.debug("In handleRouteStatusChange() for AV documents");
202: super .handleRouteStatusChange();
203:
204: if (this .getDocumentHeader().getWorkflowDocument()
205: .stateIsProcessed()) { // only do this stuff if the document has been
206: // processed and approved
207: // update the reversal data accoringdingly
208: updateReversalDate();
209: }
210: }
211:
212: /**
213: * This method handles updating the reversal data on the document in addition to all of the GLPEs, but only for the accrual and
214: * recode types.
215: */
216: private void updateReversalDate() {
217: if (isAccrualType() || isRecodeType()) {
218: java.sql.Date today = SpringContext.getBean(
219: DateTimeService.class).getCurrentSqlDateMidnight();
220: if (getReversalDate().before(today)) {
221: // set the reversal date on the document
222: setReversalDate(today);
223:
224: // set the reversal date on each GLPE for the document too
225: List<GeneralLedgerPendingEntry> glpes = getGeneralLedgerPendingEntries();
226: for (GeneralLedgerPendingEntry entry : glpes) {
227: entry
228: .setFinancialDocumentReversalDate(getReversalDate());
229: }
230: }
231: }
232: }
233:
234: /**
235: * Overrides the base implementation to return "From".
236: *
237: * @see org.kuali.kfs.document.AccountingDocument#getSourceAccountingLinesSectionTitle()
238: */
239: @Override
240: public String getSourceAccountingLinesSectionTitle() {
241: return EMPTY_STRING;
242: }
243:
244: /**
245: * @see org.kuali.kfs.document.AccountingDocumentBase#getAccountingLineParser()
246: */
247: @Override
248: public AccountingLineParser getAccountingLineParser() {
249: return new AuxiliaryVoucherAccountingLineParser();
250: }
251:
252: /**
253: * @see org.kuali.kfs.document.AccountingDocumentBase#toErrorCorrection()
254: */
255: @Override
256: public void toErrorCorrection() throws WorkflowException {
257: super .toErrorCorrection();
258: processAuxiliaryVoucherErrorCorrections();
259: }
260:
261: /**
262: * KULEDOCS-1700 This method iterates over each source line and flip the sign on the amount to nullify the super's effect, then
263: * flip the debit/credit code b/c an error corrected AV flips the debit/credit code.
264: */
265: private void processAuxiliaryVoucherErrorCorrections() {
266: Iterator i = getSourceAccountingLines().iterator();
267:
268: int index = 0;
269: while (i.hasNext()) {
270: SourceAccountingLine sLine = (SourceAccountingLine) i
271: .next();
272:
273: String debitCreditCode = sLine.getDebitCreditCode();
274:
275: if (StringUtils.isNotBlank(debitCreditCode)) {
276: // negate the amount to to nullify the effects of the super, b/c super flipped it the first time through
277: sLine.setAmount(sLine.getAmount().negated()); // offsets the effect the super
278:
279: // now just flip the debit/credit code
280: if (GL_DEBIT_CODE.equals(debitCreditCode)) {
281: sLine.setDebitCreditCode(GL_CREDIT_CODE);
282: } else if (GL_CREDIT_CODE.equals(debitCreditCode)) {
283: sLine.setDebitCreditCode(GL_DEBIT_CODE);
284: } else {
285: throw new IllegalStateException(
286: "SourceAccountingLine at index "
287: + index
288: + " does not have a debit/credit "
289: + "code associated with it. This should never have occured. Please contact your system administrator.");
290:
291: }
292: index++;
293: }
294: }
295: }
296: }
|