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.module.purap.document.dataaccess.impl; 017 018 import java.sql.Date; 019 import java.util.ArrayList; 020 import java.util.Arrays; 021 import java.util.Collection; 022 import java.util.Iterator; 023 import java.util.List; 024 025 import org.apache.log4j.Logger; 026 import org.apache.ojb.broker.query.Criteria; 027 import org.apache.ojb.broker.query.Query; 028 import org.apache.ojb.broker.query.QueryByCriteria; 029 import org.apache.ojb.broker.query.ReportQueryByCriteria; 030 import org.kuali.kfs.module.purap.PurapConstants; 031 import org.kuali.kfs.module.purap.PurapPropertyConstants; 032 import org.kuali.kfs.module.purap.PurapConstants.PaymentRequestStatuses; 033 import org.kuali.kfs.module.purap.batch.service.PurapRunDateService; 034 import org.kuali.kfs.module.purap.document.PaymentRequestDocument; 035 import org.kuali.kfs.module.purap.document.dataaccess.NegativePaymentRequestApprovalLimitDao; 036 import org.kuali.kfs.module.purap.document.dataaccess.PaymentRequestDao; 037 import org.kuali.kfs.module.purap.service.PurapAccountingService; 038 import org.kuali.kfs.module.purap.util.VendorGroupingHelper; 039 import org.kuali.kfs.sys.KFSPropertyConstants; 040 import org.kuali.kfs.sys.context.SpringContext; 041 import org.kuali.rice.kew.exception.WorkflowException; 042 import org.kuali.rice.kns.dao.impl.PlatformAwareDaoBaseOjb; 043 import org.kuali.rice.kns.exception.InfrastructureException; 044 import org.kuali.rice.kns.service.DateTimeService; 045 import org.kuali.rice.kns.service.DocumentService; 046 import org.kuali.rice.kns.service.KualiConfigurationService; 047 import org.kuali.rice.kns.util.KualiDecimal; 048 import org.kuali.rice.kns.util.TransactionalServiceUtils; 049 050 /** 051 * OJB Implementation of PaymentRequestDao. 052 */ 053 public class PaymentRequestDaoOjb extends PlatformAwareDaoBaseOjb implements PaymentRequestDao { 054 private static Logger LOG = Logger.getLogger(PaymentRequestDaoOjb.class); 055 056 private NegativePaymentRequestApprovalLimitDao negativePaymentRequestApprovalLimitDao; 057 private DateTimeService dateTimeService; 058 private PurapAccountingService purapAccountingService; 059 private KualiConfigurationService kualiConfigurationService; 060 private PurapRunDateService purapRunDateService; 061 062 public void setNegativePaymentRequestApprovalLimitDao(NegativePaymentRequestApprovalLimitDao negativePaymentRequestApprovalLimitDao) { 063 this.negativePaymentRequestApprovalLimitDao = negativePaymentRequestApprovalLimitDao; 064 } 065 066 public void setDateTimeService(DateTimeService dateTimeService) { 067 this.dateTimeService = dateTimeService; 068 } 069 070 public void setPurapAccountingService(PurapAccountingService purapAccountingService) { 071 this.purapAccountingService = purapAccountingService; 072 } 073 074 public void setKualiConfigurationService(KualiConfigurationService kualiConfigurationService) { 075 this.kualiConfigurationService = kualiConfigurationService; 076 } 077 078 public void setPurapRunDateService(PurapRunDateService purapRunDateService) { 079 this.purapRunDateService = purapRunDateService; 080 } 081 082 083 /** 084 * The special payments query should be this: select * from pur.ap_pmt_rqst_t where pmt_rqst_stat_cd in ('AUTO', 'DPTA') and 085 * prcs_cmp_cd = ? and pmt_extrt_ts is NULL and pmt_hld_ind = 'N' and ( ( ( pmt_spcl_handlg_instrc_ln1_txt is not NULL or 086 * pmt_spcl_handlg_instrc_ln2_txt is not NULL or pmt_spcl_handlg_instrc_ln3_txt is not NULL or pmt_att_ind = 'Y') and trunc 087 * (pmt_rqst_pay_dt) <= trunc (sysdate)) or IMD_PMT_IND = 'Y')}) 088 * 089 * @see org.kuali.kfs.module.purap.document.dataaccess.PaymentRequestDao#getPaymentRequestsToExtract(boolean, java.lang.String) 090 */ 091 public Collection<PaymentRequestDocument> getPaymentRequestsToExtract(boolean onlySpecialPayments, String chartCode, 092 Date onOrBeforePaymentRequestPayDate) { 093 LOG.debug("getPaymentRequestsToExtract() started"); 094 095 Criteria criteria = new Criteria(); 096 if (chartCode != null) { 097 criteria.addEqualTo("processingCampusCode", chartCode); 098 } 099 criteria.addIn("statusCode", Arrays.asList(PaymentRequestStatuses.STATUSES_ALLOWED_FOR_EXTRACTION)); 100 criteria.addIsNull("extractedTimestamp"); 101 criteria.addEqualTo("holdIndicator", Boolean.FALSE); 102 103 if (onlySpecialPayments) { 104 Criteria a = new Criteria(); 105 106 Criteria c1 = new Criteria(); 107 c1.addNotNull("specialHandlingInstructionLine1Text"); 108 Criteria c2 = new Criteria(); 109 c2.addNotNull("specialHandlingInstructionLine2Text"); 110 Criteria c3 = new Criteria(); 111 c3.addNotNull("specialHandlingInstructionLine3Text"); 112 Criteria c4 = new Criteria(); 113 c4.addEqualTo("paymentAttachmentIndicator", Boolean.TRUE); 114 115 c1.addOrCriteria(c2); 116 c1.addOrCriteria(c3); 117 c1.addOrCriteria(c4); 118 119 a.addAndCriteria(c1); 120 a.addLessOrEqualThan("paymentRequestPayDate", onOrBeforePaymentRequestPayDate); 121 122 Criteria c5 = new Criteria(); 123 c5.addEqualTo("immediatePaymentIndicator", Boolean.TRUE); 124 c5.addOrCriteria(a); 125 126 criteria.addAndCriteria(a); 127 } 128 else { 129 Criteria c1 = new Criteria(); 130 c1.addLessOrEqualThan("paymentRequestPayDate", onOrBeforePaymentRequestPayDate); 131 132 Criteria c2 = new Criteria(); 133 c2.addEqualTo("immediatePaymentIndicator", Boolean.TRUE); 134 135 c1.addOrCriteria(c2); 136 criteria.addAndCriteria(c1); 137 } 138 139 return getPersistenceBrokerTemplate().getCollectionByQuery(new QueryByCriteria(PaymentRequestDocument.class, criteria)); 140 } 141 142 /** 143 * @see org.kuali.kfs.module.purap.document.dataaccess.PaymentRequestDao#getImmediatePaymentRequestsToExtract(java.lang.String) 144 */ 145 public Collection<PaymentRequestDocument> getImmediatePaymentRequestsToExtract(String chartCode) { 146 LOG.debug("getImmediatePaymentRequestsToExtract() started"); 147 148 Criteria criteria = new Criteria(); 149 if (chartCode != null) { 150 criteria.addEqualTo("processingCampusCode", chartCode); 151 } 152 153 criteria.addIn("statusCode", Arrays.asList(PaymentRequestStatuses.STATUSES_ALLOWED_FOR_EXTRACTION)); 154 criteria.addIsNull("extractedTimestamp"); 155 criteria.addEqualTo("immediatePaymentIndicator", Boolean.TRUE); 156 157 return getPersistenceBrokerTemplate().getCollectionByQuery(new QueryByCriteria(PaymentRequestDocument.class, criteria)); 158 } 159 160 /** 161 * @see org.kuali.kfs.module.purap.document.dataaccess.PaymentRequestDao#getPaymentRequestsToExtract(java.lang.String, java.lang.Integer, 162 * java.lang.Integer, java.lang.Integer, java.lang.Integer) 163 */ 164 public Iterator<PaymentRequestDocument> getPaymentRequestsToExtract(String campusCode, Integer paymentRequestIdentifier, Integer purchaseOrderIdentifier, Integer vendorHeaderGeneratedIdentifier, Integer vendorDetailAssignedIdentifier) { 165 LOG.debug("getPaymentRequestsToExtract() started"); 166 167 List statuses = new ArrayList(); 168 statuses.add(PurapConstants.PaymentRequestStatuses.AUTO_APPROVED); 169 statuses.add(PurapConstants.PaymentRequestStatuses.DEPARTMENT_APPROVED); 170 171 Criteria criteria = new Criteria(); 172 criteria.addEqualTo("processingCampusCode", campusCode); 173 criteria.addIn("statusCode", statuses); 174 criteria.addIsNull("extractedTimestamp"); 175 criteria.addEqualTo("holdIndicator", Boolean.FALSE); 176 177 Criteria c1 = new Criteria(); 178 c1.addLessOrEqualThan("paymentRequestPayDate", dateTimeService.getCurrentSqlDateMidnight()); 179 180 Criteria c2 = new Criteria(); 181 c2.addEqualTo("immediatePaymentIndicator", Boolean.TRUE); 182 183 c1.addOrCriteria(c2); 184 criteria.addAndCriteria(c1); 185 186 if (paymentRequestIdentifier != null) { 187 criteria.addEqualTo("purapDocumentIdentifier", paymentRequestIdentifier); 188 } 189 if (purchaseOrderIdentifier != null) { 190 criteria.addEqualTo("purchaseOrderIdentifier", purchaseOrderIdentifier); 191 } 192 criteria.addEqualTo("vendorHeaderGeneratedIdentifier", vendorHeaderGeneratedIdentifier); 193 criteria.addEqualTo("vendorDetailAssignedIdentifier", vendorDetailAssignedIdentifier); 194 195 return getPersistenceBrokerTemplate().getIteratorByQuery(new QueryByCriteria(PaymentRequestDocument.class, criteria)); 196 } 197 198 /** 199 * 200 * @see org.kuali.kfs.module.purap.document.dataaccess.PaymentRequestDao#getPaymentRequestsToExtractForVendor(java.lang.String, org.kuali.kfs.module.purap.util.VendorGroupingHelper) 201 */ 202 public Collection<PaymentRequestDocument> getPaymentRequestsToExtractForVendor(String campusCode, VendorGroupingHelper vendor, Date onOrBeforePaymentRequestPayDate) { 203 LOG.debug("getPaymentRequestsToExtract() started"); 204 205 List statuses = new ArrayList(); 206 statuses.add(PurapConstants.PaymentRequestStatuses.AUTO_APPROVED); 207 statuses.add(PurapConstants.PaymentRequestStatuses.DEPARTMENT_APPROVED); 208 209 Criteria criteria = new Criteria(); 210 criteria.addEqualTo("processingCampusCode", campusCode); 211 criteria.addIn("statusCode", statuses); 212 criteria.addIsNull("extractedTimestamp"); 213 criteria.addEqualTo("holdIndicator", Boolean.FALSE); 214 215 Criteria c1 = new Criteria(); 216 c1.addLessOrEqualThan("paymentRequestPayDate", onOrBeforePaymentRequestPayDate); 217 218 Criteria c2 = new Criteria(); 219 c2.addEqualTo("immediatePaymentIndicator", Boolean.TRUE); 220 221 c1.addOrCriteria(c2); 222 criteria.addAndCriteria(c1); 223 224 criteria.addEqualTo( "vendorHeaderGeneratedIdentifier", vendor.getVendorHeaderGeneratedIdentifier() ); 225 criteria.addEqualTo( "vendorDetailAssignedIdentifier", vendor.getVendorDetailAssignedIdentifier() ); 226 criteria.addEqualTo( "vendorCountryCode", vendor.getVendorCountry() ); 227 criteria.addLike( "vendorPostalCode", vendor.getVendorPostalCode() + "%" ); 228 229 return getPersistenceBrokerTemplate().getCollectionByQuery(new QueryByCriteria(PaymentRequestDocument.class, criteria)); 230 } 231 232 /** 233 * @see org.kuali.kfs.module.purap.document.dataaccess.PaymentRequestDao#getEligibleForAutoApproval() 234 */ 235 public List<PaymentRequestDocument> getEligibleForAutoApproval() { 236 Date todayAtMidnight = dateTimeService.getCurrentSqlDateMidnight(); 237 Criteria criteria = new Criteria(); 238 criteria.addLessOrEqualThan(PurapPropertyConstants.PAYMENT_REQUEST_PAY_DATE, todayAtMidnight); 239 criteria.addNotEqualTo("holdIndicator", "Y"); 240 criteria.addNotEqualTo("paymentRequestedCancelIndicator", "Y"); 241 criteria.addIn("status", Arrays.asList(PurapConstants.PaymentRequestStatuses.PREQ_STATUSES_FOR_AUTO_APPROVE)); 242 243 Query query = new QueryByCriteria(PaymentRequestDocument.class, criteria); 244 Iterator<PaymentRequestDocument> documents = (Iterator<PaymentRequestDocument>) getPersistenceBrokerTemplate().getIteratorByQuery(query); 245 ArrayList<String> documentHeaderIds = new ArrayList<String>(); 246 while (documents.hasNext()) { 247 PaymentRequestDocument document = (PaymentRequestDocument) documents.next(); 248 documentHeaderIds.add(document.getDocumentNumber()); 249 } 250 251 if (documentHeaderIds.size() > 0) { 252 try { 253 return SpringContext.getBean(DocumentService.class).getDocumentsByListOfDocumentHeaderIds(PaymentRequestDocument.class, documentHeaderIds); 254 } 255 catch (WorkflowException e) { 256 throw new InfrastructureException("unable to retrieve paymentRequestDocuments", e); 257 } 258 } 259 else { 260 return null; 261 } 262 263 } 264 265 /** 266 * @see org.kuali.kfs.module.purap.document.dataaccess.PaymentRequestDao#getDocumentNumberByPaymentRequestId(java.lang.Integer) 267 */ 268 public String getDocumentNumberByPaymentRequestId(Integer id) { 269 Criteria criteria = new Criteria(); 270 criteria.addEqualTo(PurapPropertyConstants.PURAP_DOC_ID, id); 271 return getDocumentNumberOfPaymentRequestByCriteria(criteria); 272 } 273 274 /** 275 * @see org.kuali.kfs.module.purap.document.dataaccess.PaymentRequestDao#getDocumentNumbersByPurchaseOrderId(java.lang.Integer) 276 */ 277 public List<String> getDocumentNumbersByPurchaseOrderId(Integer poPurApId) { 278 List<String> returnList = new ArrayList<String>(); 279 Criteria criteria = new Criteria(); 280 criteria.addEqualTo(PurapPropertyConstants.PURCHASE_ORDER_IDENTIFIER, poPurApId); 281 Iterator<Object[]> iter = getDocumentNumbersOfPaymentRequestByCriteria(criteria, false); 282 while (iter.hasNext()) { 283 Object[] cols = (Object[]) iter.next(); 284 returnList.add((String) cols[0]); 285 } 286 return returnList; 287 } 288 289 /** 290 * Retrieves a document number for a payment request by user defined criteria. 291 * 292 * @param criteria - list of criteria to use in the retrieve 293 * @return - document number 294 */ 295 protected String getDocumentNumberOfPaymentRequestByCriteria(Criteria criteria) { 296 LOG.debug("getDocumentNumberOfPaymentRequestByCriteria() started"); 297 Iterator<Object[]> iter = getDocumentNumbersOfPaymentRequestByCriteria(criteria, false); 298 if (iter.hasNext()) { 299 Object[] cols = (Object[]) iter.next(); 300 if (iter.hasNext()) { 301 // the iterator should have held only a single doc id of data but it holds 2 or more 302 String errorMsg = "Expected single document number for given criteria but multiple (at least 2) were returned"; 303 LOG.error(errorMsg); 304 TransactionalServiceUtils.exhaustIterator(iter); 305 throw new RuntimeException(); 306 } 307 // at this part of the code, we know there's no more elements in iterator 308 return (String) cols[0]; 309 } 310 return null; 311 } 312 313 /** 314 * Retrieves a document number for a payment request by user defined criteria and sorts the values ascending if orderByAscending 315 * parameter is true, descending otherwise. 316 * 317 * @param criteria - list of criteria to use in the retrieve 318 * @param orderByAscending - boolean to sort results ascending if true, descending otherwise 319 * @return - Iterator of document numbers 320 */ 321 protected Iterator<Object[]> getDocumentNumbersOfPaymentRequestByCriteria(Criteria criteria, boolean orderByAscending) { 322 LOG.debug("getDocumentNumberOfPaymentRequestByCriteria() started"); 323 ReportQueryByCriteria rqbc = new ReportQueryByCriteria(PaymentRequestDocument.class, criteria); 324 rqbc.setAttributes(new String[] { KFSPropertyConstants.DOCUMENT_NUMBER }); 325 if (orderByAscending) { 326 rqbc.addOrderByAscending(KFSPropertyConstants.DOCUMENT_NUMBER); 327 } 328 else { 329 rqbc.addOrderByDescending(KFSPropertyConstants.DOCUMENT_NUMBER); 330 } 331 return getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(rqbc); 332 } 333 334 /** 335 * Retrieves a list of payment requests by user defined criteria. 336 * 337 * @param qbc - query with criteria 338 * @return - list of payment requests 339 */ 340 protected List<PaymentRequestDocument> getPaymentRequestsByQueryByCriteria(QueryByCriteria qbc) { 341 LOG.debug("getPaymentRequestsByQueryByCriteria() started"); 342 List l = (List) getPersistenceBrokerTemplate().getCollectionByQuery(qbc); 343 return l; 344 } 345 346 /** 347 * Retrieves a list of payment requests with the given vendor id and invoice number. 348 * 349 * @param vendorHeaderGeneratedId - header id of the vendor id 350 * @param vendorDetailAssignedId - detail id of the vendor id 351 * @param invoiceNumber - invoice number as entered by AP 352 * @return - List of payment requests. 353 */ 354 public List<PaymentRequestDocument> getActivePaymentRequestsByVendorNumberInvoiceNumber(Integer vendorHeaderGeneratedId, Integer vendorDetailAssignedId, String invoiceNumber) { 355 LOG.debug("getActivePaymentRequestsByVendorNumberInvoiceNumber() started"); 356 Criteria criteria = new Criteria(); 357 criteria.addEqualTo("vendorHeaderGeneratedIdentifier", vendorHeaderGeneratedId); 358 criteria.addEqualTo("vendorDetailAssignedIdentifier", vendorDetailAssignedId); 359 criteria.addEqualTo("invoiceNumber", invoiceNumber); 360 QueryByCriteria qbc = new QueryByCriteria(PaymentRequestDocument.class, criteria); 361 return this.getPaymentRequestsByQueryByCriteria(qbc); 362 } 363 364 /** 365 * Retrieves a list of payment requests with the given vendor id and invoice number. 366 * 367 * @param vendorHeaderGeneratedId - header id of the vendor id 368 * @param vendorDetailAssignedId - detail id of the vendor id 369 * @param invoiceNumber - invoice number as entered by AP 370 * @return - List of payment requests. 371 */ 372 public List<PaymentRequestDocument> getActivePaymentRequestsByVendorNumber(Integer vendorHeaderGeneratedId, Integer vendorDetailAssignedId) { 373 LOG.debug("getActivePaymentRequestsByVendorNumber started"); 374 Criteria criteria = new Criteria(); 375 criteria.addEqualTo("vendorHeaderGeneratedIdentifier", vendorHeaderGeneratedId); 376 criteria.addEqualTo("vendorDetailAssignedIdentifier", vendorDetailAssignedId); 377 QueryByCriteria qbc = new QueryByCriteria(PaymentRequestDocument.class, criteria); 378 return this.getPaymentRequestsByQueryByCriteria(qbc); 379 } 380 381 382 /** 383 * @see org.kuali.kfs.module.purap.document.dataaccess.PaymentRequestDao#getActivePaymentRequestsByPOIdInvoiceAmountInvoiceDate(java.lang.Integer, 384 * org.kuali.rice.kns.util.KualiDecimal, java.sql.Date) 385 */ 386 public List<PaymentRequestDocument> getActivePaymentRequestsByPOIdInvoiceAmountInvoiceDate(Integer poId, KualiDecimal vendorInvoiceAmount, Date invoiceDate) { 387 LOG.debug("getActivePaymentRequestsByVendorNumberInvoiceNumber() started"); 388 Criteria criteria = new Criteria(); 389 criteria.addEqualTo("purchaseOrderIdentifier", poId); 390 criteria.addEqualTo("vendorInvoiceAmount", vendorInvoiceAmount); 391 criteria.addEqualTo("invoiceDate", invoiceDate); 392 QueryByCriteria qbc = new QueryByCriteria(PaymentRequestDocument.class, criteria); 393 return this.getPaymentRequestsByQueryByCriteria(qbc); 394 } 395 396 public List<String> getActivePaymentRequestDocumentNumbersForPurchaseOrder(Integer purchaseOrderId){ 397 LOG.debug("getActivePaymentRequestsByVendorNumberInvoiceNumber() started"); 398 399 List<String> returnList = new ArrayList<String>(); 400 Criteria criteria = new Criteria(); 401 402 criteria.addEqualTo(PurapPropertyConstants.PURCHASE_ORDER_IDENTIFIER, purchaseOrderId); 403 criteria.addIn(PurapPropertyConstants.STATUS_CODE, Arrays.asList(PaymentRequestStatuses.STATUSES_POTENTIALLY_ACTIVE)); 404 QueryByCriteria qbc = new QueryByCriteria(PaymentRequestDocument.class, criteria); 405 406 Iterator<Object[]> iter = getDocumentNumbersOfPaymentRequestByCriteria(criteria, false); 407 while (iter.hasNext()) { 408 Object[] cols = (Object[]) iter.next(); 409 returnList.add((String) cols[0]); 410 } 411 return returnList; 412 } 413 414 public List<PaymentRequestDocument> getPaymentRequestInReceivingStatus() { 415 Criteria criteria = new Criteria(); 416 criteria.addNotEqualTo("holdIndicator", "Y"); 417 criteria.addNotEqualTo("paymentRequestedCancelIndicator", "Y"); 418 criteria.addEqualTo("statusCode", PurapConstants.PaymentRequestStatuses.AWAITING_RECEIVING_REVIEW); 419 420 Query query = new QueryByCriteria(PaymentRequestDocument.class, criteria); 421 Iterator<PaymentRequestDocument> documents = (Iterator<PaymentRequestDocument>) getPersistenceBrokerTemplate().getIteratorByQuery(query); 422 ArrayList<String> documentHeaderIds = new ArrayList<String>(); 423 while (documents.hasNext()) { 424 PaymentRequestDocument document = (PaymentRequestDocument) documents.next(); 425 documentHeaderIds.add(document.getDocumentNumber()); 426 } 427 428 if (documentHeaderIds.size() > 0) { 429 try { 430 return SpringContext.getBean(DocumentService.class).getDocumentsByListOfDocumentHeaderIds(PaymentRequestDocument.class, documentHeaderIds); 431 } 432 catch (WorkflowException e) { 433 throw new InfrastructureException("unable to retrieve paymentRequestDocuments", e); 434 } 435 } 436 else { 437 return null; 438 } 439 440 } 441 }