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.gl.batch.service.impl;
017    
018    import java.util.Collection;
019    import java.util.Date;
020    import java.util.Iterator;
021    
022    import org.kuali.kfs.gl.batch.service.AccountingCycleCachingService;
023    import org.kuali.kfs.gl.batch.service.BalanceCalculator;
024    import org.kuali.kfs.gl.batch.service.PostTransaction;
025    import org.kuali.kfs.gl.businessobject.Balance;
026    import org.kuali.kfs.gl.businessobject.Transaction;
027    import org.kuali.kfs.gl.dataaccess.BalanceDao;
028    import org.kuali.kfs.sys.businessobject.UniversityDate;
029    import org.kuali.kfs.sys.context.SpringContext;
030    import org.kuali.kfs.sys.service.ReportWriterService;
031    import org.kuali.kfs.sys.service.UniversityDateService;
032    import org.kuali.rice.kns.util.KualiDecimal;
033    import org.springframework.transaction.annotation.Transactional;
034    
035    /**
036     * This implementation of PostTransaction updates the appropriate Balance
037     */
038    @Transactional
039    public class PostBalance implements PostTransaction, BalanceCalculator {
040        private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PostBalance.class);
041        
042        private AccountingCycleCachingService accountingCycleCachingService;
043        private static final KualiDecimal NEGATIVE_ONE = new KualiDecimal(-1);
044        /**
045         * Constructs a PostBalance instance
046         */
047        public PostBalance() {
048            super();
049        }
050    
051        /**
052         * This posts the effect of the transaction upon the appropriate balance record.
053         * 
054         * @param t the transaction which is being posted
055         * @param mode the mode the poster is currently running in
056         * @param postDate the date this transaction should post to
057         * @param posterReportWriterService the writer service where the poster is writing its report
058         * @return the accomplished post type
059         * @see org.kuali.kfs.gl.batch.service.PostTransaction#post(org.kuali.kfs.gl.businessobject.Transaction, int, java.util.Date)
060         */
061        public String post(Transaction t, int mode, Date postDate, ReportWriterService posterReportWriterService) {
062            LOG.debug("post() started");
063    
064            String postType = "U";
065    
066            KualiDecimal amount = t.getTransactionLedgerEntryAmount();
067    
068            // Subtract the amount if offset generation indicator & the debit/credit code isn't the same
069            // as the one in the object type code table
070            if (t.getBalanceType().isFinancialOffsetGenerationIndicator()) {
071                if (!t.getTransactionDebitCreditCode().equals(t.getObjectType().getFinObjectTypeDebitcreditCd())) {
072                    amount = amount.multiply(NEGATIVE_ONE);
073                }
074            }
075    
076            Balance b = accountingCycleCachingService.getBalance(t);
077            if (b == null) {
078                postType = "I";
079                b = new Balance(t);
080            }
081            String period = t.getUniversityFiscalPeriodCode();
082            b.addAmount(period, amount);
083    
084            if (postType.equals("I")) {
085                accountingCycleCachingService.insertBalance(b);
086            } else {
087                accountingCycleCachingService.updateBalance(b);
088            }
089            
090            return postType;
091        }
092    
093        /**
094         * Given a list of balances, determines which one the given trsnaction should post to
095         * 
096         * @param balanceList a Collection of balances
097         * @param t the transaction that is being posted
098         * @return the balance, either found from the list, or, if not present in the list, newly created
099         * @see org.kuali.kfs.gl.batch.service.BalanceCalculator#findBalance(java.util.Collection, org.kuali.kfs.gl.businessobject.Transaction)
100         */
101        public Balance findBalance(Collection balanceList, Transaction t) {
102            // Try to find one that already exists
103            for (Iterator iter = balanceList.iterator(); iter.hasNext();) {
104                Balance b = (Balance) iter.next();
105    
106                if (b.getUniversityFiscalYear().equals(t.getUniversityFiscalYear()) && b.getChartOfAccountsCode().equals(t.getChartOfAccountsCode()) && b.getAccountNumber().equals(t.getAccountNumber()) && b.getSubAccountNumber().equals(t.getSubAccountNumber()) && b.getObjectCode().equals(t.getFinancialObjectCode()) && b.getSubObjectCode().equals(t.getFinancialSubObjectCode()) && b.getBalanceTypeCode().equals(t.getFinancialBalanceTypeCode()) && b.getObjectTypeCode().equals(t.getFinancialObjectTypeCode())) {
107                    return b;
108                }
109            }
110    
111            // If we couldn't find one that exists, create a new one
112            Balance b = new Balance(t);
113            balanceList.add(b);
114    
115            return b;
116        }
117    
118        /**
119         * @param t
120         * @param enc
121         */
122        public void updateBalance(Transaction t, Balance b) {
123    
124            // The pending entries haven't been scrubbed so there could be
125            // bad data. This won't update a balance if the data it needs
126            // is invalid
127            KualiDecimal amount = t.getTransactionLedgerEntryAmount();
128            if (amount == null) {
129                amount = KualiDecimal.ZERO;
130            }
131    
132            if (t.getObjectType() == null) {
133                LOG.error("updateBalance() Invalid object type (" + t.getFinancialObjectTypeCode() + ") in pending table");
134                return;
135            }
136    
137            if (t.getBalanceType() == null) {
138                LOG.error("updateBalance() Invalid balance type (" + t.getFinancialBalanceTypeCode() + ") in pending table");
139                return;
140            }
141    
142            // Subtract the amount if offset generation indicator & the debit/credit code isn't the same
143            // as the one in the object type code table
144            if (t.getBalanceType().isFinancialOffsetGenerationIndicator()) {
145                if (!t.getTransactionDebitCreditCode().equals(t.getObjectType().getFinObjectTypeDebitcreditCd())) {
146                    amount = amount.multiply(new KualiDecimal(-1));
147                }
148            }
149    
150            // update the balance amount of the cooresponding period
151            String period = t.getUniversityFiscalPeriodCode();
152            if (period == null) {
153                UniversityDate currentUniversityDate = SpringContext.getBean(UniversityDateService.class).getCurrentUniversityDate();
154                period = currentUniversityDate.getUniversityFiscalAccountingPeriod();
155            }
156    
157            b.addAmount(period, amount);
158        }
159    
160        /**
161         * @see org.kuali.kfs.gl.batch.service.PostTransaction#getDestinationName()
162         */
163        public String getDestinationName() {
164            return "GL_BALANCE_T";
165        }
166    
167        public void setAccountingCycleCachingService(AccountingCycleCachingService accountingCycleCachingService) {
168            this.accountingCycleCachingService = accountingCycleCachingService;
169        }
170    }