001/* 002 * Copyright 2007 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/* 017 * Created on Aug 30, 2004 018 * 019 */ 020package org.kuali.ole.pdp.service.impl; 021 022import java.sql.Date; 023import java.util.ArrayList; 024import java.util.Iterator; 025import java.util.List; 026 027import org.apache.commons.lang.StringUtils; 028import org.kuali.ole.coa.businessobject.AccountingPeriod; 029import org.kuali.ole.coa.businessobject.OffsetDefinition; 030import org.kuali.ole.coa.service.AccountingPeriodService; 031import org.kuali.ole.coa.service.OffsetDefinitionService; 032import org.kuali.ole.pdp.PdpConstants; 033import org.kuali.ole.pdp.businessobject.GlPendingTransaction; 034import org.kuali.ole.pdp.businessobject.PaymentAccountDetail; 035import org.kuali.ole.pdp.businessobject.PaymentDetail; 036import org.kuali.ole.pdp.businessobject.PaymentGroup; 037import org.kuali.ole.pdp.dataaccess.PendingTransactionDao; 038import org.kuali.ole.pdp.service.PendingTransactionService; 039import org.kuali.ole.sys.OLEConstants; 040import org.kuali.ole.sys.OLEKeyConstants; 041import org.kuali.ole.sys.businessobject.Bank; 042import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper; 043import org.kuali.ole.sys.context.SpringContext; 044import org.kuali.ole.sys.service.BankService; 045import org.kuali.ole.sys.service.FlexibleOffsetAccountService; 046import org.kuali.rice.core.api.config.property.ConfigurationService; 047import org.kuali.rice.core.api.datetime.DateTimeService; 048import org.kuali.rice.core.api.util.type.KualiInteger; 049import org.kuali.rice.krad.service.BusinessObjectService; 050import org.springframework.transaction.annotation.Transactional; 051 052/** 053 * @see org.kuali.ole.pdp.service.PendingTransactionService 054 */ 055@Transactional 056public class PendingTransactionServiceImpl implements PendingTransactionService { 057 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PendingTransactionServiceImpl.class); 058 059 protected static String FDOC_TYP_CD_PROCESS_ACH = "ACHD"; 060 protected static String FDOC_TYP_CD_PROCESS_CHECK = "CHKD"; 061 protected static String FDOC_TYP_CD_CANCEL_REISSUE_ACH = "ACHR"; 062 protected static String FDOC_TYP_CD_CANCEL_REISSUE_CHECK = "CHKR"; 063 protected static String FDOC_TYP_CD_CANCEL_ACH = "ACHC"; 064 protected static String FDOC_TYP_CD_CANCEL_CHECK = "CHKC"; 065 066 private PendingTransactionDao glPendingTransactionDao; 067 private AccountingPeriodService accountingPeriodService; 068 private DateTimeService dateTimeService; 069 private ConfigurationService kualiConfigurationService; 070 private BusinessObjectService businessObjectService; 071 private BankService bankService; 072 073 public PendingTransactionServiceImpl() { 074 super(); 075 } 076 077 /** 078 * @see org.kuali.ole.pdp.service.PendingTransactionService#generatePaymentGeneralLedgerPendingEntry(org.kuali.ole.pdp.businessobject.PaymentGroup) 079 */ 080 public void generatePaymentGeneralLedgerPendingEntry(PaymentGroup paymentGroup) { 081 this.populatePaymentGeneralLedgerPendingEntry(paymentGroup, FDOC_TYP_CD_PROCESS_ACH, FDOC_TYP_CD_PROCESS_CHECK, false); 082 } 083 084 /** 085 * @see org.kuali.ole.pdp.service.PendingTransactionService#generateCancellationGeneralLedgerPendingEntry(org.kuali.ole.pdp.businessobject.PaymentGroup) 086 */ 087 public void generateCancellationGeneralLedgerPendingEntry(PaymentGroup paymentGroup) { 088 this.populatePaymentGeneralLedgerPendingEntry(paymentGroup, FDOC_TYP_CD_CANCEL_ACH, FDOC_TYP_CD_CANCEL_CHECK, true); 089 } 090 091 /** 092 * @see org.kuali.ole.pdp.service.PendingTransactionService#generateReissueGeneralLedgerPendingEntry(org.kuali.ole.pdp.businessobject.PaymentGroup) 093 */ 094 public void generateReissueGeneralLedgerPendingEntry(PaymentGroup paymentGroup) { 095 this.populatePaymentGeneralLedgerPendingEntry(paymentGroup, FDOC_TYP_CD_CANCEL_REISSUE_ACH, FDOC_TYP_CD_CANCEL_REISSUE_CHECK, true); 096 } 097 098 /** 099 * Populates and stores a new GLPE for each account detail in the payment group. 100 * 101 * @param paymentGroup payment group to generate entries for 102 * @param achFdocTypeCode doc type for ach disbursements 103 * @param checkFdocTypeCod doc type for check disbursements 104 * @param reversal boolean indicating if this is a reversal 105 */ 106 protected void populatePaymentGeneralLedgerPendingEntry(PaymentGroup paymentGroup, String achFdocTypeCode, String checkFdocTypeCod, boolean reversal) { 107 List<PaymentAccountDetail> accountListings = new ArrayList<PaymentAccountDetail>(); 108 for (PaymentDetail paymentDetail : paymentGroup.getPaymentDetails()) { 109 accountListings.addAll(paymentDetail.getAccountDetail()); 110 } 111 112 GeneralLedgerPendingEntrySequenceHelper sequenceHelper = new GeneralLedgerPendingEntrySequenceHelper(); 113 for (PaymentAccountDetail paymentAccountDetail : accountListings) { 114 GlPendingTransaction glPendingTransaction = new GlPendingTransaction(); 115 glPendingTransaction.setSequenceNbr(new KualiInteger(sequenceHelper.getSequenceCounter())); 116 117 if (StringUtils.isNotBlank(paymentAccountDetail.getPaymentDetail().getFinancialSystemOriginCode()) && StringUtils.isNotBlank(paymentAccountDetail.getPaymentDetail().getFinancialDocumentTypeCode())) { 118 glPendingTransaction.setFdocRefTypCd(paymentAccountDetail.getPaymentDetail().getFinancialDocumentTypeCode()); 119 glPendingTransaction.setFsRefOriginCd(paymentAccountDetail.getPaymentDetail().getFinancialSystemOriginCode()); 120 } 121 else { 122 glPendingTransaction.setFdocRefTypCd(PdpConstants.PDP_FDOC_TYPE_CODE); 123 glPendingTransaction.setFsRefOriginCd(PdpConstants.PDP_FDOC_ORIGIN_CODE); 124 } 125 126 glPendingTransaction.setFinancialBalanceTypeCode(OLEConstants.BALANCE_TYPE_ACTUAL); 127 128 Date transactionTimestamp = new Date(dateTimeService.getCurrentDate().getTime()); 129 glPendingTransaction.setTransactionDt(transactionTimestamp); 130 AccountingPeriod fiscalPeriod = accountingPeriodService.getByDate(new java.sql.Date(transactionTimestamp.getTime())); 131 glPendingTransaction.setUniversityFiscalYear(fiscalPeriod.getUniversityFiscalYear()); 132 glPendingTransaction.setUnivFiscalPrdCd(fiscalPeriod.getUniversityFiscalPeriodCode()); 133 134 glPendingTransaction.setAccountNumber(paymentAccountDetail.getAccountNbr()); 135 glPendingTransaction.setSubAccountNumber(paymentAccountDetail.getSubAccountNbr()); 136 glPendingTransaction.setChartOfAccountsCode(paymentAccountDetail.getFinChartCode()); 137 138 if (paymentGroup.getDisbursementType().getCode().equals(PdpConstants.DisbursementTypeCodes.ACH)) { 139 glPendingTransaction.setFinancialDocumentTypeCode(achFdocTypeCode); 140 } 141 else if (paymentGroup.getDisbursementType().getCode().equals(PdpConstants.DisbursementTypeCodes.CHECK)) { 142 glPendingTransaction.setFinancialDocumentTypeCode(checkFdocTypeCod); 143 } 144 145 glPendingTransaction.setFsOriginCd(PdpConstants.PDP_FDOC_ORIGIN_CODE); 146 glPendingTransaction.setFdocNbr(paymentGroup.getDisbursementNbr().toString()); 147 148 Boolean relieveLiabilities = paymentGroup.getBatch().getCustomerProfile().getRelieveLiabilities(); 149 if ((relieveLiabilities != null) && (relieveLiabilities.booleanValue()) && paymentAccountDetail.getPaymentDetail().getFinancialDocumentTypeCode() != null) { 150 OffsetDefinition offsetDefinition = SpringContext.getBean(OffsetDefinitionService.class).getByPrimaryId(glPendingTransaction.getUniversityFiscalYear(), glPendingTransaction.getChartOfAccountsCode(), paymentAccountDetail.getPaymentDetail().getFinancialDocumentTypeCode(), glPendingTransaction.getFinancialBalanceTypeCode()); 151 glPendingTransaction.setFinancialObjectCode(offsetDefinition != null ? offsetDefinition.getFinancialObjectCode() : paymentAccountDetail.getFinObjectCode()); 152 glPendingTransaction.setFinancialSubObjectCode(OLEConstants.getDashFinancialSubObjectCode()); 153 } 154 else { 155 glPendingTransaction.setFinancialObjectCode(paymentAccountDetail.getFinObjectCode()); 156 glPendingTransaction.setFinancialSubObjectCode(paymentAccountDetail.getFinSubObjectCode()); 157 } 158 159 glPendingTransaction.setProjectCd(paymentAccountDetail.getProjectCode()); 160 if (paymentAccountDetail.getPaymentDetail().getNetPaymentAmount().bigDecimalValue().signum() >= 0) { 161 glPendingTransaction.setDebitCrdtCd(reversal ? OLEConstants.GL_CREDIT_CODE : OLEConstants.GL_DEBIT_CODE); 162 } 163 else { 164 glPendingTransaction.setDebitCrdtCd(reversal ? OLEConstants.GL_DEBIT_CODE : OLEConstants.GL_CREDIT_CODE); 165 } 166 glPendingTransaction.setAmount(paymentAccountDetail.getAccountNetAmount().abs()); 167 168 String trnDesc = ""; 169 170 String payeeName = paymentGroup.getPayeeName(); 171 if (StringUtils.isNotBlank(payeeName)) { 172 trnDesc = payeeName.length() > 40 ? payeeName.substring(0, 40) : StringUtils.rightPad(payeeName, 40); 173 } 174 175 if (reversal) { 176 String poNbr = paymentAccountDetail.getPaymentDetail().getPurchaseOrderNbr(); 177 if (StringUtils.isNotBlank(poNbr)) { 178 trnDesc += " " + (poNbr.length() > 9 ? poNbr.substring(0, 9) : StringUtils.rightPad(poNbr, 9)); 179 } 180 181 String invoiceNbr = paymentAccountDetail.getPaymentDetail().getInvoiceNbr(); 182 if (StringUtils.isNotBlank(invoiceNbr)) { 183 trnDesc += " " + (invoiceNbr.length() > 14 ? invoiceNbr.substring(0, 14) : StringUtils.rightPad(invoiceNbr, 14)); 184 } 185 186 if (trnDesc.length() > 40) { 187 trnDesc = trnDesc.substring(0, 40); 188 } 189 } 190 191 glPendingTransaction.setDescription(trnDesc); 192 193 glPendingTransaction.setOrgDocNbr(paymentAccountDetail.getPaymentDetail().getOrganizationDocNbr()); 194 glPendingTransaction.setOrgReferenceId(paymentAccountDetail.getOrgReferenceId()); 195 glPendingTransaction.setFdocRefNbr(paymentAccountDetail.getPaymentDetail().getCustPaymentDocNbr()); 196 197 // update the offset account if necessary 198 SpringContext.getBean(FlexibleOffsetAccountService.class).updateOffset(glPendingTransaction); 199 200 this.businessObjectService.save(glPendingTransaction); 201 202 sequenceHelper.increment(); 203 204 if (bankService.isBankSpecificationEnabled()) { 205 this.populateBankOffsetEntry(paymentGroup, glPendingTransaction, sequenceHelper); 206 } 207 } 208 } 209 210 /** 211 * Generates the bank offset for an entry (when enabled in the system) 212 * 213 * @param paymentGroup PaymentGroup for which entries are being generated, contains the Bank 214 * @param glPendingTransaction PDP entry created for payment detail 215 * @param sequenceHelper holds current entry sequence value 216 */ 217 protected void populateBankOffsetEntry(PaymentGroup paymentGroup, GlPendingTransaction glPendingTransaction, GeneralLedgerPendingEntrySequenceHelper sequenceHelper) { 218 GlPendingTransaction bankPendingTransaction = new GlPendingTransaction(); 219 220 bankPendingTransaction.setSequenceNbr(new KualiInteger(sequenceHelper.getSequenceCounter())); 221 bankPendingTransaction.setFdocRefTypCd(null); 222 bankPendingTransaction.setFsRefOriginCd(null); 223 bankPendingTransaction.setFinancialBalanceTypeCode(OLEConstants.BALANCE_TYPE_ACTUAL); 224 bankPendingTransaction.setTransactionDt(glPendingTransaction.getTransactionDt()); 225 bankPendingTransaction.setUniversityFiscalYear(glPendingTransaction.getUniversityFiscalYear()); 226 bankPendingTransaction.setUnivFiscalPrdCd(glPendingTransaction.getUnivFiscalPrdCd()); 227 bankPendingTransaction.setFinancialDocumentTypeCode(glPendingTransaction.getFinancialDocumentTypeCode()); 228 bankPendingTransaction.setFsOriginCd(glPendingTransaction.getFsOriginCd()); 229 bankPendingTransaction.setFdocNbr(glPendingTransaction.getFdocNbr()); 230 231 Bank bank = paymentGroup.getBank(); 232 bankPendingTransaction.setChartOfAccountsCode(bank.getCashOffsetFinancialChartOfAccountCode()); 233 bankPendingTransaction.setAccountNumber(bank.getCashOffsetAccountNumber()); 234 if (StringUtils.isBlank(bank.getCashOffsetSubAccountNumber())) { 235 bankPendingTransaction.setSubAccountNumber(OLEConstants.getDashSubAccountNumber()); 236 } 237 else { 238 bankPendingTransaction.setSubAccountNumber(bank.getCashOffsetSubAccountNumber()); 239 } 240 241 bankPendingTransaction.setFinancialObjectCode(bank.getCashOffsetObjectCode()); 242 if (StringUtils.isBlank(bank.getCashOffsetSubObjectCode())) { 243 bankPendingTransaction.setFinancialSubObjectCode(OLEConstants.getDashFinancialSubObjectCode()); 244 } 245 else { 246 bankPendingTransaction.setFinancialSubObjectCode(bank.getCashOffsetSubObjectCode()); 247 } 248 bankPendingTransaction.setProjectCd(OLEConstants.getDashProjectCode()); 249 250 if (OLEConstants.GL_CREDIT_CODE.equals(glPendingTransaction.getDebitCrdtCd())) { 251 bankPendingTransaction.setDebitCrdtCd(OLEConstants.GL_DEBIT_CODE); 252 } 253 else { 254 bankPendingTransaction.setDebitCrdtCd(OLEConstants.GL_CREDIT_CODE); 255 } 256 bankPendingTransaction.setAmount(glPendingTransaction.getAmount()); 257 258 String description = kualiConfigurationService.getPropertyValueAsString(OLEKeyConstants.Bank.DESCRIPTION_GLPE_BANK_OFFSET); 259 bankPendingTransaction.setDescription(description); 260 bankPendingTransaction.setOrgDocNbr(glPendingTransaction.getOrgDocNbr()); 261 bankPendingTransaction.setOrgReferenceId(null); 262 bankPendingTransaction.setFdocRefNbr(null); 263 264 this.businessObjectService.save(bankPendingTransaction); 265 266 sequenceHelper.increment(); 267 } 268 269 /** 270 * Gets the bankService attribute. 271 * 272 * @return Returns the bankService. 273 */ 274 protected BankService getBankService() { 275 return bankService; 276 } 277 278 /** 279 * Sets the bankService attribute value. 280 * 281 * @param bankService The bankService to set. 282 */ 283 public void setBankService(BankService bankService) { 284 this.bankService = bankService; 285 } 286 287 /** 288 * Sets the glPendingTransactionDao attribute value. 289 * 290 * @param glPendingTransactionDao The glPendingTransactionDao to set. 291 */ 292 public void setGlPendingTransactionDao(PendingTransactionDao glPendingTransactionDao) { 293 this.glPendingTransactionDao = glPendingTransactionDao; 294 } 295 296 /** 297 * Sets the accountingPeriodService attribute value. 298 * 299 * @param accountingPeriodService The accountingPeriodService to set. 300 */ 301 public void setAccountingPeriodService(AccountingPeriodService accountingPeriodService) { 302 this.accountingPeriodService = accountingPeriodService; 303 } 304 305 /** 306 * Sets the dateTimeService attribute value. 307 * 308 * @param dateTimeService The dateTimeService to set. 309 */ 310 public void setDateTimeService(DateTimeService dateTimeService) { 311 this.dateTimeService = dateTimeService; 312 } 313 314 /** 315 * Sets the kualiConfigurationService attribute value. 316 * 317 * @param kualiConfigurationService The kualiConfigurationService to set. 318 */ 319 public void setConfigurationService(ConfigurationService kualiConfigurationService) { 320 this.kualiConfigurationService = kualiConfigurationService; 321 } 322 323 /** 324 * @see org.kuali.ole.pdp.service.PendingTransactionService#save(org.kuali.ole.pdp.businessobject.GlPendingTransaction) 325 */ 326 public void save(GlPendingTransaction tran) { 327 LOG.debug("save() started"); 328 329 this.businessObjectService.save(tran); 330 } 331 332 /** 333 * @see org.kuali.ole.pdp.service.PendingTransactionService#getUnextractedTransactions() 334 */ 335 public Iterator<GlPendingTransaction> getUnextractedTransactions() { 336 LOG.debug("getUnextractedTransactions() started"); 337 338 return glPendingTransactionDao.getUnextractedTransactions(); 339 } 340 341 /** 342 * @see org.kuali.ole.pdp.service.PendingTransactionService#clearExtractedTransactions() 343 */ 344 public void clearExtractedTransactions() { 345 glPendingTransactionDao.clearExtractedTransactions(); 346 } 347 348 /** 349 * Sets the business object service 350 * 351 * @param businessObjectService 352 */ 353 public void setBusinessObjectService(BusinessObjectService businessObjectService) { 354 this.businessObjectService = businessObjectService; 355 } 356 357}