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 }