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.ar.document.service.impl; 017 018 import java.sql.Timestamp; 019 import java.text.DateFormat; 020 import java.text.ParseException; 021 import java.text.SimpleDateFormat; 022 import java.util.ArrayList; 023 import java.util.Calendar; 024 import java.util.Collection; 025 import java.util.Date; 026 import java.util.Hashtable; 027 import java.util.Iterator; 028 import java.util.List; 029 import java.util.Map; 030 031 import org.apache.commons.lang.StringUtils; 032 import org.kuali.kfs.module.ar.ArConstants; 033 import org.kuali.kfs.module.ar.businessobject.AccountsReceivableDocumentHeader; 034 import org.kuali.kfs.module.ar.businessobject.CustomerInvoiceDetail; 035 import org.kuali.kfs.module.ar.businessobject.CustomerOpenItemReportDetail; 036 import org.kuali.kfs.module.ar.businessobject.NonAppliedHolding; 037 import org.kuali.kfs.module.ar.document.CustomerInvoiceDocument; 038 import org.kuali.kfs.module.ar.document.PaymentApplicationDocument; 039 import org.kuali.kfs.module.ar.document.dataaccess.AccountsReceivableDocumentHeaderDao; 040 import org.kuali.kfs.module.ar.document.dataaccess.CustomerInvoiceDetailDao; 041 import org.kuali.kfs.module.ar.document.dataaccess.NonAppliedHoldingDao; 042 import org.kuali.kfs.module.ar.document.service.CustomerInvoiceDocumentService; 043 import org.kuali.kfs.module.ar.document.service.CustomerOpenItemReportService; 044 import org.kuali.kfs.sys.KFSConstants; 045 import org.kuali.kfs.sys.businessobject.FinancialSystemDocumentHeader; 046 import org.kuali.kfs.sys.context.SpringContext; 047 import org.kuali.kfs.sys.document.dataaccess.FinancialSystemDocumentHeaderDao; 048 import org.kuali.rice.kew.exception.WorkflowException; 049 import org.kuali.rice.kim.bo.Person; 050 import org.kuali.rice.kns.exception.InfrastructureException; 051 import org.kuali.rice.kns.exception.UnknownDocumentIdException; 052 import org.kuali.rice.kns.service.DateTimeService; 053 import org.kuali.rice.kns.service.DocumentService; 054 import org.kuali.rice.kns.util.GlobalVariables; 055 import org.kuali.rice.kns.util.KualiDecimal; 056 import org.kuali.rice.kns.util.ObjectUtils; 057 import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument; 058 import org.kuali.rice.kns.workflow.service.WorkflowDocumentService; 059 import org.springframework.transaction.annotation.Transactional; 060 061 @Transactional 062 public class CustomerOpenItemReportServiceImpl implements CustomerOpenItemReportService { 063 064 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(CustomerOpenItemReportServiceImpl.class); 065 066 private AccountsReceivableDocumentHeaderDao accountsReceivableDocumentHeaderDao; 067 private WorkflowDocumentService workflowDocumentService; 068 private CustomerInvoiceDocumentService customerInvoiceDocumentService; 069 private FinancialSystemDocumentHeaderDao financialSystemDocumentHeaderDao; 070 private DocumentService documentService; 071 private DateTimeService dateTimeService; 072 private CustomerInvoiceDetailDao customerInvoiceDetailDao; 073 private NonAppliedHoldingDao nonAppliedHoldingDao; 074 075 /** 076 * This method populates CustomerOpenItemReportDetails (Customer History Report). 077 * 078 * @param customerNumber 079 */ 080 public List getPopulatedReportDetails(String customerNumber) { 081 List results = new ArrayList(); 082 083 Collection arDocumentHeaders = accountsReceivableDocumentHeaderDao.getARDocumentHeadersByCustomerNumber(customerNumber); 084 if (arDocumentHeaders.size() == 0) 085 return results; 086 087 Person user = GlobalVariables.getUserSession().getPerson(); 088 089 List finSysDocHeaderIds = new ArrayList(); 090 List invoiceIds = new ArrayList(); 091 List paymentApplicationIds = new ArrayList(); 092 List unappliedHoldingIds = new ArrayList(); 093 094 Hashtable details = new Hashtable(); 095 KualiWorkflowDocument workflowDocument; 096 097 098 for (Iterator itr = arDocumentHeaders.iterator(); itr.hasNext();) { 099 AccountsReceivableDocumentHeader documentHeader = (AccountsReceivableDocumentHeader) itr.next(); 100 CustomerOpenItemReportDetail detail = new CustomerOpenItemReportDetail(); 101 102 // populate workflow document 103 try { 104 workflowDocument = workflowDocumentService.createWorkflowDocument(Long.valueOf(documentHeader.getDocumentNumber()), user); 105 } 106 catch (WorkflowException e) { 107 throw new UnknownDocumentIdException("No document found for documentHeaderId '" + documentHeader.getDocumentNumber() + "'", e); 108 } 109 110 // do not display not approved documents 111 Date approvedDate = getSqlDate(workflowDocument.getRouteHeader().getDateApproved()); 112 if (ObjectUtils.isNull(approvedDate)) { 113 continue; 114 } 115 116 // Document Type 117 String documentType = workflowDocument.getDocumentType(); 118 detail.setDocumentType(documentType); 119 120 // Document Number 121 String documentNumber = documentHeader.getDocumentNumber(); 122 detail.setDocumentNumber(documentNumber); 123 124 if (documentType.equals("INV")) 125 invoiceIds.add(documentNumber); 126 else { 127 // Approved Date -> for invoices Due Date, for all other documents Approved Date 128 detail.setDueApprovedDate(approvedDate); 129 130 if (documentType.equals("APP")) 131 paymentApplicationIds.add(documentNumber); 132 else 133 finSysDocHeaderIds.add(documentNumber); 134 } 135 details.put(documentNumber, detail); 136 } 137 138 // add Unapplied Payment Applications 139 Collection<NonAppliedHolding> arNonAppliedHoldings = nonAppliedHoldingDao.getNonAppliedHoldingsForCustomer(customerNumber); 140 for (NonAppliedHolding nonAppliedHolding : arNonAppliedHoldings) { 141 // populate workflow document 142 try { 143 workflowDocument = workflowDocumentService.createWorkflowDocument(Long.valueOf(nonAppliedHolding.getReferenceFinancialDocumentNumber()), user); 144 } 145 catch (WorkflowException e) { 146 throw new UnknownDocumentIdException("No document found for documentHeaderId '" + nonAppliedHolding.getReferenceFinancialDocumentNumber() + "'", e); 147 } 148 149 CustomerOpenItemReportDetail detail = new CustomerOpenItemReportDetail(); 150 detail.setDocumentType("APP"); 151 detail.setDocumentNumber(nonAppliedHolding.getReferenceFinancialDocumentNumber()); 152 Date documentApprovedDate = getSqlDate(workflowDocument.getRouteHeader().getDateApproved()); 153 detail.setDueApprovedDate(documentApprovedDate); 154 details.put(nonAppliedHolding.getReferenceFinancialDocumentNumber(), detail); 155 unappliedHoldingIds.add(nonAppliedHolding.getReferenceFinancialDocumentNumber()); 156 } 157 158 // for invoices 159 if (invoiceIds.size() > 0) 160 populateReportDetailsForInvoices(invoiceIds, results, details); 161 162 // for payment applications 163 if (paymentApplicationIds.size() > 0) { 164 try { 165 populateReportDetailsForPaymentApplications(paymentApplicationIds, results, details); 166 } catch(WorkflowException w) { 167 LOG.error("WorkflowException while populating report details for PaymentApplicationDocument", w); 168 } 169 } 170 171 // for unapplied payment applications 172 if (unappliedHoldingIds.size() > 0) { 173 try { 174 populateReportDetailsForUnappliedPaymentApplications(unappliedHoldingIds, results, details); 175 } catch(WorkflowException w) { 176 LOG.error("WorkflowException while populating report details for PaymentApplicationDocument", w); 177 } 178 } 179 180 // for all other documents 181 if (finSysDocHeaderIds.size() > 0) 182 populateReportDetails(finSysDocHeaderIds, results, details); 183 184 return results; 185 } 186 187 /** 188 * This method populates CustomerOpenItemReportDetails for CustomerInvoiceDocuments (Customer History Report). 189 * 190 * @param finSysDocHeaderIds <=> documentNumbers of CustomerInvoiceDocuments 191 * @param results <=> CustomerOpenItemReportDetails to display in the report 192 * @param details <=> <key = documentNumber, value = customerOpenItemReportDetail> 193 */ 194 protected void populateReportDetailsForInvoices(List invoiceIds, List results, Hashtable details) { 195 CustomerInvoiceDocumentService customerInvoiceDocumentService = SpringContext.getBean(CustomerInvoiceDocumentService.class); 196 Collection invoices = getDocuments(CustomerInvoiceDocument.class, invoiceIds); 197 198 for (Iterator itr = invoices.iterator(); itr.hasNext();) { 199 CustomerInvoiceDocument invoice = (CustomerInvoiceDocument) itr.next(); 200 String documentNumber = invoice.getDocumentNumber(); 201 202 CustomerOpenItemReportDetail detail = (CustomerOpenItemReportDetail) details.get(documentNumber); 203 204 // Document Description 205 String documentDescription = invoice.getDocumentHeader().getDocumentDescription(); 206 if (ObjectUtils.isNotNull(documentDescription)) 207 detail.setDocumentDescription(documentDescription); 208 else 209 detail.setDocumentDescription(""); 210 211 // Billing Date 212 detail.setBillingDate(invoice.getBillingDate()); 213 214 // Due/Approved Date -> for invoice it is Due Date, and for all other documents Approved Date 215 detail.setDueApprovedDate(invoice.getInvoiceDueDate()); 216 217 // Document Payment Amount 218 detail.setDocumentPaymentAmount(invoice.getDocumentHeader().getFinancialDocumentTotalAmount()); 219 220 // Unpaid/Unapplied Amount 221 detail.setUnpaidUnappliedAmount(customerInvoiceDocumentService.getOpenAmountForCustomerInvoiceDocument(invoice)); 222 223 results.add(detail); 224 } 225 } 226 227 /** 228 * This method populates CustomerOpenItemReportDetails for PaymentApplicationDocuments (Customer History Report). 229 * 230 * @param paymentApplicationIds <=> documentNumbers of PaymentApplicationDocuments 231 * @param results <=> CustomerOpenItemReportDetails to display in the report 232 * @param details <=> <key = documentNumber, value = customerOpenItemReportDetail> 233 */ 234 protected void populateReportDetailsForPaymentApplications(List paymentApplicationIds, List results, Hashtable details) throws WorkflowException { 235 Collection paymentApplications = getDocuments(PaymentApplicationDocument.class, paymentApplicationIds); 236 237 for (Iterator itr = paymentApplications.iterator(); itr.hasNext();) { 238 PaymentApplicationDocument paymentApplication = (PaymentApplicationDocument) itr.next(); 239 String documentNumber = paymentApplication.getDocumentNumber(); 240 241 CustomerOpenItemReportDetail detail = (CustomerOpenItemReportDetail) details.get(documentNumber); 242 243 // populate Document Description 244 String documentDescription = paymentApplication.getDocumentHeader().getDocumentDescription(); 245 if (ObjectUtils.isNotNull(documentDescription)) 246 detail.setDocumentDescription(documentDescription); 247 else 248 detail.setDocumentDescription(""); 249 250 // populate Document Payment Amount 251 detail.setDocumentPaymentAmount(paymentApplication.getDocumentHeader().getFinancialDocumentTotalAmount().negated()); 252 253 // populate Unpaid/Unapplied Amount if the customer number is the same 254 if (ObjectUtils.isNotNull(paymentApplication.getNonAppliedHolding())) { 255 if (paymentApplication.getNonAppliedHolding().getCustomerNumber().equals(paymentApplication.getAccountsReceivableDocumentHeader().getCustomerNumber())) { 256 detail.setUnpaidUnappliedAmount(paymentApplication.getNonAppliedHolding().getAvailableUnappliedAmount().negated()); 257 } 258 } 259 260 results.add(detail); 261 } 262 } 263 264 /** 265 * This method populates CustomerOpenItemReportDetails for UnappliedPaymentApplicationDocuments (Customer History Report). 266 * 267 * @param unappliedHoldingIds <=> documentNumbers of UnappliedPaymentApplicationDocuments 268 * @param results <=> CustomerOpenItemReportDetails to display in the report 269 * @param details <=> <key = documentNumber, value = customerOpenItemReportDetail> 270 */ 271 protected void populateReportDetailsForUnappliedPaymentApplications(List unappliedHoldingIds, List results, Hashtable details) throws WorkflowException { 272 Collection paymentApplications = getDocuments(PaymentApplicationDocument.class, unappliedHoldingIds); 273 274 for (Iterator itr = paymentApplications.iterator(); itr.hasNext();) { 275 PaymentApplicationDocument paymentApplication = (PaymentApplicationDocument) itr.next(); 276 String documentNumber = paymentApplication.getDocumentNumber(); 277 278 if ((paymentApplication.getNonAppliedHolding().getCustomerNumber().equals(paymentApplication.getAccountsReceivableDocumentHeader().getCustomerNumber()))) { 279 continue; 280 } 281 282 CustomerOpenItemReportDetail detail = (CustomerOpenItemReportDetail) details.get(documentNumber); 283 284 // populate Document Description 285 String documentDescription = paymentApplication.getDocumentHeader().getDocumentDescription(); 286 if (ObjectUtils.isNotNull(documentDescription)) 287 detail.setDocumentDescription(documentDescription); 288 else 289 detail.setDocumentDescription(""); 290 291 // populate Document Payment Amount 292 detail.setDocumentPaymentAmount(KualiDecimal.ZERO); 293 294 // populate Unpaid/Unapplied Amount if the customer number is not the same 295 detail.setUnpaidUnappliedAmount(paymentApplication.getNonAppliedHoldingAmount().negated()); 296 297 results.add(detail); 298 } 299 } 300 301 /** 302 * This method populates CustomerOpenItemReportDetails for CustomerCreditMemoDocuments and WriteOffDocuments <=> all documents 303 * but CustomerInvoiceDocument and PaymentApplicationDocument (Customer History Report). 304 * 305 * @param finSysDocHeaderIds <=> documentNumbers of FinancialSystemDocumentHeaders 306 * @param results <=> CustomerOpenItemReportDetails to display in the report 307 * @param details <=> <key = documentNumber, value = customerOpenItemReportDetail> 308 */ 309 public void populateReportDetails(List finSysDocHeaderIds, List results, Hashtable details) { 310 Collection financialSystemDocHeaders = financialSystemDocumentHeaderDao.getByDocumentNumbers(finSysDocHeaderIds); 311 312 for (Iterator itr = financialSystemDocHeaders.iterator(); itr.hasNext();) { 313 FinancialSystemDocumentHeader fsDocumentHeader = (FinancialSystemDocumentHeader) itr.next(); 314 String documentNumber = fsDocumentHeader.getDocumentNumber(); 315 316 CustomerOpenItemReportDetail detail = (CustomerOpenItemReportDetail) details.get(documentNumber); 317 318 // populate Document Description 319 String documentDescription = fsDocumentHeader.getDocumentDescription(); 320 if (ObjectUtils.isNotNull(documentDescription)) 321 detail.setDocumentDescription(documentDescription); 322 else 323 detail.setDocumentDescription(""); 324 325 // populate Document Payment Amount 326 detail.setDocumentPaymentAmount(fsDocumentHeader.getFinancialDocumentTotalAmount().negated()); 327 328 // Unpaid/Unapplied Amount 329 detail.setUnpaidUnappliedAmount(KualiDecimal.ZERO); 330 331 results.add(detail); 332 } 333 } 334 335 /** 336 * This method returns collection of documents of type classToSearchFrom Note: can be used for documents only, not for 337 * *DocumentHeaders @param documentNumbers 338 */ 339 public Collection getDocuments(Class classToSearchFrom, List documentNumbers) { 340 List docs; 341 342 try { 343 docs = documentService.getDocumentsByListOfDocumentHeaderIds(classToSearchFrom, documentNumbers); 344 } 345 catch (WorkflowException e) { 346 throw new InfrastructureException("Unable to retrieve documents", e); 347 } 348 return docs; 349 } 350 351 protected Date getSqlDate(Calendar cal) { 352 Date sqlDueDate = null; 353 354 if (ObjectUtils.isNull(cal)) 355 return sqlDueDate; 356 try { 357 sqlDueDate = dateTimeService.convertToSqlDate(new Timestamp(cal.getTime().getTime())); 358 } 359 catch (ParseException e) { 360 // TODO: throw an error here, but don't die 361 } 362 return sqlDueDate; 363 } 364 365 /** 366 * This method populates CustomerOpenItemReportDetails (Customer Open Item Report) 367 * 368 * @param urlParameters 369 */ 370 public List getPopulatedReportDetails(Map urlParameters) { 371 List results = new ArrayList(); 372 373 // get arDocumentHeaders 374 Collection<AccountsReceivableDocumentHeader> arDocumentHeaders = getARDocumentHeaders(urlParameters); 375 if (arDocumentHeaders.size() == 0) 376 return results; 377 378 // get ids of arDocumentHeaders 379 List<String> arDocumentHeaderIds = new ArrayList<String>(); 380 for (AccountsReceivableDocumentHeader arDocHeader : arDocumentHeaders) { 381 arDocumentHeaderIds.add(arDocHeader.getDocumentNumber()); 382 } 383 384 // get invoices 385 String reportOption = ((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.REPORT_OPTION))[0]; 386 Collection<CustomerInvoiceDocument> invoices; 387 Collection<CustomerInvoiceDetail> details = null; 388 if (StringUtils.equals(reportOption, ArConstants.CustomerAgingReportFields.ACCT)) { 389 String accountNumber = ((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.ACCOUNT_NUMBER))[0]; 390 details = customerInvoiceDetailDao.getCustomerInvoiceDetailsByAccountNumberByInvoiceDocumentNumbers(accountNumber, arDocumentHeaderIds); 391 invoices = getInvoicesByAccountNumberByDocumentIds(accountNumber, arDocumentHeaderIds, details); 392 } 393 else { 394 invoices = getDocuments(CustomerInvoiceDocument.class, arDocumentHeaderIds); 395 } 396 if (ObjectUtils.isNull(invoices) | invoices.size()==0 ) 397 return results; 398 399 List<CustomerInvoiceDocument> selectedInvoices = new ArrayList(); 400 401 String columnTitle = ((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.COLUMN_TITLE))[0]; 402 DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy"); 403 404 java.util.Date reportRunDate= null; 405 java.util.Date beginDate = null; 406 java.util.Date endDate = null; 407 try { 408 reportRunDate = dateFormat.parse(((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.REPORT_RUN_DATE))[0]); 409 if (!StringUtils.equals(columnTitle, KFSConstants.CustomerOpenItemReport.ALL_DAYS)) { 410 endDate = dateFormat.parse(((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.REPORT_END_DATE))[0]); 411 String strBeginDate = ((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.REPORT_BEGIN_DATE))[0]; 412 if (StringUtils.isNotEmpty(strBeginDate)) 413 beginDate = dateFormat.parse(strBeginDate); 414 } 415 } 416 catch (ParseException e) { 417 e.printStackTrace(); 418 } 419 420 // Billing Organization 421 if (StringUtils.equals(reportOption, ArConstants.CustomerAgingReportFields.BILLING_ORG)) { 422 // All days 423 // 1. invoice open amount > 0 424 // 2. billingDate <= reportRunDate 425 // 3. billByChartOfAccountsCode = processingOrBillingChartCode 426 // 4. billbyOrganizationCode = orgCode 427 String chartCode = ((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.PROCESSING_OR_BILLING_CHART_CODE))[0]; 428 String orgCode = ((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.ORGANIZATION_CODE))[0]; 429 if (StringUtils.equals(columnTitle, KFSConstants.CustomerOpenItemReport.ALL_DAYS)) { 430 for (CustomerInvoiceDocument invoice:invoices) { 431 // get only invoices with open amounts 432 if (ObjectUtils.isNull(invoice.getClosedDate())&& ObjectUtils.isNotNull(invoice.getBillingDate()) && !reportRunDate.before(invoice.getBillingDate()) && StringUtils.equals(chartCode, invoice.getBillByChartOfAccountCode()) && StringUtils.equals(orgCode, invoice.getBilledByOrganizationCode()) ) 433 selectedInvoices.add(invoice); 434 } 435 } 436 // *days 437 // 1. invoice open amount > 0 438 // 2. beginDate <= invoice billing date <= endDate 439 // 3. billByChartOfAccountsCode = chartCode 440 // 4. billbyOrganizationCode = orgCode 441 else { 442 for (CustomerInvoiceDocument invoice:invoices) { 443 if (ObjectUtils.isNull(invoice.getClosedDate())&& ObjectUtils.isNotNull(invoice.getBillingDate()) && StringUtils.equals(chartCode, invoice.getBillByChartOfAccountCode()) && StringUtils.equals(orgCode, invoice.getBilledByOrganizationCode()) ) 444 if ( (ObjectUtils.isNotNull(beginDate) && !beginDate.after(invoice.getBillingDate()) && !endDate.before(invoice.getBillingDate())) || (ObjectUtils.isNull(beginDate) && !endDate.before(invoice.getBillingDate())) ) 445 selectedInvoices.add(invoice); 446 } 447 } 448 } 449 // Processing Organization or Account 450 else { 451 // All days 452 // 1. invoice open amount > 0 453 // 2. invoice billing dates <= reportRunDate 454 if (StringUtils.equals(columnTitle, KFSConstants.CustomerOpenItemReport.ALL_DAYS)) { 455 for (CustomerInvoiceDocument invoice:invoices) { 456 if (ObjectUtils.isNull(invoice.getClosedDate()) && ObjectUtils.isNotNull(invoice.getBillingDate())&& !reportRunDate.before(invoice.getBillingDate())) 457 selectedInvoices.add(invoice); 458 } 459 } 460 // *days 461 // 1. invoice open amount > 0 462 // 2. beginDate <= invoice billing date <= endDate 463 else { 464 for (CustomerInvoiceDocument invoice:invoices) { 465 if (ObjectUtils.isNull(invoice.getClosedDate())&& ObjectUtils.isNotNull(invoice.getBillingDate())) 466 if ( (ObjectUtils.isNotNull(beginDate) && !beginDate.after(invoice.getBillingDate()) && !endDate.before(invoice.getBillingDate())) || (ObjectUtils.isNull(beginDate) && !endDate.before(invoice.getBillingDate())) ) 467 selectedInvoices.add(invoice); 468 } 469 } 470 } 471 472 if (selectedInvoices.size() == 0) 473 return results; 474 475 if (StringUtils.equals(reportOption, ArConstants.CustomerAgingReportFields.ACCT)) 476 populateReporDetails(selectedInvoices,results,details); 477 else 478 populateReportDetails(selectedInvoices,results); 479 480 return results; 481 } 482 483 /** 484 * This method retrieves ARDocumentHeader objects for "Customer Open Item Report" 485 * 486 * @param urlParameters 487 * @return ARDocumentHeader objects meeting the search criteria 488 */ 489 protected Collection getARDocumentHeaders(Map urlParameters) { 490 Collection arDocumentHeaders; 491 492 String reportOption = ((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.REPORT_OPTION))[0]; 493 String customerNumber = ((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.CUSTOMER_NUMBER))[0]; 494 495 if (StringUtils.equals(reportOption, ArConstants.CustomerAgingReportFields.PROCESSING_ORG)) { 496 String processingChartCode = ((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.PROCESSING_OR_BILLING_CHART_CODE))[0]; 497 String processingOrganizationCode = ((String[]) urlParameters.get(KFSConstants.CustomerOpenItemReport.ORGANIZATION_CODE))[0]; 498 arDocumentHeaders = accountsReceivableDocumentHeaderDao.getARDocumentHeadersByCustomerNumberByProcessingOrgCodeAndChartCode(customerNumber, processingChartCode, processingOrganizationCode); 499 } // reportOption is "Billing Organization" or "Account" 500 else { 501 arDocumentHeaders = accountsReceivableDocumentHeaderDao.getARDocumentHeadersByCustomerNumber(customerNumber); 502 } 503 return arDocumentHeaders; 504 } 505 506 /* 507 * This method gets called only if reportOption is Account 508 * Gets invoices based on the selected invoice details <=> invoice details meeting search criteria i.e. the accountNumber and the list of documentIds 509 * @param accountNumber 510 * @param arDocumentHeaderIds 511 * @param details (will get populated here) 512 * @return invoices 513 */ 514 protected Collection<CustomerInvoiceDocument> getInvoicesByAccountNumberByDocumentIds(String accountNumber, List arDocumentHeaderIds, Collection<CustomerInvoiceDetail> details) { 515 Collection<CustomerInvoiceDocument> invoices = null; 516 517 if (ObjectUtils.isNull(details) | details.size()==0) 518 return invoices; 519 520 // get list of invoice document ids (eliminate duplicate invoice document ids) 521 List<String> documentIds = new ArrayList(); 522 for (CustomerInvoiceDetail detail:details) { 523 String documentNumber = ((CustomerInvoiceDetail)detail).getDocumentNumber(); 524 if (!documentIds.contains(documentNumber)) 525 documentIds.add(documentNumber); 526 } 527 528 // get invoices for the document ids list 529 if (documentIds.size() != 0) 530 invoices = getDocuments(CustomerInvoiceDocument.class, documentIds); 531 532 return invoices; 533 } 534 535 protected void populateReporDetails(List<CustomerInvoiceDocument> selectedInvoices,List results, Collection<CustomerInvoiceDetail> invoiceDetails) { 536 537 for (Iterator<CustomerInvoiceDocument> iter = selectedInvoices.iterator(); iter.hasNext();) { 538 CustomerInvoiceDocument invoice = iter.next(); 539 String documentNumber = invoice.getDocumentNumber(); 540 541 KualiDecimal amount = KualiDecimal.ZERO; 542 KualiDecimal taxAmount = KualiDecimal.ZERO; 543 KualiDecimal openAmount = KualiDecimal.ZERO; 544 545 boolean foundFlag = false; 546 547 for (CustomerInvoiceDetail invoiceDetail:invoiceDetails) { 548 String tempDocumentNumber = ((CustomerInvoiceDetail)invoiceDetail).getDocumentNumber(); 549 if (!StringUtils.equals(documentNumber, tempDocumentNumber)) 550 continue; 551 foundFlag = true; 552 553 KualiDecimal itemAmount = ((CustomerInvoiceDetail)invoiceDetail).getAmount(); 554 if (ObjectUtils.isNotNull(itemAmount)) 555 amount = amount.add(itemAmount); 556 557 KualiDecimal itemTaxAmount = ((CustomerInvoiceDetail)invoiceDetail).getInvoiceItemTaxAmount(); 558 if (ObjectUtils.isNotNull(itemTaxAmount)) 559 taxAmount = taxAmount.add(itemTaxAmount); 560 561 KualiDecimal openItemAmount = ((CustomerInvoiceDetail)invoiceDetail).getAmountOpen(); 562 if (ObjectUtils.isNotNull(openItemAmount)) 563 openAmount = openAmount.add(openItemAmount); 564 } 565 // How is this possible? 566 // invoiceDetails are for the list of invoices(invoices) meeting seach criteria including accountNumber and selected arDocumentHeaders 567 // -> list of invoices gets modified based on report run date and chosen date bucket -> selectedInvoices 568 // selectedInvoices.size() <= invoices.size() 569 if (!foundFlag) 570 continue; 571 572 CustomerOpenItemReportDetail detail = new CustomerOpenItemReportDetail(); 573 // Document Type 574 detail.setDocumentType(invoice.getDocumentHeader().getWorkflowDocument().getDocumentType()); 575 // Document Number 576 detail.setDocumentNumber(documentNumber); 577 // Document Description 578 String documentDescription = invoice.getDocumentHeader().getDocumentDescription(); 579 if (ObjectUtils.isNotNull(documentDescription)) 580 detail.setDocumentDescription(documentDescription); 581 else 582 detail.setDocumentDescription(""); 583 // Billing Date 584 detail.setBillingDate(invoice.getBillingDate()); 585 // Due Date 586 detail.setDueApprovedDate(invoice.getInvoiceDueDate()); 587 // Document Payment Amount 588 detail.setDocumentPaymentAmount(amount.add(taxAmount)); 589 // Unpaid/Unapplied Amount 590 detail.setUnpaidUnappliedAmount(openAmount); 591 results.add(detail); 592 } 593 } 594 595 protected void populateReportDetails(List<CustomerInvoiceDocument> invoices, List results) { 596 for (CustomerInvoiceDocument invoice:invoices) { 597 CustomerOpenItemReportDetail detail = new CustomerOpenItemReportDetail(); 598 // Document Type 599 detail.setDocumentType(invoice.getDocumentHeader().getWorkflowDocument().getDocumentType()); 600 // Document Number 601 detail.setDocumentNumber(invoice.getDocumentNumber()); 602 // Document Description 603 String documentDescription = invoice.getDocumentHeader().getDocumentDescription(); 604 if (ObjectUtils.isNotNull(documentDescription)) 605 detail.setDocumentDescription(documentDescription); 606 else 607 detail.setDocumentDescription(""); 608 // Billing Date 609 detail.setBillingDate(invoice.getBillingDate()); 610 // Due Date 611 detail.setDueApprovedDate(invoice.getInvoiceDueDate()); 612 // Document Payment Amount 613 detail.setDocumentPaymentAmount(invoice.getDocumentHeader().getFinancialDocumentTotalAmount()); 614 // Unpaid/Unapplied Amount 615 detail.setUnpaidUnappliedAmount(customerInvoiceDocumentService.getOpenAmountForCustomerInvoiceDocument(invoice)); 616 results.add(detail); 617 618 } 619 } 620 621 public void setAccountsReceivableDocumentHeaderDao(AccountsReceivableDocumentHeaderDao accountsReceivableDocumentHeaderDao) { 622 this.accountsReceivableDocumentHeaderDao = accountsReceivableDocumentHeaderDao; 623 } 624 625 public void setWorkflowDocumentService(WorkflowDocumentService workflowDocumentService) { 626 this.workflowDocumentService = workflowDocumentService; 627 } 628 629 public void setCustomerInvoiceDocumentService(CustomerInvoiceDocumentService customerInvoiceDocumentService) { 630 this.customerInvoiceDocumentService = customerInvoiceDocumentService; 631 } 632 633 public void setFinancialSystemDocumentHeaderDao(FinancialSystemDocumentHeaderDao financialSystemDocumentHeaderDao) { 634 this.financialSystemDocumentHeaderDao = financialSystemDocumentHeaderDao; 635 } 636 637 public void setDocumentService(DocumentService documentService) { 638 this.documentService = documentService; 639 } 640 641 public void setDateTimeService(DateTimeService dateTimeService) { 642 this.dateTimeService = dateTimeService; 643 } 644 645 public void setCustomerInvoiceDetailDao(CustomerInvoiceDetailDao customerInvoiceDetailDao) { 646 this.customerInvoiceDetailDao = customerInvoiceDetailDao; 647 } 648 649 public void setNonAppliedHoldingDao(NonAppliedHoldingDao nonAppliedHoldingDao) { 650 this.nonAppliedHoldingDao = nonAppliedHoldingDao; 651 } 652 } 653