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 }