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.GeneralLedgerConstants;
023    import org.kuali.kfs.gl.batch.service.AccountBalanceCalculator;
024    import org.kuali.kfs.gl.batch.service.AccountingCycleCachingService;
025    import org.kuali.kfs.gl.batch.service.PostTransaction;
026    import org.kuali.kfs.gl.businessobject.AccountBalance;
027    import org.kuali.kfs.gl.businessobject.Transaction;
028    import org.kuali.kfs.sys.KFSConstants;
029    import org.kuali.kfs.sys.service.ReportWriterService;
030    import org.kuali.rice.kns.service.PersistenceStructureService;
031    import org.springframework.transaction.annotation.Transactional;
032    
033    @Transactional
034    public class PostAccountBalance implements PostTransaction, AccountBalanceCalculator {
035        private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PostAccountBalance.class);
036    
037        private AccountingCycleCachingService accountingCycleCachingService;
038        private PersistenceStructureService persistenceStructureService;
039    
040        /**
041         * Constructs a PostAccountBalance instance
042         */
043        public PostAccountBalance() {
044            super();
045        }
046    
047        /**
048         * Posts the transaction to the appropriate account balance record.
049         * 
050         * @param t the transaction which is being posted
051         * @param mode the mode the poster is currently running in
052         * @param postDate the date this transaction should post to
053         * @param posterReportWriterService the writer service where the poster is writing its report
054         * @return the accomplished post type
055         * @see org.kuali.kfs.gl.batch.service.PostTransaction#post(org.kuali.kfs.gl.businessobject.Transaction, int, java.util.Date)
056         */
057        public String post(Transaction t, int mode, Date postDate, ReportWriterService posterReportWriterService) {
058            LOG.debug("post() started");
059    
060            // Only post transactions where:
061            // balance type code is AC or CB
062            // or where object type isn't FB and balance type code is EX, IE, PE and CE
063            if ((t.getFinancialBalanceTypeCode().equals(t.getOption().getActualFinancialBalanceTypeCd()) || t.getFinancialBalanceTypeCode().equals(t.getOption().getBudgetCheckingBalanceTypeCd())) || (t.getFinancialBalanceTypeCode().equals(t.getOption().getExtrnlEncumFinBalanceTypCd()) || t.getFinancialBalanceTypeCode().equals(t.getOption().getIntrnlEncumFinBalanceTypCd()) || t.getFinancialBalanceTypeCode().equals(t.getOption().getPreencumbranceFinBalTypeCd()) || t.getFinancialBalanceTypeCode().equals(t.getOption().getCostShareEncumbranceBalanceTypeCd())) && (!t.getFinancialObjectTypeCode().equals(t.getOption().getFinObjectTypeFundBalanceCd()))) {
064                // We are posting this transaction
065                String returnCode = GeneralLedgerConstants.UPDATE_CODE;
066    
067                // Load it
068                AccountBalance ab = accountingCycleCachingService.getAccountBalance(t);
069    
070                if (ab == null) {
071                    returnCode = GeneralLedgerConstants.INSERT_CODE;
072                    ab = new AccountBalance(t);
073                }
074    
075                ab.setTimestamp(new java.sql.Date(postDate.getTime()));
076    
077                if (!updateAccountBalanceReturn(t, ab)) {
078                    return GeneralLedgerConstants.EMPTY_CODE;
079                }
080    
081                if (returnCode.equals(GeneralLedgerConstants.INSERT_CODE)) {
082                    accountingCycleCachingService.insertAccountBalance(ab);
083                } else {
084                    accountingCycleCachingService.updateAccountBalance(ab);
085                }
086    
087                return returnCode;
088            }
089            else {
090                return GeneralLedgerConstants.EMPTY_CODE;
091            }
092        }
093    
094        public AccountBalance findAccountBalance(Collection balanceList, Transaction t) {
095    
096            // Try to find one that already exists
097            for (Iterator iter = balanceList.iterator(); iter.hasNext();) {
098                AccountBalance b = (AccountBalance) iter.next();
099    
100                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())) {
101                    return b;
102                }
103            }
104    
105            // If we couldn't find one that exists, create a new one
106            AccountBalance b = new AccountBalance(t);
107            balanceList.add(b);
108    
109            return b;
110        }
111    
112        protected boolean updateAccountBalanceReturn(Transaction t, AccountBalance ab) {
113            if (t.getFinancialBalanceTypeCode().equals(t.getOption().getBudgetCheckingBalanceTypeCd())) {
114                ab.setCurrentBudgetLineBalanceAmount(ab.getCurrentBudgetLineBalanceAmount().add(t.getTransactionLedgerEntryAmount()));
115            }
116            else if (t.getFinancialBalanceTypeCode().equals(t.getOption().getActualFinancialBalanceTypeCd())) {
117                if (t.getObjectType().getFinObjectTypeDebitcreditCd().equals(t.getTransactionDebitCreditCode()) || ((!t.getBalanceType().isFinancialOffsetGenerationIndicator()) && KFSConstants.GL_BUDGET_CODE.equals(t.getTransactionDebitCreditCode()))) {
118                    ab.setAccountLineActualsBalanceAmount(ab.getAccountLineActualsBalanceAmount().add(t.getTransactionLedgerEntryAmount()));
119                }
120                else {
121                    ab.setAccountLineActualsBalanceAmount(ab.getAccountLineActualsBalanceAmount().subtract(t.getTransactionLedgerEntryAmount()));
122                }
123            }
124            else if (t.getFinancialBalanceTypeCode().equals(t.getOption().getExtrnlEncumFinBalanceTypCd()) || t.getFinancialBalanceTypeCode().equals(t.getOption().getIntrnlEncumFinBalanceTypCd()) || t.getFinancialBalanceTypeCode().equals(t.getOption().getPreencumbranceFinBalTypeCd()) || t.getFinancialBalanceTypeCode().equals(t.getOption().getCostShareEncumbranceBalanceTypeCd())) {
125                if (t.getObjectType().getFinObjectTypeDebitcreditCd().equals(t.getTransactionDebitCreditCode()) || ((!t.getBalanceType().isFinancialOffsetGenerationIndicator()) && KFSConstants.GL_BUDGET_CODE.equals(t.getTransactionDebitCreditCode()))) {
126                    ab.setAccountLineEncumbranceBalanceAmount(ab.getAccountLineEncumbranceBalanceAmount().add(t.getTransactionLedgerEntryAmount()));
127                }
128                else {
129                    ab.setAccountLineEncumbranceBalanceAmount(ab.getAccountLineEncumbranceBalanceAmount().subtract(t.getTransactionLedgerEntryAmount()));
130                }
131            }
132            else {
133                return false;
134            }
135            return true;
136        }
137    
138        /**
139         * @param t
140         * @param enc
141         */
142        public void updateAccountBalance(Transaction t, AccountBalance ab) {
143            updateAccountBalanceReturn(t, ab);
144        }
145    
146        public String getDestinationName() {
147            return persistenceStructureService.getTableName(AccountBalance.class);
148        }
149    
150        public void setAccountingCycleCachingService(AccountingCycleCachingService accountingCycleCachingService) {
151            this.accountingCycleCachingService = accountingCycleCachingService;
152        }
153    
154        public void setPersistenceStructureService(PersistenceStructureService persistenceStructureService) {
155            this.persistenceStructureService = persistenceStructureService;
156        }
157    }