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;
017    
018    import java.sql.Date;
019    import java.util.Iterator;
020    import java.util.List;
021    
022    import org.apache.commons.lang.StringUtils;
023    import org.kuali.kfs.fp.businessobject.BasicFormatWithLineDescriptionAccountingLineParser;
024    import org.kuali.kfs.fp.businessobject.CapitalAssetInformation;
025    import org.kuali.kfs.integration.cam.CapitalAssetManagementModuleService;
026    import org.kuali.kfs.sys.KFSConstants;
027    import org.kuali.kfs.sys.KFSPropertyConstants;
028    import org.kuali.kfs.sys.businessobject.AccountingLine;
029    import org.kuali.kfs.sys.businessobject.AccountingLineBase;
030    import org.kuali.kfs.sys.businessobject.AccountingLineParser;
031    import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry;
032    import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail;
033    import org.kuali.kfs.sys.context.SpringContext;
034    import org.kuali.kfs.sys.document.AccountingDocumentBase;
035    import org.kuali.kfs.sys.document.service.DebitDeterminerService;
036    import org.kuali.rice.kns.util.KualiDecimal;
037    import org.kuali.rice.kns.util.ObjectUtils;
038    
039    /**
040     * Abstract class which defines behavior common to CashReceipt-like documents.
041     */
042    abstract public class CashReceiptFamilyBase extends AccountingDocumentBase implements CapitalAssetEditable {
043        protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(CashReceiptFamilyBase.class);
044        protected String campusLocationCode; // TODO Needs to be an actual object - also need to clarify this
045        protected Date depositDate;
046    
047        // capital asset
048        protected transient CapitalAssetInformation capitalAssetInformation;
049    
050        /**
051         * Constructs a CashReceiptFamilyBase
052         */
053        public CashReceiptFamilyBase() {
054            setCampusLocationCode(KFSConstants.CashReceiptConstants.DEFAULT_CASH_RECEIPT_CAMPUS_LOCATION_CODE);
055        }
056    
057        /**
058         * @see org.kuali.kfs.sys.document.AccountingDocumentBase#buildListOfDeletionAwareLists()
059         */
060        @Override
061        public List buildListOfDeletionAwareLists() {
062            List<List> managedLists = super.buildListOfDeletionAwareLists();
063            if (ObjectUtils.isNotNull(capitalAssetInformation) && ObjectUtils.isNotNull(capitalAssetInformation.getCapitalAssetInformationDetails())) {
064                managedLists.add(capitalAssetInformation.getCapitalAssetInformationDetails());
065            }
066            return managedLists;
067        }
068    
069        /**
070         * Documents in the CashReceiptFamily do not perform Sufficient Funds checking
071         * 
072         * @see org.kuali.kfs.sys.document.AccountingDocumentBase#documentPerformsSufficientFundsCheck()
073         */
074        @Override
075        public boolean documentPerformsSufficientFundsCheck() {
076            return false;
077        }
078    
079        /**
080         * Gets the campusLocationCode attribute.
081         * 
082         * @return Returns the campusLocationCode.
083         */
084        public String getCampusLocationCode() {
085            return campusLocationCode;
086        }
087    
088        /**
089         * Sets the campusLocationCode attribute value.
090         * 
091         * @param campusLocationCode The campusLocationCode to set.
092         */
093        public void setCampusLocationCode(String campusLocationCode) {
094            this.campusLocationCode = campusLocationCode;
095        }
096    
097    
098        /**
099         * Gets the depositDate attribute.
100         * 
101         * @return Returns the depositDate.
102         */
103        public Date getDepositDate() {
104            return depositDate;
105        }
106    
107        /**
108         * Sets the depositDate attribute value.
109         * 
110         * @param depositDate The depositDate to set.
111         */
112        public void setDepositDate(Date depositDate) {
113            this.depositDate = depositDate;
114        }
115    
116    
117        /**
118         * Total for a Cash Receipt according to the spec should be the sum of the amounts on accounting lines belonging to object codes
119         * having the 'income' object type, less the sum of the amounts on accounting lines belonging to object codes having the
120         * 'expense' object type.
121         * 
122         * @see org.kuali.kfs.sys.document.AccountingDocument#getSourceTotal()
123         */
124        @Override
125        public KualiDecimal getSourceTotal() {
126            KualiDecimal total = KualiDecimal.ZERO;
127            AccountingLineBase al = null;
128            if (ObjectUtils.isNull(getSourceAccountingLines()) || getSourceAccountingLines().isEmpty()) {
129                refreshReferenceObject(KFSPropertyConstants.SOURCE_ACCOUNTING_LINES);
130            }
131            Iterator iter = getSourceAccountingLines().iterator();
132            while (iter.hasNext()) {
133                al = (AccountingLineBase) iter.next();
134                try {
135                    KualiDecimal amount = al.getAmount().abs();
136                    if (amount != null && amount.isNonZero()) {
137                        if (isDebit(al)) {
138                            total = total.subtract(amount);
139                        }
140                        else { // in this context, if it's not a debit, it's a credit
141                            total = total.add(amount);
142                        }
143                    }
144                }
145                catch (Exception e) {
146                    // Possibly caused by accounting lines w/ bad data
147                    LOG.error("Error occured trying to compute Cash receipt total, returning 0", e);
148                    return KualiDecimal.ZERO;
149                }
150            }
151            return total;
152        }
153    
154        /**
155         * Cash Receipts only have source lines, so this should always return 0.
156         * 
157         * @see org.kuali.kfs.sys.document.AccountingDocument#getTargetTotal()
158         */
159        @Override
160        public KualiDecimal getTargetTotal() {
161            return KualiDecimal.ZERO;
162        }
163    
164        /**
165         * Overrides the base implementation to return an empty string.
166         * 
167         * @see org.kuali.kfs.sys.document.AccountingDocument#getSourceAccountingLinesSectionTitle()
168         */
169        @Override
170        public String getSourceAccountingLinesSectionTitle() {
171            return KFSConstants.EMPTY_STRING;
172        }
173    
174        /**
175         * Overrides the base implementation to return an empty string.
176         * 
177         * @see org.kuali.kfs.sys.document.AccountingDocument#getTargetAccountingLinesSectionTitle()
178         */
179        @Override
180        public String getTargetAccountingLinesSectionTitle() {
181            return KFSConstants.EMPTY_STRING;
182        }
183    
184        /**
185         * Returns true if accounting line is debit
186         * 
187         * @param financialDocument
188         * @param accountingLine
189         * @param true if accountline line
190         * @see IsDebitUtils#isDebitConsideringType(FinancialDocumentRuleBase, FinancialDocument, AccountingLine)
191         * @see org.kuali.rice.kns.rule.AccountingLineRule#isDebit(org.kuali.rice.kns.document.FinancialDocument,
192         *      org.kuali.rice.kns.bo.AccountingLine)
193         */
194        public boolean isDebit(GeneralLedgerPendingEntrySourceDetail postable) {
195            // error corrections are not allowed
196            DebitDeterminerService isDebitUtils = SpringContext.getBean(DebitDeterminerService.class);
197            isDebitUtils.disallowErrorCorrectionDocumentCheck(this);
198            return isDebitUtils.isDebitConsideringType(this, (AccountingLine) postable);
199        }
200    
201        /**
202         * Overrides to set the entry's description to the description from the accounting line, if a value exists.
203         * 
204         * @param financialDocument submitted accounting document
205         * @param accountingLine accounting line in accounting document
206         * @param explicitEntry general ledger pending entry
207         * @see org.kuali.module.financial.rules.FinancialDocumentRuleBase#customizeExplicitGeneralLedgerPendingEntry(org.kuali.rice.kns.document.FinancialDocument,
208         *      org.kuali.rice.kns.bo.AccountingLine, org.kuali.module.gl.bo.GeneralLedgerPendingEntry)
209         */
210        @Override
211        public void customizeExplicitGeneralLedgerPendingEntry(GeneralLedgerPendingEntrySourceDetail postable, GeneralLedgerPendingEntry explicitEntry) {
212            String accountingLineDescription = postable.getFinancialDocumentLineDescription();
213            if (StringUtils.isNotBlank(accountingLineDescription)) {
214                explicitEntry.setTransactionLedgerEntryDescription(accountingLineDescription);
215            }
216        }
217    
218    
219        /**
220         * @see org.kuali.kfs.fp.document.CapitalAssetEditable#getCapitalAssetInformation()
221         */
222        public CapitalAssetInformation getCapitalAssetInformation() {
223            return ObjectUtils.isNull(capitalAssetInformation) ? null : capitalAssetInformation;
224        }
225    
226        /**
227         * @see org.kuali.kfs.fp.document.CapitalAssetEditable#setCapitalAssetInformation(org.kuali.kfs.fp.businessobject.CapitalAssetInformation)
228         */
229        public void setCapitalAssetInformation(CapitalAssetInformation capitalAssetInformation) {
230            this.capitalAssetInformation = capitalAssetInformation;
231        }
232    
233    
234        protected CapitalAssetManagementModuleService getCapitalAssetManagementModuleService() {
235            return SpringContext.getBean(CapitalAssetManagementModuleService.class);
236        }
237    }