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.apache.commons.lang.ArrayUtils;
023    import org.apache.commons.lang.StringUtils;
024    import org.kuali.kfs.gl.GeneralLedgerConstants;
025    import org.kuali.kfs.gl.batch.PosterEntriesStep;
026    import org.kuali.kfs.gl.batch.ScrubberStep;
027    import org.kuali.kfs.gl.batch.service.AccountingCycleCachingService;
028    import org.kuali.kfs.gl.batch.service.EncumbranceCalculator;
029    import org.kuali.kfs.gl.batch.service.PostTransaction;
030    import org.kuali.kfs.gl.businessobject.Encumbrance;
031    import org.kuali.kfs.gl.businessobject.Entry;
032    import org.kuali.kfs.gl.businessobject.Transaction;
033    import org.kuali.kfs.sys.KFSConstants;
034    import org.kuali.kfs.sys.service.ReportWriterService;
035    import org.kuali.rice.kns.service.DateTimeService;
036    import org.kuali.rice.kns.service.ParameterService;
037    import org.kuali.rice.kns.service.PersistenceStructureService;
038    import org.springframework.transaction.annotation.Transactional;
039    
040    /**
041     * This implementation of PostTransaction posts a transaction that could be an encumbrance
042     */
043    @Transactional
044    public class PostEncumbrance implements PostTransaction, EncumbranceCalculator {
045        private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PostEncumbrance.class);
046    
047        private AccountingCycleCachingService accountingCycleCachingService;
048        private DateTimeService dateTimeService;
049        private PersistenceStructureService persistenceStructureService;
050        private ParameterService parameterService;
051    
052        /**
053         * Constructs a PostEncumbrance instance
054         */
055        public PostEncumbrance() {
056            super();
057        }
058    
059        /**
060         * Called by the poster to post a transaction. The transaction might or might not be an encumbrance transaction.
061         * 
062         * @param t the transaction which is being posted
063         * @param mode the mode the poster is currently running in
064         * @param postDate the date this transaction should post to
065         * @param posterReportWriterService the writer service where the poster is writing its report
066         * @return the accomplished post type
067         */
068        public String post(Transaction t, int mode, Date postDate, ReportWriterService posterReportWriterService) {
069            LOG.debug("post() started");
070    
071            String returnCode = GeneralLedgerConstants.UPDATE_CODE;
072    
073            // If the encumbrance update code is space or N, or the object type code is FB
074            // we don't need to post an encumbrance
075            if ((StringUtils.isBlank(t.getTransactionEncumbranceUpdateCode())) || " ".equals(t.getTransactionEncumbranceUpdateCode()) || KFSConstants.ENCUMB_UPDT_NO_ENCUMBRANCE_CD.equals(t.getTransactionEncumbranceUpdateCode()) || t.getOption().getFinObjectTypeFundBalanceCd().equals(t.getFinancialObjectTypeCode())) {
076                LOG.debug("post() not posting non-encumbrance transaction");
077                return "";
078            }
079    
080            // Get the current encumbrance record if there is one
081            Entry e = new Entry(t, null);
082            if (KFSConstants.ENCUMB_UPDT_REFERENCE_DOCUMENT_CD.equals(t.getTransactionEncumbranceUpdateCode())) {
083                e.setDocumentNumber(t.getReferenceFinancialDocumentNumber());
084                e.setFinancialSystemOriginationCode(t.getReferenceFinancialSystemOriginationCode());
085                e.setFinancialDocumentTypeCode(t.getReferenceFinancialDocumentTypeCode());
086            }
087            
088            Encumbrance enc = accountingCycleCachingService.getEncumbrance(e);
089            if (enc == null) {
090                // Build a new encumbrance record
091                enc = new Encumbrance(e);
092    
093                returnCode = GeneralLedgerConstants.INSERT_CODE;
094            }
095            else {
096                // Use the one retrieved
097                if (enc.getTransactionEncumbranceDate() == null) {
098                    enc.setTransactionEncumbranceDate(t.getTransactionDate());
099                }
100    
101                returnCode = GeneralLedgerConstants.UPDATE_CODE;
102            }
103    
104            updateEncumbrance(t, enc);
105    
106            if (returnCode.equals(GeneralLedgerConstants.INSERT_CODE)) {
107                accountingCycleCachingService.insertEncumbrance(enc);
108            } else {
109                accountingCycleCachingService.updateEncumbrance(enc);
110            }
111    
112            return returnCode;
113        }
114    
115        /**
116         * Given a Collection of encumbrances, returns the encumbrance that would affected by the given transaction
117         * 
118         * @param encumbranceList a Collection of encumbrances
119         * @param t the transaction to find the appropriate encumbrance for
120         * @return the encumbrance found from the list, or, if not found, a newly created encumbrance
121         * @see org.kuali.kfs.gl.batch.service.EncumbranceCalculator#findEncumbrance(java.util.Collection, org.kuali.kfs.gl.businessobject.Transaction)
122         */
123        public Encumbrance findEncumbrance(Collection encumbranceList, Transaction t) {
124    
125            // If it isn't an encumbrance transaction, skip it
126            if ((!KFSConstants.ENCUMB_UPDT_DOCUMENT_CD.equals(t.getTransactionEncumbranceUpdateCode())) && (!KFSConstants.ENCUMB_UPDT_REFERENCE_DOCUMENT_CD.equals(t.getTransactionEncumbranceUpdateCode()))) {
127                return null;
128            }
129    
130            // Try to find one that already exists
131            for (Iterator iter = encumbranceList.iterator(); iter.hasNext();) {
132                Encumbrance e = (Encumbrance) iter.next();
133    
134                if (KFSConstants.ENCUMB_UPDT_DOCUMENT_CD.equals(t.getTransactionEncumbranceUpdateCode()) && e.getUniversityFiscalYear().equals(t.getUniversityFiscalYear()) && e.getChartOfAccountsCode().equals(t.getChartOfAccountsCode()) && e.getAccountNumber().equals(t.getAccountNumber()) && e.getSubAccountNumber().equals(t.getSubAccountNumber()) && e.getObjectCode().equals(t.getFinancialObjectCode()) && e.getSubObjectCode().equals(t.getFinancialSubObjectCode()) && e.getBalanceTypeCode().equals(t.getFinancialBalanceTypeCode()) && e.getDocumentTypeCode().equals(t.getFinancialDocumentTypeCode()) && e.getOriginCode().equals(t.getFinancialSystemOriginationCode()) && e.getDocumentNumber().equals(t.getDocumentNumber())) {
135                    return e;
136                }
137    
138                if (KFSConstants.ENCUMB_UPDT_REFERENCE_DOCUMENT_CD.equals(t.getTransactionEncumbranceUpdateCode()) && e.getUniversityFiscalYear().equals(t.getUniversityFiscalYear()) && e.getChartOfAccountsCode().equals(t.getChartOfAccountsCode()) && e.getAccountNumber().equals(t.getAccountNumber()) && e.getSubAccountNumber().equals(t.getSubAccountNumber()) && e.getObjectCode().equals(t.getFinancialObjectCode()) && e.getSubObjectCode().equals(t.getFinancialSubObjectCode()) && e.getBalanceTypeCode().equals(t.getFinancialBalanceTypeCode()) && e.getDocumentTypeCode().equals(t.getReferenceFinancialDocumentTypeCode()) && e.getOriginCode().equals(t.getReferenceFinancialSystemOriginationCode()) && e.getDocumentNumber().equals(t.getReferenceFinancialDocumentNumber())) {
139                    return e;
140                }
141            }
142    
143            // If we couldn't find one that exists, create a new one
144    
145            // NOTE: the date doesn't matter so there is no need to call the date service
146            // Changed to use the datetime service because of KULRNE-4183
147            Entry e = new Entry(t, dateTimeService.getCurrentDate());
148            if (KFSConstants.ENCUMB_UPDT_REFERENCE_DOCUMENT_CD.equals(t.getTransactionEncumbranceUpdateCode())) {
149                e.setDocumentNumber(t.getReferenceFinancialDocumentNumber());
150                e.setFinancialSystemOriginationCode(t.getReferenceFinancialSystemOriginationCode());
151                e.setFinancialDocumentTypeCode(t.getReferenceFinancialDocumentTypeCode());
152            }
153    
154            Encumbrance enc = new Encumbrance(e);
155            encumbranceList.add(enc);
156            return enc;
157        }
158    
159        /**
160         * @param t
161         * @param enc
162         */
163        public void updateEncumbrance(Transaction t, Encumbrance enc) {
164            //KFSMI-1571 - check parameter encumbranceOpenAmountOeverridingDocTypes
165            String[] encumbranceOpenAmountOeverridingDocTypes = parameterService.getParameterValues(PosterEntriesStep.class, GeneralLedgerConstants.PosterService.ENCUMBRANCE_OPEN_AMOUNT_OVERRIDING_DOCUMENT_TYPES).toArray(new String[] {});
166    
167            if (KFSConstants.ENCUMB_UPDT_REFERENCE_DOCUMENT_CD.equals(t.getTransactionEncumbranceUpdateCode()) && !ArrayUtils.contains(encumbranceOpenAmountOeverridingDocTypes, t.getFinancialDocumentTypeCode())) {
168                // If using referring doc number, add or subtract transaction amount from
169                // encumbrance closed amount
170                if (KFSConstants.GL_DEBIT_CODE.equals(t.getTransactionDebitCreditCode())) {
171                    enc.setAccountLineEncumbranceClosedAmount(enc.getAccountLineEncumbranceClosedAmount().subtract(t.getTransactionLedgerEntryAmount()));
172                }
173                else {
174                    enc.setAccountLineEncumbranceClosedAmount(enc.getAccountLineEncumbranceClosedAmount().add(t.getTransactionLedgerEntryAmount()));
175                }
176            }
177            else {
178                // If not using referring doc number, add or subtract transaction amount from
179                // encumbrance amount
180                if (KFSConstants.GL_DEBIT_CODE.equals(t.getTransactionDebitCreditCode()) || KFSConstants.GL_BUDGET_CODE.equals(t.getTransactionDebitCreditCode())) {
181                    enc.setAccountLineEncumbranceAmount(enc.getAccountLineEncumbranceAmount().add(t.getTransactionLedgerEntryAmount()));
182                }
183                else {
184                    enc.setAccountLineEncumbranceAmount(enc.getAccountLineEncumbranceAmount().subtract(t.getTransactionLedgerEntryAmount()));
185                }
186            }
187        }
188    
189        /**
190         * @see org.kuali.kfs.gl.batch.service.PostTransaction#getDestinationName()
191         */
192        public String getDestinationName() {
193            return persistenceStructureService.getTableName(Encumbrance.class);
194        }
195    
196    
197        public void setDateTimeService(DateTimeService dateTimeService) {
198            this.dateTimeService = dateTimeService;
199        }
200    
201        public void setAccountingCycleCachingService(AccountingCycleCachingService accountingCycleCachingService) {
202            this.accountingCycleCachingService = accountingCycleCachingService;
203        }
204    
205        public void setPersistenceStructureService(PersistenceStructureService persistenceStructureService) {
206            this.persistenceStructureService = persistenceStructureService;
207        }
208    
209        public void setParameterService(ParameterService parameterService) {
210            this.parameterService = parameterService;
211        }
212    }