View Javadoc
1   /*
2    * Copyright 2007 The Kuali Foundation
3    * 
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    * http://www.opensource.org/licenses/ecl2.php
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  /*
17   * Created on Aug 30, 2004
18   *
19   */
20  package org.kuali.ole.pdp.service.impl;
21  
22  import java.sql.Date;
23  import java.util.ArrayList;
24  import java.util.Iterator;
25  import java.util.List;
26  
27  import org.apache.commons.lang.StringUtils;
28  import org.kuali.ole.coa.businessobject.AccountingPeriod;
29  import org.kuali.ole.coa.businessobject.OffsetDefinition;
30  import org.kuali.ole.coa.service.AccountingPeriodService;
31  import org.kuali.ole.coa.service.OffsetDefinitionService;
32  import org.kuali.ole.pdp.PdpConstants;
33  import org.kuali.ole.pdp.businessobject.GlPendingTransaction;
34  import org.kuali.ole.pdp.businessobject.PaymentAccountDetail;
35  import org.kuali.ole.pdp.businessobject.PaymentDetail;
36  import org.kuali.ole.pdp.businessobject.PaymentGroup;
37  import org.kuali.ole.pdp.dataaccess.PendingTransactionDao;
38  import org.kuali.ole.pdp.service.PendingTransactionService;
39  import org.kuali.ole.sys.OLEConstants;
40  import org.kuali.ole.sys.OLEKeyConstants;
41  import org.kuali.ole.sys.businessobject.Bank;
42  import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper;
43  import org.kuali.ole.sys.context.SpringContext;
44  import org.kuali.ole.sys.service.BankService;
45  import org.kuali.ole.sys.service.FlexibleOffsetAccountService;
46  import org.kuali.rice.core.api.config.property.ConfigurationService;
47  import org.kuali.rice.core.api.datetime.DateTimeService;
48  import org.kuali.rice.core.api.util.type.KualiInteger;
49  import org.kuali.rice.krad.service.BusinessObjectService;
50  import org.springframework.transaction.annotation.Transactional;
51  
52  /**
53   * @see org.kuali.ole.pdp.service.PendingTransactionService
54   */
55  @Transactional
56  public class PendingTransactionServiceImpl implements PendingTransactionService {
57      private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PendingTransactionServiceImpl.class);
58  
59      protected static String FDOC_TYP_CD_PROCESS_ACH = "ACHD";
60      protected static String FDOC_TYP_CD_PROCESS_CHECK = "CHKD";
61      protected static String FDOC_TYP_CD_CANCEL_REISSUE_ACH = "ACHR";
62      protected static String FDOC_TYP_CD_CANCEL_REISSUE_CHECK = "CHKR";
63      protected static String FDOC_TYP_CD_CANCEL_ACH = "ACHC";
64      protected static String FDOC_TYP_CD_CANCEL_CHECK = "CHKC";
65  
66      private PendingTransactionDao glPendingTransactionDao;
67      private AccountingPeriodService accountingPeriodService;
68      private DateTimeService dateTimeService;
69      private ConfigurationService kualiConfigurationService;
70      private BusinessObjectService businessObjectService;
71      private BankService bankService;
72  
73      public PendingTransactionServiceImpl() {
74          super();
75      }
76  
77      /**
78       * @see org.kuali.ole.pdp.service.PendingTransactionService#generatePaymentGeneralLedgerPendingEntry(org.kuali.ole.pdp.businessobject.PaymentGroup)
79       */
80      public void generatePaymentGeneralLedgerPendingEntry(PaymentGroup paymentGroup) {
81          this.populatePaymentGeneralLedgerPendingEntry(paymentGroup, FDOC_TYP_CD_PROCESS_ACH, FDOC_TYP_CD_PROCESS_CHECK, false);
82      }
83  
84      /**
85       * @see org.kuali.ole.pdp.service.PendingTransactionService#generateCancellationGeneralLedgerPendingEntry(org.kuali.ole.pdp.businessobject.PaymentGroup)
86       */
87      public void generateCancellationGeneralLedgerPendingEntry(PaymentGroup paymentGroup) {
88          this.populatePaymentGeneralLedgerPendingEntry(paymentGroup, FDOC_TYP_CD_CANCEL_ACH, FDOC_TYP_CD_CANCEL_CHECK, true);
89      }
90  
91      /**
92       * @see org.kuali.ole.pdp.service.PendingTransactionService#generateReissueGeneralLedgerPendingEntry(org.kuali.ole.pdp.businessobject.PaymentGroup)
93       */
94      public void generateReissueGeneralLedgerPendingEntry(PaymentGroup paymentGroup) {
95          this.populatePaymentGeneralLedgerPendingEntry(paymentGroup, FDOC_TYP_CD_CANCEL_REISSUE_ACH, FDOC_TYP_CD_CANCEL_REISSUE_CHECK, true);
96      }
97  
98      /**
99       * 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 }