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.cab.businessobject;
017    
018    import java.util.ArrayList;
019    import java.util.List;
020    
021    import org.kuali.kfs.gl.businessobject.Entry;
022    import org.kuali.kfs.module.purap.businessobject.PurApAccountingLineBase;
023    import org.kuali.kfs.sys.KFSConstants;
024    import org.kuali.rice.kns.util.KualiDecimal;
025    import org.kuali.rice.kns.util.ObjectUtils;
026    
027    /**
028     * Accounting line grouped data for GL Line
029     */
030    public class GlAccountLineGroup extends AccountLineGroup {
031        private Entry targetEntry;
032        private List<Entry> sourceEntries = new ArrayList<Entry>();
033        private List<PurApAccountingLineBase> matchedPurApAcctLines = new ArrayList<PurApAccountingLineBase>();
034    
035        /**
036         * Constructs a GlAccountLineGroup from a GL Line Entry
037         * 
038         * @param entry GL Line
039         */
040        public GlAccountLineGroup(Entry entry) {
041            setUniversityFiscalYear(entry.getUniversityFiscalYear());
042            setChartOfAccountsCode(entry.getChartOfAccountsCode());
043            setAccountNumber(entry.getAccountNumber());
044            setSubAccountNumber(entry.getSubAccountNumber());
045            setFinancialObjectCode(entry.getFinancialObjectCode());
046            setFinancialSubObjectCode(entry.getFinancialSubObjectCode());
047            setUniversityFiscalPeriodCode(entry.getUniversityFiscalPeriodCode());
048            setDocumentNumber(entry.getDocumentNumber());
049            setReferenceFinancialDocumentNumber(entry.getReferenceFinancialDocumentNumber());
050            setOrganizationReferenceId(entry.getOrganizationReferenceId());
051            setProjectCode(entry.getProjectCode());
052            this.sourceEntries.add(entry);
053            this.targetEntry = (Entry) ObjectUtils.deepCopy(entry);
054    
055            KualiDecimal amount = entry.getTransactionLedgerEntryAmount();
056            if (KFSConstants.GL_CREDIT_CODE.equals(entry.getTransactionDebitCreditCode())) {
057                // negate the amount
058                setAmount(amount.negated());
059            }
060            else {
061                setAmount(amount);
062            }
063        }
064    
065        /**
066         * Returns true if input GL entry belongs to this account group
067         * 
068         * @param entry Entry
069         * @return true if Entry belongs to same account line group
070         */
071        public boolean isAccounted(Entry entry) {
072            GlAccountLineGroup test = new GlAccountLineGroup(entry);
073            return this.equals(test);
074        }
075    
076        /**
077         * This method will combine multiple GL entries for the same account line group, so that m:n association is prevented in the
078         * database. This could be a rare case that we need to address. First GL is used as the final target and rest of the GL entries
079         * are adjusted.
080         * 
081         * @param entry
082         */
083        public void combineEntry(Entry newEntry) {
084            this.sourceEntries.add(newEntry);
085            KualiDecimal newAmt = newEntry.getTransactionLedgerEntryAmount();
086            String newDebitCreditCode = newEntry.getTransactionDebitCreditCode();
087    
088            KualiDecimal targetAmount = this.targetEntry.getTransactionLedgerEntryAmount();
089            String targetDebitCreditCode = this.targetEntry.getTransactionDebitCreditCode();
090    
091            // if debit/credit code is same then just add the amount
092            if (targetDebitCreditCode.equals(newDebitCreditCode)) {
093                targetAmount = targetAmount.add(newAmt);
094            }
095            else {
096                // if debit/credit code is not the same and new amount is greater, toggle the debit/credit code
097                if (newAmt.isGreaterThan(targetAmount)) {
098                    targetDebitCreditCode = newDebitCreditCode;
099                    targetAmount = newAmt.subtract(targetAmount);
100                }
101                else {
102                    // if debit/credit code is not the same and current amount is greater or equal
103                    targetAmount = targetAmount.subtract(newAmt);
104                }
105            }
106            this.targetEntry.setTransactionDebitCreditCode(targetDebitCreditCode);
107            this.targetEntry.setTransactionLedgerEntryAmount(targetAmount);
108            // re-compute the absolute value of amount
109            if (KFSConstants.GL_CREDIT_CODE.equals(targetDebitCreditCode)) {
110                setAmount(targetAmount.negated());
111            }
112            else {
113                setAmount(targetAmount);
114            }
115        }
116    
117        /**
118         * Gets the targetEntry attribute.
119         * 
120         * @return Returns the targetEntry
121         */
122        public Entry getTargetEntry() {
123            return targetEntry;
124        }
125    
126        /**
127         * Sets the targetEntry attribute.
128         * 
129         * @param targetEntry The targetEntry to set.
130         */
131        public void setTargetEntry(Entry targetGlEntry) {
132            this.targetEntry = targetGlEntry;
133        }
134    
135        /**
136         * Gets the sourceEntries attribute.
137         * 
138         * @return Returns the sourceEntries
139         */
140        public List<Entry> getSourceEntries() {
141            return sourceEntries;
142        }
143    
144        /**
145         * Sets the sourceEntries attribute.
146         * 
147         * @param sourceEntries The sourceEntries to set.
148         */
149        public void setSourceEntries(List<Entry> sourceGlEntries) {
150            this.sourceEntries = sourceGlEntries;
151        }
152    
153        /**
154         * Gets the matchedPurApAcctLines attribute.
155         * 
156         * @return Returns the matchedPurApAcctLines.
157         */
158        public List<PurApAccountingLineBase> getMatchedPurApAcctLines() {
159            return matchedPurApAcctLines;
160        }
161    
162        /**
163         * Sets the matchedPurApAcctLines attribute value.
164         * 
165         * @param matchedPurApAcctLines The matchedPurApAcctLines to set.
166         */
167        public void setMatchedPurApAcctLines(List<PurApAccountingLineBase> matchedPurApAcctLines) {
168            this.matchedPurApAcctLines = matchedPurApAcctLines;
169        }
170    }